@eintrek/erp-shell 0.1.73 → 0.1.75
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/README.md +63 -0
- package/dist/chunks/{guide-runtime-CLVSNkTN.cjs → format-CVazK0hP.cjs} +1371 -59
- package/dist/chunks/format-CVazK0hP.cjs.map +1 -0
- package/dist/chunks/{guide-runtime-C7Z00QwM.esm.js → format-DCTuLpBU.esm.js} +1360 -61
- package/dist/chunks/format-DCTuLpBU.esm.js.map +1 -0
- package/dist/guide/core.d.ts +5 -3
- package/dist/guide/format.d.ts +26 -0
- package/dist/guide/guide-store.d.ts +72 -6
- package/dist/guide/guide-styles.d.ts +1 -1
- package/dist/guide/guide-ui.d.ts +38 -0
- package/dist/guide/machine.d.ts +139 -3
- package/dist/guide/pages.d.ts +79 -0
- package/dist/guide/progress-sync.d.ts +10 -1
- package/dist/guide/progress.d.ts +27 -0
- package/dist/guide/section-button.d.ts +12 -0
- package/dist/guide/types.d.ts +111 -0
- package/dist/guide-core.cjs +32 -19
- package/dist/guide-core.cjs.map +1 -1
- package/dist/guide-core.esm.js +1 -1
- package/dist/help/help-button.d.ts +6 -3
- package/dist/index.cjs +56 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.esm.js +22 -13
- package/dist/index.esm.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunks/guide-runtime-C7Z00QwM.esm.js.map +0 -1
- package/dist/chunks/guide-runtime-CLVSNkTN.cjs.map +0 -1
package/dist/guide/types.d.ts
CHANGED
|
@@ -41,6 +41,12 @@ export interface GuideContext {
|
|
|
41
41
|
can: (policyKey: string) => boolean;
|
|
42
42
|
/** Whether an anchor is on screen now. */
|
|
43
43
|
visible: (anchor: GuideAnchorKey) => boolean;
|
|
44
|
+
/**
|
|
45
|
+
* A section guide's live values, as the app last rendered them
|
|
46
|
+
* (`useSectionGuideValues` / `SectionGuideButton values`); empty
|
|
47
|
+
* elsewhere. Shell ≥ 0.1.75.
|
|
48
|
+
*/
|
|
49
|
+
values?: Readonly<Record<string, unknown>>;
|
|
44
50
|
}
|
|
45
51
|
/** Text that may depend on the context. */
|
|
46
52
|
export type GuideText = string | ((ctx: GuideContext) => string);
|
|
@@ -171,6 +177,12 @@ export interface GuideStep {
|
|
|
171
177
|
status?: (ctx: GuideContext) => string | null | undefined;
|
|
172
178
|
/** Skip the step (silently) when true. Runs every time it is entered. */
|
|
173
179
|
skipIf?: (ctx: GuideContext) => boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Section guides: the live values this step's copy uses
|
|
182
|
+
* (`ctx.values`). The step is skipped while any is missing (undefined,
|
|
183
|
+
* null, "" or a number that is not finite). Shell ≥ 0.1.75.
|
|
184
|
+
*/
|
|
185
|
+
needs?: string[];
|
|
174
186
|
/** A policy key the step needs (checked with `guides.can`); skipped when
|
|
175
187
|
* the user lacks it. */
|
|
176
188
|
requires?: string;
|
|
@@ -322,6 +334,95 @@ export interface GuideGate {
|
|
|
322
334
|
/** The line on each mission in the panel while waiting: "ต้องมีพนักงาน 2 คน". */
|
|
323
335
|
pending: string;
|
|
324
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* A page guide ("คู่มือหน้านี้", shell ≥ 0.1.74): a read-only walk through one
|
|
339
|
+
* page's regions and buttons — what the page is for, what each column,
|
|
340
|
+
* filter and status means, what each button does. It never saves: only
|
|
341
|
+
* "view" and "click" steps (the engine drops a page guide with a "commit",
|
|
342
|
+
* "input" or "select" step, with a warning in development), and it runs as
|
|
343
|
+
* a replay, so nothing it touches writes tour progress. Authors:
|
|
344
|
+
* _claude-work/guides-r4/GUIDE-PAGES.md.
|
|
345
|
+
*
|
|
346
|
+
* Progress is one row per page per user, `<app>.page.<key>`, written once:
|
|
347
|
+
* when the first-visit offer is answered or ignored, or when the guide ends
|
|
348
|
+
* (finished → completed; exited or left → skipped). Opened again from "?",
|
|
349
|
+
* it writes nothing.
|
|
350
|
+
*/
|
|
351
|
+
export interface GuidePage {
|
|
352
|
+
/** Stable, [a-z0-9-]: the row key is `${suite.app}.page.${key}` (≤ 64 characters). */
|
|
353
|
+
key: string;
|
|
354
|
+
/** Raise it to offer this page's guide again to everyone (this page only). */
|
|
355
|
+
version: number;
|
|
356
|
+
/**
|
|
357
|
+
* The page, as GuideTrigger.route ("/[code]/project/budgets",
|
|
358
|
+
* "/[code]/project/detail/[id]?view=gantt"); several for one page. When
|
|
359
|
+
* several page guides match, the most specific wins: one with `when`, then
|
|
360
|
+
* the most `?k=v` constraints, then the most static segments. If the
|
|
361
|
+
* winner is not for this user (`visible`, `requires`), there is none here.
|
|
362
|
+
*/
|
|
363
|
+
route: string | string[];
|
|
364
|
+
/**
|
|
365
|
+
* An anchor that must be on screen for this guide to apply: sub-screens
|
|
366
|
+
* that share a URL (LIFF's leave list vs its form). The offer waits for it,
|
|
367
|
+
* and the guide ends when it goes.
|
|
368
|
+
*/
|
|
369
|
+
when?: GuideAnchorKey;
|
|
370
|
+
/** "งบประมาณ": the offer card, "?" → "คู่มือหน้านี้" and the panel's list. ≤ 30 characters. */
|
|
371
|
+
title: string;
|
|
372
|
+
/**
|
|
373
|
+
* Where the panel's "คู่มือแต่ละหน้า" list opens it (`[code]` filled in).
|
|
374
|
+
* Omit it for pages that need an id (`[id]`): those are listed only on
|
|
375
|
+
* the page itself, through "คู่มือหน้านี้".
|
|
376
|
+
*/
|
|
377
|
+
href?: GuideText;
|
|
378
|
+
/** Only `true` shows it (as GuideMission.visible): role, plan, module, menu. */
|
|
379
|
+
visible?: (ctx: GuideContext) => boolean | undefined;
|
|
380
|
+
/** A policy key the page needs (checked with `guides.can`). */
|
|
381
|
+
requires?: string;
|
|
382
|
+
/** false: never offered by itself, only opened from "?". Default true. */
|
|
383
|
+
offer?: boolean;
|
|
384
|
+
/**
|
|
385
|
+
* "view" and "click" steps only, ≤ 9 (the app's tests check the count).
|
|
386
|
+
* Steps take no `route`: the guide ends when the page is left. Every step
|
|
387
|
+
* is a checkpoint unless it says `checkpoint: false` (a step inside a
|
|
388
|
+
* dialog or menu a click opened: a closed dialog goes back to the click,
|
|
389
|
+
* and closing the guide there presses Escape).
|
|
390
|
+
*/
|
|
391
|
+
steps: GuideStep[];
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* A section guide ("อธิบายส่วนนี้", shell ≥ 0.1.75): explains one section of
|
|
395
|
+
* a page — a number-heavy card or table — row by row, with the formula and
|
|
396
|
+
* this record's own numbers. Read-only ("view" steps only; a step may point
|
|
397
|
+
* at a row or cell inside the section with `targetId`), never offered by
|
|
398
|
+
* itself: it opens from the section's `SectionGuideButton` or from "?" →
|
|
399
|
+
* "อธิบายส่วนนี้ · <title>". Same switch and audience as page guides
|
|
400
|
+
* (`guides.<app>.pages` not off); one row per section guide per person,
|
|
401
|
+
* `<app>.section.<key>`, written once. Authors:
|
|
402
|
+
* _claude-work/guides-r4/GUIDE-PAGES.md §10.
|
|
403
|
+
*/
|
|
404
|
+
export interface GuideSection {
|
|
405
|
+
/** Stable, [a-z0-9-]: the row key is `${suite.app}.section.${key}` (≤ 64 characters). */
|
|
406
|
+
key: string;
|
|
407
|
+
version: number;
|
|
408
|
+
/** The page(s) the section is on, as GuidePage.route. */
|
|
409
|
+
route: string | string[];
|
|
410
|
+
/** The section's root: the guide is there only while it is on screen. */
|
|
411
|
+
anchor: GuideAnchorKey;
|
|
412
|
+
/** "สรุปกระแสเงินสด": the "?" entry and the bubble's heading. ≤ 40 characters. */
|
|
413
|
+
title: string;
|
|
414
|
+
/** Only `true` shows it (as GuideMission.visible). */
|
|
415
|
+
visible?: (ctx: GuideContext) => boolean | undefined;
|
|
416
|
+
/** A policy key the section needs (checked with `guides.can`). */
|
|
417
|
+
requires?: string;
|
|
418
|
+
/**
|
|
419
|
+
* "view" steps (the default here), about 12 at most; titles ≤ 40 and whys
|
|
420
|
+
* ≤ 90 characters (the app's tests check). Copy may be a function of
|
|
421
|
+
* `ctx.values`; list what it uses in `needs`, and a step whose value is
|
|
422
|
+
* missing is skipped (so is one whose title comes out empty).
|
|
423
|
+
*/
|
|
424
|
+
steps: GuideStep[];
|
|
425
|
+
}
|
|
325
426
|
/** One app's whole tour: the welcome, the missions, the finish. */
|
|
326
427
|
export interface GuideSuite {
|
|
327
428
|
/** Progress key on the server, "<app>.<name>": "peoplx.first-run". */
|
|
@@ -365,6 +466,10 @@ export interface GuideSuite {
|
|
|
365
466
|
};
|
|
366
467
|
};
|
|
367
468
|
missions: GuideMission[];
|
|
469
|
+
/** Page guides ("คู่มือหน้านี้"), shell ≥ 0.1.74. */
|
|
470
|
+
pages?: GuidePage[];
|
|
471
|
+
/** Section guides ("อธิบายส่วนนี้"), shell ≥ 0.1.75. */
|
|
472
|
+
sections?: GuideSection[];
|
|
368
473
|
}
|
|
369
474
|
/** AppLayoutShell's `guides` prop. */
|
|
370
475
|
export interface GuideConfig {
|
|
@@ -378,4 +483,10 @@ export interface GuideConfig {
|
|
|
378
483
|
* Default true.
|
|
379
484
|
*/
|
|
380
485
|
ready?: boolean;
|
|
486
|
+
/**
|
|
487
|
+
* False holds the page guides alone; default: as `ready`. Lets pages run
|
|
488
|
+
* while the missions wait (Accounx's settings pages are open before
|
|
489
|
+
* `module.accounting` is known). Shell ≥ 0.1.74.
|
|
490
|
+
*/
|
|
491
|
+
pagesReady?: boolean;
|
|
381
492
|
}
|
package/dist/guide-core.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var format = require('./chunks/format-CVazK0hP.cjs');
|
|
5
5
|
require('react/jsx-runtime');
|
|
6
6
|
require('react');
|
|
7
7
|
require('react-dom');
|
|
@@ -9,22 +9,35 @@ require('@floating-ui/dom');
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
|
|
12
|
-
exports.GUIDE_API_EVENT =
|
|
13
|
-
exports.GUIDE_EVENT_PREFIX =
|
|
14
|
-
exports.GUIDE_LAYER_ATTRIBUTE =
|
|
15
|
-
exports.GuideProgressConflict =
|
|
16
|
-
exports.GuideRuntime =
|
|
17
|
-
exports.
|
|
18
|
-
exports.
|
|
19
|
-
exports.
|
|
20
|
-
exports.
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
24
|
-
exports.
|
|
25
|
-
exports.
|
|
26
|
-
exports.
|
|
27
|
-
exports.
|
|
28
|
-
exports.
|
|
29
|
-
exports.
|
|
12
|
+
exports.GUIDE_API_EVENT = format.API_EVENT;
|
|
13
|
+
exports.GUIDE_EVENT_PREFIX = format.GUIDE_EVENT_PREFIX;
|
|
14
|
+
exports.GUIDE_LAYER_ATTRIBUTE = format.GUIDE_LAYER_ATTRIBUTE;
|
|
15
|
+
exports.GuideProgressConflict = format.GuideProgressConflict;
|
|
16
|
+
exports.GuideRuntime = format.GuideRuntime;
|
|
17
|
+
exports.SectionGuideButton = format.SectionGuideButton;
|
|
18
|
+
exports.THAI_MONTHS_SHORT = format.THAI_MONTHS_SHORT;
|
|
19
|
+
exports.apiCallDetail = format.apiCallDetail;
|
|
20
|
+
exports.emitGuideEvent = format.emitGuideEvent;
|
|
21
|
+
exports.fillRoute = format.fillRoute;
|
|
22
|
+
exports.formatBaht = format.formatBaht;
|
|
23
|
+
exports.guideAnchor = format.guideAnchor;
|
|
24
|
+
exports.guideMenuItems = format.guideMenuItems;
|
|
25
|
+
exports.guideMenuShown = format.guideMenuShown;
|
|
26
|
+
exports.loadGuides = format.loadGuides;
|
|
27
|
+
exports.matchApiPath = format.matchApiPath;
|
|
28
|
+
exports.matchRoute = format.matchRoute;
|
|
29
|
+
exports.openGuidePanel = format.openGuidePanel;
|
|
30
|
+
exports.openPageGuide = format.openPageGuide;
|
|
31
|
+
exports.openPagesPanel = format.openPagesPanel;
|
|
32
|
+
exports.openSectionGuide = format.openSectionGuide;
|
|
33
|
+
exports.reportApiCall = format.reportApiCall;
|
|
34
|
+
exports.reportApiEvent = format.reportApiEvent;
|
|
35
|
+
exports.setSectionGuideValues = format.setSectionGuideValues;
|
|
36
|
+
exports.storeGuides = format.storeGuides;
|
|
37
|
+
exports.thaiMonth = format.thaiMonth;
|
|
38
|
+
exports.thaiMonthYear = format.thaiMonthYear;
|
|
39
|
+
exports.useGuideEntry = format.useGuideEntry;
|
|
40
|
+
exports.usePageGuideEntry = format.usePageGuideEntry;
|
|
41
|
+
exports.usePageGuides = format.usePageGuides;
|
|
42
|
+
exports.useSectionGuideValues = format.useSectionGuideValues;
|
|
30
43
|
//# sourceMappingURL=guide-core.cjs.map
|
package/dist/guide-core.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guide-core.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"guide-core.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/guide-core.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
export { A as GUIDE_API_EVENT, G as GUIDE_EVENT_PREFIX, a as GUIDE_LAYER_ATTRIBUTE, c as GuideProgressConflict, d as GuideRuntime, e as apiCallDetail, f as emitGuideEvent, g as fillRoute, h as
|
|
2
|
+
export { A as GUIDE_API_EVENT, G as GUIDE_EVENT_PREFIX, a as GUIDE_LAYER_ATTRIBUTE, c as GuideProgressConflict, d as GuideRuntime, S as SectionGuideButton, T as THAI_MONTHS_SHORT, e as apiCallDetail, f as emitGuideEvent, g as fillRoute, h as formatBaht, i as guideAnchor, j as guideMenuItems, k as guideMenuShown, l as loadGuides, m as matchApiPath, n as matchRoute, o as openGuidePanel, p as openPageGuide, q as openPagesPanel, r as openSectionGuide, s as reportApiCall, t as reportApiEvent, u as setSectionGuideValues, v as storeGuides, w as thaiMonth, x as thaiMonthYear, y as useGuideEntry, z as usePageGuideEntry, B as usePageGuides, C as useSectionGuideValues } from './chunks/format-DCTuLpBU.esm.js';
|
|
3
3
|
import 'react/jsx-runtime';
|
|
4
4
|
import 'react';
|
|
5
5
|
import 'react-dom';
|
|
@@ -5,8 +5,11 @@ export interface HelpButtonProps {
|
|
|
5
5
|
* The ช่วยเหลือ button in the top bar. Drawn in the header's ink (the
|
|
6
6
|
* --header-* variables of the workspace chrome, white on the brand chrome).
|
|
7
7
|
*
|
|
8
|
-
* When this user has
|
|
9
|
-
* "
|
|
10
|
-
*
|
|
8
|
+
* When this user has something to open here, it opens a small menu:
|
|
9
|
+
* "คู่มือหน้านี้" (this page's guide), "อธิบายส่วนนี้ · <title>" for each
|
|
10
|
+
* section guide on screen, "ไกด์เริ่มต้น n/N" (the quest
|
|
11
|
+
* panel), "คู่มือทุกหน้า" (the panel's page guides) and "ติดต่อทีมช่วยเหลือ"
|
|
12
|
+
* (the help dialog), each only when it has something. Otherwise one press
|
|
13
|
+
* opens the help dialog, as before.
|
|
11
14
|
*/
|
|
12
15
|
export declare function HelpButton({ className }: HelpButtonProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/index.cjs
CHANGED
|
@@ -14,7 +14,7 @@ var Link = require('next/link');
|
|
|
14
14
|
var reactDom = require('react-dom');
|
|
15
15
|
var nextThemes = require('next-themes');
|
|
16
16
|
var axios = require('axios');
|
|
17
|
-
var
|
|
17
|
+
var format = require('./chunks/format-CVazK0hP.cjs');
|
|
18
18
|
var reactQueryDevtools = require('@tanstack/react-query-devtools');
|
|
19
19
|
require('@floating-ui/dom');
|
|
20
20
|
|
|
@@ -1680,7 +1680,7 @@ instance.interceptors.response.use(response => {
|
|
|
1680
1680
|
}
|
|
1681
1681
|
// The guided tour advances on saves that succeeded (method, path, status
|
|
1682
1682
|
// and the record's id only; never the body).
|
|
1683
|
-
|
|
1683
|
+
format.reportApiEvent(response);
|
|
1684
1684
|
return response;
|
|
1685
1685
|
}, async (error) => {
|
|
1686
1686
|
const originalRequest = error.config;
|
|
@@ -1697,7 +1697,7 @@ instance.interceptors.response.use(response => {
|
|
|
1697
1697
|
return instance(originalRequest);
|
|
1698
1698
|
}
|
|
1699
1699
|
await redirectToLogout();
|
|
1700
|
-
|
|
1700
|
+
format.reportApiEvent(error);
|
|
1701
1701
|
return Promise.reject(toApiError(error));
|
|
1702
1702
|
}
|
|
1703
1703
|
// The server refuses every organisation-scoped call when the account has
|
|
@@ -1713,7 +1713,7 @@ instance.interceptors.response.use(response => {
|
|
|
1713
1713
|
if (listed !== undefined)
|
|
1714
1714
|
return listed;
|
|
1715
1715
|
// A refused save keeps the tour's step and shows the server's message.
|
|
1716
|
-
|
|
1716
|
+
format.reportApiEvent(error);
|
|
1717
1717
|
return Promise.reject(toApiError(error));
|
|
1718
1718
|
});
|
|
1719
1719
|
|
|
@@ -1740,7 +1740,7 @@ function platformApiBase(app) {
|
|
|
1740
1740
|
* This package's version, attached to help messages so the back office can
|
|
1741
1741
|
* tell which shell a report came from. Keep in step with package.json.
|
|
1742
1742
|
*/
|
|
1743
|
-
const SHELL_VERSION = "0.1.
|
|
1743
|
+
const SHELL_VERSION = "0.1.75";
|
|
1744
1744
|
|
|
1745
1745
|
const HELP_APP_LABEL = {
|
|
1746
1746
|
platform: "แพลตฟอร์ม",
|
|
@@ -2412,11 +2412,11 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, ch
|
|
|
2412
2412
|
// A one-line row: a link, lit on its own page only. No open
|
|
2413
2413
|
// state, no title tooltip.
|
|
2414
2414
|
return (jsxRuntime.jsxs(React__namespace.Fragment, { children: [groupHeading, jsxRuntime.jsx(SidebarMenuItem, { children: jsxRuntime.jsx(SidebarMenuButton, { asChild: true, isActive: isItemActive, className: workspaceButton, children: jsxRuntime.jsxs(Link, { href: itemUrl, prefetch: false, className: "flex items-center w-full min-w-0 flex-1 " +
|
|
2415
|
-
(workspace ? "gap-3" : "gap-2"), onClick: handleNavLinkClick, "aria-current": isItemActive ? "page" : undefined, ...
|
|
2415
|
+
(workspace ? "gap-3" : "gap-2"), onClick: handleNavLinkClick, "aria-current": isItemActive ? "page" : undefined, ...format.guideAnchor(`nav.${item.id}`), children: [icon, jsxRuntime.jsx("span", { id: item.id, className: "flex-1 truncate", children: item.titleTh }), badge] }) }) })] }, item.id));
|
|
2416
2416
|
}
|
|
2417
2417
|
// A group: its header opens and shuts it (the chevron says which).
|
|
2418
2418
|
// An open group is not the current page — only a row in it is.
|
|
2419
|
-
return (jsxRuntime.jsxs(React__namespace.Fragment, { children: [groupHeading, jsxRuntime.jsx(erpTheme.Collapsible, { asChild: true, open: openIds.has(item.id), onOpenChange: isOpen => setItemOpen(item.id, isOpen), className: "group/collapsible", children: jsxRuntime.jsxs(SidebarMenuItem, { children: [jsxRuntime.jsx(erpTheme.CollapsibleTrigger, { asChild: true, children: jsxRuntime.jsxs(SidebarMenuButton, { isActive: isItemActive, className: workspaceButton, ...
|
|
2419
|
+
return (jsxRuntime.jsxs(React__namespace.Fragment, { children: [groupHeading, jsxRuntime.jsx(erpTheme.Collapsible, { asChild: true, open: openIds.has(item.id), onOpenChange: isOpen => setItemOpen(item.id, isOpen), className: "group/collapsible", children: jsxRuntime.jsxs(SidebarMenuItem, { children: [jsxRuntime.jsx(erpTheme.CollapsibleTrigger, { asChild: true, children: jsxRuntime.jsxs(SidebarMenuButton, { isActive: isItemActive, className: workspaceButton, ...format.guideAnchor(`nav.${item.id}`), children: [icon, jsxRuntime.jsx("span", { id: item.id, className: "flex-1 truncate text-left", children: item.titleTh }), jsxRuntime.jsx(lucideReact.ChevronRight, { className: "ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" })] }) }), item.subModules && (jsxRuntime.jsx(erpTheme.CollapsibleContent, { children: jsxRuntime.jsx(SidebarMenuSub, { className: workspace
|
|
2420
2420
|
? "mx-0 mt-1 mb-3 ml-[21px] gap-0.5 border-l border-sidebar-border pl-2.5 [&_a]:h-auto [&_a]:gap-[11px] [&_a]:px-3 [&_a]:py-2 [&_a]:text-xs [&_svg]:!size-[17px]"
|
|
2421
2421
|
: undefined, children: item.subModules.map((subItem, subIndex) => {
|
|
2422
2422
|
const subItemUrl = buildUrlWithCode(code, subItem.url);
|
|
@@ -2429,7 +2429,7 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, ch
|
|
|
2429
2429
|
subItem.subPages &&
|
|
2430
2430
|
subItem.subPages.length > 0) {
|
|
2431
2431
|
return (jsxRuntime.jsx(erpTheme.Collapsible, { asChild: true, defaultOpen: isSubItemActive || openSub === subIndex, className: "group/sub-collapsible", children: jsxRuntime.jsxs(SidebarMenuSubItem, { children: [jsxRuntime.jsx(erpTheme.CollapsibleTrigger, { asChild: true, children: jsxRuntime.jsxs(SidebarMenuSubButton, { className: "w-full", isActive: isSubItemActive &&
|
|
2432
|
-
activeSubPage === null, ...
|
|
2432
|
+
activeSubPage === null, ...format.guideAnchor(`nav.${subItem.id}`), children: [SubIcon && (jsxRuntime.jsx(SubIcon, { className: "sidebar-submodule-icon flex-shrink-0" })), jsxRuntime.jsx("span", { className: "flex-1 truncate", children: subItem.titleTh }), jsxRuntime.jsx(lucideReact.ChevronDown, { className: "ml-auto size-4 transition-transform duration-200 group-data-[state=open]/sub-collapsible:rotate-180" })] }) }), jsxRuntime.jsx(erpTheme.CollapsibleContent, { children: jsxRuntime.jsx(SidebarMenuSub, { className: "ml-4", children: subItem.subPages.map((subPage, subPageIndex) => {
|
|
2433
2433
|
const subPageUrl = buildUrlWithCode(code, subPage.url);
|
|
2434
2434
|
const isSubPageActive = isSubItemActive &&
|
|
2435
2435
|
activeSubPage === subPageIndex;
|
|
@@ -2437,7 +2437,7 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, ch
|
|
|
2437
2437
|
return (jsxRuntime.jsx(SidebarMenuSubItem, { children: jsxRuntime.jsx(SidebarMenuSubButton, { asChild: true, className: "font-thai w-full text-sm" +
|
|
2438
2438
|
(isSubPageActive
|
|
2439
2439
|
? " font-medium"
|
|
2440
|
-
: ""), isActive: isSubPageActive, children: jsxRuntime.jsxs(Link, { href: subPageUrl, prefetch: false, className: "w-full flex items-center", ...
|
|
2440
|
+
: ""), isActive: isSubPageActive, children: jsxRuntime.jsxs(Link, { href: subPageUrl, prefetch: false, className: "w-full flex items-center", ...format.guideAnchor(`nav.${subPage.id}`), onClick: handleNavLinkClick, "aria-current": isSubPageActive
|
|
2441
2441
|
? "page"
|
|
2442
2442
|
: undefined, children: [SubPageIcon && (jsxRuntime.jsx(SubPageIcon, { className: "sidebar-subpage-icon flex-shrink-0" })), jsxRuntime.jsx("span", { className: "flex-1 truncate", children: subPage.titleTh })] }) }) }, subPage.id));
|
|
2443
2443
|
}) }) })] }) }, subItem.id));
|
|
@@ -2445,7 +2445,7 @@ function NavMain({ items, orgCode, closeOnNavigation = false, approvalCounts, ch
|
|
|
2445
2445
|
return (jsxRuntime.jsx(SidebarMenuSubItem, { children: jsxRuntime.jsx(SidebarMenuSubButton, { asChild: true, className: "w-full" +
|
|
2446
2446
|
(workspace && isSubItemActive
|
|
2447
2447
|
? " font-semibold"
|
|
2448
|
-
: ""), isActive: isSubItemActive, children: jsxRuntime.jsxs(Link, { href: subItemUrl, prefetch: false, className: "w-full flex items-center", ...
|
|
2448
|
+
: ""), isActive: isSubItemActive, children: jsxRuntime.jsxs(Link, { href: subItemUrl, prefetch: false, className: "w-full flex items-center", ...format.guideAnchor(`nav.${subItem.id}`), onClick: handleNavLinkClick, "aria-current": isSubItemActive ? "page" : undefined, children: [SubIcon && (jsxRuntime.jsx(SubIcon, { className: "sidebar-submodule-icon flex-shrink-0" })), jsxRuntime.jsx("span", { className: "flex-1 truncate", children: subItem.titleTh }), approvalCount > 0 && (jsxRuntime.jsx(erpTheme.Badge, { variant: "destructive", className: "ml-auto h-5 min-w-5 px-1.5 text-xs font-medium tabular-nums", children: approvalCount > 99
|
|
2449
2449
|
? "99+"
|
|
2450
2450
|
: approvalCount }))] }) }) }, subItem.id));
|
|
2451
2451
|
}) }) }))] }) })] }, item.id));
|
|
@@ -2572,15 +2572,25 @@ const BUTTON_CLASS = "grid size-[34px] shrink-0 place-items-center rounded-lg te
|
|
|
2572
2572
|
* The ช่วยเหลือ button in the top bar. Drawn in the header's ink (the
|
|
2573
2573
|
* --header-* variables of the workspace chrome, white on the brand chrome).
|
|
2574
2574
|
*
|
|
2575
|
-
* When this user has
|
|
2576
|
-
* "
|
|
2577
|
-
*
|
|
2575
|
+
* When this user has something to open here, it opens a small menu:
|
|
2576
|
+
* "คู่มือหน้านี้" (this page's guide), "อธิบายส่วนนี้ · <title>" for each
|
|
2577
|
+
* section guide on screen, "ไกด์เริ่มต้น n/N" (the quest
|
|
2578
|
+
* panel), "คู่มือทุกหน้า" (the panel's page guides) and "ติดต่อทีมช่วยเหลือ"
|
|
2579
|
+
* (the help dialog), each only when it has something. Otherwise one press
|
|
2580
|
+
* opens the help dialog, as before.
|
|
2578
2581
|
*/
|
|
2579
2582
|
function HelpButton({ className }) {
|
|
2580
|
-
const guide =
|
|
2583
|
+
const guide = format.useGuideEntry();
|
|
2584
|
+
const pages = format.usePageGuides();
|
|
2581
2585
|
const toGuide = React.useRef(false);
|
|
2582
2586
|
const cls = BUTTON_CLASS + (className ? ` ${className}` : "");
|
|
2583
|
-
|
|
2587
|
+
const items = format.guideMenuItems(guide, pages);
|
|
2588
|
+
// The tour takes focus (a step, the panel); the button must not take it back.
|
|
2589
|
+
const toTour = (open) => () => {
|
|
2590
|
+
toGuide.current = true;
|
|
2591
|
+
setTimeout(open, 0);
|
|
2592
|
+
};
|
|
2593
|
+
if (!items.length) {
|
|
2584
2594
|
return (jsxRuntime.jsx("button", { type: "button", onClick: openHelp, "aria-label": "\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D", title: "\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D", className: cls, "data-guide": "shell.help", children: jsxRuntime.jsx(lucideReact.CircleHelp, { className: "size-5", strokeWidth: 1.65 }) }));
|
|
2585
2595
|
}
|
|
2586
2596
|
return (jsxRuntime.jsxs(erpTheme.DropdownMenu, { children: [jsxRuntime.jsx(erpTheme.DropdownMenuTrigger, { asChild: true, children: jsxRuntime.jsx("button", { type: "button", "aria-label": "\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D", title: "\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D", className: cls, "data-guide": "shell.help", children: jsxRuntime.jsx(lucideReact.CircleHelp, { className: "size-5", strokeWidth: 1.65 }) }) }), jsxRuntime.jsxs(erpTheme.DropdownMenuContent, { align: "end", sideOffset: 8, className: "w-64", onCloseAutoFocus: e => {
|
|
@@ -2589,10 +2599,9 @@ function HelpButton({ className }) {
|
|
|
2589
2599
|
e.preventDefault();
|
|
2590
2600
|
toGuide.current = false;
|
|
2591
2601
|
}
|
|
2592
|
-
}, children: [jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: ()
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
}, className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Flag, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E44\u0E01\u0E14\u0E4C\u0E40\u0E23\u0E34\u0E48\u0E21\u0E15\u0E49\u0E19" }), jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-primary tabular-nums", children: [guide.done, "/", guide.total] })] }), jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: () => setTimeout(openHelp, 0), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.MessageCircle, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D" })] })] })] }));
|
|
2602
|
+
}, children: [items.includes("page") ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openPageGuide), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.BookOpen, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E04\u0E39\u0E48\u0E21\u0E37\u0E2D\u0E2B\u0E19\u0E49\u0E32\u0E19\u0E35\u0E49" })] })) : null, items.includes("sections")
|
|
2603
|
+
? (pages.sections ?? []).map(sec => (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(() => format.openSectionGuide(sec.key)), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Info, { className: "size-4" }), jsxRuntime.jsxs("span", { className: "flex-1", children: ["\u0E2D\u0E18\u0E34\u0E1A\u0E32\u0E22\u0E2A\u0E48\u0E27\u0E19\u0E19\u0E35\u0E49 \u00B7 ", sec.title] })] }, sec.key)))
|
|
2604
|
+
: null, items.includes("missions") && guide ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openGuidePanel), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Flag, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E44\u0E01\u0E14\u0E4C\u0E40\u0E23\u0E34\u0E48\u0E21\u0E15\u0E49\u0E19" }), jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-primary tabular-nums", children: [guide.done, "/", guide.total] })] })) : null, items.includes("pages") ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openPagesPanel), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Library, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E04\u0E39\u0E48\u0E21\u0E37\u0E2D\u0E17\u0E38\u0E01\u0E2B\u0E19\u0E49\u0E32" })] })) : null, jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: () => setTimeout(openHelp, 0), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.MessageCircle, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D" })] })] })] }));
|
|
2596
2605
|
}
|
|
2597
2606
|
|
|
2598
2607
|
const hasPaginationShape = (payload) => {
|
|
@@ -3603,7 +3612,7 @@ function platformGuideProgress(organizationId) {
|
|
|
3603
3612
|
|
|
3604
3613
|
function GuideHost(props) {
|
|
3605
3614
|
// The boundary covers the adapters too (useSidebar throws without its provider).
|
|
3606
|
-
return (jsxRuntime.jsx(
|
|
3615
|
+
return (jsxRuntime.jsx(format.GuideErrorBoundary, { children: jsxRuntime.jsx(React.Suspense, { fallback: null, children: jsxRuntime.jsx(GuideHostInner, { ...props }) }) }));
|
|
3607
3616
|
}
|
|
3608
3617
|
let fallbackClient = null;
|
|
3609
3618
|
function useShellQueryClient() {
|
|
@@ -3654,7 +3663,7 @@ function GuideHostInner({ config, organizationId, code }) {
|
|
|
3654
3663
|
}, [client, organizationId, suite.app, suite.key, suite.version]);
|
|
3655
3664
|
const routing = React.useMemo(() => ({ pathname, search, navigate: (href) => router.push(href) }), [pathname, search, router]);
|
|
3656
3665
|
const menu = React.useMemo(() => ({ open: sidebarOpen }), [sidebarOpen]);
|
|
3657
|
-
return (jsxRuntime.jsx(
|
|
3666
|
+
return (jsxRuntime.jsx(format.GuideRuntime, { config: config, organizationId: organizationId, code: code, routing: routing, progress: progress, isBusy: isBusy, menu: menu, hidden: employeeBlocked }));
|
|
3658
3667
|
}
|
|
3659
3668
|
|
|
3660
3669
|
/**
|
|
@@ -3863,7 +3872,7 @@ function AppLayoutShell({ children, sidebar, loadingComponent, breadcrumb, permi
|
|
|
3863
3872
|
// As in the design: the mark, then a menu button, and the
|
|
3864
3873
|
// organisation on the right — no trail, no title, so the
|
|
3865
3874
|
// organisation's name has the room it needs on a phone.
|
|
3866
|
-
jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [mobileBrand ? (jsxRuntime.jsx("div", { className: "shrink-0", children: mobileBrand })) : null, jsxRuntime.jsx("button", { type: "button", onClick: () => setOpen(!open), "aria-label": open ? "ปิดเมนู" : "เปิดเมนู", ...
|
|
3875
|
+
jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [mobileBrand ? (jsxRuntime.jsx("div", { className: "shrink-0", children: mobileBrand })) : null, jsxRuntime.jsx("button", { type: "button", onClick: () => setOpen(!open), "aria-label": open ? "ปิดเมนู" : "เปิดเมนู", ...format.guideAnchor("shell.menu-toggle"), className: "grid size-[34px] shrink-0 place-items-center rounded-lg text-[var(--header-fg-muted)] transition-colors hover:bg-[var(--header-hover)] hover:text-[var(--header-fg)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--header-fg-muted)]", children: jsxRuntime.jsx(lucideReact.LayoutGrid, { className: "size-5", strokeWidth: 1.65 }) })] })) : (jsxRuntime.jsx(SidebarTrigger, { className: "shrink-0 text-[var(--header-fg-muted)] hover:bg-[var(--header-hover)] hover:text-[var(--header-fg)] [&_svg]:!text-current" })), jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-0.5", children: [jsxRuntime.jsx("div", { className: "hidden min-w-0 sm:block", children: trail }), jsxRuntime.jsx("div", { id: "header-title", className: "min-w-0 max-sm:hidden" })] }), headerEnd || showHelp ? (jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-3 sm:gap-5", children: [headerEnd, showHelp ? jsxRuntime.jsx(HelpButton, {}) : null] })) : null] })] })) : (jsxRuntime.jsxs("div", { className: "sticky top-0 z-30 shrink-0 w-full", children: [jsxRuntime.jsx(HeaderBackground, {}), jsxRuntime.jsxs("header", { className: "relative shrink-0 gap-2 py-4 h-auto min-h-[123.5px] w-full z-10", children: [jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-2 px-3 sm:px-4 lg:px-6", children: [jsxRuntime.jsx(SidebarTrigger, { className: "shrink-0 text-white hover:bg-white/10" }), jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: trail }), headerEnd || showHelp ? (jsxRuntime.jsxs("div", { className: "flex shrink-0 items-center gap-3", children: [headerEnd, showHelp ? jsxRuntime.jsx(HelpButton, {}) : null] })) : null] }), jsxRuntime.jsx("div", { id: "header-title" })] })] })), jsxRuntime.jsx(React.Suspense, { fallback: jsxRuntime.jsx("div", { className: "relative z-10 min-h-[calc(100vh-8rem)]", children: jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: jsxRuntime.jsxs("div", { className: "space-y-4 text-center", children: [jsxRuntime.jsx("div", { className: "mx-auto h-8 w-8 animate-spin rounded-full border-b-2 border-primary" }), jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "\u0E01\u0E33\u0E25\u0E31\u0E07\u0E42\u0E2B\u0E25\u0E14..." })] }) }) }), children: jsxRuntime.jsx("div", { className: workspace
|
|
3867
3876
|
? "relative z-10 px-[18px] pt-[26px] pb-4 sm:px-6 lg:px-10 lg:pt-[38px]"
|
|
3868
3877
|
: cx("relative z-10 pr-6", needsLeftGutter && "pl-6"), children: refusePage
|
|
3869
3878
|
? (notMemberComponent ?? (jsxRuntime.jsx(AccessDenied, { title: "\u0E44\u0E21\u0E48\u0E21\u0E35\u0E2A\u0E34\u0E17\u0E18\u0E34\u0E4C\u0E40\u0E02\u0E49\u0E32\u0E16\u0E36\u0E07\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23\u0E19\u0E35\u0E49", message: `บัญชีนี้ไม่ได้เป็นสมาชิกขององค์กร ${code}`, homeHref: selectOrganizationUrl, homeLabel: "\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23" })))
|
|
@@ -4436,18 +4445,31 @@ Object.defineProperty(exports, "isAxiosError", {
|
|
|
4436
4445
|
enumerable: true,
|
|
4437
4446
|
get: function () { return axios.isAxiosError; }
|
|
4438
4447
|
});
|
|
4439
|
-
exports.GUIDE_API_EVENT =
|
|
4440
|
-
exports.GUIDE_EVENT_PREFIX =
|
|
4441
|
-
exports.GUIDE_LAYER_ATTRIBUTE =
|
|
4442
|
-
exports.GuideProgressConflict =
|
|
4443
|
-
exports.GuideRuntime =
|
|
4444
|
-
exports.
|
|
4445
|
-
exports.
|
|
4446
|
-
exports.
|
|
4447
|
-
exports.
|
|
4448
|
-
exports.
|
|
4449
|
-
exports.
|
|
4450
|
-
exports.
|
|
4448
|
+
exports.GUIDE_API_EVENT = format.API_EVENT;
|
|
4449
|
+
exports.GUIDE_EVENT_PREFIX = format.GUIDE_EVENT_PREFIX;
|
|
4450
|
+
exports.GUIDE_LAYER_ATTRIBUTE = format.GUIDE_LAYER_ATTRIBUTE;
|
|
4451
|
+
exports.GuideProgressConflict = format.GuideProgressConflict;
|
|
4452
|
+
exports.GuideRuntime = format.GuideRuntime;
|
|
4453
|
+
exports.SectionGuideButton = format.SectionGuideButton;
|
|
4454
|
+
exports.THAI_MONTHS_SHORT = format.THAI_MONTHS_SHORT;
|
|
4455
|
+
exports.emitGuideEvent = format.emitGuideEvent;
|
|
4456
|
+
exports.formatBaht = format.formatBaht;
|
|
4457
|
+
exports.guideAnchor = format.guideAnchor;
|
|
4458
|
+
exports.guideMenuItems = format.guideMenuItems;
|
|
4459
|
+
exports.guideMenuShown = format.guideMenuShown;
|
|
4460
|
+
exports.openGuidePanel = format.openGuidePanel;
|
|
4461
|
+
exports.openPageGuide = format.openPageGuide;
|
|
4462
|
+
exports.openPagesPanel = format.openPagesPanel;
|
|
4463
|
+
exports.openSectionGuide = format.openSectionGuide;
|
|
4464
|
+
exports.reportApiCall = format.reportApiCall;
|
|
4465
|
+
exports.reportApiEvent = format.reportApiEvent;
|
|
4466
|
+
exports.setSectionGuideValues = format.setSectionGuideValues;
|
|
4467
|
+
exports.thaiMonth = format.thaiMonth;
|
|
4468
|
+
exports.thaiMonthYear = format.thaiMonthYear;
|
|
4469
|
+
exports.useGuideEntry = format.useGuideEntry;
|
|
4470
|
+
exports.usePageGuideEntry = format.usePageGuideEntry;
|
|
4471
|
+
exports.usePageGuides = format.usePageGuides;
|
|
4472
|
+
exports.useSectionGuideValues = format.useSectionGuideValues;
|
|
4451
4473
|
exports.AccessDenied = AccessDenied;
|
|
4452
4474
|
exports.ApiError = ApiError;
|
|
4453
4475
|
exports.AppBreadcrumb = AppBreadcrumb;
|