Release govoplan-scheduling v0.1.22: unify interface contracts and documentation
This commit is contained in:
+2
-2
@@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "govoplan-scheduling"
|
||||
version = "0.1.21"
|
||||
version = "0.1.22"
|
||||
description = "GovOPlaN meeting scheduling and Terminfindung module seed."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
license = { file = "LICENSE" }
|
||||
authors = [{ name = "GovOPlaN" }]
|
||||
dependencies = [
|
||||
"govoplan-core>=0.1.18",
|
||||
"govoplan-core>=0.1.45",
|
||||
"govoplan-poll>=0.1.18",
|
||||
]
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
__all__ = ["__version__"]
|
||||
|
||||
__version__ = "0.1.21"
|
||||
__version__ = "0.1.22"
|
||||
|
||||
@@ -51,7 +51,7 @@ from govoplan_scheduling.backend.dsar_provider import SCHEDULING_DSAR_CAPABILITY
|
||||
|
||||
MODULE_ID = "scheduling"
|
||||
MODULE_NAME = "Scheduling"
|
||||
MODULE_VERSION = "0.1.21"
|
||||
MODULE_VERSION = "0.1.22"
|
||||
READ_SCOPE = "scheduling:schedule:read"
|
||||
WRITE_SCOPE = "scheduling:schedule:write"
|
||||
ADMIN_SCOPE = "scheduling:schedule:admin"
|
||||
@@ -111,6 +111,21 @@ ROLE_TEMPLATES = (
|
||||
)
|
||||
|
||||
DOCUMENTATION = (
|
||||
DocumentationTopic(
|
||||
id="scheduling.workspace-layout",
|
||||
title="Scheduling workspace layout",
|
||||
summary="Find workspace actions and read consistently arranged content.",
|
||||
body="The workspace always keeps Reload and New scheduling request at the upper right, including empty, detail, and editor states. Reload sits immediately before New. Creation remains visible but disabled while saving or without creation/write permission; it never disappears inside the request-list card. An open editor keeps its own Save and Discard actions and the unsaved-change guard applies before switching requests. Administrators grant existing Scheduling permissions; this layout adds no permission or automatic invitation or Calendar action.",
|
||||
layer="static",
|
||||
documentation_types=("user", "admin"),
|
||||
audience=("user", "module_admin", "operator"),
|
||||
order=5,
|
||||
translations={"de": {
|
||||
"title": "Terminfindung: Aufbau des Arbeitsbereichs",
|
||||
"summary": "Arbeitsbereichsaktionen finden und einheitlich angeordnete Inhalte lesen.",
|
||||
"body": "Der Arbeitsbereich zeigt Neu laden und Neue Terminanfrage immer oben rechts, auch in leerem Zustand, Detailansicht und Bearbeitung. Neu laden steht unmittelbar vor Neu. Das Anlegen bleibt beim Speichern oder ohne Schreibrecht sichtbar, aber deaktiviert; es verschwindet nicht innerhalb der Anfragekartenleiste. Ein geöffneter Editor behält Speichern und Verwerfen; beim Wechsel schützt die Rückfrage ungespeicherte Änderungen. Administratoren vergeben bestehende Scheduling-Rechte; dieses Layout fügt weder Rechte noch automatische Einladungen oder Kalenderaktionen hinzu.",
|
||||
}},
|
||||
),
|
||||
DocumentationTopic(
|
||||
id="scheduling.module-boundary",
|
||||
title="Scheduling module boundary",
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@govoplan/scheduling-webui",
|
||||
"version": "0.1.21",
|
||||
"version": "0.1.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
@@ -18,7 +18,7 @@
|
||||
"test:ui-structure": "node scripts/test-scheduling-page-structure.mjs"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@govoplan/core-webui": "^0.1.18",
|
||||
"@govoplan/core-webui": "^0.1.45",
|
||||
"lucide-react": "^1.23.0",
|
||||
"react": ">=19.2.7 <20",
|
||||
"react-dom": ">=19.2.7 <20",
|
||||
|
||||
@@ -26,7 +26,12 @@ assert.match(page, /ActionBlockerHint,[\s\S]*DocumentationHelpLink,[\s\S]*StageR
|
||||
assert.match(page, /className="scheduling-workspace-layout"/);
|
||||
assert.match(page, /<aside className="scheduling-request-sidebar">/);
|
||||
assert.match(page, /<section className="scheduling-main-panel">/);
|
||||
assert.match(page, /title=\{I18N\.requests\}[\s\S]*<Plus aria-hidden="true" size=\{16\} \/> \{I18N\.add\}/);
|
||||
const workspaceBar = page.slice(page.indexOf('<section className="scheduling-workspace">'), page.indexOf('<div className="scheduling-workspace-layout">'));
|
||||
assert.match(workspaceBar, /scope="workspace"[\s\S]*variant="collection"[\s\S]*reloadAction=/);
|
||||
assert.match(workspaceBar, /createAction=\{<Button[\s\S]*disabled=\{!canCreateOrWrite \|\| saving\}[\s\S]*I18N\.newRequest/);
|
||||
assert.doesNotMatch(workspaceBar, /createAction=\{canCreateOrWrite \?/);
|
||||
assert.match(workspaceBar, /!canCreateOrWrite \? I18N\.createPermissionRequired : undefined/);
|
||||
assert.doesNotMatch(page, /scheduling-sidebar-actions/);
|
||||
assert.match(page, /title=\{I18N\.myRequests\}/);
|
||||
assert.match(page, /title=\{I18N\.invitedRequests\}/);
|
||||
assert.ok(page.indexOf("title={I18N.myRequests}") < page.indexOf("title={I18N.invitedRequests}"));
|
||||
|
||||
@@ -140,6 +140,7 @@ const I18N = {
|
||||
actions: "i18n:govoplan-core.actions.c3cd636a",
|
||||
add: "i18n:govoplan-core.add.61cc55aa",
|
||||
addRequest: "i18n:govoplan-scheduling.add_scheduling_request.3c71be15",
|
||||
createPermissionRequired: "i18n:govoplan-scheduling.create_permission_required",
|
||||
addParticipant: "i18n:govoplan-scheduling.add_participant.6cff957d",
|
||||
addSlot: "i18n:govoplan-scheduling.add_slot.9fcff3ed",
|
||||
answered: "i18n:govoplan-scheduling.answered.e0aafffa",
|
||||
@@ -933,39 +934,17 @@ export default function SchedulingPage({ settings, auth }: { settings: ApiSettin
|
||||
return (
|
||||
<WorkspaceFrame as="main" height="viewport" surface="plain" className="scheduling-page" label="Scheduling workspace">
|
||||
<section className="scheduling-workspace">
|
||||
<WorkspaceActionBar
|
||||
scope="workspace"
|
||||
variant="collection"
|
||||
refreshable
|
||||
reloadAction={{ onReload: () => void loadRequests(selected?.id), loading: loading || saving, disabledReason: saving ? I18N.saving : undefined, label: I18N.refresh }}
|
||||
helpAction={<DocumentationHelpLink reference={{ topicId: "scheduling.find-and-decide-meeting-time", documentationType: "user" }} />}
|
||||
createAction={<Button type="button" variant="primary" onClick={beginCreate} disabled={!canCreateOrWrite || saving} disabledReason={saving ? I18N.saving : !canCreateOrWrite ? I18N.createPermissionRequired : undefined}><Plus aria-hidden="true" size={16} /> {I18N.newRequest}</Button>}
|
||||
/>
|
||||
<div className="scheduling-workspace-layout">
|
||||
<aside className="scheduling-request-sidebar">
|
||||
<Card
|
||||
title={I18N.requests}
|
||||
actions={(
|
||||
<WorkspaceActionBar
|
||||
scope="collection-pane"
|
||||
variant="collection"
|
||||
refreshable
|
||||
reloadAction={{
|
||||
onReload: () => void loadRequests(selected?.id),
|
||||
loading: loading || saving,
|
||||
disabledReason: saving ? I18N.saving : undefined,
|
||||
label: I18N.refresh
|
||||
}}
|
||||
className="scheduling-sidebar-actions"
|
||||
helpAction={<DocumentationHelpLink
|
||||
reference={{
|
||||
topicId: "scheduling.find-and-decide-meeting-time",
|
||||
documentationType: "user"
|
||||
}} />}
|
||||
createAction={canCreateOrWrite ? (
|
||||
<Button
|
||||
type="button"
|
||||
variant="primary"
|
||||
onClick={beginCreate}
|
||||
disabled={saving}
|
||||
disabledReason={saving ? I18N.saving : undefined}>
|
||||
<Plus aria-hidden="true" size={16} /> {I18N.add}
|
||||
</Button>
|
||||
) : undefined}
|
||||
/>
|
||||
)}>
|
||||
<Card title={I18N.requests}>
|
||||
{loading ? <p className="scheduling-note" role="status">{I18N.loading}</p> : null}
|
||||
<RequestGroup
|
||||
title={I18N.myRequests}
|
||||
@@ -1003,7 +982,6 @@ export default function SchedulingPage({ settings, auth }: { settings: ApiSettin
|
||||
scope="editor-pane"
|
||||
variant="editor"
|
||||
state={saving ? "saving" : draftDirty && !title.trim() ? "invalid" : draftDirty ? "dirty" : "clean"}
|
||||
className="scheduling-page-header"
|
||||
contextActions={<div className="scheduling-page-title">
|
||||
<CalendarCheck aria-hidden="true" size={20} />
|
||||
<div>
|
||||
|
||||
@@ -206,6 +206,7 @@ export const generatedTranslations = {
|
||||
"i18n:govoplan-scheduling.the_response_replaces_your_previous_availability_choices.74c16d53": "The response replaces your previous availability choices.",
|
||||
"i18n:govoplan-scheduling.title.768e0c1c": "Title",
|
||||
"i18n:govoplan-scheduling.unavailable.2c9c1f79": "Unavailable",
|
||||
"i18n:govoplan-scheduling.create_permission_required": "Creating a scheduling request requires Scheduling write or administration permission. Ask an Access or tenant administrator to grant it.",
|
||||
"i18n:govoplan-scheduling.unchecked.1b927dec": "Unchecked",
|
||||
"i18n:govoplan-scheduling.update_response.346233cf": "Update response",
|
||||
"i18n:govoplan-scheduling.use_a_calendar_for_availability_checks_tentative_holds_a.20ccc1fa": "Use a calendar for availability checks, tentative holds, and the final event.",
|
||||
@@ -424,6 +425,7 @@ export const generatedTranslations = {
|
||||
"i18n:govoplan-scheduling.the_response_replaces_your_previous_availability_choices.74c16d53": "Die Antwort ersetzt Ihre vorherige Verfügbarkeitsauswahl.",
|
||||
"i18n:govoplan-scheduling.title.768e0c1c": "Titel",
|
||||
"i18n:govoplan-scheduling.unavailable.2c9c1f79": "Nicht verfügbar",
|
||||
"i18n:govoplan-scheduling.create_permission_required": "Zum Anlegen einer Terminanfrage benötigen Sie Schreib- oder Administrationsrechte für Scheduling. Bitten Sie die Access- oder Mandantenadministration um diese Berechtigung.",
|
||||
"i18n:govoplan-scheduling.unchecked.1b927dec": "Nicht geprüft",
|
||||
"i18n:govoplan-scheduling.update_response.346233cf": "Antwort aktualisieren",
|
||||
"i18n:govoplan-scheduling.use_a_calendar_for_availability_checks_tentative_holds_a.20ccc1fa": "Einen Kalender für Verfügbarkeitsprüfungen, vorläufige Reservierungen und den endgültigen Termin verwenden.",
|
||||
|
||||
@@ -145,18 +145,6 @@
|
||||
padding: 10px 12px;
|
||||
}
|
||||
|
||||
.scheduling-sidebar-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.scheduling-sidebar-actions .btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.scheduling-main-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -176,18 +164,6 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.scheduling-page-header {
|
||||
min-height: 58px;
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 10px 14px;
|
||||
border-bottom: var(--border-line);
|
||||
background: var(--panel-header);
|
||||
}
|
||||
|
||||
.scheduling-page-title,
|
||||
.scheduling-page-actions,
|
||||
.scheduling-card-actions,
|
||||
@@ -468,11 +444,6 @@
|
||||
border-bottom: var(--border-line);
|
||||
}
|
||||
|
||||
.scheduling-page-header {
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.scheduling-page-actions,
|
||||
.scheduling-card-actions,
|
||||
.scheduling-actions {
|
||||
|
||||
Reference in New Issue
Block a user