feat(ui) - dashboard - wip
This commit is contained in:
parent
ad706ededd
commit
4602de3caf
7 changed files with 102 additions and 121 deletions
|
|
@ -35,8 +35,7 @@ function CustomMetricPieChart(props: Props) {
|
|||
}
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<NoContent size="small" show={data.values && data.values.length === 0} >
|
||||
<NoContent size="small" show={!data.values || data.values.length === 0} >
|
||||
<ResponsiveContainer height={ 220 } width="100%">
|
||||
<PieChart>
|
||||
<Pie
|
||||
|
|
@ -52,105 +51,77 @@ function CustomMetricPieChart(props: Props) {
|
|||
activeIndex={1}
|
||||
onClick={onClickHandler}
|
||||
labelLine={({
|
||||
cx,
|
||||
cy,
|
||||
midAngle,
|
||||
innerRadius,
|
||||
outerRadius,
|
||||
value,
|
||||
index
|
||||
}) => {
|
||||
const RADIAN = Math.PI / 180;
|
||||
let radius1 = 15 + innerRadius + (outerRadius - innerRadius);
|
||||
let radius2 = innerRadius + (outerRadius - innerRadius);
|
||||
let x2 = cx + radius1 * Math.cos(-midAngle * RADIAN);
|
||||
let y2 = cy + radius1 * Math.sin(-midAngle * RADIAN);
|
||||
let x1 = cx + radius2 * Math.cos(-midAngle * RADIAN);
|
||||
let y1 = cy + radius2 * Math.sin(-midAngle * RADIAN);
|
||||
cx,
|
||||
cy,
|
||||
midAngle,
|
||||
innerRadius,
|
||||
outerRadius,
|
||||
value,
|
||||
index
|
||||
}) => {
|
||||
const RADIAN = Math.PI / 180;
|
||||
let radius1 = 15 + innerRadius + (outerRadius - innerRadius);
|
||||
let radius2 = innerRadius + (outerRadius - innerRadius);
|
||||
let x2 = cx + radius1 * Math.cos(-midAngle * RADIAN);
|
||||
let y2 = cy + radius1 * Math.sin(-midAngle * RADIAN);
|
||||
let x1 = cx + radius2 * Math.cos(-midAngle * RADIAN);
|
||||
let y1 = cy + radius2 * Math.sin(-midAngle * RADIAN);
|
||||
|
||||
const percentage = value * 100 / data.values.reduce((a, b) => a + b.sessionCount, 0);
|
||||
|
||||
if (percentage<3){
|
||||
return null;
|
||||
}
|
||||
|
||||
return(
|
||||
<line x1={x1} y1={y1} x2={x2} y2={y2} stroke="#3EAAAF" strokeWidth={1} />
|
||||
)
|
||||
}}
|
||||
label={({
|
||||
cx,
|
||||
cy,
|
||||
midAngle,
|
||||
innerRadius,
|
||||
outerRadius,
|
||||
value,
|
||||
index
|
||||
}) => {
|
||||
const RADIAN = Math.PI / 180;
|
||||
let radius = 20 + innerRadius + (outerRadius - innerRadius);
|
||||
let x = cx + radius * Math.cos(-midAngle * RADIAN);
|
||||
let y = cy + radius * Math.sin(-midAngle * RADIAN);
|
||||
const percentage = (value / data.values.reduce((a, b) => a + b.sessionCount, 0)) * 100;
|
||||
let name = data.values[index].name || 'Unidentified';
|
||||
name = name.length > 20 ? name.substring(0, 20) + '...' : name;
|
||||
if (percentage<3){
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<text
|
||||
x={x}
|
||||
y={y}
|
||||
fontWeight="400"
|
||||
fontSize="12px"
|
||||
// fontFamily="'Source Sans Pro', 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif'"
|
||||
textAnchor={x > cx ? "start" : "end"}
|
||||
dominantBaseline="central"
|
||||
fill='#666'
|
||||
>
|
||||
{name || 'Unidentified'} {numberWithCommas(value)}
|
||||
</text>
|
||||
);
|
||||
}}
|
||||
// label={({
|
||||
// cx,
|
||||
// cy,
|
||||
// midAngle,
|
||||
// innerRadius,
|
||||
// outerRadius,
|
||||
// value,
|
||||
// index
|
||||
// }) => {
|
||||
// const RADIAN = Math.PI / 180;
|
||||
// const radius = 30 + innerRadius + (outerRadius - innerRadius);
|
||||
// const x = cx + radius * Math.cos(-midAngle * RADIAN);
|
||||
// const y = cy + radius * Math.sin(-midAngle * RADIAN);
|
||||
|
||||
// return (
|
||||
// <text
|
||||
// x={x}
|
||||
// y={y}
|
||||
// fill="#3EAAAF"
|
||||
// textAnchor={x > cx ? "start" : "end"}
|
||||
// dominantBaseline="top"
|
||||
// fontSize={10}
|
||||
// >
|
||||
// {data.values[index].name} ({value})
|
||||
// </text>
|
||||
// );
|
||||
// }}
|
||||
const percentage = value * 100 / data.values.reduce((a, b) => a + b.sessionCount, 0);
|
||||
|
||||
if (percentage<3){
|
||||
return null;
|
||||
}
|
||||
|
||||
return(
|
||||
<line x1={x1} y1={y1} x2={x2} y2={y2} stroke="#3EAAAF" strokeWidth={1} />
|
||||
)
|
||||
}}
|
||||
label={({
|
||||
cx,
|
||||
cy,
|
||||
midAngle,
|
||||
innerRadius,
|
||||
outerRadius,
|
||||
value,
|
||||
index
|
||||
}) => {
|
||||
const RADIAN = Math.PI / 180;
|
||||
let radius = 20 + innerRadius + (outerRadius - innerRadius);
|
||||
let x = cx + radius * Math.cos(-midAngle * RADIAN);
|
||||
let y = cy + radius * Math.sin(-midAngle * RADIAN);
|
||||
const percentage = (value / data.values.reduce((a, b) => a + b.sessionCount, 0)) * 100;
|
||||
let name = data.values[index].name || 'Unidentified';
|
||||
name = name.length > 20 ? name.substring(0, 20) + '...' : name;
|
||||
if (percentage<3){
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<text
|
||||
x={x}
|
||||
y={y}
|
||||
fontWeight="400"
|
||||
fontSize="12px"
|
||||
// fontFamily="'Source Sans Pro', 'Roboto', 'Helvetica Neue', 'Helvetica', 'Arial', 'sans-serif'"
|
||||
textAnchor={x > cx ? "start" : "end"}
|
||||
dominantBaseline="central"
|
||||
fill='#666'
|
||||
>
|
||||
{name || 'Unidentified'} {numberWithCommas(value)}
|
||||
</text>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{data.values.map((entry, index) => (
|
||||
{data && data.values && data.values.map((entry, index) => (
|
||||
<Cell key={`cell-${index}`} fill={Styles.colorsPie[index % Styles.colorsPie.length]} />
|
||||
))}
|
||||
))}
|
||||
</Pie>
|
||||
<Tooltip {...Styles.tooltip} />
|
||||
</PieChart>
|
||||
|
||||
|
||||
</ResponsiveContainer>
|
||||
<div className="text-sm color-gray-medium">Top 5 </div>
|
||||
</NoContent>
|
||||
</div>
|
||||
</NoContent>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,17 +4,22 @@ import { NoContent, Pagination } from 'UI';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { getRE } from 'App/utils';
|
||||
import MetricListItem from '../MetricListItem';
|
||||
import { sliceListPerPage } from 'App/utils';
|
||||
|
||||
interface Props { }
|
||||
function MetricsList(props: Props) {
|
||||
const { metricStore } = useStore();
|
||||
const metrics = useObserver(() => metricStore.metrics);
|
||||
const lenth = metrics.length;
|
||||
|
||||
const metricsSearch = useObserver(() => metricStore.metricsSearch);
|
||||
const filterRE = getRE(metricsSearch, 'i');
|
||||
const list = useObserver(() => metrics.filter(w => filterRE.test(w.name)));
|
||||
|
||||
const filterList = (list) => {
|
||||
const filterRE = getRE(metricsSearch, 'i');
|
||||
let _list = list.filter(w => {
|
||||
return filterRE.test(w.name) || filterRE.test(w.metricType) || filterRE.test(w.owner) ;
|
||||
});
|
||||
return _list
|
||||
}
|
||||
const list: any = metricsSearch !== '' ? filterList(metrics) : metrics;
|
||||
const lenth = list.length;
|
||||
|
||||
return useObserver(() => (
|
||||
<NoContent show={lenth === 0} icon="exclamation-circle">
|
||||
|
|
@ -28,7 +33,7 @@ function MetricsList(props: Props) {
|
|||
<div className="col-span-2">Last Modified</div>
|
||||
</div>
|
||||
|
||||
{list.map((metric: any) => (
|
||||
{sliceListPerPage(list, metricStore.page - 1, metricStore.pageSize).map((metric: any) => (
|
||||
<MetricListItem metric={metric} />
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,22 +1,31 @@
|
|||
import { useObserver } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { Icon } from 'UI';
|
||||
import { debounce } from 'App/utils';
|
||||
|
||||
let debounceUpdate: any = () => {}
|
||||
function MetricsSearch(props) {
|
||||
const { dashboardStore } = useStore();
|
||||
const metricsSearch = useObserver(() => dashboardStore.metricsSearch);
|
||||
const { metricStore } = useStore();
|
||||
const [query, setQuery] = useState(metricStore.metricsSearch);
|
||||
useEffect(() => {
|
||||
debounceUpdate = debounce((key, value) => metricStore.updateKey(key, value), 500);
|
||||
}, [])
|
||||
|
||||
const write = ({ target: { name, value } }) => {
|
||||
setQuery(value);
|
||||
debounceUpdate('metricsSearch', value);
|
||||
}
|
||||
|
||||
return useObserver(() => (
|
||||
<div className="relative">
|
||||
<Icon name="search" className="absolute top-0 bottom-0 ml-2 m-auto" size="18" />
|
||||
<input
|
||||
value={metricsSearch}
|
||||
value={query}
|
||||
name="metricsSearch"
|
||||
className="bg-white p-2 border rounded w-full pl-10"
|
||||
placeholder="Filter by title, type, dashboard and owner"
|
||||
onChange={({ target: { name, value } }) => dashboardStore.updateKey(name, value)}
|
||||
onChange={write}
|
||||
/>
|
||||
</div>
|
||||
));
|
||||
|
|
|
|||
|
|
@ -59,10 +59,8 @@ function WidgetForm(props: Props) {
|
|||
if (wasCreating) {
|
||||
if (parseInt(dashboardId) > 0) {
|
||||
history.push(withSiteId(dashboardMetricDetails(parseInt(dashboardId), metric.metricId), siteId));
|
||||
history.go(0)
|
||||
} else {
|
||||
history.push(withSiteId(metricDetails(metric.metricId), siteId));
|
||||
history.go(0)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,11 +18,7 @@ function WidgetView(props: Props) {
|
|||
const { metricStore } = useStore();
|
||||
const widget = useObserver(() => metricStore.instance);
|
||||
const loading = useObserver(() => metricStore.isLoading);
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setExpanded(!widget.exists())
|
||||
}, [widget])
|
||||
const [expanded, setExpanded] = useState(!metricId || metricId === 'create');
|
||||
|
||||
React.useEffect(() => {
|
||||
if (metricId && metricId !== 'create') {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default class MetricStore implements IMetricStore {
|
|||
instance: IWidget = new Widget()
|
||||
|
||||
page: number = 1
|
||||
pageSize: number = 10
|
||||
pageSize: number = 4
|
||||
metricsSearch: string = ""
|
||||
sort: any = {}
|
||||
|
||||
|
|
@ -74,14 +74,14 @@ export default class MetricStore implements IMetricStore {
|
|||
paginatedList: computed,
|
||||
})
|
||||
|
||||
// reaction(
|
||||
// () => this.metricsSearch,
|
||||
// (metricsSearch) => { // TODO filter the list for View
|
||||
// console.log('metricsSearch', metricsSearch)
|
||||
// this.page = 1
|
||||
// this.paginatedList()
|
||||
// }
|
||||
// )
|
||||
reaction(
|
||||
() => this.metricsSearch,
|
||||
(metricsSearch) => { // TODO filter the list for View
|
||||
console.log('metricsSearch', metricsSearch)
|
||||
this.page = 1
|
||||
this.paginatedList
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// State Actions
|
||||
|
|
@ -140,6 +140,7 @@ export default class MetricStore implements IMetricStore {
|
|||
if (wasCreating) {
|
||||
toast.success('Metric created successfully')
|
||||
this.addToList(_metric)
|
||||
this.instance = _metric
|
||||
} else {
|
||||
toast.success('Metric updated successfully')
|
||||
this.updateInList(_metric)
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ export default class Widget implements IWidget {
|
|||
this.series = json.series ? json.series.map((series: any) => new FilterSeries().fromJson(series)) : [],
|
||||
this.dashboards = json.dashboards
|
||||
this.owner = json.ownerEmail
|
||||
this.lastModified = DateTime.fromMillis(json.editedAt || json.createdAt)
|
||||
// this.lastModified = json.editedAt || json.createdAt ? DateTime.fromMillis(json.editedAt || json.createdAt) : null
|
||||
this.lastModified = DateTime.fromMillis(1649319074)
|
||||
this.config = json.config
|
||||
this.position = json.config.position
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue