mirror of
https://github.com/unraid/api.git
synced 2026-01-06 00:30:22 -06:00
refactor: unraid-ui-web-migration (#1106)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced enhanced stepper components for smoother multi-step interactions. - Added new loading indicators and improved the loading experience with customizable variants. - **UI Improvements** - Refreshed the global color palette and updated styling across buttons, badges, and loading indicators for a more modern, consistent experience. - Improved the organization and readability of templates and styles across various components. - **Code & Dependency Updates** - Updated key dependencies and revised the theme and configuration settings to improve performance and maintainability. - Introduced new environment variables for better configuration management. - **Legacy Cleanup** - Removed deprecated components and streamlined registrations to simplify the codebase without affecting end-user functionality. - Eliminated unused utility functions and legacy code to enhance overall code quality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: mdatelle <mike@datelle.net> Co-authored-by: Eli Bosley <ekbosley@gmail.com>
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
<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 { storeToRefs } from 'pinia';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
|
||||
import {
|
||||
CheckIcon,
|
||||
ChevronDoubleDownIcon,
|
||||
@@ -9,16 +12,17 @@ import {
|
||||
WrenchScrewdriverIcon,
|
||||
XMarkIcon,
|
||||
} from '@heroicons/vue/24/solid';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import { BrandButton, BrandLoading } from '@unraid/ui';
|
||||
import { WEBGUI_CONNECT_SETTINGS, WEBGUI_TOOLS_REGISTRATION } from '~/helpers/urls';
|
||||
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useAccountStore } from '~/store/account';
|
||||
import { useCallbackActionsStore } from '~/store/callbackActions';
|
||||
import { useInstallKeyStore } from '~/store/installKey';
|
||||
// import { usePromoStore } from '~/store/promo';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsActionsStore } from '~/store/updateOsActions';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
export interface Props {
|
||||
open?: boolean;
|
||||
@@ -366,7 +370,7 @@ const showUpdateEligibility = computed(() => {
|
||||
<template v-if="callbackStatus === 'success' || updateOsStatus === 'confirming'" #footer>
|
||||
<div class="flex flex-row justify-center gap-16px">
|
||||
<template v-if="callbackStatus === 'success'">
|
||||
<BrandButton btn-style="underline" :icon="XMarkIcon" :text="closeText" @click="close" />
|
||||
<BrandButton variant="underline" :icon="XMarkIcon" :text="closeText" @click="close" />
|
||||
|
||||
<template v-if="connectPluginInstalled && accountActionType === 'signIn'">
|
||||
<BrandButton
|
||||
@@ -394,7 +398,7 @@ const showUpdateEligibility = computed(() => {
|
||||
|
||||
<template v-if="updateOsStatus === 'confirming' && !stateDataError">
|
||||
<BrandButton
|
||||
btn-style="underline"
|
||||
variant="underline"
|
||||
:icon="XMarkIcon"
|
||||
:text="t('Cancel')"
|
||||
@click="cancelUpdateOs"
|
||||
@@ -423,6 +427,7 @@ const showUpdateEligibility = computed(() => {
|
||||
<style lang="postcss">
|
||||
/* Import unraid-ui globals first */
|
||||
@import '@unraid/ui/styles';
|
||||
@import '../../assets/main.css';
|
||||
|
||||
.unraid_mark_2,
|
||||
.unraid_mark_4 {
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { ExclamationTriangleIcon, CheckCircleIcon, UserCircleIcon } from '@heroicons/vue/24/solid';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { CheckCircleIcon, ExclamationTriangleIcon, UserCircleIcon } from '@heroicons/vue/24/solid';
|
||||
import { BrandLoading } from '@unraid/ui';
|
||||
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import BrandLoading from '~/components/Brand/Loading.vue';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
|
||||
const props = defineProps<{ t: ComposerTranslation; }>();
|
||||
const props = defineProps<{ t: ComposerTranslation }>();
|
||||
|
||||
const { username } = storeToRefs(useServerStore());
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import {
|
||||
ArrowPathIcon,
|
||||
ArrowTopRightOnSquareIcon,
|
||||
@@ -9,22 +10,24 @@ import {
|
||||
KeyIcon,
|
||||
UserIcon,
|
||||
} from '@heroicons/vue/24/solid';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { BrandLogoConnect } from '@unraid/ui';
|
||||
import {
|
||||
CONNECT_DASHBOARD,
|
||||
WEBGUI_CONNECT_SETTINGS,
|
||||
WEBGUI_TOOLS_REGISTRATION,
|
||||
WEBGUI_TOOLS_DOWNGRADE,
|
||||
WEBGUI_TOOLS_REGISTRATION,
|
||||
WEBGUI_TOOLS_UPDATE,
|
||||
} from '~/helpers/urls';
|
||||
|
||||
import type { UserProfileLink } from '~/types/userProfile';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useAccountStore } from '~/store/account';
|
||||
import { useErrorsStore } from '~/store/errors';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUpdateOsStore } from '~/store/updateOs';
|
||||
import type { UserProfileLink } from '~/types/userProfile';
|
||||
|
||||
const props = defineProps<{ t: ComposerTranslation; }>();
|
||||
const props = defineProps<{ t: ComposerTranslation }>();
|
||||
|
||||
const accountStore = useAccountStore();
|
||||
const errorsStore = useErrorsStore();
|
||||
@@ -40,23 +43,29 @@ const {
|
||||
stateData,
|
||||
stateDataError,
|
||||
} = storeToRefs(useServerStore());
|
||||
const {
|
||||
available: osUpdateAvailable,
|
||||
availableWithRenewal: osUpdateAvailableWithRenewal,
|
||||
} = storeToRefs(updateOsStore);
|
||||
const { available: osUpdateAvailable, availableWithRenewal: osUpdateAvailableWithRenewal } =
|
||||
storeToRefs(updateOsStore);
|
||||
|
||||
const signInAction = computed(() => stateData.value.actions?.filter((act: { name: string; }) => act.name === 'signIn') ?? []);
|
||||
const signOutAction = computed(() => stateData.value.actions?.filter((act: { name: string; }) => act.name === 'signOut') ?? []);
|
||||
const signInAction = computed(
|
||||
() => stateData.value.actions?.filter((act: { name: string }) => act.name === 'signIn') ?? []
|
||||
);
|
||||
const signOutAction = computed(
|
||||
() => stateData.value.actions?.filter((act: { name: string }) => act.name === 'signOut') ?? []
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter out the renew action from the key actions so we can display it separately and link to the Tools > Registration page
|
||||
*/
|
||||
const filteredKeyActions = computed(() => keyActions.value?.filter(action => !['renew'].includes(action.name)));
|
||||
const filteredKeyActions = computed(() =>
|
||||
keyActions.value?.filter((action) => !['renew'].includes(action.name))
|
||||
);
|
||||
|
||||
const manageUnraidNetAccount = computed((): UserProfileLink => {
|
||||
return {
|
||||
external: true,
|
||||
click: () => { accountStore.manage(); },
|
||||
click: () => {
|
||||
accountStore.manage();
|
||||
},
|
||||
icon: UserIcon,
|
||||
text: props.t('Manage Unraid.net Account'),
|
||||
title: props.t('Manage Unraid.net Account in new tab'),
|
||||
@@ -86,13 +95,15 @@ const updateOsResponseModalOpenButton = computed((): UserProfileLink => {
|
||||
});
|
||||
const rebootDetectedButton = computed((): UserProfileLink => {
|
||||
return {
|
||||
href: rebootType.value === 'downgrade'
|
||||
? WEBGUI_TOOLS_DOWNGRADE.toString()
|
||||
: WEBGUI_TOOLS_UPDATE.toString(),
|
||||
href:
|
||||
rebootType.value === 'downgrade'
|
||||
? WEBGUI_TOOLS_DOWNGRADE.toString()
|
||||
: WEBGUI_TOOLS_UPDATE.toString(),
|
||||
icon: ExclamationTriangleIcon,
|
||||
text: rebootType.value === 'downgrade'
|
||||
? props.t('Reboot Required for Downgrade')
|
||||
: props.t('Reboot Required for Update'),
|
||||
text:
|
||||
rebootType.value === 'downgrade'
|
||||
? props.t('Reboot Required for Downgrade')
|
||||
: props.t('Reboot Required for Update'),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -111,15 +122,17 @@ const updateOsButton = computed((): UserProfileLink[] => {
|
||||
return btns;
|
||||
});
|
||||
|
||||
const links = computed(():UserProfileLink[] => {
|
||||
const links = computed((): UserProfileLink[] => {
|
||||
return [
|
||||
...(regUpdatesExpired.value
|
||||
? [{
|
||||
href: WEBGUI_TOOLS_REGISTRATION.toString(),
|
||||
icon: KeyIcon,
|
||||
text: props.t('OS Update Eligibility Expired'),
|
||||
title: props.t('Go to Tools > Registration to Learn More'),
|
||||
}]
|
||||
? [
|
||||
{
|
||||
href: WEBGUI_TOOLS_REGISTRATION.toString(),
|
||||
icon: KeyIcon,
|
||||
text: props.t('OS Update Eligibility Expired'),
|
||||
title: props.t('Go to Tools > Registration to Learn More'),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
|
||||
// ensure we only show the update button when we don't have an error
|
||||
@@ -136,31 +149,36 @@ const links = computed(():UserProfileLink[] => {
|
||||
text: props.t('Go to Connect'),
|
||||
title: props.t('Opens Connect in new tab'),
|
||||
},
|
||||
...([manageUnraidNetAccount.value]),
|
||||
...[manageUnraidNetAccount.value],
|
||||
{
|
||||
href: WEBGUI_CONNECT_SETTINGS.toString(),
|
||||
icon: CogIcon,
|
||||
text: props.t('Settings'),
|
||||
title: props.t('Go to Connect plugin settings'),
|
||||
},
|
||||
...(signOutAction.value),
|
||||
...signOutAction.value,
|
||||
]
|
||||
: [
|
||||
...([manageUnraidNetAccount.value]),
|
||||
]
|
||||
),
|
||||
: [...[manageUnraidNetAccount.value]]),
|
||||
];
|
||||
});
|
||||
|
||||
const showErrors = computed(() => errors.value.length);
|
||||
const showConnectStatus = computed(() => !showErrors.value && !stateData.value.error && registered.value && connectPluginInstalled.value);
|
||||
const showKeyline = computed(() =>
|
||||
(showConnectStatus.value && (keyActions.value?.length || links.value.length)) ||
|
||||
unraidConnectWelcome.value
|
||||
const showConnectStatus = computed(
|
||||
() => !showErrors.value && !stateData.value.error && registered.value && connectPluginInstalled.value
|
||||
);
|
||||
const showKeyline = computed(
|
||||
() =>
|
||||
(showConnectStatus.value && (keyActions.value?.length || links.value.length)) ||
|
||||
unraidConnectWelcome.value
|
||||
);
|
||||
|
||||
const unraidConnectWelcome = computed(() => {
|
||||
if (connectPluginInstalled.value && !registered.value && !errors.value.length && !stateDataError.value) {
|
||||
if (
|
||||
connectPluginInstalled.value &&
|
||||
!registered.value &&
|
||||
!errors.value.length &&
|
||||
!stateDataError.value
|
||||
) {
|
||||
return {
|
||||
heading: props.t('Thank you for installing Connect!'),
|
||||
message: props.t('Sign In to your Unraid.net account to get started'),
|
||||
@@ -172,9 +190,16 @@ const unraidConnectWelcome = computed(() => {
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-y-8px min-w-300px max-w-350px">
|
||||
<header v-if="connectPluginInstalled" class="flex flex-col items-start justify-between mt-8px mx-8px">
|
||||
<header
|
||||
v-if="connectPluginInstalled"
|
||||
class="flex flex-col items-start justify-between mt-8px mx-8px"
|
||||
>
|
||||
<h2 class="text-18px leading-none flex flex-row gap-x-4px items-center justify-between">
|
||||
<BrandLogoConnect gradient-start="currentcolor" gradient-stop="currentcolor" class="text-foreground w-[120px]" />
|
||||
<BrandLogoConnect
|
||||
gradient-start="currentcolor"
|
||||
gradient-stop="currentcolor"
|
||||
class="text-foreground w-[120px]"
|
||||
/>
|
||||
<UpcBeta />
|
||||
</h2>
|
||||
<template v-if="unraidConnectWelcome">
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
<script lang="ts" setup>
|
||||
import { BrandButton, BrandLoading } from '@unraid/ui';
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { h } from 'vue';
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { BrandButton, BrandLoading } from '@unraid/ui';
|
||||
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useServerStore } from '~/store/server';
|
||||
import { useUnraidApiStore } from '~/store/unraidApi';
|
||||
|
||||
defineProps<{ t: ComposerTranslation }>();
|
||||
|
||||
const BrandLoadingIcon = () => h(BrandLoading, { variant: 'white' });
|
||||
|
||||
const { expireTime, connectPluginInstalled, state, stateData } = storeToRefs(useServerStore());
|
||||
const { unraidApiStatus, unraidApiRestartAction } = storeToRefs(useUnraidApiStore());
|
||||
|
||||
@@ -35,11 +40,7 @@ const showExpireTime = computed(
|
||||
<BrandButton
|
||||
class="w-full"
|
||||
:disabled="unraidApiStatus === 'connecting' || unraidApiStatus === 'restarting'"
|
||||
:icon="
|
||||
unraidApiStatus === 'restarting'
|
||||
? h(BrandLoading, { variant: 'white' })
|
||||
: unraidApiRestartAction?.icon
|
||||
"
|
||||
:icon="unraidApiStatus === 'restarting' ? BrandLoadingIcon : unraidApiRestartAction?.icon"
|
||||
:text="
|
||||
unraidApiStatus === 'restarting' ? t('Restarting unraid-api…') : t('Restart unraid-api')
|
||||
"
|
||||
|
||||
@@ -2,16 +2,15 @@
|
||||
/**
|
||||
* @todo future idea – turn this into a carousel. each feature could have a short video if we ever them
|
||||
*/
|
||||
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
|
||||
import { ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/solid';
|
||||
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
|
||||
import { CONNECT_DOCS } from '~/helpers/urls';
|
||||
|
||||
import type { UserProfilePromoFeature } from '~/types/userProfile';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import useInstallPlugin from '~/composables/installPlugin';
|
||||
import { CONNECT_DOCS } from '~/helpers/urls';
|
||||
import { usePromoStore } from '~/store/promo';
|
||||
import type { UserProfilePromoFeature } from '~/types/userProfile';
|
||||
import 'tailwindcss/tailwind.css';
|
||||
import '~/assets/main.css';
|
||||
|
||||
export interface Props {
|
||||
open?: boolean;
|
||||
@@ -46,11 +45,11 @@ const features = ref<UserProfilePromoFeature[]>([
|
||||
},
|
||||
{
|
||||
title: 'Real-time Monitoring',
|
||||
copy: 'Get an overview of your server\'s state, storage space, apps and VMs status, and more.',
|
||||
copy: "Get an overview of your server's state, storage space, apps and VMs status, and more.",
|
||||
},
|
||||
{
|
||||
title: 'Customizable Dashboard Tiles',
|
||||
copy: 'Set custom server tiles how you like and automatically display your server\'s banner image on your Connect Dashboard.',
|
||||
copy: "Set custom server tiles how you like and automatically display your server's banner image on your Connect Dashboard.",
|
||||
},
|
||||
{
|
||||
title: 'License Management',
|
||||
@@ -65,7 +64,9 @@ const features = ref<UserProfilePromoFeature[]>([
|
||||
const staging = ref(false);
|
||||
|
||||
const connectPluginUrl = computed((): string => {
|
||||
const url = new URL(`https://sfo2.digitaloceanspaces.com/unraid-dl/unraid-api/dynamix.unraid.net${staging.value ? '.staging.plg' : '.plg'}`);
|
||||
const url = new URL(
|
||||
`https://sfo2.digitaloceanspaces.com/unraid-dl/unraid-api/dynamix.unraid.net${staging.value ? '.staging.plg' : '.plg'}`
|
||||
);
|
||||
return url.toString();
|
||||
});
|
||||
|
||||
@@ -102,8 +103,20 @@ const { install } = useInstallPlugin();
|
||||
<template #footer>
|
||||
<div class="w-full max-w-xs flex flex-col items-center gap-y-16px mx-auto">
|
||||
<SwitchGroup v-if="import.meta.env.DEV" as="div" class="flex items-center justify-center">
|
||||
<Switch v-model="staging" :class="[staging ? 'bg-indigo-600' : 'bg-gray-200', 'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2']">
|
||||
<span aria-hidden="true" :class="[staging ? 't-x-5' : 't-x-0', 'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out']" />
|
||||
<Switch
|
||||
v-model="staging"
|
||||
:class="[
|
||||
staging ? 'bg-indigo-600' : 'bg-gray-200',
|
||||
'relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2',
|
||||
]"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
:class="[
|
||||
staging ? 't-x-5' : 't-x-0',
|
||||
'pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
|
||||
]"
|
||||
/>
|
||||
</Switch>
|
||||
<SwitchLabel as="span" class="ml-3 text-12px">
|
||||
<span class="font-semibold">Install Staging</span>
|
||||
@@ -140,7 +153,7 @@ const { install } = useInstallPlugin();
|
||||
</template>
|
||||
|
||||
<style lang="postcss">
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
/* Import unraid-ui globals first */
|
||||
@import '@unraid/ui/styles';
|
||||
@import '../../assets/main.css';
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { storeToRefs } from 'pinia';
|
||||
|
||||
import { BrandLoading } from '@unraid/ui';
|
||||
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
|
||||
import { useTrialStore } from '~/store/trial';
|
||||
|
||||
Reference in New Issue
Block a user