mirror of https://github.com/rancher/dashboard.git
170 lines
6.5 KiB
TypeScript
170 lines
6.5 KiB
TypeScript
/**
|
|
*
|
|
* The code in this file is responsible for adding Support notifications driven off of the dynamic content metadata
|
|
*
|
|
* This covers these cases:
|
|
*
|
|
* 1. Current release has reached End of Maintenance (EOL)
|
|
* 2. Current release has reached End of Maintenance (EOM)
|
|
* 3. Current release is approaching End of Maintenance (EOL)
|
|
* 4. Current release is approaching End of Maintenance (EOM)
|
|
*
|
|
* Note that we process in the order to that shown above, and stop at the first one that is active - so reaching EOL will show a notification
|
|
* and we won't look at the others.
|
|
*
|
|
*/
|
|
|
|
import semver from 'semver';
|
|
import day from 'dayjs';
|
|
import { NotificationLevel } from '@shell/types/notifications';
|
|
import { READ_SUPPORT_NOTICE, READ_UPCOMING_SUPPORT_NOTICE } from '@shell/store/prefs';
|
|
import { removeMatchingNotifications } from './util';
|
|
import { Context, VersionInfo, UpcomingSupportInfo, SupportInfo } from './types';
|
|
import { UPDATE_DATE_FORMAT } from './index';
|
|
|
|
// Number of days ahead of upcoming EOM or EOL that we will notify the user
|
|
const DEFAULT_UPCOMING_WINDOW = 30;
|
|
|
|
// Prefixes used in the notifications IDs created here
|
|
const SUPPORT_NOTICE_PREFIX = 'support-notice-';
|
|
const UPCOMING_SUPPORT_NOTICE_PREFIX = 'upcoming-support-notice-';
|
|
|
|
// Prefixes used in the value of the user preference to track which notifications the user has read
|
|
const PREFIX = {
|
|
EOM: 'eom',
|
|
EOL: 'eol',
|
|
};
|
|
|
|
// Internal type used with convenience functions
|
|
type Config = {
|
|
prefValuePrefix?: string;
|
|
pref: any;
|
|
notificationPrefix: string;
|
|
titleKey: string;
|
|
messageKey: string;
|
|
};
|
|
|
|
/**
|
|
* Main exported function that will process the support (stateInfo)
|
|
*
|
|
* @param context Context helper providing access to config, logger, store
|
|
* @param statusInfo Support information
|
|
* @param versionInfo Version information
|
|
*/
|
|
|
|
export async function processSupportNotices(context: Context, statusInfo: SupportInfo | undefined, versionInfo: VersionInfo): Promise<void> {
|
|
if (!statusInfo || !versionInfo?.version) {
|
|
return;
|
|
}
|
|
|
|
const { version } = versionInfo;
|
|
const { logger } = context;
|
|
|
|
// TODO: ****************************************************************************************
|
|
// TODO: Check if the user is an admin if we are Prime - we only notify admins of EOM and EOL
|
|
// TODO: ****************************************************************************************
|
|
|
|
const status = statusInfo.status || {};
|
|
const majorMinor = `${ semver.major(version) }.${ semver.minor(version) }`;
|
|
|
|
// Check if this version is EOL - we warn of EOL
|
|
// If a version is EOL, then is has passed EOM, so we don't need to check that
|
|
if (status.eol && semver.satisfies(version, status.eol)) {
|
|
logger.info(`This version (${ version }) is End of Life`);
|
|
|
|
return await checkAndAddNotification(context, {
|
|
prefValuePrefix: PREFIX.EOL,
|
|
pref: READ_SUPPORT_NOTICE,
|
|
notificationPrefix: SUPPORT_NOTICE_PREFIX,
|
|
titleKey: 'dynamicContent.eol.title',
|
|
messageKey: 'dynamicContent.eol.message',
|
|
}, majorMinor);
|
|
}
|
|
|
|
if (status.eom && semver.satisfies(version, status.eom)) {
|
|
logger.info(`This version (${ version }) is End of Maintenance`);
|
|
|
|
return await checkAndAddNotification(context, {
|
|
prefValuePrefix: PREFIX.EOM,
|
|
pref: READ_SUPPORT_NOTICE,
|
|
notificationPrefix: SUPPORT_NOTICE_PREFIX,
|
|
titleKey: 'dynamicContent.eom.title',
|
|
messageKey: 'dynamicContent.eom.message',
|
|
}, majorMinor);
|
|
}
|
|
|
|
// Now check for upcoming EOL or EOM
|
|
|
|
// Upcoming EOL
|
|
if (statusInfo.upcoming?.eol && semver.satisfies(version, statusInfo.upcoming.eol.version)) {
|
|
if (await checkAndAddUpcomingNotification(context, statusInfo.upcoming.eol, {
|
|
prefValuePrefix: PREFIX.EOL,
|
|
pref: READ_UPCOMING_SUPPORT_NOTICE,
|
|
notificationPrefix: UPCOMING_SUPPORT_NOTICE_PREFIX,
|
|
titleKey: 'dynamicContent.upcomingEol.title',
|
|
messageKey: 'dynamicContent.upcomingEol.message',
|
|
}, majorMinor)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Upcoming EOM
|
|
if (statusInfo.upcoming?.eom && semver.satisfies(version, statusInfo.upcoming.eom.version)) {
|
|
await checkAndAddUpcomingNotification(context, statusInfo.upcoming.eom, {
|
|
prefValuePrefix: PREFIX.EOM,
|
|
pref: READ_UPCOMING_SUPPORT_NOTICE,
|
|
notificationPrefix: UPCOMING_SUPPORT_NOTICE_PREFIX,
|
|
titleKey: 'dynamicContent.upcomingEom.title',
|
|
messageKey: 'dynamicContent.upcomingEom.message',
|
|
}, majorMinor);
|
|
}
|
|
}
|
|
|
|
async function checkAndAddUpcomingNotification(context: Context, info: UpcomingSupportInfo, config: Config, majorMinor: string): Promise<boolean> {
|
|
const now = day(day().format(UPDATE_DATE_FORMAT));
|
|
const upcomingDate = day(day(info.date).format(UPDATE_DATE_FORMAT));
|
|
const distance = upcomingDate.diff(now, 'day');
|
|
const noticeWindow = info.noticeDays || DEFAULT_UPCOMING_WINDOW;
|
|
|
|
// If we've passed the upcoming date, then ignore, as this should have been covered by the eom status
|
|
if (distance > 0 && distance < noticeWindow) {
|
|
await checkAndAddNotification(context, config, majorMinor, distance);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Check if a notification already exists or has already been read and if not, add it
|
|
*
|
|
* @param context Context helper providing access to config, logger, store
|
|
* @param config Configuration for the notification
|
|
* @param majorMinor Major.Minor version number
|
|
* @param distance Number of days until the event occurs (for upcoming support events)
|
|
*/
|
|
async function checkAndAddNotification(context: Context, config: Config, majorMinor: string, distance?: number) {
|
|
const { dispatch, getters, logger } = context;
|
|
const t = getters['i18n/t'];
|
|
const lastReadNotice = getters['prefs/get'](config.pref) || '';
|
|
const prefValue = config.prefValuePrefix ? `${ config.prefValuePrefix }-${ majorMinor }` : majorMinor;
|
|
|
|
if (!await removeMatchingNotifications(context, config.notificationPrefix, prefValue) && lastReadNotice !== prefValue) {
|
|
const notification = {
|
|
id: `${ config.notificationPrefix }${ prefValue }`,
|
|
level: NotificationLevel.Warning,
|
|
title: t(config.titleKey, { version: majorMinor, days: distance }),
|
|
message: t(config.messageKey, { version: majorMinor, days: distance }),
|
|
preference: {
|
|
key: config.pref,
|
|
value: prefValue
|
|
},
|
|
};
|
|
|
|
logger.info(`Adding support notification for ${ majorMinor } (${ config.notificationPrefix }${ config.prefValuePrefix })`);
|
|
|
|
await dispatch('notifications/add', notification);
|
|
}
|
|
}
|