Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 803397ff52 |
@@ -4,5 +4,5 @@ TRAEFIK_NETWORK=internal
|
|||||||
TRAEFIK_CERT_RESOLVER=netcup
|
TRAEFIK_CERT_RESOLVER=netcup
|
||||||
|
|
||||||
# Keep these two values paired when deploying a newer published toolbox release.
|
# Keep these two values paired when deploying a newer published toolbox release.
|
||||||
TOOLBOX_RELEASE_VERSION=0.4.1
|
TOOLBOX_RELEASE_VERSION=0.4.2
|
||||||
TOOLBOX_RELEASE_SHA256=7d8907990a8b91c2bfda48d007fd8136e95222858db8f51780cd10f4165e9124
|
TOOLBOX_RELEASE_SHA256=20c1eacbcf03a9c8f0beeb53d2326a963e54dd9ca93e4f0118f95f10aec45389
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ ARG NGINX_IMAGE=nginxinc/nginx-unprivileged:1.31.3-alpine@sha256:18d67281256ded3
|
|||||||
|
|
||||||
FROM ${NGINX_IMAGE} AS release
|
FROM ${NGINX_IMAGE} AS release
|
||||||
|
|
||||||
ARG TOOLBOX_RELEASE_VERSION=0.4.1
|
ARG TOOLBOX_RELEASE_VERSION=0.4.2
|
||||||
ARG TOOLBOX_RELEASE_SHA256=7d8907990a8b91c2bfda48d007fd8136e95222858db8f51780cd10f4165e9124
|
ARG TOOLBOX_RELEASE_SHA256=20c1eacbcf03a9c8f0beeb53d2326a963e54dd9ca93e4f0118f95f10aec45389
|
||||||
ARG TOOLBOX_RELEASE_BASE_URL=https://git.add-ideas.de/zemion/toolbox-portal/releases/download
|
ARG TOOLBOX_RELEASE_BASE_URL=https://git.add-ideas.de/zemion/toolbox-portal/releases/download
|
||||||
|
|
||||||
RUN set -eu; \
|
RUN set -eu; \
|
||||||
|
|||||||
28
README.md
28
README.md
@@ -1,7 +1,7 @@
|
|||||||
# add·ideas Toolbox Portal
|
# add·ideas Toolbox Portal
|
||||||
|
|
||||||
`toolbox-portal` is the static launcher and release assembler for the add·ideas
|
`toolbox-portal` is the static launcher and release assembler for the add·ideas
|
||||||
browser toolbox. Version `0.2.1` reads one same-origin catalogue, shows each app
|
browser toolbox. Version `0.2.2` reads one same-origin catalogue, shows each app
|
||||||
as a full-page launch tile, and keeps personal pins, drag-and-drop ordering,
|
as a full-page launch tile, and keeps personal pins, drag-and-drop ordering,
|
||||||
visibility, and appearance in the current browser. Pinned tools have their own
|
visibility, and appearance in the current browser. Pinned tools have their own
|
||||||
section; search, category, and clickable tag filters stay close to the tool
|
section; search, category, and clickable tag filters stay close to the tool
|
||||||
@@ -30,7 +30,7 @@ npm run build
|
|||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
The package lock resolves the `^0.2.1` SDK ranges to the published `0.2.1`
|
The package lock resolves the `^0.2.2` SDK ranges to the published `0.2.2`
|
||||||
packages. A sibling SDK checkout is only needed when intentionally developing
|
packages. A sibling SDK checkout is only needed when intentionally developing
|
||||||
the SDK and portal together.
|
the SDK and portal together.
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ privacy and executable-code warning. Light, dark, and system modes are supported
|
|||||||
## Production deployment behind Traefik
|
## Production deployment behind Traefik
|
||||||
|
|
||||||
The committed `compose.yaml` is the shortest production path. Its release
|
The committed `compose.yaml` is the shortest production path. Its release
|
||||||
container downloads the immutable Toolbox 0.4.1 ZIP during the image build,
|
container downloads the immutable Toolbox 0.4.2 ZIP during the image build,
|
||||||
verifies SHA-256 before extracting it, and then copies only the verified static
|
verifies SHA-256 before extracting it, and then copies only the verified static
|
||||||
files into the pinned unprivileged nginx image. Node.js and a local portal
|
files into the pinned unprivileged nginx image. Node.js and a local portal
|
||||||
assembly are not required on the deployment host.
|
assembly are not required on the deployment host.
|
||||||
@@ -119,8 +119,8 @@ The app release should also publish a matching `.sha256` sidecar. The manifest
|
|||||||
must declare the pinned reverse-DNS id and version. Application and portal
|
must declare the pinned reverse-DNS id and version. Application and portal
|
||||||
versions are independent.
|
versions are independent.
|
||||||
|
|
||||||
`release/toolbox.lock.json` is the reviewed v0.4.1 lock. Its URLs and checksums
|
`release/toolbox.lock.json` is the reviewed v0.4.2 lock. Its URLs and checksums
|
||||||
pin the published PDF Tools 0.4.1, XSLT Tools 0.4.1, and OneNote Tools 0.3.1
|
pin the published PDF Tools 0.4.2, XSLT Tools 0.4.2, and OneNote Tools 0.3.2
|
||||||
release bytes. Use
|
release bytes. Use
|
||||||
`release/toolbox.lock.example.json` as the template for a future release and
|
`release/toolbox.lock.example.json` as the template for a future release and
|
||||||
verify every downloaded asset before committing updated values. Artifacts may be:
|
verify every downloaded asset before committing updated values. Artifacts may be:
|
||||||
@@ -142,7 +142,7 @@ npm run assemble -- \
|
|||||||
--lock release/toolbox.lock.json \
|
--lock release/toolbox.lock.json \
|
||||||
--portal-dist dist \
|
--portal-dist dist \
|
||||||
--output build/toolbox \
|
--output build/toolbox \
|
||||||
--archive build/add-ideas-toolbox-0.4.1.zip
|
--archive build/add-ideas-toolbox-0.4.2.zip
|
||||||
```
|
```
|
||||||
|
|
||||||
Existing output is refused. Pass `--force` only when replacing those exact
|
Existing output is refused. Pass `--force` only when replacing those exact
|
||||||
@@ -162,8 +162,8 @@ build/toolbox/
|
|||||||
├── xslt/
|
├── xslt/
|
||||||
└── onenote/
|
└── onenote/
|
||||||
|
|
||||||
build/add-ideas-toolbox-0.4.1.zip
|
build/add-ideas-toolbox-0.4.2.zip
|
||||||
build/add-ideas-toolbox-0.4.1.zip.sha256
|
build/add-ideas-toolbox-0.4.2.zip.sha256
|
||||||
```
|
```
|
||||||
|
|
||||||
The assembler verifies SHA-256 before opening an artifact, validates every app
|
The assembler verifies SHA-256 before opening an artifact, validates every app
|
||||||
@@ -184,7 +184,7 @@ directory separately:
|
|||||||
```sh
|
```sh
|
||||||
npm run package:static -- \
|
npm run package:static -- \
|
||||||
--input build/toolbox \
|
--input build/toolbox \
|
||||||
--output artifacts/add-ideas-toolbox-0.4.1.zip
|
--output artifacts/add-ideas-toolbox-0.4.2.zip
|
||||||
```
|
```
|
||||||
|
|
||||||
This also emits a `.sha256` sidecar.
|
This also emits a `.sha256` sidecar.
|
||||||
@@ -201,9 +201,9 @@ normal local XML/XSLT transformations do not require that permission.
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
podman build -f Containerfile \
|
podman build -f Containerfile \
|
||||||
-t git.add-ideas.de/zemion/toolbox:0.4.1 .
|
-t git.add-ideas.de/zemion/toolbox:0.4.2 .
|
||||||
podman run --rm -p 8080:8080 \
|
podman run --rm -p 8080:8080 \
|
||||||
git.add-ideas.de/zemion/toolbox:0.4.1
|
git.add-ideas.de/zemion/toolbox:0.4.2
|
||||||
```
|
```
|
||||||
|
|
||||||
For a direct-port local deployment after assembly, use the separate example:
|
For a direct-port local deployment after assembly, use the separate example:
|
||||||
@@ -220,7 +220,7 @@ docker login git.add-ideas.de
|
|||||||
docker buildx build \
|
docker buildx build \
|
||||||
--platform linux/amd64,linux/arm64 \
|
--platform linux/amd64,linux/arm64 \
|
||||||
--file Containerfile.release \
|
--file Containerfile.release \
|
||||||
--tag git.add-ideas.de/zemion/toolbox:0.4.1 \
|
--tag git.add-ideas.de/zemion/toolbox:0.4.2 \
|
||||||
--tag git.add-ideas.de/zemion/toolbox:0.4 \
|
--tag git.add-ideas.de/zemion/toolbox:0.4 \
|
||||||
--push .
|
--push .
|
||||||
```
|
```
|
||||||
@@ -246,8 +246,8 @@ permission to push code, releases, and container packages.
|
|||||||
all three apps, switch between them, and confirm the encoded `toolbox`
|
all three apps, switch between them, and confirm the encoded `toolbox`
|
||||||
context.
|
context.
|
||||||
5. Verify the distribution with
|
5. Verify the distribution with
|
||||||
`(cd build && sha256sum -c add-ideas-toolbox-0.4.1.zip.sha256)`.
|
`(cd build && sha256sum -c add-ideas-toolbox-0.4.2.zip.sha256)`.
|
||||||
6. Commit the reviewed lock, tag the toolbox release (for example `v0.4.1`), and
|
6. Commit the reviewed lock, tag the toolbox release (for example `v0.4.2`), and
|
||||||
push the branch and tag to Gitea.
|
push the branch and tag to Gitea.
|
||||||
7. In Gitea, open **Releases → New release**, select the tag, and upload the
|
7. In Gitea, open **Releases → New release**, select the tag, and upload the
|
||||||
static ZIP plus its `.sha256` file. Do not use a mutable “latest” URL in a
|
static ZIP plus its `.sha256` file. Do not use a mutable “latest” URL in a
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
dockerfile: Containerfile
|
dockerfile: Containerfile
|
||||||
image: git.add-ideas.de/zemion/toolbox:0.4.1
|
image: git.add-ideas.de/zemion/toolbox:0.4.2
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
read_only: true
|
read_only: true
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ services:
|
|||||||
context: .
|
context: .
|
||||||
dockerfile: Containerfile.release
|
dockerfile: Containerfile.release
|
||||||
args:
|
args:
|
||||||
TOOLBOX_RELEASE_VERSION: "${TOOLBOX_RELEASE_VERSION:-0.4.1}"
|
TOOLBOX_RELEASE_VERSION: "${TOOLBOX_RELEASE_VERSION:-0.4.2}"
|
||||||
TOOLBOX_RELEASE_SHA256: "${TOOLBOX_RELEASE_SHA256:-7d8907990a8b91c2bfda48d007fd8136e95222858db8f51780cd10f4165e9124}"
|
TOOLBOX_RELEASE_SHA256: "${TOOLBOX_RELEASE_SHA256:-20c1eacbcf03a9c8f0beeb53d2326a963e54dd9ca93e4f0118f95f10aec45389}"
|
||||||
image: "git.add-ideas.de/zemion/toolbox:${TOOLBOX_RELEASE_VERSION:-0.4.1}"
|
image: "git.add-ideas.de/zemion/toolbox:${TOOLBOX_RELEASE_VERSION:-0.4.2}"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
read_only: true
|
read_only: true
|
||||||
tmpfs:
|
tmpfs:
|
||||||
|
|||||||
22
package-lock.json
generated
22
package-lock.json
generated
@@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@add-ideas/toolbox-portal",
|
"name": "@add-ideas/toolbox-portal",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@add-ideas/toolbox-portal",
|
"name": "@add-ideas/toolbox-portal",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@add-ideas/toolbox-contract": "^0.2.1",
|
"@add-ideas/toolbox-contract": "^0.2.2",
|
||||||
"@add-ideas/toolbox-shell-react": "^0.2.1",
|
"@add-ideas/toolbox-shell-react": "^0.2.2",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
@@ -44,18 +44,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@add-ideas/toolbox-contract": {
|
"node_modules/@add-ideas/toolbox-contract": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-contract/-/0.2.1/toolbox-contract-0.2.1.tgz",
|
"resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-contract/-/0.2.2/toolbox-contract-0.2.2.tgz",
|
||||||
"integrity": "sha512-NmwV41+ZS0qBWUnI9vflm0PcsiqITmxpSQQ5vMVaToFZuSSIJupgM43tuV9G4OJ1En0eTdYNxbsd3nsYhju2kw==",
|
"integrity": "sha512-VcZ8j4O2PgFaIYgxs6r9u0uPxA+hHKwhCW+omfeVCtbjAAYhH2KhRlBGm0ERVVYcK5kchyzZLXrC4LKWRotVzg==",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@add-ideas/toolbox-shell-react": {
|
"node_modules/@add-ideas/toolbox-shell-react": {
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-shell-react/-/0.2.1/toolbox-shell-react-0.2.1.tgz",
|
"resolved": "https://git.add-ideas.de/api/packages/zemion/npm/%40add-ideas%2Ftoolbox-shell-react/-/0.2.2/toolbox-shell-react-0.2.2.tgz",
|
||||||
"integrity": "sha512-slpz9ODVbk27b+uvG3WeCmNa71Q6guabyVHT+jyGLT6ENLSbwmoEFZ0mKNJDxemltpt9KY8I7z47uNBsQ7yKYg==",
|
"integrity": "sha512-w/xbLCd50a2Jq7vQ9Z9ygUOuqlOCRkIYlk4vSJx0mf4REJNeMYi3PE2MbaLUC4DkQWyrmatsa5HNT89o0l91BA==",
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@add-ideas/toolbox-contract": "0.2.1"
|
"@add-ideas/toolbox-contract": "0.2.2"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=18 <20",
|
"react": ">=18 <20",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@add-ideas/toolbox-portal",
|
"name": "@add-ideas/toolbox-portal",
|
||||||
"version": "0.2.1",
|
"version": "0.2.2",
|
||||||
"license": "AGPL-3.0-only",
|
"license": "AGPL-3.0-only",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
"package:static": "node scripts/package-static.mjs"
|
"package:static": "node scripts/package-static.mjs"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@add-ideas/toolbox-contract": "^0.2.1",
|
"@add-ideas/toolbox-contract": "^0.2.2",
|
||||||
"@add-ideas/toolbox-shell-react": "^0.2.1",
|
"@add-ideas/toolbox-shell-react": "^0.2.2",
|
||||||
"@dnd-kit/core": "^6.3.1",
|
"@dnd-kit/core": "^6.3.1",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
"@dnd-kit/utilities": "^3.2.2",
|
"@dnd-kit/utilities": "^3.2.2",
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
# Corresponding source
|
# Corresponding source
|
||||||
|
|
||||||
The source code corresponding to add·ideas Toolbox Portal 0.2.1 is available at:
|
The source code corresponding to add·ideas Toolbox Portal 0.2.2 is available at:
|
||||||
|
|
||||||
https://git.add-ideas.de/zemion/toolbox-portal/src/tag/v0.4.1
|
https://git.add-ideas.de/zemion/toolbox-portal/src/tag/v0.4.2
|
||||||
|
|
||||||
Each bundled application contains its own `SOURCE.md`, license, and third-party
|
Each bundled application contains its own `SOURCE.md`, license, and third-party
|
||||||
license materials. The application sources are also linked from the portal.
|
license materials. The application sources are also linked from the portal.
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./toolbox-release-lock.schema.json",
|
"$schema": "./toolbox-release-lock.schema.json",
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"releaseVersion": "0.4.1",
|
"releaseVersion": "0.4.2",
|
||||||
"portalVersion": "0.2.1",
|
"portalVersion": "0.2.2",
|
||||||
"catalogue": {
|
"catalogue": {
|
||||||
"id": "de.add-ideas.toolbox",
|
"id": "de.add-ideas.toolbox",
|
||||||
"name": "add·ideas Toolbox",
|
"name": "add·ideas Toolbox",
|
||||||
@@ -15,23 +15,23 @@
|
|||||||
"apps": [
|
"apps": [
|
||||||
{
|
{
|
||||||
"id": "de.add-ideas.pdf-tools",
|
"id": "de.add-ideas.pdf-tools",
|
||||||
"version": "0.4.1",
|
"version": "0.4.2",
|
||||||
"artifact": "https://git.add-ideas.de/zemion/pdf-tools/releases/download/v0.4.1/pdf-tools-0.4.1.zip",
|
"artifact": "https://git.add-ideas.de/zemion/pdf-tools/releases/download/v0.4.2/pdf-tools-0.4.2.zip",
|
||||||
"sha256": "a7313e1fc709ec1fd3c09d46f7de84e07c299bd98f36fcba839ca0d6c8afc467",
|
"sha256": "ebb6711e149a59abf51eddc0927debba9118205bde91faf7dded132478bc23d0",
|
||||||
"target": "pdf"
|
"target": "pdf"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "de.add-ideas.xslt-tools",
|
"id": "de.add-ideas.xslt-tools",
|
||||||
"version": "0.4.1",
|
"version": "0.4.2",
|
||||||
"artifact": "https://git.add-ideas.de/zemion/xslt-tools/releases/download/v0.4.1/xslt-tools-0.4.1.zip",
|
"artifact": "https://git.add-ideas.de/zemion/xslt-tools/releases/download/v0.4.2/xslt-tools-0.4.2.zip",
|
||||||
"sha256": "0f24480b8a3f007d8e330592e598babf5982306e1e9566325c9ca60441deb2fb",
|
"sha256": "daaa821c10c6c6285f97128ba3d923e48efa24449f1fb0a21bf478abaf27499f",
|
||||||
"target": "xslt"
|
"target": "xslt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "de.add-ideas.onenote-tools",
|
"id": "de.add-ideas.onenote-tools",
|
||||||
"version": "0.3.1",
|
"version": "0.3.2",
|
||||||
"artifact": "https://git.add-ideas.de/zemion/onenote-tools/releases/download/v0.3.1/onenote-tools-0.3.1.zip",
|
"artifact": "https://git.add-ideas.de/zemion/onenote-tools/releases/download/v0.3.2/onenote-tools-0.3.2.zip",
|
||||||
"sha256": "52d0443698ae875438f01bb6b7735722d511bc99d4b9ca5060727ebb41276665",
|
"sha256": "c07e6909ae57bd7681f26ec29c7a4e927b6919123ef9e28aa2d8c55b842b65d2",
|
||||||
"target": "onenote"
|
"target": "onenote"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"$schema": "./toolbox-release-lock.schema.json",
|
"$schema": "./toolbox-release-lock.schema.json",
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"releaseVersion": "0.4.1",
|
"releaseVersion": "0.4.2",
|
||||||
"portalVersion": "0.2.1",
|
"portalVersion": "0.2.2",
|
||||||
"catalogue": {
|
"catalogue": {
|
||||||
"id": "de.add-ideas.toolbox",
|
"id": "de.add-ideas.toolbox",
|
||||||
"name": "add·ideas Toolbox",
|
"name": "add·ideas Toolbox",
|
||||||
@@ -15,23 +15,23 @@
|
|||||||
"apps": [
|
"apps": [
|
||||||
{
|
{
|
||||||
"id": "de.add-ideas.pdf-tools",
|
"id": "de.add-ideas.pdf-tools",
|
||||||
"version": "0.4.1",
|
"version": "0.4.2",
|
||||||
"artifact": "https://git.add-ideas.de/zemion/pdf-tools/releases/download/v0.4.1/pdf-tools-0.4.1.zip",
|
"artifact": "https://git.add-ideas.de/zemion/pdf-tools/releases/download/v0.4.2/pdf-tools-0.4.2.zip",
|
||||||
"sha256": "a7313e1fc709ec1fd3c09d46f7de84e07c299bd98f36fcba839ca0d6c8afc467",
|
"sha256": "ebb6711e149a59abf51eddc0927debba9118205bde91faf7dded132478bc23d0",
|
||||||
"target": "pdf"
|
"target": "pdf"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "de.add-ideas.xslt-tools",
|
"id": "de.add-ideas.xslt-tools",
|
||||||
"version": "0.4.1",
|
"version": "0.4.2",
|
||||||
"artifact": "https://git.add-ideas.de/zemion/xslt-tools/releases/download/v0.4.1/xslt-tools-0.4.1.zip",
|
"artifact": "https://git.add-ideas.de/zemion/xslt-tools/releases/download/v0.4.2/xslt-tools-0.4.2.zip",
|
||||||
"sha256": "0f24480b8a3f007d8e330592e598babf5982306e1e9566325c9ca60441deb2fb",
|
"sha256": "daaa821c10c6c6285f97128ba3d923e48efa24449f1fb0a21bf478abaf27499f",
|
||||||
"target": "xslt"
|
"target": "xslt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "de.add-ideas.onenote-tools",
|
"id": "de.add-ideas.onenote-tools",
|
||||||
"version": "0.3.1",
|
"version": "0.3.2",
|
||||||
"artifact": "https://git.add-ideas.de/zemion/onenote-tools/releases/download/v0.3.1/onenote-tools-0.3.1.zip",
|
"artifact": "https://git.add-ideas.de/zemion/onenote-tools/releases/download/v0.3.2/onenote-tools-0.3.2.zip",
|
||||||
"sha256": "52d0443698ae875438f01bb6b7735722d511bc99d4b9ca5060727ebb41276665",
|
"sha256": "c07e6909ae57bd7681f26ec29c7a4e927b6919123ef9e28aa2d8c55b842b65d2",
|
||||||
"target": "onenote"
|
"target": "onenote"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ function makeLock(artifact: string, sha256: string) {
|
|||||||
return {
|
return {
|
||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
releaseVersion: '0.1.0',
|
releaseVersion: '0.1.0',
|
||||||
portalVersion: '0.2.1',
|
portalVersion: '0.2.2',
|
||||||
catalogue: {
|
catalogue: {
|
||||||
id: 'de.add-ideas.toolbox',
|
id: 'de.add-ideas.toolbox',
|
||||||
name: 'Test Toolbox',
|
name: 'Test Toolbox',
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe('portal UI', () => {
|
|||||||
).toHaveAttribute('rel', 'noopener noreferrer');
|
).toHaveAttribute('rel', 'noopener noreferrer');
|
||||||
expect(
|
expect(
|
||||||
sourceLinks.find((link) =>
|
sourceLinks.find((link) =>
|
||||||
link.getAttribute('href')?.endsWith('/toolbox-portal/src/tag/v0.4.1')
|
link.getAttribute('href')?.endsWith('/toolbox-portal/src/tag/v0.4.2')
|
||||||
)
|
)
|
||||||
).toBeDefined();
|
).toBeDefined();
|
||||||
expect(
|
expect(
|
||||||
@@ -229,16 +229,33 @@ describe('portal UI', () => {
|
|||||||
const brand = within(header).getByRole('link', {
|
const brand = within(header).getByRole('link', {
|
||||||
name: 'add·ideas Toolbox',
|
name: 'add·ideas Toolbox',
|
||||||
});
|
});
|
||||||
|
const controls = within(header).getByRole('group', {
|
||||||
|
name: 'Toolbox controls',
|
||||||
|
});
|
||||||
expect(
|
expect(
|
||||||
personalize.compareDocumentPosition(apps) &
|
Array.from(controls.children, (element) =>
|
||||||
|
element.getAttribute('aria-label')
|
||||||
|
)
|
||||||
|
).toEqual(['Help', 'Toolbox source on Gitea', 'Apps', 'Personalize']);
|
||||||
|
expect(help.compareDocumentPosition(source)).toBe(
|
||||||
Node.DOCUMENT_POSITION_FOLLOWING
|
Node.DOCUMENT_POSITION_FOLLOWING
|
||||||
).toBeTruthy();
|
);
|
||||||
|
expect(source.compareDocumentPosition(apps)).toBe(
|
||||||
|
Node.DOCUMENT_POSITION_FOLLOWING
|
||||||
|
);
|
||||||
|
expect(apps.compareDocumentPosition(personalize)).toBe(
|
||||||
|
Node.DOCUMENT_POSITION_FOLLOWING
|
||||||
|
);
|
||||||
expect(
|
expect(
|
||||||
apps.compareDocumentPosition(source) & Node.DOCUMENT_POSITION_FOLLOWING
|
Array.from(
|
||||||
).toBeTruthy();
|
header.querySelector('.toolbox-shell__bar')?.children ?? [],
|
||||||
expect(
|
(element) => element.className
|
||||||
source.compareDocumentPosition(help) & Node.DOCUMENT_POSITION_FOLLOWING
|
)
|
||||||
).toBeTruthy();
|
).toEqual([
|
||||||
|
'toolbox-shell__brand',
|
||||||
|
'toolbox-shell__identity',
|
||||||
|
'toolbox-shell__controls',
|
||||||
|
]);
|
||||||
expect(brand.querySelector('img')).toHaveAttribute('src', './favicon.svg');
|
expect(brand.querySelector('img')).toHaveAttribute('src', './favicon.svg');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -412,6 +429,13 @@ describe('portal UI', () => {
|
|||||||
});
|
});
|
||||||
const popover = screen.getByRole('dialog', { name: 'Personalize Toolbox' });
|
const popover = screen.getByRole('dialog', { name: 'Personalize Toolbox' });
|
||||||
expect(popover).toContainElement(heading);
|
expect(popover).toContainElement(heading);
|
||||||
|
expect(popover).toContainElement(screen.getByText('On this device'));
|
||||||
|
expect(
|
||||||
|
within(popover).getByRole('group', { name: 'Appearance' })
|
||||||
|
).toBeInTheDocument();
|
||||||
|
expect(
|
||||||
|
popover.querySelector('.toolbox-shell__preferences-content')
|
||||||
|
).toBeInTheDocument();
|
||||||
expect(popover).not.toHaveAttribute('aria-modal');
|
expect(popover).not.toHaveAttribute('aria-modal');
|
||||||
expect(container.querySelector('.site-shell')).not.toHaveAttribute('inert');
|
expect(container.querySelector('.site-shell')).not.toHaveAttribute('inert');
|
||||||
expect(screen.getByText(/does not transmit them/i)).toHaveTextContent(
|
expect(screen.getByText(/does not transmit them/i)).toHaveTextContent(
|
||||||
|
|||||||
@@ -473,9 +473,9 @@ export default function App() {
|
|||||||
</span>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
<span>
|
<span>
|
||||||
Portal v0.2.1 ·{' '}
|
Portal v0.2.2 ·{' '}
|
||||||
<a
|
<a
|
||||||
href="https://git.add-ideas.de/zemion/toolbox-portal/src/tag/v0.4.1"
|
href="https://git.add-ideas.de/zemion/toolbox-portal/src/tag/v0.4.2"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { useRef, useState, type ChangeEvent } from 'react';
|
import { useRef, useState, type ChangeEvent } from 'react';
|
||||||
|
import { ToolboxPersonalizePanel } from '@add-ideas/toolbox-shell-react';
|
||||||
import {
|
import {
|
||||||
defaultPreferences,
|
defaultPreferences,
|
||||||
parsePreferences,
|
parsePreferences,
|
||||||
type Preferences,
|
type Preferences,
|
||||||
} from '../preferences';
|
} from '../preferences';
|
||||||
import type { ThemeMode } from '../types';
|
|
||||||
|
|
||||||
interface PreferencesPanelProps {
|
interface PreferencesPanelProps {
|
||||||
preferences: Preferences;
|
preferences: Preferences;
|
||||||
@@ -20,10 +20,6 @@ export function PreferencesPanel({
|
|||||||
const fileInput = useRef<HTMLInputElement>(null);
|
const fileInput = useRef<HTMLInputElement>(null);
|
||||||
const [message, setMessage] = useState('');
|
const [message, setMessage] = useState('');
|
||||||
|
|
||||||
function setTheme(theme: ThemeMode) {
|
|
||||||
onChange({ ...preferences, theme });
|
|
||||||
}
|
|
||||||
|
|
||||||
function exportPreferences() {
|
function exportPreferences() {
|
||||||
const blob = new Blob([`${JSON.stringify(preferences, null, 2)}\n`], {
|
const blob = new Blob([`${JSON.stringify(preferences, null, 2)}\n`], {
|
||||||
type: 'application/json',
|
type: 'application/json',
|
||||||
@@ -55,39 +51,11 @@ export function PreferencesPanel({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<ToolboxPersonalizePanel
|
||||||
className="preferences-content"
|
theme={preferences.theme}
|
||||||
aria-labelledby="preferences-title"
|
onThemeChange={(theme) => onChange({ ...preferences, theme })}
|
||||||
|
storageAvailable={storageAvailable}
|
||||||
>
|
>
|
||||||
<div className="preferences-heading">
|
|
||||||
<p className="preferences-kicker">On this device</p>
|
|
||||||
<h2 id="preferences-title">Personalize your toolbox</h2>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{!storageAvailable && (
|
|
||||||
<p className="inline-warning" role="status">
|
|
||||||
Browser storage is unavailable. Changes will last only until this page
|
|
||||||
closes.
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<fieldset className="theme-choice">
|
|
||||||
<legend>Appearance</legend>
|
|
||||||
<div>
|
|
||||||
{(['system', 'light', 'dark'] as const).map((theme) => (
|
|
||||||
<button
|
|
||||||
key={theme}
|
|
||||||
type="button"
|
|
||||||
aria-pressed={preferences.theme === theme}
|
|
||||||
className={preferences.theme === theme ? 'is-selected' : ''}
|
|
||||||
onClick={() => setTheme(theme)}
|
|
||||||
>
|
|
||||||
{theme.slice(0, 1).toLocaleUpperCase() + theme.slice(1)}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
|
|
||||||
<div className="preference-summary">
|
<div className="preference-summary">
|
||||||
<div>
|
<div>
|
||||||
<strong>{preferences.pinned.length}</strong>
|
<strong>{preferences.pinned.length}</strong>
|
||||||
@@ -139,6 +107,6 @@ export function PreferencesPanel({
|
|||||||
<p className="action-message" role="status" aria-live="polite">
|
<p className="action-message" role="status" aria-live="polite">
|
||||||
{message}
|
{message}
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</ToolboxPersonalizePanel>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -690,38 +690,6 @@ main {
|
|||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.portal-header .toolbox-shell__personalize-popover {
|
|
||||||
width: min(26rem, calc(100vw - 1.5rem));
|
|
||||||
max-height: calc(100vh - 5.5rem);
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preferences-content {
|
|
||||||
padding: 0.35rem;
|
|
||||||
color: var(--toolbox-text, var(--text));
|
|
||||||
}
|
|
||||||
|
|
||||||
.preferences-heading {
|
|
||||||
margin-bottom: 0.9rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preferences-content h2 {
|
|
||||||
margin: 0;
|
|
||||||
font-family: Inter, Avenir, 'Segoe UI', sans-serif;
|
|
||||||
font-size: 1rem;
|
|
||||||
letter-spacing: -0.025em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.portal-header .preferences-kicker {
|
|
||||||
margin: 0 0 0.3rem;
|
|
||||||
padding: 0;
|
|
||||||
color: var(--toolbox-accent, var(--brand));
|
|
||||||
font-size: 0.68rem;
|
|
||||||
font-weight: 750;
|
|
||||||
letter-spacing: 0.1em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.help-steps {
|
.help-steps {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.85rem;
|
gap: 0.85rem;
|
||||||
@@ -750,44 +718,6 @@ main {
|
|||||||
font-size: 1.3rem;
|
font-size: 1.3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme-choice {
|
|
||||||
margin: 1rem 0;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-choice legend {
|
|
||||||
margin-bottom: 0.6rem;
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 0.78rem;
|
|
||||||
font-weight: 700;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-choice > div {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 0.45rem;
|
|
||||||
padding: 0.35rem;
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
background: var(--surface-soft);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-choice button {
|
|
||||||
padding: 0.62rem;
|
|
||||||
border: 0;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
background: transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-choice button.is-selected {
|
|
||||||
background: var(--surface);
|
|
||||||
color: var(--brand);
|
|
||||||
box-shadow: 0 2px 8px rgba(20, 30, 60, 0.09);
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preference-summary {
|
.preference-summary {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(3, 1fr);
|
grid-template-columns: repeat(3, 1fr);
|
||||||
@@ -846,15 +776,6 @@ main {
|
|||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.portal-header .inline-warning {
|
|
||||||
margin: 0 0 0.75rem;
|
|
||||||
padding: 0.7rem 0.8rem;
|
|
||||||
border-radius: 0.6rem;
|
|
||||||
background: color-mix(in srgb, var(--danger) 8%, var(--surface));
|
|
||||||
color: var(--danger);
|
|
||||||
font-size: 0.82rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.visually-hidden {
|
.visually-hidden {
|
||||||
position: absolute !important;
|
position: absolute !important;
|
||||||
width: 1px !important;
|
width: 1px !important;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export const pdfManifest: ToolboxAppManifest = {
|
|||||||
schemaVersion: 1,
|
schemaVersion: 1,
|
||||||
id: 'de.add-ideas.pdf-tools',
|
id: 'de.add-ideas.pdf-tools',
|
||||||
name: 'PDF Workbench',
|
name: 'PDF Workbench',
|
||||||
version: '0.4.1',
|
version: '0.4.2',
|
||||||
description: 'Page-level PDF operations performed locally in the browser.',
|
description: 'Page-level PDF operations performed locally in the browser.',
|
||||||
entry: './',
|
entry: './',
|
||||||
icon: './favicon.svg',
|
icon: './favicon.svg',
|
||||||
@@ -39,7 +39,7 @@ export const xsltManifest: ToolboxAppManifest = {
|
|||||||
...pdfManifest,
|
...pdfManifest,
|
||||||
id: 'de.add-ideas.xslt-tools',
|
id: 'de.add-ideas.xslt-tools',
|
||||||
name: 'XSLT Workbench',
|
name: 'XSLT Workbench',
|
||||||
version: '0.4.1',
|
version: '0.4.2',
|
||||||
description: 'Transform XML locally with XSLT in the browser.',
|
description: 'Transform XML locally with XSLT in the browser.',
|
||||||
icon: './xslt.svg',
|
icon: './xslt.svg',
|
||||||
categories: ['documents', 'developer'],
|
categories: ['documents', 'developer'],
|
||||||
@@ -54,7 +54,7 @@ export const onenoteManifest: ToolboxAppManifest = {
|
|||||||
...pdfManifest,
|
...pdfManifest,
|
||||||
id: 'de.add-ideas.onenote-tools',
|
id: 'de.add-ideas.onenote-tools',
|
||||||
name: 'OneNote Reader',
|
name: 'OneNote Reader',
|
||||||
version: '0.3.1',
|
version: '0.3.2',
|
||||||
description: 'Inspect OneNote packages locally in the browser.',
|
description: 'Inspect OneNote packages locally in the browser.',
|
||||||
icon: './onenote.svg',
|
icon: './onenote.svg',
|
||||||
categories: ['documents', 'notes'],
|
categories: ['documents', 'notes'],
|
||||||
|
|||||||
Reference in New Issue
Block a user