mirror of
https://github.com/unraid/api.git
synced 2026-01-06 00:30:22 -06:00
Compare commits
8 Commits
4.28.2-bui
...
renovate/z
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4695e30db9 | ||
|
|
9ef1cf1eca | ||
|
|
a0745e15ca | ||
|
|
c39b0b267c | ||
|
|
73135b8328 | ||
|
|
e42d619b6d | ||
|
|
560db880cc | ||
|
|
d6055f102b |
@@ -1 +1 @@
|
||||
{".":"4.28.2"}
|
||||
{".":"4.29.2"}
|
||||
|
||||
@@ -1,5 +1,33 @@
|
||||
# Changelog
|
||||
|
||||
## [4.29.2](https://github.com/unraid/api/compare/v4.29.1...v4.29.2) (2025-12-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* unraid-connect plugin not loaded when connect is installed ([#1856](https://github.com/unraid/api/issues/1856)) ([73135b8](https://github.com/unraid/api/commit/73135b832801f5c76d60020161492e4770958c3d))
|
||||
|
||||
## [4.29.1](https://github.com/unraid/api/compare/v4.29.0...v4.29.1) (2025-12-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* revert replace docker overview table with web component (7.3+) ([#1853](https://github.com/unraid/api/issues/1853)) ([560db88](https://github.com/unraid/api/commit/560db880cc138324f9ff8753f7209b683a84c045))
|
||||
|
||||
## [4.29.0](https://github.com/unraid/api/compare/v4.28.2...v4.29.0) (2025-12-19)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* replace docker overview table with web component (7.3+) ([#1764](https://github.com/unraid/api/issues/1764)) ([277ac42](https://github.com/unraid/api/commit/277ac420464379e7ee6739c4530271caf7717503))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* handle race condition between guid loading and license check ([#1847](https://github.com/unraid/api/issues/1847)) ([8b155d1](https://github.com/unraid/api/commit/8b155d1f1c99bb19efbc9614e000d852e9f0c12d))
|
||||
* resolve issue with "Continue" button when updating ([#1852](https://github.com/unraid/api/issues/1852)) ([d099e75](https://github.com/unraid/api/commit/d099e7521d2062bb9cf84f340e46b169dd2492c5))
|
||||
* update myservers config references to connect config references ([#1810](https://github.com/unraid/api/issues/1810)) ([e1e3ea7](https://github.com/unraid/api/commit/e1e3ea7eb68cc6840f67a8aec937fd3740e75b28))
|
||||
|
||||
## [4.28.2](https://github.com/unraid/api/compare/v4.28.1...v4.28.2) (2025-12-16)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "4.28.2",
|
||||
"version": "4.29.2",
|
||||
"extraOrigins": [],
|
||||
"sandbox": true,
|
||||
"ssoSubIds": [],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@unraid/api",
|
||||
"version": "4.28.2",
|
||||
"version": "4.29.2",
|
||||
"main": "src/cli/index.ts",
|
||||
"type": "module",
|
||||
"corepack": {
|
||||
@@ -148,7 +148,7 @@
|
||||
"uuid": "13.0.0",
|
||||
"ws": "8.18.3",
|
||||
"zen-observable-ts": "1.1.0",
|
||||
"zod": "3.25.76"
|
||||
"zod": "4.3.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"unraid-api-plugin-connect": "workspace:*"
|
||||
|
||||
@@ -2,10 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import {
|
||||
AutoStartEntry,
|
||||
DockerAutostartService,
|
||||
} from '@app/unraid-api/graph/resolvers/docker/docker-autostart.service.js';
|
||||
import { DockerAutostartService } from '@app/unraid-api/graph/resolvers/docker/docker-autostart.service.js';
|
||||
import { DockerContainer } from '@app/unraid-api/graph/resolvers/docker/docker.model.js';
|
||||
|
||||
// Mock store getters
|
||||
|
||||
@@ -4,7 +4,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { AppError } from '@app/core/errors/app-error.js';
|
||||
import { DockerLogService } from '@app/unraid-api/graph/resolvers/docker/docker-log.service.js';
|
||||
import { DockerContainerLogs } from '@app/unraid-api/graph/resolvers/docker/docker.model.js';
|
||||
|
||||
// Mock dependencies
|
||||
const mockExeca = vi.fn();
|
||||
|
||||
@@ -91,7 +91,6 @@ export class DockerTailscaleService {
|
||||
);
|
||||
|
||||
const dnsName = rawStatus.Self.DNSName;
|
||||
const actualHostname = dnsName ? dnsName.split('.')[0] : undefined;
|
||||
|
||||
let relayName: string | undefined;
|
||||
if (rawStatus.Self.Relay && derpMap) {
|
||||
|
||||
@@ -2,7 +2,6 @@ import {
|
||||
Field,
|
||||
Float,
|
||||
GraphQLISODateTime,
|
||||
ID,
|
||||
InputType,
|
||||
Int,
|
||||
ObjectType,
|
||||
|
||||
@@ -13,11 +13,7 @@ import { DockerLogService } from '@app/unraid-api/graph/resolvers/docker/docker-
|
||||
import { DockerManifestService } from '@app/unraid-api/graph/resolvers/docker/docker-manifest.service.js';
|
||||
import { DockerNetworkService } from '@app/unraid-api/graph/resolvers/docker/docker-network.service.js';
|
||||
import { DockerPortService } from '@app/unraid-api/graph/resolvers/docker/docker-port.service.js';
|
||||
import {
|
||||
ContainerPortType,
|
||||
ContainerState,
|
||||
DockerContainer,
|
||||
} from '@app/unraid-api/graph/resolvers/docker/docker.model.js';
|
||||
import { ContainerState, DockerContainer } from '@app/unraid-api/graph/resolvers/docker/docker.model.js';
|
||||
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
|
||||
import { NotificationsService } from '@app/unraid-api/graph/resolvers/notifications/notifications.service.js';
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ export class DockerService {
|
||||
await this.cacheManager.del(DockerService.CONTAINER_CACHE_KEY);
|
||||
this.logger.debug(`Invalidated container cache after pausing ${id}`);
|
||||
|
||||
let containers = await this.getContainers({ skipCache: true });
|
||||
let containers: DockerContainer[];
|
||||
let updatedContainer: DockerContainer | undefined;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await sleep(500);
|
||||
@@ -349,7 +349,7 @@ export class DockerService {
|
||||
await this.cacheManager.del(DockerService.CONTAINER_CACHE_KEY);
|
||||
this.logger.debug(`Invalidated container cache after unpausing ${id}`);
|
||||
|
||||
let containers = await this.getContainers({ skipCache: true });
|
||||
let containers: DockerContainer[];
|
||||
let updatedContainer: DockerContainer | undefined;
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await sleep(500);
|
||||
|
||||
@@ -683,7 +683,7 @@ export interface MoveItemsToPositionParams {
|
||||
* Combines moveEntriesToFolder with position-based insertion.
|
||||
*/
|
||||
export function moveItemsToPosition(params: MoveItemsToPositionParams): OrganizerView {
|
||||
const { view, sourceEntryIds, destinationFolderId, position, resources } = params;
|
||||
const { view, sourceEntryIds, destinationFolderId, position } = params;
|
||||
|
||||
const movedView = moveEntriesToFolder({ view, sourceEntryIds, destinationFolderId });
|
||||
|
||||
@@ -743,7 +743,7 @@ export interface CreateFolderWithItemsParams {
|
||||
* Combines createFolder + moveItems + positioning in a single atomic operation.
|
||||
*/
|
||||
export function createFolderWithItems(params: CreateFolderWithItemsParams): OrganizerView {
|
||||
const { view, folderId, folderName, parentId, sourceEntryIds = [], position, resources } = params;
|
||||
const { view, folderId, folderName, parentId, sourceEntryIds = [], position } = params;
|
||||
|
||||
let newView = createFolderInView({
|
||||
view,
|
||||
|
||||
@@ -91,13 +91,9 @@ export class PluginService {
|
||||
return name;
|
||||
})
|
||||
);
|
||||
const { peerDependencies } = getPackageJson();
|
||||
// All api plugins must be installed as peer dependencies of the unraid-api package
|
||||
if (!peerDependencies) {
|
||||
PluginService.logger.warn('Unraid-API peer dependencies not found; skipping plugins.');
|
||||
return [];
|
||||
}
|
||||
const pluginTuples = Object.entries(peerDependencies).filter(
|
||||
const { peerDependencies = {}, dependencies = {} } = getPackageJson();
|
||||
const allDependencies = { ...peerDependencies, ...dependencies };
|
||||
const pluginTuples = Object.entries(allDependencies).filter(
|
||||
(entry): entry is [string, string] => {
|
||||
const [pkgName, version] = entry;
|
||||
return pluginNames.has(pkgName) && typeof version === 'string';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "unraid-monorepo",
|
||||
"private": true,
|
||||
"version": "4.28.2",
|
||||
"version": "4.29.2",
|
||||
"scripts": {
|
||||
"build": "pnpm -r build",
|
||||
"build:watch": "pnpm -r --parallel --filter '!@unraid/ui' build:watch",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@unraid/connect-plugin",
|
||||
"version": "4.28.2",
|
||||
"version": "4.29.2",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"commander": "14.0.0",
|
||||
@@ -11,7 +11,7 @@
|
||||
"html-sloppy-escaper": "0.1.0",
|
||||
"semver": "7.7.2",
|
||||
"tsx": "4.20.5",
|
||||
"zod": "3.25.76",
|
||||
"zod": "4.3.5",
|
||||
"zx": "8.8.1"
|
||||
},
|
||||
"type": "module",
|
||||
|
||||
56
pnpm-lock.yaml
generated
56
pnpm-lock.yaml
generated
@@ -323,8 +323,8 @@ importers:
|
||||
specifier: 1.1.0
|
||||
version: 1.1.0
|
||||
zod:
|
||||
specifier: 3.25.76
|
||||
version: 3.25.76
|
||||
specifier: 4.3.5
|
||||
version: 4.3.5
|
||||
devDependencies:
|
||||
'@eslint/js':
|
||||
specifier: 9.34.0
|
||||
@@ -837,8 +837,8 @@ importers:
|
||||
specifier: 4.20.5
|
||||
version: 4.20.5
|
||||
zod:
|
||||
specifier: 3.25.76
|
||||
version: 3.25.76
|
||||
specifier: 4.3.5
|
||||
version: 4.3.5
|
||||
zx:
|
||||
specifier: 8.8.1
|
||||
version: 8.8.1
|
||||
@@ -1090,7 +1090,7 @@ importers:
|
||||
version: 3.6.0(@jsonforms/core@3.6.0)(@jsonforms/vue@3.6.0(@jsonforms/core@3.6.0)(vue@3.5.20(typescript@5.9.2)))(ajv@8.17.1)(dayjs@1.11.14)(lodash@4.17.21)(maska@2.1.11)(vue@3.5.20(typescript@5.9.2))(vuetify@3.9.6)
|
||||
'@nuxt/ui':
|
||||
specifier: 4.0.0-alpha.0
|
||||
version: 4.0.0-alpha.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(focus-trap@7.6.5)(ioredis@5.7.0)(jwt-decode@4.0.0)(magicast@0.3.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(lightningcss@1.30.1)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.20(typescript@5.9.2)))(vue@3.5.20(typescript@5.9.2))(zod@3.25.76)
|
||||
version: 4.0.0-alpha.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(focus-trap@7.6.5)(ioredis@5.7.0)(jwt-decode@4.0.0)(magicast@0.3.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(lightningcss@1.30.1)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.20(typescript@5.9.2)))(vue@3.5.20(typescript@5.9.2))(zod@4.3.5)
|
||||
'@tanstack/vue-table':
|
||||
specifier: ^8.21.3
|
||||
version: 8.21.3(vue@3.5.20(typescript@5.9.2))
|
||||
@@ -12451,8 +12451,8 @@ packages:
|
||||
vue-component-type-helpers@3.0.6:
|
||||
resolution: {integrity: sha512-6CRM8X7EJqWCJOiKPvSLQG+hJPb/Oy2gyJx3pLjUEhY7PuaCthQu3e0zAGI1lqUBobrrk9IT0K8sG2GsCluxoQ==}
|
||||
|
||||
vue-component-type-helpers@3.1.3:
|
||||
resolution: {integrity: sha512-V1dOD8XYfstOKCnXbWyEJIrhTBMwSyNjv271L1Jlx9ExpNlCSuqOs3OdWrGJ0V544zXufKbcYabi/o+gK8lyfQ==}
|
||||
vue-component-type-helpers@3.2.1:
|
||||
resolution: {integrity: sha512-gKV7XOkQl4urSuLHNY1tnVQf7wVgtb/mKbRyxSLWGZUY9RK7aDPhBenTjm+i8ZFe0zC2PZeHMPtOZXZfyaFOzQ==}
|
||||
|
||||
vue-demi@0.14.10:
|
||||
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
|
||||
@@ -12486,6 +12486,7 @@ packages:
|
||||
vue-i18n@11.1.11:
|
||||
resolution: {integrity: sha512-LvyteQoXeQiuILbzqv13LbyBna/TEv2Ha+4ZWK2AwGHUzZ8+IBaZS0TJkCgn5izSPLcgZwXy9yyTrewCb2u/MA==}
|
||||
engines: {node: '>= 16'}
|
||||
deprecated: This version is NOT deprecated. Previous deprecation was a mistake.
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
|
||||
@@ -12576,10 +12577,12 @@ packages:
|
||||
whatwg-encoding@2.0.0:
|
||||
resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==}
|
||||
engines: {node: '>=12'}
|
||||
deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
|
||||
|
||||
whatwg-encoding@3.1.1:
|
||||
resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==}
|
||||
engines: {node: '>=18'}
|
||||
deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation
|
||||
|
||||
whatwg-mimetype@3.0.0:
|
||||
resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
|
||||
@@ -12876,6 +12879,9 @@ packages:
|
||||
zod@3.25.76:
|
||||
resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
|
||||
|
||||
zod@4.3.5:
|
||||
resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==}
|
||||
|
||||
zx@8.8.1:
|
||||
resolution: {integrity: sha512-qvsKBnvWHstHKCluKPlEgI/D3+mdiQyMoSSeFR8IX/aXzWIas5A297KxKgPJhuPXdrR6ma0Jzx43+GQ/8sqbrw==}
|
||||
engines: {node: '>= 12.17.0'}
|
||||
@@ -12885,27 +12891,27 @@ snapshots:
|
||||
|
||||
'@adobe/css-tools@4.4.3': {}
|
||||
|
||||
'@ai-sdk/gateway@1.0.15(zod@3.25.76)':
|
||||
'@ai-sdk/gateway@1.0.15(zod@4.3.5)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 2.0.0
|
||||
'@ai-sdk/provider-utils': 3.0.7(zod@3.25.76)
|
||||
zod: 3.25.76
|
||||
'@ai-sdk/provider-utils': 3.0.7(zod@4.3.5)
|
||||
zod: 4.3.5
|
||||
|
||||
'@ai-sdk/provider-utils@3.0.7(zod@3.25.76)':
|
||||
'@ai-sdk/provider-utils@3.0.7(zod@4.3.5)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider': 2.0.0
|
||||
'@standard-schema/spec': 1.0.0
|
||||
eventsource-parser: 3.0.5
|
||||
zod: 3.25.76
|
||||
zod: 4.3.5
|
||||
|
||||
'@ai-sdk/provider@2.0.0':
|
||||
dependencies:
|
||||
json-schema: 0.4.0
|
||||
|
||||
'@ai-sdk/vue@2.0.26(vue@3.5.20(typescript@5.9.2))(zod@3.25.76)':
|
||||
'@ai-sdk/vue@2.0.26(vue@3.5.20(typescript@5.9.2))(zod@4.3.5)':
|
||||
dependencies:
|
||||
'@ai-sdk/provider-utils': 3.0.7(zod@3.25.76)
|
||||
ai: 5.0.26(zod@3.25.76)
|
||||
'@ai-sdk/provider-utils': 3.0.7(zod@4.3.5)
|
||||
ai: 5.0.26(zod@4.3.5)
|
||||
swrv: 1.1.0(vue@3.5.20(typescript@5.9.2))
|
||||
optionalDependencies:
|
||||
vue: 3.5.20(typescript@5.9.2)
|
||||
@@ -15685,9 +15691,9 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- magicast
|
||||
|
||||
'@nuxt/ui@4.0.0-alpha.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(focus-trap@7.6.5)(ioredis@5.7.0)(jwt-decode@4.0.0)(magicast@0.3.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(lightningcss@1.30.1)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.20(typescript@5.9.2)))(vue@3.5.20(typescript@5.9.2))(zod@3.25.76)':
|
||||
'@nuxt/ui@4.0.0-alpha.0(@babel/parser@7.28.4)(@netlify/blobs@9.1.2)(change-case@5.4.4)(db0@0.3.2)(embla-carousel@8.6.0)(focus-trap@7.6.5)(ioredis@5.7.0)(jwt-decode@4.0.0)(magicast@0.3.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.9.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(lightningcss@1.30.1)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))(vue-router@4.5.1(vue@3.5.20(typescript@5.9.2)))(vue@3.5.20(typescript@5.9.2))(zod@4.3.5)':
|
||||
dependencies:
|
||||
'@ai-sdk/vue': 2.0.26(vue@3.5.20(typescript@5.9.2))(zod@3.25.76)
|
||||
'@ai-sdk/vue': 2.0.26(vue@3.5.20(typescript@5.9.2))(zod@4.3.5)
|
||||
'@iconify/vue': 5.0.0(vue@3.5.20(typescript@5.9.2))
|
||||
'@internationalized/date': 3.8.2
|
||||
'@internationalized/number': 3.6.5
|
||||
@@ -15735,7 +15741,7 @@ snapshots:
|
||||
vue-component-type-helpers: 3.0.6
|
||||
optionalDependencies:
|
||||
vue-router: 4.5.1(vue@3.5.20(typescript@5.9.2))
|
||||
zod: 3.25.76
|
||||
zod: 4.3.5
|
||||
transitivePeerDependencies:
|
||||
- '@azure/app-configuration'
|
||||
- '@azure/cosmos'
|
||||
@@ -16519,7 +16525,7 @@ snapshots:
|
||||
storybook: 9.1.3(@testing-library/dom@10.4.0)(prettier@3.6.2)(vite@7.1.3(@types/node@22.18.0)(jiti@2.5.1)(lightningcss@1.30.1)(stylus@0.57.0)(terser@5.43.1)(tsx@4.20.5)(yaml@2.8.1))
|
||||
type-fest: 2.19.0
|
||||
vue: 3.5.20(typescript@5.9.2)
|
||||
vue-component-type-helpers: 3.1.3
|
||||
vue-component-type-helpers: 3.2.1
|
||||
|
||||
'@swc/core-darwin-arm64@1.13.5':
|
||||
optional: true
|
||||
@@ -17865,13 +17871,13 @@ snapshots:
|
||||
|
||||
agent-base@7.1.3: {}
|
||||
|
||||
ai@5.0.26(zod@3.25.76):
|
||||
ai@5.0.26(zod@4.3.5):
|
||||
dependencies:
|
||||
'@ai-sdk/gateway': 1.0.15(zod@3.25.76)
|
||||
'@ai-sdk/gateway': 1.0.15(zod@4.3.5)
|
||||
'@ai-sdk/provider': 2.0.0
|
||||
'@ai-sdk/provider-utils': 3.0.7(zod@3.25.76)
|
||||
'@ai-sdk/provider-utils': 3.0.7(zod@4.3.5)
|
||||
'@opentelemetry/api': 1.9.0
|
||||
zod: 3.25.76
|
||||
zod: 4.3.5
|
||||
|
||||
ajv-errors@3.0.0(ajv@8.17.1):
|
||||
dependencies:
|
||||
@@ -25363,7 +25369,7 @@ snapshots:
|
||||
|
||||
vue-component-type-helpers@3.0.6: {}
|
||||
|
||||
vue-component-type-helpers@3.1.3: {}
|
||||
vue-component-type-helpers@3.2.1: {}
|
||||
|
||||
vue-demi@0.14.10(vue@3.5.20(typescript@5.9.2)):
|
||||
dependencies:
|
||||
@@ -25895,4 +25901,6 @@ snapshots:
|
||||
|
||||
zod@3.25.76: {}
|
||||
|
||||
zod@4.3.5: {}
|
||||
|
||||
zx@8.8.1: {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@unraid/ui",
|
||||
"version": "4.28.2",
|
||||
"version": "4.29.2",
|
||||
"private": true,
|
||||
"license": "GPL-2.0-or-later",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@unraid/web",
|
||||
"version": "4.28.2",
|
||||
"version": "4.29.2",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"license": "GPL-2.0-or-later",
|
||||
|
||||
@@ -299,9 +299,7 @@ function createCellWrapper(
|
||||
});
|
||||
}
|
||||
|
||||
function wrapColumnHeaderRenderer(
|
||||
header: ColumnHeaderRenderer | undefined
|
||||
): ColumnHeaderRenderer | undefined {
|
||||
function wrapColumnHeaderRenderer(header: ColumnHeaderRenderer | undefined): ColumnHeaderRenderer {
|
||||
if (typeof header === 'function') {
|
||||
return function wrappedHeaderRenderer(this: unknown, ...args: unknown[]) {
|
||||
const result = (header as (...args: unknown[]) => unknown).apply(this, args);
|
||||
@@ -481,7 +479,7 @@ const processedColumns = computed<TableColumn<TreeRow<T>>[]>(() => {
|
||||
createSelectColumn(),
|
||||
...props.columns.map((col, colIndex) => {
|
||||
const originalHeader = col.header as ColumnHeaderRenderer | undefined;
|
||||
const header = wrapColumnHeaderRenderer(originalHeader) ?? originalHeader;
|
||||
const header = wrapColumnHeaderRenderer(originalHeader);
|
||||
const cell = (col as { cell?: unknown }).cell
|
||||
? ({ row }: { row: TableInstanceRow<T> }) => {
|
||||
const cellFn = (col as { cell: (args: unknown) => VNode | string | number }).cell;
|
||||
|
||||
@@ -68,6 +68,10 @@ function appendLogLines(newLines: Array<{ timestamp: string; message: string }>)
|
||||
|
||||
state.lines = [...state.lines, ...added];
|
||||
if (state.lines.length > MAX_LOG_LINES) {
|
||||
const removed = state.lines.slice(0, state.lines.length - MAX_LOG_LINES);
|
||||
for (const line of removed) {
|
||||
state.lineKeys.delete(`${line.timestamp}|${line.message}`);
|
||||
}
|
||||
state.lines = state.lines.slice(state.lines.length - MAX_LOG_LINES);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ const refreshLogContent = async () => {
|
||||
startLogSubscription();
|
||||
};
|
||||
|
||||
watch(() => props.logFilePath, refreshLogContent);
|
||||
watch(() => props.logFilePath, refreshLogContent, { immediate: true });
|
||||
defineExpose({ refreshLogContent });
|
||||
</script>
|
||||
|
||||
|
||||
@@ -142,14 +142,16 @@ const dismissNotification = async (notification: NotificationFragmentFragment) =
|
||||
const { onResult: onNotificationAdded } = useSubscription(notificationAddedSubscription);
|
||||
|
||||
onNotificationAdded(({ data }) => {
|
||||
if (!data) {
|
||||
if (!data?.notificationAdded) {
|
||||
return;
|
||||
}
|
||||
const notification = useFragment(NOTIFICATION_FRAGMENT, data.notificationAdded);
|
||||
|
||||
// Access raw subscription data directly - don't call useFragment in async callback
|
||||
const rawNotification = data.notificationAdded as unknown as NotificationFragmentFragment;
|
||||
if (
|
||||
!notification ||
|
||||
(notification.importance !== NotificationImportance.ALERT &&
|
||||
notification.importance !== NotificationImportance.WARNING)
|
||||
!rawNotification ||
|
||||
(rawNotification.importance !== NotificationImportance.ALERT &&
|
||||
rawNotification.importance !== NotificationImportance.WARNING)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
@@ -160,7 +162,7 @@ onNotificationAdded(({ data }) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (notification.timestamp) {
|
||||
if (rawNotification.timestamp) {
|
||||
// Trigger the global toast in tandem with the subscription update.
|
||||
const funcMapping: Record<
|
||||
NotificationImportance,
|
||||
@@ -170,16 +172,16 @@ onNotificationAdded(({ data }) => {
|
||||
[NotificationImportance.WARNING]: globalThis.toast.warning,
|
||||
[NotificationImportance.INFO]: globalThis.toast.info,
|
||||
};
|
||||
const toast = funcMapping[notification.importance];
|
||||
const toast = funcMapping[rawNotification.importance];
|
||||
const createOpener = () => ({
|
||||
label: 'Open',
|
||||
onClick: () => notification.link && window.open(notification.link, '_blank', 'noopener'),
|
||||
onClick: () => rawNotification.link && window.open(rawNotification.link, '_blank', 'noopener'),
|
||||
});
|
||||
|
||||
requestAnimationFrame(() =>
|
||||
toast(notification.title, {
|
||||
description: notification.subject,
|
||||
action: notification.link ? createOpener() : undefined,
|
||||
toast(rawNotification.title, {
|
||||
description: rawNotification.subject,
|
||||
action: rawNotification.link ? createOpener() : undefined,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,6 +75,9 @@ function ensurePortalRoot(): string | undefined {
|
||||
}
|
||||
|
||||
ensureUnapiScope(portalRoot);
|
||||
if (isDarkModeActive()) {
|
||||
portalRoot.classList.add('dark');
|
||||
}
|
||||
|
||||
return `#${PORTAL_ROOT_ID}`;
|
||||
}
|
||||
|
||||
@@ -39,12 +39,12 @@ export function useContainerActions<T = unknown>(options: ContainerActionOptions
|
||||
const confirmStartStopOpen = ref(false);
|
||||
const confirmToStart = ref<{ name: string }[]>([]);
|
||||
const confirmToStop = ref<{ name: string }[]>([]);
|
||||
let pendingStartStopIds: string[] = [];
|
||||
const pendingStartStopIds = ref<string[]>([]);
|
||||
|
||||
const confirmPauseResumeOpen = ref(false);
|
||||
const confirmToPause = ref<{ name: string }[]>([]);
|
||||
const confirmToResume = ref<{ name: string }[]>([]);
|
||||
let pendingPauseResumeIds: string[] = [];
|
||||
const pendingPauseResumeIds = ref<string[]>([]);
|
||||
|
||||
function classifyStartStop(ids: string[]) {
|
||||
const toStart: { id: string; containerId: string; name: string }[] = [];
|
||||
@@ -201,7 +201,7 @@ export function useContainerActions<T = unknown>(options: ContainerActionOptions
|
||||
const { toStart, toStop } = classifyStartStop(ids);
|
||||
const isMixed = toStart.length > 0 && toStop.length > 0;
|
||||
if (isMixed) {
|
||||
pendingStartStopIds = ids;
|
||||
pendingStartStopIds.value = ids;
|
||||
confirmToStart.value = toStart.map((i) => ({ name: i.name }));
|
||||
confirmToStop.value = toStop.map((i) => ({ name: i.name }));
|
||||
confirmStartStopOpen.value = true;
|
||||
@@ -216,15 +216,15 @@ export function useContainerActions<T = unknown>(options: ContainerActionOptions
|
||||
}
|
||||
|
||||
async function confirmStartStop(close: () => void) {
|
||||
const { toStart, toStop } = classifyStartStop(pendingStartStopIds);
|
||||
setRowsBusy(pendingStartStopIds, true);
|
||||
const { toStart, toStop } = classifyStartStop(pendingStartStopIds.value);
|
||||
setRowsBusy(pendingStartStopIds.value, true);
|
||||
try {
|
||||
await runStartStopBatch(toStart, toStop);
|
||||
onSuccess?.('Action completed');
|
||||
} finally {
|
||||
setRowsBusy(pendingStartStopIds, false);
|
||||
setRowsBusy(pendingStartStopIds.value, false);
|
||||
confirmStartStopOpen.value = false;
|
||||
pendingStartStopIds = [];
|
||||
pendingStartStopIds.value = [];
|
||||
close();
|
||||
}
|
||||
}
|
||||
@@ -234,7 +234,7 @@ export function useContainerActions<T = unknown>(options: ContainerActionOptions
|
||||
const { toPause, toResume } = classifyPauseResume(ids);
|
||||
const isMixed = toPause.length > 0 && toResume.length > 0;
|
||||
if (isMixed) {
|
||||
pendingPauseResumeIds = ids;
|
||||
pendingPauseResumeIds.value = ids;
|
||||
confirmToPause.value = toPause.map((i) => ({ name: i.name }));
|
||||
confirmToResume.value = toResume.map((i) => ({ name: i.name }));
|
||||
confirmPauseResumeOpen.value = true;
|
||||
@@ -249,15 +249,15 @@ export function useContainerActions<T = unknown>(options: ContainerActionOptions
|
||||
}
|
||||
|
||||
async function confirmPauseResume(close: () => void) {
|
||||
const { toPause, toResume } = classifyPauseResume(pendingPauseResumeIds);
|
||||
setRowsBusy(pendingPauseResumeIds, true);
|
||||
const { toPause, toResume } = classifyPauseResume(pendingPauseResumeIds.value);
|
||||
setRowsBusy(pendingPauseResumeIds.value, true);
|
||||
try {
|
||||
await runPauseResumeBatch(toPause, toResume);
|
||||
onSuccess?.('Action completed');
|
||||
} finally {
|
||||
setRowsBusy(pendingPauseResumeIds, false);
|
||||
setRowsBusy(pendingPauseResumeIds.value, false);
|
||||
confirmPauseResumeOpen.value = false;
|
||||
pendingPauseResumeIds = [];
|
||||
pendingPauseResumeIds.value = [];
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user