From 73b2ce360c66cd9bedc138a5f8306af04b6bde77 Mon Sep 17 00:00:00 2001 From: Eli Bosley Date: Mon, 15 Dec 2025 16:20:18 -0500 Subject: [PATCH] fix: update @unraid/shared-callbacks to version 3.0.0 (#1831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …on and pnpm-lock.yaml ## Summary by CodeRabbit * **New Features** * Added a standalone redirect page that shows "Redirecting..." and navigates automatically. * **Improvements** * Redirect preserves hash callback data, validates targets, and logs the computed redirect. * Purchase callback origin changed to a different account host. * Date/time formatting now tolerates missing or empty server formats with safe fallbacks. * Redirect page included in backup/restore. * **Tests** * Added tests covering date/time formatting fallbacks. * **Chores** * Dependency @unraid/shared-callbacks upgraded. * Removed multiple demo/debug pages and related test UIs. ✏️ Tip: You can customize this high-level summary in your review settings. --- plugin/plugins/dynamix.unraid.net.plg | 2 + .../usr/local/emhttp/redirect.htm | 91 ++++ pnpm-lock.yaml | 13 +- web/__test__/components/KeyActions.test.ts | 28 +- web/__test__/composables/dateTime.test.ts | 58 ++ web/__test__/store/server.test.ts | 107 ++-- web/package.json | 2 +- web/src/composables/dateTime.ts | 22 +- web/src/helpers/urls.ts | 2 +- web/src/pages/apikeys.vue | 7 - web/src/pages/changelog.vue | 116 ---- web/src/pages/flashbackup.vue | 17 - web/src/pages/index.vue | 200 ------- web/src/pages/login.query.ts | 14 - web/src/pages/login.vue | 494 ------------------ web/src/pages/redirect.vue | 44 -- web/src/pages/tools/apikeyauthorize.vue | 7 - web/src/pages/tools/test-update-modal.vue | 285 ---------- web/src/pages/welcome.vue | 65 --- web/src/store/server.ts | 61 +-- web/types/server.ts | 76 +-- web/types/userProfile.ts | 4 +- 22 files changed, 276 insertions(+), 1439 deletions(-) create mode 100644 plugin/source/dynamix.unraid.net/usr/local/emhttp/redirect.htm create mode 100644 web/__test__/composables/dateTime.test.ts delete mode 100644 web/src/pages/apikeys.vue delete mode 100644 web/src/pages/changelog.vue delete mode 100644 web/src/pages/flashbackup.vue delete mode 100644 web/src/pages/index.vue delete mode 100644 web/src/pages/login.query.ts delete mode 100644 web/src/pages/login.vue delete mode 100644 web/src/pages/redirect.vue delete mode 100644 web/src/pages/tools/apikeyauthorize.vue delete mode 100644 web/src/pages/tools/test-update-modal.vue delete mode 100644 web/src/pages/welcome.vue diff --git a/plugin/plugins/dynamix.unraid.net.plg b/plugin/plugins/dynamix.unraid.net.plg index eeed6411c..4d61f4677 100755 --- a/plugin/plugins/dynamix.unraid.net.plg +++ b/plugin/plugins/dynamix.unraid.net.plg @@ -206,6 +206,7 @@ FILES_TO_BACKUP=( "/usr/local/emhttp/plugins/dynamix.my.servers/include/reboot-details.php" "/usr/local/emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php" "/usr/local/emhttp/update.htm" + "/usr/local/emhttp/redirect.htm" "/usr/local/emhttp/logging.htm" "/etc/nginx/nginx.conf" "/etc/rc.d/rc.nginx" @@ -349,6 +350,7 @@ exit 0 "/usr/local/emhttp/plugins/dynamix.my.servers/include/reboot-details.php" "/usr/local/emhttp/plugins/dynamix.my.servers/include/web-components-extractor.php" "/usr/local/emhttp/update.htm" + "/usr/local/emhttp/redirect.htm" "/usr/local/emhttp/logging.htm" "/etc/nginx/nginx.conf" "/etc/rc.d/rc.nginx" diff --git a/plugin/source/dynamix.unraid.net/usr/local/emhttp/redirect.htm b/plugin/source/dynamix.unraid.net/usr/local/emhttp/redirect.htm new file mode 100644 index 000000000..e3778ba0c --- /dev/null +++ b/plugin/source/dynamix.unraid.net/usr/local/emhttp/redirect.htm @@ -0,0 +1,91 @@ + + + + + + + Redirect Page + + + + + + + + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8db98eb3a..5892b496f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1086,8 +1086,8 @@ importers: specifier: 4.0.0-alpha.0 version: 4.0.0-alpha.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(focus-trap@7.6.5)(ioredis@5.7.0)(jwt-decode@4.0.0)(magicast@0.3.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(lightningcss@1.30.1)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.20(typescript@5.9.2)))(vue@3.5.20(typescript@5.9.2))(zod@3.25.76) '@unraid/shared-callbacks': - specifier: 1.1.1 - version: 1.1.1(@vueuse/core@13.8.0(vue@3.5.20(typescript@5.9.2))) + specifier: 3.0.0 + version: 3.0.0 '@unraid/ui': specifier: link:../unraid-ui version: link:../unraid-ui @@ -5096,10 +5096,8 @@ packages: cpu: [x64, arm64] os: [linux, darwin] - '@unraid/shared-callbacks@1.1.1': - resolution: {integrity: sha512-14x5HFBOIVfUpQFAAhcRqIvj3AIsOyx90BdShXtddW55kiVtg+dDfsnlzExSYWhb35C6gYKZ0Sm9ZhF/YamGzg==} - peerDependencies: - '@vueuse/core': ^10.9.0 || ^13.0.0 + '@unraid/shared-callbacks@3.0.0': + resolution: {integrity: sha512-O4AN5nsmnwUQ1utYhG2wS9L2NAFn3eOg5YHKq9h9EUa3n8xQeUOzeM6UV2xBg9YJGuF3wQsaEpfj1GyX/MIAGw==} '@unraid/tailwind-rem-to-rem@2.0.0': resolution: {integrity: sha512-zccpQx5fvEBkAB0JkRwwtyRrT9l26LsjkozLy44LGv0NdZGaxgscniIqJRM+OQj5pSpsWDzExebAtUKdE98Flg==} @@ -17140,9 +17138,8 @@ snapshots: - encoding - supports-color - '@unraid/shared-callbacks@1.1.1(@vueuse/core@13.8.0(vue@3.5.20(typescript@5.9.2)))': + '@unraid/shared-callbacks@3.0.0': dependencies: - '@vueuse/core': 13.8.0(vue@3.5.20(typescript@5.9.2)) crypto-js: 4.2.0 '@unraid/tailwind-rem-to-rem@2.0.0(tailwindcss@4.1.12)': diff --git a/web/__test__/components/KeyActions.test.ts b/web/__test__/components/KeyActions.test.ts index 29e861f89..217c7cedb 100644 --- a/web/__test__/components/KeyActions.test.ts +++ b/web/__test__/components/KeyActions.test.ts @@ -9,7 +9,7 @@ import { BrandButton } from '@unraid/ui'; import { createTestingPinia } from '@pinia/testing'; import { beforeEach, describe, expect, it, vi } from 'vitest'; -import type { ServerStateDataAction, ServerStateDataActionType } from '~/types/server'; +import type { ServerStateDataAction } from '~/types/server'; import KeyActions from '~/components/KeyActions.vue'; import { createTestI18n } from '../utils/i18n'; @@ -34,7 +34,7 @@ describe('KeyActions', () => { it('renders buttons from props when actions prop is provided', () => { const actions: ServerStateDataAction[] = [ - { name: 'purchase' as ServerStateDataActionType, text: 'Custom Action 1', click: vi.fn() }, + { name: 'purchase', text: 'Custom Action 1', click: vi.fn() }, ]; const wrapper = mount(KeyActions, { @@ -68,9 +68,7 @@ describe('KeyActions', () => { it('calls action click handler when button is clicked', async () => { const click = vi.fn(); - const actions: ServerStateDataAction[] = [ - { name: 'purchase' as ServerStateDataActionType, text: 'Clickable Action', click }, - ]; + const actions: ServerStateDataAction[] = [{ name: 'purchase', text: 'Clickable Action', click }]; const wrapper = mount(KeyActions, { props: { @@ -89,7 +87,7 @@ describe('KeyActions', () => { const click = vi.fn(); const actions: ServerStateDataAction[] = [ { - name: 'purchase' as ServerStateDataActionType, + name: 'purchase', text: 'Disabled Action', disabled: true, click, @@ -111,9 +109,9 @@ describe('KeyActions', () => { it('filters actions using filterBy prop', () => { const actions: ServerStateDataAction[] = [ - { name: 'purchase' as ServerStateDataActionType, text: 'Action 1', click: vi.fn() }, - { name: 'redeem' as ServerStateDataActionType, text: 'Action 2', click: vi.fn() }, - { name: 'upgrade' as ServerStateDataActionType, text: 'Action 3', click: vi.fn() }, + { name: 'purchase', text: 'Action 1', click: vi.fn() }, + { name: 'redeem', text: 'Action 2', click: vi.fn() }, + { name: 'upgrade', text: 'Action 3', click: vi.fn() }, ]; const wrapper = mount(KeyActions, { @@ -135,9 +133,9 @@ describe('KeyActions', () => { it('filters out actions using filterOut prop', () => { const actions: ServerStateDataAction[] = [ - { name: 'purchase' as ServerStateDataActionType, text: 'Action 1', click: vi.fn() }, - { name: 'redeem' as ServerStateDataActionType, text: 'Action 2', click: vi.fn() }, - { name: 'upgrade' as ServerStateDataActionType, text: 'Action 3', click: vi.fn() }, + { name: 'purchase', text: 'Action 1', click: vi.fn() }, + { name: 'redeem', text: 'Action 2', click: vi.fn() }, + { name: 'upgrade', text: 'Action 3', click: vi.fn() }, ]; const wrapper = mount(KeyActions, { @@ -158,9 +156,7 @@ describe('KeyActions', () => { }); it('applies maxWidth styling when maxWidth prop is true', () => { - const actions: ServerStateDataAction[] = [ - { name: 'purchase' as ServerStateDataActionType, text: 'Action 1', click: vi.fn() }, - ]; + const actions: ServerStateDataAction[] = [{ name: 'purchase', text: 'Action 1', click: vi.fn() }]; const wrapper = mount(KeyActions, { props: { @@ -180,7 +176,7 @@ describe('KeyActions', () => { it('passes all required props to BrandButton component', () => { const actions: ServerStateDataAction[] = [ { - name: 'purchase' as ServerStateDataActionType, + name: 'purchase', text: 'Test Action', title: 'Action Title', href: '/test-link', diff --git a/web/__test__/composables/dateTime.test.ts b/web/__test__/composables/dateTime.test.ts new file mode 100644 index 000000000..0654ac849 --- /dev/null +++ b/web/__test__/composables/dateTime.test.ts @@ -0,0 +1,58 @@ +import { defineComponent } from 'vue'; +import { mount } from '@vue/test-utils'; + +import dayjs from 'dayjs'; +import { describe, expect, it } from 'vitest'; + +import type { ServerDateTimeFormat } from '~/types/server'; + +import useDateTimeHelper from '~/composables/dateTime'; +import { testTranslate } from '../utils/i18n'; + +const formatDateWithComponent = ( + dateTimeFormat: ServerDateTimeFormat | undefined, + hideMinutesSeconds: boolean, + providedDateTime: number +) => { + const wrapper = mount( + defineComponent({ + setup() { + const { outputDateTimeFormatted } = useDateTimeHelper( + dateTimeFormat, + testTranslate, + hideMinutesSeconds, + providedDateTime + ); + return { outputDateTimeFormatted }; + }, + template: '
', + }) + ); + + const output = (wrapper.vm as unknown as { outputDateTimeFormatted: string | { value: string } }) + .outputDateTimeFormatted; + return typeof output === 'string' ? output : output.value; +}; + +describe('useDateTimeHelper', () => { + it('falls back to default date format when server format is empty', () => { + const timestamp = new Date(2025, 0, 2, 3, 4, 5).getTime(); + const formatted = formatDateWithComponent({ date: '', time: '' }, true, timestamp); + + expect(formatted).toBe(dayjs(timestamp).format('dddd, MMMM D, YYYY')); + }); + + it('falls back to default date format when server format is unknown', () => { + const timestamp = new Date(2025, 0, 2, 3, 4, 5).getTime(); + const formatted = formatDateWithComponent({ date: '%Q', time: '%Q' }, true, timestamp); + + expect(formatted).toBe(dayjs(timestamp).format('dddd, MMMM D, YYYY')); + }); + + it('falls back to default time format when server time format is unknown', () => { + const timestamp = new Date(2025, 0, 2, 3, 4, 5).getTime(); + const formatted = formatDateWithComponent({ date: '%c', time: '%Q' }, false, timestamp); + + expect(formatted).toBe(dayjs(timestamp).format('ddd, D MMMM YYYY hh:mma')); + }); +}); diff --git a/web/__test__/store/server.test.ts b/web/__test__/store/server.test.ts index 49d20b651..85fa9ae77 100644 --- a/web/__test__/store/server.test.ts +++ b/web/__test__/store/server.test.ts @@ -161,37 +161,45 @@ const getStore = () => { }, serverPurchasePayload: { get: () => ({ - apiVersion: store.apiVersion, - connectPluginVersion: store.connectPluginVersion, - deviceCount: store.deviceCount, - email: store.email, - guid: store.guid, - keyTypeForPurchase: store.state === 'PLUS' ? 'Plus' : store.state === 'PRO' ? 'Pro' : 'Trial', - locale: store.locale, - osVersion: store.osVersion, - osVersionBranch: store.osVersionBranch, - registered: store.registered ?? false, - regExp: store.regExp, - regTy: store.regTy, - regUpdatesExpired: store.regUpdatesExpired, - state: store.state, - site: store.site, - }), - }, - serverAccountPayload: { - get: () => ({ - apiVersion: store.apiVersion, - caseModel: store.caseModel, - connectPluginVersion: store.connectPluginVersion, - deviceCount: store.deviceCount, description: store.description, + deviceCount: store.deviceCount, + expireTime: store.expireTime, flashProduct: store.flashProduct, + flashVendor: store.flashVendor, guid: store.guid, + locale: store.locale, name: store.name, osVersion: store.osVersion, osVersionBranch: store.osVersionBranch, registered: store.registered ?? false, + regExp: store.regExp, + regGen: store.regGen, + regGuid: store.regGuid, regTy: store.regTy, + regUpdatesExpired: store.regUpdatesExpired, + state: store.state, + wanFQDN: store.wanFQDN, + }), + }, + serverAccountPayload: { + get: () => ({ + deviceCount: store.deviceCount, + description: store.description, + expireTime: store.expireTime, + flashProduct: store.flashProduct, + flashVendor: store.flashVendor, + guid: store.guid, + keyfile: store.keyfile, + locale: store.locale, + name: store.name, + osVersion: store.osVersion, + osVersionBranch: store.osVersionBranch, + registered: store.registered ?? false, + regExp: store.regExp, + regGen: store.regGen, + regGuid: store.regGuid, + regTy: store.regTy, + regUpdatesExpired: store.regUpdatesExpired, state: store.state, wanFQDN: store.wanFQDN, }), @@ -549,49 +557,65 @@ describe('useServerStore', () => { const store = getStore(); store.setServer({ - apiVersion: '1.0.0', - connectPluginVersion: '2.0.0', deviceCount: 6, - email: 'test@example.com', + description: 'Test Server', + expireTime: 123, + flashProduct: 'TestFlash', + flashVendor: 'TestVendor', guid: '123456', - inIframe: false, locale: 'en-US', + name: 'TestServer', osVersion: '6.10.3', osVersionBranch: 'stable', registered: true, + regGen: 7, + regGuid: 'reg-guid-1', regExp: 1234567890, regTy: 'Plus', state: 'PLUS' as ServerState, - site: 'local', + wanFQDN: 'test.myunraid.net', }); const payload = store.serverPurchasePayload; - expect(payload.apiVersion).toBe('1.0.0'); - expect(payload.connectPluginVersion).toBe('2.0.0'); + expect(payload.description).toBe('Test Server'); expect(payload.deviceCount).toBe(6); - expect(payload.email).toBe('test@example.com'); + expect(payload.expireTime).toBe(123); + expect(payload.flashProduct).toBe('TestFlash'); + expect(payload.flashVendor).toBe('TestVendor'); expect(payload.guid).toBe('123456'); - expect(payload.keyTypeForPurchase).toBe('Plus'); expect(payload.locale).toBe('en-US'); + expect(payload.name).toBe('TestServer'); expect(payload.osVersion).toBe('6.10.3'); + expect(payload.osVersionBranch).toBe('stable'); expect(payload.registered).toBe(true); + expect(payload.regExp).toBe(1234567890); + expect(payload.regGen).toBe(7); + expect(payload.regGuid).toBe('reg-guid-1'); + expect(payload.regTy).toBe('Plus'); + expect(payload.state).toBe('PLUS'); + expect(payload.wanFQDN).toBe('test.myunraid.net'); }); it('should create serverAccountPayload correctly', () => { const store = getStore(); store.setServer({ - apiVersion: '1.0.0', - caseModel: 'TestCase', - connectPluginVersion: '2.0.0', deviceCount: 6, description: 'Test Server', + expireTime: 123, flashProduct: 'TestFlash', + flashVendor: 'TestVendor', guid: '123456', + keyfile: '/boot/config/Plus.key', + locale: 'en-US', name: 'TestServer', osVersion: '6.10.3', + osVersionBranch: 'stable', registered: true, + regExp: 1234567890, + regGen: 7, + regGuid: 'reg-guid-1', regTy: 'Plus', state: 'PLUS' as ServerState, wanFQDN: 'test.myunraid.net', @@ -599,16 +623,23 @@ describe('useServerStore', () => { const payload = store.serverAccountPayload; - expect(payload.apiVersion).toBe('1.0.0'); - expect(payload.caseModel).toBe('TestCase'); - expect(payload.connectPluginVersion).toBe('2.0.0'); + expect(payload.deviceCount).toBe(6); expect(payload.description).toBe('Test Server'); + expect(payload.expireTime).toBe(123); expect(payload.flashProduct).toBe('TestFlash'); + expect(payload.flashVendor).toBe('TestVendor'); expect(payload.guid).toBe('123456'); + expect(payload.keyfile).toBe('/boot/config/Plus.key'); + expect(payload.locale).toBe('en-US'); expect(payload.name).toBe('TestServer'); expect(payload.osVersion).toBe('6.10.3'); + expect(payload.osVersionBranch).toBe('stable'); expect(payload.registered).toBe(true); + expect(payload.regExp).toBe(1234567890); + expect(payload.regGen).toBe(7); + expect(payload.regGuid).toBe('reg-guid-1'); expect(payload.regTy).toBe('Plus'); + expect(payload.regUpdatesExpired).toBe(true); expect(payload.state).toBe('PLUS'); expect(payload.wanFQDN).toBe('test.myunraid.net'); }); diff --git a/web/package.json b/web/package.json index e5ee057f1..71b8e4312 100644 --- a/web/package.json +++ b/web/package.json @@ -109,7 +109,7 @@ "@jsonforms/vue-vanilla": "3.6.0", "@jsonforms/vue-vuetify": "3.6.0", "@nuxt/ui": "4.0.0-alpha.0", - "@unraid/shared-callbacks": "1.1.1", + "@unraid/shared-callbacks": "3.0.0", "@unraid/ui": "link:../unraid-ui", "@vue/apollo-composable": "4.2.2", "@vueuse/components": "13.8.0", diff --git a/web/src/composables/dateTime.ts b/web/src/composables/dateTime.ts index 9c1acf565..753adfc5b 100644 --- a/web/src/composables/dateTime.ts +++ b/web/src/composables/dateTime.ts @@ -101,15 +101,23 @@ const useDateTimeHelper = ( ): DateFormatOption | TimeFormatOption | undefined => formats.find((formatOption) => formatOption.format === selectedFormat); - const dateFormat = findMatchingFormat(format?.date ?? dateFormatOptions[0].format, dateFormatOptions); + const defaultTimeFormat = timeFormatOptions[0]; + const fallbackDateDisplayFormat = 'dddd, MMMM D, YYYY'; - let displayFormat = `${dateFormat?.display}`; + const dateFormatFromServer = (format?.date ?? '').trim(); + const dateFormat = dateFormatFromServer + ? (findMatchingFormat(dateFormatFromServer, dateFormatOptions) as DateFormatOption | undefined) + : undefined; + + let displayFormat = dateFormat?.display ?? fallbackDateDisplayFormat; if (!hideMinutesSeconds) { - const timeFormat = findMatchingFormat( - format?.time ?? timeFormatOptions[0].format, - timeFormatOptions - ); - displayFormat = `${displayFormat} ${timeFormat?.display}`; + const timeFormatFromServer = (format?.time ?? '').trim(); + const timeFormat = timeFormatFromServer + ? (findMatchingFormat(timeFormatFromServer, timeFormatOptions) as TimeFormatOption | undefined) + : undefined; + + const timeDisplay = timeFormat?.display ?? defaultTimeFormat.display; + displayFormat = `${displayFormat} ${timeDisplay}`; } const formatDate = (date: number): string => dayjs(date).format(displayFormat); diff --git a/web/src/helpers/urls.ts b/web/src/helpers/urls.ts index faf2caf80..e20425f6e 100644 --- a/web/src/helpers/urls.ts +++ b/web/src/helpers/urls.ts @@ -16,7 +16,7 @@ const CONNECT_DASHBOARD = new URL(import.meta.env.VITE_CONNECT ?? 'https://conne const CONNECT_FORUMS = new URL('/forum/94-connect-plugin-support/', FORUMS); const CONTACT = new URL('/contact', UNRAID_NET); const DISCORD = new URL('https://discord.unraid.net'); -const PURCHASE_CALLBACK = new URL('/c', UNRAID_NET); +const PURCHASE_CALLBACK = new URL('c', ACCOUNT); const UNRAID_NET_SUPPORT = new URL('/support', UNRAID_NET); const WEBGUI_GRAPHQL = '/graphql'; diff --git a/web/src/pages/apikeys.vue b/web/src/pages/apikeys.vue deleted file mode 100644 index 8ede0a61b..000000000 --- a/web/src/pages/apikeys.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/web/src/pages/changelog.vue b/web/src/pages/changelog.vue deleted file mode 100644 index 9636bbb77..000000000 --- a/web/src/pages/changelog.vue +++ /dev/null @@ -1,116 +0,0 @@ - - - diff --git a/web/src/pages/flashbackup.vue b/web/src/pages/flashbackup.vue deleted file mode 100644 index bb5ba578b..000000000 --- a/web/src/pages/flashbackup.vue +++ /dev/null @@ -1,17 +0,0 @@ - - - diff --git a/web/src/pages/index.vue b/web/src/pages/index.vue deleted file mode 100644 index fc835f81d..000000000 --- a/web/src/pages/index.vue +++ /dev/null @@ -1,200 +0,0 @@ - - - diff --git a/web/src/pages/login.query.ts b/web/src/pages/login.query.ts deleted file mode 100644 index 5940cf1e2..000000000 --- a/web/src/pages/login.query.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { gql } from '@apollo/client/core'; - -export const SERVER_INFO_QUERY = gql` - query serverInfo { - info { - os { - hostname - } - } - vars { - comment - } - } -`; diff --git a/web/src/pages/login.vue b/web/src/pages/login.vue deleted file mode 100644 index bab79dd53..000000000 --- a/web/src/pages/login.vue +++ /dev/null @@ -1,494 +0,0 @@ - - - - diff --git a/web/src/pages/redirect.vue b/web/src/pages/redirect.vue deleted file mode 100644 index 64838c651..000000000 --- a/web/src/pages/redirect.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - diff --git a/web/src/pages/tools/apikeyauthorize.vue b/web/src/pages/tools/apikeyauthorize.vue deleted file mode 100644 index 8c83d7ffe..000000000 --- a/web/src/pages/tools/apikeyauthorize.vue +++ /dev/null @@ -1,7 +0,0 @@ - - - diff --git a/web/src/pages/tools/test-update-modal.vue b/web/src/pages/tools/test-update-modal.vue deleted file mode 100644 index 74ca039e8..000000000 --- a/web/src/pages/tools/test-update-modal.vue +++ /dev/null @@ -1,285 +0,0 @@ - - - diff --git a/web/src/pages/welcome.vue b/web/src/pages/welcome.vue deleted file mode 100644 index e14154f89..000000000 --- a/web/src/pages/welcome.vue +++ /dev/null @@ -1,65 +0,0 @@ - - - diff --git a/web/src/store/server.ts b/web/src/store/server.ts index aaa3f185e..b86f0dcab 100644 --- a/web/src/store/server.ts +++ b/web/src/store/server.ts @@ -24,22 +24,19 @@ import dayjs from 'dayjs'; import prerelease from 'semver/functions/prerelease'; import type { ApolloQueryResult } from '@apollo/client/core/index.js'; +import type { ServerActionTypes, ServerData } from '@unraid/shared-callbacks'; import type { Config, PartialCloudFragment, ServerStateQuery } from '~/composables/gql/graphql'; import type { Error } from '~/store/errors'; import type { Theme } from '~/themes/types'; import type { Server, - ServerAccountCallbackSendPayload, ServerconnectPluginInstalled, ServerDateTimeFormat, - ServerKeyTypeForPurchase, ServerOsVersionBranch, - ServerPurchaseCallbackSendPayload, ServerState, ServerStateArray, ServerStateData, ServerStateDataAction, - ServerStateDataKeyActions, ServerUpdateOsResponse, } from '~/types/server'; @@ -224,73 +221,49 @@ export const useServerStore = defineStore('server', () => { }; }); - const serverPurchasePayload = computed((): ServerPurchaseCallbackSendPayload => { - /** @todo refactor out. Just parse state on craft site to determine */ - let keyTypeForPurchase: ServerKeyTypeForPurchase = 'Trial'; - switch (state.value) { - case 'BASIC': - keyTypeForPurchase = 'Basic'; - break; - case 'PLUS': - keyTypeForPurchase = 'Plus'; - break; - case 'PRO': - keyTypeForPurchase = 'Pro'; - break; - case 'STARTER': - keyTypeForPurchase = 'Starter'; - break; - case 'UNLEASHED': - keyTypeForPurchase = 'Unleashed'; - break; - } - const server: ServerPurchaseCallbackSendPayload = { - apiVersion: apiVersion.value, - connectPluginVersion: connectPluginVersion.value, + const serverPurchasePayload = computed((): ServerData => { + const server: ServerData = { + description: description.value, deviceCount: deviceCount.value, - email: email.value, + expireTime: expireTime.value, + flashProduct: flashProduct.value, + flashVendor: flashVendor.value, guid: guid.value, - inIframe: inIframe.value, - keyTypeForPurchase, locale: locale.value, + name: name.value, osVersion: osVersion.value, osVersionBranch: osVersionBranch.value, registered: registered.value ?? false, regExp: regExp.value, + regGen: regGen.value, + regGuid: regGuid.value, regTy: regTy.value, regUpdatesExpired: regUpdatesExpired.value, state: state.value, - site: site.value, + wanFQDN: wanFQDN.value, }; return server; }); - const serverAccountPayload = computed((): ServerAccountCallbackSendPayload => { + const serverAccountPayload = computed((): ServerData => { return { - apiVersion: apiVersion.value, - caseModel: caseModel.value, - connectPluginVersion: connectPluginVersion.value, deviceCount: deviceCount.value, description: description.value, expireTime: expireTime.value, - flashBackupActivated: flashBackupActivated.value, flashProduct: flashProduct.value, flashVendor: flashVendor.value, guid: guid.value, - inIframe: inIframe.value, keyfile: keyfile.value, - lanIp: lanIp.value, + locale: locale.value, name: name.value, osVersion: osVersion.value, osVersionBranch: osVersionBranch.value, - rebootType: rebootType.value, - rebootVersion: rebootVersion.value, registered: registered.value ?? false, + regGen: regGen.value, regGuid: regGuid.value, regExp: regExp.value, regTy: regTy.value, regUpdatesExpired: regUpdatesExpired.value, - site: site.value, state: state.value, wanFQDN: wanFQDN.value, }; @@ -1301,16 +1274,14 @@ export const useServerStore = defineStore('server', () => { const filteredKeyActions = ( filterType: 'by' | 'out', - filters: string | ServerStateDataKeyActions[] + filters: ServerActionTypes[] ): ServerStateDataAction[] | undefined => { if (!stateData.value.actions) { return; } return stateData.value.actions.filter((action) => { - return filterType === 'out' - ? !filters.includes(action.name as ServerStateDataKeyActions) - : filters.includes(action.name as ServerStateDataKeyActions); + return filterType === 'out' ? !filters.includes(action.name) : filters.includes(action.name); }); }; diff --git a/web/types/server.ts b/web/types/server.ts index 022ade1cf..8045936f7 100644 --- a/web/types/server.ts +++ b/web/types/server.ts @@ -1,3 +1,4 @@ +import type { ServerActionTypes } from '@unraid/shared-callbacks'; import type { ActivationCode, Config, PartialCloudFragment } from '~/composables/gql/graphql'; import type { Theme } from '~/themes/types'; import type { UserProfileLink } from '~/types/userProfile'; @@ -29,6 +30,7 @@ export type ServerState = | 'STARTER' | 'UNLEASHED' | 'LIFETIME' + | 'STALE' | undefined; export type ServerOsVersionBranch = 'stable' | 'next' | 'preview' | 'test'; @@ -124,78 +126,8 @@ export interface Server { wanIp?: string; } -export interface ServerAccountCallbackSendPayload { - activationCodeData?: ActivationCode; - apiVersion?: string; - caseModel?: string; - connectPluginVersion?: string; - description?: string; - deviceCount?: number; - expireTime?: number; - flashBackupActivated?: boolean; - flashProduct?: string; - flashVendor?: string; - guid?: string; - inIframe: boolean; - keyfile?: string; - lanIp?: string; - locale?: string; - name?: string; - osVersion?: string; - osVersionBranch?: ServerOsVersionBranch; - rebootType?: ServerRebootType; - rebootVersion?: string; - registered: boolean; - regExp?: number; - regGen?: number; - regGuid?: string; - regTy?: string; - regUpdatesExpired?: boolean; - site?: string; - state: ServerState; - wanFQDN?: string; -} - -export type ServerKeyTypeForPurchase = 'Basic' | 'Plus' | 'Pro' | 'Starter' | 'Trial' | 'Unleashed'; - -export interface ServerPurchaseCallbackSendPayload { - activationCodeData?: ActivationCode; - apiVersion?: string; - connectPluginVersion?: string; - deviceCount: number; - email: string; - guid: string; - inIframe: boolean; - keyTypeForPurchase: ServerKeyTypeForPurchase; - locale: string; - osVersion?: string; - osVersionBranch?: ServerOsVersionBranch; - registered: boolean; - regExp?: number; - regTy?: string; - regUpdatesExpired?: boolean; - state: ServerState; - site: string; -} - -export type ServerStateDataKeyActions = - | 'activate' - | 'purchase' - | 'redeem' - | 'upgrade' - | 'recover' - | 'renew' - | 'replace' - | 'trialExtend' - | 'trialStart' - | 'updateOs'; - -export type ServerStateDataAccountActions = 'signIn' | 'signOut' | 'troubleshoot'; - -export type ServerStateDataActionType = ServerStateDataKeyActions | ServerStateDataAccountActions; - -export interface ServerStateDataAction extends UserProfileLink { - name: ServerStateDataActionType; +export interface ServerStateDataAction extends UserProfileLink { + name: ServerActionTypes; } export interface ServerStateDataError { diff --git a/web/types/userProfile.ts b/web/types/userProfile.ts index a9f62950a..33e198b98 100644 --- a/web/types/userProfile.ts +++ b/web/types/userProfile.ts @@ -8,7 +8,7 @@ export type UserProfileLinkClick = | ((...args: UserProfileLinkClickParams[]) => void | Promise) | ((...args: UserProfileLinkClickParams[]) => Promise); -export interface UserProfileLink { +export interface UserProfileLink { click?: UserProfileLinkClick; clickParams?: UserProfileLinkClickParams; disabled?: boolean; @@ -16,7 +16,7 @@ export interface UserProfileLink { external?: boolean; href?: string; icon?: typeof ArrowTopRightOnSquareIcon; - name?: string; + name?: Name; text: string; textParams?: string[] | number[]; title?: string;