@@ -6,6 +6,7 @@ import { generalSettings } from '../utils/storage-utils';
66import { updateUrl } from '../utils/routing' ;
77import { handleDragStart , handleDragOver , handleDrop , handleDragEnd } from '../utils/drag-and-drop' ;
88import browser from '../utils/browser-polyfill' ;
9+ import { createElementWithClass , createElementWithHTML } from '../utils/dom-utils' ;
910
1011let hasUnsavedChanges = false ;
1112
@@ -26,15 +27,21 @@ export function updateTemplateList(loadedTemplates?: Template[]): void {
2627 templatesToUse . forEach ( ( template , index ) => {
2728 if ( template && template . name && template . id ) {
2829 const li = document . createElement ( 'li' ) ;
29- li . innerHTML = `
30- <div class="drag-handle">
31- <i data-lucide="grip-vertical"></i>
32- </div>
33- <span class="template-name">${ template . name } </span>
34- <button type="button" class="delete-template-btn clickable-icon" aria-label="Delete template">
35- <i data-lucide="trash-2"></i>
36- </button>
37- ` ;
30+
31+ const dragHandle = createElementWithClass ( 'div' , 'drag-handle' ) ;
32+ dragHandle . appendChild ( createElementWithHTML ( 'i' , '' , { 'data-lucide' : 'grip-vertical' } ) ) ;
33+ li . appendChild ( dragHandle ) ;
34+
35+ const templateName = createElementWithClass ( 'span' , 'template-name' ) ;
36+ templateName . textContent = template . name ;
37+ li . appendChild ( templateName ) ;
38+
39+ const deleteBtn = createElementWithClass ( 'button' , 'delete-template-btn clickable-icon' ) ;
40+ deleteBtn . setAttribute ( 'type' , 'button' ) ;
41+ deleteBtn . setAttribute ( 'aria-label' , 'Delete template' ) ;
42+ deleteBtn . appendChild ( createElementWithHTML ( 'i' , '' , { 'data-lucide' : 'trash-2' } ) ) ;
43+ li . appendChild ( deleteBtn ) ;
44+
3845 li . dataset . id = template . id ;
3946 li . dataset . index = index . toString ( ) ;
4047 li . draggable = true ;
@@ -44,13 +51,12 @@ export function updateTemplateList(loadedTemplates?: Template[]): void {
4451 showTemplateEditor ( template ) ;
4552 }
4653 } ) ;
47- const deleteBtn = li . querySelector ( '.delete-template-btn' ) ;
48- if ( deleteBtn ) {
49- deleteBtn . addEventListener ( 'click' , ( e ) => {
50- e . stopPropagation ( ) ;
51- deleteTemplate ( template . id ) ;
52- } ) ;
53- }
54+
55+ deleteBtn . addEventListener ( 'click' , ( e ) => {
56+ e . stopPropagation ( ) ;
57+ deleteTemplate ( template . id ) ;
58+ } ) ;
59+
5460 if ( index === editingTemplateIndex ) {
5561 li . classList . add ( 'active' ) ;
5662 }
@@ -173,7 +179,11 @@ export function showTemplateEditor(template: Template | null): void {
173179
174180 const vaultSelect = document . getElementById ( 'template-vault' ) as HTMLSelectElement ;
175181 if ( vaultSelect ) {
176- vaultSelect . innerHTML = '<option value="">Last used</option>' ;
182+ vaultSelect . innerHTML = '' ;
183+ const lastUsedOption = document . createElement ( 'option' ) ;
184+ lastUsedOption . value = '' ;
185+ lastUsedOption . textContent = 'Last used' ;
186+ vaultSelect . appendChild ( lastUsedOption ) ;
177187 generalSettings . vaults . forEach ( vault => {
178188 const option = document . createElement ( 'option' ) ;
179189 option . value = vault ;
@@ -238,32 +248,55 @@ export function addPropertyToEditor(name: string = '', value: string = '', type:
238248 if ( ! templateProperties ) return ;
239249
240250 const propertyId = id || Date . now ( ) . toString ( ) + Math . random ( ) . toString ( 36 ) . slice ( 2 , 11 ) ;
241- const propertyDiv = document . createElement ( 'div' ) ;
242- propertyDiv . className = 'property-editor' ;
243- propertyDiv . innerHTML = `
244- <div class="drag-handle">
245- <i data-lucide="grip-vertical"></i>
246- </div>
247- <div class="property-select">
248- <div class="property-selected" data-value="${ type } ">
249- <i data-lucide="${ getPropertyTypeIcon ( type ) } "></i>
250- </div>
251- <select class="property-type" id="${ propertyId } -type">
252- <option value="text">Text</option>
253- <option value="multitext">List</option>
254- <option value="number">Number</option>
255- <option value="checkbox">Checkbox</option>
256- <option value="date">Date</option>
257- <option value="datetime">Date & time</option>
258- </select>
259- </div>
260- <input type="text" class="property-name" id="${ propertyId } -name" value="${ name } " placeholder="Property name">
261- <input type="text" class="property-value" id="${ propertyId } -value" value="${ escapeHtml ( unescapeValue ( value ) ) } " placeholder="Property value">
262- <button type="button" class="remove-property-btn clickable-icon" aria-label="Remove property">
263- <i data-lucide="trash-2"></i>
264- </button>
265- ` ;
251+ const propertyDiv = createElementWithClass ( 'div' , 'property-editor' ) ;
266252 propertyDiv . dataset . id = propertyId ;
253+
254+ const dragHandle = createElementWithClass ( 'div' , 'drag-handle' ) ;
255+ dragHandle . appendChild ( createElementWithHTML ( 'i' , '' , { 'data-lucide' : 'grip-vertical' } ) ) ;
256+ propertyDiv . appendChild ( dragHandle ) ;
257+
258+ const propertySelectDiv = createElementWithClass ( 'div' , 'property-select' ) ;
259+ const propertySelectedDiv = createElementWithClass ( 'div' , 'property-selected' ) ;
260+ propertySelectedDiv . dataset . value = type ;
261+ propertySelectedDiv . appendChild ( createElementWithHTML ( 'i' , '' , { 'data-lucide' : getPropertyTypeIcon ( type ) } ) ) ;
262+ propertySelectDiv . appendChild ( propertySelectedDiv ) ;
263+
264+ const select = document . createElement ( 'select' ) ;
265+ select . className = 'property-type' ;
266+ select . id = `${ propertyId } -type` ;
267+ [ 'text' , 'multitext' , 'number' , 'checkbox' , 'date' , 'datetime' ] . forEach ( optionValue => {
268+ const option = document . createElement ( 'option' ) ;
269+ option . value = optionValue ;
270+ option . textContent = optionValue . charAt ( 0 ) . toUpperCase ( ) + optionValue . slice ( 1 ) ;
271+ select . appendChild ( option ) ;
272+ } ) ;
273+ propertySelectDiv . appendChild ( select ) ;
274+ propertyDiv . appendChild ( propertySelectDiv ) ;
275+
276+ const nameInput = createElementWithHTML ( 'input' , '' , {
277+ type : 'text' ,
278+ class : 'property-name' ,
279+ id : `${ propertyId } -name` ,
280+ value : name ,
281+ placeholder : 'Property name'
282+ } ) ;
283+ propertyDiv . appendChild ( nameInput ) ;
284+
285+ const valueInput = createElementWithHTML ( 'input' , '' , {
286+ type : 'text' ,
287+ class : 'property-value' ,
288+ id : `${ propertyId } -value` ,
289+ value : escapeHtml ( unescapeValue ( value ) ) ,
290+ placeholder : 'Property value'
291+ } ) ;
292+ propertyDiv . appendChild ( valueInput ) ;
293+
294+ const removeBtn = createElementWithClass ( 'button' , 'remove-property-btn clickable-icon' ) ;
295+ removeBtn . setAttribute ( 'type' , 'button' ) ;
296+ removeBtn . setAttribute ( 'aria-label' , 'Remove property' ) ;
297+ removeBtn . appendChild ( createElementWithHTML ( 'i' , '' , { 'data-lucide' : 'trash-2' } ) ) ;
298+ propertyDiv . appendChild ( removeBtn ) ;
299+
267300 templateProperties . appendChild ( propertyDiv ) ;
268301
269302 propertyDiv . addEventListener ( 'mousedown' , ( event ) => {
@@ -288,23 +321,16 @@ export function addPropertyToEditor(name: string = '', value: string = '', type:
288321 propertyDiv . addEventListener ( 'dragend' , resetDraggable ) ;
289322 propertyDiv . addEventListener ( 'mouseup' , resetDraggable ) ;
290323
291- const propertySelect = propertyDiv . querySelector ( '.property-select' ) ;
292- if ( ! propertySelect ) return ;
293-
294- const propertySelected = propertySelect . querySelector ( '.property-selected' ) ;
295- const hiddenSelect = propertySelect . querySelector ( 'select' ) ;
324+ if ( select ) {
325+ select . value = type ;
296326
297- if ( hiddenSelect ) {
298- hiddenSelect . value = type ;
299-
300- hiddenSelect . addEventListener ( 'change' , function ( ) {
301- if ( propertySelected ) updateSelectedOption ( this . value , propertySelected as HTMLElement ) ;
327+ select . addEventListener ( 'change' , function ( ) {
328+ if ( propertySelectedDiv ) updateSelectedOption ( this . value , propertySelectedDiv ) ;
302329 } ) ;
303330 }
304331
305- const removePropertyBtn = propertyDiv . querySelector ( '.remove-property-btn' ) ;
306- if ( removePropertyBtn ) {
307- removePropertyBtn . addEventListener ( 'click' , ( ) => {
332+ if ( removeBtn ) {
333+ removeBtn . addEventListener ( 'click' , ( ) => {
308334 templateProperties . removeChild ( propertyDiv ) ;
309335 } ) ;
310336 }
@@ -314,14 +340,21 @@ export function addPropertyToEditor(name: string = '', value: string = '', type:
314340 propertyDiv . addEventListener ( 'drop' , handleDrop ) ;
315341 propertyDiv . addEventListener ( 'dragend' , handleDragEnd ) ;
316342
317- if ( propertySelected ) updateSelectedOption ( type , propertySelected as HTMLElement ) ;
343+ updateSelectedOption ( type , propertySelectedDiv ) ;
318344
319345 initializeIcons ( propertyDiv ) ;
320346}
321347
322348function updateSelectedOption ( value : string , propertySelected : HTMLElement ) : void {
323349 const iconName = getPropertyTypeIcon ( value ) ;
324- propertySelected . innerHTML = `<i data-lucide="${ iconName } "></i>` ;
350+
351+ // Clear existing content
352+ propertySelected . innerHTML = '' ;
353+
354+ // Create and append the new icon element
355+ const iconElement = createElementWithHTML ( 'i' , '' , { 'data-lucide' : iconName } ) ;
356+ propertySelected . appendChild ( iconElement ) ;
357+
325358 propertySelected . setAttribute ( 'data-value' , value ) ;
326359 initializeIcons ( propertySelected ) ;
327360}
0 commit comments