mdboard 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.html +77 -2
- package/package.json +1 -1
- package/presets/shape-up/entities.json +4 -4
package/index.html
CHANGED
|
@@ -223,6 +223,14 @@ th.sorted .sort-arrow{opacity:1;color:var(--accent)}
|
|
|
223
223
|
.prop-value select:disabled,.prop-value input:disabled{opacity:.6;cursor:default}
|
|
224
224
|
.prop-value select:disabled:hover,.prop-value input:disabled:hover{border-color:transparent}
|
|
225
225
|
.prop-text{font-size:13px;color:var(--text2);padding:4px 8px}
|
|
226
|
+
.prop-longtext{width:100%}
|
|
227
|
+
.prop-longtext-preview{display:flex;align-items:center;gap:6px;cursor:pointer;padding:4px 8px;border-radius:var(--radius-sm);transition:background .15s;min-height:28px}
|
|
228
|
+
.prop-longtext-preview:hover{background:var(--surface2)}
|
|
229
|
+
.prop-longtext-text{flex:1;font-size:13px;color:var(--text2);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
230
|
+
.prop-longtext-toggle{font-size:9px;color:var(--text3);flex-shrink:0;transition:transform .15s}
|
|
231
|
+
.prop-longtext-editor{width:100%;min-height:80px;resize:vertical;background:var(--surface);border:1px solid var(--border);color:var(--text);padding:8px;border-radius:var(--radius-sm);font-family:var(--font);font-size:13px;line-height:1.5;outline:none;margin-top:4px;transition:border-color .2s}
|
|
232
|
+
.prop-longtext-editor:focus{border-color:var(--accent)}
|
|
233
|
+
.prop-longtext-editor:disabled{opacity:.6;cursor:default}
|
|
226
234
|
.prop-icon{flex-shrink:0}
|
|
227
235
|
.prop-row-toggle{cursor:pointer;user-select:none}
|
|
228
236
|
.prop-row-toggle:hover{background:var(--surface2);border-radius:var(--radius-sm)}
|
|
@@ -1156,6 +1164,12 @@ function renderFieldPill(item, entityType, field) {
|
|
|
1156
1164
|
}
|
|
1157
1165
|
}
|
|
1158
1166
|
|
|
1167
|
+
if (fieldDef && fieldDef.type === 'longtext') {
|
|
1168
|
+
var ltText = String(value);
|
|
1169
|
+
var ltTrunc = ltText.length > 50 ? ltText.substring(0, 50) + '...' : ltText;
|
|
1170
|
+
return '<span class="pill" style="background:var(--surface2);color:var(--text2)">' + escHtml(ltTrunc) + '</span>';
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1159
1173
|
if (fieldDef && fieldDef.type === 'number' && value != null) {
|
|
1160
1174
|
return '<span class="pill pill-points">' + value + (fieldDef.label === 'Points' ? ' pts' : '') + '</span>';
|
|
1161
1175
|
}
|
|
@@ -1185,6 +1199,12 @@ function renderFieldCell(item, entityType, col) {
|
|
|
1185
1199
|
statusIcon(entityType, value) + ' ' + escHtml(getFieldLabel(entityType, col, value)) + '</span>';
|
|
1186
1200
|
}
|
|
1187
1201
|
|
|
1202
|
+
if (fieldDef && fieldDef.type === 'longtext') {
|
|
1203
|
+
var ltText = String(value);
|
|
1204
|
+
var ltTrunc = ltText.length > 50 ? ltText.substring(0, 50) + '...' : ltText;
|
|
1205
|
+
return '<span style="color:var(--text2)">' + escHtml(ltTrunc) + '</span>';
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1188
1208
|
if (fieldDef && fieldDef.type === 'list') {
|
|
1189
1209
|
var arr = Array.isArray(value) ? value : [value];
|
|
1190
1210
|
return escHtml(arr.join(', '));
|
|
@@ -2592,11 +2612,20 @@ async function deleteCurrentNote(id) {
|
|
|
2592
2612
|
══════════════════════════════════════════════════════════════ */
|
|
2593
2613
|
var panelState = { open: false, entityType: null, item: null, isCreate: false, editor: null };
|
|
2594
2614
|
|
|
2595
|
-
function openPanel(entityType, item) {
|
|
2615
|
+
async function openPanel(entityType, item) {
|
|
2596
2616
|
panelState = { open: true, entityType: entityType, item: JSON.parse(JSON.stringify(item)), isCreate: false, editor: null };
|
|
2597
|
-
renderPanel();
|
|
2598
2617
|
document.getElementById('detail-panel').classList.add('open');
|
|
2599
2618
|
document.getElementById('panel-overlay').classList.add('open');
|
|
2619
|
+
|
|
2620
|
+
// Fetch full item with content from single endpoint
|
|
2621
|
+
var plural = getEntityPlural(entityType);
|
|
2622
|
+
var base = apiBase();
|
|
2623
|
+
var full = await fetchJson(base + '/' + plural + '/' + encodeURIComponent(item.id));
|
|
2624
|
+
if (full && full.content !== undefined) {
|
|
2625
|
+
panelState.item.content = full.content;
|
|
2626
|
+
}
|
|
2627
|
+
|
|
2628
|
+
renderPanel();
|
|
2600
2629
|
}
|
|
2601
2630
|
|
|
2602
2631
|
function closePanel() {
|
|
@@ -2773,6 +2802,38 @@ function renderPanel() {
|
|
|
2773
2802
|
});
|
|
2774
2803
|
}
|
|
2775
2804
|
|
|
2805
|
+
// Longtext expand/collapse
|
|
2806
|
+
panel.querySelectorAll('.prop-longtext-preview').forEach(function(prev) {
|
|
2807
|
+
prev.addEventListener('click', function() {
|
|
2808
|
+
var wrap = prev.parentNode;
|
|
2809
|
+
var textarea = wrap.querySelector('.prop-longtext-editor');
|
|
2810
|
+
var toggle = prev.querySelector('.prop-longtext-toggle');
|
|
2811
|
+
if (textarea.style.display === 'none') {
|
|
2812
|
+
textarea.style.display = '';
|
|
2813
|
+
prev.style.display = 'none';
|
|
2814
|
+
textarea.style.height = 'auto';
|
|
2815
|
+
textarea.style.height = Math.max(80, textarea.scrollHeight) + 'px';
|
|
2816
|
+
textarea.focus();
|
|
2817
|
+
}
|
|
2818
|
+
});
|
|
2819
|
+
});
|
|
2820
|
+
panel.querySelectorAll('.prop-longtext-editor').forEach(function(ta) {
|
|
2821
|
+
ta.addEventListener('blur', function() {
|
|
2822
|
+
var wrap = ta.parentNode;
|
|
2823
|
+
var prev = wrap.querySelector('.prop-longtext-preview');
|
|
2824
|
+
var textSpan = prev.querySelector('.prop-longtext-text');
|
|
2825
|
+
var val = ta.value || '';
|
|
2826
|
+
var truncated = val.length > 80 ? val.substring(0, 80) + '...' : (val || 'Empty');
|
|
2827
|
+
textSpan.textContent = truncated;
|
|
2828
|
+
ta.style.display = 'none';
|
|
2829
|
+
prev.style.display = '';
|
|
2830
|
+
});
|
|
2831
|
+
ta.addEventListener('input', function() {
|
|
2832
|
+
ta.style.height = 'auto';
|
|
2833
|
+
ta.style.height = Math.max(80, ta.scrollHeight) + 'px';
|
|
2834
|
+
});
|
|
2835
|
+
});
|
|
2836
|
+
|
|
2776
2837
|
// Live icon updates for enum fields
|
|
2777
2838
|
panel.querySelectorAll('select[id^="p-"]').forEach(function(sel) {
|
|
2778
2839
|
sel.addEventListener('change', function() {
|
|
@@ -2827,6 +2888,18 @@ function renderPropRow(name, field, value, entityType, isReadonly) {
|
|
|
2827
2888
|
html += '<input type="text" id="p-' + name + '" value="' + escHtml(value || '') + '" placeholder=""' + (isReadonly ? ' disabled' : '') + '>';
|
|
2828
2889
|
break;
|
|
2829
2890
|
|
|
2891
|
+
case 'longtext':
|
|
2892
|
+
var ltVal = value || '';
|
|
2893
|
+
var ltTruncated = ltVal.length > 80 ? ltVal.substring(0, 80) + '...' : ltVal;
|
|
2894
|
+
html += '<div class="prop-longtext" id="p-lt-wrap-' + name + '">';
|
|
2895
|
+
html += '<div class="prop-longtext-preview" id="p-lt-preview-' + name + '" title="Click to expand">';
|
|
2896
|
+
html += '<span class="prop-longtext-text">' + escHtml(ltTruncated || 'Empty') + '</span>';
|
|
2897
|
+
html += '<span class="prop-longtext-toggle">▼</span>';
|
|
2898
|
+
html += '</div>';
|
|
2899
|
+
html += '<textarea id="p-' + name + '" class="prop-longtext-editor" style="display:none" placeholder="Enter text..."' + (isReadonly ? ' disabled' : '') + '>' + escHtml(ltVal) + '</textarea>';
|
|
2900
|
+
html += '</div>';
|
|
2901
|
+
break;
|
|
2902
|
+
|
|
2830
2903
|
case 'list':
|
|
2831
2904
|
var listVal = Array.isArray(value) ? value.join(', ') : (value || '');
|
|
2832
2905
|
html += '<input type="text" id="p-' + name + '" value="' + escHtml(listVal) + '" placeholder="Comma-separated"' + (isReadonly ? ' disabled' : '') + '>';
|
|
@@ -2944,6 +3017,8 @@ function readFieldValue(el, fieldDef) {
|
|
|
2944
3017
|
return el.value.trim() || null;
|
|
2945
3018
|
case 'date':
|
|
2946
3019
|
return el.value || null;
|
|
3020
|
+
case 'longtext':
|
|
3021
|
+
return el.value || '';
|
|
2947
3022
|
case 'enum':
|
|
2948
3023
|
case 'string':
|
|
2949
3024
|
case 'text':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mdboard",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Git-based project management dashboard. Reads markdown files with YAML frontmatter and serves a visual kanban board, table, milestones, and metrics views.",
|
|
5
5
|
"main": "./src/server/server.js",
|
|
6
6
|
"bin": {
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
],
|
|
49
49
|
"default": "big"
|
|
50
50
|
},
|
|
51
|
-
"problem": { "type": "
|
|
52
|
-
"solution": { "type": "
|
|
51
|
+
"problem": { "type": "longtext", "label": "Problem" },
|
|
52
|
+
"solution": { "type": "longtext", "label": "Solution" },
|
|
53
53
|
"no_gos": { "type": "list", "label": "No-gos" }
|
|
54
54
|
}
|
|
55
55
|
},
|
|
@@ -115,8 +115,8 @@
|
|
|
115
115
|
],
|
|
116
116
|
"default": "big"
|
|
117
117
|
},
|
|
118
|
-
"problem": { "type": "
|
|
119
|
-
"solution": { "type": "
|
|
118
|
+
"problem": { "type": "longtext", "label": "Problem" },
|
|
119
|
+
"solution": { "type": "longtext", "label": "Solution" },
|
|
120
120
|
"no_gos": { "type": "list", "label": "No-gos" }
|
|
121
121
|
}
|
|
122
122
|
},
|