nuspace 0.7.1__tar.gz → 0.7.2__tar.gz
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.
- {nuspace-0.7.1 → nuspace-0.7.2}/CHANGELOG.md +14 -2
- {nuspace-0.7.1 → nuspace-0.7.2}/PKG-INFO +6 -6
- {nuspace-0.7.1 → nuspace-0.7.2}/pyproject.toml +6 -6
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/__init__.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/devices.py +3 -3
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/layout.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/resources.py +0 -3
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/stores.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/plane.py +5 -2
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/__init__.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/content.py +2 -2
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/plane.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/store.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/specs/ops.py +2 -2
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/placement.py +8 -6
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/__init__.py +16 -20
- nuspace-0.7.2/src/nuspace/web/desks/__init__.py +58 -0
- nuspace-0.7.2/src/nuspace/web/desks/feed.py +152 -0
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/desks/interactions.py +18 -7
- nuspace-0.7.2/src/nuspace/web/desks/model.py +542 -0
- nuspace-0.7.2/src/nuspace/web/desks/ops.py +418 -0
- {nuspace-0.7.1/src/nuspace/devices/web → nuspace-0.7.2/src/nuspace/web/desks}/pruner.py +28 -28
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/desks/ref.py +2 -2
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/device.py +7 -6
- nuspace-0.7.2/src/nuspace/web/home/__init__.py +56 -0
- nuspace-0.7.2/src/nuspace/web/home/common.py +103 -0
- nuspace-0.7.2/src/nuspace/web/home/history.py +141 -0
- {nuspace-0.7.1/src/nuspace/devices/web → nuspace-0.7.2/src/nuspace/web/home}/indexer.py +2 -2
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/home/now.py +129 -136
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/home/runs.py +42 -70
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/home/space.py +58 -90
- nuspace-0.7.2/src/nuspace/web/interactions.py +261 -0
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/ops.py +26 -128
- nuspace-0.7.1/src/nuspace/devices/web/planes.py → nuspace-0.7.2/src/nuspace/web/planes/__init__.py +20 -28
- {nuspace-0.7.1/src/nuspace/devices/web → nuspace-0.7.2/src/nuspace/web/planes}/search.py +189 -137
- nuspace-0.7.2/src/nuspace/web/planes/settings.py +211 -0
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/ref.py +3 -3
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/shapes.py +25 -12
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/shell.py +4 -4
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/sidebar/__init__.py +3 -3
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/sidebar/feed.py +6 -6
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/sidebar/interactions.py +1 -1
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/sidebar/ref.py +2 -2
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/stores.py +1 -2
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/utils.py +7 -1
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/viewer/__init__.py +3 -3
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/viewer/feed.py +12 -12
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/viewer/interactions.py +1 -1
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/viewer/ref.py +2 -2
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/conftest.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_cli.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_host.py +3 -3
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_nav.py +3 -3
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_session_pipe.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_shapes.py +8 -7
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_specs.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_system_utils.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_telemetry.py +1 -1
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_web.py +18 -17
- nuspace-0.7.2/tests/nuspace/test_web_desks.py +711 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_web_home.py +202 -134
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_web_indexer.py +4 -3
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_web_ops.py +22 -2
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_web_planes.py +76 -33
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_web_pruner.py +63 -35
- nuspace-0.7.1/src/nuspace/devices/__init__.py +0 -10
- nuspace-0.7.1/src/nuspace/devices/web/desks/__init__.py +0 -39
- nuspace-0.7.1/src/nuspace/devices/web/desks/feed.py +0 -132
- nuspace-0.7.1/src/nuspace/devices/web/home/__init__.py +0 -106
- nuspace-0.7.1/src/nuspace/devices/web/home/common.py +0 -72
- nuspace-0.7.1/src/nuspace/devices/web/home/history.py +0 -153
- nuspace-0.7.1/src/nuspace/devices/web/interactions.py +0 -630
- nuspace-0.7.1/src/nuspace/devices/web/settings.py +0 -27
- nuspace-0.7.1/tests/nuspace/test_web_desks.py +0 -543
- {nuspace-0.7.1 → nuspace-0.7.2}/.gitignore +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/.pre-commit-config.yaml +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/LICENSE.md +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/Makefile +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/README.md +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/examples/space.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/pkgs/ts/nuspace-ui/python/nuspace_ui/build +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_branding/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_branding/header.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_branding/logo.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_branding/palette.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/__main__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/_installed.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/_meta.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/commands/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/commands/init.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/commands/run.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/commands/telemetry.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/commands/verse.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_cli/main.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_telemetry/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_telemetry/config.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_telemetry/send.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/_telemetry/usage.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/errors.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/interactions.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/lock.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/presets.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/host/space.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/backends/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/backends/async_.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/backends/base.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/backends/interactions.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/backends/mp.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/backends/pool.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/body.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/close.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/envs.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/interactions.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/kernel.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/out.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/reap.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/kernel/records.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/brackets.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/cell.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/cell_run.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/interactions.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/plane_run.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/state.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/ops/worker.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/places.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/cell.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/cell_run.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/exec.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/plane_run.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/space.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/state.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/shapes/worker.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/specs/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/specs/registry.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/specs/specs.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/init/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/init/ops.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/init/plane.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/init/shapes.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/planes.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/reactions/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/reactions/ops.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/reactions/plane.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/reactions/shapes.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/reload/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/reload/plane.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/supervisor/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/supervisor/ops.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/supervisor/plane.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/system/supervisor/shapes.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/checks.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/interactions.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/policies.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/reads.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/tree.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/src/nuspace/utils/typed.py +0 -0
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/env.py +0 -0
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/nav.py +0 -0
- {nuspace-0.7.1/src/nuspace/devices → nuspace-0.7.2/src/nuspace}/web/session.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_ext/nuspace_testing/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_ext/pyproject.toml +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/__init__.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/actions.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/contents.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/crash_host.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/kernel.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/kernel_envs.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/made.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/probe.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/_lib/_support/specs.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_brackets.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_content.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_errors.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_exports.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_kernel.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_ops_cell.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_ops_cell_run.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_ops_plane.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_ops_plane_run.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_ops_state.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_ops_worker.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_packaging.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_places.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_system_ops.py +0 -0
- {nuspace-0.7.1 → nuspace-0.7.2}/tests/nuspace/test_system_planes.py +0 -0
|
@@ -2,13 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
## Packages shipped from this repo
|
|
4
4
|
|
|
5
|
-
- **nuspace** (the runtime, the `nuspace` command) — 0.7.
|
|
6
|
-
- **nuspace-ui** (the compiled web bundle) — 0.7.
|
|
5
|
+
- **nuspace** (the runtime, the `nuspace` command) — 0.7.2
|
|
6
|
+
- **nuspace-ui** (the compiled web bundle) — 0.7.2
|
|
7
7
|
|
|
8
8
|
Below is the changelog for **nuspace** - the full commit stream. Newest first.
|
|
9
9
|
The `nuspace-ui` wheel is the same source tree's vite output and is not tracked
|
|
10
10
|
separately here.
|
|
11
11
|
|
|
12
|
+
## 0.7.2 - 2026-11-13
|
|
13
|
+
|
|
14
|
+
- Release nuspace and nuspace-ui 0.7.2
|
|
15
|
+
- Home, settings and search follow the new layout model; plane links share one helper
|
|
16
|
+
- New planes get a default icon when created without one
|
|
17
|
+
- Home, settings and search planes get clean sectioned layouts with real tables
|
|
18
|
+
- Drops show the region they make, and single planes stack anywhere
|
|
19
|
+
- Sidebar states use the kit hover, press and selected washes in both themes
|
|
20
|
+
- Desks keep each item on its own, programs get item ops, cross-desk drags commit once
|
|
21
|
+
- The web device moves to nuspace.web, the devices package is gone
|
|
22
|
+
- Group the web device by area: desk ops under desks, shipped planes together
|
|
23
|
+
|
|
12
24
|
## 0.7.1 - 2026-11-12
|
|
13
25
|
|
|
14
26
|
- Release nuspace and nuspace-ui 0.7.1
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nuspace
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.2
|
|
4
4
|
Summary: Computational space for your data and tools.
|
|
5
5
|
Project-URL: Repository, https://github.com/nustackdev/nuspace
|
|
6
6
|
Author-email: Gor Arakelyan <gorarkln@gmail.com>
|
|
@@ -17,16 +17,16 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
17
17
|
Requires-Python: >=3.10
|
|
18
18
|
Requires-Dist: certifi>=2023.7.22
|
|
19
19
|
Requires-Dist: click>=8.0
|
|
20
|
-
Requires-Dist: nucore>=0.7.
|
|
21
|
-
Requires-Dist: nuspace-ui>=0.7.
|
|
22
|
-
Requires-Dist: nustd[kv,mp-pool,proxy,ui,valkey]>=0.7.
|
|
23
|
-
Requires-Dist: nuverse>=0.3.
|
|
20
|
+
Requires-Dist: nucore>=0.7.4
|
|
21
|
+
Requires-Dist: nuspace-ui>=0.7.2
|
|
22
|
+
Requires-Dist: nustd[kv,mp-pool,proxy,ui,valkey]>=0.7.4
|
|
23
|
+
Requires-Dist: nuverse>=0.3.10
|
|
24
24
|
Requires-Dist: rich-click>=1.6
|
|
25
25
|
Requires-Dist: rich>=10.7
|
|
26
26
|
Requires-Dist: typing-extensions>=4.7.0
|
|
27
27
|
Requires-Dist: virtuals-py[redis]>=0.2.2
|
|
28
28
|
Provides-Extra: all
|
|
29
|
-
Requires-Dist: nustd[all]>=0.7.
|
|
29
|
+
Requires-Dist: nustd[all]>=0.7.4; extra == 'all'
|
|
30
30
|
Description-Content-Type: text/markdown
|
|
31
31
|
|
|
32
32
|
<div align="center">
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "nuspace"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.2"
|
|
8
8
|
description = "Computational space for your data and tools."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "AGPL-3.0-or-later"
|
|
@@ -14,17 +14,17 @@ dependencies = [
|
|
|
14
14
|
# The fabrics a space runs on, nothing more: kv for the store, valkey for
|
|
15
15
|
# its change notifications, ui for the browser, mp_pool for the workers,
|
|
16
16
|
# proxy (invisibles) for the worker's session.
|
|
17
|
-
"nucore>=0.7.
|
|
18
|
-
"nustd[kv,ui,valkey,mp_pool,proxy]>=0.7.
|
|
17
|
+
"nucore>=0.7.4",
|
|
18
|
+
"nustd[kv,ui,valkey,mp_pool,proxy]>=0.7.4",
|
|
19
19
|
# The store's change notifications run over virtuals' redis backend.
|
|
20
20
|
"virtuals-py[redis]>=0.2.2",
|
|
21
21
|
# The compiled web bundle. A separate distribution only because PyPI caps
|
|
22
22
|
# project size and a SPA rebuilt on every UI tweak would eat the quota --
|
|
23
23
|
# not optional. `pip install nuspace` gives you the browser.
|
|
24
|
-
"nuspace-ui>=0.7.
|
|
24
|
+
"nuspace-ui>=0.7.2",
|
|
25
25
|
# The everyday Planes and Cells. A plugin like any other, found through
|
|
26
26
|
# its entry point, but every space ships with it.
|
|
27
|
-
"nuverse>=0.3.
|
|
27
|
+
"nuverse>=0.3.10",
|
|
28
28
|
"typing-extensions>=4.7.0",
|
|
29
29
|
"click>=8.0",
|
|
30
30
|
"rich>=10.7",
|
|
@@ -55,7 +55,7 @@ classifiers = [
|
|
|
55
55
|
[project.optional-dependencies]
|
|
56
56
|
# Every nustd fabric and kv backend, for cells that reach past the defaults.
|
|
57
57
|
all = [
|
|
58
|
-
"nustd[all]>=0.7.
|
|
58
|
+
"nustd[all]>=0.7.4",
|
|
59
59
|
]
|
|
60
60
|
|
|
61
61
|
[project.urls]
|
|
@@ -15,7 +15,7 @@ The top level holds the everyday names only:
|
|
|
15
15
|
- ``nuspace.specs`` (PlaneSpec, CellSpec, the registry, add_plane,
|
|
16
16
|
add_cell) and ``nuspace.errors`` (what an op raises).
|
|
17
17
|
|
|
18
|
-
``nuspace.kernel``, ``nuspace.system.*``, ``nuspace.
|
|
18
|
+
``nuspace.kernel``, ``nuspace.system.*``, ``nuspace.web``,
|
|
19
19
|
``nuspace.host`` and ``nuspace.utils`` stay namespaced.
|
|
20
20
|
|
|
21
21
|
Workers import this package: nothing here may pull in a server.
|
|
@@ -56,11 +56,11 @@ class Device:
|
|
|
56
56
|
|
|
57
57
|
def _web() -> Device:
|
|
58
58
|
"""The web device. Its stores and planes import no server; :func:`serve` does, when called."""
|
|
59
|
-
from nuspace.
|
|
60
|
-
from nuspace.
|
|
59
|
+
from nuspace.web.planes import ensure
|
|
60
|
+
from nuspace.web.stores import CONN_STORE, WEB_STORE
|
|
61
61
|
|
|
62
62
|
def serve(*, registry: Registry, **options: object) -> tuple[nu.Nu, Mapping[str, EnvFactory]]:
|
|
63
|
-
from nuspace.
|
|
63
|
+
from nuspace.web.device import serve_web
|
|
64
64
|
|
|
65
65
|
return serve_web(registry=registry, **options)
|
|
66
66
|
|
|
@@ -13,7 +13,7 @@ repository keeps ``.git/``::
|
|
|
13
13
|
infra/valkey/ the notification server's dir, per open
|
|
14
14
|
|
|
15
15
|
The store files are the store records' (:mod:`.stores`,
|
|
16
|
-
:mod:`nuspace.
|
|
16
|
+
:mod:`nuspace.web.stores`). The Space store's file is the mark of a
|
|
17
17
|
space: ``~/.nuspace`` holds the user's config whether or not home is a space.
|
|
18
18
|
"""
|
|
19
19
|
|
|
@@ -126,9 +126,6 @@ class Warmed:
|
|
|
126
126
|
Never the web device's server.
|
|
127
127
|
"""
|
|
128
128
|
import nu.prog # noqa: F401 -- imported for the module cache
|
|
129
|
-
import nuspace.devices.web.env
|
|
130
|
-
import nuspace.kernel.body
|
|
131
|
-
import nuspace.kernel.out # noqa: F401
|
|
132
129
|
import nustd.ui # noqa: F401
|
|
133
130
|
|
|
134
131
|
async def asetup(self, ctx: Context) -> None:
|
|
@@ -10,7 +10,7 @@ so stores never wake each other's subscribers. Each is declared as a
|
|
|
10
10
|
store/state.db State nuspace.state what programs keep
|
|
11
11
|
|
|
12
12
|
A device keeps its own stores beside these (the web device:
|
|
13
|
-
:mod:`nuspace.
|
|
13
|
+
:mod:`nuspace.web.stores`).
|
|
14
14
|
|
|
15
15
|
A container never written is absent, and reading one (its length, its keys,
|
|
16
16
|
whether it holds an id) raises. So each store's fixed containers are made
|
|
@@ -56,6 +56,9 @@ __all__ = [
|
|
|
56
56
|
#: The prefixes an icon is spelled with, a lucide name or an emoji after it.
|
|
57
57
|
ICON_PREFIXES = ("lucide:", "emoji:")
|
|
58
58
|
|
|
59
|
+
#: The icon a plane is made with when none is given.
|
|
60
|
+
DEFAULT_ICON = "lucide:file-text"
|
|
61
|
+
|
|
59
62
|
|
|
60
63
|
def _icon_spelled(icon: nu.StrArg) -> None:
|
|
61
64
|
"""A literal icon is ``""`` or a prefix with something after it. A term is stored as it is.
|
|
@@ -138,7 +141,7 @@ def add(
|
|
|
138
141
|
name: Display text only.
|
|
139
142
|
key: An optional handle in key chars (letters, digits, ``_``, ``-``),
|
|
140
143
|
case-sensitive, ``""`` for none.
|
|
141
|
-
icon: ``lucide:<name
|
|
144
|
+
icon: ``lucide:<name>`` or ``emoji:<char>``. ``""``: :data:`DEFAULT_ICON`.
|
|
142
145
|
backend: What its runs execute on. ``""``: it does not run.
|
|
143
146
|
system: Protected: ``remove`` refuses it. Only a system plane takes
|
|
144
147
|
a :data:`~nuspace.shapes.plane.RESERVED` id.
|
|
@@ -169,7 +172,7 @@ def add(
|
|
|
169
172
|
return (
|
|
170
173
|
row.name.set(name)
|
|
171
174
|
>> row.key.set(key)
|
|
172
|
-
>> row.icon.set(icon)
|
|
175
|
+
>> row.icon.set(icon or DEFAULT_ICON if isinstance(icon, str) else icon)
|
|
173
176
|
>> row.parent.set(parent)
|
|
174
177
|
>> row.version.set(0)
|
|
175
178
|
>> row.cells.set(nu.Dict.create())
|
|
@@ -28,7 +28,7 @@ for a cell run's output.
|
|
|
28
28
|
|
|
29
29
|
Each store is a :class:`Store` record (root, file, channel, init), declared
|
|
30
30
|
by the host for the core stores. The web device keeps its own stores and
|
|
31
|
-
shapes, in :mod:`nuspace.
|
|
31
|
+
shapes, in :mod:`nuspace.web.shapes`. Core never reads them.
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
34
|
from .cell import Cell
|
|
@@ -13,7 +13,7 @@ Finding reads one kind's subtree, scope by scope, all bare reads:
|
|
|
13
13
|
the items ``match`` holds for in one scope, :meth:`Content.find` both
|
|
14
14
|
together. A search reads per kind, so it never touches another kind's
|
|
15
15
|
items; the web device's search drives it a place at a time
|
|
16
|
-
(:mod:`nuspace.
|
|
16
|
+
(:mod:`nuspace.web.planes.search`).
|
|
17
17
|
|
|
18
18
|
Workers import this module: nothing here may pull in a server.
|
|
19
19
|
"""
|
|
@@ -219,7 +219,7 @@ class Content(Generic[S]):
|
|
|
219
219
|
only the checks asked for.
|
|
220
220
|
- :meth:`render`, :meth:`render_hit`: how an item draws in full and as a
|
|
221
221
|
search hit. Bare ui chains, landed under wherever the drawing goes
|
|
222
|
-
(:class:`~nuspace.
|
|
222
|
+
(:class:`~nuspace.web.interactions.Drawing`).
|
|
223
223
|
- :meth:`form`: the search form, generated from ``match``'s keywords.
|
|
224
224
|
- :meth:`find`: every item ``match`` holds for, from every place.
|
|
225
225
|
|
|
@@ -16,7 +16,7 @@ ROOT = "root"
|
|
|
16
16
|
|
|
17
17
|
#: Plane ids only nuspace's own planes take: ``plane.add`` refuses them
|
|
18
18
|
#: unless ``system=True``. The system planes' (``nuspace.system``), then the
|
|
19
|
-
#: web device's (``nuspace.
|
|
19
|
+
#: web device's (``nuspace.web.planes``): the searches folder, the
|
|
20
20
|
#: home indexer and the desk pruner. Home, search and settings have minted
|
|
21
21
|
#: ids, found through the web device's roles. Root's id and ``""`` are
|
|
22
22
|
#: refused for every add.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Store: one store of a space, as a record: its root shape, its file, its channel, its init.
|
|
2
2
|
|
|
3
3
|
The core stores are declared in :mod:`nuspace.host.stores`, a device's
|
|
4
|
-
beside its shapes (the web device: :mod:`nuspace.
|
|
4
|
+
beside its shapes (the web device: :mod:`nuspace.web.stores`). The
|
|
5
5
|
record sits here, with the roots, so the host and the devices both read it
|
|
6
6
|
and neither imports the other for it. A store has no ops of its own: its
|
|
7
7
|
init term is the one thing it runs, and the store's declaration builds it.
|
|
@@ -119,11 +119,11 @@ class _Tree:
|
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
def _web_row(pid: nu.Str, spec: PlaneSpec) -> nu.Nu:
|
|
122
|
-
"""The plane's web row, from ``spec.web``: ``nuspace.
|
|
122
|
+
"""The plane's web row, from ``spec.web``: ``nuspace.web.add``, the plane shows on the web.
|
|
123
123
|
|
|
124
124
|
Imported here, not at the top, so core loads without the web device.
|
|
125
125
|
"""
|
|
126
|
-
from nuspace.
|
|
126
|
+
from nuspace.web import ops as web
|
|
127
127
|
|
|
128
128
|
flags = spec.web
|
|
129
129
|
return web.add(
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""Placing an id in an ordered list: before an anchor, after one, or at the end.
|
|
2
2
|
|
|
3
3
|
The one spelling of "placement is ``before=`` / ``after=`` an id, neither
|
|
4
|
-
means the end" that ops share. Generic: it works on any ``OrderedDictRef
|
|
5
|
-
of bool. The checks that make an anchor valid (it is there, it is a
|
|
4
|
+
means the end" that ops share. Generic: it works on any ``OrderedDictRef``,
|
|
5
|
+
of bool (membership, the default) or of values. The checks that make an anchor valid (it is there, it is a
|
|
6
6
|
sibling) are the caller's, made before this runs.
|
|
7
7
|
"""
|
|
8
8
|
|
|
@@ -37,17 +37,19 @@ def place(
|
|
|
37
37
|
*,
|
|
38
38
|
before: nu.StrArg | None = None,
|
|
39
39
|
after: nu.StrArg | None = None,
|
|
40
|
+
value: object = True,
|
|
40
41
|
) -> nu.Nu:
|
|
41
42
|
"""Put ``id`` into ``listed`` before or after an anchor, or at the end. One view call.
|
|
42
43
|
|
|
43
|
-
``
|
|
44
|
+
``value`` is what ``id`` holds, ``True`` for a membership list. ``id``
|
|
45
|
+
must not be listed yet: to move one, take it out first. No bracket.
|
|
44
46
|
|
|
45
47
|
Raises:
|
|
46
48
|
TypeError: Both ``before`` and ``after`` are given, at build.
|
|
47
49
|
"""
|
|
48
50
|
anchor_of(before, after)
|
|
49
51
|
if before is not None:
|
|
50
|
-
return listed.insert_before(before, id)
|
|
52
|
+
return listed.insert_before(before, id, value)
|
|
51
53
|
if after is not None:
|
|
52
|
-
return listed.insert_after(after, id)
|
|
53
|
-
return listed.set_item(id,
|
|
54
|
+
return listed.insert_after(after, id, value)
|
|
55
|
+
return listed.set_item(id, value)
|
|
@@ -1,49 +1,49 @@
|
|
|
1
|
-
"""``nuspace.
|
|
1
|
+
"""``nuspace.web``: the web device, the browser's way into the space, with its own stores.
|
|
2
2
|
|
|
3
3
|
The sdk, what a program calls, is the ops (:mod:`.ops`), flat here::
|
|
4
4
|
|
|
5
|
-
import nuspace.
|
|
5
|
+
import nuspace.web as web
|
|
6
6
|
|
|
7
7
|
nuspace.atomic(web.add(plane, editable=True)) # put a plane on the web
|
|
8
8
|
web.params(), web.on_params() # a cell's own pane params
|
|
9
9
|
web.restart_cell(sid, cell) # run one cell again, brackets itself
|
|
10
10
|
nuspace.atomic(web.link(row.link, plane)) # draw a link to a plane
|
|
11
|
-
nuspace.atomic(web.
|
|
11
|
+
nuspace.atomic(web.page(plane)) # {id, title, icon, href}: a PageLink table cell
|
|
12
|
+
web.url(plane, {"id": 3}) # its URL, plain python, for rows built outside a term
|
|
12
13
|
nuspace.atomic(web.set_role("home", plane)) # make a plane the home
|
|
13
14
|
|
|
14
15
|
- :mod:`.shapes`: :class:`Web` (web planes, recents, desks, roles) and :class:`Conn`
|
|
15
16
|
(browser tabs, their panes and sidebar folds); :mod:`.stores`: their
|
|
16
17
|
files, channels and init terms.
|
|
17
|
-
- :mod:`.ops`: the ops over them.
|
|
18
|
+
- :mod:`.ops`: the ops over them, all but the desks'.
|
|
19
|
+
- :mod:`.desks`: the desks: their ops (``web.desks.add_plane``, ...), the
|
|
20
|
+
browser node and feed, the desk pruner.
|
|
21
|
+
- :mod:`.home`: Home and the home indexer; :mod:`.planes`: every plane
|
|
22
|
+
the device ships with, made at open (search and settings live there).
|
|
18
23
|
- :mod:`.nav`: the driver running what the panes show.
|
|
19
24
|
- :mod:`.device`: the server and one arm per tab, the sidebar, viewer and
|
|
20
|
-
desks feeds under it
|
|
21
|
-
role planes) it ships with.
|
|
25
|
+
desks feeds under it.
|
|
22
26
|
Imported by the host only: it pulls in the web server.
|
|
23
27
|
|
|
24
28
|
Safe for a worker to import: nothing imported here pulls in a server.
|
|
25
29
|
"""
|
|
26
30
|
|
|
31
|
+
from . import desks
|
|
32
|
+
from .interactions import url
|
|
27
33
|
from .ops import (
|
|
28
34
|
add,
|
|
29
35
|
close_tab,
|
|
30
36
|
collapse,
|
|
31
|
-
create_desk,
|
|
32
|
-
delete_desk,
|
|
33
|
-
desk_order,
|
|
34
37
|
expand,
|
|
35
|
-
get_desk,
|
|
36
38
|
href,
|
|
37
39
|
link,
|
|
38
|
-
list_desks,
|
|
39
|
-
move_desk,
|
|
40
40
|
on_params,
|
|
41
41
|
open_tab,
|
|
42
|
+
page,
|
|
42
43
|
params,
|
|
43
44
|
restart_cell,
|
|
44
45
|
restart_pane,
|
|
45
46
|
set,
|
|
46
|
-
set_desk,
|
|
47
47
|
set_pane_params,
|
|
48
48
|
set_panes,
|
|
49
49
|
set_role,
|
|
@@ -66,24 +66,20 @@ __all__ = [
|
|
|
66
66
|
"add",
|
|
67
67
|
"close_tab",
|
|
68
68
|
"collapse",
|
|
69
|
-
"
|
|
70
|
-
"delete_desk",
|
|
71
|
-
"desk_order",
|
|
69
|
+
"desks",
|
|
72
70
|
"expand",
|
|
73
|
-
"get_desk",
|
|
74
71
|
"href",
|
|
75
72
|
"link",
|
|
76
|
-
"list_desks",
|
|
77
|
-
"move_desk",
|
|
78
73
|
"on_params",
|
|
79
74
|
"open_tab",
|
|
75
|
+
"page",
|
|
80
76
|
"params",
|
|
81
77
|
"restart_cell",
|
|
82
78
|
"restart_pane",
|
|
83
79
|
"set",
|
|
84
|
-
"set_desk",
|
|
85
80
|
"set_pane_params",
|
|
86
81
|
"set_panes",
|
|
87
82
|
"set_role",
|
|
83
|
+
"url",
|
|
88
84
|
"visit",
|
|
89
85
|
]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""The desks: their ops, the tab's copy of the desks and the roles, and the pruner.
|
|
2
|
+
|
|
3
|
+
``ops``
|
|
4
|
+
The desk ops a program calls, re-exported here::
|
|
5
|
+
|
|
6
|
+
import nuspace.web.desks as desks
|
|
7
|
+
|
|
8
|
+
nuspace.atomic(desks.add_plane(desk_id, plane))
|
|
9
|
+
|
|
10
|
+
``model``
|
|
11
|
+
The desk shape in plain python, and the hosts running it.
|
|
12
|
+
``ref``
|
|
13
|
+
The node the browser keeps, write only: it draws nothing.
|
|
14
|
+
``interactions``
|
|
15
|
+
Everything that node says and hears, in the browser's words.
|
|
16
|
+
``feed``
|
|
17
|
+
One arm per interaction. An event runs one op, a store change ships
|
|
18
|
+
the desks, the roles or the desk planes' titles again.
|
|
19
|
+
``pruner``
|
|
20
|
+
The system plane taking removed planes off every desk.
|
|
21
|
+
|
|
22
|
+
The wire contract is ``task-167/contract.md`` in Go.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
from nuspace.web.desks.ops import (
|
|
26
|
+
add_item,
|
|
27
|
+
add_plane,
|
|
28
|
+
create_desk,
|
|
29
|
+
delete_desk,
|
|
30
|
+
get_desk,
|
|
31
|
+
list_desks,
|
|
32
|
+
move_desk,
|
|
33
|
+
move_item,
|
|
34
|
+
remove_item,
|
|
35
|
+
rename_desk,
|
|
36
|
+
reset_item,
|
|
37
|
+
save_desk,
|
|
38
|
+
set_item,
|
|
39
|
+
write_items,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
"add_item",
|
|
45
|
+
"add_plane",
|
|
46
|
+
"create_desk",
|
|
47
|
+
"delete_desk",
|
|
48
|
+
"get_desk",
|
|
49
|
+
"list_desks",
|
|
50
|
+
"move_desk",
|
|
51
|
+
"move_item",
|
|
52
|
+
"remove_item",
|
|
53
|
+
"rename_desk",
|
|
54
|
+
"reset_item",
|
|
55
|
+
"save_desk",
|
|
56
|
+
"set_item",
|
|
57
|
+
"write_items",
|
|
58
|
+
]
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""The desks feed: one arm per interaction, all in parallel, for one tab. Host only.
|
|
2
|
+
|
|
3
|
+
- **browser to store.** A desk event runs its ops in one Web commit: a
|
|
4
|
+
create, a rename, a delete, a move, or ``items.write``, item writes on
|
|
5
|
+
one desk or more (a move across desks is one of these). A failure toasts
|
|
6
|
+
on the tab (:meth:`~nuspace.web.utils.Arms.event`) and writes nothing.
|
|
7
|
+
- **store to browser.** Any desk write (a desk created, renamed, moved or
|
|
8
|
+
deleted, an item set, moved or taken off, by any tab or program): every
|
|
9
|
+
desk ships again, whole, read back as ``{name, items}``, in sidebar
|
|
10
|
+
order, with that order as a list. A desk is a few hundred bytes, so
|
|
11
|
+
shipping all of them is cheaper than tracking which one moved. The roles
|
|
12
|
+
changed: the roles ship again.
|
|
13
|
+
- **titles.** The title and icon of every plane a desk links to, original
|
|
14
|
+
or recent, ship as their own write, so a tab names an item it neither
|
|
15
|
+
has open nor sees in its lazy tree. They ship again when the desks
|
|
16
|
+
change and when a plane's name or icon changes, the watches the
|
|
17
|
+
sidebar's tree uses. A plane with no row, or removed, is left out.
|
|
18
|
+
|
|
19
|
+
Level, with no re-checks, as the sidebar: a missed notification leaves
|
|
20
|
+
the tab stale until the next change.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from typing import TYPE_CHECKING
|
|
26
|
+
|
|
27
|
+
import nu
|
|
28
|
+
import nuspace
|
|
29
|
+
from nuspace.ops.brackets import atomic
|
|
30
|
+
from nuspace.shapes.space import Space
|
|
31
|
+
from nuspace.web import ops as web
|
|
32
|
+
from nuspace.web.desks import interactions
|
|
33
|
+
from nuspace.web.desks import ops as desk_ops
|
|
34
|
+
from nuspace.web.desks.model import DeskPlanes, DesksView, Items
|
|
35
|
+
from nuspace.web.shapes import Web
|
|
36
|
+
from nuspace.web.utils import Arms, field_dict, field_dicts, field_str
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
if TYPE_CHECKING:
|
|
40
|
+
from collections.abc import Callable
|
|
41
|
+
|
|
42
|
+
from nustd.ui.core import Ref
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
__all__ = ["desks_feed", "titles"]
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _ship(read: nu.Nu, send: Callable[[nu.Dict], nu.Nu]) -> nu.Nu:
|
|
49
|
+
"""``read`` in one snapshot, then ``send(value)`` to the browser."""
|
|
50
|
+
return nu.let(atomic(read), lambda held: send(nu.Dict(held)))
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def titles() -> nu.Dict:
|
|
54
|
+
"""``{plane_id: {title, icon}}`` for every plane a desk links to, original or recent. Bare read.
|
|
55
|
+
|
|
56
|
+
A title or icon the plane lacks is ``""``. A plane with no row, or
|
|
57
|
+
removed, is left out. Cost: one read of the desks, four reads a plane
|
|
58
|
+
on them.
|
|
59
|
+
"""
|
|
60
|
+
|
|
61
|
+
def look(at: nu.Attr) -> nu.List:
|
|
62
|
+
plane = nu.Str(at)
|
|
63
|
+
row = Space.planes[plane]
|
|
64
|
+
return nu.List.of(
|
|
65
|
+
plane, nu.Dict.of(title=row.name.fallback(""), icon=row.icon.fallback(""))
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
planes = nu.List(DeskPlanes(Web.desks.extract()))
|
|
69
|
+
shown = planes.iter().filter(lambda p: nuspace.plane.exists(nu.Str(p)))
|
|
70
|
+
return nu.dict(shown.map(look).to_list())
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _create(ev: nu.Attr) -> nu.Nu:
|
|
74
|
+
"""``desk.create``: the desk, last, then its items in their order."""
|
|
75
|
+
desk_id = field_str(ev, "desk_id")
|
|
76
|
+
desk = field_dict(ev, "desk")
|
|
77
|
+
made = desk_ops.create_desk(nu.Str(desk["name"]), id=desk_id)
|
|
78
|
+
return made >> desk_ops.write_items(desk_id, Items(desk["items"]))
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _move(ev: nu.Attr) -> nu.Nu:
|
|
82
|
+
"""``desk.move``: in front of ``before``, last for ``""``."""
|
|
83
|
+
desk_id, before = field_str(ev, "desk_id"), field_str(ev, "before")
|
|
84
|
+
return nu.IfDo(
|
|
85
|
+
before == "", desk_ops.move_desk(desk_id), desk_ops.move_desk(desk_id, before=before)
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _write(ev: nu.Attr) -> nu.Nu:
|
|
90
|
+
"""``items.write``: each desk's writes in turn, the caller's one commit around them all."""
|
|
91
|
+
|
|
92
|
+
def one(held: nu.Attr) -> nu.Nu:
|
|
93
|
+
w = nu.Dict(held)
|
|
94
|
+
return desk_ops.write_items(nu.Str(w["desk_id"]), w["sets"], w["deletes"], w["order"])
|
|
95
|
+
|
|
96
|
+
return nu.ForEachDo(field_dicts(ev, "writes"), one)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def desks_feed(desks: Ref, toasts: Ref) -> nu.Nu:
|
|
100
|
+
"""The desks, the roles and the desk planes' titles of one tab, live, as one term. Built per tab, never ends.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
desks: The shell's desks ref.
|
|
104
|
+
toasts: The tab's toast ref, where a failed event shows.
|
|
105
|
+
"""
|
|
106
|
+
arms = Arms("desks", toasts)
|
|
107
|
+
|
|
108
|
+
def op(name: str, change: nu.Nu, run: Callable[[nu.Attr], nu.Nu]) -> nu.Nu:
|
|
109
|
+
return arms.event(name, change, lambda ev: atomic(run(ev)))
|
|
110
|
+
|
|
111
|
+
def send_desks(held: nu.Dict) -> nu.Nu:
|
|
112
|
+
return interactions.set_desks(desks, held, nu.list(held.keys()))
|
|
113
|
+
|
|
114
|
+
shipped_desks = _ship(DesksView(Web.desks.extract()), send_desks)
|
|
115
|
+
shipped_roles = _ship(Web.roles.extract(), lambda r: interactions.set_roles(desks, r))
|
|
116
|
+
shipped_titles = _ship(titles(), lambda t: interactions.set_titles(desks, t))
|
|
117
|
+
on_desks = atomic(Web.desks.on_change())
|
|
118
|
+
return nu.ParallelAsync(
|
|
119
|
+
arms.states("desks", [on_desks], shipped_desks),
|
|
120
|
+
arms.states(
|
|
121
|
+
"roles",
|
|
122
|
+
[atomic(Web.roles.on_children_change()), atomic(Web.roles.on_descendants_change("*"))],
|
|
123
|
+
shipped_roles,
|
|
124
|
+
),
|
|
125
|
+
arms.states(
|
|
126
|
+
"titles",
|
|
127
|
+
[
|
|
128
|
+
atomic(Web.desks.on_change()),
|
|
129
|
+
atomic(Space.planes.on_descendants_change("*", "name")),
|
|
130
|
+
atomic(Space.planes.on_descendants_change("*", "icon")),
|
|
131
|
+
],
|
|
132
|
+
shipped_titles,
|
|
133
|
+
),
|
|
134
|
+
op("create", interactions.on_create_desk(desks), _create),
|
|
135
|
+
op(
|
|
136
|
+
"rename",
|
|
137
|
+
interactions.on_rename_desk(desks),
|
|
138
|
+
lambda ev: desk_ops.rename_desk(field_str(ev, "desk_id"), field_str(ev, "name")),
|
|
139
|
+
),
|
|
140
|
+
op(
|
|
141
|
+
"delete",
|
|
142
|
+
interactions.on_delete_desk(desks),
|
|
143
|
+
lambda ev: desk_ops.delete_desk(field_str(ev, "desk_id")),
|
|
144
|
+
),
|
|
145
|
+
op("move", interactions.on_move_desk(desks), _move),
|
|
146
|
+
op("write", interactions.on_write_items(desks), _write),
|
|
147
|
+
op(
|
|
148
|
+
"role",
|
|
149
|
+
interactions.on_set_role(desks),
|
|
150
|
+
lambda ev: web.set_role(field_str(ev, "role"), field_str(ev, "plane_id")),
|
|
151
|
+
),
|
|
152
|
+
)
|
|
@@ -13,7 +13,7 @@ from __future__ import annotations
|
|
|
13
13
|
|
|
14
14
|
from typing import TYPE_CHECKING
|
|
15
15
|
|
|
16
|
-
from nuspace.
|
|
16
|
+
from nuspace.web.utils import event, write
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
if TYPE_CHECKING:
|
|
@@ -25,8 +25,9 @@ __all__ = [
|
|
|
25
25
|
"on_create_desk",
|
|
26
26
|
"on_delete_desk",
|
|
27
27
|
"on_move_desk",
|
|
28
|
-
"
|
|
28
|
+
"on_rename_desk",
|
|
29
29
|
"on_set_role",
|
|
30
|
+
"on_write_items",
|
|
30
31
|
"set_desks",
|
|
31
32
|
"set_roles",
|
|
32
33
|
"set_titles",
|
|
@@ -37,7 +38,7 @@ __all__ = [
|
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
def set_desks(desks: Ref, held: DictArg, order: ListArg[str]) -> Nu:
|
|
40
|
-
"""Replace every desk: ``{desk_id:
|
|
41
|
+
"""Replace every desk: ``{desk_id: {name, items}}``, each desk whole, and ``order``, their ids in sidebar order."""
|
|
41
42
|
return write(desks, "set_desks", desks=held, order=order)
|
|
42
43
|
|
|
43
44
|
|
|
@@ -55,13 +56,23 @@ def set_titles(desks: Ref, titles: DictArg) -> Nu:
|
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
def on_create_desk(desks: Ref) -> Changed:
|
|
58
|
-
"""``{desk_id, desk}
|
|
59
|
+
"""``{desk_id, desk}``, ``desk`` as ``{name, items}``, last among the desks. The browser minted ``desk_id``."""
|
|
59
60
|
return event(desks, "desk.create")
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
def
|
|
63
|
-
"""``{desk_id,
|
|
64
|
-
return event(desks, "desk.
|
|
63
|
+
def on_rename_desk(desks: Ref) -> Changed:
|
|
64
|
+
"""``{desk_id, name}``."""
|
|
65
|
+
return event(desks, "desk.rename")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def on_write_items(desks: Ref) -> Changed:
|
|
69
|
+
"""``{writes: [{desk_id, sets, deletes, order}]}``: item writes on one desk or more, as one commit.
|
|
70
|
+
|
|
71
|
+
``sets`` item id to item (no id in it), ``deletes`` and ``order`` item
|
|
72
|
+
ids. A move across desks is one event: a delete on one desk, a set on
|
|
73
|
+
the other.
|
|
74
|
+
"""
|
|
75
|
+
return event(desks, "items.write")
|
|
65
76
|
|
|
66
77
|
|
|
67
78
|
def on_delete_desk(desks: Ref) -> Changed:
|