mirror of
https://github.com/unraid/api.git
synced 2025-12-31 13:39:52 -06:00
feat: upgrade nuxt-custom-elements (#1461)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added new modal dialogs and UI components, including activation steps, OS update feedback, and expanded notification management. * Introduced a plugin to configure internationalization, state management, and Apollo client support in web components. * Added a new Log Viewer page with a streamlined interface for viewing logs. * **Improvements** * Centralized Pinia state management by consolidating all stores to use a shared global Pinia instance. * Simplified component templates by removing redundant internationalization host wrappers. * Enhanced ESLint configuration with stricter rules and global variable declarations. * Refined custom element build process to prevent jQuery conflicts and optimize minification. * Updated component imports and templates for consistent structure and maintainability. * Streamlined log viewer dropdowns using simplified select components with improved formatting. * Improved notification sidebar with filtering by importance and modular components. * Replaced legacy notification popups with new UI components and added automatic root session creation for localhost requests. * Updated OS version display and user profile UI with refined styling and component usage. * **Bug Fixes** * Fixed component tag capitalization and improved type annotations across components. * **Chores** * Updated development dependencies including ESLint plugins and build tools. * Removed deprecated log viewer patch class and cleaned up related test fixtures. * Removed unused imports and simplified Apollo client setup. * Cleaned up test mocks and removed obsolete i18n host component tests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- - To see the specific tasks where the Asana app for GitHub is being used, see below: - https://app.asana.com/0/0/1210730229632804 --------- Co-authored-by: Pujit Mehrotra <pujit@lime-technology.com> Co-authored-by: Zack Spear <zackspear@users.noreply.github.com>
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(rg:*)",
|
||||
"Bash(find:*)"
|
||||
]
|
||||
},
|
||||
"enableAllProjectMcpServers": false
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
1750864232307
|
||||
1751630630443
|
||||
@@ -1 +1 @@
|
||||
1750864231987
|
||||
1751630630198
|
||||
@@ -1 +1 @@
|
||||
1750864232160
|
||||
1751630630343
|
||||
@@ -1 +1 @@
|
||||
1750864232467
|
||||
1751630630571
|
||||
@@ -1 +1 @@
|
||||
1750864333264
|
||||
1751630630810
|
||||
@@ -706,6 +706,7 @@ $.ajaxPrefilter(function(s, orig, xhr){
|
||||
<?include "$docroot/plugins/dynamix.my.servers/include/myservers1.php"?>
|
||||
</head>
|
||||
<body>
|
||||
<unraid-modals></unraid-modals>
|
||||
<div id="displaybox">
|
||||
<div class="upgrade_notice" style="display:none"></div>
|
||||
<div id="header" class="<?=$display['banner']?>">
|
||||
|
||||
@@ -72,6 +72,9 @@ if (is_localhost() && !is_good_session()) {
|
||||
);
|
||||
}
|
||||
|
||||
private addModalsWebComponent(source: string): string {
|
||||
return source.replace('<body>', '<body>\n<unraid-modals></unraid-modals>');
|
||||
}
|
||||
private applyToSource(fileContent: string): string {
|
||||
const transformers = [
|
||||
this.removeNotificationBell.bind(this),
|
||||
@@ -79,6 +82,7 @@ if (is_localhost() && !is_good_session()) {
|
||||
this.addToaster.bind(this),
|
||||
this.patchGuiBootAuth.bind(this),
|
||||
this.hideHeaderLogo.bind(this),
|
||||
this.addModalsWebComponent.bind(this),
|
||||
];
|
||||
|
||||
return transformers.reduce((content, transformer) => transformer(content), fileContent);
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { readFile, rm, writeFile } from 'node:fs/promises';
|
||||
|
||||
import { fileExists } from '@app/core/utils/files/file-exists.js';
|
||||
import {
|
||||
FileModification,
|
||||
ShouldApplyWithReason,
|
||||
} from '@app/unraid-api/unraid-file-modifier/file-modification.js';
|
||||
|
||||
export default class LogViewerModification extends FileModification {
|
||||
id: string = 'log-viewer';
|
||||
public readonly filePath: string =
|
||||
'/usr/local/emhttp/plugins/dynamix.my.servers/LogViewer.page' as const;
|
||||
|
||||
private readonly logViewerConfig: string = `
|
||||
Menu="UNRAID-OS"
|
||||
Title="Log Viewer (new)"
|
||||
Icon="icon-log"
|
||||
Tag="list"
|
||||
---
|
||||
<unraid-i18n-host>
|
||||
<unraid-log-viewer></unraid-log-viewer>
|
||||
</unraid-i18n-host>
|
||||
|
||||
`.trimStart();
|
||||
|
||||
constructor(logger: Logger) {
|
||||
super(logger);
|
||||
}
|
||||
|
||||
protected async generatePatch(overridePath?: string): Promise<string> {
|
||||
const currentContent = (await fileExists(this.filePath))
|
||||
? await readFile(this.filePath, 'utf8')
|
||||
: '';
|
||||
|
||||
return this.createPatchWithDiff(
|
||||
overridePath ?? this.filePath,
|
||||
currentContent,
|
||||
this.logViewerConfig
|
||||
);
|
||||
}
|
||||
|
||||
async shouldApply(): Promise<ShouldApplyWithReason> {
|
||||
if (await this.isUnraidVersionGreaterThanOrEqualTo('7.2.0')) {
|
||||
return {
|
||||
shouldApply: false,
|
||||
reason: 'Skipping for Unraid 7.2 or later, where the Unraid API is integrated.',
|
||||
};
|
||||
}
|
||||
const alreadyConfigured = await fileExists(this.filePath);
|
||||
if (alreadyConfigured) {
|
||||
return { shouldApply: false, reason: 'LogViewer configuration already exists' };
|
||||
}
|
||||
return { shouldApply: true, reason: 'No LogViewer config for the API configured yet' };
|
||||
}
|
||||
|
||||
async apply(): Promise<string> {
|
||||
await this.rollback();
|
||||
await writeFile(this.filePath, this.logViewerConfig, { mode: 0o644 });
|
||||
return this.logViewerConfig;
|
||||
}
|
||||
|
||||
async rollback(): Promise<void> {
|
||||
await rm(this.getPathToAppliedPatch(), { force: true });
|
||||
await rm(this.filePath, { force: true });
|
||||
}
|
||||
}
|
||||
@@ -53,8 +53,13 @@ Index: /usr/local/emhttp/plugins/dynamix/include/DefaultPageLayout.php
|
||||
}
|
||||
|
||||
function closeNotifier() {
|
||||
@@ -699,11 +708,11 @@
|
||||
@@ -695,15 +704,16 @@
|
||||
});
|
||||
</script>
|
||||
<?include "$docroot/plugins/dynamix.my.servers/include/myservers1.php"?>
|
||||
</head>
|
||||
<body>
|
||||
+<unraid-modals></unraid-modals>
|
||||
<div id="displaybox">
|
||||
<div class="upgrade_notice" style="display:none"></div>
|
||||
<div id="header" class="<?=$display['banner']?>">
|
||||
@@ -66,7 +71,7 @@ Index: /usr/local/emhttp/plugins/dynamix/include/DefaultPageLayout.php
|
||||
<?include "$docroot/plugins/dynamix.my.servers/include/myservers2.php"?>
|
||||
</div>
|
||||
<a href="#" class="move_to_end" title="<?=_('Move To End')?>"><i class="fa fa-arrow-circle-down"></i></a>
|
||||
@@ -748,12 +757,12 @@
|
||||
@@ -748,12 +758,12 @@
|
||||
}
|
||||
// create list of nchan scripts to be started
|
||||
if (isset($button['Nchan'])) nchan_merge($button['root'], $button['Nchan']);
|
||||
@@ -80,7 +85,7 @@ Index: /usr/local/emhttp/plugins/dynamix/include/DefaultPageLayout.php
|
||||
foreach ($buttons as $button) {
|
||||
annotate($button['file']);
|
||||
// include page specific stylesheets (if existing)
|
||||
@@ -960,26 +969,18 @@
|
||||
@@ -960,26 +970,18 @@
|
||||
case 'warning': bell2++; break;
|
||||
case 'normal' : bell3++; break;
|
||||
}
|
||||
@@ -112,7 +117,7 @@ Index: /usr/local/emhttp/plugins/dynamix/include/DefaultPageLayout.php
|
||||
});
|
||||
|
||||
<?if ($wlan0):?>
|
||||
@@ -1363,7 +1364,8 @@
|
||||
@@ -1363,7 +1365,8 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,4 @@ Title="API Keys"
|
||||
Icon="icon-u-key"
|
||||
Tag="key"
|
||||
---
|
||||
<unraid-i18n-host>
|
||||
<unraid-api-key-manager />
|
||||
</unraid-i18n-host>
|
||||
<unraid-api-key-manager />
|
||||
|
||||
@@ -577,5 +577,5 @@ _(GraphQL API Developer Sandbox)_:
|
||||
</div>
|
||||
|
||||
<!-- start unraid-api section -->
|
||||
<unraid-i18n-host><unraid-connect-settings></unraid-connect-settings></unraid-i18n-host>
|
||||
<unraid-connect-settings></unraid-connect-settings>
|
||||
<!-- end unraid-api section -->
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
Menu="UNRAID-OS"
|
||||
Title="Log Viewer (new)"
|
||||
Icon="icon-log"
|
||||
Tag="list"
|
||||
---
|
||||
<unraid-log-viewer></unraid-log-viewer>
|
||||
@@ -18,6 +18,4 @@ require_once "$docroot/plugins/dynamix/include/ReplaceKey.php";
|
||||
$replaceKey = new ReplaceKey();
|
||||
$replaceKey->check(true);
|
||||
?>
|
||||
<unraid-i18n-host>
|
||||
<unraid-registration></unraid-registration>
|
||||
</unraid-i18n-host>
|
||||
<unraid-registration></unraid-registration>
|
||||
|
||||
@@ -17,20 +17,5 @@ $wCTranslations = new WebComponentTranslations();
|
||||
?>
|
||||
<script>
|
||||
window.LOCALE_DATA = '<?= $wCTranslations->getTranslationsJson(true) ?>';
|
||||
/**
|
||||
* So we're not needing to modify DefaultLayout with an additional include, we'll add the Modals web component to the bottom of the body.
|
||||
*/
|
||||
const i18nHostWebComponent = 'unraid-i18n-host';
|
||||
const modalsWebComponent = 'unraid-modals';
|
||||
if (!document.getElementsByTagName(modalsWebComponent).length) {
|
||||
const $body = document.getElementsByTagName('body')[0];
|
||||
const $i18nHost = document.createElement(i18nHostWebComponent);
|
||||
const $modals = document.createElement(modalsWebComponent);
|
||||
$body.appendChild($i18nHost);
|
||||
$i18nHost.appendChild($modals);
|
||||
}
|
||||
</script>
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-user-profile server="<?= $serverState->getServerStateJsonForHtmlAttr() ?>"></unraid-user-profile>
|
||||
</unraid-i18n-host>
|
||||
<unraid-user-profile server="<?= $serverState->getServerStateJsonForHtmlAttr() ?>"></unraid-user-profile>
|
||||
|
||||
@@ -17,6 +17,4 @@ $wcExtractor = new WebComponentsExtractor();
|
||||
echo $wcExtractor->getScriptTagHtml();
|
||||
?>
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-sso-button ssoenabled="<?= $serverState->ssoEnabled ? "true" : "false" ?>"></unraid-sso-button>
|
||||
</unraid-i18n-host>
|
||||
<unraid-sso-button ssoenabled="<?= $serverState->ssoEnabled ? "true" : "false" ?>"></unraid-sso-button>
|
||||
@@ -5,6 +5,7 @@ class WebComponentsExtractor
|
||||
{
|
||||
private const PREFIXED_PATH = '/plugins/dynamix.my.servers/unraid-components/';
|
||||
private const RICH_COMPONENTS_ENTRY = 'unraid-components.client.mjs';
|
||||
private const RICH_COMPONENTS_ENTRY_JS = 'unraid-components.client.js';
|
||||
private const UI_ENTRY = 'src/register.ts';
|
||||
private const UI_STYLES_ENTRY = 'style.css';
|
||||
|
||||
@@ -47,7 +48,16 @@ class WebComponentsExtractor
|
||||
$subfolder = $this->getRelativePath($manifestPath);
|
||||
|
||||
foreach ($manifest as $key => $value) {
|
||||
if (strpos($key, self::RICH_COMPONENTS_ENTRY) !== false && isset($value["file"])) {
|
||||
// Skip timestamp entries
|
||||
if ($key === 'ts' || !is_array($value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for both old format (direct key match) and new format (path-based key)
|
||||
$matchesMjs = strpos($key, self::RICH_COMPONENTS_ENTRY) !== false;
|
||||
$matchesJs = strpos($key, self::RICH_COMPONENTS_ENTRY_JS) !== false;
|
||||
|
||||
if (($matchesMjs || $matchesJs) && isset($value["file"])) {
|
||||
return ($subfolder ? $subfolder . '/' : '') . $value["file"];
|
||||
}
|
||||
}
|
||||
@@ -59,7 +69,7 @@ class WebComponentsExtractor
|
||||
{
|
||||
$jsFile = $this->getRichComponentsFile();
|
||||
if (empty($jsFile)) {
|
||||
return '<script>console.error("%cNo matching key containing \'' . self::RICH_COMPONENTS_ENTRY . '\' found.", "font-weight: bold; color: white; background-color: red");</script>';
|
||||
return '<script>console.error("%cNo matching key containing \'' . self::RICH_COMPONENTS_ENTRY . '\' or \'' . self::RICH_COMPONENTS_ENTRY_JS . '\' found.", "font-weight: bold; color: white; background-color: red");</script>';
|
||||
}
|
||||
return '<script src="' . $this->getAssetPath($jsFile) . '"></script>';
|
||||
}
|
||||
|
||||
@@ -14,7 +14,5 @@ $wcExtractor = new WebComponentsExtractor();
|
||||
echo $wcExtractor->getScriptTagHtml();
|
||||
?>
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-welcome-modal></unraid-welcome-modal>
|
||||
</unraid-i18n-host>
|
||||
<unraid-welcome-modal></unraid-welcome-modal>
|
||||
|
||||
|
||||
@@ -146,9 +146,7 @@ function confirmDowngrade() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-downgrade-os
|
||||
<unraid-downgrade-os
|
||||
reboot-version="<?= $rebootDetails->rebootVersion ?>"
|
||||
restore-version="<?= $rebootDetails->previousVersion ?>"
|
||||
restore-release-date="<?= $rebootDetails->previousReleaseDate ?>"></unraid-downgrade-os>
|
||||
</unraid-i18n-host>
|
||||
|
||||
@@ -49,6 +49,4 @@ function flashBackup() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<unraid-i18n-host>
|
||||
<unraid-update-os reboot-version="<?= $rebootDetails->rebootVersion ?>"></unraid-update-os>
|
||||
</unraid-i18n-host>
|
||||
<unraid-update-os reboot-version="<?= $rebootDetails->rebootVersion ?>"></unraid-update-os>
|
||||
|
||||
333
pnpm-lock.yaml
generated
333
pnpm-lock.yaml
generated
@@ -432,7 +432,7 @@ importers:
|
||||
version: 9.29.0(jiti@2.4.2)
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.31.0
|
||||
version: 2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.29.0(jiti@2.4.2))
|
||||
version: 2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.29.0(jiti@2.4.2))
|
||||
eslint-plugin-n:
|
||||
specifier: ^17.0.0
|
||||
version: 17.20.0(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
@@ -922,7 +922,7 @@ importers:
|
||||
version: 10.1.5(eslint@9.29.0(jiti@2.4.2))
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.31.0
|
||||
version: 2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.29.0(jiti@2.4.2))
|
||||
version: 2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.29.0(jiti@2.4.2))
|
||||
eslint-plugin-no-relative-import-paths:
|
||||
specifier: ^1.6.1
|
||||
version: 1.6.1
|
||||
@@ -1098,6 +1098,9 @@ importers:
|
||||
vue-i18n:
|
||||
specifier: ^11.0.0
|
||||
version: 11.1.6(vue@3.5.17(typescript@5.8.3))
|
||||
vue-web-component-wrapper:
|
||||
specifier: ^1.7.7
|
||||
version: 1.7.7
|
||||
vuetify:
|
||||
specifier: ^3.7.14
|
||||
version: 3.8.10(typescript@5.8.3)(vite-plugin-vuetify@2.1.0)(vue@3.5.17(typescript@5.8.3))
|
||||
@@ -1156,6 +1159,9 @@ importers:
|
||||
'@types/semver':
|
||||
specifier: ^7.5.8
|
||||
version: 7.7.0
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^8.34.1
|
||||
version: 8.34.1(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
'@unraid/tailwind-rem-to-rem':
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0(tailwindcss@3.4.17(ts-node@10.9.2(@swc/core@1.12.4)(@types/node@22.15.32)(typescript@5.8.3)))
|
||||
@@ -1183,6 +1189,12 @@ importers:
|
||||
eslint-config-prettier:
|
||||
specifier: ^10.0.0
|
||||
version: 10.1.5(eslint@9.29.0(jiti@2.4.2))
|
||||
eslint-import-resolver-typescript:
|
||||
specifier: ^4.4.4
|
||||
version: 4.4.4(eslint-plugin-import-x@4.15.2(@typescript-eslint/utils@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.29.0(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.29.0(jiti@2.4.2))
|
||||
eslint-plugin-import:
|
||||
specifier: ^2.31.0
|
||||
version: 2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.29.0(jiti@2.4.2))
|
||||
happy-dom:
|
||||
specifier: ^18.0.0
|
||||
version: 18.0.0
|
||||
@@ -1193,8 +1205,8 @@ importers:
|
||||
specifier: ^3.14.1592
|
||||
version: 3.17.5(@parcel/watcher@2.5.1)(@types/node@22.15.32)(db0@0.3.2)(eslint@9.29.0(jiti@2.4.2))(ioredis@5.6.1)(magicast@0.3.5)(meow@13.2.0)(optionator@0.9.4)(rollup@4.44.0)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.3)(typescript@5.8.3)(vite@6.3.5(@types/node@22.15.32)(jiti@2.4.2)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))(vue-tsc@2.2.10(typescript@5.8.3))(xml2js@0.6.2)(yaml@2.8.0)
|
||||
nuxt-custom-elements:
|
||||
specifier: 2.0.0-beta.18
|
||||
version: 2.0.0-beta.18(webpack@5.98.0(@swc/core@1.12.4)(esbuild@0.23.1))
|
||||
specifier: 2.0.0-beta.32
|
||||
version: 2.0.0-beta.32(webpack@5.99.9(@swc/core@1.12.4)(esbuild@0.23.1))
|
||||
prettier:
|
||||
specifier: 3.5.3
|
||||
version: 3.5.3
|
||||
@@ -1216,6 +1228,9 @@ importers:
|
||||
typescript:
|
||||
specifier: ^5.7.3
|
||||
version: 5.8.3
|
||||
vite:
|
||||
specifier: ^6.3.5
|
||||
version: 6.3.5(@types/node@22.15.32)(jiti@2.4.2)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)
|
||||
vite-plugin-remove-console:
|
||||
specifier: ^2.2.0
|
||||
version: 2.2.0
|
||||
@@ -3117,9 +3132,15 @@ packages:
|
||||
'@jridgewell/sourcemap-codec@1.5.0':
|
||||
resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.4':
|
||||
resolution: {integrity: sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.29':
|
||||
resolution: {integrity: sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==}
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.9':
|
||||
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
|
||||
|
||||
@@ -4668,6 +4689,9 @@ packages:
|
||||
'@types/node@22.15.32':
|
||||
resolution: {integrity: sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA==}
|
||||
|
||||
'@types/node@22.16.0':
|
||||
resolution: {integrity: sha512-B2egV9wALML1JCpv3VQoQ+yesQKAmNMBIAY7OteVrikcOcAkWm+dGL6qpeCktPjAv6N1JLnhbNiqS35UpFyBsQ==}
|
||||
|
||||
'@types/normalize-package-data@2.4.4':
|
||||
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
|
||||
|
||||
@@ -5873,6 +5897,11 @@ packages:
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
browserslist@4.25.1:
|
||||
resolution: {integrity: sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==}
|
||||
engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
|
||||
hasBin: true
|
||||
|
||||
bser@2.1.1:
|
||||
resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==}
|
||||
|
||||
@@ -6030,6 +6059,9 @@ packages:
|
||||
caniuse-lite@1.0.30001724:
|
||||
resolution: {integrity: sha512-WqJo7p0TbHDOythNTqYujmaJTvtYRZrjpP8TCvH6Vb9CYJerJNKamKzIWOM4BkQatWj9H2lYulpdAQNBe7QhNA==}
|
||||
|
||||
caniuse-lite@1.0.30001727:
|
||||
resolution: {integrity: sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q==}
|
||||
|
||||
capital-case@1.0.4:
|
||||
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
|
||||
|
||||
@@ -6937,9 +6969,6 @@ packages:
|
||||
resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
defu@6.1.2:
|
||||
resolution: {integrity: sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==}
|
||||
|
||||
defu@6.1.4:
|
||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||
|
||||
@@ -7184,6 +7213,9 @@ packages:
|
||||
electron-to-chromium@1.5.171:
|
||||
resolution: {integrity: sha512-scWpzXEJEMrGJa4Y6m/tVotb0WuvNmasv3wWVzUAeCgKU0ToFOhUW6Z+xWnRQANMYGxN4ngJXIThgBJOqzVPCQ==}
|
||||
|
||||
electron-to-chromium@1.5.180:
|
||||
resolution: {integrity: sha512-ED+GEyEh3kYMwt2faNmgMB0b8O5qtATGgR4RmRsIp4T6p7B8vdMbIedYndnvZfsaXvSzegtpfqRMDNCjjiSduA==}
|
||||
|
||||
emoji-regex@10.4.0:
|
||||
resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==}
|
||||
|
||||
@@ -7217,6 +7249,10 @@ packages:
|
||||
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
enhanced-resolve@5.18.2:
|
||||
resolution: {integrity: sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
|
||||
enquirer@2.3.6:
|
||||
resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==}
|
||||
engines: {node: '>=8.6'}
|
||||
@@ -7520,6 +7556,19 @@ packages:
|
||||
eslint-import-resolver-node@0.3.9:
|
||||
resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==}
|
||||
|
||||
eslint-import-resolver-typescript@4.4.4:
|
||||
resolution: {integrity: sha512-1iM2zeBvrYmUNTj2vSC/90JTHDth+dfOfiNKkxApWRsTJYNrc8rOdxxIf5vazX+BiAXTeOT0UvWpGI/7qIWQOw==}
|
||||
engines: {node: ^16.17.0 || >=18.6.0}
|
||||
peerDependencies:
|
||||
eslint: '*'
|
||||
eslint-plugin-import: '*'
|
||||
eslint-plugin-import-x: '*'
|
||||
peerDependenciesMeta:
|
||||
eslint-plugin-import:
|
||||
optional: true
|
||||
eslint-plugin-import-x:
|
||||
optional: true
|
||||
|
||||
eslint-merge-processors@2.0.0:
|
||||
resolution: {integrity: sha512-sUuhSf3IrJdGooquEUB5TNpGNpBoQccbnaLHsb1XkBLUPPqCNivCpY05ZcpCOiV9uHwO2yxXEWVczVclzMxYlA==}
|
||||
peerDependencies:
|
||||
@@ -8559,11 +8608,17 @@ packages:
|
||||
html-sloppy-escaper@0.1.0:
|
||||
resolution: {integrity: sha512-ONSUC5HwiImkny/29ApddyM+BxpqjgTZ+pOag6y39Q5FQgJuWypPLl7cGDpPYp1RtC5+6Wi5yQld3zAXhlO3xg==}
|
||||
|
||||
html-webpack-plugin@5.5.3:
|
||||
resolution: {integrity: sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==}
|
||||
html-webpack-plugin@5.6.3:
|
||||
resolution: {integrity: sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
peerDependencies:
|
||||
'@rspack/core': 0.x || 1.x
|
||||
webpack: ^5.20.0
|
||||
peerDependenciesMeta:
|
||||
'@rspack/core':
|
||||
optional: true
|
||||
webpack:
|
||||
optional: true
|
||||
|
||||
htmlparser2@6.1.0:
|
||||
resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==}
|
||||
@@ -8821,6 +8876,9 @@ packages:
|
||||
resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==}
|
||||
engines: {node: '>=18.20'}
|
||||
|
||||
is-bun-module@2.0.0:
|
||||
resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==}
|
||||
|
||||
is-callable@1.2.7:
|
||||
resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -9868,10 +9926,6 @@ packages:
|
||||
module-details-from-path@1.0.3:
|
||||
resolution: {integrity: sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==}
|
||||
|
||||
mrmime@1.0.1:
|
||||
resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
mrmime@2.0.1:
|
||||
resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -10123,8 +10177,8 @@ packages:
|
||||
nullthrows@1.1.1:
|
||||
resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==}
|
||||
|
||||
nuxt-custom-elements@2.0.0-beta.18:
|
||||
resolution: {integrity: sha512-9FLjCgxHl9xcfQlRexX1TXk6vQC10j2zafhHXCPYC2lQ3xJ7r1sRC9r2XJy7B7tyOJCLPsEEtlD2EWXECeBzdA==}
|
||||
nuxt-custom-elements@2.0.0-beta.32:
|
||||
resolution: {integrity: sha512-uT8v+3f6N68/r0wOgcxyb2h9nxiDm8yeEQK8Ura4jr5ifMGsZebFZ272XgeNM2DH39vZ3RLeP1g3MVQQY4+nFg==}
|
||||
|
||||
nuxt@3.17.5:
|
||||
resolution: {integrity: sha512-HWTWpM1/RDcCt9DlnzrPcNvUmGqc62IhlZJvr7COSfnJq2lKYiBKIIesEaOF+57Qjw7TfLPc1DQVBNtxfKBxEw==}
|
||||
@@ -11758,8 +11812,8 @@ packages:
|
||||
resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
sirv@1.0.19:
|
||||
resolution: {integrity: sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ==}
|
||||
sirv@2.0.4:
|
||||
resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==}
|
||||
engines: {node: '>= 10'}
|
||||
|
||||
sirv@3.0.1:
|
||||
@@ -11890,6 +11944,10 @@ packages:
|
||||
resolution: {integrity: sha512-l0x1D6vhnsNUGPFVDx45eif0y6eedVC8nm5uACTrVFJFtl2mLRW17aWtVyxFCpn5t94VUPkjU8vSLwIuwwqtJQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
stable-hash-x@0.2.0:
|
||||
resolution: {integrity: sha512-o3yWv49B/o4QZk5ZcsALc6t0+eCelPc44zZsLtCQnZPDwFpDYSWcDnrv2TtMmMbQ7uKo3J0HTURCqckw23czNQ==}
|
||||
engines: {node: '>=12.0.0'}
|
||||
|
||||
stack-trace@0.0.10:
|
||||
resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==}
|
||||
|
||||
@@ -12344,10 +12402,6 @@ packages:
|
||||
toml@3.0.0:
|
||||
resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==}
|
||||
|
||||
totalist@1.1.0:
|
||||
resolution: {integrity: sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
totalist@3.0.1:
|
||||
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -13151,6 +13205,12 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=5.0.0'
|
||||
|
||||
vue-web-component-wrapper@1.6.9:
|
||||
resolution: {integrity: sha512-65Ybkjg2Y+MAMsx62AgEL2n5RCfzSvqbzJLEy6WvPalLATGEUhfT88Lbx5EYC6yzvZArfLKHq7Zl75Dg29ssNQ==}
|
||||
|
||||
vue-web-component-wrapper@1.7.7:
|
||||
resolution: {integrity: sha512-2uy6VdN8AwSzCeqc9tV4ZK2HKtgZ/NWL1rvdgOsddF1UFtszBZHKyQT9sDBUc4BpyXmP7f8tmI1rI0n/A6Qptw==}
|
||||
|
||||
vue@3.5.17:
|
||||
resolution: {integrity: sha512-LbHV3xPN9BeljML+Xctq4lbz2lVHCR6DtbpTf5XIO6gugpXUN49j2QQPcMj086r9+AkJ0FfUT8xjulKKBkkr9g==}
|
||||
peerDependencies:
|
||||
@@ -13200,8 +13260,8 @@ packages:
|
||||
resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
webpack-bundle-analyzer@4.9.0:
|
||||
resolution: {integrity: sha512-+bXGmO1LyiNx0i9enBu3H8mv42sj/BJWhZNFwjz92tVnBa9J3JMGo2an2IXlEleoDOPn/Hofl5hr/xCpObUDtw==}
|
||||
webpack-bundle-analyzer@4.10.2:
|
||||
resolution: {integrity: sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==}
|
||||
engines: {node: '>= 10.13.0'}
|
||||
hasBin: true
|
||||
|
||||
@@ -13212,8 +13272,8 @@ packages:
|
||||
webpack-virtual-modules@0.6.2:
|
||||
resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
|
||||
|
||||
webpack@5.98.0:
|
||||
resolution: {integrity: sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==}
|
||||
webpack@5.99.9:
|
||||
resolution: {integrity: sha512-brOPwM3JnmOa+7kd3NsmOUOwbDAj8FT9xDsG3IW0MgbN9yZV7Oi/s/+MNQ/EcSMqw7qfoRyXPoeEWT8zLVdVGg==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@@ -15339,7 +15399,7 @@ snapshots:
|
||||
'@graphql-tools/optimize@2.0.0(graphql@16.11.0)':
|
||||
dependencies:
|
||||
graphql: 16.11.0
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
'@graphql-tools/prisma-loader@8.0.17(@types/node@22.15.32)(crossws@0.3.5)(graphql@16.11.0)':
|
||||
dependencies:
|
||||
@@ -15385,7 +15445,7 @@ snapshots:
|
||||
'@ardatan/relay-compiler': 12.0.2(graphql@16.11.0)
|
||||
'@graphql-tools/utils': 10.8.6(graphql@16.11.0)
|
||||
graphql: 16.11.0
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
@@ -15394,7 +15454,7 @@ snapshots:
|
||||
'@ardatan/relay-compiler': 12.0.3(graphql@16.11.0)
|
||||
'@graphql-tools/utils': 10.8.6(graphql@16.11.0)
|
||||
graphql: 16.11.0
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
|
||||
@@ -15689,15 +15749,24 @@ snapshots:
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.0': {}
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.4':
|
||||
optional: true
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.25':
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.29':
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.4
|
||||
optional: true
|
||||
|
||||
'@jridgewell/trace-mapping@0.3.9':
|
||||
dependencies:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.0
|
||||
'@jridgewell/sourcemap-codec': 1.5.4
|
||||
optional: true
|
||||
|
||||
'@js-sdsl/ordered-map@4.4.2': {}
|
||||
@@ -16688,7 +16757,7 @@ snapshots:
|
||||
|
||||
'@pm2/pm2-version-check@1.0.4':
|
||||
dependencies:
|
||||
debug: 4.4.1
|
||||
debug: 4.4.0(supports-color@5.5.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -17475,11 +17544,13 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/eslint': 9.6.1
|
||||
'@types/estree': 1.0.8
|
||||
optional: true
|
||||
|
||||
'@types/eslint@9.6.1':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
'@types/json-schema': 7.0.15
|
||||
optional: true
|
||||
|
||||
'@types/estree@1.0.6': {}
|
||||
|
||||
@@ -17582,6 +17653,11 @@ snapshots:
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
|
||||
'@types/node@22.16.0':
|
||||
dependencies:
|
||||
undici-types: 6.21.0
|
||||
optional: true
|
||||
|
||||
'@types/normalize-package-data@2.4.4': {}
|
||||
|
||||
'@types/parse-path@7.0.3': {}
|
||||
@@ -18342,20 +18418,26 @@ snapshots:
|
||||
dependencies:
|
||||
'@webassemblyjs/helper-numbers': 1.13.2
|
||||
'@webassemblyjs/helper-wasm-bytecode': 1.13.2
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/floating-point-hex-parser@1.13.2': {}
|
||||
'@webassemblyjs/floating-point-hex-parser@1.13.2':
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/helper-api-error@1.13.2': {}
|
||||
'@webassemblyjs/helper-api-error@1.13.2':
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/helper-buffer@1.14.1': {}
|
||||
'@webassemblyjs/helper-buffer@1.14.1':
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/helper-numbers@1.13.2':
|
||||
dependencies:
|
||||
'@webassemblyjs/floating-point-hex-parser': 1.13.2
|
||||
'@webassemblyjs/helper-api-error': 1.13.2
|
||||
'@xtuc/long': 4.2.2
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/helper-wasm-bytecode@1.13.2': {}
|
||||
'@webassemblyjs/helper-wasm-bytecode@1.13.2':
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/helper-wasm-section@1.14.1':
|
||||
dependencies:
|
||||
@@ -18363,16 +18445,20 @@ snapshots:
|
||||
'@webassemblyjs/helper-buffer': 1.14.1
|
||||
'@webassemblyjs/helper-wasm-bytecode': 1.13.2
|
||||
'@webassemblyjs/wasm-gen': 1.14.1
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/ieee754@1.13.2':
|
||||
dependencies:
|
||||
'@xtuc/ieee754': 1.2.0
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/leb128@1.13.2':
|
||||
dependencies:
|
||||
'@xtuc/long': 4.2.2
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/utf8@1.13.2': {}
|
||||
'@webassemblyjs/utf8@1.13.2':
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/wasm-edit@1.14.1':
|
||||
dependencies:
|
||||
@@ -18384,6 +18470,7 @@ snapshots:
|
||||
'@webassemblyjs/wasm-opt': 1.14.1
|
||||
'@webassemblyjs/wasm-parser': 1.14.1
|
||||
'@webassemblyjs/wast-printer': 1.14.1
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/wasm-gen@1.14.1':
|
||||
dependencies:
|
||||
@@ -18392,6 +18479,7 @@ snapshots:
|
||||
'@webassemblyjs/ieee754': 1.13.2
|
||||
'@webassemblyjs/leb128': 1.13.2
|
||||
'@webassemblyjs/utf8': 1.13.2
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/wasm-opt@1.14.1':
|
||||
dependencies:
|
||||
@@ -18399,6 +18487,7 @@ snapshots:
|
||||
'@webassemblyjs/helper-buffer': 1.14.1
|
||||
'@webassemblyjs/wasm-gen': 1.14.1
|
||||
'@webassemblyjs/wasm-parser': 1.14.1
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/wasm-parser@1.14.1':
|
||||
dependencies:
|
||||
@@ -18408,11 +18497,13 @@ snapshots:
|
||||
'@webassemblyjs/ieee754': 1.13.2
|
||||
'@webassemblyjs/leb128': 1.13.2
|
||||
'@webassemblyjs/utf8': 1.13.2
|
||||
optional: true
|
||||
|
||||
'@webassemblyjs/wast-printer@1.14.1':
|
||||
dependencies:
|
||||
'@webassemblyjs/ast': 1.14.1
|
||||
'@xtuc/long': 4.2.2
|
||||
optional: true
|
||||
|
||||
'@whatwg-node/disposablestack@0.0.5':
|
||||
dependencies:
|
||||
@@ -18477,9 +18568,11 @@ snapshots:
|
||||
dependencies:
|
||||
tslib: 2.8.1
|
||||
|
||||
'@xtuc/ieee754@1.2.0': {}
|
||||
'@xtuc/ieee754@1.2.0':
|
||||
optional: true
|
||||
|
||||
'@xtuc/long@4.2.2': {}
|
||||
'@xtuc/long@4.2.2':
|
||||
optional: true
|
||||
|
||||
JSONStream@1.3.5:
|
||||
dependencies:
|
||||
@@ -18515,7 +18608,7 @@ snapshots:
|
||||
|
||||
acorn-walk@8.3.4:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
|
||||
acorn@7.4.1: {}
|
||||
|
||||
@@ -18544,6 +18637,7 @@ snapshots:
|
||||
dependencies:
|
||||
ajv: 8.17.1
|
||||
fast-deep-equal: 3.1.3
|
||||
optional: true
|
||||
|
||||
ajv@6.12.6:
|
||||
dependencies:
|
||||
@@ -18983,6 +19077,14 @@ snapshots:
|
||||
node-releases: 2.0.19
|
||||
update-browserslist-db: 1.1.3(browserslist@4.25.0)
|
||||
|
||||
browserslist@4.25.1:
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001727
|
||||
electron-to-chromium: 1.5.180
|
||||
node-releases: 2.0.19
|
||||
update-browserslist-db: 1.1.3(browserslist@4.25.1)
|
||||
optional: true
|
||||
|
||||
bser@2.1.1:
|
||||
dependencies:
|
||||
node-int64: 0.4.0
|
||||
@@ -19173,6 +19275,9 @@ snapshots:
|
||||
|
||||
caniuse-lite@1.0.30001724: {}
|
||||
|
||||
caniuse-lite@1.0.30001727:
|
||||
optional: true
|
||||
|
||||
capital-case@1.0.4:
|
||||
dependencies:
|
||||
no-case: 3.0.4
|
||||
@@ -19277,7 +19382,8 @@ snapshots:
|
||||
|
||||
chownr@3.0.0: {}
|
||||
|
||||
chrome-trace-event@1.0.4: {}
|
||||
chrome-trace-event@1.0.4:
|
||||
optional: true
|
||||
|
||||
ci-info@4.2.0: {}
|
||||
|
||||
@@ -20172,8 +20278,6 @@ snapshots:
|
||||
has-property-descriptors: 1.0.2
|
||||
object-keys: 1.1.1
|
||||
|
||||
defu@6.1.2: {}
|
||||
|
||||
defu@6.1.4: {}
|
||||
|
||||
degenerator@5.0.1:
|
||||
@@ -20416,6 +20520,9 @@ snapshots:
|
||||
|
||||
electron-to-chromium@1.5.171: {}
|
||||
|
||||
electron-to-chromium@1.5.180:
|
||||
optional: true
|
||||
|
||||
emoji-regex@10.4.0: {}
|
||||
|
||||
emoji-regex@7.0.3: {}
|
||||
@@ -20443,6 +20550,12 @@ snapshots:
|
||||
graceful-fs: 4.2.11
|
||||
tapable: 2.2.1
|
||||
|
||||
enhanced-resolve@5.18.2:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
tapable: 2.2.2
|
||||
optional: true
|
||||
|
||||
enquirer@2.3.6:
|
||||
dependencies:
|
||||
ansi-colors: 4.1.3
|
||||
@@ -20831,17 +20944,34 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-import-resolver-typescript@4.4.4(eslint-plugin-import-x@4.15.2(@typescript-eslint/utils@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.29.0(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.29.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
debug: 4.4.1
|
||||
eslint: 9.29.0(jiti@2.4.2)
|
||||
eslint-import-context: 0.1.8(unrs-resolver@1.9.1)
|
||||
get-tsconfig: 4.10.1
|
||||
is-bun-module: 2.0.0
|
||||
stable-hash-x: 0.2.0
|
||||
tinyglobby: 0.2.14
|
||||
unrs-resolver: 1.9.1
|
||||
optionalDependencies:
|
||||
eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.29.0(jiti@2.4.2))
|
||||
eslint-plugin-import-x: 4.15.2(@typescript-eslint/utils@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.29.0(jiti@2.4.2))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-merge-processors@2.0.0(eslint@9.29.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
eslint: 9.29.0(jiti@2.4.2)
|
||||
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.29.0(jiti@2.4.2)):
|
||||
eslint-module-utils@2.12.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.29.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
debug: 3.2.7
|
||||
optionalDependencies:
|
||||
'@typescript-eslint/parser': 8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3)
|
||||
eslint: 9.29.0(jiti@2.4.2)
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-import-resolver-typescript: 4.4.4(eslint-plugin-import-x@4.15.2(@typescript-eslint/utils@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.29.0(jiti@2.4.2)))(eslint-plugin-import@2.31.0)(eslint@9.29.0(jiti@2.4.2))
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -20870,7 +21000,7 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint@9.29.0(jiti@2.4.2)):
|
||||
eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-typescript@4.4.4)(eslint@9.29.0(jiti@2.4.2)):
|
||||
dependencies:
|
||||
'@rtsao/scc': 1.1.0
|
||||
array-includes: 3.1.8
|
||||
@@ -20881,7 +21011,7 @@ snapshots:
|
||||
doctrine: 2.1.0
|
||||
eslint: 9.29.0(jiti@2.4.2)
|
||||
eslint-import-resolver-node: 0.3.9
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.29.0(jiti@2.4.2))
|
||||
eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@2.4.2))(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@4.4.4)(eslint@9.29.0(jiti@2.4.2))
|
||||
hasown: 2.0.2
|
||||
is-core-module: 2.16.1
|
||||
is-glob: 4.0.3
|
||||
@@ -20996,6 +21126,7 @@ snapshots:
|
||||
dependencies:
|
||||
esrecurse: 4.3.0
|
||||
estraverse: 4.3.0
|
||||
optional: true
|
||||
|
||||
eslint-scope@8.4.0:
|
||||
dependencies:
|
||||
@@ -21079,7 +21210,8 @@ snapshots:
|
||||
dependencies:
|
||||
estraverse: 5.3.0
|
||||
|
||||
estraverse@4.3.0: {}
|
||||
estraverse@4.3.0:
|
||||
optional: true
|
||||
|
||||
estraverse@5.3.0: {}
|
||||
|
||||
@@ -21772,7 +21904,8 @@ snapshots:
|
||||
dependencies:
|
||||
is-glob: 4.0.3
|
||||
|
||||
glob-to-regexp@0.4.1: {}
|
||||
glob-to-regexp@0.4.1:
|
||||
optional: true
|
||||
|
||||
glob@10.4.5:
|
||||
dependencies:
|
||||
@@ -22120,14 +22253,15 @@ snapshots:
|
||||
dependencies:
|
||||
html-escaper: 3.0.3
|
||||
|
||||
html-webpack-plugin@5.5.3(webpack@5.98.0(@swc/core@1.12.4)(esbuild@0.23.1)):
|
||||
html-webpack-plugin@5.6.3(webpack@5.99.9(@swc/core@1.12.4)(esbuild@0.23.1)):
|
||||
dependencies:
|
||||
'@types/html-minifier-terser': 6.1.0
|
||||
html-minifier-terser: 6.1.0
|
||||
lodash: 4.17.21
|
||||
pretty-error: 4.0.0
|
||||
tapable: 2.2.1
|
||||
webpack: 5.98.0(@swc/core@1.12.4)(esbuild@0.23.1)
|
||||
optionalDependencies:
|
||||
webpack: 5.99.9(@swc/core@1.12.4)(esbuild@0.23.1)
|
||||
|
||||
htmlparser2@6.1.0:
|
||||
dependencies:
|
||||
@@ -22461,6 +22595,10 @@ snapshots:
|
||||
dependencies:
|
||||
builtin-modules: 5.0.0
|
||||
|
||||
is-bun-module@2.0.0:
|
||||
dependencies:
|
||||
semver: 7.7.2
|
||||
|
||||
is-callable@1.2.7: {}
|
||||
|
||||
is-core-module@2.16.1:
|
||||
@@ -22529,7 +22667,7 @@ snapshots:
|
||||
|
||||
is-lower-case@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
is-map@2.0.3: {}
|
||||
|
||||
@@ -22626,7 +22764,7 @@ snapshots:
|
||||
|
||||
is-upper-case@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
is-url-superb@4.0.0: {}
|
||||
|
||||
@@ -22722,9 +22860,10 @@ snapshots:
|
||||
|
||||
jest-worker@27.5.1:
|
||||
dependencies:
|
||||
'@types/node': 22.15.32
|
||||
'@types/node': 22.16.0
|
||||
merge-stream: 2.0.0
|
||||
supports-color: 8.1.1
|
||||
optional: true
|
||||
|
||||
jiti@1.21.7: {}
|
||||
|
||||
@@ -23065,7 +23204,8 @@ snapshots:
|
||||
|
||||
load-tsconfig@0.2.5: {}
|
||||
|
||||
loader-runner@4.3.0: {}
|
||||
loader-runner@4.3.0:
|
||||
optional: true
|
||||
|
||||
local-pkg@0.5.1:
|
||||
dependencies:
|
||||
@@ -23191,11 +23331,11 @@ snapshots:
|
||||
|
||||
lower-case-first@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
lower-case@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
lowercase-keys@3.0.0: {}
|
||||
|
||||
@@ -23450,8 +23590,6 @@ snapshots:
|
||||
|
||||
module-details-from-path@1.0.3: {}
|
||||
|
||||
mrmime@1.0.1: {}
|
||||
|
||||
mrmime@2.0.1: {}
|
||||
|
||||
ms@2.0.0: {}
|
||||
@@ -23776,14 +23914,17 @@ snapshots:
|
||||
|
||||
nullthrows@1.1.1: {}
|
||||
|
||||
nuxt-custom-elements@2.0.0-beta.18(webpack@5.98.0(@swc/core@1.12.4)(esbuild@0.23.1)):
|
||||
nuxt-custom-elements@2.0.0-beta.32(webpack@5.99.9(@swc/core@1.12.4)(esbuild@0.23.1)):
|
||||
dependencies:
|
||||
change-case: 4.1.2
|
||||
change-case: 5.4.4
|
||||
clone: 2.1.2
|
||||
defu: 6.1.2
|
||||
html-webpack-plugin: 5.5.3(webpack@5.98.0(@swc/core@1.12.4)(esbuild@0.23.1))
|
||||
webpack-bundle-analyzer: 4.9.0
|
||||
defu: 6.1.4
|
||||
html-webpack-plugin: 5.6.3(webpack@5.99.9(@swc/core@1.12.4)(esbuild@0.23.1))
|
||||
lodash-es: 4.17.21
|
||||
vue-web-component-wrapper: 1.6.9
|
||||
webpack-bundle-analyzer: 4.10.2
|
||||
transitivePeerDependencies:
|
||||
- '@rspack/core'
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
- webpack
|
||||
@@ -25551,6 +25692,7 @@ snapshots:
|
||||
ajv: 8.17.1
|
||||
ajv-formats: 2.1.1(ajv@8.17.1)
|
||||
ajv-keywords: 5.1.0(ajv@8.17.1)
|
||||
optional: true
|
||||
|
||||
scslre@0.3.0:
|
||||
dependencies:
|
||||
@@ -25796,11 +25938,11 @@ snapshots:
|
||||
dependencies:
|
||||
semver: 7.7.2
|
||||
|
||||
sirv@1.0.19:
|
||||
sirv@2.0.4:
|
||||
dependencies:
|
||||
'@polka/url': 1.0.0-next.28
|
||||
mrmime: 1.0.1
|
||||
totalist: 1.1.0
|
||||
mrmime: 2.0.1
|
||||
totalist: 3.0.1
|
||||
|
||||
sirv@3.0.1:
|
||||
dependencies:
|
||||
@@ -25913,7 +26055,7 @@ snapshots:
|
||||
|
||||
sponge-case@1.0.1:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
sprintf-js@1.0.3: {}
|
||||
|
||||
@@ -25943,6 +26085,8 @@ snapshots:
|
||||
|
||||
stable-hash-x@0.1.1: {}
|
||||
|
||||
stable-hash-x@0.2.0: {}
|
||||
|
||||
stack-trace@0.0.10: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
@@ -26188,7 +26332,7 @@ snapshots:
|
||||
|
||||
swap-case@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
symbol-observable@1.2.0: {}
|
||||
|
||||
@@ -26271,7 +26415,8 @@ snapshots:
|
||||
|
||||
tapable@2.2.1: {}
|
||||
|
||||
tapable@2.2.2: {}
|
||||
tapable@2.2.2:
|
||||
optional: true
|
||||
|
||||
tar-fs@2.1.2:
|
||||
dependencies:
|
||||
@@ -26312,17 +26457,18 @@ snapshots:
|
||||
mkdirp: 3.0.1
|
||||
yallist: 5.0.0
|
||||
|
||||
terser-webpack-plugin@5.3.14(@swc/core@1.12.4)(esbuild@0.23.1)(webpack@5.98.0(@swc/core@1.12.4)(esbuild@0.23.1)):
|
||||
terser-webpack-plugin@5.3.14(@swc/core@1.12.4)(esbuild@0.23.1)(webpack@5.99.9(@swc/core@1.12.4)(esbuild@0.23.1)):
|
||||
dependencies:
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
'@jridgewell/trace-mapping': 0.3.29
|
||||
jest-worker: 27.5.1
|
||||
schema-utils: 4.3.2
|
||||
serialize-javascript: 6.0.2
|
||||
terser: 5.43.1
|
||||
webpack: 5.98.0(@swc/core@1.12.4)(esbuild@0.23.1)
|
||||
webpack: 5.99.9(@swc/core@1.12.4)(esbuild@0.23.1)
|
||||
optionalDependencies:
|
||||
'@swc/core': 1.12.4
|
||||
esbuild: 0.23.1
|
||||
optional: true
|
||||
|
||||
terser@5.43.1:
|
||||
dependencies:
|
||||
@@ -26402,7 +26548,7 @@ snapshots:
|
||||
|
||||
title-case@3.0.3:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
tldts-core@6.1.86: {}
|
||||
|
||||
@@ -26437,8 +26583,6 @@ snapshots:
|
||||
|
||||
toml@3.0.0: {}
|
||||
|
||||
totalist@1.1.0: {}
|
||||
|
||||
totalist@3.0.1: {}
|
||||
|
||||
touch@3.1.1: {}
|
||||
@@ -26676,7 +26820,7 @@ snapshots:
|
||||
|
||||
unctx@2.4.1:
|
||||
dependencies:
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
estree-walker: 3.0.3
|
||||
magic-string: 0.30.17
|
||||
unplugin: 2.3.5
|
||||
@@ -26888,13 +27032,20 @@ snapshots:
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.1
|
||||
|
||||
update-browserslist-db@1.1.3(browserslist@4.25.1):
|
||||
dependencies:
|
||||
browserslist: 4.25.1
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.1
|
||||
optional: true
|
||||
|
||||
upper-case-first@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
upper-case@2.0.2:
|
||||
dependencies:
|
||||
tslib: 2.6.3
|
||||
tslib: 2.8.1
|
||||
|
||||
uqr@0.1.2: {}
|
||||
|
||||
@@ -27350,6 +27501,10 @@ snapshots:
|
||||
'@vue/language-core': 2.2.10(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
|
||||
vue-web-component-wrapper@1.6.9: {}
|
||||
|
||||
vue-web-component-wrapper@1.7.7: {}
|
||||
|
||||
vue@3.5.17(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@vue/compiler-dom': 3.5.17
|
||||
@@ -27396,6 +27551,7 @@ snapshots:
|
||||
dependencies:
|
||||
glob-to-regexp: 0.4.1
|
||||
graceful-fs: 4.2.11
|
||||
optional: true
|
||||
|
||||
wcwidth@1.0.1:
|
||||
dependencies:
|
||||
@@ -27407,37 +27563,41 @@ snapshots:
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
|
||||
webpack-bundle-analyzer@4.9.0:
|
||||
webpack-bundle-analyzer@4.10.2:
|
||||
dependencies:
|
||||
'@discoveryjs/json-ext': 0.5.7
|
||||
acorn: 8.14.1
|
||||
acorn: 8.15.0
|
||||
acorn-walk: 8.3.4
|
||||
chalk: 4.1.2
|
||||
commander: 7.2.0
|
||||
debounce: 1.2.1
|
||||
escape-string-regexp: 4.0.0
|
||||
gzip-size: 6.0.0
|
||||
lodash: 4.17.21
|
||||
html-escaper: 2.0.2
|
||||
opener: 1.5.2
|
||||
sirv: 1.0.19
|
||||
picocolors: 1.1.1
|
||||
sirv: 2.0.4
|
||||
ws: 7.5.10
|
||||
transitivePeerDependencies:
|
||||
- bufferutil
|
||||
- utf-8-validate
|
||||
|
||||
webpack-sources@3.3.3: {}
|
||||
webpack-sources@3.3.3:
|
||||
optional: true
|
||||
|
||||
webpack-virtual-modules@0.6.2: {}
|
||||
|
||||
webpack@5.98.0(@swc/core@1.12.4)(esbuild@0.23.1):
|
||||
webpack@5.99.9(@swc/core@1.12.4)(esbuild@0.23.1):
|
||||
dependencies:
|
||||
'@types/eslint-scope': 3.7.7
|
||||
'@types/estree': 1.0.8
|
||||
'@types/json-schema': 7.0.15
|
||||
'@webassemblyjs/ast': 1.14.1
|
||||
'@webassemblyjs/wasm-edit': 1.14.1
|
||||
'@webassemblyjs/wasm-parser': 1.14.1
|
||||
acorn: 8.15.0
|
||||
browserslist: 4.25.0
|
||||
browserslist: 4.25.1
|
||||
chrome-trace-event: 1.0.4
|
||||
enhanced-resolve: 5.18.1
|
||||
enhanced-resolve: 5.18.2
|
||||
es-module-lexer: 1.7.0
|
||||
eslint-scope: 5.1.1
|
||||
events: 3.3.0
|
||||
@@ -27449,13 +27609,14 @@ snapshots:
|
||||
neo-async: 2.6.2
|
||||
schema-utils: 4.3.2
|
||||
tapable: 2.2.2
|
||||
terser-webpack-plugin: 5.3.14(@swc/core@1.12.4)(esbuild@0.23.1)(webpack@5.98.0(@swc/core@1.12.4)(esbuild@0.23.1))
|
||||
terser-webpack-plugin: 5.3.14(@swc/core@1.12.4)(esbuild@0.23.1)(webpack@5.99.9(@swc/core@1.12.4)(esbuild@0.23.1))
|
||||
watchpack: 2.4.4
|
||||
webpack-sources: 3.3.3
|
||||
transitivePeerDependencies:
|
||||
- '@swc/core'
|
||||
- esbuild
|
||||
- uglify-js
|
||||
optional: true
|
||||
|
||||
whatwg-encoding@2.0.0:
|
||||
dependencies:
|
||||
|
||||
@@ -78,15 +78,13 @@ const commonLanguageOptions = {
|
||||
|
||||
// Define globals separately
|
||||
const commonGlobals = {
|
||||
browser: true,
|
||||
window: true,
|
||||
document: true,
|
||||
console: true,
|
||||
Event: true,
|
||||
HTMLElement: true,
|
||||
HTMLInputElement: true,
|
||||
CustomEvent: true,
|
||||
es2022: true,
|
||||
window: 'readonly',
|
||||
document: 'readonly',
|
||||
console: 'readonly',
|
||||
Event: 'readonly',
|
||||
HTMLElement: 'readonly',
|
||||
HTMLInputElement: 'readonly',
|
||||
CustomEvent: 'readonly',
|
||||
};
|
||||
|
||||
export default [
|
||||
|
||||
@@ -13,7 +13,7 @@ import { computed } from 'vue';
|
||||
|
||||
type SelectValueType = string | number;
|
||||
|
||||
type AcceptableValue = SelectValueType | SelectValueType[] | Record<string, unknown> | null;
|
||||
type AcceptableValue = SelectValueType | SelectValueType[] | Record<string, unknown> | bigint | null;
|
||||
|
||||
interface SelectItemInterface {
|
||||
label: string;
|
||||
@@ -89,7 +89,13 @@ function getItemValue(item: SelectItemType): SelectValueType | null {
|
||||
if (isStructuredItem(item)) {
|
||||
const value = props.valueKey in item ? item[props.valueKey] : item.value;
|
||||
|
||||
return typeof value === 'string' || typeof value === 'number' ? value : null;
|
||||
if (typeof value === 'string' || typeof value === 'number') {
|
||||
return value;
|
||||
} else if (typeof value === 'bigint') {
|
||||
return String(value);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (isLabelItem(item) || isSeparatorItem(item)) return null;
|
||||
@@ -174,8 +180,6 @@ function handleUpdateModelValue(value: AcceptableValue) {
|
||||
</SelectTrigger>
|
||||
|
||||
<SelectContent>
|
||||
<slot name="content-top" />
|
||||
|
||||
<SelectGroup v-for="{ groupIndex, items } in groupedOrderedItems" :key="groupIndex">
|
||||
<template v-for="{ item, index, type } in items" :key="index">
|
||||
<SelectLabel v-if="type === 'label'">
|
||||
@@ -196,7 +200,6 @@ function handleUpdateModelValue(value: AcceptableValue) {
|
||||
</SelectItem>
|
||||
</template>
|
||||
</SelectGroup>
|
||||
<slot name="content-bottom" />
|
||||
</SelectContent>
|
||||
</SelectRoot>
|
||||
</template>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { onMounted, ref } from 'vue';
|
||||
const useTeleport = () => {
|
||||
const teleportTarget = ref<string | HTMLElement>('#modals');
|
||||
|
||||
const determineTeleportTarget = () => {
|
||||
const determineTeleportTarget = (): HTMLElement | undefined => {
|
||||
const myModalsComponent =
|
||||
document.querySelector('unraid-modals') || document.querySelector('uui-modals');
|
||||
if (!myModalsComponent?.shadowRoot) return;
|
||||
@@ -12,6 +12,7 @@ const useTeleport = () => {
|
||||
if (!potentialTarget) return;
|
||||
|
||||
teleportTarget.value = potentialTarget as HTMLElement;
|
||||
return teleportTarget.value;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from '@/components/ui/select';
|
||||
import useTeleport from '@/composables/useTeleport';
|
||||
import type { ControlElement } from '@jsonforms/core';
|
||||
import { useJsonFormsControl } from '@jsonforms/vue';
|
||||
import type { RendererProps } from '@jsonforms/vue';
|
||||
@@ -32,12 +31,6 @@ const options = computed(() => {
|
||||
const onChange = (value: unknown) => {
|
||||
handleChange(control.value.path, String(value));
|
||||
};
|
||||
|
||||
// Without this, the select dropdown will not be visible, unless it's already in a teleported context.
|
||||
const { teleportTarget, determineTeleportTarget } = useTeleport();
|
||||
const onSelectOpen = () => {
|
||||
determineTeleportTarget();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -46,14 +39,13 @@ const onSelectOpen = () => {
|
||||
:disabled="!control.enabled"
|
||||
:required="control.required"
|
||||
@update:model-value="onChange"
|
||||
@update:open="onSelectOpen"
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue v-if="selected">{{ selected }}</SelectValue>
|
||||
<span v-else>{{ control.schema.default ?? 'Select an option' }}</span>
|
||||
</SelectTrigger>
|
||||
|
||||
<SelectContent :to="teleportTarget">
|
||||
<SelectContent>
|
||||
<template v-for="option in options" :key="option.value">
|
||||
<TooltipProvider v-if="option.tooltip" :delay-duration="50">
|
||||
<Tooltip>
|
||||
@@ -62,7 +54,7 @@ const onSelectOpen = () => {
|
||||
<SelectItemText>{{ option.label }}</SelectItemText>
|
||||
</SelectItem>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent :to="teleportTarget" side="right" :side-offset="5">
|
||||
<TooltipContent side="right" :side-offset="5">
|
||||
<p class="max-w-xs">{{ option.tooltip }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
@@ -46,6 +46,15 @@ vi.mock('~/store/activationCode', () => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('~/components/Activation/store/activationCodeData', () => ({
|
||||
useActivationCodeDataStore: () => ({
|
||||
loading: ref(false),
|
||||
activationCode: ref(null),
|
||||
isFreshInstall: ref(false),
|
||||
partnerInfo: ref(null),
|
||||
}),
|
||||
}));
|
||||
|
||||
describe('Auth Component', () => {
|
||||
let serverStore: ReturnType<typeof useServerStore>;
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import { nextTick } from 'vue';
|
||||
import { setActivePinia } from 'pinia';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
import { Badge } from '@unraid/ui';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
@@ -26,6 +25,22 @@ vi.mock('@unraid/shared-callbacks', () => ({
|
||||
useCallback: vi.fn(() => ({ send: vi.fn(), watcher: vi.fn() })),
|
||||
}));
|
||||
|
||||
vi.mock('@vue/apollo-composable', () => ({
|
||||
useQuery: () => ({
|
||||
result: { value: {} },
|
||||
loading: { value: false },
|
||||
}),
|
||||
useLazyQuery: () => ({
|
||||
result: { value: {} },
|
||||
loading: { value: false },
|
||||
load: vi.fn(),
|
||||
refetch: vi.fn(),
|
||||
onResult: vi.fn(),
|
||||
onError: vi.fn(),
|
||||
}),
|
||||
provideApolloClient: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('~/helpers/urls', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('~/helpers/urls')>();
|
||||
const mockReleaseNotesUrl = 'http://mock.release.notes/v';
|
||||
@@ -66,14 +81,6 @@ vi.mock('vue-i18n', () => ({
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('@unraid/ui', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@unraid/ui')>();
|
||||
return {
|
||||
...actual,
|
||||
Badge: actual.Badge,
|
||||
};
|
||||
});
|
||||
|
||||
describe('HeaderOsVersion', () => {
|
||||
let wrapper: VueWrapper<unknown>;
|
||||
let testingPinia: TestingPinia;
|
||||
@@ -102,7 +109,6 @@ describe('HeaderOsVersion', () => {
|
||||
wrapper = mount(HeaderOsVersion, {
|
||||
global: {
|
||||
plugins: [testingPinia],
|
||||
components: { Badge },
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -112,16 +118,13 @@ describe('HeaderOsVersion', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('renders OS version badge with correct link and no update status initially', () => {
|
||||
const versionBadgeLink = wrapper.find('a[title*="release notes"]');
|
||||
it('renders OS version link with correct URL and no update status initially', () => {
|
||||
const versionLink = wrapper.find('a[title*="release notes"]');
|
||||
|
||||
expect(versionBadgeLink.exists()).toBe(true);
|
||||
expect(versionBadgeLink.attributes('href')).toBe(`${testMockReleaseNotesUrl}6.12.0`);
|
||||
expect(versionLink.exists()).toBe(true);
|
||||
expect(versionLink.attributes('href')).toBe(`${testMockReleaseNotesUrl}6.12.0`);
|
||||
|
||||
const badge = versionBadgeLink.findComponent(Badge);
|
||||
|
||||
expect(badge.exists()).toBe(true);
|
||||
expect(badge.text()).toContain('6.12.0');
|
||||
expect(versionLink.text()).toContain('6.12.0');
|
||||
expect(findUpdateStatusComponent()).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
/**
|
||||
* I18nHost Component Test Coverage
|
||||
*/
|
||||
|
||||
import { defineComponent, inject } from 'vue';
|
||||
import { I18nInjectionKey } from 'vue-i18n';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
import _en_US from '~/locales/en_US.json';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import type { VueWrapper } from '@vue/test-utils';
|
||||
import type { Composer, I18n } from 'vue-i18n';
|
||||
|
||||
import I18nHost from '~/components/I18nHost.ce.vue';
|
||||
|
||||
const en_US: Record<string, string> = _en_US;
|
||||
|
||||
vi.mock('~/helpers/i18n-utils', () => ({
|
||||
createHtmlEntityDecoder: vi.fn(() => (text: string) => text),
|
||||
}));
|
||||
|
||||
const TestConsumerComponent = defineComponent({
|
||||
template: '<div>{{ i18n?.global.locale.value }}</div>',
|
||||
|
||||
setup() {
|
||||
const i18n = inject(I18nInjectionKey);
|
||||
return { i18n };
|
||||
},
|
||||
});
|
||||
|
||||
describe('I18nHost', () => {
|
||||
let wrapper: VueWrapper<unknown>;
|
||||
const originalWindowLocaleData = (window as unknown as { LOCALE_DATA?: string }).LOCALE_DATA;
|
||||
|
||||
beforeEach(() => {
|
||||
delete (window as unknown as { LOCALE_DATA?: string }).LOCALE_DATA;
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper?.unmount();
|
||||
|
||||
if (originalWindowLocaleData !== undefined) {
|
||||
(window as unknown as { LOCALE_DATA?: string }).LOCALE_DATA = originalWindowLocaleData;
|
||||
} else {
|
||||
delete (window as unknown as { LOCALE_DATA?: string }).LOCALE_DATA;
|
||||
}
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('provides i18n instance with default locale when no window data exists', () => {
|
||||
wrapper = mount(I18nHost, {
|
||||
slots: {
|
||||
default: TestConsumerComponent,
|
||||
},
|
||||
});
|
||||
|
||||
const consumerWrapper = wrapper.findComponent(TestConsumerComponent);
|
||||
const providedI18n = consumerWrapper.vm.i18n as I18n<{
|
||||
message: typeof en_US;
|
||||
}>;
|
||||
|
||||
expect(providedI18n).toBeDefined();
|
||||
expect((providedI18n.global as Composer).locale.value).toBe('en_US');
|
||||
expect((providedI18n.global as Composer).fallbackLocale.value).toBe('en_US');
|
||||
|
||||
const messages = (providedI18n.global as Composer).messages.value as {
|
||||
en_US?: Record<string, string>;
|
||||
ja?: Record<string, string>;
|
||||
};
|
||||
|
||||
expect(messages.en_US?.['My Servers']).toBe(en_US['My Servers']);
|
||||
});
|
||||
|
||||
it('parses and provides i18n instance with locale from window.LOCALE_DATA', () => {
|
||||
const mockJaMessages = { 'test-key': 'テストキー' };
|
||||
const localeData = { ja: mockJaMessages };
|
||||
(window as unknown as { LOCALE_DATA?: string }).LOCALE_DATA = encodeURIComponent(
|
||||
JSON.stringify(localeData)
|
||||
);
|
||||
|
||||
wrapper = mount(I18nHost, {
|
||||
slots: {
|
||||
default: TestConsumerComponent,
|
||||
},
|
||||
});
|
||||
|
||||
const consumerWrapper = wrapper.findComponent(TestConsumerComponent);
|
||||
const providedI18n = consumerWrapper.vm.i18n as I18n<{
|
||||
message: typeof en_US;
|
||||
}>;
|
||||
const messages = (providedI18n.global as Composer).messages.value as {
|
||||
en_US?: Record<string, string>;
|
||||
ja?: Record<string, string>;
|
||||
};
|
||||
|
||||
expect(providedI18n).toBeDefined();
|
||||
expect((providedI18n.global as Composer).locale.value).toBe('ja');
|
||||
expect((providedI18n.global as Composer).fallbackLocale.value).toBe('en_US');
|
||||
expect(messages.ja?.['test-key']).toBe(mockJaMessages['test-key']);
|
||||
expect(messages.en_US?.['My Servers']).toBe(en_US['My Servers']);
|
||||
});
|
||||
|
||||
it('handles invalid JSON in window.LOCALE_DATA gracefully', () => {
|
||||
(window as unknown as { LOCALE_DATA?: string }).LOCALE_DATA = 'invalid JSON string{%';
|
||||
const errorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
|
||||
wrapper = mount(I18nHost, {
|
||||
slots: {
|
||||
default: TestConsumerComponent,
|
||||
},
|
||||
});
|
||||
|
||||
const consumerWrapper = wrapper.findComponent(TestConsumerComponent);
|
||||
const providedI18n = consumerWrapper.vm.i18n as I18n<{
|
||||
message: typeof en_US;
|
||||
}>;
|
||||
const messages = (providedI18n.global as Composer).messages.value as {
|
||||
en_US?: Record<string, string>;
|
||||
ja?: Record<string, string>;
|
||||
};
|
||||
|
||||
expect(providedI18n).toBeDefined();
|
||||
expect((providedI18n.global as Composer).locale.value).toBe('en_US');
|
||||
expect((providedI18n.global as Composer).fallbackLocale.value).toBe('en_US');
|
||||
expect(errorSpy).toHaveBeenCalledOnce();
|
||||
expect(errorSpy).toHaveBeenCalledWith('[I18nHost] error parsing messages', expect.any(Error));
|
||||
expect(messages.en_US?.['My Servers']).toBe(en_US['My Servers']);
|
||||
|
||||
errorSpy.mockRestore();
|
||||
});
|
||||
});
|
||||
@@ -28,6 +28,22 @@ vi.mock('@unraid/shared-callbacks', () => ({
|
||||
})),
|
||||
}));
|
||||
|
||||
vi.mock('@vue/apollo-composable', () => ({
|
||||
useQuery: () => ({
|
||||
result: { value: {} },
|
||||
loading: { value: false },
|
||||
}),
|
||||
useLazyQuery: () => ({
|
||||
result: { value: {} },
|
||||
loading: { value: false },
|
||||
load: vi.fn(),
|
||||
refetch: vi.fn(),
|
||||
onResult: vi.fn(),
|
||||
onError: vi.fn(),
|
||||
}),
|
||||
provideApolloClient: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('@unraid/ui', async (importOriginal) => {
|
||||
const actual = await importOriginal<typeof import('@unraid/ui')>();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import type { VueWrapper } from '@vue/test-utils';
|
||||
import type { Server, ServerconnectPluginInstalled, ServerState } from '~/types/server';
|
||||
import type { Pinia } from 'pinia';
|
||||
import type { MaybeRef } from '@vueuse/core';
|
||||
|
||||
import UserProfile from '~/components/UserProfile.ce.vue';
|
||||
import { useServerStore } from '~/store/server';
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
const { registerEntry } = useCustomElements();
|
||||
onBeforeMount(() => {
|
||||
registerEntry('UnraidComponents');
|
||||
});
|
||||
import { NuxtLayout, NuxtPage } from '#components';
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -14,6 +14,9 @@ import { useActivationCodeModalStore } from '~/components/Activation/store/activ
|
||||
import { usePurchaseStore } from '~/store/purchase';
|
||||
import { useThemeStore } from '~/store/theme';
|
||||
|
||||
import Modal from '~/components/Modal.vue';
|
||||
import ActivationSteps from './ActivationSteps.vue';
|
||||
|
||||
export interface Props {
|
||||
t: ComposerTranslation;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { computed } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useQuery } from '@vue/apollo-composable';
|
||||
|
||||
import {
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
} from '~/components/Activation/graphql/activationCode.query';
|
||||
import { RegistrationState } from '~/composables/gql/graphql';
|
||||
|
||||
setActivePinia(createPinia()); /** required in web component context */
|
||||
// Uses the shared global Pinia instance
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export const useActivationCodeDataStore = defineStore('activationCodeData', () => {
|
||||
const { result: activationCodeResult, loading: activationCodeLoading } = useQuery(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { computed, onMounted, onUnmounted } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia, storeToRefs } from 'pinia';
|
||||
import { defineStore, storeToRefs } from 'pinia';
|
||||
import { useSessionStorage } from '@vueuse/core';
|
||||
|
||||
import { ACTIVATION_CODE_MODAL_HIDDEN_STORAGE_KEY } from '~/consts';
|
||||
@@ -7,7 +7,8 @@ import { ACTIVATION_CODE_MODAL_HIDDEN_STORAGE_KEY } from '~/consts';
|
||||
import { useActivationCodeDataStore } from '~/components/Activation/store/activationCodeData';
|
||||
import { useCallbackActionsStore } from '~/store/callbackActions';
|
||||
|
||||
setActivePinia(createPinia()); /** required in web component context */
|
||||
// Uses the shared global Pinia instance
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export const useActivationCodeModalStore = defineStore('activationCodeModal', () => {
|
||||
const isHidden = useSessionStorage<boolean | null>(ACTIVATION_CODE_MODAL_HIDDEN_STORAGE_KEY, null);
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
import ApiKeyManager from '~/components/ApiKey/ApiKeyManager.vue';
|
||||
</script>
|
||||
<template>
|
||||
<ApiKeyManager />
|
||||
<div>
|
||||
<ApiKeyManager />
|
||||
</div>
|
||||
</template>
|
||||
<style lang="postcss">
|
||||
/* Import unraid-ui globals first */
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useServerStore } from '~/store/server';
|
||||
|
||||
import BrandMark from '~/components/Brand/Mark.vue';
|
||||
|
||||
export interface Props {
|
||||
gradientStart?: string;
|
||||
gradientStop?: string;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeMount } from 'vue';
|
||||
import { useCallbackActionsStore } from '~/store/callbackActions';
|
||||
|
||||
const callbackStore = useCallbackActionsStore();
|
||||
@@ -9,7 +10,9 @@ onBeforeMount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot />
|
||||
<div>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
|
||||
// const { t } = useI18n();
|
||||
|
||||
import { ref, computed, watch } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { watchDebounced } from '@vueuse/core';
|
||||
import { useMutation, useQuery } from '@vue/apollo-composable';
|
||||
|
||||
import { BrandButton, jsonFormsRenderers, Label } from '@unraid/ui';
|
||||
@@ -104,12 +107,12 @@ const onChange = ({ data }: { data: Record<string, unknown> }) => {
|
||||
>
|
||||
<template v-if="connectPluginInstalled">
|
||||
<Label>Account Status:</Label>
|
||||
<div v-html="'<unraid-i18n-host><unraid-auth></unraid-auth></unraid-i18n-host>'"></div>
|
||||
<div v-html="'<unraid-auth></unraid-auth>'"></div>
|
||||
</template>
|
||||
<Label>Download Unraid API Logs:</Label>
|
||||
<div
|
||||
v-html="
|
||||
'<unraid-i18n-host><unraid-download-api-logs></unraid-download-api-logs></unraid-i18n-host>'
|
||||
'<unraid-download-api-logs></unraid-download-api-logs>'
|
||||
"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
Button,
|
||||
} from '@unraid/ui';
|
||||
|
||||
import DummyServerSwitcher from '~/components/DummyServerSwitcher.vue';
|
||||
|
||||
import { CogIcon } from '@heroicons/vue/24/solid';
|
||||
</script>
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ import { storeToRefs } from 'pinia';
|
||||
import { PageContainer } from '@unraid/ui';
|
||||
|
||||
import { useServerStore } from '~/store/server';
|
||||
import UpdateOsStatus from '~/components/UpdateOs/Status.vue';
|
||||
import UpdateOsDowngrade from '~/components/UpdateOs/Downgrade.vue';
|
||||
import UpdateOsThirdPartyDrivers from '~/components/UpdateOs/ThirdPartyDrivers.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -55,22 +58,24 @@ onBeforeMount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<UpdateOsStatus
|
||||
:title="t('Downgrade Unraid OS')"
|
||||
:subtitle="subtitle"
|
||||
:downgrade-not-available="restoreVersion === '' && rebootType === ''"
|
||||
:show-external-downgrade="showExternalDowngrade"
|
||||
:t="t"
|
||||
/>
|
||||
<UpdateOsDowngrade
|
||||
v-if="restoreVersion && rebootType === ''"
|
||||
:release-date="restoreReleaseDate"
|
||||
:version="restoreVersion"
|
||||
:t="t"
|
||||
/>
|
||||
<UpdateOsThirdPartyDrivers v-if="rebootType === 'thirdPartyDriversDownloading'" :t="t" />
|
||||
</PageContainer>
|
||||
<div>
|
||||
<PageContainer>
|
||||
<UpdateOsStatus
|
||||
:title="t('Downgrade Unraid OS')"
|
||||
:subtitle="subtitle"
|
||||
:downgrade-not-available="restoreVersion === '' && rebootType === ''"
|
||||
:show-external-downgrade="showExternalDowngrade"
|
||||
:t="t"
|
||||
/>
|
||||
<UpdateOsDowngrade
|
||||
v-if="restoreVersion && rebootType === ''"
|
||||
:release-date="restoreReleaseDate"
|
||||
:version="restoreVersion"
|
||||
:t="t"
|
||||
/>
|
||||
<UpdateOsThirdPartyDrivers v-if="rebootType === 'thirdPartyDriversDownloading'" :t="t" />
|
||||
</PageContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
|
||||
@@ -78,7 +78,7 @@ const updateOsStatus = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col gap-y-2">
|
||||
<a
|
||||
:href="unraidLogoHeaderLink.href"
|
||||
:title="unraidLogoHeaderLink.title"
|
||||
@@ -88,28 +88,21 @@ const updateOsStatus = computed(() => {
|
||||
>
|
||||
<img
|
||||
:src="'/webGui/images/UN-logotype-gradient.svg'"
|
||||
class="w-[160px] h-auto max-h-[30px] ml-[10px] mt-[25px] mb-[8px] object-contain"
|
||||
class="w-[160px] h-auto max-h-[30px] object-contain"
|
||||
alt="Unraid Logo"
|
||||
/>
|
||||
</a>
|
||||
|
||||
<div class="flex flex-row justify-start gap-x-4px">
|
||||
<div class="flex flex-wrap justify-start gap-2">
|
||||
<a
|
||||
class="group leading-none"
|
||||
class="text-xs xs:text-sm flex flex-row items-center gap-x-1 font-semibold text-header-text-secondary hover:text-orange-dark focus:text-orange-dark hover:underline focus:underline leading-none"
|
||||
:title="t('View release notes')"
|
||||
:href="getReleaseNotesUrl(osVersion).toString()"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<Badge
|
||||
variant="custom"
|
||||
:icon="InformationCircleIcon"
|
||||
icon-styles="text-header-text-secondary"
|
||||
size="sm"
|
||||
class="text-header-text-secondary group-hover:text-orange-dark group-focus:text-orange-dark group-hover:underline group-focus:underline"
|
||||
>
|
||||
{{ osVersion }}
|
||||
</Badge>
|
||||
<InformationCircleIcon class="fill-current w-3 h-3 xs:w-4 xs:h-4 flex-shrink-0" />
|
||||
{{ osVersion }}
|
||||
</a>
|
||||
<component
|
||||
:is="updateOsStatus.href ? 'a' : 'button'"
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
<script lang="ts" setup>
|
||||
import en_US from '~/locales/en_US.json';
|
||||
import { provide } from 'vue';
|
||||
import { createI18n, I18nInjectionKey } from 'vue-i18n';
|
||||
import { createHtmlEntityDecoder } from '~/helpers/i18n-utils';
|
||||
|
||||
// import ja from '~/locales/ja.json';
|
||||
|
||||
const defaultLocale = 'en_US'; // ja, en_US
|
||||
let parsedLocale = '';
|
||||
let parsedMessages = {};
|
||||
let nonDefaultLocale = false;
|
||||
/**
|
||||
* In myservers2.php, we have a script tag that sets window.LOCALE_DATA to a stringified JSON object.
|
||||
* Unfortunately, this was the only way I could get the data from PHP to vue-i18n :(
|
||||
* I tried using i18n.setLocaleMessage() but it didn't work no matter what I tried.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const windowLocaleData = (window as any).LOCALE_DATA || null;
|
||||
if (windowLocaleData) {
|
||||
try {
|
||||
parsedMessages = JSON.parse(decodeURIComponent(windowLocaleData));
|
||||
parsedLocale = Object.keys(parsedMessages)[0];
|
||||
nonDefaultLocale = parsedLocale !== defaultLocale;
|
||||
} catch (error) {
|
||||
console.error('[I18nHost] error parsing messages', error);
|
||||
}
|
||||
}
|
||||
|
||||
const i18n = createI18n<false>({
|
||||
legacy: false, // must set to `false`
|
||||
locale: nonDefaultLocale ? parsedLocale : defaultLocale,
|
||||
fallbackLocale: defaultLocale,
|
||||
messages: {
|
||||
en_US,
|
||||
// ja,
|
||||
...(nonDefaultLocale ? parsedMessages : {}),
|
||||
},
|
||||
/** safely decodes html-encoded symbols like & and ' */
|
||||
postTranslation: createHtmlEntityDecoder(),
|
||||
});
|
||||
|
||||
provide(I18nInjectionKey, i18n);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<slot />
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/* unraid-i18n-host {
|
||||
font-size: 16px;
|
||||
} */
|
||||
</style>
|
||||
@@ -6,17 +6,19 @@ import {
|
||||
Input,
|
||||
Label,
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
Switch,
|
||||
useTeleport,
|
||||
} from '@unraid/ui';
|
||||
|
||||
import { GET_LOG_FILES } from './log.query';
|
||||
import SingleLogViewer from './SingleLogViewer.vue';
|
||||
|
||||
// Types
|
||||
interface LogFile {
|
||||
path: string;
|
||||
name: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
// Component state
|
||||
const selectedLogFile = ref<string>('');
|
||||
const lineCount = ref<number>(100);
|
||||
@@ -48,6 +50,14 @@ const logFiles = computed(() => {
|
||||
return logFilesResult.value?.logFiles || [];
|
||||
});
|
||||
|
||||
// Transform log files for the Select component
|
||||
const logFileOptions = computed(() => {
|
||||
return logFiles.value.map((file: LogFile) => ({
|
||||
value: file.path,
|
||||
label: `${file.name} (${formatFileSize(file.size)})`
|
||||
}));
|
||||
});
|
||||
|
||||
// Format file size for display
|
||||
const formatFileSize = (bytes: number): string => {
|
||||
if (bytes === 0) return '0 Bytes';
|
||||
@@ -92,13 +102,6 @@ watch(selectedLogFile, (newValue) => {
|
||||
highlightLanguage.value = autoDetectLanguage(newValue);
|
||||
}
|
||||
});
|
||||
|
||||
// Without this, the select dropdown will not be visible, unless it's already in a teleported context.
|
||||
const { teleportTarget, determineTeleportTarget } = useTeleport();
|
||||
const onSelectOpen = () => {
|
||||
determineTeleportTarget();
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -111,16 +114,12 @@ const onSelectOpen = () => {
|
||||
<div class="flex flex-wrap gap-4 items-end">
|
||||
<div class="flex-1 min-w-[200px]">
|
||||
<Label for="log-file-select">Log File</Label>
|
||||
<Select v-model="selectedLogFile" @update:open="onSelectOpen">
|
||||
<SelectTrigger class="w-full">
|
||||
<SelectValue placeholder="Select a log file" />
|
||||
</SelectTrigger>
|
||||
<SelectContent :to="teleportTarget">
|
||||
<SelectItem v-for="file in logFiles" :key="file.path" :value="file.path">
|
||||
{{ file.name }} ({{ formatFileSize(file.size) }})
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select
|
||||
v-model="selectedLogFile"
|
||||
:items="logFileOptions"
|
||||
placeholder="Select a log file"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@@ -137,16 +136,12 @@ const onSelectOpen = () => {
|
||||
|
||||
<div>
|
||||
<Label for="highlight-language">Syntax</Label>
|
||||
<Select v-model="highlightLanguage" @update:open="onSelectOpen">
|
||||
<SelectTrigger id="highlight-language" class="w-full">
|
||||
<SelectValue placeholder="Select language" />
|
||||
</SelectTrigger>
|
||||
<SelectContent :to="teleportTarget">
|
||||
<SelectItem v-for="lang in highlightLanguages" :key="lang.value" :value="lang.value">
|
||||
{{ lang.label }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<Select
|
||||
v-model="highlightLanguage"
|
||||
:items="highlightLanguages"
|
||||
placeholder="Select language"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
|
||||
@@ -7,6 +7,11 @@ import { useTrialStore } from '~/store/trial';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
import { useApiKeyStore } from '~/store/apiKey';
|
||||
import ApiKeyCreate from '~/components/ApiKey/ApiKeyCreate.vue';
|
||||
import UpcCallbackFeedback from '~/components/UserProfile/CallbackFeedback.vue';
|
||||
import UpcTrial from '~/components/UserProfile/Trial.vue';
|
||||
import UpdateOsCheckUpdateResponseModal from '~/components/UpdateOs/CheckUpdateResponseModal.vue';
|
||||
import UpdateOsChangelogModal from '~/components/UpdateOs/ChangelogModal.vue';
|
||||
import ActivationModal from '~/components/Activation/ActivationModal.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, type Component } from 'vue';
|
||||
import { BellIcon, ExclamationTriangleIcon, ShieldExclamationIcon } from '@heroicons/vue/24/solid';
|
||||
import { cn } from '@unraid/ui';
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, type Component } from 'vue';
|
||||
import { computedAsync } from '@vueuse/core';
|
||||
import { Markdown } from '@/helpers/markdown';
|
||||
import {
|
||||
ArchiveBoxIcon,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, watch } from 'vue';
|
||||
import { useQuery } from '@vue/apollo-composable';
|
||||
import { vInfiniteScroll } from '@vueuse/components';
|
||||
|
||||
@@ -12,6 +13,8 @@ import { useFragment } from '~/composables/gql/fragment-masking';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
import { getNotifications, NOTIFICATION_FRAGMENT } from './graphql/notification.query';
|
||||
|
||||
import NotificationsItem from './Item.vue';
|
||||
|
||||
/**
|
||||
* Page size is the max amount of items fetched from the api in a single request.
|
||||
*/
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { useMutation, useQuery, useSubscription } from '@vue/apollo-composable';
|
||||
|
||||
import {
|
||||
@@ -29,11 +30,12 @@ import {
|
||||
notificationAddedSubscription,
|
||||
notificationOverviewSubscription,
|
||||
} from './graphql/notification.subscription';
|
||||
import NotificationsIndicator from './Indicator.vue';
|
||||
import NotificationsList from './List.vue';
|
||||
|
||||
const { mutate: archiveAll, loading: loadingArchiveAll } = useMutation(archiveAllNotifications);
|
||||
const { mutate: deleteArchives, loading: loadingDeleteAll } = useMutation(deleteArchivedNotifications);
|
||||
const { mutate: recalculateOverview } = useMutation(resetOverview);
|
||||
const { determineTeleportTarget } = useTeleport();
|
||||
const importance = ref<Importance | undefined>(undefined);
|
||||
|
||||
const filterItems = [
|
||||
@@ -117,13 +119,12 @@ const readArchivedCount = computed(() => {
|
||||
});
|
||||
|
||||
const prepareToViewNotifications = () => {
|
||||
determineTeleportTarget();
|
||||
void recalculateOverview();
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Sheet :modal="false">
|
||||
<Sheet>
|
||||
<SheetTrigger @click="prepareToViewNotifications">
|
||||
<span class="sr-only">Notifications</span>
|
||||
<NotificationsIndicator :overview="overview" :seen="haveSeenNotifications" />
|
||||
@@ -187,7 +188,7 @@ const prepareToViewNotifications = () => {
|
||||
importance = strVal === 'all' || !strVal ? undefined : (strVal as Importance);
|
||||
}
|
||||
"
|
||||
/>
|
||||
></Select>
|
||||
</div>
|
||||
|
||||
<TabsContent value="unread" class="flex-col flex-1 min-h-0">
|
||||
|
||||
@@ -30,6 +30,7 @@ import RegistrationKeyLinkedStatus from '~/components/Registration/KeyLinkedStat
|
||||
import RegistrationReplaceCheck from '~/components/Registration/ReplaceCheck.vue';
|
||||
import RegistrationUpdateExpirationAction from '~/components/Registration/UpdateExpirationAction.vue';
|
||||
import UserProfileUptimeExpire from '~/components/UserProfile/UptimeExpire.vue';
|
||||
import RegistrationItem from '~/components/Registration/Item.vue';
|
||||
import useDateTimeHelper from '~/composables/dateTime';
|
||||
import { useReplaceRenewStore } from '~/store/replaceRenew';
|
||||
import { useServerStore } from '~/store/server';
|
||||
@@ -269,57 +270,59 @@ const items = computed((): RegistrationItemProps[] => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer class="max-w-800px">
|
||||
<CardWrapper :increased-padding="true">
|
||||
<div class="flex flex-col gap-20px sm:gap-24px">
|
||||
<header class="flex flex-col gap-y-16px">
|
||||
<h3
|
||||
class="text-20px md:text-24px font-semibold leading-normal flex flex-row items-center gap-8px"
|
||||
:class="serverErrors.length ? 'text-unraid-red' : 'text-green-500'"
|
||||
>
|
||||
<component :is="headingIcon" class="w-24px h-24px" />
|
||||
<span>
|
||||
{{ heading }}
|
||||
</span>
|
||||
</h3>
|
||||
<div
|
||||
v-if="subheading"
|
||||
class="prose text-16px leading-relaxed whitespace-normal opacity-75"
|
||||
v-html="subheading"
|
||||
/>
|
||||
<span v-if="authAction" class="grow-0">
|
||||
<BrandButton
|
||||
:disabled="authAction?.disabled"
|
||||
:icon="authAction.icon"
|
||||
:text="t(authAction.text)"
|
||||
:title="authAction.title ? t(authAction.title) : undefined"
|
||||
@click="authAction.click?.()"
|
||||
<div>
|
||||
<PageContainer class="max-w-800px">
|
||||
<CardWrapper :increased-padding="true">
|
||||
<div class="flex flex-col gap-20px sm:gap-24px">
|
||||
<header class="flex flex-col gap-y-16px">
|
||||
<h3
|
||||
class="text-20px md:text-24px font-semibold leading-normal flex flex-row items-center gap-8px"
|
||||
:class="serverErrors.length ? 'text-unraid-red' : 'text-green-500'"
|
||||
>
|
||||
<component :is="headingIcon" class="w-24px h-24px" />
|
||||
<span>
|
||||
{{ heading }}
|
||||
</span>
|
||||
</h3>
|
||||
<div
|
||||
v-if="subheading"
|
||||
class="prose text-16px leading-relaxed whitespace-normal opacity-75"
|
||||
v-html="subheading"
|
||||
/>
|
||||
</span>
|
||||
</header>
|
||||
<dl>
|
||||
<RegistrationItem
|
||||
v-for="item in items"
|
||||
:key="item.label"
|
||||
:component="item?.component"
|
||||
:component-props="item?.componentProps"
|
||||
:error="item.error ?? false"
|
||||
:warning="item.warning ?? false"
|
||||
:label="item.label"
|
||||
:text="item.text"
|
||||
>
|
||||
<template v-if="item.component" #right>
|
||||
<component
|
||||
:is="item.component"
|
||||
v-bind="item.componentProps"
|
||||
:class="[item.componentOpacity && !item.error ? 'opacity-75' : '']"
|
||||
<span v-if="authAction" class="grow-0">
|
||||
<BrandButton
|
||||
:disabled="authAction?.disabled"
|
||||
:icon="authAction.icon"
|
||||
:text="t(authAction.text)"
|
||||
:title="authAction.title ? t(authAction.title) : undefined"
|
||||
@click="authAction.click?.()"
|
||||
/>
|
||||
</template>
|
||||
</RegistrationItem>
|
||||
</dl>
|
||||
</div>
|
||||
</CardWrapper>
|
||||
</PageContainer>
|
||||
</span>
|
||||
</header>
|
||||
<dl>
|
||||
<RegistrationItem
|
||||
v-for="item in items"
|
||||
:key="item.label"
|
||||
:component="item?.component"
|
||||
:component-props="item?.componentProps"
|
||||
:error="item.error ?? false"
|
||||
:warning="item.warning ?? false"
|
||||
:label="item.label"
|
||||
:text="item.text"
|
||||
>
|
||||
<template v-if="item.component" #right>
|
||||
<component
|
||||
:is="item.component"
|
||||
v-bind="item.componentProps"
|
||||
:class="[item.componentOpacity && !item.error ? 'opacity-75' : '']"
|
||||
/>
|
||||
</template>
|
||||
</RegistrationItem>
|
||||
</dl>
|
||||
</div>
|
||||
</CardWrapper>
|
||||
</PageContainer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { ShieldExclamationIcon } from '@heroicons/vue/24/solid';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { ArrowPathIcon, ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/solid';
|
||||
@@ -10,6 +11,7 @@ import type { ComposerTranslation } from 'vue-i18n';
|
||||
import useDateTimeHelper from '~/composables/dateTime';
|
||||
import { useReplaceRenewStore } from '~/store/replaceRenew';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import RegistrationUpdateExpiration from './UpdateExpiration.vue';
|
||||
|
||||
export interface Props {
|
||||
t: ComposerTranslation;
|
||||
|
||||
@@ -134,19 +134,21 @@ const navigateToExternalSSOUrl = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<template v-if="isSsoEnabled">
|
||||
<div class="w-full flex flex-col gap-1 my-1">
|
||||
<p v-if="currentState === 'idle' || currentState === 'error'" class="text-center">or</p>
|
||||
<p v-if="currentState === 'error'" class="text-red-500 text-center">{{ error }}</p>
|
||||
<BrandButton
|
||||
:disabled="currentState === 'loading'"
|
||||
variant="outline"
|
||||
class="rounded-none uppercase tracking-widest"
|
||||
@click="navigateToExternalSSOUrl"
|
||||
>{{ buttonText }}</BrandButton
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
<div>
|
||||
<template v-if="isSsoEnabled">
|
||||
<div class="w-full flex flex-col gap-1 my-1">
|
||||
<p v-if="currentState === 'idle' || currentState === 'error'" class="text-center">or</p>
|
||||
<p v-if="currentState === 'error'" class="text-red-500 text-center">{{ error }}</p>
|
||||
<BrandButton
|
||||
:disabled="currentState === 'loading'"
|
||||
variant="outline"
|
||||
class="rounded-none uppercase tracking-widest"
|
||||
@click="navigateToExternalSSOUrl"
|
||||
>{{ buttonText }}</BrandButton
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
|
||||
@@ -73,21 +73,23 @@ const handleThemeChange = (event: Event) => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<select
|
||||
v-if="enableThemeSwitcher"
|
||||
:disabled="submitting"
|
||||
:value="props.current"
|
||||
class="text-xs relative float-left mr-2 text-white bg-black"
|
||||
@change="handleThemeChange"
|
||||
>
|
||||
<option
|
||||
v-for="theme in computedThemes"
|
||||
:key="theme"
|
||||
:value="theme"
|
||||
<div>
|
||||
<select
|
||||
v-if="enableThemeSwitcher"
|
||||
:disabled="submitting"
|
||||
:value="props.current"
|
||||
class="text-xs relative float-left mr-2 text-white bg-black"
|
||||
@change="handleThemeChange"
|
||||
>
|
||||
{{ theme }}
|
||||
</option>
|
||||
</select>
|
||||
<option
|
||||
v-for="theme in computedThemes"
|
||||
:key="theme"
|
||||
:value="theme"
|
||||
>
|
||||
{{ theme }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
|
||||
@@ -24,6 +24,8 @@ import { WEBGUI_TOOLS_UPDATE } from '~/helpers/urls';
|
||||
|
||||
import { useAccountStore } from '~/store/account';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import UpdateOsStatus from '~/components/UpdateOs/Status.vue';
|
||||
import UpdateOsThirdPartyDrivers from '~/components/UpdateOs/ThirdPartyDrivers.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -59,17 +61,17 @@ onBeforeMount(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<PageContainer>
|
||||
<BrandLoading v-if="showLoader" class="mx-auto my-12 max-w-160px" />
|
||||
<UpdateOsStatus
|
||||
v-else
|
||||
:show-update-check="true"
|
||||
:title="t('Update Unraid OS')"
|
||||
:subtitle="subtitle"
|
||||
:t="t"
|
||||
/>
|
||||
<UpdateOsThirdPartyDrivers v-if="rebootType === 'thirdPartyDriversDownloading'" :t="t" />
|
||||
</PageContainer>
|
||||
<PageContainer>
|
||||
<BrandLoading v-if="showLoader" class="mx-auto my-12 max-w-160px" />
|
||||
<UpdateOsStatus
|
||||
v-else
|
||||
:show-update-check="true"
|
||||
:title="t('Update Unraid OS')"
|
||||
:subtitle="subtitle"
|
||||
:t="t"
|
||||
/>
|
||||
<UpdateOsThirdPartyDrivers v-if="rebootType === 'thirdPartyDriversDownloading'" :t="t" />
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
|
||||
@@ -18,6 +18,7 @@ import RawChangelogRenderer from '~/components/UpdateOs/RawChangelogRenderer.vue
|
||||
import { usePurchaseStore } from '~/store/purchase';
|
||||
import { useThemeStore } from '~/store/theme';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
import Modal from '~/components/Modal.vue';
|
||||
|
||||
export interface Props {
|
||||
open?: boolean;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, onBeforeMount, ref, watch } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import {
|
||||
@@ -20,6 +21,8 @@ import { useAccountStore } from '~/store/account';
|
||||
import { usePurchaseStore } from '~/store/purchase';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
import Modal from '~/components/Modal.vue';
|
||||
import UpdateOsIgnoredRelease from './IgnoredRelease.vue';
|
||||
|
||||
export interface Props {
|
||||
open?: boolean;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { XMarkIcon } from '@heroicons/vue/24/solid';
|
||||
import { BrandButton } from '@unraid/ui';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { h } from 'vue';
|
||||
import { computed, h } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* @todo require keyfile to update
|
||||
* @todo require valid guid / server state to update
|
||||
*/
|
||||
import { ref, watchEffect } from 'vue';
|
||||
import { computed, ref, watchEffect } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, watchEffect } from 'vue';
|
||||
import { computed, ref, watchEffect } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { ArrowTopRightOnSquareIcon, ExclamationTriangleIcon, EyeIcon } from '@heroicons/vue/24/solid';
|
||||
@@ -13,6 +13,7 @@ import useDateTimeHelper from '~/composables/dateTime';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
import { useUpdateOsActionsStore } from '~/store/updateOsActions';
|
||||
import RegistrationUpdateExpiration from '~/components/Registration/UpdateExpiration.vue';
|
||||
|
||||
const props = defineProps<{
|
||||
t: ComposerTranslation;
|
||||
|
||||
@@ -13,6 +13,13 @@ import { useCallbackActionsStore } from '~/store/callbackActions';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useThemeStore } from '~/store/theme';
|
||||
|
||||
// Auto-imported components - now manually imported
|
||||
import UpcUptimeExpire from '~/components/UserProfile/UptimeExpire.vue';
|
||||
import UpcServerState from '~/components/UserProfile/ServerState.vue';
|
||||
import NotificationsSidebar from '~/components/Notifications/Sidebar.vue';
|
||||
import UpcDropdownContent from '~/components/UserProfile/DropdownContent.vue';
|
||||
import UpcDropdownTrigger from '~/components/UserProfile/DropdownTrigger.vue';
|
||||
|
||||
export interface Props {
|
||||
server?: Server | string;
|
||||
}
|
||||
@@ -93,7 +100,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<div
|
||||
id="UserProfile"
|
||||
class="text-foreground relative z-20 flex flex-col h-full gap-y-4px pt-4px pr-16px pl-40px"
|
||||
class="text-foreground relative z-20 flex flex-col h-full gap-y-1"
|
||||
>
|
||||
<div
|
||||
v-if="bannerGradient"
|
||||
@@ -102,11 +109,11 @@ onMounted(() => {
|
||||
/>
|
||||
|
||||
<div
|
||||
class="text-xs text-header-text-secondary text-right font-semibold leading-normal relative z-10 flex flex-col items-end justify-end gap-x-4px xs:flex-row xs:items-baseline xs:gap-x-12px"
|
||||
class="text-xs text-header-text-secondary text-right font-semibold leading-normal relative z-10 flex flex-wrap items-baseline justify-end gap-x-1 xs:flex-row xs:gap-x-4"
|
||||
>
|
||||
<UpcUptimeExpire :t="t" />
|
||||
<UpcUptimeExpire :as="'span'" :t="t" class="text-12px" />
|
||||
<span class="hidden xs:block">•</span>
|
||||
<UpcServerState :t="t" />
|
||||
<UpcServerState :t="t" class="text-12px" />
|
||||
</div>
|
||||
|
||||
<div class="relative z-10 flex flex-row items-center justify-end gap-x-16px h-full">
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
// @todo ensure key installs and updateOs can be handled at the same time
|
||||
// @todo with multiple actions of key install and update after successful key install, rather than showing default success message, show a message to have them confirm the update
|
||||
import { computed, ref } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
|
||||
@@ -22,6 +23,10 @@ import { useCallbackActionsStore } from '~/store/callbackActions';
|
||||
import { useInstallKeyStore } from '~/store/installKey';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsActionsStore } from '~/store/updateOsActions';
|
||||
import Modal from '~/components/Modal.vue';
|
||||
import UpcCallbackFeedbackStatus from './CallbackFeedbackStatus.vue';
|
||||
import UpcUptimeExpire from './UptimeExpire.vue';
|
||||
import RegistrationUpdateExpiration from '~/components/Registration/UpdateExpiration.vue';
|
||||
|
||||
export interface Props {
|
||||
open?: boolean;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, h } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { CheckCircleIcon, ExclamationTriangleIcon, UserCircleIcon } from '@heroicons/vue/24/solid';
|
||||
@@ -8,6 +9,7 @@ import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
import UpcDropdownItem from './DropdownItem.vue';
|
||||
|
||||
const props = defineProps<{ t: ComposerTranslation }>();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import {
|
||||
@@ -27,6 +28,12 @@ import { useErrorsStore } from '~/store/errors';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
|
||||
import Beta from './Beta.vue';
|
||||
import DropdownConnectStatus from './DropdownConnectStatus.vue';
|
||||
import DropdownError from './DropdownError.vue';
|
||||
import DropdownItem from './DropdownItem.vue';
|
||||
import Keyline from './Keyline.vue';
|
||||
|
||||
const props = defineProps<{ t: ComposerTranslation }>();
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
@@ -200,7 +207,7 @@ const unraidConnectWelcome = computed(() => {
|
||||
gradient-stop="currentcolor"
|
||||
class="text-foreground w-[120px]"
|
||||
/>
|
||||
<UpcBeta />
|
||||
<Beta />
|
||||
</h2>
|
||||
<template v-if="unraidConnectWelcome">
|
||||
<h3 class="text-16px font-semibold mt-2">
|
||||
@@ -211,29 +218,29 @@ const unraidConnectWelcome = computed(() => {
|
||||
</p>
|
||||
</template>
|
||||
</header>
|
||||
<ul class="list-reset flex flex-col gap-y-4px p-0">
|
||||
<UpcDropdownConnectStatus v-if="showConnectStatus" :t="t" />
|
||||
<UpcDropdownError v-if="showErrors" :t="t" />
|
||||
<ul class="list-reset flex flex-col gap-y-4px p-0">
|
||||
<DropdownConnectStatus v-if="showConnectStatus" :t="t" />
|
||||
<DropdownError v-if="showErrors" :t="t" />
|
||||
|
||||
<li v-if="showKeyline" class="my-8px">
|
||||
<UpcKeyline />
|
||||
</li>
|
||||
|
||||
<li v-if="!registered && connectPluginInstalled">
|
||||
<UpcDropdownItem :item="signInAction[0]" :t="t" />
|
||||
</li>
|
||||
|
||||
<template v-if="filteredKeyActions">
|
||||
<li v-for="action in filteredKeyActions" :key="action.name">
|
||||
<UpcDropdownItem :item="action" :t="t" />
|
||||
<li v-if="showKeyline" class="my-8px">
|
||||
<Keyline />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<template v-if="links.length">
|
||||
<li v-for="(link, index) in links" :key="`link_${index}`">
|
||||
<UpcDropdownItem :item="link" :t="t" />
|
||||
<li v-if="!registered && connectPluginInstalled">
|
||||
<DropdownItem :item="signInAction[0]" :t="t" />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<template v-if="filteredKeyActions">
|
||||
<li v-for="action in filteredKeyActions" :key="action.name">
|
||||
<DropdownItem :item="action" :t="t" />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<template v-if="links.length">
|
||||
<li v-for="(link, index) in links" :key="`link_${index}`">
|
||||
<DropdownItem :item="link" :t="t" />
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useErrorsStore } from '~/store/errors';
|
||||
import type { UserProfileLink } from '~/types/userProfile';
|
||||
import UpcDropdownItem from './DropdownItem.vue';
|
||||
|
||||
defineProps<{ t: ComposerTranslation; }>();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/solid';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { h } from 'vue';
|
||||
import { computed, h } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { BrandButton, BrandLoading } from '@unraid/ui';
|
||||
@@ -8,6 +8,8 @@ import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
import UpcUptimeExpire from './UptimeExpire.vue';
|
||||
import KeyActions from '~/components/KeyActions.vue';
|
||||
|
||||
defineProps<{ t: ComposerTranslation }>();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import {
|
||||
@@ -11,6 +12,7 @@ import {
|
||||
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import BrandAvatar from '~/components/Brand/Avatar.vue';
|
||||
import { useErrorsStore } from '~/store/errors';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
@@ -18,7 +20,7 @@ import { useUpdateOsStore } from '~/store/updateOs';
|
||||
const props = defineProps<{ t: ComposerTranslation }>();
|
||||
|
||||
const { errors } = storeToRefs(useErrorsStore());
|
||||
const { rebootType, state, stateData } = storeToRefs(useServerStore());
|
||||
const { connectPluginInstalled, rebootType, state, stateData } = storeToRefs(useServerStore());
|
||||
const { available: osUpdateAvailable } = storeToRefs(useUpdateOsStore());
|
||||
|
||||
const showErrorIcon = computed(() => errors.value.length || stateData.value.error);
|
||||
@@ -77,6 +79,6 @@ const title = computed((): string => {
|
||||
|
||||
<Bars3Icon class="w-20px" />
|
||||
|
||||
<BrandAvatar />
|
||||
<BrandAvatar v-if="connectPluginInstalled" />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useServerStore } from '~/store/server';
|
||||
import type { ServerStateDataAction } from '~/types/server';
|
||||
import UpcServerStateBuy from './ServerStateBuy.vue';
|
||||
|
||||
defineProps<{ t: ComposerTranslation; }>();
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { BrandLoading } from '@unraid/ui';
|
||||
@@ -6,6 +7,7 @@ import { BrandLoading } from '@unraid/ui';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useTrialStore } from '~/store/trial';
|
||||
import Modal from '~/components/Modal.vue';
|
||||
|
||||
export interface Props {
|
||||
open?: boolean;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
@@ -8,12 +9,14 @@ import { useServerStore } from '~/store/server';
|
||||
export interface Props {
|
||||
forExpire?: boolean;
|
||||
shortText?: boolean;
|
||||
as?: 'p' | 'span';
|
||||
t: ComposerTranslation;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
forExpire: false,
|
||||
shortText: false,
|
||||
as: 'p',
|
||||
});
|
||||
|
||||
const serverStore = useServerStore();
|
||||
@@ -59,7 +62,7 @@ const output = computed(() => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<p :title="output.title">
|
||||
<component :is="as" :title="output.title">
|
||||
{{ output.text }}
|
||||
</p>
|
||||
</component>
|
||||
</template>
|
||||
|
||||
@@ -55,27 +55,29 @@ watchEffect(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<span v-if="loading" class="italic">{{ t('Checking WAN IPs…') }}</span>
|
||||
<template v-else>
|
||||
<span v-if="computedError" class="text-unraid-red font-semibold">{{ computedError }}</span>
|
||||
<div>
|
||||
<span v-if="loading" class="italic">{{ t('Checking WAN IPs…') }}</span>
|
||||
<template v-else>
|
||||
<span v-if="isRemoteAccess || (phpWanIp === wanIp && !isRemoteAccess)">{{
|
||||
t('Remark: your WAN IPv4 is {0}', [wanIp])
|
||||
}}</span>
|
||||
<span v-else class="inline-block w-1/2 whitespace-normal">
|
||||
{{
|
||||
t("Remark: Unraid's WAN IPv4 {0} does not match your client's WAN IPv4 {1}.", [
|
||||
phpWanIp,
|
||||
wanIp,
|
||||
])
|
||||
}}
|
||||
{{
|
||||
t('This may indicate a complex network that will not work with this Remote Access solution.')
|
||||
}}
|
||||
{{ t('Ignore this message if you are currently connected via Remote Access or VPN.') }}
|
||||
</span>
|
||||
<span v-if="computedError" class="text-unraid-red font-semibold">{{ computedError }}</span>
|
||||
<template v-else>
|
||||
<span v-if="isRemoteAccess || (phpWanIp === wanIp && !isRemoteAccess)">{{
|
||||
t('Remark: your WAN IPv4 is {0}', [wanIp])
|
||||
}}</span>
|
||||
<span v-else class="inline-block w-1/2 whitespace-normal">
|
||||
{{
|
||||
t("Remark: Unraid's WAN IPv4 {0} does not match your client's WAN IPv4 {1}.", [
|
||||
phpWanIp,
|
||||
wanIp,
|
||||
])
|
||||
}}
|
||||
{{
|
||||
t('This may indicate a complex network that will not work with this Remote Access solution.')
|
||||
}}
|
||||
{{ t('Ignore this message if you are currently connected via Remote Access or VPN.') }}
|
||||
</span>
|
||||
</template>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
|
||||
49
web/components/Wrapper/web-component-plugins.ts
Normal file
49
web/components/Wrapper/web-component-plugins.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import type { App } from 'vue';
|
||||
import { DefaultApolloClient } from '@vue/apollo-composable';
|
||||
|
||||
import en_US from '~/locales/en_US.json';
|
||||
import { createHtmlEntityDecoder } from '~/helpers/i18n-utils';
|
||||
import { globalPinia } from '~/store/globalPinia';
|
||||
import { client } from '~/helpers/create-apollo-client';
|
||||
|
||||
export default function (Vue: App) {
|
||||
// Create and configure i18n
|
||||
const defaultLocale = 'en_US';
|
||||
let parsedLocale = '';
|
||||
let parsedMessages = {};
|
||||
let nonDefaultLocale = false;
|
||||
|
||||
// Check for window locale data
|
||||
if (typeof window !== 'undefined') {
|
||||
const windowLocaleData = (window as unknown as { LOCALE_DATA?: string }).LOCALE_DATA || null;
|
||||
if (windowLocaleData) {
|
||||
try {
|
||||
parsedMessages = JSON.parse(decodeURIComponent(windowLocaleData));
|
||||
parsedLocale = Object.keys(parsedMessages)[0];
|
||||
nonDefaultLocale = parsedLocale !== defaultLocale;
|
||||
} catch (error) {
|
||||
console.error('[WebComponentPlugins] error parsing messages', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
locale: nonDefaultLocale ? parsedLocale : defaultLocale,
|
||||
fallbackLocale: defaultLocale,
|
||||
messages: {
|
||||
en_US,
|
||||
...(nonDefaultLocale ? parsedMessages : {}),
|
||||
},
|
||||
postTranslation: createHtmlEntityDecoder(),
|
||||
});
|
||||
|
||||
Vue.use(i18n);
|
||||
|
||||
// Use the shared Pinia instance
|
||||
Vue.use(globalPinia);
|
||||
|
||||
// Provide Apollo client for all web components
|
||||
Vue.provide(DefaultApolloClient, client);
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { computed, onUnmounted, ref, watchEffect } from 'vue';
|
||||
import { useQuery } from '@vue/apollo-composable';
|
||||
import { useStorage } from '@vueuse/core';
|
||||
import { useStorage, watchOnce } from '@vueuse/core';
|
||||
import {
|
||||
getNotifications,
|
||||
NOTIFICATION_FRAGMENT,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ref, computed, onBeforeMount, onBeforeUnmount } from 'vue';
|
||||
import dayjs, { extend } from 'dayjs';
|
||||
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
@@ -206,7 +207,7 @@ const useDateTimeHelper = (
|
||||
outputDateTimeReadableDiff.value = buildStringFromValues(dateDiff((providedDateTime ?? Date.now()).toString(), diffCountUp ?? false));
|
||||
};
|
||||
|
||||
let interval: string | number | NodeJS.Timeout | undefined;
|
||||
let interval: string | number | ReturnType<typeof setInterval> | undefined;
|
||||
onBeforeMount(() => {
|
||||
if (providedDateTime) {
|
||||
runDiff();
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import { ref, onMounted } from "vue";
|
||||
|
||||
const useTeleport = () => {
|
||||
const teleportTarget = ref<string | HTMLElement | Element>("#modals");
|
||||
|
||||
const determineTeleportTarget = () => {
|
||||
const myModalsComponent = document.querySelector("unraid-modals");
|
||||
if (!myModalsComponent?.shadowRoot) return;
|
||||
|
||||
const potentialTarget = myModalsComponent.shadowRoot.querySelector("#modals");
|
||||
if (!potentialTarget) return;
|
||||
|
||||
teleportTarget.value = potentialTarget;
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
determineTeleportTarget();
|
||||
});
|
||||
|
||||
return {
|
||||
teleportTarget,
|
||||
determineTeleportTarget,
|
||||
};
|
||||
};
|
||||
|
||||
export default useTeleport;
|
||||
@@ -6,10 +6,57 @@ import withNuxt from './.nuxt/eslint.config.mjs';
|
||||
export default withNuxt(
|
||||
{
|
||||
ignores: ['./coverage/**'],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
// Node.js globals
|
||||
NodeJS: 'readonly',
|
||||
// Browser APIs
|
||||
EventListenerOrEventListenerObject: 'readonly',
|
||||
HTMLCollectionOf: 'readonly',
|
||||
// webGUI-specific globals
|
||||
openPlugin: 'readonly',
|
||||
openBox: 'readonly',
|
||||
openChanges: 'readonly',
|
||||
FeedbackButton: 'readonly',
|
||||
flashBackup: 'readonly',
|
||||
confirmDowngrade: 'readonly',
|
||||
downloadDiagnostics: 'readonly',
|
||||
// Nuxt globals
|
||||
defineNuxtConfig: 'readonly',
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/no-v-html': 'off',
|
||||
'vue/no-undef-components': [
|
||||
'error',
|
||||
{
|
||||
ignorePatterns: [
|
||||
// Custom Elements (components ending with Ce)
|
||||
'.*Ce$',
|
||||
// Web Components (components starting with unraid-)
|
||||
'^unraid-.*',
|
||||
// Client-only component
|
||||
'^client-only$',
|
||||
// Other common components
|
||||
'^ClientOnly$',
|
||||
'^BrandLogo$',
|
||||
'^ColorSwitcherCe$',
|
||||
'^DummyServerSwitcher$',
|
||||
'^HeaderOsVersionCe$',
|
||||
'^ConnectSettingsCe$',
|
||||
],
|
||||
},
|
||||
],
|
||||
'eol-last': ['error', 'always'],
|
||||
|
||||
// TypeScript rules for unused variables and undefined variables
|
||||
'@typescript-eslint/no-unused-vars': ['error', {
|
||||
argsIgnorePattern: '^_',
|
||||
varsIgnorePattern: '^_',
|
||||
caughtErrorsIgnorePattern: '^_'
|
||||
}],
|
||||
'no-undef': 'error',
|
||||
},
|
||||
},
|
||||
eslintPrettier
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { InMemoryCache } from '@apollo/client/core/index.js';
|
||||
import { InMemoryCache, type InMemoryCacheConfig } from '@apollo/client/core';
|
||||
|
||||
import type { InMemoryCacheConfig } from '@apollo/client/core/index.js';
|
||||
import type { NotificationOverview } from '~/composables/gql/graphql';
|
||||
|
||||
import {
|
||||
@@ -11,6 +10,11 @@ import { NotificationType } from '~/composables/gql/graphql';
|
||||
import { NotificationTypename } from '~/composables/gql/typename';
|
||||
import { mergeAndDedup } from './merge';
|
||||
|
||||
// Utility function to check if a value is defined (not null and not undefined)
|
||||
const isDefined = <T>(value: T | null | undefined): value is T => {
|
||||
return value !== null && value !== undefined;
|
||||
};
|
||||
|
||||
/**------------------------------------------------------------------------
|
||||
* ! Understanding Cache Type Policies
|
||||
*
|
||||
|
||||
@@ -3,7 +3,6 @@ import { onError } from '@apollo/client/link/error/index.js';
|
||||
import { RetryLink } from '@apollo/client/link/retry/index.js';
|
||||
import { GraphQLWsLink } from '@apollo/client/link/subscriptions/index.js';
|
||||
import { getMainDefinition } from '@apollo/client/utilities/index.js';
|
||||
import { provideApolloClient } from '@vue/apollo-composable';
|
||||
import { createClient } from 'graphql-ws';
|
||||
import { createApolloCache } from './apollo-cache';
|
||||
import { WEBGUI_GRAPHQL } from './urls';
|
||||
@@ -94,6 +93,4 @@ const additiveLink = from([errorLink, retryLink, disableQueryLink, splitLinks]);
|
||||
export const client = new ApolloClient({
|
||||
link: additiveLink,
|
||||
cache: createApolloCache(),
|
||||
});
|
||||
|
||||
provideApolloClient(client);
|
||||
});
|
||||
2
web/helpers/globals.d.ts
vendored
2
web/helpers/globals.d.ts
vendored
@@ -1,5 +1,5 @@
|
||||
declare global {
|
||||
// eslint-disable-next-line no-var
|
||||
|
||||
var csrf_token: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="text-black bg-white dark:text-white dark:bg-black">
|
||||
<client-only>
|
||||
<ClientOnly>
|
||||
<div class="flex flex-row items-center justify-center gap-6 p-6 bg-white dark:bg-zinc-800">
|
||||
<template v-for="route in routes" :key="route.path">
|
||||
<NuxtLink
|
||||
@@ -14,11 +14,15 @@
|
||||
<ModalsCe />
|
||||
</div>
|
||||
<slot />
|
||||
</client-only>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, watch } from 'vue';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { ClientOnly, NuxtLink } from '#components';
|
||||
import ModalsCe from '~/components/Modals.ce.vue';
|
||||
import { useThemeStore } from '~/store/theme';
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import path from 'path';
|
||||
|
||||
import removeConsole from 'vite-plugin-remove-console';
|
||||
|
||||
import type { UserConfig } from 'vite';
|
||||
|
||||
/**
|
||||
* Used to avoid redeclaring variables in the webgui codebase.
|
||||
* @see alt solution https://github.com/terser/terser/issues/1001, https://github.com/terser/terser/pull/1038
|
||||
@@ -53,6 +56,11 @@ export default defineNuxtConfig({
|
||||
'@nuxt/eslint',
|
||||
],
|
||||
|
||||
// Disable auto-imports
|
||||
imports: {
|
||||
autoImport: false,
|
||||
},
|
||||
|
||||
// Properly handle ES modules in testing and build environments
|
||||
build: {
|
||||
transpile: [/node_modules\/.*\.mjs$/],
|
||||
@@ -60,13 +68,8 @@ export default defineNuxtConfig({
|
||||
|
||||
ignore: ['/webGui/images'],
|
||||
|
||||
components: [
|
||||
{ path: '~/components/Brand', prefix: 'Brand' },
|
||||
{ path: '~/components/ConnectSettings', prefix: 'ConnectSettings' },
|
||||
{ path: '~/components/UserProfile', prefix: 'Upc' },
|
||||
{ path: '~/components/UpdateOs', prefix: 'UpdateOs' },
|
||||
'~/components',
|
||||
],
|
||||
// Disable component auto-imports
|
||||
components: false,
|
||||
|
||||
vite: {
|
||||
plugins: [
|
||||
@@ -88,77 +91,156 @@ export default defineNuxtConfig({
|
||||
reserved: terserReservations(charsToReserve),
|
||||
toplevel: true,
|
||||
},
|
||||
// keep_fnames: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
customElements: {
|
||||
analyzer: process.env.NODE_ENV !== 'test',
|
||||
entries: [
|
||||
// @ts-expect-error The nuxt-custom-elements module types don't perfectly match our configuration object structure.
|
||||
// The custom elements configuration requires specific properties and methods that may not align with the
|
||||
// module's TypeScript definitions, particularly around the viteExtend function and tag configuration format.
|
||||
{
|
||||
name: 'UnraidComponents',
|
||||
viteExtend(config: UserConfig) {
|
||||
// Configure terser options for custom elements build
|
||||
if (!config.build) config.build = {};
|
||||
config.build.minify = 'terser';
|
||||
config.build.terserOptions = {
|
||||
mangle: {
|
||||
reserved: terserReservations(charsToReserve),
|
||||
toplevel: true,
|
||||
},
|
||||
};
|
||||
|
||||
// Add a custom plugin to wrap the bundle and preserve jQuery
|
||||
if (!config.plugins) config.plugins = [];
|
||||
config.plugins.push({
|
||||
name: 'jquery-isolation',
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
generateBundle(options: any, bundle: any) {
|
||||
// Find the main JS file
|
||||
const jsFile = Object.keys(bundle).find(key => key.endsWith('.js'));
|
||||
if (jsFile && bundle[jsFile] && 'code' in bundle[jsFile]) {
|
||||
const originalCode = bundle[jsFile].code;
|
||||
// Wrap the entire bundle to preserve and restore jQuery
|
||||
bundle[jsFile].code = `
|
||||
(function() {
|
||||
// Preserve the original jQuery $ if it exists
|
||||
var originalJQuery = (typeof window !== 'undefined' && typeof window.$ !== 'undefined') ? window.$ : undefined;
|
||||
|
||||
// Temporarily clear $ to avoid conflicts
|
||||
if (typeof window !== 'undefined' && typeof window.$ !== 'undefined') {
|
||||
window.$ = undefined;
|
||||
}
|
||||
|
||||
// Execute the web component code
|
||||
${originalCode}
|
||||
|
||||
// Restore jQuery $ if it was originally defined
|
||||
if (originalJQuery !== undefined && typeof window !== 'undefined') {
|
||||
window.$ = originalJQuery;
|
||||
}
|
||||
})();
|
||||
`;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return config;
|
||||
},
|
||||
tags: [
|
||||
|
||||
{
|
||||
name: 'UnraidI18nHost',
|
||||
path: '@/components/I18nHost.ce',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidAuth',
|
||||
path: '@/components/Auth.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidConnectSettings',
|
||||
path: '@/components/ConnectSettings/ConnectSettings.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidDownloadApiLogs',
|
||||
path: '@/components/DownloadApiLogs.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidHeaderOsVersion',
|
||||
path: '@/components/HeaderOsVersion.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidModals',
|
||||
path: '@/components/Modals.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidUserProfile',
|
||||
path: '@/components/UserProfile.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidUpdateOs',
|
||||
path: '@/components/UpdateOs.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidDowngradeOs',
|
||||
path: '@/components/DowngradeOs.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidRegistration',
|
||||
path: '@/components/Registration.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidWanIpCheck',
|
||||
path: '@/components/WanIpCheck.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidWelcomeModal',
|
||||
path: '@/components/Activation/WelcomeModal.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidSsoButton',
|
||||
path: '@/components/SsoButton.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidLogViewer',
|
||||
path: '@/components/Logs/LogViewer.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidThemeSwitcher',
|
||||
path: '@/components/ThemeSwitcher.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
{
|
||||
async: false,
|
||||
name: 'UnraidApiKeyManager',
|
||||
path: '@/components/ApiKeyPage.ce',
|
||||
appContext: '@/components/Wrapper/web-component-plugins',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
"@types/eslint-config-prettier": "^6.11.3",
|
||||
"@types/node": "^22",
|
||||
"@types/semver": "^7.5.8",
|
||||
"@typescript-eslint/eslint-plugin": "^8.34.1",
|
||||
"@unraid/tailwind-rem-to-rem": "^1.1.0",
|
||||
"@vitejs/plugin-vue": "^5.0.0",
|
||||
"@vitest/coverage-v8": "^3.1.1",
|
||||
@@ -64,10 +65,12 @@
|
||||
"@vueuse/nuxt": "^13.0.0",
|
||||
"eslint": "^9.21.0",
|
||||
"eslint-config-prettier": "^10.0.0",
|
||||
"eslint-import-resolver-typescript": "^4.4.4",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"happy-dom": "^18.0.0",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nuxt": "^3.14.1592",
|
||||
"nuxt-custom-elements": "2.0.0-beta.18",
|
||||
"nuxt-custom-elements": "2.0.0-beta.32",
|
||||
"prettier": "3.5.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.9",
|
||||
"shadcn-nuxt": "^2.0.0",
|
||||
@@ -75,6 +78,7 @@
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"terser": "^5.37.0",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.3.5",
|
||||
"vite-plugin-remove-console": "^2.2.0",
|
||||
"vite-plugin-vue-tracer": "^0.1.3",
|
||||
"vitest": "^3.1.1",
|
||||
@@ -118,6 +122,7 @@
|
||||
"semver": "^7.6.3",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
"vue-i18n": "^11.0.0",
|
||||
"vue-web-component-wrapper": "^1.7.7",
|
||||
"vuetify": "^3.7.14",
|
||||
"wretch": "^2.11.0"
|
||||
},
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { onBeforeMount } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import UpdateOsChangelogModal from '~/components/UpdateOs/ChangelogModal.vue';
|
||||
import ColorSwitcherCe from '~/components/ColorSwitcher.ce.vue';
|
||||
|
||||
const updateOsStore = useUpdateOsStore();
|
||||
const { changelogModalVisible } = storeToRefs(updateOsStore);
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
<script setup>
|
||||
import { onMounted } from 'vue';
|
||||
import RCloneConfig from '~/components/RClone/RCloneConfig.vue';
|
||||
import RCloneOverview from '~/components/RClone/RCloneOverview.vue';
|
||||
import { useDummyServerStore } from '~/_data/serverState';
|
||||
|
||||
const { registerEntry } = useCustomElements();
|
||||
|
||||
useDummyServerStore();
|
||||
|
||||
onBeforeMount(() => {
|
||||
registerEntry('UnraidComponents');
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
document.cookie = 'unraid_session_cookie=mockusersession';
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useHead } from '#imports';
|
||||
import { ExclamationTriangleIcon } from '@heroicons/vue/24/solid';
|
||||
import { BrandButton, Toaster } from '@unraid/ui';
|
||||
import { useDummyServerStore } from '~/_data/serverState';
|
||||
@@ -11,14 +14,18 @@ import SsoButtonCe from '~/components/SsoButton.ce.vue';
|
||||
import { useThemeStore } from '~/store/theme';
|
||||
import ModalsCe from '~/components/Modals.ce.vue';
|
||||
import ConnectSettingsCe from '~/components/ConnectSettings/ConnectSettings.ce.vue';
|
||||
import DummyServerSwitcher from '~/components/DummyServerSwitcher.vue';
|
||||
import ColorSwitcherCe from '~/components/ColorSwitcher.ce.vue';
|
||||
import HeaderOsVersionCe from '~/components/HeaderOsVersion.ce.vue';
|
||||
import UserProfileCe from '~/components/UserProfile.ce.vue';
|
||||
import UpdateOsCe from '~/components/UpdateOs.ce.vue';
|
||||
import DowngradeOsCe from '~/components/DowngradeOs.ce.vue';
|
||||
import RegistrationCe from '~/components/Registration.ce.vue';
|
||||
import WelcomeModalCe from '~/components/Activation/WelcomeModal.ce.vue';
|
||||
|
||||
const serverStore = useDummyServerStore();
|
||||
const { serverState } = storeToRefs(serverStore);
|
||||
const { registerEntry } = useCustomElements();
|
||||
const { theme } = storeToRefs(useThemeStore());
|
||||
onBeforeMount(() => {
|
||||
registerEntry('UnraidComponents');
|
||||
});
|
||||
|
||||
useHead({
|
||||
meta: [{ name: 'viewport', content: 'width=1300' }],
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted } from 'vue';
|
||||
|
||||
const parseRedirectTarget = (target: string | null) => {
|
||||
if (target && target !== '/') {
|
||||
// parse target and ensure it is a bare path with no query parameters
|
||||
|
||||
@@ -1,18 +1,19 @@
|
||||
<script lang="ts" setup>
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useDummyServerStore } from '~/_data/serverState';
|
||||
import { Toaster } from '@unraid/ui';
|
||||
import BrandLogo from '~/components/Brand/Logo.vue';
|
||||
import HeaderOsVersionCe from '~/components/HeaderOsVersion.ce.vue';
|
||||
import ConnectSettingsCe from '~/components/ConnectSettings/ConnectSettings.ce.vue';
|
||||
|
||||
const serverStore = useDummyServerStore();
|
||||
const { serverState } = storeToRefs(serverStore);
|
||||
const { registerEntry } = useCustomElements();
|
||||
onBeforeMount(() => {
|
||||
registerEntry('UnraidComponents');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<client-only>
|
||||
<unraid-i18n-host
|
||||
<div
|
||||
class="flex flex-col gap-6 p-6 mx-auto text-black bg-white dark:text-white dark:bg-black"
|
||||
>
|
||||
<h2 class="text-xl font-semibold font-mono">Web Components</h2>
|
||||
@@ -60,7 +61,7 @@ onBeforeMount(() => {
|
||||
<hr class="border-black dark:border-white" />
|
||||
<h3 class="text-lg font-semibold font-mono">ApiKeyManagerCe</h3>
|
||||
<unraid-api-key-manager />
|
||||
</unraid-i18n-host>
|
||||
</div>
|
||||
<Toaster rich-colors close-button />
|
||||
</client-only>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useActivationCodeModalStore } from '~/components/Activation/store/activationCodeModal';
|
||||
import { useActivationCodeDataStore } from '~/components/Activation/store/activationCodeData';
|
||||
import { useCallbackActionsStore } from '~/store/callbackActions';
|
||||
|
||||
7
web/plugins/apollo.ts
Normal file
7
web/plugins/apollo.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { defineNuxtPlugin } from '#imports';
|
||||
import { DefaultApolloClient } from '@vue/apollo-composable';
|
||||
import { client } from '~/helpers/create-apollo-client';
|
||||
|
||||
export default defineNuxtPlugin(({ vueApp }) => {
|
||||
vueApp.provide(DefaultApolloClient, client);
|
||||
});
|
||||
@@ -1,4 +1,5 @@
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import { defineNuxtPlugin } from '#imports';
|
||||
|
||||
import en_US from '@/locales/en_US.json';
|
||||
import { createHtmlEntityDecoder } from '~/helpers/i18n-utils';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { computed, ref, watchEffect } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useMutation } from '@vue/apollo-composable';
|
||||
import { logErrorMessages } from '@vue/apollo-util';
|
||||
|
||||
@@ -15,11 +15,11 @@ import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
import { CONNECT_SIGN_IN, CONNECT_SIGN_OUT } from './account.fragment';
|
||||
|
||||
/**
|
||||
* Uses the shared global Pinia instance from ~/store/globalPinia.ts
|
||||
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
|
||||
* @see https://github.com/vuejs/pinia/discussions/1085
|
||||
*/
|
||||
|
||||
setActivePinia(createPinia());
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export interface ConnectSignInMutationPayload {
|
||||
apiKey: string;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ref } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import type { ApiKeyFragment, ApiKeyWithKeyFragment } from '~/composables/gql/graphql';
|
||||
|
||||
setActivePinia(createPinia());
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export const useApiKeyStore = defineStore('apiKey', () => {
|
||||
const modalVisible = ref(false);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { computed, ref, watch, watchEffect } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import { useCallback } from '@unraid/shared-callbacks';
|
||||
|
||||
@@ -19,9 +19,9 @@ import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
import { useUpdateOsActionsStore } from '~/store/updateOsActions';
|
||||
|
||||
type CallbackStatus = 'closing' | 'error' | 'loading' | 'ready' | 'success';
|
||||
import '~/store/globalPinia';
|
||||
|
||||
setActivePinia(createPinia());
|
||||
type CallbackStatus = 'closing' | 'error' | 'loading' | 'ready' | 'success';
|
||||
|
||||
export const useCallbackActionsStore = defineStore('callbackActions', () => {
|
||||
const { send, watcher: providedWatcher } = useCallback({
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { ref } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
|
||||
/**
|
||||
* Uses the shared global Pinia instance from ~/store/globalPinia.ts
|
||||
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
|
||||
* @see https://github.com/vuejs/pinia/discussions/1085
|
||||
*/
|
||||
setActivePinia(createPinia());
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export const useDropdownStore = defineStore('dropdown', () => {
|
||||
const dropdownVisible = ref<boolean>(false);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ref } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import { OBJ_TO_STR } from '~/helpers/functions';
|
||||
|
||||
@@ -7,10 +7,11 @@ import type { BrandButtonProps } from '@unraid/ui';
|
||||
import type { Server } from '~/types/server';
|
||||
|
||||
/**
|
||||
* Uses the shared global Pinia instance from ~/store/globalPinia.ts
|
||||
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
|
||||
* @see https://github.com/vuejs/pinia/discussions/1085
|
||||
*/
|
||||
setActivePinia(createPinia());
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export type ErrorType =
|
||||
| 'account'
|
||||
|
||||
7
web/store/globalPinia.ts
Normal file
7
web/store/globalPinia.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { createPinia, setActivePinia } from 'pinia';
|
||||
|
||||
// Create a single shared Pinia instance for all web components
|
||||
export const globalPinia = createPinia();
|
||||
|
||||
// Set it as the active pinia instance
|
||||
setActivePinia(globalPinia);
|
||||
@@ -1,5 +1,5 @@
|
||||
import { computed, ref } from 'vue';
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
|
||||
import type { ExternalKeyActions } from '@unraid/shared-callbacks';
|
||||
|
||||
@@ -7,10 +7,11 @@ import { WebguiInstallKey } from '~/composables/services/webgui';
|
||||
import { useErrorsStore } from '~/store/errors';
|
||||
|
||||
/**
|
||||
* Uses the shared global Pinia instance from ~/store/globalPinia.ts
|
||||
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
|
||||
* @see https://github.com/vuejs/pinia/discussions/1085
|
||||
*/
|
||||
setActivePinia(createPinia());
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export const useInstallKeyStore = defineStore('installKey', () => {
|
||||
const errorsStore = useErrorsStore();
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { createPinia, defineStore, setActivePinia } from 'pinia';
|
||||
import { defineStore } from 'pinia';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
|
||||
/**
|
||||
* Uses the shared global Pinia instance from ~/store/globalPinia.ts
|
||||
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
|
||||
* @see https://github.com/vuejs/pinia/discussions/1085
|
||||
*/
|
||||
setActivePinia(createPinia());
|
||||
import '~/store/globalPinia';
|
||||
|
||||
export const useModalStore = defineStore('modal', () => {
|
||||
const [modalVisible, modalToggle] = useToggle(true);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user