diff --git a/pkg/webui/html/states.html b/pkg/webui/html/states.html index f602242..fecfdee 100644 --- a/pkg/webui/html/states.html +++ b/pkg/webui/html/states.html @@ -1,69 +1,46 @@ {{ define "main" }} -<div> - <div class="tabs"> - <a data-ui="#explorer"{{ if eq .ActiveTab 0 }} class="active"{{ end }}>States</a> - <a data-ui="#new"{{ if eq .ActiveTab 1 }} class="active"{{ end }}>Create New State</a> +<h1>States</h1> +<div class="flex-row" style="justify-content: space-between;"> + <div style="min-width: 240px;"> + <p>TfStated is currently managing {{ len .States }} states.</p> + <p>Use this page to inspect the existing states.</p> + <p>You also have the option to upload a state file in order to create a new one. This is equivalent to using the <code>state push</code> command of OpenTofu/Terraform on a brand new state.</p> </div> - <div id="explorer" class="page padding{{ if eq .ActiveTab 0 }} active{{ end }}"> - <table class="clickable-rows no-space"> - <thead> - <tr> - <th>Path</th> - <th>Updated</th> - <th>Locked</th> - </tr> - </thead> - <tbody> - {{ range .States }} - <tr> - <td><a href="/states/{{ .Id }}">{{ .Path }}</a></td> - <td><a href="/states/{{ .Id }}">{{ .Updated }}</a></td> - <td> - <a href="/states/{{ .Id }}"> - {{ if eq .Lock nil }}no{{ else }} - <span>yes</span> - <div class="tooltip left max"> - <b>Lock</b> - <p>{{ .Lock }}</p> - </div> - {{ end }} - </a> - </td> - </tr> + <form action="/states" enctype="multipart/form-data" method="post"> + <fieldset> + <legend>New State</legend> + <div class="grid-2"> + <label for="path">Path</label> + <input autofocus + class="flex-stretch" + id="path" + name="path" + required + type="text" + value="{{ .Path }}"> + {{ if .PathDuplicate }} + <span class="error">This path already exist</span> + {{ else if .PathError }} + <span class="error">A valid URL path beginning with a / is expected.</span> {{ end }} - </tbody> - </table> - </div> - <div id="new" class="page padding{{ if eq .ActiveTab 1 }} active{{ end }}"> - <form action="/states" enctype="multipart/form-data" method="post"> - <fieldset> - <div class="field border label{{ if .PathError }} invalid{{ end }}"> - <input autofocus - id="path" - name="path" - required - type="text" - value="{{ .Path }}"> - <label for="path">Path</label> - {{ if .PathDuplicate }} - <span class="error">This path already exist</span> - {{ else if .PathError }} - <span class="error">Invalid path</span> - {{ else }} - <span class="helper">Valid URL path beginning with a /</span> - {{ end }} - </div> - <div class="field label border"> - <input name="file" - required - type="file"> - <input type="text"> - <label>File</label> - <span class="helper">JSON state file</span> - </div> - <button class="small-round" type="submit" value="submit">New</button> - </fieldset> - </form> - </div> + <label for="file" style="min-width: 120px">JSON state file</label> + <input id="file" + name="file" + required + type="file"> + </div> + <button class="primary" type="submit" value="submit">Upload and Create State</button> + </fieldset> + </form> </div> +<article aria-role="table" class="grid-3" style="margin-top: 16px; justify-items: stretch;"> + <span>Path</span> + <span>Updated</span> + <span>Locked</span> + {{ range .States }} + <a href="/states/{{ .Id }}">{{ .Path }}</a> + <a href="/states/{{ .Id }}">{{ .Updated }}</a> + <a href="/states/{{ .Id }}" style="text-align: center;">{{ if eq .Lock nil }}no{{ else }}yes{{ end }}</a> + {{ end }} +</article> {{ end }} diff --git a/pkg/webui/static/main.css b/pkg/webui/static/main.css index 122af08..2e44218 100644 --- a/pkg/webui/static/main.css +++ b/pkg/webui/static/main.css @@ -105,7 +105,7 @@ header { #main { display: flex; flex-direction: row; - gap: 8px; + gap: 16px; margin-left: auto; margin-right: auto; padding: 8px 0px; @@ -130,17 +130,22 @@ header { text-align: center; text-decoration: none; } -#main aside a.active { - background-color: var(--bg-2); +#main aside a:hover { + background-color: var(--br_orange); + color: var(--red); } main { background-color: var(--bg-1); margin-right: auto; + padding: 8px; overflow-wrap: anywhere; scrollbar-gutter: stable both-edges; max-width: 776px; min-width: 776px; } +hr { + width: 50%; +} h1, h2, h3, h4, h5, h6 { font-family: open, serif; font-weight: 700; @@ -225,14 +230,62 @@ ul { ul li { margin-bottom: 4px; } -.fullwidth { - width: 100%; +article, fieldset { + border: 1px solid var(--fg-0); + border-radius: 4px; + padding: 8px; } -img[src*='#center'] { - display: block; - margin: auto; +button { + background-color: var(--bg-2); + border: 1px solid var(--orange); + color: var(--orange); + align-items: center; + border: 1px solid var(--fg-1); + border-radius: 8px; + display: inline-flex; + font-size: 16px; + gap: 8px; + margin: 4px 2px; + padding: 4px 4px; + text-align: center; + text-decoration: none; +} +button:hover { + background-color: var(--br_orange); + border: 1px solid var(--red); + color: var(--red); +} +.primary { + background-color: var(--orange); + color: var(--fg-1); +} +.flex-column { + display: flex; + flex-direction: column; + gap: 4px; +} +.flex-row { + align-items: start; + display: flex; + flex-direction: row; + gap: 16px; +} +.flex-stretch { + flex: 1; +} +.grid-2 { + align-items: center; + display: grid; + grid-template-columns: min-content 1fr; +} +.grid-3 { + align-items: center; + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} +.grid-3 span { + text-align: center; } - a { color: var(--yellow); } @@ -262,9 +315,9 @@ footer a { color: var(--green); } -@media only screen and (640px <= width < 960px) { /*864*/ +@media only screen and (640px <= width < 968px) { /*856*/ header { - width: calc(100vw - 16px); + width: calc(100vw - 32px); /* 8x2 padding + 16 gap */ } #main { /* These 16px account for the vertical scrollbar */ @@ -280,13 +333,16 @@ footer a { display: none; } main { - max-width: calc(100vw - 16px - 64px); - min-width: calc(100vw - 16px - 64px); + max-width: calc(100vw - 32px - 64px); + min-width: calc(100vw - 32px - 64px); } } @media only screen and (width < 640px) { header { width: calc(100vw - 16px); + } + #main aside hr { + width: auto; } #main { display: block; @@ -298,6 +354,7 @@ footer a { min-width: calc(100vw - 16px); } #main aside { + background-color: var(--bg-0); bottom: 0; flex-direction: row; position: fixed;