aboutsummaryrefslogtreecommitdiffstats
path: root/web_src/js/features/comp/LabelEdit.ts
blob: a5bb750cdbe8537fd38918c3c0f67cff82830da3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import {toggleElem} from '../../utils/dom.ts';
import {fomanticQuery} from '../../modules/fomantic/base.ts';

function nameHasScope(name: string): boolean {
  return /.*[^/]\/[^/].*/.test(name);
}

export function initCompLabelEdit(pageSelector: string) {
  const pageContent = document.querySelector<HTMLElement>(pageSelector);
  if (!pageContent) return;

  // for guest view, the modal is not available, the "labels" are read-only
  const elModal = pageContent.querySelector<HTMLElement>('#issue-label-edit-modal');
  if (!elModal) return;

  const elLabelId = elModal.querySelector<HTMLInputElement>('input[name="id"]');
  const elNameInput = elModal.querySelector<HTMLInputElement>('.label-name-input');
  const elExclusiveField = elModal.querySelector('.label-exclusive-input-field');
  const elExclusiveInput = elModal.querySelector<HTMLInputElement>('.label-exclusive-input');
  const elExclusiveWarning = elModal.querySelector('.label-exclusive-warning');
  const elExclusiveOrderField = elModal.querySelector<HTMLInputElement>('.label-exclusive-order-input-field');
  const elExclusiveOrderInput = elModal.querySelector<HTMLInputElement>('.label-exclusive-order-input');
  const elIsArchivedField = elModal.querySelector('.label-is-archived-input-field');
  const elIsArchivedInput = elModal.querySelector<HTMLInputElement>('.label-is-archived-input');
  const elDescInput = elModal.querySelector<HTMLInputElement>('.label-desc-input');
  const elColorInput = elModal.querySelector<HTMLInputElement>('.js-color-picker-input input');

  const syncModalUi = () => {
    const hasScope = nameHasScope(elNameInput.value);
    elExclusiveField.classList.toggle('disabled', !hasScope);
    const showExclusiveWarning = hasScope && elExclusiveInput.checked && elModal.hasAttribute('data-need-warn-exclusive');
    toggleElem(elExclusiveWarning, showExclusiveWarning);
    if (!hasScope) elExclusiveInput.checked = false;
    toggleElem(elExclusiveOrderField, elExclusiveInput.checked);

    if (parseInt(elExclusiveOrderInput.value) <= 0) {
      elExclusiveOrderInput.style.color = 'var(--color-placeholder-text) !important';
    } else {
      elExclusiveOrderInput.style.color = null;
    }
  };

  const showLabelEditModal = (btn:HTMLElement) => {
    // the "btn" should contain the label's attributes by its `data-label-xxx` attributes
    const form = elModal.querySelector<HTMLFormElement>('form');
    elLabelId.value = btn.getAttribute('data-label-id') || '';
    elNameInput.value = btn.getAttribute('data-label-name') || '';
    elExclusiveOrderInput.value = btn.getAttribute('data-label-exclusive-order') || '0';
    elIsArchivedInput.checked = btn.getAttribute('data-label-is-archived') === 'true';
    elExclusiveInput.checked = btn.getAttribute('data-label-exclusive') === 'true';
    elDescInput.value = btn.getAttribute('data-label-description') || '';
    elColorInput.value = btn.getAttribute('data-label-color') || '';
    elColorInput.dispatchEvent(new Event('input', {bubbles: true})); // trigger the color picker

    // if label id exists: "edit label" mode; otherwise: "new label" mode
    const isEdit = Boolean(elLabelId.value);

    // if a label was not exclusive but has issues, then it should warn user if it will become exclusive
    const numIssues = parseInt(btn.getAttribute('data-label-num-issues') || '0');
    elModal.toggleAttribute('data-need-warn-exclusive', !elExclusiveInput.checked && numIssues > 0);
    elModal.querySelector('.header').textContent = isEdit ? elModal.getAttribute('data-text-edit-label') : elModal.getAttribute('data-text-new-label');

    const curPageLink = elModal.getAttribute('data-current-page-link');
    form.action = isEdit ? `${curPageLink}/edit` : `${curPageLink}/new`;
    toggleElem(elIsArchivedField, isEdit);
    syncModalUi();
    fomanticQuery(elModal).modal({
      onApprove() {
        if (!form.checkValidity()) {
          form.reportValidity();
          return false;
        }
        form.dispatchEvent(new Event('submit', {bubbles: true}));
      },
    }).modal('show');
  };

  elModal.addEventListener('input', () => syncModalUi());

  // theoretically, if the modal exists, the "new label" button should also exist, just in case it doesn't, use "?."
  const elNewLabel = pageContent.querySelector<HTMLElement>('.ui.button.new-label');
  elNewLabel?.addEventListener('click', () => showLabelEditModal(elNewLabel));

  const elEditLabelButtons = pageContent.querySelectorAll<HTMLElement>('.edit-label-button');
  for (const btn of elEditLabelButtons) {
    btn.addEventListener('click', (e) => {
      e.preventDefault();
      showLabelEditModal(btn);
    });
  }
}