jsgui3-server 0.0.147 → 0.0.149
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/.github/workflows/control-scan-manifest-check.yml +31 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-071799b982906680f5fd699d.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-07352945ad5c92654fcb8b65.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-138a601fadb6191ea314c6fd.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-171f6c381c2cadf2e9fa7087.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-1d973388156b84a04373fac9.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-20e117bc8a10d2cd16234bbe.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-2b028a82b0e5efddba42425f.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-4518556cd5c7e059e82b22b8.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-5bac1aa0f213902f718ed74f.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-5f9996ac7822caf777d92f56.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-60a92c702e65fd9cf748e3ec.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-6164c1f8f738995c541895d2.js +44 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-6718a85eb9e5aa782dd47a05.js +45 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-69e280f14e37aee76a1d4675.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-7570d1b030d44b111ed59c4c.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-7798c9bbd55e510d5039f936.js +42 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-78cd511ea1ef18ecb03d1be5.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-7d482e0b95bcb5e3c543118b.js +43 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-80e9476d1127c55b40fdb36f.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-810ced55d5320a3088a05b13.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-8423565f1a40e329afc8c6cf.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-900bef783b8cee36506ec282.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-a1a37aff6416fdad74040ddf.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-ad48d5e8eda40f175b4df090.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-aec5a2d963015528c9099462.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-af9d34e0f1722fab9e28c269.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-b818e4015e2f1fe86280b5ab.js +41 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-bcb2541adc70b7aba61768c5.js +44 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-bfe89d2c78ed44f95ed7dd73.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-c06f04806a1e688e1187110c.js +40 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-c3f3adf904f585afc544b96a.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-d45acb873e1d8e32d5e60f2e.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-db06f132533706f4a0163b8c.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-f660f40d78b135fc8560a862.js +39 -0
- package/.jsgui3-server-cache/jsgui3-html-shims/jsgui3-html-controls-shim-f9dee4ec18a96e09bee06bae.js +39 -0
- package/README.md +85 -3
- package/admin-ui/client.js +213 -0
- package/admin-ui/server.js +104 -0
- package/client/controls/auto-observable.js +207 -0
- package/dev-status.svg +139 -0
- package/docs/api-reference.md +301 -43
- package/docs/books/admin-ui/01-introduction.md +32 -0
- package/docs/books/admin-ui/02-architecture.md +92 -0
- package/docs/books/admin-ui/03-controls.md +194 -0
- package/docs/books/admin-ui/04-implementation-plan.md +62 -0
- package/docs/books/admin-ui/README.md +26 -0
- package/docs/books/jsgui3-bundling-research-book/00-table-of-contents.md +35 -0
- package/docs/books/jsgui3-bundling-research-book/01-pipeline-and-runtime-semantics.md +34 -0
- package/docs/books/jsgui3-bundling-research-book/02-javascript-bundling-core.md +36 -0
- package/docs/books/jsgui3-bundling-research-book/03-style-extraction-and-css-compilation.md +35 -0
- package/docs/books/jsgui3-bundling-research-book/04-static-publishing-and-delivery.md +39 -0
- package/docs/books/jsgui3-bundling-research-book/05-current-limits-and-size-bloat-vectors.md +25 -0
- package/docs/books/jsgui3-bundling-research-book/06-unused-module-elimination-strategy.md +77 -0
- package/docs/books/jsgui3-bundling-research-book/07-jsgui3-html-control-and-mixin-pruning.md +63 -0
- package/docs/books/jsgui3-bundling-research-book/08-test-and-verification-methodology.md +43 -0
- package/docs/books/jsgui3-bundling-research-book/09-roadmap-and-rollout.md +42 -0
- package/docs/books/jsgui3-bundling-research-book/10-further-research-strategies-and-upgrades.md +211 -0
- package/docs/books/jsgui3-bundling-research-book/README.md +35 -0
- package/docs/bundling-system-deep-dive.md +9 -4
- package/docs/comprehensive-documentation.md +49 -18
- package/docs/configuration-reference.md +152 -27
- package/docs/core/README.md +19 -0
- package/docs/core/jsgui3-server-core-book/00-table-of-contents.md +21 -0
- package/docs/core/jsgui3-server-core-book/01-startup-readiness-state-machine.md +41 -0
- package/docs/core/jsgui3-server-core-book/02-resource-abstraction-and-lifecycle.md +92 -0
- package/docs/core/jsgui3-server-core-book/03-resource-pool-and-event-topology.md +47 -0
- package/docs/core/jsgui3-server-core-book/04-sse-publisher-semantics.md +41 -0
- package/docs/core/jsgui3-server-core-book/05-serve-factory-resource-wiring.md +46 -0
- package/docs/core/jsgui3-server-core-book/06-e2e-testing-methodology.md +48 -0
- package/docs/core/jsgui3-server-core-book/07-defect-detection-and-hardening-loop.md +47 -0
- package/docs/publishers-guide.md +59 -4
- package/docs/resources-guide.md +184 -35
- package/docs/simple-server-api-design.md +72 -17
- package/docs/system-architecture.md +18 -14
- package/examples/controls/15) window, observable SSE/server.js +6 -1
- package/examples/controls/19) window, auto observable ui/client.js +125 -0
- package/examples/controls/19) window, auto observable ui/server.js +73 -0
- package/examples/controls/20) window, task manager app/README.md +133 -0
- package/examples/controls/20) window, task manager app/client.js +797 -0
- package/examples/controls/20) window, task manager app/server.js +178 -0
- package/examples/controls/6) window, color_palette/client.js +165 -68
- package/examples/controls/9) window, date picker/client.js +362 -76
- package/examples/controls/9b) window, shared data.model mirrored date pickers/client.js +104 -83
- package/examples/jsgui3-html/06) theming/client.js +22 -1
- package/examples/jsgui3-html/10) binding-debugger/client.js +137 -1
- package/http/responders/static/Static_Route_HTTP_Responder.js +52 -34
- package/lab/experiments/capture-color-controls.js +196 -0
- package/lab/results/screenshots/color-controls/full_page.png +0 -0
- package/lab/results/screenshots/color-controls/section_1_color_grid_12x12.png +0 -0
- package/lab/results/screenshots/color-controls/section_2_color_grid_4x2.png +0 -0
- package/lab/results/screenshots/color-controls/section_3_color_palette.png +0 -0
- package/lab/results/screenshots/color-controls/section_4_palette_comparison.png +0 -0
- package/lab/results/screenshots/color-controls/section_5_raw_swatches.png +0 -0
- package/lab/results/screenshots/color-controls/section_6_optimized_crayola.png +0 -0
- package/lab/results/screenshots/color-controls/section_7_pastel_palette.png +0 -0
- package/lab/results/screenshots/color-controls/section_8_extended_144.png +0 -0
- package/lab/screenshot-utils.js +248 -0
- package/module.js +11 -4
- package/package.json +14 -4
- package/publishers/Publishers.js +4 -3
- package/publishers/helpers/assigners/static-compressed-response-buffers/Single_Control_Webpage_Server_Static_Compressed_Response_Buffers_Assigner.js +5 -5
- package/publishers/http-observable-publisher.js +8 -0
- package/publishers/http-sse-publisher.js +341 -0
- package/publishers/http-webpage-publisher.js +13 -3
- package/publishers/http-webpageorsite-publisher.js +18 -0
- package/resources/process-resource.js +950 -0
- package/resources/processors/bundlers/js/esbuild/Advanced_JS_Bundler_Using_ESBuild.js +164 -46
- package/resources/processors/bundlers/js/esbuild/Core_JS_Non_Minifying_Bundler_Using_ESBuild.js +18 -7
- package/resources/processors/bundlers/js/esbuild/JSGUI3_HTML_Control_Optimizer.js +829 -0
- package/resources/remote-process-resource.js +355 -0
- package/resources/server-resource-pool.js +354 -41
- package/serve-factory.js +441 -259
- package/server.js +161 -16
- package/tests/README.md +66 -4
- package/tests/admin-ui-render.test.js +24 -0
- package/tests/assigners.test.js +56 -40
- package/tests/bundling-default-control-elimination.puppeteer.test.js +260 -0
- package/tests/configuration-validation.test.js +21 -18
- package/tests/content-analysis.test.js +7 -6
- package/tests/control-optimizer-cache-behavior.test.js +52 -0
- package/tests/control-scan-manifest-regression.test.js +144 -0
- package/tests/end-to-end.test.js +15 -14
- package/tests/error-handling.test.js +222 -179
- package/tests/fixtures/bundling-default-button-client.js +37 -0
- package/tests/fixtures/bundling-default-window-client.js +34 -0
- package/tests/fixtures/control_scan_manifest_expectations.json +48 -0
- package/tests/fixtures/resource-monitor-client.js +319 -0
- package/tests/helpers/puppeteer-e2e-harness.js +317 -0
- package/tests/http-sse-publisher.test.js +136 -0
- package/tests/performance.test.js +69 -65
- package/tests/process-resource.test.js +138 -0
- package/tests/publishers.test.js +7 -7
- package/tests/remote-process-resource.test.js +160 -0
- package/tests/sass-controls.e2e.test.js +7 -1
- package/tests/serve-resources.test.js +270 -0
- package/tests/serve.test.js +120 -50
- package/tests/server-resource-pool.test.js +106 -0
- package/tests/small-controls-bundle-size.test.js +252 -0
- package/tests/test-runner.js +13 -1
- package/tests/window-examples.puppeteer.test.js +204 -1
- package/tests/window-resource-integration.puppeteer.test.js +585 -0
- package/tests/temp_invalid.js +0 -7
- package/tests/temp_invalid_utf8.js +0 -1
- package/tests/temp_malformed.js +0 -10
|
@@ -21,7 +21,7 @@ This document explains the design principles and implementation of the simplifie
|
|
|
21
21
|
2. **Convention Over Configuration** – Smart defaults; minimal required config
|
|
22
22
|
3. **Consistent Patterns** – Same API shape at every scale
|
|
23
23
|
4. **Zero-to-Hero Path** – Clear upgrade path from simple to advanced
|
|
24
|
-
5. **Composable** – Mix and match features (pages, APIs, static files)
|
|
24
|
+
5. **Composable** – Mix and match features (pages, APIs, static files, managed resources, SSE events)
|
|
25
25
|
|
|
26
26
|
---
|
|
27
27
|
|
|
@@ -218,7 +218,59 @@ Server.serve({
|
|
|
218
218
|
|
|
219
219
|
---
|
|
220
220
|
|
|
221
|
-
### Layer 5:
|
|
221
|
+
### Layer 5: Managed Resources + Lifecycle Events
|
|
222
|
+
|
|
223
|
+
**Use Case:** Run and supervise background workers alongside your web app, with optional SSE event streaming.
|
|
224
|
+
|
|
225
|
+
```javascript
|
|
226
|
+
let server;
|
|
227
|
+
server = await Server.serve({
|
|
228
|
+
page: {
|
|
229
|
+
content: DashboardControl,
|
|
230
|
+
title: 'Ops Dashboard'
|
|
231
|
+
},
|
|
232
|
+
resources: {
|
|
233
|
+
// In-process resource object
|
|
234
|
+
cache: new In_Process_Cache_Resource({ name: 'cache' }),
|
|
235
|
+
|
|
236
|
+
// Local process resource (default manager: direct)
|
|
237
|
+
worker_direct: {
|
|
238
|
+
type: 'process',
|
|
239
|
+
command: process.execPath,
|
|
240
|
+
args: ['worker.js'],
|
|
241
|
+
autoRestart: true
|
|
242
|
+
},
|
|
243
|
+
|
|
244
|
+
// PM2-backed local process (pm2Path optional)
|
|
245
|
+
worker_pm2: {
|
|
246
|
+
type: 'process',
|
|
247
|
+
processManager: { type: 'pm2' },
|
|
248
|
+
command: process.execPath,
|
|
249
|
+
args: ['worker.js']
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
// Remote HTTP-controlled process
|
|
253
|
+
remote_agent: {
|
|
254
|
+
type: 'remote',
|
|
255
|
+
host: '127.0.0.1',
|
|
256
|
+
port: 3400
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
events: true, // enables /events SSE endpoint
|
|
260
|
+
api: {
|
|
261
|
+
'resources/summary': () => server.resource_pool.summary
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Lifecycle conventions:**
|
|
267
|
+
- Process-like resources expose the same API shape: `start()`, `stop()`, `restart()`, `status`, `get_abstract()`
|
|
268
|
+
- Resource pool forwards lifecycle events (`resource_state_change`, `crashed`, `unhealthy`, `unreachable`, `recovered`)
|
|
269
|
+
- `server.close()` stops managed resources and SSE publisher cleanly
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
### Layer 6: Shorthand Routes (Mixed Types)
|
|
222
274
|
|
|
223
275
|
**Use Case:** Mix controls, functions, and static content flexibly
|
|
224
276
|
|
|
@@ -242,7 +294,7 @@ Server.serve({
|
|
|
242
294
|
|
|
243
295
|
---
|
|
244
296
|
|
|
245
|
-
### Layer
|
|
297
|
+
### Layer 7: Full Website Object
|
|
246
298
|
|
|
247
299
|
**Use Case:** Complex multi-page sites, existing `Website` instances
|
|
248
300
|
|
|
@@ -283,7 +335,7 @@ Server.serve({
|
|
|
283
335
|
|
|
284
336
|
---
|
|
285
337
|
|
|
286
|
-
### Layer
|
|
338
|
+
### Layer 8: Legacy/Advanced (Current API)
|
|
287
339
|
|
|
288
340
|
**Still fully supported for maximum control:**
|
|
289
341
|
|
|
@@ -542,12 +594,14 @@ require('../../../server').serve(require('./client').controls.Demo_UI);
|
|
|
542
594
|
- [x] Return a Promise that resolves with the server instance
|
|
543
595
|
- [x] Support Promise/async and callback patterns
|
|
544
596
|
|
|
545
|
-
### Phase 2: API & Static (Partially Complete)
|
|
546
|
-
- [x] `api` option for function publishing
|
|
547
|
-
- [x] Auto-prefix `/api/` routes
|
|
548
|
-
- [x] JSON/text content-type detection
|
|
549
|
-
- [
|
|
550
|
-
- [
|
|
597
|
+
### Phase 2: API & Static (Partially Complete)
|
|
598
|
+
- [x] `api` option for function publishing
|
|
599
|
+
- [x] Auto-prefix `/api/` routes
|
|
600
|
+
- [x] JSON/text content-type detection
|
|
601
|
+
- [x] `resources` option for in-process/process/remote managed resources
|
|
602
|
+
- [x] `events` option for built-in SSE lifecycle publisher
|
|
603
|
+
- [ ] `static` option for directory serving
|
|
604
|
+
- [ ] MIME type detection for static files
|
|
551
605
|
|
|
552
606
|
### Phase 3: Enhanced Features (Partially Complete)
|
|
553
607
|
- [x] ENV var support (PORT, HOST, JSGUI_DEBUG)
|
|
@@ -706,10 +760,11 @@ server.on('ready', () => {
|
|
|
706
760
|
- Promise/async support
|
|
707
761
|
- Still 100% backwards compatible
|
|
708
762
|
|
|
709
|
-
### Key Benefits
|
|
710
|
-
1. **Faster prototyping** – from idea to running in seconds
|
|
711
|
-
2. **Less boilerplate** – 90% reduction for simple cases
|
|
712
|
-
3. **Better defaults** – works out of the box
|
|
713
|
-
4. **Clearer intent** – code reads like configuration
|
|
714
|
-
5. **Easy scaling** – simple projects grow naturally
|
|
715
|
-
6. **Zero breaking changes** – all existing code still works
|
|
763
|
+
### Key Benefits
|
|
764
|
+
1. **Faster prototyping** – from idea to running in seconds
|
|
765
|
+
2. **Less boilerplate** – 90% reduction for simple cases
|
|
766
|
+
3. **Better defaults** – works out of the box
|
|
767
|
+
4. **Clearer intent** – code reads like configuration
|
|
768
|
+
5. **Easy scaling** – simple projects grow naturally
|
|
769
|
+
6. **Zero breaking changes** – all existing code still works
|
|
770
|
+
7. **Unified runtime operations** – consistent process/resource lifecycle APIs with optional SSE observability
|
|
@@ -32,25 +32,29 @@ JSGUI3 Server is a Node.js-based web framework that serves modern JavaScript GUI
|
|
|
32
32
|
|
|
33
33
|
**Purpose:** Handles conversion of various content types to HTTP responses.
|
|
34
34
|
|
|
35
|
-
**Key Publishers:**
|
|
36
|
-
- `HTTP_Webpage_Publisher`: Serves bundled JSGUI3 controls as complete web pages
|
|
37
|
-
- `HTTP_Website_Publisher`: Manages multi-page websites
|
|
38
|
-
- `HTTP_Function_Publisher`: Exposes JavaScript functions as REST API endpoints
|
|
39
|
-
- `
|
|
40
|
-
- `
|
|
41
|
-
- `
|
|
35
|
+
**Key Publishers:**
|
|
36
|
+
- `HTTP_Webpage_Publisher`: Serves bundled JSGUI3 controls as complete web pages
|
|
37
|
+
- `HTTP_Website_Publisher`: Manages multi-page websites
|
|
38
|
+
- `HTTP_Function_Publisher`: Exposes JavaScript functions as REST API endpoints
|
|
39
|
+
- `HTTP_Observable_Publisher`: Streams observable-backed SSE
|
|
40
|
+
- `HTTP_SSE_Publisher`: General-purpose SSE fan-out publisher
|
|
41
|
+
- `HTTP_CSS_Publisher`: Serves CSS stylesheets
|
|
42
|
+
- `HTTP_JS_Publisher`: Serves JavaScript bundles
|
|
43
|
+
- `HTTP_Image_Publisher`: Handles image file serving
|
|
42
44
|
|
|
43
45
|
### 3. Resource Management Layer
|
|
44
46
|
**Directory:** `resources/`
|
|
45
47
|
|
|
46
48
|
**Purpose:** Provides abstractions for accessing different types of data and functionality.
|
|
47
49
|
|
|
48
|
-
**Key Resources:**
|
|
49
|
-
- `Server_Resource_Pool`: Manages collections of resources with lifecycle management
|
|
50
|
-
- `
|
|
51
|
-
- `
|
|
52
|
-
- `
|
|
53
|
-
- `
|
|
50
|
+
**Key Resources:**
|
|
51
|
+
- `Server_Resource_Pool`: Manages collections of resources with lifecycle management
|
|
52
|
+
- `Process_Resource`: Local process resource (`direct` default, optional `pm2`)
|
|
53
|
+
- `Remote_Process_Resource`: HTTP-controlled remote process resource
|
|
54
|
+
- `Website_Resource`: Wraps website objects for server integration
|
|
55
|
+
- `File_System_Resource`: Provides file system access
|
|
56
|
+
- `Data_Resource`: Handles data storage and retrieval
|
|
57
|
+
- `Local_Server_Info_Resource`: Provides server environment information
|
|
54
58
|
|
|
55
59
|
### 4. Processing Layer
|
|
56
60
|
**Directory:** `resources/processors/`
|
|
@@ -272,4 +276,4 @@ Add new processing pipelines for assets and data.
|
|
|
272
276
|
|
|
273
277
|
---
|
|
274
278
|
|
|
275
|
-
This architecture document provides the foundation for understanding how JSGUI3 Server components work together. For detailed implementation of specific components, refer to their individual documentation files.
|
|
279
|
+
This architecture document provides the foundation for understanding how JSGUI3 Server components work together. For detailed implementation of specific components, refer to their individual documentation files.
|
|
@@ -64,13 +64,18 @@ if (require.main === module) {
|
|
|
64
64
|
});
|
|
65
65
|
|
|
66
66
|
// Register the SSE endpoint with the server's router
|
|
67
|
+
// You can use the manual approach (full control):
|
|
67
68
|
server.server_router.set_route('/api/tick-stream', tick_publisher, tick_publisher.handle_http);
|
|
68
69
|
console.log(' ✓ /api/tick-stream - Hot tick stream (SSE)');
|
|
69
70
|
|
|
71
|
+
// Or use the simplified API (auto-prefixes /api/ for simple names):
|
|
72
|
+
// server.publish_observable('tick-stream', tick_observable);
|
|
73
|
+
|
|
70
74
|
// ========================================
|
|
71
75
|
// Also publish a simple JSON API endpoint for comparison
|
|
72
76
|
// ========================================
|
|
73
|
-
|
|
77
|
+
// Simple name (auto-prefixes /api/)
|
|
78
|
+
server.publish('status', () => {
|
|
74
79
|
return {
|
|
75
80
|
status: 'ok',
|
|
76
81
|
tick_count: tick_count,
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const jsgui = require('jsgui3-client');
|
|
2
|
+
const { controls, Control } = jsgui;
|
|
3
|
+
const Auto_Observable_UI = require('../../../client/controls/auto-observable');
|
|
4
|
+
controls.Auto_Observable_UI = Auto_Observable_UI;
|
|
5
|
+
|
|
6
|
+
const Active_HTML_Document = require('../../../controls/Active_HTML_Document');
|
|
7
|
+
|
|
8
|
+
class Demo_Page extends Active_HTML_Document {
|
|
9
|
+
constructor(spec = {}) {
|
|
10
|
+
spec.__type_name = spec.__type_name || 'demo_page';
|
|
11
|
+
super(spec);
|
|
12
|
+
const { context } = this;
|
|
13
|
+
|
|
14
|
+
if (typeof this.body.add_class === 'function') {
|
|
15
|
+
this.body.add_class('demo-page');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const compose = () => {
|
|
19
|
+
const h1 = new controls.h1({ context });
|
|
20
|
+
h1.add('Auto Observable UI Demo');
|
|
21
|
+
this.body.add(h1);
|
|
22
|
+
|
|
23
|
+
const container = new controls.div({ context, class: 'params-container' });
|
|
24
|
+
this.body.add(container);
|
|
25
|
+
|
|
26
|
+
// 1. Tick Counter (Int)
|
|
27
|
+
const ui_tick = new Auto_Observable_UI({
|
|
28
|
+
context,
|
|
29
|
+
url: '/api/tick',
|
|
30
|
+
class: 'param-ui'
|
|
31
|
+
});
|
|
32
|
+
container.add(ui_tick);
|
|
33
|
+
|
|
34
|
+
// 2. CPU Load (Gauge)
|
|
35
|
+
const ui_cpu = new Auto_Observable_UI({
|
|
36
|
+
context,
|
|
37
|
+
url: '/api/cpu',
|
|
38
|
+
class: 'param-ui'
|
|
39
|
+
});
|
|
40
|
+
container.add(ui_cpu);
|
|
41
|
+
|
|
42
|
+
// 3. System Logs (Log)
|
|
43
|
+
const ui_log = new Auto_Observable_UI({
|
|
44
|
+
context,
|
|
45
|
+
url: '/api/logs',
|
|
46
|
+
class: 'param-ui span-2'
|
|
47
|
+
});
|
|
48
|
+
container.add(ui_log);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
if (!spec.el) {
|
|
52
|
+
compose();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
Demo_Page.css = `
|
|
58
|
+
body {
|
|
59
|
+
background: #222;
|
|
60
|
+
color: #eee;
|
|
61
|
+
font-family: sans-serif;
|
|
62
|
+
padding: 20px;
|
|
63
|
+
}
|
|
64
|
+
.params-container {
|
|
65
|
+
display: grid;
|
|
66
|
+
grid-template-columns: 1fr 1fr;
|
|
67
|
+
gap: 20px;
|
|
68
|
+
max-width: 800px;
|
|
69
|
+
}
|
|
70
|
+
.param-ui {
|
|
71
|
+
background: #333;
|
|
72
|
+
padding: 15px;
|
|
73
|
+
border-radius: 8px;
|
|
74
|
+
box-shadow: 0 2px 10px rgba(0,0,0,0.5);
|
|
75
|
+
}
|
|
76
|
+
.span-2 {
|
|
77
|
+
grid-column: span 2;
|
|
78
|
+
}
|
|
79
|
+
.value-display {
|
|
80
|
+
text-align: center;
|
|
81
|
+
}
|
|
82
|
+
.value-text {
|
|
83
|
+
font-size: 3em;
|
|
84
|
+
font-weight: bold;
|
|
85
|
+
color: #4facfe;
|
|
86
|
+
}
|
|
87
|
+
.progress-bg {
|
|
88
|
+
background: #444;
|
|
89
|
+
height: 20px;
|
|
90
|
+
border-radius: 10px;
|
|
91
|
+
overflow: hidden;
|
|
92
|
+
margin: 10px 0;
|
|
93
|
+
}
|
|
94
|
+
.progress-fill {
|
|
95
|
+
background: linear-gradient(90deg, #4facfe 0%, #00f2fe 100%);
|
|
96
|
+
height: 100%;
|
|
97
|
+
width: 0%;
|
|
98
|
+
transition: width 0.3s ease;
|
|
99
|
+
}
|
|
100
|
+
.log-area {
|
|
101
|
+
height: 150px;
|
|
102
|
+
background: #111;
|
|
103
|
+
overflow-y: auto;
|
|
104
|
+
text-align: left;
|
|
105
|
+
padding: 10px;
|
|
106
|
+
font-family: monospace;
|
|
107
|
+
font-size: 0.9em;
|
|
108
|
+
border: 1px solid #444;
|
|
109
|
+
}
|
|
110
|
+
.log-entry {
|
|
111
|
+
margin-bottom: 4px;
|
|
112
|
+
border-bottom: 1px solid #222;
|
|
113
|
+
}
|
|
114
|
+
.status-indicator {
|
|
115
|
+
font-size: 0.8em;
|
|
116
|
+
text-transform: uppercase;
|
|
117
|
+
margin-bottom: 5px;
|
|
118
|
+
color: #888;
|
|
119
|
+
}
|
|
120
|
+
.status-connected { color: #0f0; }
|
|
121
|
+
.status-error { color: #f00; }
|
|
122
|
+
`;
|
|
123
|
+
|
|
124
|
+
module.exports = jsgui;
|
|
125
|
+
controls.Demo_Page = Demo_Page;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const jsgui = require('./client');
|
|
2
|
+
const Server = require('../../../server');
|
|
3
|
+
const { Demo_Page } = jsgui.controls;
|
|
4
|
+
const { observable } = require('fnl');
|
|
5
|
+
|
|
6
|
+
if (require.main === module) {
|
|
7
|
+
const server = new Server({
|
|
8
|
+
Ctrl: Demo_Page,
|
|
9
|
+
src_path_client_js: require.resolve('./client.js')
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
server.on('ready', () => {
|
|
13
|
+
// 1. Tick Observable
|
|
14
|
+
const obs_tick = observable((next) => {
|
|
15
|
+
let i = 0;
|
|
16
|
+
const timer = setInterval(() => next(++i), 1000);
|
|
17
|
+
return () => clearInterval(timer);
|
|
18
|
+
});
|
|
19
|
+
// Attach schema manually (or could be done via helper)
|
|
20
|
+
obs_tick.schema = {
|
|
21
|
+
name: 'Uptime (Seconds)',
|
|
22
|
+
type: 'int'
|
|
23
|
+
};
|
|
24
|
+
server.publish_observable('/api/tick', obs_tick);
|
|
25
|
+
|
|
26
|
+
// 2. CPU Observable (Simulated)
|
|
27
|
+
const obs_cpu = observable((next) => {
|
|
28
|
+
const timer = setInterval(() => {
|
|
29
|
+
const load = 40 + Math.random() * 30;
|
|
30
|
+
next(Math.floor(load));
|
|
31
|
+
}, 500);
|
|
32
|
+
return () => clearInterval(timer);
|
|
33
|
+
});
|
|
34
|
+
obs_cpu.schema = {
|
|
35
|
+
name: 'CPU Load',
|
|
36
|
+
type: 'number',
|
|
37
|
+
min: 0,
|
|
38
|
+
max: 100
|
|
39
|
+
};
|
|
40
|
+
server.publish_observable('/api/cpu', obs_cpu);
|
|
41
|
+
|
|
42
|
+
// 3. Logs Observable
|
|
43
|
+
const obs_logs = observable((next) => {
|
|
44
|
+
const msgs = ['System check OK', 'Request received', 'Cache invalidated', 'User login', 'Background job started'];
|
|
45
|
+
const timer = setInterval(() => {
|
|
46
|
+
const msg = msgs[Math.floor(Math.random() * msgs.length)];
|
|
47
|
+
next({ message: msg, level: 'info' });
|
|
48
|
+
}, 2000);
|
|
49
|
+
return () => clearInterval(timer);
|
|
50
|
+
});
|
|
51
|
+
obs_logs.schema = {
|
|
52
|
+
name: 'Server Logs',
|
|
53
|
+
type: 'log'
|
|
54
|
+
};
|
|
55
|
+
server.publish_observable('/api/logs', obs_logs);
|
|
56
|
+
|
|
57
|
+
// Expose Status Diagram
|
|
58
|
+
server.publish('/dev-status.svg', (req, res) => {
|
|
59
|
+
const fs = require('fs');
|
|
60
|
+
const path = require('path');
|
|
61
|
+
const filePath = path.join(__dirname, '../../../../dev-status.svg');
|
|
62
|
+
res.setHeader('Content-Type', 'image/svg+xml');
|
|
63
|
+
fs.createReadStream(filePath).pipe(res);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Start
|
|
67
|
+
const port = 52100;
|
|
68
|
+
server.start(port, (err) => {
|
|
69
|
+
if (err) throw err;
|
|
70
|
+
console.log(`Demo running at http://localhost:${port}`);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# 20) Task Manager Application
|
|
2
|
+
|
|
3
|
+
A comprehensive example demonstrating a multi-window task management application built with jsgui3.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multiple Windows**: Main task manager window + floating quick-add window
|
|
8
|
+
- **Tabbed Interface**: Tasks, Projects, and Stats tabs in the main window
|
|
9
|
+
- **Data Binding**: Uses `Data_Object` and `field()` for reactive state management
|
|
10
|
+
- **API Integration**: Full CRUD operations via `server.publish()` endpoints
|
|
11
|
+
- **Interactive Controls**: Checkboxes, text inputs, select dropdowns, buttons
|
|
12
|
+
- **Real-time Updates**: UI updates immediately after API responses
|
|
13
|
+
- **Statistics Dashboard**: Tracks completion rates with visual progress bar
|
|
14
|
+
|
|
15
|
+
## Running the Example
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cd examples/controls/20) window, task manager app
|
|
19
|
+
node server.js
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then open http://localhost:52021 in your browser.
|
|
23
|
+
|
|
24
|
+
## Architecture
|
|
25
|
+
|
|
26
|
+
### Client (`client.js`)
|
|
27
|
+
|
|
28
|
+
The `Task_Manager_App` class extends `Active_HTML_Document` and demonstrates:
|
|
29
|
+
|
|
30
|
+
1. **Data Model Setup**:
|
|
31
|
+
```javascript
|
|
32
|
+
this.data = { model: new Data_Object({ context }) };
|
|
33
|
+
field(this.data.model, 'tasks');
|
|
34
|
+
field(this.data.model, 'projects');
|
|
35
|
+
field(this.data.model, 'stats');
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
2. **Multiple Windows**:
|
|
39
|
+
```javascript
|
|
40
|
+
const main_window = new controls.Window({ context, title: 'Task Manager', pos: [20, 20] });
|
|
41
|
+
const quick_add_window = new controls.Window({ context, title: 'Quick Add Task', pos: [540, 20] });
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
3. **Tabbed Panel**:
|
|
45
|
+
```javascript
|
|
46
|
+
const main_tabs = new controls.Tabbed_Panel({
|
|
47
|
+
context,
|
|
48
|
+
tabs: [
|
|
49
|
+
['Tasks', this._create_tasks_panel(context)],
|
|
50
|
+
['Projects', this._create_projects_panel(context)],
|
|
51
|
+
['Stats', this._create_stats_panel(context)]
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
4. **API Calls**:
|
|
57
|
+
```javascript
|
|
58
|
+
async _add_task() {
|
|
59
|
+
const response = await fetch('/api/tasks/add', {
|
|
60
|
+
method: 'POST',
|
|
61
|
+
headers: { 'Content-Type': 'application/json' },
|
|
62
|
+
body: JSON.stringify({ text, project })
|
|
63
|
+
});
|
|
64
|
+
const result = await response.json();
|
|
65
|
+
// Update UI...
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Server (`server.js`)
|
|
70
|
+
|
|
71
|
+
Uses the simple `server.publish()` API for endpoints:
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// GET /api/tasks/list
|
|
75
|
+
server.publish('tasks/list', () => ({ tasks: get_tasks() }));
|
|
76
|
+
|
|
77
|
+
// POST /api/tasks/add
|
|
78
|
+
server.publish('tasks/add', (data) => {
|
|
79
|
+
const new_task = { id: next_id++, text: data.text, ... };
|
|
80
|
+
tasks.push(new_task);
|
|
81
|
+
return { success: true, tasks: get_tasks() };
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## API Endpoints
|
|
86
|
+
|
|
87
|
+
| Method | Endpoint | Description |
|
|
88
|
+
|--------|----------|-------------|
|
|
89
|
+
| GET | `/api/tasks/list` | Get all tasks |
|
|
90
|
+
| POST | `/api/tasks/add` | Add a new task |
|
|
91
|
+
| POST | `/api/tasks/toggle` | Toggle task completion |
|
|
92
|
+
| POST | `/api/tasks/delete` | Delete a task |
|
|
93
|
+
| POST | `/api/tasks/clear-completed` | Remove completed tasks |
|
|
94
|
+
| GET | `/api/stats` | Get statistics by project |
|
|
95
|
+
|
|
96
|
+
## UI Components Used
|
|
97
|
+
|
|
98
|
+
- `Window` - Draggable, resizable window containers
|
|
99
|
+
- `Tabbed_Panel` - Tab navigation between views
|
|
100
|
+
- `Text_Field` - Text input for task descriptions
|
|
101
|
+
- `Select_Options` - Dropdown for project selection
|
|
102
|
+
- `Button` - Action buttons with click handlers
|
|
103
|
+
- `Checkbox` - Task completion (rendered dynamically)
|
|
104
|
+
|
|
105
|
+
## Key Patterns Demonstrated
|
|
106
|
+
|
|
107
|
+
1. **Control References**: Storing component references for later access
|
|
108
|
+
```javascript
|
|
109
|
+
this._ctrl_fields = { main_window, main_tabs, quick_add_window };
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
2. **Conditional Composition**: Only compose if not hydrating from DOM
|
|
113
|
+
```javascript
|
|
114
|
+
if (!spec.el) { compose(); }
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
3. **Activation Guard**: Prevent double-activation
|
|
118
|
+
```javascript
|
|
119
|
+
if (!this.__active) { super.activate(); ... }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
4. **CSS as Static Property**: Scoped styles
|
|
123
|
+
```javascript
|
|
124
|
+
Task_Manager_App.css = `...`;
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Customization Ideas
|
|
128
|
+
|
|
129
|
+
- Add task due dates with `Date_Picker`
|
|
130
|
+
- Implement drag-and-drop task reordering
|
|
131
|
+
- Add task priority levels
|
|
132
|
+
- Connect to a real database instead of in-memory store
|
|
133
|
+
- Add real-time updates with `publish_observable` for multi-user sync
|