forked from tangled.org/core
Monorepo for Tangled — https://tangled.org

appview: improve label editing workflow

Signed-off-by: oppiliappan <me@oppi.li>

oppi.li d0cc53d6 9772312c

verified
Changed files
+433 -212
appview
+21 -2
appview/pages/templates/labels/fragments/label.html
···
{{ define "labels/fragments/label" }}
{{ $d := .def }}
{{ $v := .val }}
+
{{ $withPrefix := .withPrefix }}
<span class="flex items-center gap-2 font-normal normal-case rounded py-1 px-2 border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 text-sm">
{{ template "repo/fragments/colorBall" (dict "color" $d.GetColor) }}
-
{{ $d.Name }}{{ if not $d.ValueType.IsNull }}/{{ template "labelVal" (dict "def" $d "val" $v) }}{{ end }}
+
+
{{ $lhs := printf "%s" $d.Name }}
+
{{ $rhs := "" }}
+
+
{{ if not $d.ValueType.IsNull }}
+
{{ if $d.ValueType.IsDidFormat }}
+
{{ $v = resolve $v }}
+
{{ end }}
+
+
{{ if not $withPrefix }}
+
{{ $lhs = "" }}
+
{{ else }}
+
{{ $lhs = printf "%s/" $d.Name }}
+
{{ end }}
+
+
{{ $rhs = printf "%s" $v }}
+
{{ end }}
+
+
{{ printf "%s%s" $lhs $rhs }}
</span>
{{ end }}
···
{{ $v := .val }}
{{ if $d.ValueType.IsDidFormat }}
-
{{ resolve $v }}
+
{{ resolve $v }}
{{ else }}
{{ $v }}
{{ end }}
-127
appview/pages/templates/repo/fragments/addLabelModal.html
···
-
{{ define "repo/fragments/addLabelModal" }}
-
{{ $root := .root }}
-
{{ $subject := .subject }}
-
{{ $state := .state }}
-
{{ with $root }}
-
<form
-
hx-put="/{{ .RepoInfo.FullName }}/labels/perform"
-
hx-on::after-request="this.reset()"
-
hx-indicator="#spinner"
-
hx-swap="none"
-
class="flex flex-col gap-4"
-
>
-
<p class="text-gray-500 dark:text-gray-400">Add, remove or update labels.</p>
-
-
<input class="hidden" name="repo" value="{{ .RepoInfo.RepoAt.String }}">
-
<input class="hidden" name="subject" value="{{ $subject }}">
-
-
<div class="flex flex-col gap-2">
-
{{ $id := 0 }}
-
{{ range $k, $valset := $state.Inner }}
-
{{ $d := index $root.LabelDefs $k }}
-
{{ range $v, $s := $valset }}
-
{{ template "labelCheckbox" (dict "def" $d "key" $k "val" $v "id" $id "isChecked" true) }}
-
{{ $id = add $id 1 }}
-
{{ end }}
-
{{ end }}
-
-
{{ range $k, $d := $root.LabelDefs }}
-
{{ if not ($state.ContainsLabel $k) }}
-
{{ template "labelCheckbox" (dict "def" $d "key" $k "val" "" "id" $id "isChecked" false) }}
-
{{ $id = add $id 1 }}
-
{{ end }}
-
{{ else }}
-
<span>
-
No labels defined yet. You can define custom labels in <a class="underline" href="/{{ .RepoInfo.FullName }}/settings">settings</a>.
-
</span>
-
{{ end }}
-
</div>
-
-
<div class="flex gap-2 pt-2">
-
<button
-
type="button"
-
popovertarget="add-label-modal"
-
popovertargetaction="hide"
-
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
-
>
-
{{ i "x" "size-4" }} cancel
-
</button>
-
<button type="submit" class="btn w-1/2 flex items-center">
-
<span class="inline-flex gap-2 items-center">{{ i "check" "size-4" }} save</span>
-
<span id="spinner" class="group">
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
-
</div>
-
<div id="add-label-error" class="text-red-500 dark:text-red-400"></div>
-
</form>
-
{{ end }}
-
{{ end }}
-
-
{{ define "labelCheckbox" }}
-
{{ $key := .key }}
-
{{ $val := .val }}
-
{{ $def := .def }}
-
{{ $id := .id }}
-
{{ $isChecked := .isChecked }}
-
<div class="grid grid-cols-[auto_1fr_50%] gap-2 items-center cursor-pointer">
-
<input type="checkbox" id="op-{{$id}}" name="op-{{$id}}" value="add" {{if $isChecked}}checked{{end}} class="peer">
-
<label for="op-{{$id}}" class="flex items-center gap-2 text-base">{{ template "labels/fragments/labelDef" $def }}</label>
-
<div class="w-full hidden peer-checked:block">{{ template "valueTypeInput" (dict "valueType" $def.ValueType "value" $val "key" $key) }}</div>
-
<input type="hidden" name="operand-key" value="{{ $key }}">
-
</div>
-
{{ end }}
-
-
{{ define "valueTypeInput" }}
-
{{ $valueType := .valueType }}
-
{{ $value := .value }}
-
{{ $key := .key }}
-
-
{{ if $valueType.IsEnumType }}
-
{{ template "enumTypeInput" $ }}
-
{{ else if $valueType.IsBool }}
-
{{ template "boolTypeInput" $ }}
-
{{ else if $valueType.IsInt }}
-
{{ template "intTypeInput" $ }}
-
{{ else if $valueType.IsString }}
-
{{ template "stringTypeInput" $ }}
-
{{ else if $valueType.IsNull }}
-
{{ template "nullTypeInput" $ }}
-
{{ end }}
-
{{ end }}
-
-
{{ define "enumTypeInput" }}
-
{{ $valueType := .valueType }}
-
{{ $value := .value }}
-
<select name="operand-val" class="w-full p-1 rounded border border-gray-300 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-600">
-
{{ range $valueType.Enum }}
-
<option value="{{.}}" {{ if eq $value . }} selected {{ end }}>{{.}}</option>
-
{{ end }}
-
</select>
-
{{ end }}
-
-
{{ define "boolTypeInput" }}
-
{{ $value := .value }}
-
<select name="operand-val" class="w-full p-1 rounded border border-gray-300 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-600">
-
<option value="true" {{ if $value }} selected {{ end }}>true</option>
-
<option value="false" {{ if not $value }} selected {{ end }}>false</option>
-
</select>
-
{{ end }}
-
-
{{ define "intTypeInput" }}
-
{{ $value := .value }}
-
<input class="p-1 w-full" type="number" name="operand-val" value="{{$value}}" max="100">
-
{{ end }}
-
-
{{ define "stringTypeInput" }}
-
{{ $valueType := .valueType }}
-
{{ $value := .value }}
-
{{ if $valueType.IsDidFormat }}
-
{{ $value = resolve .value }}
-
{{ end }}
-
<input class="p-1 w-full" type="text" name="operand-val" value="{{$value}}">
-
{{ end }}
-
-
{{ define "nullTypeInput" }}
-
<input class="p-1" type="hidden" name="operand-val" value="null">
-
{{ end }}
+208
appview/pages/templates/repo/fragments/editLabelPanel.html
···
+
{{ define "repo/fragments/editLabelPanel" }}
+
<form
+
id="edit-label-panel"
+
hx-put="/{{ .RepoInfo.FullName }}/labels/perform"
+
hx-indicator="#spinner"
+
hx-disabled-elt="#save-btn,#cancel-btn"
+
hx-swap="none"
+
class="flex flex-col gap-6"
+
>
+
<input type="hidden" name="repo" value="{{ .RepoInfo.RepoAt }}">
+
<input type="hidden" name="subject" value="{{ .Subject }}">
+
{{ template "editBasicLabels" . }}
+
{{ template "editKvLabels" . }}
+
{{ template "editLabelPanelActions" . }}
+
<div id="add-label-error" class="text-red-500 dark:text-red-400"></div>
+
</form>
+
{{ end }}
+
+
{{ define "editBasicLabels" }}
+
{{ $defs := .Defs }}
+
{{ $subject := .Subject }}
+
{{ $state := .State }}
+
{{ $labelStyle := "flex items-center gap-2 rounded py-1 px-2 border border-gray-200 dark:border-gray-700 text-sm bg-white dark:bg-gray-800 text-black dark:text-white" }}
+
<div>
+
{{ template "repo/fragments/labelSectionHeaderText" "Labels" }}
+
+
<div class="flex gap-1 items-center flex-wrap">
+
{{ range $k, $d := $defs }}
+
{{ $isChecked := $state.ContainsLabel $k }}
+
{{ if $d.ValueType.IsNull }}
+
{{ $fieldName := $d.AtUri }}
+
<label class="{{$labelStyle}}">
+
<input type="checkbox" id="{{ $fieldName }}" name="{{ $fieldName }}" value="null" {{if $isChecked}}checked{{end}}>
+
{{ template "labels/fragments/labelDef" $d }}
+
</label>
+
{{ end }}
+
{{ else }}
+
<p class="text-gray-500 dark:text-gray-400 text-sm py-1">
+
No labels defined yet. You can choose default labels or define custom
+
labels in <a class="underline" href="/{{ $.RepoInfo.FullName }}/settings">settings</a>.
+
</p>
+
{{ end }}
+
</div>
+
</div>
+
{{ end }}
+
+
{{ define "editKvLabels" }}
+
{{ $defs := .Defs }}
+
{{ $subject := .Subject }}
+
{{ $state := .State }}
+
{{ $labelStyle := "font-normal normal-case flex items-center gap-2 p-0" }}
+
+
{{ range $k, $d := $defs }}
+
{{ if (not $d.ValueType.IsNull) }}
+
{{ $fieldName := $d.AtUri }}
+
{{ $valset := $state.GetValSet $k }}
+
<div id="label-{{$d.Id}}" class="flex flex-col gap-1">
+
{{ template "repo/fragments/labelSectionHeaderText" $d.Name }}
+
{{ if (and $d.Multiple $d.ValueType.IsEnum) }}
+
<!-- checkbox -->
+
{{ range $variant := $d.ValueType.Enum }}
+
<label class="{{$labelStyle}}">
+
<input type="checkbox" name="{{ $fieldName }}" value="{{$variant}}" {{if $state.ContainsLabelAndVal $k $variant}}checked{{end}}>
+
{{ $variant }}
+
</label>
+
{{ end }}
+
{{ else if $d.Multiple }}
+
<!-- dynamically growing input fields -->
+
{{ range $v, $s := $valset }}
+
{{ template "multipleInputField" (dict "def" $d "value" $v "key" $k) }}
+
{{ else }}
+
{{ template "multipleInputField" (dict "def" $d "value" "" "key" $k) }}
+
{{ end }}
+
{{ template "addFieldButton" $d }}
+
{{ else if $d.ValueType.IsEnum }}
+
<!-- radio buttons -->
+
{{ $isUsed := $state.ContainsLabel $k }}
+
{{ range $variant := $d.ValueType.Enum }}
+
<label class="{{$labelStyle}}">
+
<input type="radio" name="{{ $fieldName }}" value="{{$variant}}" {{if $state.ContainsLabelAndVal $k $variant}}checked{{end}}>
+
{{ $variant }}
+
</label>
+
{{ end }}
+
<label class="{{$labelStyle}}">
+
<input type="radio" name="{{ $fieldName }}" value="" {{ if not $isUsed }}checked{{ end }}>
+
None
+
</label>
+
{{ else }}
+
<!-- single input field based on value type -->
+
{{ range $v, $s := $valset }}
+
{{ template "valueTypeInput" (dict "def" $d "value" $v "key" $k) }}
+
{{ else }}
+
{{ template "valueTypeInput" (dict "def" $d "value" "" "key" $k) }}
+
{{ end }}
+
{{ end }}
+
</div>
+
{{ end }}
+
{{ end }}
+
{{ end }}
+
+
{{ define "multipleInputField" }}
+
<div class="flex gap-1 items-stretch">
+
{{ template "valueTypeInput" . }}
+
{{ template "removeFieldButton" }}
+
</div>
+
{{ end }}
+
+
{{ define "addFieldButton" }}
+
<div style="display:none" id="tpl-{{ .Id }}">
+
{{ template "multipleInputField" (dict "def" . "value" "" "key" .AtUri.String) }}
+
</div>
+
<button type="button" onClick="this.insertAdjacentHTML('beforebegin', document.getElementById('tpl-{{ .Id }}').innerHTML)" class="w-full btn flex items-center gap-2">
+
{{ i "plus" "size-4" }} add
+
</button>
+
{{ end }}
+
+
{{ define "removeFieldButton" }}
+
<button type="button" onClick="this.parentElement.remove()" class="btn flex items-center gap-2 text-red-400 dark:text-red-500">
+
{{ i "trash-2" "size-4" }}
+
</button>
+
{{ end }}
+
+
{{ define "valueTypeInput" }}
+
{{ $def := .def }}
+
{{ $valueType := $def.ValueType }}
+
{{ $value := .value }}
+
{{ $key := .key }}
+
+
{{ if $valueType.IsBool }}
+
{{ template "boolTypeInput" $ }}
+
{{ else if $valueType.IsInt }}
+
{{ template "intTypeInput" $ }}
+
{{ else if $valueType.IsString }}
+
{{ template "stringTypeInput" $ }}
+
{{ else if $valueType.IsNull }}
+
{{ template "nullTypeInput" $ }}
+
{{ end }}
+
{{ end }}
+
+
{{ define "boolTypeInput" }}
+
{{ $def := .def }}
+
{{ $fieldName := $def.AtUri }}
+
{{ $value := .value }}
+
{{ $labelStyle = "font-normal normal-case flex items-center gap-2" }}
+
<div class="flex flex-col gap-1">
+
<label class="{{$labelStyle}}">
+
<input type="radio" name="{{ $fieldName }}" value="true" {{ if not $value }}checked{{ end }}>
+
None
+
</label>
+
<label class="{{$labelStyle}}">
+
<input type="radio" name="{{ $fieldName }}" value="true" {{ if not $value }}checked{{ end }}>
+
None
+
</label>
+
<label class="{{$labelStyle}}">
+
<input type="radio" name="{{ $fieldName }}" value="true" {{ if not $value }}checked{{ end }}>
+
None
+
</label>
+
</div>
+
{{ end }}
+
+
{{ define "intTypeInput" }}
+
{{ $def := .def }}
+
{{ $fieldName := $def.AtUri }}
+
{{ $value := .value }}
+
<input class="p-1 w-full" type="number" name="{{$fieldName}}" value="{{$value}}">
+
{{ end }}
+
+
{{ define "stringTypeInput" }}
+
{{ $def := .def }}
+
{{ $fieldName := $def.AtUri }}
+
{{ $valueType := $def.ValueType }}
+
{{ $value := .value }}
+
{{ if $valueType.IsDidFormat }}
+
{{ $value = trimPrefix (resolve .value) "@" }}
+
{{ end }}
+
<input class="p-1 w-full" type="text" name="{{$fieldName}}" value="{{$value}}">
+
{{ end }}
+
+
{{ define "nullTypeInput" }}
+
{{ $def := .def }}
+
{{ $fieldName := $def.AtUri }}
+
<input class="p-1" type="hidden" name="{{$fieldName}}" value="null">
+
{{ end }}
+
+
{{ define "editLabelPanelActions" }}
+
<div class="flex gap-2 pt-2">
+
<button
+
id="cancel-btn"
+
type="button"
+
hx-get="/{{ .RepoInfo.FullName }}/label"
+
hx-vals='{"subject": "{{.Subject}}"}'
+
hx-swap="outerHTML"
+
hx-target="#edit-label-panel"
+
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300 group">
+
{{ i "x" "size-4" }} cancel
+
</button>
+
+
<button
+
id="save-btn"
+
type="submit"
+
class="btn w-1/2 flex items-center">
+
<span class="inline-flex gap-2 items-center">{{ i "check" "size-4" }} save</span>
+
<span id="spinner" class="group">
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
+
</div>
+
{{ end }}
+43
appview/pages/templates/repo/fragments/labelPanel.html
···
+
{{ define "repo/fragments/labelPanel" }}
+
<div id="label-panel" class="flex flex-col gap-6">
+
{{ template "basicLabels" . }}
+
{{ template "kvLabels" . }}
+
</div>
+
{{ end }}
+
+
{{ define "basicLabels" }}
+
<div>
+
{{ template "repo/fragments/labelSectionHeader" (dict "Name" "Labels" "RepoInfo" .RepoInfo "Subject" .Subject) }}
+
+
{{ $hasLabel := false }}
+
<div class="flex gap-1 items-center flex-wrap">
+
{{ range $k, $d := .Defs }}
+
{{ if (and $d.ValueType.IsNull ($.State.ContainsLabel $k)) }}
+
{{ $hasLabel = true }}
+
{{ template "labels/fragments/label" (dict "def" $d "val" "") }}
+
{{ end }}
+
{{ end }}
+
+
{{ if not $hasLabel }}
+
<p class="text-gray-500 dark:text-gray-400 text-sm py-1">None yet.</p>
+
{{ end }}
+
</div>
+
</div>
+
{{ end }}
+
+
{{ define "kvLabels" }}
+
{{ range $k, $d := .Defs }}
+
{{ if (not $d.ValueType.IsNull) }}
+
<div id="label-{{$d.Id}}">
+
{{ template "repo/fragments/labelSectionHeader" (dict "Name" $d.Name "RepoInfo" $.RepoInfo "Subject" $.Subject) }}
+
<div class="flex gap-1 items-center flex-wrap">
+
{{ range $v, $s := $.State.GetValSet $d.AtUri.String }}
+
{{ template "labels/fragments/label" (dict "def" $d "val" $v "withPrefix" false) }}
+
{{ else }}
+
<p class="text-gray-500 dark:text-gray-400 text-sm py-1">None yet.</p>
+
{{ end }}
+
</div>
+
</div>
+
{{ end }}
+
{{ end }}
+
{{ end }}
+16
appview/pages/templates/repo/fragments/labelSectionHeader.html
···
+
{{ define "repo/fragments/labelSectionHeader" }}
+
+
<div class="flex justify-between items-center gap-2">
+
{{ template "repo/fragments/labelSectionHeaderText" .Name }}
+
{{ if (or .RepoInfo.Roles.IsOwner .RepoInfo.Roles.IsCollaborator) }}
+
<a
+
class="text-gray-500 dark:text-gray-400 flex gap-1 items-center group"
+
hx-get="/{{ .RepoInfo.FullName }}/label/edit"
+
hx-vals='{"subject": "{{.Subject}}"}'
+
hx-swap="outerHTML"
+
hx-target="#label-panel">
+
{{ i "pencil" "size-3" }}
+
</a>
+
{{ end }}
+
</div>
+
{{ end }}
+3
appview/pages/templates/repo/fragments/labelSectionHeaderText.html
···
+
{{ define "repo/fragments/labelSectionHeaderText" }}
+
<span class="text-sm py-1 font-bold text-gray-500 dark:text-gray-400 capitalize">{{ . }}</span>
+
{{ end }}
+135 -83
appview/pages/templates/repo/settings/fragments/addLabelDefModal.html
···
{{ define "repo/settings/fragments/addLabelDefModal" }}
-
<form
-
hx-put="/{{ $.RepoInfo.FullName }}/settings/label"
-
hx-indicator="#spinner"
-
hx-swap="none"
-
hx-on::after-request="if(event.detail.successful) this.reset()"
-
class="flex flex-col gap-4"
-
>
-
<p class="text-gray-500 dark:text-gray-400">Labels can have a name and a value. Set the value type to "none" to create a simple label.</p>
+
<div class="grid grid-cols-2">
+
<input type="radio" name="tab" id="basic-tab" value="basic" class="hidden peer/basic" checked>
+
<input type="radio" name="tab" id="kv-tab" value="kv" class="hidden peer/kv">
-
<div class="w-full">
-
<label for="name">Name</label>
-
<input class="w-full" type="text" id="label-name" name="name" required placeholder="improvement"/>
+
<!-- Labels as direct siblings -->
+
{{ $base := "py-2 text-sm font-normal normal-case block hover:no-underline text-center cursor-pointer bg-gray-100 dark:bg-gray-800 shadow-inner border border-gray-200 dark:border-gray-700" }}
+
<label for="basic-tab" class="{{$base}} peer-checked/basic:bg-white peer-checked/basic:dark:bg-gray-700 peer-checked/basic:shadow-sm rounded-l">
+
Basic Labels
+
</label>
+
<label for="kv-tab" class="{{$base}} peer-checked/kv:bg-white peer-checked/kv:dark:bg-gray-700 peer-checked/kv:shadow-sm rounded-r">
+
Key-value Labels
+
</label>
+
+
<!-- Basic Labels Content - direct sibling -->
+
<div class="mt-4 hidden peer-checked/basic:block col-span-full">
+
{{ template "basicLabelDef" . }}
+
</div>
+
+
<!-- Key-value Labels Content - direct sibling -->
+
<div class="mt-4 hidden peer-checked/kv:block col-span-full">
+
{{ template "kvLabelDef" . }}
</div>
-
<!-- Value Type -->
-
<div class="w-full">
-
<label for="valueType">Value Type</label>
-
<select id="value-type" name="valueType" class="w-full p-3 rounded border border-gray-300 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-600">
-
<option value="null" selected>None</option>
-
<option value="string">String</option>
-
<option value="integer">Integer</option>
-
<option value="boolean">Boolean</option>
-
</select>
-
<details id="constrain-values" class="group hidden">
-
<summary class="list-none cursor-pointer flex items-center gap-2 py-2">
-
<span class="group-open:hidden inline text-gray-500 dark:text-gray-400">{{ i "square-plus" "w-4 h-4" }}</span>
-
<span class="hidden group-open:inline text-gray-500 dark:text-gray-400">{{ i "square-minus" "w-4 h-4" }}</span>
-
<span>Constrain values</span>
-
</summary>
-
<label for="enumValues">Permitted values</label>
-
<input type="text" id="enumValues" name="enumValues" placeholder="value1, value2, value3" class="w-full"/>
-
<p class="text-sm text-gray-400 dark:text-gray-500 mt-1">Enter comma-separated list of permitted values.</p>
+
<div id="add-label-error" class="text-red-500 dark:text-red-400 col-span-full"></div>
+
</div>
+
{{ end }}
+
+
{{ define "basicLabelDef" }}
+
<form
+
hx-put="/{{ $.RepoInfo.FullName }}/settings/label"
+
hx-indicator="#spinner"
+
hx-swap="none"
+
hx-on::after-request="if(event.detail.successful) this.reset()"
+
class="flex flex-col space-y-4">
+
+
<p class="text-gray-500 dark:text-gray-400">These labels can have a name and a color.</p>
+
+
{{ template "nameInput" . }}
+
{{ template "scopeInput" . }}
+
{{ template "colorInput" . }}
+
+
<div class="flex gap-2 pt-2">
+
{{ template "cancelButton" . }}
+
{{ template "submitButton" . }}
+
</div>
+
</form>
+
{{ end }}
-
<label for="valueFormat">String format</label>
-
<select id="valueFormat" name="valueFormat" class="w-full p-3 rounded border border-gray-300 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-600">
-
<option value="any" selected>Any</option>
-
<option value="did">DID</option>
-
</select>
-
<p class="text-sm text-gray-400 dark:text-gray-500 mt-1">Choose a string format.</p>
-
</details>
-
</div>
+
{{ define "kvLabelDef" }}
+
<form
+
hx-put="/{{ $.RepoInfo.FullName }}/settings/label"
+
hx-indicator="#spinner"
+
hx-swap="none"
+
hx-on::after-request="if(event.detail.successful) this.reset()"
+
class="flex flex-col space-y-4">
-
<!-- Scope -->
+
<p class="text-gray-500 dark:text-gray-400">
+
These labels are more detailed, they can have a key and an associated
+
value. You may define additional constraints on label values.
+
</p>
+
+
{{ template "nameInput" . }}
+
{{ template "valueInput" . }}
+
{{ template "multipleInput" . }}
+
{{ template "scopeInput" . }}
+
{{ template "colorInput" . }}
+
+
<div class="flex gap-2 pt-2">
+
{{ template "cancelButton" . }}
+
{{ template "submitButton" . }}
+
</div>
+
</form>
+
{{ end }}
+
+
{{ define "nameInput" }}
<div class="w-full">
-
<label for="scope">Scope</label>
-
<select id="scope" name="scope" class="w-full p-3 rounded border border-gray-300 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-600">
-
<option value="sh.tangled.repo.issue">Issues</option>
-
<option value="sh.tangled.repo.pull">Pull Requests</option>
-
</select>
+
<label for="name">Name</label>
+
<input class="w-full" type="text" id="label-name" name="name" required placeholder="improvement"/>
</div>
+
{{ end }}
-
<!-- Color -->
+
{{ define "colorInput" }}
<div class="w-full">
<label for="color">Color</label>
<div class="grid grid-cols-4 grid-rows-2 place-items-center">
···
{{ end }}
</div>
</div>
+
{{ end }}
-
<!-- Multiple -->
-
<div class="w-full flex flex-wrap gap-2">
-
<input type="checkbox" id="multiple" name="multiple" value="true" />
-
<span>
-
Allow multiple values
-
</span>
+
{{ define "scopeInput" }}
+
<div class="w-full">
+
<label>Scope</label>
+
<label class="font-normal normal-case flex items-center gap-2 p-0">
+
<input type="checkbox" id="issue-scope" name="scope" value="sh.tangled.repo.issue" checked />
+
Issues
+
</label>
+
<label class="font-normal normal-case flex items-center gap-2 p-0">
+
<input type="checkbox" id="pulls-scope" name="scope" value="sh.tangled.repo.pull" checked />
+
Pull Requests
+
</label>
+
</div>
+
{{ end }}
+
+
{{ define "valueInput" }}
+
<div class="w-full">
+
<label for="valueType">Value Type</label>
+
<select id="value-type" name="valueType" class="w-full p-3 rounded border border-gray-300 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-600">
+
<option value="string">String</option>
+
<option value="integer">Integer</option>
+
</select>
+
</div>
+
+
<div class="w-full">
+
<label for="enumValues">Permitted values</label>
+
<input type="text" id="enumValues" name="enumValues" placeholder="value1, value2, value3" class="w-full"/>
+
<p class="text-sm text-gray-400 dark:text-gray-500 mt-1">
+
Enter comma-separated list of permitted values, or leave empty to allow any value.
+
</p>
</div>
-
<div class="flex gap-2 pt-2">
-
<button
-
type="button"
-
popovertarget="add-labeldef-modal"
-
popovertargetaction="hide"
-
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
-
>
-
{{ i "x" "size-4" }} cancel
-
</button>
-
<button type="submit" class="btn w-1/2 flex items-center">
-
<span class="inline-flex gap-2 items-center">{{ i "plus" "size-4" }} add</span>
-
<span id="spinner" class="group">
-
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
-
</span>
-
</button>
+
<div class="w-full">
+
<label for="valueFormat">String format</label>
+
<select id="valueFormat" name="valueFormat" class="w-full p-3 rounded border border-gray-300 bg-white dark:bg-gray-800 dark:text-white dark:border-gray-600">
+
<option value="any" selected>Any</option>
+
<option value="did">DID</option>
+
</select>
</div>
-
<div id="add-label-error" class="text-red-500 dark:text-red-400"></div>
-
</form>
+
{{ end }}
-
<script>
-
document.getElementById('value-type').addEventListener('change', function() {
-
const constrainValues = document.getElementById('constrain-values');
-
const selectedValue = this.value;
+
{{ define "multipleInput" }}
+
<div class="w-full flex flex-wrap gap-2">
+
<input type="checkbox" id="multiple" name="multiple" value="true" />
+
<span>Allow multiple values</span>
+
</div>
+
{{ end }}
-
if (selectedValue === 'string') {
-
constrainValues.classList.remove('hidden');
-
} else {
-
constrainValues.classList.add('hidden');
-
constrainValues.removeAttribute('open');
-
document.getElementById('enumValues').value = '';
-
}
-
});
+
{{ define "cancelButton" }}
+
<button
+
type="button"
+
popovertarget="add-labeldef-modal"
+
popovertargetaction="hide"
+
class="btn w-1/2 flex items-center gap-2 text-red-500 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
+
>
+
{{ i "x" "size-4" }} cancel
+
</button>
+
{{ end }}
-
function toggleDarkMode() {
-
document.documentElement.classList.toggle('dark');
-
}
-
</script>
+
{{ define "submitButton" }}
+
<button type="submit" class="btn-create w-1/2 flex items-center">
+
<span class="inline-flex gap-2 items-center">{{ i "plus" "size-4" }} add</span>
+
<span id="spinner" class="group">
+
{{ i "loader-circle" "ml-2 w-4 h-4 animate-spin hidden group-[.htmx-request]:inline" }}
+
</span>
+
</button>
{{ end }}
+
+6
appview/repo/router.go
···
r.Get("/*", rp.RepoCompare)
})
+
// label panel in issues/pulls/discussions/tasks
+
r.Route("/label", func(r chi.Router) {
+
r.Get("/", rp.LabelPanel)
+
r.Get("/edit", rp.EditLabelPanel)
+
})
+
// settings routes, needs auth
r.Group(func(r chi.Router) {
r.Use(middleware.AuthMiddleware(rp.oauth))
+1
appview/reporesolver/resolver.go
···
OwnerDid: f.OwnerDid(),
OwnerHandle: f.OwnerHandle(),
Name: f.Name,
+
Rkey: f.Repo.Rkey,
RepoAt: repoAt,
Description: f.Description,
IsStarred: isStarred,