diff --git a/public/javascript/JSON.js b/public/javascript/JSON.js
index 108ecd6..abc6033 100644
--- a/public/javascript/JSON.js
+++ b/public/javascript/JSON.js
@@ -2,7 +2,6 @@
createJsonTree({
container: domElement,
data: jsonData,
- expandInitially = true // optional: expand all nodes
onChange: (data) => { }, // optional: callback on change
onSave: (data) => { } // optional: if set, a save button will be added
});
@@ -12,7 +11,7 @@ function createJsonTree({
data,
onChange = () => {},
onSave = null,
- expandInitially = true
+ readonly = false
}) {
container.innerHTML = "";
container.classList.add("json-tree-root");
@@ -22,8 +21,6 @@ function createJsonTree({
let lastSnapshot = clone(data);
- const expandedPaths = new Set();
-
function clone(obj) {
return JSON.parse(JSON.stringify(obj));
}
@@ -70,6 +67,7 @@ function createJsonTree({
}
function undo() {
+ if (readonly) return;
if (!history.length) return;
redoStack.push(clone(data));
data = history.pop();
@@ -77,6 +75,7 @@ function createJsonTree({
}
function redo() {
+ if (readonly) return;
if (!redoStack.length) return;
history.push(clone(data));
data = redoStack.pop();
@@ -84,6 +83,7 @@ function createJsonTree({
}
function save() {
+ if (readonly) return;
if (onSave) onSave(data);
}
@@ -93,6 +93,7 @@ function createJsonTree({
}
function remove(key, parent) {
+ if (readonly) return;
if (key === null || parent == null) return;
if (!confirm("Wirklich löschen?")) return;
@@ -109,28 +110,10 @@ function createJsonTree({
render();
}
- function collectPaths(obj, path = "root") {
- if (typeof obj !== "object" || obj === null) return;
-
- expandedPaths.add(path);
-
- const entries = Array.isArray(obj)
- ? obj.map((v, i) => [i, v])
- : Object.entries(obj);
-
- for (const [k, v] of entries) {
- collectPaths(v, `${path}.${k}`);
- }
- }
-
- if (expandInitially) {
- collectPaths(data);
- }
-
function render() {
container.innerHTML = "";
- if (onSave) {
+ if (onSave && !readonly) {
const controls = document.createElement("div");
controls.className = "json-controls";
@@ -174,10 +157,13 @@ function createJsonTree({
const removeBtn = document.createElement("span");
removeBtn.className = "json-remove";
removeBtn.textContent = " [x]";
- removeBtn.onclick = (evt) => {
- evt.stopPropagation();
- remove(key, parent);
- };
+
+ if (!readonly) {
+ removeBtn.onclick = (evt) => {
+ evt.stopPropagation();
+ remove(key, parent);
+ };
+ }
// OBJECT / ARRAY
if (typeof value === "object" && value !== null) {
@@ -201,81 +187,67 @@ function createJsonTree({
const children = document.createElement("div");
children.className = "json-children";
- const toggleState = () => {
- if (expandedPaths.has(path)) {
- expandedPaths.delete(path);
- children.classList.add("collapsed");
- } else {
- expandedPaths.add(path);
- children.classList.remove("collapsed");
- }
+ keyLabel.onclick = toggle.onclick = () => {
+ if (readonly) return;
+ children.classList.toggle("collapsed");
};
- keyLabel.onclick = toggle.onclick = toggleState;
+ if (!readonly) {
+ addBtn.onclick = () => {
+ let newKey = "";
+ let newValue;
- if (expandedPaths.has(path)) {
- children.classList.remove("collapsed");
- } else {
- children.classList.add("collapsed");
+ feedbox({
+ title: `Key hinzufügen`,
+ message: `
+
+ ${!isArray ? `
+
+ ` : ``}
+
+
+ `,
+ buttons: {
+ yes: {
+ text: 'Anlegen',
+ onClick: () => {
+ pushHistory();
+
+ if (!isArray) {
+ const input = document.querySelector('#newJsonKeyName');
+ newKey = input?.value?.trim();
+ if (!newKey) return;
+ }
+
+ const selectedType = document.querySelector('#newJsonValueType').value;
+
+ switch (selectedType) {
+ case "number": newValue = 0; break;
+ case "boolean": newValue = false; break;
+ case "object": newValue = {}; break;
+ case "array": newValue = []; break;
+ default: newValue = "";
+ }
+
+ if (isArray) value.push(newValue);
+ else value[newKey] = newValue;
+
+ onChange(data);
+ render();
+ }
+ },
+ no: { text: "Abbrechen" }
+ }
+ });
+ };
}
- addBtn.onclick = () => {
- let newKey = "";
- let newValue;
-
- feedbox({
- title: `Key hinzufügen`,
- message: `
-
- ${!isArray ? `
-
- ` : ``}
-
-
- `,
- buttons: {
- yes: {
- text: 'Anlegen',
- onClick: () => {
- pushHistory();
-
- if (!isArray) {
- const input = document.querySelector('#newJsonKeyName');
- newKey = input?.value?.trim();
- if (!newKey) return;
- }
-
- const selectedType = document.querySelector('#newJsonValueType').value;
-
- switch (selectedType) {
- case "number": newValue = 0; break;
- case "boolean": newValue = false; break;
- case "object": newValue = {}; break;
- case "array": newValue = []; break;
- default: newValue = "";
- }
-
- if (isArray) {
- value.push(newValue);
- } else {
- value[newKey] = newValue;
- }
-
- onChange(data);
- render();
- }
- },
- no: { text: 'Abbrechen' }
- }
- });
- };
-
const inner = document.createElement("div");
const entries = isArray
@@ -292,9 +264,8 @@ function createJsonTree({
header.appendChild(keyLabel);
header.appendChild(toggle);
- header.appendChild(addBtn);
-
- if (key !== null) header.appendChild(removeBtn);
+ if (!readonly) header.appendChild(addBtn);
+ if (key !== null && !readonly) header.appendChild(removeBtn);
wrapper.appendChild(header);
wrapper.appendChild(children);
@@ -308,18 +279,22 @@ function createJsonTree({
input.className = "json-input string";
input.value = value;
- input.oninput = () => {
- pushHistory();
- parent[key] = input.value;
- autoResize(input);
- onChange(data);
- };
+ if (readonly) {
+ input.disabled = true;
+ } else {
+ input.oninput = () => {
+ pushHistory();
+ parent[key] = input.value;
+ autoResize(input);
+ onChange(data);
+ };
+ }
setTimeout(() => autoResize(input), 0);
wrapper.appendChild(keySpan);
wrapper.appendChild(input);
- if (key !== null) wrapper.appendChild(removeBtn);
+ if (key !== null && !readonly) wrapper.appendChild(removeBtn);
return wrapper;
}
@@ -330,18 +305,22 @@ function createJsonTree({
input.className = "json-input number";
input.value = value;
- input.oninput = () => {
- pushHistory();
- parent[key] = Number(input.value);
- autoResize(input);
- onChange(data);
- };
+ if (readonly) {
+ input.disabled = true;
+ } else {
+ input.oninput = () => {
+ pushHistory();
+ parent[key] = Number(input.value);
+ autoResize(input);
+ onChange(data);
+ };
+ }
setTimeout(() => autoResize(input), 0);
wrapper.appendChild(keySpan);
wrapper.appendChild(input);
- if (key !== null) wrapper.appendChild(removeBtn);
+ if (key !== null && !readonly) wrapper.appendChild(removeBtn);
return wrapper;
}
@@ -351,15 +330,19 @@ function createJsonTree({
input.type = "checkbox";
input.checked = value;
- input.onchange = () => {
- pushHistory();
- parent[key] = input.checked;
- onChange(data);
- };
+ if (readonly) {
+ input.disabled = true;
+ } else {
+ input.onchange = () => {
+ pushHistory();
+ parent[key] = input.checked;
+ onChange(data);
+ };
+ }
wrapper.appendChild(keySpan);
wrapper.appendChild(input);
- if (key !== null) wrapper.appendChild(removeBtn);
+ if (key !== null && !readonly) wrapper.appendChild(removeBtn);
return wrapper;
}
@@ -368,8 +351,7 @@ function createJsonTree({
wrapper.appendChild(keySpan);
wrapper.appendChild(span);
-
- if (key !== null) wrapper.appendChild(removeBtn);
+ if (key !== null && !readonly) wrapper.appendChild(removeBtn);
return wrapper;
}
diff --git a/public/views/integrated/serverinfo.hbs b/public/views/integrated/serverinfo.hbs
index 32d0b59..7e2d12c 100644
--- a/public/views/integrated/serverinfo.hbs
+++ b/public/views/integrated/serverinfo.hbs
@@ -8,8 +8,8 @@
⧉
-
-
+
+
@@ -58,21 +58,6 @@
data: [],
buffer: 5,
rowHeight: 30,
- filterConfig:{
- exceptedColumns: [ 'Erledigt' ],
- columnModes: {
- 'datetime': 'text',
- 'sAMAccountName': 'text',
- 'Note': 'text'
- },
- checkboxFilter: {
- column: 'finish',
- rules: [
- { label: 'Nur erledigte', test: v => v === true },
- { label: 'Nur unerledigte', test: v => v === false },
- ]
- }
- },
customRender: (row, tr) => {
createTd(tr,
`
@@ -87,14 +72,14 @@
}
});
- vt.addData(json.releaseNotes)
- //document.querySelector('#package').innerHTML = JSON.stringify(json.package).split(',').join('
');
-
- createJsonTree({
- container: document.getElementById("package"),
- data: json.package,
- expandInitially: true
- });
+ vt.addData(json.releaseNotes.sort((a, b) => new Date(b.datetime) - new Date(a.datetime)));
+ createJsonTree({
+ container: document.getElementById("package"),
+ data: json.package,
+ expandInitially: true,
+ readonly: true
});
+
+});
\ No newline at end of file
diff --git a/public/views/plugindashboard.hbs b/public/views/plugindashboard.hbs
index 249b7cf..2467d53 100644
--- a/public/views/plugindashboard.hbs
+++ b/public/views/plugindashboard.hbs
@@ -97,7 +97,7 @@
pluginsTabWrapper.innerHTML = '';
const objectsContainer = document.createElement('div');
- objectsContainer.className = 'card static';
+ objectsContainer.className = 'card static row';
objectsContainer.style = ``;
const card = document.createElement('div');
card.className = 'card static row';
@@ -167,14 +167,14 @@
if(typeof value === 'object') {
const objectCard = document.createElement('div');
objectCard.className = 'card static';
- objectCard.style = `min-height:400px;`;
+ objectCard.style = `flex:1;height:100%`;
objectCard.innerHTML = `
`;
objectsContainer.appendChild(objectCard);
pluginsTabWrapper.appendChild(objectsContainer);
- const menu = createJsonTree({
+ createJsonTree({
container: document.getElementById(`${metaData.name}-${key}`),
data: metaData[key],
onChange: (data) => { },
diff --git a/src/models/integratedStartMenuItems.json b/src/models/integratedStartMenuItems.json
index 2e9187e..d6a120f 100644
--- a/src/models/integratedStartMenuItems.json
+++ b/src/models/integratedStartMenuItems.json
@@ -18,15 +18,15 @@
"label": "Configs",
"view": "serverconfig",
"icon": "app.png",
+ "defaultSize": {
+ "width": "900px",
+ "height": "900px"
+ },
"permissions": [
"Administration"
]
}
]
- },
- "defaultSize": {
- "width": 800,
- "height": 600
}
},
{
@@ -49,10 +49,6 @@
]
}
]
- },
- "defaultSize": {
- "width": "1200px",
- "height": "1200px"
}
},
{
@@ -75,10 +71,6 @@
]
}
]
- },
- "defaultSize": {
- "width": "900px",
- "height": "800px"
}
},
{
@@ -101,10 +93,6 @@
]
}
]
- },
- "defaultSize": {
- "width": "900px",
- "height": "500px"
}
},
{
@@ -127,10 +115,6 @@
]
}
]
- },
- "defaultSize": {
- "width": "460px",
- "height": "515px"
}
},
{
diff --git a/src/models/releasenotes.json b/src/models/releasenotes.json
index 22a4bac..d26dfb5 100644
--- a/src/models/releasenotes.json
+++ b/src/models/releasenotes.json
@@ -54,5 +54,12 @@
"datetime": "2026-04-21",
"value": "Plugin-System + JSONtree bugfixes",
"finish": true
+ },
+ {
+ "sAMAccountName": "manuel.sowada",
+ "plugin": "System",
+ "datetime": "2026-04-23",
+ "value": "Neues Stylesheet, integratedStartMenuItems JS > JSON, JSONtree Updates, OS-Styles (Mauszeiger, Scrollbalken, Responsive Design, Window-Resize)",
+ "finish": true
}
]
diff --git a/src/routes/indexRoutes.js b/src/routes/indexRoutes.js
index 1d66fad..45dab4c 100644
--- a/src/routes/indexRoutes.js
+++ b/src/routes/indexRoutes.js
@@ -28,7 +28,7 @@ module.exports = {
let context = fs.existsSync(pluginPath)
? service.get('fileSystemManager').loadJSON(pluginPath)
- : (global.json.startMenuItems.live).find(item => item.name == name);
+ : (JSON.parse(JSON.stringify(global.json.startMenuItems.live))).find(item => item.name == name);
context.defaultSize =
context.menu.items.find(item => item.label == viewLabel)?.defaultSize ||
diff --git a/utils.js b/utils.js
index f2efa34..5a08e12 100644
--- a/utils.js
+++ b/utils.js
@@ -30,7 +30,7 @@ module.exports = startMenuItems = async function (app, sAMAccountName) {
return JSON.parse(JSON.stringify(obj));
}
- const integratedStartmenuItems = safeClone(global.json.startMenuItems.live);
+ const integratedStartmenuItems = safeClone(service.get('fileSystemManager').loadJSON(global.json.startMenuItems.filePath));
const plugins = service
.get('pluginManager')