Skip to content

Commit 1198f47

Browse files
committed
improve dev-tools in model
1 parent c0c9140 commit 1198f47

7 files changed

+191
-54
lines changed

__html__/model.html

+2-5
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,13 @@
1717
</nav>
1818

1919
<div id="root" class="h-100 d-flex flex-center flex-column">
20-
<ul>
21-
<li data-for="item in items">{{ item }}</li>
22-
</ul>
2320
<div class="h1">Counter</div>
2421
<div class="m-2">Counter: {{ counter }}</div>
2522
<div class="m-2"><input class="text-center" type="text" data-model="counter"></div>
2623
<div>Статус: {{ status }}</div>
2724
<div class="m-2 d-flex flex-row gap-2">
28-
<button onclick="updateCounter('+')">Inc Counter</button>
29-
<button onclick="updateCounter('-')">Dec Counter</button>
25+
<button onclick="updateCounter('+')">+</button>
26+
<button onclick="updateCounter('-')">-</button>
3027
</div>
3128
</div>
3229

lib/metro.all.js

+90-20
Original file line numberDiff line numberDiff line change
@@ -9386,6 +9386,14 @@
93869386
border: 1px solid #333;
93879387
z-index: 9999;
93889388
font-family: monospace;
9389+
9390+
.devtools-section:not(:last-child) {
9391+
border-bottom: 1px solid #333;
9392+
}
9393+
9394+
h3 {
9395+
margin: 0;
9396+
}
93899397
}
93909398

93919399
#model-dev-tools-toggle-button {
@@ -9403,25 +9411,34 @@
94039411

94049412
#model-devtools-time-travel-dialog {
94059413
position: fixed;
9406-
top: 50%;
9407-
left: 50%;
9408-
transform: translate(-50%, -50%);
9414+
bottom: 0;
9415+
right: 300px;
94099416
background: #2a2a2a;
9410-
padding: 10px;
94119417
border: 1px solid #444;
94129418
border-radius: 4px;
9413-
max-height: 80vh;
9414-
overflow-y: auto;
9419+
height: 400px;
9420+
width: 300px;
94159421
z-index: 10000;
94169422
color: #fff;
94179423
font-family: monospace;
94189424

9425+
.time-travel-items {
9426+
padding: 8px; height: calc(100% - 35px);
9427+
overflow: auto;
9428+
position: relative;
9429+
}
9430+
94199431
.time-travel-item {
94209432
padding: 8px;
9421-
margin: 4px 0;
9433+
margin: 4px;
94229434
border: 1px solid #444;
94239435
cursor: pointer;
94249436
hover: background-color: #333;
9437+
9438+
button {
9439+
margin-top: 8px;
9440+
background: dodgerblue;
9441+
}
94259442
}
94269443
}
94279444

@@ -9451,6 +9468,13 @@
94519468
}
94529469
}
94539470
}
9471+
9472+
.dev-tools-header {
9473+
padding: 8px;
9474+
border-bottom: 1px solid #333;
9475+
display: flex;
9476+
justify-content: space-between;
9477+
}
94549478
</style>
94559479
`;
94569480
var ModelDevTools = class {
@@ -9478,7 +9502,7 @@
94789502
const header2 = document.createElement("div");
94799503
header2.innerHTML = `
94809504
${DevToolsWindowStyle}
9481-
<div style="padding: 8px; border-bottom: 1px solid #333; display: flex; justify-content: space-between;">
9505+
<div class="dev-tools-header">
94829506
<span>Model DevTools</span>
94839507
<div>
94849508
<button id="devtools-time-travel" title="Time Travel">\u23F1</button>
@@ -9501,30 +9525,38 @@
95019525
document.getElementById("devtools-time-travel").onclick = () => this.showTimeTravelDialog();
95029526
}
95039527
showTimeTravelDialog() {
9504-
const dialog2 = document.createElement("div");
9505-
dialog2.id = "model-devtools-time-travel-dialog";
9528+
let dialog2 = document.getElementById("model-devtools-time-travel-dialog");
9529+
if (!dialog2) {
9530+
dialog2 = document.createElement("div");
9531+
dialog2.id = "model-devtools-time-travel-dialog";
9532+
}
95069533
const statesList = this.history.map((snapshot, index) => `
95079534
<div class="time-travel-item">
95089535
<div>Time: ${new Date(snapshot.timestamp).toLocaleTimeString()}</div>
95099536
<div>Type: ${snapshot.type}</div>
95109537
<div>Property: ${snapshot.property || snapshot.event || snapshot.path || ""}</div>
95119538
<div>Value: ${snapshot.oldValue + " -> " + snapshot.newValue}</div>
9512-
<button style="margin-top: 8px; background: dodgerblue;" onclick="window.__MODEL_DEVTOOLS__.timeTravel(${index})">
9539+
<button data-time-travel-index="${index}">
95139540
Go to this state
95149541
</button>
95159542
</div>
95169543
`).join("");
95179544
dialog2.innerHTML = `
9518-
<div style="display: flex; gap: 10px;">
9519-
<h3 style="margin: 0">Time Travel</h3>
9545+
<div class="dev-tools-header">
9546+
<span>Time Travel</span>
95209547
<button style="margin-left: auto" onclick="this.parentElement.parentElement.remove()">\xD7</button>
95219548
</div>
9522-
<div>${statesList || "Nothing to show!"}</div>
9549+
<div class="time-travel-items">${statesList || '<div style="height: 100%; display: flex; align-items: center; justify-content: center;">Nothing to show!</div>'}</div>
95239550
`;
95249551
document.body.appendChild(dialog2);
9552+
dialog2.querySelectorAll("[data-time-travel-index]").forEach((button2) => {
9553+
button2.onclick = () => {
9554+
const index = button2.getAttribute("data-time-travel-index");
9555+
this.timeTravel(index);
9556+
};
9557+
});
95259558
if (!statesList) {
95269559
setTimeout(() => {
9527-
dialog2.remove();
95289560
}, 2e3);
95299561
}
95309562
}
@@ -9658,6 +9690,10 @@
96589690
<pre>${JSON.stringify(recentChanges, null, 2)}</pre>
96599691
</div>
96609692
`;
9693+
const timeTravelDialog = document.getElementById("model-devtools-time-travel-dialog");
9694+
if (timeTravelDialog) {
9695+
this.showTimeTravelDialog();
9696+
}
96619697
}
96629698
getComputedValues() {
96639699
return Object.fromEntries(
@@ -9681,7 +9717,7 @@
96819717
if (!this.options.timeTravel) return;
96829718
if (index < 0 || index >= this.history.length) return;
96839719
const snapshot = this.history[index];
9684-
this.model.loadState(JSON.stringify(snapshot.state));
9720+
this.model.loadStateFromSnapshot(snapshot.state);
96859721
this.currentIndex = index;
96869722
}
96879723
// Методи для аналізу продуктивності
@@ -10139,6 +10175,39 @@
1013910175
});
1014010176
}
1014110177
}
10178+
loadStateFromSnapshot(snapshot) {
10179+
if (!snapshot) {
10180+
console.error("Snapshot is undefined or null");
10181+
return;
10182+
}
10183+
try {
10184+
const computed = {};
10185+
for (const key in snapshot) {
10186+
if (typeof snapshot[key] === "function") {
10187+
computed[key] = {
10188+
getter: snapshot[key],
10189+
value: null,
10190+
dependencies: []
10191+
// Будет заполнено при первом вызове
10192+
};
10193+
} else {
10194+
this.data[key] = snapshot[key];
10195+
}
10196+
}
10197+
this.emit("restoreState", {
10198+
timestamp: Date.now(),
10199+
snapshot
10200+
});
10201+
return true;
10202+
} catch (error) {
10203+
console.error("Error loading state from snapshot:", error);
10204+
this.emit("restoreStateError", {
10205+
error,
10206+
snapshot
10207+
});
10208+
return false;
10209+
}
10210+
}
1014210211
// Допоміжний метод для отримання всіх обчислюваних значень
1014310212
getComputedValues() {
1014410213
return Object.fromEntries(
@@ -10207,6 +10276,7 @@
1020710276
this.parseConditionals(rootElement);
1020810277
this.parse(rootElement);
1020910278
this.updateAllDOM();
10279+
this.emit("init");
1021010280
return this;
1021110281
}
1021210282
// Ініціюємо DevTools
@@ -10215,8 +10285,8 @@
1021510285
}
1021610286
};
1021710287
var model_default = Model;
10218-
var version6 = "0.5.0";
10219-
var build_time6 = "01.03.2025, 23:19:15";
10288+
var version6 = "0.7.0";
10289+
var build_time6 = "02.03.2025, 00:39:42";
1022010290
model_default.info = () => {
1022110291
console.info(`%c Model %c v${version6} %c ${build_time6} `, "color: white; font-weight: bold; background: #0080fe", "color: white; background: darkgreen", "color: white; background: #0080fe;");
1022210292
};
@@ -39446,8 +39516,8 @@
3944639516

3944739517
@olton/model/dist/model.js:
3944839518
(*!
39449-
* Model v0.5.0
39450-
* Build: 01.03.2025, 23:19:15
39519+
* Model v0.7.0
39520+
* Build: 02.03.2025, 00:39:42
3945139521
* Copyright 2012-2025 by Serhii Pimenov
3945239522
* Licensed under MIT
3945339523
*)

lib/metro.all.js.map

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)