/* * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * SPDX-License-Identifier: Apache-2.0 */ import React, { useCallback, useEffect, useMemo, useState } from "react"; import { useForm } from "react-hook-form"; import { useHistory, useParams } from "react-router-dom"; import { useTranslation } from "react-i18next"; import { Metric, WidgetType, LocationState, Dataset, DatasetSchema, DatasetType } from "../models"; import { useDashboard, useDateTimeFormatter, useDatasets, useFullPreview, useChangeBackgroundColor, useScrollUp, useWindowSize, } from "../hooks"; import BackendService from "../services/BackendService"; import Breadcrumbs from "../components/Breadcrumbs"; import MetricsWidget from "../components/MetricsWidget"; import TextField from "../components/TextField"; import Button from "../components/Button"; import MetricsList from "../components/MetricsList"; import OrderingService from "../services/OrderingService"; import StorageService from "../services/StorageService"; import StepIndicator from "../components/StepIndicator"; import Link from "../components/Link"; import Table from "../components/Table"; import UtilsService from "../services/UtilsService"; import Spinner from "../components/Spinner"; import Alert from "../components/Alert"; import PrimaryActionBar from "../components/PrimaryActionBar"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { faSearch } from "@fortawesome/free-solid-svg-icons"; import RadioButtonsTile from "../components/RadioButtonsTile"; interface FormValues { title: string; showTitle: boolean; oneMetricPerRow: boolean; datasetType: string; significantDigitLabels: boolean; metricsCenterAlign: boolean; } interface PathParams { dashboardId: string; } function AddMetrics() { const { t } = useTranslation(); const history = useHistory(); const { state } = history.location; const { dashboardId } = useParams(); const dateFormatter = useDateTimeFormatter(); const { dashboard, loading } = useDashboard(dashboardId); const { dynamicMetricDatasets } = useDatasets(); const { register, errors, handleSubmit, watch } = useForm({ defaultValues: { title: state && state.metricTitle !== undefined ? state.metricTitle : "", showTitle: state && state.showTitle !== undefined ? state.showTitle : true, oneMetricPerRow: state && state.oneMetricPerRow !== undefined ? state.oneMetricPerRow : false, }, }); const [filter, setFilter] = useState(""); const [query, setQuery] = useState(""); const [dynamicJson, setDynamicJson] = useState>([]); const [dynamicDataset, setDynamicDataset] = useState(undefined); const [fileLoading, setFileLoading] = useState(false); const [creatingWidget, setCreatingWidget] = useState(false); const [metrics, setMetrics] = useState>( state && state.metrics ? [...state.metrics] : [], ); const [submittedMetricsNum, setSubmittedMetricsNum] = useState(); const [step, setStep] = useState(state && state.metrics ? 1 : 0); const [datasetType, setDatasetType] = useState( state && state.datasetType ? state.datasetType : undefined, ); const [datasetError, setDatasetError] = useState(""); function hasDatasetErrors() { return !datasetType || (datasetType === DatasetType.DynamicDataset && !metrics.length); } const windowSize = useWindowSize(); const isMobile = windowSize.width <= 600; useEffect(() => { if (datasetError && !hasDatasetErrors()) { setDatasetError(""); } }, [datasetError, datasetType, metrics]); const previewPanelId = "preview-metrics-panel"; const { fullPreview, fullPreviewButton } = useFullPreview(previewPanelId); const [oldStep, setOldStep] = useState(-1); const title = watch("title"); const showTitle = watch("showTitle"); const oneMetricPerRow = watch("oneMetricPerRow"); const significantDigitLabels = watch("significantDigitLabels"); const metricsCenterAlign = watch("metricsCenterAlign"); const rows = useMemo(() => dynamicMetricDatasets, [dynamicMetricDatasets]); const columns = useMemo( () => [ { Header: t("AddMetricsScreen.Name"), accessor: "fileName", }, { Header: t("AddMetricsScreen.LastUpdated"), accessor: "updatedAt", Cell: (props: any) => dateFormatter(props.value), }, { Header: t("AddMetricsScreen.Description"), accessor: "description", }, { Header: t("AddMetricsScreen.Tags"), accessor: "tags", }, ], [dateFormatter, t], ); const uploadDataset = async (): Promise => { setFileLoading(true); const uploadResponse = await StorageService.uploadMetric(JSON.stringify(metrics)); const newDataset = await BackendService.createDataset( title, { raw: uploadResponse.s3Keys.raw, json: uploadResponse.s3Keys.json, }, DatasetSchema.Metrics, ); setFileLoading(false); return newDataset; }; const onSubmit = async (values: FormValues) => { if (metrics.length === 0) { setSubmittedMetricsNum(0); return; } try { if (datasetType) { let newDataset; if (datasetType === DatasetType.DynamicDataset && dynamicJson === metrics) { newDataset = { ...dynamicDataset }; } else { newDataset = await uploadDataset(); } setCreatingWidget(true); await BackendService.createWidget( dashboardId, values.title, WidgetType.Metrics, values.showTitle, { title: values.title, datasetId: newDataset.id, s3Key: newDataset.s3Key, oneMetricPerRow: values.oneMetricPerRow, datasetType: datasetType === DatasetType.DynamicDataset && dynamicJson === metrics ? DatasetType.DynamicDataset : DatasetType.CreateNew, significantDigitLabels: values.significantDigitLabels, metricsCenterAlign: values.metricsCenterAlign, }, ); setCreatingWidget(false); history.push(`/admin/dashboard/edit/${dashboardId}`, { alert: { type: "success", message: t("AddMetricsScreen.MetricsAddedSuccessfully", { title: values.title, }), }, }); } } catch (err) { console.log(t("AddContentFailure"), err); setCreatingWidget(false); } }; const onAddMetric = async () => { history.push(`/admin/dashboard/${dashboardId}/add-metric`, { metrics, showTitle, oneMetricPerRow, metricTitle: title, origin: history.location.pathname, datasetType: datasetType, }); }; const onEditMetric = async (metric: Metric, position: number) => { history.push(`/admin/dashboard/${dashboardId}/edit-metric`, { metrics, metric, position, showTitle, oneMetricPerRow, metricTitle: title, origin: history.location.pathname, datasetType: datasetType, }); }; const onDeleteMetric = (metric: Metric) => { const newMetrics = metrics.filter((m) => m !== metric); setMetrics(newMetrics); }; const onCancel = () => { history.push(`/admin/dashboard/edit/${dashboardId}`); }; const onMoveMetricUp = async (index: number) => { return setMetricOrder(index, index - 1); }; const onMoveMetricDown = async (index: number) => { return setMetricOrder(index, index + 1); }; const setMetricOrder = async (index: number, newIndex: number) => { const metricsOrdered = OrderingService.moveMetric(metrics, index, newIndex); // if no change in order ocurred, exit if (metricsOrdered === metrics) { return; } setMetrics(metricsOrdered); }; const goBack = () => { history.push(`/admin/dashboard/${dashboardId}/add-content`); document.getElementById("Home")?.focus(); }; const handleChange = async (event: React.FormEvent) => { const target = event.target as HTMLInputElement; if (target.name === "datasetType") { const datasetType = target.value as DatasetType; setDatasetType(datasetType); await UtilsService.timeout(0); if (datasetType === DatasetType.DynamicDataset) { setMetrics(dynamicJson); } if (datasetType === DatasetType.CreateNew) { setMetrics([]); } } }; const selectDynamicDataset = useCallback(async (selectedDataset: Dataset) => { if (selectedDataset && selectedDataset.s3Key && selectedDataset.s3Key.json) { const jsonFile = selectedDataset.s3Key.json; const dataset = await StorageService.downloadJson(jsonFile); setDynamicJson(dataset); setMetrics(dataset); setDynamicDataset(selectedDataset); } }, []); const onSelect = useCallback( (selectedDataset: Array) => { selectDynamicDataset(selectedDataset[0]); }, [selectDynamicDataset], ); const advanceStep = () => { if (hasDatasetErrors()) { setDatasetError(t("AddMetricsScreen.InvalidDatasetType")); return; } setStep(1); document.getElementById("Home")?.focus(); }; const backStep = () => { setStep(0); document.getElementById("Home")?.focus(); }; const onSearch = (query: string) => { setFilter(query); }; const crumbs = [ { label: t("Dashboards"), url: "/admin/dashboards", }, { label: dashboard?.name, url: `/admin/dashboard/edit/${dashboardId}`, }, ]; if (!loading) { crumbs.push({ label: t("AddMetricsScreen.AddMetrics"), url: "", }); } useChangeBackgroundColor(); useScrollUp(oldStep, step, setOldStep); const segments = [ { label: t("AddMetricsScreen.ChooseData"), }, { label: t("AddMetricsScreen.Visualize"), }, ]; const configHeader = (

{t("AddMetricsScreen.AddMetrics")}

); return ( <> {fileLoading || creatingWidget ? ( ) : (