Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plugin catalog extras #2148

Merged
merged 3 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 67 additions & 19 deletions app/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,17 @@ import 'regenerator-runtime/runtime';
import { ChildProcessWithoutNullStreams, execSync, spawn } from 'child_process';
import { randomBytes } from 'crypto';
import dotenv from 'dotenv';
import { app, BrowserWindow, dialog, ipcMain, Menu, MenuItem, screen, shell } from 'electron';
import {
app,
BrowserWindow,
dialog,
ipcMain,
Menu,
MenuItem,
MessageBoxOptions,
screen,
shell,
} from 'electron';
import { IpcMainEvent, MenuItemConstructorOptions } from 'electron/main';
import log from 'electron-log';
import find_process from 'find-process';
Expand Down Expand Up @@ -223,34 +233,72 @@ class PluginManagerEventListeners {
* @private
*/
private handleInstall(eventData: Action, updateCache: (progress: ProgressResp) => void) {
const { identifier, URL, destinationFolder, headlampVersion } = eventData;
const { identifier, URL, destinationFolder, headlampVersion, pluginName } = eventData;

if (!mainWindow) {
return Promise.resolve({ type: 'error', message: 'Main window is not available' });
}

if (!URL) {
this.cache[identifier] = {
action: 'INSTALL',
progress: { type: 'error', message: 'URL is required' },
};
return;
return Promise.resolve({ type: 'error', message: 'URL is required' });
}

const dialogOptions: MessageBoxOptions = {
type: 'question',
buttons: ['Yes', 'No'],
defaultId: 1,
title: 'Plugin Installation',
message: 'Do you want to install this plugin?',
detail: `You are about to install ${pluginName} plugin from: ${URL}\nDo you want to proceed?`,
};
const controller = new AbortController();
this.cache[identifier] = {
action: 'INSTALL',
progress: { type: 'info', message: 'installing plugin' },
percentage: 10,
progress: { type: 'info', message: 'waiting for user consent' },
percentage: 0,
controller,
};

PluginManager.install(
URL,
destinationFolder,
headlampVersion,
progress => {
updateCache(progress);
},
controller.signal
);
}
return dialog
.showMessageBox(mainWindow, dialogOptions)
.then(({ response }) => {
console.log('User response:', response);
if (response === 1) {
// User clicked "No"
this.cache[identifier] = {
action: 'INSTALL',
progress: { type: 'error', message: 'installation cancelled due to user consent' },
percentage: 0,
controller,
};
return { type: 'error', message: 'Installation cancelled due to user consent' };
}

// User clicked "Yes", proceed with installation
this.cache[identifier] = {
action: 'INSTALL',
progress: { type: 'info', message: 'installing plugin' },
percentage: 10,
controller,
};

PluginManager.install(
URL,
destinationFolder,
headlampVersion,
progress => {
updateCache(progress);
},
controller.signal
);

return { type: 'info', message: 'Installation started' };
})
.catch(error => {
console.error('Error during installation process:', error);
return { type: 'error', message: 'An error occurred during the installation process' };
});
}
/**
* Handles the update process.
*
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/App/pluginManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,20 @@ export class PluginManager {
* Sends a request to install a plugin from the specified ArtifactHub URL.
*
* @param {string} identifier - The unique identifier for the plugin.
* @param {string} name - The name of the plugin to be installed.
* @param {string} URL - The URL from where the plugin will be installed.
* @static
* @example
* PluginManager.install('pluginID', ' https://artifacthub.io/packages/headlamp/<repo_name>/<plugin_name>');
*/
static install(identifier: string, URL: string) {
static install(identifier: string, name: string, URL: string) {
window.desktopApi.send(
'plugin-manager',
JSON.stringify({
action: 'INSTALL',
identifier,
URL,
pluginName: name,
})
);
}
Expand Down
8 changes: 3 additions & 5 deletions plugins/headlamp-plugin/bin/headlamp-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -1312,16 +1312,14 @@ yargs(process.argv.slice(2))
console.log(JSON.stringify(data.data));
} else {
// display table
const rows = [
['Name', 'Version', 'Folder Name', 'ArticaftHub URL', 'ArtifactHub Version'],
];
const rows = [['Name', 'Version', 'Folder Name', 'Repo', 'Author']];
data.data.forEach(plugin => {
rows.push([
plugin.pluginName,
plugin.pluginVersion,
plugin.folderName,
plugin.artifacthubURL,
plugin.artifacthubVersion,
plugin.repoName,
plugin.author,
]);
});
console.log(table(rows));
Expand Down
3 changes: 3 additions & 0 deletions plugins/headlamp-plugin/plugin-management-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ class PluginManager {
const pluginVersion = packageJson.version || null;
const artifacthubURL = packageJson.artifacthub ? packageJson.artifacthub.url : null;
const repoName = packageJson.artifacthub ? packageJson.artifacthub.repoName : null;
const author = packageJson.artifacthub ? packageJson.artifacthub.author : null;
const artifacthubVersion = packageJson.artifacthub
? packageJson.artifacthub.version
: null;
Expand All @@ -215,6 +216,7 @@ class PluginManager {
folderName: pluginFolder.name,
artifacthubURL: artifacthubURL,
repoName: repoName,
author: author,
artifacthubVersion: artifacthubVersion,
});
}
Expand Down Expand Up @@ -371,6 +373,7 @@ async function downloadExtractPlugin(URL, headlampVersion, progressCallback, sig
url: `https://artifacthub.io/packages/headlamp/${pluginInfo.repository.name}/${pluginName}`,
version: pluginInfo.version,
repoName: pluginInfo.repository.name,
author: pluginInfo.repository.user_alias,
};
packageJSON.isManagedByHeadlampPlugin = true;
fs.writeFileSync(`${tempFolder}/package.json`, JSON.stringify(packageJSON, null, 2));
Expand Down
Loading