@trops/dash-core 0.1.86 → 0.1.88
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/electron/index.js +439 -123
- package/dist/electron/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -588,10 +588,14 @@ var clientCacheEvents$1 = {
|
|
|
588
588
|
|
|
589
589
|
const DASHBOARD_CONFIG_EXPORT$1 = "dashboard-config-export";
|
|
590
590
|
const DASHBOARD_CONFIG_IMPORT$1 = "dashboard-config-import";
|
|
591
|
+
const DASHBOARD_CONFIG_INSTALL$1 = "dashboard-config-install";
|
|
592
|
+
const DASHBOARD_CONFIG_COMPATIBILITY$1 = "dashboard-config-compatibility";
|
|
591
593
|
|
|
592
594
|
var dashboardConfigEvents$1 = {
|
|
593
|
-
|
|
594
|
-
|
|
595
|
+
DASHBOARD_CONFIG_EXPORT: DASHBOARD_CONFIG_EXPORT$1,
|
|
596
|
+
DASHBOARD_CONFIG_IMPORT: DASHBOARD_CONFIG_IMPORT$1,
|
|
597
|
+
DASHBOARD_CONFIG_INSTALL: DASHBOARD_CONFIG_INSTALL$1,
|
|
598
|
+
DASHBOARD_CONFIG_COMPATIBILITY: DASHBOARD_CONFIG_COMPATIBILITY$1,
|
|
595
599
|
};
|
|
596
600
|
|
|
597
601
|
/**
|
|
@@ -8354,12 +8358,98 @@ function applyEventWiringToLayout$1(layout, eventWiring) {
|
|
|
8354
8358
|
return layout;
|
|
8355
8359
|
}
|
|
8356
8360
|
|
|
8361
|
+
/**
|
|
8362
|
+
* Check compatibility of a dashboard config against installed widgets.
|
|
8363
|
+
* Returns a per-widget status report indicating what's installed,
|
|
8364
|
+
* what needs to be installed, and what's unavailable.
|
|
8365
|
+
*
|
|
8366
|
+
* @param {Array} dashboardWidgets - Widget deps from dashboard config (widgets array)
|
|
8367
|
+
* @param {Array} installedWidgets - Currently installed widget metadata (from widgetRegistry.getWidgets())
|
|
8368
|
+
* @param {Array} registryPackages - Available packages from registry index (optional)
|
|
8369
|
+
* @returns {Object} Compatibility report
|
|
8370
|
+
*/
|
|
8371
|
+
function checkDashboardCompatibility(
|
|
8372
|
+
dashboardWidgets = [],
|
|
8373
|
+
installedWidgets = [],
|
|
8374
|
+
registryPackages = [],
|
|
8375
|
+
) {
|
|
8376
|
+
const installedByName = new Map();
|
|
8377
|
+
for (const w of installedWidgets) {
|
|
8378
|
+
if (w.name) {
|
|
8379
|
+
installedByName.set(w.name, w);
|
|
8380
|
+
}
|
|
8381
|
+
}
|
|
8382
|
+
|
|
8383
|
+
const registryByName = new Map();
|
|
8384
|
+
for (const p of registryPackages) {
|
|
8385
|
+
if (p.name) {
|
|
8386
|
+
registryByName.set(p.name, p);
|
|
8387
|
+
}
|
|
8388
|
+
}
|
|
8389
|
+
|
|
8390
|
+
const widgets = [];
|
|
8391
|
+
let installedCount = 0;
|
|
8392
|
+
let toInstallCount = 0;
|
|
8393
|
+
let unavailableCount = 0;
|
|
8394
|
+
|
|
8395
|
+
for (const dep of dashboardWidgets) {
|
|
8396
|
+
const packageName = dep.package;
|
|
8397
|
+
const required = dep.required !== false;
|
|
8398
|
+
const installed = installedByName.get(packageName);
|
|
8399
|
+
|
|
8400
|
+
if (installed) {
|
|
8401
|
+
installedCount++;
|
|
8402
|
+
widgets.push({
|
|
8403
|
+
package: packageName,
|
|
8404
|
+
required,
|
|
8405
|
+
status: "installed",
|
|
8406
|
+
installedVersion: installed.version || null,
|
|
8407
|
+
requiredVersion: dep.version || "*",
|
|
8408
|
+
});
|
|
8409
|
+
} else if (registryByName.has(packageName)) {
|
|
8410
|
+
toInstallCount++;
|
|
8411
|
+
const registryPkg = registryByName.get(packageName);
|
|
8412
|
+
widgets.push({
|
|
8413
|
+
package: packageName,
|
|
8414
|
+
required,
|
|
8415
|
+
status: "to-install",
|
|
8416
|
+
availableVersion: registryPkg.version || null,
|
|
8417
|
+
requiredVersion: dep.version || "*",
|
|
8418
|
+
});
|
|
8419
|
+
} else {
|
|
8420
|
+
unavailableCount++;
|
|
8421
|
+
widgets.push({
|
|
8422
|
+
package: packageName,
|
|
8423
|
+
required,
|
|
8424
|
+
status: "unavailable",
|
|
8425
|
+
requiredVersion: dep.version || "*",
|
|
8426
|
+
});
|
|
8427
|
+
}
|
|
8428
|
+
}
|
|
8429
|
+
|
|
8430
|
+
const hasUnavailableRequired = widgets.some(
|
|
8431
|
+
(w) => w.status === "unavailable" && w.required,
|
|
8432
|
+
);
|
|
8433
|
+
|
|
8434
|
+
return {
|
|
8435
|
+
compatible: !hasUnavailableRequired,
|
|
8436
|
+
summary: {
|
|
8437
|
+
total: dashboardWidgets.length,
|
|
8438
|
+
installed: installedCount,
|
|
8439
|
+
toInstall: toInstallCount,
|
|
8440
|
+
unavailable: unavailableCount,
|
|
8441
|
+
},
|
|
8442
|
+
widgets,
|
|
8443
|
+
};
|
|
8444
|
+
}
|
|
8445
|
+
|
|
8357
8446
|
var dashboardConfigUtils$1 = {
|
|
8358
8447
|
collectComponentNames: collectComponentNames$1,
|
|
8359
8448
|
extractEventWiring: extractEventWiring$1,
|
|
8360
8449
|
buildWidgetDependencies: buildWidgetDependencies$1,
|
|
8361
8450
|
buildProviderRequirements: buildProviderRequirements$1,
|
|
8362
8451
|
applyEventWiringToLayout: applyEventWiringToLayout$1,
|
|
8452
|
+
checkDashboardCompatibility,
|
|
8363
8453
|
};
|
|
8364
8454
|
|
|
8365
8455
|
var widgetRegistry$1 = {exports: {}};
|
|
@@ -9974,134 +10064,292 @@ async function importDashboardConfig$1(win, appId, widgetRegistry = null) {
|
|
|
9974
10064
|
// Apply defaults to fill in optional fields
|
|
9975
10065
|
dashboardConfig = applyDefaults(dashboardConfig);
|
|
9976
10066
|
|
|
9977
|
-
//
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
10067
|
+
// Delegate to shared import pipeline
|
|
10068
|
+
return await processDashboardConfig(
|
|
10069
|
+
win,
|
|
10070
|
+
appId,
|
|
10071
|
+
dashboardConfig,
|
|
10072
|
+
widgetRegistry,
|
|
10073
|
+
);
|
|
10074
|
+
} catch (error) {
|
|
10075
|
+
console.error(
|
|
10076
|
+
"[DashboardConfigController] Error importing dashboard:",
|
|
10077
|
+
error,
|
|
10078
|
+
);
|
|
10079
|
+
return {
|
|
10080
|
+
success: false,
|
|
10081
|
+
error: error.message,
|
|
9982
10082
|
};
|
|
10083
|
+
}
|
|
10084
|
+
}
|
|
9983
10085
|
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
10086
|
+
/**
|
|
10087
|
+
* Shared import pipeline: install widgets, create workspace, wire events.
|
|
10088
|
+
* Used by both importDashboardConfig (ZIP) and installDashboardFromRegistry.
|
|
10089
|
+
*
|
|
10090
|
+
* @param {BrowserWindow} win - The main window
|
|
10091
|
+
* @param {string} appId - Application identifier
|
|
10092
|
+
* @param {Object} dashboardConfig - Validated dashboard config object
|
|
10093
|
+
* @param {Object} widgetRegistry - WidgetRegistry instance
|
|
10094
|
+
* @param {Object} options - Additional options
|
|
10095
|
+
* @param {string} options.source - Source label ("zip" or "registry")
|
|
10096
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
10097
|
+
*/
|
|
10098
|
+
async function processDashboardConfig(
|
|
10099
|
+
win,
|
|
10100
|
+
appId,
|
|
10101
|
+
dashboardConfig,
|
|
10102
|
+
widgetRegistry = null,
|
|
10103
|
+
options = {},
|
|
10104
|
+
) {
|
|
10105
|
+
const source = options.source || "zip";
|
|
9991
10106
|
|
|
9992
|
-
|
|
9993
|
-
|
|
10107
|
+
// 1. Auto-install missing widgets from registry
|
|
10108
|
+
const installSummary = {
|
|
10109
|
+
installed: [],
|
|
10110
|
+
alreadyInstalled: [],
|
|
10111
|
+
failed: [],
|
|
10112
|
+
};
|
|
9994
10113
|
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
10114
|
+
if (
|
|
10115
|
+
widgetRegistry &&
|
|
10116
|
+
dashboardConfig.widgets &&
|
|
10117
|
+
dashboardConfig.widgets.length
|
|
10118
|
+
) {
|
|
10119
|
+
const installedWidgets = widgetRegistry.getWidgets();
|
|
10120
|
+
const installedPackages = new Set(installedWidgets.map((w) => w.name));
|
|
9999
10121
|
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10122
|
+
for (const widgetDep of dashboardConfig.widgets) {
|
|
10123
|
+
const packageName = widgetDep.package;
|
|
10124
|
+
|
|
10125
|
+
if (installedPackages.has(packageName)) {
|
|
10126
|
+
installSummary.alreadyInstalled.push(packageName);
|
|
10127
|
+
continue;
|
|
10128
|
+
}
|
|
10129
|
+
|
|
10130
|
+
// Try to find the widget in the registry and install it
|
|
10131
|
+
try {
|
|
10132
|
+
const registryPkg = await getPackage(packageName);
|
|
10133
|
+
if (registryPkg && registryPkg.downloadUrl) {
|
|
10134
|
+
await widgetRegistry.downloadWidget(
|
|
10135
|
+
packageName,
|
|
10136
|
+
registryPkg.downloadUrl,
|
|
10137
|
+
registryPkg.dashConfigUrl || null,
|
|
10138
|
+
);
|
|
10139
|
+
installSummary.installed.push(packageName);
|
|
10140
|
+
installedPackages.add(packageName);
|
|
10141
|
+
} else {
|
|
10018
10142
|
installSummary.failed.push({
|
|
10019
10143
|
package: packageName,
|
|
10020
|
-
reason:
|
|
10144
|
+
reason: "Not found in registry",
|
|
10021
10145
|
});
|
|
10022
10146
|
}
|
|
10147
|
+
} catch (installError) {
|
|
10148
|
+
installSummary.failed.push({
|
|
10149
|
+
package: packageName,
|
|
10150
|
+
reason: installError.message,
|
|
10151
|
+
});
|
|
10023
10152
|
}
|
|
10024
10153
|
}
|
|
10154
|
+
}
|
|
10025
10155
|
|
|
10026
|
-
|
|
10027
|
-
|
|
10156
|
+
// 2. Build workspace from config
|
|
10157
|
+
const workspace = { ...dashboardConfig.workspace };
|
|
10028
10158
|
|
|
10029
|
-
|
|
10159
|
+
if (!workspace || !workspace.layout) {
|
|
10160
|
+
return {
|
|
10161
|
+
success: false,
|
|
10162
|
+
error: "Dashboard config has no workspace data",
|
|
10163
|
+
};
|
|
10164
|
+
}
|
|
10165
|
+
|
|
10166
|
+
// Generate a unique ID for the imported workspace
|
|
10167
|
+
workspace.id = Date.now();
|
|
10168
|
+
|
|
10169
|
+
// 3. Apply event wiring to layout
|
|
10170
|
+
const eventWiringSummary = [];
|
|
10171
|
+
if (
|
|
10172
|
+
dashboardConfig.eventWiring &&
|
|
10173
|
+
dashboardConfig.eventWiring.length &&
|
|
10174
|
+
workspace.layout
|
|
10175
|
+
) {
|
|
10176
|
+
applyEventWiringToLayout(workspace.layout, dashboardConfig.eventWiring);
|
|
10177
|
+
for (const wire of dashboardConfig.eventWiring) {
|
|
10178
|
+
eventWiringSummary.push(
|
|
10179
|
+
`${wire.source?.widget}.${wire.source?.event} → ${wire.target?.widget}.${wire.target?.handler}`,
|
|
10180
|
+
);
|
|
10181
|
+
}
|
|
10182
|
+
}
|
|
10183
|
+
|
|
10184
|
+
// 4. Mark as not shareable (imported dashboards cannot be re-published)
|
|
10185
|
+
workspace._dashboardConfig = {
|
|
10186
|
+
shareable: false,
|
|
10187
|
+
source,
|
|
10188
|
+
importedFrom: dashboardConfig.name,
|
|
10189
|
+
importedAt: new Date().toISOString(),
|
|
10190
|
+
originalAuthor: dashboardConfig.author,
|
|
10191
|
+
schemaVersion: dashboardConfig.schemaVersion,
|
|
10192
|
+
};
|
|
10193
|
+
|
|
10194
|
+
// Save workspace to workspaces.json
|
|
10195
|
+
const workspaceController = workspaceController_1;
|
|
10196
|
+
const saveResult = workspaceController.saveWorkspaceForApplication(
|
|
10197
|
+
win,
|
|
10198
|
+
appId,
|
|
10199
|
+
workspace,
|
|
10200
|
+
);
|
|
10201
|
+
|
|
10202
|
+
if (saveResult.error) {
|
|
10203
|
+
return {
|
|
10204
|
+
success: false,
|
|
10205
|
+
error: `Failed to save workspace: ${saveResult.message}`,
|
|
10206
|
+
};
|
|
10207
|
+
}
|
|
10208
|
+
|
|
10209
|
+
// Build provider requirements summary
|
|
10210
|
+
const providerSummary = (dashboardConfig.providers || []).map((p) => ({
|
|
10211
|
+
type: p.type,
|
|
10212
|
+
providerClass: p.providerClass,
|
|
10213
|
+
required: p.required,
|
|
10214
|
+
usedBy: p.usedBy,
|
|
10215
|
+
}));
|
|
10216
|
+
|
|
10217
|
+
console.log(
|
|
10218
|
+
`[DashboardConfigController] Imported dashboard "${dashboardConfig.name}" (${source}) as workspace ${workspace.id}`,
|
|
10219
|
+
);
|
|
10220
|
+
|
|
10221
|
+
return {
|
|
10222
|
+
success: true,
|
|
10223
|
+
workspace,
|
|
10224
|
+
summary: {
|
|
10225
|
+
name: dashboardConfig.name,
|
|
10226
|
+
description: dashboardConfig.description || "",
|
|
10227
|
+
author: dashboardConfig.author,
|
|
10228
|
+
widgets: installSummary,
|
|
10229
|
+
eventsWired: eventWiringSummary,
|
|
10230
|
+
providersRequired: providerSummary,
|
|
10231
|
+
},
|
|
10232
|
+
};
|
|
10233
|
+
}
|
|
10234
|
+
|
|
10235
|
+
/**
|
|
10236
|
+
* Install a dashboard from the registry by package name.
|
|
10237
|
+
*
|
|
10238
|
+
* Fetches the dashboard ZIP from the registry, extracts the .dashboard.json,
|
|
10239
|
+
* validates it, and delegates to the shared import pipeline.
|
|
10240
|
+
*
|
|
10241
|
+
* @param {BrowserWindow} win - The main window
|
|
10242
|
+
* @param {string} appId - Application identifier
|
|
10243
|
+
* @param {string} packageName - Registry package name for the dashboard
|
|
10244
|
+
* @param {Object} widgetRegistry - WidgetRegistry instance
|
|
10245
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
10246
|
+
*/
|
|
10247
|
+
async function installDashboardFromRegistry$1(
|
|
10248
|
+
win,
|
|
10249
|
+
appId,
|
|
10250
|
+
packageName,
|
|
10251
|
+
widgetRegistry = null,
|
|
10252
|
+
) {
|
|
10253
|
+
try {
|
|
10254
|
+
// 1. Look up the dashboard package in the registry
|
|
10255
|
+
const registryPkg = await getPackage(packageName);
|
|
10256
|
+
if (!registryPkg) {
|
|
10030
10257
|
return {
|
|
10031
10258
|
success: false,
|
|
10032
|
-
error:
|
|
10259
|
+
error: `Dashboard package not found in registry: ${packageName}`,
|
|
10033
10260
|
};
|
|
10034
10261
|
}
|
|
10035
10262
|
|
|
10036
|
-
|
|
10037
|
-
|
|
10038
|
-
|
|
10039
|
-
|
|
10040
|
-
|
|
10041
|
-
if (
|
|
10042
|
-
dashboardConfig.eventWiring &&
|
|
10043
|
-
dashboardConfig.eventWiring.length &&
|
|
10044
|
-
workspace.layout
|
|
10045
|
-
) {
|
|
10046
|
-
applyEventWiringToLayout(workspace.layout, dashboardConfig.eventWiring);
|
|
10047
|
-
for (const wire of dashboardConfig.eventWiring) {
|
|
10048
|
-
eventWiringSummary.push(
|
|
10049
|
-
`${wire.source?.widget}.${wire.source?.event} → ${wire.target?.widget}.${wire.target?.handler}`,
|
|
10050
|
-
);
|
|
10051
|
-
}
|
|
10263
|
+
if (!registryPkg.downloadUrl) {
|
|
10264
|
+
return {
|
|
10265
|
+
success: false,
|
|
10266
|
+
error: `Dashboard package has no download URL: ${packageName}`,
|
|
10267
|
+
};
|
|
10052
10268
|
}
|
|
10053
10269
|
|
|
10054
|
-
//
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
originalAuthor: dashboardConfig.author,
|
|
10060
|
-
schemaVersion: dashboardConfig.schemaVersion,
|
|
10061
|
-
};
|
|
10270
|
+
// 2. Resolve the download URL and fetch the ZIP
|
|
10271
|
+
const version = registryPkg.version || "1.0.0";
|
|
10272
|
+
let downloadUrl = registryPkg.downloadUrl;
|
|
10273
|
+
downloadUrl = downloadUrl.replace("{version}", version);
|
|
10274
|
+
downloadUrl = downloadUrl.replace("{name}", packageName);
|
|
10062
10275
|
|
|
10063
|
-
//
|
|
10064
|
-
const
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10276
|
+
// Enforce HTTPS
|
|
10277
|
+
const parsedUrl = new URL(downloadUrl);
|
|
10278
|
+
if (parsedUrl.protocol !== "https:") {
|
|
10279
|
+
return {
|
|
10280
|
+
success: false,
|
|
10281
|
+
error: `Dashboard downloads must use HTTPS. Refusing: ${downloadUrl}`,
|
|
10282
|
+
};
|
|
10283
|
+
}
|
|
10284
|
+
|
|
10285
|
+
console.log(
|
|
10286
|
+
`[DashboardConfigController] Fetching dashboard from: ${downloadUrl}`,
|
|
10069
10287
|
);
|
|
10070
10288
|
|
|
10071
|
-
|
|
10289
|
+
const response = await fetch(downloadUrl);
|
|
10290
|
+
if (!response.ok) {
|
|
10072
10291
|
return {
|
|
10073
10292
|
success: false,
|
|
10074
|
-
error: `Failed to
|
|
10293
|
+
error: `Failed to download dashboard: ${response.status} ${response.statusText}`,
|
|
10075
10294
|
};
|
|
10076
10295
|
}
|
|
10077
10296
|
|
|
10078
|
-
|
|
10079
|
-
const
|
|
10080
|
-
type: p.type,
|
|
10081
|
-
providerClass: p.providerClass,
|
|
10082
|
-
required: p.required,
|
|
10083
|
-
usedBy: p.usedBy,
|
|
10084
|
-
}));
|
|
10297
|
+
const buffer = await response.arrayBuffer();
|
|
10298
|
+
const zip = new AdmZip(Buffer.from(buffer));
|
|
10085
10299
|
|
|
10086
|
-
|
|
10087
|
-
|
|
10300
|
+
// 3. Validate ZIP entries
|
|
10301
|
+
const tempDir = path.join(app.getPath("temp"), "dash-registry-import");
|
|
10302
|
+
const { validateZipEntries } = widgetRegistryExports;
|
|
10303
|
+
validateZipEntries(zip, tempDir);
|
|
10304
|
+
|
|
10305
|
+
// 4. Find and parse .dashboard.json
|
|
10306
|
+
const entries = zip.getEntries();
|
|
10307
|
+
const configEntry = entries.find((e) =>
|
|
10308
|
+
e.entryName.endsWith(".dashboard.json"),
|
|
10088
10309
|
);
|
|
10089
10310
|
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10311
|
+
if (!configEntry) {
|
|
10312
|
+
return {
|
|
10313
|
+
success: false,
|
|
10314
|
+
error: "No .dashboard.json file found in downloaded archive",
|
|
10315
|
+
};
|
|
10316
|
+
}
|
|
10317
|
+
|
|
10318
|
+
const configJson = configEntry.getData().toString("utf-8");
|
|
10319
|
+
let dashboardConfig;
|
|
10320
|
+
try {
|
|
10321
|
+
dashboardConfig = JSON.parse(configJson);
|
|
10322
|
+
} catch (parseError) {
|
|
10323
|
+
return {
|
|
10324
|
+
success: false,
|
|
10325
|
+
error: `Invalid JSON in dashboard config: ${parseError.message}`,
|
|
10326
|
+
};
|
|
10327
|
+
}
|
|
10328
|
+
|
|
10329
|
+
// 5. Validate against schema
|
|
10330
|
+
const validation = validateDashboardConfig(dashboardConfig);
|
|
10331
|
+
if (!validation.valid) {
|
|
10332
|
+
return {
|
|
10333
|
+
success: false,
|
|
10334
|
+
error: `Invalid dashboard config: ${validation.errors.join(", ")}`,
|
|
10335
|
+
};
|
|
10336
|
+
}
|
|
10337
|
+
|
|
10338
|
+
dashboardConfig = applyDefaults(dashboardConfig);
|
|
10339
|
+
|
|
10340
|
+
// 6. Delegate to shared import pipeline
|
|
10341
|
+
return await processDashboardConfig(
|
|
10342
|
+
win,
|
|
10343
|
+
appId,
|
|
10344
|
+
dashboardConfig,
|
|
10345
|
+
widgetRegistry,
|
|
10346
|
+
{
|
|
10347
|
+
source: "registry",
|
|
10100
10348
|
},
|
|
10101
|
-
|
|
10349
|
+
);
|
|
10102
10350
|
} catch (error) {
|
|
10103
10351
|
console.error(
|
|
10104
|
-
"[DashboardConfigController] Error
|
|
10352
|
+
"[DashboardConfigController] Error installing dashboard from registry:",
|
|
10105
10353
|
error,
|
|
10106
10354
|
);
|
|
10107
10355
|
return {
|
|
@@ -10111,9 +10359,43 @@ async function importDashboardConfig$1(win, appId, widgetRegistry = null) {
|
|
|
10111
10359
|
}
|
|
10112
10360
|
}
|
|
10113
10361
|
|
|
10362
|
+
/**
|
|
10363
|
+
* Check compatibility of a dashboard's widget dependencies against
|
|
10364
|
+
* installed widgets and registry availability.
|
|
10365
|
+
*
|
|
10366
|
+
* @param {Array} dashboardWidgets - Widget deps from dashboard config
|
|
10367
|
+
* @param {Object} widgetRegistry - WidgetRegistry instance (needs getWidgets())
|
|
10368
|
+
* @returns {Promise<Object>} Compatibility report
|
|
10369
|
+
*/
|
|
10370
|
+
async function checkCompatibility$1(dashboardWidgets, widgetRegistry = null) {
|
|
10371
|
+
const { checkDashboardCompatibility } = dashboardConfigUtils$1;
|
|
10372
|
+
const { fetchRegistryIndex } = registryController$1;
|
|
10373
|
+
|
|
10374
|
+
const installedWidgets = widgetRegistry ? widgetRegistry.getWidgets() : [];
|
|
10375
|
+
|
|
10376
|
+
let registryPackages = [];
|
|
10377
|
+
try {
|
|
10378
|
+
const index = await fetchRegistryIndex();
|
|
10379
|
+
registryPackages = index.packages || [];
|
|
10380
|
+
} catch (err) {
|
|
10381
|
+
console.warn(
|
|
10382
|
+
"[DashboardConfigController] Could not fetch registry index for compatibility check:",
|
|
10383
|
+
err.message,
|
|
10384
|
+
);
|
|
10385
|
+
}
|
|
10386
|
+
|
|
10387
|
+
return checkDashboardCompatibility(
|
|
10388
|
+
dashboardWidgets,
|
|
10389
|
+
installedWidgets,
|
|
10390
|
+
registryPackages,
|
|
10391
|
+
);
|
|
10392
|
+
}
|
|
10393
|
+
|
|
10114
10394
|
var dashboardConfigController$1 = {
|
|
10115
10395
|
exportDashboardConfig: exportDashboardConfig$1,
|
|
10116
10396
|
importDashboardConfig: importDashboardConfig$1,
|
|
10397
|
+
installDashboardFromRegistry: installDashboardFromRegistry$1,
|
|
10398
|
+
checkCompatibility: checkCompatibility$1,
|
|
10117
10399
|
};
|
|
10118
10400
|
|
|
10119
10401
|
/**
|
|
@@ -10205,6 +10487,8 @@ const { install: pluginInstall } = pluginController_1;
|
|
|
10205
10487
|
const {
|
|
10206
10488
|
exportDashboardConfig,
|
|
10207
10489
|
importDashboardConfig,
|
|
10490
|
+
installDashboardFromRegistry,
|
|
10491
|
+
checkCompatibility,
|
|
10208
10492
|
} = dashboardConfigController$1;
|
|
10209
10493
|
|
|
10210
10494
|
var controller = {
|
|
@@ -10250,6 +10534,8 @@ var controller = {
|
|
|
10250
10534
|
searchIndex,
|
|
10251
10535
|
exportDashboardConfig,
|
|
10252
10536
|
importDashboardConfig,
|
|
10537
|
+
installDashboardFromRegistry,
|
|
10538
|
+
checkCompatibility,
|
|
10253
10539
|
};
|
|
10254
10540
|
|
|
10255
10541
|
const { ipcRenderer: ipcRenderer$i } = require$$0$1;
|
|
@@ -11626,36 +11912,66 @@ var clientCacheApi_1 = clientCacheApi$2;
|
|
|
11626
11912
|
|
|
11627
11913
|
const { ipcRenderer: ipcRenderer$1 } = require$$0$1;
|
|
11628
11914
|
const {
|
|
11629
|
-
|
|
11630
|
-
|
|
11915
|
+
DASHBOARD_CONFIG_EXPORT,
|
|
11916
|
+
DASHBOARD_CONFIG_IMPORT,
|
|
11917
|
+
DASHBOARD_CONFIG_INSTALL,
|
|
11918
|
+
DASHBOARD_CONFIG_COMPATIBILITY,
|
|
11631
11919
|
} = events$8;
|
|
11632
11920
|
|
|
11633
11921
|
const dashboardConfigApi$2 = {
|
|
11634
|
-
|
|
11635
|
-
|
|
11636
|
-
|
|
11637
|
-
|
|
11638
|
-
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
|
|
11654
|
-
|
|
11655
|
-
|
|
11656
|
-
|
|
11657
|
-
|
|
11658
|
-
|
|
11922
|
+
/**
|
|
11923
|
+
* Export a workspace as a dashboard config ZIP file.
|
|
11924
|
+
*
|
|
11925
|
+
* @param {string} appId - Application identifier
|
|
11926
|
+
* @param {number|string} workspaceId - ID of the workspace to export
|
|
11927
|
+
* @param {Object} options - Export options (authorName, authorId, description, tags, icon)
|
|
11928
|
+
* @returns {Promise<Object>} Result with success, filePath, and config
|
|
11929
|
+
*/
|
|
11930
|
+
exportDashboardConfig: (appId, workspaceId, options = {}) =>
|
|
11931
|
+
ipcRenderer$1.invoke(DASHBOARD_CONFIG_EXPORT, {
|
|
11932
|
+
appId,
|
|
11933
|
+
workspaceId,
|
|
11934
|
+
options,
|
|
11935
|
+
}),
|
|
11936
|
+
|
|
11937
|
+
/**
|
|
11938
|
+
* Import a dashboard config from a ZIP file.
|
|
11939
|
+
* Shows a file picker, validates the config, installs missing widgets,
|
|
11940
|
+
* creates the workspace, and applies event wiring.
|
|
11941
|
+
*
|
|
11942
|
+
* @param {string} appId - Application identifier
|
|
11943
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
11944
|
+
*/
|
|
11945
|
+
importDashboardConfig: (appId) =>
|
|
11946
|
+
ipcRenderer$1.invoke(DASHBOARD_CONFIG_IMPORT, { appId }),
|
|
11947
|
+
|
|
11948
|
+
/**
|
|
11949
|
+
* Install a dashboard from the registry by package name.
|
|
11950
|
+
* Fetches the dashboard ZIP, validates config, installs widgets,
|
|
11951
|
+
* creates workspace, and applies event wiring.
|
|
11952
|
+
*
|
|
11953
|
+
* @param {string} appId - Application identifier
|
|
11954
|
+
* @param {string} packageName - Registry package name
|
|
11955
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
11956
|
+
*/
|
|
11957
|
+
installDashboardFromRegistry: (appId, packageName) =>
|
|
11958
|
+
ipcRenderer$1.invoke(DASHBOARD_CONFIG_INSTALL, {
|
|
11959
|
+
appId,
|
|
11960
|
+
packageName,
|
|
11961
|
+
}),
|
|
11962
|
+
|
|
11963
|
+
/**
|
|
11964
|
+
* Check compatibility of a dashboard config against installed widgets.
|
|
11965
|
+
*
|
|
11966
|
+
* @param {string} appId - Application identifier
|
|
11967
|
+
* @param {Array} dashboardWidgets - Widget dependencies from dashboard config
|
|
11968
|
+
* @returns {Promise<Object>} Compatibility report with per-widget status
|
|
11969
|
+
*/
|
|
11970
|
+
checkDashboardCompatibility: (appId, dashboardWidgets) =>
|
|
11971
|
+
ipcRenderer$1.invoke(DASHBOARD_CONFIG_COMPATIBILITY, {
|
|
11972
|
+
appId,
|
|
11973
|
+
dashboardWidgets,
|
|
11974
|
+
}),
|
|
11659
11975
|
};
|
|
11660
11976
|
|
|
11661
11977
|
var dashboardConfigApi_1 = dashboardConfigApi$2;
|