From a1b656dc6ad6c4cb75d5b2e6eb4aae4f56a19cd8 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 2 May 2022 16:07:00 +0200 Subject: [PATCH] feat(ui) - session settings - ui and state --- .../app/components/BugFinder/BugFinder.js | 2 - .../BugFinder/SessionsMenu/SessionsMenu.js | 10 ++- .../app/components/shared/Select/Select.tsx | 63 ++++++++++++++ .../app/components/shared/Select/index.ts | 1 + .../SessionSettings/SessionSettings.tsx | 40 +++++++++ .../components/CaptureRate.tsx | 43 ++++++++++ .../components/DefaultPlaying.tsx | 25 ++++++ .../components/DefaultTimezone.tsx | 42 ++++++++++ .../components/ListingVisibility.tsx | 57 +++++++++++++ .../shared/SessionSettings/index.ts | 1 + .../ui/ToggleButton/ToggleButton.tsx | 84 +++++++++++++++++++ frontend/app/components/ui/Toggler/Toggler.js | 22 +++-- .../app/components/ui/Toggler/toggler.css | 19 ++++- frontend/app/components/ui/index.js | 1 + frontend/app/mstore/index.tsx | 3 + frontend/app/mstore/settingsStore.ts | 15 ++++ frontend/app/mstore/types/sessionSettings.ts | 26 ++++++ frontend/app/svg/icons/percent.svg | 3 + 18 files changed, 442 insertions(+), 15 deletions(-) create mode 100644 frontend/app/components/shared/Select/Select.tsx create mode 100644 frontend/app/components/shared/Select/index.ts create mode 100644 frontend/app/components/shared/SessionSettings/SessionSettings.tsx create mode 100644 frontend/app/components/shared/SessionSettings/components/CaptureRate.tsx create mode 100644 frontend/app/components/shared/SessionSettings/components/DefaultPlaying.tsx create mode 100644 frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx create mode 100644 frontend/app/components/shared/SessionSettings/components/ListingVisibility.tsx create mode 100644 frontend/app/components/shared/SessionSettings/index.ts create mode 100644 frontend/app/components/ui/ToggleButton/ToggleButton.tsx create mode 100644 frontend/app/mstore/settingsStore.ts create mode 100644 frontend/app/mstore/types/sessionSettings.ts create mode 100644 frontend/app/svg/icons/percent.svg diff --git a/frontend/app/components/BugFinder/BugFinder.js b/frontend/app/components/BugFinder/BugFinder.js index 3ce09d23b..6e4f589a6 100644 --- a/frontend/app/components/BugFinder/BugFinder.js +++ b/frontend/app/components/BugFinder/BugFinder.js @@ -20,7 +20,6 @@ import { LAST_7_DAYS } from 'Types/app/period'; import { resetFunnel } from 'Duck/funnels'; import { resetFunnelFilters } from 'Duck/funnelFilters' import NoSessionsMessage from 'Shared/NoSessionsMessage'; -// import TrackerUpdateMessage from 'Shared/TrackerUpdateMessage'; import SessionSearch from 'Shared/SessionSearch'; import MainSearchBar from 'Shared/MainSearchBar'; import { clearSearch, fetchSessions } from 'Duck/search'; @@ -130,7 +129,6 @@ export default class BugFinder extends React.PureComponent { />
- {/* */}
diff --git a/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js b/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js index fa0594316..978eb0003 100644 --- a/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js +++ b/frontend/app/components/BugFinder/SessionsMenu/SessionsMenu.js @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useEffect } from 'react' import { connect } from 'react-redux'; import cn from 'classnames'; import { SideMenuitem, SavedSearchList, Progress, Popup } from 'UI' @@ -7,17 +7,23 @@ import { fetchWatchdogStatus } from 'Duck/watchdogs'; import { clearEvents } from 'Duck/filters'; import { issues_types } from 'Types/session/issue' import { fetchList as fetchSessionList } from 'Duck/sessions'; +import { useModal } from 'App/components/Modal'; +import SessionSettings from 'Shared/SessionSettings/SessionSettings' function SessionsMenu(props) { const { activeTab, keyMap, wdTypeCount, toggleRehydratePanel } = props; + const { hideModal, showModal } = useModal(); const onMenuItemClick = (filter) => { props.onMenuItemClick(filter) } - const capturingAll = props.captureRate && props.captureRate.get('captureAll'); + useEffect(() => { + showModal(, {}); + }, []) + return (
diff --git a/frontend/app/components/shared/Select/Select.tsx b/frontend/app/components/shared/Select/Select.tsx new file mode 100644 index 000000000..c4523cf25 --- /dev/null +++ b/frontend/app/components/shared/Select/Select.tsx @@ -0,0 +1,63 @@ +import React from 'react'; +import Select from 'react-select'; + +interface Props { + options: any[]; + isSearchable?: boolean; + defaultValue?: any; + plain?: boolean; + [x:string]: any; +} +export default function({ plain = false, options, isSearchable = false, defaultValue, ...rest }: Props) { + const customStyles = { + option: (provided, state) => ({ + ...provided, + whiteSpace: 'nowrap', + }), + menu: (provided, state) => ({ + ...provided, + top: 31, + }), + control: (provided) => { + const obj = { + ...provided, + border: 'solid thin #ddd' + } + if (plain) { + obj['border'] = '1px solid transparent' + } + return obj; + }, + valueContainer: (provided) => ({ + ...provided, + paddingRight: '0px', + }), + singleValue: (provided, state) => { + const opacity = state.isDisabled ? 0.5 : 1; + const transition = 'opacity 300ms'; + + return { ...provided, opacity, transition }; + } + } + return ( + setCaptureRate(value)} + disabled={captureAll} + min={0} + minValue={0} + /> + +
+ of the sessions + +
+ + ); +} + +export default CaptureRate; \ No newline at end of file diff --git a/frontend/app/components/shared/SessionSettings/components/DefaultPlaying.tsx b/frontend/app/components/shared/SessionSettings/components/DefaultPlaying.tsx new file mode 100644 index 000000000..cb80c30b2 --- /dev/null +++ b/frontend/app/components/shared/SessionSettings/components/DefaultPlaying.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Toggler } from 'UI'; +import { useStore } from 'App/mstore'; +import { useObserver } from 'mobx-react-lite'; + +function DefaultPlaying(props) { + const { settingsStore } = useStore(); + const sessionSettings = useObserver(() => settingsStore.sessionSettings) + + return useObserver(() => ( + <> +

Default Playing Options

+
Always start playing the session from the first issue.
+
+ sessionSettings.updateKey('skipToIssue', !sessionSettings.skipToIssue)} + /> +
+ + )); +} + +export default DefaultPlaying; \ No newline at end of file diff --git a/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx b/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx new file mode 100644 index 000000000..c2f585a3d --- /dev/null +++ b/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx @@ -0,0 +1,42 @@ +import React, { useEffect } from 'react'; +import { Toggler, Button } from 'UI'; +import Select from 'Shared/Select'; +import { useStore } from 'App/mstore'; +import { useObserver } from 'mobx-react-lite'; + +const timezoneOptions = [ + { label: 'UTC', value: 'UTC' }, + { label: 'EST', value: 'EST' }, +] + +function DefaultTimezone(props) { + const [changed, setChanged] = React.useState(false); + const { settingsStore } = useStore(); + const sessionSettings = useObserver(() => settingsStore.sessionSettings) + + return ( + <> +

Default Timezone

+
Session Time
+
+ +
+
+ +
+
+ +
+ ); +} + +ToggleButton.defaultProps = { + icons: { + checked: , + unchecked: + } +}; + +ToggleButton.propTypes = { + disabled: PropTypes.bool, + defaultChecked: PropTypes.bool, + className: PropTypes.string, + onChange: PropTypes.func, + icons: PropTypes.oneOfType([ + PropTypes.bool, + PropTypes.shape({ + checked: PropTypes.node, + unchecked: PropTypes.node + }) + ]) +}; + +export default ToggleButton; \ No newline at end of file diff --git a/frontend/app/components/ui/Toggler/Toggler.js b/frontend/app/components/ui/Toggler/Toggler.js index ef6097936..1cf3ba78a 100644 --- a/frontend/app/components/ui/Toggler/Toggler.js +++ b/frontend/app/components/ui/Toggler/Toggler.js @@ -3,18 +3,22 @@ import styles from './toggler.css'; export default ({ onChange, name, - className, + className = '', checked, + label = '', }) => (
-
); diff --git a/frontend/app/components/ui/Toggler/toggler.css b/frontend/app/components/ui/Toggler/toggler.css index 171272d67..cf9cf0838 100644 --- a/frontend/app/components/ui/Toggler/toggler.css +++ b/frontend/app/components/ui/Toggler/toggler.css @@ -6,6 +6,16 @@ height: 16px; } +.label { + display: flex; + align-items: center; + cursor: pointer; + + & span { + padding-left: 10px; + color: $gray-medium; + } +} .switch input { display:none; } @@ -29,18 +39,23 @@ width: 20px; left: 0; bottom: -2px; - background-color: white; + /* background-color: white; */ transition: .4s; border-radius: 50%; border: solid 1px rgba(0, 0, 0, 0.2); + + background: #394EFF; + box-shadow: 0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px rgba(0, 0, 0, 0.14), 0px 1px 3px rgba(0, 0, 0, 0.12); } .slider.checked { - background-color: $teal !important; + /* background-color: $teal !important; */ + background-color: #b2bcff !important; } .slider.checked:before { border: solid 1px $teal; + transform: translateX(15px); } .slider.checked:before { diff --git a/frontend/app/components/ui/index.js b/frontend/app/components/ui/index.js index e6a4253e0..193d24384 100644 --- a/frontend/app/components/ui/index.js +++ b/frontend/app/components/ui/index.js @@ -58,5 +58,6 @@ export { default as HelpText } from './HelpText'; export { default as SideMenuHeader } from './SideMenuHeader'; export { default as PageTitle } from './PageTitle'; export { default as Pagination } from './Pagination'; +export { default as Toggler } from './Toggler'; export { Input, Modal, Form, Message, Card } from 'semantic-ui-react'; diff --git a/frontend/app/mstore/index.tsx b/frontend/app/mstore/index.tsx index 88f5472c2..39c1d84a4 100644 --- a/frontend/app/mstore/index.tsx +++ b/frontend/app/mstore/index.tsx @@ -3,14 +3,17 @@ import DashboardStore, { IDashboardSotre } from './dashboardStore'; import MetricStore, { IMetricStore } from './metricStore'; import APIClient from 'App/api_client'; import { dashboardService, metricService } from 'App/services'; +import SettingsStore from './settingsStore'; export class RootStore { dashboardStore: IDashboardSotre; metricStore: IMetricStore; + settingsStore: SettingsStore; constructor() { this.dashboardStore = new DashboardStore(); this.metricStore = new MetricStore(); + this.settingsStore = new SettingsStore(); } initClient() { diff --git a/frontend/app/mstore/settingsStore.ts b/frontend/app/mstore/settingsStore.ts new file mode 100644 index 000000000..82a33a5cb --- /dev/null +++ b/frontend/app/mstore/settingsStore.ts @@ -0,0 +1,15 @@ +import { makeAutoObservable, runInAction, observable, action, reaction } from "mobx" +import SessionSettings from "./types/sessionSettings" + +export default class SettingsStore { + sessionSettings: SessionSettings = new SessionSettings() + constructor() { + makeAutoObservable(this, { + sessionSettings: observable, + }) + } + + updateCaptureRate(value: number) { + this.sessionSettings.updateKey('captureRate', value); + } +} \ No newline at end of file diff --git a/frontend/app/mstore/types/sessionSettings.ts b/frontend/app/mstore/types/sessionSettings.ts new file mode 100644 index 000000000..37317cacd --- /dev/null +++ b/frontend/app/mstore/types/sessionSettings.ts @@ -0,0 +1,26 @@ +import { makeAutoObservable, runInAction, observable, action, reaction } from "mobx" + +export default class SessionSettings { + skipToIssue: boolean = false + timezone: string = "EST" + durationFilter: any = { + count: 0, + countType: 'min', + operator: '>' + } + captureRate: number = 0 + captureAll: boolean = false + + constructor() { + makeAutoObservable(this, { + updateKey: action + }) + } + + updateKey(key: string, value: any) { + console.log(`SessionSettings.updateKey(${key}, ${value})`) + runInAction(() => { + this[key] = value + }) + } +} diff --git a/frontend/app/svg/icons/percent.svg b/frontend/app/svg/icons/percent.svg new file mode 100644 index 000000000..6904d8218 --- /dev/null +++ b/frontend/app/svg/icons/percent.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file