refactor: trial extension to happen in modal

This commit is contained in:
Zack Spear
2023-07-07 13:33:08 -07:00
parent 58735fd807
commit d5b0efd1e4
7 changed files with 52 additions and 40 deletions

View File

@@ -9,14 +9,14 @@ import { useTrialStore } from '~/store/trial';
const { callbackStatus } = storeToRefs(useCallbackActionsStore());
const { promoVisible } = storeToRefs(usePromoStore());
const { trialStatus } = storeToRefs(useTrialStore());
const { showModal } = storeToRefs(useTrialStore());
</script>
<template>
<div class="relative z-[99999]">
<UpcCallbackFeedback :open="callbackStatus !== 'ready'" />
<UpcPromo :open="promoVisible" />
<UpcTrial :open="trialStatus === 'requestNew' || trialStatus === 'failed'" />
<UpcTrial :open="showModal" />
</div>
</template>

View File

@@ -16,7 +16,7 @@ withDefaults(defineProps<Props>(), {
<template>
<div class="mx-auto max-w-[45ch]">
<div class="flex items-start justify-start gap-x-8px">
<div class="flex items-start justify-center gap-x-8px">
<CheckCircleIcon v-if="success" class="fill-green-600 w-28px shrink-0" />
<XCircleIcon v-if="error" class="fill-unraid-red w-28px shrink-0" />
<component v-if="icon" :is="icon" class="fill-current opacity-75 w-28px shrink-0" />

View File

@@ -15,20 +15,23 @@ const { trialStatus } = storeToRefs(trialStore);
const heading = computed(() => {
if (trialStatus.value === 'failed') return 'Failed to start your free 30 day trial';
if (trialStatus.value === 'requestNew') return 'Starting your free 30 day trial…';
if (trialStatus.value === 'trialExtend') return 'Extending your free trial by 15 days';
if (trialStatus.value === 'trialStart') return 'Starting your free 30 day trial…';
if (trialStatus.value === 'success') return 'Free 30 Day Trial Created';
return '';
});
const subheading = computed(() => {
/** @todo show response error */
if (trialStatus.value === 'failed') return 'Key server did not return a trial key. Please try again later.';
if (trialStatus.value === 'requestNew') return 'Please wait while and keep this window open';
if (trialStatus.value === 'trialExtend' || trialStatus.value === 'trialStart') return 'Please keep this window open';
if (trialStatus.value === 'success') return 'Please wait while the page reloads to install your trial key';
return '';
});
const loading = computed(() => trialStatus.value === 'trialExtend' || trialStatus.value === 'trialStart');
const close = () => {
if (trialStatus.value === 'requestNew') return console.debug("[close] not allowed");
if (trialStatus.value === 'trialStart') return console.debug("[close] not allowed");
trialStore.setTrialStatus('ready');
};
</script>
@@ -39,17 +42,14 @@ const close = () => {
:open="open"
:title="heading"
:description="subheading"
:show-close-x="trialStatus !== 'requestNew'"
:show-close-x="!loading"
max-width="max-w-640px"
>
<template #main>
<BrandLoading v-if="trialStatus === 'requestNew'" class="w-[150px] mx-auto my-24px" />
<div v-if="trialStatus === 'failed'" class="my-24px">
<p class="text-red"></p>
</div>
<BrandLoading v-if="loading" class="w-[150px] mx-auto my-24px" />
</template>
<template v-if="trialStatus !== 'requestNew'" #footer>
<template v-if="!loading" #footer>
<div class="w-full max-w-xs flex flex-col items-center gap-y-16px mx-auto">
<div>
<button

View File

@@ -67,22 +67,25 @@ export const useInstallKeyStore = defineStore('installKey', () => {
};
case 'installing':
let txt1 = 'Installing';
if (keyActionType.value === 'replace') txt1 = 'Installing Replaced';
if (keyActionType.value === 'trialExtend') txt1 = 'Installing Extended Trial';
if (keyActionType.value === 'recover') txt1 = 'Installing Recovered';
if (keyActionType.value === 'replace') txt1 = 'Installing Replaced';
return {
text: `${txt1} ${keyType.value} Key...`,
};
case 'success':
let txt2 = 'Installed';
if (keyActionType.value === 'replace') txt2 = 'Replaced';
if (keyActionType.value === 'trialExtend') txt2 = 'Extension Installed';
if (keyActionType.value === 'recover') txt2 = 'Recovered';
if (keyActionType.value === 'replace') txt2 = 'Replaced';
return {
text: `${keyType.value} Key ${txt2} Successfully`,
};
case 'failed':
let txt3 = 'Install';
if (keyActionType.value === 'trialExtend') txt3 = 'Install Extended';
if (keyActionType.value === 'recover') txt3 = 'Install Recovered';
if (keyActionType.value === 'replace') txt3 = 'Install Replaced';
if (keyActionType.value === 'recover') txt3 = 'Install Recoverd';
return {
text: `Failed to ${txt3} ${keyType.value} Key`,
};

View File

@@ -41,6 +41,7 @@ export const useServerStore = defineStore('server', () => {
const guidBlacklisted = ref<boolean>();
const guidRegistered = ref<boolean>();
const guidReplaceable = ref<boolean | undefined>();
const inIframe = ref<boolean>(window.self !== window.top);
const keyfile = ref<string>('');
const lanIp = ref<string>('');
const license = ref<string>('');
@@ -79,6 +80,7 @@ export const useServerStore = defineStore('server', () => {
flashProduct: flashProduct.value,
flashVendor: flashVendor.value,
guid: guid.value,
inIframe: inIframe.value,
keyfile: keyfile.value,
lanIp: lanIp.value,
license: license.value,
@@ -115,6 +117,7 @@ export const useServerStore = defineStore('server', () => {
deviceCount: deviceCount.value,
email: email.value,
guid: guid.value,
inIframe: inIframe.value,
keyTypeForPurchase,
locale: locale.value,
registered: registered.value ?? false,
@@ -132,6 +135,7 @@ export const useServerStore = defineStore('server', () => {
flashProduct: flashProduct.value,
flashVendor: flashVendor.value,
guid: guid.value,
inIframe: inIframe.value,
keyfile: keyfile.value,
lanIp: lanIp.value,
name: name.value,
@@ -196,14 +200,14 @@ export const useServerStore = defineStore('server', () => {
text: 'Sign Out of Unraid.net',
};
const trialExtendAction: ServerStateDataAction = {
click: () => { trialStore.extend() },
click: () => { trialStore.setTrialStatus('trialExtend') },
external: true,
icon: KeyIcon,
name: 'trialExtend',
text: 'Extend Trial',
};
const trialStartAction: ServerStateDataAction = {
click: () => { trialStore.setTrialStatus('requestNew') },
click: () => { trialStore.setTrialStatus('trialStart') },
external: true,
icon: KeyIcon,
name: 'trialStart',

View File

@@ -6,7 +6,7 @@ import { startTrial, type StartTrialResponse } from '~/composables/services/keyS
import { useCallbackStore, useCallbackActionsStore } from '~/store/callbackActions';
import { useDropdownStore } from '~/store/dropdown';
import { useServerStore } from '~/store/server';
import type { ExternalPayload } from '~/store/callback';
import type { ExternalPayload, TrialExtend, TrialStart } from '~/store/callback';
/**
* @see https://stackoverflow.com/questions/73476371/using-pinia-with-vue-js-web-components
@@ -20,50 +20,51 @@ export const useTrialStore = defineStore('trial', () => {
const dropdownStore = useDropdownStore();
const serverStore = useServerStore();
type TrialStatus = 'failed' | 'ready' | 'requestNew' | 'success';
type TrialStatus = 'failed' | 'ready' | TrialExtend | TrialStart | 'success';
const trialStatus = ref<TrialStatus>('ready');
const extend = () => {
console.debug('[extend]');
callbackStore.send('https://localhost:8008/connect', [{
server: {
...serverStore.serverAccountPayload,
},
type: 'trialExtend',
}]);
};
const showModal = computed(() => trialStatus.value === 'failed' || trialStatus.value === 'trialExtend' || trialStatus.value === 'trialStart');
// @todo post to key server
const requestTrialNew = async () => {
console.debug('[requestTrialNew]');
// const extend = () => {
// console.debug('[extend]');
// callbackStore.send('https://localhost:8008/connect', [{
// server: {
// ...serverStore.serverAccountPayload,
// },
// type: 'trialExtend',
// }]);
// };
const requestTrial = async (type?: TrialExtend | TrialStart) => {
console.debug('[requestTrial]');
try {
const payload = {
guid: serverStore.guid,
timestamp: Math.floor(Date.now() / 1000),
};
const response: StartTrialResponse = await startTrial(payload).json();
console.debug('[requestTrialNew]', response);
console.debug('[requestTrial]', response);
if (!response.license) {
trialStatus.value = 'failed';
return console.error('[requestTrialNew]', 'No license returned', response);
return console.error('[requestTrial]', 'No license returned', response);
}
// manually create a payload to mimic a callback for key installs
const trialStartData: ExternalPayload = {
actions: [
{
keyUrl: response.license,
type: 'trialStart',
type: type ?? 'trialStart',
},
],
sender: window.location.href,
type: 'forUpc',
};
console.debug('[requestTrialNew]', trialStartData);
console.debug('[requestTrial]', trialStartData);
trialStatus.value = 'success';
return callbackActionsStore.redirectToCallbackType(trialStartData);
} catch (error) {
trialStatus.value = 'failed';
console.error('[requestTrialNew]', error);
console.error('[requestTrial]', error);
}
};
@@ -72,11 +73,11 @@ export const useTrialStore = defineStore('trial', () => {
watch(trialStatus, (newVal, oldVal) => {
console.debug('[trialStatus]', newVal, oldVal);
// opening
if (newVal === 'requestNew') {
if (newVal === 'trialExtend' || newVal === 'trialStart') {
addPreventClose();
dropdownStore.dropdownHide(); // close the dropdown when the trial modal is opened
setTimeout(() => {
requestTrialNew();
requestTrial(newVal);
}, 1500);
}
// allow closure
@@ -87,10 +88,11 @@ export const useTrialStore = defineStore('trial', () => {
return {
// State
showModal,
trialStatus,
// Actions
extend,
requestTrialNew,
// extend,
requestTrial,
setTrialStatus,
};
});

View File

@@ -31,6 +31,7 @@ export interface Server {
flashProduct?: string;
flashVendor?: string;
guid?: string;
inIframe: boolean;
keyfile?: string;
lanIp?: string;
license?: string;
@@ -57,6 +58,7 @@ export interface ServerAccountCallbackSendPayload {
flashProduct?: string;
flashVendor?: string;
guid?: string;
inIframe: boolean;
keyfile?: string;
lanIp?: string;
locale?: string;
@@ -75,6 +77,7 @@ export interface ServerPurchaseCallbackSendPayload {
deviceCount: number;
email: string;
guid: string;
inIframe: boolean;
keyTypeForPurchase: ServerKeyTypeForPurchase;
locale: string;
registered: boolean;