Yunus M 932d892d9e
feat: dashboard revamp according to the latest designs (#4868)
* feat: dashboard list view

* feat: update sort menu items

* feat: wire up add / import dashboard functionss

* feat: update import json styles

* feat: new dashboard templates modal

* feat: add template filter logic

* feat: revamp the overview settings modal (#4894)

* feat: revamp the overview settings modal

* feat: dashboard settings variable landing page

* feat: dashboard add variable button settings

* feat: add variable modal changes

* feat: handle the unsaved changes for general settings

* feat: follow ups for side panel section for dashboards  (#4906)

* feat: changes for tags input

* feat: side panel header styles

* feat: changes for textbox variable

* feat: handle changes for custom type variable

* feat: overflow preview vales

* feat: overflow preview vales

* feat: setup for new dashboard landing page (#4921)

* feat: setup for new dashboard landing page

* feat: added empty state widgets

* feat: added functionality to the configure and the add panel button

* feat: tag variables changes

* feat: dashboard revamp changes follow ups (#4929)

* feat: changes for new panel type modal

* fix: added missing / in the breadcrumbs

* feat: added dashboard settings menu items

* feat: added dashboard rename modal

* feat: move full screen handle a few components up

* feat: handle rename and copy export changes

* feat: minor cleanup

* feat: delete button changes

* feat: dashboard widget edit page design revamp (#4946)

* feat: dashboard edit page base setup

* feat: right container design revamp

* feat: alerts and thresholds changes right container

* feat: right container

* feat: fix graph styles

* fix: some edits for dashboard edit page

* feat: threshold preview changes (#4990)

* feat: threshold preview changes

* feat: threshold preview changes

* feat: threshold discard handler

* fix: remove the horizontal scroll from the dashboards landing page

* fix: added margin to dashboard widgets (#4991)

* fix: rebase conflicts

* feat: dashboard panel grouping change for new designs (#4992)

* feat: dashboard panel groping base cleanups

* feat: move add panel code from inner component to parent component

* feat: new dashboard section panel naming modal

* feat: dashboard panel groping base cleanups

* feat: grip changes

* feat: dashboard list page revamp and functionality additions (#4994)

* feat: fix types and code structure for list page

* feat: dashboard actions

* feat: design changes for tags

* feat: design changes for tags

* feat: update import json styles

* feat: added all dashboards row

* feat: added configure metadata linking

* feat: added local storage changes for dynamic columns

* feat: added user metadata display for metadata modal

* feat: configure metadata final changes

* feat: handle dashboard list loading state

* feat: sort and pagination changes for dashboard list view designs (#4996)

* feat: minor list view css changes

* feat: added sort functionality to the dashboards list

* feat: added sort functionality to the dashboards list

* feat: added name dropdown in the settings drawer and image as base64 format (#5000)

* feat: added name input in settings drawer

* feat: discard handler

* feat: implemented the name dropdown

* feat: added dashboard list page header

* fix: margin of dashboard list container

* feat: dashboard empty state (#5005)

* feat: light mode changes for new dashboard revamp (#5006)

* feat: light mode changes for dahsboards list page

* feat: dashboard description landing page changes

* feat: variable panels landing page light theme changes

* feat: dashboard edit panel light mode

* feat: added dashboard list error state (#5011)

* feat: added missing light mode designs

* fix: usability / customer issues  (#5014)

* fix: [GH-4986]: preview values not getting updated when the query result is empty

* fix: [GH-4985]: fix the usability of dahsboards variables drawer

* fix: light mode design for component slider

* fix: code cleanup

* fix: 0 being added in case of no tags

* fix: minor styling fixes

* fix: handle silent error for dashboard edit mutation (#5022)

* fix: handle silent error for dashboard edit mutation

* fix: handle silent error for dashboard edit mutation

* fix: rbac changes

* fix: grip icon color

* fix: new dashboards feedback from testing (#5030)

* fix: hide create new dashboards from viewer roles

* fix: move the elipsis button right of date time picker and make it a button

* fix: remove duplicate button from actions for now

* fix: last updated by and created by difference

* fix: hide intercom for modals

* fix: actions popover not closing

* fix: temp remove templates modal from normal flow

* fix: delete button event propagation

* fix: minor UI fixes (#5032)

* fix: update dashboards landing page icons

* fix: added lock icon for locked dashboards

* fix: updated dashboards list page styles

* fix: comment out filters code for phase 2 (#5034)

* fix: dashboard revamp ui fixes  (#5037)

* fix: increase the width of the graph section

* fix: remove select and next from component slider

* Dashboard vqa 1 (#5090)

* fix: dashboard VQA pt 1

* fix: dashboard VQA pt 2

* fix: dashboard VQA pt 3

* fix: dashboard VQA pt 4

* fix: dashboard VQA pt 5

* fix: dashboard VQA pt 6

* fix: dashboard VQA pt 7

* fix: added dashboard locked footer and base64 icons (#5091)

* fix: added dashboard locked footer

* fix: update base64 images

* fix: dashboard delete hover and row actions refactor

* fix: dashboard vqa pt 2 (#5098)

* fix: review comments

* fix: alerts plot tag spacing

* fix: css variables update

---------

Co-authored-by: Vikrant Gupta <vikrant.thomso@gmail.com>
2024-05-28 19:09:04 +05:30

251 lines
6.5 KiB
TypeScript

import './importJSON.styles.scss';
import { red } from '@ant-design/colors';
import { ExclamationCircleTwoTone } from '@ant-design/icons';
import MEditor, { Monaco } from '@monaco-editor/react';
import { Color } from '@signozhq/design-tokens';
import { Button, Modal, Space, Typography, Upload, UploadProps } from 'antd';
import createDashboard from 'api/dashboard/create';
import ROUTES from 'constants/routes';
import { useIsDarkMode } from 'hooks/useDarkMode';
import { MESSAGE } from 'hooks/useFeatureFlag';
import { useNotifications } from 'hooks/useNotifications';
import { getUpdatedLayout } from 'lib/dashboard/getUpdatedLayout';
import history from 'lib/history';
import { MonitorDot, MoveRight, X } from 'lucide-react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { generatePath } from 'react-router-dom';
import { DashboardData } from 'types/api/dashboard/getAll';
function ImportJSON({
isImportJSONModalVisible,
uploadedGrafana,
onModalHandler,
}: ImportJSONProps): JSX.Element {
const [jsonData, setJsonData] = useState<Record<string, unknown>>();
const { t } = useTranslation(['dashboard', 'common']);
const [isUploadJSONError, setIsUploadJSONError] = useState<boolean>(false);
const [isCreateDashboardError, setIsCreateDashboardError] = useState<boolean>(
false,
);
const [isFeatureAlert, setIsFeatureAlert] = useState<boolean>(false);
const [dashboardCreating, setDashboardCreating] = useState<boolean>(false);
const [editorValue, setEditorValue] = useState<string>('');
const { notifications } = useNotifications();
const onChangeHandler: UploadProps['onChange'] = (info) => {
const { fileList } = info;
const reader = new FileReader();
const lastFile = fileList[fileList.length - 1];
if (lastFile.originFileObj) {
reader.onload = async (event): Promise<void> => {
if (event.target) {
const target = event.target.result;
try {
if (target) {
const targetFile = target.toString();
const parsedValue = JSON.parse(targetFile);
setJsonData(parsedValue);
setEditorValue(JSON.stringify(parsedValue, null, 2));
setIsUploadJSONError(false);
}
} catch (error) {
setIsUploadJSONError(true);
}
}
};
reader.readAsText(lastFile.originFileObj);
}
};
const onClickLoadJsonHandler = async (): Promise<void> => {
try {
setDashboardCreating(true);
const dashboardData = JSON.parse(editorValue) as DashboardData;
if (dashboardData?.layout) {
dashboardData.layout = getUpdatedLayout(dashboardData.layout);
} else {
dashboardData.layout = [];
}
const response = await createDashboard({
...dashboardData,
uploadedGrafana,
});
if (response.statusCode === 200) {
history.push(
generatePath(ROUTES.DASHBOARD, {
dashboardId: response.payload.uuid,
}),
);
} else if (response.error === 'feature usage exceeded') {
setIsFeatureAlert(true);
notifications.error({
message:
response.error ||
t('something_went_wrong', {
ns: 'common',
}),
});
} else {
setIsCreateDashboardError(true);
notifications.error({
message:
response.error ||
t('something_went_wrong', {
ns: 'common',
}),
});
}
setDashboardCreating(false);
} catch {
setDashboardCreating(false);
setIsFeatureAlert(false);
setIsCreateDashboardError(true);
}
};
const getErrorNode = (error: string): JSX.Element => (
<Space>
<ExclamationCircleTwoTone twoToneColor={[red[7], '#1f1f1f']} />
<Typography style={{ color: '#D89614' }}>{error}</Typography>
</Space>
);
const onCancelHandler = (): void => {
setIsUploadJSONError(false);
setIsCreateDashboardError(false);
setIsFeatureAlert(false);
onModalHandler();
};
const isDarkMode = useIsDarkMode();
function setEditorTheme(monaco: Monaco): void {
monaco.editor.defineTheme('my-theme', {
base: 'vs-dark',
inherit: true,
rules: [
{ token: 'string.key.json', foreground: Color.BG_VANILLA_400 },
{ token: 'string.value.json', foreground: Color.BG_ROBIN_400 },
],
colors: {
'editor.background': Color.BG_INK_300,
},
fontFamily: 'Space Mono',
fontSize: 20,
fontWeight: 'normal',
lineHeight: 18,
letterSpacing: -0.06,
});
}
return (
<Modal
wrapClassName="import-json-modal"
open={isImportJSONModalVisible}
centered
closable={false}
destroyOnClose
width="60vw"
footer={
<div className="import-json-modal-footer">
{isCreateDashboardError && (
<div className="create-dashboard-json-error">
{getErrorNode(t('error_loading_json'))}
</div>
)}
{isUploadJSONError && (
<div className="create-dashboard-json-error">
{getErrorNode(t('error_upload_json'))}
</div>
)}
<div className="action-btns-container">
<Upload
accept=".json"
showUploadList={false}
multiple={false}
onChange={onChangeHandler}
beforeUpload={(): boolean => false}
action="none"
data={jsonData}
>
<Button
type="default"
className="periscope-btn"
icon={<MonitorDot size={14} />}
>
{' '}
{t('upload_json_file')}
</Button>
</Upload>
<Button
// disabled={editorValue.length === 0}
onClick={onClickLoadJsonHandler}
loading={dashboardCreating}
className="periscope-btn primary"
type="primary"
>
{t('import_and_next')} &nbsp; <MoveRight size={14} />
</Button>
{isFeatureAlert && (
<Typography.Text type="danger">
{MESSAGE.CREATE_DASHBOARD}
</Typography.Text>
)}
</div>
</div>
}
>
<div className="import-json-content-container">
<div className="import-json-content-header">
<Typography.Text>{t('import_json')}</Typography.Text>
<X size={14} className="periscope-btn ghost" onClick={onCancelHandler} />
</div>
<MEditor
language="json"
height="40vh"
onChange={(newValue): void => setEditorValue(newValue || '')}
value={editorValue}
options={{
scrollbar: {
alwaysConsumeMouseWheel: false,
},
minimap: {
enabled: false,
},
fontSize: 14,
fontFamily: 'Space Mono',
}}
theme={isDarkMode ? 'my-theme' : 'light'}
// eslint-disable-next-line react/jsx-no-bind
beforeMount={setEditorTheme}
/>
</div>
</Modal>
);
}
interface ImportJSONProps {
isImportJSONModalVisible: boolean;
onModalHandler: VoidFunction;
uploadedGrafana: boolean;
}
export default ImportJSON;