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

Feature/epmrpp 90913 merge develop to org #3835

Merged
merged 9 commits into from
May 17, 2024
2 changes: 1 addition & 1 deletion app/localization/translated/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@
"NotificationsEnableForm.integrationSettings": "Налады інтэграцыі",
"NotificationsEnableForm.integrationSettingsDescription": "Наладзьце злучэнне плагінаў з серверамі",
"NotificationsEnableForm.notConfiguredIntegration": "Integration not configured yet",
"NotificationsEnableForm.tabDescription": "Кіруйце апавяшчэннямі аб запуску для розных каналаў сувязі: Email, Slack, Teams і г.д.",
"NotificationsEnableForm.tabDescription": "Кіруйце апавяшчэннямі аб запуску для розных каналаў сувязі: Email, Slack, і г.д.",
"NotificationsEnableForm.title": "Няма інтэграцыі з E-mail серверам",
"NotificationsEnableForm.toggleNotificationsLabel": "Аўтаматычныя апавяшчэнні па электроннай пошце",
"NotificationsEnableForm.toggleNotificationsNote": "Адпраўляць апавяшчэнні па электроннай пошце аб заканчэнні запуску",
Expand Down
2 changes: 1 addition & 1 deletion app/localization/translated/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@
"NotificationsEnableForm.integrationSettings": "Настройки интеграции",
"NotificationsEnableForm.integrationSettingsDescription": "Настройте соединение плагинов с серверами",
"NotificationsEnableForm.notConfiguredIntegration": "Интеграция еще не настроена",
"NotificationsEnableForm.tabDescription": "Управляйте уведомлениями, связанными с запуском, для разных каналов связи: E-mail, Slack, Teams и т. д.",
"NotificationsEnableForm.tabDescription": "Управляйте уведомлениями, связанными с запуском, для разных каналов связи: E-mail, Slack, и т. д.",
"NotificationsEnableForm.title": "Нет интеграции с E-mail сервером",
"NotificationsEnableForm.toggleNotificationsLabel": "Автоматические уведомления по электронной почте",
"NotificationsEnableForm.toggleNotificationsNote": "Отправлять уведомления по электронной почте о завершении запуска",
Expand Down
2 changes: 1 addition & 1 deletion app/localization/translated/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@
"NotificationsEnableForm.integrationSettings": "Налаштування інтеграції",
"NotificationsEnableForm.integrationSettingsDescription": "Налаштувати підключення плагінів до серверів",
"NotificationsEnableForm.notConfiguredIntegration": "Інтеграцію ще не налаштовано",
"NotificationsEnableForm.tabDescription": "Керуйте повідомленнями, пов'язаними із запуском, для різних каналів зв'язку: Email, Slack, Teams і т.д.",
"NotificationsEnableForm.tabDescription": "Керуйте повідомленнями, пов'язаними із запуском, для різних каналів зв'язку: Email, Slack, і т.д.",
"NotificationsEnableForm.title": "Немає інтеграції з електронною поштою сервером",
"NotificationsEnableForm.toggleNotificationsLabel": "Автоматичне сповіщення електронною поштою",
"NotificationsEnableForm.toggleNotificationsNote": "Надсилайте сповіщення електронною поштою про завершення запуску",
Expand Down
4 changes: 2 additions & 2 deletions app/localization/translated/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@
"NotificationsEnableForm.integrationSettings": "集成设置",
"NotificationsEnableForm.integrationSettingsDescription": "配置插件与服务器的连接",
"NotificationsEnableForm.notConfiguredIntegration": "尚未配置集成",
"NotificationsEnableForm.tabDescription": "跨多个通信渠道管理与启动相关的通知:Email、Slack、Teams 等。",
"NotificationsEnableForm.tabDescription": "跨多个通信渠道管理与启动相关的通知:Email、Slack, 等。",
"NotificationsEnableForm.title": "未与电子邮件集成",
"NotificationsEnableForm.toggleNotificationsLabel": "电子邮件通知",
"NotificationsEnableForm.toggleNotificationsNote": "在启测试任务成时发送电子邮件通知",
Expand Down Expand Up @@ -2194,4 +2194,4 @@
"usersGrid.roleNonAdmin": "非管理",
"usersGrid.type": "类型",
"usersGrid.user": "登录"
}
}
20 changes: 20 additions & 0 deletions app/src/common/constants/retentionPolicy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright 2024 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.
*/

export const RETENTION_POLICY = {
REGULAR: 'REGULAR',
IMPORTANT: 'IMPORTANT',
};
5 changes: 5 additions & 0 deletions app/src/common/img/star-inline.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 4 additions & 4 deletions app/src/common/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ export const URLS = {
apiDocs: (apiType) => `${apiType}/api-docs`,

dataPhoto: (at, loadThumbnail) => `${urlBase}data/photo${getQueryParams({ at, loadThumbnail })}`,
dataUserPhoto: (projectKey, id, loadThumbnail) =>
`${urlBase}data/${projectKey}/userphoto${getQueryParams({ id, loadThumbnail })}`,
dataUserPhoto: (projectKey, login, loadThumbnail) =>
`${urlBase}data/${projectKey}/userphoto${getQueryParams({ login, loadThumbnail })}`,

dashboard: (projectKey, id) => `${urlBase}${projectKey}/dashboard/${id}`,
dashboards: (projectKey) =>
Expand Down Expand Up @@ -137,8 +137,8 @@ export const URLS = {
projectDefectType: (projectKey) => `${urlBase}${projectKey}/settings/sub-type`,
projectDeleteDefectType: (projectKey, id) => `${urlBase}${projectKey}/settings/sub-type/${id}`,
projects: () => `${urlBase}project/list`,
projectPreferences: (projectKey, userId, filterId = '') =>
`${urlBase}project/${projectKey}/preference/${userId}/${filterId}`,
projectPreferences: (projectKey, filterId = '') =>
`${urlBase}project/${projectKey}/preference/${filterId}`,
projectUsers: (projectKey) => `${urlBase}project/${projectKey}/users`,
projectUserSearchUser: (projectKey) => (searchTerm) =>
`${urlBase}project/${projectKey}/usernames/search${getQueryParams({
Expand Down
48 changes: 28 additions & 20 deletions app/src/components/extensionLoader/extensionLoader.jsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,37 @@
/*
* Copyright 2024 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 React from 'react';
import PropTypes from 'prop-types';
import { BubblesLoader } from '@reportportal/ui-kit';
import { PLUGIN_TYPE_REMOTE } from 'controllers/plugins/uiExtensions/constants';
import { ErrorBoundary } from 'components/containers/errorBoundary';
import { createImportProps } from 'controllers/plugins/uiExtensions/createImportProps';
import { ExtensionError } from './extensionError';
import { extensionType } from './extensionTypes';
import { useFederatedComponent } from './hooks';
import { getExtensionUrl } from './utils';
import { FederatedExtensionLoader } from './federatedExtensionLoader';
import { StandaloneExtensionLoader } from './standaloneExtensionLoader';

function ExtensionLoader({ extension, withPreloader, ...componentProps }) {
const { moduleName, scope, pluginName } = extension;
const url = getExtensionUrl(extension);

const { failed, Component } = useFederatedComponent(scope, moduleName, url);

if (failed) {
return <h2>Failed to load extension: {moduleName}</h2>;
}

// TODO: remove legacy extensions when all existing plugins will be migrated to the new engine
const extensionImportProps = createImportProps(pluginName);

return (
<React.Suspense fallback={withPreloader ? <BubblesLoader /> : null}>
{Component ? <Component {...extensionImportProps} {...componentProps} /> : null}
</React.Suspense>
return extension.pluginType === PLUGIN_TYPE_REMOTE ? (
<StandaloneExtensionLoader extension={extension} />
) : (
<FederatedExtensionLoader
extension={extension}
withPreloader={withPreloader}
{...componentProps}
/>
);
}
ExtensionLoader.propTypes = {
Expand All @@ -44,6 +51,7 @@ export function ExtensionLoaderWrapper({
}) {
return (
<ErrorBoundary getFallback={silentOnError ? undefined : () => <ExtensionError />}>
{/* TODO: remove legacy extensions when all existing plugins will be migrated to the new engine */}
{extension.component ? (
<extension.component {...componentProps} />
) : (
Expand Down
39 changes: 37 additions & 2 deletions app/src/components/extensionLoader/extensionTypes.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
/*
* Copyright 2024 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 PropTypes from 'prop-types';
import { PLUGIN_TYPE_REMOTE } from 'controllers/plugins/uiExtensions/constants';

/* TODO: remove legacy extensions when all existing plugins will be migrated to the new engine
and within next major version release */
Expand All @@ -11,13 +28,31 @@ const oldExtensionType = PropTypes.shape({

/* New plugins mechanism related code below */

const newExtensionType = PropTypes.shape({
const embeddedExtensionType = PropTypes.shape({
name: PropTypes.string.isRequired,
title: PropTypes.string,
// TODO: describe this field more specifically
type: PropTypes.string.isRequired,
moduleName: PropTypes.string,
scope: PropTypes.string,
pluginName: PropTypes.string.isRequired,
});

export const extensionType = PropTypes.oneOfType([oldExtensionType, newExtensionType]);
const standaloneExtensionType = PropTypes.shape({
pluginName: PropTypes.string.isRequired,
pluginType: PropTypes.oneOf([PLUGIN_TYPE_REMOTE]),
// TODO: describe this field more specifically
type: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
internalRoute: PropTypes.string,
icon: PropTypes.shape({
url: PropTypes.string,
svg: PropTypes.string,
}),
});

export const extensionType = PropTypes.oneOfType([
oldExtensionType,
embeddedExtensionType,
standaloneExtensionType,
]);
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2024 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 React from 'react';
import PropTypes from 'prop-types';
import { BubblesLoader } from '@reportportal/ui-kit';
import { createImportProps } from 'controllers/plugins/uiExtensions/createImportProps';
import { getExtensionUrl } from '../utils';
import { useFederatedComponent } from '../hooks';
import { extensionType } from '../extensionTypes';

export function FederatedExtensionLoader({ extension, withPreloader, ...componentProps }) {
const { moduleName, scope, pluginName } = extension;
const url = getExtensionUrl(extension);

const { failed, Component } = useFederatedComponent(scope, moduleName, url);

// TODO: replace with proper failed state
if (failed) {
return <h2>Failed to load extension: {moduleName}</h2>;
}

// TODO: Provide extensionImportProps via React Context
const extensionImportProps = createImportProps(pluginName);

return (
<React.Suspense fallback={withPreloader ? <BubblesLoader /> : null}>
{Component ? <Component {...extensionImportProps} {...componentProps} /> : null}
</React.Suspense>
);
}
FederatedExtensionLoader.propTypes = {
extension: extensionType,
withPreloader: PropTypes.bool,
};
FederatedExtensionLoader.defaultProps = {
extension: {},
withPreloader: false,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2024 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.
*/

export { FederatedExtensionLoader } from './federatedExtensionLoader';
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2024 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.
*/

export { StandaloneExtensionLoader } from './standaloneExtensionLoader';
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright 2024 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 React, { useRef, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { userInfoSelector } from 'controllers/user';
import { projectInfoSelector } from 'controllers/project';
import { extensionType } from '../extensionTypes';

// http://localhost:3000/#superadmin_personal/plugin/BrowserKube
// TODO: add loader while loading the iframe
// TODO: configure sandbox for iframe
function StandaloneExtensionLoader({ extension, userInfo, projectInfo }) {
const [loaded, setLoaded] = useState(false);
const ref = useRef();

const onLoad = () => {
setLoaded(true);
};

const sendRpContext = () => {
const consumerOrigin = new URL(extension.url).origin;
const data = {
user: userInfo,
project: projectInfo,
};
ref?.current?.contentWindow.postMessage(data, consumerOrigin);
};

useEffect(() => {
if (loaded) {
sendRpContext();
}
}, [loaded, userInfo, projectInfo]);

Check warning on line 48 in app/src/components/extensionLoader/standaloneExtensionLoader/standaloneExtensionLoader.jsx

View workflow job for this annotation

GitHub Actions / build (20)

React Hook useEffect has a missing dependency: 'sendRpContext'. Either include it or remove the dependency array

return (
<iframe
ref={ref}
name={extension.pluginName}
title={extension.pluginName}
src={extension.url}
style={{ width: '100%', height: '100%' }}
onLoad={onLoad}
seamless
/>
);
}
StandaloneExtensionLoader.propTypes = {
extension: extensionType,
userInfo: PropTypes.object.isRequired,
projectInfo: PropTypes.object.isRequired,
};
StandaloneExtensionLoader.defaultProps = {
extension: {},
};

const withConnect = connect((state) => ({
userInfo: userInfoSelector(state),
projectInfo: projectInfoSelector(state),
}));

const ConnectedStandaloneExtensionLoader = withConnect(StandaloneExtensionLoader);

export { ConnectedStandaloneExtensionLoader as StandaloneExtensionLoader };
Loading
Loading