Files
api/web/components/UpdateOs/UpdateIneligible.vue
Eli Bosley 345e83bfb0 feat: upgrade nuxt-custom-elements (#1461)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added new modal dialogs and UI components, including activation steps,
OS update feedback, and expanded notification management.
* Introduced a plugin to configure internationalization, state
management, and Apollo client support in web components.
* Added a new Log Viewer page with a streamlined interface for viewing
logs.

* **Improvements**
* Centralized Pinia state management by consolidating all stores to use
a shared global Pinia instance.
* Simplified component templates by removing redundant
internationalization host wrappers.
* Enhanced ESLint configuration with stricter rules and global variable
declarations.
* Refined custom element build process to prevent jQuery conflicts and
optimize minification.
* Updated component imports and templates for consistent structure and
maintainability.
* Streamlined log viewer dropdowns using simplified select components
with improved formatting.
* Improved notification sidebar with filtering by importance and modular
components.
* Replaced legacy notification popups with new UI components and added
automatic root session creation for localhost requests.
* Updated OS version display and user profile UI with refined styling
and component usage.

* **Bug Fixes**
* Fixed component tag capitalization and improved type annotations
across components.

* **Chores**
* Updated development dependencies including ESLint plugins and build
tools.
* Removed deprecated log viewer patch class and cleaned up related test
fixtures.
  * Removed unused imports and simplified Apollo client setup.
* Cleaned up test mocks and removed obsolete i18n host component tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210730229632804

---------

Co-authored-by: Pujit Mehrotra <pujit@lime-technology.com>
Co-authored-by: Zack Spear <zackspear@users.noreply.github.com>
2025-07-08 10:05:39 -04:00

130 lines
4.3 KiB
Vue

<script lang="ts" setup>
import { computed, ref, watchEffect } from 'vue';
import { storeToRefs } from 'pinia';
import { ArrowTopRightOnSquareIcon, ExclamationTriangleIcon, EyeIcon } from '@heroicons/vue/24/solid';
import { BrandButton, CardWrapper } from '@unraid/ui';
import dayjs from 'dayjs';
import type { UserProfileLink } from '~/types/userProfile';
import type { ComposerTranslation } from 'vue-i18n';
import useDateTimeHelper from '~/composables/dateTime';
import { useServerStore } from '~/store/server';
import { useUpdateOsStore } from '~/store/updateOs';
import { useUpdateOsActionsStore } from '~/store/updateOsActions';
import RegistrationUpdateExpiration from '~/components/Registration/UpdateExpiration.vue';
const props = defineProps<{
t: ComposerTranslation;
}>();
const serverStore = useServerStore();
const updateOsStore = useUpdateOsStore();
const updateOsActionsStore = useUpdateOsActionsStore();
const { dateTimeFormat, regTy, renewAction, updateOsResponse } = storeToRefs(serverStore);
const { availableWithRenewal } = storeToRefs(updateOsStore);
const { ineligibleText } = storeToRefs(updateOsActionsStore);
const availableWithRenewalRelease = computed(() =>
availableWithRenewal.value ? updateOsResponse.value : undefined
);
const { outputDateTimeFormatted: formattedReleaseDate } = useDateTimeHelper(
dateTimeFormat.value,
props.t,
true,
dayjs(availableWithRenewalRelease.value?.date, 'YYYY-MM-DD').valueOf()
);
const heading = computed((): string => {
if (availableWithRenewal.value) {
return props.t('Unraid OS {0} Released', [availableWithRenewal.value]);
}
return props.t('License Key Updates Expired');
});
const text = computed(() => {
return props.t(ineligibleText.value, [regTy.value, formattedReleaseDate.value]);
});
const updateButton = ref<UserProfileLink | undefined>();
watchEffect(() => {
if (availableWithRenewal.value) {
updateButton.value = updateOsActionsStore.updateCallbackButton();
} else {
updateButton.value = updateOsActionsStore.updateCallbackButton();
}
});
</script>
<template>
<CardWrapper :increased-padding="true" :warning="true">
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-20px sm:gap-24px">
<div class="grid gap-y-16px">
<h3 class="font-semibold leading-normal flex flex-row items-start justify-start gap-8px">
<ExclamationTriangleIcon class="w-20px shrink-0" />
<span class="leading-none inline-flex flex-wrap justify-start items-baseline gap-8px">
<span class="text-20px">
{{ heading }}
</span>
<span
v-if="
availableWithRenewalRelease && availableWithRenewalRelease.date && formattedReleaseDate
"
class="text-16px opacity-75 shrink"
>
{{ formattedReleaseDate }}
</span>
</span>
</h3>
<h4 class="text-18px font-semibold italic">
<RegistrationUpdateExpiration :t="t" />
</h4>
<div class="prose text-black text-16px leading-relaxed whitespace-normal" v-html="text" />
</div>
<div class="flex flex-col sm:flex-shrink-0 items-center gap-16px">
<BrandButton
:disabled="renewAction?.disabled"
:external="renewAction?.external"
:icon="renewAction.icon"
:icon-right="ArrowTopRightOnSquareIcon"
:text="t('Extend License')"
:title="t('Pay your annual fee to continue receiving OS updates.')"
class="flex-grow"
@click="renewAction.click?.()"
/>
<!-- <BrandButton
variant="black"
href="/Tools/Registration"
:icon="WrenchScrewdriverIcon"
:icon-right="ArrowSmallRightIcon"
:text="t('Learn more and fix')"
class="flex-none" /> -->
<BrandButton
v-if="availableWithRenewal && updateButton"
variant="outline-black"
:external="updateButton?.external"
:icon="EyeIcon"
:icon-right="ArrowTopRightOnSquareIcon"
:name="updateButton?.name"
:text="t('View Changelog')"
class="flex-none"
@click="updateButton?.click"
/>
</div>
</div>
</CardWrapper>
</template>
<style lang="postcss">
/* Import unraid-ui globals first */
@import '@unraid/ui/styles';
@import '~/assets/main.css';
</style>