Skip to content

Commit

Permalink
EPMRPP-98929 || Allow registering UI extensions without plugins insta…
Browse files Browse the repository at this point in the history
…lled
  • Loading branch information
AmsterGet committed Jan 24, 2025
1 parent cef8d16 commit f12d238
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 28 deletions.
9 changes: 4 additions & 5 deletions app/src/components/extensionLoader/utils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 EPAM Systems
* Copyright 2025 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,12 +20,11 @@ import { MAIN_FILE_KEY } from 'controllers/plugins/uiExtensions/constants';
const DEFAULT_EXTENSION_FILE_NAME = 'remoteEntity.js';

export const getExtensionUrl = (extension) => {
const isDev = process.env.NODE_ENV === 'development';
const { pluginName, url: defaultUrl, binaryData = {} } = extension;
const { pluginName, url: remoteUrl, binaryData = {} } = extension;
const fileName = binaryData[MAIN_FILE_KEY] || DEFAULT_EXTENSION_FILE_NAME;

if (isDev && defaultUrl) {
return `${defaultUrl}/${fileName}`;
if (remoteUrl) {
return `${remoteUrl}/${fileName}`;
}

return URLS.pluginPublicFile(pluginName, fileName);
Expand Down
12 changes: 10 additions & 2 deletions app/src/controllers/plugins/uiExtensions/actions.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 EPAM Systems
* Copyright 2025 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -14,7 +14,11 @@
* limitations under the License.
*/

import { FETCH_EXTENSION_MANIFESTS_SUCCESS, UPDATE_EXTENSION_MANIFEST } from './constants';
import {
FETCH_EXTENSION_MANIFESTS_SUCCESS,
UPDATE_EXTENSION_MANIFEST,
ADD_EXTENSION_MANIFEST,
} from './constants';

export const fetchExtensionManifestsSuccessAction = (extensionManifests) => ({
type: FETCH_EXTENSION_MANIFESTS_SUCCESS,
Expand All @@ -24,3 +28,7 @@ export const updateExtensionManifestAction = (extensionManifest) => ({
type: UPDATE_EXTENSION_MANIFEST,
payload: extensionManifest,
});
export const addExtensionManifestAction = (extensionManifest) => ({
type: ADD_EXTENSION_MANIFEST,
payload: extensionManifest,
});
6 changes: 5 additions & 1 deletion app/src/controllers/plugins/uiExtensions/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 EPAM Systems
* Copyright 2025 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -53,5 +53,9 @@ export const ICON_FILE_KEY = 'icon';
// redux actions
export const FETCH_EXTENSION_MANIFESTS_SUCCESS = 'fetchExtensionManifestsSuccess';
export const UPDATE_EXTENSION_MANIFEST = 'updateExtensionManifest';
export const ADD_EXTENSION_MANIFEST = 'addExtensionManifest';

// for remotely hosted plugins (e.g. Browser Kube)
export const PLUGIN_TYPE_REMOTE = 'remote';
// for locally hosted plugins (e.g. Test library)
export const PLUGIN_TYPE_CORE = 'core';
41 changes: 36 additions & 5 deletions app/src/controllers/plugins/uiExtensions/overrideExtension.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,51 @@
/*
* Copyright 2025 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { pluginByNameSelector } from 'controllers/plugins';
import { updateExtensionManifestAction } from './actions';
import { updateExtensionManifestAction, addExtensionManifestAction } from './actions';
import { MANIFEST_FILE_KEY } from './constants';

const fetchManifest = async (url, manifestFileName) => {
const response = await fetch(`${url}/${manifestFileName}`, {
contentType: 'application/json',
});
return response.json();
};

// TODO: restrict access to this function (f.e. only for admins)
export const createExtensionOverrider = (store) => async (pluginName, url) => {
const plugin = pluginByNameSelector(store.getState(), pluginName);

const manifestFileName =
plugin.details?.binaryData?.[MANIFEST_FILE_KEY] || `${MANIFEST_FILE_KEY}.json`;

const response = await fetch(`${url}/${manifestFileName}`, {
contentType: 'application/json',
});
const manifest = await response.json();
const manifest = await fetchManifest(url, manifestFileName);

store.dispatch(updateExtensionManifestAction({ ...manifest, pluginName, url }));

return manifest;
};

// TODO: restrict access to this function (f.e. only for admins)
export const createExtensionAppender = (store) => async (url) => {
const manifestFileName = `${MANIFEST_FILE_KEY}.json`;

const manifest = await fetchManifest(url, manifestFileName);

store.dispatch(addExtensionManifestAction({ ...manifest, url }));

return manifest;
};
10 changes: 8 additions & 2 deletions app/src/controllers/plugins/uiExtensions/reducer.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 EPAM Systems
* Copyright 2025 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,7 +15,11 @@
*/

import { combineReducers } from 'redux';
import { FETCH_EXTENSION_MANIFESTS_SUCCESS, UPDATE_EXTENSION_MANIFEST } from './constants';
import {
FETCH_EXTENSION_MANIFESTS_SUCCESS,
UPDATE_EXTENSION_MANIFEST,
ADD_EXTENSION_MANIFEST,
} from './constants';

const extensionManifestsReducer = (state = [], { type = '', payload = {} }) => {
switch (type) {
Expand All @@ -28,6 +32,8 @@ const extensionManifestsReducer = (state = [], { type = '', payload = {} }) => {
}
return item;
});
case ADD_EXTENSION_MANIFEST:
return [...state, payload];
default:
return state;
}
Expand Down
9 changes: 5 additions & 4 deletions app/src/controllers/plugins/uiExtensions/registerPlugin.jsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { createExtensionOverrider } from './overrideExtension';
import { createExtensionOverrider, createExtensionAppender } from './overrideExtension';

window.RP = {};

export const initPluginRegistration = (store) => {
// allows overriding plugin UI extensions in favor of separately hosted files (e.g. locally hosted plugin files)
const overrideExtension = createExtensionOverrider(store);
window.RP = {
overrideExtension,
// allows overriding plugin UI extensions in favor of separately hosted files (e.g. locally hosted plugin files)
overrideExtension: createExtensionOverrider(store),
// allows appending UI extensions (e.g. locally or somewhere hosted files)
appendExtension: createExtensionAppender(store),
};
};
6 changes: 3 additions & 3 deletions app/src/controllers/plugins/uiExtensions/sagas.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 EPAM Systems
* Copyright 2025 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -49,7 +49,7 @@ export function* fetchExtensionManifests(action) {

try {
const results = yield Promise.allSettled(calls);
const metadataArray = results.reduce((acc, result, index) => {
const manifestsArray = results.reduce((acc, result, index) => {
if (result.status !== 'fulfilled') {
return acc;
}
Expand All @@ -62,7 +62,7 @@ export function* fetchExtensionManifests(action) {
});
}, []);

yield put(fetchExtensionManifestsSuccessAction(metadataArray));
yield put(fetchExtensionManifestsSuccessAction(manifestsArray));
} catch (error) {
console.error('Plugin manifests load error'); // eslint-disable-line no-console
}
Expand Down
9 changes: 6 additions & 3 deletions app/src/controllers/plugins/uiExtensions/selectors.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2024 EPAM Systems
* Copyright 2025 EPAM Systems
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -35,6 +35,7 @@ import {
EXTENSION_TYPE_TEST_ITEM_DETAILS_ADDON,
EXTENSION_TYPE_PROJECT_PAGE,
PLUGIN_TYPE_REMOTE,
PLUGIN_TYPE_CORE,
} from './constants';
import {
domainSelector,
Expand All @@ -50,11 +51,13 @@ const createExtensionSelectorByType = (type, pluginNamesSelector = enabledPlugin
pluginNamesSelector,
extensionManifestsSelector,
(enabledPluginNames, extensionManifests) => {
// TODO: update 'pluginType' usage once the backend for remote plugins will be ready
// TODO: update 'pluginType' usage once the backend for remote and core plugins will be ready
const uiExtensions = extensionManifests
.filter(
({ pluginName, pluginType }) =>
enabledPluginNames.includes(pluginName) || pluginType === PLUGIN_TYPE_REMOTE,
enabledPluginNames.includes(pluginName) ||
pluginType === PLUGIN_TYPE_REMOTE ||
pluginType === PLUGIN_TYPE_CORE,
)
.reduce(
(acc, { extensions, ...commonManifestProperties }) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,13 @@ export const ProjectSidebar = ({ onClickNavBtn }) => {
icon: SettingsIcon,
message: formatMessage(messages.projectsSettings),
});
projectPageExtensions.forEach(({ icon, internalRoute }) => {
projectPageExtensions.forEach(({ icon, internalRoute, name }) => {
if (icon) {
sidebarItems.push({
onClick: onClickNavBtn,
link: {
type: PROJECT_PLUGIN_PAGE,
payload: { organizationSlug, projectSlug, pluginPage: internalRoute },
payload: { organizationSlug, projectSlug, pluginPage: internalRoute || name },
},
icon: icon.svg,
message: icon.title,
Expand Down
3 changes: 2 additions & 1 deletion app/src/routes/routesMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@ const routesMap = {
},
},
[PLUGIN_UI_EXTENSION_ADMIN_PAGE]: '/plugin/:pluginPage/:pluginRoute*',
[PROJECT_PLUGIN_PAGE]: '/:projectId/plugin/:pluginPage/:pluginRoute*',
[PROJECT_PLUGIN_PAGE]:
'/organizations/:organizationSlug/projects/:projectSlug/plugin/:pluginPage/:pluginRoute*',
};

export const onBeforeRouteChange = (dispatch, getState, { action }) => {
Expand Down

0 comments on commit f12d238

Please sign in to comment.