worker-service 0.2.0

Worker Service - A worker administration microservice that interoperates with the worker-matcher crate
{% extends "layout.html.tera" %}

{% block title %}Settings — {{ app_display }}{% endblock title %}

{% block content %}
<nav class="breadcrumb-nav" aria-label="Breadcrumb">
  <ol class="breadcrumb-list" aria-label="Breadcrumb trail">
    <li class="breadcrumb-list-item"><a href="/">Home</a></li>
    <li class="breadcrumb-list-item" aria-current="page">Settings</li>
  </ol>
</nav>

<section aria-label="User settings"
         x-data='{
           settings: JSON.parse(localStorage.getItem("lily-settings") || "{}"),
           save() {
             localStorage.setItem("lily-settings", JSON.stringify(this.settings));
             if (window.lily &amp;&amp; window.lily.toast) {
               window.lily.toast("Settings saved", "success");
             }
           },
           reset() {
             this.settings = {};
             localStorage.removeItem("lily-settings");
             if (window.lily &amp;&amp; window.lily.toast) {
               window.lily.toast("Settings reset", "info");
             }
           },
           toggle(key) {
             this.settings[key] = !this.settings[key];
             this.save();
           }
         }'>
  <h2>Settings</h2>
  <p>
    <span class="hint" aria-label="Settings description">
      Per-browser preferences. Stored in <code>localStorage["lily-settings"]</code>;
      no server round-trip required.
    </span>
  </p>

  <div class="action-bar" role="toolbar" aria-label="Settings shortcuts">
    <a class="button"
       href="/tokens"
       aria-label="Manage personal API tokens">API tokens</a>
  </div>

  <form class="form" aria-label="Settings form" @submit.prevent="save()">
    <fieldset class="fieldset" aria-label="Display preferences">
      <legend>Display</legend>

      <div class="field" aria-label="Mask sensitive fields preference">
        <label class="label" for="mask-sensitive-default">Mask sensitive fields by default</label>
        <span class="hint" id="mask-sensitive-default-hint">
          Apply privacy masking to identifiers, phones, SSN, NHS number in lists and search.
        </span>
        <button class="switch-button"
                role="switch"
                type="button"
                id="mask-sensitive-default"
                aria-label="Mask sensitive fields by default"
                aria-describedby="mask-sensitive-default-hint"
                x-bind:aria-checked="settings.mask_sensitive_default ? 'true' : 'false'"
                @click="toggle('mask_sensitive_default')">
          <span x-text="settings.mask_sensitive_default ? 'On' : 'Off'"></span>
        </button>
      </div>

      <div class="field" aria-label="Show inactive preference">
        <label class="label" for="show-inactive">Show inactive records in lists</label>
        <span class="hint" id="show-inactive-hint">
          When off, soft-deleted records are hidden from the index and search.
        </span>
        <button class="switch-button"
                role="switch"
                type="button"
                id="show-inactive"
                aria-label="Show inactive records"
                aria-describedby="show-inactive-hint"
                x-bind:aria-checked="settings.show_inactive ? 'true' : 'false'"
                @click="toggle('show_inactive')">
          <span x-text="settings.show_inactive ? 'On' : 'Off'"></span>
        </button>
      </div>

      <div class="field" aria-label="Toast notifications preference">
        <label class="label" for="toasts-on">Toast notifications</label>
        <span class="hint" id="toasts-on-hint">
          Show transient confirmation messages after actions like merge / delete.
        </span>
        <button class="switch-button"
                role="switch"
                type="button"
                id="toasts-on"
                aria-label="Toast notifications"
                aria-describedby="toasts-on-hint"
                x-bind:aria-checked="settings.toasts_on === false ? 'false' : 'true'"
                @click="toggle('toasts_on')">
          <span x-text="settings.toasts_on === false ? 'Off' : 'On'"></span>
        </button>
      </div>

      <div class="field" aria-label="Page size preference">
        <label class="label" for="page-size">Page size</label>
        <span class="hint" id="page-size-hint">Rows per page on the index and search.</span>
        <select class="select"
                id="page-size"
                aria-label="Page size"
                aria-describedby="page-size-hint"
                x-model.number="settings.page_size"
                @change="save()">
          <option class="option" value="10">10</option>
          <option class="option" value="25" selected>25</option>
          <option class="option" value="50">50</option>
          <option class="option" value="100">100</option>
        </select>
      </div>
    </fieldset>

    <fieldset class="fieldset" aria-label="Accent color preferences"
              x-data='{
                presets: [
                  { value: "#005eb8", name: "NHS blue" },
                  { value: "#330072", name: "Purple" },
                  { value: "#7c2855", name: "Dark pink" },
                  { value: "#8a1538", name: "Dark red" },
                  { value: "#ed8b00", name: "Orange" },
                  { value: "#006747", name: "Dark green" },
                  { value: "#00a499", name: "Aqua green" },
                  { value: "#231f20", name: "Charcoal" }
                ],
                accent: localStorage.getItem("lily-accent") || "",
                apply(v) {
                  this.accent = v;
                  if (v) {
                    document.documentElement.style.setProperty("--nhs-blue", v);
                    localStorage.setItem("lily-accent", v);
                  } else {
                    document.documentElement.style.removeProperty("--nhs-blue");
                    localStorage.removeItem("lily-accent");
                  }
                  if (window.lily &amp;&amp; window.lily.toast) {
                    window.lily.toast("Accent updated", "info");
                  }
                }
              }'>
      <legend>Accent color</legend>

      <div class="field" aria-label="Accent presets field">
        <label class="label" for="accent-picker">Pick a preset</label>
        <span class="hint" id="accent-picker-hint">Overrides the primary blue (<code>--nhs-blue</code>) on every page.</span>
        <div class="color-picker"
             id="accent-picker"
             role="radiogroup"
             aria-label="Accent color presets"
             aria-describedby="accent-picker-hint">
          <template x-for="p in presets" :key="p.value">
            <button class="color-picker-button"
                    type="button"
                    role="radio"
                    x-bind:aria-label="'Set accent to ' + p.name"
                    x-bind:aria-checked="accent === p.value ? 'true' : 'false'"
                    x-bind:style="'background-color: ' + p.value"
                    @click="apply(p.value)"></button>
          </template>
        </div>
      </div>

      <div class="field" aria-label="Custom accent field">
        <label class="label" for="accent-input">Custom hex</label>
        <span class="hint" id="accent-input-hint">Use the native color picker for any color outside the presets.</span>
        <input class="color-input"
               type="color"
               id="accent-input"
               aria-label="Custom accent color"
               aria-describedby="accent-input-hint"
               x-bind:value="accent || '#005eb8'"
               @change="apply($event.target.value)">
      </div>

      <div class="action-bar" role="toolbar" aria-label="Accent actions">
        <button class="button"
                type="button"
                aria-label="Reset accent to NHS blue"
                @click="apply('')">Reset to default</button>
        <span class="action-bar-count">
          Current: <code x-text="accent || '(default)'"></code>
        </span>
      </div>
    </fieldset>

    <fieldset class="fieldset" aria-label="Diagnostics preferences">
      <legend>Diagnostics</legend>

      <div class="field" aria-label="Show technical detail preference">
        <label class="label" for="show-detail">Show technical detail on error pages</label>
        <span class="hint" id="show-detail-hint">
          Expand the technical-detail <code>&lt;details&gt;</code> block on 500 pages by default.
        </span>
        <button class="switch-button"
                role="switch"
                type="button"
                id="show-detail"
                aria-label="Show technical detail"
                aria-describedby="show-detail-hint"
                x-bind:aria-checked="settings.show_detail ? 'true' : 'false'"
                @click="toggle('show_detail')">
          <span x-text="settings.show_detail ? 'On' : 'Off'"></span>
        </button>
      </div>
    </fieldset>

    <div class="action-bar" role="toolbar" aria-label="Settings actions">
      <button class="button" type="submit" aria-label="Save settings">Save</button>
      <button class="button"
              type="button"
              aria-label="Reset settings to defaults"
              @click="reset()">Reset</button>
    </div>
  </form>
</section>
{% endblock content %}