@yadsh/dsh-qa-surface 0.7.0 → 0.7.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/README.md +27 -0
- package/lib/client/QaSurface.js +2 -2
- package/lib/client/QaSurface.js.map +1 -1
- package/lib/client/admin/routes.js +18 -2
- package/lib/client/admin/routes.js.map +1 -1
- package/lib/client/components/QaChangelog.js +18 -0
- package/lib/client/components/QaChangelog.js.map +1 -1
- package/lib/client/index.js +15 -0
- package/lib/client/index.js.map +1 -1
- package/lib/client/settings-extensions/index.js +1 -0
- package/lib/client/settings-extensions/index.js.map +1 -1
- package/lib/client/settings-extensions/user-session.js +62 -0
- package/lib/client/settings-extensions/user-session.js.map +1 -0
- package/lib/client.js +99 -5
- package/lib/client.js.map +1 -1
- package/lib/types/client/admin/routes.d.ts +10 -0
- package/lib/types/client/settings-extensions/index.d.ts +2 -0
- package/lib/types/client/settings-extensions/user-session.d.ts +59 -0
- package/package.json +2 -2
package/lib/client.js
CHANGED
|
@@ -16572,8 +16572,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16572
16572
|
}
|
|
16573
16573
|
//#endregion
|
|
16574
16574
|
//#region src/client/components/QaChangelog.tsx
|
|
16575
|
-
const QA_VERSION = "0.7.
|
|
16575
|
+
const QA_VERSION = "0.7.1";
|
|
16576
16576
|
const QA_CHANGELOG = [
|
|
16577
|
+
{
|
|
16578
|
+
version: "0.7.1",
|
|
16579
|
+
date: "2026-09-16",
|
|
16580
|
+
sections: [{
|
|
16581
|
+
title: "Исправления",
|
|
16582
|
+
items: ["В консоли администратора открываются все разделы, а не только «Обзор»: «Пользователи», «Саброли», «Общие возможности», «Навыки», «Разговоры», «Очередь разбора», «Обратная связь», «Аналитика» и «Аудит». Раньше переход в любой раздел закрывал консоль и возвращал в чат, а ссылка на конкретный разговор или сообщение вместо разбора открывала обычный чат. Каждый такой переход ещё и оставлял в стенде пустой чат, попадавший в счётчики разговоров; переходы внутри консоли чатов больше не создают."]
|
|
16583
|
+
}, {
|
|
16584
|
+
title: "Прочее",
|
|
16585
|
+
items: ["Внутренняя доработка для плагинов стенда: карточка плагина в настройках DSH теперь может узнать, вошёл ли пользователь в QA, и работать с его подключениями от его имени — на этом подключения к рабочим сервисам показываются и в списке плагинов. Интерфейс QA это не меняет: вход, чаты и настройки работают как раньше, а без входа карточка подключений ничего не показывает."]
|
|
16586
|
+
}]
|
|
16587
|
+
},
|
|
16577
16588
|
{
|
|
16578
16589
|
version: "0.7.0",
|
|
16579
16590
|
date: "2026-09-16",
|
|
@@ -16779,7 +16790,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16779
16790
|
className: "dsh-qa-changelog__date",
|
|
16780
16791
|
children: entry.date
|
|
16781
16792
|
}),
|
|
16782
|
-
entry.version === "0.7.
|
|
16793
|
+
entry.version === "0.7.1" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
16783
16794
|
className: "dsh-qa-changelog__current",
|
|
16784
16795
|
children: "текущая"
|
|
16785
16796
|
}) : null
|
|
@@ -19967,9 +19978,25 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19967
19978
|
}
|
|
19968
19979
|
//#endregion
|
|
19969
19980
|
//#region src/client/admin/routes.ts
|
|
19981
|
+
/** The console's own base path under the surface route. */
|
|
19982
|
+
function adminBasePath(routePath) {
|
|
19983
|
+
return `${routePath === "/" ? "" : routePath}/admin`;
|
|
19984
|
+
}
|
|
19985
|
+
/**
|
|
19986
|
+
* Whether a pathname addresses the console at all. Sections and entities each
|
|
19987
|
+
* own a path under the base ({@link adminPath}), and the surface hosting the
|
|
19988
|
+
* console must stay the console while any of them is open, so the test is by
|
|
19989
|
+
* prefix. An equality test against the base alone unmounts the console on the
|
|
19990
|
+
* first navigation inside it, and every deep link lands in the chat instead.
|
|
19991
|
+
*/
|
|
19992
|
+
function isAdminPath(pathname, routePath) {
|
|
19993
|
+
const base = adminBasePath(routePath);
|
|
19994
|
+
const trimmed = pathname.replace(/\/+$/u, "");
|
|
19995
|
+
return trimmed === base || trimmed.startsWith(`${base}/`);
|
|
19996
|
+
}
|
|
19970
19997
|
/** Path segments after `/qa/admin`, without the leading slash. */
|
|
19971
19998
|
function adminSegments(pathname, routePath) {
|
|
19972
|
-
const base =
|
|
19999
|
+
const base = adminBasePath(routePath);
|
|
19973
20000
|
return (pathname.startsWith(base) ? pathname.slice(base.length) : "").split("/").map((segment) => segment.trim()).filter((segment) => segment !== "");
|
|
19974
20001
|
}
|
|
19975
20002
|
/**
|
|
@@ -20009,7 +20036,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20009
20036
|
}
|
|
20010
20037
|
/** The pathname for one console route; the inverse of {@link parseAdminRoute}. */
|
|
20011
20038
|
function adminPath(routePath, route, search = "") {
|
|
20012
|
-
return `${
|
|
20039
|
+
return `${adminBasePath(routePath)}${(() => {
|
|
20013
20040
|
switch (route.page) {
|
|
20014
20041
|
case "overview": return "";
|
|
20015
20042
|
case "users": return "/users";
|
|
@@ -22799,7 +22826,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
22799
22826
|
const accounts = props.accounts;
|
|
22800
22827
|
const accountsSnapshot = (0, react.useSyncExternalStore)(accounts?.subscribe ?? noopSubscribe$1, accounts?.getSnapshot ?? noopAccountsSnapshot, accounts?.getSnapshot ?? noopAccountsSnapshot);
|
|
22801
22828
|
const accountsStage = accountsSnapshot.stage;
|
|
22802
|
-
const adminRoute = route.pathname
|
|
22829
|
+
const adminRoute = isAdminPath(route.pathname, config.route.path);
|
|
22803
22830
|
const [access, setAccess] = (0, react.useState)();
|
|
22804
22831
|
const [selectedSubrole, setSelectedSubrole] = (0, react.useState)(null);
|
|
22805
22832
|
const [adminPreview, setAdminPreview] = (0, react.useState)(false);
|
|
@@ -26590,6 +26617,64 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26590
26617
|
}
|
|
26591
26618
|
};
|
|
26592
26619
|
//#endregion
|
|
26620
|
+
//#region src/client/settings-extensions/user-session.ts
|
|
26621
|
+
const CHECKING = Object.freeze({
|
|
26622
|
+
stage: "checking",
|
|
26623
|
+
token: null
|
|
26624
|
+
});
|
|
26625
|
+
const ANONYMOUS = Object.freeze({
|
|
26626
|
+
stage: "anonymous",
|
|
26627
|
+
token: null
|
|
26628
|
+
});
|
|
26629
|
+
/**
|
|
26630
|
+
* Publishes the account state of the controller the QA overlay mounts. The
|
|
26631
|
+
* service lives for the whole host page while the controller is rebuilt
|
|
26632
|
+
* whenever the remote wiring re-injects, so {@link attach} swaps the source and
|
|
26633
|
+
* republishes; an unattached mirror stays in `checking`, which is what a card
|
|
26634
|
+
* that mounts before the accounts subsystem sees.
|
|
26635
|
+
*/
|
|
26636
|
+
var QaUserSessionMirror = class {
|
|
26637
|
+
controller;
|
|
26638
|
+
unsubscribeSource;
|
|
26639
|
+
snapshot = CHECKING;
|
|
26640
|
+
listeners = /* @__PURE__ */ new Set();
|
|
26641
|
+
/** Bind the controller whose account state this view publishes. */
|
|
26642
|
+
attach(controller) {
|
|
26643
|
+
this.unsubscribeSource?.();
|
|
26644
|
+
this.unsubscribeSource = void 0;
|
|
26645
|
+
this.controller = controller;
|
|
26646
|
+
this.unsubscribeSource = controller?.subscribe(() => {
|
|
26647
|
+
this.publish();
|
|
26648
|
+
});
|
|
26649
|
+
this.publish();
|
|
26650
|
+
}
|
|
26651
|
+
dispose() {
|
|
26652
|
+
this.attach(void 0);
|
|
26653
|
+
this.listeners.clear();
|
|
26654
|
+
}
|
|
26655
|
+
getSnapshot = () => this.snapshot;
|
|
26656
|
+
subscribe = (listener) => {
|
|
26657
|
+
this.listeners.add(listener);
|
|
26658
|
+
return () => this.listeners.delete(listener);
|
|
26659
|
+
};
|
|
26660
|
+
publish() {
|
|
26661
|
+
const next = this.derive();
|
|
26662
|
+
if (next.stage === this.snapshot.stage && next.token === this.snapshot.token) return;
|
|
26663
|
+
this.snapshot = next;
|
|
26664
|
+
for (const listener of [...this.listeners]) listener();
|
|
26665
|
+
}
|
|
26666
|
+
derive() {
|
|
26667
|
+
const state = this.controller?.getSnapshot();
|
|
26668
|
+
const token = this.controller?.token() ?? null;
|
|
26669
|
+
if (state?.stage === "authed" && token !== null) return Object.freeze({
|
|
26670
|
+
stage: "authed",
|
|
26671
|
+
token
|
|
26672
|
+
});
|
|
26673
|
+
if (state === void 0 || state.stage === "checking") return CHECKING;
|
|
26674
|
+
return ANONYMOUS;
|
|
26675
|
+
}
|
|
26676
|
+
};
|
|
26677
|
+
//#endregion
|
|
26593
26678
|
//#region src/client/index.tsx
|
|
26594
26679
|
const QA_WELCOME_SLOT_ID = "welcome-notice";
|
|
26595
26680
|
function qaWelcomeStorageKey(config) {
|
|
@@ -26607,6 +26692,7 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26607
26692
|
async function apply(ctx) {
|
|
26608
26693
|
const panels = new QaSurfacePanelRegistry();
|
|
26609
26694
|
const settingsSections = new QaUserSettingsSectionRegistry();
|
|
26695
|
+
const userSession = new QaUserSessionMirror();
|
|
26610
26696
|
ctx.effect(() => {
|
|
26611
26697
|
const removeService = ctx.provide("qaSurfacePanels", panels);
|
|
26612
26698
|
return () => {
|
|
@@ -26621,6 +26707,13 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26621
26707
|
removeService();
|
|
26622
26708
|
};
|
|
26623
26709
|
}, "dsh-qa-surface: user settings extension service");
|
|
26710
|
+
ctx.effect(() => {
|
|
26711
|
+
const removeService = ctx.provide("qaUserSession", userSession);
|
|
26712
|
+
return () => {
|
|
26713
|
+
userSession.dispose();
|
|
26714
|
+
removeService();
|
|
26715
|
+
};
|
|
26716
|
+
}, "dsh-qa-surface: user session service");
|
|
26624
26717
|
const disposeRemote = await ctx.remote.$mount(TYPERT_REMOTE);
|
|
26625
26718
|
await ctx.inject([
|
|
26626
26719
|
"remote.qaSurface",
|
|
@@ -26700,6 +26793,7 @@ textarea.qa-card-control{height:auto;padding:8px 12px;line-height:1.5;resize:ver
|
|
|
26700
26793
|
new QaChatIndex(window.localStorage, qaStorageNamespace(snapshot)).forgetChat(sessionId);
|
|
26701
26794
|
}
|
|
26702
26795
|
});
|
|
26796
|
+
userSession.attach(accounts);
|
|
26703
26797
|
const route = new QaRouteController();
|
|
26704
26798
|
const settingsScope = ctx.settingsScope.bind({ namespace: QA_SURFACE_SETTINGS_NAMESPACE });
|
|
26705
26799
|
const config = new QaConfigController(settingsScope, async () => {
|