Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugin/scripts/deploy-dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fi

if [ "$deploy" = "yes" ]; then
cd web || exit
npm run deploy-wc:dev
npm run deploy-to-unraid:dev
elif [ "$deploy" = "build" ]; then
cd web || exit
npm run build:dev
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ private function initializeTranslations()
'<p>Your Unraid registration key is ineligible for replacement as it has been replaced within the last 12 months.</p>' => '<p>' . _('Your Unraid registration key is ineligible for replacement as it has been replaced within the last 12 months.') . '</p>',
'A Trial key provides all the functionality of an Unleashed Registration key' => _('A Trial key provides all the functionality of an Unleashed Registration key'),
'Acklowledge that you have made a Flash Backup to enable this action' => _('Acklowledge that you have made a Flash Backup to enable this action'),
'Activate License' => _('Activate License'),
'Activate Now' => _('Activate Now'),
'ago' => _('ago'),
'All you need is an active internet connection, an Unraid.net account, and the Connect plugin. Get started by installing the plugin.' => _('All you need is an active internet connection, an Unraid.net account, and the Connect plugin.') . ' ' . _('Get started by installing the plugin.'),
Expand Down Expand Up @@ -119,11 +120,14 @@ private function initializeTranslations()
'Copy your Key URL: {0}' => sprintf(_('Copy your Key URL: %s'), '{0}'),
'Create Flash Backup' => _('Create Flash Backup'),
'Create a password' => _('Create a password'),
'Create an Unraid.net account and activate your key' => _('Create an Unraid.net account and activate your key'),
'Create Device Password' => _('Create Device Password'),
'Current Version {0}' => sprintf(_('Current Version %s'), '{0}'),
'Current Version: Unraid {0}' => sprintf(_('Current Version: Unraid %s'), '{0}'),
'Customizable Dashboard Tiles' => _('Customizable Dashboard Tiles'),
'day' => sprintf(_('%s day'), '{n}') . ' | ' . sprintf(_('%s days'), '{n}'),
'Deep Linking' => _('Deep Linking'),
'Device is ready to configure' => _('Device is ready to configure'),
'DNS issue, unable to resolve wanip4.unraid.net' => _('DNS issue, unable to resolve wanip4.unraid.net'),
'Downgrade Unraid OS to {0}' => sprintf(_('Downgrade Unraid OS to %s'), '{0}'),
'Downgrade Unraid OS' => _('Downgrade Unraid OS'),
Expand Down Expand Up @@ -206,7 +210,7 @@ private function initializeTranslations()
'Learn more and link your key to your account' => _('Learn more and link your key to your account'),
'Learn More' => _('Learn More'),
'Learn more' => _('Learn more'),
'Let\'s activate your Unraid license!' => _('Let\'s activate your Unraid license!'),
'Let\'s activate your Unraid OS License' => _('Let\'s activate your Unraid OS License'),
'Let\'s Unleash your Hardware!' => _('Let\'s Unleash your Hardware!'),
'License key actions' => _('License key actions'),
'License key type' => _('License key type'),
Expand Down Expand Up @@ -286,6 +290,7 @@ private function initializeTranslations()
'Requires the local unraid-api to be running successfully' => _('Requires the local unraid-api to be running successfully'),
'Restarting unraid-api…' => _('Restarting unraid-api…'),
'second' => sprintf(_('%s second'), '{n}') . ' | ' . sprintf(_('%s seconds'), '{n}'),
'Secure your device' => _('Secure your device'),
'Server Up Since {0}' => sprintf(_('Server Up Since %s'), '{0}'),
'Servers equipped with a myunraid.net certificate can be managed directly from within the Connect web UI. Manage multiple servers from your phone, tablet, laptop, or PC in the same browser window.' => _('Servers equipped with a myunraid.net certificate can be managed directly from within the Connect web UI.') . ' ' . _('Manage multiple servers from your phone, tablet, laptop, or PC in the same browser window.'),
'Set custom server tiles how you like and automatically display your server\'s banner image on your Connect Dashboard.' => _('Set custom server tiles how you like and automatically display your server\'s banner image on your Connect Dashboard.'),
Expand All @@ -307,7 +312,7 @@ private function initializeTranslations()
'SSL certificates for unraid.net deprecated' => _('SSL certificates for unraid.net deprecated'),
'Stale Server' => _('Stale Server'),
'Stale' => _('Stale'),
'Start by creating an Unraid.net account — this will let you manage your license and access support. Once that\'s done, we\'ll guide you through a quick checkout process to register your license and install your key.' => _('Start by creating an Unraid.net account — this will let you manage your license and access support.') . ' ' . _('Once that\'s done, we\'ll guide you through a quick checkout process to register your license and install your key.'),
'On the following screen, your license will be activated. You\'ll then create an Unraid.net Account to manage your license going forward.' => _('On the following screen, your license will be activated.') . ' ' . _('You\'ll then create an Unraid.net Account to manage your license going forward.'),
'Start Free 30 Day Trial' => _('Start Free 30 Day Trial'),
'Starting your free 30 day trial' => _('Starting your free 30 day trial'),
'Success!' => _('Success!'),
Expand Down
2 changes: 0 additions & 2 deletions web/_data/serverState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
;
// import dayjs, { extend } from 'dayjs';
// import customParseFormat from 'dayjs/plugin/customParseFormat';
// import relativeTime from 'dayjs/plugin/relativeTime';
Expand All @@ -11,7 +10,6 @@ import type { Server, ServerState
// ServerUpdateOsResponse,
} from '~/types/server';


// dayjs plugins
// extend(customParseFormat);
// extend(relativeTime);
Expand Down
76 changes: 41 additions & 35 deletions web/components/Activation/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ const activationCodeStore = useActivationCodeStore();
const { partnerLogo, showActivationModal } = storeToRefs(activationCodeStore);
const purchaseStore = usePurchaseStore();

const title = computed<string>(() => props.t("Let's activate your Unraid license!"));
const title = computed<string>(() => props.t("Let's activate your Unraid OS License"));
const description = computed<string>(() =>
props.t(
`Start by creating an Unraid.net account — this will let you manage your license and access support. Once that's done, we'll guide you through a quick checkout process to register your license and install your key.`
`On the following screen, your license will be activated. You’ll then create an Unraid.net Account to manage your license going forward.`
)
);
const docsButtons = computed<ButtonProps[]>(() => {
Expand All @@ -47,40 +47,41 @@ const docsButtons = computed<ButtonProps[]>(() => {
});

/**
* Listen for a key sequence to close the modal
* @todo - temporary solution until we have a better way to handle this
* Listen for konami code sequence to close the modal
*/
onMounted(() => {
const keySequence = [
"ArrowUp",
"ArrowUp",
"ArrowDown",
"ArrowDown",
"ArrowLeft",
"ArrowRight",
"ArrowLeft",
"ArrowRight",
"b",
"a",
];
let sequenceIndex = 0;
const keySequence = [
"ArrowUp",
"ArrowUp",
"ArrowDown",
"ArrowDown",
"ArrowLeft",
"ArrowRight",
"ArrowLeft",
"ArrowRight",
"b",
"a",
];
let sequenceIndex = 0;

const handleKeydown = (event: KeyboardEvent) => {
if (event.key === keySequence[sequenceIndex]) {
sequenceIndex++;
} else {
sequenceIndex = 0;
}

window.addEventListener("keydown", (event) => {
if (event.key === keySequence[sequenceIndex]) {
sequenceIndex++;
} else {
sequenceIndex = 0;
}
if (sequenceIndex === keySequence.length) {
activationCodeStore.setActivationModalHidden(true);
window.location.href = "/Tools/Registration";
}
};

if (sequenceIndex === keySequence.length) {
activationCodeStore.setActivationModalHidden(true);
window.location.href = "/Tools/Registration";
}
});
onMounted(() => {
window.addEventListener("keydown", handleKeydown);
});

onUnmounted(() => {
window.removeEventListener("keydown", () => {});
window.removeEventListener("keydown", handleKeydown);
});
</script>

Expand All @@ -103,11 +104,6 @@ onUnmounted(() => {
<ActivationPartnerLogo />
</template>

<template #main>
<div class="flex justify-center gap-4 mx-auto w-full">
<BrandButton v-for="button in docsButtons" :key="button.text" v-bind="button" />
</div>
</template>
<template #footer>
<div class="w-full flex gap-8px justify-center mx-auto">
<BrandButton
Expand All @@ -117,5 +113,15 @@ onUnmounted(() => {
/>
</div>
</template>

<template #subFooter>
<div class="flex flex-col gap-6">
<ActivationSteps :active-step="2" class="hidden sm:flex mt-6" />

<div class="flex flex-col sm:flex-row justify-center gap-4 mx-auto w-full">
<BrandButton v-for="button in docsButtons" :key="button.text" v-bind="button" />
</div>
</div>
</template>
</Modal>
</template>
119 changes: 119 additions & 0 deletions web/components/Activation/Steps.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<script setup lang="ts">
import { Button } from "@/components/shadcn/button";

import {
Stepper,
StepperDescription,
StepperItem,
StepperSeparator,
StepperTitle,
StepperTrigger,
} from "@/components/shadcn/stepper";
import { CheckIcon, KeyIcon, ServerStackIcon } from "@heroicons/vue/24/outline";
import {
KeyIcon as KeyIconSolid,
LockClosedIcon,
ServerStackIcon as ServerStackIconSolid,
} from "@heroicons/vue/24/solid";

import type { Component } from 'vue'

type StepState = "inactive" | "active" | "completed";

withDefaults(defineProps<{
activeStep: number
}>(), {
activeStep: 1
})

interface Step {
step: number;
title: string;
description: string;
icon: {
inactive: Component;
active: Component;
completed: Component;
};
};
const steps: readonly Step[] = [
{
step: 1,
title: "Create Device Password",
description: "Secure your device",
icon: {
inactive: LockClosedIcon,
active: LockClosedIcon,
completed: CheckIcon,
},
},
{
step: 2,
title: "Activate License",
description: "Create an Unraid.net account and activate your key",
icon: {
inactive: KeyIcon,
active: KeyIconSolid,
completed: CheckIcon,
},
},
{
step: 3,
title: "Unleash Your Hardware",
description: "Device is ready to configure",
icon: {
inactive: ServerStackIcon,
active: ServerStackIconSolid,
completed: CheckIcon,
},
},
] as const;
</script>

<template>
<Stepper
:default-value="activeStep"
class="text-foreground flex w-full items-start gap-2 text-16px"
>
<StepperItem
v-for="step in steps"
:key="step.step"
v-slot="{ state }: { state: StepState }"
class="relative flex w-full flex-col items-center justify-center"
:step="step.step"
:disabled="true"
>
<StepperSeparator
v-if="step.step !== steps[steps.length - 1].step"
class="absolute left-[calc(50%+20px)] right-[calc(-50%+10px)] top-[1.5rem] &block h-0.5 shrink-0 rounded-full bg-muted group-data-[state=completed]:bg-primary"
/>

<StepperTrigger as-child>
<Button
:variant="state === 'completed' || state === 'active' ? 'default' : 'outline'"
size="default"
class="z-10 rounded-full shrink-0 opacity-100"
:class="[
state !== 'inactive' &&
'ring-2 ring-primary ring-offset-2 ring-offset-background *:cursor-default',
]"
:disabled="state === 'inactive'"
>
<component :is="step.icon[state]" class="size-4" />
</Button>
</StepperTrigger>

<div class="mt-2 flex flex-col items-center text-center">
<StepperTitle
:class="[state === 'active' && 'text-primary']"
class="text-2xs font-semibold transition"
>
{{ step.title }}
</StepperTitle>
<StepperDescription class="text-2xs font-normal">
{{ step.description }}
</StepperDescription>
</div>
</StepperItem>
</Stepper>
</template>
23 changes: 19 additions & 4 deletions web/components/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,12 @@ const closeModal = () => {
const ariaLablledById = computed<string|undefined>(() => props.title ? `ModalTitle-${Math.random()}`.replace('0.', '') : undefined);
const computedVerticalCenter = computed<string>(() => {
if (props.tallContent) {
return 'items-start sm:items-center';
return 'justify-start sm:justify-center';
}
if (typeof props.modalVerticalCenter === 'string') {
return props.modalVerticalCenter;
}
return props.modalVerticalCenter ? 'items-center' : 'items-start';
return props.modalVerticalCenter ? 'justify-center' : 'justify-start';
});
</script>

Expand All @@ -78,7 +78,7 @@ const computedVerticalCenter = computed<string>(() => {
@keyup.esc="closeModal"
>
<div
class="fixed inset-0 flex min-h-screen w-screen justify-center p-8px sm:p-16px overflow-y-auto"
class="fixed inset-0 flex flex-col min-h-screen w-screen items-center p-8px sm:p-16px overflow-y-auto"
:class="computedVerticalCenter"
>
<TransitionChild
Expand Down Expand Up @@ -115,7 +115,7 @@ const computedVerticalCenter = computed<string>(() => {
success ? 'shadow-green-600/30 border-green-600/10' : '',
!error && !success && !disableShadow ? 'shadow-orange/10 border-white/10' : '',
]"
class="text-16px text-foreground bg-background text-left relative z-10 flex flex-col justify-around border-2 border-solid transform overflow-hidden rounded-lg transition-all sm:w-full"
class="text-16px text-foreground bg-background text-left relative z-10 mx-auto flex flex-col justify-around border-2 border-solid transform overflow-hidden rounded-lg transition-all sm:w-full"
>
<div v-if="showCloseX" class="absolute z-20 right-0 top-0 pt-4px pr-4px hidden sm:block">
<button
Expand Down Expand Up @@ -174,6 +174,21 @@ const computedVerticalCenter = computed<string>(() => {
</footer>
</div>
</TransitionChild>

<TransitionChild
appear
as="template"
enter="duration-300 ease-out"
enter-from="opacity-0"
enter-to="opacity-100"
leave="duration-200 ease-in"
leave-from="opacity-100"
leave-to="opacity-0"
>
<div v-if="$slots['subFooter']" class="mt-4 flex justify-center mx-auto" :class="[maxWidth]">
<slot name="subFooter" />
</div>
</TransitionChild>
</div>
</div>
</TransitionRoot>
Expand Down
7 changes: 6 additions & 1 deletion web/components/WelcomeModal.ce.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n';
import 'tailwindcss/tailwind.css';
import '~/assets/main.css';

import ActivationSteps from '~/components/Activation/Steps.vue';
import { useActivationCodeStore } from '~/store/activationCode';
import { useServerStore } from '~/store/server';
import type { Server } from '~/types/server';
Expand All @@ -28,7 +29,7 @@ const title = computed<string>(() =>
);

const description = computed<string>(() =>
t(`You're about to create a password to secure access to your system. This password is essential for managing and configuring your server. You’ll use this password every time you access the Unraid web interface.`)
t(`First, you’ll create your device’s login credentials, then you’ll activate your Unraid license—your device’s operating system (OS).`)
);

const showModal = ref<boolean>(true);
Expand Down Expand Up @@ -98,6 +99,10 @@ onBeforeMount(() => {
/>
</div>
</template>

<template #subFooter>
<ActivationSteps :active-step="1" class="hidden sm:flex mt-6" />
</template>
</Modal>
</div>
</template>
Expand Down
Loading
Loading