@ti-engine/web-framework 1.13.1
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/.env +4 -0
- package/CHANGELOG.md +274 -0
- package/README.md +26 -0
- package/bin/build/post-install.js +18 -0
- package/bin/localization/web-server-labels.json +28 -0
- package/bin/static/.well-known/appspecific/com.chrome.devtools.json +6 -0
- package/bin/static/favicon.ico +0 -0
- package/bin/static/fragments/components/component-notification-bar.html +21 -0
- package/bin/static/fragments/components/component-sidebar-flyout.html +37 -0
- package/bin/static/fragments/components/component-sidebar.html +33 -0
- package/bin/static/fragments/components/component-tooltip.html +11 -0
- package/bin/static/fragments/components/component-topbar.html +6 -0
- package/bin/static/fragments/frame-administration.html +3 -0
- package/bin/static/fragments/frame-application.html +19 -0
- package/bin/static/fragments/frame-dashboard.html +3 -0
- package/bin/static/fragments/frame-login.html +105 -0
- package/bin/static/fragments/frame-not-found.html +3 -0
- package/bin/static/fragments/frame-profile.html +3 -0
- package/bin/static/index.html +23 -0
- package/bin/static/scripts/lib/alpinejs-csp.min.js +7 -0
- package/bin/static/scripts/lib/htmx.min.js +1 -0
- package/bin/static/scripts/lib/safe-nonce.min.js +1 -0
- package/bin/static/scripts/ti-charts.js +1591 -0
- package/bin/static/scripts/ti-framework.css +3195 -0
- package/bin/static/scripts/ti-framework.js +1427 -0
- package/bin/static/scripts/ti-theme-black-glass.css +216 -0
- package/bin/static/scripts/ti-theme-daylight.css +87 -0
- package/bin/web-app-manager.js +564 -0
- package/bin/web-server.js +604 -0
- package/bin/web-server.json +49 -0
- package/components/admin-config-handlers.js +92 -0
- package/components/auth-manager.js +344 -0
- package/components/authorization.js +135 -0
- package/components/config-change-notifier.js +98 -0
- package/components/config-registry.js +246 -0
- package/components/config-service.js +349 -0
- package/components/config-store.js +246 -0
- package/components/definitions.types.js +26 -0
- package/components/session-store.js +111 -0
- package/components/user.js +133 -0
- package/components/web-handlers.js +765 -0
- package/package.json +66 -0
package/.env
ADDED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
# ti-engine web-framework changelog
|
|
2
|
+
|
|
3
|
+
This document will contain the list of changes made to the framework. The format is based on the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification.
|
|
4
|
+
|
|
5
|
+
## Version 1.13.0
|
|
6
|
+
|
|
7
|
+
A reusable role-based screen gate and a per-screen title override (back the competence screen-access work and the evaluation/scores screen split).
|
|
8
|
+
|
|
9
|
+
* feat(web-framework): the default `TiWebAppManager.verifyAccess` now enforces a fragment's declared `roles` — a fragment registered (via `addFragment`) with a `roles` array is served only to sessions holding at least one of them (otherwise rejected `E_SEC_UNAUTHORIZED_ACCESS` 403), while a fragment with no `roles` stays public. This makes role-restricted screens unreachable by direct URL, not merely hidden in the UI; apps just declare `roles` on `addFragment` — no `verifyAccess` override needed. Backward compatible: all existing role-less fragments remain public
|
|
10
|
+
* feat(web-framework): add `authorization.isAccessAllowed( requiredRoles, userRoles )` — a pure, unit-tested access decision (empty/absent roles = public; otherwise ≥1 overlap; no implicit hierarchy, so an `admin` gate is never satisfied by a numeric role) that backs the default `verifyAccess`
|
|
11
|
+
* feat(web-framework): add `tiApplication.setScreenTitle( title )` — a per-screen topbar/document-title override (cleared automatically on navigation) so a screen can correct its own title at runtime (e.g. a manager viewing another user's scores must not read "My …")
|
|
12
|
+
* build(release): bump package version from `1.12.0` to `1.13.0`
|
|
13
|
+
|
|
14
|
+
## Version 1.12.0
|
|
15
|
+
|
|
16
|
+
Chart primitives gain legends + value labels for grouped bars and a legend for radar (backs the leaner competence evaluation results view) (CA-61).
|
|
17
|
+
|
|
18
|
+
* feat(web-framework): `ti-charts` grouped bars now render an optional swatch legend (`options.legend`) and per-bar value captions (`options.valueLabels`); radar charts render an optional legend, with a dashed swatch variant (`{ dashed: true }`) for dashed series such as an "expected" curve (CA-61)
|
|
19
|
+
* feat(web-framework): add `.ti-chart-bar-seg.tone-info`, `.ti-chart-legend-swatch.tone-info`, and `.ti-chart-legend-swatch.is-dashed` so grouped/radar source series and their legends share one colour scale across both themes (CA-61)
|
|
20
|
+
* feat(web-framework): `ti-charts` radar accepts an optional per-axis `tone`, applied as a `tone-*` class on the axis label so consumers can colour axis labels (e.g. by category) — threaded through `radarLayout` (CA-61)
|
|
21
|
+
* feat(web-framework): `ti-charts` grouped bars accept optional `options.barThickness` (bar height) and `options.valueFontSize` (value-caption font); value captions carry a dedicated `ti-chart-bar-value` class that intentionally sets no CSS `font-size`, so the renderer's `font-size` presentation attribute (default 4) actually governs — previously the caption also carried `ti-chart-bar-label`, whose CSS `font-size: 4px` overrode the attribute and made `valueFontSize` a no-op (CA-61)
|
|
22
|
+
* build(release): bump package version from `1.11.1` to `1.12.0`
|
|
23
|
+
|
|
24
|
+
## Version 1.11.1
|
|
25
|
+
|
|
26
|
+
Post-review fix from the CA-72 CodeRabbit review (PR #85) on the login test-user panel.
|
|
27
|
+
|
|
28
|
+
* fix(web-framework): turning the "override roles (dev)" toggle OFF now always strips any persisted roles from the `ti-test-user` cookie — even when the selected employee is no longer in the panel's profile list — so a stale roles array can't keep overriding the app's org-derived roles on the next login (CA-72)
|
|
29
|
+
* build(release): bump package version from `1.11.0` to `1.11.1`
|
|
30
|
+
|
|
31
|
+
## Version 1.11.0
|
|
32
|
+
|
|
33
|
+
Login test-user panel defaults to identity-only injection so the app derives roles itself (CA-72).
|
|
34
|
+
|
|
35
|
+
* feat(web-framework): login test-user panel injects identity only by default (roles derived by the app); role injection becomes an opt-in dev override (CA-72)
|
|
36
|
+
* docs(web-framework): clarify the augmentSession contract (derive vs. override) (CA-72)
|
|
37
|
+
* build(release): bump package version from `1.10.4` to `1.11.0`
|
|
38
|
+
|
|
39
|
+
## Version 1.10.4
|
|
40
|
+
|
|
41
|
+
Login test-user fixture follow-up (CA-71).
|
|
42
|
+
|
|
43
|
+
* chore(web-framework): login test-user `8` carries the `MANAGER` role (`[1, 2]`) so manager / self-manage scenarios (e.g. the competence Org Chart self-manage gate) can be exercised without re-seeding
|
|
44
|
+
* build(release): bump package version from `1.10.3` to `1.10.4`
|
|
45
|
+
|
|
46
|
+
## Version 1.10.3
|
|
47
|
+
|
|
48
|
+
Developer-tooling and formatting touch-ups on the shared frontend bundle.
|
|
49
|
+
|
|
50
|
+
* chore(web-framework): the login test-user panel offers more seeded employees (3, 8, 9 alongside 22/20/1/4) so manager / direct-report / skip-level scenarios can be exercised without re-seeding
|
|
51
|
+
* style(web-framework): minor formatting of `formatException`'s return object
|
|
52
|
+
* build(release): bump package version from `1.10.2` to `1.10.3`
|
|
53
|
+
|
|
54
|
+
## Version 1.10.2
|
|
55
|
+
|
|
56
|
+
Readability and scaling fixes for the chart primitives, surfaced while polishing the Statistics & Results screens (CA-61).
|
|
57
|
+
|
|
58
|
+
* fix(web-framework): stacked bar charts now caption each row (the group/cycle label plus an optional per-row value) and render an optional swatch legend driven by `spec.options.legend`, so a coverage "By group" chart reads as labelled bars instead of anonymous colour blocks; the row labels also land on the cross-cycle trend bars
|
|
59
|
+
* fix(css): horizontal bar charts opt out of the global `svg` `max-height` so bar thickness and label size stay identical regardless of row count — a tall org-wide chart is no longer uniformly scaled down and rendered finer than the same chart on a smaller subtree; the per-row geometry is trimmed for a cleaner look
|
|
60
|
+
* feat(css): `.ti-chart-legend` / `.ti-chart-legend-item` / `.ti-chart-legend-swatch` — a chart swatch legend whose colours route through the inherited grade/ink chart tokens
|
|
61
|
+
* build(release): bump package version from `1.10.1` to `1.10.2`
|
|
62
|
+
|
|
63
|
+
## Version 1.10.1
|
|
64
|
+
|
|
65
|
+
Review fixes for the ti-chart primitives (Statistics & Results, CA-61, PR #83 — CodeRabbit pass).
|
|
66
|
+
|
|
67
|
+
* fix(web-framework): drillable heatmap/box marks get an accessible name; `renderChart` clears stale `data-ti-chart-empty`/`aria-label` on rerender; `renderStat` renders a missing value as an em dash; the provisional line-dot stroke follows its `tone-*` class
|
|
68
|
+
* fix(css): `.ti-chart-sr` uses `clip-path: inset(50%)` instead of the deprecated `clip` property
|
|
69
|
+
* build(release): bump package version from `1.10.0` to `1.10.1`
|
|
70
|
+
|
|
71
|
+
## Version 1.10.0
|
|
72
|
+
|
|
73
|
+
### Charting primitive library (Statistics & Results, CA-61)
|
|
74
|
+
|
|
75
|
+
* feat(web-framework): new `ti-charts.js` — a CSP-safe SVG charting library backing the competence Statistics & Results reporting. Eight primitives via a single `renderChart(figure, spec)` dispatcher: `gauge`, `bars` (stacked / grouped / diverging modes), `stat`, `scatter`, `heatmap` (sequential / diverging scales), `box`, `radar`, and `line` (mean + p25–p75 band, sparkline, stacked, dashed-provisional trailing segment). The pure layout helpers (`gaugeArcPath`, `barSegments`, `scatterLayout`, `heatmapLayout`, `boxLayout`, `radarLayout`, `lineLayout`, …) are unit-tested in isolation
|
|
76
|
+
* feat(web-framework): register the `x-ti-chart` Alpine CSP directive (binds a spec object to a host `<figure>`); every chart builds its SVG with `createElementNS` + `setAttribute` only (never `element.style.*` except `setProperty("--var")`) and ships a visually-hidden `.ti-chart-sr` accessibility table
|
|
77
|
+
* feat(css): `.ti-chart-*` styles + per-type `figure[data-ti-chart-type]` size caps + `--chart-seq-1…5` sequential ramp tokens and grade/tone colours in both themes (daylight + black-glass)
|
|
78
|
+
* build(release): bump package version from `1.9.3` to `1.10.0`
|
|
79
|
+
|
|
80
|
+
## Version 1.9.3
|
|
81
|
+
|
|
82
|
+
* feat(css): an empty `.ti-grade-chip` (a competency whose rating is still awaited) now renders an hourglass glyph via `::before` instead of a literal dash, so "awaiting rating" reads as a clear visual state wherever an empty grade chip is shown to a permitted viewer
|
|
83
|
+
* build(release): bump package version from `1.9.2` to `1.9.3`
|
|
84
|
+
|
|
85
|
+
## Version 1.9.2
|
|
86
|
+
|
|
87
|
+
* feat(css): add `.ti-spacer` — a flexible spacer (`flex: 1 1 auto`) that pushes following siblings to the far end of a flex row/column. Promotes the bespoke per-screen `competence-empmgmt-actions-spacer` into a shared primitive, now consumed by the employee-management actions panel and the evaluation screen's team-feedback finalize bar
|
|
88
|
+
* build(release): bump package version from `1.9.1` to `1.9.2`
|
|
89
|
+
|
|
90
|
+
## Version 1.9.1
|
|
91
|
+
|
|
92
|
+
* build(deps): upgrade `ajv` from ^6.15.0 to ^8.20.0 — ajv 8 renamed the validation-error `dataPath` (dot style) to `instancePath` (JSON Pointer)
|
|
93
|
+
* fix(config-registry): normalize ajv 8's `instancePath` back to the dot/bracket data path the registry has always exposed on schema issues (e.g. `.competencies.E1-1.name`, array indices as `[0]`), so the public `ConfigValidationIssue.path` contract is unchanged across the upgrade; the ajv compile options (`meta`, `schemaId: "$id"`, `validateSchema: false`) and Draft-07 handling are unchanged
|
|
94
|
+
* build(deps): update `helmet` from ^8.1.0 to ^8.2.0
|
|
95
|
+
|
|
96
|
+
## Version 1.9.0
|
|
97
|
+
|
|
98
|
+
* feat(css): add `.ti-panel-body-intro` — the canonical description/intro line under a `.ti-panel-head` (`--fs-sm`, secondary foreground, `0 var(--s-3) var(--s-5)` padding, 1.5 line-height); replaces the per-screen intro paragraphs that screens used to hand-style
|
|
99
|
+
* refactor(css): tighten the key/value primitives — `.ti-kv-label` is now an uppercase `--fs-xs` 600-weight caption (0.05em letter-spacing); `.ti-kv-value` is `--fs-sm` 400-weight — for a consistent, scannable key/value rhythm across screens
|
|
100
|
+
* refactor(css): drop the redundant `margin-left: auto` from `.ti-panel-head-aside` (the panel head already positions it via its flex layout)
|
|
101
|
+
* fix(sidebar): the user-profile flyout actions (Profile, Settings, Logout) now actually fire. The menu items bind their `hx-*` attributes through Alpine (`x-bind`), which HTMX does not pick up on its initial document scan — so the buttons previously only closed the flyout. The flyout now runs `htmx.process` on its panel when it opens (idempotent on re-open), wiring up each button's `hx-get`/`hx-post`/`hx-target`/`hx-swap`
|
|
102
|
+
* fix(sidebar): the role/department line under the user name no longer overflows the fixed-width sidebar — `.ti-sidebar-user-name` and `.ti-sidebar-user-sub` truncate with an ellipsis, and `.ti-sidebar-user-text` gets `flex: 1` so it bounds the text column
|
|
103
|
+
* style(css): expand the `.ti-icon` size-modifier one-liners (`.xs`/`.sm`/`.md`/`.lg`/`.xl`) to block form for consistency with the rest of the sheet
|
|
104
|
+
* build(release): bump package version from `1.8.0` to `1.9.0`
|
|
105
|
+
|
|
106
|
+
## Version 1.8.0
|
|
107
|
+
|
|
108
|
+
* feat(notifications): notifications can now show a secondary **details** line under the generic message. `tiApplication.formatException` returns `{ message, details }` (resolved from the exception's `data.details`, falling back to the raw text for non-localized messages) and `tiApplication.notify` accepts that payload — so an error like "The request parameters are not recognized or not supported." now also shows the specifics (e.g. "Competency codes not in the 'QE' pool: …") in a smaller, muted font. The returned object stringifies to its message, so existing string usages keep working unchanged
|
|
109
|
+
* fix(css): raise the toast stack above the modal layer (`z-index` 1100 → 1300; the modal backdrop is 1200) so a notification raised while a modal is open is no longer hidden behind it
|
|
110
|
+
|
|
111
|
+
## Version 1.7.1
|
|
112
|
+
|
|
113
|
+
* fix(web-handlers): web-application request errors that carry no explicit `httpCode` are no longer reported as `500`. A new `resolveHttpCode` derives the status from the exception code — request-validation and application-logic errors (`E_WEB_*` / `E_APP_*`) map to `422 Unprocessable Content`, security (`E_SEC_*`) to `403`, resource not-found/already-exists to `404`/`409`, and method/URI/content errors to `405`/`404`/`415`; only genuine internal, communication, and unknown errors still default to `500`. An explicit `httpCode` on the exception always wins. Applied in both the `/app` request handler (`formatException`) and the default error handler
|
|
114
|
+
|
|
115
|
+
## Version 1.7.0
|
|
116
|
+
|
|
117
|
+
* feat(css): introduce `.ti-data-grid` family — `.ti-data-grid`, `.ti-data-grid-head`, `.ti-data-grid-rows`, `.ti-data-grid-row` with shared `--ti-grid-cols` template; row state modifiers `.is-current` (accent-soft, "current user") and `.is-selected` (accent-soft + left accent bar); wrapper variants `.bordered` (horizontal dividers for tabular displays) and `.compact` (denser padding); cell utilities `.ti-cell-center` / `.ti-cell-right` for per-cell alignment
|
|
118
|
+
* feat(css): introduce `.ti-page-head` as a vertical block stack (eyebrow above title, subtitle below) using `--fs-xs` for the eyebrow and clamping subtitle width at 60ch
|
|
119
|
+
* feat(css): introduce a reusable `.ti-form*` family — `.ti-form`, `.ti-form-section`, `.ti-form-section-title`, `.ti-form-grid` (with `.cols-1` / `.cols-3` modifiers), `.ti-form-row` (with `.wide` for grid-spanning), `.ti-form-readonly`, `.ti-form-hint`, `.ti-form-error`, `.ti-form-actions`, `.ti-form-state` (with `.saved` / `.unsaved`); single responsive collapse to one column under 720px
|
|
120
|
+
* feat(css): extend `.ti-panel-head` with sub-elements — `.ti-panel-head-icon` (32x32 framed icon slot), `.ti-panel-head-text` (title + subtitle stack inside a flex row), `.ti-panel-title-aside` (inline qualifier next to the title), `.ti-panel-subtitle` (dimmed sub line), `.ti-panel-head-aside` (right-aligned read-only info with left-border separator), and the `.bar` modifier (sunken full-width banner)
|
|
121
|
+
* feat(icons)!: rebase `.ti-icon` on `background-color: currentColor` so icons inherit the surrounding text colour; add size modifiers `.xs` (12px), `.sm` (14px), `.md` (16px), `.lg` (24px), `.xl` (32px); add `.legacy-gray` modifier to preserve the previous gray/hover behaviour for consumers that rely on the fixed colour scheme
|
|
122
|
+
* feat(icons): add 21 new `.ti-icon` variants (lucide / feather style, 24x24 viewBox) — `plus`, `close`, `check`, `check-clipboard`, `send`, `search`, `clock`, `warning-triangle`, `info-circle`, `bell`, `check-circle`, `eye`, `calendar-blank`, `user`, `users`, `briefcase`, `folder`, `book`, `help-circle`, `bar-chart`, `chevron-left`, `chevron-right`, `dashboard-grid`, `cycles-loop`, `sun`
|
|
123
|
+
* feat(icons): add `.ti-icon.moon` mask variant so theme toggles can mirror the target mode
|
|
124
|
+
* feat(framework): add `tiApplication.hasRole(roleCode)` helper that does the array-shape check in plain JS (the Alpine CSP build does not expose `Array` to its expression evaluator, so `Array.isArray(...)` written inline in a template raises `Undefined variable: Array`)
|
|
125
|
+
* feat(framework): add `tiApplication.topbarPrimaryCta` store slot plus `setTopbarPrimaryCta` / `setTopbarPrimaryCtaDisabled` API for per-screen CTA buttons in the topbar; auto-cleared on screen navigation so each screen owns its slot
|
|
126
|
+
* feat(css): native select chevron replaced by a custom down-chevron SVG positioned at right: 10px / 14x14; padding-right reserves the slot; glass theme overrides the SVG stroke colour because `background-image` can't pick up `currentColor`
|
|
127
|
+
* feat(css): subdue `::-webkit-calendar-picker-indicator` to opacity 0.7 (1 on hover) so date-input visual weight matches the chevron
|
|
128
|
+
* feat(notification bar): replace inline toast SVGs with `.ti-icon` mask classes (success check, danger close, warn triangle, info circle, close button)
|
|
129
|
+
* feat(sidebar): replace inline navigation SVGs with `.ti-icon` mask classes (collapse chevron, dashboard home, sun theme toggle)
|
|
130
|
+
* refactor(css): drop the screen-specific page-header, form, and tabular-layout CSS that duplicated framework primitives; all in-tree screens (`frame-employees-list`, `frame-cycles`, `frame-cycle-setup`, `frame-competence-evaluation`, `frame-new-evaluation`, `frame-manager-calendar`, `frame-interview-schedule`, `frame-employee-management`) now consume `.ti-page-head`, `.ti-data-grid`, `.ti-form*`, and `.ti-panel-head*` instead
|
|
131
|
+
* docs(modal): doc-block on `.ti-modal-*` confirming it as the canonical shared primitive (introduced in 1.6.3 via the competence cycle-setup work)
|
|
132
|
+
* build(release): bump package version from `1.6.3` to `1.7.0`
|
|
133
|
+
|
|
134
|
+
## Version 1.6.3
|
|
135
|
+
|
|
136
|
+
* feat(css): add `--ti-internal-padding` CSS variable to the design token system
|
|
137
|
+
* feat(css): add `--ti-border-color` CSS variable for consistent border theming
|
|
138
|
+
* feat(icons): add `.ti-icon.calendar` and `.ti-icon.schedule` icon variants with hover states
|
|
139
|
+
* feat(css): add `.ti-data-value.fill-space` modifier for flex-grow behavior in inline data value layouts
|
|
140
|
+
* fix(css): remove `min-width: 120px` constraint from `.ti-button.inline` for more flexible sizing
|
|
141
|
+
* fix(css): update z-index stacking values for dropdown and overlay elements to prevent layering conflicts
|
|
142
|
+
* build(deps): update `openid-client` from ^6.8.2 to ^6.8.4
|
|
143
|
+
* build(deps): update bundled `@alpinejs/csp` from ^3.15.11 to ^3.15.12
|
|
144
|
+
* build(deps): update bundled `htmx.org` from ^2.0.8 to ^2.0.10
|
|
145
|
+
* build(static): refresh bundled Alpine.js CSP and HTMX library files to match updated dependency versions
|
|
146
|
+
|
|
147
|
+
## Version 1.6.2
|
|
148
|
+
|
|
149
|
+
* feat(ui): replace Material Symbols usage with framework-native `.ti-icon` classes across sidebar flyouts, login actions, and notification bar
|
|
150
|
+
* feat(sidebar): merge administration and user flyout menus into a single `sidebarApplicationMenu` with configurable menu icon and updated actions
|
|
151
|
+
* feat(css): add embedded SVG mask icon variants (`app-menu`, `dashboard`, `settings`, `error`, `user-profile`, `login`, `logout`, `internet`) and increase default icon size to `24px`
|
|
152
|
+
* refactor(theme): remove Material Symbols-specific icon styling from the black-glass theme
|
|
153
|
+
* build(static): remove external Google Material Symbols stylesheet import from static `index.html`
|
|
154
|
+
* build(release): bump package version from `1.6.1` to `1.6.2`
|
|
155
|
+
|
|
156
|
+
## Version 1.6.1
|
|
157
|
+
|
|
158
|
+
* feat(css): add inline button support via `.ti-button.inline` and new `--ti-button-inline-height` design token
|
|
159
|
+
* refactor(ui): update sidebar flyout positioning logic to use shared `tiToolbox` viewport helpers (`getVisibleBox`, `clampToBox`)
|
|
160
|
+
* fix(ui): fix the call to utility functions `getVisibleBox` and `clampToBox` in the sidebar flyout component
|
|
161
|
+
* build(release): bump package version from `1.6.0` to `1.6.1`
|
|
162
|
+
|
|
163
|
+
## Version 1.6.0
|
|
164
|
+
|
|
165
|
+
* feat(toolbox): add Alpine.js `tiToolbox` store with shared utility methods (`deepMerge`, `deepFreeze`, `structuredClone`, `formatDate`, viewport helpers, and cookie access)
|
|
166
|
+
* feat(ui): move sidebar menu configuration into `ti-framework.js` and register `tiComponentsConfig` during Alpine.js initialization
|
|
167
|
+
* refactor(static): remove legacy `ti-user-interface.js` from static assets and stop loading it from `index.html`
|
|
168
|
+
* refactor(components): update framework components to consume toolbox utilities through Alpine stores
|
|
169
|
+
* refactor(docs): add and expand JSDoc typedefs and method-level documentation in `ti-framework.js`
|
|
170
|
+
* build(release): bump package version from `1.5.3` to `1.6.0`
|
|
171
|
+
|
|
172
|
+
## Version 1.5.3
|
|
173
|
+
|
|
174
|
+
* feat(framework): add `openScreen` method for in-app navigation
|
|
175
|
+
* fix(auth): add explicit HTTP `401` status to authentication failure
|
|
176
|
+
|
|
177
|
+
## Version 1.5.2
|
|
178
|
+
|
|
179
|
+
* feat(framework): expand application API by improving `sendRequest`, `notify`, and `getLabel` methods
|
|
180
|
+
* feat(tooltip): add helper methods `getTooltipMessage`, `handleEnter`, `handleLeave`, `showTooltip`, `hideTooltip` to the tooltip component
|
|
181
|
+
* feat(css): improve styles and style structure
|
|
182
|
+
|
|
183
|
+
## Version 1.5.1
|
|
184
|
+
|
|
185
|
+
* feat(framework): add `isValidDate` utility function for validating Date instances
|
|
186
|
+
* feat(framework): add `deepFreeze` utility function for recursive object freezing
|
|
187
|
+
* feat(framework): add `getLabel` method on application configuration for nested label resolution with dot notation
|
|
188
|
+
* feat(framework): add Alpine.js directive `x-text-label` for runtime label translation
|
|
189
|
+
* feat(framework): add a configuration object to replace labels object with enhanced structure
|
|
190
|
+
* feat(config): add authentication state (`auth.isAuthenticated`) to config endpoint response
|
|
191
|
+
* feat(placeholder): add inner content capture and injection for placeholder replacement
|
|
192
|
+
* feat(tooltip): add a new tooltip component with Alpine.js integration and positioning
|
|
193
|
+
* feat(css): add CSS custom properties for padding, margin, and font-family
|
|
194
|
+
* feat(css): add tooltip styling variables (background, foreground, size, shadow, arrow)
|
|
195
|
+
* feat(css): add `.ti-content.pane` block with flex layout and overflow handling
|
|
196
|
+
* feat(css): add error color, flyout item shadows, and separator color variables
|
|
197
|
+
* feat(css): add `.ti-glass-btn-black.large` variant with left-justified content
|
|
198
|
+
* refactor(framework): change user initialization from `undefined` to `null`
|
|
199
|
+
* refactor(framework): improve request failure handling with proper error rejection
|
|
200
|
+
* refactor(css): replace hard-coded spacing with CSS variables across components
|
|
201
|
+
* refactor(css): add `overflow: hidden` to body and `.ti-main` for better layout control
|
|
202
|
+
* refactor(css): convert color and styling values to CSS variables throughout
|
|
203
|
+
* refactor(handlers): add `convertUriToString` helper for safe URI object stringification
|
|
204
|
+
* refactor(handlers): add a request context object (query, params, headers, url, method) to JSON responses
|
|
205
|
+
* refactor(handlers): augment user data with default employeeID and roles in the user information handler
|
|
206
|
+
* build(deps): update express from ^5.1.0 to ^5.2.1
|
|
207
|
+
* build(deps): update express-session from ^1.18.2 to ^1.19.0
|
|
208
|
+
* build(deps): update lodash from ^4.17.21 to ^4.17.23
|
|
209
|
+
* build(deps): update openid-client from ^6.8.1 to ^6.8.2
|
|
210
|
+
* build(deps): update `@alpinejs/csp` from ^3.15.2 to ^3.15.8
|
|
211
|
+
* build(engines): update Node.js requirement from >=18.0.0 to >=20.0.0
|
|
212
|
+
|
|
213
|
+
## Version 1.5.0
|
|
214
|
+
|
|
215
|
+
* feat(web-app)!: change `TiWebAppManager` to be an abstract class
|
|
216
|
+
* feat(web-app): rename class `WebAppManager` to `TiWebAppManager` and add a static file caching mechanism
|
|
217
|
+
* feat(web-app): add `addFragment` method with override protection for custom HTML fragment registration
|
|
218
|
+
* feat(web-app): add `webAppIdentifier` getter to expose application identifier
|
|
219
|
+
* feat(web-server): add support for dynamic web application instantiation from config via `classPath`
|
|
220
|
+
* feat(web-server): add `defineWebApplicationRoutes` and `defineUnprotectedRoutes` extension points
|
|
221
|
+
* feat(web-server): add `endpointEnabled` flag to conditionally enable API endpoint proxy
|
|
222
|
+
* feat(web-server): add serving for `.well-known` directory for web standards compliance
|
|
223
|
+
* feat(package): add public exports for `./web-application` and `./web-server` subpaths
|
|
224
|
+
* feat(package): add `files` whitelist and repository metadata (homepage, bugs URL, git repository)
|
|
225
|
+
* feat(package): add Node.js version requirement (>=18.0.0) via the `engines` field
|
|
226
|
+
* feat(build): add a post-install script to vendor HTMX and Alpine.js CSP libraries locally
|
|
227
|
+
* refactor(web-app): replace `fullPublicPath` with `staticContentPaths` array for multi-path static content resolution
|
|
228
|
+
* refactor(web-app): add file location search algorithm with caching via `#locateStaticFile` method
|
|
229
|
+
* refactor(web-app): update `transformHtml` signature to remove `fullPublicPath` parameter
|
|
230
|
+
* refactor(web-app): update `assembleHtmlView` to accept `staticContentPaths` instead of `fullPublicPath`
|
|
231
|
+
* refactor(web-server): replace the single static path with configurable `staticContentPaths` array
|
|
232
|
+
* refactor(web-server): merge web server default config with the provided service config in constructor
|
|
233
|
+
* refactor(web-server): load web server default config directly from the package JSON import instead of the ENV configuration
|
|
234
|
+
* refactor(web-server): improve TLS initialization error handling to reject promise instead of throw
|
|
235
|
+
* refactor(package): reorganize imports from `./server/...` to `./bin/...` and `./components/...` paths
|
|
236
|
+
* refactor(package): move `@alpinejs/csp` from dependencies to devDependencies
|
|
237
|
+
* build(static): replace CDN script references with local copies for HTMX and Alpine.js CSP
|
|
238
|
+
* build(env): remove `TI_INSTANCE_CONFIG` and update `TI_LOCALIZATION_LABELS_PATH` to use `bin/localization/` path
|
|
239
|
+
* build(env): add `TI_AUDITING_LOG_MIN_LEVEL` configuration variable
|
|
240
|
+
* fix(ui): change `aria-expanded` binding from string to boolean in the sidebar flyout component
|
|
241
|
+
* fix(ui): remove incorrect `type="button"` attribute from `Home` anchor element
|
|
242
|
+
* docs: improve various documentation comments and class descriptions
|
|
243
|
+
|
|
244
|
+
## Version 1.4.0
|
|
245
|
+
|
|
246
|
+
* feat(ui): add a notification bar component with Alpine.js integration and auto-dismiss functionality
|
|
247
|
+
* feat(ui): add CSS variables and styles for the notification system
|
|
248
|
+
* feat(routes): add `/not-found` fragment and route for 404 error pages
|
|
249
|
+
* feat(routes): add `/app/error` route for error handling testing - will be removed later
|
|
250
|
+
* feat(routes): add `/app/config` data endpoint for serving application configuration
|
|
251
|
+
* feat(localization): add language property to `User` class with getter and JSON serialization
|
|
252
|
+
* feat(localization): integrate localization module for label management and localized error messages
|
|
253
|
+
* feat(session): add language property to session data populated from user or service configuration
|
|
254
|
+
* feat(handlers): add response type detection helper `isAcceptingResponseType` for content negotiation
|
|
255
|
+
* feat(handlers): enhance error responses with localized messages via localization module
|
|
256
|
+
* feat(handlers): add HTMX-aware error handling with HX-Redirect and HX-Retarget headers
|
|
257
|
+
* feat(handlers): implement `processDataRequest` method in WebAppManager for serving data resources
|
|
258
|
+
* feat(config): add a language configuration option to the `WebServiceConfiguration` object
|
|
259
|
+
* refactor(handlers): delegate error handling from resource protection to error middleware
|
|
260
|
+
* refactor(handlers): improve 401/404 response handling by routing through exceptions and middleware
|
|
261
|
+
* refactor(handlers): enhance CSRF and origin validation to use error middleware instead of direct responses
|
|
262
|
+
* refactor(handlers): improve service call error handling to raise exceptions and delegate to middleware
|
|
263
|
+
* refactor(handlers): refactor invalid route handler to raise exceptions instead of direct 404 responses
|
|
264
|
+
* fix(types): correct ExpressRequest typedef from `import("express").req` to `import("express").Request`
|
|
265
|
+
* build(config): update publicPath from `packages/web-framework/bin/static` to `bin/static`
|
|
266
|
+
* build(config): update TLS certificate paths to use relative `bin/tls/` paths
|
|
267
|
+
* build(env): update `TI_INSTANCE_CLASS` and `TI_INSTANCE_CONFIG` paths to use relative `bin/` paths
|
|
268
|
+
* build(env): add `TI_LOCALIZATION_LABELS_PATH` environment variable for custom labels
|
|
269
|
+
* build(run): update IDE run configuration to use relative paths and the correct working directory
|
|
270
|
+
* build(labels): add an empty `web-server-labels.json` file for custom localization labels
|
|
271
|
+
|
|
272
|
+
## Version 1.3.0
|
|
273
|
+
|
|
274
|
+
* feat: first working prototype version
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# ti-engine web framework
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Flexible framework for the creation of microservices with node.js.
|
|
6
|
+
|
|
7
|
+
## Information
|
|
8
|
+
|
|
9
|
+
This is a customizable web framework based on the **ti-engine** framework. Currently under development.
|
|
10
|
+
|
|
11
|
+
## Configure HTTPS for development
|
|
12
|
+
|
|
13
|
+
Use the `mkcert` tool to create a certificate for development.
|
|
14
|
+
|
|
15
|
+
Step 1: Install the tool:
|
|
16
|
+
```text
|
|
17
|
+
choco install mkcert
|
|
18
|
+
```
|
|
19
|
+
Step 2: Install certificate authority:
|
|
20
|
+
```text
|
|
21
|
+
mkcert -install
|
|
22
|
+
```
|
|
23
|
+
Step 3: Generate certificate files for localhost:
|
|
24
|
+
```text
|
|
25
|
+
mkcert localhost 127.0.0.1 ::1
|
|
26
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const fs = require( "node:fs" );
|
|
2
|
+
const path = require( "node:path" );
|
|
3
|
+
|
|
4
|
+
function copyLibrary( source, destination ) {
|
|
5
|
+
try {
|
|
6
|
+
fs.mkdirSync( path.dirname( destination ), { recursive: true } );
|
|
7
|
+
fs.copyFileSync( source, destination );
|
|
8
|
+
console.log( `Copied ${ source } -> ${ destination }` );
|
|
9
|
+
} catch ( error ) {
|
|
10
|
+
console.error( `Failed to copy ${ source } -> ${ destination }:`, error.message );
|
|
11
|
+
process.exit( 1 );
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const staticDir = path.join( __dirname, "..", "static", "scripts", "lib" );
|
|
16
|
+
|
|
17
|
+
copyLibrary( require.resolve( "htmx.org/dist/htmx.min.js" ), path.join( staticDir, "htmx.min.js" ) );
|
|
18
|
+
copyLibrary( require.resolve( "@alpinejs/csp/dist/cdn.min.js" ), path.join( staticDir, "alpinejs-csp.min.js" ) );
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"interface": {
|
|
3
|
+
"default": {
|
|
4
|
+
"login": {
|
|
5
|
+
"password": {
|
|
6
|
+
"en": "Password",
|
|
7
|
+
"bg": "Парола"
|
|
8
|
+
},
|
|
9
|
+
"sign-in": {
|
|
10
|
+
"en": "Sign In",
|
|
11
|
+
"bg": "Вход"
|
|
12
|
+
},
|
|
13
|
+
"sign-in-azure": {
|
|
14
|
+
"en": "Sign In - Azure",
|
|
15
|
+
"bg": "Вход с Azure"
|
|
16
|
+
},
|
|
17
|
+
"sign-in-google": {
|
|
18
|
+
"en": "Sign In - Google",
|
|
19
|
+
"bg": "Вход с Google"
|
|
20
|
+
},
|
|
21
|
+
"username": {
|
|
22
|
+
"en": "Username",
|
|
23
|
+
"bg": "Потребител"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<div id="ti-notifications" x-data="tiComponentNotificationBar" class="ti-toast-stack" aria-live="polite" aria-atomic="false">
|
|
2
|
+
<template x-for="n in notifications" x-bind:key="n.id">
|
|
3
|
+
<div class="ti-toast" x-bind:class="n.tone || 'info'" role="alert">
|
|
4
|
+
<div class="ti-toast-bar" aria-hidden="true"></div>
|
|
5
|
+
<div class="ti-toast-icon" aria-hidden="true">
|
|
6
|
+
<span class="ti-icon check md" aria-hidden="true" x-show="n.tone === 'success'"></span>
|
|
7
|
+
<span class="ti-icon close md" aria-hidden="true" x-show="n.tone === 'danger'"></span>
|
|
8
|
+
<span class="ti-icon warning-triangle md" aria-hidden="true" x-show="n.tone === 'warn'"></span>
|
|
9
|
+
<span class="ti-icon info-circle md" aria-hidden="true" x-show="!n.tone || n.tone === 'info'"></span>
|
|
10
|
+
</div>
|
|
11
|
+
<div class="ti-toast-body">
|
|
12
|
+
<div class="ti-toast-title" x-text="n.title || ''"></div>
|
|
13
|
+
<div class="ti-toast-msg" x-text="n.message || ''"></div>
|
|
14
|
+
<div class="ti-toast-details" x-show="n.details" x-text="n.details || ''"></div>
|
|
15
|
+
</div>
|
|
16
|
+
<button class="ti-toast-close" @click="remove(n.id)" aria-label="Dismiss notification" type="button">
|
|
17
|
+
<span class="ti-icon close sm" aria-hidden="true"></span>
|
|
18
|
+
</button>
|
|
19
|
+
</div>
|
|
20
|
+
</template>
|
|
21
|
+
</div>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<div x-id="['component-flyout']"
|
|
2
|
+
x-data="tiComponentSidebarFlyout('{ti-config-key}')"
|
|
3
|
+
class="ti-sidebar-flyout-container">
|
|
4
|
+
<!--
|
|
5
|
+
Trigger slot. The placeholder consumer can replace this with any custom button — typically a user avatar
|
|
6
|
+
or app menu trigger. The trigger MUST set x-ref="flyoutButton" and call toggle() to integrate with the
|
|
7
|
+
encapsulated flyout state. If the consumer omits inner content, this default icon button is used.
|
|
8
|
+
-->
|
|
9
|
+
<ti-slot>
|
|
10
|
+
<button x-on:click.stop="toggle()"
|
|
11
|
+
x-on:ti-close-all-flyout="close()"
|
|
12
|
+
x-bind:aria-expanded="isOpen"
|
|
13
|
+
x-bind:aria-controls="$id('component-flyout')"
|
|
14
|
+
x-bind:aria-label="menuTitle"
|
|
15
|
+
x-ref="flyoutButton"
|
|
16
|
+
type="button" class="ti-sidebar-button">
|
|
17
|
+
<span class="ti-icon" x-bind:class="icon" aria-hidden="true"></span>
|
|
18
|
+
</button>
|
|
19
|
+
</ti-slot>
|
|
20
|
+
<div x-on:click.outside="close()"
|
|
21
|
+
x-bind:id="$id('component-flyout')"
|
|
22
|
+
x-show="isOpen"
|
|
23
|
+
x-ref="flyoutPanel"
|
|
24
|
+
role="menu" class="ti-sidebar-flyout">
|
|
25
|
+
<template x-for="(buttonConfig, index) in buttonConfigs">
|
|
26
|
+
<button x-on:click="close()"
|
|
27
|
+
x-bind:hx-get="(!buttonConfig.action.method || buttonConfig.action.method === 'get') ? buttonConfig.action.href : null"
|
|
28
|
+
x-bind:hx-post="(buttonConfig.action.method && buttonConfig.action.method === 'post') ? buttonConfig.action.href : null"
|
|
29
|
+
x-bind:hx-target="buttonConfig.action.target"
|
|
30
|
+
x-bind:hx-swap="buttonConfig.action.swap"
|
|
31
|
+
hx-push-url="true"
|
|
32
|
+
type="button" class="ti-sidebar-flyout-item">
|
|
33
|
+
<span class="ti-icon" x-bind:class="buttonConfig.icon" aria-hidden="true"></span><span x-text="buttonConfig.title"></span>
|
|
34
|
+
</button>
|
|
35
|
+
</template>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
<nav class="ti-sidebar" x-data="tiComponentSidebarNav" aria-label="Main navigation">
|
|
2
|
+
<button class="ti-sidebar-collapse-btn" @click="toggleCollapse()" x-bind:aria-label="collapsed ? 'Expand sidebar' : 'Collapse sidebar'" type="button">
|
|
3
|
+
<span class="ti-icon chevron-left xs" aria-hidden="true"></span>
|
|
4
|
+
</button>
|
|
5
|
+
|
|
6
|
+
<!-- Brand slot — override in app-specific frame -->
|
|
7
|
+
<div class="ti-sidebar-brand">
|
|
8
|
+
<div class="ti-sidebar-brand-mark">T</div>
|
|
9
|
+
<div class="ti-sidebar-brand-text-block">
|
|
10
|
+
<span class="ti-sidebar-brand-text">ti-engine</span>
|
|
11
|
+
</div>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<!-- Navigation slot — override in app-specific frame -->
|
|
15
|
+
<div class="ti-sidebar-nav">
|
|
16
|
+
<a href="/" class="ti-sidebar-item" data-tip="Dashboard" aria-label="Dashboard">
|
|
17
|
+
<span class="ti-sidebar-item-icon">
|
|
18
|
+
<span class="ti-icon dashboard md" aria-hidden="true"></span>
|
|
19
|
+
</span>
|
|
20
|
+
<span class="ti-sidebar-item-label">Dashboard</span>
|
|
21
|
+
</a>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<!-- Footer -->
|
|
25
|
+
<div class="ti-sidebar-foot">
|
|
26
|
+
<button class="ti-sidebar-item" @click="toggleTheme()" data-tip="Toggle theme" aria-label="Toggle theme" type="button">
|
|
27
|
+
<span class="ti-sidebar-item-icon">
|
|
28
|
+
<span class="ti-icon sun md" aria-hidden="true"></span>
|
|
29
|
+
</span>
|
|
30
|
+
<span class="ti-sidebar-item-label" x-text="theme === 'daylight' ? 'Glass Theme' : 'Daylight Theme'">Toggle Theme</span>
|
|
31
|
+
</button>
|
|
32
|
+
</div>
|
|
33
|
+
</nav>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<div x-data="tiComponentTooltip()"
|
|
2
|
+
x-on:mouseover="handleEnter($event)"
|
|
3
|
+
x-on:mouseout="handleLeave($event)"
|
|
4
|
+
x-on:focusin="handleEnter($event)"
|
|
5
|
+
x-on:focusout="handleLeave($event)"
|
|
6
|
+
class="ti-tooltip">
|
|
7
|
+
<div x-show="isVisible"
|
|
8
|
+
x-text="text"
|
|
9
|
+
x-transition
|
|
10
|
+
class="ti-tooltip-bubble"></div>
|
|
11
|
+
</div>
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<header id="ti-topbar" class="ti-topbar" x-data="tiComponentTopbar">
|
|
2
|
+
<div id="ti-topbar-info">
|
|
3
|
+
<div class="ti-topbar-title" x-text="screenTitle"></div>
|
|
4
|
+
<div class="ti-topbar-sub" x-show="$store.tiApplication.topbarSubtitle" x-text="$store.tiApplication.topbarSubtitle"></div>
|
|
5
|
+
</div>
|
|
6
|
+
</header>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<div class="ti-application" x-data="tiApplication" x-bind:class="{ collapsed: collapsed }">
|
|
2
|
+
<!-- Sidebar -->
|
|
3
|
+
<ti-component-sidebar-placeholder></ti-component-sidebar-placeholder>
|
|
4
|
+
|
|
5
|
+
<!-- Content -->
|
|
6
|
+
<div id="ti-content-wrapper" class="ti-content">
|
|
7
|
+
<!-- Topbar -->
|
|
8
|
+
<ti-component-topbar-placeholder></ti-component-topbar-placeholder>
|
|
9
|
+
|
|
10
|
+
<!-- Application Screen -->
|
|
11
|
+
<div id="ti-content" class="ti-page-scrollable">
|
|
12
|
+
<ti-nested-frame-placeholder hx-get="/app/dashboard" hx-trigger="load" hx-target="this" hx-swap="outerHTML"
|
|
13
|
+
hx-push-url="true"></ti-nested-frame-placeholder>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
|
|
17
|
+
<!-- Toast notification stack -->
|
|
18
|
+
<ti-component-notification-bar-placeholder></ti-component-notification-bar-placeholder>
|
|
19
|
+
</div>
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<div id="ti-login" x-data="tiLoginTestUserPanel">
|
|
2
|
+
<div class="ti-login-container">
|
|
3
|
+
<!-- Brand mark -->
|
|
4
|
+
<div class="ti-login-brand">
|
|
5
|
+
<div class="ti-login-brand-mark">T</div>
|
|
6
|
+
<div class="ti-login-brand-text">
|
|
7
|
+
<div class="ti-login-brand-title">Welcome back</div>
|
|
8
|
+
<div class="ti-login-brand-sub">Sign in to continue</div>
|
|
9
|
+
</div>
|
|
10
|
+
</div>
|
|
11
|
+
|
|
12
|
+
<!-- Login card -->
|
|
13
|
+
<div class="ti-login-card">
|
|
14
|
+
<!-- Error message -->
|
|
15
|
+
<div id="ti-error" class="ti-login-error"></div>
|
|
16
|
+
|
|
17
|
+
<!-- Local auth form -->
|
|
18
|
+
<form id="ti-login-form" action="/login/local" method="post" class="ti-login-form">
|
|
19
|
+
<input type="hidden" name="_csrf" value='{ti-csrf-placeholder}'>
|
|
20
|
+
<div>
|
|
21
|
+
<label class="ti-field-label" x-text-label="interface.default.login.username" for="ti-username">Username</label>
|
|
22
|
+
<input id="ti-username"
|
|
23
|
+
name="username"
|
|
24
|
+
autocomplete="username"
|
|
25
|
+
autocapitalize="none"
|
|
26
|
+
spellcheck="false"
|
|
27
|
+
required class="ti-input"
|
|
28
|
+
placeholder="Enter your username"/>
|
|
29
|
+
</div>
|
|
30
|
+
<div>
|
|
31
|
+
<label class="ti-field-label" x-text-label="interface.default.login.password" for="ti-password">Password</label>
|
|
32
|
+
<input id="ti-password"
|
|
33
|
+
name="password"
|
|
34
|
+
type="password"
|
|
35
|
+
autocomplete="current-password"
|
|
36
|
+
enterkeyhint="go"
|
|
37
|
+
required class="ti-input"
|
|
38
|
+
placeholder="Enter your password"/>
|
|
39
|
+
</div>
|
|
40
|
+
<button type="submit" class="ti-btn primary lg full ti-login-submit">
|
|
41
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
42
|
+
stroke-linejoin="round" aria-hidden="true">
|
|
43
|
+
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M15 12H3"/>
|
|
44
|
+
</svg>
|
|
45
|
+
<span x-text-label="interface.default.login.sign-in">Sign In</span>
|
|
46
|
+
</button>
|
|
47
|
+
</form>
|
|
48
|
+
|
|
49
|
+
<!-- Divider -->
|
|
50
|
+
<div class="ti-login-divider">
|
|
51
|
+
<div class="ti-login-divider-line"></div>
|
|
52
|
+
<span class="ti-login-divider-label">or continue with</span>
|
|
53
|
+
<div class="ti-login-divider-line"></div>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<!-- Social auth -->
|
|
57
|
+
<div class="ti-login-social">
|
|
58
|
+
<a href="/login/openid-google" class="ti-btn full">
|
|
59
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
60
|
+
<path d="M21.6 12.23c0-.68-.06-1.33-.17-1.96H12v3.71h5.39a4.6 4.6 0 0 1-2 3.02v2.51h3.23c1.9-1.74 2.98-4.31 2.98-7.28Z" fill="#4285F4"/>
|
|
61
|
+
<path d="M12 22c2.7 0 4.97-.9 6.62-2.42l-3.23-2.51c-.9.6-2.04.96-3.39.96-2.6 0-4.81-1.76-5.6-4.12H3.07v2.6A10 10 0 0 0 12 22Z"
|
|
62
|
+
fill="#34A853"/>
|
|
63
|
+
<path d="M6.4 13.91A6.01 6.01 0 0 1 6.4 12c0-.66.11-1.3.31-1.91V7.49H3.07A10 10 0 0 0 2 12c0 1.61.39 3.14 1.07 4.51l3.33-2.6Z"
|
|
64
|
+
fill="#FBBC05"/>
|
|
65
|
+
<path d="M12 5.97c1.47 0 2.79.5 3.83 1.5l2.87-2.87C16.96 2.99 14.7 2 12 2A10 10 0 0 0 3.07 7.49l3.33 2.6C7.19 7.73 9.4 5.97 12 5.97Z"
|
|
66
|
+
fill="#EA4335"/>
|
|
67
|
+
</svg>
|
|
68
|
+
<span x-text-label="interface.default.login.sign-in-google">Sign in with Google</span>
|
|
69
|
+
</a>
|
|
70
|
+
<a href="/login/openid-azure" class="ti-btn full">
|
|
71
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
72
|
+
<path d="M11.5 2L4 8.5l4 1-4 6.5h8l-2-4 4-1-2.5 8H20L14 2h-2.5Z" fill="#0078D4"/>
|
|
73
|
+
</svg>
|
|
74
|
+
<span x-text-label="interface.default.login.sign-in-azure">Sign in with Azure</span>
|
|
75
|
+
</a>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<!-- TEMPORARY: Test user selector for augmentSession() experimentation. Remove once AD-driven identity is wired up. -->
|
|
80
|
+
<div class="ti-login-test-panel" role="group" aria-label="Test user selector">
|
|
81
|
+
<div class="ti-login-test-panel-title">Test user</div>
|
|
82
|
+
<div class="ti-login-test-panel-sub">Pick an identity to inject on login. Roles are derived from the org chart unless you override them.</div>
|
|
83
|
+
<div class="ti-login-test-panel-pills">
|
|
84
|
+
<template x-for="profile in profiles" :key="profile.employeeID">
|
|
85
|
+
<button type="button"
|
|
86
|
+
class="ti-login-test-pill"
|
|
87
|
+
x-bind:class="{ selected: isSelected(profile) }"
|
|
88
|
+
x-bind:aria-pressed="isSelected(profile)"
|
|
89
|
+
x-on:click="select(profile)">
|
|
90
|
+
<span class="ti-login-test-pill-id" x-text="'#' + profile.employeeID"></span>
|
|
91
|
+
<span class="ti-login-test-pill-roles" x-text="'roles ' + profile.roles.join(', ')"></span>
|
|
92
|
+
</button>
|
|
93
|
+
</template>
|
|
94
|
+
<button type="button"
|
|
95
|
+
class="ti-login-test-pill ghost"
|
|
96
|
+
x-show="selected"
|
|
97
|
+
x-on:click="clear()">Clear</button>
|
|
98
|
+
</div>
|
|
99
|
+
<label class="ti-login-test-panel-override">
|
|
100
|
+
<input type="checkbox" x-model="overrideRoles" x-on:change="onOverrideChanged()"/>
|
|
101
|
+
<span>Override roles (dev) — inject this profile's role list instead of deriving</span>
|
|
102
|
+
</label>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|