From 377ffe31b47e42d04a63a6aa22f23e49d80342ab Mon Sep 17 00:00:00 2001 From: okorie2 Date: Wed, 26 Jun 2024 10:08:37 +0100 Subject: [PATCH 01/58] feat:DX-1543; enable wysiwyg formatting for report heading --- .../components/chartSubheaderToolbar/data.ts | 6 +- .../chartSubheaderToolbar/index.tsx | 6 +- src/app/modules/common/RichEditor/index.tsx | 25 +++- .../home-module/components/All/assetsGrid.tsx | 16 ++- .../components/Charts/chartsGrid.tsx | 12 +- .../components/Reports/gridItem.tsx | 7 +- .../components/Reports/reportsGrid.tsx | 13 +- .../home-module/components/Table/index.tsx | 4 +- .../__test__/headerBlock.test.tsx | 3 + .../reportSubHeaderToolbar/index.tsx | 6 +- .../right-panel-create-view/index.tsx | 10 +- .../components/right-panel/data.ts | 1 + src/app/modules/report-module/data.ts | 7 +- src/app/modules/report-module/index.tsx | 42 +++--- .../components/headerBlock/index.tsx | 123 ++++++++++++------ .../report-module/views/create/data.ts | 26 +--- .../report-module/views/create/index.tsx | 4 +- .../modules/report-module/views/edit/data.ts | 28 +--- .../report-module/views/edit/index.tsx | 16 ++- .../report-module/views/preview/index.tsx | 11 +- src/app/state/recoil/atoms/index.ts | 4 + 21 files changed, 226 insertions(+), 144 deletions(-) diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/data.ts b/src/app/modules/chart-module/components/chartSubheaderToolbar/data.ts index cd2917a43..0fb59ed72 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/data.ts +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/data.ts @@ -2,7 +2,7 @@ import { IFramesArray } from "app/modules/report-module/views/create/data"; import { IHeaderDetails } from "app/modules/report-module/components/right-panel/data"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; -export interface SubheaderToolbarProps { +export interface ChartSubheaderToolbarProps { name: string; isAiSwitchActive: boolean; visualOptions?: any; @@ -38,8 +38,8 @@ export interface ReportSubheaderToolbarProps { setName: (name: string) => void; isSaveEnabled?: boolean; rawViz?: any; - setHasSubHeaderTitleFocused?: (value: boolean) => void; - setHasSubHeaderTitleBlurred?: (value: boolean) => void; + setHasReportNameFocused?: (value: boolean) => void; + setHasReportNameBlurred?: (value: boolean) => void; plugins: ToolbarPluginsType; headerDetails: IHeaderDetails; framesArray: IFramesArray[]; diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx index 7820c52d1..20ba94534 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx @@ -25,7 +25,7 @@ import { styles } from "app/modules/chart-module/components/chartSubheaderToolba import { useStoreActions, useStoreState } from "app/state/store/hooks"; import DeleteChartDialog from "app/components/Dialogs/deleteChartDialog"; import { ChartAPIModel, emptyChartAPI } from "app/modules/chart-module/data"; -import { SubheaderToolbarProps } from "app/modules/chart-module/components/chartSubheaderToolbar/data"; +import { ChartSubheaderToolbarProps } from "app/modules/chart-module/components/chartSubheaderToolbar/data"; import { ExportChartButton } from "app/modules/chart-module/components/chartSubheaderToolbar/exportButton"; import { ISnackbarState } from "app/modules/dataset-upload-module/upload-steps/previewFragment"; import { chartFromReportAtom, homeDisplayAtom } from "app/state/recoil/atoms"; @@ -36,7 +36,9 @@ import useAutosave from "app/hooks/useAutoSave"; import { useStyles } from "app/modules/report-module/components/reportSubHeaderToolbar"; import AutoResizeInput from "app/modules/report-module/components/reportSubHeaderToolbar/autoResizeInput"; -export function ChartSubheaderToolbar(props: Readonly) { +export function ChartSubheaderToolbar( + props: Readonly +) { const classes = useStyles(); const history = useHistory(); const { user, isAuthenticated } = useAuth0(); diff --git a/src/app/modules/common/RichEditor/index.tsx b/src/app/modules/common/RichEditor/index.tsx index 51409af34..309722d25 100644 --- a/src/app/modules/common/RichEditor/index.tsx +++ b/src/app/modules/common/RichEditor/index.tsx @@ -4,7 +4,7 @@ import bgPicker from "app/modules/common/RichEditor/BGColorModal/Picker"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; /*plugins */ -import { EditorState } from "draft-js"; +import { EditorState, SelectionState } from "draft-js"; import Editor from "@draft-js-plugins/editor"; import createLinkPlugin from "@draft-js-plugins/anchor"; import createEmojiPlugin from "@draft-js-plugins/emoji"; @@ -40,13 +40,34 @@ export const RichEditor = (props: { placeholder: string; }): ReactElement => { const editor = useRef(null); + const containerRef = useRef(null); const focus = (): void => { editor.current?.focus(); }; + const moveSelectionToEnd = (editorState: EditorState) => { + const content = editorState.getCurrentContent(); + const blockMap = content.getBlockMap(); + + const key = blockMap.last().getKey(); + const length = blockMap.last().getLength(); + + // On Chrome and Safari, calling focus on contenteditable focuses the + // cursor at the first character. This is something you don't expect when + // you're clicking on an input element but not directly on a character. + // Put the cursor back where it was before the blur. + const selection = new SelectionState({ + anchorKey: key, + anchorOffset: length, + focusKey: key, + focusOffset: length, + }); + return EditorState.forceSelection(editorState, selection); + }; + React.useEffect(() => { - if (props.focusOnMount) { + if (props.focusOnMount && props.editMode) { focus(); } }, []); diff --git a/src/app/modules/home-module/components/All/assetsGrid.tsx b/src/app/modules/home-module/components/All/assetsGrid.tsx index 88c82bdeb..b06db29bd 100644 --- a/src/app/modules/home-module/components/All/assetsGrid.tsx +++ b/src/app/modules/home-module/components/All/assetsGrid.tsx @@ -20,6 +20,10 @@ import ColoredReportIcon from "app/assets/icons/ColoredReportIcon"; import DeleteDatasetDialog from "app/components/Dialogs/deleteDatasetDialog"; import DeleteReportDialog from "app/components/Dialogs/deleteReportDialog"; import { HomepageTable } from "../Table"; +import { EditorState, convertFromRaw } from "draft-js"; +import { IChartAsset } from "app/modules/home-module/components/Charts/chartsGrid"; +import { ReportModel } from "app/modules/report-module/data"; +import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; interface Props { sortBy: string; @@ -259,7 +263,9 @@ export default function AssetsGrid(props: Props) { return { id: data.id, name: data.name, - description: data.title, + heading: data.heading + ? EditorState.createWithContent(convertFromRaw(data.heading)) + : EditorState.createEmpty(), createdDate: data.createdDate, type: data.assetType, }; @@ -326,7 +332,13 @@ export default function AssetsGrid(props: Props) { handleDuplicate={() => handleDuplicate(d.id, d.assetType as assetType) } - title={d.title || d.name} + heading={ + d.heading + ? EditorState.createWithContent( + convertFromRaw(d.heading) + ) + : EditorState.createEmpty() + } owner={d.owner} /> ), diff --git a/src/app/modules/home-module/components/Charts/chartsGrid.tsx b/src/app/modules/home-module/components/Charts/chartsGrid.tsx index 33f195ab6..7dbbde1f0 100644 --- a/src/app/modules/home-module/components/Charts/chartsGrid.tsx +++ b/src/app/modules/home-module/components/Charts/chartsGrid.tsx @@ -25,6 +25,16 @@ interface Props { addCard?: boolean; } +export interface IChartAsset { + id: string; + name: string; + createdDate: Date; + vizType: string; + isMappingValid: boolean; + owner: string; + isAIAssisted: boolean; +} + export default function ChartsGrid(props: Props) { const observerTarget = React.useRef(null); const [chartId, setChartId] = React.useState(""); @@ -42,7 +52,7 @@ export default function ChartsGrid(props: Props) { const { isObserved } = useInfinityScroll(observerTarget); const charts = useStoreState( - (state) => (state.charts.ChartGetList.crudData ?? []) as any[] + (state) => (state.charts.ChartGetList.crudData ?? []) as IChartAsset[] ); const loadChartsCount = useStoreActions( (actions) => actions.charts.ChartsCount.fetch diff --git a/src/app/modules/home-module/components/Reports/gridItem.tsx b/src/app/modules/home-module/components/Reports/gridItem.tsx index e777566fd..7bf9c5207 100644 --- a/src/app/modules/home-module/components/Reports/gridItem.tsx +++ b/src/app/modules/home-module/components/Reports/gridItem.tsx @@ -9,11 +9,12 @@ import { ReactComponent as EditIcon } from "app/modules/home-module/assets/edit. import { ReactComponent as DeleteIcon } from "app/modules/home-module/assets/delete.svg"; import { ReactComponent as ClockIcon } from "app/modules/home-module/assets/clock-icon.svg"; import { ReactComponent as DuplicateIcon } from "app/modules/home-module/assets/duplicate.svg"; +import { EditorState } from "draft-js"; interface Props { date: Date; id?: string; - title: string; + heading: EditorState; descr: string; color: string; viz: JSX.Element; @@ -85,7 +86,7 @@ export default function gridItem(props: Props) { `} >

- {props.title} + {props.heading.getCurrentContent().getPlainText()}

handleModal(data.id)} handleDuplicate={() => handleDuplicate(data.id)} - title={data.title || data.name} + heading={ + data.heading + ? EditorState.createWithContent( + convertFromRaw(data.heading) + ) + : EditorState.createEmpty() + } owner={data.owner} /> @@ -222,7 +229,9 @@ export default function ReportsGrid(props: Props) { data={loadedReports.map((data) => ({ id: data.id, name: data.name, - description: data.title, + heading: data.heading + ? EditorState.createWithContent(convertFromRaw(data.heading)) + : EditorState.createEmpty(), createdDate: data.createdDate, type: "report", }))} diff --git a/src/app/modules/home-module/components/Table/index.tsx b/src/app/modules/home-module/components/Table/index.tsx index e5d13c17c..98cb69465 100644 --- a/src/app/modules/home-module/components/Table/index.tsx +++ b/src/app/modules/home-module/components/Table/index.tsx @@ -8,11 +8,13 @@ import TableBody from "@material-ui/core/TableBody"; import TableCell from "@material-ui/core/TableCell"; import TableContainer from "@material-ui/core/TableContainer"; import _ from "lodash"; +import { EditorState } from "draft-js"; interface IData { id: string; name: string; - description: string; + description?: string; + heading?: EditorState; createdDate: Date; type: string; } diff --git a/src/app/modules/report-module/__test__/headerBlock.test.tsx b/src/app/modules/report-module/__test__/headerBlock.test.tsx index 477b5256d..b412bcf9f 100644 --- a/src/app/modules/report-module/__test__/headerBlock.test.tsx +++ b/src/app/modules/report-module/__test__/headerBlock.test.tsx @@ -28,6 +28,7 @@ interface MockProps { title: string; showHeader: boolean; description: EditorState; + heading: EditorState; createdDate: Date; backgroundColor: string; titleColor: string; @@ -39,6 +40,7 @@ interface MockProps { const headerDetailsResult = { headerDetails: { title: "", + heading: EditorState.createEmpty(), description: EditorState.createEmpty(), backgroundColor: "", titleColor: "", @@ -72,6 +74,7 @@ const defaultProps = (props: Partial): MockProps => { headerDetails: { title: "Test Title", showHeader: true, + heading: EditorState.createEmpty(), description: EditorState.createEmpty(), createdDate: new Date(), backgroundColor: "#fff", diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx index c6315cff0..b78dbed24 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx @@ -271,11 +271,11 @@ export function ReportSubheaderToolbar( }} onBlur={() => { setInputSpanVisibility(true); - props.setHasSubHeaderTitleBlurred?.(true); + props.setHasReportNameBlurred?.(true); }} onFocus={() => { - props.setHasSubHeaderTitleFocused?.(true); - props.setHasSubHeaderTitleBlurred?.(false); + props.setHasReportNameFocused?.(true); + props.setHasReportNameBlurred?.(false); setInputSpanVisibility(false); }} disabled={props.isPreviewView} diff --git a/src/app/modules/report-module/components/right-panel-create-view/index.tsx b/src/app/modules/report-module/components/right-panel-create-view/index.tsx index f1af6bb0a..8c90b138f 100644 --- a/src/app/modules/report-module/components/right-panel-create-view/index.tsx +++ b/src/app/modules/report-module/components/right-panel-create-view/index.tsx @@ -59,16 +59,8 @@ import { useSearchMediaSources } from "app/hooks/useSearchMediaSources"; import { useDebounce } from "react-use"; import Skeleton from "@material-ui/lab/Skeleton"; import { useInfinityScroll } from "app/hooks/useInfinityScroll"; +import { IHeaderDetails } from "app/modules/report-module/components/right-panel/data"; -interface IHeaderDetails { - title: string; - showHeader: boolean; - description: EditorState; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; -} interface Props { showHeaderItem: boolean; headerDetails: IHeaderDetails; diff --git a/src/app/modules/report-module/components/right-panel/data.ts b/src/app/modules/report-module/components/right-panel/data.ts index 3330f5aa3..b421256a6 100644 --- a/src/app/modules/report-module/components/right-panel/data.ts +++ b/src/app/modules/report-module/components/right-panel/data.ts @@ -3,6 +3,7 @@ import { IFramesArray } from "../../views/create/data"; export interface IHeaderDetails { title: string; + heading: EditorState; showHeader: boolean; description: EditorState; backgroundColor: string; diff --git a/src/app/modules/report-module/data.ts b/src/app/modules/report-module/data.ts index a349a5747..e387f0163 100644 --- a/src/app/modules/report-module/data.ts +++ b/src/app/modules/report-module/data.ts @@ -6,7 +6,8 @@ export interface ReportModel { title: string; public: boolean; showHeader: boolean; - subTitle: RawDraftContentState; + description: RawDraftContentState; + heading: RawDraftContentState; rows: { structure: | null @@ -48,7 +49,9 @@ export const emptyReport: ReportModel = { name: "Untitled report", title: "", public: false, - subTitle: convertToRaw(EditorState.createEmpty().getCurrentContent()), + description: convertToRaw(EditorState.createEmpty().getCurrentContent()), + heading: convertToRaw(EditorState.createEmpty().getCurrentContent()), + showHeader: false, rows: [], createdDate: new Date(), diff --git a/src/app/modules/report-module/index.tsx b/src/app/modules/report-module/index.tsx index 601c1907a..3aff54fca 100644 --- a/src/app/modules/report-module/index.tsx +++ b/src/app/modules/report-module/index.tsx @@ -108,10 +108,8 @@ export default function ReportModule() { const [rightPanelOpen, setRightPanelOpen] = React.useState(true); const [reportName, setReportName] = React.useState("Untitled report"); - const [hasSubHeaderTitleFocused, setHasSubHeaderTitleFocused] = - React.useState(false); - const [hasSubHeaderTitleBlurred, setHasSubHeaderTitleBlurred] = - React.useState(false); + const [hasReportNameFocused, setHasReportNameFocused] = React.useState(false); + const [hasReportNameBlurred, setHasReportNameBlurred] = React.useState(false); const [reportType, setReportType] = React.useState< "basic" | "advanced" | "ai" | null @@ -119,6 +117,7 @@ export default function ReportModule() { const [headerDetails, setHeaderDetails] = React.useState({ title: "", description: EditorState.createEmpty(), + heading: EditorState.createEmpty(), showHeader: true, backgroundColor: "#252c34", titleColor: "#ffffff", @@ -131,13 +130,13 @@ export default function ReportModule() { React.useEffect(() => { //set report name back to untitled report if it is empty and user is not focused on subheader title - if (reportName === "" && hasSubHeaderTitleBlurred) { + if (reportName === "" && hasReportNameBlurred) { setReportName("Untitled report"); } return () => { - setHasSubHeaderTitleBlurred(false); + setHasReportNameBlurred(false); }; - }, [hasSubHeaderTitleBlurred]); + }, [hasReportNameBlurred]); const handleRowFrameItemResize = ( rowId: string, @@ -197,6 +196,9 @@ export default function ReportModule() { reportName: reportNameRef.current, headerDetails: { ...headerDetailsRef.current, + heading: JSON.stringify( + convertToRaw(headerDetailsRef.current.heading.getCurrentContent()) + ), description: JSON.stringify( convertToRaw(headerDetailsRef.current.description.getCurrentContent()) ), @@ -326,7 +328,9 @@ export default function ReportModule() { setReportName(persistedReportState.reportName || "Untitled report"); setHeaderDetails({ ...persistedReportState.headerDetails, - + heading: EditorState.createWithContent( + convertFromRaw(JSON.parse(persistedReportState.headerDetails.heading)) + ), description: EditorState.createWithContent( convertFromRaw( JSON.parse(persistedReportState.headerDetails.description) @@ -445,6 +449,9 @@ export default function ReportModule() { reportName: "Untitled report", headerDetails: { title: "", + heading: JSON.stringify( + convertToRaw(EditorState.createEmpty().getCurrentContent()) + ), description: JSON.stringify( convertToRaw(EditorState.createEmpty().getCurrentContent()) ), @@ -460,6 +467,7 @@ export default function ReportModule() { setHeaderDetails({ title: "", + heading: EditorState.createEmpty(), description: EditorState.createEmpty(), showHeader: true, backgroundColor: "#252c34", @@ -484,7 +492,12 @@ export default function ReportModule() { authId: user?.sub, showHeader: headerDetails.showHeader, title: headerDetails.showHeader ? headerDetails.title : undefined, - subTitle: convertToRaw( + heading: convertToRaw( + headerDetails.showHeader + ? headerDetails.heading.getCurrentContent() + : EditorState.createEmpty().getCurrentContent() + ), + description: convertToRaw( headerDetails.showHeader ? headerDetails.description.getCurrentContent() : EditorState.createEmpty().getCurrentContent() @@ -570,7 +583,6 @@ export default function ReportModule() { }, [user, isAuthenticated, reportGetData]); const showReportHeader = view === "edit" ? canEditDeleteReport : true; - return ( {!reportError401 && @@ -582,8 +594,8 @@ export default function ReportModule() { setAutoSave={setAutoSave} onReportSave={onSave} setName={setReportName} - setHasSubHeaderTitleFocused={setHasSubHeaderTitleFocused} - setHasSubHeaderTitleBlurred={setHasSubHeaderTitleBlurred} + setHasReportNameFocused={setHasReportNameFocused} + setHasReportNameBlurred={setHasReportNameBlurred} isSaveEnabled={isSaveEnabled} name={page !== "new" && !view ? reportGetData.name : reportName} framesArray={framesArray} @@ -640,7 +652,7 @@ export default function ReportModule() { setReportName={setReportName} reportName={reportName} deleteFrame={deleteFrame} - hasSubHeaderTitleFocused={hasSubHeaderTitleFocused} + hasReportNameFocused={hasReportNameFocused} reportType={reportType} framesArray={framesArray} headerDetails={headerDetails} @@ -667,8 +679,8 @@ export default function ReportModule() { stopInitializeFramesWidth={stopInitializeFramesWidth} setStopInitializeFramesWidth={setStopInitializeFramesWidth} view={view} - hasSubHeaderTitleFocused={hasSubHeaderTitleFocused} - setHasSubHeaderTitleFocused={setHasSubHeaderTitleFocused} + hasReportNameFocused={hasReportNameFocused} + setHasReportNameFocused={setHasReportNameFocused} setPlugins={setPlugins} setAutoSave={setAutoSave} isSaveEnabled={isSaveEnabled} diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index 5252833a0..6faa9d99d 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -16,35 +16,17 @@ import { ReactComponent as HeaderHandlesvg } from "app/modules/report-module/ass import { Tooltip } from "@material-ui/core"; import useDebounce from "react-use/lib/useDebounce"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; +import { IHeaderDetails } from "app/modules/report-module/components/right-panel/data"; interface Props { previewMode: boolean; - hasSubHeaderTitleFocused?: boolean; - setHasSubHeaderTitleFocused?: React.Dispatch>; + hasReportNameFocused?: boolean; + sethasReportNameFocused?: React.Dispatch>; setReportName?: React.Dispatch>; reportName?: string; setPlugins: React.Dispatch>; - headerDetails: { - title: string; - showHeader: boolean; - description: EditorState; - createdDate: Date; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; - }; - setHeaderDetails: React.Dispatch< - React.SetStateAction<{ - title: string; - showHeader: boolean; - description: EditorState; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; - }> - >; + headerDetails: IHeaderDetails; + setHeaderDetails: React.Dispatch>; } export default function HeaderBlock(props: Props) { @@ -55,11 +37,14 @@ export default function HeaderBlock(props: Props) { reportRightPanelViewAtom ); const [handleDisplay, setHandleDisplay] = React.useState(false); - const placeholder = "Add a header description"; + const descriptionPlaceholder = "Add a header description"; + const headingPlaceholder = "Add a header title"; + const [headingPlaceholderState, setHeadingPlaceholderState] = + React.useState(headingPlaceholder); const [descriptionPlaceholderState, setDescriptionPlaceholderState] = - React.useState(placeholder); + React.useState(descriptionPlaceholder); - const [isReportTitleModified, setIsReportTitleModified] = + const [isReportHeadingModified, setIsReportHeadingModified] = React.useState(false); const viewOnlyMode = @@ -78,13 +63,15 @@ export default function HeaderBlock(props: Props) { //handles report name state const [,] = useDebounce( () => { - // checks when headerDetails.title is empty and report title has not been focused - if (!props.hasSubHeaderTitleFocused && isReportTitleModified) { - props.setReportName?.(props.headerDetails.title); + // checks when headerDetails.heading is empty and report heading has not been focused + if (!props.hasReportNameFocused && isReportHeadingModified) { + props.setReportName?.( + props.headerDetails.heading.getCurrentContent().getPlainText() + ); } }, 500, - [props.headerDetails.title] + [props.headerDetails.heading] ); const [{ isOver }, drop] = useDrop(() => ({ @@ -109,6 +96,16 @@ export default function HeaderBlock(props: Props) { }); }; + const setHeadingContent = (text: EditorState) => { + props.setHeaderDetails({ + ...props.headerDetails, + heading: text, + }); + if (text.getCurrentContent().getPlainText().length > 0) { + setIsReportHeadingModified(true); + } + }; + const handleChange = ( event: React.ChangeEvent ) => { @@ -118,7 +115,7 @@ export default function HeaderBlock(props: Props) { [name]: value, }); if (name == "title") { - setIsReportTitleModified(true); + setIsReportHeadingModified(true); } }; @@ -221,17 +218,57 @@ export default function HeaderBlock(props: Props) { )}

-
- div { + padding: 0; + .public-DraftEditorPlaceholder-inner { + position: absolute; + color: ${props.headerDetails.titleColor}; + opacity: 0.5; + font-size: 29px; !important; + font-family: "GothamNarrow-Bold", sans-serif; + } + span { + font-family: "GothamNarrow-Bold", sans-serif; + } + > div { + > div { + > div { + font-family: "GothamNarrow-Bold", sans-serif; + + min-height: 32px !important; + } + } + } + } + `} + > +
@@ -278,7 +315,7 @@ export default function HeaderBlock(props: Props) { invertColors editMode={true} setTextContent={setDescriptionContent} - placeholder={placeholder} + placeholder={descriptionPlaceholder} placeholderState={descriptionPlaceholderState} setPlaceholderState={setDescriptionPlaceholderState} textContent={props.headerDetails.description} diff --git a/src/app/modules/report-module/views/create/data.ts b/src/app/modules/report-module/views/create/data.ts index 717829166..2c883f185 100644 --- a/src/app/modules/report-module/views/create/data.ts +++ b/src/app/modules/report-module/views/create/data.ts @@ -1,5 +1,5 @@ -import { EditorState } from "draft-js"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; +import { IHeaderDetails } from "../../components/right-panel/data"; export interface IRowFrame { rowIndex: number; @@ -45,28 +45,10 @@ export interface ReportCreateViewProps { setFramesArray: React.Dispatch>; deleteFrame: (id: string) => void; framesArray: IFramesArray[]; - hasSubHeaderTitleFocused: boolean; + hasReportNameFocused: boolean; handlePersistReportState: () => void; - headerDetails: { - title: string; - showHeader: boolean; - description: EditorState; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; - }; - setHeaderDetails: React.Dispatch< - React.SetStateAction<{ - title: string; - showHeader: boolean; - description: EditorState; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; - }> - >; + headerDetails: IHeaderDetails; + setHeaderDetails: React.Dispatch>; handleRowFrameItemResize: ( rowId: string, diff --git a/src/app/modules/report-module/views/create/index.tsx b/src/app/modules/report-module/views/create/index.tsx index 7e30985f5..d05fc6b59 100644 --- a/src/app/modules/report-module/views/create/index.tsx +++ b/src/app/modules/report-module/views/create/index.tsx @@ -113,11 +113,11 @@ function ReportCreateView(props: Readonly) { /> diff --git a/src/app/modules/report-module/views/edit/data.ts b/src/app/modules/report-module/views/edit/data.ts index ff4005a77..081291e83 100644 --- a/src/app/modules/report-module/views/edit/data.ts +++ b/src/app/modules/report-module/views/edit/data.ts @@ -1,14 +1,14 @@ -import { EditorState } from "draft-js"; import { IFramesArray } from "app/modules/report-module/views/create/data"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; +import { IHeaderDetails } from "../../components/right-panel/data"; export interface ReportEditViewProps { open: boolean; reportType: "basic" | "advanced" | "ai" | null; isSaveEnabled: boolean; view: "initial" | "edit" | "create" | "preview" | "ai-template"; - hasSubHeaderTitleFocused: boolean; - setHasSubHeaderTitleFocused: React.Dispatch>; + hasReportNameFocused: boolean; + setHasReportNameFocused: React.Dispatch>; setFramesArray: React.Dispatch>; framesArray: IFramesArray[]; localPickedCharts: string[]; @@ -20,26 +20,8 @@ export interface ReportEditViewProps { >; handlePersistReportState: () => void; reportName: string; - headerDetails: { - title: string; - showHeader: boolean; - description: EditorState; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; - }; - setHeaderDetails: React.Dispatch< - React.SetStateAction<{ - title: string; - showHeader: boolean; - description: EditorState; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; - }> - >; + headerDetails: IHeaderDetails; + setHeaderDetails: React.Dispatch>; handleRowFrameItemResize: ( rowId: string, diff --git a/src/app/modules/report-module/views/edit/index.tsx b/src/app/modules/report-module/views/edit/index.tsx index 30f0dbb63..d6b01a984 100644 --- a/src/app/modules/report-module/views/edit/index.tsx +++ b/src/app/modules/report-module/views/edit/index.tsx @@ -145,14 +145,19 @@ function ReportEditView(props: ReportEditViewProps) { return; } if (JSON.parse(persistedReportState.framesArray || "[]").length < 1) { - props.setHasSubHeaderTitleFocused(reportData.name !== "Untitled report"); + props.setHasReportNameFocused(reportData.name !== "Untitled report"); props.setReportName(reportData.name); props.setHeaderDetails({ title: reportData.title, showHeader: reportData.showHeader, - description: reportData?.subTitle + heading: reportData?.heading ? EditorState.createWithContent( - convertFromRaw(reportData?.subTitle as RawDraftContentState) + convertFromRaw(reportData?.heading as RawDraftContentState) + ) + : EditorState.createEmpty(), + description: reportData?.description + ? EditorState.createWithContent( + convertFromRaw(reportData?.description as RawDraftContentState) ) : EditorState.createEmpty(), backgroundColor: reportData.backgroundColor, @@ -256,12 +261,11 @@ function ReportEditView(props: ReportEditViewProps) { previewMode={false} headerDetails={{ ...props.headerDetails, - createdDate: reportData.createdDate, }} reportName={reportData.name} setReportName={props.setReportName} - hasSubHeaderTitleFocused={props.hasSubHeaderTitleFocused} - setHasSubHeaderTitleFocused={props.setHasSubHeaderTitleFocused} + hasReportNameFocused={props.hasReportNameFocused} + sethasReportNameFocused={props.setHasReportNameFocused} setHeaderDetails={props.setHeaderDetails} setPlugins={props.setPlugins} /> diff --git a/src/app/modules/report-module/views/preview/index.tsx b/src/app/modules/report-module/views/preview/index.tsx index 6b12c65c6..878df3a7d 100644 --- a/src/app/modules/report-module/views/preview/index.tsx +++ b/src/app/modules/report-module/views/preview/index.tsx @@ -137,7 +137,8 @@ export function ReportPreviewView(props: { descriptionColor: persistedReportState.headerDetails.descriptionColor, dateColor: persistedReportState.headerDetails.dateColor, rows: JSON.parse(persistedReportState.framesArray || "[]"), - subTitle: JSON.parse(persistedReportState.headerDetails.description), + description: JSON.parse(persistedReportState.headerDetails.description), + heading: JSON.parse(persistedReportState.headerDetails.heading), }); } }, [persistedReportState]); @@ -171,14 +172,18 @@ export function ReportPreviewView(props: { headerDetails={{ title: reportPreviewData.title, showHeader: reportPreviewData.showHeader, + heading: EditorState.createWithContent( + convertFromRaw(reportPreviewData.heading ?? emptyReport.heading) + ), description: EditorState.createWithContent( - convertFromRaw(reportPreviewData.subTitle ?? emptyReport.subTitle) + convertFromRaw( + reportPreviewData.description ?? emptyReport.description + ) ), backgroundColor: reportPreviewData.backgroundColor, titleColor: reportPreviewData.titleColor, descriptionColor: reportPreviewData.descriptionColor, dateColor: reportPreviewData.dateColor, - createdDate: reportPreviewData.createdDate, }} setPlugins={() => {}} setHeaderDetails={() => {}} diff --git a/src/app/state/recoil/atoms/index.ts b/src/app/state/recoil/atoms/index.ts index 3296ffbd9..7cdb09c97 100644 --- a/src/app/state/recoil/atoms/index.ts +++ b/src/app/state/recoil/atoms/index.ts @@ -149,6 +149,7 @@ export const persistedReportStateAtom = atom<{ headerDetails: { title: string; description: string; + heading: string; showHeader: boolean; backgroundColor: string; titleColor: string; @@ -166,6 +167,9 @@ export const persistedReportStateAtom = atom<{ description: JSON.stringify( convertToRaw(EditorState.createEmpty().getCurrentContent()) ), + heading: JSON.stringify( + convertToRaw(EditorState.createEmpty().getCurrentContent()) + ), showHeader: true, backgroundColor: "#252c34", titleColor: "#ffffff", From ac31d2bb4ac06d098712b9d8bed50edc3f52fde2 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Tue, 9 Jul 2024 16:28:07 +0100 Subject: [PATCH 02/58] chore: review fixes --- .../modules/home-module/components/Reports/gridItem.tsx | 9 +++++++-- .../home-module/components/Reports/reportsGrid.tsx | 6 ++++-- src/app/modules/home-module/components/Table/index.tsx | 1 - 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/app/modules/home-module/components/Reports/gridItem.tsx b/src/app/modules/home-module/components/Reports/gridItem.tsx index 7bf9c5207..64c7a1ef7 100644 --- a/src/app/modules/home-module/components/Reports/gridItem.tsx +++ b/src/app/modules/home-module/components/Reports/gridItem.tsx @@ -86,7 +86,9 @@ export default function gridItem(props: Props) { `} >

- {props.heading.getCurrentContent().getPlainText()} + + {props.heading.getCurrentContent().getPlainText() || + props.descr} +

({ id: data.id, name: data.name, - heading: data.heading + description: data.heading ? EditorState.createWithContent(convertFromRaw(data.heading)) - : EditorState.createEmpty(), + .getCurrentContent() + .getPlainText() + : "", createdDate: data.createdDate, type: "report", }))} diff --git a/src/app/modules/home-module/components/Table/index.tsx b/src/app/modules/home-module/components/Table/index.tsx index 98cb69465..bd9c4bc15 100644 --- a/src/app/modules/home-module/components/Table/index.tsx +++ b/src/app/modules/home-module/components/Table/index.tsx @@ -14,7 +14,6 @@ interface IData { id: string; name: string; description?: string; - heading?: EditorState; createdDate: Date; type: string; } From 7418e195721da1f1707caeaebc33347355098f8c Mon Sep 17 00:00:00 2001 From: okorie2 Date: Tue, 9 Jul 2024 20:46:54 +0100 Subject: [PATCH 03/58] feat: includde heading to comparison check --- src/app/modules/report-module/views/edit/compareStates.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/modules/report-module/views/edit/compareStates.ts b/src/app/modules/report-module/views/edit/compareStates.ts index 4a2105b80..f4a3753f0 100644 --- a/src/app/modules/report-module/views/edit/compareStates.ts +++ b/src/app/modules/report-module/views/edit/compareStates.ts @@ -24,7 +24,7 @@ export const compareHeaderDetailsState = ( // Check if all values are the same for (const key of propsKeys) { - if (key === "description") { + if (key === "description" || key === "heading") { if ( headerDetailsProps[key].getCurrentContent().getPlainText() !== headerDetailsState[key].getCurrentContent().getPlainText() From 5710159e7f479aa31c3b99a5efbdc146bbb6cac6 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Tue, 30 Jul 2024 19:49:38 +0100 Subject: [PATCH 04/58] feat: add char count to report title/descr --- .../__test__/headerBlock.test.tsx | 2 + .../components/headerBlock/index.tsx | 44 +++++++++++++++---- .../components/headerBlock/style.ts | 7 ++- .../report-module/views/create/index.tsx | 1 + .../report-module/views/edit/index.tsx | 1 + .../report-module/views/preview/index.tsx | 1 + 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/app/modules/report-module/__test__/headerBlock.test.tsx b/src/app/modules/report-module/__test__/headerBlock.test.tsx index 477b5256d..bfd699843 100644 --- a/src/app/modules/report-module/__test__/headerBlock.test.tsx +++ b/src/app/modules/report-module/__test__/headerBlock.test.tsx @@ -18,6 +18,7 @@ import { DndProvider, useDrag } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; interface MockProps { + isToolboxOpen: boolean; previewMode: boolean; hasSubHeaderTitleFocused?: boolean; setHasSubHeaderTitleFocused?: React.Dispatch>; @@ -63,6 +64,7 @@ jest.mock("react-router-dom", () => ({ const defaultProps = (props: Partial): MockProps => { return { + isToolboxOpen: false, previewMode: false, hasSubHeaderTitleFocused: false, setHasSubHeaderTitleFocused: jest.fn(), diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index 8ee7aee5a..f08012a98 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -18,6 +18,7 @@ import useDebounce from "react-use/lib/useDebounce"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; interface Props { + isToolboxOpen: boolean; previewMode: boolean; hasSubHeaderTitleFocused?: boolean; setHasSubHeaderTitleFocused?: React.Dispatch>; @@ -55,6 +56,8 @@ export default function HeaderBlock(props: Props) { ); const [handleDisplay, setHandleDisplay] = React.useState(false); const placeholder = "Add a header description"; + const [charCount, setCharCount] = React.useState(0); + const [maxCharCount, setMaxCharCount] = React.useState(250); const [descriptionPlaceholderState, setDescriptionPlaceholderState] = React.useState(placeholder); @@ -102,20 +105,27 @@ export default function HeaderBlock(props: Props) { })); const setDescriptionContent = (text: EditorState) => { - props.setHeaderDetails({ - ...props.headerDetails, - description: text, - }); + setMaxCharCount(250); + if (text.getCurrentContent().getPlainText().length <= 250) { + setCharCount(text.getCurrentContent().getPlainText().length); + props.setHeaderDetails({ + ...props.headerDetails, + description: text, + }); + } }; const handleChange = ( event: React.ChangeEvent ) => { const { name, value } = event.target; - props.setHeaderDetails({ - ...props.headerDetails, - [name]: value, - }); + if (value.length <= 50) { + setCharCount(value.length); + props.setHeaderDetails({ + ...props.headerDetails, + [name]: value, + }); + } if (name == "title") { setIsReportTitleModified(true); } @@ -150,7 +160,10 @@ export default function HeaderBlock(props: Props) { return (

+
+ {charCount} / {maxCharCount} +
{ + setMaxCharCount(50); + setCharCount(e.target.value.length); + }} />
diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/style.ts b/src/app/modules/report-module/sub-module/components/headerBlock/style.ts index 4ab138de4..5f8a09faa 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/style.ts +++ b/src/app/modules/report-module/sub-module/components/headerBlock/style.ts @@ -1,8 +1,9 @@ import { css } from "styled-components/macro"; export const headerBlockcss = { - container: (backgroundColor: string) => css` - width: 100%; + container: (backgroundColor: string, istoolboxOpen: boolean) => css` + width: ${istoolboxOpen ? "calc(100% - 400px)" : "100%"}; + transition: width 225ms cubic-bezier(0, 0, 0.2, 1) 0ms; height: 215px; padding: 35px 0; position: relative; @@ -32,6 +33,8 @@ export const headerBlockcss = { `, innerContainer: css` width: 100%; + position: relative; + background-color: pink; `, date: (dateColor: string) => css` gap: 0.7rem; diff --git a/src/app/modules/report-module/views/create/index.tsx b/src/app/modules/report-module/views/create/index.tsx index 0099db94d..513e08d48 100644 --- a/src/app/modules/report-module/views/create/index.tsx +++ b/src/app/modules/report-module/views/create/index.tsx @@ -106,6 +106,7 @@ function ReportCreateView(props: Readonly) { `} />
Date: Wed, 31 Jul 2024 12:21:41 +0100 Subject: [PATCH 05/58] feat: char limit for editorstate --- .../components/headerBlock/index.tsx | 53 ++++++++++++------- .../components/headerBlock/style.ts | 4 +- 2 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index f08012a98..5b58e05de 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import get from "lodash/get"; import { useDrop } from "react-dnd"; -import { EditorState } from "draft-js"; +import { ContentState, EditorState } from "draft-js"; import { useRecoilState } from "recoil"; import Box from "@material-ui/core/Box"; import Container from "@material-ui/core/Container"; @@ -106,12 +106,29 @@ export default function HeaderBlock(props: Props) { const setDescriptionContent = (text: EditorState) => { setMaxCharCount(250); - if (text.getCurrentContent().getPlainText().length <= 250) { + if ( + props.headerDetails.description.getCurrentContent().getPlainText() + .length <= 250 && + text.getCurrentContent().getPlainText().length <= 250 + ) { setCharCount(text.getCurrentContent().getPlainText().length); props.setHeaderDetails({ ...props.headerDetails, description: text, }); + } else { + const slicedText = props.headerDetails.description + .getCurrentContent() + .getPlainText() + .slice(0, 250); + + const slicedEditorState = EditorState.createWithContent( + ContentState.createFromText(slicedText) + ); + props.setHeaderDetails({ + ...props.headerDetails, + description: EditorState.moveFocusToEnd(slicedEditorState), + }); } }; @@ -119,13 +136,11 @@ export default function HeaderBlock(props: Props) { event: React.ChangeEvent ) => { const { name, value } = event.target; - if (value.length <= 50) { - setCharCount(value.length); - props.setHeaderDetails({ - ...props.headerDetails, - [name]: value, - }); - } + setCharCount(value.length); + props.setHeaderDetails({ + ...props.headerDetails, + [name]: value, + }); if (name == "title") { setIsReportTitleModified(true); } @@ -168,6 +183,16 @@ export default function HeaderBlock(props: Props) { data-cy="report-header-block" data-testid="header-block" > +
+ {charCount} / {maxCharCount} +
{(handleDisplay || currentView === "editHeader") && (
-
- {charCount} / {maxCharCount} -
diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/style.ts b/src/app/modules/report-module/sub-module/components/headerBlock/style.ts index 5f8a09faa..01cc3eb76 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/style.ts +++ b/src/app/modules/report-module/sub-module/components/headerBlock/style.ts @@ -2,7 +2,7 @@ import { css } from "styled-components/macro"; export const headerBlockcss = { container: (backgroundColor: string, istoolboxOpen: boolean) => css` - width: ${istoolboxOpen ? "calc(100% - 400px)" : "100%"}; + width: 100%; transition: width 225ms cubic-bezier(0, 0, 0.2, 1) 0ms; height: 215px; padding: 35px 0; @@ -33,8 +33,6 @@ export const headerBlockcss = { `, innerContainer: css` width: 100%; - position: relative; - background-color: pink; `, date: (dateColor: string) => css` gap: 0.7rem; From 1a43096adb74b33de46ea46743527a371fd6083c Mon Sep 17 00:00:00 2001 From: okorie2 Date: Thu, 1 Aug 2024 10:31:41 +0100 Subject: [PATCH 06/58] feat: character limit for draftjs Editor --- src/app/modules/common/RichEditor/index.tsx | 2 + .../components/headerBlock/index.tsx | 47 ++++++++++++++----- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/app/modules/common/RichEditor/index.tsx b/src/app/modules/common/RichEditor/index.tsx index 51409af34..873409ec7 100644 --- a/src/app/modules/common/RichEditor/index.tsx +++ b/src/app/modules/common/RichEditor/index.tsx @@ -38,6 +38,7 @@ export const RichEditor = (props: { focusOnMount?: boolean; setPlaceholderState: React.Dispatch>; placeholder: string; + onBlur?: () => void; }): ReactElement => { const editor = useRef(null); @@ -154,6 +155,7 @@ export const RichEditor = (props: { editorState={props.textContent} onChange={props.setTextContent} onBlur={() => { + props.onBlur?.(); if (props.textContent.getCurrentContent().getPlainText().length === 0) props.setPlaceholderState(props.placeholder); }} diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index 5b58e05de..a93ce8bab 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -103,28 +103,46 @@ export default function HeaderBlock(props: Props) { }); }, })); - + const getPlainTextFromEditorState = (text: EditorState) => { + return text.getCurrentContent().getPlainText(); + }; const setDescriptionContent = (text: EditorState) => { setMaxCharCount(250); if ( - props.headerDetails.description.getCurrentContent().getPlainText() - .length <= 250 && - text.getCurrentContent().getPlainText().length <= 250 + getPlainTextFromEditorState(props.headerDetails.description).length <= + 250 && + getPlainTextFromEditorState(text).length <= 250 ) { - setCharCount(text.getCurrentContent().getPlainText().length); + setCharCount(getPlainTextFromEditorState(text).length); props.setHeaderDetails({ ...props.headerDetails, description: text, }); } else { - const slicedText = props.headerDetails.description - .getCurrentContent() - .getPlainText() - .slice(0, 250); - - const slicedEditorState = EditorState.createWithContent( - ContentState.createFromText(slicedText) - ); + let slicedEditorState = EditorState.createEmpty(); + if ( + getPlainTextFromEditorState(props.headerDetails.description).length > + 250 + ) { + setCharCount( + getPlainTextFromEditorState(props.headerDetails.description).length + ); + slicedEditorState = EditorState.createWithContent( + ContentState.createFromText( + getPlainTextFromEditorState(props.headerDetails.description).slice( + 0, + 250 + ) + ) + ); + } else if (getPlainTextFromEditorState(text).length > 250) { + setCharCount(getPlainTextFromEditorState(text).length); + slicedEditorState = EditorState.createWithContent( + ContentState.createFromText( + getPlainTextFromEditorState(text).slice(0, 250) + ) + ); + } props.setHeaderDetails({ ...props.headerDetails, description: EditorState.moveFocusToEnd(slicedEditorState), @@ -189,6 +207,7 @@ export default function HeaderBlock(props: Props) { right: ${props.isToolboxOpen ? "404px" : "4px"}; top: 4px; color: #ffffff; + display: ${maxCharCount === 0 ? "none" : "block"}; `} > {charCount} / {maxCharCount} @@ -273,6 +292,7 @@ export default function HeaderBlock(props: Props) { setMaxCharCount(50); setCharCount(e.target.value.length); }} + onBlur={() => setMaxCharCount(0)} maxLength={50} />
@@ -325,6 +345,7 @@ export default function HeaderBlock(props: Props) { setPlaceholderState={setDescriptionPlaceholderState} textContent={props.headerDetails.description} setPlugins={props.setPlugins} + onBlur={() => setMaxCharCount(0)} />
From be2265fe49a6d97c09b3e977ca465c40b31bda7e Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Thu, 1 Aug 2024 16:43:49 +0100 Subject: [PATCH 07/58] feat: DX-1674 - Update the Pricing Page according to new copy --- .../sub-modules/pricing/assets/info-icon.tsx | 26 ++++ .../pricing/components/features.tsx | 133 ++++++++++++++---- .../home-module/sub-modules/pricing/index.tsx | 63 ++++++--- 3 files changed, 169 insertions(+), 53 deletions(-) create mode 100644 src/app/modules/home-module/sub-modules/pricing/assets/info-icon.tsx diff --git a/src/app/modules/home-module/sub-modules/pricing/assets/info-icon.tsx b/src/app/modules/home-module/sub-modules/pricing/assets/info-icon.tsx new file mode 100644 index 000000000..9a0f53c36 --- /dev/null +++ b/src/app/modules/home-module/sub-modules/pricing/assets/info-icon.tsx @@ -0,0 +1,26 @@ +import React from "react"; + +const InfoIcon = () => { + return ( + + + + + ); +}; + +export default InfoIcon; diff --git a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx index 22ae91049..99eba847e 100644 --- a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx +++ b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx @@ -5,6 +5,9 @@ import GoodIcon from "../assets/good-icon"; import ReportIcon from "../assets/report"; import UserShieldIcon from "../assets/user-shied"; import SupportIcon from "../assets/support"; +import { InfoOutlined } from "@material-ui/icons"; +import InfoIcon from "../assets/info-icon"; +import { Tooltip } from "react-tooltip"; const Features = () => { const features = [ @@ -17,6 +20,7 @@ const Features = () => { options: [ { name: "Number of datasets or data size", + info: "The amount datasets you can manage", values: [ "5 datasets / 1GB", "100 datasets / 10GB", @@ -26,23 +30,34 @@ const Features = () => { }, { name: "Federated search", - values: ["Max 10 results", ">", "Unlimited", "<"], - }, - { - name: "Data export (CSV)", - values: ["Max 100 lines", ">", "Unlimited", "<"], + info: "Access to datasources like Worldbank, Kaggle, WHO, HDX and more.", + values: ["Max 10 results", "Unlimited", "Unlimited", "Unlimited"], }, + { name: "Availability", - values: ["180 days", ">", "Unlimited", "<"], + info: "How long Dataxplorer will keep your assets", + values: ["180 days", "Unlimited", "Unlimited", "Unlimited"], }, { - name: "Local Data Upload", + name: "Connect Data", + info: "Bring your own data via CSV, SQL, noSQL or connect your REST services", values: [true, true, true, true], }, { - name: "Connect to 3rd Party services ", - values: [false, true, true, true], + name: "Data export (CSV)", + info: "Export your view in a nice CSV file", + values: ["", true, true, true], + }, + { + name: "Connect your own data source", + info: "Connect data from your database", + values: ["", true, true, true], + }, + { + name: "Google Drive data connect", + info: "Connect data from your Google Drive", + values: ["", true, true, true], }, ], }, @@ -55,14 +70,17 @@ const Features = () => { options: [ { name: "Number of charts", + info: "The amount of charts you can manage.", values: [10, 100, "5.000", "50.000"], }, { name: "Access to the Chartbuilder", + info: "Create charts from your datasets", values: [true, true, true, true], }, { - name: "Share Chart Powered by Dataxplorer", + name: "Share Chart Powered by\n Dataxplorer", + info: "Sharing charts standalone as link AND embed code", values: [true, true, true, true], }, { @@ -71,16 +89,19 @@ const Features = () => { }, { name: "Advanced Charting", - values: [false, true, true, true], + info: "Advanced charting all CB charting features", + values: ["", true, true, true], }, { - name: "Custom Charting", - button: true, - values: [false, true, true, true], + name: "AI Agent", + info: "Use AI Agent to help you chart", + values: ["", true, true, true], }, { - name: "AI Agent", - values: [false, true, true, true], + name: "Custom Charting", + info: "", + button: true, + values: ["", true, true, true], }, ], }, @@ -93,29 +114,35 @@ const Features = () => { options: [ { name: "Number of reports", + info: "The amount of reports you can manage.", values: [5, 100, "1.000", "10.000"], }, { name: "Basic Templates", + info: "Access to Basic templates", values: [true, true, true, true], }, { name: "Advanced Templates", + info: "Access to Advanced templates", values: [true, true, true, true], }, { name: "Media / Video support", - values: [false, true, true, true], + info: "Add images and video", + values: ["", true, true, true], }, { name: "Report AI Chat", + info: "Talk to your data", button: true, - values: [false, true, true, true], + values: ["", true, true, true], }, { name: "Report AI Builder", + info: "Use AI Agent to draft your Report", button: true, - values: [false, true, true, true], + values: ["", true, true, true], }, ], }, @@ -128,7 +155,7 @@ const Features = () => { options: [ { name: "User Management", - values: [1, 1, 5, 10], + values: [1, 1, 5, 100], }, { name: "Pricing Management", @@ -136,7 +163,7 @@ const Features = () => { }, { name: "Team Management", - values: [false, true, true, true], + values: ["", true, true, true], }, ], }, @@ -149,23 +176,28 @@ const Features = () => { options: [ { name: "Ticketing support", - values: [false, true, true, true], + info: "Access to a ticketing system", + values: ["", true, true, true], }, { name: "Webinars", - values: [false, true, true, true], + info: "Access to monthly webinars", + values: ["", true, true, true], }, { name: "Live chat", - values: [false, true, true, true], + info: "Chat with support", + values: ["", true, true, true], }, { name: "Dedicated support", - values: [false, false, false, "5/8 CET"], + info: "Dedicated support only", + values: ["", "", "", "5/8 CET"], }, { name: "Service Level Agreement", - values: [false, false, false, "5/8 CET"], + info: "Custom Service Level", + values: ["", "", "", "5/8 CET"], }, ], }, @@ -252,7 +284,15 @@ const Features = () => { `} > {feature.options.map( - (option: { name: string; values: any[]; button?: boolean }) => ( + ( + option: { + name: string; + values: any[]; + button?: boolean; + info?: string; + }, + optionIndex + ) => (
{ align-items: center; gap: 8px; margin: 0; - padding: 9px 12px; + padding: 0px 12px; line-height: normal; font-family: "Inter", sans-serif; - font-size: 14px; + font-size: 13px; font-style: normal; font-weight: 500; + white-space: pre-line; button { border: none; background: none; @@ -296,7 +337,39 @@ const Features = () => { `} > {option.name}{" "} - {option.button && } +
+ {option.button ? ( + + ) : ( + + )} +
+ + {option.info} +

DATAXPLORER simplifies and empowers visual data reporting for all. - Free for all. + Free for all.

-

- Choose Your Subscription -

+
+

+ Choose Your Subscription +

+

+ Save 20% for annual plans +

+
Date: Thu, 1 Aug 2024 19:19:39 +0100 Subject: [PATCH 08/58] style: landing page responsiveness --- src/app/index.tsx | 4 - .../components/Footer/DesktopFooter.tsx | 297 ++++++++++++++++++ .../components/Footer/MobileFooter.tsx | 102 ++++++ .../home-module/components/Footer/index.tsx | 291 +---------------- src/app/modules/home-module/index.tsx | 25 +- src/app/modules/home-module/style.ts | 10 +- 6 files changed, 427 insertions(+), 302 deletions(-) create mode 100644 src/app/modules/home-module/components/Footer/DesktopFooter.tsx create mode 100644 src/app/modules/home-module/components/Footer/MobileFooter.tsx diff --git a/src/app/index.tsx b/src/app/index.tsx index e10973e0d..395591ee1 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -6,17 +6,13 @@ import { MainRoutes } from "app/Routes"; import { AppDialogs } from "app/components/Dialogs"; import useMediaQuery from "@material-ui/core/useMediaQuery"; import { CookieDialog } from "app/components/Dialogs/CookieDialog"; -import { MobileBottomNavigation } from "app/components/Mobile/BottomNavigation"; export function App() { - const isMobile = useMediaQuery("(max-width: 767px)"); - return ( - {isMobile && } ); } diff --git a/src/app/modules/home-module/components/Footer/DesktopFooter.tsx b/src/app/modules/home-module/components/Footer/DesktopFooter.tsx new file mode 100644 index 000000000..0e55b8b6d --- /dev/null +++ b/src/app/modules/home-module/components/Footer/DesktopFooter.tsx @@ -0,0 +1,297 @@ +import React from "react"; +import Grid from "@material-ui/core/Grid"; +import Container from "@material-ui/core/Container"; +import { homeFootercss } from "app/modules/home-module/components/Footer/style"; +import { ReactComponent as CopyIcon } from "app/modules/home-module/components/Footer/asset/copy.svg"; +import { ReactComponent as LogoIcon } from "app/modules/home-module/components/Footer/asset/logo.svg"; +import { Link } from "react-router-dom"; +import NewsletterForm from "app/modules/common/newsletterForm"; +import { FieldErrors } from "react-hook-form"; +import moment from "moment"; + +export default function DesktopFooter() { + const [isSubscribed, setIsSubscribed] = React.useState(false); + const [isSubscriptionFailed, setIsSubscriptionFailed] = React.useState(false); + const [formError, setFormError] = React.useState< + FieldErrors<{ + email: string; + }> + >({}); + return ( + <> +
+
+ + + +
    +
  • + + + +
  • +
  • + Why Dataxplorer?{" "} +
  • +
  • + Explore{" "} +
  • +
  • + About +
  • +
  • + Partners +
  • +
  • + Contact +
  • +
+
+ + + + + +

+ Subscribe to our newsletter +

+ {formError.email && ( + + )} +
+ +
+

+ {isSubscribed + ? "Thank you for subscribing!" + : isSubscriptionFailed + ? "Oops! Something went wrong with the request! Please fill your email again." + : " You will receive occasional emails from DX. You always have choice to unsubscribe within every Email."} +

+ + + +
+
+
+

+ + {moment(new Date()).format("YYYY")} Dataxplorer All Rights + Reserved +

+

+ {" "} + + Privacy + {" "} +

+

+ {" "} + + Terms and conditions + {" "} +

+
+
+
+ + ); +} diff --git a/src/app/modules/home-module/components/Footer/MobileFooter.tsx b/src/app/modules/home-module/components/Footer/MobileFooter.tsx new file mode 100644 index 000000000..dc3536a59 --- /dev/null +++ b/src/app/modules/home-module/components/Footer/MobileFooter.tsx @@ -0,0 +1,102 @@ +import React from "react"; +import { Link } from "react-router-dom"; +import { ReactComponent as LogoIcon } from "app/modules/home-module/components/Footer/asset/logo.svg"; +import { ReactComponent as CopyIcon } from "app/modules/home-module/components/Footer/asset/copy.svg"; +import moment from "moment"; + +export default function MobileFooter() { + return ( + <> +
+
+ + + +
+
+
+

+ + Privacy + {" "} + + Terms and conditions + {" "} +

+

+ + {moment(new Date()).format("YYYY")} Dataxplorer All Rights Reserved +

+
+
+ + ); +} diff --git a/src/app/modules/home-module/components/Footer/index.tsx b/src/app/modules/home-module/components/Footer/index.tsx index ea42aa934..9343cdabf 100644 --- a/src/app/modules/home-module/components/Footer/index.tsx +++ b/src/app/modules/home-module/components/Footer/index.tsx @@ -1,291 +1,10 @@ import React from "react"; -import Grid from "@material-ui/core/Grid"; -import Container from "@material-ui/core/Container"; -import { homeFootercss } from "app/modules/home-module/components/Footer/style"; -import { ReactComponent as CopyIcon } from "app/modules/home-module/components/Footer/asset/copy.svg"; -import { ReactComponent as LogoIcon } from "app/modules/home-module/components/Footer/asset/logo.svg"; -import { Link } from "react-router-dom"; -import NewsletterForm from "app/modules/common/newsletterForm"; -import { FieldErrors } from "react-hook-form"; -import moment from "moment"; +import useMediaQuery from "@material-ui/core/useMediaQuery"; +import MobileFooter from "./MobileFooter"; +import DesktopFooter from "./DesktopFooter"; export default function HomeFooter() { - const [isSubscribed, setIsSubscribed] = React.useState(false); - const [isSubscriptionFailed, setIsSubscriptionFailed] = React.useState(false); - const [formError, setFormError] = React.useState< - FieldErrors<{ - email: string; - }> - >({}); - return ( - <> -
-
- - - -
    -
  • - - - -
  • -
  • - Why Dataxplorer?{" "} -
  • -
  • - Explore{" "} -
  • -
  • - About -
  • -
  • - Partners -
  • -
  • - Contact -
  • -
-
- -
    -
  • Tel: +3185 401 5241
  • -
  • - {" "} - - Email: contact@dataxplorer.org - {" "} -
  • -
  • -

    Keizersgracht 520H

    + const isMobile = useMediaQuery("(max-width: 767px)"); -

    1017 EK Amsterdam

    - -

    The Netherlands

    -
  • -
-
- - -

- Subscribe to our newsletter -

- {formError.email && ( - - )} -
- -
-

- {isSubscribed - ? "Thank you for subscribing!" - : isSubscriptionFailed - ? "Oops! Something went wrong with the request! Please fill your email again." - : " You will receive occasional emails from DX. You always have choice to unsubscribe within every Email."} -

- - - -
-
-
-

- - {moment(new Date()).format("YYYY")} Dataxplorer All Rights - Reserved -

-

- {" "} - - Privacy - {" "} -

-

- {" "} - - Terms and conditions - {" "} -

-
-
-
- - ); + return <>{isMobile ? : }; } diff --git a/src/app/modules/home-module/index.tsx b/src/app/modules/home-module/index.tsx index 0c852d21b..656a3ee04 100644 --- a/src/app/modules/home-module/index.tsx +++ b/src/app/modules/home-module/index.tsx @@ -54,13 +54,20 @@ export default function HomeModule() { `} > - - + +
Date: Mon, 5 Aug 2024 12:17:21 +0100 Subject: [PATCH 09/58] style: responsiveness for contact page --- package.json | 1 + .../home-module/__test__/chartCard.test.tsx | 9 +- .../home-module/sub-modules/contact/index.tsx | 162 ++++++++++++++---- .../sub-modules/contact/newsletterBlock.tsx | 109 ++++++++++++ .../partners/components/empowerBlock.tsx | 4 +- .../home-module/sub-modules/partners/style.ts | 9 + 6 files changed, 254 insertions(+), 40 deletions(-) create mode 100644 src/app/modules/home-module/sub-modules/contact/newsletterBlock.tsx diff --git a/package.json b/package.json index 944c59d41..2847ef521 100644 --- a/package.json +++ b/package.json @@ -172,6 +172,7 @@ "depcheck": "depcheck", "start": "craco --max_old_space_size=4096 start", "build": "craco --max_old_space_size=4096 build", + "test-no-coverage": "react-scripts test --watchAll=true", "test": "react-scripts test --watchAll=false --coverage", "eject": "craco eject", "upgrade-all": "yarn-upgrade-all", diff --git a/src/app/modules/home-module/__test__/chartCard.test.tsx b/src/app/modules/home-module/__test__/chartCard.test.tsx index be2a381c5..89095a83b 100644 --- a/src/app/modules/home-module/__test__/chartCard.test.tsx +++ b/src/app/modules/home-module/__test__/chartCard.test.tsx @@ -73,14 +73,7 @@ test("card should display chart title, and date", async () => { expect(screen.getByText("August 2021")).toBeInTheDocument(); }); -test("card should display chart title, and date", async () => { - const { app } = appSetup({}); - render(app); - expect(screen.getByText("chart-title")).toBeInTheDocument(); - expect(screen.getByText("August 2021")).toBeInTheDocument(); -}); - -test("ai tag should not be visible if chart is isAIAssisted is false", async () => { +test("ai tag should not be visible if chart isAIAssisted is false", async () => { const { app } = appSetup({}); render(app); expect(screen.queryByTestId("chart-grid-item-ai-icon")).toBeNull(); diff --git a/src/app/modules/home-module/sub-modules/contact/index.tsx b/src/app/modules/home-module/sub-modules/contact/index.tsx index 4b55bbf7b..2beedf1bb 100644 --- a/src/app/modules/home-module/sub-modules/contact/index.tsx +++ b/src/app/modules/home-module/sub-modules/contact/index.tsx @@ -1,31 +1,27 @@ import React from "react"; import EmpowerBlock from "../partners/components/empowerBlock"; -import { Box, Container, Snackbar, TextField } from "@material-ui/core"; +import { + Box, + Container, + Snackbar, + TextField, + withStyles, +} from "@material-ui/core"; import HomeFooter from "../../components/Footer"; import { ReactComponent as FullEllipse } from "app/modules/home-module/assets/contact-lg-ellispe.svg"; import axios, { AxiosError, AxiosResponse } from "axios"; import { useTitle } from "react-use"; -import Subscribe from "../../components/Subscribe"; import { PageLoader } from "app/modules/common/page-loader"; +import NewsletterBlock from "./newsletterBlock"; +import { FieldErrors } from "react-hook-form"; -const DXLogo = ( - - - - -); +const CssTextField = withStyles({ + root: { + "& .MuiFormControl-root": { + marginTop: "unset", + }, + }, +})(TextField); export default function ContactModule() { useTitle("DX Dataxplorer - Contact"); @@ -33,6 +29,13 @@ export default function ContactModule() { const [openSnackbar, setOpenSnackbar] = React.useState(false); const [message, setMessage] = React.useState(""); const [loading, setLoading] = React.useState(false); + const [isSubscribed, setIsSubscribed] = React.useState(false); + const [isSubscriptionFailed, setIsSubscriptionFailed] = React.useState(false); + const [formError, setFormError] = React.useState< + FieldErrors<{ + email: string; + }> + >({}); const [contactFormDetails, setContactFormDetails] = React.useState({ email: "", @@ -115,16 +118,17 @@ export default function ContactModule() { css={` position: relative; z-index: 1; - height: 874px; - margin: auto; margin-top: 18px; - display: flex; justify-content: center; align-items: center; flex-direction: column; + @media (max-width: 940px) { + margin-top: 56px; + height: 100%; + } `} >

Contact us!

@@ -168,7 +201,7 @@ export default function ContactModule() { Schedule a free demo now or ask us any data related question you may have.

- - - - -
+
+
+
p:nth-of-type(1) { + color: #fff; + font-family: "GothamNarrow-Bold", sans-serif; + font-size: 24px; + margin: 0; + } + > p:nth-of-type(2) { + color: #fff; + font-family: "GothamNarrow-Book", sans-serif; + font-size: 14px; + margin-bottom: 28px; + line-height: 17px; + margin-top: 8px; + } + } + `} + > +

Want to stay up to date with new releases?

+

+ Stay informed with exclusive updates, offers, and exclusive + content delivered straight to your inbox! +

+ +
+
diff --git a/src/app/modules/home-module/sub-modules/contact/newsletterBlock.tsx b/src/app/modules/home-module/sub-modules/contact/newsletterBlock.tsx new file mode 100644 index 000000000..4ca05b6fa --- /dev/null +++ b/src/app/modules/home-module/sub-modules/contact/newsletterBlock.tsx @@ -0,0 +1,109 @@ +import NewsletterForm from "app/modules/common/newsletterForm"; +import React from "react"; +import { FieldErrors } from "react-hook-form"; + +export default function NewsletterBlock(props: { + formError: FieldErrors<{ + email: string; + }>; + setIsSubscribed: React.Dispatch>; + setIsSubscriptionFailed: React.Dispatch>; + setFormError: React.Dispatch< + React.SetStateAction> + >; + isSubscribed: boolean; + isSubscriptionFailed: boolean; +}) { + return ( +
+

+ Subscribe to our newsletter +

+ {props.formError.email && ( + + )} +
+ +
+

+ {props.isSubscribed + ? "Thank you for subscribing!" + : props.isSubscriptionFailed + ? "Oops! Something went wrong with the request! Please fill your email again." + : ""} +

+
+ ); +} diff --git a/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx b/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx index 22fa70983..64bf2fdcf 100644 --- a/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx +++ b/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx @@ -112,12 +112,12 @@ export default function EmpowerBlock(props: { gap: 10px; color: #fff; display: flex; - padding: 9px 18px !important; + padding: 9px 17px !important; background: #a1a2ff; align-items: center; justify-content: center; text-transform: uppercase; - + white-space: nowrap; > svg { transform: scale(0.8); } diff --git a/src/app/modules/home-module/sub-modules/partners/style.ts b/src/app/modules/home-module/sub-modules/partners/style.ts index 5b3b039b4..3a7466f8c 100644 --- a/src/app/modules/home-module/sub-modules/partners/style.ts +++ b/src/app/modules/home-module/sub-modules/partners/style.ts @@ -27,6 +27,10 @@ export const empowercss = (view: string) => css` text-align: center; margin-bottom: ${view === "landing" ? "14px" : "26px"}; font-family: "GothamNarrow-Bold", sans-serif; + @media (max-width: 768px) { + font-size: 40px; + line-height: 48px; + } } p { margin: 0; @@ -62,6 +66,11 @@ export const empowercss = (view: string) => css` opacity: 0.8; cursor: pointer; } + @media (max-width: 500px) { + font-size: 13px; + padding: 8px 16px; + width: 185px; + } } } `; From 46da617a91fae5cb57da1f926a0837176013edfa Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Mon, 5 Aug 2024 14:10:26 +0100 Subject: [PATCH 10/58] feat: DX-1159 - Implement Pricing Page Logic --- .../Dialogs/PlanDialog/common/message.tsx | 129 ++++++++++++++++++ .../components/Dialogs/PlanDialog/index.tsx | 96 +++++++++++++ src/app/hooks/useCheckUserPlan.tsx | 115 ++++++++++++++++ src/app/index.tsx | 2 + .../chartSubheaderToolbar/index.tsx | 14 +- src/app/modules/chart-module/index.tsx | 28 +++- .../component/datasetSubHeaderToolbar.tsx | 11 ++ .../__test__/processing.test.tsx | 4 + .../upload-module/component/uploadOption.tsx | 36 ++++- .../upload-steps/addDatasetFragment.tsx | 14 ++ .../upload-steps/externalSearch.tsx | 25 +++- .../upload-module/upload-steps/index.tsx | 51 ++++++- .../upload-module/upload-steps/processing.tsx | 110 ++++++++------- .../AssetCollection/All/assetsGrid.tsx | 22 ++- .../AssetCollection/Charts/chartsGrid.tsx | 22 ++- .../AssetCollection/Datasets/datasetsGrid.tsx | 23 +++- .../AssetCollection/Reports/reportsGrid.tsx | 22 ++- .../components/AssetCollection/index.tsx | 39 ++++-- .../pricing/components/features.tsx | 4 +- .../pricing/components/plan-card.tsx | 1 + .../reportSubHeaderToolbar/index.tsx | 14 +- src/app/modules/report-module/index.tsx | 38 +++++- src/app/state/api/index.ts | 15 +- src/app/state/api/interfaces/index.ts | 3 + src/app/state/recoil/atoms/index.ts | 15 ++ 25 files changed, 762 insertions(+), 91 deletions(-) create mode 100644 src/app/components/Dialogs/PlanDialog/common/message.tsx create mode 100644 src/app/components/Dialogs/PlanDialog/index.tsx create mode 100644 src/app/hooks/useCheckUserPlan.tsx diff --git a/src/app/components/Dialogs/PlanDialog/common/message.tsx b/src/app/components/Dialogs/PlanDialog/common/message.tsx new file mode 100644 index 000000000..e5f026c80 --- /dev/null +++ b/src/app/components/Dialogs/PlanDialog/common/message.tsx @@ -0,0 +1,129 @@ +import React from "react"; +import Box from "@material-ui/core/Box"; +import styled from "styled-components/macro"; +import Typography from "@material-ui/core/Typography"; +import { useRecoilState } from "recoil"; +import { planDialogAtom } from "app/state/recoil/atoms"; +import { useHistory } from "react-router-dom"; + +const MessageContainer = styled((props) => )` + align-items: center; + width: 100%; + justify-content: space-between; + @media (max-width: 960px) { + flex-direction: column; + align-items: normal; + } + p { + font-family: Inter; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: normal; + color: #231d2c; + cursor: pointer; + } +`; + +const Typo = styled((props) => )` + && { + align-self: center; + @media (max-width: 960px) { + margin-bottom: 8px; + } + } +`; + +const Button = styled.button` + padding: 16px 24px; + border-radius: 48px; + background: #6061e5; + color: #fff; + outline: none; + border: none; + font-family: "Inter", sans-serif; + font-size: 14px; + font-style: normal; + font-weight: 500; + line-height: normal; + text-transform: uppercase; + cursor: pointer; + flex-shrink: 0; + + @media (max-width: 960px) { + margin-bottom: 8px; + } +`; + +type MessageProps = { + onClose?: () => void; + message: string; +}; + +export const Message = (props: MessageProps) => { + const [planDialog, setPlanDialog] = useRecoilState(planDialogAtom); + + const history = useHistory(); + return ( + + +
+

+ Not Now +

+ {planDialog.tryAgain && ( + + )} + +
+
+ ); +}; diff --git a/src/app/components/Dialogs/PlanDialog/index.tsx b/src/app/components/Dialogs/PlanDialog/index.tsx new file mode 100644 index 000000000..750682a4f --- /dev/null +++ b/src/app/components/Dialogs/PlanDialog/index.tsx @@ -0,0 +1,96 @@ +import React from "react"; +import styled from "styled-components/macro"; +import Snackbar from "@material-ui/core/Snackbar"; +import SnackbarContent from "@material-ui/core/SnackbarContent"; +import { Message } from "./common/message"; +import { useRecoilState } from "recoil"; +import { planDialogAtom } from "app/state/recoil/atoms"; + +type SnackBarProps = { + open: boolean; + handleClose: () => void; + message: string; +}; + +const BaseSnackbar = styled((props) => ( + +))` + && { + bottom: 16px; + } + + & [class*="MuiSnackbarContent-root"] { + background-color: white; + width: 1232px; + border-radius: 10px; + box-shadow: 0 8px 17px -4px rgba(130, 142, 148, 0.35), + 0 0 4px 0 rgba(130, 142, 148, 0.16), 0 0 2px 0 rgba(130, 142, 148, 0.12); + flex-wrap: nowrap; + padding: 0 0; + display: flex; + justify-content: space-between; + + @media (max-width: 1280px) { + width: 100%; + } + } + + /* & [class*="MuiButtonBase-root"] { + border-radius: 10px; + height: 32px; + } */ + & [class*="MuiTypography-root"] { + font-weight: 325; + font-size: 16px; + font-family: "GothamNarrow-Book", sans-serif; + + > a { + font-family: "GothamNarrow-Book", sans-serif; + } + } + + & [class*="MuiSnackbarContent-message"] { + padding: 24px 76px; + width: 100%; + } + + & [class*="MuiSnackbarContent-action"] { + padding-left: 64px; + font-family: "GothamNarrow-Book", sans-serif; + } +`; + +export const PlanDialog = () => { + const [planDialog, setPlanDialog] = useRecoilState(planDialogAtom); + + const handleClose = () => { + setPlanDialog({ + open: false, + message: "", + tryAgain: "", + onTryAgain: () => {}, + }); + }; + + return ( + <> + + + } + /> + + + ); +}; diff --git a/src/app/hooks/useCheckUserPlan.tsx b/src/app/hooks/useCheckUserPlan.tsx new file mode 100644 index 000000000..6b6a63349 --- /dev/null +++ b/src/app/hooks/useCheckUserPlan.tsx @@ -0,0 +1,115 @@ +import { useAuth0 } from "@auth0/auth0-react"; +import { planDialogAtom } from "app/state/recoil/atoms"; +import { useStoreState } from "app/state/store/hooks"; +import axios from "axios"; +import React from "react"; +import { useSetRecoilState } from "recoil"; + +export function useCheckUserPlan() { + const { isAuthenticated } = useAuth0(); + const token = useStoreState((state) => state.AuthToken.value); + const setPlanDialog = useSetRecoilState(planDialogAtom); + + const [userPlan, setUserPlan] = React.useState<{ + planData: { + name: string; + datasets: { + noOfDatasets: number; + datasetsSize: number; + availability: number; + connectData: boolean; + exportDatasetCsv: boolean; + connectYourOwnDataSource: boolean; + googleDrive: boolean; + }; + charts: { + noOfCharts: number; + chartBuilderAccess: boolean; + shareChart: boolean; + basicCharts: boolean; + advancedCharts: boolean; + aiAgent: boolean; + customCharting: boolean; + }; + reports: { + noOfReports: number; + basicTemplates: boolean; + advancedTemplates: boolean; + mediaSupport: boolean; + aiChat: boolean; + aiAgent: boolean; + }; + }; + assetsCount: { + datasets: number; + charts: number; + reports: number; + }; + } | null>(null); + + React.useEffect(() => { + if (!token) return; + axios + .get(`${process.env.REACT_APP_API}/users/plan-data`, { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }) + .then((response) => { + setUserPlan(response.data); + }); + }, [token]); + + const handleClick = ( + asset: "report" | "chart" | "dataset", + handleCreate: () => void + ) => { + if (!isAuthenticated) { + return handleCreate(); + } + if (userPlan) { + if (asset === "dataset") { + if ( + userPlan.planData.datasets.noOfDatasets > + userPlan.assetsCount.datasets + ) { + handleCreate(); + } else { + setPlanDialog({ + open: true, + message: `You have reached the ${userPlan.planData.datasets.noOfDatasets} datasets limit for your ${userPlan.planData.name} Plan. Upgrade to increase.`, + tryAgain: "", + onTryAgain: () => {}, + }); + } + } else if (asset === "chart") { + if (userPlan.planData.charts.noOfCharts > userPlan.assetsCount.charts) { + handleCreate(); + } else { + setPlanDialog({ + open: true, + message: `You have reached the ${userPlan.planData.charts.noOfCharts} charts limit for your ${userPlan.planData.name} Plan. Upgrade to increase.`, + tryAgain: "", + onTryAgain: () => {}, + }); + } + } else if (asset === "report") { + if ( + userPlan.planData.reports.noOfReports > userPlan.assetsCount.reports + ) { + handleCreate(); + } else { + setPlanDialog({ + open: true, + message: `You have reached the ${userPlan.planData.reports.noOfReports} reports limit for your ${userPlan.planData.name} Plan. Upgrade to increase.`, + tryAgain: "", + onTryAgain: () => {}, + }); + } + } + } + }; + + return { userPlan, handleClick }; +} diff --git a/src/app/index.tsx b/src/app/index.tsx index e10973e0d..f69e69e24 100644 --- a/src/app/index.tsx +++ b/src/app/index.tsx @@ -7,6 +7,7 @@ import { AppDialogs } from "app/components/Dialogs"; import useMediaQuery from "@material-ui/core/useMediaQuery"; import { CookieDialog } from "app/components/Dialogs/CookieDialog"; import { MobileBottomNavigation } from "app/components/Mobile/BottomNavigation"; +import { PlanDialog } from "./components/Dialogs/PlanDialog"; export function App() { const isMobile = useMediaQuery("(max-width: 767px)"); @@ -15,6 +16,7 @@ export function App() { + {isMobile && } diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx index 0e50117fb..655a5aa25 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import axios from "axios"; import isEmpty from "lodash/isEmpty"; -import { useRecoilState } from "recoil"; +import { useRecoilState, useSetRecoilState } from "recoil"; import { useAuth0 } from "@auth0/auth0-react"; import Button from "@material-ui/core/Button"; import SaveIcon from "@material-ui/icons/Save"; @@ -28,7 +28,7 @@ import { ChartAPIModel, emptyChartAPI } from "app/modules/chart-module/data"; import { SubheaderToolbarProps } from "app/modules/chart-module/components/chartSubheaderToolbar/data"; import { ExportChartButton } from "app/modules/chart-module/components/chartSubheaderToolbar/exportButton"; import { ISnackbarState } from "app/modules/dataset-module/routes/upload-module/upload-steps/previewFragment"; -import { chartFromReportAtom } from "app/state/recoil/atoms"; +import { chartFromReportAtom, planDialogAtom } from "app/state/recoil/atoms"; import { InfoSnackbar } from "app/modules/chart-module/components/chartSubheaderToolbar/infoSnackbar"; import { getRequiredFieldsAndErrors } from "../../routes/mapping/utils"; import AutoSaveSwitch from "app/modules/report-module/components/reportSubHeaderToolbar/autoSaveSwitch"; @@ -97,6 +97,8 @@ export function ChartSubheaderToolbar(props: Readonly) { return isAuthenticated && loadedChart && loadedChart.owner === user?.sub; }, [user, isAuthenticated, loadedChart]); + const setPlanDialog = useSetRecoilState(planDialogAtom); + const [snackbarState, setSnackbarState] = React.useState({ open: false, vertical: "bottom", @@ -233,6 +235,14 @@ export function ChartSubheaderToolbar(props: Readonly) { }, }) .then(async (response) => { + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } loadCharts({ token, storeInCrudData: true, diff --git a/src/app/modules/chart-module/index.tsx b/src/app/modules/chart-module/index.tsx index a94eafa70..fd7172ca3 100644 --- a/src/app/modules/chart-module/index.tsx +++ b/src/app/modules/chart-module/index.tsx @@ -45,11 +45,17 @@ import useResizeObserver from "use-resize-observer"; import { ChartType } from "app/modules/chart-module/components/common-chart"; import { getRequiredFieldsAndErrors } from "app/modules/chart-module/routes/mapping/utils"; import axios from "axios"; -import { useRecoilState, useRecoilValue, useResetRecoilState } from "recoil"; +import { + useRecoilState, + useRecoilValue, + useResetRecoilState, + useSetRecoilState, +} from "recoil"; import { chartFromReportAtom, isChartAIAgentActive, isChartAutoMappedAtom, + planDialogAtom, } from "app/state/recoil/atoms"; import { IDatasetDetails } from "./components/toolbox/steps/panels-content/SelectDataset"; @@ -65,6 +71,8 @@ export default function ChartModule() { {} ); + const setPlanDialog = useSetRecoilState(planDialogAtom); + const [rawViz, setRawViz] = React.useState(null); const [toolboxOpen, setToolboxOpen] = React.useState(Boolean(view)); const [savedChanges, setSavedChanges] = React.useState(false); @@ -295,7 +303,23 @@ export default function ChartModule() { }); if (page === "new") { const response = await onSave(); - const data = response?.data; + const data = response?.data?.data; + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } + if (response?.data.planWarning) { + setPlanDialog({ + open: true, + message: response.data.planWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } history.push( `/chart/${data.id}/mapping${ chartFromReport.state diff --git a/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx b/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx index a4fe33d51..1d5617574 100644 --- a/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx +++ b/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx @@ -24,6 +24,8 @@ import DeleteDatasetDialog from "app/components/Dialogs/deleteDatasetDialog"; import { ISnackbarState } from "app/modules/dataset-module/routes/upload-module/upload-steps/previewFragment"; import { InfoSnackbar } from "app/modules/report-module/components/reportSubHeaderToolbar/infosnackbar"; import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; +import { useSetRecoilState } from "recoil"; +import { planDialogAtom } from "app/state/recoil/atoms"; export default function DatasetSubHeaderToolbar( props: Readonly<{ name: string }> @@ -46,6 +48,7 @@ export default function DatasetSubHeaderToolbar( vertical: "bottom", horizontal: "center", }); + const setPlanDialog = useSetRecoilState(planDialogAtom); const open = Boolean(anchorEl); const popoverId = open ? "simple-popover" : undefined; @@ -85,6 +88,14 @@ export default function DatasetSubHeaderToolbar( }, }) .then((response) => { + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } setDuplicatedDatasetId(response.data.id); setSnackbarState({ ...snackbarState, diff --git a/src/app/modules/dataset-module/routes/upload-module/__test__/processing.test.tsx b/src/app/modules/dataset-module/routes/upload-module/__test__/processing.test.tsx index 3ae13bc11..297c1c399 100644 --- a/src/app/modules/dataset-module/routes/upload-module/__test__/processing.test.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/__test__/processing.test.tsx @@ -17,6 +17,7 @@ test("data should be processing", async () => { processingError={null} setProcessingError={mockSetProcessingError} tryAgain={mockTryAgain} + processingMessage="" /> ); @@ -41,6 +42,7 @@ test("when estimated times <=0, it should display 'finishing up...'", async () = processingError={null} setProcessingError={mockSetProcessingError} tryAgain={mockTryAgain} + processingMessage="" /> ); const estimatedTime = screen.getByTestId("estimated-time"); @@ -60,6 +62,7 @@ test('when estimated times > 60, it should display "minutes and seconds (estimat processingError={null} setProcessingError={mockSetProcessingError} tryAgain={mockTryAgain} + processingMessage="" /> ); const estimatedTime = screen.getByTestId("estimated-time"); @@ -79,6 +82,7 @@ test("renders processing message when processingError is true", async () => { processingError={defaultProcessingError} setProcessingError={mockSetProcessingError} tryAgain={mockTryAgain} + processingMessage="" /> ); const ErrorText = screen.getByTestId("error-message"); diff --git a/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx b/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx index ebef45a68..ab531a61c 100644 --- a/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx @@ -1,5 +1,6 @@ import React from "react"; import SettingsIcon from "../assets/upload-options-icons/settings"; +import { useHistory } from "react-router-dom"; const UploadOption = (props: { name: string; @@ -12,8 +13,12 @@ const UploadOption = (props: { connected?: boolean; onLogout?: () => void; canConnect?: boolean; + pro: boolean; }) => { const [openSettings, setOpenSettings] = React.useState(false); + + const history = useHistory(); + return (
+ {props.pro ? ( +
+ UPGRADE +
+ ) : null} +
+ /> {props.connected ? "Connected" : "Not Connected"} @@ -136,7 +168,6 @@ const UploadOption = (props: { position: absolute; right: calc(100% + 10px); top: -4px; - box-shadow: 0px 4px 30px 0px rgba(0, 0, 0, 0.1); `} hidden={!openSettings} onClick={(e) => { @@ -158,6 +189,7 @@ const UploadOption = (props: { font-family: "GothamNarrow-Bold", sans-serif; border-radius: 12px; background: #6061e5; + box-shadow: 0px 4px 30px 0px rgba(0, 0, 0, 0.1); border: none; /* padding: 5px 0; */ width: 113px; diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx index 4ca755770..628a7747e 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx @@ -18,6 +18,7 @@ import UploadOption from "../component/uploadOption"; import { useCookie } from "react-use"; import useGoogleDrivePicker from "app/hooks/useGoogleDrivePicker"; import { useOneDrivePicker } from "app/hooks/useOneDrivePicker"; +import { useCheckUserPlan } from "app/hooks/useCheckUserPlan"; interface Props { disabled: boolean; @@ -32,6 +33,8 @@ export default function AddDatasetFragment(props: Props) { const [googleDriveToken, setGoogleDriveToken, deleteGoogleDriveToken] = useCookie("googleDriveToken"); + const { userPlan } = useCheckUserPlan(); + const { getAccessTokenAndOpenPicker } = useGoogleDrivePicker({ onCancel: () => { props.setActiveOption(null); @@ -68,6 +71,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["CSV", "XSLX", "JSON", "ODS", "SQLite"], icon: , onClick: () => {}, + pro: false, }, { name: "Google Drive", @@ -83,6 +87,7 @@ export default function AddDatasetFragment(props: Props) { onLogout: () => { deleteGoogleDriveToken(); }, + pro: userPlan?.planData.name === "Free", }, { name: "Microsoft Cloud", @@ -98,6 +103,7 @@ export default function AddDatasetFragment(props: Props) { onLogout: async () => { await clearToken(); }, + pro: userPlan?.planData.name === "Free", }, { name: "API Connection", @@ -105,6 +111,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["CSV", "XSLX", "JSON", "ODS", "SQLite"], icon: , onClick: () => {}, + pro: false, }, { name: "MSSQL", @@ -112,6 +119,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, + pro: false, }, { name: "MYSQL", @@ -119,6 +127,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, + pro: false, }, { name: "PostgreSQL", @@ -126,6 +135,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, + pro: false, }, { name: "MongoDB", @@ -133,6 +143,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, + pro: false, }, { name: "Hubspot", @@ -140,6 +151,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, + pro: false, }, ]; @@ -227,6 +239,7 @@ export default function AddDatasetFragment(props: Props) { canConnect={option.canConnect} connected={option.connected} onLogout={option.onLogout} + pro={option.pro} /> ))}
@@ -256,6 +269,7 @@ export default function AddDatasetFragment(props: Props) { onClick={option.onClick} disabled setActiveOption={props.setActiveOption} + pro={option.pro} /> ))}
diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx index 956d81c64..6a6e874fc 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx @@ -9,6 +9,8 @@ import axios from "axios"; import CircleLoader from "app/modules/home-module/components/Loader"; import { useInfinityScroll } from "app/hooks/useInfinityScroll"; import SourceCategoryList from "../component/externalSourcesList"; +import { useSetRecoilState } from "recoil"; +import { planDialogAtom } from "app/state/recoil/atoms"; export interface IExternalDataset { name: string; @@ -48,6 +50,8 @@ export default function ExternalSearch(props: { const [offset, setOffset] = React.useState(0); const limit = 20; const [datasets, setDatasets] = React.useState([]); + const [planWarning, setPlanWarning] = React.useState(null); + const setPlanDialog = useSetRecoilState(planDialogAtom); const baseSources = [ { name: "Kaggle", value: "Kaggle" }, @@ -68,9 +72,10 @@ export default function ExternalSearch(props: { setOffset(0); }; + const free = true; // Pagination on scroll React.useEffect(() => { - if (isObserved && datasets.length > 0) { + if (isObserved && datasets.length > 0 && !free) { loadSearch(true); } }, [isObserved]); @@ -98,11 +103,14 @@ export default function ExternalSearch(props: { console.log(response.data.error); return; } + if (response.data.planWarning) { + setPlanWarning(response.data.planWarning); + } if (nextPage) { - setDatasets([...datasets, ...response.data]); + setDatasets([...datasets, ...response.data.result]); setOffset(offset + limit); } else { - setDatasets(response.data); + setDatasets(response.data.result); setOffset(limit); } } catch (e) { @@ -111,6 +119,17 @@ export default function ExternalSearch(props: { } }; + React.useEffect(() => { + if (planWarning) { + setPlanDialog({ + open: true, + message: planWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } + }, [planWarning]); + React.useEffect(() => { const controller = abortControllerRef.current; return () => { diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/index.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/index.tsx index 62d439637..b725a0ea5 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/index.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/index.tsx @@ -25,7 +25,7 @@ import BreadCrumbs from "app/modules/home-module/components/Breadcrumbs"; import UploadTabs from "../component/tabs"; import SmallFooter from "app/modules/home-module/components/Footer/smallFooter"; import { useRecoilState } from "recoil"; -import { dataUploadTabAtom } from "app/state/recoil/atoms"; +import { dataUploadTabAtom, planDialogAtom } from "app/state/recoil/atoms"; interface Props { datasetId: string; @@ -38,6 +38,7 @@ function DatasetUploadSteps(props: Props) { const { user } = useAuth0(); const token = useStoreState((state) => state.AuthToken.value); const steps = ["Connect", "Processing Data", "Description", "Finished"]; + const [_, setPlanDialog] = useRecoilState(planDialogAtom); const [formDetails, setFormDetails] = React.useState({ name: "", description: "", @@ -50,6 +51,7 @@ function DatasetUploadSteps(props: Props) { const [processingError, setProcessingError] = React.useState( null ); + const [processingMessage, setProcessingMessage] = React.useState(""); const [processed, setProcessed] = React.useState(false); const [selectedFile, setSelectedFile] = React.useState(null); const [searchValue, setSearchValue] = React.useState(""); @@ -150,6 +152,7 @@ function DatasetUploadSteps(props: Props) { React.useEffect(() => { if (activeStep === 0) { setProcessingError(""); + setProcessingMessage(""); setProcessed(false); } }, [activeStep]); @@ -170,9 +173,25 @@ function DatasetUploadSteps(props: Props) { .then((response) => { //load dataset and datasets on upload success //we do this to load data to populate the table - loadSampleDataset(response.data.id); + loadSampleDataset(response.data.data.id); //we do this to update the dataset list with the new dataset loadDatasets({ token, storeInCrudData: true }); + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } + if (response.data.planWarning) { + setPlanDialog({ + open: true, + message: response.data.planWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } //set active step to finished setActiveStep(3); }) @@ -199,17 +218,38 @@ function DatasetUploadSteps(props: Props) { .post(`${process.env.REACT_APP_API}/files`, formData, { headers: { "Content-Type": "multipart/form-data", + Authorization: `Bearer ${token}`, }, onUploadProgress, }) .then((response) => { //go to next step - metadata - if (response.data.error) { + if (!response.data.error) { + setActiveStep(2); + setProcessed(true); + return; + } + if (response.data?.errorType !== "planError") { setProcessingError(response.data.error); console.debug("Dataset upload error", response.data.error); + return; + } + if (response.data?.processingMessage) { + setPlanDialog({ + open: true, + message: response.data.error, + tryAgain: "Try another dataset", + onTryAgain: tryAgain, + }); + setProcessingMessage(response.data?.processingMessage ?? ""); } else { - setActiveStep(2); - setProcessed(true); + setPlanDialog({ + open: true, + message: response.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + setProcessingMessage(response.data.error ?? ""); } }) .catch((error) => { @@ -342,6 +382,7 @@ function DatasetUploadSteps(props: Props) { loaded={loadedProgress} percentageLoaded={percentageLoadedProgress} estimatedUploadTime={estUploadTime} + processingMessage={processingMessage} tryAgain={tryAgain} /> ); diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx index 797b67680..4b5ca9dec 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx @@ -8,6 +8,7 @@ export interface ProcessingMetaDataProps { loaded: string; percentageLoaded: number; estimatedUploadTime: number; + processingMessage: string; tryAgain: () => void; } @@ -92,76 +93,79 @@ export default function Processing(props: ProcessingMetaDataProps) { display: flex; justify-content: center; align-items: center; - height: 100vh; + height: calc(100vh - 98px); flex-direction: column; `} > -
+

+ +

- Data is being processed... + {props.fileName}

- -
-

- {props.fileName} -

+ font-size: 12px; + color: #adb5bd; + margin-top: 0; + } + `} + >
-
-
-

{props.loaded}

-

- {getTimeInHoursnMins(props.estimatedUploadTime)} -

+ />
+

{props.loaded}

+

+ {getTimeInHoursnMins(props.estimatedUploadTime)} +

diff --git a/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx index 5607a0e4d..fe883a6dc 100644 --- a/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx @@ -20,6 +20,8 @@ import ColoredReportIcon from "app/assets/icons/ColoredReportIcon"; import DeleteDatasetDialog from "app/components/Dialogs/deleteDatasetDialog"; import DeleteReportDialog from "app/components/Dialogs/deleteReportDialog"; import { HomepageTable } from "../../Table"; +import { planDialogAtom } from "app/state/recoil/atoms"; +import { useSetRecoilState } from "recoil"; interface Props { sortBy: string; @@ -43,6 +45,8 @@ export default function AssetsGrid(props: Props) { const [enableButton, setEnableButton] = React.useState(false); const initialRender = React.useRef(true); + const setPlanDialog = useSetRecoilState(planDialogAtom); + const token = useStoreState((state) => state.AuthToken.value); const limit = 15; @@ -180,7 +184,23 @@ export default function AssetsGrid(props: Props) { Authorization: `Bearer ${token}`, }, }) - .then(() => { + .then((response) => { + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } + if (response.data.planWarning) { + setPlanDialog({ + open: true, + message: response.data.planWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } reloadData(); }) .catch((error) => console.log(error)); diff --git a/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx index 48cebd305..b1a4f51fa 100644 --- a/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx @@ -17,6 +17,8 @@ import { coloredEchartTypes } from "app/modules/chart-module/routes/chart-type/d import ChartAddnewCard from "app/modules/home-module/components/AssetCollection/Charts/chartAddNewCard"; import GridItem from "app/modules/home-module/components/AssetCollection/Charts/gridItem"; import { useAuth0 } from "@auth0/auth0-react"; +import { useSetRecoilState } from "recoil"; +import { planDialogAtom } from "app/state/recoil/atoms"; interface Props { sortBy: string; @@ -38,6 +40,8 @@ export default function ChartsGrid(props: Props) { const { isObserved } = useInfinityScroll(observerTarget); + const setPlanDialog = useSetRecoilState(planDialogAtom); + const charts = useStoreState( (state) => (state.charts.ChartGetList.crudData ?? []) as any[] ); @@ -150,7 +154,23 @@ export default function ChartsGrid(props: Props) { Authorization: `Bearer ${token}`, }, }) - .then(() => { + .then((response) => { + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } + if (response.data.planWarning) { + setPlanDialog({ + open: true, + message: response.data.planWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } reloadData(); }) .catch((error) => console.log(error)); diff --git a/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx index 22c71f855..0645e5c02 100644 --- a/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx @@ -4,7 +4,7 @@ import axios from "axios"; import get from "lodash/get"; import Box from "@material-ui/core/Box"; import Grid, { GridSize } from "@material-ui/core/Grid"; -import { useRecoilState } from "recoil"; +import { useRecoilState, useSetRecoilState } from "recoil"; import useDebounce from "react-use/lib/useDebounce"; /** project */ import { useInfinityScroll } from "app/hooks/useInfinityScroll"; @@ -14,7 +14,7 @@ import DeleteDatasetDialog from "app/components/Dialogs/deleteDatasetDialog"; import GridItem from "app/modules/home-module/components/AssetCollection/Datasets/gridItem"; import DatasetAddnewCard from "app/modules/home-module/components/AssetCollection/Datasets/datasetAddNewCard"; import CircleLoader from "app/modules/home-module/components/Loader"; -import { loadedDatasetsAtom } from "app/state/recoil/atoms"; +import { loadedDatasetsAtom, planDialogAtom } from "app/state/recoil/atoms"; import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; interface Props { @@ -40,6 +40,7 @@ export default function DatasetsGrid(props: Readonly) { const [offset, setOffset] = React.useState(0); const { isObserved } = useInfinityScroll(observerTarget); const token = useStoreState((state) => state.AuthToken.value); + const setPlanDialog = useSetRecoilState(planDialogAtom); const [loadedDatasets, setLoadedDatasets] = useRecoilState(loadedDatasetsAtom); @@ -146,7 +147,23 @@ export default function DatasetsGrid(props: Readonly) { Authorization: `Bearer ${token}`, }, }) - .then(() => { + .then((response) => { + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } + if (response.data.planWarning) { + setPlanDialog({ + open: true, + message: response.data.planWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } reloadData(); }) .catch((error) => console.log(error)); diff --git a/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx index f2ee83725..9b1880da6 100644 --- a/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx @@ -14,6 +14,8 @@ import ReportAddnewCard from "./reportAddNewCard"; import { useInfinityScroll } from "app/hooks/useInfinityScroll"; import CircleLoader from "../../Loader"; import { useAuth0 } from "@auth0/auth0-react"; +import { useSetRecoilState } from "recoil"; +import { planDialogAtom } from "app/state/recoil/atoms"; interface Props { sortBy: string; @@ -35,6 +37,8 @@ export default function ReportsGrid(props: Props) { const { isObserved } = useInfinityScroll(observerTarget); const token = useStoreState((state) => state.AuthToken.value); + const setPlanDialog = useSetRecoilState(planDialogAtom); + const reports = useStoreState( (state) => (state.reports.ReportGetList.crudData ?? []) as ReportModel[] ); @@ -144,7 +148,23 @@ export default function ReportsGrid(props: Props) { Authorization: `Bearer ${token}`, }, }) - .then(() => { + .then((response) => { + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } + if (response.data.planWarning) { + setPlanDialog({ + open: true, + message: response.data.planWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } reloadData(); }) .catch((error) => console.log(error)); diff --git a/src/app/modules/home-module/components/AssetCollection/index.tsx b/src/app/modules/home-module/components/AssetCollection/index.tsx index ec5eb41b0..962b55055 100644 --- a/src/app/modules/home-module/components/AssetCollection/index.tsx +++ b/src/app/modules/home-module/components/AssetCollection/index.tsx @@ -1,7 +1,7 @@ import React from "react"; /* third-party */ -import { Link } from "react-router-dom"; +import { Link, useHistory } from "react-router-dom"; import { useAuth0 } from "@auth0/auth0-react"; import { useRecoilState } from "recoil"; import Box from "@material-ui/core/Box"; @@ -27,6 +27,7 @@ import { datasetCategories } from "app/modules/dataset-module/routes/upload-modu import AssetsGrid from "app/modules/home-module/components/AssetCollection/All/assetsGrid"; import BreadCrumbs from "app/modules/home-module/components/Breadcrumbs"; import Filter from "app/modules/home-module/components/Filter"; +import { useCheckUserPlan } from "app/hooks/useCheckUserPlan"; function AssetsCollection() { const { isAuthenticated, user } = useAuth0(); @@ -38,6 +39,10 @@ function AssetsCollection() { const [display, setDisplay] = useRecoilState(homeDisplayAtom); const [tabPrevPosition, setTabPrevPosition] = React.useState(""); + const { handleClick } = useCheckUserPlan(); + + const history = useHistory(); + const handleChange = (newValue: "all" | "data" | "charts" | "reports") => { setDisplay(newValue); }; @@ -114,35 +119,45 @@ function AssetsCollection() { } `} > - + handleClick("dataset", () => + history.push( + `/dataset/new/upload${ + location.pathname === "/" ? "?fromHome=true" : "" + }` + ) + ) + } css={` background: #e492bd; `} data-cy="home-connect-dataset-button" > CONNECT DATASET - - +
diff --git a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx index 99eba847e..470ead09f 100644 --- a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx +++ b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx @@ -20,7 +20,7 @@ const Features = () => { options: [ { name: "Number of datasets or data size", - info: "The amount datasets you can manage", + info: "The amount of datasets you can manage", values: [ "5 datasets / 1GB", "100 datasets / 10GB", @@ -31,7 +31,7 @@ const Features = () => { { name: "Federated search", info: "Access to datasources like Worldbank, Kaggle, WHO, HDX and more.", - values: ["Max 10 results", "Unlimited", "Unlimited", "Unlimited"], + values: ["Max 12 results", "Unlimited", "Unlimited", "Unlimited"], }, { diff --git a/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx b/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx index e36b032b5..f2a330bc7 100644 --- a/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx +++ b/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx @@ -85,6 +85,7 @@ function PlanCard({ activeView, plan, onButtonClick }: PlanCardProps) { `} > per {activeView === "monthly" ? "month" : "year"} + {plan.key === "team" ? " / per user" : ""}

(null); + const setPlanDialog = useSetRecoilState(planDialogAtom); + const [anchorEl, setAnchorEl] = React.useState( null ); @@ -204,6 +206,14 @@ export function ReportSubheaderToolbar( }, }) .then((response) => { + if (response?.data.error && response?.data.errorType === "planError") { + return setPlanDialog({ + open: true, + message: response?.data.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } loadReports({ token, storeInCrudData: true, diff --git a/src/app/modules/report-module/index.tsx b/src/app/modules/report-module/index.tsx index 6e7ddeb00..c2733a3c8 100644 --- a/src/app/modules/report-module/index.tsx +++ b/src/app/modules/report-module/index.tsx @@ -3,7 +3,7 @@ import { v4 } from "uuid"; import get from "lodash/get"; import isEmpty from "lodash/isEmpty"; import { DndProvider } from "react-dnd"; -import { useRecoilState } from "recoil"; +import { useRecoilState, useSetRecoilState } from "recoil"; import { useAuth0 } from "@auth0/auth0-react"; import { HTML5Backend } from "react-dnd-html5-backend"; import { NoMatchPage } from "app/modules/common/no-match-page"; @@ -26,6 +26,7 @@ import { } from "react-router-dom"; import { persistedReportStateAtom, + planDialogAtom, reportRightPanelViewAtom, unSavedReportPreviewModeAtom, } from "app/state/recoil/atoms"; @@ -45,6 +46,8 @@ export default function ReportModule() { isAutoSaveEnabled: boolean; }>({ isAutoSaveEnabled: false }); + const setPlanDialog = useSetRecoilState(planDialogAtom); + /** static toolbar states */ const [plugins, setPlugins] = React.useState([]); /** end of static toolbar states */ @@ -127,6 +130,39 @@ export default function ReportModule() { get(state.reports.ReportGet.crudData, "error", "") === "Unauthorized" ); + const reportCreateData = useStoreState( + (state) => state.reports.ReportCreate.crudData as any + ); + + React.useEffect(() => { + if ( + reportCreateData?.error && + reportCreateData?.errorType === "planError" + ) { + setPlanDialog({ + open: true, + message: reportCreateData?.error, + tryAgain: "", + onTryAgain: () => {}, + }); + } + }, [reportCreateData]); + + const reportPlanWarning = useStoreState( + (state) => state.reports.ReportCreate.planWarning + ); + + React.useEffect(() => { + if (reportPlanWarning) { + setPlanDialog({ + open: true, + message: reportPlanWarning, + tryAgain: "", + onTryAgain: () => {}, + }); + } + }, [reportPlanWarning]); + const [headerDetails, setHeaderDetails] = React.useState({ title: "", description: EditorState.createEmpty(), diff --git a/src/app/state/api/index.ts b/src/app/state/api/index.ts index 4f1deb4af..068bfd30f 100644 --- a/src/app/state/api/index.ts +++ b/src/app/state/api/index.ts @@ -20,6 +20,7 @@ export const APIModel = ( }, crudData: null, errorData: null, + planWarning: null, onError: action((state, payload: Errors) => { state.loading = false; state.errorData = payload; @@ -103,6 +104,12 @@ export const APIModel = ( setCrudData: action((state, payload: any) => { state.crudData = payload; }), + setPlanWarning: action((state, payload: any) => { + state.planWarning = payload; + }), + clearPlanWarning: action((state) => { + state.planWarning = null; + }), clear: action((state) => { state.loading = false; state.success = false; @@ -112,6 +119,7 @@ export const APIModel = ( }; state.crudData = null; state.errorData = null; + state.planWarning = null; }), fetchWithEndpoint: thunk( async (actions, query: RequestValues) => { @@ -148,7 +156,12 @@ export const APIModel = ( }) .then( (resp: AxiosResponse) => { - if (resp.data) { + if (resp.data.data) { + actions.onSuccess({ ...resp.data.data, isUpdateCrudData: true }); + if (resp.data.planWarning) { + actions.setPlanWarning(resp.data.planWarning); + } + } else if (resp.data) { actions.onSuccess({ ...resp.data, isUpdateCrudData: true }); } }, diff --git a/src/app/state/api/interfaces/index.ts b/src/app/state/api/interfaces/index.ts index 3762d4a76..a08a4758a 100644 --- a/src/app/state/api/interfaces/index.ts +++ b/src/app/state/api/interfaces/index.ts @@ -110,6 +110,7 @@ export interface Errors { export interface ApiModel { loading: boolean; success: boolean; + planWarning: string | null; data: ResponseData | null | ResponseData[]; crudData: object | object[] | null; setData: Action, any>; @@ -117,6 +118,8 @@ export interface ApiModel { errorData: Errors | null; onError: Action, Errors>; setSuccess: Action>; + setPlanWarning: Action, string>; + clearPlanWarning: Action>; onSuccess: Action< ApiModel, ResponseData | ResponseData[] diff --git a/src/app/state/recoil/atoms/index.ts b/src/app/state/recoil/atoms/index.ts index 5b5186001..07d64eaab 100644 --- a/src/app/state/recoil/atoms/index.ts +++ b/src/app/state/recoil/atoms/index.ts @@ -196,3 +196,18 @@ export const dataUploadTabAtom = atom<"search" | "file">({ default: "search", effects_UNSTABLE: [persistAtom], }); + +export const planDialogAtom = atom<{ + open: boolean; + message: string; + tryAgain: string; + onTryAgain: () => void; +}>({ + key: "planDialogAtom", + default: { + open: false, + message: "", + tryAgain: "", + onTryAgain: () => {}, + }, +}); From aeff1d0dc2ec9b788626265e23dbaf2a3ad2d713 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Mon, 5 Aug 2024 22:32:11 +0100 Subject: [PATCH 11/58] style: responsiveness for contact page --- .../home-module/sub-modules/contact/index.tsx | 86 ++++++++++++------- .../home-module/sub-modules/partners/style.ts | 3 + 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/app/modules/home-module/sub-modules/contact/index.tsx b/src/app/modules/home-module/sub-modules/contact/index.tsx index 2beedf1bb..f985dc138 100644 --- a/src/app/modules/home-module/sub-modules/contact/index.tsx +++ b/src/app/modules/home-module/sub-modules/contact/index.tsx @@ -1,10 +1,10 @@ import React from "react"; import EmpowerBlock from "../partners/components/empowerBlock"; import { - Box, Container, Snackbar, TextField, + useMediaQuery, withStyles, } from "@material-ui/core"; import HomeFooter from "../../components/Footer"; @@ -17,15 +17,18 @@ import { FieldErrors } from "react-hook-form"; const CssTextField = withStyles({ root: { - "& .MuiFormControl-root": { - marginTop: "unset", + ["@media (max-width:938px)"]: { + marginTop: "unset !important", + "& label": { + fontSize: "12px", + }, }, }, })(TextField); export default function ContactModule() { useTitle("DX Dataxplorer - Contact"); - + const md = useMediaQuery("(max-width: 940px)"); const [openSnackbar, setOpenSnackbar] = React.useState(false); const [message, setMessage] = React.useState(""); const [loading, setLoading] = React.useState(false); @@ -129,6 +132,33 @@ export default function ContactModule() { margin-top: 56px; height: 100%; } + h4 { + font-family: "GothamNarrow-Bold", sans-serif; + font-size: 36px; + line-height: 43px; + color: #231d2c; + text-align: center; + @media (max-width: 640px) { + margin: 0; + margin-bottom: 20px; + } + } + p { + font-size: 20px; + line-height: 24px; + text-align: center; + font-family: "GothamNarrow-Medium", sans-serif; + margin-top: 0; + + /* width: 60%; */ + + @media (max-width: 600px) { + font-family: "GothamNarrow-Book", sans-serif; + font-size: 16px; + line-height: 19px; + width: auto; + } + } `} > +

Contact us!

+

+ Schedule a free demo now or ask us any data related
question + you may have. +

-

Contact us!

-

- Schedule a free demo now or ask us any data related question you - may have. -

- +
css` margin-top: ${view === "landing" ? "28px" : "50px"}; align-items: center; justify-content: center; + @media (max-width: 768px) { + gap: 20px; + } } #auth-buttons { button, From bb19ee6f7a3ad9885268ff63a550de4c358b1efb Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Wed, 7 Aug 2024 08:24:59 +0100 Subject: [PATCH 12/58] feat: DX-1509 - Implement state of Pricing Page when new user sign in --- .../chart-module/routes/chart-type/index.tsx | 19 ++- .../upload-module/component/uploadOption.tsx | 6 +- .../upload-steps/addDatasetFragment.tsx | 22 +-- .../pricing/components/plan-card.tsx | 9 +- .../home-module/sub-modules/pricing/index.tsx | 121 +++++++++-------- .../right-panel-create-view/index.tsx | 126 +++++++++++++++++- .../right-panel-create-view/style.ts | 5 +- 7 files changed, 229 insertions(+), 79 deletions(-) diff --git a/src/app/modules/chart-module/routes/chart-type/index.tsx b/src/app/modules/chart-module/routes/chart-type/index.tsx index 810e68b22..a69c60148 100644 --- a/src/app/modules/chart-module/routes/chart-type/index.tsx +++ b/src/app/modules/chart-module/routes/chart-type/index.tsx @@ -23,6 +23,7 @@ import { import { charts } from "app/modules/chart-module/data"; import AILoader from "app/modules/chart-module/routes/chart-type/loader"; import { handleValidityCheckOfDimensionsToBeMapped } from "app/modules/chart-module/components/toolbox/steps/panels-content/Mapping"; +import { useCheckUserPlan } from "app/hooks/useCheckUserPlan"; function ChartBuilderChartType(props: Readonly) { useTitle("DX Dataxplorer - Chart Type"); @@ -34,6 +35,8 @@ function ChartBuilderChartType(props: Readonly) { const [isAiActive, setIsAiActive] = useRecoilState(isChartAIAgentActive); const datasetId = useStoreState((state) => state.charts.dataset.value); const chartType = useStoreState((state) => state.charts.chartType.value); + + const { userPlan } = useCheckUserPlan(); const loadChartTypesSuggestions = useStoreActions( (actions) => actions.charts.ChartTypesSuggest.fetch ); @@ -88,6 +91,12 @@ function ChartBuilderChartType(props: Readonly) { } }, [datasetId]); + React.useEffect(() => { + if (userPlan?.planData.name === "Free") { + setIsAiActive(false); + } + }, [userPlan]); + React.useEffect(() => { if (fromReportParamValue === "true") { setChartFromReport((prev) => ({ @@ -269,6 +278,7 @@ function ChartBuilderChartType(props: Readonly) { checked={isAiActive} setIsAiActive={setIsAiActive} dataset={datasetId as string} + disabled={userPlan?.planData?.name === "Free"} />
@@ -444,6 +454,7 @@ function ChartBuilderChartType(props: Readonly) { ct.label === "" ? () => {} : onChartTypeChange(ct.id) } data-cy="chart-type-item" + disabled={userPlan?.planData?.name === "Free"} css={` position: relative; width: 100%; @@ -456,7 +467,9 @@ function ChartBuilderChartType(props: Readonly) { align-items: center; background: ${getColor(ct.id).background}; border: 1px solid ${getColor(ct.id).border}; - + filter: ${userPlan?.planData?.name === "Free" + ? "blur(5px)" + : "none"}; ${ct.label === "" && `pointer-events: none;background: #f1f3f5;`} @@ -581,6 +594,7 @@ function ChartBuilderChartType(props: Readonly) { ct.label === "" ? () => {} : onChartTypeChange(ct.id) } data-cy="chart-type-item" + disabled={userPlan?.planData?.name === "Free"} css={` position: relative; width: 100%; @@ -593,6 +607,9 @@ function ChartBuilderChartType(props: Readonly) { align-items: center; background: ${getColor(ct.id).background}; border: 1px solid ${getColor(ct.id).border}; + filter: ${userPlan?.planData?.name === "Free" + ? "blur(5px)" + : "none"}; ${ct.label === "" && `pointer-events: none;background: #f1f3f5;`} diff --git a/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx b/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx index 13144d62b..ee6ea9b48 100644 --- a/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx @@ -13,7 +13,7 @@ const UploadOption = (props: { connected?: boolean; onLogout?: () => void; canConnect?: boolean; - pro: boolean; + upgradeRequired: boolean; }) => { const [openSettings, setOpenSettings] = React.useState(false); @@ -36,7 +36,7 @@ const UploadOption = (props: { `} disabled={props.disabled} onClick={(e) => { - if (props.pro) { + if (props.upgradeRequired) { return history.push("/pricing"); } props.setActiveOption(props.name); @@ -89,7 +89,7 @@ const UploadOption = (props: {

- {props.pro ? ( + {props.upgradeRequired ? (
, onClick: () => {}, - pro: false, + upgradeRequired: false, }, { name: "Google Drive", @@ -87,7 +87,7 @@ export default function AddDatasetFragment(props: Props) { onLogout: () => { deleteGoogleDriveToken(); }, - pro: userPlan?.planData.name === "Free", + upgradeRequired: userPlan?.planData.name === "Free", }, { name: "Microsoft Cloud", @@ -103,7 +103,7 @@ export default function AddDatasetFragment(props: Props) { onLogout: async () => { await clearToken(); }, - pro: userPlan?.planData.name === "Free", + upgradeRequired: userPlan?.planData.name === "Free", }, { name: "API Connection", @@ -111,7 +111,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["CSV", "XSLX", "JSON", "ODS", "SQLite"], icon: , onClick: () => {}, - pro: false, + upgradeRequired: false, }, { name: "MSSQL", @@ -119,7 +119,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, - pro: false, + upgradeRequired: false, }, { name: "MYSQL", @@ -127,7 +127,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, - pro: false, + upgradeRequired: false, }, { name: "PostgreSQL", @@ -135,7 +135,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, - pro: false, + upgradeRequired: false, }, { name: "MongoDB", @@ -143,7 +143,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, - pro: false, + upgradeRequired: false, }, { name: "Hubspot", @@ -151,7 +151,7 @@ export default function AddDatasetFragment(props: Props) { formats: ["Coming Soon"], icon: , onClick: () => {}, - pro: false, + upgradeRequired: false, }, ]; @@ -239,7 +239,7 @@ export default function AddDatasetFragment(props: Props) { canConnect={option.canConnect} connected={option.connected} onLogout={option.onLogout} - pro={option.pro} + upgradeRequired={option.upgradeRequired} /> ))}
@@ -269,7 +269,7 @@ export default function AddDatasetFragment(props: Props) { onClick={option.onClick} disabled setActiveOption={props.setActiveOption} - pro={option.pro} + upgradeRequired={option.upgradeRequired} /> ))}
diff --git a/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx b/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx index f2a330bc7..48f119c42 100644 --- a/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx +++ b/src/app/modules/home-module/sub-modules/pricing/components/plan-card.tsx @@ -13,6 +13,7 @@ interface PlanCardProps { buttonText: string; discount: string; key: string; + available: boolean; }; onButtonClick: (key: string) => void; } @@ -155,10 +156,14 @@ function PlanCard({ activeView, plan, onButtonClick }: PlanCardProps) { cursor: not-allowed; } `} - disabled={plan.current} + disabled={plan.current || !plan.available} onClick={() => onButtonClick(plan.key)} > - {plan.current ? "Current Plan" : plan.buttonText} + {plan.current + ? "Current Plan" + : !plan.available + ? "Coming soon" + : plan.buttonText} {plan.recommended ? (
state.AuthToken.value); + const history = useHistory(); + const createNewStripeCustomer = async () => { const customerCreationResponse = await axios.post( `${process.env.REACT_APP_API}/stripe/new-customer`, @@ -99,6 +55,57 @@ export default function PricingModule() { return customerId; }; + const plans = [ + { + name: "Free Plan", + yearlyPrice: "Free forever", + monthlyPrice: "Free forever", + text: "For individuals or teams just getting started in Dataxplorer", + current: isAuthenticated ? true : false, + recommended: isAuthenticated ? false : true, + buttonText: "Activate", + discount: "", + key: "free", + available: true, + }, + { + name: "Pro", + yearlyPrice: "€720", + monthlyPrice: "€75", + text: "For individual users.", + current: false, + recommended: false, + buttonText: "Activate a free trial", + discount: "(Save 20%)", + key: "pro", + available: false, + }, + { + name: "Team", + yearlyPrice: "€576", + monthlyPrice: "€60", + text: "Scale up to 100 users and connect your team.", + current: false, + recommended: false, + buttonText: "Activate free trial", + discount: "(Save 20%)", + key: "team", + available: false, + }, + { + name: "Enterprise", + yearlyPrice: "Custom", + monthlyPrice: "Custom", + text: "For organisations looking scale into powerful data visualization, with full support and security", + current: false, + recommended: false, + buttonText: "Contact us", + discount: "", + key: "enterprise", + available: false, + }, + ]; + const createStripeCheckoutSession = async ( customerId: string, planName: string @@ -124,19 +131,17 @@ export default function PricingModule() { }; const handlePlanButtonClick = async (key: string) => { + if (!isAuthenticated) { + return history.replace( + `/onboarding/login?to=${location.pathname}${location.search}` + ); + } switch (key) { case plans[0].key: - if (isAuthenticated) { - const customerId = await createNewStripeCustomer(); - if (customerId) { - const sessionUrl = await createStripeCheckoutSession( - customerId, - key - ); - if (sessionUrl) window.location.href = sessionUrl; - } - } else { - // redirect to login page + const customerId = await createNewStripeCustomer(); + if (customerId) { + const sessionUrl = await createStripeCheckoutSession(customerId, key); + if (sessionUrl) window.location.href = sessionUrl; } break; case plans[1].key: diff --git a/src/app/modules/report-module/components/right-panel-create-view/index.tsx b/src/app/modules/report-module/components/right-panel-create-view/index.tsx index 4a8090ae0..9ba437807 100644 --- a/src/app/modules/report-module/components/right-panel-create-view/index.tsx +++ b/src/app/modules/report-module/components/right-panel-create-view/index.tsx @@ -59,6 +59,7 @@ import { useSearchMediaSources } from "app/hooks/useSearchMediaSources"; import { useDebounce } from "react-use"; import Skeleton from "@material-ui/lab/Skeleton"; import { useInfinityScroll } from "app/hooks/useInfinityScroll"; +import { useCheckUserPlan } from "app/hooks/useCheckUserPlan"; interface IHeaderDetails { title: string; @@ -181,6 +182,107 @@ const imageSources = [ // { value: "shutterstock", label: "Shutterstock" }, ]; +const UpgradeCard = (props: { onClose: () => void }) => { + const history = useHistory(); + + return ( +
+

+ Enhance Your Reports with Multimedia! +

+

+ Currently, adding videos and images to reports is a feature exclusive to + our premium plans. Upgrade now to bring your data to life with engaging + visuals and make your reports more impactful. +

+ +
+

+ Not Now +

+ + +
+
+ ); +}; + export function ReportRightPanelCreateView(props: Readonly) { const [currentView, setCurrentView] = useRecoilState( reportRightPanelViewAtom @@ -195,6 +297,10 @@ export function ReportRightPanelCreateView(props: Readonly) { const whiteBackgroundNotRounded = whiteBackgroundOnly + " border-radius: 0px 0px 0px 0px"; + const { userPlan } = useCheckUserPlan(); + + const [open, setOpen] = useState(true); + const [elementItemDetails, setElementItemDetails] = React.useState([ { elementType: ReportElementsType.HEADER, @@ -293,6 +399,7 @@ export function ReportRightPanelCreateView(props: Readonly) { height: 100%; flex-direction: column; box-shadow: 0px 0px 10px 0px rgba(152, 161, 170, 0.6); + position: relative; `} >
) { `} >
+ {open && + currentView === "media" && + userPlan?.planData?.name === "Free" ? ( + setOpen(false)} /> + ) : null} {currentView === "elements" && ( @@ -448,6 +560,11 @@ export function ReportRightPanelCreateView(props: Readonly) { key={item.elementType} {...item} disabled={false} + upgradeRequired={ + (item.elementType === ReportElementsType.IMAGE || + item.elementType === ReportElementsType.VIDEO) && + userPlan?.planData?.name === "Free" + } ItemDetails={mediaItemDetails} setItemDetails={setMediaItemDetails} index={index} @@ -830,6 +947,7 @@ function ElementItem(props: { index?: number; description: string; draggable?: boolean; + upgradeRequired?: boolean; }) { const nullRef = React.useRef(null); @@ -951,9 +1069,13 @@ function ElementItem(props: { props.disabled as boolean, isDragging, props.draggable, - dropDown + dropDown, + props.upgradeRequired )} - onClick={() => setDropDown((prev) => !prev)} + onClick={() => { + if (props.disabled || props.upgradeRequired) return; + setDropDown((prev) => !prev); + }} > {props.leftIcon}
diff --git a/src/app/modules/report-module/components/right-panel-create-view/style.ts b/src/app/modules/report-module/components/right-panel-create-view/style.ts index 5e54e8096..afbf40c18 100644 --- a/src/app/modules/report-module/components/right-panel-create-view/style.ts +++ b/src/app/modules/report-module/components/right-panel-create-view/style.ts @@ -4,7 +4,8 @@ export const elementItemcss = ( disabled: boolean, isDragging: boolean, draggable?: boolean, - dropDown?: boolean + dropDown?: boolean, + upgradeRequired?: boolean ) => css` cursor: ${disabled ? "not-allowed" : !draggable ? "pointer" : "grab"}; ${isDragging && "cursor: grabbing;"} @@ -16,7 +17,7 @@ export const elementItemcss = ( background: #dfe3e5; border-radius: 8px; /* transform: translate(0, 0); */ - opacity: ${disabled ? 0.5 : 1}; + opacity: ${upgradeRequired ? 0.2 : disabled ? 0.5 : 1}; position: relative; padding: 0 8px 0 16px; From 2e0ba3e5893cd2c74b5390b3a36c2835a7e62a0b Mon Sep 17 00:00:00 2001 From: okorie2 Date: Thu, 8 Aug 2024 19:41:11 +0100 Subject: [PATCH 13/58] style; responsiveness for app header & why dx page --- src/app/components/AppBar/index.tsx | 404 +++++++++++------- .../why-dx/components/keyFeaturesBlock.tsx | 179 +++++--- .../why-dx/components/tryUsBlock.tsx | 67 ++- .../home-module/sub-modules/why-dx/index.tsx | 5 +- .../home-module/sub-modules/why-dx/style.ts | 94 +++- 5 files changed, 525 insertions(+), 224 deletions(-) diff --git a/src/app/components/AppBar/index.tsx b/src/app/components/AppBar/index.tsx index 1bfc40d40..dc53e90f2 100644 --- a/src/app/components/AppBar/index.tsx +++ b/src/app/components/AppBar/index.tsx @@ -1,56 +1,207 @@ import React from "react"; -import get from "lodash/get"; import Grid from "@material-ui/core/Grid"; import { useAuth0 } from "@auth0/auth0-react"; import Popover from "@material-ui/core/Popover"; import Toolbar from "@material-ui/core/Toolbar"; import MUIAppBar from "@material-ui/core/AppBar"; import Container from "@material-ui/core/Container"; -import IconButton from "@material-ui/core/IconButton"; import useMediaQuery from "@material-ui/core/useMediaQuery"; -import IconChevronLeft from "@material-ui/icons/ChevronLeft"; -import { MobileAppbarSearch } from "app/components/Mobile/AppBarSearch"; +import CloseIcon from "@material-ui/icons/CloseOutlined"; import { NavLink, useLocation, useHistory, Link } from "react-router-dom"; import { headercss, logocss, navLinkcss } from "app/components/AppBar/style"; import { isChartAIAgentActive } from "app/state/recoil/atoms"; import { useRecoilState } from "recoil"; +import MenuIcon from "@material-ui/icons/Menu"; -const TextHeader = (label: string) => ( -

- {label} -

-); +const NavList = (props: { + navLocation: string; + setIsNavExpanded?: React.Dispatch>; +}) => { + const list = [ + { name: "Explore", path: "/", cy: "nav-explore", class: "" }, + { + name: "Why Dataxplorer", + path: "/why-dataxplorer", + cy: "nav-why", + class: "why-dataxplorer", + }, + { + name: "About", + path: "/about", + cy: "nav-about", + }, + { + name: "Partners", + path: "/partners", + cy: "nav-partners", + class: "partners", + }, + { name: "Pricing", path: "/pricing", cy: "nav-pricing", class: "pricing" }, + { name: "Contact", path: "/contact", cy: "nav-contact", class: "contact" }, + ]; + const handleNavigation = () => { + props.setIsNavExpanded?.(false); + }; + return ( + <> + {list.map((item) => ( +
+ + {item.name} + +
+ ))} + + ); +}; -function MobileHeader() { +function MobileHeader(props: { navLocation: string }) { const history = useHistory(); - + const { user, isAuthenticated } = useAuth0(); + const [isNavExpanded, setIsNavExpanded] = React.useState(false); + const handleNavExpand = () => { + setIsNavExpanded(!isNavExpanded); + }; return ( - history.goBack()} +
- - - +
+
+ + + logo + +
+
+ {isAuthenticated ? ( + + ) : ( + + Log in + + )} +
+
+
+ +
+
); } export function AppBar() { const location = useLocation(); - const isMobile = useMediaQuery("(max-width: 767px)"); + const isMobile = useMediaQuery("(max-width: 846px)"); const [openSearch, setOpenSearch] = React.useState(false); const [anchorEl, setAnchorEl] = React.useState(null); - const navLocation = location.pathname.split("/").join(""); function handleClick(event: React.MouseEvent) { @@ -61,22 +212,6 @@ export function AppBar() { setAnchorEl(null); } - function getMobilePageHeader() { - switch (location.pathname) { - case "/about": - return "About"; - case "/datasets": - return ( - - {TextHeader("Explore")} - - - ); - default: - return ; - } - } - React.useEffect(() => { if (anchorEl) { handleClose(); @@ -86,118 +221,89 @@ export function AppBar() { } }, [location.pathname]); - if (location.pathname === "/" && isMobile) { - return ; - } - return ( - - + {isMobile && } + {!isMobile && ( + + + { + + + + + logo + + + + {" "} + + + + + } - } - `} - > - {isMobile && getMobilePageHeader()} - {!isMobile && ( - - - - - logo - - - - {" "} -
- - Explore - -
-
- - Why Dataxplorer? - -
-
- - About - -
-
- - Partners - -
-
- - Pricing - -
-
- - Contact - -
- -
-
-
- )} -
-
+
+
+ )} + ); } diff --git a/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx b/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx index 4c7ff4831..90e3be927 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx +++ b/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx @@ -1,61 +1,48 @@ import React from "react"; -import Grid from "@material-ui/core/Grid"; +import Grid, { GridSpacing } from "@material-ui/core/Grid"; import { ReactComponent as AIPoweredImg } from "app/modules/home-module/assets/whydx-ai-powered-illustration.svg"; import { ReactComponent as CharVizImg } from "app/modules/home-module/assets/whydx-chartviz-illustration.svg"; import { ReactComponent as OpenSourceImg } from "app/modules/home-module/assets/whydx-opensource-illustration.svg"; import { ReactComponent as ReportsImg } from "app/modules/home-module/assets/whydx-reports-illustration.svg"; import { ReactComponent as SearchImg } from "app/modules/home-module/assets/whydx-search-illustration.svg"; +import { keyfeaturescss } from "../style"; +import { useMediaQuery } from "@material-ui/core"; export default function KeyFeaturesBlock() { + const isTablet = useMediaQuery("(max-width:1024px)"); + const isMobile = useMediaQuery("(max-width:600px)"); + + let spacing: GridSpacing = 9; + if (isTablet) { + spacing = 6; + } + if (isMobile) { + spacing = 2; + } return ( -
-

- Unlock the Power of Data with Dataxplorer -

+
+

Unlock the Power of Data with Dataxplorer

- + - -
+ +

All-in-One Stack

Dataxplorer consolidates all your data management needs into a @@ -72,11 +59,32 @@ export default function KeyFeaturesBlock() {

- - -
+ + +

Connect Data with Ease

Dataxplorer simplifies the complex task of data integration, @@ -88,7 +96,7 @@ export default function KeyFeaturesBlock() {

- + - - + + - -
+ +

Visualize Your Impact

Your data is a valuable resource, and Dataxplorer empowers you to @@ -126,11 +155,29 @@ export default function KeyFeaturesBlock() {

- - -
+ + +

Interactive Reports

Transform your data-driven insights into engaging narratives that @@ -143,25 +190,43 @@ export default function KeyFeaturesBlock() {

- +
- - + + - -
+ +

Join The Data Revolution

Become a pioneer in the realm of data-driven decision-making. diff --git a/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx b/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx index 4c523ebe9..b39d21c9e 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx +++ b/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx @@ -21,6 +21,14 @@ export default function TryUsBlock() { margin-bottom: 34px; margin-top: 0; color: #231d2c; + @media (max-width: 1200px) { + font-size: 36px; + line-height: normal; + } + @media (max-width: 600px) { + font-size: 24px; + line-height: normal; + } `} > Best decisions are based on data @@ -36,29 +44,50 @@ export default function TryUsBlock() { align-items: center; height: 215px; width: 100%; - `} - > -

-

- Try Dataxplorer for free -

{" "} -

- Dataxplorer turns data into impact  -

+ } + } + @media (max-width: 900px) { + padding: 58px 43px 45px 45px; + } + @media (max-width: 774px) { + padding: 32px 32px; + flex-direction: column; + align-items: flex-start; + gap: 20px; + height: 296px; + + p { + margin: 0; + &:nth-of-type(1) { + font-size: 31px; + font-family: "GothamNarrow-Bold", sans-serif; + line-height: normal; + } + &:nth-of-type(2) { + font-size: 18px; + font-family: "GothamNarrow-Book", sans-serif; + line-height: normal; + margin-top: 8px; + } + } + } + `} + > +
+

Try Dataxplorer for free

{" "} +

Dataxplorer turns data into impact 

{isAuthenticated && (
- {/* */}
diff --git a/src/app/modules/home-module/sub-modules/why-dx/style.ts b/src/app/modules/home-module/sub-modules/why-dx/style.ts index 73665a146..df4f31a2f 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/style.ts +++ b/src/app/modules/home-module/sub-modules/why-dx/style.ts @@ -24,12 +24,104 @@ export const benefitscss = css` p { font-size: 20px; line-height: 24px; - /* width: 90%; */ font-family: "GothamNarrow-Medium", sans-serif; margin-top: 14px; } `; +export const keyfeaturescss = { + container: css` + position: relative; + z-index: 1; + padding-top: 114px; + + svg { + @media (max-width: 1200px) { + flex-direction: column; + width: 100%; + height: 100%; + margin: unset; + } + } + h3 { + font-size: 48px; + line-height: 43px; + text-align: center; + color: #000000; + margin-top: 0; + margin-bottom: 83px; + font-family: "GothamNarrow-Bold", sans-serif; + @media (max-width: 1200px) { + font-size: 36px; + line-height: normal; + } + @media (max-width: 600px) { + font-size: 24px; + line-height: normal; + margin-bottom: 48px; + } + } + p:nth-of-type(1) { + font-size: 36px; + line-height: 20px; + font-weight: 350; + font-family: "GothamNarrow-Medium", sans-serif; + margin-bottom: 25px; + margin-top: 0; + color: #231d2c; + @media (max-width: 600px) { + font-size: 24px; + line-height: normal; + text-align: center; + } + } + p:nth-of-type(2) { + font-family: "GothamNarrow-Medium", sans-serif; + font-weight: 350; + line-height: 30px; + letter-spacing: 0.5px; + font-size: 20px; + color: #231d2c; + @media (max-width: 600px) { + font-size: 14px; + line-height: normal; + text-align: center; + } + } + @media (min-width: 750px) { + @media (max-width: 1024px) { + padding-top: 40px; + } + } + @media (max-width: 600px) { + padding-top: 56px; + } + `, + flexContainer: css``, + text: css` + @media (min-width: 1111px) { + @media (max-width: 1279px) { + width: 91%; + } + } + @media (max-width: 1110px) { + width: 75%; + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + margin: auto; + } + @media (max-width: 600px) { + width: 100%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + `, +}; + export const firstColcss = css` display: grid; grid-template-rows: 42.45% 55.5%; From 4d3954059c45312221eaee43a33b50edea6b8f0d Mon Sep 17 00:00:00 2001 From: okorie2 Date: Sat, 10 Aug 2024 06:55:36 +0100 Subject: [PATCH 14/58] style: responsiveness for about page --- package.json | 2 +- src/app/components/Styled/button.ts | 1 + .../components/Footer/MobileFooter.tsx | 9 + .../home-module/sub-modules/about/index.tsx | 334 +++++++++++++++--- .../home-module/sub-modules/about/style.ts | 51 ++- .../why-dx/components/tryUsBlock.tsx | 4 +- yarn.lock | 31 +- 7 files changed, 374 insertions(+), 58 deletions(-) diff --git a/package.json b/package.json index 3b2bb4ca9..ba5e02211 100644 --- a/package.json +++ b/package.json @@ -67,10 +67,10 @@ "react-hook-form": "^7.43.9", "react-indexed-db": "^1.0.12", "react-range": "1.4.7", + "react-responsive-carousel": "^3.2.23", "react-router-dom": "^5.2.0", "react-router-hash-link": "^2.4.3", "react-scripts": "^5.0.0", - "react-swipeable-views": "^0.14.0", "react-swipeable-views-utils": "^0.14.0", "react-toastify": "^7.0.4", "react-tooltip": "^5.27.1", diff --git a/src/app/components/Styled/button.ts b/src/app/components/Styled/button.ts index 8dfcf0e6d..dcc193642 100644 --- a/src/app/components/Styled/button.ts +++ b/src/app/components/Styled/button.ts @@ -38,6 +38,7 @@ export const HomePrimaryButton = styled.button` font-weight: 700; font-size: 14px; text-transform: uppercase; + white-space: nowrap; background: ${(props) => (props.color ? props.color : "inherit")}; :hover { opacity: 0.8; diff --git a/src/app/modules/home-module/components/Footer/MobileFooter.tsx b/src/app/modules/home-module/components/Footer/MobileFooter.tsx index 5d1298502..51d0322f1 100644 --- a/src/app/modules/home-module/components/Footer/MobileFooter.tsx +++ b/src/app/modules/home-module/components/Footer/MobileFooter.tsx @@ -7,6 +7,11 @@ import moment from "moment"; export default function MobileFooter() { return ( <> +
diff --git a/src/app/modules/home-module/sub-modules/about/index.tsx b/src/app/modules/home-module/sub-modules/about/index.tsx index 8d5ead0d2..7b88ee0dd 100644 --- a/src/app/modules/home-module/sub-modules/about/index.tsx +++ b/src/app/modules/home-module/sub-modules/about/index.tsx @@ -5,7 +5,8 @@ import { ReactComponent as MissionImg } from "app/modules/home-module/assets/abo import { ReactComponent as DXImg } from "app/modules/home-module/assets/about-dx.svg"; import { ReactComponent as StoryImg } from "app/modules/home-module/assets/about-story.svg"; import Ellipses from "app/modules/home-module/assets/about-page-ellipses.svg"; - +import "react-responsive-carousel/lib/styles/carousel.min.css"; +import { Carousel } from "react-responsive-carousel"; import HomeFooter from "../../components/Footer"; import { subParagraphcss } from "./style"; import { useTitle } from "react-use"; @@ -30,22 +31,21 @@ import EmptyAvi from "app/modules/home-module/assets/team/empty.png"; export default function AboutModule() { useTitle("DX Dataxplorer - About"); const { isAuthenticated } = useAuth0(); - const features = [ { title: "+100.000", subtitle: "Datasets available", - text: "Access over 100.000 datasets to\n create reports and charts. Create\n impact with data from 3rd parties\n built in Dataxplorer or connect\n your in-house datasources.", + text: "Access over 100.000 datasets to create reports and charts. Create impact with data from 3rd parties built in Dataxplorer or connect your in-house datasources.", }, { title: "+15 Visuals", subtitle: "Chart type provided", - text: "Dataxplorer offers over 15\n different chart types for you to\n work with. Based on the open\n sources Apache E-charts library\n you are able to create rich graphs.", + text: "Dataxplorer offers over 15 different chart types for you to work with. Based on the open sources Apache E-charts library you are able to create rich graphs.", }, { title: "+3", subtitle: "Languages are supported", - text: "Dataxplorer caters to a global\n clientele, ensuring seamless data\n integration and communication.\n We will offer Dataxplorer in 3\n different languages.", + text: "Dataxplorer caters to a global clientele, ensuring seamless data integration and communication. We will offer Dataxplorer in 3 different languages.", }, ]; @@ -94,7 +94,7 @@ export default function AboutModule() { }, { img: SamuelAvi, - name: "Okechukwu Samuel Owhondah", + name: "Okechukwu Samuel \n Owhondah", role: "Frontend Developer", linkedIn: "https://ng.linkedin.com/in/okorie-emmanuella-350916173", }, @@ -112,6 +112,90 @@ export default function AboutModule() { }, ]; + const teamCarousel = team.map((member) => ( +
+ {member.name} +

+ {member.name} +

+

+ {member.role} +

+
+ )); + const futureTeam = Array.from({ length: 1 }).map((_, index) => ( +
+ {"Empty"} + + Join Our Team + +
+ )); + const allTeamCarousel = [...teamCarousel, ...futureTeam]; + return (
- +

@@ -165,7 +272,10 @@ export default function AboutModule() { font-style: normal; font-weight: 350; line-height: normal; - font-family: "GothamNarrow-Medium"; + font-family: "GothamNarrow-Medium", sans-serif; + @media (max-width: 1024px) { + font-family: "GothamNarrow-Book", sans-serif; + } `} > With 20+ years combined experience in data and global health @@ -181,6 +291,9 @@ export default function AboutModule() {
{isAuthenticated && ( @@ -188,6 +301,13 @@ export default function AboutModule() { css={` display: flex; column-gap: 20px; + @media (max-width: 425px) { + flex-direction: column; + gap: 10px; + button { + width: 51%; + } + } `} > button { gap: 10px; color: #fff; @@ -232,7 +357,7 @@ export default function AboutModule() { font-size: 14px; text-transform: uppercase; text-decoration: none; - + white-space: nowrap; :hover { opacity: 0.8; cursor: pointer; @@ -241,6 +366,9 @@ export default function AboutModule() { > svg { transform: scale(0.8); } + @media (max-width: 600px) { + gap: 3px; + } } `} > @@ -258,6 +386,16 @@ export default function AboutModule() {
@@ -275,12 +413,38 @@ export default function AboutModule() {
- {features.map((feature) => ( -
+ {features.map((feature, index) => ( +

{feature.title} @@ -300,9 +465,10 @@ export default function AboutModule() { font-family: "GothamNarrow-Bold"; font-style: normal; font-weight: 400; - line-height: 130%; /* 31.2px */ + line-height: 130%; margin: 0; color: #fff; + margin-left: 16.3%; `} > {feature.subtitle} @@ -310,10 +476,10 @@ export default function AboutModule() {

{feature.text} @@ -359,13 +525,70 @@ export default function AboutModule() { dashboards.

+
+ + {allTeamCarousel} + +
{team.map((member) => ( @@ -389,6 +612,7 @@ export default function AboutModule() { font-weight: 400; line-height: normal; color: #504e4e; + white-space: pre-line; `} > {member.name} @@ -446,28 +670,42 @@ export default function AboutModule() {
))}

- +
-
+
+

+ Mission +

-

+

Mission

- -

+

+

Our mission is to create lasting impact for organizations that bring positive change to our world by helping them to unlock the power of data. Our trusted and easy-to-use data solutions boost @@ -476,17 +714,28 @@ export default function AboutModule() {

- -
-
+
+
div:nth-of-type(1) { + display: flex; + flex-direction: column-reverse; + } + } + `} + > +
-

+

Dataxplorer

@@ -506,6 +755,9 @@ export default function AboutModule() {
+

+ Dataxplorer +

diff --git a/src/app/modules/home-module/sub-modules/about/style.ts b/src/app/modules/home-module/sub-modules/about/style.ts index 36f2684a2..6312f554f 100644 --- a/src/app/modules/home-module/sub-modules/about/style.ts +++ b/src/app/modules/home-module/sub-modules/about/style.ts @@ -2,13 +2,46 @@ import { css } from "styled-components/macro"; export const subParagraphcss = css` color: #231d2c; - h3 { + > div:nth-of-type(1) { + display: flex; + column-gap: 97px; + align-items: start; + @media (max-width: 1024px) { + flex-direction: column; + align-items: center; + justify-content: center; + text-align: center; + } + } + #ab-mobile { margin: 0; font-size: 36px; font-style: normal; font-weight: 350; line-height: normal; font-family: "GothamNarrow-Medium", sans-serif; + display: none; + @media (max-width: 1024px) { + display: block; + margin: 37px; + } + @media (max-width: 500px) { + display: block; + margin: 0px; + margin-bottom: 32px; + } + } + #ab-desktop { + margin: 0; + font-size: 36px; + font-style: normal; + font-weight: 350; + line-height: normal; + font-family: "GothamNarrow-Medium", sans-serif; + display: block; + @media (max-width: 1024px) { + display: none; + } } p { margin: 0; @@ -18,5 +51,21 @@ export const subParagraphcss = css` font-weight: 350; line-height: 30px; /* 150% */ letter-spacing: 0.5px; + @media (max-width: 1024px) { + font-size: 24px; + font-family: "GothamNarrow-Book", sans-serif; + line-height: 28.5px; /* 150% */ + } + @media (max-width: 500px) { + font-size: 14px; + font-family: "GothamNarrow-Book", sans-serif; + line-height: 16.8px; /* 150% */ + } + } + svg { + @media (max-width: 1024px) { + width: 100%; + height: 100%; + } } `; diff --git a/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx b/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx index b39d21c9e..7092dfb2e 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx +++ b/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx @@ -146,10 +146,10 @@ export default function TryUsBlock() { `} > -

CREATE REPORT

+ CREATE REPORT -

Contact sales

+ Contact sales
)} diff --git a/yarn.lock b/yarn.lock index e907553c8..0f8f5d368 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4001,7 +4001,7 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz" integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA== -classnames@^2.3.0: +classnames@^2.2.5, classnames@^2.3.0: version "2.5.1" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b" integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow== @@ -10293,7 +10293,7 @@ prop-types-extra@^1.1.0: react-is "^16.3.2" warning "^4.0.0" -prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -10554,6 +10554,13 @@ react-dropzone@^14.2.3: file-selector "^0.6.0" prop-types "^15.8.1" +react-easy-swipe@^0.0.21: + version "0.0.21" + resolved "https://registry.yarnpkg.com/react-easy-swipe/-/react-easy-swipe-0.0.21.tgz#ce9384d576f7a8529dc2ca377c1bf03920bac8eb" + integrity sha512-OeR2jAxdoqUMHIn/nS9fgreI5hSpgGoL5ezdal4+oO7YSSgJR8ga+PkYGJrSrJ9MKlPcQjMQXnketrD7WNmNsg== + dependencies: + prop-types "^15.5.8" + react-error-boundary@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-4.0.10.tgz#975cc298e93ab7760d1460b7ea5a7855621e355a" @@ -10643,6 +10650,15 @@ react-refresh@^0.11.0: resolved "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz" integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A== +react-responsive-carousel@^3.2.23: + version "3.2.23" + resolved "https://registry.yarnpkg.com/react-responsive-carousel/-/react-responsive-carousel-3.2.23.tgz#4c0016ff54603e604bb5c1f9e7ef2d1eda133f1d" + integrity sha512-pqJLsBaKHWJhw/ItODgbVoziR2z4lpcJg+YwmRlSk4rKH32VE633mAtZZ9kDXjy4wFO+pgUZmDKPsPe1fPmHCg== + dependencies: + classnames "^2.2.5" + prop-types "^15.5.8" + react-easy-swipe "^0.0.21" + react-router-dom@^5.2.0: version "5.3.0" resolved "https://registry.npmjs.org/react-router-dom/-/react-router-dom-5.3.0.tgz" @@ -10754,17 +10770,6 @@ react-swipeable-views-utils@^0.14.0: react-swipeable-views-core "^0.14.0" shallow-equal "^1.2.1" -react-swipeable-views@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/react-swipeable-views/-/react-swipeable-views-0.14.0.tgz#149c0df3d92220cc89e3f6d5c04a78dfe46f9b54" - integrity sha512-wrTT6bi2nC3JbmyNAsPXffUXLn0DVT9SbbcFr36gKpbaCgEp7rX/OFxsu5hPc/NBsUhHyoSRGvwqJNNrWTwCww== - dependencies: - "@babel/runtime" "7.0.0" - prop-types "^15.5.4" - react-swipeable-views-core "^0.14.0" - react-swipeable-views-utils "^0.14.0" - warning "^4.0.1" - react-toastify@^7.0.4: version "7.0.4" resolved "https://registry.npmjs.org/react-toastify/-/react-toastify-7.0.4.tgz" From 62115345cfb3b5a6ff488ed602ff3d58a1b72862 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Sat, 10 Aug 2024 06:58:36 +0100 Subject: [PATCH 15/58] chore: reinstall package --- package.json | 1 + yarn.lock | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index ba5e02211..8c3cbe550 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "react-router-dom": "^5.2.0", "react-router-hash-link": "^2.4.3", "react-scripts": "^5.0.0", + "react-swipeable-views": "^0.14.0", "react-swipeable-views-utils": "^0.14.0", "react-toastify": "^7.0.4", "react-tooltip": "^5.27.1", diff --git a/yarn.lock b/yarn.lock index 0f8f5d368..6c0bd4e08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10293,7 +10293,7 @@ prop-types-extra@^1.1.0: react-is "^16.3.2" warning "^4.0.0" -prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: +prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz" integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== @@ -10770,6 +10770,17 @@ react-swipeable-views-utils@^0.14.0: react-swipeable-views-core "^0.14.0" shallow-equal "^1.2.1" +react-swipeable-views@^0.14.0: + version "0.14.0" + resolved "https://registry.yarnpkg.com/react-swipeable-views/-/react-swipeable-views-0.14.0.tgz#149c0df3d92220cc89e3f6d5c04a78dfe46f9b54" + integrity sha512-wrTT6bi2nC3JbmyNAsPXffUXLn0DVT9SbbcFr36gKpbaCgEp7rX/OFxsu5hPc/NBsUhHyoSRGvwqJNNrWTwCww== + dependencies: + "@babel/runtime" "7.0.0" + prop-types "^15.5.4" + react-swipeable-views-core "^0.14.0" + react-swipeable-views-utils "^0.14.0" + warning "^4.0.1" + react-toastify@^7.0.4: version "7.0.4" resolved "https://registry.npmjs.org/react-toastify/-/react-toastify-7.0.4.tgz" From 2403efbc341f11a95b7706a6908814918a981699 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Mon, 12 Aug 2024 09:27:51 +0100 Subject: [PATCH 16/58] chore: refactor code --- .../EmbedChartDialog/chartContainer.tsx | 2 - .../Dialogs/EmbedChartDialog/index.tsx | 5 - .../components/common-chart/index.tsx | 220 ++++++------------ src/app/modules/chart-module/data.ts | 3 +- src/app/modules/chart-module/index.tsx | 14 -- .../chart-module/routes/chart-type/data.tsx | 32 ++- .../chart-module/routes/chart-type/index.tsx | 3 +- .../chart-module/routes/customize/data.ts | 1 - .../chart-module/routes/customize/index.tsx | 1 - .../chart-module/routes/filters/data.ts | 1 - .../chart-module/routes/filters/index.tsx | 1 - .../chart-module/routes/mapping/data.tsx | 1 - .../chart-module/routes/mapping/index.tsx | 1 - .../chart-module/routes/preview-theme/data.ts | 1 - .../routes/preview-theme/index.tsx | 125 +++------- .../modules/embed-module/embedChart/index.tsx | 5 - .../components/chart-wrapper/index.tsx | 5 - .../api/action-reducers/sync/charts/index.tsx | 27 ++- 18 files changed, 145 insertions(+), 303 deletions(-) diff --git a/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx b/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx index 21ff8ee0c..80936b477 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx @@ -13,7 +13,6 @@ export default function ChartContainer(props: { visualOptions: any; withHeader?: boolean; renderedChart: string; - renderedChartSsr: boolean; renderedChartMappedData: any; setRawViz?: React.Dispatch; setVisualOptions: (value: any) => void; @@ -96,7 +95,6 @@ export default function ChartContainer(props: { containerRef={props.containerRef} renderedChart={props.renderedChart} visualOptions={props.visualOptions} - renderedChartSsr={props.renderedChartSsr} setVisualOptions={props.setVisualOptions} renderedChartType={props.renderedChartType} renderedChartMappedData={props.renderedChartMappedData} diff --git a/src/app/components/Dialogs/EmbedChartDialog/index.tsx b/src/app/components/Dialogs/EmbedChartDialog/index.tsx index a6d9481a1..b4e4ea4ec 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/index.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/index.tsx @@ -71,10 +71,6 @@ export default function EmbedChartDialog(props: { return get(chartFromAPI, "mappedData", []); }, [chartFromAPI]); - const renderedChartSsr = React.useMemo(() => { - return get(chartFromAPI, "ssr", false); - }, [chartFromAPI]); - const renderedChartType = React.useMemo(() => { return get(chartFromAPI, "vizType", "echartsBarchart"); }, [chartFromAPI]); @@ -188,7 +184,6 @@ export default function EmbedChartDialog(props: { datasetDetails={datasetDetails} renderedChart={renderedChart} renderedChartMappedData={renderedChartMappedData} - renderedChartSsr={renderedChartSsr} renderedChartType={renderedChartType} setChartError={setNotFound} setNotFound={setNotFound} diff --git a/src/app/modules/chart-module/components/common-chart/index.tsx b/src/app/modules/chart-module/components/common-chart/index.tsx index b3d471fbd..1c850350a 100644 --- a/src/app/modules/chart-module/components/common-chart/index.tsx +++ b/src/app/modules/chart-module/components/common-chart/index.tsx @@ -33,7 +33,6 @@ interface Props { visualOptions: any; withHeader?: boolean; renderedChart: string; - renderedChartSsr: boolean; renderedChartMappedData: any; setRawViz?: React.Dispatch; setVisualOptions: (value: any) => void; @@ -79,6 +78,14 @@ export function CommonChart(props: Readonly) { .getElementById(`datasource-${props.chartId || "1"}`) ?.getBoundingClientRect().height; + let content; + let contentHeight; + if (!props.chartPreviewInReport && props.renderedChartType !== "bigNumber") { + contentHeight = props.visualOptions?.height - 28 + "px"; + } else { + contentHeight = "auto"; + } + React.useEffect(() => { if (token) { loadDataset({ @@ -107,34 +114,6 @@ export function CommonChart(props: Readonly) { } }, []); - // server side rendering - React.useEffect(() => { - if (props.renderedChartSsr && domRef && domRef.current) { - try { - while (domRef.current.firstChild) { - domRef.current.removeChild(domRef.current.firstChild); - } - } catch (e) {} - try { - const element = document.createElement("div"); - element.innerHTML = props.renderedChart.trim(); - const newRawViz = domRef.current.appendChild( - chartType === "bigNumber" - ? element.children[0].children[0].children[0] - : element.firstChild || element - ); - props.setRawViz && props.setRawViz(newRawViz); - } catch (e) { - while (domRef.current.firstChild) { - domRef.current.removeChild(domRef.current.firstChild); - } - if (process.env.NODE_ENV === "development") { - console.log("chart error", e); - } - } - } - }, [props.renderedChart]); - // client side rendering React.useEffect(() => { const visualOptions = props.containerRef.current @@ -147,13 +126,7 @@ export function CommonChart(props: Readonly) { : props.visualOptions.height, } : props.visualOptions; - if ( - !props.renderedChartSsr && - domRef && - domRef.current && - chartType && - props.containerRef.current - ) { + if (domRef && domRef.current && chartType && props.containerRef.current) { try { render( props.renderedChartMappedData, @@ -200,82 +173,34 @@ export function CommonChart(props: Readonly) { } } } - }, [ - chartType, - props.visualOptions, - props.renderedChartSsr, - props.renderedChartMappedData, - ]); - let content; - let contentHeight; - if (!props.chartPreviewInReport && props.renderedChartType !== "bigNumber") { - contentHeight = props.visualOptions?.height - 28 + "px"; - } else { - contentHeight = "auto"; - } + }, [chartType, props.visualOptions, props.renderedChartMappedData]); - if (props.renderedChartSsr) { - content = ( + content = ( +
-1 && - ` - > div { - width: 135px; - } - `} - ${chartType === "bigNumber" && - props.inChartWrapper && - ` - > div { - ::nth-child(1) { - font-size: 10px !important; - } - } - `} + width: auto !important; + height: calc(100% - ${dataSourcePHeight ?? 0}px); - * { - font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif !important; - } - `} - /> - ); - } else { - content = ( -
-
div:first-of-type { - ${props.renderedChartType === "bigNumber" && - props.inChartWrapper && - ` + > div:first-of-type { + ${props.renderedChartType === "bigNumber" && + props.inChartWrapper && + ` div:nth-child(1) { font-size: 12px !important; padding-bottom: 6px !important; @@ -309,58 +234,57 @@ export function CommonChart(props: Readonly) { } `} - > svg { - height: calc(100% - ${dataSourcePHeight ?? 0}px); + > svg { + height: calc(100% - ${dataSourcePHeight ?? 0}px); - > rect { - height: calc(100% - ${dataSourcePHeight ?? 0}px); - } + > rect { + height: calc(100% - ${dataSourcePHeight ?? 0}px); } } - `} - /> + } + `} + /> -

+ Source:{" "} + + {props.datasetDetails?.source ?? datasetDetails.source} - Data file:{" "} + {filename} + +

+ {chartType === "echartsGeomap" && props.visualOptions?.showLegend ? ( +
- Source:{" "} - - {props.datasetDetails?.source ?? datasetDetails.source} - Data file:{" "} - {filename} - -

- {chartType === "echartsGeomap" && props.visualOptions?.showLegend ? ( -
- -
- ) : null} -
- ); - } + +
+ ) : null} +
+ ); return ( <> diff --git a/src/app/modules/chart-module/data.ts b/src/app/modules/chart-module/data.ts index d2a9611ac..479475e85 100644 --- a/src/app/modules/chart-module/data.ts +++ b/src/app/modules/chart-module/data.ts @@ -24,6 +24,7 @@ import { // @ts-ignore } from "@rawgraphs/rawgraphs-charts"; import { FilterGroupModel } from "app/components/ToolBoxPanel/components/filters/data"; +import { IChartType } from "app/state/api/action-reducers/sync/charts"; export const charts = { echartsBarchart, @@ -350,7 +351,7 @@ export const defaultChartOptions = { export interface ChartAPIModel { id: string; name: string; - vizType: string | null; + vizType: IChartType | null; datasetId: string | null; mapping: any; vizOptions: any; diff --git a/src/app/modules/chart-module/index.tsx b/src/app/modules/chart-module/index.tsx index 5c5ad8cf9..f5bf720f1 100644 --- a/src/app/modules/chart-module/index.tsx +++ b/src/app/modules/chart-module/index.tsx @@ -387,15 +387,6 @@ export default function ChartModule() { return get(chartFromAPI, "mappedData", []); }, [chartFromAPI]); - const renderedChartSsr = React.useMemo(() => { - return get(chartFromAPI, "ssr", false); - }, [chartFromAPI]); - - const activeRenderedChartSsr = React.useMemo( - () => Boolean(renderedChartSsr), - [renderedChartSsr] - ); - function setVisualOptionsOnChange(chartType: string | null = null) { const options = { ...getOptionsConfig( @@ -589,7 +580,6 @@ export default function ChartModule() { renderedChart={content} visualOptions={visualOptions} setVisualOptions={setVisualOptions} - renderedChartSsr={activeRenderedChartSsr} renderedChartMappedData={renderedChartMappedData} renderedChartType={chartType as ChartType} setChartErrorMessage={setChartErrorMessage} @@ -609,7 +599,6 @@ export default function ChartModule() { visualOptions={visualOptions} containerRef={containerRef} setVisualOptions={setVisualOptions} - renderedChartSsr={activeRenderedChartSsr} renderedChartMappedData={renderedChartMappedData} renderedChartType={chartType as ChartType} setChartErrorMessage={setChartErrorMessage} @@ -628,7 +617,6 @@ export default function ChartModule() { dimensions={dimensions} renderedChart={content} containerRef={containerRef} - renderedChartSsr={activeRenderedChartSsr} renderedChartMappedData={renderedChartMappedData} renderedChartType={chartType as ChartType} setChartErrorMessage={setChartErrorMessage} @@ -675,7 +663,6 @@ export default function ChartModule() { visualOptions={visualOptions} renderedChart={renderedChart} setVisualOptions={setVisualOptions} - renderedChartSsr={renderedChartSsr} renderedChartMappedData={renderedChartMappedData} editable={!isPreviewMode || (page === "new" && !view)} setIsPreviewView={setIsPreviewView} @@ -695,7 +682,6 @@ export default function ChartModule() { visualOptions={visualOptions} renderedChart={renderedChart} setVisualOptions={setVisualOptions} - renderedChartSsr={renderedChartSsr} renderedChartMappedData={renderedChartMappedData} editable={!isPreviewMode} setIsPreviewView={setIsPreviewView} diff --git a/src/app/modules/chart-module/routes/chart-type/data.tsx b/src/app/modules/chart-module/routes/chart-type/data.tsx index d0fbabbbd..f38ac1d0e 100644 --- a/src/app/modules/chart-module/routes/chart-type/data.tsx +++ b/src/app/modules/chart-module/routes/chart-type/data.tsx @@ -72,6 +72,7 @@ import { ReactComponent as ScatterChartPreviewImg } from "app/modules/chart-modu import { ReactComponent as GraphGlPreviewImg } from "app/modules/chart-module/assets/graphglPreview.svg"; import { ReactComponent as AreatimeaxisPreviewImg } from "app/modules/chart-module/assets/areastackedPreview.svg"; import { ChartRenderedItem } from "app/modules/chart-module/data"; +import { IChartType } from "app/state/api/action-reducers/sync/charts"; export interface ChartBuilderChartTypeProps { loading: boolean; @@ -85,7 +86,7 @@ export interface ChartBuilderChartTypeProps { } export interface ChartTypeModel { - id: string; + id: IChartType; label: string; icon: React.ReactNode; categories: string[]; @@ -113,8 +114,18 @@ export const chartTypesFromMiddleWare = { areatimeaxis: "echartsAreatimeaxis", scatterchart: "echartsScatterchart", }; +interface IEchartTypes { + id: IChartType; + label: string; + icon: React.ReactNode; + preview: React.ReactNode; + categories: string[]; + class: string; + ssr: boolean; + description: string; +} -export const echartTypes = (big: boolean) => { +export const echartTypes = (big: boolean): IEchartTypes[] => { return [ { id: "echartsBarchart", @@ -345,23 +356,6 @@ export const echartTypes = (big: boolean) => { description: "Network graphs illustrate relationships between nodes in a network. Nodes are represented as points, and connections between nodes are depicted as lines", }, - - { - id: "placeholder9", - label: "", - icon: <>, - categories: [], - ssr: false, - description: "", - }, - { - id: "placeholder10", - label: "", - icon: <>, - categories: [], - ssr: false, - description: "", - }, ]; }; diff --git a/src/app/modules/chart-module/routes/chart-type/index.tsx b/src/app/modules/chart-module/routes/chart-type/index.tsx index 810e68b22..863df459d 100644 --- a/src/app/modules/chart-module/routes/chart-type/index.tsx +++ b/src/app/modules/chart-module/routes/chart-type/index.tsx @@ -23,6 +23,7 @@ import { import { charts } from "app/modules/chart-module/data"; import AILoader from "app/modules/chart-module/routes/chart-type/loader"; import { handleValidityCheckOfDimensionsToBeMapped } from "app/modules/chart-module/components/toolbox/steps/panels-content/Mapping"; +import { IChartType } from "app/state/api/action-reducers/sync/charts"; function ChartBuilderChartType(props: Readonly) { useTitle("DX Dataxplorer - Chart Type"); @@ -180,7 +181,7 @@ function ChartBuilderChartType(props: Readonly) { } const onChartTypeChange = - (chartTypeId: string) => (e: React.MouseEvent) => { + (chartTypeId: IChartType) => (e: React.MouseEvent) => { sessionStorage.setItem("visualOptions", JSON.stringify({})); props.setVisualOptionsOnChange( chartType === chartTypeId ? null : chartTypeId diff --git a/src/app/modules/chart-module/routes/customize/data.ts b/src/app/modules/chart-module/routes/customize/data.ts index 4cf2f7147..36f95a357 100644 --- a/src/app/modules/chart-module/routes/customize/data.ts +++ b/src/app/modules/chart-module/routes/customize/data.ts @@ -6,7 +6,6 @@ export interface ChartBuilderCustomizeProps { mappedData: any[]; visualOptions: any; renderedChart: string; - renderedChartSsr: boolean; renderedChartMappedData: any; setVisualOptions: (value: any) => void; setChartErrorMessage: React.Dispatch>; diff --git a/src/app/modules/chart-module/routes/customize/index.tsx b/src/app/modules/chart-module/routes/customize/index.tsx index 3d5327044..904693d6f 100644 --- a/src/app/modules/chart-module/routes/customize/index.tsx +++ b/src/app/modules/chart-module/routes/customize/index.tsx @@ -42,7 +42,6 @@ function ChartBuilderCustomize(props: Readonly) { renderedChart={props.renderedChart} visualOptions={props.visualOptions} setVisualOptions={props.setVisualOptions} - renderedChartSsr={props.renderedChartSsr} renderedChartMappedData={props.renderedChartMappedData} setChartErrorMessage={props.setChartErrorMessage} setChartError={props.setChartError} diff --git a/src/app/modules/chart-module/routes/filters/data.ts b/src/app/modules/chart-module/routes/filters/data.ts index ac8558336..1219944a4 100644 --- a/src/app/modules/chart-module/routes/filters/data.ts +++ b/src/app/modules/chart-module/routes/filters/data.ts @@ -5,7 +5,6 @@ export interface ChartBuilderFiltersProps { dimensions: any[]; visualOptions: any; renderedChart: string; - renderedChartSsr: boolean; renderedChartMappedData: any; setVisualOptions: (value: any) => void; setChartErrorMessage: React.Dispatch>; diff --git a/src/app/modules/chart-module/routes/filters/index.tsx b/src/app/modules/chart-module/routes/filters/index.tsx index 25aae325d..182919dad 100644 --- a/src/app/modules/chart-module/routes/filters/index.tsx +++ b/src/app/modules/chart-module/routes/filters/index.tsx @@ -42,7 +42,6 @@ function ChartBuilderFilters(props: Readonly) { renderedChart={props.renderedChart} visualOptions={props.visualOptions} setVisualOptions={props.setVisualOptions} - renderedChartSsr={props.renderedChartSsr} renderedChartMappedData={props.renderedChartMappedData} setChartErrorMessage={props.setChartErrorMessage} setChartError={props.setChartError} diff --git a/src/app/modules/chart-module/routes/mapping/data.tsx b/src/app/modules/chart-module/routes/mapping/data.tsx index 28f5d14f6..ad948a211 100644 --- a/src/app/modules/chart-module/routes/mapping/data.tsx +++ b/src/app/modules/chart-module/routes/mapping/data.tsx @@ -5,7 +5,6 @@ export interface ChartBuilderMappingProps { dimensions: any[]; visualOptions: any; renderedChart: string; - renderedChartSsr: boolean; renderedChartMappedData: any; setChartError: React.Dispatch>; setChartErrorMessage: React.Dispatch>; diff --git a/src/app/modules/chart-module/routes/mapping/index.tsx b/src/app/modules/chart-module/routes/mapping/index.tsx index 1af6fb9ab..f05b8a300 100644 --- a/src/app/modules/chart-module/routes/mapping/index.tsx +++ b/src/app/modules/chart-module/routes/mapping/index.tsx @@ -95,7 +95,6 @@ function ChartBuilderMapping(props: Readonly) { renderedChart={props.renderedChart} visualOptions={props.visualOptions} setVisualOptions={props.setVisualOptions} - renderedChartSsr={props.renderedChartSsr} renderedChartMappedData={props.renderedChartMappedData} setChartErrorMessage={props.setChartErrorMessage} setChartError={props.setChartError} diff --git a/src/app/modules/chart-module/routes/preview-theme/data.ts b/src/app/modules/chart-module/routes/preview-theme/data.ts index b77ed1f18..8756631b1 100644 --- a/src/app/modules/chart-module/routes/preview-theme/data.ts +++ b/src/app/modules/chart-module/routes/preview-theme/data.ts @@ -5,7 +5,6 @@ export interface ChartBuilderPreviewThemeProps { loading: boolean; visualOptions: any; renderedChart: string; - renderedChartSsr: boolean; renderedChartMappedData: any; setVisualOptions: (value: any) => void; setIsPreviewView: React.Dispatch>; diff --git a/src/app/modules/chart-module/routes/preview-theme/index.tsx b/src/app/modules/chart-module/routes/preview-theme/index.tsx index bb7a37011..ba10e7c9e 100644 --- a/src/app/modules/chart-module/routes/preview-theme/index.tsx +++ b/src/app/modules/chart-module/routes/preview-theme/index.tsx @@ -3,10 +3,10 @@ import React from "react"; import get from "lodash/get"; import isEmpty from "lodash/isEmpty"; import useTitle from "react-use/lib/useTitle"; -import { useStoreActions, useStoreState } from "app/state/store/hooks"; import { useHistory, useParams } from "react-router-dom"; -/* project */ import Skeleton from "@material-ui/lab/Skeleton"; +/* project */ +import { useStoreActions, useStoreState } from "app/state/store/hooks"; import { useDataThemesEchart } from "app/hooks/useDataThemesEchart"; import { styles as commonStyles } from "app/modules/chart-module/routes/common/styles"; import { ChartBuilderPreviewThemeProps } from "app/modules/chart-module/routes/preview-theme/data"; @@ -16,29 +16,20 @@ import GeomapLegend from "app/modules/chart-module/components/geomap-legend"; import ErrorComponent from "app/modules/chart-module/components/dialog/errrorComponent"; import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; import { getDatasetDetailsSource } from "app/modules/chart-module/util/getDatasetDetailsSource"; -import { ChartAPIModel } from "app/modules/chart-module/data"; export function ChartBuilderPreviewTheme(props: ChartBuilderPreviewThemeProps) { useTitle("DX Dataxplorer - Preview Chart"); + const { visualOptions } = props; const token = useStoreState((state) => state.AuthToken.value); - const domRef = React.useRef(null); - const { page } = useParams<{ page: string; view: string }>(); const dataset = useStoreState((state) => state.charts.dataset.value); const history = useHistory(); const { render } = useDataThemesEchart(); - - const { visualOptions } = props; - const mapping = useStoreState((state) => state.charts.mapping.value); const selectedChartType = useStoreState( (state) => state.charts.chartType.value ); - const editChartCrudData = useStoreState( - (state) => state.charts.ChartUpdate.crudData - ) as ChartAPIModel; - const loadDataset = useStoreActions( (actions) => actions.dataThemes.DatasetGet.fetch ); @@ -80,92 +71,52 @@ export function ChartBuilderPreviewTheme(props: ChartBuilderPreviewThemeProps) { !isEmpty(visualOptions) ) { const loader = document.getElementById("chart-placeholder"); - + if (loader) { + loader.style.display = "flex"; + } try { - new Promise((resolve, reject) => { - try { - if (loader) { - loader.style.display = "flex"; - } - if (props.renderedChartSsr) { - const element = document.createElement("div"); - element.innerHTML = props.renderedChart.trim(); - if (domRef.current?.firstChild) { - while (domRef.current.firstChild) { - domRef.current.removeChild(domRef.current.firstChild); - } - } - // @ts-ignore - domRef.current.appendChild( - selectedChartType === "bigNumber" - ? element.children[0].children[0].children[0] - : element.firstChild || element - ); - } else { - render( - props.renderedChartMappedData, - // @ts-ignore - domRef.current, - selectedChartType || "echartsBarchart", - visualOptions, - mapping, - "common-chart-render-container" - ); - } - resolve(1); - } catch (e) { - if (process.env.NODE_ENV === "development") { - console.log("chart error", e); - } - - if (loader) { - loader.style.display = "none"; - } - reject(0); - } - }) - .then(() => { - if (loader) { - loader.style.display = "none"; - } - }) - .catch(() => { - if (loader) { - loader.style.display = "none"; - } - }); - } catch (e) { if (loader) { loader.style.display = "none"; } - - while (domRef.current.firstChild) { - domRef.current.removeChild(domRef.current.firstChild); - } + render( + props.renderedChartMappedData, + // @ts-ignore + domRef.current, + selectedChartType ?? "echartsBarchart", + visualOptions, + mapping, + "common-chart-render-container" + ); + } catch (e) { if (process.env.NODE_ENV === "development") { console.log("chart error", e); } + + if (loader) { + loader.style.display = "none"; + } } } }, [ mapping, visualOptions, props.renderedChart, - props.renderedChartSsr, props.renderedChartMappedData, ]); - const handleVizClick = () => { - if (page === "new" || props.editable) { - history.push(`/chart/${page}/customize`); - } - }; React.useEffect(() => { props.setIsPreviewView(true); return () => { props.setIsPreviewView(false); }; }, []); + + const handleVizClick = () => { + if (page === "new" || props.editable) { + history.push(`/chart/${page}/customize`); + } + }; + if (props.dataError || props.chartError) { return ( <> @@ -179,12 +130,6 @@ export function ChartBuilderPreviewTheme(props: ChartBuilderPreviewThemeProps) { ); } - const isMappingValid = React.useMemo(() => { - return ( - editChartCrudData?.isMappingValid && props.loadedChart?.isMappingValid - ); - }, [props.loadedChart?.isMappingValid, editChartCrudData?.isMappingValid]); - return (
{!props.isMappingValid ? ( @@ -248,22 +193,16 @@ export function ChartBuilderPreviewTheme(props: ChartBuilderPreviewThemeProps) { onClick={handleVizClick} id="common-chart-render-container" css={` - ${props.renderedChartSsr - ? `overflow-x: auto;` - : `height: ${get(visualOptions, "height", 500)}px;`} + height: ${get(visualOptions, "height", 500)}px; ${selectedChartType === "bigNumber" && window.location.pathname.indexOf("/chart/") > -1 && ` - - - > div { - width: 135px; - } + > div { + width: 135px; + } `} - - - * { + * { font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif !important; } diff --git a/src/app/modules/embed-module/embedChart/index.tsx b/src/app/modules/embed-module/embedChart/index.tsx index e595a5147..04892ab70 100644 --- a/src/app/modules/embed-module/embedChart/index.tsx +++ b/src/app/modules/embed-module/embedChart/index.tsx @@ -56,10 +56,6 @@ export default function EmbedChartRoute() { return get(chartFromAPI, "mappedData", []); }, [chartFromAPI]); - const renderedChartSsr = React.useMemo(() => { - return get(chartFromAPI, "ssr", false); - }, [chartFromAPI]); - const renderedChartType = React.useMemo(() => { return get(chartFromAPI, "vizType", "echartsBarchart"); }, [chartFromAPI]); @@ -112,7 +108,6 @@ export default function EmbedChartRoute() { datasetDetails={datasetDetails} renderedChart={renderedChart} renderedChartMappedData={renderedChartMappedData} - renderedChartSsr={renderedChartSsr} renderedChartType={renderedChartType} setChartError={setNotFound} setNotFound={setNotFound} diff --git a/src/app/modules/report-module/components/chart-wrapper/index.tsx b/src/app/modules/report-module/components/chart-wrapper/index.tsx index 11197beb3..db3ef3d2e 100644 --- a/src/app/modules/report-module/components/chart-wrapper/index.tsx +++ b/src/app/modules/report-module/components/chart-wrapper/index.tsx @@ -66,10 +66,6 @@ export function ReportChartWrapper(props: Props) { return get(chartFromAPI, "mappedData", []); }, [chartFromAPI]); - const renderedChartSsr = React.useMemo(() => { - return get(chartFromAPI, "ssr", false); - }, [chartFromAPI]); - const renderedChartType = React.useMemo(() => { return get(chartFromAPI, "vizType", "echartsBarchart"); }, [chartFromAPI]); @@ -235,7 +231,6 @@ export function ReportChartWrapper(props: Props) { containerRef={containerRef} renderedChart={renderedChart} visualOptions={visualOptions} - renderedChartSsr={renderedChartSsr} setVisualOptions={setVisualOptions} renderedChartType={renderedChartType} renderedChartMappedData={renderedChartMappedData} diff --git a/src/app/state/api/action-reducers/sync/charts/index.tsx b/src/app/state/api/action-reducers/sync/charts/index.tsx index 8322a0ced..eff549713 100644 --- a/src/app/state/api/action-reducers/sync/charts/index.tsx +++ b/src/app/state/api/action-reducers/sync/charts/index.tsx @@ -118,14 +118,35 @@ export const ChartsMappingState: ChartsMappingStateModel = { }), }; +export type IChartType = + | "echartsBarchart" + | "echartsGeomap" + | "echartsLinechart" + | "echartsAreatimeaxis" + | "echartsAreastack" + | "echartsSankey" + | "echartsTreemap" + | "bigNumber" + | "echartsSunburst" + | "echartsForcegraph" + | "echartsCirculargraph" + | "echartsPiechart" + | "echartsBubblechart" + | "echartsMultisetBarchart" + | "echartsStackedBarchart" + | "echartsScatterchart" + | "echartsHeatmap" + | "echartsGraphgl" + | "echartsRadarchart" + | "echartsCirclepacking"; export interface ChartsChartTypeStateModel { - value: string | null; - setValue: Action; + value: IChartType | null; + setValue: Action; reset: Action; } export const ChartsChartTypeState: ChartsChartTypeStateModel = { value: null, - setValue: action((state, payload: string | null) => { + setValue: action((state, payload: IChartType | null) => { state.value = payload; }), reset: action((state) => { From f445b7ce3f4a2fd1a988ea1ccca16b0ef6df4ae9 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Wed, 14 Aug 2024 18:06:06 +0100 Subject: [PATCH 17/58] feat: DX-1693 - Dataset Listing Name start with Z-A, must be A-Z --- .../components/AssetCollection/Charts/chartsGrid.tsx | 6 +++--- .../components/AssetCollection/Datasets/datasetsGrid.tsx | 4 +++- .../components/AssetCollection/Reports/reportsGrid.tsx | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx index b08539b4f..fbe685fa3 100644 --- a/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Charts/chartsGrid.tsx @@ -63,9 +63,9 @@ export default function ChartsGrid(props: Props) { props.searchStr?.length > 0 ? `"where":{"name":{"like":"${props.searchStr}.*","options":"i"}},` : ""; - return `filter={${value}"order":"${ - props.sortBy - } desc","limit":${limit},"offset":${fromZeroOffset ? 0 : offset}}`; + return `filter={${value}"order":"${props.sortBy} ${ + props.sortBy === "name" ? "asc" : "desc" + }","limit":${limit},"offset":${fromZeroOffset ? 0 : offset}}`; }; const getWhereString = () => { diff --git a/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx index 60220d87c..8667383e3 100644 --- a/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Datasets/datasetsGrid.tsx @@ -72,7 +72,9 @@ export default function DatasetsGrid(props: Readonly) { return `${props.userOnly ? "userOnly=true&" : ""}filter={${value}"order":"${ props.sortBy - } desc","limit":${limit},"offset":${fromZeroOffset ? 0 : offset}}`; + } ${props.sortBy === "name" ? "asc" : "desc"}","limit":${limit},"offset":${ + fromZeroOffset ? 0 : offset + }}`; }; const getWhereString = () => { diff --git a/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx index b8a1f273e..70360fccd 100644 --- a/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Reports/reportsGrid.tsx @@ -57,9 +57,9 @@ export default function ReportsGrid(props: Props) { props.searchStr?.length > 0 ? `"where":{"name":{"like":"${props.searchStr}.*","options":"i"}},` : ""; - return `filter={${value}"order":"${ - props.sortBy - } desc","limit":${limit},"offset":${fromZeroOffset ? 0 : offset}}`; + return `filter={${value}"order":"${props.sortBy} ${ + props.sortBy === "name" ? "asc" : "desc" + }","limit":${limit},"offset":${fromZeroOffset ? 0 : offset}}`; }; const getWhereString = () => { From 85293d695ffd36bfcf992ffdab92fd07aba23c03 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Wed, 14 Aug 2024 21:10:18 +0100 Subject: [PATCH 18/58] style: responsiveness for web pages --- src/app/components/AppBar/index.tsx | 23 +- .../assets/about-page-ellipses-mobile.svg | 76 +++++ .../home-module/assets/ellipses-mobile.svg | 58 ++++ .../assets/whydx-ellipses-mobile.svg | 126 ++++++++ .../assets/whydx-ellipses-tablet.svg | 292 ++++++++++++++++++ .../home-module/sub-modules/about/index.tsx | 14 +- .../partners/components/bestDecisionBlock.tsx | 38 ++- .../partners/components/empowerBlock.tsx | 53 +++- .../partners/components/ourPartnersBlock.tsx | 13 + .../partners/components/tabCard.tsx | 55 +++- .../sub-modules/partners/index.tsx | 75 ++++- .../home-module/sub-modules/partners/style.ts | 63 +++- .../home-module/sub-modules/why-dx/index.tsx | 15 +- .../sub-module/rowStructure/index.tsx | 1 - 14 files changed, 860 insertions(+), 42 deletions(-) create mode 100644 src/app/modules/home-module/assets/about-page-ellipses-mobile.svg create mode 100644 src/app/modules/home-module/assets/ellipses-mobile.svg create mode 100644 src/app/modules/home-module/assets/whydx-ellipses-mobile.svg create mode 100644 src/app/modules/home-module/assets/whydx-ellipses-tablet.svg diff --git a/src/app/components/AppBar/index.tsx b/src/app/components/AppBar/index.tsx index dc53e90f2..9355c2ea8 100644 --- a/src/app/components/AppBar/index.tsx +++ b/src/app/components/AppBar/index.tsx @@ -29,6 +29,7 @@ const NavList = (props: { name: "About", path: "/about", cy: "nav-about", + class: "about", }, { name: "Partners", @@ -41,6 +42,7 @@ const NavList = (props: { ]; const handleNavigation = () => { props.setIsNavExpanded?.(false); + document.body.style.overflow = "auto"; }; return ( <> @@ -64,6 +66,11 @@ function MobileHeader(props: { navLocation: string }) { const { user, isAuthenticated } = useAuth0(); const [isNavExpanded, setIsNavExpanded] = React.useState(false); const handleNavExpand = () => { + if (!isNavExpanded) { + document.body.style.overflow = "hidden"; + } else { + document.body.style.overflow = "auto"; + } setIsNavExpanded(!isNavExpanded); }; return ( @@ -74,7 +81,7 @@ function MobileHeader(props: { navLocation: string }) { overflow: ${isNavExpanded ? "auto" : "hidden"}; padding: 0px 16px 16px 16px; width: 100%; - background: ${isNavExpanded ? "#F2F7FD" : "transparent"}; + background: ${isNavExpanded ? "#F2F7FD" : "#fff"}; transition: all cubic-bezier(0.4, 0, 0.2, 1) 0.3s; position: fixed; top: 0; @@ -96,7 +103,7 @@ function MobileHeader(props: { navLocation: string }) { gap: 5px; align-items: center; height: 100%; - width: 100%; + /* width: 100%; */ `} >
-
+
{isAuthenticated ? (
)} + + ); } diff --git a/src/app/modules/home-module/sub-modules/partners/components/ourPartnersBlock.tsx b/src/app/modules/home-module/sub-modules/partners/components/ourPartnersBlock.tsx index da256ad1f..2da08fb7c 100644 --- a/src/app/modules/home-module/sub-modules/partners/components/ourPartnersBlock.tsx +++ b/src/app/modules/home-module/sub-modules/partners/components/ourPartnersBlock.tsx @@ -17,6 +17,15 @@ export default function OurPartnersBlock() { height: 78px; object-fit: contain; } + @media (max-width: 1024px) { + gap: 30px; + } + @media (max-width: 818px) { + flex-direction: column; + gap: 2px; + padding-top: 56px; + border-bottom: none; + } `} >

Our partners diff --git a/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx b/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx index 91a6653eb..2ce0c70ad 100644 --- a/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx +++ b/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx @@ -18,8 +18,6 @@ function TabCard(props: { css={` position: relative; z-index: 1; - background: linear-gradient(180deg, #a4a0ff -61.62%, #f8fcfc 114.5%); - border-radius: 29px; width: 100%; display: flex; justify-content: center; @@ -27,6 +25,7 @@ function TabCard(props: { font-family: "GothamNarrow-Bold", sans-serif; padding: 72px 40px 100px 88px; color: #231d2c; + overflow-x: hidden; a { text-decoration: none; @@ -54,18 +53,62 @@ function TabCard(props: { white-space: pre-line; font-weight: 400; line-height: 19px; + color: #231d2c; + font-size: 16px; } - @media (max-width: 768px) { + @media (max-width: 1179px) { flex-direction: column; align-items: center; justify-content: center; + height: 644px; + gap: 22px; + padding: unset; + div:nth-child(1) { + width: auto; + } + @media (max-width: 761px) { + height: 100%; + padding-top: 40px; + h4 { + font-size: 20px; + line-height: 24px; + } + p { + font-size: 16px; + line-height: 19.2px; + } + div:nth-child(1) { + img { + width: 100%; + height: 100%; + } + } + } } `} >
{props.alt}
-
+

{props.title}

@@ -79,7 +122,7 @@ function TabCard(props: { export const AboutTabCard = () => { const description = ( -
+

The Global Fund's Data Explorer is one of the key transparency tools of the organization.
@@ -95,7 +138,7 @@ export const AboutTabCard = () => { > Visit the Global Fund Data Explorer -

+

); return ( ({ fontSize: "24px", fontWeight: 700, fontFamily: "Inter, sans-serif", - "@media (max-width: 768px)": { + "@media (max-width: 1024px)": { fontSize: "16px", }, }, @@ -45,7 +44,7 @@ const StyledTab = withStyles(() => ({ fontSize: "24px", fontWeight: 700, fontFamily: "Inter, sans-serif", - "@media (max-width: 768px)": { + "@media (max-width: 1024px)": { fontSize: "16px", }, }, @@ -60,7 +59,10 @@ const StyledTabs = withStyles({ "& .MuiTabs-flexContainer": { gap: "113px", "@media (max-width: 768px)": { - gap: "40px", + gap: "36px", + }, + "@media (max-width: 390px)": { + gap: "18px", }, }, }, @@ -80,11 +82,15 @@ const Pagination = (props: { justify-content: center; align-items: center; position: absolute; - top: 95%; left: 0%; + bottom: 26px; width: 100%; - padding-bottom: 40px; + height: 12px; gap: 8px; + @media (max-width: 1129px) { + top: unset; + bottom: 3%; + } `} > {new Array(props.dots).fill(0).map((_, i) => ( @@ -112,7 +118,7 @@ export default function PartnersModule() { ) => { setDisplayTab(newValue); }; - const [autoPlay, setAutoPlay] = React.useState(true); + const [autoPlay, setAutoPlay] = React.useState(false); const cards = [ , @@ -144,6 +150,14 @@ export default function PartnersModule() { margin-top: 78px; position: relative; height: 639px; + @media (max-width: 1129px) { + width: 83%; + height: 100%; + } + @media (max-width: 600px) { + width: 100%; + height: 100%; + } `} >
-
+
+
autoPlay && handleChange(null, index)} - style={{ margin: "55px 0 110px 0" }} animateTransitions={true} interval={3000} > @@ -188,12 +219,19 @@ export default function PartnersModule() {
{card}
))}
+ handleChange(null, index)} + />
- - handleChange(null, index)} +
- +
diff --git a/src/app/modules/home-module/sub-modules/partners/style.ts b/src/app/modules/home-module/sub-modules/partners/style.ts index 90f13c2e9..4f71b79e6 100644 --- a/src/app/modules/home-module/sub-modules/partners/style.ts +++ b/src/app/modules/home-module/sub-modules/partners/style.ts @@ -1,7 +1,5 @@ import { css } from "styled-components/macro"; import styled from "styled-components/macro"; -import Ellipses from "app/modules/home-module/assets/ellipses.svg"; -import Ellipses2 from "app/modules/home-module/assets/ellipses-2.svg"; export const empowercss = (view: string) => css` height: ${view === "landing" ? "533px" : "418px"}; @@ -9,10 +7,19 @@ export const empowercss = (view: string) => css` margin-top: 48px; padding: 78px 0 55px 0; font-family: "GothamNarrow-Bold", sans-serif; - background: url(${view === "landing" ? Ellipses2 : Ellipses}), - linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #f2f7fd 100%); + background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #f2f7fd 100%); background-repeat: no-repeat; background-size: 100% 100%, auto; + overflow-x: hidden; + z-index: 0; + @media (max-width: 641px) { + height: 100%; + background: linear-gradient( + 180deg, + rgba(255, 255, 255, 0) 0%, + #f2f7fd 100% + ); + } a { text-decoration: none; } @@ -26,7 +33,7 @@ export const empowercss = (view: string) => css` text-align: center; margin-bottom: ${view === "landing" ? "14px" : "26px"}; font-family: "GothamNarrow-Bold", sans-serif; - @media (max-width: 768px) { + @media (max-width: 1024px) { font-size: 40px; line-height: 48px; } @@ -82,6 +89,11 @@ export const TabCardEllipseCss = css` right: 25%; z-index: -1; position: absolute; + @media (max-width: 500px) { + top: 7%; + right: -180px; + width: 100%; + } `; export const quotesEllipseCss = css` @@ -89,6 +101,11 @@ export const quotesEllipseCss = css` left: -8.1%; z-index: -1; position: absolute; + @media (max-width: 500px) { + width: 100%; + height: 100%; + left: -51%; + } `; export const useDXcss = css` @@ -101,6 +118,13 @@ export const useDXcss = css` text-align: center; font-family: "GothamNarrow-Medium", sans-serif; margin-top: 0; + @media (max-width: 1024px) { + font-family: "GothamNarrow-Bold", sans-serif; + } + @media (max-width: 600px) { + font-size: 32px; + line-height: 38.4px; + } } h3 { font-size: 24px; @@ -117,6 +141,15 @@ export const useDXcss = css` font-family: "GothamNarrow-Medium", sans-serif; width: 85%; margin: 16px auto 0 auto; + @media (max-width: 1024px) { + font-size: 16px; + line-height: 19.24px; + width: 67%; + font-family: "GothamNarrow-Book", sans-serif; + @media (max-width: 600px) { + width: 97%; + } + } } `; @@ -133,8 +166,15 @@ export const quotecss = css` line-height: 48px; text-align: center; font-family: "GothamNarrow-Medium", sans-serif; - margin: 0; + @media (max-width: 1024px) { + font-size: 34px; + line-height: 40.8px; + } + @media (max-width: 1024px) { + font-size: 24px; + line-height: 28.8px; + } } img { margin-bottom: 15px; @@ -151,6 +191,10 @@ export const quotecss = css` line-height: 19px; text-align: center; font-family: "GothamNarrow-Bold", sans-serif; + @media (max-width: 1024px) { + font-size: 14px; + line-height: 16.8px; + } } } `; @@ -164,6 +208,10 @@ export const bestDecisioncss = css` color: #231d2c; margin: 0; margin-bottom: 36px; + @media (max-width: 1024px) { + font-size: 34px; + line-height: 40.8px; + } } div { button { @@ -201,6 +249,8 @@ export const bestDecisioncss = css` display: flex; justify-content: center; align-items: center; + flex-shrink: 0; + white-space: nowrap; padding: 12px 27px; gap: 10px; p { @@ -209,6 +259,7 @@ export const bestDecisioncss = css` font-weight: 700; font-size: 14px; color: #231d2c; + white-space: nowrap; } :hover { opacity: 0.95; diff --git a/src/app/modules/home-module/sub-modules/why-dx/index.tsx b/src/app/modules/home-module/sub-modules/why-dx/index.tsx index fda77c675..17e15e2da 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/index.tsx +++ b/src/app/modules/home-module/sub-modules/why-dx/index.tsx @@ -1,14 +1,25 @@ import React from "react"; import Container from "@material-ui/core/Container"; import HomeFooter from "app/modules/home-module/components/Footer"; -import Ellipses from "app/modules/home-module/assets/whydx-ellipses.svg"; +import EllipsesDesktop from "app/modules/home-module/assets/whydx-ellipses.svg"; +import EllipsesTablet from "app/modules/home-module/assets/whydx-ellipses-tablet.svg"; +import EllipsesMobile from "app/modules/home-module/assets/whydx-ellipses-mobile.svg"; import TryUsBlock from "app/modules/home-module/sub-modules/why-dx/components/tryUsBlock"; import EmpowerBlock from "app/modules/home-module/sub-modules/partners/components/empowerBlock"; import KeyFeaturesBlock from "app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock"; import { useTitle } from "react-use"; +import { useMediaQuery } from "usehooks-ts"; export default function WhyDX() { useTitle("DX Dataxplorer - Why Dataxplorer?"); + const isTablet = useMediaQuery("(max-width: 1024px)"); + const isMobile = useMediaQuery("(max-width: 641px)"); + let Ellipses = EllipsesDesktop; + if (isTablet) { + Ellipses = EllipsesTablet; + } else if (isMobile) { + Ellipses = EllipsesMobile; + } return ( <> @@ -17,7 +28,7 @@ export default function WhyDX() { css={` background-image: url(${Ellipses}); background-repeat: no-repeat; - background-position: 44% 4%; + background-position: ${isTablet ? "49% 58%" : "44% 4%"}; `} > diff --git a/src/app/modules/report-module/sub-module/rowStructure/index.tsx b/src/app/modules/report-module/sub-module/rowStructure/index.tsx index 82e8e07d1..a146fe871 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/index.tsx +++ b/src/app/modules/report-module/sub-module/rowStructure/index.tsx @@ -807,7 +807,6 @@ function Divider(props: { display: flex; align-items: center; position: relative; - background: pink; `} > {handleDisplay && ( From 914ac07550ac57eea787567d983cfb7495615070 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Thu, 15 Aug 2024 06:13:02 +0100 Subject: [PATCH 19/58] feat: DX-1678 - update fonts fallback --- .../components/Dialogs/CookieDialog/index.tsx | 8 +-- .../EmbedChartDialog/chartContainer.tsx | 4 +- .../Dialogs/EmbedChartDialog/copyButton.tsx | 2 +- .../Dialogs/EmbedChartDialog/embedOptions.tsx | 8 +-- .../Dialogs/EmbedChartDialog/index.tsx | 8 +-- .../Dialogs/EmbedChartDialog/linkOptions.tsx | 2 +- .../Dialogs/EmbedChartDialog/shareContent.tsx | 2 +- .../Dialogs/TourGuide/rowFrameIntro.tsx | 2 +- .../Dialogs/TourGuide/selectStructure.tsx | 2 +- .../components/Dialogs/TourGuide/tourEnd.tsx | 2 +- src/app/components/Styled/tabs.ts | 6 +-- .../components/Table/Preview-table/style.ts | 2 +- .../chartSubheaderToolbar/index.tsx | 9 ++-- .../chartSubheaderToolbar/styles.ts | 2 +- .../components/dialog/errrorComponent.tsx | 4 +- .../components/dialog/warningDialog.tsx | 2 +- .../components/exporter/styles.ts | 50 +++++++++---------- .../components/toolbox/steps/index.tsx | 2 +- .../steps/panels-content/ChartType.tsx | 6 ++- .../toolbox/steps/panels-content/Mapping.tsx | 4 +- .../steps/panels-content/SelectDataset.tsx | 4 +- .../components/toolbox/steps/sub-header.tsx | 4 +- .../chart-module/routes/chart-type/index.tsx | 23 +++++---- .../chart-module/routes/mapping/error.tsx | 6 +-- .../routes/preview-theme/index.tsx | 6 ++- .../RichEditor/FontSizeController/index.tsx | 4 +- .../common/not-authorized-message/index.tsx | 2 +- .../dataset-module/component/styles.ts | 2 +- .../component/dataParserToolBox/style.ts | 2 +- .../component/dropzone/index.tsx | 2 +- .../component/externalSourcesList.tsx | 4 +- .../table/externalSearchTable/index.tsx | 2 +- .../upload-module/component/uploadOption.tsx | 9 ++-- .../routes/upload-module/style.ts | 4 +- .../upload-steps/addDatasetFragment.tsx | 5 +- .../upload-steps/externalSearch.tsx | 4 +- .../upload-steps/finishedFragment.tsx | 10 ++-- .../upload-module/upload-steps/processing.tsx | 5 +- .../modules/embed-module/embedChart/index.tsx | 6 +-- .../Charts/chartAddNewCard.tsx | 2 +- .../AssetCollection/Charts/gridItem.tsx | 2 +- .../Datasets/datasetAddNewCard.tsx | 2 +- .../Datasets/externalDatasetCard.tsx | 6 +-- .../AssetCollection/Datasets/gridItem.tsx | 4 +- .../AssetCollection/Reports/gridItem.tsx | 4 +- .../Reports/reportAddNewCard.tsx | 2 +- .../components/AssetCollection/index.tsx | 2 +- .../components/Breadcrumbs/index.tsx | 4 +- .../home-module/components/Footer/index.tsx | 9 ++-- .../components/Subscribe/index.tsx | 6 +-- .../home-module/components/Table/index.tsx | 2 +- src/app/modules/home-module/style.ts | 12 ++--- .../home-module/sub-modules/about/index.tsx | 21 ++++---- .../home-module/sub-modules/about/style.ts | 4 +- .../home-module/sub-modules/contact/index.tsx | 4 +- .../home-module/sub-modules/landing/index.tsx | 6 +-- .../partners/components/bestDecisionBlock.tsx | 4 +- .../partners/components/tabCard.tsx | 4 +- .../home-module/sub-modules/partners/style.ts | 18 +++---- .../pricing/components/features.tsx | 3 +- .../why-dx/components/keyFeaturesBlock.tsx | 4 +- .../why-dx/components/tryUsBlock.tsx | 6 +-- .../home-module/sub-modules/why-dx/style.ts | 6 +-- .../component/card/index.tsx | 2 +- .../onboarding-module/component/card/style.ts | 2 +- .../component/splibar/index.tsx | 4 +- src/app/modules/onboarding-module/index.tsx | 2 +- .../components/chart-wrapper/index.tsx | 4 +- .../autoSaveSwitch/style.css | 2 +- .../reportSubHeaderToolbar/index.tsx | 9 ++-- .../right-panel-create-view/index.tsx | 8 +-- .../right-panel-create-view/panelLabel.tsx | 4 +- .../right-panel-create-view/rhpGridItem.tsx | 2 +- .../components/use-report-panel/index.tsx | 4 +- .../components/headerBlock/style.ts | 2 +- .../rowStructure/addRowFrameButton.tsx | 2 +- .../sub-module/rowStructure/index.tsx | 2 +- .../report-module/views/ai-template/index.tsx | 3 +- .../report-module/views/ai-template/style.ts | 8 +-- .../report-module/views/initial/index.tsx | 2 +- src/app/modules/user-profile-module/style.ts | 2 +- 81 files changed, 229 insertions(+), 203 deletions(-) diff --git a/src/app/components/Dialogs/CookieDialog/index.tsx b/src/app/components/Dialogs/CookieDialog/index.tsx index 8576a6eb0..24bac54e1 100644 --- a/src/app/components/Dialogs/CookieDialog/index.tsx +++ b/src/app/components/Dialogs/CookieDialog/index.tsx @@ -37,12 +37,12 @@ const BaseSnackbar = styled((props) => ( height: 32px; } & [class*="MuiTypography-root"] { - font-weight: bold; + font-weight: 400; font-size: 18px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; > a { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } } @@ -54,7 +54,7 @@ const BaseSnackbar = styled((props) => ( & [class*="MuiSnackbarContent-action"] { padding-left: 64px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } `; diff --git a/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx b/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx index 21ff8ee0c..435e26b24 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx @@ -50,7 +50,7 @@ export default function ChartContainer(props: { p:nth-of-type(1) { color: #e75656; text-align: center; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 18px; margin-top: 16px; margin-bottom: 0; @@ -58,7 +58,7 @@ export default function ChartContainer(props: { p:nth-of-type(2) { color: #e75656; text-align: center; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; font-size: 14px; margin-top: 16px; } diff --git a/src/app/components/Dialogs/EmbedChartDialog/copyButton.tsx b/src/app/components/Dialogs/EmbedChartDialog/copyButton.tsx index dcd380013..56508eaf5 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/copyButton.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/copyButton.tsx @@ -17,7 +17,7 @@ export default function CopyButton(props: { align-items: center; color: #fff; text-transform: uppercase; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 14px; border: none; outline: none; diff --git a/src/app/components/Dialogs/EmbedChartDialog/embedOptions.tsx b/src/app/components/Dialogs/EmbedChartDialog/embedOptions.tsx index 8d1b2405f..fa1326c2b 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/embedOptions.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/embedOptions.tsx @@ -32,7 +32,7 @@ export default function EmbedOptions(props: {

@@ -84,7 +84,7 @@ export default function EmbedOptions(props: {

@@ -111,7 +111,7 @@ export default function EmbedOptions(props: { height: 41px; display: flex; align-items: end; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; font-size: 14px; `} > diff --git a/src/app/components/Dialogs/EmbedChartDialog/index.tsx b/src/app/components/Dialogs/EmbedChartDialog/index.tsx index a6d9481a1..ca2f7a27e 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/index.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/index.tsx @@ -169,7 +169,7 @@ export default function EmbedChartDialog(props: { width: 73%; > p { color: #231d2c; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 14px; overflow: hidden; text-overflow: ellipsis; @@ -210,14 +210,16 @@ export default function EmbedChartDialog(props: { margin: 0; span:nth-of-type(1) { color: #70777e; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", + sans-serif; font-size: 12px; margin: 0; line-height: 14.52px; } span:nth-of-type(2) { color: #231d2c; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", + sans-serif; font-size: 12px; margin: 0; line-height: 14.52px; diff --git a/src/app/components/Dialogs/EmbedChartDialog/linkOptions.tsx b/src/app/components/Dialogs/EmbedChartDialog/linkOptions.tsx index 476d2bfae..3ec16674e 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/linkOptions.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/linkOptions.tsx @@ -19,7 +19,7 @@ export default function LinkOptions(props: { justify-content: center; align-items: center; p { - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; font-size: 14px; } `} diff --git a/src/app/components/Dialogs/EmbedChartDialog/shareContent.tsx b/src/app/components/Dialogs/EmbedChartDialog/shareContent.tsx index 2096382f5..65fdf9f3c 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/shareContent.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/shareContent.tsx @@ -19,7 +19,7 @@ export default function ShareContent(props: { border-radius: 8px; line-height: 16px; background: #f5f5f7; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; color: #000; font-size: 14px; `} diff --git a/src/app/components/Dialogs/TourGuide/rowFrameIntro.tsx b/src/app/components/Dialogs/TourGuide/rowFrameIntro.tsx index eb6a0c1fb..f9abf7bf4 100644 --- a/src/app/components/Dialogs/TourGuide/rowFrameIntro.tsx +++ b/src/app/components/Dialogs/TourGuide/rowFrameIntro.tsx @@ -37,7 +37,7 @@ export default function RowFrameIntro(props: { border-radius: 8px; background: #231d2c; color: #fff; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; font-size: 12px; font-style: normal; font-weight: 350; diff --git a/src/app/components/Dialogs/TourGuide/selectStructure.tsx b/src/app/components/Dialogs/TourGuide/selectStructure.tsx index d6d07861c..ddd0903f4 100644 --- a/src/app/components/Dialogs/TourGuide/selectStructure.tsx +++ b/src/app/components/Dialogs/TourGuide/selectStructure.tsx @@ -33,7 +33,7 @@ export default function SelectStructure(props: { border-radius: 8px; background: #231d2c; color: #fff; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; font-size: 12px; font-style: normal; font-weight: 350; diff --git a/src/app/components/Dialogs/TourGuide/tourEnd.tsx b/src/app/components/Dialogs/TourGuide/tourEnd.tsx index 4028d9005..ce20a3787 100644 --- a/src/app/components/Dialogs/TourGuide/tourEnd.tsx +++ b/src/app/components/Dialogs/TourGuide/tourEnd.tsx @@ -42,7 +42,7 @@ export default function TourEnd({ border-radius: 8px; background: #231d2c; color: #fff; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; font-style: normal; font-weight: 350; line-height: 16px; diff --git a/src/app/components/Styled/tabs.ts b/src/app/components/Styled/tabs.ts index d78cb1935..34853ecd3 100644 --- a/src/app/components/Styled/tabs.ts +++ b/src/app/components/Styled/tabs.ts @@ -22,7 +22,7 @@ export const Tab = { font-weight: ${(props) => (props.active ? "bold" : "normal")}; font-family: ${(props) => props.active ? "GothamNarrow-Bold" : "GothamNarrow-Book"}, - sans-serif; + "Helvetica Neue", sans-serif; ::after { content: ""; @@ -44,7 +44,7 @@ export const Tab = { font-weight: ${(props) => (props.active ? "bold" : "normal")}; font-family: ${(props) => props.active ? "GothamNarrow-Bold" : "GothamNarrow-Book"}, - sans-serif; + "Helvetica Neue", sans-serif; ::after { content: ""; @@ -69,7 +69,7 @@ export const Tab = { font-weight: ${(props) => (props.active ? "700" : "normal")}; font-family: ${(props) => props.active ? "GothamNarrow-Bold" : "GothamNarrow-Book"}, - sans-serif; + "Helvetica Neue", sans-serif; ::after { content: ""; diff --git a/src/app/components/Table/Preview-table/style.ts b/src/app/components/Table/Preview-table/style.ts index d5a507c3b..e86714753 100644 --- a/src/app/components/Table/Preview-table/style.ts +++ b/src/app/components/Table/Preview-table/style.ts @@ -23,7 +23,7 @@ export const previewTablecss = css` height: 35px; font-weight: 400; font-size: 14px; - font-family: "GothamNarrow-Book"; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; } tr { diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx index 22f0cad35..95665fd3c 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx @@ -373,7 +373,8 @@ export function ChartSubheaderToolbar(props: Readonly) {

) {

) { css={` color: #000; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", + sans-serif; font-size: 12px; font-style: normal; font-weight: 325; diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/styles.ts b/src/app/modules/chart-module/components/chartSubheaderToolbar/styles.ts index 647af325f..f2010842b 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/styles.ts +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/styles.ts @@ -52,7 +52,7 @@ export const styles = { align-items: center; height: 32px; padding: 10px 20px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; gap: 10px; outline: none; border: none; diff --git a/src/app/modules/chart-module/components/dialog/errrorComponent.tsx b/src/app/modules/chart-module/components/dialog/errrorComponent.tsx index 4e13a447d..d98549389 100644 --- a/src/app/modules/chart-module/components/dialog/errrorComponent.tsx +++ b/src/app/modules/chart-module/components/dialog/errrorComponent.tsx @@ -31,7 +31,7 @@ export default function ErrorComponent(props: { font-size: 14px; line-height: 20px; font-weight: bold; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; text-align: center; button { outline: none; @@ -44,7 +44,7 @@ export default function ErrorComponent(props: { margin-top: 34px; white-space: pre-line; line-height: 11px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } `} > diff --git a/src/app/modules/chart-module/components/dialog/warningDialog.tsx b/src/app/modules/chart-module/components/dialog/warningDialog.tsx index 2ba507ca4..fc49d8e94 100644 --- a/src/app/modules/chart-module/components/dialog/warningDialog.tsx +++ b/src/app/modules/chart-module/components/dialog/warningDialog.tsx @@ -18,7 +18,7 @@ export default function WarningDialog(props: { isMappingValid: boolean }) { font-size: 14px; line-height: 20px; font-weight: bold; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; text-align: center; button { outline: none; diff --git a/src/app/modules/chart-module/components/exporter/styles.ts b/src/app/modules/chart-module/components/exporter/styles.ts index e8968eeab..8b10e9608 100644 --- a/src/app/modules/chart-module/components/exporter/styles.ts +++ b/src/app/modules/chart-module/components/exporter/styles.ts @@ -13,43 +13,43 @@ export const styles = { flex-direction: row; > input { - width: 140px; - height: 32px; - font-size 14px; - background: #fff; - padding-left: 16px; - border-style: none; - border-radius: 16px 0px 0px 16px; + width: 140px; + height: 32px; + font-size: 14px; + background: #fff; + padding-left: 16px; + border-style: none; + border-radius: 16px 0px 0px 16px; } > button { - color: #fff; - width: 60px; - height: 32px; - font-size 14px; - cursor: pointer; - border-style: none; - background: #262C34; - border-radius: 0px 16px 16px 0px; + color: #fff; + width: 60px; + height: 32px; + font-size: 14px; + cursor: pointer; + border-style: none; + background: #262c34; + border-radius: 0px 16px 16px 0px; - > svg { - top: -2px; - margin-left: 5px; - position: relative; - transition: all 0.2s ease-in-out; - transform: rotate(${open ? 0 : 180}deg); + > svg { + top: -2px; + margin-left: 5px; + position: relative; + transition: all 0.2s ease-in-out; + transform: rotate(${open ? 0 : 180}deg); - > path { - fill: #fff; - } + > path { + fill: #fff; } + } } `, downloadBtn: css` color: #fff; width: 120px; height: 32px; - font-size 14px; + font-size: 14px; cursor: pointer; font-weight: bold; border-style: none; diff --git a/src/app/modules/chart-module/components/toolbox/steps/index.tsx b/src/app/modules/chart-module/components/toolbox/steps/index.tsx index 472ac4b4f..03d1d95a5 100644 --- a/src/app/modules/chart-module/components/toolbox/steps/index.tsx +++ b/src/app/modules/chart-module/components/toolbox/steps/index.tsx @@ -186,7 +186,7 @@ export function ChartToolBoxSteps(props: ChartToolBoxStepsProps) { align-items: center; justify-content: center; font-size: 14px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; cursor: ${props.isClickable ? "pointer" : "not-allowed"}; /* pointer-events: ${props.isClickable ? "auto" : "none"}; */ :nth-child(1) { diff --git a/src/app/modules/chart-module/components/toolbox/steps/panels-content/ChartType.tsx b/src/app/modules/chart-module/components/toolbox/steps/panels-content/ChartType.tsx index ddab50b05..84e706c10 100644 --- a/src/app/modules/chart-module/components/toolbox/steps/panels-content/ChartType.tsx +++ b/src/app/modules/chart-module/components/toolbox/steps/panels-content/ChartType.tsx @@ -116,7 +116,8 @@ export function ChartToolBoxChartType() { font-size: 14px; margin: 0px; line-height: 20px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", + sans-serif; `} > {fChartType.label} @@ -158,7 +159,8 @@ export function ChartToolBoxChartType() { />

{ css={` font-size: 14px; color: #262c34; - font-family: "GothamNarrow-Bold", sans-serif; ; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; `} > {props.dimension.name} diff --git a/src/app/modules/chart-module/components/toolbox/steps/panels-content/SelectDataset.tsx b/src/app/modules/chart-module/components/toolbox/steps/panels-content/SelectDataset.tsx index cf41f51aa..619e8c25a 100644 --- a/src/app/modules/chart-module/components/toolbox/steps/panels-content/SelectDataset.tsx +++ b/src/app/modules/chart-module/components/toolbox/steps/panels-content/SelectDataset.tsx @@ -99,7 +99,7 @@ function ChartToolBoxSelectDataset(props: { deselectDataset: () => void }) { margin-top: -8px; color: #231d2c; font-size: 14px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } > label { @@ -203,7 +203,7 @@ const ConnectData = () => { cursor: pointer; } p { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; margin-bottom: 4px; margin-top: -8px; font-size: 14px; diff --git a/src/app/modules/chart-module/components/toolbox/steps/sub-header.tsx b/src/app/modules/chart-module/components/toolbox/steps/sub-header.tsx index 8311b1bfc..e11ea117a 100644 --- a/src/app/modules/chart-module/components/toolbox/steps/sub-header.tsx +++ b/src/app/modules/chart-module/components/toolbox/steps/sub-header.tsx @@ -36,7 +36,7 @@ export default function ToolboxSubHeader( align-items: center; } p:nth-child(1) { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 14px; font-weight: 700; } @@ -59,7 +59,7 @@ export default function ToolboxSubHeader( borderRadius: "8px", color: "#fff", fontSize: "12px", - fontFamily: "GothamNarrow-Medium", + fontFamily: '"GothamNarrow-Medium", "Helvetica Neue", sans-serif', width: "320px", lineHeight: "16px", }} diff --git a/src/app/modules/chart-module/routes/chart-type/index.tsx b/src/app/modules/chart-module/routes/chart-type/index.tsx index 810e68b22..adb6e65a4 100644 --- a/src/app/modules/chart-module/routes/chart-type/index.tsx +++ b/src/app/modules/chart-module/routes/chart-type/index.tsx @@ -217,13 +217,15 @@ function ChartBuilderChartType(props: Readonly) { {isAiActive ? (

@@ -258,7 +260,7 @@ function ChartBuilderChartType(props: Readonly) { span { color: #000000; font-size: 12px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; } `} > @@ -281,7 +283,7 @@ function ChartBuilderChartType(props: Readonly) {

) { height: 16px; color: #373d43; font-size: 10px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", + sans-serif; `} data-cy="ai-suggestion-icon" > @@ -417,7 +420,7 @@ function ChartBuilderChartType(props: Readonly) {

) { height: 16px; color: #373d43; font-size: 10px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", + sans-serif; `} data-cy="ai-suggestion-icon" > @@ -555,7 +559,7 @@ function ChartBuilderChartType(props: Readonly) {

) { height: 16px; color: #373d43; font-size: 10px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", + sans-serif; `} data-cy="ai-suggestion-icon" > diff --git a/src/app/modules/chart-module/routes/mapping/error.tsx b/src/app/modules/chart-module/routes/mapping/error.tsx index 6f386b4f6..ff7f8b969 100644 --- a/src/app/modules/chart-module/routes/mapping/error.tsx +++ b/src/app/modules/chart-module/routes/mapping/error.tsx @@ -408,7 +408,7 @@ export default function MappingErrorComponent(props: { font-size: 14px; line-height: 20px; font-weight: bold; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; text-align: center; svg { width: 48px; @@ -425,12 +425,12 @@ export default function MappingErrorComponent(props: { margin-top: 34px; white-space: pre-line; line-height: 22px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 18px; } p:nth-of-type(2) { margin: 0; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; } `} > diff --git a/src/app/modules/chart-module/routes/preview-theme/index.tsx b/src/app/modules/chart-module/routes/preview-theme/index.tsx index bb7a37011..4df1136ed 100644 --- a/src/app/modules/chart-module/routes/preview-theme/index.tsx +++ b/src/app/modules/chart-module/routes/preview-theme/index.tsx @@ -284,10 +284,12 @@ export function ChartBuilderPreviewTheme(props: ChartBuilderPreviewThemeProps) {

{" "}

{ font-size: 20px; line-height: normal; font-style: normal; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; font-weight: 325; margin: 0; padding: 0; diff --git a/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx b/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx index e2103d191..0f475acd4 100644 --- a/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx @@ -44,7 +44,7 @@ export default function SourceCategoryList(props: Readonly) { background: #fff; border-radius: 30px; border: 0.5px solid #231d2c; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; padding: 12px 0px; } `} @@ -69,7 +69,7 @@ export default function SourceCategoryList(props: Readonly) { background: "#6061E5", border: "none", fontWeight: 400, - fontFamily: "GothamNarrow-Bold, sans-serif", + fontFamily: "GothamNarrow-Bold, 'Helvetica Neue', sans-serif", } : {} } diff --git a/src/app/modules/dataset-module/routes/upload-module/component/table/externalSearchTable/index.tsx b/src/app/modules/dataset-module/routes/upload-module/component/table/externalSearchTable/index.tsx index 9cf6d31e1..e24e0bae3 100644 --- a/src/app/modules/dataset-module/routes/upload-module/component/table/externalSearchTable/index.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/component/table/externalSearchTable/index.tsx @@ -64,7 +64,7 @@ export default function ExternalSearchTable(props: { > tr > th { font-size: 14px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; border-right: 1px solid #e4e4e4; } `} diff --git a/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx b/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx index a7cfc56ad..6bf3923b7 100644 --- a/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/component/uploadOption.tsx @@ -55,7 +55,7 @@ const UploadOption = (props: { font-weight: 400; line-height: 20px; /* 111.111% */ letter-spacing: 0.5px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; margin: 0; padding: 0; text-align: left; @@ -70,7 +70,7 @@ const UploadOption = (props: { font-weight: 325; line-height: 20px; /* 111.111% */ letter-spacing: 0.5px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; margin: 0; padding: 0; text-align: left; @@ -106,7 +106,7 @@ const UploadOption = (props: { font-weight: 325; line-height: 15px; /* 125% */ letter-spacing: 0.5px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; color: #6b727b; `} > @@ -155,7 +155,8 @@ const UploadOption = (props: { line-height: 15px; /* 125% */ letter-spacing: 0.5px; color: white; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", + sans-serif; border-radius: 12px; background: #6061e5; border: none; diff --git a/src/app/modules/dataset-module/routes/upload-module/style.ts b/src/app/modules/dataset-module/routes/upload-module/style.ts index 1507aa761..4d7b7bf55 100644 --- a/src/app/modules/dataset-module/routes/upload-module/style.ts +++ b/src/app/modules/dataset-module/routes/upload-module/style.ts @@ -108,7 +108,7 @@ export const CssTextField = withStyles({ }, "&.MuiInputLabel-outlined": { fontSize: "16px", - fontFamily: "'GothamNarrow-Book', sans-serif", + fontFamily: "'GothamNarrow-Book', 'Helvetica Neue', sans-serif", color: "#231D2C", }, "& .MuiOutlinedInput-input": { @@ -151,7 +151,7 @@ export const CssSelectField = withStyles({ }, "&.MuiInputLabel-outlined": { fontSize: "16px", - fontFamily: "'GothamNarrow-Book', sans-serif", + fontFamily: "'GothamNarrow-Book', 'Helvetica Neue', sans-serif", color: "#231D2C", }, "&.MuiSelect-outlined": { diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx index 4ca755770..f41d494a4 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx @@ -156,7 +156,7 @@ export default function AddDatasetFragment(props: Props) { } p { color: #231d2c; - font-family: "GothamNarrow-Book"; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; font-size: 14px; font-weight: 325; line-height: 20px; @@ -195,8 +195,7 @@ export default function AddDatasetFragment(props: Props) { font-style: normal; font-weight: 400; line-height: normal; - font-family: "GothamNarrow-Bold", sans-serif; - background: #dadaf84d; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; border-radius: 16px 16px 0px 0px; width: 100%; `} diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx index 28dd47069..700707dcc 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx @@ -156,7 +156,7 @@ export default function ExternalSearch(props: { } p { color: #231d2c; - font-family: "GothamNarrow-Book"; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; font-size: 14px; font-weight: 325; line-height: 20px; @@ -262,7 +262,7 @@ export default function ExternalSearch(props: { font-weight: 325; line-height: normal; letter-spacing: 0.5px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; `} > No datasets were found using federated search. Please consider trying diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx index 663dcfea2..2be676d97 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx @@ -100,14 +100,14 @@ export default function FinishedFragment(props: Props) { font-size: 14px; font-weight: 400; font-style: normal; - font-family: "GothamNarrow-Book"; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; `} >

diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx index 03e772700..74b3e6569 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/processing.tsx @@ -112,7 +112,7 @@ export default function Processing(props: ProcessingMetaDataProps) {

@@ -127,7 +127,8 @@ export default function Processing(props: ProcessingMetaDataProps) { justify-content: space-between; align-items: center; p { - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", + sans-serif; font-size: 12px; color: #adb5bd; margin-top: 0; diff --git a/src/app/modules/embed-module/embedChart/index.tsx b/src/app/modules/embed-module/embedChart/index.tsx index e595a5147..53c812e07 100644 --- a/src/app/modules/embed-module/embedChart/index.tsx +++ b/src/app/modules/embed-module/embedChart/index.tsx @@ -91,7 +91,7 @@ export default function EmbedChartRoute() { padding: 24px; > p { color: #231d2c; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 18px; width: 100%; overflow: hidden; @@ -137,11 +137,11 @@ export default function EmbedChartRoute() { id={`datasource-${loadedChart.id || "1"}`} css={` color: #70777e; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 12px; margin: 0; a { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; color: #70777e; text-decoration: none; border-bottom: 1px solid #70777e; diff --git a/src/app/modules/home-module/components/AssetCollection/Charts/chartAddNewCard.tsx b/src/app/modules/home-module/components/AssetCollection/Charts/chartAddNewCard.tsx index 97d274b74..70299b223 100644 --- a/src/app/modules/home-module/components/AssetCollection/Charts/chartAddNewCard.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Charts/chartAddNewCard.tsx @@ -53,7 +53,7 @@ export default function ChartAddnewCard() {

) { margin-top: -5px; font-size: 14px; line-height: 22px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; overflow: hidden; margin-bottom: 2px; white-space: nowrap; @@ -210,7 +210,7 @@ export default function GridItem(props: Readonly) { height: 20px; border-radius: 20px; color: #ffffff; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; right: 8px; bottom: 30px; z-index: 2; diff --git a/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx b/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx index c427f7580..c4b5603c5 100644 --- a/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx @@ -89,7 +89,7 @@ export default function gridItem(props: Props) { css={` font-size: 14px; line-height: 22px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; margin-top: 2px; overflow: hidden; @@ -105,7 +105,7 @@ export default function gridItem(props: Props) { css={` font-size: 10px; line-height: 14px; - font-family: "Gotham Narrow ", sans-serif; + font-family: "Gotham Narrow ", "Helvetica Neue", sans-serif; margin-top: 1px; overflow: hidden; display: -webkit-box; diff --git a/src/app/modules/home-module/components/AssetCollection/Reports/reportAddNewCard.tsx b/src/app/modules/home-module/components/AssetCollection/Reports/reportAddNewCard.tsx index 25a2d2ee8..52504cc0b 100644 --- a/src/app/modules/home-module/components/AssetCollection/Reports/reportAddNewCard.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Reports/reportAddNewCard.tsx @@ -52,7 +52,7 @@ export default function ReportAddnewCard() {

diff --git a/src/app/modules/home-module/components/Breadcrumbs/index.tsx b/src/app/modules/home-module/components/Breadcrumbs/index.tsx index 47e0e4b01..5853027c1 100644 --- a/src/app/modules/home-module/components/Breadcrumbs/index.tsx +++ b/src/app/modules/home-module/components/Breadcrumbs/index.tsx @@ -28,7 +28,7 @@ function BreadCrumbs(props: BreadCrumbsProps) { &, * { font-size: 24px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-weight: 400; line-height: 29px; color: #2b3674; @@ -47,7 +47,7 @@ function BreadCrumbs(props: BreadCrumbsProps) { &, * { font-size: 24px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; font-weight: 325; line-height: 29px; color: #2b3674; diff --git a/src/app/modules/home-module/components/Footer/index.tsx b/src/app/modules/home-module/components/Footer/index.tsx index ea42aa934..7692b1659 100644 --- a/src/app/modules/home-module/components/Footer/index.tsx +++ b/src/app/modules/home-module/components/Footer/index.tsx @@ -41,7 +41,8 @@ export default function HomeFooter() { font-size: 16px; text-decoration: none; color: #000; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", + sans-serif; } `} > @@ -91,7 +92,8 @@ export default function HomeFooter() { margin-top: 20px; color: #000; font-weight: 325; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", + sans-serif; } a { text-decoration: none; @@ -134,7 +136,8 @@ export default function HomeFooter() { font-size: 16px; font-weight: 350; color: #000; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", + sans-serif; `} > Subscribe to our newsletter diff --git a/src/app/modules/home-module/components/Subscribe/index.tsx b/src/app/modules/home-module/components/Subscribe/index.tsx index cd502e4b8..11f71ec68 100644 --- a/src/app/modules/home-module/components/Subscribe/index.tsx +++ b/src/app/modules/home-module/components/Subscribe/index.tsx @@ -31,7 +31,7 @@ export default function Subscribe() {

tr > th { font-size: 14px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } `} > diff --git a/src/app/modules/home-module/style.ts b/src/app/modules/home-module/style.ts index 32d30b402..adea221f4 100644 --- a/src/app/modules/home-module/style.ts +++ b/src/app/modules/home-module/style.ts @@ -12,7 +12,7 @@ export const turnsDataCss = css` align-items: center; h1 { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-weight: 700; font-size: 40px; line-height: 48px; @@ -22,7 +22,7 @@ export const turnsDataCss = css` padding: 0; } h2 { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-weight: 400; font-size: 34px; line-height: 42px; @@ -33,7 +33,7 @@ export const turnsDataCss = css` p { color: #495057; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 18px; line-height: 22px; text-align: center; @@ -50,7 +50,7 @@ export const turnsDataCss = css` outline: none; border: none; color: #ffffff; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-weight: 400; font-size: 14px; text-transform: uppercase; @@ -70,7 +70,7 @@ export const turnsDataCss = css` export const featuredAssetsCss = css` h3 { font-size: 24px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; line-height: 29px; color: #000000; margin: 0; @@ -148,7 +148,7 @@ export const sortByItemCss = (active: boolean) => css` color: #231d2c; font-size: 12px; padding: 8px 22px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; background: ${active ? "#f1f3f5" : "transparent"}; &:hover { diff --git a/src/app/modules/home-module/sub-modules/about/index.tsx b/src/app/modules/home-module/sub-modules/about/index.tsx index 8d5ead0d2..092dbeed3 100644 --- a/src/app/modules/home-module/sub-modules/about/index.tsx +++ b/src/app/modules/home-module/sub-modules/about/index.tsx @@ -146,7 +146,7 @@ export default function AboutModule() { >

With 20+ years combined experience in data and global health @@ -283,7 +283,8 @@ export default function AboutModule() {

@@ -328,7 +331,7 @@ export default function AboutModule() {

diff --git a/src/app/modules/home-module/sub-modules/about/style.ts b/src/app/modules/home-module/sub-modules/about/style.ts index 36f2684a2..6361c0069 100644 --- a/src/app/modules/home-module/sub-modules/about/style.ts +++ b/src/app/modules/home-module/sub-modules/about/style.ts @@ -8,11 +8,11 @@ export const subParagraphcss = css` font-style: normal; font-weight: 350; line-height: normal; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; } p { margin: 0; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; font-size: 20px; font-style: normal; font-weight: 350; diff --git a/src/app/modules/home-module/sub-modules/contact/index.tsx b/src/app/modules/home-module/sub-modules/contact/index.tsx index 4b55bbf7b..c74fedc3a 100644 --- a/src/app/modules/home-module/sub-modules/contact/index.tsx +++ b/src/app/modules/home-module/sub-modules/contact/index.tsx @@ -141,7 +141,7 @@ export default function ContactModule() { height: 100%; margin: auto; h4 { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 36px; line-height: 43px; color: #231d2c; @@ -151,7 +151,7 @@ export default function ContactModule() { font-size: 20px; line-height: 24px; text-align: center; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; margin-top: 0; } .MuiFormControl-root { diff --git a/src/app/modules/home-module/sub-modules/landing/index.tsx b/src/app/modules/home-module/sub-modules/landing/index.tsx index 1f1f45f64..9821c858c 100644 --- a/src/app/modules/home-module/sub-modules/landing/index.tsx +++ b/src/app/modules/home-module/sub-modules/landing/index.tsx @@ -41,7 +41,7 @@ export default function LandingModule() { margin: 0; padding: 0; font-size: 36px; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; color: #231d2c; font-weight: 350; } @@ -53,7 +53,7 @@ export default function LandingModule() { font-weight: 350; line-height: 30px; /* 150% */ letter-spacing: 0.5px; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; } `} > @@ -143,7 +143,7 @@ export default function LandingModule() { font-style: normal; font-weight: 400; line-height: normal; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; text-align: center; `} > diff --git a/src/app/modules/home-module/sub-modules/partners/components/bestDecisionBlock.tsx b/src/app/modules/home-module/sub-modules/partners/components/bestDecisionBlock.tsx index 87f2c0e6a..7da38e07d 100644 --- a/src/app/modules/home-module/sub-modules/partners/components/bestDecisionBlock.tsx +++ b/src/app/modules/home-module/sub-modules/partners/components/bestDecisionBlock.tsx @@ -38,7 +38,7 @@ export default function BestDecisionBlock() { color: #ffffff; font-size: 40px; line-height: 48px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; margin: 0; `} > @@ -49,7 +49,7 @@ export default function BestDecisionBlock() { font-weight: 325; font-size: 24px; color: #f4f4f4; - font-family: "GothamNarrow-Light", sans-serif; + font-family: "GothamNarrow-Light", "Helvetica Neue", sans-serif; `} > Dataxplorer turns data into impact in minutes  diff --git a/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx b/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx index 91a6653eb..58e3e77fa 100644 --- a/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx +++ b/src/app/modules/home-module/sub-modules/partners/components/tabCard.tsx @@ -24,7 +24,7 @@ function TabCard(props: { display: flex; justify-content: center; gap: 39px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; padding: 72px 40px 100px 88px; color: #231d2c; @@ -50,7 +50,7 @@ function TabCard(props: { margin-bottom: 11px; } p { - font-family: "GothamNarrow-Light", sans-serif; + font-family: "GothamNarrow-Light", "Helvetica Neue", sans-serif; white-space: pre-line; font-weight: 400; line-height: 19px; diff --git a/src/app/modules/home-module/sub-modules/partners/style.ts b/src/app/modules/home-module/sub-modules/partners/style.ts index 807b1576a..0f38e7f41 100644 --- a/src/app/modules/home-module/sub-modules/partners/style.ts +++ b/src/app/modules/home-module/sub-modules/partners/style.ts @@ -8,7 +8,7 @@ export const empowercss = (view: string) => css` position: relative; margin-top: 48px; padding: 78px 0 55px 0; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; background: url(${view === "landing" ? Ellipses2 : Ellipses}), linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #f2f7fd 100%); background-repeat: no-repeat; @@ -25,7 +25,7 @@ export const empowercss = (view: string) => css` white-space: pre-line; text-align: center; margin-bottom: ${view === "landing" ? "14px" : "26px"}; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } p { margin: 0; @@ -33,7 +33,7 @@ export const empowercss = (view: string) => css` font-size: 18px; line-height: 22px; text-align: center; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } div { gap: 34px; @@ -87,13 +87,13 @@ export const useDXcss = css` font-size: 40px; line-height: 48px; text-align: center; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; margin-top: 0; } h3 { font-size: 24px; line-height: 29px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; text-align: center; margin-bottom: 0; margin-top: 48px; @@ -102,7 +102,7 @@ export const useDXcss = css` font-size: 20px; line-height: 24px; text-align: center; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; width: 85%; margin: 16px auto 0 auto; } @@ -120,7 +120,7 @@ export const quotecss = css` font-size: 40px; line-height: 48px; text-align: center; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; margin: 0; } @@ -138,7 +138,7 @@ export const quotecss = css` font-size: 16px; line-height: 19px; text-align: center; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } } `; @@ -148,7 +148,7 @@ export const bestDecisioncss = css` font-size: 48px; line-height: 58px; text-align: center; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; color: #231d2c; margin: 0; margin-bottom: 36px; diff --git a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx index 22ae91049..eb0185071 100644 --- a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx +++ b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx @@ -291,7 +291,8 @@ const Features = () => { align-items: center; text-transform: uppercase; font-size: 10px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", + sans-serif; } `} > diff --git a/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx b/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx index 4c7ff4831..7d9d4f2c2 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx +++ b/src/app/modules/home-module/sub-modules/why-dx/components/keyFeaturesBlock.tsx @@ -25,13 +25,13 @@ export default function KeyFeaturesBlock() { font-size: 36px; line-height: 20px; font-weight: 350; - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; margin-bottom: 25px; margin-top: 0; color: #231d2c; } p :nth-of-type(2) { - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; font-weight: 350; line-height: 30px; letter-spacing: 0.5px; diff --git a/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx b/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx index 4c523ebe9..945bac068 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx +++ b/src/app/modules/home-module/sub-modules/why-dx/components/tryUsBlock.tsx @@ -14,7 +14,7 @@ export default function TryUsBlock() {

@@ -54,7 +54,7 @@ export default function TryUsBlock() { css={` font-size: 24px; color: #f4f4f4; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; `} > Dataxplorer turns data into impact  diff --git a/src/app/modules/home-module/sub-modules/why-dx/style.ts b/src/app/modules/home-module/sub-modules/why-dx/style.ts index 73665a146..b7d1e9d9e 100644 --- a/src/app/modules/home-module/sub-modules/why-dx/style.ts +++ b/src/app/modules/home-module/sub-modules/why-dx/style.ts @@ -9,12 +9,12 @@ export const benefitscss = css` line-height: 43px; text-align: center; color: #000000; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; margin-bottom: 66px; margin-top: 0px; } h3 { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-weight: 400; font-size: 40px; line-height: 48px; @@ -25,7 +25,7 @@ export const benefitscss = css` font-size: 20px; line-height: 24px; /* width: 90%; */ - font-family: "GothamNarrow-Medium", sans-serif; + font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; margin-top: 14px; } `; diff --git a/src/app/modules/onboarding-module/component/card/index.tsx b/src/app/modules/onboarding-module/component/card/index.tsx index 0532af9a0..03c2bd26d 100644 --- a/src/app/modules/onboarding-module/component/card/index.tsx +++ b/src/app/modules/onboarding-module/component/card/index.tsx @@ -98,7 +98,7 @@ export default function AuthCard(props: { isLogin?: boolean }) { css={` color: #231d2c; font-size: 12px; - font-family: "GothamNarrow-Book"; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; `} > I agree with DX's{" "} diff --git a/src/app/modules/onboarding-module/component/card/style.ts b/src/app/modules/onboarding-module/component/card/style.ts index f824f1daa..0df5d01fb 100644 --- a/src/app/modules/onboarding-module/component/card/style.ts +++ b/src/app/modules/onboarding-module/component/card/style.ts @@ -9,7 +9,7 @@ export const socialloginbuttoncss = css` padding: 6px 0; font-size: 14px; cursor: pointer; - font-family: "GothamNarrow-Book"; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; line-height: 20px; border: 1px solid #231d2c; border-radius: 10px; diff --git a/src/app/modules/onboarding-module/component/splibar/index.tsx b/src/app/modules/onboarding-module/component/splibar/index.tsx index e81e0dc58..d2c01266f 100644 --- a/src/app/modules/onboarding-module/component/splibar/index.tsx +++ b/src/app/modules/onboarding-module/component/splibar/index.tsx @@ -32,7 +32,7 @@ export default function SplitBar(props: Props) {

{props.leftLabel} @@ -48,7 +48,7 @@ export default function SplitBar(props: Props) {
{props.rightLabel} diff --git a/src/app/modules/onboarding-module/index.tsx b/src/app/modules/onboarding-module/index.tsx index 0fe46eaa1..520aeb9df 100644 --- a/src/app/modules/onboarding-module/index.tsx +++ b/src/app/modules/onboarding-module/index.tsx @@ -53,7 +53,7 @@ export default function Onboarding() { font-size: 24px; font-weight: 700; font-style: normal; - font-family: "GothamNarrow-Bold"; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; padding: 0; margin: 0; `} diff --git a/src/app/modules/report-module/components/chart-wrapper/index.tsx b/src/app/modules/report-module/components/chart-wrapper/index.tsx index 11197beb3..d6c7782d4 100644 --- a/src/app/modules/report-module/components/chart-wrapper/index.tsx +++ b/src/app/modules/report-module/components/chart-wrapper/index.tsx @@ -143,7 +143,7 @@ export function ReportChartWrapper(props: Props) { font-size: ${parseInt(props.width) > 250 ? "14px" : "10px"}; line-height: 15px; font-weight: bold; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; text-align: center; `} > @@ -210,7 +210,7 @@ export function ReportChartWrapper(props: Props) { css={` margin: 0; margin-bottom: 12px; - font-family: "GothamNarrow-bold", sans-serif; + font-family: "GothamNarrow-bold", "Helvetica Neue", sans-serif; font-size: 14px; color: #231d2c; letter-spacing: 0.5px; diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/autoSaveSwitch/style.css b/src/app/modules/report-module/components/reportSubHeaderToolbar/autoSaveSwitch/style.css index 64633b05a..9b645c064 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/autoSaveSwitch/style.css +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/autoSaveSwitch/style.css @@ -115,7 +115,7 @@ #button-13 .knobs:after { content: "OFF"; right: 4px; - font-family: "GothamNarrow-Light", sans-serif; + font-family: "GothamNarrow-Light", "Helvetica Neue", sans-serif; } #button-13 .knobs span { diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx index df29e7e1d..7a6dd1422 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx @@ -330,7 +330,8 @@ export function ReportSubheaderToolbar(

({ fontSize: "14px", borderRadius: "0px", backgroundColor: "#C7CDD1", - fontFamily: "GothamNarrow-Bold, sans-serif", + fontFamily: "GothamNarrow-Bold, 'Helvetica Neue', sans-serif", "&:first-child": { borderRight: "1px solid #f1f3f5", }, @@ -98,7 +98,7 @@ const Button = withStyles(() => ({ color: "#fff", fontSize: "14px", textTransform: "none", - fontFamily: "GothamNarrow-Book, sans-serif", + fontFamily: "GothamNarrow-Book, 'Helvetica Neue', sans-serif", }, }))(MuiButton); @@ -1224,7 +1224,7 @@ function CreateChartCard(props: {

Added diff --git a/src/app/modules/report-module/components/use-report-panel/index.tsx b/src/app/modules/report-module/components/use-report-panel/index.tsx index 7d8c346bf..f22e15a53 100644 --- a/src/app/modules/report-module/components/use-report-panel/index.tsx +++ b/src/app/modules/report-module/components/use-report-panel/index.tsx @@ -43,7 +43,7 @@ function ReportUsePanel() { font-style: normal; font-weight: 400; line-height: normal; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; color: #fff; `} > @@ -58,7 +58,7 @@ function ReportUsePanel() { font-style: normal; font-weight: 325; line-height: normal; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; margin-top: 12.03px; color: #fff; `} diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/style.ts b/src/app/modules/report-module/sub-module/components/headerBlock/style.ts index 4ab138de4..ca70ea4ea 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/style.ts +++ b/src/app/modules/report-module/sub-module/components/headerBlock/style.ts @@ -16,7 +16,7 @@ export const headerBlockcss = { outline: none; font-size: 28.9px; font-weight: 400; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; line-height: 48px; background: inherit; padding-left: 0px; diff --git a/src/app/modules/report-module/sub-module/rowStructure/addRowFrameButton.tsx b/src/app/modules/report-module/sub-module/rowStructure/addRowFrameButton.tsx index 9a30758b6..ff1f1ece2 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/addRowFrameButton.tsx +++ b/src/app/modules/report-module/sub-module/rowStructure/addRowFrameButton.tsx @@ -77,7 +77,7 @@ export default function AddRowFrameButton(props: Props) { background-color: #626262; border-radius: 4px; font-size: 12px; - font-family: "GothamNarrow-Book"; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; display: flex; justify-content: center; align-items: center; diff --git a/src/app/modules/report-module/sub-module/rowStructure/index.tsx b/src/app/modules/report-module/sub-module/rowStructure/index.tsx index 82e8e07d1..95d375d41 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/index.tsx +++ b/src/app/modules/report-module/sub-module/rowStructure/index.tsx @@ -508,7 +508,7 @@ export default function RowFrame(props: RowFrameProps) { css={` margin-bottom: 0; color: #000; - font-family: "GothamNarrow-bold", sans-serif; + font-family: "GothamNarrow-bold", "Helvetica Neue", sans-serif; `} > Select your row structure diff --git a/src/app/modules/report-module/views/ai-template/index.tsx b/src/app/modules/report-module/views/ai-template/index.tsx index c77085294..9e6ac14b3 100644 --- a/src/app/modules/report-module/views/ai-template/index.tsx +++ b/src/app/modules/report-module/views/ai-template/index.tsx @@ -134,7 +134,8 @@ export default function AITemplate() { padding-left: 10px; color: #e75656; p { - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", + sans-serif; text-align: left; display: flex; align-items: center; diff --git a/src/app/modules/report-module/views/ai-template/style.ts b/src/app/modules/report-module/views/ai-template/style.ts index 76bf559f1..a0d01be99 100644 --- a/src/app/modules/report-module/views/ai-template/style.ts +++ b/src/app/modules/report-module/views/ai-template/style.ts @@ -20,7 +20,7 @@ export const newsletterIllustrationcss = css` } p { font-size: 18px; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; color: #231d2c; margin-top: 44px; margin-bottom: 24px; @@ -54,10 +54,10 @@ export const subscribedcss = css` font-size: 18px; line-height: 22px; color: #231d2c; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; } p { - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; text-align: center; } @@ -89,7 +89,7 @@ export const notSubscribedcss = (error: boolean) => css` font-weight: 325; font-size: 14px; line-height: 17px; - font-family: "GothamNarrow-Book", sans-serif; + font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; } input { background: #f7f7f7; diff --git a/src/app/modules/report-module/views/initial/index.tsx b/src/app/modules/report-module/views/initial/index.tsx index fa6a7369c..d6e8f556a 100644 --- a/src/app/modules/report-module/views/initial/index.tsx +++ b/src/app/modules/report-module/views/initial/index.tsx @@ -134,7 +134,7 @@ function ReportInitialView(props: Readonly) { font-size: 18px; line-height: 22px; color: #000000; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; `} > Explore or duplicate reports diff --git a/src/app/modules/user-profile-module/style.ts b/src/app/modules/user-profile-module/style.ts index 724d8725d..29c5f7ca1 100644 --- a/src/app/modules/user-profile-module/style.ts +++ b/src/app/modules/user-profile-module/style.ts @@ -65,7 +65,7 @@ export const avicss = css` align-items: center; border-radius: 50%; justify-self: flex-start; - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; font-size: 22.0606px; line-height: 32px; b { From 937dc98b7c914ab8c8b46728ef454b047470a7f9 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Mon, 19 Aug 2024 12:03:35 +0100 Subject: [PATCH 20/58] style: responsiveness for detail pages --- src/app/components/AppBar/index.tsx | 10 +- src/app/components/AppBar/style.ts | 1 - .../EmbedChartDialog/assets/pdf-icon.svg | 8 + .../EmbedChartDialog/assets/png-icon.svg | 8 + .../EmbedChartDialog/chartContainer.tsx | 3 + .../Dialogs/EmbedChartDialog/index.tsx | 4 +- .../Dialogs/EmbedChartDialog/shareContent.tsx | 5 + .../chartSubheaderToolbar/index.tsx | 94 ++++++--- .../chartSubheaderToolbar/styles.ts | 21 +- .../common/RichEditor/editorStyles.module.css | 5 + .../common/mobile-duplicate-message/index.tsx | 32 +++ .../dataset-module/assets/copy-icon.svg | 8 + .../dataset-module/assets/share-icon.svg | 8 + .../component/datasetSubHeaderToolbar.tsx | 100 ++++++--- .../dataset-module/component/shareModal.tsx | 166 +++++++++++++++ .../dataset-module/component/styles.ts | 16 +- .../routes/datasetDetail/index.tsx | 11 +- .../routes/upload-module/style.ts | 27 +++ .../upload-steps/finishedFragment.tsx | 165 ++++++++++----- .../upload-module/upload-steps/index.tsx | 6 +- .../home-module/components/Filter/index.tsx | 1 + src/app/modules/onboarding-module/index.tsx | 2 - .../reportSubHeaderToolbar/index.tsx | 105 +++++++--- .../reportSubHeaderToolbar/infosnackbar.tsx | 195 +++++++++++++++++- .../reportSubHeaderToolbar/styles.ts | 15 +- .../components/headerBlock/index.tsx | 12 ++ src/app/utils/copyToClipboard.ts | 5 - 27 files changed, 841 insertions(+), 192 deletions(-) create mode 100644 src/app/components/Dialogs/EmbedChartDialog/assets/pdf-icon.svg create mode 100644 src/app/components/Dialogs/EmbedChartDialog/assets/png-icon.svg create mode 100644 src/app/modules/common/mobile-duplicate-message/index.tsx create mode 100644 src/app/modules/dataset-module/assets/copy-icon.svg create mode 100644 src/app/modules/dataset-module/assets/share-icon.svg create mode 100644 src/app/modules/dataset-module/component/shareModal.tsx diff --git a/src/app/components/AppBar/index.tsx b/src/app/components/AppBar/index.tsx index 9355c2ea8..340d15b51 100644 --- a/src/app/components/AppBar/index.tsx +++ b/src/app/components/AppBar/index.tsx @@ -86,7 +86,7 @@ function MobileHeader(props: { navLocation: string }) { position: fixed; top: 0; left: 0; - z-index: 100; + z-index: 101; `} >
{isNavExpanded ? ( @@ -212,7 +214,7 @@ function MobileHeader(props: { navLocation: string }) { export function AppBar() { const location = useLocation(); - const isMobile = useMediaQuery("(max-width: 846px)"); + const isMobile = useMediaQuery("(max-width: 881px)"); const [openSearch, setOpenSearch] = React.useState(false); const [anchorEl, setAnchorEl] = React.useState(null); const navLocation = location.pathname.split("/").join(""); diff --git a/src/app/components/AppBar/style.ts b/src/app/components/AppBar/style.ts index 014b22f60..b0f3cc849 100644 --- a/src/app/components/AppBar/style.ts +++ b/src/app/components/AppBar/style.ts @@ -39,7 +39,6 @@ export const headercss = css` export const logocss = css` display: flex; - padding-top: 5px; margin-right: 64px; justify-content: center; `; diff --git a/src/app/components/Dialogs/EmbedChartDialog/assets/pdf-icon.svg b/src/app/components/Dialogs/EmbedChartDialog/assets/pdf-icon.svg new file mode 100644 index 000000000..f53317fff --- /dev/null +++ b/src/app/components/Dialogs/EmbedChartDialog/assets/pdf-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/app/components/Dialogs/EmbedChartDialog/assets/png-icon.svg b/src/app/components/Dialogs/EmbedChartDialog/assets/png-icon.svg new file mode 100644 index 000000000..e0fec9192 --- /dev/null +++ b/src/app/components/Dialogs/EmbedChartDialog/assets/png-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx b/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx index 21ff8ee0c..095144442 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/chartContainer.tsx @@ -54,6 +54,9 @@ export default function ChartContainer(props: { font-size: 18px; margin-top: 16px; margin-bottom: 0; + @media (max-width: 599px) { + font-size: 16px; + } } p:nth-of-type(2) { color: #e75656; diff --git a/src/app/components/Dialogs/EmbedChartDialog/index.tsx b/src/app/components/Dialogs/EmbedChartDialog/index.tsx index a6d9481a1..e973a7059 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/index.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/index.tsx @@ -26,7 +26,6 @@ export default function EmbedChartDialog(props: { const token = useStoreState((state) => state.AuthToken.value); const classes = useStyles(); const { user } = useAuth0(); - console.log(props.datasetId, "datasetId"); const { datasetDetails } = useLoadDatasetDetails( props.datasetId!, token ?? undefined @@ -115,6 +114,9 @@ export default function EmbedChartDialog(props: { width: 691px; padding: 24px 24px 32px 24px; border-radius: 8px; + @media (max-width: 768px) { + width: 93%; + } `} >
diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx index 22f0cad35..79ba5ec83 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx @@ -29,7 +29,6 @@ import { SubheaderToolbarProps } from "app/modules/chart-module/components/chart import { ExportChartButton } from "app/modules/chart-module/components/chartSubheaderToolbar/exportButton"; import { ISnackbarState } from "app/modules/dataset-module/routes/upload-module/upload-steps/previewFragment"; import { chartFromReportAtom } from "app/state/recoil/atoms"; -import { InfoSnackbar } from "app/modules/chart-module/components/chartSubheaderToolbar/infoSnackbar"; import { getRequiredFieldsAndErrors } from "../../routes/mapping/utils"; import AutoSaveSwitch from "app/modules/report-module/components/reportSubHeaderToolbar/autoSaveSwitch"; import useAutosave from "app/hooks/useAutoSave"; @@ -37,10 +36,15 @@ import { useStyles } from "app/modules/report-module/components/reportSubHeaderT import AutoResizeInput from "app/modules/report-module/components/reportSubHeaderToolbar/autoResizeInput"; import { isEqual } from "lodash"; import EmbedChartDialog from "app/components/Dialogs/EmbedChartDialog"; +import useMediaQuery from "@material-ui/core/useMediaQuery"; +import DuplicateMessage from "app/modules/common/mobile-duplicate-message"; +import { InfoSnackbar } from "app/modules/report-module/components/reportSubHeaderToolbar/infosnackbar"; export function ChartSubheaderToolbar(props: Readonly) { const classes = useStyles(); const history = useHistory(); + const isMobile = useMediaQuery("(max-width: 599px)"); + const isSmallScreen = useMediaQuery("(max-width: 800px)"); //at this breakpoint, we limit user creation abilities const { user, isAuthenticated } = useAuth0(); const token = useStoreState((state) => state.AuthToken.value); const titleRef = React.useRef(null); @@ -248,7 +252,12 @@ export function ChartSubheaderToolbar(props: Readonly) { props.onSave(); history.push(`/chart/${page}`); }; + const handleViewDuplicatedChart = () => { + setSnackbarState({ ...snackbarState, open: false }); + history.push(`/chart/${duplicatedChartId}`); + setDuplicatedChartId(null); + }; const handleBackToEdit = () => { history.go(-1); }; @@ -345,14 +354,7 @@ export function ChartSubheaderToolbar(props: Readonly) { />
-
+
{editChartLoading && canChartEditDelete && (
) { )} {page !== "new" && !view && ( - + {!isSmallScreen && ( + + )} {isAuthenticated && ( ) {
- {canChartEditDelete && ( + {canChartEditDelete && !isSmallScreen && ( )} - {canChartEditDelete && ( + {canChartEditDelete && !isSmallScreen && ( ) {
- setSnackbarState({ ...snackbarState, open: false })} - message={`Chart has been duplicated successfully!`} - key={snackbarState.vertical + snackbarState.horizontal} - action={ - - } - /> + + setSnackbarState({ ...snackbarState, open: false }) + } + name={loadedChart.name} + type="chart" + /> + + ) : ( + setSnackbarState({ ...snackbarState, open: false })} + message={`Chart has been duplicated successfully!`} + key={snackbarState.vertical + snackbarState.horizontal} + action={ + + } + /> + )} + void; + action: () => void; + type: "data" | "chart" | "report"; +}) { + return ( +
+

+ {props.name}{" "} + + + +

+

+ The {props.type} has been successfully duplicated. You can find the + duplicated version in the library. +

+ +
+ ); +} diff --git a/src/app/modules/dataset-module/assets/copy-icon.svg b/src/app/modules/dataset-module/assets/copy-icon.svg new file mode 100644 index 000000000..a4bed4e03 --- /dev/null +++ b/src/app/modules/dataset-module/assets/copy-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/app/modules/dataset-module/assets/share-icon.svg b/src/app/modules/dataset-module/assets/share-icon.svg new file mode 100644 index 000000000..64a4def2d --- /dev/null +++ b/src/app/modules/dataset-module/assets/share-icon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx b/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx index a4fe33d51..1f47f172f 100644 --- a/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx +++ b/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx @@ -5,8 +5,8 @@ import { Popover, Snackbar, Tooltip, + useMediaQuery, } from "@material-ui/core"; -import { LinkIcon } from "app/assets/icons/Link"; import FileCopyIcon from "@material-ui/icons/FileCopy"; import ShareIcon from "@material-ui/icons/Share"; import EditIcon from "@material-ui/icons/Edit"; @@ -17,24 +17,30 @@ import CopyToClipboard from "react-copy-to-clipboard"; import { Link, useHistory, useParams } from "react-router-dom"; import { useAuth0 } from "@auth0/auth0-react"; import axios from "axios"; -import { useStoreActions, useStoreState } from "app/state/store/hooks"; /** Project */ +import { LinkIcon } from "app/assets/icons/Link"; +import { useStoreActions, useStoreState } from "app/state/store/hooks"; import { styles } from "app/modules/dataset-module/component/styles"; import DeleteDatasetDialog from "app/components/Dialogs/deleteDatasetDialog"; import { ISnackbarState } from "app/modules/dataset-module/routes/upload-module/upload-steps/previewFragment"; import { InfoSnackbar } from "app/modules/report-module/components/reportSubHeaderToolbar/infosnackbar"; import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; +import ShareModal from "./shareModal"; +import DuplicateMessage from "app/modules/common/mobile-duplicate-message"; export default function DatasetSubHeaderToolbar( props: Readonly<{ name: string }> ) { const { user, isAuthenticated } = useAuth0(); const history = useHistory(); + const isMobile = useMediaQuery("(max-width: 599px)"); const { page } = useParams<{ page: string }>(); const token = useStoreState((state) => state.AuthToken.value); const [anchorEl, setAnchorEl] = React.useState( null ); + const [isShareModalOpen, setIsShareModalOpen] = + React.useState(false); const [openSnackbar, setOpenSnackbar] = React.useState(false); const [enableButton, setEnableButton] = React.useState(false); const [modalDisplay, setModalDisplay] = React.useState(false); @@ -56,6 +62,7 @@ export default function DatasetSubHeaderToolbar( (state) => (state.dataThemes.DatasetGet.crudData ?? {}) as DatasetListItemAPIModel ); + const shareURL = `${window.location.origin}/dataset/${datasetDetails.id}/detail`; const loadDatasets = useStoreActions( (actions) => actions.dataThemes.DatasetGetList.fetch ); @@ -77,6 +84,13 @@ export default function DatasetSubHeaderToolbar( }); } }, [token, page]); + + const handleBackToDataset = () => { + setSnackbarState({ ...snackbarState, open: false }); + history.push(`/dataset/${duplicatedDatasetId}/detail`); + setDuplicatedDatasetId(null); + }; + const handleDuplicate = () => { axios .get(`${process.env.REACT_APP_API}/dataset/duplicate/${page}`, { @@ -93,15 +107,21 @@ export default function DatasetSubHeaderToolbar( }) .catch((error) => console.log(error)); }; + const handleCloseSnackbar = () => { setOpenSnackbar(false); }; - const handleClose = () => { + const handleCloseSharePopup = () => { setAnchorEl(null); }; - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); + + const handleSharePopup = (event: React.MouseEvent) => { + if (isMobile) { + setIsShareModalOpen(true); + } else { + setAnchorEl(event.currentTarget); + } }; const handleCopy = (text: string, result: boolean) => { @@ -134,7 +154,7 @@ export default function DatasetSubHeaderToolbar(
- setSnackbarState({ ...snackbarState, open: false })} - message={`Dataset has been duplicated successfully!`} - key={snackbarState.vertical + snackbarState.horizontal} - action={ - - } + {isMobile ? ( + setSnackbarState({ ...snackbarState, open: false })} + key={snackbarState.vertical + snackbarState.horizontal} + > + + setSnackbarState({ ...snackbarState, open: false }) + } + name={datasetDetails.name} + type="data" + /> + + ) : ( + setSnackbarState({ ...snackbarState, open: false })} + message={`Dataset has been duplicated successfully!`} + key={snackbarState.vertical + snackbarState.horizontal} + action={} + /> + )} + +

)} - + @@ -205,7 +245,7 @@ export default function DatasetSubHeaderToolbar( id={popoverId} open={open} anchorEl={anchorEl} - onClose={handleClose} + onClose={handleCloseSharePopup} anchorOrigin={{ vertical: "bottom", horizontal: "right", @@ -230,14 +270,14 @@ export default function DatasetSubHeaderToolbar(

- {canDatasetEditDelete && ( + {canDatasetEditDelete && !isMobile && ( )} - {canDatasetEditDelete && ( + {canDatasetEditDelete && !isMobile && ( diff --git a/src/app/modules/dataset-module/component/shareModal.tsx b/src/app/modules/dataset-module/component/shareModal.tsx new file mode 100644 index 000000000..01442b477 --- /dev/null +++ b/src/app/modules/dataset-module/component/shareModal.tsx @@ -0,0 +1,166 @@ +import React from "react"; +import Modal from "@material-ui/core/Modal"; +import { CloseOutlined } from "@material-ui/icons"; +import LinkIcon from "@material-ui/icons/Link"; +import { ReactComponent as ShareIconLight } from "app/modules/dataset-module/assets/share-icon.svg"; +import { ReactComponent as CopyIconLight } from "app/modules/dataset-module/assets/copy-icon.svg"; +import { ReactComponent as FacebookIcon } from "app/components/Dialogs/EmbedChartDialog/assets/facebook.svg"; +import { ReactComponent as TwitterIcon } from "app/components/Dialogs/EmbedChartDialog/assets/twitter.svg"; +import { ReactComponent as LinkedinIcon } from "app/components/Dialogs/EmbedChartDialog/assets/linkedIn.svg"; +import { ReactComponent as PNGIcon } from "app/components/Dialogs/EmbedChartDialog/assets/png-icon.svg"; +import { ReactComponent as PDFIcon } from "app/components/Dialogs/EmbedChartDialog/assets/pdf-icon.svg"; +import { shareModalcss } from "app/modules/report-module/components/reportSubHeaderToolbar/infosnackbar"; +import SaveAlt from "@material-ui/icons/SaveAlt"; +import { makeStyles, createStyles } from "@material-ui/core"; +import CopyToClipboard from "react-copy-to-clipboard"; +import { exportPage } from "app/utils/exportPage"; + +const useStyles = makeStyles(() => + createStyles({ + modal: { + display: "flex", + alignItems: "flex-end", + justifyContent: "center", + width: "100%", + height: "100%", + }, + }) +); +export default function ShareModal(props: { + isShareModalOpen: boolean; + setIsShareModalOpen: (val: boolean) => void; + datasetDetails: any; + handleCopy: (text: string, result: boolean) => void; + url: string; +}) { + const classes = useStyles(); + function handleTypeChange(value: ".svg" | ".png" | ".pdf", filename: string) { + if (value === ".png") { + exportPage("png", "#f2f7fd", filename); + } + if (value === ".svg") { + exportPage("svg", "#f2f7fd", filename); + } + if (value === ".pdf") { + exportPage("pdf", "", filename); + } + } + + return ( + props.setIsShareModalOpen(false)} + aria-labelledby="simple-modal-title" + aria-describedby="simple-modal-description" + className={classes.modal} + > +
+

+ + {props.datasetDetails?.name} + {" "} + + props.setIsShareModalOpen(false)} /> + +

+

+ Share via Social Media +

+
+ + + + + + + + + + + +
+
+
+

+ Copy The Link +

+ + + +
+
+

{props.url}

+
+
+
+

+ Download{" "} +

+
+ + + +
+
+
+
+ ); +} diff --git a/src/app/modules/dataset-module/component/styles.ts b/src/app/modules/dataset-module/component/styles.ts index ca3f37e66..81ba51eb6 100644 --- a/src/app/modules/dataset-module/component/styles.ts +++ b/src/app/modules/dataset-module/component/styles.ts @@ -12,6 +12,9 @@ export const styles = { background: #f4f4f4; flex-direction: column; justify-content: center; + @media (max-width: 881px) { + top: 66px; + } `, innercontainer: css` height: 100%; @@ -29,10 +32,16 @@ export const styles = { @media (max-width: 1280px) { margin-left: 0; width: calc(100vw - 400px); + @media (max-width: 700px) { + width: calc(100vw - 337px); + } } @media (max-width: 600px) { - padding: 13px 16px 0 16px; + width: calc(100vw - 153px); + p { + font-size: 20px; + } } `, backToEdit: css` @@ -116,9 +125,12 @@ export const styles = { `, endContainer: css` display: flex; - right: 29px; + right: 17px; position: absolute; gap: 13px; + @media (max-width: 881px) { + right: 11px; + } `, iconbtns: css` display: flex; diff --git a/src/app/modules/dataset-module/routes/datasetDetail/index.tsx b/src/app/modules/dataset-module/routes/datasetDetail/index.tsx index 5a79d989b..fdb124ea9 100644 --- a/src/app/modules/dataset-module/routes/datasetDetail/index.tsx +++ b/src/app/modules/dataset-module/routes/datasetDetail/index.tsx @@ -3,7 +3,7 @@ import { useChartsRawData } from "app/hooks/useChartsRawData"; import React from "react"; import DatasetSubHeaderToolbar from "../../component/datasetSubHeaderToolbar"; import { useStoreActions, useStoreState } from "app/state/store/hooks"; -import { find, get } from "lodash"; +import get from "lodash/get"; import { Container } from "@material-ui/core"; import { useParams } from "react-router-dom"; import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; @@ -95,6 +95,9 @@ export default function DatasetDetail() {
{loadDatasetLoading ? : null} @@ -104,12 +107,8 @@ export default function DatasetDetail() { dataTypes={dataTypes} datasetId={page} dataTotalCount={dataTotalCount} - description={datasetDetails.description} canDatasetEditDelete={canDatasetEditDelete} - title={datasetDetails.name} - dataCategory={datasetDetails.category} - dataSource={datasetDetails.source} - dataSourceURL={datasetDetails.sourceUrl} + datasetDetails={datasetDetails} /> ); diff --git a/src/app/modules/dataset-module/routes/upload-module/style.ts b/src/app/modules/dataset-module/routes/upload-module/style.ts index 1507aa761..b746a1502 100644 --- a/src/app/modules/dataset-module/routes/upload-module/style.ts +++ b/src/app/modules/dataset-module/routes/upload-module/style.ts @@ -100,6 +100,33 @@ export const dataSetsCss = css` text-decoration: none; } `; +export const mobileDescriptioncss = css` + display: none; + @media (max-width: 450px) { + display: flex; + padding: 24px; + flex-direction: column; + align-items: flex-start; + gap: 24px; + border-radius: 10px; + background: #fff; + box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1); + width: 100%; + height: 100%; + div { + p { + margin: 0px; + &:nth-of-type(1) { + color: #231d2c; + font-family: "GothamNarrow-Bold", sans-serif; + } + &:nth-of-type(2) { + font-family: "GothamNarrow-Book", sans-serif; + } + } + } + } +`; export const CssTextField = withStyles({ root: { diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx index 663dcfea2..955ee11e6 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx @@ -1,32 +1,32 @@ import React from "react"; -import { Link, useHistory, useLocation } from "react-router-dom"; -import { dataSetsCss } from "app/modules/dataset-module/routes/upload-module/style"; +import { Link, useLocation } from "react-router-dom"; +import { + dataSetsCss, + mobileDescriptioncss, +} from "app/modules/dataset-module/routes/upload-module/style"; import { useStoreActions } from "app/state/store/hooks"; import { DatasetDataTable } from "app/modules/dataset-module/routes/upload-module/component/table/data-table"; import { CssSnackbar, ISnackbarState } from "./previewFragment"; import { ReactComponent as FullScreenIcon } from "../assets/full-screen.svg"; import { ReactComponent as CloseFullScreenIcon } from "../assets/close-full-screen.svg"; -import { useRecoilState } from "recoil"; -import { homeDisplayAtom } from "app/state/recoil/atoms"; import { ArrowBack } from "@material-ui/icons"; +import { useMediaQuery } from "usehooks-ts"; +import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; +import moment from "moment"; interface Props { data: any[]; stats: any[]; datasetId: string; dataTotalCount: number; - description: string; dataTypes: never[]; canDatasetEditDelete?: boolean; - title: string; - dataCategory: string; - dataSource: string; - dataSourceURL: string; + datasetDetails: DatasetListItemAPIModel; } export default function FinishedFragment(props: Props) { - const history = useHistory(); const location = useLocation(); + const isSmallScreen = useMediaQuery("(max-width: 800px)"); //at this breakpoint, we limit user creation abilities const queryParams = new URLSearchParams(location.search); const reportPage = queryParams.get("page") as string; const fromHome = location.search.includes("fromHome=true"); @@ -88,6 +88,9 @@ export default function FinishedFragment(props: Props) { margin-bottom: 16px; column-gap: 8px; cursor: pointer; + @media (max-width: 450px) { + display: none; + } `} data-cy="dataset-back-to-library-btn" > @@ -110,9 +113,12 @@ export default function FinishedFragment(props: Props) { font-family: "GothamNarrow-Bold", sans-serif; line-height: 19px; margin-top: 19px; + @media (max-width: 450px) { + display: none; + } `} > - {props.description} + {props.datasetDetails.description}
setOpenFullScreenTooltip(true)} onMouseLeave={() => setOpenFullScreenTooltip(false)} @@ -168,56 +177,65 @@ export default function FinishedFragment(props: Props) { font-family: "GothamNarrow-Book", sans-serif; padding: 0; margin: 0; + @media (max-width: 450px) { + font-size: 12px; + } `} > {props.dataTotalCount} rows &{" "} {Object.keys(props.data[0] || {}).length} columns

- - - + + + )}
-

Data Title : {props.title}

-

Data Description : {props.description}

-

Data Category : {props.dataCategory}

-

Data Source : {props.dataSource}

-

Link to data source : {props.dataSourceURL || "NIL"}

+

Data Title : {props.datasetDetails.name}

+

Data Description : {props.datasetDetails.description}

+

Data Category : {props.datasetDetails.category}

+

Data Source : {props.datasetDetails.source}

+

Link to data source : {props.datasetDetails.sourceUrl || "NIL"}

+
+
+
+

Details

+

{props.datasetDetails.description}

+
+
+

category

+ {props.datasetDetails.category} +
+
+
+
+
+

Published date

+

{moment(props.datasetDetails.createdDate).format("MMMM YYYY")}

+
+
+

Last edit time

+

{moment(props.datasetDetails.createdDate).format("MMMM YYYY")}

+
+
diff --git a/src/app/modules/home-module/components/Filter/index.tsx b/src/app/modules/home-module/components/Filter/index.tsx index 908f25835..d8929c786 100644 --- a/src/app/modules/home-module/components/Filter/index.tsx +++ b/src/app/modules/home-module/components/Filter/index.tsx @@ -99,6 +99,7 @@ export default function Filter( width: ${displayIcons ? "100%" : "0"}; height: ${displayIcons ? "auto" : "0"}; transition: all 0.5s ease-in-out 0s; + overflow: hidden; } `} > diff --git a/src/app/modules/onboarding-module/index.tsx b/src/app/modules/onboarding-module/index.tsx index 0fe46eaa1..6a6b1c0ae 100644 --- a/src/app/modules/onboarding-module/index.tsx +++ b/src/app/modules/onboarding-module/index.tsx @@ -1,7 +1,5 @@ import React from "react"; -import Box from "@material-ui/core/Box"; import Grid from "@material-ui/core/Grid"; -import SplitBar from "./component/splibar"; import { useAuth0 } from "@auth0/auth0-react"; import useMediaQuery from "@material-ui/core/useMediaQuery"; import { Route, Switch, useHistory, useLocation } from "react-router-dom"; diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx index df29e7e1d..1c9eff95c 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx @@ -1,6 +1,5 @@ import React from "react"; import axios from "axios"; -import { useRecoilState } from "recoil"; import { useAuth0 } from "@auth0/auth0-react"; import Button from "@material-ui/core/Button"; import SaveIcon from "@material-ui/icons/Save"; @@ -17,9 +16,8 @@ import CopyToClipboard from "react-copy-to-clipboard"; import FileCopyIcon from "@material-ui/icons/FileCopy"; import AutorenewIcon from "@material-ui/icons/Autorenew"; import CloudDoneIcon from "@material-ui/icons/CloudDone"; -import { homeDisplayAtom } from "app/state/recoil/atoms"; import { PageLoader } from "app/modules/common/page-loader"; -import { createStyles, makeStyles } from "@material-ui/core"; +import { createStyles, makeStyles, useMediaQuery } from "@material-ui/core"; import { Link, useHistory, useParams } from "react-router-dom"; import { useStoreActions, useStoreState } from "app/state/store/hooks"; import { ReportModel, emptyReport } from "app/modules/report-module/data"; @@ -34,6 +32,8 @@ import StaticToolbar from "app/modules/report-module/components/reportSubHeaderT import AutoSaveSwitch from "app/modules/report-module/components/reportSubHeaderToolbar/autoSaveSwitch"; import AutoResizeInput from "app/modules/report-module/components/reportSubHeaderToolbar/autoResizeInput"; import { InfoSnackbar } from "app/modules/report-module/components/reportSubHeaderToolbar/infosnackbar"; +import ShareModal from "app/modules/dataset-module/component/shareModal"; +import DuplicateMessage from "app/modules/common/mobile-duplicate-message"; export const useStyles = makeStyles(() => createStyles({ @@ -57,6 +57,8 @@ export function ReportSubheaderToolbar( const history = useHistory(); const classes = useStyles(); const { user, isAuthenticated } = useAuth0(); + const isMobile = useMediaQuery("(max-width: 599px)"); + const isSmallScreen = useMediaQuery("(max-width: 800px)"); //at this breakpoint, we limit user creation abilities const titleRef = React.useRef(null); const { page, view } = useParams<{ page: string; view?: string }>(); const token = useStoreState((state) => state.AuthToken.value); @@ -76,7 +78,8 @@ export function ReportSubheaderToolbar( vertical: "bottom", horizontal: "center", }); - + const [isShareModalOpen, setIsShareModalOpen] = + React.useState(false); const [savedChanges, setSavedChanges] = React.useState(false); const loadReports = useStoreActions( @@ -85,6 +88,7 @@ export function ReportSubheaderToolbar( const loadedReport = useStoreState( (state) => (state.reports.ReportGet.crudData ?? emptyReport) as ReportModel ); + const shareURL = `${window.location.origin}/report/${loadedReport.id}`; const loadedChart = useStoreState( (state) => @@ -134,8 +138,12 @@ export function ReportSubheaderToolbar( } }; - const handleClick = (event: React.MouseEvent) => { - setAnchorEl(event.currentTarget); + const handleSharePopup = (event: React.MouseEvent) => { + if (isMobile) { + setIsShareModalOpen(true); + } else { + setAnchorEl(event.currentTarget); + } }; const handleClose = () => { @@ -218,6 +226,12 @@ export function ReportSubheaderToolbar( .catch((error) => console.log(error)); }; + const handleViewDuplocatedReport = () => { + setSnackbarState({ ...snackbarState, open: false }); + history.push(`/report/${duplicatedReportId}`); + setDuplicatedReportId(null); + }; + const canReportEditDelete = React.useMemo(() => { return isAuthenticated && loadedReport && loadedReport.owner === user?.sub; }, [user, isAuthenticated, loadedChart, loadedReport]); @@ -258,7 +272,7 @@ export function ReportSubheaderToolbar( placeholder="Title" autoResize={true} maxWidth={(titleRef.current?.offsetWidth ?? 1000) - 100} - spanBuffer={150} + spanBuffer={isMobile ? 0 : 150} minWidth={200} spanVisibility={inputSpanVisibiltiy} setSpanVisibility={setInputSpanVisibility} @@ -415,7 +429,9 @@ export function ReportSubheaderToolbar( )} {page !== "new" && !view && (
- + {!isSmallScreen && ( + + )} @@ -463,7 +479,7 @@ export function ReportSubheaderToolbar(
- {canReportEditDelete && ( + {canReportEditDelete && !isSmallScreen && ( )} - {canReportEditDelete && ( + {canReportEditDelete && !isSmallScreen && ( )} - setSnackbarState({ ...snackbarState, open: false })} - message={`Report has been duplicated successfully!`} - key={snackbarState.vertical + snackbarState.horizontal} - action={ - - } + + setSnackbarState({ ...snackbarState, open: false }) + } + name={loadedReport.name} + type="report" + /> + + ) : ( + setSnackbarState({ ...snackbarState, open: false })} + message={`Report has been duplicated successfully!`} + key={snackbarState.vertical + snackbarState.horizontal} + action={ + + } + /> + )} + + )` && { - bottom: 40px; + bottom: 8px; + @media (max-width: 900px) { + width: 80%; + } + @media (max-width: 660px) { + width: 90%; + } + @media (max-width: 599px) { + width: 100%; + left: auto; + right: auto; + bottom: 0px; + } } & [class*="MuiSnackbarContent-root"] { @@ -17,9 +29,12 @@ export const InfoSnackbar = styled((props) => )` justify-content: center; box-shadow: 0 8px 17px -4px rgba(130, 142, 148, 0.35), 0 0 4px 0 rgba(130, 142, 148, 0.16), 0 0 2px 0 rgba(130, 142, 148, 0.12); - - @media (max-width: 550px) { - width: calc(100% - 16px); + @media (max-width: 880px) { + gap: 24px; + } + @media (max-width: 599px) { + height: 280px; + border-radius: 20px 20px 0px 0px; } } @@ -29,6 +44,7 @@ export const InfoSnackbar = styled((props) => )` padding: 16px 0; font-weight: 700; font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; + white-space: nowrap; } & [class*="MuiSnackbarContent-action"] { @@ -40,6 +56,7 @@ export const InfoSnackbar = styled((props) => )` padding: 12px 27px; background: #262c34; border-radius: 20px; + white-space: nowrap; } } @@ -47,3 +64,171 @@ export const InfoSnackbar = styled((props) => )` padding: 16px 0; } `; + +export const shareModalcss = css` + border-radius: 20px 20px 0px 0px; + background: #fff; + width: 100%; + display: flex; + padding: 24px; + flex-direction: column; + align-items: flex-start; + justify-content: center; + gap: 16px; + color: #231d2c; + > p:nth-of-type(1) { + margin: 0px; + display: flex; + align-items: flex-start; + justify-content: space-between; + width: 100%; + span:nth-child(1) { + color: #231d2c; + font-family: "GothamNarrow-Bold", sans-serif; + font-size: 24px; + font-weight: 400; + display: -webkit-box; + max-width: 90%; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + } + > p:nth-of-type(2) { + margin: 0px; + display: flex; + align-items: center; + gap: 8px; + } + > div:nth-of-type(1) { + display: flex; + align-items: center; + gap: 16px; + justify-content: center; + a { + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + background: #3d5a96; + display: flex; + justify-content: center; + align-items: center; + } + + a:nth-of-type(2) { + background: #000000; + } + } + > div:nth-of-type(2) { + width: 100%; + div:nth-child(1) { + display: flex; + justify-content: space-between; + align-items: center; + p { + display: flex; + align-items: center; + gap: 8px; + margin: 0; + } + button { + outline: none; + border: none; + background-color: transparent; + display: flex; + align-items: center; + justify-content: center; + /* width: 100%; + height: 100%; */ + } + } + div:nth-child(2) { + padding: 13px; + } + } + > div:nth-of-type(3) { + p { + margin: 0; + display: flex; + align-items: center; + gap: 8px; + color: #231d2c; + font-family: "GothamNarrow-Book", sans-serif; + } + div { + display: flex; + gap: 16px; + margin-top: 10.5px; + button { + display: flex; + align-items: center; + justify-content: start; + gap: 8px; + border: none; + outline: none; + background: #dfe3e5; + color: #000; + font-family: "GothamNarrow-Book", sans-serif; + text-transform: uppercase; + border-radius: 10px; + width: 115.3px; + height: 37px; + cursor: pointer; + } + } + } +`; +export const InfoSnackbarDuplicateContentcss = css` + border-radius: 20px 20px 0px 0px; + background: #fff; + height: 224px; + width: 100%; + display: flex; + padding: 24px; + flex-direction: column; + align-items: flex-start; + justify-content: center; + gap: 16px; + p:nth-of-type(1) { + margin: 0px; + display: flex; + align-items: flex-start; + justify-content: space-between; + width: 100%; + span:nth-child(1) { + color: #231d2c; + font-family: "GothamNarrow-Bold", sans-serif; + font-size: 24px; + font-weight: 400; + display: -webkit-box; + max-width: 90%; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; + } + } + p:nth-of-type(2) { + color: #231d2c; + margin: 0px; + font-family: "GothamNarrow-Book", sans-serif; + } + button { + border: none; + outline: none; + display: flex; + width: 100%; + height: 46px; + justify-content: center; + align-items: center; + border-radius: 8px; + background: #231d2c; + color: #fff; + text-align: right; + font-family: "GothamNarrow-Medium", sans-serif; + font-size: 14px; + text-transform: uppercase; + } +`; diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/styles.ts b/src/app/modules/report-module/components/reportSubHeaderToolbar/styles.ts index 4acc5f427..4f331ecdb 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/styles.ts +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/styles.ts @@ -14,6 +14,9 @@ export const styles = { flex-direction: column; justify-content: center; align-items: center; + @media (max-width: 881px) { + top: 66px; + } `, innercontainer: css` display: flex; @@ -23,11 +26,7 @@ export const styles = { @media (max-width: 1280px) { margin-left: 0; - width: calc(100vw - 400px); - } - - @media (max-width: 600px) { - padding: 13px 16px 0 16px; + width: 100%; } `, viewReportBtn: css` @@ -108,6 +107,9 @@ export const styles = { z-index: 2; padding-left: 0px; outline: none; + @media (max-width: 600px) { + font-size: 20px; + } `, endContainer: css` display: flex; @@ -144,6 +146,9 @@ export const styles = { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + @media (max-width: 600px) { + font-size: 20px; + } `, highlightPicker: (active: boolean) => css` vertical-align: bottom; diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index 8ee7aee5a..a67159960 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -271,6 +271,18 @@ export default function HeaderBlock(props: Props) { } } } + @media (max-width: 1024px) { + width: 100%; + } + @media (max-width: 600px) { + max-height: 100%; + overflow-y: hidden; + display: -webkit-box; + width: 100%; + min-width: unset; + -webkit-line-clamp: 6; + -webkit-box-orient: vertical; + } `} > Date: Mon, 19 Aug 2024 12:03:57 +0100 Subject: [PATCH 21/58] style: responsiveness for detail pages --- src/app/modules/common/RichEditor/editorStyles.module.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/modules/common/RichEditor/editorStyles.module.css b/src/app/modules/common/RichEditor/editorStyles.module.css index 8257b1050..cccd2b07c 100644 --- a/src/app/modules/common/RichEditor/editorStyles.module.css +++ b/src/app/modules/common/RichEditor/editorStyles.module.css @@ -9,8 +9,8 @@ width: 100%; } @media (max-width: 1024px) { - .editor{ - max-width:100% !important; + .editor { + max-width: 100% !important; } } From 65a3015d87a939085714e2b3a56cc39e9ba3f72e Mon Sep 17 00:00:00 2001 From: okorie2 Date: Wed, 21 Aug 2024 20:04:57 +0100 Subject: [PATCH 22/58] style: report builder responsiveness --- .../chartSubheaderToolbar/index.tsx | 76 ++++++++--------- .../common/RichEditor/buttonStyles.module.css | 82 +++---------------- .../RichEditor/toolbarStyles.module.css | 23 ++++++ .../__test__/headerBlock.test.tsx | 2 + .../autoResizeInput/index.tsx | 3 + .../reportSubHeaderToolbar/index.tsx | 64 ++++++++++++--- .../reportSubHeaderToolbar/styles.ts | 9 ++ src/app/modules/report-module/index.tsx | 6 +- .../components/headerBlock/index.tsx | 10 +++ .../sub-module/rowStructure/index.tsx | 6 +- .../rowStructure/rowStructureDisplay.tsx | 33 ++++++-- .../sub-module/rowStructure/style.ts | 4 + .../report-module/views/create/data.ts | 3 +- .../report-module/views/create/index.tsx | 5 +- .../modules/report-module/views/edit/data.ts | 3 +- .../report-module/views/edit/index.tsx | 8 +- .../report-module/views/initial/data.tsx | 10 ++- .../report-module/views/initial/index.tsx | 11 +-- .../report-module/views/preview/index.tsx | 1 + 19 files changed, 217 insertions(+), 142 deletions(-) diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx index 79ba5ec83..5491fa363 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx @@ -15,6 +15,7 @@ import Container from "@material-ui/core/Container"; import IconButton from "@material-ui/core/IconButton"; import AutorenewIcon from "@material-ui/icons/Autorenew"; import CloudDoneIcon from "@material-ui/icons/CloudDone"; +import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos"; import CopyToClipboard from "react-copy-to-clipboard"; import FileCopyIcon from "@material-ui/icons/FileCopy"; import { PageLoader } from "app/modules/common/page-loader"; @@ -271,42 +272,7 @@ export function ChartSubheaderToolbar(props: Readonly) { return (
{createChartLoading && } - setShowSnackbar(null)} - open={showSnackbar !== null && showSnackbar !== ""} - > - - {!location.pathname.includes("report") && ( - - )} - - } - /> - - +
) { position: relative; `} > + {isMobile && history.go(-1)} />} ) { /> )} - + setShowSnackbar(null)} + open={showSnackbar !== null && showSnackbar !== ""} + > + + {!location.pathname.includes("report") && ( + + )} + + } + /> + + >; setReportName?: React.Dispatch>; reportName?: string; + handleRightPanelOpen: () => void; setPlugins: React.Dispatch>; headerDetails: { title: string; @@ -79,6 +80,7 @@ const defaultProps = (props: Partial): MockProps => { descriptionColor: "#000", dateColor: "#000", }, + handleRightPanelOpen: jest.fn(), setHeaderDetails: jest.fn( (newHeaderDetails) => (headerDetailsResult.headerDetails = newHeaderDetails) diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/autoResizeInput/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/autoResizeInput/index.tsx index 887458df4..34dd19c24 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/autoResizeInput/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/autoResizeInput/index.tsx @@ -106,6 +106,9 @@ export default function AutoResizeInput(props: InputProps) { visibility: ${spanVisibility ? "visible" : "hidden"}; max-width: ${autoResize ? `calc(100% - ${spanBuffer}px)` : "100%"}; margin-left: -0.8px; + @media (max-width: 1200px) { + max-width: 100%; + } `} > {` ${name}`} diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx index 1c9eff95c..a07d70951 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx @@ -11,6 +11,7 @@ import { LinkIcon } from "app/assets/icons/Link"; import Snackbar from "@material-ui/core/Snackbar"; import DeleteIcon from "@material-ui/icons/Delete"; import Container from "@material-ui/core/Container"; +import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos"; import IconButton from "@material-ui/core/IconButton"; import CopyToClipboard from "react-copy-to-clipboard"; import FileCopyIcon from "@material-ui/icons/FileCopy"; @@ -244,16 +245,7 @@ export function ReportSubheaderToolbar( return (
{createOrEditChartLoading && } - +
+ {isMobile && history.go(-1)} />} {view === "edit" && ( @@ -407,6 +410,35 @@ export function ReportSubheaderToolbar( setAutoSave={props.setAutoSave} />
+ {view === "edit" && ( + + + + + + + + + )} )} + css` @@ -167,5 +173,8 @@ export const styles = { &:hover { background: #f2f2f2; } + @media (max-width: 1050px) { + width: 24px; + } `, }; diff --git a/src/app/modules/report-module/index.tsx b/src/app/modules/report-module/index.tsx index 757759826..fbe15084d 100644 --- a/src/app/modules/report-module/index.tsx +++ b/src/app/modules/report-module/index.tsx @@ -454,7 +454,8 @@ export default function ReportModule() { setRightPanelOpen(true)} view={view} setReportName={setReportName} reportName={reportName} @@ -471,7 +472,8 @@ export default function ReportModule() { setRightPanelOpen(true)} autoSave={autoSave.isAutoSaveEnabled} reportType={reportType} setHasChangesBeenMade={setHasChangesBeenMade} diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index a67159960..77872cda0 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -23,6 +23,7 @@ interface Props { setHasSubHeaderTitleFocused?: React.Dispatch>; setReportName?: React.Dispatch>; reportName?: string; + handleRightPanelOpen: () => void; setPlugins: React.Dispatch>; headerDetails: { title: string; @@ -123,6 +124,7 @@ export default function HeaderBlock(props: Props) { const onEdit = () => { setCurrentView("editHeader"); + props.handleRightPanelOpen(); }; const onRemove = () => { @@ -165,6 +167,14 @@ export default function HeaderBlock(props: Props) { gap: 4px; z-index: 101; position: absolute; + @media (max-width: 881px) { + top: 16.5px; + svg { + rect { + height: 91%; + } + } + } `} > diff --git a/src/app/modules/report-module/sub-module/rowStructure/index.tsx b/src/app/modules/report-module/sub-module/rowStructure/index.tsx index a146fe871..4f5761c2c 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/index.tsx +++ b/src/app/modules/report-module/sub-module/rowStructure/index.tsx @@ -146,7 +146,6 @@ interface IRowStructureType { export default function RowFrame(props: RowFrameProps) { const history = useHistory(); - const { handleRowFrameItemResize } = usehandleRowFrameItemResize( props.updateFramesArray ); @@ -394,6 +393,7 @@ export default function RowFrame(props: RowFrameProps) { onRowBoxItemResize={onRowBoxItemResize} setPlugins={props.setPlugins} onSave={props.onSave} + forceSelectedType={props.forceSelectedType} /> ), oneByTwo: ( @@ -416,6 +416,7 @@ export default function RowFrame(props: RowFrameProps) { onRowBoxItemResize={onRowBoxItemResize} setPlugins={props.setPlugins} onSave={props.onSave} + forceSelectedType={props.forceSelectedType} /> ), oneByThree: ( @@ -438,6 +439,7 @@ export default function RowFrame(props: RowFrameProps) { onRowBoxItemResize={onRowBoxItemResize} setPlugins={props.setPlugins} onSave={props.onSave} + forceSelectedType={props.forceSelectedType} /> ), oneByFour: ( @@ -460,6 +462,7 @@ export default function RowFrame(props: RowFrameProps) { setPlugins={props.setPlugins} onSave={props.onSave} previewItems={props.previewItems} + forceSelectedType={props.forceSelectedType} /> ), oneByFive: ( @@ -482,6 +485,7 @@ export default function RowFrame(props: RowFrameProps) { onRowBoxItemResize={onRowBoxItemResize} setPlugins={props.setPlugins} onSave={props.onSave} + forceSelectedType={props.forceSelectedType} /> ), }; diff --git a/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx b/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx index 1d076a3df..67ade1e31 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx +++ b/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx @@ -28,6 +28,7 @@ import { IFramesArray } from "../../views/create/data"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; import { css } from "styled-components"; import { Updater } from "use-immer"; +import { useMediaQuery } from "@material-ui/core"; interface RowStructureDisplayProps { gap: string; @@ -58,6 +59,7 @@ interface RowStructureDisplayProps { ) => void; setPlugins: React.Dispatch>; onSave: (type: "create" | "edit") => Promise; + forceSelectedType: string | undefined; } export default function RowstructureDisplay(props: RowStructureDisplayProps) { @@ -66,7 +68,7 @@ export default function RowstructureDisplay(props: RowStructureDisplayProps) { const { page } = useParams<{ page: string }>(); const [handleDisplay, setHandleDisplay] = React.useState(false); const [reportPreviewMode] = useRecoilState(unSavedReportPreviewModeAtom); - + const smScreen = useMediaQuery("(max-width: 850px)"); const viewOnlyMode = (page !== "new" && get(location.pathname.split("/"), "[3]", "") !== "edit") || @@ -224,6 +226,13 @@ export default function RowstructureDisplay(props: RowStructureDisplayProps) { overflow: hidden; gap: ${props.gap}; border: ${border}; + @media (max-width: 768px) { + display: grid; + grid-template-columns: ${props.forceSelectedType === + "oneByFive" || props.forceSelectedType === "oneByFour" + ? " auto auto" + : "auto"}; + } `} data-cy={`row-frame-${props.rowIndex}`} > @@ -272,7 +281,7 @@ const Box = (props: { const location = useLocation(); const history = useHistory(); const { page, view } = useParams<{ page: string; view: string }>(); - + const smScreen = useMediaQuery("(max-width: 768px)"); const setDataset = useStoreActions( (actions) => actions.charts.dataset.setValue ); @@ -525,7 +534,10 @@ const Box = (props: { grid={[5, 5]} onResize={onResize} onResizeStop={onResizeStop} - size={{ width: width, height: `${props.height}px` }} + size={{ + width: smScreen ? "100%" : width, + height: `height: 100%`, + }} maxWidth={!viewOnlyMode ? containerWidth : undefined} minWidth={78} enable={{ @@ -604,7 +616,10 @@ const Box = (props: { key={chartId} onResize={onResize} onResizeStop={onResizeStop} - size={{ width: width, height: `${props.height}px` }} + size={{ + width: smScreen ? "100%" : width, + height: `${props.height}px`, + }} maxWidth={!viewOnlyMode ? containerWidth : undefined} minWidth={78} enable={{ @@ -707,7 +722,10 @@ const Box = (props: { grid={[5, 5]} onResize={onResize} onResizeStop={onResizeStop} - size={{ width: width, height: `${props.height}px` }} + size={{ + width: smScreen ? "100%" : width, + height: `${props.height}px`, + }} maxWidth={!viewOnlyMode ? containerWidth : undefined} minWidth={78} enable={{ @@ -789,7 +807,10 @@ const Box = (props: { grid={[5, 5]} onResize={onResize} onResizeStop={onResizeStop} - size={{ width: width, height: `${props.height}px` }} + size={{ + width: smScreen ? "100%" : width, + height: `${props.height}px`, + }} maxWidth={!viewOnlyMode ? containerWidth : undefined} minWidth={78} enable={{ diff --git a/src/app/modules/report-module/sub-module/rowStructure/style.ts b/src/app/modules/report-module/sub-module/rowStructure/style.ts index d7ea97287..b56c2a46d 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/style.ts +++ b/src/app/modules/report-module/sub-module/rowStructure/style.ts @@ -29,6 +29,10 @@ export const containercss = css` padding: 5px 40px; position: relative; border: 1px dashed #adb5bd; + @media (max-width: 1440px) { + height: 100%; + padding-bottom: 20px; + } p { font-size: 12px; diff --git a/src/app/modules/report-module/views/create/data.ts b/src/app/modules/report-module/views/create/data.ts index d023e2358..7bd3fc0c1 100644 --- a/src/app/modules/report-module/views/create/data.ts +++ b/src/app/modules/report-module/views/create/data.ts @@ -26,7 +26,8 @@ export interface IFramesArray { } export interface ReportCreateViewProps { - open: boolean; + rightPanelOpen: boolean; + handleRightPanelOpen: () => void; view: "initial" | "edit" | "create" | "preview" | "ai-template"; setReportName: React.Dispatch>; reportName: string; diff --git a/src/app/modules/report-module/views/create/index.tsx b/src/app/modules/report-module/views/create/index.tsx index 3af600cea..983e403cf 100644 --- a/src/app/modules/report-module/views/create/index.tsx +++ b/src/app/modules/report-module/views/create/index.tsx @@ -113,6 +113,7 @@ function ReportCreateView(props: Readonly) { reportName={props.reportName} hasSubHeaderTitleFocused={props.hasSubHeaderTitleFocused} setPlugins={props.setPlugins} + handleRightPanelOpen={props.handleRightPanelOpen} />
) { css={` position: relative; transition: width 225ms cubic-bezier(0, 0, 0.2, 1) 0ms; - width: ${props.open + width: ${props.rightPanelOpen ? "calc(100vw - ((100vw - 1280px) / 2) - 400px - 50px)" : "100%"}; @@ -133,7 +134,7 @@ function ReportCreateView(props: Readonly) { {}} open /> diff --git a/src/app/modules/report-module/views/edit/data.ts b/src/app/modules/report-module/views/edit/data.ts index 8d867dcfd..6d35f339d 100644 --- a/src/app/modules/report-module/views/edit/data.ts +++ b/src/app/modules/report-module/views/edit/data.ts @@ -4,7 +4,8 @@ import { ToolbarPluginsType } from "app/modules/report-module/components/reportS import { Updater } from "use-immer"; export interface ReportEditViewProps { - open: boolean; + rightPanelOpen: boolean; + handleRightPanelOpen: () => void; reportType: "basic" | "advanced" | "ai" | null; isSaveEnabled: boolean; view: "initial" | "edit" | "create" | "preview" | "ai-template"; diff --git a/src/app/modules/report-module/views/edit/index.tsx b/src/app/modules/report-module/views/edit/index.tsx index 91ea04c12..3a2025140 100644 --- a/src/app/modules/report-module/views/edit/index.tsx +++ b/src/app/modules/report-module/views/edit/index.tsx @@ -319,6 +319,7 @@ function ReportEditView(props: ReportEditViewProps) { setHasSubHeaderTitleFocused={props.setHasSubHeaderTitleFocused} setHeaderDetails={props.setHeaderDetails} setPlugins={props.setPlugins} + handleRightPanelOpen={props.handleRightPanelOpen} />
diff --git a/src/app/modules/report-module/views/initial/data.tsx b/src/app/modules/report-module/views/initial/data.tsx index 414ffaf98..55e51c2ec 100644 --- a/src/app/modules/report-module/views/initial/data.tsx +++ b/src/app/modules/report-module/views/initial/data.tsx @@ -54,7 +54,7 @@ export const TemplateItem = ({
) { useTitle("DX Dataxplorer - New Report"); const history = useHistory(); - + const isMobile = useMediaQuery("(max-width: 599px)"); const [reportsView, setReportsView] = React.useState<"grid" | "table">( "grid" ); @@ -90,9 +91,9 @@ function ReportInitialView(props: Readonly) { height: 48px; `} /> - + {templates.map((option) => ( - + ) { margin-bottom: 44px; `} > - +

) { Explore or duplicate reports

- + {}} setHeaderDetails={() => {}} + handleRightPanelOpen={() => {}} /> From cd6d6bd3093bd45eaeca534aee4284d83023a8ad Mon Sep 17 00:00:00 2001 From: okorie2 Date: Wed, 21 Aug 2024 20:06:11 +0100 Subject: [PATCH 23/58] style: report builder responsiveness --- .../common/RichEditor/buttonStyles.module.css | 7 +++-- .../RichEditor/toolbarStyles.module.css | 28 ++++++++++--------- .../report-module/views/edit/index.tsx | 5 ++-- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/app/modules/common/RichEditor/buttonStyles.module.css b/src/app/modules/common/RichEditor/buttonStyles.module.css index 339fca9ab..5ddebc77f 100644 --- a/src/app/modules/common/RichEditor/buttonStyles.module.css +++ b/src/app/modules/common/RichEditor/buttonStyles.module.css @@ -31,9 +31,10 @@ @media (min-width: 801px) { @media (max-width: 853px) { - .button { - width: 30px; - }} + .button { + width: 30px; + } + } } @media (max-width: 1055px) { .button { diff --git a/src/app/modules/common/RichEditor/toolbarStyles.module.css b/src/app/modules/common/RichEditor/toolbarStyles.module.css index 24b3a8326..733d69ce7 100644 --- a/src/app/modules/common/RichEditor/toolbarStyles.module.css +++ b/src/app/modules/common/RichEditor/toolbarStyles.module.css @@ -15,22 +15,24 @@ .toolbar { padding: 6px 9px; gap: 6px; - }} -} -@media (min-width: 921px){ - @media (max-width: 1083px){ - .toolbar { - padding: 6px 14px; - gap: 11px; - }} + } + } } -@media (min-width: 1084px){ -@media (max-width: 1109px){ - .toolbar { - padding: 6px 13px; - gap: 13px; +@media (min-width: 921px) { + @media (max-width: 1083px) { + .toolbar { + padding: 6px 14px; + gap: 11px; + } } } +@media (min-width: 1084px) { + @media (max-width: 1109px) { + .toolbar { + padding: 6px 13px; + gap: 13px; + } + } } .toolbar button { diff --git a/src/app/modules/report-module/views/edit/index.tsx b/src/app/modules/report-module/views/edit/index.tsx index 3a2025140..54fdc1ad2 100644 --- a/src/app/modules/report-module/views/edit/index.tsx +++ b/src/app/modules/report-module/views/edit/index.tsx @@ -327,9 +327,10 @@ function ReportEditView(props: ReportEditViewProps) { id="content-container" css={` transition: width 225ms cubic-bezier(0, 0, 0.2, 1) 0ms; - width: ${props.rightPanelOpen + /* width: ${props.rightPanelOpen ? "calc(100vw - ((100vw - 1280px) / 2) - 400px - 50px)" - : "100%"}; + : "100%"}; */ + width: 100%; position: relative; `} > From 3ce33d0cefba231a7814eac4c4fe098a868789f5 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Fri, 23 Aug 2024 12:14:03 +0100 Subject: [PATCH 24/58] style; wrap up responsiveness --- .../chartSubheaderToolbar/index.tsx | 17 ++++++- .../components/toolbox/steps/navbar/index.tsx | 6 +++ .../components/toolbox/steps/navbar/style.ts | 1 - .../components/toolbox/styles.tsx | 5 ++ src/app/modules/chart-module/index.tsx | 5 ++ .../chart-module/routes/chart-type/index.tsx | 1 + .../chart-module/routes/common/styles.ts | 4 -- .../RichEditor/toolbarStyles.module.css | 14 ++++-- .../routes/upload-module/style.ts | 10 +++- .../upload-steps/addDatasetFragment.tsx | 3 ++ .../upload-steps/finishedFragment.tsx | 2 +- .../upload-module/upload-steps/metaData.tsx | 6 +++ .../AssetCollection/Charts/gridItem.tsx | 50 +++++++++++-------- .../AssetCollection/Datasets/gridItem.tsx | 41 ++++++++------- .../AssetCollection/Reports/gridItem.tsx | 39 ++++++++------- .../components/AssetCollection/index.tsx | 31 +++++++++--- .../home-module/components/Filter/index.tsx | 40 +-------------- src/app/modules/home-module/style.ts | 11 +++- .../components/chart-wrapper/index.tsx | 1 + .../reportSubHeaderToolbar/index.tsx | 19 ++++--- .../reportSubHeaderToolbar/styles.ts | 5 ++ .../rowStructure/rowStructureDisplay.tsx | 6 +-- .../report-module/views/edit/index.tsx | 5 +- 23 files changed, 192 insertions(+), 130 deletions(-) diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx index 5491fa363..2191a5ce6 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx @@ -45,7 +45,7 @@ export function ChartSubheaderToolbar(props: Readonly) { const classes = useStyles(); const history = useHistory(); const isMobile = useMediaQuery("(max-width: 599px)"); - const isSmallScreen = useMediaQuery("(max-width: 800px)"); //at this breakpoint, we limit user creation abilities + const isSmallScreen = useMediaQuery("(max-width:788px)"); //at this breakpoint, we limit user creation abilities const { user, isAuthenticated } = useAuth0(); const token = useStoreState((state) => state.AuthToken.value); const titleRef = React.useRef(null); @@ -283,6 +283,21 @@ export function ChartSubheaderToolbar(props: Readonly) { gap: 12px; width: 72%; position: relative; + @media (min-width: 768px) { + @media (max-width: 828px) { + width: ${canChartEditDelete ? "50%" : "90%"}; + } + } + @media (min-width: 829px) { + @media (max-width: 1040px) { + width: 55%; + } + } + @media (min-width: 1041px) { + @media (max-width: 1373px) { + width: 64%; + } + } `} > {isMobile && history.go(-1)} />} diff --git a/src/app/modules/chart-module/components/toolbox/steps/navbar/index.tsx b/src/app/modules/chart-module/components/toolbox/steps/navbar/index.tsx index f63fac503..6424ceb69 100644 --- a/src/app/modules/chart-module/components/toolbox/steps/navbar/index.tsx +++ b/src/app/modules/chart-module/components/toolbox/steps/navbar/index.tsx @@ -61,6 +61,12 @@ export default function ToolboxNav( css={` background: #f5f5f7; display: flex; + height: 67px; + @media (min-width: 768px) { + @media (max-width: 881px) { + height: 50px; + } + } `} > {navContent.map((item, index) => ( diff --git a/src/app/modules/chart-module/components/toolbox/steps/navbar/style.ts b/src/app/modules/chart-module/components/toolbox/steps/navbar/style.ts index 11403c297..61e296762 100644 --- a/src/app/modules/chart-module/components/toolbox/steps/navbar/style.ts +++ b/src/app/modules/chart-module/components/toolbox/steps/navbar/style.ts @@ -2,7 +2,6 @@ import { css } from "styled-components"; export const stepcss = (activeStep: boolean) => css` width: 79px; - height: 67px; display: flex; justify-content: center; align-items: center; diff --git a/src/app/modules/chart-module/components/toolbox/styles.tsx b/src/app/modules/chart-module/components/toolbox/styles.tsx index 394132678..2e1cb77b6 100644 --- a/src/app/modules/chart-module/components/toolbox/styles.tsx +++ b/src/app/modules/chart-module/components/toolbox/styles.tsx @@ -28,6 +28,11 @@ export const styles = { font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; } } + @media (min-width: 768px) { + @media (max-width: 881px) { + top: 113px; + } + } `, contentlist: css` width: 100%; diff --git a/src/app/modules/chart-module/index.tsx b/src/app/modules/chart-module/index.tsx index 5c5ad8cf9..bff7e23e2 100644 --- a/src/app/modules/chart-module/index.tsx +++ b/src/app/modules/chart-module/index.tsx @@ -576,6 +576,11 @@ export default function ChartModule() { : "100%"}; transition: width 225ms cubic-bezier(0, 0, 0.2, 1) 0ms; + @media (min-width: 768px) { + @media (max-width: 1024px) { + width: 100%; + } + } `} ref={ref} > diff --git a/src/app/modules/chart-module/routes/chart-type/index.tsx b/src/app/modules/chart-module/routes/chart-type/index.tsx index 810e68b22..ca9ac8140 100644 --- a/src/app/modules/chart-module/routes/chart-type/index.tsx +++ b/src/app/modules/chart-module/routes/chart-type/index.tsx @@ -255,6 +255,7 @@ function ChartBuilderChartType(props: Readonly) { align-items: center; justify-content: end; gap: 5px; + flex-shrink: 0; span { color: #000000; font-size: 12px; diff --git a/src/app/modules/chart-module/routes/common/styles.ts b/src/app/modules/chart-module/routes/common/styles.ts index aed52010e..9731b774c 100644 --- a/src/app/modules/chart-module/routes/common/styles.ts +++ b/src/app/modules/chart-module/routes/common/styles.ts @@ -12,10 +12,6 @@ export const styles = { padding: 67px 0px 0 0; align-self: flex-start; min-height: calc(100vh - 98px); - - @media (max-width: 1280px) { - width: calc(100vw - 400px); - } `, previewInnercontainer: (isEditMode: boolean) => css` left: 0; diff --git a/src/app/modules/common/RichEditor/toolbarStyles.module.css b/src/app/modules/common/RichEditor/toolbarStyles.module.css index 733d69ce7..c544610d5 100644 --- a/src/app/modules/common/RichEditor/toolbarStyles.module.css +++ b/src/app/modules/common/RichEditor/toolbarStyles.module.css @@ -10,11 +10,19 @@ align-items: center; gap: 14px; } +@media (min-width: 768px) { + @media (max-width: 800px) { + .toolbar { + padding: 5px 13px; + gap: 5px; + } + } +} @media (min-width: 801px) { @media (max-width: 920px) { .toolbar { - padding: 6px 9px; - gap: 6px; + padding: 6px 3px; + gap: 1%; } } } @@ -22,7 +30,7 @@ @media (max-width: 1083px) { .toolbar { padding: 6px 14px; - gap: 11px; + gap: 1.4%; } } } diff --git a/src/app/modules/dataset-module/routes/upload-module/style.ts b/src/app/modules/dataset-module/routes/upload-module/style.ts index b746a1502..4ae572783 100644 --- a/src/app/modules/dataset-module/routes/upload-module/style.ts +++ b/src/app/modules/dataset-module/routes/upload-module/style.ts @@ -15,7 +15,9 @@ export const stepcss = css` background: #f4f4f4; gap: 1rem; @media (min-width: 768px) { - height: 50px; + @media (max-width: 881px) { + top: 66px; + } } `; @@ -74,6 +76,12 @@ export const metaDatacss = css` font-family: "Inter", sans-serif; margin-bottom: 4.5rem; + @media (min-width: 768px) { + @media (max-width: 1024px) { + margin-top: 10px; + margin-bottom: 3.5rem; + } + } } button { border-radius: 30px; diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx index 4ca755770..b2e08b801 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/addDatasetFragment.tsx @@ -199,6 +199,9 @@ export default function AddDatasetFragment(props: Props) { background: #dadaf84d; border-radius: 16px 16px 0px 0px; width: 100%; + @media (max-width: 1024px) { + margin-bottom: 40px; + } `} > Connect your data diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx index 955ee11e6..2c2c66600 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx @@ -26,7 +26,7 @@ interface Props { export default function FinishedFragment(props: Props) { const location = useLocation(); - const isSmallScreen = useMediaQuery("(max-width: 800px)"); //at this breakpoint, we limit user creation abilities + const isSmallScreen = useMediaQuery("(max-width:767px)"); //at this breakpoint, we limit user creation abilities const queryParams = new URLSearchParams(location.search); const reportPage = queryParams.get("page") as string; const fromHome = location.search.includes("fromHome=true"); diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/metaData.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/metaData.tsx index 2d5a78178..1ecfd4bce 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/metaData.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/metaData.tsx @@ -290,6 +290,12 @@ export default function MetaData(props: Readonly) { justify-content: flex-end; margin-top: 12rem; gap: 1rem; + @media (min-width: 768px) { + @media (max-width: 13004px) { + margin-top: 4rem; + padding-bottom: 10px; + } + } `} >
-
- - - - - -
+ + + + + +
+ )}
) { React.useState(false); const setIsAiSwitchActive = useRecoilState(isChartAIAgentActive)[1]; const { user, isAuthenticated } = useAuth0(); + const isMobile = useMediaQuery("(max-width: 767px)"); const showMenuOptions = (e: React.MouseEvent) => { e.preventDefault(); @@ -256,7 +257,7 @@ export default function GridItem(props: Readonly) { display: flex; height: 38px; - width: 143px; + padding: 0 23px; position: absolute; background: #adb5bd; border-radius: 100px; @@ -298,23 +299,25 @@ export default function GridItem(props: Readonly) {
-
- - - - - -
+ {!isMobile && ( +
+ + + + + +
+ )}
) => { e.preventDefault(); e.stopPropagation(); @@ -203,7 +204,7 @@ export default function gridItem(props: Props) { display: flex; height: 38px; - width: 143px; + padding: 0 23px; background: #adb5bd; border-radius: 100px; align-items: center; @@ -249,21 +250,25 @@ export default function gridItem(props: Props) {
-
- - - - - -
+ {!isMobile && ( +
+ + + + + +
+ )}
{isAuthenticated ? ( - +

Welcome {user?.given_name ?? user?.name?.split(" ")[0]}

@@ -178,9 +182,12 @@ function AssetsCollection() { alignItems="center" css={` width: 100%; + @media (max-width: 599px) { + flex-flow: wrap-reverse; + } `} > - + - + + +
diff --git a/src/app/modules/home-module/components/Filter/index.tsx b/src/app/modules/home-module/components/Filter/index.tsx index d8929c786..11db9c99f 100644 --- a/src/app/modules/home-module/components/Filter/index.tsx +++ b/src/app/modules/home-module/components/Filter/index.tsx @@ -29,7 +29,7 @@ export default function Filter( }> ) { const inputRef = React.useRef(null); - const [displayIcons, setDisplayIcons] = React.useState(false); + const [displayIcons, setDisplayIcons] = React.useState(true); const [sortPopoverAnchorEl, setSortPopoverAnchorEl] = React.useState(null); const handleCloseSortPopover = () => { @@ -58,49 +58,11 @@ export default function Filter( gap: 8px; `} > -
- -
css` diff --git a/src/app/modules/report-module/components/chart-wrapper/index.tsx b/src/app/modules/report-module/components/chart-wrapper/index.tsx index 11197beb3..9bb6a3258 100644 --- a/src/app/modules/report-module/components/chart-wrapper/index.tsx +++ b/src/app/modules/report-module/components/chart-wrapper/index.tsx @@ -214,6 +214,7 @@ export function ReportChartWrapper(props: Props) { font-size: 14px; color: #231d2c; letter-spacing: 0.5px; + word-break: break-all; `} > {chartName} diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx index a07d70951..11afdaabb 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx @@ -59,7 +59,7 @@ export function ReportSubheaderToolbar( const classes = useStyles(); const { user, isAuthenticated } = useAuth0(); const isMobile = useMediaQuery("(max-width: 599px)"); - const isSmallScreen = useMediaQuery("(max-width: 800px)"); //at this breakpoint, we limit user creation abilities + const isTabletView = useMediaQuery("(min-width: 768px)"); //at this breakpoint, we limit user creation abilities const titleRef = React.useRef(null); const { page, view } = useParams<{ page: string; view?: string }>(); const token = useStoreState((state) => state.AuthToken.value); @@ -256,6 +256,11 @@ export function ReportSubheaderToolbar( gap: 28px; position: relative; width: 70%; + @media (min-width: 768px) { + @media (max-width: 800px) { + width: 48%; + } + } @media (min-width: 801px) { @media (max-width: 1199px) { width: 49%; @@ -302,7 +307,7 @@ export function ReportSubheaderToolbar( display: flex; flex-shrink: 0; gap: 12px; - @media (min-width: 801px) { + @media (min-width: 768px) { @media (max-width: 1200px) { display: none; } @@ -420,7 +425,7 @@ export function ReportSubheaderToolbar( opacity: 0.5; } display: none; - @media (min-width: 801px) { + @media (min-width: 768px) { @media (max-width: 1200px) { display: block; } @@ -461,9 +466,7 @@ export function ReportSubheaderToolbar( )} {page !== "new" && !view && (
- {!isSmallScreen && ( - - )} + {isTabletView && }
- {canReportEditDelete && !isSmallScreen && ( + {canReportEditDelete && isTabletView && ( )} - {canReportEditDelete && !isSmallScreen && ( + {canReportEditDelete && isTabletView && ( (); - const smScreen = useMediaQuery("(max-width: 768px)"); + const smScreen = useMediaQuery("(max-width: 767px)"); const setDataset = useStoreActions( (actions) => actions.charts.dataset.setValue ); @@ -536,7 +536,7 @@ const Box = (props: { onResizeStop={onResizeStop} size={{ width: smScreen ? "100%" : width, - height: `height: 100%`, + height: `${props.height}px`, }} maxWidth={!viewOnlyMode ? containerWidth : undefined} minWidth={78} diff --git a/src/app/modules/report-module/views/edit/index.tsx b/src/app/modules/report-module/views/edit/index.tsx index 54fdc1ad2..3a2025140 100644 --- a/src/app/modules/report-module/views/edit/index.tsx +++ b/src/app/modules/report-module/views/edit/index.tsx @@ -327,10 +327,9 @@ function ReportEditView(props: ReportEditViewProps) { id="content-container" css={` transition: width 225ms cubic-bezier(0, 0, 0.2, 1) 0ms; - /* width: ${props.rightPanelOpen + width: ${props.rightPanelOpen ? "calc(100vw - ((100vw - 1280px) / 2) - 400px - 50px)" - : "100%"}; */ - width: 100%; + : "100%"}; position: relative; `} > From cde2e68ee6b4abd97678201e65bacd2203e7d810 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Sun, 25 Aug 2024 21:24:59 +0100 Subject: [PATCH 25/58] test: update unit & e2e tests --- cypress/e2e/1-dx/2-datasets.cy.ts | 14 +- package.json | 2 + .../component/externalSourcesList.tsx | 1 - .../upload-steps/externalSearch.tsx | 4 + .../__test__/reportSubheaderToolbar.test.tsx | 668 +++++++++--------- .../reportSubHeaderToolbar/index.tsx | 4 +- src/app/utils/setMediaQueryForTest.ts | 20 + yarn.lock | 10 + 8 files changed, 398 insertions(+), 325 deletions(-) create mode 100644 src/app/utils/setMediaQueryForTest.ts diff --git a/cypress/e2e/1-dx/2-datasets.cy.ts b/cypress/e2e/1-dx/2-datasets.cy.ts index 7865bba97..1b967c5a4 100644 --- a/cypress/e2e/1-dx/2-datasets.cy.ts +++ b/cypress/e2e/1-dx/2-datasets.cy.ts @@ -33,6 +33,9 @@ describe("Testing connecting data on DX", () => { it("Can filter results by source in the federated search", () => { cy.wait("@getDefaultData").then((interception) => { + cy.wait(2000); + cy.contains('[data-cy="source-category-button"]', "Kaggle").click(); + cy.wait("@getDefaultData"); cy.get('[data-cy="external-search-card-Kaggle"]').should( "have.length.greaterThan", 1 @@ -49,6 +52,9 @@ describe("Testing connecting data on DX", () => { it("Can import data from External Search", () => { cy.wait("@getDefaultData").then((interception) => { + cy.wait(2000); + cy.contains('[data-cy="source-category-button"]', "Kaggle").click(); + cy.wait("@getDefaultData"); cy.get('[data-cy="external-search-card-Kaggle"]').should( "have.length.greaterThan", 1 @@ -56,11 +62,11 @@ describe("Testing connecting data on DX", () => { }); cy.get('[data-cy="open-search-button"]').click(); - cy.intercept(`${apiUrl}/external-sources/search?q=world%20population*`).as( - "getDefaultData2" - ); + cy.intercept( + `${apiUrl}/external-sources/search?q=Exclusive%20breastfeeding*` + ).as("getDefaultData2"); cy.wait(2000); - cy.get('[data-cy="filter-search-input"]').type("world population"); + cy.get('[data-cy="filter-search-input"]').type("Exclusive breastfeeding"); cy.wait("@getDefaultData2").then((interception) => { cy.get('[data-cy="external-search-card-Kaggle"]').should( diff --git a/package.json b/package.json index 8c3cbe550..d62f202a1 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "@types/react-router-hash-link": "^2.4.0", "auth0-js": "^9.23.3", "axios": "0.24.0", + "css-mediaquery": "^0.1.2", "d3-hierarchy": "^3.1.2", "detect-it": "^4.0.1", "dom-to-image": "^2.6.0", @@ -90,6 +91,7 @@ }, "devDependencies": { "@testing-library/user-event": "14.5.2", + "@types/css-mediaquery": "^0.1.4", "@types/d3-hierarchy": "^3.1.6", "@types/jest": "^29.5.12", "@types/node": "^14.14.41", diff --git a/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx b/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx index e2103d191..b85d633a3 100644 --- a/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/component/externalSourcesList.tsx @@ -18,7 +18,6 @@ export default function SourceCategoryList(props: Readonly) {
{ diff --git a/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx b/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx index 14f496f6d..f32d02382 100644 --- a/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx +++ b/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx @@ -30,6 +30,7 @@ import { } from "app/state/api/action-reducers/reports"; import axios, { AxiosResponse } from "axios"; import { ReportSubheaderToolbar } from "../components/reportSubHeaderToolbar"; +import { setMediaQueryForTest } from "app/utils/setMediaQueryForTest"; interface MockProps { name: string; @@ -165,371 +166,402 @@ const appSetup = (params: Params, newProps: Partial = {}) => { }; //test cases +describe("Tests for tablet and desktop view", () => { + beforeEach(() => { + setMediaQueryForTest(768); + }); + test("focusing on input should call setHasSubHeaderTitleFocused", async () => { + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + const { app, props } = appSetup({ mockActions: false }); + render(app); + screen.getByRole("textbox").focus(); + expect(props.setHasSubHeaderTitleFocused).toHaveBeenCalledWith(true); + }); -test("focusing on input should call setHasSubHeaderTitleFocused", async () => { - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - const { app, props } = appSetup({ mockActions: false }); - render(app); - screen.getByRole("textbox").focus(); - expect(props.setHasSubHeaderTitleFocused).toHaveBeenCalledWith(true); -}); - -test("blurring on input should call setHasSubHeaderTitleBlurred", async () => { - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - const { app, props } = appSetup({ mockActions: false }); - render(app); - screen.getByRole("textbox").focus(); - screen.getByRole("textbox").blur(); - expect(props.setHasSubHeaderTitleBlurred).toHaveBeenCalledWith(true); -}); - -test("clicking on input when value is Untitled report should clear the input", async () => { - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - const { app, props } = appSetup({ mockActions: false }); - render(app); - screen.getByRole("textbox").focus(); - fireEvent.change(screen.getByRole("textbox"), { - target: { value: "new title" }, + test("blurring on input should call setHasSubHeaderTitleBlurred", async () => { + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + const { app, props } = appSetup({ mockActions: false }); + render(app); + screen.getByRole("textbox").focus(); + screen.getByRole("textbox").blur(); + expect(props.setHasSubHeaderTitleBlurred).toHaveBeenCalledWith(true); }); - fireEvent.click(screen.getByRole("textbox")); - expect(screen.getByRole("textbox")).toHaveValue(""); -}); -test("typing on input should edit report title", async () => { - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "n65e6d7498ad6100d2b27bd5cew", view: "edit" }); - const initialRecoilState = (snap: MutableSnapshot) => { - snap.set(chartFromReportAtom, { - state: true, - page: "65dcb26aaf4c8500693f1ab7", - action: "edit", - view: "edit", - chartId: null, + test("clicking on input when value is Untitled report should clear the input", async () => { + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + const { app, props } = appSetup({ mockActions: false }); + render(app); + screen.getByRole("textbox").focus(); + fireEvent.change(screen.getByRole("textbox"), { + target: { value: "new title" }, }); - }; - const { app, props } = appSetup({ mockActions: false, initialRecoilState }); - render(app); - - screen.getByRole("textbox").focus(); - fireEvent.change(screen.getByRole("textbox"), { - target: { value: "new title" }, + fireEvent.click(screen.getByRole("textbox")); + expect(screen.getByRole("textbox")).toHaveValue(""); }); - expect(mockSetValues.name).toBe("new title"); -}); -test("clicking view report button should save report and go to report detail page", async () => { - const user = userEvent.setup(); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - - const { app, props } = appSetup({ mockActions: false }); - render(app); - const viewReportButton = screen.getByRole("button", { - name: /view report button/, - }); - await user.click(viewReportButton); - await waitFor(() => { - expect(props.onReportSave).toHaveBeenCalledWith("edit"); - expect(history.location.pathname).toBe("/report/65dcb26aaf4c8500693f1ab7"); + test("typing on input should edit report title", async () => { + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "n65e6d7498ad6100d2b27bd5cew", view: "edit" }); + const initialRecoilState = (snap: MutableSnapshot) => { + snap.set(chartFromReportAtom, { + state: true, + page: "65dcb26aaf4c8500693f1ab7", + action: "edit", + view: "edit", + chartId: null, + }); + }; + const { app, props } = appSetup({ mockActions: false, initialRecoilState }); + render(app); + + screen.getByRole("textbox").focus(); + fireEvent.change(screen.getByRole("textbox"), { + target: { value: "new title" }, + }); + expect(mockSetValues.name).toBe("new title"); }); -}); -test("autosave switch should toggle autosave state from false to true", async () => { - const user = userEvent.setup(); + test("clicking view report button should save report and go to report detail page", async () => { + const user = userEvent.setup(); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - const { app, props } = appSetup({ mockActions: false }); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - render(app); + const { app, props } = appSetup({ mockActions: false }); + render(app); + const viewReportButton = screen.getByRole("button", { + name: /view report button/i, + }); + await user.click(viewReportButton); + await waitFor(() => { + expect(props.onReportSave).toHaveBeenCalledWith("edit"); + expect(history.location.pathname).toBe( + "/report/65dcb26aaf4c8500693f1ab7" + ); + }); + }); - expect(screen.getByTestId("auto-save-switch")).not.toBeChecked(); + test("clicking view report button in tablet view should save report and go to report detail page", async () => { + const user = userEvent.setup(); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - await user.click(screen.getByTestId("auto-save-switch")); - expect(props.setAutoSave).toHaveBeenCalledWith({ - isAutoSaveEnabled: true, - enableAutoSaveSwitch: true, + const { app, props } = appSetup({ mockActions: false }); + render(app); + const viewReportButton = screen.getByRole("button", { + name: /view-report-button-tablet/i, + }); + await user.click(viewReportButton); + await waitFor(() => { + expect(props.onReportSave).toHaveBeenCalledWith("edit"); + expect(history.location.pathname).toBe( + "/report/65dcb26aaf4c8500693f1ab7" + ); + }); }); - expect(mockSetValues.autoSave).toBeTruthy(); -}); -test("autosave switch should toggle autosave state from true to false", async () => { - const user = userEvent.setup(); + test("autosave switch should toggle autosave state from false to true", async () => { + const user = userEvent.setup(); - const { app, props } = appSetup({ mockActions: false }, { autoSave: true }); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - render(app); - expect(screen.getByTestId("auto-save-switch")).toBeChecked(); + const { app, props } = appSetup({ mockActions: false }); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + render(app); - await user.click(screen.getByTestId("auto-save-switch")); - expect(props.setAutoSave).toHaveBeenCalledWith({ - isAutoSaveEnabled: false, - enableAutoSaveSwitch: true, - }); - expect(mockSetValues.autoSave).toBeFalsy(); -}); + expect(screen.getByTestId("auto-save-switch")).not.toBeChecked(); -test("save button should be disabled when user has performed no action", async () => { - const { app, props } = appSetup({ mockActions: false }); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - render(app); + await user.click(screen.getByTestId("auto-save-switch")); + expect(props.setAutoSave).toHaveBeenCalledWith({ + isAutoSaveEnabled: true, + enableAutoSaveSwitch: true, + }); + expect(mockSetValues.autoSave).toBeTruthy(); + }); - expect(screen.getByRole("button", { name: /save button/ })).toBeDisabled(); -}); + test("autosave switch should toggle autosave state from true to false", async () => { + const user = userEvent.setup(); -test("save button should be enabled when user has performed an action", async () => { - const { app, props } = appSetup( - { mockActions: false }, - { isSaveEnabled: true } - ); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - render(app); + const { app, props } = appSetup({ mockActions: false }, { autoSave: true }); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + render(app); + expect(screen.getByTestId("auto-save-switch")).toBeChecked(); - expect(screen.getByRole("button", { name: /save button/ })).toBeEnabled(); -}); + await user.click(screen.getByTestId("auto-save-switch")); + expect(props.setAutoSave).toHaveBeenCalledWith({ + isAutoSaveEnabled: false, + enableAutoSaveSwitch: true, + }); + expect(mockSetValues.autoSave).toBeFalsy(); + }); -test("save button should call onReportSave when clicked", async () => { - const user = userEvent.setup(); - const { app, mockStore, props } = appSetup( - { mockActions: true }, - { isSaveEnabled: true } - ); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - render(app); + test("save button should be disabled when user has performed no action", async () => { + const { app, props } = appSetup({ mockActions: false }); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + render(app); - await user.click(screen.getByRole("button", { name: /save button/ })); - expect(props.onReportSave).toHaveBeenCalledWith("edit"); -}); + expect(screen.getByRole("button", { name: /save button/ })).toBeDisabled(); + }); -test("savedChanges state should be true after edit success", async () => { - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: true } - ); + test("save button should be enabled when user has performed an action", async () => { + const { app, props } = appSetup( + { mockActions: false }, + { isSaveEnabled: true } + ); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + render(app); + + expect(screen.getByRole("button", { name: /save button/ })).toBeEnabled(); + }); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); - render(app); - await act(async () => { - mockStore.getActions().reports.ReportUpdate.onSuccess([]); + test("save button should call onReportSave when clicked", async () => { + const user = userEvent.setup(); + const { app, mockStore, props } = appSetup( + { mockActions: true }, + { isSaveEnabled: true } + ); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + render(app); + + await user.click(screen.getByRole("button", { name: /save button/ })); + expect(props.onReportSave).toHaveBeenCalledWith("edit"); }); - expect(mockStore.getState().reports.ReportUpdate.success).toBeTruthy(); - expect(screen.getByText(/All changes saved/)).toBeVisible(); + test("savedChanges state should be true after edit success", async () => { + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: true } + ); + + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); + render(app); + await act(async () => { + mockStore.getActions().reports.ReportUpdate.onSuccess([]); + }); - // expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 3000); -}); + expect(mockStore.getState().reports.ReportUpdate.success).toBeTruthy(); + expect(screen.getByText(/All changes saved/)).toBeVisible(); -test("export, duplicate, share, edit, delete buttons should be visible in report detail mode", async () => { - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: true } - ); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: undefined }); - act(() => { - mockStore.getActions().reports.ReportGet.setCrudData({ - id: "12345", - name: "test", - owner: "auth0|123", - }); + // expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 3000); }); - render(app); - expect(screen.getByRole("button", { name: "export-button" })).toBeVisible(); - - expect(screen.getByTestId("duplicate-button")).toBeVisible(); - expect(screen.getByTestId("share-button")).toBeVisible(); - expect(screen.getByTestId("edit-button")).toBeVisible(); - expect(screen.getByTestId("delete-button")).toBeVisible(); -}); -test("input field should be disabled in report detail page", async () => { - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: true, isPreviewView: true } - ); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: undefined }); - act(() => { - mockStore.getActions().reports.ReportGet.setCrudData({ - id: "12345", - name: "test", - owner: "auth0|123", + test("input field should be disabled in report detail page", async () => { + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: true, isPreviewView: true } + ); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: undefined }); + act(() => { + mockStore.getActions().reports.ReportGet.setCrudData({ + id: "12345", + name: "test", + owner: "auth0|123", + }); }); + render(app); + expect(screen.getByRole("textbox")).toBeDisabled(); }); - render(app); - expect(screen.getByRole("textbox")).toBeDisabled(); -}); -test("clicking on export button should open export menu", async () => { - const user = userEvent.setup(); - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: true, isPreviewView: true } - ); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: undefined }); - act(() => { - mockStore.getActions().reports.ReportGet.setCrudData({ - id: "12345", - name: "test", - owner: "auth0|123", + test("clicking on export button should open export menu", async () => { + const user = userEvent.setup(); + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: true, isPreviewView: true } + ); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: undefined }); + act(() => { + mockStore.getActions().reports.ReportGet.setCrudData({ + id: "12345", + name: "test", + owner: "auth0|123", + }); }); + render(app); + await user.click(screen.getByRole("button", { name: "export-button" })); + expect(screen.getByRole("menu")).toBeVisible(); + expect(screen.getByText(".png")).toBeVisible(); + expect(screen.getByText(".svg")).toBeVisible(); }); - render(app); - await user.click(screen.getByRole("button", { name: "export-button" })); - expect(screen.getByRole("menu")).toBeVisible(); - expect(screen.getByText(".png")).toBeVisible(); - expect(screen.getByText(".svg")).toBeVisible(); -}); -test("clicking on duplicate button should open duplicate dialog", async () => { - const user = userEvent.setup(); - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: false, isPreviewView: true } - ); - const axiosMock = axios.get as jest.Mock; - - axiosMock - .mockResolvedValueOnce({ data: { id: "12345" } } as AxiosResponse) - .mockResolvedValueOnce({ data: [] }); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "12345", view: undefined }); - act(() => { - mockStore.getActions().reports.ReportGet.setCrudData({ - id: "12345", - name: "test", - owner: "auth0|123", + test("clicking on duplicate button should open duplicate dialog", async () => { + const user = userEvent.setup(); + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: false, isPreviewView: true } + ); + const axiosMock = axios.get as jest.Mock; + + axiosMock + .mockResolvedValueOnce({ data: { id: "12345" } } as AxiosResponse) + .mockResolvedValueOnce({ data: [] }); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "12345", view: undefined }); + act(() => { + mockStore.getActions().reports.ReportGet.setCrudData({ + id: "12345", + name: "test", + owner: "auth0|123", + }); }); - }); - render(app); - await user.click(screen.getByTestId("duplicate-button")); - expect(axiosMock).toHaveBeenCalled(); + render(app); + await user.click(screen.getByTestId("duplicate-button")); + expect(axiosMock).toHaveBeenCalled(); - expect( - screen.getByText("Report has been duplicated successfully!") - ).toBeVisible(); + expect( + screen.getByText("Report has been duplicated successfully!") + ).toBeVisible(); - expect(screen.getByRole("button", { name: "GO TO REPORT" })).toBeVisible(); - await user.click(screen.getByRole("button", { name: "GO TO REPORT" })); - expect( - screen.getByRole("button", { name: "GO TO REPORT" }) - ).not.toBeVisible(); + expect(screen.getByRole("button", { name: "GO TO REPORT" })).toBeVisible(); + await user.click(screen.getByRole("button", { name: "GO TO REPORT" })); + expect( + screen.getByRole("button", { name: "GO TO REPORT" }) + ).not.toBeVisible(); - expect(history.location.pathname).toBe("/report/12345"); -}); + expect(history.location.pathname).toBe("/report/12345"); + }); -test("clicking on share button should open share dialog", async () => { - const user = userEvent.setup(); - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: false, isPreviewView: true } - ); - const axiosMock = axios.get as jest.Mock; - - axiosMock - .mockResolvedValueOnce({ data: { id: "12345" } } as AxiosResponse) - .mockResolvedValueOnce({ data: [] }); - jest.spyOn(window, "prompt").mockImplementation((message) => "Link copied"); - - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "12345", view: undefined }); - act(() => { - mockStore.getActions().reports.ReportGet.setCrudData({ - id: "12345", - name: "test", - owner: "auth0|123", + test("clicking on share button should open share dialog", async () => { + const user = userEvent.setup(); + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: false, isPreviewView: true } + ); + const axiosMock = axios.get as jest.Mock; + + axiosMock + .mockResolvedValueOnce({ data: { id: "12345" } } as AxiosResponse) + .mockResolvedValueOnce({ data: [] }); + jest.spyOn(window, "prompt").mockImplementation((message) => "Link copied"); + + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "12345", view: undefined }); + act(() => { + mockStore.getActions().reports.ReportGet.setCrudData({ + id: "12345", + name: "test", + owner: "auth0|123", + }); }); + render(app); + await user.click(screen.getByTestId("share-button")); + expect(screen.getByRole("button", { name: "Copy link" })).toBeVisible(); + await user.click(screen.getByRole("button", { name: "Copy link" })); + expect(screen.getByText("Link copied to clipboard")).toBeVisible(); }); - render(app); - await user.click(screen.getByTestId("share-button")); - expect(screen.getByRole("button", { name: "Copy link" })).toBeVisible(); - await user.click(screen.getByRole("button", { name: "Copy link" })); - expect(screen.getByText("Link copied to clipboard")).toBeVisible(); -}); -test("clicking on edit button should redirect to report edit page", async () => { - const user = userEvent.setup(); - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: false, isPreviewView: true } - ); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "12345", view: undefined }); - act(() => { - mockStore.getActions().reports.ReportGet.setCrudData({ - id: "12345", - name: "test", - owner: "auth0|123", + test("clicking on edit button should redirect to report edit page", async () => { + const user = userEvent.setup(); + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: false, isPreviewView: true } + ); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "12345", view: undefined }); + act(() => { + mockStore.getActions().reports.ReportGet.setCrudData({ + id: "12345", + name: "test", + owner: "auth0|123", + }); }); + render(app); + await user.click(screen.getByTestId("edit-button")); + expect(history.location.pathname).toBe("/report/12345/edit"); }); - render(app); - await user.click(screen.getByTestId("edit-button")); - expect(history.location.pathname).toBe("/report/12345/edit"); -}); -test("clicking on delete button should open delete dialog", async () => { - const user = userEvent.setup(); - const { app, mockStore } = appSetup( - { mockActions: false }, - { isSaveEnabled: false, isPreviewView: true } - ); + test("clicking on delete button should open delete dialog", async () => { + const user = userEvent.setup(); + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: false, isPreviewView: true } + ); + + const axiosMock = axios.delete as jest.Mock; + const axiosGetMock = axios.get as jest.Mock; + axiosGetMock.mockResolvedValueOnce({ + data: [], + } as AxiosResponse); + + axiosMock.mockResolvedValueOnce({ + data: { id: "12345" }, + } as AxiosResponse); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "12345", view: undefined }); + act(() => { + mockStore.getActions().reports.ReportGet.setCrudData({ + id: "12345", + name: "test", + owner: "auth0|123", + }); + }); + render(app); + await user.click(screen.getByTestId("delete-button")); + expect(screen.getByRole("button", { name: "Delete" })).toBeVisible(); + await user.click(screen.getByRole("button", { name: "Delete" })); + expect(screen.getByRole("form")).toBeInTheDocument(); + expect( + screen.getByText("Absolutely sure you want to delete the report(s)?") + ).toBeVisible(); + const input = screen.getByPlaceholderText('Type "DELETE" to confirm'); + await user.type(input, "DELETE"); + expect(input).toHaveValue("DELETE"); + expect(screen.getByRole("button", { name: "Delete" })).toBeEnabled(); + fireEvent.submit(screen.getByRole("form")); + expect(axiosMock).toHaveBeenCalled(); + }); +}); - const axiosMock = axios.delete as jest.Mock; - const axiosGetMock = axios.get as jest.Mock; - axiosGetMock.mockResolvedValueOnce({ - data: [], - } as AxiosResponse); - - axiosMock.mockResolvedValueOnce({ - data: { id: "12345" }, - } as AxiosResponse); - jest - .spyOn(Router, "useParams") - .mockReturnValue({ page: "12345", view: undefined }); - act(() => { - mockStore.getActions().reports.ReportGet.setCrudData({ - id: "12345", - name: "test", - owner: "auth0|123", +describe("Tests for mobile view", () => { + beforeEach(() => { + setMediaQueryForTest(450); + }); + test("export, share, edit, buttons should not be visible in report detail mode for mobile views", async () => { + const { app, mockStore } = appSetup( + { mockActions: false }, + { isSaveEnabled: true } + ); + jest + .spyOn(Router, "useParams") + .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: undefined }); + act(() => { + mockStore.getActions().reports.ReportGet.setCrudData({ + id: "12345", + name: "test", + owner: "auth0|123", + }); }); + render(app); + expect(screen.queryByRole("button", { name: "export-button" })).toBeNull(); + + expect(screen.getByTestId("duplicate-button")).toBeVisible(); + expect(screen.getByTestId("share-button")).toBeVisible(); + expect(screen.queryByTestId("edit-button")).toBeNull(); + expect(screen.queryByTestId("delete-button")).toBeNull(); }); - render(app); - await user.click(screen.getByTestId("delete-button")); - expect(screen.getByRole("button", { name: "Delete" })).toBeVisible(); - await user.click(screen.getByRole("button", { name: "Delete" })); - expect(screen.getByRole("form")).toBeInTheDocument(); - expect( - screen.getByText("Absolutely sure you want to delete the report(s)?") - ).toBeVisible(); - const input = screen.getByPlaceholderText('Type "DELETE" to confirm'); - await user.type(input, "DELETE"); - expect(input).toHaveValue("DELETE"); - expect(screen.getByRole("button", { name: "Delete" })).toBeEnabled(); - fireEvent.submit(screen.getByRole("form")); - expect(axiosMock).toHaveBeenCalled(); }); diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx index 11afdaabb..29156734a 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx @@ -431,8 +431,8 @@ export function ReportSubheaderToolbar( } } `} - data-cy="view-report-button" - aria-label="view report button" + data-cy="view-report-button-tablet" + aria-label="view-report-button-tablet" > diff --git a/src/app/utils/setMediaQueryForTest.ts b/src/app/utils/setMediaQueryForTest.ts new file mode 100644 index 000000000..e2002cc0b --- /dev/null +++ b/src/app/utils/setMediaQueryForTest.ts @@ -0,0 +1,20 @@ +import React from "react"; +import mediaQuery from "css-mediaquery"; + +function createMatchMedia(width: number) { + return (query: string) => ({ + matches: mediaQuery.match(query, { + width, + }), + addListener: () => {}, + removeListener: () => {}, + media: "", + onchange: () => {}, + addEventListener: () => {}, + removeEventListener: () => {}, + dispatchEvent: () => false, + }); +} +export function setMediaQueryForTest(width: number) { + window.matchMedia = createMatchMedia(width); +} diff --git a/yarn.lock b/yarn.lock index 6c0bd4e08..6237027f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2255,6 +2255,11 @@ dependencies: "@types/node" "*" +"@types/css-mediaquery@^0.1.4": + version "0.1.4" + resolved "https://registry.yarnpkg.com/@types/css-mediaquery/-/css-mediaquery-0.1.4.tgz#8efbebbc0cebaf34c77db2b63892711e19143c63" + integrity sha512-DZyHAz716ZUctpqkUU2COwUoZ4gI6mZK2Q1oIz/fvNS6XHVpKSJgDnE7vRxZUBn9vjJHDVelCVW0dkshKOLFsA== + "@types/d3-hierarchy@^3.1.6": version "3.1.6" resolved "https://registry.yarnpkg.com/@types/d3-hierarchy/-/d3-hierarchy-3.1.6.tgz#8d3638df273ec90da34b3ac89d8784c59708cb0d" @@ -4445,6 +4450,11 @@ css-loader@^6.5.1: postcss-value-parser "^4.1.0" semver "^7.3.5" +css-mediaquery@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/css-mediaquery/-/css-mediaquery-0.1.2.tgz#6a2c37344928618631c54bd33cedd301da18bea0" + integrity sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q== + css-minimizer-webpack-plugin@^3.2.0: version "3.4.1" resolved "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz" From d4c6149b1e0524d89fa8ed3962ff0a47399a9d5e Mon Sep 17 00:00:00 2001 From: okorie2 Date: Mon, 26 Aug 2024 09:55:06 +0100 Subject: [PATCH 26/58] test: fix test --- cypress/e2e/1-dx/2-datasets.cy.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/cypress/e2e/1-dx/2-datasets.cy.ts b/cypress/e2e/1-dx/2-datasets.cy.ts index 1b967c5a4..0ff9e8284 100644 --- a/cypress/e2e/1-dx/2-datasets.cy.ts +++ b/cypress/e2e/1-dx/2-datasets.cy.ts @@ -42,6 +42,7 @@ describe("Testing connecting data on DX", () => { ); }); cy.wait(2000); + cy.contains('[data-cy="source-category-button"]', "Kaggle").click(); cy.contains('[data-cy="source-category-button"]', "WHO").click(); cy.wait("@getDefaultData"); From b2edb646aff8db7287d83b664de5f3284ccf813e Mon Sep 17 00:00:00 2001 From: okorie2 Date: Tue, 27 Aug 2024 14:14:36 +0100 Subject: [PATCH 27/58] chore: minor fixes --- .../home-module/sub-modules/partners/style.ts | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/src/app/modules/home-module/sub-modules/partners/style.ts b/src/app/modules/home-module/sub-modules/partners/style.ts index 61a520d97..0f3c94006 100644 --- a/src/app/modules/home-module/sub-modules/partners/style.ts +++ b/src/app/modules/home-module/sub-modules/partners/style.ts @@ -10,7 +10,7 @@ export const empowercss = (view: string) => css` background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #f2f7fd 100%); background-repeat: no-repeat; background-size: 100% 100%, auto; - overflow-x: hidden; + overflow: hidden; z-index: 0; @media (max-width: 641px) { height: 100%; @@ -165,12 +165,7 @@ export const quotecss = css` font-size: 40px; line-height: 48px; text-align: center; -<<<<<<< HEAD - font-family: "GothamNarrow-Medium", sans-serif; -======= font-family: "GothamNarrow-Medium", "Helvetica Neue", sans-serif; - ->>>>>>> db32d54e69ebec5355e034485b0f6fbce32a5cef margin: 0; @media (max-width: 1024px) { font-size: 34px; @@ -195,15 +190,11 @@ export const quotecss = css` font-size: 16px; line-height: 19px; text-align: center; -<<<<<<< HEAD - font-family: "GothamNarrow-Bold", sans-serif; + font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; @media (max-width: 1024px) { font-size: 14px; line-height: 16.8px; } -======= - font-family: "GothamNarrow-Bold", "Helvetica Neue", sans-serif; ->>>>>>> db32d54e69ebec5355e034485b0f6fbce32a5cef } } `; From 256b1997037672ed5a9c4e00548ac2ed634a5a0d Mon Sep 17 00:00:00 2001 From: okorie2 Date: Tue, 27 Aug 2024 14:38:08 +0100 Subject: [PATCH 28/58] style: responsiveness updates --- .../routes/preview-theme/index.tsx | 36 +++++++++++++++++++ .../routes/upload-module/style.ts | 2 +- .../upload-steps/finishedFragment.tsx | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/app/modules/chart-module/routes/preview-theme/index.tsx b/src/app/modules/chart-module/routes/preview-theme/index.tsx index 4df1136ed..238b09b88 100644 --- a/src/app/modules/chart-module/routes/preview-theme/index.tsx +++ b/src/app/modules/chart-module/routes/preview-theme/index.tsx @@ -17,6 +17,8 @@ import ErrorComponent from "app/modules/chart-module/components/dialog/errrorCom import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; import { getDatasetDetailsSource } from "app/modules/chart-module/util/getDatasetDetailsSource"; import { ChartAPIModel } from "app/modules/chart-module/data"; +import { mobileDescriptioncss } from "app/modules/dataset-module/routes/upload-module/style"; +import moment from "moment"; export function ChartBuilderPreviewTheme(props: ChartBuilderPreviewThemeProps) { useTitle("DX Dataxplorer - Preview Chart"); @@ -323,6 +325,40 @@ export function ChartBuilderPreviewTheme(props: ChartBuilderPreviewThemeProps) { )} +
+
+

Source

+

{datasetDetails.description}

+
+
+
+
+
+

Published date

+

{moment(datasetDetails.createdDate).format("MMMM YYYY")}

+
+
+

Last edit time

+

{moment(datasetDetails.createdDate).format("MMMM YYYY")}

+
+
+
); } diff --git a/src/app/modules/dataset-module/routes/upload-module/style.ts b/src/app/modules/dataset-module/routes/upload-module/style.ts index 478264c90..4a3521db4 100644 --- a/src/app/modules/dataset-module/routes/upload-module/style.ts +++ b/src/app/modules/dataset-module/routes/upload-module/style.ts @@ -110,7 +110,7 @@ export const dataSetsCss = css` `; export const mobileDescriptioncss = css` display: none; - @media (max-width: 450px) { + @media (max-width: 500px) { display: flex; padding: 24px; flex-direction: column; diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx index 2454aa0dd..8361df1fe 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/finishedFragment.tsx @@ -346,7 +346,7 @@ export default function FinishedFragment(props: Props) {
Date: Wed, 4 Sep 2024 14:03:44 +0100 Subject: [PATCH 29/58] chore: update livesession tag --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index b85e74b3d..5c1f22bc8 100644 --- a/public/index.html +++ b/public/index.html @@ -192,7 +192,7 @@ window["__ls_script_url"], window["__ls_namespace"] ); - __ls("init", "2db6e1f8.44426a15", { keystrokes: false }); + __ls("init", "2db6e1f8.99b8c0c5", { keystrokes: false }); __ls("newPageView"); } From 42dbe7de58777d73290930ed9178b76cb43212ab Mon Sep 17 00:00:00 2001 From: okorie2 Date: Wed, 4 Sep 2024 15:46:44 +0100 Subject: [PATCH 30/58] chore: use livesession sdk --- package.json | 1 + public/index.html | 4 ++-- src/app/Routes.tsx | 2 ++ src/app/hooks/useRouteListener.ts | 16 ++++++++++++++++ yarn.lock | 5 +++++ 5 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/app/hooks/useRouteListener.ts diff --git a/package.json b/package.json index d62f202a1..23717e610 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "@draft-js-plugins/text-alignment": "^2.0.1", "@draft-js-plugins/undo": "^4.1.3", "@hookform/resolvers": "^3.3.0", + "@livesession/sdk": "^1.1.4", "@material-ui/core": "^4.11.3", "@material-ui/icons": "^4.11.2", "@material-ui/lab": "^4.0.0-alpha.57", diff --git a/public/index.html b/public/index.html index 5c1f22bc8..e96acf79c 100644 --- a/public/index.html +++ b/public/index.html @@ -157,7 +157,7 @@ - --> diff --git a/src/app/Routes.tsx b/src/app/Routes.tsx index 634ee6df3..98f9741c6 100755 --- a/src/app/Routes.tsx +++ b/src/app/Routes.tsx @@ -5,6 +5,7 @@ import React, { Suspense, lazy } from "react"; import { socialAuth } from "app/utils/socialAuth"; import { useScrollToTop } from "app/hooks/useScrollToTop"; +import { useRouteListener } from "app/hooks/useRouteListener"; import { PageLoader } from "app/modules/common/page-loader"; import { RouteWithAppBar } from "app/utils/RouteWithAppBar"; import { Route, Switch, useHistory } from "react-router-dom"; @@ -218,6 +219,7 @@ const IntercomBootupComponent = () => { export function MainRoutes() { useScrollToTop(); + useRouteListener(); return ( { + const location = useLocation(); + + React.useEffect(() => { + if (window.location.hostname === "dataxplorer.org") { + ls.init(process.env.REACT_APP_LIVE_SESSION_ID as string); + ls.newPageView(); + } + }, [location.pathname]); + + return null; +}; diff --git a/yarn.lock b/yarn.lock index 6237027f1..2332158fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1729,6 +1729,11 @@ resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.4.0.tgz#08d6c5e20cf7e4cc02fd181c4b0c225cd31dbb60" integrity sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA== +"@livesession/sdk@^1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@livesession/sdk/-/sdk-1.1.4.tgz#e8c020faffe4b51308a6b0bf404a1871f246a595" + integrity sha512-xyiDd3M9wx5k586BIQRcVxSJP5/2XWF9Ca1seLGRSaFoV8o270p5Mn5kpceZFN4STzlYubiMcrPZFFSNWEceVw== + "@material-ui/core@^4.11.3": version "4.12.3" resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.12.3.tgz" From 78c8d9b7d3438a20e25287d7431cdfa37dacd249 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Wed, 4 Sep 2024 16:56:37 +0100 Subject: [PATCH 31/58] fix: intercom messenger prod --- src/app/Routes.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/app/Routes.tsx b/src/app/Routes.tsx index 634ee6df3..8788cde68 100755 --- a/src/app/Routes.tsx +++ b/src/app/Routes.tsx @@ -230,7 +230,9 @@ export function MainRoutes() { > - {process.env.ENV_TYPE === "prod" ? : null} + {process.env.REACT_APP_ENV_TYPE === "prod" ? ( + + ) : null} }> From 459fd11a2bf19d2ca7ee9c1cffb7fb6488c5bcae Mon Sep 17 00:00:00 2001 From: okorie2 Date: Wed, 4 Sep 2024 17:57:31 +0100 Subject: [PATCH 32/58] feat: fill incomplete table with empty cells --- .../components/Table/Preview-table/index.tsx | 36 +++++++++++++------ src/app/utils/setMediaQueryForTest 2.ts | 20 +++++++++++ 2 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 src/app/utils/setMediaQueryForTest 2.ts diff --git a/src/app/components/Table/Preview-table/index.tsx b/src/app/components/Table/Preview-table/index.tsx index 848353047..0aa87cc89 100644 --- a/src/app/components/Table/Preview-table/index.tsx +++ b/src/app/components/Table/Preview-table/index.tsx @@ -31,9 +31,24 @@ interface PreviewTableProps { observerTarget: React.MutableRefObject; loading: boolean; } - +type IdatasStats = { + name: string; + type: "bar" | "percentage" | "unique"; + data: { name: string; value: number }[]; +}; export default function PreviewTable(props: PreviewTableProps) { const [toolboxDisplay, setToolboxDisplay] = React.useState(false); + let columns: string[] = []; + let dataStats: IdatasStats[] = []; + if (props.columns.length > 0 && props.dataStats.length > 0) { + if (props.columns.length < 5) { + columns = [...props.columns, ...Array(5).fill("")]; + dataStats = [...props.dataStats, ...Array(5).fill("")]; + } else { + columns = [...props.columns, ...Array(2).fill("")]; + dataStats = [...props.dataStats, ...Array(2).fill("")]; + } + } return ( <> @@ -88,7 +103,7 @@ export default function PreviewTable(props: PreviewTableProps) { padding: 0rem 0.4rem; `} > - {props.columns.map((val, index) => { + {columns.map((val, index) => { return (
{props.dataTypes?.[val] === "string" ? "Aa" : "#"} @@ -127,25 +143,25 @@ export default function PreviewTable(props: PreviewTableProps) { > {val}

- - - + {val && ( + + + + )}
); })} - {props.dataStats?.map((val) => ( + {dataStats?.map((val) => ( {val.name !== "ID" && (
- {props.columns.map((val, cellIndex) => ( + {columns.map((val, cellIndex) => (

({ + matches: mediaQuery.match(query, { + width, + }), + addListener: () => {}, + removeListener: () => {}, + media: "", + onchange: () => {}, + addEventListener: () => {}, + removeEventListener: () => {}, + dispatchEvent: () => false, + }); +} +export function setMediaQueryForTest(width: number) { + window.matchMedia = createMatchMedia(width); +} From 2a44f5e1150a4fcebfc5a07cd1bba92058ccae61 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Thu, 5 Sep 2024 07:56:27 +0100 Subject: [PATCH 33/58] fix: intercom messenger not dislayed in prod --- src/app/Routes.tsx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/app/Routes.tsx b/src/app/Routes.tsx index 8788cde68..c6b51844d 100755 --- a/src/app/Routes.tsx +++ b/src/app/Routes.tsx @@ -159,8 +159,6 @@ const OneTapLoginComponent = () => { const IntercomBootupComponent = () => { const { isAuthenticated, user, getAccessTokenSilently } = useAuth0(); - const APP_ID = "tfvurn19"; - React.useEffect(() => { if (window?.Intercom) { window.Intercom("update"); @@ -192,7 +190,7 @@ const IntercomBootupComponent = () => { // @ts-ignore window.Intercom("boot", { api_base: "https://api-iam.intercom.io", - app_id: APP_ID, + app_id: "tfvurn19", name: user?.name, // Full name email: user?.email, // the email for your user user_id: user?.sub, // user_id as a string @@ -208,7 +206,7 @@ const IntercomBootupComponent = () => { // @ts-ignore window.Intercom("boot", { api_base: "https://api-iam.intercom.io", - app_id: APP_ID, + app_id: "tfvurn19", }); } }, [isAuthenticated]); From 6dc9cf5a11d20fbf4dc0048ee272c6b1b6ca3a8e Mon Sep 17 00:00:00 2001 From: okorie2 Date: Mon, 9 Sep 2024 08:25:16 +0100 Subject: [PATCH 34/58] feat:DX-1615; implement 404 logic --- .../chart-module/components/toolbox/index.tsx | 14 +- src/app/modules/chart-module/data.ts | 20 +++ src/app/modules/chart-module/index.tsx | 23 ++-- .../routes/{data => select-data}/index.tsx | 0 .../common/no-match-page/asset/404.svg | 3 + .../common/no-match-page/asset/bg-ellipse.svg | 76 +++++++++++ .../modules/common/no-match-page/index.tsx | 126 +++++++++++------- src/app/modules/dataset-module/index.tsx | 10 +- src/app/modules/report-module/index.tsx | 70 +++------- 9 files changed, 227 insertions(+), 115 deletions(-) rename src/app/modules/chart-module/routes/{data => select-data}/index.tsx (100%) create mode 100644 src/app/modules/common/no-match-page/asset/404.svg create mode 100644 src/app/modules/common/no-match-page/asset/bg-ellipse.svg diff --git a/src/app/modules/chart-module/components/toolbox/index.tsx b/src/app/modules/chart-module/components/toolbox/index.tsx index 24d29e121..0e4a673d0 100644 --- a/src/app/modules/chart-module/components/toolbox/index.tsx +++ b/src/app/modules/chart-module/components/toolbox/index.tsx @@ -1,6 +1,5 @@ /* third-party */ import React from "react"; -import { useRecoilState } from "recoil"; import { useAuth0 } from "@auth0/auth0-react"; import { useHistory, useParams } from "react-router-dom"; import { useStoreActions, useStoreState } from "app/state/store/hooks"; @@ -15,12 +14,17 @@ import { } from "app/modules/chart-module/components/toolbox/data"; import { ChartToolBoxSteps } from "app/modules/chart-module/components/toolbox/steps"; import { TriangleXSIcon } from "app/assets/icons/TriangleXS"; -import { emptyChartAPI, ChartAPIModel } from "app/modules/chart-module/data"; +import { + emptyChartAPI, + ChartAPIModel, + chartViews, +} from "app/modules/chart-module/data"; import ToolboxNav from "app/modules/chart-module/components/toolbox/steps/navbar"; import { InfoSnackbar } from "../chartSubheaderToolbar/infoSnackbar"; export function ChartModuleToolBox(props: Readonly) { const { page, view } = useParams<{ page: string; view?: string }>(); + const isValidView = Object.values(chartViews).find((v) => v === view); const history = useHistory(); const { isAuthenticated, user } = useAuth0(); const isMobile = useMediaQuery("(max-width: 767px)"); @@ -114,7 +118,11 @@ export function ChartModuleToolBox(props: Readonly) { }; React.useEffect(() => { - if (location.pathname === `/chart/${page}` || view == "preview") { + if ( + location.pathname === `/chart/${page}` || + view == "preview" || + !isValidView + ) { setDisplayToolbar("none"); props.setToolboxOpen(false); } else { diff --git a/src/app/modules/chart-module/data.ts b/src/app/modules/chart-module/data.ts index 479475e85..d8e71f186 100644 --- a/src/app/modules/chart-module/data.ts +++ b/src/app/modules/chart-module/data.ts @@ -490,3 +490,23 @@ export const emptyChartAPI: ChartAPIModel = { isMappingValid: false, isAIAssisted: false, }; +export const chartViews = { + customize: "customize", + preview: "preview", + previewData: "preview-data", + filters: "filters", + data: "data", + mapping: "mapping", + chartType: "chart-type", +}; + +export const chartPaths = { + detail: "/chart/:page", + customize: `/chart/:page/${chartViews.customize}`, + preview: `/chart/:page/${chartViews.preview}`, + previewData: `/chart/:page/${chartViews.previewData}`, + filters: `/chart/:page/${chartViews.filters}`, + data: `/chart/:page/${chartViews.data}`, + mapping: `/chart/:page/${chartViews.mapping}`, + chartType: `/chart/:page/${chartViews.chartType}`, +}; diff --git a/src/app/modules/chart-module/index.tsx b/src/app/modules/chart-module/index.tsx index c59de515e..bd1f2464a 100644 --- a/src/app/modules/chart-module/index.tsx +++ b/src/app/modules/chart-module/index.tsx @@ -23,7 +23,7 @@ import { import { PageLoader } from "app/modules/common/page-loader"; import { useChartsRawData } from "app/hooks/useChartsRawData"; import { NoMatchPage } from "app/modules/common/no-match-page"; -import ChartModuleDataView from "app/modules/chart-module/routes/data"; +import ChartModuleDataView from "app/modules/chart-module/routes/select-data"; import { ChartSubheaderToolbar } from "./components/chartSubheaderToolbar"; import ChartBuilderMapping from "app/modules/chart-module/routes/mapping"; import ChartBuilderFilters from "app/modules/chart-module/routes/filters"; @@ -38,6 +38,8 @@ import { routeToConfig, ChartRenderedItem, defaultChartOptions, + chartViews, + chartPaths, } from "app/modules/chart-module/data"; import { NotAuthorizedMessageModule } from "app/modules/common/not-authorized-message"; import { isEmpty } from "lodash"; @@ -64,6 +66,7 @@ export default function ChartModule() { const token = useStoreState((state) => state.AuthToken.value); const history = useHistory(); const { page, view } = useParams<{ page: string; view?: string }>(); + const isValidView = Object.values(chartViews).find((v) => v === view); const [chartFromAPI, setChartFromAPI] = React.useState(null); const [visualOptions, setVisualOptions] = useSessionStorage( @@ -74,7 +77,7 @@ export default function ChartModule() { const setPlanDialog = useSetRecoilState(planDialogAtom); const [rawViz, setRawViz] = React.useState(null); - const [toolboxOpen, setToolboxOpen] = React.useState(Boolean(view)); + const [toolboxOpen, setToolboxOpen] = React.useState(Boolean(isValidView)); const [savedChanges, setSavedChanges] = React.useState(false); const [chartName, setChartName] = React.useState("Untitled Chart"); @@ -600,7 +603,7 @@ export default function ChartModule() { ref={ref} > - + - + - + - + - + - + - + - + + + diff --git a/src/app/modules/common/no-match-page/asset/bg-ellipse.svg b/src/app/modules/common/no-match-page/asset/bg-ellipse.svg new file mode 100644 index 000000000..94166dd6b --- /dev/null +++ b/src/app/modules/common/no-match-page/asset/bg-ellipse.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/modules/common/no-match-page/index.tsx b/src/app/modules/common/no-match-page/index.tsx index 2937bcb04..69e8f0db6 100644 --- a/src/app/modules/common/no-match-page/index.tsx +++ b/src/app/modules/common/no-match-page/index.tsx @@ -1,100 +1,128 @@ import React from "react"; import get from "lodash/get"; -import { Link } from "react-router-dom"; +import { Link, useHistory } from "react-router-dom"; +import { ReactComponent as NotFoundIcon } from "app/modules/common/no-match-page/asset/404.svg"; +import SmallFooter from "app/modules/home-module/components/Footer/smallFooter"; // cc:refactor this component, inline css need to be moved to proper styled components export const NoMatchPage = () => { + const history = useHistory(); return (

-
-
Oops! Page not found
+
+
-
404
-
+ />
-
We are sorry, but the page you requested was not found
+

Oops! This page could not be found

+

+ Sorry but the page you are looking for does not exist, have been + removed, have changed or is temporarily unavailable. +

- -
-
Back to Home Page
+ Back to Home Page
-
- + + +
+
); }; diff --git a/src/app/modules/dataset-module/index.tsx b/src/app/modules/dataset-module/index.tsx index 01e994e2f..d63e24a32 100644 --- a/src/app/modules/dataset-module/index.tsx +++ b/src/app/modules/dataset-module/index.tsx @@ -4,6 +4,7 @@ import DatasetUploadSteps from "app/modules/dataset-module/routes/upload-module/ import { Route, Switch } from "react-router-dom"; import DatasetDetail from "app/modules/dataset-module/routes/datasetDetail"; import EditMetaData from "app/modules/dataset-module/routes/edit"; +import { NoMatchPage } from "app/modules/common/no-match-page"; export default function DatasetDetailModule() { useTitle("Dataxplorer - Datasets"); @@ -11,15 +12,18 @@ export default function DatasetDetailModule() { return ( - + - + - + + + + ); } diff --git a/src/app/modules/report-module/index.tsx b/src/app/modules/report-module/index.tsx index 1e5bbfc63..33a3b985c 100644 --- a/src/app/modules/report-module/index.tsx +++ b/src/app/modules/report-module/index.tsx @@ -431,8 +431,7 @@ export default function ReportModule() { {!reportError401 && showReportHeader && - view !== "ai-template" && - view !== "initial" && ( + (view === "edit" || view === undefined) && ( )} - {view && - !reportError401 && - view !== "preview" && - canEditDeleteReport && - view !== "initial" && - view !== "ai-template" && ( - setRightPanelOpen(true)} - onClose={() => setRightPanelOpen(false)} - showHeaderItem={!headerDetails.showHeader} - framesArray={framesArray} - reportName={reportName} - onSave={onSave} - /> - )} + {view && !reportError401 && view === "edit" && canEditDeleteReport && ( + setRightPanelOpen(true)} + onClose={() => setRightPanelOpen(false)} + showHeaderItem={!headerDetails.showHeader} + framesArray={framesArray} + reportName={reportName} + onSave={onSave} + /> + )}
- + - + - - setRightPanelOpen(true)} - view={view} - setReportName={setReportName} - reportName={reportName} - deleteFrame={deleteFrame} - hasSubHeaderTitleFocused={hasSubHeaderTitleFocused} - reportType={reportType} - framesArray={framesArray} - headerDetails={headerDetails} - updateFramesArray={updateFramesArray} - setHeaderDetails={setHeaderDetails} - setPlugins={setPlugins} - onSave={onSave} - /> - - + setRightPanelOpen(true)} @@ -531,19 +507,13 @@ export default function ReportModule() { onSave={onSave} /> - - - - + - + From f7998264a4b1eb238dda97aaf5dfdd655264e0af Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Mon, 9 Sep 2024 10:50:49 +0100 Subject: [PATCH 35/58] fix: Issue with Federated search scrolling/loading assets --- src/app/Routes.tsx | 16 ++++++++++++++-- src/app/hooks/useCheckUserPlan.tsx | 11 ++++++++++- src/app/hooks/useOneDrivePicker.tsx | 2 +- .../upload-steps/externalSearch.tsx | 5 ++++- src/app/state/recoil/atoms/index.ts | 5 +++++ 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/app/Routes.tsx b/src/app/Routes.tsx index 3950088ac..bcc959847 100755 --- a/src/app/Routes.tsx +++ b/src/app/Routes.tsx @@ -49,6 +49,8 @@ import { PaymentSuccessCallbackModule, PaymentCanceledCallbackModule, } from "app/modules/callback-module/payment"; +import { useRecoilValue } from "recoil"; +import { fetchPlanLoadingAtom } from "./state/recoil/atoms"; const ChartModule = lazy(() => import("app/modules/chart-module")); const ReportModule = lazy(() => import("app/modules/report-module")); @@ -104,6 +106,15 @@ const Auth0ProviderWithRedirectCallback = (props: { ); }; +const PlanLoader = () => { + const planLoading = useRecoilValue(fetchPlanLoadingAtom); + + if (planLoading) { + return ; + } + return null; +}; + const AuthLoader = () => { const { isLoading } = useAuth0(); @@ -191,7 +202,7 @@ const IntercomBootupComponent = () => { // @ts-ignore window.Intercom("boot", { api_base: "https://api-iam.intercom.io", - app_id: "tfvurn19", + app_id: process.env.REACT_APP_INTERCOM_APP_ID, name: user?.name, // Full name email: user?.email, // the email for your user user_id: user?.sub, // user_id as a string @@ -207,7 +218,7 @@ const IntercomBootupComponent = () => { // @ts-ignore window.Intercom("boot", { api_base: "https://api-iam.intercom.io", - app_id: "tfvurn19", + app_id: process.env.REACT_APP_INTERCOM_APP_ID, }); } }, [isAuthenticated]); @@ -229,6 +240,7 @@ export function MainRoutes() { }} > + {process.env.REACT_APP_ENV_TYPE === "prod" ? ( diff --git a/src/app/hooks/useCheckUserPlan.tsx b/src/app/hooks/useCheckUserPlan.tsx index 6b6a63349..060464e7a 100644 --- a/src/app/hooks/useCheckUserPlan.tsx +++ b/src/app/hooks/useCheckUserPlan.tsx @@ -1,5 +1,5 @@ import { useAuth0 } from "@auth0/auth0-react"; -import { planDialogAtom } from "app/state/recoil/atoms"; +import { fetchPlanLoadingAtom, planDialogAtom } from "app/state/recoil/atoms"; import { useStoreState } from "app/state/store/hooks"; import axios from "axios"; import React from "react"; @@ -10,6 +10,8 @@ export function useCheckUserPlan() { const token = useStoreState((state) => state.AuthToken.value); const setPlanDialog = useSetRecoilState(planDialogAtom); + const setLoading = useSetRecoilState(fetchPlanLoadingAtom); + const [userPlan, setUserPlan] = React.useState<{ planData: { name: string; @@ -49,6 +51,7 @@ export function useCheckUserPlan() { React.useEffect(() => { if (!token) return; + setLoading(true); axios .get(`${process.env.REACT_APP_API}/users/plan-data`, { headers: { @@ -58,6 +61,12 @@ export function useCheckUserPlan() { }) .then((response) => { setUserPlan(response.data); + }) + .catch((error) => { + console.error(error); + }) + .finally(() => { + setLoading(false); }); }, [token]); diff --git a/src/app/hooks/useOneDrivePicker.tsx b/src/app/hooks/useOneDrivePicker.tsx index cbf612f57..5508ab5d6 100644 --- a/src/app/hooks/useOneDrivePicker.tsx +++ b/src/app/hooks/useOneDrivePicker.tsx @@ -21,7 +21,7 @@ export const useOneDrivePicker = ({ const msalParams = { auth: { authority: "https://login.microsoftonline.com/consumers", - clientId: "a5f756dd-d422-443e-93d2-3361f8a4a6f8", + clientId: process.env.REACT_APP_ONEDRIVE_CLIENT_ID!, redirectUri: window.location.origin, }, }; diff --git a/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx b/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx index 6343ed762..3bb181970 100644 --- a/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx +++ b/src/app/modules/dataset-module/routes/upload-module/upload-steps/externalSearch.tsx @@ -12,6 +12,7 @@ import { useSetRecoilState } from "recoil"; import { planDialogAtom } from "app/state/recoil/atoms"; import SaveAltIcon from "@material-ui/icons/SaveAlt"; import ExternalSearchTable from "../component/table/externalSearchTable"; +import { useCheckUserPlan } from "app/hooks/useCheckUserPlan"; export interface IExternalDataset { name: string; @@ -73,7 +74,9 @@ export default function ExternalSearch(props: { setOffset(0); }; - const free = true; + const { userPlan } = useCheckUserPlan(); + + const free = userPlan?.planData.name === "Free"; // Pagination on scroll React.useEffect(() => { if (isObserved && datasets.length > 0 && !free) { diff --git a/src/app/state/recoil/atoms/index.ts b/src/app/state/recoil/atoms/index.ts index 7b76f21c7..bb24843f2 100644 --- a/src/app/state/recoil/atoms/index.ts +++ b/src/app/state/recoil/atoms/index.ts @@ -175,3 +175,8 @@ export const planDialogAtom = atom<{ onTryAgain: () => {}, }, }); + +export const fetchPlanLoadingAtom = atom({ + key: "fetchPlanLoadingAtom", + default: false, +}); From 6aaa31a6e50e18c533d7f064b10e944d2247602e Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Mon, 9 Sep 2024 15:20:44 +0100 Subject: [PATCH 36/58] fix: insert onedrive id --- src/app/hooks/useOneDrivePicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/hooks/useOneDrivePicker.tsx b/src/app/hooks/useOneDrivePicker.tsx index 5508ab5d6..51ffb347e 100644 --- a/src/app/hooks/useOneDrivePicker.tsx +++ b/src/app/hooks/useOneDrivePicker.tsx @@ -21,7 +21,7 @@ export const useOneDrivePicker = ({ const msalParams = { auth: { authority: "https://login.microsoftonline.com/consumers", - clientId: process.env.REACT_APP_ONEDRIVE_CLIENT_ID!, + clientId: "a5f756dd-d422-443e-93d2-3361f8a4a6f8", // Doesn't work if used as an env variable redirectUri: window.location.origin, }, }; From add03bbb9a39e40a409f167a932d6fd28e138652 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Tue, 10 Sep 2024 11:06:23 +0100 Subject: [PATCH 37/58] chore: update prop name --- src/app/modules/report-module/views/create/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/modules/report-module/views/create/index.tsx b/src/app/modules/report-module/views/create/index.tsx index f99f1d898..806ab83de 100644 --- a/src/app/modules/report-module/views/create/index.tsx +++ b/src/app/modules/report-module/views/create/index.tsx @@ -106,7 +106,7 @@ function ReportCreateView(props: Readonly) { `} /> Date: Tue, 10 Sep 2024 12:10:52 +0100 Subject: [PATCH 38/58] chore:update prop --- src/app/modules/home-module/__test__/reportCard.test.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app/modules/home-module/__test__/reportCard.test.tsx b/src/app/modules/home-module/__test__/reportCard.test.tsx index a750f641c..ba1afee33 100644 --- a/src/app/modules/home-module/__test__/reportCard.test.tsx +++ b/src/app/modules/home-module/__test__/reportCard.test.tsx @@ -8,6 +8,7 @@ import { mockUseAuth0 } from "app/utils/mockAuth0"; import { Router } from "react-router-dom"; import { createMemoryHistory } from "history"; import GridItem from "app/modules/home-module/components/AssetCollection/Reports/gridItem"; +import { EditorState } from "draft-js"; interface MockProps { date: Date; @@ -20,6 +21,7 @@ interface MockProps { handleDuplicate?: jest.Mock; showMenuButton: boolean; owner: string; + heading: EditorState; } let mockLoginStatus = true; From ff49547aa0ff1e104253d29691788dbb1be2a2f1 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Tue, 10 Sep 2024 14:10:33 +0100 Subject: [PATCH 39/58] chore: minor updates --- src/app/modules/common/RichEditor/index.tsx | 3 ++- .../home-module/__test__/reportCard.test.tsx | 7 +++---- .../components/AssetCollection/All/assetsGrid.tsx | 2 +- .../AssetCollection/Reports/gridItem.tsx | 15 +++++---------- .../AssetCollection/Reports/reportsGrid.tsx | 4 ++-- 5 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/app/modules/common/RichEditor/index.tsx b/src/app/modules/common/RichEditor/index.tsx index 309722d25..8968a7ac0 100644 --- a/src/app/modules/common/RichEditor/index.tsx +++ b/src/app/modules/common/RichEditor/index.tsx @@ -43,7 +43,8 @@ export const RichEditor = (props: { const containerRef = useRef(null); const focus = (): void => { - editor.current?.focus(); + // editor.current?.focus(); + EditorState.moveFocusToEnd(props.textContent); }; const moveSelectionToEnd = (editorState: EditorState) => { diff --git a/src/app/modules/home-module/__test__/reportCard.test.tsx b/src/app/modules/home-module/__test__/reportCard.test.tsx index ba1afee33..a12dac298 100644 --- a/src/app/modules/home-module/__test__/reportCard.test.tsx +++ b/src/app/modules/home-module/__test__/reportCard.test.tsx @@ -1,9 +1,8 @@ import { Auth0Provider } from "@auth0/auth0-react"; -import { render } from "@testing-library/react"; import userEvent, { PointerEventsCheckLevel, } from "@testing-library/user-event"; -import { screen } from "@testing-library/react"; +import { screen, render } from "@testing-library/react"; import { mockUseAuth0 } from "app/utils/mockAuth0"; import { Router } from "react-router-dom"; import { createMemoryHistory } from "history"; @@ -14,7 +13,7 @@ interface MockProps { date: Date; id?: string; title: string; - descr: string; + name: string; color: string; viz: JSX.Element; handleDelete?: jest.Mock; @@ -44,7 +43,7 @@ const defaultProps = (newProps: Partial = {}): MockProps => { date: "2021-08-13", id: "report-id", title: "report-title", - descr: "report-description", + name: "report-description", color: "#ffffff", viz:
report
, handleDelete: jest.fn(), diff --git a/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx b/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx index 065be0e94..eed5d3f01 100644 --- a/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx +++ b/src/app/modules/home-module/components/AssetCollection/All/assetsGrid.tsx @@ -345,7 +345,7 @@ export default function AssetsGrid(props: Props) { } color={d.backgroundColor} diff --git a/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx b/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx index b0643edbd..8484790e7 100644 --- a/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx +++ b/src/app/modules/home-module/components/AssetCollection/Reports/gridItem.tsx @@ -16,7 +16,7 @@ interface Props { date: Date; id?: string; heading: EditorState; - descr: string; + name: string; color: string; viz: JSX.Element; handleDelete?: (id: string) => void; @@ -87,9 +87,7 @@ export default function GridItem(props: Readonly) { `} >

) { margin-bottom: 0; `} > - - {props.heading.getCurrentContent().getPlainText() || - props.descr} - + {props.heading.getCurrentContent().getPlainText()}

) { color: #495057; `} > - {props.descr} + {props.name}

) { const observerTarget = React.useRef(null); const [cardId, setCardId] = React.useState(""); const [modalDisplay, setModalDisplay] = React.useState(false); @@ -221,7 +221,7 @@ export default function ReportsGrid(props: Props) { } color={data.backgroundColor} From 8be13b8ff5c3a9bb59e8c09223882f1272767b55 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Thu, 12 Sep 2024 07:25:58 +0100 Subject: [PATCH 40/58] feat: adjust if statement --- .../sub-module/components/headerBlock/index.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index 21d9eba22..4b075900f 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import get from "lodash/get"; import { useDrop } from "react-dnd"; -import { ContentState, EditorState } from "draft-js"; +import { ContentState, EditorState, convertToRaw } from "draft-js"; import { useRecoilState } from "recoil"; import Box from "@material-ui/core/Box"; import Container from "@material-ui/core/Container"; @@ -110,10 +110,10 @@ export default function HeaderBlock(props: Props) { setMaxCharCount(max); const plainText = getPlainTextFromEditorState(text); const plainDescr = getPlainTextFromEditorState(propsState); + if (updateCharCount) { + setCharCount(plainText.length); + } if (plainText.length <= max) { - if (updateCharCount) { - setCharCount(plainText.length); - } if (type === "heading") { props.setHeaderDetails({ ...props.headerDetails, From fc1cfe43cddb98fd4f55e59b01ac9a4c4f07ecec Mon Sep 17 00:00:00 2001 From: okorie2 Date: Thu, 12 Sep 2024 12:11:04 +0100 Subject: [PATCH 41/58] feat: get chart owner --- .../Dialogs/EmbedChartDialog/index.tsx | 18 +++++++++++++----- .../state/api/action-reducers/user/index.ts | 6 ++++++ src/app/state/api/interfaces/index.ts | 3 +++ src/app/state/store/index.ts | 5 ++++- 4 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 src/app/state/api/action-reducers/user/index.ts diff --git a/src/app/components/Dialogs/EmbedChartDialog/index.tsx b/src/app/components/Dialogs/EmbedChartDialog/index.tsx index 5119ac1f0..e697ac6c1 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/index.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/index.tsx @@ -7,10 +7,9 @@ import IconButton from "@material-ui/core/IconButton"; import Snackbar from "@material-ui/core/Snackbar"; import get from "lodash/get"; import { useLoadDatasetDetails } from "app/modules/report-module/components/chart-wrapper/useLoadDatasetDetailsAPI"; -import { useAuth0 } from "@auth0/auth0-react"; import ChartContainer from "./chartContainer"; import { copyToClipboard } from "app/utils/copyToClipboard"; -import { useStoreState } from "app/state/store/hooks"; +import { useStoreActions, useStoreState } from "app/state/store/hooks"; import LinkOptions from "./linkOptions"; import BasicSwitch from "app/components/Switch/BasicSwitch"; import EmbedOptions from "./embedOptions"; @@ -24,8 +23,13 @@ export default function EmbedChartDialog(props: { }) { const containerRef = React.useRef(null); const token = useStoreState((state) => state.AuthToken.value); + const fetchUserProfile = useStoreActions( + (state) => state.user.UserProfile.fetch + ); + const userProfile = useStoreState( + (state) => state.user.UserProfile.crudData + ) as { username: string }; const classes = useStyles(); - const { user } = useAuth0(); const { datasetDetails } = useLoadDatasetDetails( props.datasetId!, token ?? undefined @@ -38,7 +42,6 @@ export default function EmbedChartDialog(props: { React.useState("embed-code"); const { - loading, notFound, chartErrorMessage, dataError, @@ -49,6 +52,11 @@ export default function EmbedChartDialog(props: { setNotFound, } = useRenderChartFromAPI(token, props.chartId); + React.useEffect(() => { + if (datasetDetails.owner) { + fetchUserProfile({ getId: datasetDetails.owner }); + } + }, [datasetDetails]); let newVisualOptions = visualOptions; const displayModes = [ @@ -226,7 +234,7 @@ export default function EmbedChartDialog(props: { >

Author: - {user?.given_name || "NOT SPECIFIED"} + {userProfile.username}

Date: Thu, 12 Sep 2024 14:46:12 +0100 Subject: [PATCH 42/58] test:fix failing unit tests --- src/app/modules/common/RichEditor/index.tsx | 2 ++ .../home-module/__test__/reportCard.test.tsx | 7 +++++-- .../__test__/headerBlock.test.tsx | 20 +++++++++---------- .../__test__/reportSubheaderToolbar.test.tsx | 12 +++++------ .../components/headerBlock/index.tsx | 1 + 5 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/app/modules/common/RichEditor/index.tsx b/src/app/modules/common/RichEditor/index.tsx index c3ea3de37..d087a7c5e 100644 --- a/src/app/modules/common/RichEditor/index.tsx +++ b/src/app/modules/common/RichEditor/index.tsx @@ -40,6 +40,7 @@ export const RichEditor = (props: { placeholder: string; onBlur?: () => void; onFocus?: () => void; + testId?: string; }): ReactElement => { const editor = useRef(null); @@ -138,6 +139,7 @@ export const RichEditor = (props: { } `} data-cy="rich-text-editor-container" + data-testid={`rich-text-editor-container-${props.testId}`} > = {}): MockProps => { return { date: "2021-08-13", id: "report-id", - title: "report-title", + heading: EditorState.createWithContent( + ContentState.createFromText("report-title") + ), name: "report-description", color: "#ffffff", viz:
report
, @@ -50,6 +52,7 @@ const defaultProps = (newProps: Partial = {}): MockProps => { handleDuplicate: jest.fn(), showMenuButton: true, owner: "auth0|123", + ...newProps, } as MockProps; }; diff --git a/src/app/modules/report-module/__test__/headerBlock.test.tsx b/src/app/modules/report-module/__test__/headerBlock.test.tsx index dbf700746..9ad3b5349 100644 --- a/src/app/modules/report-module/__test__/headerBlock.test.tsx +++ b/src/app/modules/report-module/__test__/headerBlock.test.tsx @@ -7,7 +7,7 @@ import { } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import HeaderBlock from "app/modules/report-module/sub-module/components/headerBlock/"; -import { EditorState } from "draft-js"; +import { ContentState, EditorState } from "draft-js"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; import Router from "react-router-dom"; import { MutableSnapshot, RecoilRoot } from "recoil"; @@ -77,7 +77,9 @@ const defaultProps = (props: Partial): MockProps => { headerDetails: { title: "Test Title", showHeader: true, - heading: EditorState.createEmpty(), + heading: EditorState.createWithContent( + ContentState.createFromText("heading") + ), description: EditorState.createEmpty(), createdDate: new Date(), backgroundColor: "#fff", @@ -149,6 +151,7 @@ const appSetup = (newProps: Partial = {}) => { }; test("title input should be visible and editable", async () => { + const user = userEvent.setup(); jest .spyOn(Router, "useParams") .mockReturnValue({ page: "12345", view: "edit" }); @@ -160,14 +163,11 @@ test("title input should be visible and editable", async () => { jest.spyOn(window, "scrollTo").mockImplementation(() => {}); const { app, props } = appSetup(); render(app); - expect(screen.getByPlaceholderText("Add a header title")).toBeEnabled(); - fireEvent.change(screen.getByPlaceholderText("Add a header title"), { - target: { value: "Test Tite" }, - }); - expect(props.setHeaderDetails).toHaveBeenCalledWith( - expect.objectContaining({ title: "Test Tite" }) - ); - expect(headerDetailsResult.headerDetails.title).toBe("Test Tite"); + expect(screen.getByText("heading")).toBeEnabled(); + await user.type(screen.getByText("heading"), "Test Tite"); + expect( + headerDetailsResult.headerDetails.heading.getCurrentContent().getPlainText() + ).toBe("headingTest Tite"); }); test("focusing on description input should clear placeholder", async () => { diff --git a/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx b/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx index f32d02382..ab1733f65 100644 --- a/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx +++ b/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx @@ -42,7 +42,7 @@ interface MockProps { isSaveEnabled?: boolean; rawViz?: any; setHasSubHeaderTitleFocused?: (value: boolean) => void; - setHasSubHeaderTitleBlurred?: (value: boolean) => void; + setHasReportNameFocused?: (value: boolean) => void; plugins: ToolbarPluginsType; isEditorFocused: boolean; headerDetails: IHeaderDetails; @@ -94,7 +94,7 @@ const defaultProps = (props: Partial = {}): MockProps => { isSaveEnabled: false, rawViz: {}, setHasSubHeaderTitleFocused: jest.fn(), - setHasSubHeaderTitleBlurred: jest.fn(), + setHasReportNameFocused: jest.fn(), plugins: {} as ToolbarPluginsType, isEditorFocused: false, headerDetails: {} as IHeaderDetails, @@ -170,17 +170,17 @@ describe("Tests for tablet and desktop view", () => { beforeEach(() => { setMediaQueryForTest(768); }); - test("focusing on input should call setHasSubHeaderTitleFocused", async () => { + test("focusing on input should call setHasReportNameFocused", async () => { jest .spyOn(Router, "useParams") .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); const { app, props } = appSetup({ mockActions: false }); render(app); screen.getByRole("textbox").focus(); - expect(props.setHasSubHeaderTitleFocused).toHaveBeenCalledWith(true); + expect(props.setHasReportNameFocused).toHaveBeenCalledWith(true); }); - test("blurring on input should call setHasSubHeaderTitleBlurred", async () => { + test("blurring on input should call setHasReportNameFocused", async () => { jest .spyOn(Router, "useParams") .mockReturnValue({ page: "65dcb26aaf4c8500693f1ab7", view: "edit" }); @@ -188,7 +188,7 @@ describe("Tests for tablet and desktop view", () => { render(app); screen.getByRole("textbox").focus(); screen.getByRole("textbox").blur(); - expect(props.setHasSubHeaderTitleBlurred).toHaveBeenCalledWith(true); + expect(props.setHasReportNameFocused).toHaveBeenCalledWith(true); }); test("clicking on input when value is Untitled report should clear the input", async () => { diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index 4b075900f..89b42456b 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -328,6 +328,7 @@ export default function HeaderBlock(props: Props) { onFocus={() => { setIsHeadingFocused(true); }} + testId="heading" />
From 564f7810743dee6fe8b16080d302800ad68fdb6e Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Thu, 12 Sep 2024 16:20:53 +0100 Subject: [PATCH 43/58] test: update cypress tests --- cypress/e2e/1-dx/2-datasets.cy.ts | 9 +++++++++ cypress/e2e/1-dx/3-charts.cy.ts | 12 ++++++++++++ cypress/e2e/1-dx/4-reports.cy.ts | 8 ++++++++ 3 files changed, 29 insertions(+) diff --git a/cypress/e2e/1-dx/2-datasets.cy.ts b/cypress/e2e/1-dx/2-datasets.cy.ts index 0ff9e8284..2ac91085b 100644 --- a/cypress/e2e/1-dx/2-datasets.cy.ts +++ b/cypress/e2e/1-dx/2-datasets.cy.ts @@ -24,11 +24,16 @@ describe("Testing connecting data on DX", () => { cy.restoreLocalStorageCache(); // cy.setGoogleAccessToken(); + cy.intercept("GET", `${apiUrl}/users/plan-data`).as("planData"); + cy.visit("/"); + cy.wait("@planData"); + cy.get('[data-cy="cookie-btn"]').click(); cy.intercept(`${apiUrl}/external-sources/search?q=*`).as("getDefaultData"); cy.get('[data-cy="home-connect-dataset-button"]').click(); + cy.wait("@planData"); }); it("Can filter results by source in the federated search", () => { @@ -212,7 +217,11 @@ describe("Edit, Delete and Duplicate Dataset", () => { beforeEach(() => { cy.restoreLocalStorageCache(); + cy.intercept("GET", `${apiUrl}/users/plan-data`).as("planData"); + cy.visit("/"); + + cy.wait("@planData"); cy.get('[data-cy="cookie-btn"]').click(); cy.intercept("GET", `${apiUrl}/datasets?filter=*`).as("fetchDatasets"); diff --git a/cypress/e2e/1-dx/3-charts.cy.ts b/cypress/e2e/1-dx/3-charts.cy.ts index 723aecddc..f2128047c 100644 --- a/cypress/e2e/1-dx/3-charts.cy.ts +++ b/cypress/e2e/1-dx/3-charts.cy.ts @@ -21,8 +21,12 @@ describe("Testing create chart on DX", () => { beforeEach(() => { cy.restoreLocalStorageCache(); + cy.intercept("GET", `${apiUrl}/users/plan-data`).as("planData"); + cy.visit("/"); + cy.wait("@planData"); + cy.get('[data-cy="cookie-btn"]').click(); cy.intercept("GET", `${apiUrl}/datasets?**`).as("getDatasets"); @@ -186,8 +190,12 @@ describe("Testing Ai chart creation", () => { beforeEach(() => { cy.restoreLocalStorageCache(); + cy.intercept("GET", `${apiUrl}/users/plan-data`).as("planData"); + cy.visit("/"); + cy.wait("@planData"); + cy.get('[data-cy="cookie-btn"]').click(); cy.intercept("GET", `${apiUrl}/datasets?**`).as("getDatasets"); cy.get('[data-cy="home-create-chart-button"]').click(); @@ -271,8 +279,12 @@ describe("Edit, duplicate and delete chart", () => { const apiUrl = Cypress.env("api_url"); beforeEach(() => { cy.restoreLocalStorageCache(); + cy.intercept("GET", `${apiUrl}/users/plan-data`).as("planData"); + cy.visit("/"); + cy.wait("@planData"); + cy.get('[data-cy="cookie-btn"]').click(); cy.intercept("GET", `${apiUrl}/charts*`).as("fetchCharts"); diff --git a/cypress/e2e/1-dx/4-reports.cy.ts b/cypress/e2e/1-dx/4-reports.cy.ts index ffb23c361..ad7d11b87 100644 --- a/cypress/e2e/1-dx/4-reports.cy.ts +++ b/cypress/e2e/1-dx/4-reports.cy.ts @@ -21,8 +21,12 @@ describe("Testing reports on DX", () => { cy.restoreLocalStorageCache(); // Navigating to dx home page + cy.intercept("GET", `${apiUrl}/users/plan-data`).as("planData"); + cy.visit("/"); + cy.wait("@planData"); + cy.get('[data-cy="cookie-btn"]').click(); }); @@ -176,8 +180,12 @@ describe("Edit, duplicate and delete report", () => { beforeEach(() => { cy.restoreLocalStorageCache(); + cy.intercept("GET", `${apiUrl}/users/plan-data`).as("planData"); + cy.visit("/"); + cy.wait("@planData"); + cy.get('[data-cy="cookie-btn"]').click(); cy.intercept(`${apiUrl}/reports?filter=*`).as("fetchReports"); From 9e601c97ebea2ea364d8e6f78de377da924e1ac6 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Thu, 12 Sep 2024 16:53:56 +0100 Subject: [PATCH 44/58] feat: add background image --- .../modules/common/no-match-page/index.tsx | 204 ++++++++++-------- 1 file changed, 109 insertions(+), 95 deletions(-) diff --git a/src/app/modules/common/no-match-page/index.tsx b/src/app/modules/common/no-match-page/index.tsx index 69e8f0db6..41a2de510 100644 --- a/src/app/modules/common/no-match-page/index.tsx +++ b/src/app/modules/common/no-match-page/index.tsx @@ -2,6 +2,8 @@ import React from "react"; import get from "lodash/get"; import { Link, useHistory } from "react-router-dom"; import { ReactComponent as NotFoundIcon } from "app/modules/common/no-match-page/asset/404.svg"; +import { ReactComponent as BgImg } from "app/modules/common/no-match-page/asset/bg-ellipse.svg"; + import SmallFooter from "app/modules/home-module/components/Footer/smallFooter"; // cc:refactor this component, inline css need to be moved to proper styled components @@ -9,118 +11,130 @@ import SmallFooter from "app/modules/home-module/components/Footer/smallFooter"; export const NoMatchPage = () => { const history = useHistory(); return ( -
-
- -
-
-
-

Oops! This page could not be found

-

- Sorry but the page you are looking for does not exist, have been - removed, have changed or is temporarily unavailable. -

-
+
- - +
+ +
+
+
- Back to Home Page - - -
+
- + + Back to Home Page + + + + + Previous page + + +
From 719db9131e20cfca000975bdb358e657e8f4e669 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Thu, 12 Sep 2024 17:57:52 +0100 Subject: [PATCH 45/58] fix: review fixes --- src/app/modules/report-module/index.tsx | 32 +++++++++++++++---------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/app/modules/report-module/index.tsx b/src/app/modules/report-module/index.tsx index 33a3b985c..47c7a540b 100644 --- a/src/app/modules/report-module/index.tsx +++ b/src/app/modules/report-module/index.tsx @@ -462,27 +462,30 @@ export default function ReportModule() { onSave={onSave} /> )} -
+ - + +
- + +
setRightPanelOpen(true)} @@ -508,6 +511,11 @@ export default function ReportModule() { /> +
Date: Thu, 12 Sep 2024 18:26:04 +0100 Subject: [PATCH 46/58] fix: review fixes --- src/app/components/Dialogs/EmbedChartDialog/index.tsx | 2 +- src/app/state/store/index.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/app/components/Dialogs/EmbedChartDialog/index.tsx b/src/app/components/Dialogs/EmbedChartDialog/index.tsx index e697ac6c1..724166138 100644 --- a/src/app/components/Dialogs/EmbedChartDialog/index.tsx +++ b/src/app/components/Dialogs/EmbedChartDialog/index.tsx @@ -234,7 +234,7 @@ export default function EmbedChartDialog(props: { >

Author: - {userProfile.username} + {userProfile?.username}

Date: Thu, 12 Sep 2024 19:23:16 +0100 Subject: [PATCH 47/58] test: update cypress tests --- cypress/e2e/1-dx/4-reports.cy.ts | 16 +++++++--------- src/app/modules/common/RichEditor/index.tsx | 7 +++---- .../sub-module/components/headerBlock/index.tsx | 3 ++- .../rowStructure/rowStructureDisplay.tsx | 1 + 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/cypress/e2e/1-dx/4-reports.cy.ts b/cypress/e2e/1-dx/4-reports.cy.ts index ad7d11b87..220766498 100644 --- a/cypress/e2e/1-dx/4-reports.cy.ts +++ b/cypress/e2e/1-dx/4-reports.cy.ts @@ -47,11 +47,9 @@ describe("Testing reports on DX", () => { cy.get('[data-cy="report-sub-header-title-input"]').type(reportTestName); cy.get('[data-cy="report-header-block"]').within(() => { - cy.get('[data-cy="report-header-block-title-input"]').type( - reportTestName - ); - cy.get('[data-cy="rich-text-editor-container"]').click(); - cy.get('[data-testid="rich-text-editor"]').type( + cy.get('[data-testid="heading-rich-text-editor"]').type(reportTestName); + cy.get('[data-cy="description-rich-text-editor-container"]').click(); + cy.get('[data-testid="description-rich-text-editor"]').type( "This is a report on football players" ); }); @@ -79,7 +77,7 @@ describe("Testing reports on DX", () => { cy.get('[data-cy="row-frame-item-drop-zone-0-0"]').drop(); cy.get("[data-cy=row-frame-0]").within(() => { - cy.get('[data-testid="rich-text-editor"]') + cy.get('[data-testid="report-rich-text-editor"]') .first() .type( "This is a report on football players who played in a match last year" @@ -221,9 +219,9 @@ describe("Edit, duplicate and delete report", () => { cy.get('[data-cy="report-sub-header-title-input"]').type(" - Edited"); cy.get('[data-cy="report-header-block"]').within(() => { - cy.get('[data-cy="report-header-block-title-input"]').type(" - Edited"); - cy.get('[data-cy="rich-text-editor-container"]').click(); - cy.get('[data-testid="rich-text-editor"]').type(" - Edited"); + cy.get('[data-testid="heading-rich-text-editor"]').type(" - Edited"); + cy.get('[data-cy="description-rich-text-editor-container"]').click(); + cy.get('[data-testid="description-rich-text-editor"]').type(" - Edited"); }); cy.get('[data-cy="save-report-button"]').click(); diff --git a/src/app/modules/common/RichEditor/index.tsx b/src/app/modules/common/RichEditor/index.tsx index d087a7c5e..4a00378a4 100644 --- a/src/app/modules/common/RichEditor/index.tsx +++ b/src/app/modules/common/RichEditor/index.tsx @@ -138,8 +138,8 @@ export const RichEditor = (props: { font-family: "GothamNarrow-Book", "Helvetica Neue", sans-serif; } `} - data-cy="rich-text-editor-container" - data-testid={`rich-text-editor-container-${props.testId}`} + data-cy={`${props.testId}-container`} + data-testid={`${props.testId}-container`} > { editor.current = element; }} - webDriverTestID="rich-text-editor" - data-cy="rich-text-editor" + webDriverTestID={props.testId} />
); diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx index 89b42456b..512c070bd 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx @@ -328,7 +328,7 @@ export default function HeaderBlock(props: Props) { onFocus={() => { setIsHeadingFocused(true); }} - testId="heading" + testId="heading-rich-text-editor" />
@@ -404,6 +404,7 @@ export default function HeaderBlock(props: Props) { onFocus={() => { setIsDescriptionFocused(true); }} + testId="description-rich-text-editor" />
diff --git a/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx b/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx index 8b9d9cae4..39fe30fe7 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx +++ b/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx @@ -604,6 +604,7 @@ const Box = (props: { placeholder={placeholder} setPlaceholderState={setTextPlaceholderState} placeholderState={textPlaceholderState} + testId="report-rich-text-editor" />
From 902d7a04f5e19882bc54301f9329cafaa3d43879 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Thu, 12 Sep 2024 23:38:54 +0100 Subject: [PATCH 48/58] style: apply z-index --- src/app/modules/common/no-match-page/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/modules/common/no-match-page/index.tsx b/src/app/modules/common/no-match-page/index.tsx index 41a2de510..ddbbf763d 100644 --- a/src/app/modules/common/no-match-page/index.tsx +++ b/src/app/modules/common/no-match-page/index.tsx @@ -27,7 +27,7 @@ export const NoMatchPage = () => { css={` position: absolute; top: 80px; - + z-index: -1; left: 0; width: 100%; `} From 642bb7a649f724ca5769c7f60ed458146ea7bab7 Mon Sep 17 00:00:00 2001 From: okorie2 Date: Fri, 13 Sep 2024 17:50:38 +0100 Subject: [PATCH 49/58] chore: remove unused state in RB --- src/app/modules/report-module/index.tsx | 50 ----------- .../rowStructure/rowStructureDisplay.tsx | 19 ++--- .../modules/report-module/views/edit/data.ts | 1 - .../report-module/views/edit/index.tsx | 30 +++---- .../report-module/views/initial/index.tsx | 10 +-- .../report-module/views/preview/index.tsx | 84 +++++-------------- src/app/state/recoil/atoms/index.ts | 44 ---------- 7 files changed, 39 insertions(+), 199 deletions(-) diff --git a/src/app/modules/report-module/index.tsx b/src/app/modules/report-module/index.tsx index 1619f55f4..195067922 100644 --- a/src/app/modules/report-module/index.tsx +++ b/src/app/modules/report-module/index.tsx @@ -13,7 +13,6 @@ import AITemplate from "app/modules/report-module/views/ai-template"; import { EditorState, convertToRaw } from "draft-js"; import { useStoreActions, useStoreState } from "app/state/store/hooks"; import { ReportModel, emptyReport } from "app/modules/report-module/data"; -import ReportCreateView from "app/modules/report-module/views/create"; import { ReportPreviewView } from "app/modules/report-module/views/preview"; import ReportInitialView from "app/modules/report-module/views/initial"; import { IFramesArray } from "app/modules/report-module/views/create/data"; @@ -26,10 +25,8 @@ import { Redirect, } from "react-router-dom"; import { - persistedReportStateAtom, planDialogAtom, reportRightPanelViewAtom, - unSavedReportPreviewModeAtom, } from "app/state/recoil/atoms"; import { ReportSubheaderToolbar } from "app/modules/report-module/components/reportSubHeaderToolbar"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; @@ -48,37 +45,12 @@ export default function ReportModule() { }>({ isAutoSaveEnabled: false }); const setPlanDialog = useSetRecoilState(planDialogAtom); - - /** static toolbar states */ const [plugins, setPlugins] = React.useState([]); - /** end of static toolbar states */ - const token = useStoreState((state) => state.AuthToken.value); - const [_rightPanelView, setRightPanelView] = useRecoilState( reportRightPanelViewAtom ); - - const [_reportPreviewMode, setReportPreviewMode] = useRecoilState( - unSavedReportPreviewModeAtom - ); - - const [persistedReportState, setPersistedReportState] = useRecoilState( - persistedReportStateAtom - ); const [isPreviewView, setIsPreviewView] = React.useState(false); - - const localReportState = JSON.parse(persistedReportState.framesArray); - - let localPickedCharts: string[] = []; - localReportState.map((data: any) => { - return data.contentTypes.map((item: any, index: number) => { - if (item === "chart") { - localPickedCharts.push(data.content[index]); - } - }); - }); - const [rightPanelOpen, setRightPanelOpen] = React.useState(true); const [reportName, setReportName] = React.useState("Untitled report"); const [hasReportNameFocused, setHasReportNameFocused] = React.useState(false); @@ -300,26 +272,6 @@ export default function ReportModule() { const resetReport = () => { updateFramesArray(initialFramesArray); - setPersistedReportState({ - reportName: "Untitled report", - headerDetails: { - title: "", - heading: JSON.stringify( - convertToRaw(EditorState.createEmpty().getCurrentContent()) - ), - description: JSON.stringify( - convertToRaw(EditorState.createEmpty().getCurrentContent()) - ), - showHeader: true, - backgroundColor: "#252c34", - titleColor: "#ffffff", - descriptionColor: "#ffffff", - dateColor: "#ffffff", - }, - - framesArray: JSON.stringify([]), - }); - setHeaderDetails({ title: "", heading: EditorState.createEmpty(), @@ -333,7 +285,6 @@ export default function ReportModule() { setReportName("Untitled report"); setRightPanelView("charts"); setRightPanelOpen(true); - setReportPreviewMode(false); setAutoSave({ isAutoSaveEnabled: false }); }; @@ -500,7 +451,6 @@ export default function ReportModule() { setHasChangesBeenMade={setHasChangesBeenMade} setReportName={setReportName} reportName={reportName} - localPickedCharts={localPickedCharts} framesArray={framesArray} headerDetails={headerDetails} updateFramesArray={updateFramesArray} diff --git a/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx b/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx index 39fe30fe7..741bea874 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx +++ b/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx @@ -21,7 +21,6 @@ import { chartFromReportAtom, reportContentIsResizingAtom, reportContentContainerWidth, - unSavedReportPreviewModeAtom, isChartDraggingAtom, } from "app/state/recoil/atoms"; import { IFramesArray } from "../../views/create/data"; @@ -62,17 +61,14 @@ interface RowStructureDisplayProps { forceSelectedType: string | undefined; } -export default function RowstructureDisplay(props: RowStructureDisplayProps) { +export default function RowstructureDisplay( + props: Readonly +) { const ref = useRef(null); const location = useLocation(); const { page } = useParams<{ page: string }>(); const [handleDisplay, setHandleDisplay] = React.useState(false); - const [reportPreviewMode] = useRecoilState(unSavedReportPreviewModeAtom); - const smScreen = useMediaQuery("(max-width: 850px)"); - const viewOnlyMode = - (page !== "new" && - get(location.pathname.split("/"), "[3]", "") !== "edit") || - reportPreviewMode; + const viewOnlyMode = location.pathname === `/report/${page}`; const handlers = viewOnlyMode ? {} @@ -381,15 +377,10 @@ const Box = (props: { }; const containerWidth = useRecoilValue(reportContentContainerWidth); - const [reportPreviewMode] = useRecoilState(unSavedReportPreviewModeAtom); const [_isResizing, setIsResizing] = useRecoilState( reportContentIsResizingAtom ); - - const viewOnlyMode = - (page !== "new" && - get(location.pathname.split("/"), "[3]", "") !== "edit") || - reportPreviewMode; + const viewOnlyMode = location.pathname === `/report/${page}`; const elementTypes = [ ReportElementsType.TEXT, diff --git a/src/app/modules/report-module/views/edit/data.ts b/src/app/modules/report-module/views/edit/data.ts index 5efcd2178..91c0ab2c8 100644 --- a/src/app/modules/report-module/views/edit/data.ts +++ b/src/app/modules/report-module/views/edit/data.ts @@ -13,7 +13,6 @@ export interface ReportEditViewProps { setHasReportNameFocused: React.Dispatch>; updateFramesArray: Updater; framesArray: IFramesArray[]; - localPickedCharts: string[]; setReportName: React.Dispatch>; autoSave: boolean; setAutoSave: React.Dispatch< diff --git a/src/app/modules/report-module/views/edit/index.tsx b/src/app/modules/report-module/views/edit/index.tsx index 5107863d9..8c209eb4f 100644 --- a/src/app/modules/report-module/views/edit/index.tsx +++ b/src/app/modules/report-module/views/edit/index.tsx @@ -5,7 +5,7 @@ import { useRecoilState } from "recoil"; import { useParams } from "react-router-dom"; import useResizeObserver from "use-resize-observer"; import Container from "@material-ui/core/Container"; -import { EditorState, RawDraftContentState, convertFromRaw } from "draft-js"; +import { EditorState, convertFromRaw } from "draft-js"; import { useTitle } from "react-use"; import { useAuth0 } from "@auth0/auth0-react"; import { PlaceHolder } from "app/modules/report-module/views/create"; @@ -21,7 +21,6 @@ import { GridColumns } from "app/modules/report-module/components/grid-columns"; import { IRowFrameStructure, - persistedReportStateAtom, reportContentContainerWidth, } from "app/state/recoil/atoms"; import { IFramesArray } from "app/modules/report-module/views/create/data"; @@ -37,7 +36,7 @@ import { compareHeaderDetailsState, } from "app/modules/report-module/views/edit/compareStates"; -function ReportEditView(props: ReportEditViewProps) { +function ReportEditView(props: Readonly) { useTitle("DX Dataxplorer - Edit Report"); const { page } = useParams<{ page: string }>(); @@ -53,7 +52,6 @@ function ReportEditView(props: ReportEditViewProps) { ); const [isReportHeadingModified, setIsReportHeadingModified] = React.useState(false); - const [persistedReportState] = useRecoilState(persistedReportStateAtom); const [rowStructureType, setRowStructuretype] = React.useState({ index: 0, @@ -112,15 +110,13 @@ function ReportEditView(props: ReportEditViewProps) { if (reportData.id !== page) { return; } - if (props.localPickedCharts.length === 0) { - const items = reportData.rows.map((rowFrame, index) => - rowFrame.items.filter((item) => typeof item === "string") - ) as string[][]; - let pickedItems: string[] = []; - - for (const element of items) { - pickedItems = [...pickedItems, ...element]; - } + const items = reportData.rows.map((rowFrame, index) => + rowFrame.items.filter((item) => typeof item === "string") + ) as string[][]; + let pickedItems: string[] = []; + + for (const element of items) { + pickedItems = [...pickedItems, ...element]; } }, [reportData]); @@ -197,15 +193,11 @@ function ReportEditView(props: ReportEditViewProps) { showHeader: reportData.showHeader, heading: reportData?.heading ? EditorState.moveFocusToEnd( - EditorState.createWithContent( - convertFromRaw(reportData?.heading as RawDraftContentState) - ) + EditorState.createWithContent(convertFromRaw(reportData?.heading)) ) : EditorState.moveFocusToEnd(EditorState.createEmpty()), description: reportData?.description - ? EditorState.createWithContent( - convertFromRaw(reportData?.description as RawDraftContentState) - ) + ? EditorState.createWithContent(convertFromRaw(reportData?.description)) : EditorState.createEmpty(), backgroundColor: reportData.backgroundColor, titleColor: reportData.titleColor, diff --git a/src/app/modules/report-module/views/initial/index.tsx b/src/app/modules/report-module/views/initial/index.tsx index ab4be72d6..4cac8d67a 100644 --- a/src/app/modules/report-module/views/initial/index.tsx +++ b/src/app/modules/report-module/views/initial/index.tsx @@ -9,8 +9,6 @@ import { } from "app/modules/report-module/views/initial/data"; import { ReportModel, emptyReport } from "app/modules/report-module/data"; import ReportsGrid from "app/modules/home-module/components/AssetCollection/Reports/reportsGrid"; -import { persistedReportStateAtom } from "app/state/recoil/atoms"; -import { useResetRecoilState } from "recoil"; import { useHistory } from "react-router-dom"; import { useStoreActions, useStoreState } from "app/state/store/hooks"; import { useMount, useTitle, useUpdateEffect } from "react-use"; @@ -50,12 +48,7 @@ function ReportInitialView(props: Readonly) { props.handleSetButtonActive(option.value); }; - const clearPersistedReportState = useResetRecoilState( - persistedReportStateAtom - ); - React.useEffect(() => { - clearPersistedReportState(); props.resetReport(); }, []); @@ -66,8 +59,7 @@ function ReportInitialView(props: Readonly) { useUpdateEffect(() => { if (reportCreateSuccess && !isEmpty(reportCreateData?.id)) { - const id = reportCreateData.id; - history.push(`/report/${id}/edit`); + history.push(`/report/${reportCreateData.id}/edit`); } }, [reportCreateSuccess, reportCreateData]); diff --git a/src/app/modules/report-module/views/preview/index.tsx b/src/app/modules/report-module/views/preview/index.tsx index 7d74fad96..5c6409895 100644 --- a/src/app/modules/report-module/views/preview/index.tsx +++ b/src/app/modules/report-module/views/preview/index.tsx @@ -13,27 +13,24 @@ import RowFrame from "app/modules/report-module/sub-module/rowStructure"; import HeaderBlock from "app/modules/report-module/sub-module/components/headerBlock"; import { NotAuthorizedMessageModule } from "app/modules/common/not-authorized-message"; import { ReportElementsType } from "app/modules/report-module/components/right-panel-create-view"; -import { - persistedReportStateAtom, - reportContentContainerWidth, - unSavedReportPreviewModeAtom, -} from "app/state/recoil/atoms"; +import { reportContentContainerWidth } from "app/state/recoil/atoms"; import { linkDecorator } from "app/modules/common/RichEditor/decorators"; import { useTitle } from "react-use"; import ReportUsePanel from "../../components/use-report-panel"; import HomeFooter from "app/modules/home-module/components/Footer"; import { PageLoader } from "app/modules/common/page-loader"; -export function ReportPreviewView(props: { - setIsPreviewView: React.Dispatch>; - setAutoSave: React.Dispatch< - React.SetStateAction<{ - isAutoSaveEnabled: boolean; - }> - >; -}) { - const previewMode = location.pathname.endsWith("preview"); - useTitle(`DX DataXplorer - Report ${previewMode ? "Preview" : "View"}`); +export function ReportPreviewView( + props: Readonly<{ + setIsPreviewView: React.Dispatch>; + setAutoSave: React.Dispatch< + React.SetStateAction<{ + isAutoSaveEnabled: boolean; + }> + >; + }> +) { + useTitle(`DX DataXplorer - Report View`); const { page } = useParams<{ page: string }>(); @@ -41,9 +38,6 @@ export function ReportPreviewView(props: { const { ref, width } = useResizeObserver(); - const persistedReportState = useRecoilState(persistedReportStateAtom)[0]; - const reportPreviewMode = useRecoilState(unSavedReportPreviewModeAtom)[0]; - const [containerWidth, setContainerWidth] = useRecoilState( reportContentContainerWidth ); @@ -91,8 +85,6 @@ export function ReportPreviewView(props: { (actions) => actions.reports.ReportGet.clear ); - const [reportPreviewData, setReportPreviewData] = React.useState(reportData); - React.useEffect(() => { props.setAutoSave({ isAutoSaveEnabled: false }); if (!isLoading) { @@ -113,12 +105,6 @@ export function ReportPreviewView(props: { } }, [width]); - React.useEffect(() => { - if (!reportPreviewMode) { - setReportPreviewData(reportData); - } - }, [reportData]); - React.useEffect(() => { props.setIsPreviewView(true); return () => { @@ -129,24 +115,6 @@ export function ReportPreviewView(props: { }; }, []); - React.useEffect(() => { - if (reportPreviewMode) { - setReportPreviewData({ - ...reportPreviewData, - - title: JSON.parse(persistedReportState.headerDetails.title), - showHeader: persistedReportState.headerDetails.showHeader, - backgroundColor: persistedReportState.headerDetails.backgroundColor, - titleColor: persistedReportState.headerDetails.titleColor, - descriptionColor: persistedReportState.headerDetails.descriptionColor, - dateColor: persistedReportState.headerDetails.dateColor, - rows: JSON.parse(persistedReportState.framesArray || "[]"), - description: JSON.parse(persistedReportState.headerDetails.description), - heading: JSON.parse(persistedReportState.headerDetails.heading), - }); - } - }, [persistedReportState]); - React.useEffect(() => { if (!loadingReportData && isReportLoading === null) { return; @@ -182,20 +150,18 @@ export function ReportPreviewView(props: { isToolboxOpen={false} previewMode={true} headerDetails={{ - title: reportPreviewData.title, - showHeader: reportPreviewData.showHeader, + title: reportData.title, + showHeader: reportData.showHeader, heading: EditorState.createWithContent( - convertFromRaw(reportPreviewData.heading ?? emptyReport.heading) + convertFromRaw(reportData.heading ?? emptyReport.heading) ), description: EditorState.createWithContent( - convertFromRaw( - reportPreviewData.description ?? emptyReport.description - ) + convertFromRaw(reportData.description ?? emptyReport.description) ), - backgroundColor: reportPreviewData.backgroundColor, - titleColor: reportPreviewData.titleColor, - descriptionColor: reportPreviewData.descriptionColor, - dateColor: reportPreviewData.dateColor, + backgroundColor: reportData.backgroundColor, + titleColor: reportData.titleColor, + descriptionColor: reportData.descriptionColor, + dateColor: reportData.dateColor, }} setPlugins={() => {}} setHeaderDetails={() => {}} @@ -205,7 +171,7 @@ export function ReportPreviewView(props: { {!reportError401 && - get(reportPreviewData, "rows", []).map((rowFrame, index) => { + get(reportData, "rows", []).map((rowFrame, index) => { const contentTypes = rowFrame.items.map((item) => { if (item === null) { return null; @@ -270,16 +236,10 @@ export function ReportPreviewView(props: { })} - {location.search.includes("?fromLanding=true") && !isAuthenticated ? ( ) : null} - - {!previewMode ? ( - <> - - - ) : null} +
); } diff --git a/src/app/state/recoil/atoms/index.ts b/src/app/state/recoil/atoms/index.ts index 7e5a60047..fc1885118 100644 --- a/src/app/state/recoil/atoms/index.ts +++ b/src/app/state/recoil/atoms/index.ts @@ -1,6 +1,5 @@ import { atom } from "recoil"; import { recoilPersist } from "recoil-persist"; -import { convertToRaw, EditorState } from "draft-js"; import { DatasetListItemAPIModel } from "app/modules/dataset-module/data"; export interface IRowFrameStructure { @@ -91,11 +90,6 @@ export const reportCreationTourStepAtom = atom({ key: "reportCreationTourStepAtom", default: 0, }); -export const unSavedReportPreviewModeAtom = atom({ - key: "unSavedReportPreviewModeAtom", - default: false, - effects_UNSTABLE: [persistAtom], -}); export const loadedDatasetsAtom = atom({ key: "loadedDatasetsAtom", @@ -121,44 +115,6 @@ export const chartFromReportAtom = atom<{ effects_UNSTABLE: [persistAtom], }); -export const persistedReportStateAtom = atom<{ - reportName: string; - headerDetails: { - title: string; - description: string; - heading: string; - showHeader: boolean; - backgroundColor: string; - titleColor: string; - descriptionColor: string; - dateColor: string; - }; - - framesArray: string; -}>({ - key: "reportCreateStateAtom", - default: { - reportName: "Untitled report", - headerDetails: { - title: "", - description: JSON.stringify( - convertToRaw(EditorState.createEmpty().getCurrentContent()) - ), - heading: JSON.stringify( - convertToRaw(EditorState.createEmpty().getCurrentContent()) - ), - showHeader: true, - backgroundColor: "#252c34", - titleColor: "#ffffff", - descriptionColor: "#ffffff", - dateColor: "#ffffff", - }, - - framesArray: JSON.stringify([]), - }, - effects_UNSTABLE: [persistAtom], -}); - export const dataUploadTabAtom = atom<"search" | "file">({ key: "dataUploadTabAtom", default: "search", From c9372f8e1341fe23d2d46edd719b26f4a5f8202f Mon Sep 17 00:00:00 2001 From: okorie2 Date: Fri, 13 Sep 2024 18:56:43 +0100 Subject: [PATCH 50/58] feat:adjust placeholder & row gap --- .../components/placeholder/index.tsx | 134 ++++++++++++++++++ .../report-module/views/edit/index.tsx | 17 ++- 2 files changed, 145 insertions(+), 6 deletions(-) create mode 100644 src/app/modules/report-module/components/placeholder/index.tsx diff --git a/src/app/modules/report-module/components/placeholder/index.tsx b/src/app/modules/report-module/components/placeholder/index.tsx new file mode 100644 index 000000000..0ec0e5671 --- /dev/null +++ b/src/app/modules/report-module/components/placeholder/index.tsx @@ -0,0 +1,134 @@ +import React from "react"; +import { PlaceholderProps } from "app/modules/report-module/views/create/data"; +import { ReportElementsType } from "app/modules/report-module/components/right-panel-create-view"; +import { useDrop } from "react-dnd"; +import { isDividerOrRowFrameDraggingAtom } from "app/state/recoil/atoms"; +import { useRecoilValue } from "recoil"; +import { v4 } from "uuid"; + +const PlaceHolder = (props: PlaceholderProps) => { + const moveCard = React.useCallback((itemId: string) => { + props.updateFramesArray((draft) => { + const dragIndex = draft.findIndex((frame) => frame.id === itemId); + + const dropIndex = + props.index ?? draft.findIndex((frame) => frame.id === props.rowId) + 1; + + const fakeId = v4(); + const tempItem = draft[dragIndex]; + draft[dragIndex].id = fakeId; + + draft.splice(dropIndex, 0, tempItem); + const fakeIndex = draft.findIndex((frame) => frame.id === fakeId); + draft.splice(fakeIndex, 1); + }); + }, []); + const [{ isOver, handlerId, item: dragItem }, drop] = useDrop(() => ({ + // The type (or types) to accept - strings or symbols + accept: [ + ReportElementsType.DIVIDER, + ReportElementsType.ROWFRAME, + ReportElementsType.ROW, + ], + // Props to collect + collect: (monitor) => ({ + isOver: monitor.isOver(), + canDrop: monitor.canDrop(), + item: monitor.getItem(), + handlerId: monitor.getHandlerId(), + }), + drop: (item: any, monitor) => { + if (item.type === ReportElementsType.ROW) { + moveCard(item.id); + } else { + props.updateFramesArray((draft) => { + const tempIndex = + props.index ?? + draft.findIndex((frame) => frame.id === props.rowId) + 1; + + const id = v4(); + draft.splice(tempIndex, 0, { + id, + frame: { + rowId: id, + rowIndex: tempIndex, + + type: item.type, + }, + content: + item.type === ReportElementsType.ROWFRAME ? [] : ["divider"], + contentWidths: [], + contentHeights: [], + contentTypes: + item.type === ReportElementsType.ROWFRAME ? [] : ["divider"], + structure: null, + }); + }); + } + }, + })); + + const isItemDragging = useRecoilValue(isDividerOrRowFrameDraggingAtom); + + const itemDragIndex = props.framesArray.findIndex( + (frame) => frame.id === isItemDragging.rowId + ); + + const placeholderIndex = + props.index ?? + props.framesArray.findIndex((frame) => frame.id === props.rowId) + 1; + + const dragIndex = props.framesArray.findIndex( + (frame) => frame.id === (dragItem as any)?.id + ); + + const placeholderActive = () => { + if (isOver) { + if (dragIndex === -1) { + return true; + } + if (placeholderIndex === dragIndex) { + return false; + } + if (placeholderIndex - 1 === dragIndex) { + return false; + } + return true; + } + return false; + }; + + const isDroppable = () => { + if (isItemDragging.state) { + if (itemDragIndex === -1) { + return true; + } + if (placeholderIndex === itemDragIndex) { + return false; + } + if (placeholderIndex - 1 === itemDragIndex) { + return false; + } + return true; + } + return false; + }; + + return ( +
+ ); +}; + +export default PlaceHolder; diff --git a/src/app/modules/report-module/views/edit/index.tsx b/src/app/modules/report-module/views/edit/index.tsx index 5107863d9..c0c948aaf 100644 --- a/src/app/modules/report-module/views/edit/index.tsx +++ b/src/app/modules/report-module/views/edit/index.tsx @@ -8,15 +8,14 @@ import Container from "@material-ui/core/Container"; import { EditorState, RawDraftContentState, convertFromRaw } from "draft-js"; import { useTitle } from "react-use"; import { useAuth0 } from "@auth0/auth0-react"; -import { PlaceHolder } from "app/modules/report-module/views/create"; import { useStoreActions, useStoreState } from "app/state/store/hooks"; import { ReportModel, emptyReport } from "app/modules/report-module/data"; import { ReportEditViewProps } from "app/modules/report-module/views/edit/data"; -import HeaderBlock from "app/modules/report-module/sub-module/components/headerBlock"; +import HeaderBlock from "app/modules/report-module/components/headerBlock"; import { NotAuthorizedMessageModule } from "app/modules/common/not-authorized-message"; import { ItemComponent } from "app/modules/report-module/components/order-container"; import { ReportElementsType } from "app/modules/report-module/components/right-panel-create-view"; -import AddRowFrameButton from "app/modules/report-module/sub-module/rowStructure/addRowFrameButton"; +import AddRowFrameButton from "app/modules/report-module/components/rowStructure/addRowFrameButton"; import { GridColumns } from "app/modules/report-module/components/grid-columns"; import { @@ -25,7 +24,7 @@ import { reportContentContainerWidth, } from "app/state/recoil/atoms"; import { IFramesArray } from "app/modules/report-module/views/create/data"; -import RowFrame from "app/modules/report-module/sub-module/rowStructure"; +import RowFrame from "app/modules/report-module/components/rowStructure"; import TourGuide from "app/components/Dialogs/TourGuide"; import useCookie from "@devhammed/use-cookie"; import isEqual from "lodash/isEqual"; @@ -36,8 +35,9 @@ import { compareFramesArrayState, compareHeaderDetailsState, } from "app/modules/report-module/views/edit/compareStates"; +import PlaceHolder from "app/modules/report-module/components/placeholder"; -function ReportEditView(props: ReportEditViewProps) { +function ReportEditView(props: Readonly) { useTitle("DX Dataxplorer - Edit Report"); const { page } = useParams<{ page: string }>(); @@ -395,7 +395,12 @@ function ReportEditView(props: ReportEditViewProps) { />
- +
+ {/* */} Date: Fri, 13 Sep 2024 18:57:21 +0100 Subject: [PATCH 51/58] chore: folder restructure --- .../__test__/headerBlock.test.tsx | 10 +- .../components/headerBlock/index.tsx | 2 +- .../components/headerBlock/style.ts | 0 .../rowStructure/addRowFrameButton.tsx | 0 .../rowStructure/index.tsx | 4 +- .../rowStructure/rowStructureDisplay.tsx | 0 .../rowStructure/style.ts | 0 .../report-module/views/create/index.tsx | 141 +----------------- .../report-module/views/edit/index.tsx | 1 - .../report-module/views/preview/index.tsx | 4 +- 10 files changed, 13 insertions(+), 149 deletions(-) rename src/app/modules/report-module/{sub-module => }/components/headerBlock/index.tsx (99%) rename src/app/modules/report-module/{sub-module => }/components/headerBlock/style.ts (100%) rename src/app/modules/report-module/{sub-module => components}/rowStructure/addRowFrameButton.tsx (100%) rename src/app/modules/report-module/{sub-module => components}/rowStructure/index.tsx (99%) rename src/app/modules/report-module/{sub-module => components}/rowStructure/rowStructureDisplay.tsx (100%) rename src/app/modules/report-module/{sub-module => components}/rowStructure/style.ts (100%) diff --git a/src/app/modules/report-module/__test__/headerBlock.test.tsx b/src/app/modules/report-module/__test__/headerBlock.test.tsx index 9ad3b5349..10380eb7c 100644 --- a/src/app/modules/report-module/__test__/headerBlock.test.tsx +++ b/src/app/modules/report-module/__test__/headerBlock.test.tsx @@ -1,12 +1,6 @@ -import { - act, - fireEvent, - render, - screen, - waitFor, -} from "@testing-library/react"; +import { fireEvent, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; -import HeaderBlock from "app/modules/report-module/sub-module/components/headerBlock/"; +import HeaderBlock from "app/modules/report-module/components/headerBlock"; import { ContentState, EditorState } from "draft-js"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; import Router from "react-router-dom"; diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx b/src/app/modules/report-module/components/headerBlock/index.tsx similarity index 99% rename from src/app/modules/report-module/sub-module/components/headerBlock/index.tsx rename to src/app/modules/report-module/components/headerBlock/index.tsx index 512c070bd..e870a375c 100644 --- a/src/app/modules/report-module/sub-module/components/headerBlock/index.tsx +++ b/src/app/modules/report-module/components/headerBlock/index.tsx @@ -11,7 +11,7 @@ import { reportRightPanelViewAtom } from "app/state/recoil/atoms"; import { RichEditor } from "app/modules/common/RichEditor"; import { ReactComponent as EditIcon } from "app/modules/report-module/asset/editIcon.svg"; import { ReactComponent as DeleteIcon } from "app/modules/report-module/asset/deleteIcon.svg"; -import { headerBlockcss } from "app/modules/report-module/sub-module/components/headerBlock/style"; +import { headerBlockcss } from "app/modules/report-module/components/headerBlock/style"; import { ReactComponent as HeaderHandlesvg } from "app/modules/report-module/asset/header-handle.svg"; import { Tooltip } from "@material-ui/core"; import useDebounce from "react-use/lib/useDebounce"; diff --git a/src/app/modules/report-module/sub-module/components/headerBlock/style.ts b/src/app/modules/report-module/components/headerBlock/style.ts similarity index 100% rename from src/app/modules/report-module/sub-module/components/headerBlock/style.ts rename to src/app/modules/report-module/components/headerBlock/style.ts diff --git a/src/app/modules/report-module/sub-module/rowStructure/addRowFrameButton.tsx b/src/app/modules/report-module/components/rowStructure/addRowFrameButton.tsx similarity index 100% rename from src/app/modules/report-module/sub-module/rowStructure/addRowFrameButton.tsx rename to src/app/modules/report-module/components/rowStructure/addRowFrameButton.tsx diff --git a/src/app/modules/report-module/sub-module/rowStructure/index.tsx b/src/app/modules/report-module/components/rowStructure/index.tsx similarity index 99% rename from src/app/modules/report-module/sub-module/rowStructure/index.tsx rename to src/app/modules/report-module/components/rowStructure/index.tsx index ce2ac197e..6dddbeda5 100644 --- a/src/app/modules/report-module/sub-module/rowStructure/index.tsx +++ b/src/app/modules/report-module/components/rowStructure/index.tsx @@ -5,7 +5,7 @@ import { useUpdateEffect } from "react-use"; import IconButton from "@material-ui/core/IconButton"; import { useHistory, useLocation, useParams } from "react-router-dom"; import { itemSpacing, containerGap } from "app/modules/report-module/data"; -import RowstructureDisplay from "app/modules/report-module/sub-module/rowStructure/rowStructureDisplay"; +import RowstructureDisplay from "app/modules/report-module/components/rowStructure/rowStructureDisplay"; import { ReactComponent as CloseIcon } from "app/modules/report-module/asset/closeIcon.svg"; import { ReactComponent as DeleteIcon } from "app/modules/report-module/asset/deleteIcon.svg"; import { @@ -15,7 +15,7 @@ import { import { blockcss, containercss, -} from "app/modules/report-module/sub-module/rowStructure/style"; +} from "app/modules/report-module/components/rowStructure/style"; import { IFramesArray } from "app/modules/report-module/views/create/data"; import { useOnClickOutside } from "usehooks-ts"; import { ToolbarPluginsType } from "app/modules/report-module/components/reportSubHeaderToolbar/staticToolbar"; diff --git a/src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx b/src/app/modules/report-module/components/rowStructure/rowStructureDisplay.tsx similarity index 100% rename from src/app/modules/report-module/sub-module/rowStructure/rowStructureDisplay.tsx rename to src/app/modules/report-module/components/rowStructure/rowStructureDisplay.tsx diff --git a/src/app/modules/report-module/sub-module/rowStructure/style.ts b/src/app/modules/report-module/components/rowStructure/style.ts similarity index 100% rename from src/app/modules/report-module/sub-module/rowStructure/style.ts rename to src/app/modules/report-module/components/rowStructure/style.ts diff --git a/src/app/modules/report-module/views/create/index.tsx b/src/app/modules/report-module/views/create/index.tsx index f3bd6f27d..11688a9a6 100644 --- a/src/app/modules/report-module/views/create/index.tsx +++ b/src/app/modules/report-module/views/create/index.tsx @@ -1,27 +1,22 @@ import React from "react"; import { v4 } from "uuid"; -import { useDrop } from "react-dnd"; import Box from "@material-ui/core/Box"; import Container from "@material-ui/core/Container"; import useResizeObserver from "use-resize-observer"; -import { useRecoilState, useRecoilValue } from "recoil"; +import { useRecoilState } from "recoil"; import { GridColumns } from "app/modules/report-module/components/grid-columns"; -import HeaderBlock from "app/modules/report-module/sub-module/components/headerBlock"; +import HeaderBlock from "app/modules/report-module/components/headerBlock"; import { ItemComponent } from "app/modules/report-module/components/order-container"; -import { ReportElementsType } from "app/modules/report-module/components/right-panel-create-view"; -import AddRowFrameButton from "app/modules/report-module/sub-module/rowStructure/addRowFrameButton"; -import RowFrame from "app/modules/report-module/sub-module/rowStructure"; -import { - ReportCreateViewProps, - PlaceholderProps, -} from "app/modules/report-module/views/create/data"; +import AddRowFrameButton from "app/modules/report-module/components/rowStructure/addRowFrameButton"; +import RowFrame from "app/modules/report-module/components/rowStructure"; +import { ReportCreateViewProps } from "app/modules/report-module/views/create/data"; import { IRowFrameStructure, reportContentContainerWidth, - isDividerOrRowFrameDraggingAtom, } from "app/state/recoil/atoms"; import TourGuide from "app/components/Dialogs/TourGuide"; import { useTitle } from "react-use"; +import PlaceHolder from "app/modules/report-module/components/placeholder"; function ReportCreateView(props: Readonly) { useTitle("DX Dataxplorer - Create Report"); @@ -197,127 +192,3 @@ function ReportCreateView(props: Readonly) { } export default ReportCreateView; - -export const PlaceHolder = (props: PlaceholderProps) => { - const moveCard = React.useCallback((itemId: string) => { - props.updateFramesArray((draft) => { - const dragIndex = draft.findIndex((frame) => frame.id === itemId); - - const dropIndex = - props.index ?? draft.findIndex((frame) => frame.id === props.rowId) + 1; - - const fakeId = v4(); - const tempItem = draft[dragIndex]; - draft[dragIndex].id = fakeId; - - draft.splice(dropIndex, 0, tempItem); - const fakeIndex = draft.findIndex((frame) => frame.id === fakeId); - draft.splice(fakeIndex, 1); - }); - }, []); - const [{ isOver, handlerId, item: dragItem }, drop] = useDrop(() => ({ - // The type (or types) to accept - strings or symbols - accept: [ - ReportElementsType.DIVIDER, - ReportElementsType.ROWFRAME, - ReportElementsType.ROW, - ], - // Props to collect - collect: (monitor) => ({ - isOver: monitor.isOver(), - canDrop: monitor.canDrop(), - item: monitor.getItem(), - handlerId: monitor.getHandlerId(), - }), - drop: (item: any, monitor) => { - if (item.type === ReportElementsType.ROW) { - moveCard(item.id); - } else { - props.updateFramesArray((draft) => { - const tempIndex = - props.index ?? - draft.findIndex((frame) => frame.id === props.rowId) + 1; - - const id = v4(); - draft.splice(tempIndex, 0, { - id, - frame: { - rowId: id, - rowIndex: tempIndex, - - type: item.type, - }, - content: - item.type === ReportElementsType.ROWFRAME ? [] : ["divider"], - contentWidths: [], - contentHeights: [], - contentTypes: - item.type === ReportElementsType.ROWFRAME ? [] : ["divider"], - structure: null, - }); - }); - } - }, - })); - - const isItemDragging = useRecoilValue(isDividerOrRowFrameDraggingAtom); - - const itemDragIndex = props.framesArray.findIndex( - (frame) => frame.id === isItemDragging.rowId - ); - - const placeholderIndex = - props.index ?? - props.framesArray.findIndex((frame) => frame.id === props.rowId) + 1; - - const dragIndex = props.framesArray.findIndex( - (frame) => frame.id === (dragItem as any)?.id - ); - - const placeholderActive = () => { - if (isOver) { - if (dragIndex === -1) { - return true; - } - if (placeholderIndex === dragIndex) { - return false; - } - if (placeholderIndex - 1 === dragIndex) { - return false; - } - return true; - } - return false; - }; - - const isDroppable = () => { - if (isItemDragging.state) { - if (itemDragIndex === -1) { - return true; - } - if (placeholderIndex === itemDragIndex) { - return false; - } - if (placeholderIndex - 1 === itemDragIndex) { - return false; - } - return true; - } - return false; - }; - - return ( -
- ); -}; diff --git a/src/app/modules/report-module/views/edit/index.tsx b/src/app/modules/report-module/views/edit/index.tsx index c0c948aaf..677353f7b 100644 --- a/src/app/modules/report-module/views/edit/index.tsx +++ b/src/app/modules/report-module/views/edit/index.tsx @@ -400,7 +400,6 @@ function ReportEditView(props: Readonly) { height: 20px; `} /> - {/* */} Date: Mon, 30 Sep 2024 14:27:51 +0100 Subject: [PATCH 52/58] feat: DX-1815 - Implement the Homepage missing MS button for sign in --- src/app/modules/home-module/index.tsx | 4 ++++ src/app/modules/home-module/sub-modules/about/index.tsx | 4 ++++ .../sub-modules/partners/components/empowerBlock.tsx | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/app/modules/home-module/index.tsx b/src/app/modules/home-module/index.tsx index 52629c4cb..dc2e3d865 100644 --- a/src/app/modules/home-module/index.tsx +++ b/src/app/modules/home-module/index.tsx @@ -11,6 +11,7 @@ import HomeFooter from "app/modules/home-module/components/Footer"; import DatasetDetailImage from "app/modules/home-module/assets/dataset-detail.png"; import { ReactComponent as GoogleIcon } from "app/modules/onboarding-module/asset/google-img.svg"; import { ReactComponent as LinkedInIcon } from "app/modules/onboarding-module/asset/linkedIn-img.svg"; +import { ReactComponent as MicrosoftIcon } from "app/modules/onboarding-module/asset/microsoft-img.svg"; import HeroEllipses from "app/modules/home-module/assets/hero-ellipses.svg"; import { homeDisplayAtom } from "app/state/recoil/atoms"; @@ -142,6 +143,9 @@ export default function HomeModule() { +
)}
diff --git a/src/app/modules/home-module/sub-modules/about/index.tsx b/src/app/modules/home-module/sub-modules/about/index.tsx index 970453e8c..920f8c0e0 100644 --- a/src/app/modules/home-module/sub-modules/about/index.tsx +++ b/src/app/modules/home-module/sub-modules/about/index.tsx @@ -16,6 +16,7 @@ import { useAuth0 } from "@auth0/auth0-react"; import { socialAuth } from "app/utils/socialAuth"; import { ReactComponent as GoogleIcon } from "app/modules/onboarding-module/asset/google-img.svg"; import { ReactComponent as LinkedInIcon } from "app/modules/onboarding-module/asset/linkedIn-img.svg"; +import { ReactComponent as MicrosoftIcon } from "app/modules/onboarding-module/asset/microsoft-img.svg"; import SiemAvi from "app/modules/home-module/assets/team/siem.png"; import JohnAvi from "app/modules/home-module/assets/team/john.png"; import KennyAvi from "app/modules/home-module/assets/team/kenny.png"; @@ -382,6 +383,9 @@ export default function AboutModule() { +
)}
diff --git a/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx b/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx index a533e5541..9b0eca865 100644 --- a/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx +++ b/src/app/modules/home-module/sub-modules/partners/components/empowerBlock.tsx @@ -5,6 +5,7 @@ import { socialAuth } from "app/utils/socialAuth"; import { HomePrimaryButton } from "app/components/Styled/button"; import { ReactComponent as GoogleIcon } from "app/modules/onboarding-module/asset/google-img.svg"; import { ReactComponent as LinkedInIcon } from "app/modules/onboarding-module/asset/linkedIn-img.svg"; +import { ReactComponent as MicrosoftIcon } from "app/modules/onboarding-module/asset/microsoft-img.svg"; import { ReactComponent as Ellipses } from "app/modules/home-module/assets/ellipses.svg"; import { ReactComponent as EllipsesMobile } from "app/modules/home-module/assets/ellipses-mobile.svg"; import { @@ -147,6 +148,9 @@ export default function EmpowerBlock(props: { +
)} Date: Mon, 30 Sep 2024 14:34:37 +0100 Subject: [PATCH 53/58] feat: DX-1821 - Implement MS Drive in Pricing as well --- .../home-module/sub-modules/pricing/components/features.tsx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx index 354697d38..49945d19a 100644 --- a/src/app/modules/home-module/sub-modules/pricing/components/features.tsx +++ b/src/app/modules/home-module/sub-modules/pricing/components/features.tsx @@ -54,6 +54,11 @@ const Features = () => { info: "Connect data from your database", values: ["", true, true, true], }, + { + name: "Microsoft Drive data connect", + info: "Connect data from your Microsoft Drive", + values: ["", true, true, true], + }, { name: "Google Drive data connect", info: "Connect data from your Google Drive", From ad6ef94a222a3429acf3a4b5adc6669d65343a92 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Mon, 30 Sep 2024 14:36:52 +0100 Subject: [PATCH 54/58] feat: DX-1829 - Update new SAVE state feedback as per 1828 --- .../chart-module/components/toolbox/index.tsx | 96 +++++++++++++++---- .../components/toolbox/steps/index.tsx | 15 ++- src/app/modules/chart-module/index.tsx | 7 ++ src/app/state/recoil/atoms/index.ts | 12 +++ 4 files changed, 110 insertions(+), 20 deletions(-) diff --git a/src/app/modules/chart-module/components/toolbox/index.tsx b/src/app/modules/chart-module/components/toolbox/index.tsx index 0e4a673d0..0e09c5248 100644 --- a/src/app/modules/chart-module/components/toolbox/index.tsx +++ b/src/app/modules/chart-module/components/toolbox/index.tsx @@ -217,6 +217,7 @@ export function ChartModuleToolBox(props: Readonly) { onMouseOverNavBtn={onMouseOverNavBtn} setChartFromAPI={props.setChartFromAPI} deselectDataset={props.deselectDataset} + setShowSnackbar={setShowSnackbar} /> )} @@ -233,24 +234,83 @@ export function ChartModuleToolBox(props: Readonly) { onClose={() => setShowSnackbar(null)} open={showSnackbar !== null && showSnackbar !== ""} > - - {!location.pathname.includes("report") && ( - - )} - - } - /> +
+

+ Your chart has been successfully created! You can now find it in + your library. +

+
+ +

+ or +

+ + +
+
); diff --git a/src/app/modules/chart-module/components/toolbox/steps/index.tsx b/src/app/modules/chart-module/components/toolbox/steps/index.tsx index 03d1d95a5..158b37922 100644 --- a/src/app/modules/chart-module/components/toolbox/steps/index.tsx +++ b/src/app/modules/chart-module/components/toolbox/steps/index.tsx @@ -18,7 +18,7 @@ import { isEmpty } from "lodash"; import { ToolboxNavType } from "app/modules/chart-module/components/toolbox/data"; import { ChartRenderedItem } from "app/modules/chart-module/data"; -import { chartFromReportAtom } from "app/state/recoil/atoms"; +import { chartFromReportAtom, newChartAtom } from "app/state/recoil/atoms"; import { useRecoilState } from "recoil"; interface ChartToolBoxStepsProps { @@ -45,6 +45,7 @@ interface ChartToolBoxStepsProps { value: React.SetStateAction ) => void; deselectDataset: () => void; + setShowSnackbar: (value: string | null) => void; } export function ChartToolBoxSteps(props: ChartToolBoxStepsProps) { @@ -56,6 +57,7 @@ export function ChartToolBoxSteps(props: ChartToolBoxStepsProps) { const appliedFilters = useStoreState( (state) => state.charts.appliedFilters.value ); + const [newChart, setNewChart] = useRecoilState(newChartAtom); const [chartFromReport, setChartFromReport] = useRecoilState(chartFromReportAtom); let appliedFiltersCount = 0; @@ -71,6 +73,15 @@ export function ChartToolBoxSteps(props: ChartToolBoxStepsProps) { if (chartFromReport.state) { setChartFromReport((prev) => ({ ...prev, chartId: page })); history.push(`/report/${reportPage}/edit`); + } else { + if (newChart.state && newChart.chartId === page) { + props.setShowSnackbar("Chart saved successfully"); + setNewChart({ + state: false, + chartId: null, + }); + } + history.push(`/chart/${page}`); } } }; @@ -226,7 +237,7 @@ export function ChartToolBoxSteps(props: ChartToolBoxStepsProps) { }} data-cy="toolbox-chart-next" > - {currentPathIndex < 5 ? "Next" : "Save"} + {currentPathIndex < 5 ? "Next" : "Save and Preview"}
diff --git a/src/app/modules/chart-module/index.tsx b/src/app/modules/chart-module/index.tsx index bd1f2464a..d0dc41747 100644 --- a/src/app/modules/chart-module/index.tsx +++ b/src/app/modules/chart-module/index.tsx @@ -57,6 +57,7 @@ import { chartFromReportAtom, isChartAIAgentActive, isChartAutoMappedAtom, + newChartAtom, planDialogAtom, } from "app/state/recoil/atoms"; import { IDatasetDetails } from "./components/toolbox/steps/panels-content/SelectDataset"; @@ -76,6 +77,8 @@ export default function ChartModule() { const setPlanDialog = useSetRecoilState(planDialogAtom); + const setNewChart = useSetRecoilState(newChartAtom); + const [rawViz, setRawViz] = React.useState(null); const [toolboxOpen, setToolboxOpen] = React.useState(Boolean(isValidView)); const [savedChanges, setSavedChanges] = React.useState(false); @@ -333,6 +336,10 @@ export default function ChartModule() { onTryAgain: () => {}, }); } + setNewChart({ + state: true, + chartId: data.id, + }); history.push( `/chart/${data.id}/mapping${ chartFromReport.state diff --git a/src/app/state/recoil/atoms/index.ts b/src/app/state/recoil/atoms/index.ts index 7e5a60047..6f5be3745 100644 --- a/src/app/state/recoil/atoms/index.ts +++ b/src/app/state/recoil/atoms/index.ts @@ -121,6 +121,18 @@ export const chartFromReportAtom = atom<{ effects_UNSTABLE: [persistAtom], }); +export const newChartAtom = atom<{ + state: boolean; + chartId: string | null; +}>({ + key: "newChartAtom", + default: { + state: false, + chartId: null, + }, + effects_UNSTABLE: [persistAtom], +}); + export const persistedReportStateAtom = atom<{ reportName: string; headerDetails: { From d99d5155dd0e27a388d7b9fafebb462c2aa4076b Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Mon, 30 Sep 2024 14:39:06 +0100 Subject: [PATCH 55/58] feat: DX-1725 - [bar chart] 8 pixel gap between bars --- src/app/hooks/useDataThemesEchart.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/app/hooks/useDataThemesEchart.tsx b/src/app/hooks/useDataThemesEchart.tsx index 9c18037bb..daaf93d42 100644 --- a/src/app/hooks/useDataThemesEchart.tsx +++ b/src/app/hooks/useDataThemesEchart.tsx @@ -79,6 +79,7 @@ export function useDataThemesEchart() { barWidth, xAxisLineColor, xAxisLabelFontSize, + autoBarWidth, focus, xAxisLabelColor, xAxisLabelInterval, @@ -136,11 +137,11 @@ export function useDataThemesEchart() { { type: "inside", start: 0, - end: 20, + end: 100, }, { start: 0, - end: 20, + end: 100, }, ] : null, @@ -162,7 +163,7 @@ export function useDataThemesEchart() { emphasis: { focus, }, - barWidth, + barWidth: autoBarWidth ? undefined : barWidth, }, ], tooltip: { From 4d892bb37d9c933651e07de6a328b438756a6057 Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Mon, 30 Sep 2024 14:40:03 +0100 Subject: [PATCH 56/58] feat: DX-1824 - A sign in button is drifting in the footer, not sure why :-) --- .../components/Footer/DesktopFooter.tsx | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/app/modules/home-module/components/Footer/DesktopFooter.tsx b/src/app/modules/home-module/components/Footer/DesktopFooter.tsx index 0e55b8b6d..938601003 100644 --- a/src/app/modules/home-module/components/Footer/DesktopFooter.tsx +++ b/src/app/modules/home-module/components/Footer/DesktopFooter.tsx @@ -216,25 +216,6 @@ export default function DesktopFooter() { ? "Oops! Something went wrong with the request! Please fill your email again." : " You will receive occasional emails from DX. You always have choice to unsubscribe within every Email."}

- - -
Date: Tue, 1 Oct 2024 06:44:28 +0100 Subject: [PATCH 57/58] fix: Duplicating an asset in detail page leads to undefined route --- .../chart-module/components/chartSubheaderToolbar/index.tsx | 2 +- .../dataset-module/component/datasetSubHeaderToolbar.tsx | 2 +- .../report-module/components/reportSubHeaderToolbar/index.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx index 8b578b244..a36f4fc90 100644 --- a/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx +++ b/src/app/modules/chart-module/components/chartSubheaderToolbar/index.tsx @@ -252,7 +252,7 @@ export function ChartSubheaderToolbar( storeInCrudData: true, filterString: "filter[order]=updatedDate desc", }); - setDuplicatedChartId(response.data.id); + setDuplicatedChartId(response.data?.data?.id); setSnackbarState({ ...snackbarState, open: true, diff --git a/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx b/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx index 6ad638dcf..9d406388c 100644 --- a/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx +++ b/src/app/modules/dataset-module/component/datasetSubHeaderToolbar.tsx @@ -110,7 +110,7 @@ export default function DatasetSubHeaderToolbar( onTryAgain: () => {}, }); } - setDuplicatedDatasetId(response.data.id); + setDuplicatedDatasetId(response.data?.data?.id); setSnackbarState({ ...snackbarState, open: true, diff --git a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx index 76acdbd84..8ce6f7e47 100644 --- a/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx +++ b/src/app/modules/report-module/components/reportSubHeaderToolbar/index.tsx @@ -230,7 +230,7 @@ export function ReportSubheaderToolbar( storeInCrudData: true, filterString: "filter[order]=updatedDate desc", }); - setDuplicatedReportId(response.data.id); + setDuplicatedReportId(response.data?.data?.id); setSnackbarState({ ...snackbarState, open: true, From 9ee1a5f27f04db082cea00df40e0fb88da72b39a Mon Sep 17 00:00:00 2001 From: Psami-wondah Date: Tue, 1 Oct 2024 07:06:47 +0100 Subject: [PATCH 58/58] test: update jest test --- .../chart-module/__test__/chartSubheaderToolbar.test.tsx | 2 +- .../report-module/__test__/reportSubheaderToolbar.test.tsx | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/app/modules/chart-module/__test__/chartSubheaderToolbar.test.tsx b/src/app/modules/chart-module/__test__/chartSubheaderToolbar.test.tsx index 126446bcc..49a60d8f1 100644 --- a/src/app/modules/chart-module/__test__/chartSubheaderToolbar.test.tsx +++ b/src/app/modules/chart-module/__test__/chartSubheaderToolbar.test.tsx @@ -581,7 +581,7 @@ test("clicking duplicate button should duplicate chart", async () => { const mockedAxios = axios.get as jest.Mock; mockedAxios .mockResolvedValueOnce({ - data: { id: "chart-id" }, + data: { data: { id: "chart-id" } }, } as AxiosResponse) .mockResolvedValueOnce({ data: mockChartList }); jest diff --git a/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx b/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx index ab1733f65..4874a179c 100644 --- a/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx +++ b/src/app/modules/report-module/__test__/reportSubheaderToolbar.test.tsx @@ -414,8 +414,10 @@ describe("Tests for tablet and desktop view", () => { const axiosMock = axios.get as jest.Mock; axiosMock - .mockResolvedValueOnce({ data: { id: "12345" } } as AxiosResponse) - .mockResolvedValueOnce({ data: [] }); + .mockResolvedValueOnce({ + data: { data: { id: "12345" } }, + } as AxiosResponse) + .mockResolvedValueOnce({ data: { data: [] } }); jest .spyOn(Router, "useParams") .mockReturnValue({ page: "12345", view: undefined });