diff options
| author | historia <[not public]> | 2026-07-12 21:16:58 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-07-12 21:16:58 -0400 |
| commit | f601a40776843f6196221e74ba502c571a5b1bcd (patch) | |
| tree | a5b3fc0ae5b8774d642439fc4d369b96bf3932ab /internal/admin/static | |
| parent | beb0b73a9e56fdc717d55bbf1a1c7c5b49d4c6a4 (diff) | |
| download | thehouseoficarus-f601a40776843f6196221e74ba502c571a5b1bcd.tar.gz | |
fix(admin): standardize most search dropdowns and radio buttons
Diffstat (limited to 'internal/admin/static')
| -rw-r--r-- | internal/admin/static/admin.css | 29 | ||||
| -rw-r--r-- | internal/admin/static/cardeditor.js | 48 | ||||
| -rw-r--r-- | internal/admin/static/hazardeditor.js | 2 | ||||
| -rw-r--r-- | internal/admin/static/itemeditor.js | 23 | ||||
| -rw-r--r-- | internal/admin/static/mobeditor.js | 38 | ||||
| -rw-r--r-- | internal/admin/static/moduleeditor.js | 8 | ||||
| -rw-r--r-- | internal/admin/static/talktree.js | 8 | ||||
| -rw-r--r-- | internal/admin/static/techeditor.js | 4 |
8 files changed, 131 insertions, 29 deletions
diff --git a/internal/admin/static/admin.css b/internal/admin/static/admin.css index c500aad..a1a364e 100644 --- a/internal/admin/static/admin.css +++ b/internal/admin/static/admin.css @@ -38,7 +38,8 @@ body{font-family:monospace;background:var(--bg);color:var(--text);display:flex;f .table a{color:var(--text);text-decoration:none} .table a:hover{color:#fff} .search-bar{margin-bottom:12px} -.search-bar input{width:100%;padding:6px 8px;font-size:13px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px} +.search-bar input{width:100%;padding:6px 28px 6px 8px;font-size:13px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 8px center} +input.search-input{padding-right:24px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center} .login{max-width:360px;margin:80px auto;background:var(--panel);padding:30px;border:1px solid var(--border);border-radius:6px} .login h1{font-size:18px;margin-bottom:20px;text-align:center} .z-controls-wrapper{position:absolute;top:12px;left:12px;z-index:10} @@ -278,7 +279,7 @@ g.ud-hover:hover text{font-weight:bold} .panel-tab-content .entry-fields textarea{resize:vertical;min-height:28px} .panel-tab-content .entry-fields .entry-id{font-size:11px;color:#6cf;display:block;padding:3px 0} .panel-tab-content .section-search{position:relative;margin-top:4px} -.panel-tab-content .search-input{width:100%;padding:4px 6px;font-size:11px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace} +.panel-tab-content .search-input{width:100%;padding:4px 24px 4px 6px;font-size:11px;background-color:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace} .panel-tab-content .search-results{position:absolute;top:100%;left:0;right:0;max-height:160px;overflow-y:auto;background:var(--panel);border:1px solid var(--border);border-radius:3px;z-index:50;box-shadow:0 4px 12px rgba(0,0,0,.4)} .panel-tab-content .search-results .sr-item{padding:4px 8px;font-size:11px;cursor:pointer;color:var(--text);border-bottom:1px solid rgba(255,255,255,.03)} .panel-tab-content .search-results .sr-item:hover,.panel-tab-content .search-results .sr-item.active{background:var(--accent)} @@ -300,7 +301,7 @@ g.ud-hover:hover text{font-weight:bold} .obj-card-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:6px 8px} .obj-field{display:flex;flex-direction:column;gap:2px;font-size:11px} .obj-field span{color:#888;font-size:9px;text-transform:uppercase;letter-spacing:.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} -.obj-field input,.obj-field textarea,.obj-field select{padding:4px 6px;font-size:11px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace;width:100%} +.obj-field input,.obj-field textarea,.obj-field select{padding:4px 6px;font-size:11px;background-color:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:3px;font-family:monospace;width:100%} .obj-field textarea{resize:vertical;min-height:28px} .obj-field.obj-wide{grid-column:1/-1} .obj-field.obj-check{flex-direction:row;align-items:center;gap:4px;padding-bottom:3px} @@ -313,6 +314,15 @@ g.ud-hover:hover text{font-weight:bold} .seg-toggle input:checked+span{color:#3a8fd4} .seg-toggle label:has(input:checked){color:var(--text);background:var(--accent)} .seg-toggle input{position:absolute;opacity:0;pointer-events:none;width:0;height:0} +.seg-pill{position:relative;border-radius:6px;background:var(--input-bg);display:inline-flex;border:1px solid var(--border)} +.seg-pill .seg-opt{flex:1;text-align:center;position:relative;z-index:1;padding:5px 14px;font-size:11px;cursor:pointer;color:#888;background:transparent;border:none;font-family:monospace;transition:color .15s} +.seg-pill .seg-opt:hover{color:var(--text)} +.seg-pill .seg-opt.seg-active{color:var(--text)} +.seg-pill::before{content:'';position:absolute;top:2px;bottom:2px;left:0;width:calc(100% / 3);background:var(--accent);border-radius:4px;transition:transform .2s ease;z-index:0} +.seg-pill.seg-pill-3.seg-idx-0::before{transform:translateX(0)} +.seg-pill.seg-pill-3.seg-idx-1::before{transform:translateX(100%)} +.seg-pill.seg-pill-3.seg-idx-2::before{transform:translateX(200%)} +.seg-pill .seg-opt:focus-visible{outline:2px solid var(--accent);outline-offset:-1px;border-radius:3px;z-index:2} .obj-color-row{display:flex;align-items:center;gap:4px} .obj-color-row .color-swatch{flex-shrink:0} .obj-color-row input{width:38px!important;text-align:center;padding:4px 2px} @@ -335,16 +345,21 @@ g.ud-hover:hover text{font-weight:bold} .add-section-bar button{padding:4px 12px;font-size:11px} .obj-kv-list{margin-top:4px} .obj-kv-row{display:flex;gap:4px;align-items:center;margin-bottom:3px} -.obj-kv-row input{padding:3px 5px;font-size:10px;background:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:2px;font-family:monospace;flex:1} +.obj-kv-row input{padding:3px 5px;font-size:10px;background-color:var(--input-bg);color:var(--text);border:1px solid var(--input-border);border-radius:2px;font-family:monospace;flex:1} .obj-kv-row .obj-kv-key{flex:1} +.obj-kv-key-wrap.obj-search{position:relative!important} +.obj-kv-key-wrap.obj-search .search-input.obj-kv-key{width:100%;flex:none;padding-right:24px} +.obj-kv-key-wrap.obj-search .search-results{position:absolute;top:100%;left:0;right:0;max-height:160px;overflow-y:auto;background:var(--panel);border:1px solid var(--border);border-radius:3px;z-index:50;box-shadow:0 4px 12px rgba(0,0,0,.4);margin-top:2px} +.obj-kv-key-wrap.obj-search .search-results .sr-item{padding:4px 8px;font-size:11px;cursor:pointer;color:var(--text);border-bottom:1px solid rgba(255,255,255,.03)} +.obj-kv-key-wrap.obj-search .search-results .sr-item:hover,.obj-kv-key-wrap.obj-search .search-results .sr-item.active{background:var(--accent)} .obj-kv-row .obj-kv-val{width:70px;flex:none} .obj-core-row{display:flex;gap:6px;align-items:flex-end;margin-bottom:8px} -.obj-field-error input,.obj-field-error textarea,.obj-field-error select{border-color:var(--danger)!important;background:rgba(192,57,43,.08)} +.obj-field-error input,.obj-field-error textarea,.obj-field-error select{border-color:var(--danger)!important;background-color:rgba(192,57,43,.08)} .obj-search{position:relative!important} .obj-search .search-results{position:absolute;top:100%;left:0;right:0;max-height:160px;overflow-y:auto;background:var(--panel);border:1px solid var(--border);border-radius:3px;z-index:50;box-shadow:0 4px 12px rgba(0,0,0,.4);margin-top:2px} .obj-search .search-results .sr-item{padding:4px 8px;font-size:11px;cursor:pointer;color:var(--text);border-bottom:1px solid rgba(255,255,255,.03)} .obj-search .search-results .sr-item:hover,.obj-search .search-results .sr-item.active{background:var(--accent)} -.obj-search input.search-input{padding-right:24px;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23888' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 6px center} +.obj-search input.search-input{padding-right:24px} .obj-search input.search-input::placeholder{color:#666} .obj-narrow.obj-search input{width:80px} .obj-sub-row .obj-search input.search-input{min-width:80px} @@ -475,3 +490,5 @@ g.ud-hover:hover text{font-weight:bold} .obj-card[data-card="trigger_action"]>.obj-card-body>.obj-sub-add{display:none} .obj-card[data-card="trigger_action"] .ie-inter-header .ie-trig-up, .obj-card[data-card="trigger_action"] .ie-inter-header .ie-trig-dn{display:none} +input:focus-visible,select:focus-visible,textarea:focus-visible,button:focus-visible{outline:2px solid rgba(100,160,255,.5);outline-offset:1px} +.sr-no-results{padding:6px 8px;font-size:11px;color:#666;text-align:center;cursor:default;pointer-events:none} diff --git a/internal/admin/static/cardeditor.js b/internal/admin/static/cardeditor.js index 1e8d259..1b2b76b 100644 --- a/internal/admin/static/cardeditor.js +++ b/internal/admin/static/cardeditor.js @@ -90,6 +90,46 @@ function ced_addKVRow(cardID, subKey) { el.appendChild(row); } +function ced_buildDynamicSelect(fid, dpAttr, val, dynKey) { + var items = (window._dynOpts && window._dynOpts[dynKey]) ? window._dynOpts[dynKey].slice().sort() : []; + var s = '<select id="' + fid + '"' + dpAttr + '>'; + s += '<option value="">(none)</option>'; + items.forEach(function(o) { + s += '<option value="' + escAttr(o) + '"' + (String(val) === o ? ' selected' : '') + '>' + esc(o) + '</option>'; + }); + s += '</select>'; + return s; +} + +function ced_renderKVSearch(sec, il, data, getter) { + var sectionRoot = data[ced_cardPath(sec)] || data; + var map = getter ? getter(sectionRoot, il) : (sectionRoot[il.key] || {}); + var entity = il.searchEntity || 'items'; + var h = '<div class="obj-inline-group">'; + h += '<span class="obj-inline-label">' + esc(il.label) + '</span>'; + h += '<div class="obj-kv-list" data-sec="' + sec.id + '" data-key="' + il.key + '">'; + Object.keys(map).forEach(function(k, idx) { + h += '<div class="obj-kv-row">'; + h += '<div class="obj-kv-key-wrap obj-search" style="flex:1;position:relative"><div style="position:relative;width:100%"><input value="' + escAttr(k) + '" class="search-input obj-kv-key" data-search-type="' + entity + '" placeholder="Search ' + entity + '..."><div class="search-results" style="display:none"></div></div></div>'; + h += '<input value="' + escAttr(String(map[k])) + '" placeholder="val" class="obj-kv-val">'; + h += '<button class="btn btn-sm btn-danger" onclick="this.parentElement.remove()">X</button></div>'; + }); + h += '</div>'; + h += '<button class="btn btn-sm obj-sub-add" onclick="ced_addKVSearchRow(\'' + sec.id + '\',\'' + il.key + '\',\'' + entity + '\')">+ Add</button>'; + h += '</div>'; + return h; +} + +function ced_addKVSearchRow(cardID, subKey, entity) { + var el = document.querySelector('.obj-kv-list[data-sec="' + cardID + '"][data-key="' + subKey + '"]'); + if (!el) return; + var row = document.createElement('div'); + row.className = 'obj-kv-row'; + row.innerHTML = '<div class="obj-kv-key-wrap obj-search" style="flex:1;position:relative"><div style="position:relative;width:100%"><input value="" class="search-input obj-kv-key" data-search-type="' + entity + '" placeholder="Search ' + entity + '..."><div class="search-results" style="display:none"></div></div></div><input value="0" placeholder="val" class="obj-kv-val"><button class="btn btn-sm btn-danger" onclick="this.parentElement.remove()">X</button>'; + el.appendChild(row); + ced_setupSearchFields(row); +} + // ---- Search autocomplete ---- function ced_setupSearchFields(root) { @@ -114,7 +154,7 @@ function ced_setupSearchFields(root) { if (entityType === 'drops' && data.drops) items = data.drops; if (items.length === 0) { results.style.display = 'block'; - results.innerHTML = '<div class="sr-item" style="color:#888">No results</div>'; + results.innerHTML = '<div class="sr-item sr-no-results">No results</div>'; return; } results.style.display = 'block'; @@ -315,6 +355,10 @@ function ced_renderField(sec, f, data, idx, subPath, optStyle, cardPathFn, field return wrap('obj-field', '<span>' + esc(label) + '</span><textarea id="' + fid + '" rows="3"' + dpAttr + '>' + esc(dstr) + '</textarea>'); } if (type === 'select') { + if (hint && hint.indexOf('dyn:') === 0) { + var inner = '<span>' + esc(label) + '</span>' + ced_buildDynamicSelect(fid, dpAttr, val, hint.substring(4)); + return wrap('obj-field', inner); + } var opts = hint ? hint.split('|') : []; var inner = '<span>' + esc(label) + '</span><select id="' + fid + '"' + dpAttr + '>'; opts.forEach(function(o) { @@ -423,7 +467,7 @@ function ced_saveInlineFields(sec, sectionObj, cardPathFn, fieldIDFn) { sectionObj[il.key] = el.value.split(',').map(function(s) { return s.trim(); }).filter(function(s) { return s; }); hasValues = true; } - } else if (il.type === 'kv') { + } else if (il.type === 'kv' || il.type === 'kv_search') { var kvEl = document.querySelector('.obj-kv-list[data-sec="' + sec.id + '"][data-key="' + il.key + '"]'); if (kvEl) { var map = {}; diff --git a/internal/admin/static/hazardeditor.js b/internal/admin/static/hazardeditor.js index 10def4b..e849512 100644 --- a/internal/admin/static/hazardeditor.js +++ b/internal/admin/static/hazardeditor.js @@ -13,7 +13,7 @@ var HAZARD_SECTIONS = [ ['warn_message', 'Warn Message', 'text', 'The air grows thick with toxic fumes...', 'wide'], ['hit_message', 'Hit Message', 'text', 'You cough and choke on the toxic gas!'], ['miss_message', 'Miss Message', 'text', 'You hold your breath and avoid the fumes.'], - ['required_item', 'Required Item', 'text', 'e.g. gas_mask'], + ['required_item', 'Required Item', 'search', 'e.g. gas_mask', '', null, 'items'], ['speed', 'Speed', 'number', '10', 'narrow'], ] }, diff --git a/internal/admin/static/itemeditor.js b/internal/admin/static/itemeditor.js index 53242ab..d48d70e 100644 --- a/internal/admin/static/itemeditor.js +++ b/internal/admin/static/itemeditor.js @@ -53,8 +53,8 @@ var SECTIONS = [ ['xp', 'XP', 'number', '', 'narrow'], ['ticks_per_cycle', 'Ticks/Cycle', 'number', '', 'narrow'], ['output_qty', 'Output Qty', 'number', '', 'narrow'], - ['station', 'Station', 'select', '|anvil|cooking_range|fire|furnace|pottery_oven|pottery_wheel|spinning_wheel|workbench'], - ['tool', 'Tool', 'select', '|pickaxe|axe|fire|chisel|hammer|knife|needle|rake|saw|shears|spade|watering_can|fishing_rod|fly_rod|harpoon|small_net|big_net|lobster_pot'], + ['station', 'Station', 'select', 'dyn:stations'], + ['tool', 'Tool', 'select', 'dyn:tools'], ['fail', 'Fail Item', 'search', 'e.g. burnt_fish', '', null, 'items'], ['success_base', 'Base', 'number', '0.5', 'narrow'], ['success_per_level', 'Per Lvl', 'number', '0.01', 'narrow'], @@ -125,6 +125,7 @@ function initItemEditor() { window._ieRenderCurrent = renderCurrent; window._ieRenderOnly = function() { if (itemID && itemData) renderItemEditor(itemID, itemData); }; window._ieSyncAll = function(ed) { if (ed) ie_syncAllInteractions(ed, SECTIONS); }; + fetchDynamicOptions(); editorType = 'items'; editorFields = []; loadList(); @@ -647,7 +648,11 @@ function renderSubFieldHTML(sec, stKey, idx, f, val) { return '<label class="obj-field obj-check' + extraCls + '"' + extraStyle + '><input type="checkbox" id="' + fid + '"' + (val ? ' checked' : '') + dpAttr + '> <span>' + esc(f[1]) + '</span></label>'; } if (f[2] === 'select') { - var opts = f[3] ? f[3].split('|') : []; + var hint = f[3] || ''; + if (hint.indexOf('dyn:') === 0) { + return '<label class="obj-field' + extraCls + '"' + extraStyle + '><span>' + esc(f[1]) + '</span>' + ced_buildDynamicSelect(fid, dpAttr, val, hint.substring(4)) + '</label>'; + } + var opts = hint.split('|'); var sel = '<label class="obj-field' + extraCls + '"' + extraStyle + '><span>' + esc(f[1]) + '</span><select id="' + fid + '"' + dpAttr + '>'; opts.forEach(function(o) { sel += '<option value="' + escAttr(o) + '"' + (String(val) === o ? ' selected' : '') + '>' + esc(o || '(none)') + '</option>'; @@ -1244,6 +1249,18 @@ function selectSearchResult(el) { ced_selectSearchResult(el); } function updateSearchHighlight(results) { ced_updateSearchHighlight(results); } +function fetchDynamicOptions() { + Promise.all([ + API.get('/api/tools').catch(function() { return []; }), + API.get('/api/stations').catch(function() { return []; }) + ]).then(function(results) { + window._dynOpts = window._dynOpts || {}; + window._dynOpts.tools = results[0] || []; + window._dynOpts.stations = results[1] || []; + if (itemID && itemData) renderCurrent(); + }); +} + // ========================================================================= // Validation // ========================================================================= diff --git a/internal/admin/static/mobeditor.js b/internal/admin/static/mobeditor.js index 2c8db21..3934fcd 100644 --- a/internal/admin/static/mobeditor.js +++ b/internal/admin/static/mobeditor.js @@ -46,7 +46,7 @@ var MOB_SECTIONS = [ ['stats.defenses.crush_defense', 'Crush Def', 'number', '0', 'narrow'], ['stats.defenses.science_defense', 'Sci Def', 'number', '0', 'narrow'], ['stats.defenses.ranged_defense', 'Rng Def', 'number', '0', 'narrow'], - ['stats.defenses.weakness', 'Weakness', 'text', 'e.g. crush'], + ['stats.defenses.weakness', 'Weakness', 'select', '|bio|eco|hydro|solar|chaos'], ['stats.defenses.weakness_percent', 'Weakness %', 'number', '50', 'narrow'], ['assassin_level', 'Assassin Lvl', 'number', '1', 'narrow'], ['finishing_blow', 'Finishing Blow', 'search', 'e.g. stake', '', null, 'items'], @@ -314,19 +314,22 @@ function normalizeAttackTypes(v) { } // renderMobAttackTypeWidget renders the Atk Type selector: one required melee -// type (radio: stab/slash/crush) plus optional ranged/science (checkboxes). +// type (pill: stab/slash/crush) plus optional ranged/science (checkboxes). function renderMobAttackTypeWidget(data) { var combat = data.combat || {}; var types = normalizeAttackTypes(combat.attack_types); var melee = types.filter(function(t) { return t === 'stab' || t === 'slash' || t === 'crush'; })[0] || 'crush'; var hasRanged = types.indexOf('ranged') >= 0; var hasScience = types.indexOf('science') >= 0; + var meleeOpts = ['stab','slash','crush']; + var activeIdx = meleeOpts.indexOf(melee); + if (activeIdx < 0) activeIdx = 2; var h = '<div class="obj-inline-group">'; h += '<span class="obj-inline-label">Atk Type</span>'; - h += '<div class="obj-card-grid" style="margin-top:4px">'; - ['stab','slash','crush'].forEach(function(m) { - h += '<label class="obj-field obj-check obj-narrow"><input type="radio" name="mob_atktype_melee" value="' + m + '"' + (melee === m ? ' checked' : '') + '> <span>' + m + '</span></label>'; + h += '<div class="seg-pill seg-pill-3 seg-idx-' + activeIdx + '" id="mob_atktype_pill" style="margin-top:4px">'; + meleeOpts.forEach(function(t, i) { + h += '<button type="button" class="seg-opt' + (i === activeIdx ? ' seg-active' : '') + '" data-v="' + t + '" onclick="mobAtkPillSelect(\'' + t + '\',this)">' + t + '</button>'; }); h += '</div>'; h += '<div class="obj-card-grid" style="margin-top:4px">'; @@ -337,12 +340,31 @@ function renderMobAttackTypeWidget(data) { return h; } +function mobAtkPillSelect(val, btn) { + var pill = document.getElementById('mob_atktype_pill'); + if (!pill) return; + var opts = pill.querySelectorAll('.seg-opt'); + var idx = -1; + opts.forEach(function(o, i) { + if (o.getAttribute('data-v') === val) { + o.classList.add('seg-active'); + idx = i; + } else { + o.classList.remove('seg-active'); + } + }); + pill.className = pill.className.replace(/seg-idx-\d/g, 'seg-idx-' + idx); +} + // collectMobAttackType reads the Atk Type widget into an array: the selected // melee type first, then any optional ranged/science types. function collectMobAttackType() { var melee = 'crush'; - var r = document.querySelector('input[name="mob_atktype_melee"]:checked'); - if (r) melee = r.value; + var pill = document.getElementById('mob_atktype_pill'); + if (pill) { + var active = pill.querySelector('.seg-opt.seg-active'); + if (active) melee = active.getAttribute('data-v'); + } var out = [melee]; var rng = document.getElementById('mob_atktype_ranged'); var sci = document.getElementById('mob_atktype_science'); @@ -852,7 +874,7 @@ function saveMob() { hasValues = ced_saveSectionFields(sec, sectionObj, cardPath, fieldID) || hasValues; } - if (sec.id === 'combat' && document.querySelector('input[name="mob_atktype_melee"]')) { + if (sec.id === 'combat' && document.getElementById('mob_atktype_pill')) { sectionObj['attack_types'] = collectMobAttackType(); hasValues = true; } diff --git a/internal/admin/static/moduleeditor.js b/internal/admin/static/moduleeditor.js index 739fc2e..fe71f88 100644 --- a/internal/admin/static/moduleeditor.js +++ b/internal/admin/static/moduleeditor.js @@ -13,11 +13,11 @@ var MODULE_SECTIONS = [ ['max_hit', 'Max Hit', 'number', '10', 'narrow'], ['base_xp', 'Base XP', 'number', '50', 'narrow'], ['category', 'Category', 'select', 'combat|utility|enchant|processing|transport'], - ['element', 'Element', 'text', 'e.g. fire'], + ['element', 'Element', 'select', '|bio|eco|hydro|solar|chaos'], ['destination', 'Destination', 'number', '5', 'narrow'], ], inline: [ - {label:'Junk Cost', key:'junk_cost', type:'kv', valType:'number'}, + {label:'Junk Cost', key:'junk_cost', type:'kv_search', searchEntity:'items', valType:'number'}, ] }, { @@ -144,6 +144,8 @@ function renderCard(sec, data) { sec.inline.forEach(function(il) { if (il.type === 'kv') { h += ced_renderKV(sec, il, data); + } else if (il.type === 'kv_search') { + h += ced_renderKVSearch(sec, il, data); } }); } @@ -274,7 +276,7 @@ function saveModule() { if (sec.inline) { sec.inline.forEach(function(il) { - if (il.type === 'kv') { + if (il.type === 'kv' || il.type === 'kv_search') { var kvEl = document.querySelector('.obj-kv-list[data-sec="' + sec.id + '"][data-key="' + il.key + '"]'); if (kvEl) { var map = {}; diff --git a/internal/admin/static/talktree.js b/internal/admin/static/talktree.js index b8c7106..e55653e 100644 --- a/internal/admin/static/talktree.js +++ b/internal/admin/static/talktree.js @@ -207,7 +207,7 @@ else if (type === 'number') { var n = parseFloat(el.value); val = isNaN(n) ? 0 : n; } else { val = el.value; } talkSyncPath(path, val); - if (path.endsWith('.goto')) renderTalkTree(window._talkData); + if (path.endsWith('.goto') && e.type === 'change') renderTalkTree(window._talkData); } else if (tag === 'SELECT') { talkSyncPath(path, el.value); } @@ -492,7 +492,7 @@ label = label || 'Auto-advance to'; return '<div class="talk-goto-fallback">' + '<span class="talk-prop-label">' + esc(label) + '</span>' + - '<input class="talk-input talk-input-sm" data-tp="nodes.' + escAttr(nodeKey) + '.goto" list="talkNodeKeys" value="' + escAttr(node.goto || '') + '" placeholder="Fallback node...">' + + '<input class="talk-input talk-input-sm search-input" data-tp="nodes.' + escAttr(nodeKey) + '.goto" list="talkNodeKeys" value="' + escAttr(node.goto || '') + '" placeholder="Fallback node...">' + '</div>'; } @@ -530,7 +530,7 @@ html += '<div class="talk-opt-edit-row">'; html += '<span class="talk-seq-num">' + (idx + 1) + '</span>'; html += '<input class="talk-input talk-opt-text" data-tp="nodes.' + escAttr(nodeKey) + '.options.' + idx + '.text" value="' + escAttr(opt.text || '') + '" placeholder="Option text...">'; - html += '<input class="talk-input talk-opt-goto" data-tp="nodes.' + escAttr(nodeKey) + '.options.' + idx + '.goto" list="talkNodeKeys" value="' + escAttr(opt.goto || '') + '" placeholder="Goto...">'; + html += '<input class="talk-input talk-opt-goto search-input" data-tp="nodes.' + escAttr(nodeKey) + '.options.' + idx + '.goto" list="talkNodeKeys" value="' + escAttr(opt.goto || '') + '" placeholder="Goto...">'; html += '<div class="talk-opt-edit-actions">'; if (opt.condition && typeof opt.condition === 'object' && !Array.isArray(opt.condition)) { @@ -582,7 +582,7 @@ html += '<div class="talk-add-opt-row">' + '<span class="talk-seq-num" style="color:#555">' + (options.length + 1) + '</span>' + '<input class="talk-input talk-opt-text" id="talkOptText_' + escAttr(nodeKey) + '" placeholder="Option text...">' + - '<input class="talk-input talk-opt-goto" id="talkOptGoto_' + escAttr(nodeKey) + '" list="talkNodeKeys" placeholder="Goto...">' + + '<input class="talk-input talk-opt-goto search-input" id="talkOptGoto_' + escAttr(nodeKey) + '" list="talkNodeKeys" placeholder="Goto...">' + '<span class="talk-opt-gap"></span>' + '<button class="talk-add-btn" data-action="add-option" data-nk="' + escAttr(nodeKey) + '">Add</button>' + '</div>'; diff --git a/internal/admin/static/techeditor.js b/internal/admin/static/techeditor.js index c9d7c24..812cded 100644 --- a/internal/admin/static/techeditor.js +++ b/internal/admin/static/techeditor.js @@ -10,8 +10,8 @@ var TECH_SECTIONS = [ ['name', 'Name', 'text', 'Protect from Melee'], ['level', 'Level', 'number', '37', 'narrow'], ['drain_rate', 'Drain Rate', 'number', '0.5', 'narrow'], - ['category', 'Category', 'text', 'protection'], - ['group', 'Group', 'text', 'melee'], + ['category', 'Category', 'select', '|accuracy|combo|defense|protection|ranged|science|strength|utility'], + ['group', 'Group', 'select', '|accuracy_tier|defense_tier|protection|ranged_tier|regen_tier|science_tier|strength_tier'], ] }, { |
