feat(fp): WP-26 — admin org-template editor
CI / frontend (push) Failing after 57s
CI / storybook-a11y (push) Successful in 4m27s
CI / backend (push) Successful in 1m15s
CI / codeql (csharp) (push) Failing after 1m42s
CI / codeql (javascript-typescript) (push) Failing after 1m19s
CI / api-client-drift (push) Successful in 1m40s
CI / e2e (push) Failing after 3h11m33s
CI / frontend (push) Failing after 57s
CI / storybook-a11y (push) Successful in 4m27s
CI / backend (push) Successful in 1m15s
CI / codeql (csharp) (push) Failing after 1m42s
CI / codeql (javascript-typescript) (push) Failing after 1m19s
CI / api-client-drift (push) Successful in 1m40s
CI / e2e (push) Failing after 3h11m33s
Edit the letter's org identity in place on the same canvas the drafter composes on (editableRegions='template'): letterhead/signature/footer become inline controls, content a read-only sample. Margins (bounded), logo upload (reuses the shared upload transport + single-upload), version history + rollback, proefbrief, and publish-with-impact-confirmation. House form-machine idiom (org-template.machine.ts) + root store with debounced save. Capability-gated (orgtemplate:edit) with a deny-by-default alert; route /brief/huisstijl. Backend + generated client were already in place (WP-23). Also fixes a pre-existing red check:tokens (WP-24 canvas hex fallbacks) and threads the published logo through to the drafter's canvas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -33,4 +33,11 @@ export class AccessStore {
|
||||
const rd = this.capabilities();
|
||||
return rd.tag === 'Success' && rd.value.includes(capability);
|
||||
}
|
||||
|
||||
/** True once `/me` has resolved (success or failure) — lets a page-level gate tell
|
||||
"still loading" apart from "denied", so an admin doesn't flash the denial alert. */
|
||||
readonly ready = computed(() => {
|
||||
const tag = this.capabilities().tag;
|
||||
return tag === 'Success' || tag === 'Failure';
|
||||
});
|
||||
}
|
||||
|
||||
@@ -38,6 +38,12 @@ export interface XhrUploadHandle {
|
||||
/** Sentinel rejection so the caller can tell a user-cancel from a real failure. */
|
||||
export const UPLOAD_ABORTED = Symbol('upload-aborted');
|
||||
|
||||
/** Direct URL to a stored document's bytes. Pure (no injection) so a store can build
|
||||
a letterhead-logo `src` without pulling `ApiClient` into its dependency graph. */
|
||||
export function uploadContentUrl(documentId: string): string {
|
||||
return `${environment.apiBaseUrl}/api/v1/uploads/${documentId}/content`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Infrastructure: the only place upload HTTP lives. Reads (categories, status,
|
||||
* delete) go through the NSwag client; the multipart POST is hand-written XHR
|
||||
@@ -94,7 +100,7 @@ export class UploadAdapter {
|
||||
* browser opens it. demo-* ids (dev simulation) have no bytes and 404 here.
|
||||
*/
|
||||
contentUrl(documentId: string): string {
|
||||
return `${environment.apiBaseUrl}/api/v1/uploads/${documentId}/content`;
|
||||
return uploadContentUrl(documentId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user