mirror of
https://github.com/unraid/api.git
synced 2026-01-02 14:40:01 -06:00
refactor(onboarding): remove unnecessary fields from UpgradeStep type
- Removed `title`, `description`, and `icon` fields from the `UpgradeStep` type in the GraphQL schema and related TypeScript definitions to simplify the onboarding process. - Updated documentation to reflect changes in how onboarding steps are tracked and displayed. - Adjusted related tests and components to ensure compatibility with the updated schema. This update streamlines the onboarding experience by focusing on essential information for upgrade steps.
This commit is contained in:
@@ -929,15 +929,6 @@ type UpgradeStep {
|
||||
|
||||
"""Version of Unraid when this step was introduced"""
|
||||
introducedIn: String
|
||||
|
||||
"""Display title for the onboarding step"""
|
||||
title: String!
|
||||
|
||||
"""Display description for the onboarding step"""
|
||||
description: String!
|
||||
|
||||
"""Icon identifier for the onboarding step"""
|
||||
icon: String
|
||||
}
|
||||
|
||||
type UpgradeInfo {
|
||||
|
||||
@@ -148,7 +148,8 @@ export type ActivationOnboardingStep = {
|
||||
export enum ActivationOnboardingStepId {
|
||||
ACTIVATION = 'ACTIVATION',
|
||||
PLUGINS = 'PLUGINS',
|
||||
TIMEZONE = 'TIMEZONE'
|
||||
TIMEZONE = 'TIMEZONE',
|
||||
WELCOME = 'WELCOME'
|
||||
}
|
||||
|
||||
export type AddPermissionInput = {
|
||||
@@ -2682,18 +2683,12 @@ export type UpgradeInfo = {
|
||||
|
||||
export type UpgradeStep = {
|
||||
__typename?: 'UpgradeStep';
|
||||
/** Display description for the onboarding step */
|
||||
description: Scalars['String']['output'];
|
||||
/** Icon identifier for the onboarding step */
|
||||
icon?: Maybe<Scalars['String']['output']>;
|
||||
/** Identifier of the onboarding step */
|
||||
id: Scalars['String']['output'];
|
||||
/** Version of Unraid when this step was introduced */
|
||||
introducedIn?: Maybe<Scalars['String']['output']>;
|
||||
/** Whether the step is required to continue */
|
||||
required: Scalars['Boolean']['output'];
|
||||
/** Display title for the onboarding step */
|
||||
title: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type Uptime = {
|
||||
|
||||
@@ -44,6 +44,7 @@ const mockReadFile = vi.mocked(readFile);
|
||||
const mockReaddir = vi.mocked(readdir);
|
||||
const mockAccess = vi.mocked(access);
|
||||
const mockAtomicWriteFile = vi.mocked(atomicWriteFile);
|
||||
type ReaddirResult = Awaited<ReturnType<typeof readdir>>;
|
||||
|
||||
describe('ApiConfigPersistence', () => {
|
||||
let service: ApiConfigPersistence;
|
||||
@@ -84,7 +85,6 @@ describe('ApiConfigPersistence', () => {
|
||||
ssoSubIds: [],
|
||||
plugins: [],
|
||||
});
|
||||
expect(defaultConfig.lastSeenOsVersion).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should migrate config from legacy format', async () => {
|
||||
@@ -110,7 +110,6 @@ describe('ApiConfigPersistence', () => {
|
||||
ssoSubIds: ['sub1', 'sub2'],
|
||||
plugins: [],
|
||||
});
|
||||
expect(result.lastSeenOsVersion).toBeUndefined();
|
||||
});
|
||||
|
||||
it('sets api.version on bootstrap', async () => {
|
||||
@@ -142,7 +141,7 @@ describe('OnboardingTracker', () => {
|
||||
mockReadFile.mockReset();
|
||||
mockReaddir.mockReset();
|
||||
mockAccess.mockReset();
|
||||
mockReaddir.mockResolvedValue([]);
|
||||
mockReaddir.mockResolvedValue([] as unknown as ReaddirResult);
|
||||
mockAccess.mockResolvedValue(undefined);
|
||||
mockAtomicWriteFile.mockReset();
|
||||
|
||||
@@ -165,7 +164,6 @@ describe('OnboardingTracker', () => {
|
||||
expect(setMock).toHaveBeenCalledWith('store.emhttp.var.version', '7.2.0-beta.3.4');
|
||||
expect(setMock).toHaveBeenCalledWith('onboardingTracker.lastTrackedVersion', undefined);
|
||||
expect(setMock).toHaveBeenCalledWith('onboardingTracker.completedSteps', {});
|
||||
expect(configStore['api.lastSeenOsVersion']).toBeUndefined();
|
||||
expect(mockAtomicWriteFile).not.toHaveBeenCalled();
|
||||
|
||||
await tracker.onApplicationShutdown();
|
||||
@@ -209,7 +207,6 @@ describe('OnboardingTracker', () => {
|
||||
TIMEZONE: expect.objectContaining({ version: '6.12.0' }),
|
||||
})
|
||||
);
|
||||
expect(configStore['api.lastSeenOsVersion']).toBe('6.12.0');
|
||||
expect(mockAtomicWriteFile).not.toHaveBeenCalled();
|
||||
|
||||
await tracker.onApplicationShutdown();
|
||||
@@ -265,7 +262,6 @@ describe('OnboardingTracker', () => {
|
||||
expect(configStore['onboardingTracker.lastTrackedVersion']).toBe('7.0.0');
|
||||
expect(configStore['store.emhttp.var.version']).toBe('7.1.0');
|
||||
expect(configStore['onboardingTracker.completedSteps']).toEqual({});
|
||||
expect(configStore['api.lastSeenOsVersion']).toBe('7.0.0');
|
||||
|
||||
expect(mockAtomicWriteFile).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -281,7 +277,6 @@ describe('OnboardingTracker', () => {
|
||||
expect(setMock).toHaveBeenCalledWith('onboardingTracker.lastTrackedVersion', undefined);
|
||||
expect(setMock).toHaveBeenCalledWith('onboardingTracker.completedSteps', {});
|
||||
expect(mockAtomicWriteFile).not.toHaveBeenCalled();
|
||||
expect(configStore['api.lastSeenOsVersion']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('marks onboarding steps complete for the current version without clearing upgrade flag', async () => {
|
||||
@@ -304,7 +299,6 @@ describe('OnboardingTracker', () => {
|
||||
|
||||
expect(configStore['store.emhttp.var.version']).toBe('7.2.0');
|
||||
expect(configStore['onboardingTracker.lastTrackedVersion']).toBe('6.12.0');
|
||||
expect(configStore['api.lastSeenOsVersion']).toBe('6.12.0');
|
||||
|
||||
setMock.mockClear();
|
||||
mockAtomicWriteFile.mockReset();
|
||||
@@ -427,7 +421,7 @@ describe('OnboardingTracker', () => {
|
||||
throw Object.assign(new Error('Not found'), { code: 'ENOENT' });
|
||||
});
|
||||
|
||||
mockReaddir.mockResolvedValueOnce(['pending.activationcode']);
|
||||
mockReaddir.mockResolvedValueOnce(['pending.activationcode'] as unknown as ReaddirResult);
|
||||
mockEmhttpState.var.regState = 'ENOKEYFILE';
|
||||
|
||||
const tracker = new OnboardingTracker(configService);
|
||||
@@ -463,7 +457,6 @@ describe('loadApiConfig', () => {
|
||||
ssoSubIds: [],
|
||||
plugins: [],
|
||||
});
|
||||
expect(result.lastSeenOsVersion).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle errors gracefully and return defaults', async () => {
|
||||
@@ -476,6 +469,5 @@ describe('loadApiConfig', () => {
|
||||
ssoSubIds: [],
|
||||
plugins: [],
|
||||
});
|
||||
expect(result.lastSeenOsVersion).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -96,7 +96,6 @@ export class OnboardingTracker implements OnApplicationBootstrap, OnApplicationS
|
||||
const lastTrackedVersion =
|
||||
this.sessionLastTrackedVersion ??
|
||||
this.configService.get<string>(`${CONFIG_PREFIX}.lastTrackedVersion`) ??
|
||||
this.configService.get<string>('api.lastSeenOsVersion') ??
|
||||
undefined;
|
||||
|
||||
await this.ensureStateLoaded();
|
||||
@@ -248,7 +247,6 @@ export class OnboardingTracker implements OnApplicationBootstrap, OnApplicationS
|
||||
this.configService.set('store.emhttp.var.version', currentVersion);
|
||||
this.configService.set(`${CONFIG_PREFIX}.lastTrackedVersion`, this.sessionLastTrackedVersion);
|
||||
this.configService.set(`${CONFIG_PREFIX}.completedSteps`, completedStepsMap);
|
||||
this.configService.set('api.lastSeenOsVersion', this.sessionLastTrackedVersion);
|
||||
}
|
||||
|
||||
private async readCurrentVersion(): Promise<string | undefined> {
|
||||
|
||||
@@ -59,18 +59,6 @@ export class UpgradeStep {
|
||||
description: 'Version of Unraid when this step was introduced',
|
||||
})
|
||||
introducedIn?: string;
|
||||
|
||||
@Field(() => String, { description: 'Display title for the onboarding step' })
|
||||
title!: string;
|
||||
|
||||
@Field(() => String, { description: 'Display description for the onboarding step' })
|
||||
description!: string;
|
||||
|
||||
@Field(() => String, {
|
||||
nullable: true,
|
||||
description: 'Icon identifier for the onboarding step',
|
||||
})
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
## Overview
|
||||
|
||||
This system shows contextual onboarding steps to users when they upgrade their Unraid OS to a new version. It tracks the last seen OS version in the API config and allows you to define which steps should be shown for specific version upgrades.
|
||||
This system shows contextual onboarding steps to users when they upgrade their Unraid OS to a new version. It tracks the last seen OS version using the onboarding tracker state and allows you to define which steps should be shown for specific version upgrades.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Backend (API)
|
||||
|
||||
1. **Version Tracking** - `api/src/unraid-api/config/api-config.module.ts`
|
||||
- On boot, compares current OS version with `lastSeenOsVersion` in API config
|
||||
- Automatically updates `lastSeenOsVersion` when version changes
|
||||
- Persists to `/boot/config/modules/api.json`
|
||||
1. **Version Tracking** - `api/src/unraid-api/config/onboarding-tracker.module.ts`
|
||||
- On boot, compares current OS version with `lastTrackedVersion` in the onboarding tracker
|
||||
- Automatically updates `lastTrackedVersion` when version changes
|
||||
- Persists to `/boot/config/modules/onboarding-tracker.json`
|
||||
|
||||
2. **GraphQL API** - `api/src/unraid-api/graph/resolvers/customization/`
|
||||
- Exposes `activationOnboarding` query which returns:
|
||||
@@ -122,7 +122,7 @@ The `ActivationModal` is already integrated into the app and automatically handl
|
||||
|
||||
To test the upgrade flow:
|
||||
|
||||
1. Edit `/boot/config/modules/api.json` and set `lastSeenOsVersion` to an older version
|
||||
1. Edit `/boot/config/modules/onboarding-tracker.json` and set `lastTrackedVersion` to an older version
|
||||
2. Ensure an activation code exists (or remove it to test conditional logic)
|
||||
3. Restart the API
|
||||
4. The modal should appear on next page load with relevant steps from `activationOnboarding`
|
||||
|
||||
@@ -2683,18 +2683,12 @@ export type UpgradeInfo = {
|
||||
|
||||
export type UpgradeStep = {
|
||||
__typename?: 'UpgradeStep';
|
||||
/** Display description for the onboarding step */
|
||||
description: Scalars['String']['output'];
|
||||
/** Icon identifier for the onboarding step */
|
||||
icon?: Maybe<Scalars['String']['output']>;
|
||||
/** Identifier of the onboarding step */
|
||||
id: Scalars['String']['output'];
|
||||
/** Version of Unraid when this step was introduced */
|
||||
introducedIn?: Maybe<Scalars['String']['output']>;
|
||||
/** Whether the step is required to continue */
|
||||
required: Scalars['Boolean']['output'];
|
||||
/** Display title for the onboarding step */
|
||||
title: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type Uptime = {
|
||||
|
||||
Reference in New Issue
Block a user