@trops/dash-core 0.1.86 → 0.1.87
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 +302 -123
- package/dist/electron/index.js.map +1 -1
- package/package.json +1 -1
package/dist/electron/index.js
CHANGED
|
@@ -588,10 +588,12 @@ 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";
|
|
591
592
|
|
|
592
593
|
var dashboardConfigEvents$1 = {
|
|
593
|
-
|
|
594
|
-
|
|
594
|
+
DASHBOARD_CONFIG_EXPORT: DASHBOARD_CONFIG_EXPORT$1,
|
|
595
|
+
DASHBOARD_CONFIG_IMPORT: DASHBOARD_CONFIG_IMPORT$1,
|
|
596
|
+
DASHBOARD_CONFIG_INSTALL: DASHBOARD_CONFIG_INSTALL$1,
|
|
595
597
|
};
|
|
596
598
|
|
|
597
599
|
/**
|
|
@@ -9974,134 +9976,292 @@ async function importDashboardConfig$1(win, appId, widgetRegistry = null) {
|
|
|
9974
9976
|
// Apply defaults to fill in optional fields
|
|
9975
9977
|
dashboardConfig = applyDefaults(dashboardConfig);
|
|
9976
9978
|
|
|
9977
|
-
//
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9979
|
+
// Delegate to shared import pipeline
|
|
9980
|
+
return await processDashboardConfig(
|
|
9981
|
+
win,
|
|
9982
|
+
appId,
|
|
9983
|
+
dashboardConfig,
|
|
9984
|
+
widgetRegistry,
|
|
9985
|
+
);
|
|
9986
|
+
} catch (error) {
|
|
9987
|
+
console.error(
|
|
9988
|
+
"[DashboardConfigController] Error importing dashboard:",
|
|
9989
|
+
error,
|
|
9990
|
+
);
|
|
9991
|
+
return {
|
|
9992
|
+
success: false,
|
|
9993
|
+
error: error.message,
|
|
9982
9994
|
};
|
|
9995
|
+
}
|
|
9996
|
+
}
|
|
9983
9997
|
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9998
|
+
/**
|
|
9999
|
+
* Shared import pipeline: install widgets, create workspace, wire events.
|
|
10000
|
+
* Used by both importDashboardConfig (ZIP) and installDashboardFromRegistry.
|
|
10001
|
+
*
|
|
10002
|
+
* @param {BrowserWindow} win - The main window
|
|
10003
|
+
* @param {string} appId - Application identifier
|
|
10004
|
+
* @param {Object} dashboardConfig - Validated dashboard config object
|
|
10005
|
+
* @param {Object} widgetRegistry - WidgetRegistry instance
|
|
10006
|
+
* @param {Object} options - Additional options
|
|
10007
|
+
* @param {string} options.source - Source label ("zip" or "registry")
|
|
10008
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
10009
|
+
*/
|
|
10010
|
+
async function processDashboardConfig(
|
|
10011
|
+
win,
|
|
10012
|
+
appId,
|
|
10013
|
+
dashboardConfig,
|
|
10014
|
+
widgetRegistry = null,
|
|
10015
|
+
options = {},
|
|
10016
|
+
) {
|
|
10017
|
+
const source = options.source || "zip";
|
|
9991
10018
|
|
|
9992
|
-
|
|
9993
|
-
|
|
10019
|
+
// 1. Auto-install missing widgets from registry
|
|
10020
|
+
const installSummary = {
|
|
10021
|
+
installed: [],
|
|
10022
|
+
alreadyInstalled: [],
|
|
10023
|
+
failed: [],
|
|
10024
|
+
};
|
|
9994
10025
|
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
10026
|
+
if (
|
|
10027
|
+
widgetRegistry &&
|
|
10028
|
+
dashboardConfig.widgets &&
|
|
10029
|
+
dashboardConfig.widgets.length
|
|
10030
|
+
) {
|
|
10031
|
+
const installedWidgets = widgetRegistry.getWidgets();
|
|
10032
|
+
const installedPackages = new Set(installedWidgets.map((w) => w.name));
|
|
9999
10033
|
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10004
|
-
|
|
10005
|
-
|
|
10006
|
-
|
|
10007
|
-
|
|
10008
|
-
|
|
10009
|
-
|
|
10010
|
-
|
|
10011
|
-
|
|
10012
|
-
|
|
10013
|
-
|
|
10014
|
-
|
|
10015
|
-
|
|
10016
|
-
|
|
10017
|
-
|
|
10034
|
+
for (const widgetDep of dashboardConfig.widgets) {
|
|
10035
|
+
const packageName = widgetDep.package;
|
|
10036
|
+
|
|
10037
|
+
if (installedPackages.has(packageName)) {
|
|
10038
|
+
installSummary.alreadyInstalled.push(packageName);
|
|
10039
|
+
continue;
|
|
10040
|
+
}
|
|
10041
|
+
|
|
10042
|
+
// Try to find the widget in the registry and install it
|
|
10043
|
+
try {
|
|
10044
|
+
const registryPkg = await getPackage(packageName);
|
|
10045
|
+
if (registryPkg && registryPkg.downloadUrl) {
|
|
10046
|
+
await widgetRegistry.downloadWidget(
|
|
10047
|
+
packageName,
|
|
10048
|
+
registryPkg.downloadUrl,
|
|
10049
|
+
registryPkg.dashConfigUrl || null,
|
|
10050
|
+
);
|
|
10051
|
+
installSummary.installed.push(packageName);
|
|
10052
|
+
installedPackages.add(packageName);
|
|
10053
|
+
} else {
|
|
10018
10054
|
installSummary.failed.push({
|
|
10019
10055
|
package: packageName,
|
|
10020
|
-
reason:
|
|
10056
|
+
reason: "Not found in registry",
|
|
10021
10057
|
});
|
|
10022
10058
|
}
|
|
10059
|
+
} catch (installError) {
|
|
10060
|
+
installSummary.failed.push({
|
|
10061
|
+
package: packageName,
|
|
10062
|
+
reason: installError.message,
|
|
10063
|
+
});
|
|
10023
10064
|
}
|
|
10024
10065
|
}
|
|
10066
|
+
}
|
|
10025
10067
|
|
|
10026
|
-
|
|
10027
|
-
|
|
10068
|
+
// 2. Build workspace from config
|
|
10069
|
+
const workspace = { ...dashboardConfig.workspace };
|
|
10028
10070
|
|
|
10029
|
-
|
|
10071
|
+
if (!workspace || !workspace.layout) {
|
|
10072
|
+
return {
|
|
10073
|
+
success: false,
|
|
10074
|
+
error: "Dashboard config has no workspace data",
|
|
10075
|
+
};
|
|
10076
|
+
}
|
|
10077
|
+
|
|
10078
|
+
// Generate a unique ID for the imported workspace
|
|
10079
|
+
workspace.id = Date.now();
|
|
10080
|
+
|
|
10081
|
+
// 3. Apply event wiring to layout
|
|
10082
|
+
const eventWiringSummary = [];
|
|
10083
|
+
if (
|
|
10084
|
+
dashboardConfig.eventWiring &&
|
|
10085
|
+
dashboardConfig.eventWiring.length &&
|
|
10086
|
+
workspace.layout
|
|
10087
|
+
) {
|
|
10088
|
+
applyEventWiringToLayout(workspace.layout, dashboardConfig.eventWiring);
|
|
10089
|
+
for (const wire of dashboardConfig.eventWiring) {
|
|
10090
|
+
eventWiringSummary.push(
|
|
10091
|
+
`${wire.source?.widget}.${wire.source?.event} → ${wire.target?.widget}.${wire.target?.handler}`,
|
|
10092
|
+
);
|
|
10093
|
+
}
|
|
10094
|
+
}
|
|
10095
|
+
|
|
10096
|
+
// 4. Mark as not shareable (imported dashboards cannot be re-published)
|
|
10097
|
+
workspace._dashboardConfig = {
|
|
10098
|
+
shareable: false,
|
|
10099
|
+
source,
|
|
10100
|
+
importedFrom: dashboardConfig.name,
|
|
10101
|
+
importedAt: new Date().toISOString(),
|
|
10102
|
+
originalAuthor: dashboardConfig.author,
|
|
10103
|
+
schemaVersion: dashboardConfig.schemaVersion,
|
|
10104
|
+
};
|
|
10105
|
+
|
|
10106
|
+
// Save workspace to workspaces.json
|
|
10107
|
+
const workspaceController = workspaceController_1;
|
|
10108
|
+
const saveResult = workspaceController.saveWorkspaceForApplication(
|
|
10109
|
+
win,
|
|
10110
|
+
appId,
|
|
10111
|
+
workspace,
|
|
10112
|
+
);
|
|
10113
|
+
|
|
10114
|
+
if (saveResult.error) {
|
|
10115
|
+
return {
|
|
10116
|
+
success: false,
|
|
10117
|
+
error: `Failed to save workspace: ${saveResult.message}`,
|
|
10118
|
+
};
|
|
10119
|
+
}
|
|
10120
|
+
|
|
10121
|
+
// Build provider requirements summary
|
|
10122
|
+
const providerSummary = (dashboardConfig.providers || []).map((p) => ({
|
|
10123
|
+
type: p.type,
|
|
10124
|
+
providerClass: p.providerClass,
|
|
10125
|
+
required: p.required,
|
|
10126
|
+
usedBy: p.usedBy,
|
|
10127
|
+
}));
|
|
10128
|
+
|
|
10129
|
+
console.log(
|
|
10130
|
+
`[DashboardConfigController] Imported dashboard "${dashboardConfig.name}" (${source}) as workspace ${workspace.id}`,
|
|
10131
|
+
);
|
|
10132
|
+
|
|
10133
|
+
return {
|
|
10134
|
+
success: true,
|
|
10135
|
+
workspace,
|
|
10136
|
+
summary: {
|
|
10137
|
+
name: dashboardConfig.name,
|
|
10138
|
+
description: dashboardConfig.description || "",
|
|
10139
|
+
author: dashboardConfig.author,
|
|
10140
|
+
widgets: installSummary,
|
|
10141
|
+
eventsWired: eventWiringSummary,
|
|
10142
|
+
providersRequired: providerSummary,
|
|
10143
|
+
},
|
|
10144
|
+
};
|
|
10145
|
+
}
|
|
10146
|
+
|
|
10147
|
+
/**
|
|
10148
|
+
* Install a dashboard from the registry by package name.
|
|
10149
|
+
*
|
|
10150
|
+
* Fetches the dashboard ZIP from the registry, extracts the .dashboard.json,
|
|
10151
|
+
* validates it, and delegates to the shared import pipeline.
|
|
10152
|
+
*
|
|
10153
|
+
* @param {BrowserWindow} win - The main window
|
|
10154
|
+
* @param {string} appId - Application identifier
|
|
10155
|
+
* @param {string} packageName - Registry package name for the dashboard
|
|
10156
|
+
* @param {Object} widgetRegistry - WidgetRegistry instance
|
|
10157
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
10158
|
+
*/
|
|
10159
|
+
async function installDashboardFromRegistry$1(
|
|
10160
|
+
win,
|
|
10161
|
+
appId,
|
|
10162
|
+
packageName,
|
|
10163
|
+
widgetRegistry = null,
|
|
10164
|
+
) {
|
|
10165
|
+
try {
|
|
10166
|
+
// 1. Look up the dashboard package in the registry
|
|
10167
|
+
const registryPkg = await getPackage(packageName);
|
|
10168
|
+
if (!registryPkg) {
|
|
10030
10169
|
return {
|
|
10031
10170
|
success: false,
|
|
10032
|
-
error:
|
|
10171
|
+
error: `Dashboard package not found in registry: ${packageName}`,
|
|
10033
10172
|
};
|
|
10034
10173
|
}
|
|
10035
10174
|
|
|
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
|
-
}
|
|
10175
|
+
if (!registryPkg.downloadUrl) {
|
|
10176
|
+
return {
|
|
10177
|
+
success: false,
|
|
10178
|
+
error: `Dashboard package has no download URL: ${packageName}`,
|
|
10179
|
+
};
|
|
10052
10180
|
}
|
|
10053
10181
|
|
|
10054
|
-
//
|
|
10055
|
-
|
|
10056
|
-
|
|
10057
|
-
|
|
10058
|
-
|
|
10059
|
-
originalAuthor: dashboardConfig.author,
|
|
10060
|
-
schemaVersion: dashboardConfig.schemaVersion,
|
|
10061
|
-
};
|
|
10182
|
+
// 2. Resolve the download URL and fetch the ZIP
|
|
10183
|
+
const version = registryPkg.version || "1.0.0";
|
|
10184
|
+
let downloadUrl = registryPkg.downloadUrl;
|
|
10185
|
+
downloadUrl = downloadUrl.replace("{version}", version);
|
|
10186
|
+
downloadUrl = downloadUrl.replace("{name}", packageName);
|
|
10062
10187
|
|
|
10063
|
-
//
|
|
10064
|
-
const
|
|
10065
|
-
|
|
10066
|
-
|
|
10067
|
-
|
|
10068
|
-
|
|
10188
|
+
// Enforce HTTPS
|
|
10189
|
+
const parsedUrl = new URL(downloadUrl);
|
|
10190
|
+
if (parsedUrl.protocol !== "https:") {
|
|
10191
|
+
return {
|
|
10192
|
+
success: false,
|
|
10193
|
+
error: `Dashboard downloads must use HTTPS. Refusing: ${downloadUrl}`,
|
|
10194
|
+
};
|
|
10195
|
+
}
|
|
10196
|
+
|
|
10197
|
+
console.log(
|
|
10198
|
+
`[DashboardConfigController] Fetching dashboard from: ${downloadUrl}`,
|
|
10069
10199
|
);
|
|
10070
10200
|
|
|
10071
|
-
|
|
10201
|
+
const response = await fetch(downloadUrl);
|
|
10202
|
+
if (!response.ok) {
|
|
10072
10203
|
return {
|
|
10073
10204
|
success: false,
|
|
10074
|
-
error: `Failed to
|
|
10205
|
+
error: `Failed to download dashboard: ${response.status} ${response.statusText}`,
|
|
10075
10206
|
};
|
|
10076
10207
|
}
|
|
10077
10208
|
|
|
10078
|
-
|
|
10079
|
-
const
|
|
10080
|
-
type: p.type,
|
|
10081
|
-
providerClass: p.providerClass,
|
|
10082
|
-
required: p.required,
|
|
10083
|
-
usedBy: p.usedBy,
|
|
10084
|
-
}));
|
|
10209
|
+
const buffer = await response.arrayBuffer();
|
|
10210
|
+
const zip = new AdmZip(Buffer.from(buffer));
|
|
10085
10211
|
|
|
10086
|
-
|
|
10087
|
-
|
|
10212
|
+
// 3. Validate ZIP entries
|
|
10213
|
+
const tempDir = path.join(app.getPath("temp"), "dash-registry-import");
|
|
10214
|
+
const { validateZipEntries } = widgetRegistryExports;
|
|
10215
|
+
validateZipEntries(zip, tempDir);
|
|
10216
|
+
|
|
10217
|
+
// 4. Find and parse .dashboard.json
|
|
10218
|
+
const entries = zip.getEntries();
|
|
10219
|
+
const configEntry = entries.find((e) =>
|
|
10220
|
+
e.entryName.endsWith(".dashboard.json"),
|
|
10088
10221
|
);
|
|
10089
10222
|
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10094
|
-
|
|
10095
|
-
|
|
10096
|
-
|
|
10097
|
-
|
|
10098
|
-
|
|
10099
|
-
|
|
10223
|
+
if (!configEntry) {
|
|
10224
|
+
return {
|
|
10225
|
+
success: false,
|
|
10226
|
+
error: "No .dashboard.json file found in downloaded archive",
|
|
10227
|
+
};
|
|
10228
|
+
}
|
|
10229
|
+
|
|
10230
|
+
const configJson = configEntry.getData().toString("utf-8");
|
|
10231
|
+
let dashboardConfig;
|
|
10232
|
+
try {
|
|
10233
|
+
dashboardConfig = JSON.parse(configJson);
|
|
10234
|
+
} catch (parseError) {
|
|
10235
|
+
return {
|
|
10236
|
+
success: false,
|
|
10237
|
+
error: `Invalid JSON in dashboard config: ${parseError.message}`,
|
|
10238
|
+
};
|
|
10239
|
+
}
|
|
10240
|
+
|
|
10241
|
+
// 5. Validate against schema
|
|
10242
|
+
const validation = validateDashboardConfig(dashboardConfig);
|
|
10243
|
+
if (!validation.valid) {
|
|
10244
|
+
return {
|
|
10245
|
+
success: false,
|
|
10246
|
+
error: `Invalid dashboard config: ${validation.errors.join(", ")}`,
|
|
10247
|
+
};
|
|
10248
|
+
}
|
|
10249
|
+
|
|
10250
|
+
dashboardConfig = applyDefaults(dashboardConfig);
|
|
10251
|
+
|
|
10252
|
+
// 6. Delegate to shared import pipeline
|
|
10253
|
+
return await processDashboardConfig(
|
|
10254
|
+
win,
|
|
10255
|
+
appId,
|
|
10256
|
+
dashboardConfig,
|
|
10257
|
+
widgetRegistry,
|
|
10258
|
+
{
|
|
10259
|
+
source: "registry",
|
|
10100
10260
|
},
|
|
10101
|
-
|
|
10261
|
+
);
|
|
10102
10262
|
} catch (error) {
|
|
10103
10263
|
console.error(
|
|
10104
|
-
"[DashboardConfigController] Error
|
|
10264
|
+
"[DashboardConfigController] Error installing dashboard from registry:",
|
|
10105
10265
|
error,
|
|
10106
10266
|
);
|
|
10107
10267
|
return {
|
|
@@ -10114,6 +10274,7 @@ async function importDashboardConfig$1(win, appId, widgetRegistry = null) {
|
|
|
10114
10274
|
var dashboardConfigController$1 = {
|
|
10115
10275
|
exportDashboardConfig: exportDashboardConfig$1,
|
|
10116
10276
|
importDashboardConfig: importDashboardConfig$1,
|
|
10277
|
+
installDashboardFromRegistry: installDashboardFromRegistry$1,
|
|
10117
10278
|
};
|
|
10118
10279
|
|
|
10119
10280
|
/**
|
|
@@ -10205,6 +10366,7 @@ const { install: pluginInstall } = pluginController_1;
|
|
|
10205
10366
|
const {
|
|
10206
10367
|
exportDashboardConfig,
|
|
10207
10368
|
importDashboardConfig,
|
|
10369
|
+
installDashboardFromRegistry,
|
|
10208
10370
|
} = dashboardConfigController$1;
|
|
10209
10371
|
|
|
10210
10372
|
var controller = {
|
|
@@ -10250,6 +10412,7 @@ var controller = {
|
|
|
10250
10412
|
searchIndex,
|
|
10251
10413
|
exportDashboardConfig,
|
|
10252
10414
|
importDashboardConfig,
|
|
10415
|
+
installDashboardFromRegistry,
|
|
10253
10416
|
};
|
|
10254
10417
|
|
|
10255
10418
|
const { ipcRenderer: ipcRenderer$i } = require$$0$1;
|
|
@@ -11626,36 +11789,52 @@ var clientCacheApi_1 = clientCacheApi$2;
|
|
|
11626
11789
|
|
|
11627
11790
|
const { ipcRenderer: ipcRenderer$1 } = require$$0$1;
|
|
11628
11791
|
const {
|
|
11629
|
-
|
|
11630
|
-
|
|
11792
|
+
DASHBOARD_CONFIG_EXPORT,
|
|
11793
|
+
DASHBOARD_CONFIG_IMPORT,
|
|
11794
|
+
DASHBOARD_CONFIG_INSTALL,
|
|
11631
11795
|
} = events$8;
|
|
11632
11796
|
|
|
11633
11797
|
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
|
-
|
|
11798
|
+
/**
|
|
11799
|
+
* Export a workspace as a dashboard config ZIP file.
|
|
11800
|
+
*
|
|
11801
|
+
* @param {string} appId - Application identifier
|
|
11802
|
+
* @param {number|string} workspaceId - ID of the workspace to export
|
|
11803
|
+
* @param {Object} options - Export options (authorName, authorId, description, tags, icon)
|
|
11804
|
+
* @returns {Promise<Object>} Result with success, filePath, and config
|
|
11805
|
+
*/
|
|
11806
|
+
exportDashboardConfig: (appId, workspaceId, options = {}) =>
|
|
11807
|
+
ipcRenderer$1.invoke(DASHBOARD_CONFIG_EXPORT, {
|
|
11808
|
+
appId,
|
|
11809
|
+
workspaceId,
|
|
11810
|
+
options,
|
|
11811
|
+
}),
|
|
11812
|
+
|
|
11813
|
+
/**
|
|
11814
|
+
* Import a dashboard config from a ZIP file.
|
|
11815
|
+
* Shows a file picker, validates the config, installs missing widgets,
|
|
11816
|
+
* creates the workspace, and applies event wiring.
|
|
11817
|
+
*
|
|
11818
|
+
* @param {string} appId - Application identifier
|
|
11819
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
11820
|
+
*/
|
|
11821
|
+
importDashboardConfig: (appId) =>
|
|
11822
|
+
ipcRenderer$1.invoke(DASHBOARD_CONFIG_IMPORT, { appId }),
|
|
11823
|
+
|
|
11824
|
+
/**
|
|
11825
|
+
* Install a dashboard from the registry by package name.
|
|
11826
|
+
* Fetches the dashboard ZIP, validates config, installs widgets,
|
|
11827
|
+
* creates workspace, and applies event wiring.
|
|
11828
|
+
*
|
|
11829
|
+
* @param {string} appId - Application identifier
|
|
11830
|
+
* @param {string} packageName - Registry package name
|
|
11831
|
+
* @returns {Promise<Object>} Result with success, workspace, and summary
|
|
11832
|
+
*/
|
|
11833
|
+
installDashboardFromRegistry: (appId, packageName) =>
|
|
11834
|
+
ipcRenderer$1.invoke(DASHBOARD_CONFIG_INSTALL, {
|
|
11835
|
+
appId,
|
|
11836
|
+
packageName,
|
|
11837
|
+
}),
|
|
11659
11838
|
};
|
|
11660
11839
|
|
|
11661
11840
|
var dashboardConfigApi_1 = dashboardConfigApi$2;
|