mirror of
https://github.com/unraid/api.git
synced 2026-01-03 23:19:54 -06:00
feat(api): restructure versioning information in GraphQL schema (#1600)
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "4.13.1",
|
||||
"version": "4.14.0",
|
||||
"extraOrigins": [],
|
||||
"sandbox": true,
|
||||
"ssoSubIds": [],
|
||||
|
||||
@@ -1501,98 +1501,51 @@ type InfoBaseboard implements Node {
|
||||
memSlots: Float
|
||||
}
|
||||
|
||||
type InfoVersions implements Node {
|
||||
id: PrefixedID!
|
||||
type CoreVersions {
|
||||
"""Unraid version"""
|
||||
unraid: String
|
||||
|
||||
"""Unraid API version"""
|
||||
api: String
|
||||
|
||||
"""Kernel version"""
|
||||
kernel: String
|
||||
}
|
||||
|
||||
type PackageVersions {
|
||||
"""OpenSSL version"""
|
||||
openssl: String
|
||||
|
||||
"""System OpenSSL version"""
|
||||
systemOpenssl: String
|
||||
|
||||
"""Node.js version"""
|
||||
node: String
|
||||
|
||||
"""V8 engine version"""
|
||||
v8: String
|
||||
|
||||
"""npm version"""
|
||||
npm: String
|
||||
|
||||
"""Yarn version"""
|
||||
yarn: String
|
||||
|
||||
"""pm2 version"""
|
||||
pm2: String
|
||||
|
||||
"""Gulp version"""
|
||||
gulp: String
|
||||
|
||||
"""Grunt version"""
|
||||
grunt: String
|
||||
|
||||
"""Git version"""
|
||||
git: String
|
||||
|
||||
"""tsc version"""
|
||||
tsc: String
|
||||
|
||||
"""MySQL version"""
|
||||
mysql: String
|
||||
|
||||
"""Redis version"""
|
||||
redis: String
|
||||
|
||||
"""MongoDB version"""
|
||||
mongodb: String
|
||||
|
||||
"""Apache version"""
|
||||
apache: String
|
||||
|
||||
"""nginx version"""
|
||||
nginx: String
|
||||
|
||||
"""PHP version"""
|
||||
php: String
|
||||
|
||||
"""Postfix version"""
|
||||
postfix: String
|
||||
|
||||
"""PostgreSQL version"""
|
||||
postgresql: String
|
||||
|
||||
"""Perl version"""
|
||||
perl: String
|
||||
|
||||
"""Python version"""
|
||||
python: String
|
||||
|
||||
"""Python3 version"""
|
||||
python3: String
|
||||
|
||||
"""pip version"""
|
||||
pip: String
|
||||
|
||||
"""pip3 version"""
|
||||
pip3: String
|
||||
|
||||
"""Java version"""
|
||||
java: String
|
||||
|
||||
"""gcc version"""
|
||||
gcc: String
|
||||
|
||||
"""VirtualBox version"""
|
||||
virtualbox: String
|
||||
|
||||
"""Docker version"""
|
||||
docker: String
|
||||
}
|
||||
|
||||
"""Unraid version"""
|
||||
unraid: String
|
||||
type InfoVersions implements Node {
|
||||
id: PrefixedID!
|
||||
|
||||
"""Core system versions"""
|
||||
core: CoreVersions!
|
||||
|
||||
"""Software package versions"""
|
||||
packages: PackageVersions!
|
||||
}
|
||||
|
||||
type Info implements Node {
|
||||
|
||||
@@ -64,9 +64,13 @@ describe('ApiReportService', () => {
|
||||
uuid: 'test-uuid',
|
||||
},
|
||||
versions: {
|
||||
unraid: '6.12.0',
|
||||
kernel: '5.19.17',
|
||||
openssl: '3.0.8',
|
||||
core: {
|
||||
unraid: '6.12.0',
|
||||
kernel: '5.19.17',
|
||||
},
|
||||
packages: {
|
||||
openssl: '3.0.8',
|
||||
},
|
||||
},
|
||||
},
|
||||
config: {
|
||||
|
||||
@@ -82,7 +82,7 @@ export class ApiReportService {
|
||||
? {
|
||||
id: systemData.info.system.uuid,
|
||||
name: systemData.server?.name || 'Unknown',
|
||||
version: systemData.info.versions.unraid || 'Unknown',
|
||||
version: systemData.info.versions.core.unraid || 'Unknown',
|
||||
machineId: 'REDACTED',
|
||||
manufacturer: systemData.info.system.manufacturer,
|
||||
model: systemData.info.system.model,
|
||||
|
||||
@@ -20,7 +20,7 @@ type Documents = {
|
||||
"\n mutation UpdateSandboxSettings($input: JSON!) {\n updateSettings(input: $input) {\n restartRequired\n values\n }\n }\n": typeof types.UpdateSandboxSettingsDocument,
|
||||
"\n query GetPlugins {\n plugins {\n name\n version\n hasApiModule\n hasCliModule\n }\n }\n": typeof types.GetPluginsDocument,
|
||||
"\n query GetSSOUsers {\n settings {\n api {\n ssoSubIds\n }\n }\n }\n": typeof types.GetSsoUsersDocument,
|
||||
"\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n unraid\n kernel\n openssl\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n": typeof types.SystemReportDocument,
|
||||
"\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n core {\n unraid\n kernel\n }\n packages {\n openssl\n }\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n": typeof types.SystemReportDocument,
|
||||
"\n query ConnectStatus {\n connect {\n id\n dynamicRemoteAccess {\n enabledType\n runningType\n error\n }\n }\n }\n": typeof types.ConnectStatusDocument,
|
||||
"\n query Services {\n services {\n id\n name\n online\n uptime {\n timestamp\n }\n version\n }\n }\n": typeof types.ServicesDocument,
|
||||
"\n query ValidateOidcSession($token: String!) {\n validateOidcSession(token: $token) {\n valid\n username\n }\n }\n": typeof types.ValidateOidcSessionDocument,
|
||||
@@ -32,7 +32,7 @@ const documents: Documents = {
|
||||
"\n mutation UpdateSandboxSettings($input: JSON!) {\n updateSettings(input: $input) {\n restartRequired\n values\n }\n }\n": types.UpdateSandboxSettingsDocument,
|
||||
"\n query GetPlugins {\n plugins {\n name\n version\n hasApiModule\n hasCliModule\n }\n }\n": types.GetPluginsDocument,
|
||||
"\n query GetSSOUsers {\n settings {\n api {\n ssoSubIds\n }\n }\n }\n": types.GetSsoUsersDocument,
|
||||
"\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n unraid\n kernel\n openssl\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n": types.SystemReportDocument,
|
||||
"\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n core {\n unraid\n kernel\n }\n packages {\n openssl\n }\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n": types.SystemReportDocument,
|
||||
"\n query ConnectStatus {\n connect {\n id\n dynamicRemoteAccess {\n enabledType\n runningType\n error\n }\n }\n }\n": types.ConnectStatusDocument,
|
||||
"\n query Services {\n services {\n id\n name\n online\n uptime {\n timestamp\n }\n version\n }\n }\n": types.ServicesDocument,
|
||||
"\n query ValidateOidcSession($token: String!) {\n validateOidcSession(token: $token) {\n valid\n username\n }\n }\n": types.ValidateOidcSessionDocument,
|
||||
@@ -79,7 +79,7 @@ export function gql(source: "\n query GetSSOUsers {\n settings {\n
|
||||
/**
|
||||
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function gql(source: "\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n unraid\n kernel\n openssl\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n"): (typeof documents)["\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n unraid\n kernel\n openssl\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n"];
|
||||
export function gql(source: "\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n core {\n unraid\n kernel\n }\n packages {\n openssl\n }\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n"): (typeof documents)["\n query SystemReport {\n info {\n id\n machineId\n system {\n manufacturer\n model\n version\n sku\n serial\n uuid\n }\n versions {\n core {\n unraid\n kernel\n }\n packages {\n openssl\n }\n }\n }\n config {\n id\n valid\n error\n }\n server {\n id\n name\n }\n }\n"];
|
||||
/**
|
||||
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
@@ -520,6 +520,16 @@ export enum ContainerState {
|
||||
RUNNING = 'RUNNING'
|
||||
}
|
||||
|
||||
export type CoreVersions = {
|
||||
__typename?: 'CoreVersions';
|
||||
/** Unraid API version */
|
||||
api?: Maybe<Scalars['String']['output']>;
|
||||
/** Kernel version */
|
||||
kernel?: Maybe<Scalars['String']['output']>;
|
||||
/** Unraid version */
|
||||
unraid?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
/** CPU load for a single core */
|
||||
export type CpuLoad = {
|
||||
__typename?: 'CpuLoad';
|
||||
@@ -1039,67 +1049,11 @@ export type InfoUsb = Node & {
|
||||
|
||||
export type InfoVersions = Node & {
|
||||
__typename?: 'InfoVersions';
|
||||
/** Apache version */
|
||||
apache?: Maybe<Scalars['String']['output']>;
|
||||
/** Docker version */
|
||||
docker?: Maybe<Scalars['String']['output']>;
|
||||
/** gcc version */
|
||||
gcc?: Maybe<Scalars['String']['output']>;
|
||||
/** Git version */
|
||||
git?: Maybe<Scalars['String']['output']>;
|
||||
/** Grunt version */
|
||||
grunt?: Maybe<Scalars['String']['output']>;
|
||||
/** Gulp version */
|
||||
gulp?: Maybe<Scalars['String']['output']>;
|
||||
/** Core system versions */
|
||||
core: CoreVersions;
|
||||
id: Scalars['PrefixedID']['output'];
|
||||
/** Java version */
|
||||
java?: Maybe<Scalars['String']['output']>;
|
||||
/** Kernel version */
|
||||
kernel?: Maybe<Scalars['String']['output']>;
|
||||
/** MongoDB version */
|
||||
mongodb?: Maybe<Scalars['String']['output']>;
|
||||
/** MySQL version */
|
||||
mysql?: Maybe<Scalars['String']['output']>;
|
||||
/** nginx version */
|
||||
nginx?: Maybe<Scalars['String']['output']>;
|
||||
/** Node.js version */
|
||||
node?: Maybe<Scalars['String']['output']>;
|
||||
/** npm version */
|
||||
npm?: Maybe<Scalars['String']['output']>;
|
||||
/** OpenSSL version */
|
||||
openssl?: Maybe<Scalars['String']['output']>;
|
||||
/** Perl version */
|
||||
perl?: Maybe<Scalars['String']['output']>;
|
||||
/** PHP version */
|
||||
php?: Maybe<Scalars['String']['output']>;
|
||||
/** pip version */
|
||||
pip?: Maybe<Scalars['String']['output']>;
|
||||
/** pip3 version */
|
||||
pip3?: Maybe<Scalars['String']['output']>;
|
||||
/** pm2 version */
|
||||
pm2?: Maybe<Scalars['String']['output']>;
|
||||
/** Postfix version */
|
||||
postfix?: Maybe<Scalars['String']['output']>;
|
||||
/** PostgreSQL version */
|
||||
postgresql?: Maybe<Scalars['String']['output']>;
|
||||
/** Python version */
|
||||
python?: Maybe<Scalars['String']['output']>;
|
||||
/** Python3 version */
|
||||
python3?: Maybe<Scalars['String']['output']>;
|
||||
/** Redis version */
|
||||
redis?: Maybe<Scalars['String']['output']>;
|
||||
/** System OpenSSL version */
|
||||
systemOpenssl?: Maybe<Scalars['String']['output']>;
|
||||
/** tsc version */
|
||||
tsc?: Maybe<Scalars['String']['output']>;
|
||||
/** Unraid version */
|
||||
unraid?: Maybe<Scalars['String']['output']>;
|
||||
/** V8 engine version */
|
||||
v8?: Maybe<Scalars['String']['output']>;
|
||||
/** VirtualBox version */
|
||||
virtualbox?: Maybe<Scalars['String']['output']>;
|
||||
/** Yarn version */
|
||||
yarn?: Maybe<Scalars['String']['output']>;
|
||||
/** Software package versions */
|
||||
packages: PackageVersions;
|
||||
};
|
||||
|
||||
export type InitiateFlashBackupInput = {
|
||||
@@ -1526,6 +1480,26 @@ export type Owner = {
|
||||
username: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type PackageVersions = {
|
||||
__typename?: 'PackageVersions';
|
||||
/** Docker version */
|
||||
docker?: Maybe<Scalars['String']['output']>;
|
||||
/** Git version */
|
||||
git?: Maybe<Scalars['String']['output']>;
|
||||
/** nginx version */
|
||||
nginx?: Maybe<Scalars['String']['output']>;
|
||||
/** Node.js version */
|
||||
node?: Maybe<Scalars['String']['output']>;
|
||||
/** npm version */
|
||||
npm?: Maybe<Scalars['String']['output']>;
|
||||
/** OpenSSL version */
|
||||
openssl?: Maybe<Scalars['String']['output']>;
|
||||
/** PHP version */
|
||||
php?: Maybe<Scalars['String']['output']>;
|
||||
/** pm2 version */
|
||||
pm2?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type ParityCheck = {
|
||||
__typename?: 'ParityCheck';
|
||||
/** Whether corrections are being written to parity */
|
||||
@@ -2553,7 +2527,7 @@ export type GetSsoUsersQuery = { __typename?: 'Query', settings: { __typename?:
|
||||
export type SystemReportQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type SystemReportQuery = { __typename?: 'Query', info: { __typename?: 'Info', id: any, machineId?: string | null, system: { __typename?: 'InfoSystem', manufacturer?: string | null, model?: string | null, version?: string | null, sku?: string | null, serial?: string | null, uuid?: string | null }, versions: { __typename?: 'InfoVersions', unraid?: string | null, kernel?: string | null, openssl?: string | null } }, config: { __typename?: 'Config', id: any, valid?: boolean | null, error?: string | null }, server?: { __typename?: 'Server', id: any, name: string } | null };
|
||||
export type SystemReportQuery = { __typename?: 'Query', info: { __typename?: 'Info', id: any, machineId?: string | null, system: { __typename?: 'InfoSystem', manufacturer?: string | null, model?: string | null, version?: string | null, sku?: string | null, serial?: string | null, uuid?: string | null }, versions: { __typename?: 'InfoVersions', core: { __typename?: 'CoreVersions', unraid?: string | null, kernel?: string | null }, packages: { __typename?: 'PackageVersions', openssl?: string | null } } }, config: { __typename?: 'Config', id: any, valid?: boolean | null, error?: string | null }, server?: { __typename?: 'Server', id: any, name: string } | null };
|
||||
|
||||
export type ConnectStatusQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -2579,7 +2553,7 @@ export const UpdateSsoUsersDocument = {"kind":"Document","definitions":[{"kind":
|
||||
export const UpdateSandboxSettingsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateSandboxSettings"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"JSON"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateSettings"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"restartRequired"}},{"kind":"Field","name":{"kind":"Name","value":"values"}}]}}]}}]} as unknown as DocumentNode<UpdateSandboxSettingsMutation, UpdateSandboxSettingsMutationVariables>;
|
||||
export const GetPluginsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetPlugins"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"plugins"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"hasApiModule"}},{"kind":"Field","name":{"kind":"Name","value":"hasCliModule"}}]}}]}}]} as unknown as DocumentNode<GetPluginsQuery, GetPluginsQueryVariables>;
|
||||
export const GetSsoUsersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetSSOUsers"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"settings"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"api"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"ssoSubIds"}}]}}]}}]}}]} as unknown as DocumentNode<GetSsoUsersQuery, GetSsoUsersQueryVariables>;
|
||||
export const SystemReportDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SystemReport"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"info"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"machineId"}},{"kind":"Field","name":{"kind":"Name","value":"system"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"manufacturer"}},{"kind":"Field","name":{"kind":"Name","value":"model"}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"sku"}},{"kind":"Field","name":{"kind":"Name","value":"serial"}},{"kind":"Field","name":{"kind":"Name","value":"uuid"}}]}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"unraid"}},{"kind":"Field","name":{"kind":"Name","value":"kernel"}},{"kind":"Field","name":{"kind":"Name","value":"openssl"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"config"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"valid"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"server"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<SystemReportQuery, SystemReportQueryVariables>;
|
||||
export const SystemReportDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"SystemReport"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"info"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"machineId"}},{"kind":"Field","name":{"kind":"Name","value":"system"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"manufacturer"}},{"kind":"Field","name":{"kind":"Name","value":"model"}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"sku"}},{"kind":"Field","name":{"kind":"Name","value":"serial"}},{"kind":"Field","name":{"kind":"Name","value":"uuid"}}]}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"core"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"unraid"}},{"kind":"Field","name":{"kind":"Name","value":"kernel"}}]}},{"kind":"Field","name":{"kind":"Name","value":"packages"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"openssl"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"config"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"valid"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}},{"kind":"Field","name":{"kind":"Name","value":"server"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<SystemReportQuery, SystemReportQueryVariables>;
|
||||
export const ConnectStatusDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ConnectStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"connect"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dynamicRemoteAccess"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"enabledType"}},{"kind":"Field","name":{"kind":"Name","value":"runningType"}},{"kind":"Field","name":{"kind":"Name","value":"error"}}]}}]}}]}}]} as unknown as DocumentNode<ConnectStatusQuery, ConnectStatusQueryVariables>;
|
||||
export const ServicesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"Services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"services"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"online"}},{"kind":"Field","name":{"kind":"Name","value":"uptime"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"timestamp"}}]}},{"kind":"Field","name":{"kind":"Name","value":"version"}}]}}]}}]} as unknown as DocumentNode<ServicesQuery, ServicesQueryVariables>;
|
||||
export const ValidateOidcSessionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ValidateOidcSession"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"token"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"validateOidcSession"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"token"},"value":{"kind":"Variable","name":{"kind":"Name","value":"token"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"valid"}},{"kind":"Field","name":{"kind":"Name","value":"username"}}]}}]}}]} as unknown as DocumentNode<ValidateOidcSessionQuery, ValidateOidcSessionQueryVariables>;
|
||||
@@ -14,9 +14,13 @@ export const SYSTEM_REPORT_QUERY = gql(`
|
||||
uuid
|
||||
}
|
||||
versions {
|
||||
unraid
|
||||
kernel
|
||||
openssl
|
||||
core {
|
||||
unraid
|
||||
kernel
|
||||
}
|
||||
packages {
|
||||
openssl
|
||||
}
|
||||
}
|
||||
}
|
||||
config {
|
||||
|
||||
@@ -8,6 +8,8 @@ import { DisplayService } from '@app/unraid-api/graph/resolvers/info/display/dis
|
||||
import { InfoResolver } from '@app/unraid-api/graph/resolvers/info/info.resolver.js';
|
||||
import { MemoryService } from '@app/unraid-api/graph/resolvers/info/memory/memory.service.js';
|
||||
import { OsService } from '@app/unraid-api/graph/resolvers/info/os/os.service.js';
|
||||
import { CoreVersionsResolver } from '@app/unraid-api/graph/resolvers/info/versions/core-versions.resolver.js';
|
||||
import { VersionsResolver } from '@app/unraid-api/graph/resolvers/info/versions/versions.resolver.js';
|
||||
import { VersionsService } from '@app/unraid-api/graph/resolvers/info/versions/versions.service.js';
|
||||
import { ServicesModule } from '@app/unraid-api/graph/services/services.module.js';
|
||||
|
||||
@@ -19,6 +21,8 @@ import { ServicesModule } from '@app/unraid-api/graph/services/services.module.j
|
||||
|
||||
// Sub-resolvers
|
||||
DevicesResolver,
|
||||
VersionsResolver,
|
||||
CoreVersionsResolver,
|
||||
|
||||
// Services
|
||||
CpuService,
|
||||
@@ -28,6 +32,6 @@ import { ServicesModule } from '@app/unraid-api/graph/services/services.module.j
|
||||
VersionsService,
|
||||
DisplayService,
|
||||
],
|
||||
exports: [InfoResolver, DevicesResolver, DisplayService],
|
||||
exports: [InfoResolver, DevicesResolver, VersionsResolver, CoreVersionsResolver, DisplayService],
|
||||
})
|
||||
export class InfoModule {}
|
||||
|
||||
@@ -165,16 +165,12 @@ describe('InfoResolver Integration Tests', () => {
|
||||
expect(typeof result.platform).toBe('string');
|
||||
});
|
||||
|
||||
it.skipIf(process.env.CI)('should return versions data from service', async () => {
|
||||
const result = await infoResolver.versions();
|
||||
it('should return versions stub for field resolvers', () => {
|
||||
const result = infoResolver.versions();
|
||||
|
||||
expect(result).toHaveProperty('id', 'info/versions');
|
||||
expect(result).toHaveProperty('unraid');
|
||||
expect(result).toHaveProperty('kernel');
|
||||
expect(result).toHaveProperty('node');
|
||||
expect(result).toHaveProperty('npm');
|
||||
// Verify unraid version from mock
|
||||
expect(result.unraid).toBe('6.12.0');
|
||||
// Versions now returns a stub object, with actual data resolved via field resolvers
|
||||
expect(Object.keys(result)).toEqual(['id']);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ export class InfoResolver {
|
||||
}
|
||||
|
||||
@ResolveField(() => InfoVersions)
|
||||
public async versions(): Promise<InfoVersions> {
|
||||
public versions(): Partial<InfoVersions> {
|
||||
return this.versionsService.generateVersions();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { ResolveField, Resolver } from '@nestjs/graphql';
|
||||
|
||||
import { versions } from 'systeminformation';
|
||||
|
||||
import { CoreVersions } from '@app/unraid-api/graph/resolvers/info/versions/versions.model.js';
|
||||
|
||||
@Resolver(() => CoreVersions)
|
||||
export class CoreVersionsResolver {
|
||||
@ResolveField(() => String, { nullable: true })
|
||||
async kernel(): Promise<string | undefined> {
|
||||
const softwareVersions = await versions();
|
||||
return softwareVersions.kernel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
let cachedVersion: string | undefined;
|
||||
|
||||
export function getApiVersion(): string {
|
||||
if (cachedVersion) {
|
||||
return cachedVersion;
|
||||
}
|
||||
|
||||
try {
|
||||
const packagePath = join(process.cwd(), 'package.json');
|
||||
const packageJson = JSON.parse(readFileSync(packagePath, 'utf-8'));
|
||||
const version = packageJson.version || 'unknown';
|
||||
cachedVersion = version;
|
||||
return version;
|
||||
} catch (error) {
|
||||
console.error('Failed to read API version from package.json:', error);
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
||||
@@ -2,95 +2,50 @@ import { Field, ObjectType } from '@nestjs/graphql';
|
||||
|
||||
import { Node } from '@unraid/shared/graphql.model.js';
|
||||
|
||||
@ObjectType({ implements: () => Node })
|
||||
export class InfoVersions extends Node {
|
||||
@ObjectType()
|
||||
export class CoreVersions {
|
||||
@Field(() => String, { nullable: true, description: 'Unraid version' })
|
||||
unraid?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Unraid API version' })
|
||||
api?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Kernel version' })
|
||||
kernel?: string;
|
||||
}
|
||||
|
||||
@ObjectType()
|
||||
export class PackageVersions {
|
||||
@Field(() => String, { nullable: true, description: 'OpenSSL version' })
|
||||
openssl?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'System OpenSSL version' })
|
||||
systemOpenssl?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Node.js version' })
|
||||
node?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'V8 engine version' })
|
||||
v8?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'npm version' })
|
||||
npm?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Yarn version' })
|
||||
yarn?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'pm2 version' })
|
||||
pm2?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Gulp version' })
|
||||
gulp?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Grunt version' })
|
||||
grunt?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Git version' })
|
||||
git?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'tsc version' })
|
||||
tsc?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'MySQL version' })
|
||||
mysql?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Redis version' })
|
||||
redis?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'MongoDB version' })
|
||||
mongodb?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Apache version' })
|
||||
apache?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'nginx version' })
|
||||
nginx?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'PHP version' })
|
||||
php?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Postfix version' })
|
||||
postfix?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'PostgreSQL version' })
|
||||
postgresql?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Perl version' })
|
||||
perl?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Python version' })
|
||||
python?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Python3 version' })
|
||||
python3?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'pip version' })
|
||||
pip?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'pip3 version' })
|
||||
pip3?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Java version' })
|
||||
java?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'gcc version' })
|
||||
gcc?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'VirtualBox version' })
|
||||
virtualbox?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Docker version' })
|
||||
docker?: string;
|
||||
|
||||
@Field(() => String, { nullable: true, description: 'Unraid version' })
|
||||
unraid?: string;
|
||||
}
|
||||
|
||||
@ObjectType({ implements: () => Node })
|
||||
export class InfoVersions extends Node {
|
||||
@Field(() => CoreVersions, { description: 'Core system versions' })
|
||||
core!: CoreVersions;
|
||||
|
||||
@Field(() => PackageVersions, { description: 'Software package versions' })
|
||||
packages!: PackageVersions;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { ResolveField, Resolver } from '@nestjs/graphql';
|
||||
|
||||
import { versions } from 'systeminformation';
|
||||
|
||||
import {
|
||||
CoreVersions,
|
||||
InfoVersions,
|
||||
PackageVersions,
|
||||
} from '@app/unraid-api/graph/resolvers/info/versions/versions.model.js';
|
||||
|
||||
@Resolver(() => InfoVersions)
|
||||
export class VersionsResolver {
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
|
||||
@ResolveField(() => CoreVersions)
|
||||
core(): CoreVersions {
|
||||
const unraid = this.configService.get<string>('store.emhttp.var.version') || 'unknown';
|
||||
const api = this.configService.get<string>('api.version') || 'unknown';
|
||||
|
||||
return {
|
||||
unraid,
|
||||
api,
|
||||
kernel: undefined, // Will be resolved separately if requested
|
||||
};
|
||||
}
|
||||
|
||||
@ResolveField(() => PackageVersions)
|
||||
async packages(): Promise<PackageVersions> {
|
||||
const softwareVersions = await versions();
|
||||
|
||||
return {
|
||||
openssl: softwareVersions.openssl,
|
||||
node: softwareVersions.node,
|
||||
npm: softwareVersions.npm,
|
||||
pm2: softwareVersions.pm2,
|
||||
git: softwareVersions.git,
|
||||
nginx: softwareVersions.nginx,
|
||||
php: softwareVersions.php,
|
||||
docker: softwareVersions.docker,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,12 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
|
||||
import { versions } from 'systeminformation';
|
||||
|
||||
import { InfoVersions } from '@app/unraid-api/graph/resolvers/info/versions/versions.model.js';
|
||||
|
||||
@Injectable()
|
||||
export class VersionsService {
|
||||
constructor(private readonly configService: ConfigService) {}
|
||||
|
||||
async generateVersions(): Promise<InfoVersions> {
|
||||
const unraid = this.configService.get<string>('store.emhttp.var.version') || 'unknown';
|
||||
const softwareVersions = await versions();
|
||||
|
||||
generateVersions(): Partial<InfoVersions> {
|
||||
return {
|
||||
id: 'info/versions',
|
||||
unraid,
|
||||
...softwareVersions,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,13 +18,42 @@ import HeaderOsVersion from '~/components/HeaderOsVersion.ce.vue';
|
||||
import { useErrorsStore } from '~/store/errors';
|
||||
import { useServerStore } from '~/store/server';
|
||||
|
||||
const testMockReleaseNotesUrl = 'http://mock.release.notes/v';
|
||||
|
||||
vi.mock('crypto-js/aes', () => ({ default: {} }));
|
||||
vi.mock('@unraid/shared-callbacks', () => ({
|
||||
useCallback: vi.fn(() => ({ send: vi.fn(), watcher: vi.fn() })),
|
||||
}));
|
||||
|
||||
vi.mock('@unraid/ui', () => ({
|
||||
Badge: {
|
||||
name: 'Badge',
|
||||
template: '<div><slot /></div>',
|
||||
},
|
||||
DropdownMenuRoot: {
|
||||
name: 'DropdownMenuRoot',
|
||||
template: '<div><slot /></div>',
|
||||
},
|
||||
DropdownMenuTrigger: {
|
||||
name: 'DropdownMenuTrigger',
|
||||
template: '<div><slot /></div>',
|
||||
},
|
||||
DropdownMenuContent: {
|
||||
name: 'DropdownMenuContent',
|
||||
template: '<div><slot /></div>',
|
||||
},
|
||||
DropdownMenuItem: {
|
||||
name: 'DropdownMenuItem',
|
||||
template: '<div><slot /></div>',
|
||||
},
|
||||
DropdownMenuLabel: {
|
||||
name: 'DropdownMenuLabel',
|
||||
template: '<div><slot /></div>',
|
||||
},
|
||||
DropdownMenuSeparator: {
|
||||
name: 'DropdownMenuSeparator',
|
||||
template: '<div />',
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock('@vue/apollo-composable', () => ({
|
||||
useQuery: () => ({
|
||||
result: { value: {} },
|
||||
@@ -123,13 +152,11 @@ describe('HeaderOsVersion', () => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('renders OS version link with correct URL and no update status initially', () => {
|
||||
const versionLink = wrapper.find('a[title*="release notes"]');
|
||||
it('renders OS version button with correct version and no update status initially', () => {
|
||||
const versionButton = wrapper.find('button[title*="Version Information"]');
|
||||
|
||||
expect(versionLink.exists()).toBe(true);
|
||||
expect(versionLink.attributes('href')).toBe(`${testMockReleaseNotesUrl}6.12.0`);
|
||||
|
||||
expect(versionLink.text()).toContain('6.12.0');
|
||||
expect(versionButton.exists()).toBe(true);
|
||||
expect(versionButton.text()).toContain('6.12.0');
|
||||
expect(findUpdateStatusComponent()).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { computed, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { storeToRefs } from 'pinia';
|
||||
import { useQuery } from '@vue/apollo-composable';
|
||||
|
||||
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 { BellAlertIcon, ExclamationTriangleIcon, InformationCircleIcon, DocumentTextIcon, ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/solid';
|
||||
import { Badge, DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator } from '@unraid/ui';
|
||||
import { 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';
|
||||
import { INFO_VERSIONS_QUERY } from './UserProfile/versions.query';
|
||||
import ReleaseNotesModal from '~/components/ReleaseNotesModal.vue';
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@@ -23,6 +26,20 @@ const { osVersion, rebootType, stateDataError } = storeToRefs(serverStore);
|
||||
const { available, availableWithRenewal } = storeToRefs(updateOsStore);
|
||||
const { rebootTypeText } = storeToRefs(updateOsActionsStore);
|
||||
|
||||
// Query for version information
|
||||
const { result: versionsResult } = useQuery(INFO_VERSIONS_QUERY, null, {
|
||||
fetchPolicy: 'cache-first',
|
||||
});
|
||||
|
||||
// Use versions endpoint as primary source, fallback to store
|
||||
const displayOsVersion = computed(() => versionsResult.value?.info?.versions?.core?.unraid || osVersion.value || null);
|
||||
const apiVersion = computed(() => versionsResult.value?.info?.versions?.core?.api || null);
|
||||
const showOsReleaseNotesModal = ref(false);
|
||||
|
||||
const openApiChangelog = () => {
|
||||
window.open('https://github.com/unraid/api/releases', '_blank');
|
||||
};
|
||||
|
||||
const unraidLogoHeaderLink = computed<{ href: string; title: string }>(() => {
|
||||
if (partnerInfo.value?.partnerUrl) {
|
||||
return {
|
||||
@@ -94,16 +111,56 @@ const updateOsStatus = computed(() => {
|
||||
</a>
|
||||
|
||||
<div class="flex flex-wrap justify-start gap-2">
|
||||
<a
|
||||
class="text-xs xs:text-sm flex flex-row items-center gap-x-1 font-semibold text-header-text-secondary hover:text-orange-dark focus:text-orange-dark hover:underline focus:underline leading-none"
|
||||
:title="t('View release notes')"
|
||||
:href="getReleaseNotesUrl(osVersion).toString()"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
<InformationCircleIcon class="fill-current w-3 h-3 xs:w-4 xs:h-4 shrink-0" />
|
||||
{{ osVersion }}
|
||||
</a>
|
||||
<DropdownMenuRoot>
|
||||
<DropdownMenuTrigger as-child>
|
||||
<button
|
||||
class="text-xs xs:text-sm flex flex-row items-center gap-x-1 font-semibold text-header-text-secondary hover:text-orange-dark focus:text-orange-dark hover:underline focus:underline leading-none"
|
||||
:title="t('Version Information')"
|
||||
>
|
||||
<InformationCircleIcon class="fill-current w-3 h-3 xs:w-4 xs:h-4 shrink-0" />
|
||||
{{ displayOsVersion }}
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent class="min-w-[200px]" align="start" :side-offset="4">
|
||||
<DropdownMenuLabel>
|
||||
{{ t('Version Information') }}
|
||||
</DropdownMenuLabel>
|
||||
|
||||
<DropdownMenuItem disabled class="text-xs opacity-100">
|
||||
<span class="flex justify-between w-full">
|
||||
<span>{{ t('Unraid OS') }}</span>
|
||||
<span class="font-semibold">{{ displayOsVersion || t('Unknown') }}</span>
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuItem disabled class="text-xs opacity-100">
|
||||
<span class="flex justify-between w-full">
|
||||
<span>{{ t('Unraid API') }}</span>
|
||||
<span class="font-semibold">{{ apiVersion || t('Unknown') }}</span>
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuSeparator />
|
||||
|
||||
<DropdownMenuItem @click="showOsReleaseNotesModal = true">
|
||||
<span class="flex items-center gap-x-2">
|
||||
<InformationCircleIcon class="w-4 h-4" />
|
||||
{{ t('View OS Release Notes') }}
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
|
||||
<DropdownMenuItem @click="openApiChangelog">
|
||||
<span class="flex items-center justify-between w-full">
|
||||
<span class="flex items-center gap-x-2">
|
||||
<DocumentTextIcon class="w-4 h-4" />
|
||||
{{ t('View API Changelog') }}
|
||||
</span>
|
||||
<ArrowTopRightOnSquareIcon class="w-3 h-3 opacity-60" />
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenuRoot>
|
||||
<component
|
||||
:is="updateOsStatus.href ? 'a' : 'button'"
|
||||
v-if="updateOsStatus"
|
||||
@@ -125,5 +182,14 @@ const updateOsStatus = computed(() => {
|
||||
</template>
|
||||
</component>
|
||||
</div>
|
||||
|
||||
<!-- OS Release Notes Modal -->
|
||||
<ReleaseNotesModal
|
||||
v-if="displayOsVersion"
|
||||
:open="showOsReleaseNotesModal"
|
||||
:version="displayOsVersion"
|
||||
:t="t"
|
||||
@close="showOsReleaseNotesModal = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
93
web/components/ReleaseNotesModal.vue
Normal file
93
web/components/ReleaseNotesModal.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import type { ComposerTranslation } from 'vue-i18n';
|
||||
import { ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/solid';
|
||||
import { BrandButton, BrandLoading } from '@unraid/ui';
|
||||
import Modal from '~/components/Modal.vue';
|
||||
import { getReleaseNotesUrl } from '~/helpers/urls';
|
||||
|
||||
export interface Props {
|
||||
open: boolean;
|
||||
version: string;
|
||||
t: ComposerTranslation;
|
||||
}
|
||||
|
||||
const props = defineProps<Props>();
|
||||
const emit = defineEmits<{
|
||||
close: [];
|
||||
}>();
|
||||
|
||||
const iframeRef = ref<HTMLIFrameElement | null>(null);
|
||||
const isLoading = ref(true);
|
||||
|
||||
const releaseNotesUrl = computed(() => {
|
||||
return getReleaseNotesUrl(props.version).toString();
|
||||
});
|
||||
|
||||
const handleIframeLoad = () => {
|
||||
isLoading.value = false;
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
emit('close');
|
||||
};
|
||||
|
||||
const openInNewTab = () => {
|
||||
window.open(releaseNotesUrl.value, '_blank');
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Modal
|
||||
:center-content="false"
|
||||
max-width="max-w-[800px]"
|
||||
:open="open"
|
||||
:show-close-x="true"
|
||||
:t="t"
|
||||
:tall-content="true"
|
||||
:title="`Unraid OS ${version} Release Notes`"
|
||||
:disable-overlay-close="false"
|
||||
@close="handleClose"
|
||||
>
|
||||
<template #main>
|
||||
<div class="flex flex-col gap-4 min-w-[280px] sm:min-w-[400px]">
|
||||
<!-- Loading state -->
|
||||
<div
|
||||
v-if="isLoading"
|
||||
class="text-center flex flex-col justify-center w-full min-h-[250px] min-w-[280px] sm:min-w-[400px]"
|
||||
>
|
||||
<BrandLoading class="w-[150px] mx-auto mt-6" />
|
||||
<p>Loading release notes…</p>
|
||||
</div>
|
||||
|
||||
<!-- iframe for release notes -->
|
||||
<div class="w-[calc(100%+3rem)] h-[475px] -mx-6 -my-6">
|
||||
<iframe
|
||||
ref="iframeRef"
|
||||
:src="releaseNotesUrl"
|
||||
class="w-full h-full border-0 rounded-md"
|
||||
sandbox="allow-scripts allow-same-origin"
|
||||
title="Unraid Release Notes"
|
||||
@load="handleIframeLoad"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div class="flex justify-end">
|
||||
<!-- View on docs button -->
|
||||
<BrandButton
|
||||
variant="underline"
|
||||
:external="true"
|
||||
:href="releaseNotesUrl"
|
||||
:icon="ArrowTopRightOnSquareIcon"
|
||||
aria-label="View on Docs"
|
||||
@click="openInNewTab"
|
||||
>
|
||||
Open in New Tab
|
||||
</BrandButton>
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
20
web/components/UserProfile/versions.query.ts
Normal file
20
web/components/UserProfile/versions.query.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { graphql } from '~/composables/gql';
|
||||
|
||||
export const INFO_VERSIONS_QUERY = graphql(/* GraphQL */ `
|
||||
query InfoVersions {
|
||||
info {
|
||||
id
|
||||
os {
|
||||
id
|
||||
hostname
|
||||
}
|
||||
versions {
|
||||
id
|
||||
core {
|
||||
unraid
|
||||
api
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`);
|
||||
@@ -39,7 +39,7 @@ export function useHaveSeenNotifications() {
|
||||
*
|
||||
* Writing this ref will persist to local storage and affect global state.
|
||||
*/
|
||||
haveSeenNotifications: useStorage<boolean>(HAVE_SEEN_NOTIFICATIONS_KEY, null),
|
||||
haveSeenNotifications: useStorage<boolean>(HAVE_SEEN_NOTIFICATIONS_KEY, false),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ type Documents = {
|
||||
"\n mutation DeleteRCloneRemote($input: DeleteRCloneRemoteInput!) {\n rclone {\n deleteRCloneRemote(input: $input)\n }\n }\n": typeof types.DeleteRCloneRemoteDocument,
|
||||
"\n query GetRCloneConfigForm($formOptions: RCloneConfigFormInput) {\n rclone {\n configForm(formOptions: $formOptions) {\n id\n dataSchema\n uiSchema\n }\n }\n }\n": typeof types.GetRCloneConfigFormDocument,
|
||||
"\n query ListRCloneRemotes {\n rclone {\n remotes {\n name\n type\n parameters\n config\n }\n }\n }\n": typeof types.ListRCloneRemotesDocument,
|
||||
"\n query InfoVersions {\n info {\n id\n os {\n id\n hostname\n }\n versions {\n id\n core {\n unraid\n api\n }\n }\n }\n }\n": typeof types.InfoVersionsDocument,
|
||||
"\n query OidcProviders {\n settings {\n sso {\n oidcProviders {\n id\n name\n clientId\n issuer\n authorizationEndpoint\n tokenEndpoint\n jwksUri\n scopes\n authorizationRules {\n claim\n operator\n value\n }\n authorizationRuleMode\n buttonText\n buttonIcon\n }\n }\n }\n }\n": typeof types.OidcProvidersDocument,
|
||||
"\n query PublicOidcProviders {\n publicOidcProviders {\n id\n name\n buttonText\n buttonIcon\n buttonVariant\n buttonStyle\n }\n }\n": typeof types.PublicOidcProvidersDocument,
|
||||
"\n query serverInfo {\n info {\n os {\n hostname\n }\n }\n vars {\n comment\n }\n }\n": typeof types.ServerInfoDocument,
|
||||
@@ -86,6 +87,7 @@ const documents: Documents = {
|
||||
"\n mutation DeleteRCloneRemote($input: DeleteRCloneRemoteInput!) {\n rclone {\n deleteRCloneRemote(input: $input)\n }\n }\n": types.DeleteRCloneRemoteDocument,
|
||||
"\n query GetRCloneConfigForm($formOptions: RCloneConfigFormInput) {\n rclone {\n configForm(formOptions: $formOptions) {\n id\n dataSchema\n uiSchema\n }\n }\n }\n": types.GetRCloneConfigFormDocument,
|
||||
"\n query ListRCloneRemotes {\n rclone {\n remotes {\n name\n type\n parameters\n config\n }\n }\n }\n": types.ListRCloneRemotesDocument,
|
||||
"\n query InfoVersions {\n info {\n id\n os {\n id\n hostname\n }\n versions {\n id\n core {\n unraid\n api\n }\n }\n }\n }\n": types.InfoVersionsDocument,
|
||||
"\n query OidcProviders {\n settings {\n sso {\n oidcProviders {\n id\n name\n clientId\n issuer\n authorizationEndpoint\n tokenEndpoint\n jwksUri\n scopes\n authorizationRules {\n claim\n operator\n value\n }\n authorizationRuleMode\n buttonText\n buttonIcon\n }\n }\n }\n }\n": types.OidcProvidersDocument,
|
||||
"\n query PublicOidcProviders {\n publicOidcProviders {\n id\n name\n buttonText\n buttonIcon\n buttonVariant\n buttonStyle\n }\n }\n": types.PublicOidcProvidersDocument,
|
||||
"\n query serverInfo {\n info {\n os {\n hostname\n }\n }\n vars {\n comment\n }\n }\n": types.ServerInfoDocument,
|
||||
@@ -232,6 +234,10 @@ export function graphql(source: "\n query GetRCloneConfigForm($formOptions: RCl
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n query ListRCloneRemotes {\n rclone {\n remotes {\n name\n type\n parameters\n config\n }\n }\n }\n"): (typeof documents)["\n query ListRCloneRemotes {\n rclone {\n remotes {\n name\n type\n parameters\n config\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n query InfoVersions {\n info {\n id\n os {\n id\n hostname\n }\n versions {\n id\n core {\n unraid\n api\n }\n }\n }\n }\n"): (typeof documents)["\n query InfoVersions {\n info {\n id\n os {\n id\n hostname\n }\n versions {\n id\n core {\n unraid\n api\n }\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
@@ -520,6 +520,16 @@ export enum ContainerState {
|
||||
RUNNING = 'RUNNING'
|
||||
}
|
||||
|
||||
export type CoreVersions = {
|
||||
__typename?: 'CoreVersions';
|
||||
/** Unraid API version */
|
||||
api?: Maybe<Scalars['String']['output']>;
|
||||
/** Kernel version */
|
||||
kernel?: Maybe<Scalars['String']['output']>;
|
||||
/** Unraid version */
|
||||
unraid?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
/** CPU load for a single core */
|
||||
export type CpuLoad = {
|
||||
__typename?: 'CpuLoad';
|
||||
@@ -1039,67 +1049,11 @@ export type InfoUsb = Node & {
|
||||
|
||||
export type InfoVersions = Node & {
|
||||
__typename?: 'InfoVersions';
|
||||
/** Apache version */
|
||||
apache?: Maybe<Scalars['String']['output']>;
|
||||
/** Docker version */
|
||||
docker?: Maybe<Scalars['String']['output']>;
|
||||
/** gcc version */
|
||||
gcc?: Maybe<Scalars['String']['output']>;
|
||||
/** Git version */
|
||||
git?: Maybe<Scalars['String']['output']>;
|
||||
/** Grunt version */
|
||||
grunt?: Maybe<Scalars['String']['output']>;
|
||||
/** Gulp version */
|
||||
gulp?: Maybe<Scalars['String']['output']>;
|
||||
/** Core system versions */
|
||||
core: CoreVersions;
|
||||
id: Scalars['PrefixedID']['output'];
|
||||
/** Java version */
|
||||
java?: Maybe<Scalars['String']['output']>;
|
||||
/** Kernel version */
|
||||
kernel?: Maybe<Scalars['String']['output']>;
|
||||
/** MongoDB version */
|
||||
mongodb?: Maybe<Scalars['String']['output']>;
|
||||
/** MySQL version */
|
||||
mysql?: Maybe<Scalars['String']['output']>;
|
||||
/** nginx version */
|
||||
nginx?: Maybe<Scalars['String']['output']>;
|
||||
/** Node.js version */
|
||||
node?: Maybe<Scalars['String']['output']>;
|
||||
/** npm version */
|
||||
npm?: Maybe<Scalars['String']['output']>;
|
||||
/** OpenSSL version */
|
||||
openssl?: Maybe<Scalars['String']['output']>;
|
||||
/** Perl version */
|
||||
perl?: Maybe<Scalars['String']['output']>;
|
||||
/** PHP version */
|
||||
php?: Maybe<Scalars['String']['output']>;
|
||||
/** pip version */
|
||||
pip?: Maybe<Scalars['String']['output']>;
|
||||
/** pip3 version */
|
||||
pip3?: Maybe<Scalars['String']['output']>;
|
||||
/** pm2 version */
|
||||
pm2?: Maybe<Scalars['String']['output']>;
|
||||
/** Postfix version */
|
||||
postfix?: Maybe<Scalars['String']['output']>;
|
||||
/** PostgreSQL version */
|
||||
postgresql?: Maybe<Scalars['String']['output']>;
|
||||
/** Python version */
|
||||
python?: Maybe<Scalars['String']['output']>;
|
||||
/** Python3 version */
|
||||
python3?: Maybe<Scalars['String']['output']>;
|
||||
/** Redis version */
|
||||
redis?: Maybe<Scalars['String']['output']>;
|
||||
/** System OpenSSL version */
|
||||
systemOpenssl?: Maybe<Scalars['String']['output']>;
|
||||
/** tsc version */
|
||||
tsc?: Maybe<Scalars['String']['output']>;
|
||||
/** Unraid version */
|
||||
unraid?: Maybe<Scalars['String']['output']>;
|
||||
/** V8 engine version */
|
||||
v8?: Maybe<Scalars['String']['output']>;
|
||||
/** VirtualBox version */
|
||||
virtualbox?: Maybe<Scalars['String']['output']>;
|
||||
/** Yarn version */
|
||||
yarn?: Maybe<Scalars['String']['output']>;
|
||||
/** Software package versions */
|
||||
packages: PackageVersions;
|
||||
};
|
||||
|
||||
export type InitiateFlashBackupInput = {
|
||||
@@ -1526,6 +1480,26 @@ export type Owner = {
|
||||
username: Scalars['String']['output'];
|
||||
};
|
||||
|
||||
export type PackageVersions = {
|
||||
__typename?: 'PackageVersions';
|
||||
/** Docker version */
|
||||
docker?: Maybe<Scalars['String']['output']>;
|
||||
/** Git version */
|
||||
git?: Maybe<Scalars['String']['output']>;
|
||||
/** nginx version */
|
||||
nginx?: Maybe<Scalars['String']['output']>;
|
||||
/** Node.js version */
|
||||
node?: Maybe<Scalars['String']['output']>;
|
||||
/** npm version */
|
||||
npm?: Maybe<Scalars['String']['output']>;
|
||||
/** OpenSSL version */
|
||||
openssl?: Maybe<Scalars['String']['output']>;
|
||||
/** PHP version */
|
||||
php?: Maybe<Scalars['String']['output']>;
|
||||
/** pm2 version */
|
||||
pm2?: Maybe<Scalars['String']['output']>;
|
||||
};
|
||||
|
||||
export type ParityCheck = {
|
||||
__typename?: 'ParityCheck';
|
||||
/** Whether corrections are being written to parity */
|
||||
@@ -2707,6 +2681,11 @@ export type ListRCloneRemotesQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
export type ListRCloneRemotesQuery = { __typename?: 'Query', rclone: { __typename?: 'RCloneBackupSettings', remotes: Array<{ __typename?: 'RCloneRemote', name: string, type: string, parameters: any, config: any }> } };
|
||||
|
||||
export type InfoVersionsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type InfoVersionsQuery = { __typename?: 'Query', info: { __typename?: 'Info', id: string, os: { __typename?: 'InfoOs', id: string, hostname?: string | null }, versions: { __typename?: 'InfoVersions', id: string, core: { __typename?: 'CoreVersions', unraid?: string | null, api?: string | null } } } };
|
||||
|
||||
export type OidcProvidersQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
@@ -2790,6 +2769,7 @@ export const CreateRCloneRemoteDocument = {"kind":"Document","definitions":[{"ki
|
||||
export const DeleteRCloneRemoteDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteRCloneRemote"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DeleteRCloneRemoteInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"rclone"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteRCloneRemote"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]}}]} as unknown as DocumentNode<DeleteRCloneRemoteMutation, DeleteRCloneRemoteMutationVariables>;
|
||||
export const GetRCloneConfigFormDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"GetRCloneConfigForm"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"formOptions"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"RCloneConfigFormInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"rclone"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"configForm"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"formOptions"},"value":{"kind":"Variable","name":{"kind":"Name","value":"formOptions"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSchema"}},{"kind":"Field","name":{"kind":"Name","value":"uiSchema"}}]}}]}}]}}]} as unknown as DocumentNode<GetRCloneConfigFormQuery, GetRCloneConfigFormQueryVariables>;
|
||||
export const ListRCloneRemotesDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ListRCloneRemotes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"rclone"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"remotes"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"parameters"}},{"kind":"Field","name":{"kind":"Name","value":"config"}}]}}]}}]}}]} as unknown as DocumentNode<ListRCloneRemotesQuery, ListRCloneRemotesQueryVariables>;
|
||||
export const InfoVersionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"InfoVersions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"info"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"os"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"hostname"}}]}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"core"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"unraid"}},{"kind":"Field","name":{"kind":"Name","value":"api"}}]}}]}}]}}]}}]} as unknown as DocumentNode<InfoVersionsQuery, InfoVersionsQueryVariables>;
|
||||
export const OidcProvidersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"OidcProviders"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"settings"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"sso"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"oidcProviders"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"clientId"}},{"kind":"Field","name":{"kind":"Name","value":"issuer"}},{"kind":"Field","name":{"kind":"Name","value":"authorizationEndpoint"}},{"kind":"Field","name":{"kind":"Name","value":"tokenEndpoint"}},{"kind":"Field","name":{"kind":"Name","value":"jwksUri"}},{"kind":"Field","name":{"kind":"Name","value":"scopes"}},{"kind":"Field","name":{"kind":"Name","value":"authorizationRules"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"claim"}},{"kind":"Field","name":{"kind":"Name","value":"operator"}},{"kind":"Field","name":{"kind":"Name","value":"value"}}]}},{"kind":"Field","name":{"kind":"Name","value":"authorizationRuleMode"}},{"kind":"Field","name":{"kind":"Name","value":"buttonText"}},{"kind":"Field","name":{"kind":"Name","value":"buttonIcon"}}]}}]}}]}}]}}]} as unknown as DocumentNode<OidcProvidersQuery, OidcProvidersQueryVariables>;
|
||||
export const PublicOidcProvidersDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"PublicOidcProviders"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"publicOidcProviders"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"buttonText"}},{"kind":"Field","name":{"kind":"Name","value":"buttonIcon"}},{"kind":"Field","name":{"kind":"Name","value":"buttonVariant"}},{"kind":"Field","name":{"kind":"Name","value":"buttonStyle"}}]}}]}}]} as unknown as DocumentNode<PublicOidcProvidersQuery, PublicOidcProvidersQueryVariables>;
|
||||
export const ServerInfoDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"info"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"os"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hostname"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"vars"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"comment"}}]}}]}}]} as unknown as DocumentNode<ServerInfoQuery, ServerInfoQueryVariables>;
|
||||
|
||||
Reference in New Issue
Block a user