mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 19:06:18 +01:00 
			
		
		
		
	Refactor LabelEdit (#32752)
And fix a regression: https://github.com/go-gitea/gitea/pull/30053#discussion_r1874405470 Major changes: * rewrite without jquery * remove the "delete modal", using "link-action" is good enough * merge "new modal" and "edit modal"
This commit is contained in:
		| @@ -1,96 +1,81 @@ | ||||
| import $ from 'jquery'; | ||||
| import {toggleElem} from '../../utils/dom.ts'; | ||||
| import {fomanticQuery} from '../../modules/fomantic/base.ts'; | ||||
|  | ||||
| function isExclusiveScopeName(name) { | ||||
| function nameHasScope(name: string): boolean { | ||||
|   return /.*[^/]\/[^/].*/.test(name); | ||||
| } | ||||
|  | ||||
| function updateExclusiveLabelEdit(form) { | ||||
|   const nameInput = document.querySelector(`${form} .label-name-input`); | ||||
|   const exclusiveField = document.querySelector(`${form} .label-exclusive-input-field`); | ||||
|   const exclusiveCheckbox = document.querySelector(`${form} .label-exclusive-input`); | ||||
|   const exclusiveWarning = document.querySelector(`${form} .label-exclusive-warning`); | ||||
| export function initCompLabelEdit(pageSelector: string) { | ||||
|   const pageContent = document.querySelector<HTMLElement>(pageSelector); | ||||
|   if (!pageContent) return; | ||||
|  | ||||
|   if (isExclusiveScopeName(nameInput.value)) { | ||||
|     exclusiveField?.classList.remove('muted'); | ||||
|     exclusiveField?.removeAttribute('aria-disabled'); | ||||
|     if (exclusiveCheckbox.checked && exclusiveCheckbox.getAttribute('data-exclusive-warn')) { | ||||
|       exclusiveWarning?.classList.remove('tw-hidden'); | ||||
|     } else { | ||||
|       exclusiveWarning?.classList.add('tw-hidden'); | ||||
|     } | ||||
|   } else { | ||||
|     exclusiveField?.classList.add('muted'); | ||||
|     exclusiveField?.setAttribute('aria-disabled', 'true'); | ||||
|     exclusiveWarning?.classList.add('tw-hidden'); | ||||
|   // 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 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; | ||||
|   }; | ||||
|  | ||||
|   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') || ''; | ||||
|     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.submit(); | ||||
|       }, | ||||
|     }).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); | ||||
|     }); | ||||
|   } | ||||
| } | ||||
|  | ||||
| export function initCompLabelEdit(selector) { | ||||
|   if (!$(selector).length) return; | ||||
|  | ||||
|   // Create label | ||||
|   $('.new-label.button').on('click', () => { | ||||
|     updateExclusiveLabelEdit('.new-label'); | ||||
|     $('.new-label.modal').modal({ | ||||
|       onApprove() { | ||||
|         const form = document.querySelector('.new-label.form'); | ||||
|         if (!form.checkValidity()) { | ||||
|           form.reportValidity(); | ||||
|           return false; | ||||
|         } | ||||
|         $('.new-label.form').trigger('submit'); | ||||
|       }, | ||||
|     }).modal('show'); | ||||
|     return false; | ||||
|   }); | ||||
|  | ||||
|   // Edit label | ||||
|   $('.edit-label-button').on('click', function () { | ||||
|     $('#label-modal-id').val($(this).data('id')); | ||||
|  | ||||
|     const $nameInput = $('.edit-label .label-name-input'); | ||||
|     $nameInput.val($(this).data('title')); | ||||
|  | ||||
|     const $isArchivedCheckbox = $('.edit-label .label-is-archived-input'); | ||||
|     $isArchivedCheckbox[0].checked = this.hasAttribute('data-is-archived'); | ||||
|  | ||||
|     const $exclusiveCheckbox = $('.edit-label .label-exclusive-input'); | ||||
|     $exclusiveCheckbox[0].checked = this.hasAttribute('data-exclusive'); | ||||
|     // Warn when label was previously not exclusive and used in issues | ||||
|     $exclusiveCheckbox.data('exclusive-warn', | ||||
|       $(this).data('num-issues') > 0 && | ||||
|       (!this.hasAttribute('data-exclusive') || !isExclusiveScopeName($nameInput.val()))); | ||||
|     updateExclusiveLabelEdit('.edit-label'); | ||||
|  | ||||
|     $('.edit-label .label-desc-input').val(this.getAttribute('data-description')); | ||||
|  | ||||
|     const colorInput = document.querySelector('.edit-label .js-color-picker-input input'); | ||||
|     colorInput.value = this.getAttribute('data-color'); | ||||
|     colorInput.dispatchEvent(new Event('input', {bubbles: true})); | ||||
|  | ||||
|     $('.edit-label.modal').modal({ | ||||
|       onApprove() { | ||||
|         const form = document.querySelector('.edit-label.form'); | ||||
|         if (!form.checkValidity()) { | ||||
|           form.reportValidity(); | ||||
|           return false; | ||||
|         } | ||||
|         $('.edit-label.form').trigger('submit'); | ||||
|       }, | ||||
|     }).modal('show'); | ||||
|     return false; | ||||
|   }); | ||||
|  | ||||
|   $('.new-label .label-name-input').on('input', () => { | ||||
|     updateExclusiveLabelEdit('.new-label'); | ||||
|   }); | ||||
|   $('.new-label .label-exclusive-input').on('change', () => { | ||||
|     updateExclusiveLabelEdit('.new-label'); | ||||
|   }); | ||||
|   $('.edit-label .label-name-input').on('input', () => { | ||||
|     updateExclusiveLabelEdit('.edit-label'); | ||||
|   }); | ||||
|   $('.edit-label .label-exclusive-input').on('change', () => { | ||||
|     updateExclusiveLabelEdit('.edit-label'); | ||||
|   }); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user