change(ui): small ui fixes, new border for assist etc
This commit is contained in:
parent
e8c9e95dca
commit
9e25f8ef69
13 changed files with 91 additions and 84 deletions
|
|
@ -146,7 +146,7 @@ const NewAlert = (props: IProps) => {
|
|||
// @ts-ignore
|
||||
.toJS();
|
||||
|
||||
|
||||
|
||||
|
||||
const writeQueryOption = (
|
||||
e: React.ChangeEvent,
|
||||
|
|
@ -196,7 +196,7 @@ const NewAlert = (props: IProps) => {
|
|||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className="px-6 pb-3 flex flex-col">
|
||||
<Section
|
||||
index="1"
|
||||
|
|
@ -244,7 +244,7 @@ const NewAlert = (props: IProps) => {
|
|||
title="Notify Through"
|
||||
description="You'll be noticed in app notifications. Additionally opt in to receive alerts on:"
|
||||
content={
|
||||
<NotifyHooks
|
||||
<NotifyHooks
|
||||
instance={instance}
|
||||
onChangeCheck={onChangeCheck}
|
||||
slackChannels={slackChannels}
|
||||
|
|
@ -257,14 +257,14 @@ const NewAlert = (props: IProps) => {
|
|||
</div>
|
||||
|
||||
<div className="flex items-center justify-between p-6 border-t">
|
||||
<BottomButtons
|
||||
<BottomButtons
|
||||
loading={loading}
|
||||
instance={instance}
|
||||
deleting={deleting}
|
||||
onDelete={onDelete}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
</Form>
|
||||
|
||||
<div className="bg-white mt-4 border rounded mb-10">
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import DashboardListItem from './DashboardListItem';
|
|||
function DashboardList() {
|
||||
const { dashboardStore } = useStore();
|
||||
const [shownDashboards, setDashboards] = React.useState([]);
|
||||
const dashboards = dashboardStore.dashboards;
|
||||
const dashboards = dashboardStore.sortedDashboards;
|
||||
const dashboardsSearch = dashboardStore.dashboardsSearch;
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
|
|||
|
|
@ -74,11 +74,13 @@ function DashboardRouter(props: Props) {
|
|||
<Alerts siteId={siteId} />
|
||||
</Route>
|
||||
|
||||
<Route exact strict path={withSiteId(alertCreate(), siteId)}>
|
||||
<CreateAlert siteId={siteId} />
|
||||
<Route exact path={withSiteId(alertCreate(), siteId)}>
|
||||
{/* @ts-ignore */}
|
||||
<CreateAlert siteId={siteId as string} />
|
||||
</Route>
|
||||
|
||||
<Route exact strict path={withSiteId(alertEdit(), siteId)}>
|
||||
<Route exact path={withSiteId(alertEdit(), siteId)}>
|
||||
{/* @ts-ignore */}
|
||||
<CreateAlert siteId={siteId} {...props} />
|
||||
</Route>
|
||||
</Switch>
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import { useObserver } from 'mobx-react-lite';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React, { useEffect } from 'react';
|
||||
import { NoContent, Pagination, Icon } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { filterList } from 'App/utils';
|
||||
import MetricListItem from '../MetricListItem';
|
||||
import { sliceListPerPage } from 'App/utils';
|
||||
import { IWidget } from 'App/mstore/types/widget';
|
||||
import Widget from 'App/mstore/types/widget';
|
||||
|
||||
function MetricsList({ siteId }: { siteId: string }) {
|
||||
const { metricStore } = useStore();
|
||||
const metrics = useObserver(() => metricStore.metrics);
|
||||
const metricsSearch = useObserver(() => metricStore.metricsSearch);
|
||||
const metrics = metricStore.sortedWidgets;
|
||||
const metricsSearch = metricStore.metricsSearch;
|
||||
|
||||
const filterByDashboard = (item: IWidget, searchRE: RegExp) => {
|
||||
const filterByDashboard = (item: Widget, searchRE: RegExp) => {
|
||||
const dashboardsStr = item.dashboards.map((d: any) => d.name).join(' ');
|
||||
return searchRE.test(dashboardsStr);
|
||||
};
|
||||
|
|
@ -26,7 +26,7 @@ function MetricsList({ siteId }: { siteId: string }) {
|
|||
metricStore.updateKey('sessionsPage', 1);
|
||||
}, []);
|
||||
|
||||
return useObserver(() => (
|
||||
return (
|
||||
<NoContent
|
||||
show={lenth === 0}
|
||||
title={
|
||||
|
|
@ -68,7 +68,7 @@ function MetricsList({ siteId }: { siteId: string }) {
|
|||
/>
|
||||
</div>
|
||||
</NoContent>
|
||||
));
|
||||
);
|
||||
}
|
||||
|
||||
export default MetricsList;
|
||||
export default observer(MetricsList);
|
||||
|
|
|
|||
|
|
@ -2,12 +2,13 @@ import React, { useEffect, useState } from 'react';
|
|||
import { connect } from 'react-redux';
|
||||
import { NavLink, withRouter } from 'react-router-dom';
|
||||
import cn from 'classnames';
|
||||
import {
|
||||
import {
|
||||
sessions,
|
||||
metrics,
|
||||
assist,
|
||||
client,
|
||||
dashboard,
|
||||
alerts,
|
||||
withSiteId,
|
||||
CLIENT_DEFAULT_TAB,
|
||||
} from 'App/routes';
|
||||
|
|
@ -28,18 +29,19 @@ import { useStore } from 'App/mstore';
|
|||
import { useObserver } from 'mobx-react-lite';
|
||||
|
||||
const DASHBOARD_PATH = dashboard();
|
||||
const ALERTS_PATH = alerts();
|
||||
const METRICS_PATH = metrics();
|
||||
const SESSIONS_PATH = sessions();
|
||||
const ASSIST_PATH = assist();
|
||||
const CLIENT_PATH = client(CLIENT_DEFAULT_TAB);
|
||||
|
||||
const Header = (props) => {
|
||||
const {
|
||||
sites, location, account,
|
||||
const {
|
||||
sites, location, account,
|
||||
onLogoutClick, siteId,
|
||||
boardingCompletion = 100, showAlerts = false,
|
||||
} = props;
|
||||
|
||||
|
||||
const name = account.get('name').split(" ")[0];
|
||||
const [hideDiscover, setHideDiscover] = useState(false)
|
||||
const { userStore, notificationStore } = useStore();
|
||||
|
|
@ -52,7 +54,7 @@ const Header = (props) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (!account.id || initialDataFetched) return;
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
Promise.all([
|
||||
userStore.fetchLimits(),
|
||||
|
|
@ -101,9 +103,11 @@ const Header = (props) => {
|
|||
className={ styles.nav }
|
||||
activeClassName={ styles.active }
|
||||
isActive={ (_, location) => {
|
||||
return location.pathname.includes(DASHBOARD_PATH) || location.pathname.includes(METRICS_PATH);
|
||||
return location.pathname.includes(DASHBOARD_PATH)
|
||||
|| location.pathname.includes(METRICS_PATH)
|
||||
|| location.pathname.includes(ALERTS_PATH)
|
||||
}}
|
||||
>
|
||||
>
|
||||
<span>{ 'Dashboards' }</span>
|
||||
</NavLink>
|
||||
<div className={ styles.right }>
|
||||
|
|
@ -111,18 +115,18 @@ const Header = (props) => {
|
|||
<div className={ styles.divider } />
|
||||
|
||||
{ (boardingCompletion < 100 && !hideDiscover) && (
|
||||
<React.Fragment>
|
||||
<React.Fragment>
|
||||
<OnboardingExplore onComplete={() => setHideDiscover(true)} />
|
||||
<div className={ styles.divider } />
|
||||
</React.Fragment>
|
||||
)}
|
||||
|
||||
|
||||
<Notifications />
|
||||
<div className={ styles.divider } />
|
||||
<Popup content={ `Preferences` } >
|
||||
<NavLink to={ CLIENT_PATH } className={ styles.headerIcon }><Icon name="cog" size="20" /></NavLink>
|
||||
</Popup>
|
||||
|
||||
|
||||
<div className={ styles.divider } />
|
||||
<div className={ styles.userDetails }>
|
||||
<div className="flex items-center">
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import React from 'react';
|
||||
import cn from "classnames";
|
||||
import { connect } from 'react-redux';
|
||||
import { } from 'Player';
|
||||
import {
|
||||
NONE, OVERVIEW,
|
||||
NONE,
|
||||
} from 'Duck/components/player';
|
||||
import Player from './Player';
|
||||
import SubHeader from './Subheader';
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
makeAutoObservable,
|
||||
runInAction,
|
||||
computed,
|
||||
} from "mobx";
|
||||
import Dashboard from "./types/dashboard";
|
||||
import Widget from "./types/widget";
|
||||
|
|
@ -64,6 +65,11 @@ export default class DashboardStore {
|
|||
this.drillDownFilter.updateKey("endTimestamp", timeStamps.endTimestamp);
|
||||
}
|
||||
|
||||
@computed
|
||||
get sortedDashboards() {
|
||||
return [...this.dashboards].sort((a, b) => b.createdAt - a.createdAt)
|
||||
}
|
||||
|
||||
toggleAllSelectedWidgets(isSelected: boolean) {
|
||||
if (isSelected) {
|
||||
const allWidgets = this.widgetCategories.reduce((acc, cat) => {
|
||||
|
|
@ -89,7 +95,7 @@ export default class DashboardStore {
|
|||
}
|
||||
|
||||
removeSelectedWidgetByCategory = (category: any) => {
|
||||
const categoryWidgetIds = category.widgets.map((w) => w.metricId);
|
||||
const categoryWidgetIds = category.widgets.map((w: Widget) => w.metricId);
|
||||
this.selectedWidgets = this.selectedWidgets.filter(
|
||||
(widget: any) => !categoryWidgetIds.includes(widget.metricId)
|
||||
);
|
||||
|
|
@ -119,7 +125,8 @@ export default class DashboardStore {
|
|||
this.selectedWidgets = [];
|
||||
}
|
||||
|
||||
updateKey(key: any, value: any) {
|
||||
updateKey(key: string, value: any) {
|
||||
// @ts-ignore
|
||||
this[key] = value;
|
||||
}
|
||||
|
||||
|
|
@ -138,7 +145,7 @@ export default class DashboardStore {
|
|||
.getDashboards()
|
||||
.then((list: any) => {
|
||||
runInAction(() => {
|
||||
this.dashboards = list.map((d) =>
|
||||
this.dashboards = list.map((d: Record<string, any>) =>
|
||||
new Dashboard().fromJson(d)
|
||||
);
|
||||
});
|
||||
|
|
@ -168,7 +175,7 @@ export default class DashboardStore {
|
|||
this.fetchingDashboard = value;
|
||||
}
|
||||
|
||||
save(dashboard: IDashboard): Promise<any> {
|
||||
save(dashboard: Dashboard): Promise<any> {
|
||||
this.isSaving = true;
|
||||
const isCreating = !dashboard.dashboardId;
|
||||
|
||||
|
|
@ -205,7 +212,7 @@ export default class DashboardStore {
|
|||
});
|
||||
}
|
||||
|
||||
saveMetric(metric: IWidget, dashboardId: string): Promise<any> {
|
||||
saveMetric(metric: Widget, dashboardId: string): Promise<any> {
|
||||
const isCreating = !metric.widgetId;
|
||||
return dashboardService
|
||||
.saveMetric(metric, dashboardId)
|
||||
|
|
@ -252,7 +259,7 @@ export default class DashboardStore {
|
|||
|
||||
fromJson(json: any) {
|
||||
runInAction(() => {
|
||||
this.dashboards = json.dashboards.map((d) =>
|
||||
this.dashboards = json.dashboards.map((d: Record<string, any>) =>
|
||||
new Dashboard().fromJson(d)
|
||||
);
|
||||
});
|
||||
|
|
@ -367,7 +374,7 @@ export default class DashboardStore {
|
|||
});
|
||||
}
|
||||
|
||||
addWidgetToDashboard(dashboard: IDashboard, metricIds: any): Promise<any> {
|
||||
addWidgetToDashboard(dashboard: Dashboard, metricIds: any): Promise<any> {
|
||||
this.isSaving = true;
|
||||
return dashboardService
|
||||
.addWidget(dashboard, metricIds)
|
||||
|
|
@ -399,7 +406,7 @@ export default class DashboardStore {
|
|||
}
|
||||
|
||||
fetchMetricChartData(
|
||||
metric: IWidget,
|
||||
metric: Widget,
|
||||
data: any,
|
||||
isWidget: boolean = false,
|
||||
period: Record<string, any>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { makeAutoObservable, runInAction, observable, action, reaction, computed } from "mobx"
|
||||
import Widget, { IWidget } from "./types/widget";
|
||||
import { makeAutoObservable, computed } from "mobx"
|
||||
import Widget from "./types/widget";
|
||||
import { metricService, errorService } from "App/services";
|
||||
import { toast } from 'react-toastify';
|
||||
import Error from "./types/error";
|
||||
|
|
@ -8,8 +8,8 @@ export default class MetricStore {
|
|||
isLoading: boolean = false
|
||||
isSaving: boolean = false
|
||||
|
||||
metrics: IWidget[] = []
|
||||
instance: IWidget = new Widget()
|
||||
metrics: Widget[] = []
|
||||
instance = new Widget()
|
||||
|
||||
page: number = 1
|
||||
pageSize: number = 10
|
||||
|
|
@ -20,41 +20,21 @@ export default class MetricStore {
|
|||
sessionsPageSize: number = 10
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this, {
|
||||
isLoading: observable,
|
||||
metrics: observable,
|
||||
instance: observable,
|
||||
page: observable,
|
||||
pageSize: observable,
|
||||
metricsSearch: observable,
|
||||
sort: observable,
|
||||
makeAutoObservable(this)
|
||||
}
|
||||
|
||||
init: action,
|
||||
updateKey: action,
|
||||
merge: action,
|
||||
reset: action,
|
||||
addToList: action,
|
||||
updateInList: action,
|
||||
findById: action,
|
||||
removeById: action,
|
||||
|
||||
save: action,
|
||||
fetchList: action,
|
||||
fetch: action,
|
||||
delete: action,
|
||||
|
||||
fetchError: action,
|
||||
|
||||
paginatedList: computed,
|
||||
})
|
||||
@computed
|
||||
get sortedWidgets() {
|
||||
return [...this.metrics].sort((a, b) => b.lastModified - a.lastModified)
|
||||
}
|
||||
|
||||
// State Actions
|
||||
init(metric?: IWidget|null) {
|
||||
init(metric?: Widget | null) {
|
||||
this.instance.update(metric || new Widget())
|
||||
}
|
||||
|
||||
updateKey(key: string, value: any) {
|
||||
// @ts-ignore
|
||||
this[key] = value
|
||||
}
|
||||
|
||||
|
|
@ -70,33 +50,36 @@ export default class MetricStore {
|
|||
}
|
||||
}
|
||||
|
||||
addToList(metric: IWidget) {
|
||||
addToList(metric: Widget) {
|
||||
this.metrics.push(metric)
|
||||
}
|
||||
|
||||
updateInList(metric: IWidget) {
|
||||
const index = this.metrics.findIndex((m: IWidget) => m[Widget.ID_KEY] === metric[Widget.ID_KEY])
|
||||
updateInList(metric: Widget) {
|
||||
// @ts-ignore
|
||||
const index = this.metrics.findIndex((m: Widget) => m[Widget.ID_KEY] === metric[Widget.ID_KEY])
|
||||
if (index >= 0) {
|
||||
this.metrics[index] = metric
|
||||
}
|
||||
}
|
||||
|
||||
findById(id: string) {
|
||||
// @ts-ignore
|
||||
return this.metrics.find(m => m[Widget.ID_KEY] === id)
|
||||
}
|
||||
|
||||
removeById(id: string): void {
|
||||
// @ts-ignore
|
||||
this.metrics = this.metrics.filter(m => m[Widget.ID_KEY] !== id)
|
||||
}
|
||||
|
||||
get paginatedList(): IWidget[] {
|
||||
get paginatedList(): Widget[] {
|
||||
const start = (this.page - 1) * this.pageSize
|
||||
const end = start + this.pageSize
|
||||
return this.metrics.slice(start, end)
|
||||
}
|
||||
|
||||
// API Communication
|
||||
save(metric: IWidget, dashboardId?: string): Promise<any> {
|
||||
save(metric: Widget, dashboardId?: string): Promise<any> {
|
||||
const wasCreating = !metric.exists()
|
||||
this.isSaving = true
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -143,10 +126,12 @@ export default class MetricStore {
|
|||
})
|
||||
}
|
||||
|
||||
delete(metric: IWidget) {
|
||||
delete(metric: Widget) {
|
||||
this.isSaving = true
|
||||
// @ts-ignore
|
||||
return metricService.deleteMetric(metric[Widget.ID_KEY])
|
||||
.then(() => {
|
||||
// @ts-ignore
|
||||
this.removeById(metric[Widget.ID_KEY])
|
||||
toast.success('Metric deleted successfully')
|
||||
}).finally(() => {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default class Dashboard {
|
|||
isValid: boolean = false
|
||||
currentWidget: Widget = new Widget()
|
||||
config: any = {}
|
||||
createdAt: Date = new Date()
|
||||
createdAt: number = new Date().getTime()
|
||||
|
||||
constructor() {
|
||||
makeAutoObservable(this)
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export default class Widget {
|
|||
sessions: [] = []
|
||||
isPublic: boolean = true
|
||||
owner: string = ""
|
||||
lastModified: Date = new Date()
|
||||
lastModified: number = new Date().getTime()
|
||||
dashboards: any[] = []
|
||||
dashboardIds: any[] = []
|
||||
config: any = {}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ function getElementsFromInternalPoint(doc: Document, { x, y }: Point): Element[]
|
|||
}
|
||||
|
||||
if (typeof doc.elementsFromPoint === 'function') {
|
||||
return doc.elementsFromPoint(x, y)
|
||||
return doc.elementsFromPoint(x, y)
|
||||
}
|
||||
const el = doc.elementFromPoint(x, y)
|
||||
return el ? [ el ] : []
|
||||
|
|
@ -53,10 +53,13 @@ function isIframe(el: Element): el is HTMLIFrameElement {
|
|||
}
|
||||
|
||||
export default abstract class BaseScreen {
|
||||
public readonly overlay: HTMLDivElement;
|
||||
private readonly iframe: HTMLIFrameElement;
|
||||
protected readonly screen: HTMLDivElement;
|
||||
public readonly overlay: HTMLDivElement;
|
||||
|
||||
private readonly iframe: HTMLIFrameElement;
|
||||
protected readonly screen: HTMLDivElement;
|
||||
protected readonly controlButton: HTMLDivElement;
|
||||
protected parentElement: HTMLElement | null = null;
|
||||
|
||||
constructor() {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.className = styles.iframe;
|
||||
|
|
@ -83,7 +86,7 @@ export default abstract class BaseScreen {
|
|||
|
||||
this.parentElement = parentElement;
|
||||
// parentElement.onresize = this.scale;
|
||||
window.addEventListener('resize', this.scale);
|
||||
window.addEventListener('resize', this.scale);
|
||||
this.scale();
|
||||
|
||||
/* == For the Inspecting Document content == */
|
||||
|
|
@ -101,6 +104,11 @@ export default abstract class BaseScreen {
|
|||
})
|
||||
}
|
||||
|
||||
toggleRemoteControlStatus(isEnabled: boolean ) {
|
||||
const styles = isEnabled ? { border: '2px dashed blue' } : { border: 'unset'}
|
||||
return Object.assign(this.screen.style, styles)
|
||||
}
|
||||
|
||||
get window(): WindowProxy | null {
|
||||
return this.iframe.contentWindow;
|
||||
}
|
||||
|
|
@ -145,7 +153,7 @@ export default abstract class BaseScreen {
|
|||
}
|
||||
|
||||
getElementFromInternalPoint({ x, y }: Point): Element | null {
|
||||
// elementFromPoint && elementFromPoints require viewpoint-related coordinates,
|
||||
// elementFromPoint && elementFromPoints require viewpoint-related coordinates,
|
||||
// not document-related
|
||||
return this.document?.elementFromPoint(x, y) || null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,5 +18,5 @@
|
|||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
z-index: 10;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,11 +295,13 @@ export default class AssistManager {
|
|||
this.md.overlay.addEventListener("mousemove", this.onMouseMove)
|
||||
this.md.overlay.addEventListener("click", this.onMouseClick)
|
||||
this.md.overlay.addEventListener("wheel", this.onWheel)
|
||||
this.md.toggleRemoteControlStatus(true)
|
||||
update({ remoteControl: RemoteControlStatus.Enabled })
|
||||
} else {
|
||||
this.md.overlay.removeEventListener("mousemove", this.onMouseMove)
|
||||
this.md.overlay.removeEventListener("click", this.onMouseClick)
|
||||
this.md.overlay.removeEventListener("wheel", this.onWheel)
|
||||
this.md.toggleRemoteControlStatus(false)
|
||||
update({ remoteControl: RemoteControlStatus.Disabled })
|
||||
this.toggleAnnotation(false)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue