fix(ui): last fixes for 1.7
This commit is contained in:
parent
082ab4215b
commit
f30912a307
14 changed files with 87 additions and 55 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Loader, NoContent, Pagination } from 'UI';
|
||||
import { applyFilter, addAttribute, addEvent } from 'Duck/filters';
|
||||
import { fetchSessions, addFilterByKeyAndValue, updateCurrentPage, setScrollPosition } from 'Duck/search';
|
||||
|
|
@ -7,6 +8,7 @@ import SessionItem from 'Shared/SessionItem';
|
|||
import SessionListHeader from './SessionListHeader';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
import SettingsStore from 'App/mstore/settingsStore';
|
||||
|
||||
// const ALL = 'all';
|
||||
const PER_PAGE = 10;
|
||||
|
|
@ -77,14 +79,13 @@ export default class SessionList extends React.PureComponent {
|
|||
componentDidMount() {
|
||||
const { scrollY } = this.props;
|
||||
window.scrollTo(0, scrollY);
|
||||
console.log(SettingsStore)
|
||||
}
|
||||
|
||||
renderActiveTabContent(list) {
|
||||
const {
|
||||
loading,
|
||||
filters,
|
||||
// onMenuItemClick,
|
||||
// allList,
|
||||
activeTab,
|
||||
metaList,
|
||||
currentPage,
|
||||
|
|
|
|||
|
|
@ -74,7 +74,11 @@ function DashboardSideMenu(props: RouteComponentProps<Props>) {
|
|||
className="group"
|
||||
leading = {(
|
||||
<div className="ml-2 flex items-center cursor-default">
|
||||
{item.isPublic && <div className="p-1"><Icon name="user-friends" color="gray-light" size="16" /></div>}
|
||||
{item.isPublic && (
|
||||
<Popup delay={500} content="Visible to the team" hideOnClick>
|
||||
<div className="p-1"><Icon name="user-friends" color="gray-light" size="16" /></div>
|
||||
</Popup>
|
||||
)}
|
||||
{item.isPinned && <div className="p-1 pointer-events-none"><Icon name="pin-fill" size="16" /></div>}
|
||||
{!item.isPinned && (
|
||||
<Popup
|
||||
|
|
|
|||
|
|
@ -88,13 +88,13 @@ function WidgetWrapper(props: Props & RouteComponentProps) {
|
|||
onClick={props.onClick ? props.onClick : () => {}}
|
||||
id={`widget-${widget.widgetId}`}
|
||||
>
|
||||
{!isTemplate && isWidget &&
|
||||
{!isTemplate && isWidget && isPredefined &&
|
||||
<div
|
||||
className={cn(
|
||||
stl.drillDownMessage,
|
||||
'disabled text-gray text-sm invisible group-hover:visible')}
|
||||
>
|
||||
{isPredefined ? 'Cannot drill down system provided metrics' : 'Click to drill down'}
|
||||
{'Cannot drill down system provided metrics'}
|
||||
</div>
|
||||
}
|
||||
{/* @ts-ignore */}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import cn from 'classnames';
|
||||
import { connectPlayer } from 'Player';
|
||||
import { Popup, TimelinePointer, Icon } from 'UI';
|
||||
import { connectPlayer, Controls } from 'Player';
|
||||
import { TimelinePointer, Icon } from 'UI';
|
||||
import TimeTracker from './TimeTracker';
|
||||
import { ReduxTime } from './Time';
|
||||
import stl from './timeline.module.css';
|
||||
import { TYPES } from 'Types/session/event';
|
||||
import { setTimelinePointer } from 'Duck/sessions';
|
||||
|
|
@ -64,7 +63,8 @@ let deboucneJump = () => null;
|
|||
skipIntervals: state.skipIntervals,
|
||||
events: state.eventList,
|
||||
skip: state.skip,
|
||||
skipToIssue: state.skipToIssue,
|
||||
// not updating properly rn
|
||||
// skipToIssue: state.skipToIssue,
|
||||
disabled: state.cssLoading || state.messagesLoading || state.markedTargets,
|
||||
endTime: state.endTime,
|
||||
live: state.live,
|
||||
|
|
@ -100,7 +100,7 @@ export default class Timeline extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { issues, skipToIssue } = this.props;
|
||||
const skipToIssue = Controls.updateSkipToIssue();
|
||||
const firstIssue = issues.get(0);
|
||||
deboucneJump = debounce(this.props.jump, 500);
|
||||
|
||||
|
|
@ -109,7 +109,7 @@ export default class Timeline extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
onDragEnd = (item, monitor) => {
|
||||
onDragEnd = () => {
|
||||
if (this.wasPlaying) {
|
||||
this.props.togglePlay();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ function SessionSearchField(props: Props) {
|
|||
id="search"
|
||||
type="search"
|
||||
autoComplete="off"
|
||||
className="hover:border-gray-medium"
|
||||
/>
|
||||
|
||||
{ showModal && (
|
||||
|
|
@ -62,4 +63,4 @@ export default connect((state: any) => ({
|
|||
filterSearchListLive: state.getIn([ 'liveSearch', 'filterSearchList' ]),
|
||||
filterList: state.getIn([ 'search', 'filterList' ]),
|
||||
filterListLive: state.getIn([ 'search', 'filterListLive' ]),
|
||||
}), { })(SessionSearchField);
|
||||
}), { })(SessionSearchField);
|
||||
|
|
|
|||
|
|
@ -1,32 +1,43 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Icon, Toggler, Button, Input, Loader } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
function CaptureRate(props) {
|
||||
const [changed, setChanged] = React.useState(false);
|
||||
function CaptureRate() {
|
||||
const { settingsStore } = useStore();
|
||||
const sessionSettings = useObserver(() => settingsStore.sessionSettings)
|
||||
const loading = useObserver(() => settingsStore.loadingCaptureRate)
|
||||
const [captureRate, setCaptureRate] = React.useState(sessionSettings.captureRate);
|
||||
const [captureAll, setCaptureAll] = React.useState(sessionSettings.captureAll);
|
||||
const [changed, setChanged] = useState(false);
|
||||
const [sessionSettings] = useState(settingsStore.sessionSettings)
|
||||
const [loading] = useState(settingsStore.loadingCaptureRate)
|
||||
|
||||
const captureRate = sessionSettings.captureRate;
|
||||
const setCaptureRate = sessionSettings.changeCaptureRate
|
||||
const captureAll = sessionSettings.captureAll
|
||||
const setCaptureAll = sessionSettings.changeCaptureAll
|
||||
|
||||
useEffect(() => {
|
||||
settingsStore.fetchCaptureRate().then(() => {
|
||||
setCaptureRate(sessionSettings.captureRate);
|
||||
setCaptureAll(sessionSettings.captureAll);
|
||||
});
|
||||
settingsStore.fetchCaptureRate()
|
||||
}, [])
|
||||
|
||||
const toggleRate = () => {
|
||||
if (captureAll === false) {
|
||||
settingsStore.saveCaptureRate({ captureAll: true, rate: "100" })
|
||||
}
|
||||
setCaptureAll(!captureAll)
|
||||
setChanged(true)
|
||||
const changeCaptureRate = (input: string) => {
|
||||
setChanged(true);
|
||||
setCaptureRate(input);
|
||||
}
|
||||
|
||||
return useObserver(() => (
|
||||
const toggleRate = () => {
|
||||
const newValue = !captureAll;
|
||||
setChanged(true)
|
||||
if (newValue === true) {
|
||||
const updateObj = {
|
||||
rate:"100",
|
||||
captureAll: true,
|
||||
}
|
||||
settingsStore.saveCaptureRate(updateObj)
|
||||
} else {
|
||||
setCaptureAll(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Loader loading={loading}>
|
||||
<h3 className="text-lg">Recordings</h3>
|
||||
<div className="my-1">The percentage of session you want to capture</div>
|
||||
|
|
@ -43,16 +54,12 @@ function CaptureRate(props) {
|
|||
<div className="relative">
|
||||
<Input
|
||||
type="number"
|
||||
value={captureRate}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => changeCaptureRate(e.target.value)}
|
||||
value={captureRate.toString()}
|
||||
style={{ height: '38px', width: '100px'}}
|
||||
// htmn input event
|
||||
onChange={(e) => {
|
||||
setCaptureRate(e.target.value)
|
||||
setChanged(true);
|
||||
}}
|
||||
disabled={captureAll}
|
||||
min={0}
|
||||
minValue={0}
|
||||
max={100}
|
||||
/>
|
||||
<Icon className="absolute right-0 mr-6 top-0 bottom-0 m-auto" name="percent" color="gray-medium" size="18" />
|
||||
</div>
|
||||
|
|
@ -70,7 +77,7 @@ function CaptureRate(props) {
|
|||
</div>
|
||||
)}
|
||||
</Loader>
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
export default CaptureRate;
|
||||
export default observer(CaptureRate);
|
||||
|
|
|
|||
|
|
@ -2,8 +2,10 @@ import React from 'react';
|
|||
import Select from 'Shared/Select';
|
||||
import { Button, Input } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { toast } from 'react-toastify';
|
||||
import { connect } from 'react-redux';
|
||||
import { fetchSessions } from 'Duck/search';
|
||||
|
||||
const numberOptions = [
|
||||
{ label: 'Less than', value: '<' },
|
||||
|
|
@ -14,10 +16,10 @@ const periodOptions = [
|
|||
{ label: 'Secs', value: 'sec' },
|
||||
]
|
||||
|
||||
function ListingVisibility(props) {
|
||||
function ListingVisibility() {
|
||||
const [changed, setChanged] = React.useState(false);
|
||||
const { settingsStore } = useStore();
|
||||
const sessionSettings = useObserver(() => settingsStore.sessionSettings)
|
||||
const sessionSettings = settingsStore.sessionSettings
|
||||
const [durationSettings, setDurationSettings] = React.useState(sessionSettings.durationFilter);
|
||||
|
||||
const changeSettings = (changes) => {
|
||||
|
|
@ -73,4 +75,4 @@ function ListingVisibility(props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default ListingVisibility;
|
||||
export default observer(ListingVisibility);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export default ({
|
|||
className = '',
|
||||
checked,
|
||||
label = '',
|
||||
plain,
|
||||
plain = false,
|
||||
}) => (
|
||||
<div className={ className }>
|
||||
<label className={styles.label}>
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@ if (storedString) {
|
|||
Object.assign(options, storedOptions)
|
||||
}
|
||||
|
||||
window[KEY] = options
|
||||
window[KEY] = options
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { options } from 'App/dev/console';
|
||||
|
||||
function log(...args) {
|
||||
if (!window.env.PRODUCTION || options.verbose) {
|
||||
if (options.verbose) {
|
||||
console.log(...args);
|
||||
}
|
||||
}
|
||||
|
|
@ -24,4 +24,4 @@ export default {
|
|||
log,
|
||||
warn,
|
||||
error,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ export default class SettingsStore {
|
|||
|
||||
saveCaptureRate(data: any) {
|
||||
return sessionService.saveCaptureRate(data)
|
||||
.then((data: any) => {
|
||||
.then(data => data.json())
|
||||
.then(({ data }) => {
|
||||
this.sessionSettings.merge({
|
||||
captureRate: data.rate,
|
||||
captureAll: data.captureAll
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default class SessionSettings {
|
|||
skipToIssue: boolean = localStorage.getItem(SKIP_TO_ISSUE) === 'true';
|
||||
timezone: Timezone;
|
||||
durationFilter: any = JSON.parse(localStorage.getItem(DURATION_FILTER) || '{}');
|
||||
captureRate: number = 0
|
||||
captureRate: string = '0'
|
||||
captureAll: boolean = false
|
||||
|
||||
constructor() {
|
||||
|
|
@ -18,12 +18,10 @@ export default class SessionSettings {
|
|||
// TODO: remove after a while (1.7.1?)
|
||||
this.timezoneFix()
|
||||
this.timezone = JSON.parse(localStorage.getItem(TIMEZONE)) || { label: 'UTC / GMT +00:00', value: 'UTC' }
|
||||
makeAutoObservable(this, {
|
||||
updateKey: action
|
||||
})
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
|
||||
merge(settings: any) {
|
||||
merge = (settings: any) => {
|
||||
for (const key in settings) {
|
||||
if (settings.hasOwnProperty(key)) {
|
||||
this.updateKey(key, settings[key]);
|
||||
|
|
@ -31,13 +29,23 @@ export default class SessionSettings {
|
|||
}
|
||||
}
|
||||
|
||||
changeCaptureRate = (rate: string) => {
|
||||
if (!rate) return this.captureRate = '0';
|
||||
// react do no see the difference between 01 and 1 decimals, this is why we have to use string casting
|
||||
if (parseInt(rate, 10) <= 100) this.captureRate = `${parseInt(rate, 10)}`;
|
||||
}
|
||||
|
||||
changeCaptureAll = (all: boolean) => {
|
||||
this.captureAll = all;
|
||||
}
|
||||
|
||||
timezoneFix() {
|
||||
if (localStorage.getItem(TIMEZONE) === '[object Object]') {
|
||||
localStorage.setItem(TIMEZONE, JSON.stringify({ label: 'UTC / GMT +00:00', value: 'UTC' }));
|
||||
}
|
||||
}
|
||||
|
||||
updateKey(key: string, value: any) {
|
||||
updateKey = (key: string, value: any) => {
|
||||
runInAction(() => {
|
||||
this[key] = value
|
||||
})
|
||||
|
|
|
|||
|
|
@ -206,6 +206,12 @@ export default class Player extends MessageDistributor {
|
|||
localStorage.setItem(SKIP_TO_ISSUE_STORAGE_KEY, `${skipToIssue}`);
|
||||
update({ skipToIssue });
|
||||
}
|
||||
|
||||
updateSkipToIssue() {
|
||||
const skipToIssue = localStorage.getItem(SKIP_TO_ISSUE_STORAGE_KEY) === 'true';
|
||||
update({ skipToIssue });
|
||||
return skipToIssue;
|
||||
}
|
||||
|
||||
toggleAutoplay() {
|
||||
const autoplay = !getState().autoplay;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ export const togglePlay = initCheck((...args) => instance.togglePlay(...args));
|
|||
export const pause = initCheck((...args) => instance.pause(...args));
|
||||
export const toggleSkip = initCheck((...args) => instance.toggleSkip(...args));
|
||||
export const toggleSkipToIssue = initCheck((...args) => instance.toggleSkipToIssue(...args));
|
||||
export const updateSkipToIssue = initCheck((...args) => instance.updateSkipToIssue(...args));
|
||||
export const toggleAutoplay = initCheck((...args) => instance.toggleAutoplay(...args));
|
||||
export const toggleSpeed = initCheck((...args) => instance.toggleSpeed(...args));
|
||||
export const toggleEvents = initCheck((...args) => instance.toggleEvents(...args));
|
||||
|
|
@ -80,6 +81,7 @@ export const Controls = {
|
|||
pause,
|
||||
toggleSkip,
|
||||
toggleSkipToIssue,
|
||||
updateSkipToIssue,
|
||||
toggleAutoplay,
|
||||
toggleEvents,
|
||||
toggleSpeed,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue