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

EPMRPP-98425 || Duplicate dashboard on current project #4181

Merged
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
4 changes: 4 additions & 0 deletions app/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

[![Build Status](https://semaphoreci.com/api/v1/lexecon/rp_service-ui/branches/develop/shields_badge.svg)](https://semaphoreci.com/lexecon/rp_service-ui)

# Project Setup Note

**Important**: This project is primarily developed in the `app` directory. When using an IDE or code editor, it is recommended to open the project from the `app` folder to ensure proper configuration and dependency resolution.

## Installation

For local development, you need a [node.js](https://nodejs.org)(version 20 is recommended).
Expand Down
5 changes: 5 additions & 0 deletions app/localization/translated/be.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@
"DashboardTable.deleteDashboard": "Выдаліць",
"DashboardTable.description": "Апісанне",
"DashboardTable.edit": "Рэдагаваць",
"DashboardTable.duplicate": "Дубляваць",
iso9000t marked this conversation as resolved.
Show resolved Hide resolved
"DashboardForm.duplicateModalTitle": "Дубляваць дашборд",
"DashboardForm.duplicateModalSubmitButtonText": "Дубляваць",
"DashboardTable.copyConfig": "Скапіраваць канфігурацыю дашборда ў буфер абмену",
"DashboardTable.owner": "Уласнік",
"DefaultProjectSettings.from": "з",
"DefaultProjectSettings.keepAttachments": "Захоўваць скрыншоты",
Expand Down Expand Up @@ -1510,6 +1514,7 @@
"NotificationItem.successLogin": "Паспяховы ўваход",
"NotificationRule.launchNameLabel": "Імя запуску",
"NotificationRule.launchOwner": "Уласнік запуску",
"Notifications.duplicateDashboardSuccess": "Дублікат дашборда паспяхова створаны",
"Notifications.notifications": "Апавяшчэнні па электроннай пошце",
"Notifications.ruleNameDuplicateHint": "Для гэтага канала сувязі ўжо існуе правіла з такім жа імем",
"Notifications.updateEmail": "абноўлены",
Expand Down
5 changes: 5 additions & 0 deletions app/localization/translated/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
"ActiveDirectoryFormFields.photoAttributeLabel": "Atributo de fotografía",
"ActiveDirectoryFormFields.searchFilter": "Filtro de búsqueda",
"ActiveDirectoryFormFields.urlLabel": "URL",
"DashboardForm.duplicateModalTitle": "Duplicate Dashboard",
"DashboardForm.duplicateModalSubmitButtonText": "Duplicate",
"DashboardTable.duplicate": "Duplicate",
"DashboardTable.copyConfig": "Copy dashboard configuration to clipboard",
"Notifications.duplicateDashboardSuccess": "Dashboard has been duplicated successfully",
"AddEditDashboard.dashboardNameExistsHint": "Este nombre ya está en uso.",
"AddEditDashboard.dashboardNameHint": "El nombre del panel debe tener entre 3 y 128 caracteres.",
"AddEditDefectTypeModal.abbreviation": "Abreviatura",
Expand Down
5 changes: 5 additions & 0 deletions app/localization/translated/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@
"DashboardTable.deleteDashboard": "Удалить",
"DashboardTable.description": "Описание",
"DashboardTable.edit": "Редактировать",
"DashboardForm.duplicateModalTitle": "Дублировать дашборд",
"DashboardForm.duplicateModalSubmitButtonText": "Дублировать",
"DashboardTable.duplicate": "Дублировать",
"DashboardTable.copyConfig": "Копировать конфигурацию дашборда в буфер обмена",
"DashboardTable.owner": "Владелец",
"DefaultProjectSettings.from": "с",
"DefaultProjectSettings.keepAttachments": "Сохранять скриншоты",
Expand Down Expand Up @@ -1510,6 +1514,7 @@
"NotificationItem.successLogin": "Успешный вход",
"NotificationRule.launchNameLabel": "Название запуска",
"NotificationRule.launchOwner": "Владелец запуска",
"Notifications.duplicateDashboardSuccess": "Дубликат дашборда успешно создан",
"Notifications.notifications": "Уведомления по электронной почте",
"Notifications.ruleNameDuplicateHint": "Правило с таким названием уже существует для этого канала связи",
"Notifications.updateEmail": "обновлено",
Expand Down
5 changes: 5 additions & 0 deletions app/localization/translated/uk.json
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,10 @@
"DashboardTable.deleteDashboard": "Видалити",
"DashboardTable.description": "Опис",
"DashboardTable.edit": "Редагувати",
"DashboardTable.duplicate": "Дублювати",
"DashboardForm.duplicateModalTitle": "Дублювати дашборд",
"DashboardForm.duplicateModalSubmitButtonText": "Дублювати",
"DashboardTable.copyConfig": "Копіювати конфігурацію дашборду в буфер обміну",
"DashboardTable.owner": "Власник",
"DefaultProjectSettings.from": "з",
"DefaultProjectSettings.keepAttachments": "Зберігати скріншоти",
Expand Down Expand Up @@ -1510,6 +1514,7 @@
"NotificationItem.successLogin": "Успішний вхід",
"NotificationRule.launchNameLabel": "Назва запуску",
"NotificationRule.launchOwner": "Власник запуску",
"Notifications.duplicateDashboardSuccess": "Дублікат дашборду успішно створено",
"Notifications.notifications": "Повідомлення електронною поштою",
"Notifications.ruleNameDuplicateHint": "Правило з такою назвою вже існує для цього каналу зв’язку",
"Notifications.updateEmail": "оновлено",
Expand Down
5 changes: 5 additions & 0 deletions app/localization/translated/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
"ActiveDirectoryFormFields.photoAttributeLabel": "图片属性",
"ActiveDirectoryFormFields.searchFilter": "搜索过滤",
"ActiveDirectoryFormFields.urlLabel": "Url",
"DashboardForm.duplicateModalTitle": "Duplicate Dashboard",
"DashboardForm.duplicateModalSubmitButtonText": "Duplicate",
"DashboardTable.duplicate": "Duplicate",
"DashboardTable.copyConfig": "Copy dashboard configuration to clipboard",
"Notifications.duplicateDashboardSuccess": "Dashboard has been duplicated successfully",
"AddEditDashboard.dashboardNameExistsHint": "名字已存在,请更换后进行重试。",
"AddEditDashboard.dashboardNameHint": "名字长度的取值范围是3~128",
"AddEditDefectTypeModal.abbreviation": "缩写",
Expand Down
7 changes: 6 additions & 1 deletion app/src/common/urls.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export const URLS = {
dashboard: (activeProject, id) => `${urlBase}${activeProject}/dashboard/${id}`,
dashboards: (activeProject, params) =>
`${urlBase}${activeProject}/dashboard${getQueryParams({ ...params })}`,
dashboardConfig: (activeProject, id) => `${urlBase}${activeProject}/dashboard/${id}/config`,
dashboardPreconfigured: (activeProject) => `${urlBase}${activeProject}/dashboard/preconfigured`,

widget: (activeProject, widgetId = '') => {
const widgetIdPart = widgetId ? `/${widgetId}` : '';
Expand Down Expand Up @@ -315,7 +317,10 @@ export const URLS = {
btsIntegrationPostTicket: (projectId, integrationId) =>
`${urlBase}bts/${projectId}/${integrationId}/ticket`,
btsTicket: (activeProject, issueId, btsProject, btsUrl) =>
`${urlBase}bts/${activeProject}/ticket/${issueId}${getQueryParams({ btsProject, btsUrl })}`,
`${urlBase}bts/${activeProject}/ticket/${issueId}${getQueryParams({
btsProject,
btsUrl,
})}`,
runUniqueErrorAnalysis: (activeProject) => `${urlBase}${activeProject}/launch/cluster`,
clusterByLaunchId: (activeProject, launchId, query) =>
`${urlBase}${activeProject}/launch/cluster/${launchId}${getQueryParams(query)}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,19 @@ export const DASHBOARD_EVENTS = {
number: dashboardId,
}),

clickOnDuplicateMenuOption: (option) => ({
...getBasicClickEventParameters(DASHBOARDS),
element_name: option,
}),

clickOnBtnInModalDuplicateDashboard: (dashboardId, isDescriptionEdited) => ({
...getBasicClickEventParameters(DASHBOARDS),
element_name: 'duplicate',
modal: 'duplicate_dashboard',
link_name: isDescriptionEdited,
number: dashboardId,
}),

clickOnButtonUpdateInModalEditDashboard: (dashboardId, linkName) => ({
...getBasicClickEventParameters(DASHBOARDS),
element_name: 'update',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ const messages = defineMessages({
id: 'DashboardPage.deleteDashboardSuccess',
defaultMessage: 'Dashboard has been deleted',
},
duplicateDashboardSuccess: {
id: 'Notifications.duplicateDashboardSuccess',
defaultMessage: 'Dashboard has been duplicated successfully',
},
addPatternSuccess: {
id: 'PatternAnalysis.addPatternSuccess',
defaultMessage: 'Pattern rule has been created',
Expand Down
12 changes: 12 additions & 0 deletions app/src/controllers/dashboard/actionCreators.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ import {
UPDATE_DASHBOARD,
UPDATE_DASHBOARD_SUCCESS,
UPDATE_DASHBOARD_WIDGETS,
DUPLICATE_DASHBOARD,
DUPLICATE_DASHBOARD_SUCCESS,
} from './constants';

export const fetchDashboardsAction = (params) => ({
Expand All @@ -51,6 +53,16 @@ export const addDashboardSuccessAction = (item) => ({
payload: item,
});

export const duplicateDashboardAction = (item) => ({
type: DUPLICATE_DASHBOARD,
payload: item,
});

export const duplicateDashboardSuccessAction = (item) => ({
type: DUPLICATE_DASHBOARD_SUCCESS,
payload: item,
});

export const updateDashboardAction = (item) => ({
type: UPDATE_DASHBOARD,
payload: item,
Expand Down
2 changes: 2 additions & 0 deletions app/src/controllers/dashboard/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ export const ADD_DASHBOARD_SUCCESS = 'addDashboardSuccess';
export const UPDATE_DASHBOARD = 'updateDashboard';
export const UPDATE_DASHBOARD_WIDGETS = 'updateDashboardWidgets';
export const UPDATE_DASHBOARD_SUCCESS = 'updateDashboardSuccess';
export const DUPLICATE_DASHBOARD = 'duplicateDashboard';
export const DUPLICATE_DASHBOARD_SUCCESS = 'duplicateDashboardSuccess';
export const REMOVE_DASHBOARD = 'removeDashboard';
export const REMOVE_DASHBOARD_SUCCESS = 'removeDashboardSuccess';
export const CHANGE_VISIBILITY_TYPE = 'changeVisibilityType';
Expand Down
2 changes: 2 additions & 0 deletions app/src/controllers/dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export {
updateDashboardWidgetsAction,
toggleFullScreenModeAction,
changeFullScreenModeAction,
duplicateDashboardAction,
duplicateDashboardSuccessAction,
} from './actionCreators';
export { dashboardReducer } from './reducer';
export {
Expand Down
3 changes: 3 additions & 0 deletions app/src/controllers/dashboard/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import {
REMOVE_DASHBOARD_SUCCESS,
TOGGLE_FULL_SCREEN_MODE,
UPDATE_DASHBOARD_SUCCESS,
DUPLICATE_DASHBOARD_SUCCESS,
} from './constants';

const dashboardsReducer = (state = INITIAL_STATE.dashboards, { type = '', payload = {} }) => {
Expand All @@ -46,6 +47,8 @@ const dashboardsReducer = (state = INITIAL_STATE.dashboards, { type = '', payloa
return state.map((item) => (item.id === payload.id ? payload : item));
case REMOVE_DASHBOARD_SUCCESS:
return state.filter((item) => item.id !== payload);
case DUPLICATE_DASHBOARD_SUCCESS:
return [...state, payload];
default:
return state;
}
Expand Down
30 changes: 30 additions & 0 deletions app/src/controllers/dashboard/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
REMOVE_DASHBOARD_SUCCESS,
INCREASE_TOTAL_DASHBOARDS_LOCALLY,
DECREASE_TOTAL_DASHBOARDS_LOCALLY,
DUPLICATE_DASHBOARD,
} from './constants';
import { dashboardItemsSelector, querySelector } from './selectors';
import {
Expand Down Expand Up @@ -131,6 +132,34 @@ function* addDashboard({ payload: dashboard }) {
});
}

function* duplicateDashboard({ payload: dashboard }) {
const activeProject = yield select(activeProjectSelector);
try {
const config = yield call(fetch, URLS.dashboardConfig(activeProject, dashboard.id));
const result = yield call(fetch, URLS.dashboardPreconfigured(activeProject), {
method: 'post',
data: {
name: dashboard.name,
description: dashboard.description,
config,
},
});

const newDashboard = yield call(fetch, URLS.dashboard(activeProject, result.id));
yield put(addDashboardSuccessAction(newDashboard));

yield put(
showNotification({
messageId: 'duplicateDashboardSuccess',
type: NOTIFICATION_TYPES.SUCCESS,
}),
);
yield put(hideModalAction());
} catch (error) {
yield put(showDefaultErrorNotification(error));
}
}

function* updateDashboard({ payload: dashboard }) {
const activeProject = yield select(activeProjectSelector);
const { name, description, id } = dashboard;
Expand Down Expand Up @@ -205,5 +234,6 @@ export function* dashboardSagas() {
yield takeEvery(REMOVE_DASHBOARD, removeDashboard),
yield takeEvery(CHANGE_VISIBILITY_TYPE, changeVisibilityType),
yield takeEvery(REMOVE_DASHBOARD_SUCCESS, redirectAfterDelete),
yield takeEvery(DUPLICATE_DASHBOARD, duplicateDashboard),
]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,41 +19,21 @@ import classNames from 'classnames/bind';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { activeProjectSelector } from 'controllers/user';
import { injectIntl, defineMessages } from 'react-intl';
import { injectIntl } from 'react-intl';
import { Grid, ALIGN_CENTER } from 'components/main/grid';
import { EmptyDashboards } from 'pages/inside/dashboardPage/dashboardList/EmptyDashboards';
import { messages } from './messages';
import {
NameColumn,
DescriptionColumn,
OwnerColumn,
EditColumn,
DeleteColumn,
DuplicateColumn,
} from './dashboardTableColumns';
import styles from './dashboardTable.scss';

const cx = classNames.bind(styles);
const messages = defineMessages({
dashboardName: {
id: 'DashboardTable.dashboardName',
defaultMessage: 'Dashboard Name',
},
description: {
id: 'DashboardTable.description',
defaultMessage: 'Description',
},
owner: {
id: 'DashboardTable.owner',
defaultMessage: 'Owner',
},
edit: {
id: 'DashboardTable.edit',
defaultMessage: 'Edit',
},
deleteDashboard: {
id: 'DashboardTable.deleteDashboard',
defaultMessage: 'Delete',
},
});

@injectIntl
@connect((state) => ({
Expand All @@ -64,6 +44,7 @@ export class DashboardTable extends Component {
intl: PropTypes.object.isRequired,
onDeleteItem: PropTypes.func,
onEditItem: PropTypes.func,
onDuplicate: PropTypes.func,
onAddItem: PropTypes.func,
projectId: PropTypes.string,
dashboardItems: PropTypes.array,
Expand All @@ -74,6 +55,7 @@ export class DashboardTable extends Component {
static defaultProps = {
onDeleteItem: () => {},
onEditItem: () => {},
onDuplicate: () => {},
onAddItem: () => {},
projectId: '',
dashboardItems: [],
Expand All @@ -82,7 +64,7 @@ export class DashboardTable extends Component {
};

getTableColumns() {
const { onDeleteItem, onEditItem, intl, projectId } = this.props;
const { onDeleteItem, onEditItem, onDuplicate, intl, projectId } = this.props;

return [
{
Expand Down Expand Up @@ -111,6 +93,17 @@ export class DashboardTable extends Component {
formatter: (value) => value.owner,
component: OwnerColumn,
},
{
title: {
full: intl.formatMessage(messages.duplicate),
short: intl.formatMessage(messages.duplicate),
},
component: DuplicateColumn,
customProps: {
onDuplicate,
},
align: ALIGN_CENTER,
},
{
title: {
full: intl.formatMessage(messages.edit),
Expand Down
Loading
Loading