diff --git a/packages/bot-web-ui/src/components/dashboard/bot-builder/bot-builder.tsx b/packages/bot-web-ui/src/components/dashboard/bot-builder/bot-builder.tsx index c3b4a246bef4..52343434c53e 100644 --- a/packages/bot-web-ui/src/components/dashboard/bot-builder/bot-builder.tsx +++ b/packages/bot-web-ui/src/components/dashboard/bot-builder/bot-builder.tsx @@ -6,42 +6,60 @@ import ReactJoyride from 'react-joyride'; import classNames from 'classnames'; import WorkspaceWrapper from './workspace-wrapper'; import { BOT_BUILDER_TOUR } from '../joyride-config'; +import LoadModal from 'Components/load-modal'; type TBotBuilder = { app: AppStore; active_tab: number; + has_onboard_tour_started: boolean; + is_preview_on_popup: boolean; + setOnBoardTourRunState: (has_onboard_tour_started: boolean) => boolean; }; -const BotBuilder = ({ app, active_tab }: TBotBuilder) => { +const BotBuilder = ({ app, active_tab, has_onboard_tour_started, is_preview_on_popup }: TBotBuilder) => { const { onMount, onUnmount } = app; React.useEffect(() => { onMount(); return () => onUnmount(); }, []); - return ( -
-
- - {active_tab === 1 && ( - - )} -
+
+ {is_preview_on_popup ? null : ( +
+ + {active_tab === 1 && !has_onboard_tour_started && ( + + )} +
+ )} + {/* removed this outside from toolbar becuase it needs to loaded seperately without dependency */} +
); }; @@ -49,4 +67,7 @@ const BotBuilder = ({ app, active_tab }: TBotBuilder) => { export default connect(({ app, dashboard }: RootStore) => ({ app, active_tab: dashboard.active_tab, + has_onboard_tour_started: dashboard.has_onboard_tour_started, + setOnBoardTourRunState: dashboard.setOnBoardTourRunState, + is_preview_on_popup: dashboard.is_preview_on_popup, }))(BotBuilder); diff --git a/packages/bot-web-ui/src/components/dashboard/bot-builder/index.ts b/packages/bot-web-ui/src/components/dashboard/bot-builder/index.ts index d3dea9d16a25..1c8f93b29e84 100644 --- a/packages/bot-web-ui/src/components/dashboard/bot-builder/index.ts +++ b/packages/bot-web-ui/src/components/dashboard/bot-builder/index.ts @@ -1,3 +1,4 @@ import BotBuilder from './bot-builder'; +import './workspace.scss'; export default BotBuilder; diff --git a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/icon-button.tsx b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/icon-button.tsx new file mode 100644 index 000000000000..b2796294f606 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/icon-button.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Popover, Icon } from '@deriv/components'; +import { popover_zindex } from 'Constants/z-indexes'; + +type TIconButton = { + icon: string; + icon_id: string; + iconOnClick: () => void; + icon_color?: string; + popover_message: string; +}; + +const IconButton = ({ popover_message, icon, icon_id, icon_color, iconOnClick }: TIconButton) => { + + + ; +}; + +export default IconButton; diff --git a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/run-strategy.tsx b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/run-strategy.tsx new file mode 100644 index 000000000000..bef7c154a4d6 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/run-strategy.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import TradeAnimation from 'Components/trade-animation'; + +const RunStrategy = () => ( +
+ +
+); + +export default RunStrategy; diff --git a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/toolbar.tsx b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/toolbar.tsx index a896ee8a995c..00794c4cf808 100644 --- a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/toolbar.tsx +++ b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/toolbar.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { Dialog } from '@deriv/components'; import { Localize, localize } from '@deriv/translations'; -import LoadModal from 'Components/load-modal'; import SaveModal from 'Components/save-modal'; import { connect } from 'Stores/connect'; import RootStore from 'Stores/index'; @@ -44,7 +43,6 @@ const Toolbar = (props: TToolbar) => {
- { cancel_button_text={cancel_button_text} onCancel={closeResetDialog} is_mobile_full_width={false} - className={'toolbar__dialog dc-dialog__wrapper--fixed'} + className={'toolbar__dialog'} has_close_icon > {is_running ? ( diff --git a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/workspace-group.tsx b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/workspace-group.tsx index a7daab926f10..56ea39e87b53 100644 --- a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/workspace-group.tsx +++ b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbar/workspace-group.tsx @@ -1,6 +1,8 @@ import React from 'react'; import { localize } from '@deriv/translations'; import ToolbarIcon from './toolbar-icon'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; type TWorkspaceGroup = { has_redo_stack: boolean; @@ -9,6 +11,7 @@ type TWorkspaceGroup = { onSortClick: () => void; onUndoClick: (param?: boolean) => void; onZoomInOutClick: (param?: boolean) => void; + setPreviewOnPopup: (param: boolean) => void; toggleLoadModal: () => void; toggleSaveModal: () => void; }; @@ -20,6 +23,7 @@ const WorkspaceGroup = ({ onSortClick, onUndoClick, onZoomInOutClick, + setPreviewOnPopup, toggleLoadModal, toggleSaveModal, }: TWorkspaceGroup) => ( @@ -34,7 +38,10 @@ const WorkspaceGroup = ({ popover_message={localize('Import')} icon='IcFolderOpen' icon_id='db-toolbar__import-button' - action={toggleLoadModal} + action={() => { + setPreviewOnPopup(true); + toggleLoadModal(); + }} /> ); -export default WorkspaceGroup; +export default connect(({ dashboard }: RootStore) => ({ + setPreviewOnPopup: dashboard.setPreviewOnPopup, +}))(WorkspaceGroup); diff --git a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbox/toolbox.tsx b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbox/toolbox.tsx index b7df9f513add..5c10e926e0ea 100644 --- a/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbox/toolbox.tsx +++ b/packages/bot-web-ui/src/components/dashboard/bot-builder/toolbox/toolbox.tsx @@ -1,11 +1,12 @@ import React from 'react'; import classNames from 'classnames'; -import { Icon, Text } from '@deriv/components'; +import { Field as FormField, Formik, Form, FieldProps } from 'formik'; +import { Input, Icon, Text } from '@deriv/components'; import { localize } from '@deriv/translations'; import { ToolboxItems } from './toolbox-items'; import { connect } from 'Stores/connect'; import RootStore from 'Stores/index'; -import SearchBox from './search-box/search-box'; +import SearchBox from './search-box'; type TToolbox = { hasSubCategory: (param: HTMLCollection) => boolean; @@ -58,20 +59,12 @@ const Toolbox = ({
setOpen(!is_open)}> {localize('Blocks menu')} - +
-
+
void; + dialog_options: { [key: string]: string }; + handleFileChange: (e: React.ChangeEvent, flag?: boolean) => boolean; + has_file_loaded: boolean; + is_dialog_open: boolean; + is_running: boolean; load_modal: LoadModalStore; + loadFileFromLocal: () => void; + openFileLoader: () => void; + onConfirmSave: () => void; + onOkButtonClick: () => void; setActiveTab: (active_tab: number) => void; + save_modal: SaveModalStore; + setFileLoaded: (param: boolean) => void; + showVideoDialog: (param: { [key: string]: string | React.ReactNode }) => void; }; -const Cards = ({ load_modal, setActiveTab }: TCard) => { - const { onDriveConnect } = load_modal; - const actions = [ +const Card = ({ + closeResetDialog, + dialog_options, + handleFileChange, + has_file_loaded, + is_dialog_open, + loadFileFromLocal, + onConfirmSave, + setActiveTab, + setFileLoaded, + showVideoDialog, +}: TCardProps) => { + type TCardArray = { + icon: string; + content: string; + method: () => void; + disable: string | ''; + }; + const openGoogleDriveDialog = () => { + showVideoDialog({ + type: 'google', + }); + }; + const file_input_ref = React.useRef(null); + const [is_file_supported, setIsFileSupported] = React.useState(true); + + const clear_preview_ref = React.useRef(null); + const openFileLoader = () => { + file_input_ref?.current?.click(); + }; + + const actions: TCardArray[] = [ { icon: 'IcMyComputer', - label: localize('My computer'), + content: localize('My computer'), + method: openFileLoader, + disable: has_file_loaded ? 'tab__dashboard__table__disabled-card' : '', }, { icon: 'IcGoogleDriveDbot', - label: localize('Google Drive'), - method: onDriveConnect, + content: localize('Google Drive'), + method: openGoogleDriveDialog, + disable: has_file_loaded ? 'tab__dashboard__table__disabled-card' : '', }, { icon: 'IcBotBuilder', - label: localize('Bot Builder'), + content: localize('Bot Builder'), method: () => setActiveTab(1), + disable: '', }, { icon: 'IcQuickStrategy', - label: localize('Quick Strategy'), + content: localize('Quick Strategy'), method: () => setActiveTab(2), + disable: '', }, ]; return React.useMemo( () => ( -
- {actions.map(({ icon, label, method }) => ( -
- - - {label} - -
- ))} +
+
+ {actions.map(icons => { + const { icon, content, method, disable } = icons; + return ( +
+ + + {content} + +
+ ); + })} + { + clear_preview_ref.current?.click(); + onConfirmSave(); + setIsFileSupported(handleFileChange(e, false)); + loadFileFromLocal(); + setFileLoaded(true); + }} + /> + + + +
+
), - [] + [is_dialog_open] ); }; -export default connect(({ load_modal, dashboard }: RootStore) => ({ +export default connect(({ load_modal, dashboard, save_modal }: RootStore) => ({ + active_tab: dashboard.active_tab, + closeResetDialog: dashboard.onCloseDialog, + dialog_options: dashboard.dialog_options, + handleFileChange: load_modal.handleFileChange, + has_file_loaded: dashboard.has_file_loaded, + is_dialog_open: dashboard.is_dialog_open, load_modal, + loadFileFromLocal: load_modal.loadFileFromLocal, + onConfirmSave: save_modal.onConfirmSave, + onDriveConnect: load_modal.onDriveConnect, + onOkButtonClick: dashboard.onCloseDialog, + setFileLoaded: dashboard.setFileLoaded, setActiveTab: dashboard.setActiveTab, -}))(Cards); + setLoadedLocalFile: load_modal.setLoadedLocalFile, + showVideoDialog: dashboard.showVideoDialog, +}))(Card); diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/dashboard-component.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/dashboard-component.tsx index bfb3ee0204a3..9e8a66db6176 100644 --- a/packages/bot-web-ui/src/components/dashboard/dashboard-component/dashboard-component.tsx +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/dashboard-component.tsx @@ -6,42 +6,58 @@ import InfoPanel from './info-panel'; import { connect } from 'Stores/connect'; import RootStore from 'Stores/index'; import classNames from 'classnames'; +import Local from './load-bot-preview/local'; type TDashboard = { is_info_panel_visible: boolean; + recent_strategies: boolean; }; -const DashboardComponent = ({ is_info_panel_visible }: TDashboard) => ( -
-
-
-
- - {localize('Load or build your bot')} - -
-
- - {localize( - 'Import bot from your computer or Google Drive, build it from scratch, or start with a quick strategy.' +const DashboardComponent = ({ is_info_panel_visible, recent_strategies }: TDashboard) => { + return ( + +
+
+
+ {!recent_strategies && ( +
+ + {localize('Load or build your bot')} + +
)} - +
+ + {localize( + 'Import bot from your computer or Google Drive, build it from scratch, or start with a quick strategy.' + )} + +
+ +
+
+ +
- -
-
- -
-
-
-
-); + +
+ +
+
+ + ); +}; -export default connect(({ dashboard }: RootStore) => ({ +export default connect(({ dashboard, load_modal }: RootStore) => ({ is_info_panel_visible: dashboard.is_info_panel_visible, + recent_strategies: load_modal.recent_strategies, }))(DashboardComponent); diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/index.scss b/packages/bot-web-ui/src/components/dashboard/dashboard-component/index.scss index 4946f8790261..d56a5a7c1379 100644 --- a/packages/bot-web-ui/src/components/dashboard/dashboard-component/index.scss +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/index.scss @@ -8,6 +8,7 @@ .toolbar__section { justify-content: end; } + .run-panel__container { height: var(--tab-content-height) !important; position: unset !important; @@ -16,6 +17,7 @@ transition: all 0.4s; margin-top: 1rem; } + .dc-drawer--open { transform: translateX(calc(0px)) !important; } @@ -26,6 +28,7 @@ display: flex; overflow: hidden; } + &__container { border: none; max-width: 100%; @@ -77,6 +80,12 @@ display: flex; justify-content: center; align-items: center; + + &__loaded { + text-align: left; + padding-left: 1.5rem; + } + svg { width: 1.6rem; height: 1.6rem; @@ -84,6 +93,7 @@ margin-right: 0.8rem; } } + &__dashboard-cards-wrapper { display: flex; margin-top: 4rem; @@ -111,9 +121,11 @@ &:hover { cursor: pointer; } + &:last-child { margin-right: 0; } + &__image { background: var(--general-section-1); } @@ -121,6 +133,24 @@ margin-bottom: 0.8rem; } } + + &__content-group { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + height: calc(100vh - 20rem); + margin-top: 1rem; + + &__header { + margin-bottom: 1.3rem; + } + + &__description { + max-width: 44rem; + text-align: center; + } + } } } } @@ -133,6 +163,23 @@ margin-top: -4.8rem; } +.db-sidebar { + position: relative; + background-color: var(--general-main-1); + padding: 2.4rem; + height: 100%; + + &--block { + display: block; + } + + display: none; + + &__images { + background: var(--general-section-6); + } +} + .db-info-panel { &__close-action { position: absolute; @@ -143,11 +190,13 @@ line-height: 2.3rem; text-align: center; border-radius: 1rem; + &:hover { cursor: pointer; background: var(--general-section-1); } } + &__card { margin-bottom: 1.6rem; h1 { @@ -158,7 +207,7 @@ } p { - font-size: 1.4rem; + font-size: var(--text-size-xs); margin-bottom: 0.8rem; line-height: 2rem; font-weight: 400; @@ -166,13 +215,10 @@ } } -.db-tour { - text-align: left; -} - .tab { &__dashboard { display: flex; + &__content { min-width: 70%; display: flex; @@ -185,12 +231,20 @@ height: var(--tab-content-height-mobile); } } + &__centered { display: flex; flex-direction: column; align-items: center; justify-content: center; + width: 50%; } + + &__preview { + width: 50%; + height: 100%; + } + &__header { margin-bottom: 1.3rem; } @@ -198,17 +252,55 @@ &__description { max-width: 44rem; text-align: center; + margin-bottom: 4rem; + + &__loaded { + max-width: 65rem; + text-align: left; + margin-top: 4rem; + } } + &__info-panel { position: relative; background-color: var(--general-main-1); padding: 2.4rem; margin-left: 1.6rem; display: none; + &--active { display: block; width: 35rem; } } + + &__table { + width: 90%; + + &__tiles { + display: flex; + justify-content: center; + align-items: center; + } + + &__disabled-card { + pointer-events: none; + cursor: not-allowed; + opacity: 0.6; + } + + &__block { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + margin-right: 1rem; + } + + &__images { + background-color: var(--general-section-1); + margin-bottom: 0.8rem; + } + } } } diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/intro-card.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/intro-card.tsx new file mode 100644 index 000000000000..9b40574749ec --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/intro-card.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { TSidebarItem } from './constants'; + +type TIntroCard = { + sidebar_item: TSidebarItem; +}; + +const Index = ({ sidebar_item }: TIntroCard) => { + const { label, content } = sidebar_item; + return ( +
+

{label}

+ {content?.map((text, key) => ( +

{text}

+ ))} +
+ ); +}; + +export default Index; diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/delete-dialog.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/delete-dialog.tsx new file mode 100644 index 000000000000..a59476c36397 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/delete-dialog.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { Dialog, Text } from '@deriv/components'; +import { localize } from '@deriv/translations'; +import { connect } from 'Stores/connect'; + +type TDeleteDialog = { + is_running: boolean; + is_delete_modal_open: boolean; + onToggleDeleteDialog: (type: string, param: boolean) => void; +}; + +const DeleteDialog = ({ is_delete_modal_open, is_running, onToggleDeleteDialog }: TDeleteDialog) => { + const onHandleChange = (type: string, param: boolean) => { + onToggleDeleteDialog(type, false); + }; + + return ( +
+ { + onHandleChange('confirm', false); + }} + cancel_button_text={is_running ? localize('No') : localize('Cancel')} + onCancel={() => { + onHandleChange('cancel', false); + }} + is_mobile_full_width={false} + className={'dc-dialog__delete-strategy--delete'} + has_close_icon + > +
+ + {localize('Your bot will be permanently deleted when you hit ')} + {localize('Yes, delete.')} + +
+
+ + {localize('Are you sure you want to delete it?')} + +
+
+
+ ); +}; + +export default connect(({ toolbar, load_modal }) => ({ + is_dialog_open: toolbar.is_dialog_open, + is_delete_modal_open: load_modal.is_delete_modal_open, + onToggleDeleteDialog: load_modal.onToggleDeleteDialog, + selected_strategy_id: load_modal.selected_strategy_id, +}))(DeleteDialog); diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/google-drive.scss b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/google-drive.scss new file mode 100644 index 000000000000..920ce9cf06e4 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/google-drive.scss @@ -0,0 +1,22 @@ +.dc-dialog__wrapper--google-drive { + .dc-dialog { + &__dialog { + width: unset; + max-width: unset; + height: unset; + max-height: unset; + padding: 2.4rem; + background-color: var(--general-main-2); + } + &__content { + .load-strategy { + &__container { + height: unset; + } + } + } + &__footer { + display: none; + } + } +} diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/google-drive.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/google-drive.tsx new file mode 100644 index 000000000000..a230b9a9d252 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/google-drive.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import classnames from 'classnames'; +import { Button, Icon, Text } from '@deriv/components'; +import { Localize, localize } from '@deriv/translations'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; + +type TGoogleDrive = { + is_authorised: boolean; + is_open_button_loading: boolean; + onDriveConnect: () => void; + onDriveOpen: () => void; + is_mobile: boolean; +}; + +const google_content = [ + localize("To import your bot from your Google Drive, you'll need to sign in to your Google account."), + localize('To know how Google Drive handles your data, please review Deriv’s Privacy policy.'), +]; + +const GoogleDrive = ({ + is_authorised, + is_open_button_loading, + onDriveConnect, + onDriveOpen, + is_mobile, +}: TGoogleDrive) => { + return ( +
+
+ + +
+ {is_authorised ? ( + + ) : ( + 'Google Drive' + )} +
+ {google_content.map(content => { + return ( + + {content} + + ); + })} + {is_authorised ? ( + +
+
+ ); +}; + +export default connect(({ load_modal, ui, google_drive }: RootStore) => ({ + is_authorised: google_drive.is_authorised, + is_mobile: ui.is_mobile, + is_open_button_loading: load_modal.is_open_button_loading, + onDriveConnect: load_modal.onDriveConnect, + onDriveOpen: load_modal.onDriveOpen, +}))(GoogleDrive); diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/icon-radio.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/icon-radio.tsx new file mode 100644 index 000000000000..52bc7172f068 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/icon-radio.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import classNames from 'classnames'; +import { localize } from '@deriv/translations'; +import { Text } from '@deriv/components'; + +type TIconRadio = { + google_drive_connected: boolean; + icon: string; + text: string; + onDriveConnect: () => void; +}; +const IconRadio = ({ icon, text, google_drive_connected, onDriveConnect }: TIconRadio) => { + const is_drive_radio = text === 'Google Drive'; + + return ( +
+
+ {icon && + React.cloneElement(icon, { + className: classNames( + 'save-type__icon', + { + 'save-type__icon--active': is_drive_radio && google_drive_connected, + 'save-type__icon--disabled': is_drive_radio && !google_drive_connected, + }, + icon.props.className + ), + })} + + {localize(text)} + +
+ {is_drive_radio && ( + + {localize(google_drive_connected ? localize('Disconnect') : localize('Connect'))} + + )} +
+ ); +}; + +export default IconRadio; diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/index.scss b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/index.scss new file mode 100644 index 000000000000..bc3520c90fd8 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/index.scss @@ -0,0 +1,409 @@ +@import './google-drive.scss'; + +.load-strategy { + &__wrapper { + position: fixed; + top: 4rem; + z-index: 10; + width: 100%; + + .dc-mobile-full-page-modal { + @include mobile { + width: 100%; + } + + &__body { + height: 100%; + } + } + + & .dc-tabs { + @include mobile { + height: 100%; + display: unset; + flex: 1; + + &__content { + height: calc(100% - 4rem); + } + } + } + } + + &__container { + @include desktop { + height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem); + + &--has-footer { + height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem - 7.4rem); + } + + > * { + height: 100%; + margin-top: 0.8rem; + } + } + + @include tablet { + height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem); + + &--has-footer { + height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem - 7.4rem); + } + + > * { + height: 100%; + margin-top: 0.8rem; + } + } + + @include mobile { + height: 100%; + } + } + + &__title { + font-size: var(--text-size-s); + font-weight: 700; + margin: 1.5rem; + } + + &__button-group { + display: flex; + justify-content: flex-end; + margin-right: 1.6rem; + + &--clear { + height: 3.4rem; + width: 6.7rem; + background-color: $color-grey-6; + border-radius: 0.4rem; + color: $color-white; + outline: none; + border: none; + font-weight: 700; + font-size: 1.4rem; + cursor: pointer; + margin-right: 1.6rem; + } + + &--open { + height: 3.4rem; + width: 6.7rem; + background-color: $color-red; + border-radius: 0.4rem; + color: $color-white; + outline: none; + border: none; + font-weight: 700; + font-size: '1.4rem'; + cursor: pointer; + } + } + + &__preview-workspace { + padding: 1.5rem; + border-radius: $BORDER_RADIUS; + border: solid 1px var(--border-normal); + min-height: calc(100vh - 30rem); + height: calc(100% - 30rem); // TODO: What is 37px? + position: relative; + overflow: hidden; + margin-bottom: 1.6rem; + margin-right: 1.6rem; + + &-controls { + padding: 0.7rem 0.5rem; + display: flex; + flex-direction: column; + position: absolute; + right: 1.6rem; + bottom: 1.6rem; + border-radius: 3rem; + background-color: $color-grey-2; + box-shadow: 0.2rem 0.2rem 0.5rem var(--shadow-menu); + z-index: 99; + } + + &-icon { + margin: 0.5rem; + cursor: pointer; + } + } + + &__recent { + display: flex; + gap: 1.6rem; + &-preview-title { + color: var(--text-general); + } + + &__files { + flex-basis: 100%; + + &__list { + overflow: auto; + /* TODO: ThemedScrollbars! */ + height: calc(100% - 5.2rem); // 100% - Title height + } + } + + &__preview { + flex-basis: 65%; + display: flex; + flex-direction: column; + + &__title { + margin-left: 0; + } + } + + &-empty { + display: flex; + align-items: center; + flex-direction: column; + justify-content: center; + text-align: center; + + &-icon { + margin-bottom: 1.6rem; + } + + &-title { + margin-bottom: 0.8rem; + font-size: var(--text-size-s); + font-weight: bold; + line-height: 2.4rem; + } + + &-description { + margin-bottom: 1.6rem; + font-size: var(--text-size-xs); + line-height: 2rem; + } + + &-expand { + margin-bottom: 0.8rem; + color: var(--brand-red-coral); + font-size: var(--text-size-xs); + font-weight: bold; + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } + + &-explanation { + font-size: var(--text-size-xxs); + text-align: left; + opacity: 0; + + &-list { + margin-top: 0.8rem; + } + + &--show { + opacity: 1; + width: fit-content; + } + } + } + + &-item { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-areas: ('text location'); + padding: 0.8rem; + align-items: center; + text-align: center; + &__loaded { + text-align: left; + padding-left: 3.5rem; + } + + &:not(.load-strategy__recent-item--selected):hover { + background-color: var(--state-hover); + cursor: pointer; + } + + &:not(:last-child) { + border-bottom: solid 0.1rem var(--border-normal); + } + + &--selected { + background-color: var(--state-active); + } + + &-text { + flex-direction: column; + display: flex; + justify-content: center; + } + + &-title { + font-size: var(--text-size-s); + color: var(--text-general); + } + + &-time { + font-size: var(--text-size-xxs); + color: var(--text-general); + text-align: center; + } + + &-location { + display: flex; + align-items: center; + justify-content: center; + color: var(--text-general); + } + + &-saved { + margin-left: 1rem; + font-size: var(--text-size-s); + line-height: 1.43; + } + + &__button { + display: flex; + + &__edit { + margin-right: 0.8rem; + } + + &__save { + margin-right: 0.8rem; + } + } + } + } + + &__local { + &-dropzone { + @include desktop { + padding-top: 1.6rem; + } + + @include mobile { + height: 100%; + padding: 1.6rem; + } + + &-area { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center; + border: dashed 0.2rem var(--border-normal); + border-radius: $BORDER_RADIUS; + height: 100%; + padding: 1.6rem; + } + } + + &-icon { + margin-bottom: 1.6rem; + } + + &-title { + margin-bottom: 1.6rem; + font-size: var(--text-size-s); + } + + &-description { + margin-bottom: 1.6rem; + font-size: var(--text-size-xs); + } + + &-preview { + display: flex; + flex-direction: column; + position: relative; + + @include mobile { + padding: 1.6rem; + height: calc(100% - 7.4rem); // - footer height + } + + &-close { + background-image: radial-gradient(at right top); + position: absolute; + padding: 2.5rem; + border-bottom-left-radius: 50%; + right: 0; + top: 0; + z-index: 99; + cursor: pointer; + } + } + + &-footer { + padding: 1.6rem; + display: flex; + justify-content: flex-end; + border-top: 1px solid var(--general-section-1); + } + } + + &__google-drive { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + + @include mobile { + border: dashed 0.2rem var(--border-normal); + border-radius: $BORDER_RADIUS; + margin: 1.6rem; + padding: 1.6rem; + height: calc(100% - 3.2rem); // - 2x margin. + } + + &-icon { + margin-bottom: 1.6rem; + + &--disabled { + opacity: 0.32; + } + } + + &-text { + margin-bottom: 1.6rem; + font-size: var(--text-size-s); + font-weight: bold; + line-height: 2.4rem; + } + + &-terms { + font-size: var(--text-size-xs); + line-height: 2rem; + margin-top: 1.6rem; + text-align: center; + color: var(--text-general); + } + } +} + +.picker { + max-width: 98%; + border-radius: 8px; + max-height: 99%; + + &-content { + max-width: 98%; + padding: 1%; + } + + @include mobile { + height: 100%; + width: 100%; + top: 0px; + } +} + +.dc-modal__container_load-strategy { + @include tablet { + width: calc(100vw - 4.8rem) !important; + } +} diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/index.ts b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/index.ts new file mode 100644 index 000000000000..c9c70417bd2c --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/index.ts @@ -0,0 +1,4 @@ +import LoadBotPreview from './local'; +import './index.scss'; + +export default LoadBotPreview; diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/local-footer.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/local-footer.tsx new file mode 100644 index 000000000000..90a37d593245 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/local-footer.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { Button } from '@deriv/components'; +import { localize } from '@deriv/translations'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; +import './index.scss'; + +type Nullable = T | null; +type TLocalFooter = { + is_mobile: boolean; + is_open_button_loading: boolean; + loadFileFromLocal: () => void; + setLoadedLocalFile: (data: Nullable) => void; + setPreviewOnPopup: (param: boolean) => boolean; + toggleLoadModal: () => void; +}; + +const LocalFooter = ({ + is_mobile, + is_open_button_loading, + loadFileFromLocal, + setLoadedLocalFile, + setPreviewOnPopup, + toggleLoadModal, +}: TLocalFooter) => { + const Wrapper = is_mobile ? Button.Group : React.Fragment; + return ( + + {is_mobile && ( + + { + clearInjectionDiv(); + onConfirmSave(); + setIsFileSupported(handleFileChange(e, false)); + }} + /> + +
+
+
+ {is_mobile && ( +
+ +
+ )} +
+ ); +}; + +const Local = connect(({ load_modal, ui, save_modal, dashboard }: RootStore) => ({ + handleFileChange: load_modal.handleFileChange, + is_mobile: ui.is_mobile, + is_open_button_loading: load_modal.is_open_button_loading, + loaded_local_file: load_modal.loaded_local_file, + setLoadedLocalFile: load_modal.setLoadedLocalFile, + onConfirmSave: save_modal.onConfirmSave, + setActiveTab: dashboard.setActiveTab, + loadFileFromLocal: load_modal.loadFileFromLocal, + loadFileFromRecent: load_modal.loadFileFromRecent, + setFileLoaded: dashboard.setFileLoaded, +}))(LocalComponent); + +Local.Footer = LocalFooter; + +export default Local; diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/recent-footer.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/recent-footer.tsx new file mode 100644 index 000000000000..a70673bf0266 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/recent-footer.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Button } from '@deriv/components'; +import { localize } from '@deriv/translations'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; +import './index.scss'; + +type TRecentFooter = { + is_open_button_loading: boolean; + loadFileFromRecent: () => void; +}; + +const RecentFooter = ({ is_open_button_loading, loadFileFromRecent }: TRecentFooter) => { + return ( +
+ + + ); + }} + +); +const SaveModal = ({ + bot_name, + button_status, + is_authorised, + is_save_modal_open, + onConfirmSave, + onDriveConnect, + toggleSaveModal, + validateBotName, + is_mobile, + setCurrentFocus, + is_onscreen_keyboard_active, +}: TSaveModalForm) => + is_mobile ? ( + + + + ) : ( + + + + ); + +export default connect(({ save_modal, google_drive, ui }) => ({ + button_status: save_modal.button_status, + is_authorised: google_drive.is_authorised, + is_mobile: ui.is_mobile, + is_save_modal_open: save_modal.is_save_modal_open, + is_onscreen_keyboard_active: ui.is_onscreen_keyboard_active, + onConfirmSave: save_modal.onConfirmSave, + onDriveConnect: save_modal.onDriveConnect, + toggleSaveModal: save_modal.toggleSaveModal, + validateBotName: save_modal.validateBotName, + bot_name: save_modal.bot_name, + setCurrentFocus: ui.setCurrentFocus, +}))(SaveModal); diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/workspace-control.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/workspace-control.tsx new file mode 100644 index 000000000000..d1202395c651 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/load-bot-preview/workspace-control.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Icon } from '@deriv/components'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; + +type TWorkspaceControl = { + onZoomInOutClick: (param: boolean) => void; +}; + +const WorkspaceControl = ({ onZoomInOutClick }: TWorkspaceControl) => ( +
+ onZoomInOutClick(true)} + /> + onZoomInOutClick(false)} + /> +
+); + +export default connect(({ load_modal }: RootStore) => ({ + onZoomInOutClick: load_modal.onZoomInOutClick, +}))(WorkspaceControl); diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard-component/sidebar.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard-component/sidebar.tsx new file mode 100644 index 000000000000..dbf3602586d6 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/dashboard-component/sidebar.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { Icon } from '@deriv/components'; +import classNames from 'classnames'; +import { SIDEBAR_INTRO } from './constants'; +import IntroCard from './intro-card'; + +type TSideBar = { + is_sidebar_open: boolean; + setSideBarState: (state: boolean) => void; +}; + +const Sidebar = ({ setSideBarState, is_sidebar_open }: TSideBar) => { + return ( +
+
+ { + setSideBarState(false); + }} + /> +
+ {SIDEBAR_INTRO.map(sidebar_item => { + const { label } = sidebar_item; + return ( + + ; + + ); + })} +
+ ); +}; + +export default Sidebar; diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard.scss b/packages/bot-web-ui/src/components/dashboard/dashboard.scss index 4aba531a59ec..319b46c42f69 100644 --- a/packages/bot-web-ui/src/components/dashboard/dashboard.scss +++ b/packages/bot-web-ui/src/components/dashboard/dashboard.scss @@ -14,6 +14,7 @@ &__container { position: relative; } + &__chart-wrapper { position: relative; height: var(--tab-content-height); @@ -24,6 +25,7 @@ width: calc(100vw - 39.8rem); } } + &__toolbox { position: absolute; top: 0; @@ -38,33 +40,40 @@ line-height: 2.6rem; position: relative; cursor: pointer; + &__chevron { position: absolute; right: 0; top: 0.3rem; transition: transform 0.3s ease; + &--active { transform: rotate(180deg); top: -0.2rem; } } } + &__content { border: solid 1px var(--general-section-1); } + &__category-menu { height: calc(100vh - 28.4rem); } + &__search { padding: 1.3rem 0.8rem; height: 6rem; } + &__content-wrapper { height: 0; transition: height 0.4s ease; - &--active { - height: auto; - } + } + + &__content-wrapper.active { + height: 100%; } } } @@ -73,20 +82,24 @@ right: 1.6rem; top: 1.6rem; z-index: 2; + .animation { &__button { background-color: var(--purchase-main-1); } + &__container { background-color: var(--general-main-1); } } } + &__sidebar-wrapper { &--active { position: fixed; right: 0; } + &--hidden { display: none; } @@ -104,8 +117,17 @@ &--active { z-index: 1; } + &--inactive { + display: none; + } @include mobile { width: calc(100vw - 3.2rem); height: var(--tab-content-height-mobile); } } + +.dbot-onboarding__container { + img { + width: 100%; + } +} diff --git a/packages/bot-web-ui/src/components/dashboard/dashboard.tsx b/packages/bot-web-ui/src/components/dashboard/dashboard.tsx index abfd8d564295..eac7cb992288 100644 --- a/packages/bot-web-ui/src/components/dashboard/dashboard.tsx +++ b/packages/bot-web-ui/src/components/dashboard/dashboard.tsx @@ -2,37 +2,79 @@ import React from 'react'; import { Tabs, DesktopWrapper } from '@deriv/components'; import { localize } from '@deriv/translations'; import Chart from 'Components/chart'; -import RootStore from 'Stores/index'; -import { connect } from 'Stores/connect'; -import classNames from 'classnames'; import ReactJoyride from 'react-joyride'; +import { DBOT_ONBOARDING, handleJoyrideCallback, getTourSettings } from './joyride-config'; +import classNames from 'classnames'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; import DashboardComponent from './dashboard-component'; -import { DBOT_ONBOARDING } from './joyride-config'; import RunStrategy from './dashboard-component/run-strategy'; import RunPanel from '../run-panel'; import QuickStrategy from './quick-strategy'; import Tutorial from './tutorial-tab'; +import TourTriggrerDialog from './tour-trigger-dialog'; type TDashboard = { active_tab: number; is_drawer_open: boolean; setActiveTab: (active_tab: number) => void; + onEntered: () => void; + has_file_loaded: boolean; + has_tour_started: boolean; + has_onboard_tour_started: boolean; + setTourActive: (param: boolean) => void; + setOnBoardTourRunState: (param: boolean) => void; toggleStrategyModal: () => void; }; -const Dashboard = ({ active_tab, setActiveTab, toggleStrategyModal, is_drawer_open }: TDashboard) => { - const [tour_run, setTourRun] = React.useState(true); +const Dashboard = ({ + active_tab, + setActiveTab, + toggleStrategyModal, + onEntered, + setTourActive, + has_tour_started, + has_file_loaded, + is_drawer_open, + setOnBoardTourRunState, +}: TDashboard) => { + const [show_side_bar, setShowSideBar] = React.useState(true); + const [is_tour_running, setTourRun] = React.useState(true); const handleClick = (e: React.MouseEvent) => { e.preventDefault(); setTourRun(true); toggleStrategyModal(); }; + React.useEffect(() => { + if (active_tab === 0 && has_file_loaded) { + onEntered(); + } + const tour_status = getTourSettings('status'); + + if (tour_status) { + const { action } = tour_status; + const actions = ['skip', 'close', 'reset']; + if (actions.includes(action)) { + setOnBoardTourRunState(false); + setTourActive(false); + } + } + }, [active_tab, handleJoyrideCallback]); return (
- + + {has_tour_started && ( + + )}
@@ -42,7 +84,7 @@ const Dashboard = ({ active_tab, setActiveTab, toggleStrategyModal, is_drawer_op icon='IcQuickStrategyIcon' label={localize('Quick Strategy')} id='id-quick-strategy' - onTabItemClick={handleClick} + onClick={handleClick} >
({ +export default connect(({ dashboard, quick_strategy, run_panel, load_modal }: RootStore) => ({ active_tab: dashboard.active_tab, is_drawer_open: run_panel.is_drawer_open, setActiveTab: dashboard.setActiveTab, toggleStrategyModal: quick_strategy.toggleStrategyModal, + onEntered: load_modal.onEntered, + has_file_loaded: dashboard.has_file_loaded, + has_tour_started: dashboard.has_tour_started, + setTourActive: dashboard.setTourActive, + setOnBoardTourRunState: dashboard.setOnBoardTourRunState, }))(Dashboard); diff --git a/packages/bot-web-ui/src/components/dashboard/joyride-config.tsx b/packages/bot-web-ui/src/components/dashboard/joyride-config.tsx index 235ba6da02db..338510e1493f 100644 --- a/packages/bot-web-ui/src/components/dashboard/joyride-config.tsx +++ b/packages/bot-web-ui/src/components/dashboard/joyride-config.tsx @@ -1,14 +1,30 @@ import React from 'react'; import { localize } from '@deriv/translations'; +import { storeSetting, getSetting } from '../../utils/settings'; +import TourGuide from './tour-guide'; +import { CallBackProps } from 'react-joyride'; import { Text } from '@deriv/components'; - -type TJoyrideConfig = Record<'showProgress' | 'showSkipButton' | 'spotlightClicks' | 'disableBeacon', boolean>; +import { getImageLocation } from '../../public-path'; type TStep = { label?: string; content: string[]; }; +export const setTourSettings = (param: number | { [key: string]: string }, type: string) => { + if (type === 'token') { + return storeSetting('onboard_tour_token', param); + } + return storeSetting('onboard_tour_status', param); +}; + +export const getTourSettings = (type: string) => { + if (type === 'token') { + return getSetting('onboard_tour_token'); + } + return getSetting('onboard_tour_status'); +}; + export const Step = ({ label, content }: TStep) => { return (
@@ -28,17 +44,143 @@ export const Step = ({ label, content }: TStep) => { ); }; -/** - * Joyride specifc config - * It should be in camel casing. - */ -const joyride_config: TJoyrideConfig = { +let onboarding_tour: { [key: string]: string } = {}; +let current_target: number; +export const handleJoyrideCallback = (data: CallBackProps) => { + const { action, index, status, type } = data; + if (current_target && current_target !== index) { + onboarding_tour = {}; + onboarding_tour.status = status; + onboarding_tour.action = action; + } + current_target = index; + setTourSettings(onboarding_tour, 'tour'); + if (!getTourSettings('token')) setTourSettings(new Date().getTime(), 'token'); +}; + +type TJoyrideProps = Record<'showProgress' | 'showSkipButton' | 'spotlightClicks' | 'disableBeacon', boolean>; + +const joyride_props: TJoyrideProps = { showProgress: true, showSkipButton: true, spotlightClicks: true, disableBeacon: true, }; +export const DBOT_ONBOARDING = [ + { + target: '#tab__dashboard__table__tiles', + content: ( + + ), + ...joyride_props, + }, + { + target: '#id-bot-builder', + content: ( + + ), + ...joyride_props, + }, + { + target: '#id-quick-strategy', + content: ( + + ), + ...joyride_props, + }, + { + target: '#id-charts', + content: ( + + ), + ...joyride_props, + }, + { + target: '#id-tutorials', + content: ( + + ), + ...joyride_props, + }, + { + target: '.animation__wrapper', + content: ( + + ), + ...joyride_props, + }, + { + target: '[data-testid="drawer"]', + content: ( + + ), + ...joyride_props, + }, + + { + target: 'body', + content: ( + + ), + ...joyride_props, + }, +]; export const BOT_BUILDER_TOUR = [ { target: 'body', @@ -53,7 +195,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: '[data-category="trade_parameters"]', @@ -72,7 +214,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: '[data-category="trade_parameters"]', @@ -86,7 +228,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: '[data-category="purchase_conditions"]', @@ -101,7 +243,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: '[data-category="sell_conditions"]', @@ -116,7 +258,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: '.dashboard__toolbox', @@ -136,7 +278,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: '.dashboard__toolbox', @@ -161,7 +303,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: '[data-category="trade_results"]', @@ -176,7 +318,7 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, { target: 'body', @@ -193,6 +335,6 @@ export const BOT_BUILDER_TOUR = [ ]} />, ], - ...joyride_config, + ...joyride_props, }, ]; diff --git a/packages/bot-web-ui/src/components/dashboard/tour-guide.tsx b/packages/bot-web-ui/src/components/dashboard/tour-guide.tsx new file mode 100644 index 000000000000..1686e01f1ce1 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/tour-guide.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { Text } from '@deriv/components'; +import RootStore from 'Stores/index'; +import { connect } from 'Stores/connect'; + +type TTourGuide = { + label: string | boolean; + content: string[]; + img?: string; + className: string; + dashboardTabIndex: number; + setActiveTab: (param: number) => void; +}; + +const TourGuide = ({ label, content, img, className, dashboardTabIndex, setActiveTab }: TTourGuide) => { + React.useEffect(() => { + const tour_guide_timer = setTimeout(() => setActiveTab(dashboardTabIndex), 50); + return () => { + clearTimeout(tour_guide_timer); + }; + }, [dashboardTabIndex]); + return ( + +
+ + {label} + +
+ + {img && ( +
+ +
+ )} + +
+ + {content} + +
+
+ ); +}; +export default connect(({ dashboard }: RootStore) => ({ + setActiveTab: dashboard.setActiveTab, + active_tab: dashboard.active_tab, +}))(TourGuide); diff --git a/packages/bot-web-ui/src/components/dashboard/tour-trigger-dialog.tsx b/packages/bot-web-ui/src/components/dashboard/tour-trigger-dialog.tsx new file mode 100644 index 000000000000..436c60623252 --- /dev/null +++ b/packages/bot-web-ui/src/components/dashboard/tour-trigger-dialog.tsx @@ -0,0 +1,66 @@ +import React from 'react'; +import { Dialog, Text } from '@deriv/components'; +import { localize, Localize } from '@deriv/translations'; +import { connect } from 'Stores/connect'; +import RootStore from 'Stores/index'; + +type TourTriggrerDialog = { + setTourActive: (param: boolean) => void; + is_tour_dialog_visible: boolean; + setTourDialogVisibility: (param: boolean) => void; + setOnBoardTourRunState: (param: boolean) => void; +}; + +const TourTriggrerDialog = ({ + is_tour_dialog_visible, + setTourDialogVisibility, + setOnBoardTourRunState, + setTourActive, +}: TourTriggrerDialog) => { + const handleChange = () => { + setTourActive(true); + setOnBoardTourRunState(true); + setTourDialogVisibility(false); + }; + const closTourChange = () => { + setTourDialogVisibility(false); + setOnBoardTourRunState(false); + setTourActive(false); + }; + return ( +
+ +
+ + {localize('Get started on DBot')} + +
+
+ + , ]} + /> + +
+
+
+ ); +}; + +export default connect(({ dashboard }: RootStore) => ({ + setTourActive: dashboard.setTourActive, + is_tour_dialog_visible: dashboard.is_tour_dialog_visible, + setTourDialogVisibility: dashboard.setTourDialogVisibility, + setOnBoardTourRunState: dashboard.setOnBoardTourRunState, +}))(TourTriggrerDialog); diff --git a/packages/bot-web-ui/src/components/dashboard/tutorial-tab/dialog.scss b/packages/bot-web-ui/src/components/dashboard/tutorial-tab/dialog.scss index 6caafe80aedf..2f9ebc156ae6 100644 --- a/packages/bot-web-ui/src/components/dashboard/tutorial-tab/dialog.scss +++ b/packages/bot-web-ui/src/components/dashboard/tutorial-tab/dialog.scss @@ -37,3 +37,16 @@ } } } + +.onboarding-tour-guide { + .dc-dialog__content { + &__header { + text-align: left; + margin-bottom: 2.4rem; + } + + &__description { + text-align: left; + } + } +} diff --git a/packages/bot-web-ui/src/components/dashboard/tutorial-tab/guide-content.tsx b/packages/bot-web-ui/src/components/dashboard/tutorial-tab/guide-content.tsx index 0a4c21f4553d..9ceefe2100b4 100644 --- a/packages/bot-web-ui/src/components/dashboard/tutorial-tab/guide-content.tsx +++ b/packages/bot-web-ui/src/components/dashboard/tutorial-tab/guide-content.tsx @@ -10,7 +10,7 @@ type TGuideContent = { faq_search_value: string; is_dialog_open: boolean; onOkButtonClick: () => void; - showVideoDialog: (url: string) => void; + showVideoDialog: (param: { [key: string]: string }) => void; guide_list: []; }; @@ -43,7 +43,12 @@ const GuideContent = ({ width='4rem' height='4rem' icon={'IcPlayOutline'} - onClick={() => showVideoDialog(url)} + onClick={() => + showVideoDialog({ + type: 'url', + url, + }) + } />
@@ -68,7 +73,7 @@ const GuideContent = ({ confirm_button_text={localize('OK')} onConfirm={onOkButtonClick} is_mobile_full_width - className={'dc-dialog dc-dialog__wrapper-guide--fixed'} + className={'dc-dialog'} has_close_icon onClose={onOkButtonClick} > diff --git a/packages/bot-web-ui/src/components/dashboard/tutorial-tab/tutorial-content.tsx b/packages/bot-web-ui/src/components/dashboard/tutorial-tab/tutorial-content.tsx index 3e51b49ba4df..aede0f15d57f 100644 --- a/packages/bot-web-ui/src/components/dashboard/tutorial-tab/tutorial-content.tsx +++ b/packages/bot-web-ui/src/components/dashboard/tutorial-tab/tutorial-content.tsx @@ -1,5 +1,5 @@ import { localize } from '@deriv/translations'; -import { getUrlBase } from '@deriv/shared'; +import { getImageLocation } from '../../../public-path'; export type TDescription = Pick; @@ -17,8 +17,6 @@ export type TContent = { url?: string; }; -const getImageLocation = (image_name: string) => getUrlBase(`/public/images/common/${image_name}`); - export const guide_content: TGuideContent[] = [ { id: 1, diff --git a/packages/bot-web-ui/src/components/load-modal/load-modal.jsx b/packages/bot-web-ui/src/components/load-modal/load-modal.jsx index e5822e569090..df03332af0e3 100644 --- a/packages/bot-web-ui/src/components/load-modal/load-modal.jsx +++ b/packages/bot-web-ui/src/components/load-modal/load-modal.jsx @@ -18,6 +18,7 @@ const LoadModal = ({ setActiveTabIndex, tab_name, toggleLoadModal, + setPreviewOnPopup, }) => { const header_text = localize('Load strategy'); @@ -27,7 +28,10 @@ const LoadModal = ({ is_modal_open={is_load_modal_open} className='load-strategy__wrapper' header={localize('Load strategy')} - onClickClose={toggleLoadModal} + onClickClose={() => { + setPreviewOnPopup(false); + toggleLoadModal(); + }} height_offset='80px' page_overlay > @@ -90,9 +94,10 @@ LoadModal.propTypes = { recent_strategies: PropTypes.array, setActiveTabIndex: PropTypes.func, toggleLoadModal: PropTypes.func, + setPreviewOnPopup: PropTypes.func, }; -export default connect(({ load_modal, ui }) => ({ +export default connect(({ load_modal, ui, dashboard }) => ({ active_index: load_modal.active_index, is_load_modal_open: load_modal.is_load_modal_open, is_mobile: ui.is_mobile, @@ -102,4 +107,5 @@ export default connect(({ load_modal, ui }) => ({ setActiveTabIndex: load_modal.setActiveTabIndex, tab_name: load_modal.tab_name, toggleLoadModal: load_modal.toggleLoadModal, + setPreviewOnPopup: dashboard.setPreviewOnPopup, }))(LoadModal); diff --git a/packages/bot-web-ui/src/components/load-modal/load-modal.scss b/packages/bot-web-ui/src/components/load-modal/load-modal.scss index 852e1d7e1d34..c8af23a8e77c 100644 --- a/packages/bot-web-ui/src/components/load-modal/load-modal.scss +++ b/packages/bot-web-ui/src/components/load-modal/load-modal.scss @@ -1,311 +1,21 @@ -.load-strategy { - &__wrapper { - position: fixed; - top: 40px; - z-index: 10; - width: 100%; - - .dc-mobile-full-page-modal { - @include mobile { - width: 100%; - } - - &__body { - height: 100%; - } - } - & .dc-tabs { - @include mobile { - height: 100%; - display: unset; - flex: 1; - - &__content { - height: calc(100% - 40px); - } - } - } - } - &__container { - @include desktop { - height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem); - - &--has-footer { - height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem - 7.4rem); - } - > * { - height: 100%; - margin-top: 0.8rem; - } - } - @include tablet { - height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem); - - &--has-footer { - height: calc(80vh - 0.8rem - 4rem - 4.8rem - 5.8rem - 7.4rem); - } - > * { - height: 100%; - margin-top: 0.8rem; - } - } - @include mobile { - height: 100%; - } - } - &__title { - font-size: var(--text-size-s); - font-weight: 700; - margin: 1.5rem; - } - &__preview-workspace { - padding: 1.5rem; - border-radius: $BORDER_RADIUS; - border: solid 1px var(--border-normal); - height: calc(100% - 3.7rem); // TODO: What is 37px? - position: relative; - - &-controls { - padding: 0.7rem 0.5rem; - display: flex; - flex-direction: column; - position: absolute; - right: 1.6rem; - bottom: 1.6rem; - border-radius: 3rem; - background-color: $color-grey-2; - box-shadow: 0.2rem 0.2rem 0.5rem var(--shadow-menu); - z-index: 99; - } - &-icon { - margin: 0.5rem; - cursor: pointer; - } - } - &__recent { - display: flex; - flex-direction: row; - gap: 1.6rem; - - &-files { - flex-basis: 35%; - - &-list { - overflow: auto; /* TODO: ThemedScrollbars! */ - height: calc(100% - 52px); // 100% - Title height - } - } - &-preview { - flex-basis: 65%; - display: flex; - flex-direction: column; - - &-title { - margin-left: 0; - } - } - &-empty { - display: flex; - align-items: center; - flex-direction: column; - justify-content: center; - text-align: center; - - &-icon { - margin-bottom: 1.6rem; - } - &-title { - margin-bottom: 0.8rem; - font-size: var(--text-size-s); - font-weight: bold; - line-height: 2.4rem; - } - &-description { - margin-bottom: 1.6rem; - font-size: var(--text-size-xs); - line-height: 2rem; - } - &-expand { - margin-bottom: 0.8rem; - color: var(--brand-red-coral); - font-size: var(--text-size-xs); - font-weight: bold; - cursor: pointer; - - &:hover { - text-decoration: underline; - } - } - &-explanation { - font-size: var(--text-size-xxs); - text-align: left; - opacity: 0; - - &-list { - margin-top: 0.8rem; - } - &--show { - opacity: 1; - width: fit-content; - } - } - } - &-item { - display: grid; +#modal_root { + .load-strategy { + &__recent-item { grid-template-columns: 1fr 1fr; - grid-template-areas: ('text location'); - padding: 1.6rem; - height: 100px; - - &:not(.load-strategy__recent-item--selected):hover { - background-color: var(--state-hover); - cursor: pointer; - } - &:not(:last-child) { - border-bottom: solid 0.1rem var(--border-normal); - } - &--selected { - background-color: var(--state-active); - } - &-text { - flex-direction: column; - display: flex; - justify-content: center; - } - &-title { - font-size: var(--text-size-s); - } - &-time { - font-size: var(--text-size-xxs); - } - &-location { - flex-direction: row; - display: flex; - align-items: center; - justify-content: center; - } - &-saved { - margin-left: 1rem; - font-size: var(--text-size-s); - line-height: 1.43; - } - } - } - &__local { - &-dropzone { - @include desktop { - padding-top: 1.6rem; - } - @include mobile { - height: 100%; - padding: 1.6rem; - } - - &-area { - align-items: center; - display: flex; - flex-direction: column; - justify-content: center; - border: dashed 0.2rem var(--border-normal); - border-radius: $BORDER_RADIUS; - height: 100%; - padding: 1.6rem; - } } - &-icon { - margin-bottom: 1.6rem; - } - &-title { - margin-bottom: 1.6rem; - font-size: var(--text-size-s); - } - &-description { - margin-bottom: 1.6rem; - font-size: var(--text-size-xs); - } - &-preview { - display: flex; - flex-direction: column; - position: relative; - - @include mobile { - padding: 1.6rem; - height: calc(100% - 7.4rem); // - footer height - } - &-close { - // TODO : Dark Theme - background-image: radial-gradient(at right top); - position: absolute; - padding: 25px; - border-bottom-left-radius: 50%; - right: 0; - top: 0; - z-index: 99; - cursor: pointer; - } - } - &-footer { - padding: 1.6rem; - display: flex; - justify-content: flex-end; - border-top: 1px solid var(--general-section-1); + &__recent-files { + width: 35%; } - } - &__google-drive { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - @include mobile { - border: dashed 0.2rem var(--border-normal); - border-radius: $BORDER_RADIUS; - margin: 1.6rem; - padding: 1.6rem; - height: calc(100% - 3.2rem); // - 2x margin. + &__recent-preview { + width: 65%; } - &-icon { - margin-bottom: 1.6rem; - - &--disabled { - opacity: 0.32; + &__container { + &--has-footer { + overflow: auto; } } - &-text { - margin-bottom: 1.6rem; - font-size: var(--text-size-s); - font-weight: bold; - line-height: 2.4rem; - } - &-terms { - font-size: var(--text-size-xs); - line-height: 2rem; - margin-top: 1.6rem; - text-align: center; - color: var(--text-general); - } - } -} - -.picker { - max-width: 98%; - border-radius: 8px; - max-height: 99%; - - &-content { - max-width: 98%; - padding: 1%; - } - @include mobile { - height: 100%; - width: 100%; - top: 0px; - } -} -.dc-modal__container_load-strategy { - @include tablet { - width: calc(100vw - 4.8rem) !important; } } diff --git a/packages/bot-web-ui/src/components/load-modal/local-footer.jsx b/packages/bot-web-ui/src/components/load-modal/local-footer.jsx index 8b2288b50043..0efbd7a67081 100644 --- a/packages/bot-web-ui/src/components/load-modal/local-footer.jsx +++ b/packages/bot-web-ui/src/components/load-modal/local-footer.jsx @@ -4,7 +4,14 @@ import { Button } from '@deriv/components'; import { localize } from '@deriv/translations'; import { connect } from 'Stores/connect'; -const LocalFooter = ({ is_mobile, is_open_button_loading, loadFileFromLocal, setLoadedLocalFile }) => { +const LocalFooter = ({ + is_mobile, + is_open_button_loading, + loadFileFromLocal, + setLoadedLocalFile, + toggleLoadModal, + setPreviewOnPopup, +}) => { const Wrapper = is_mobile ? Button.Group : React.Fragment; return ( @@ -13,7 +20,11 @@ const LocalFooter = ({ is_mobile, is_open_button_loading, loadFileFromLocal, set )}