Files
api/web/components/HeaderOsVersion.ce.vue
Eli Bosley 39e83b2aa1 feat: move activation code logic into the API (#1369)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added comprehensive activation code customization service with dynamic
theming, partner branding, and UI updates.
- Introduced new GraphQL types and public queries for activation code,
partner info, and theme data.
- Implemented new web UI stores and components for activation modal,
partner logos, and theme management.
- **Improvements**
- Removed legacy activation code scripts, PHP components, and plugin
references, streamlining activation logic.
- Enhanced configuration and environment support for activation and
theming features.
- Improved error handling, validation, and type safety in activation and
customization modules.
- **Bug Fixes**
- Fixed color code validation and path handling in customization
service.
- **Chores**
  - Added pre-commit linting hooks and related configuration.
  - Cleaned up test and development environment files.
- **Tests**
- Added extensive tests covering activation customization service
initialization, data handling, and file modifications.
  - Removed obsolete tests related to legacy activation code store.
- **Refactor**
- Migrated activation and partner branding logic from legacy scripts and
PHP to TypeScript services and GraphQL resolvers.
- Reorganized store and component architecture for activation-related
features.
- **Style**
- Updated UI components for improved branding, theming, accessibility,
and layout consistency.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Zack Spear <hi@zackspear.com>
2025-05-01 17:40:36 -04:00

144 lines
4.1 KiB
Vue

<script lang="ts" setup>
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { BellAlertIcon, ExclamationTriangleIcon, InformationCircleIcon } from '@heroicons/vue/24/solid';
import { Badge } from '@unraid/ui';
import { getReleaseNotesUrl, WEBGUI_TOOLS_DOWNGRADE, WEBGUI_TOOLS_UPDATE } from '~/helpers/urls';
import { useActivationCodeDataStore } from '~/components/Activation/store/activationCodeData';
import { useServerStore } from '~/store/server';
import { useUpdateOsStore } from '~/store/updateOs';
import { useUpdateOsActionsStore } from '~/store/updateOsActions';
const { t } = useI18n();
const serverStore = useServerStore();
const updateOsStore = useUpdateOsStore();
const updateOsActionsStore = useUpdateOsActionsStore();
const { partnerInfo } = storeToRefs(useActivationCodeDataStore());
const { osVersion, rebootType, stateDataError } = storeToRefs(serverStore);
const { available, availableWithRenewal } = storeToRefs(updateOsStore);
const { rebootTypeText } = storeToRefs(updateOsActionsStore);
const unraidLogoHeaderLink = computed<{ href: string; title: string }>(() => {
if (partnerInfo.value?.partnerUrl) {
return {
href: partnerInfo.value.partnerUrl,
title: t('Visit Partner website'),
};
}
return {
href: 'https://unraid.net',
title: t('Visit Unraid website'),
};
});
const updateOsStatus = computed(() => {
if (stateDataError.value) {
// only allowed to update when server is does not have a state error
return null;
}
if (rebootTypeText.value) {
return {
badge: {
color: 'yellow',
icon: ExclamationTriangleIcon,
},
href:
rebootType.value === 'downgrade'
? WEBGUI_TOOLS_DOWNGRADE.toString()
: WEBGUI_TOOLS_UPDATE.toString(),
text: t(rebootTypeText.value),
};
}
if (availableWithRenewal.value || available.value) {
return {
badge: {
color: 'orange',
icon: BellAlertIcon,
},
click: () => {
updateOsStore.setModalOpen(true);
},
text: availableWithRenewal.value ? t('Update Released') : t('Update Available'),
title: availableWithRenewal.value
? t('Unraid OS {0} Released', [availableWithRenewal.value])
: t('Unraid OS {0} Update Available', [available.value]),
};
}
return null;
});
</script>
<template>
<div class="flex flex-col">
<a
:href="unraidLogoHeaderLink.href"
:title="unraidLogoHeaderLink.title"
target="_blank"
rel="noopener"
:aria-label="unraidLogoHeaderLink.title"
>
<img
:src="'/webGui/images/UN-logotype-gradient.svg'"
class="w-[160px] h-auto max-h-[30px] ml-[10px] mt-[25px] mb-[8px] object-contain"
alt="Unraid Logo"
/>
</a>
<div class="flex flex-row justify-start gap-x-4px">
<a
class="group leading-none"
:title="t('View release notes')"
:href="getReleaseNotesUrl(osVersion).toString()"
target="_blank"
rel="noopener"
>
<Badge
variant="custom"
:icon="InformationCircleIcon"
icon-styles="text-header-text-secondary"
size="sm"
class="text-header-text-secondary group-hover:text-orange-dark group-focus:text-orange-dark group-hover:underline group-focus:underline"
>
{{ osVersion }}
</Badge>
</a>
<component
:is="updateOsStatus.href ? 'a' : 'button'"
v-if="updateOsStatus"
:href="updateOsStatus.href ?? undefined"
:title="updateOsStatus.title ?? undefined"
class="group"
@click="updateOsStatus.click?.()"
>
<Badge
v-if="updateOsStatus.badge"
:color="updateOsStatus.badge.color"
:icon="updateOsStatus.badge.icon"
size="xs"
>
{{ updateOsStatus.text }}
</Badge>
<template v-else>
{{ updateOsStatus.text }}
</template>
</component>
</div>
</div>
</template>
<style lang="postcss">
/* Import unraid-ui globals first */
@import '@unraid/ui/styles';
@import '~/assets/main.css';
</style>