feat: vue components pass t prop

This commit is contained in:
Zack Spear
2023-08-01 15:20:30 -07:00
committed by Zack Spear
parent d6b8f8182c
commit 99b3037f0f
12 changed files with 93 additions and 71 deletions
+3 -4
View File
@@ -15,12 +15,11 @@ const { authAction, stateData } = storeToRefs(serverStore);
<template>
<div class="whitespace-normal flex flex-col gap-y-16px max-w-3xl">
<span v-if="stateData.error" class="text-unraid-red font-semibold leading-8">
<h3 class="text-14px mb-8px">{{ t(stateData.heading) }}</h3>
<span v-html="t(stateData.message)" />
<h3 class="text-16px mb-8px">{{ t(stateData.heading) }}</h3>
<span class="text-14px" v-html="t(stateData.message)" />
</span>
<span>
<span v-if="authAction">
<BrandButton
v-if="authAction"
:icon="authAction.icon"
:text="t(authAction.text)"
@click="authAction.click()"
+23 -16
View File
@@ -13,25 +13,32 @@ withDefaults(defineProps<Props>(), {
<template>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" data-name="Layer 1" viewBox="0 0 954.29 142.4">
<defs>
<linearGradient id="a" x1="-57.82" x2="923.39" y1="71.2" y2="71.2" gradientUnits="userSpaceOnUse">
<linearGradient
id="a"
x1="-57.82"
x2="923.39"
y1="71.2"
y2="71.2"
gradientUnits="userSpaceOnUse"
>
<stop offset="0" :stop-color="gradientStart" />
<stop offset="1" :stop-color="gradientStop" />
</linearGradient>
<linearGradient xlink:href="#a" id="b" x2="923.39"/>
<linearGradient xlink:href="#a" id="c" x2="923.39" y1="71.2" y2="71.2"/>
<linearGradient xlink:href="#a" id="d" x2="923.39" y1="71.2" y2="71.2"/>
<linearGradient xlink:href="#a" id="e" x2="923.39" y1="71.2" y2="71.2"/>
<linearGradient xlink:href="#a" id="f" x2="923.39"/>
<linearGradient xlink:href="#a" id="g" y1="12.16" y2="12.16"/>
<linearGradient xlink:href="#a" id="h" x2="923.39" y1="86.94" y2="86.94"/>
<linearGradient id="b" xlink:href="#a" x2="923.39" />
<linearGradient id="c" xlink:href="#a" x2="923.39" y1="71.2" y2="71.2" />
<linearGradient id="d" xlink:href="#a" x2="923.39" y1="71.2" y2="71.2" />
<linearGradient id="e" xlink:href="#a" x2="923.39" y1="71.2" y2="71.2" />
<linearGradient id="f" xlink:href="#a" x2="923.39" />
<linearGradient id="g" xlink:href="#a" y1="12.16" y2="12.16" />
<linearGradient id="h" xlink:href="#a" x2="923.39" y1="86.94" y2="86.94" />
</defs>
<path fill="url(#a)" d="M54.39 0C20.96 0 0 17.4 0 49.84v42.52c0 32.63 20.96 50.04 53.99 50.04s53.8-16.81 53.8-48.06v-.99H84.25v.99c0 17.8-11.47 27.49-30.26 27.49s-30.46-10.28-30.46-29.47V49.84c0-18.99 11.67-29.47 30.85-29.47s29.86 9.89 29.86 27.69v.79h23.54v-.79C107.79 16.81 87.02 0 54.39 0Z"/>
<path fill="url(#b)" d="M197.58 0c-33.42 0-54.59 17.4-54.59 49.84v42.52c0 32.63 21.16 50.04 54.19 50.04s54.59-17.4 54.59-50.04V49.84C251.77 17.4 230.61 0 197.58 0Zm30.66 92.36c0 19.18-11.87 29.47-31.05 29.47s-30.66-10.28-30.66-29.47V49.84c0-18.99 11.87-29.47 31.05-29.47s30.66 10.48 30.66 29.47v42.52Z"/>
<path fill="url(#c)" d="M373.8 97.31 312.49 1.98h-21.95v138.44h23.53V45.09l61.32 95.33h21.95V1.98H373.8v95.33z"/>
<path fill="url(#d)" d="M521.35 97.31 460.04 1.98h-21.96v138.44h23.54V45.09l61.31 95.33h21.95V1.98h-23.53v95.33z"/>
<path fill="url(#e)" d="M585.63 140.42h92.95v-20.57h-69.42V81.29h59.54V60.92h-59.54V22.35h69.42V1.98h-92.95v138.44z"/>
<path fill="url(#f)" d="M766.8 0c-33.43 0-54.39 17.4-54.39 49.84v42.52c0 32.63 20.96 50.04 53.99 50.04s53.8-16.81 53.8-48.06v-.99h-23.54v.99c0 17.8-11.47 27.49-30.26 27.49s-30.46-10.28-30.46-29.47V49.84c0-18.99 11.67-29.47 30.85-29.47s29.86 9.89 29.86 27.69v.79h23.54v-.79c0-31.25-20.77-48.06-53.4-48.06Z"/>
<path fill="url(#g)" d="M846.11 1.98h108.18v20.37H846.11z"/>
<path fill="url(#h)" d="M888.43 33.45h23.54v106.97h-23.54z"/>
<path fill="url(#a)" d="M54.39 0C20.96 0 0 17.4 0 49.84v42.52c0 32.63 20.96 50.04 53.99 50.04s53.8-16.81 53.8-48.06v-.99H84.25v.99c0 17.8-11.47 27.49-30.26 27.49s-30.46-10.28-30.46-29.47V49.84c0-18.99 11.67-29.47 30.85-29.47s29.86 9.89 29.86 27.69v.79h23.54v-.79C107.79 16.81 87.02 0 54.39 0Z" />
<path fill="url(#b)" d="M197.58 0c-33.42 0-54.59 17.4-54.59 49.84v42.52c0 32.63 21.16 50.04 54.19 50.04s54.59-17.4 54.59-50.04V49.84C251.77 17.4 230.61 0 197.58 0Zm30.66 92.36c0 19.18-11.87 29.47-31.05 29.47s-30.66-10.28-30.66-29.47V49.84c0-18.99 11.87-29.47 31.05-29.47s30.66 10.48 30.66 29.47v42.52Z" />
<path fill="url(#c)" d="M373.8 97.31 312.49 1.98h-21.95v138.44h23.53V45.09l61.32 95.33h21.95V1.98H373.8v95.33z" />
<path fill="url(#d)" d="M521.35 97.31 460.04 1.98h-21.96v138.44h23.54V45.09l61.31 95.33h21.95V1.98h-23.53v95.33z" />
<path fill="url(#e)" d="M585.63 140.42h92.95v-20.57h-69.42V81.29h59.54V60.92h-59.54V22.35h69.42V1.98h-92.95v138.44z" />
<path fill="url(#f)" d="M766.8 0c-33.43 0-54.39 17.4-54.39 49.84v42.52c0 32.63 20.96 50.04 53.99 50.04s53.8-16.81 53.8-48.06v-.99h-23.54v.99c0 17.8-11.47 27.49-30.26 27.49s-30.46-10.28-30.46-29.47V49.84c0-18.99 11.67-29.47 30.85-29.47s29.86 9.89 29.86 27.69v.79h23.54v-.79c0-31.25-20.77-48.06-53.4-48.06Z" />
<path fill="url(#g)" d="M846.11 1.98h108.18v20.37H846.11z" />
<path fill="url(#h)" d="M888.43 33.45h23.54v106.97h-23.54z" />
</svg>
</template>
+5 -5
View File
@@ -11,6 +11,8 @@ import type { Server } from '~/types/server';
import 'tailwindcss/tailwind.css';
import '~/assets/main.css';
const { t } = useI18n();
export interface Props {
server?: Server | string;
}
@@ -78,8 +80,6 @@ onBeforeMount(() => {
*/
callbackStore.watcher();
});
const { t } = useI18n();
</script>
<template>
@@ -89,7 +89,7 @@ const { t } = useI18n();
<div class="text-gamma text-10px xs:text-12px 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">
<UpcUptimeExpire />
<span class="hidden xs:block">&bull;</span>
<UpcServerState />
<UpcServerState :t="t" />
</div>
<div class="relative z-10 flex flex-row items-center justify-end gap-x-16px h-full">
@@ -113,8 +113,8 @@ const { t } = useI18n();
<div class="block w-2px h-24px bg-gamma" />
<OnClickOutside class="flex items-center justify-end h-full" :options="{ ignore: [clickOutsideIgnoreTarget] }" @trigger="outsideDropdown">
<UpcDropdownTrigger ref="clickOutsideIgnoreTarget" />
<UpcDropdown ref="clickOutsideTarget" />
<UpcDropdownTrigger ref="clickOutsideIgnoreTarget" :t="t" />
<UpcDropdown ref="clickOutsideTarget" :t="t" />
</OnClickOutside>
</div>
</div>
+4 -2
View File
@@ -5,6 +5,8 @@ import { storeToRefs } from 'pinia';
import { useDropdownStore } from '~/store/dropdown';
import { useServerStore } from '~/store/server';
defineProps<{ t: any; }>();
const dropdownStore = useDropdownStore();
const { dropdownVisible } = storeToRefs(dropdownStore);
const { connectPluginInstalled, registered, state, stateDataError } = storeToRefs(useServerStore());
@@ -25,8 +27,8 @@ const showLaunchpad = computed(() => state.value === 'ENOKEYFILE' || ((connectPl
leave-to="opacity-0 translate-y-[16px]"
>
<UpcDropdownWrapper class="DropdownWrapper_blip text-beta absolute z-30 top-full right-0 transition-all">
<UpcDropdownContent v-if="showDefaultContent" />
<UpcDropdownLaunchpad v-else />
<UpcDropdownContent v-if="showDefaultContent" :t="t" />
<UpcDropdownLaunchpad v-else :t="t" />
</UpcDropdownWrapper>
</TransitionRoot>
</template>
@@ -1,10 +1,12 @@
<script setup lang="ts">
import { ExclamationTriangleIcon, CheckCircleIcon } from '@heroicons/vue/24/solid';
import { storeToRefs } from 'pinia';
import BrandLoading from '~/components/Brand/Loading.vue';
import BrandLoading from '~/components/Brand/Loading.vue';
import { useUnraidApiStore } from '~/store/unraidApi';
const props = defineProps<{ t: any; }>();
const unraidApiStore = useUnraidApiStore();
const { unraidApiStatus, unraidApiRestartAction } = storeToRefs(unraidApiStore);
@@ -19,7 +21,7 @@ const status = computed((): StatusOutput | undefined => {
return {
icon: BrandLoading,
iconClasses: 'w-16px',
text: 'Loading…',
text: props.t('Loading…'),
textClasses: 'italic',
};
}
@@ -27,7 +29,7 @@ const status = computed((): StatusOutput | undefined => {
return {
icon: BrandLoading,
iconClasses: 'w-16px',
text: 'Restarting unraid-api…',
text: props.t('Restarting unraid-api…'),
textClasses: 'italic',
};
}
@@ -35,14 +37,14 @@ const status = computed((): StatusOutput | undefined => {
return {
icon: ExclamationTriangleIcon,
iconClasses: 'text-red-500 w-16px h-16px',
text: 'unraid-api is offline',
text: props.t('unraid-api is offline'),
};
}
if (unraidApiStatus.value === 'online') {
return {
icon: CheckCircleIcon,
iconClasses: 'text-red-500 w-16px h-16px',
text: 'Connected',
text: props.t('Connected'),
};
}
return undefined;
@@ -64,6 +66,6 @@ const status = computed((): StatusOutput | undefined => {
</span>
</li>
<li v-if="unraidApiRestartAction" class="w-full">
<UpcDropdownItem :item="unraidApiRestartAction" />
<UpcDropdownItem :item="unraidApiRestartAction" :t="t" />
</li>
</template>
+14 -12
View File
@@ -8,6 +8,8 @@ import { usePromoStore } from '~/store/promo';
import { useServerStore } from '~/store/server';
import type { UserProfileLink } from '~/types/userProfile';
const props = defineProps<{ t: any; }>();
const errorsStore = useErrorsStore();
const promoStore = usePromoStore();
@@ -26,21 +28,21 @@ const links = computed(():UserProfileLink[] => {
external: true,
href: CONNECT_DASHBOARD,
icon: ArrowTopRightOnSquareIcon,
text: 'Go to Connect',
title: 'Opens Connect in new tab',
text: props.t('Go to Connect'),
title: props.t('Opens Connect in new tab'),
},
{
external: true,
href: ACCOUNT,
icon: ArrowTopRightOnSquareIcon,
text: 'Manage Unraid.net Account',
title: 'Manage Unraid.net Account in new tab',
text: props.t('Manage Unraid.net Account'),
title: props.t('Manage Unraid.net Account in new tab'),
},
{
href: PLUGIN_SETTINGS,
icon: CogIcon,
text: 'Settings',
title: 'Go to Connect plugin settings',
text: props.t('Settings'),
title: props.t('Go to Connect plugin settings'),
},
...(signOutAction.value),
]
@@ -59,8 +61,8 @@ const links = computed(():UserProfileLink[] => {
promoStore.promoShow();
},
icon: InformationCircleIcon,
text: 'Enhance your Unraid experience with Connect',
title: 'Enhance your Unraid experience with Connect',
text: props.t('Enhance your Unraid experience with Connect'),
title: props.t('Enhance your Unraid experience with Connect'),
},
]
: []
@@ -82,8 +84,8 @@ const showKeyline = computed(() => showConnectStatus.value && (keyActions.value?
</h2>
</header>
<ul class="list-reset flex flex-col gap-y-4px p-0">
<UpcDropdownConnectStatus v-if="showConnectStatus" />
<UpcDropdownError v-if="showErrors" />
<UpcDropdownConnectStatus v-if="showConnectStatus" :t="t" />
<UpcDropdownError v-if="showErrors" :t="t" />
<li v-if="showKeyline" class="my-8px">
<UpcKeyline />
@@ -91,13 +93,13 @@ const showKeyline = computed(() => showConnectStatus.value && (keyActions.value?
<template v-if="keyActions">
<li v-for="action in keyActions" :key="action.name">
<UpcDropdownItem :item="action" />
<UpcDropdownItem :item="action" :t="t" />
</li>
</template>
<template v-if="links.length">
<li v-for="(link, index) in links" :key="`link_${index}`">
<UpcDropdownItem :item="link" />
<UpcDropdownItem :item="link" :t="t" />
</li>
</template>
</ul>
+5 -4
View File
@@ -4,6 +4,8 @@ import { storeToRefs } from 'pinia';
import { useErrorsStore } from '~/store/errors';
defineProps<{ t: any; }>();
const errorsStore = useErrorsStore();
const { errors } = storeToRefs(errorsStore);
</script>
@@ -12,13 +14,12 @@ const { errors } = storeToRefs(errorsStore);
<ul v-if="errors.length" class="list-reset flex flex-col gap-y-8px mb-4px border-2 border-solid border-unraid-red/90 rounded-md">
<li v-for="(error, index) in errors" :key="index" class="flex flex-col gap-8px">
<h3 class="text-18px py-4px px-12px text-white bg-unraid-red/90 font-semibold">
<span>{{ error.heading }}</span>
<span>{{ t(error.heading) }}</span>
</h3>
<!-- eslint-disable-next-line vue/no-v-html -->
<div class="text-14px px-12px" :class="{ 'pb-8px': !error.actions }" v-html="error.message" />
<div class="text-14px px-12px" :class="{ 'pb-8px': !error.actions }" v-html="t(error.message)" />
<nav v-if="error.actions">
<li v-for="(link, idx) in error.actions" :key="`link_${idx}`">
<UpcDropdownItem :item="link" :rounded="false" />
<UpcDropdownItem :item="link" :rounded="false" :t="t" />
</li>
</nav>
</li>
+2 -1
View File
@@ -6,6 +6,7 @@ import type { UserProfileLink } from '~/types/userProfile';
export interface Props {
item: ServerStateDataAction | UserProfileLink;
rounded?: boolean;
t: any;
}
const props = withDefaults(defineProps<Props>(), {
@@ -33,7 +34,7 @@ const showExternalIconOnHover = computed(() => props.item?.external && props.ite
>
<span class="leading-snug inline-flex flex-row items-center gap-x-8px">
<component :is="item?.icon" class="flex-shrink-0 text-current w-16px h-16px" aria-hidden="true" />
{{ item?.text }}
{{ t(item?.text) }}
</span>
<ArrowTopRightOnSquareIcon
v-if="showExternalIconOnHover"
+10 -8
View File
@@ -4,18 +4,20 @@ import { useServerStore } from '~/store/server';
import 'tailwindcss/tailwind.css';
import '~/assets/main.css';
const props = defineProps<{ t: any; }>();
const { expireTime, connectPluginInstalled, registered, state, stateData } = storeToRefs(useServerStore());
const showConnectCopy = computed(() => (connectPluginInstalled.value && !registered.value && !stateData.value?.error));
const heading = computed(() => {
if (showConnectCopy.value) return 'Thank you for installing Connect!';
return stateData.value.heading;
if (showConnectCopy.value) { return props.t('Thank you for installing Connect!'); }
return props.t(stateData.value.heading);
});
const subheading = computed(() => {
if (showConnectCopy.value) return 'Sign In to your Unraid.net account to get started';
return stateData.value.message;
if (showConnectCopy.value) { return props.t('Sign In to your Unraid.net account to get started'); }
return props.t(stateData.value.message);
});
const showExpireTime = computed(() => {
@@ -27,18 +29,18 @@ const showExpireTime = computed(() => {
<div class="flex flex-col gap-y-24px w-full min-w-300px md:min-w-[500px] max-w-xl p-16px">
<header :class="{ 'text-center': showConnectCopy }">
<h2 class="text-24px text-center font-semibold" v-html="heading" />
<div v-html="subheading" class="flex flex-col gap-y-8px" />
<div class="flex flex-col gap-y-8px" v-html="subheading" />
<UpcUptimeExpire v-if="showExpireTime" class="text-center opacity-75 mt-12px" />
</header>
<ul class="list-reset flex flex-col gap-y-8px px-16px" v-if="stateData.actions">
<ul v-if="stateData.actions" class="list-reset flex flex-col gap-y-8px px-16px">
<li v-for="action in stateData.actions" :key="action.name">
<BrandButton
class="w-full"
@click="action.click()"
:external="action?.external"
:href="action?.href"
:icon="action.icon"
:text="action.text"
:text="t(action.text)"
@click="action.click()"
/>
</li>
</ul>
+8 -5
View File
@@ -1,10 +1,13 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { InformationCircleIcon, ExclamationTriangleIcon, ShieldExclamationIcon } from '@heroicons/vue/24/solid';
import { useDropdownStore } from '~/store/dropdown';
import { useErrorsStore } from '~/store/errors';
import { useServerStore } from '~/store/server';
const props = defineProps<{ t: any; }>();
const dropdownStore = useDropdownStore();
const { dropdownVisible } = storeToRefs(dropdownStore);
const { errors } = storeToRefs(useErrorsStore());
@@ -20,15 +23,15 @@ const registeredAndconnectPluginInstalled = computed(() => connectPluginInstalle
const showErrorIcon = computed(() => errors.value.length || stateData.value.error);
const text = computed((): string | undefined => {
if ((stateData.value.error) && state.value !== 'EEXPIRED') { return 'Fix Error'; }
if ((stateData.value.error) && state.value !== 'EEXPIRED') { return props.t('Fix Error'); }
if (registeredAndconnectPluginInstalled.value) { return username.value; }
});
const title = computed((): string => {
if (state.value === 'ENOKEYFILE') { return 'Get Started'; }
if (state.value === 'EEXPIRED') { return 'Trial Expired, see options below'; }
if (showErrorIcon.value) { return 'Learn more about the error'; }
return dropdownVisible.value ? 'Close Dropdown' : 'Open Dropdown';
if (state.value === 'ENOKEYFILE') { return props.t('Get Started'); }
if (state.value === 'EEXPIRED') { return props.t('Trial Expired, see options below'); }
if (showErrorIcon.value) { return props.t('Learn more about the error'); }
return dropdownVisible.value ? props.t('Close Dropdown') : props.t('Open Dropdown');
});
</script>
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { Bars3Icon, XMarkIcon } from "@heroicons/vue/24/solid";
import { Bars3Icon, XMarkIcon } from '@heroicons/vue/24/solid';
export interface Props {
open?: boolean;
+10 -7
View File
@@ -1,8 +1,11 @@
<script setup lang="ts">
import { storeToRefs } from 'pinia';
import { useServerStore } from '~/store/server';
import type { ServerStateDataAction } from '~/types/server';
defineProps<{ t: any; }>();
const { state, stateData } = storeToRefs(useServerStore());
const purchaseAction = computed((): ServerStateDataAction | undefined => {
@@ -17,23 +20,23 @@ const upgradeAction = computed((): ServerStateDataAction | undefined => {
<span class="flex flex-row items-center gap-x-8px">
<template v-if="upgradeAction">
<UpcServerStateBuy
@click="upgradeAction.click()"
class="text-gamma"
:title="'Upgrade'"
:title="t('Upgrade')"
@click="upgradeAction.click()"
>
<h5>Unraid OS <em><strong>{{ stateData.humanReadable }}</strong></em></h5>
<h5>Unraid OS <em><strong>{{ t(stateData.humanReadable) }}</strong></em></h5>
</UpcServerStateBuy>
</template>
<h5 v-else>
Unraid OS <em :class="{ 'text-unraid-red': stateData.error || state === 'EEXPIRED' }"><strong>{{ stateData.humanReadable }}</strong></em>
Unraid OS <em :class="{ 'text-unraid-red': stateData.error || state === 'EEXPIRED' }"><strong>{{ t(stateData.humanReadable) }}</strong></em>
</h5>
<template v-if="purchaseAction">
<UpcServerStateBuy
@click="purchaseAction.click()"
class="text-orange-dark relative top-[1px] hidden sm:block"
:title="'Purchase'"
>{{ 'Purchase' }}</UpcServerStateBuy>
:title="t('Purchase')"
@click="purchaseAction.click()"
>{{ t('Purchase') }}</UpcServerStateBuy>
</template>
</span>
</template>