From 373dbf50ba5aa33c79c055ba9da4386e795eccb4 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Tue, 1 Mar 2022 23:03:50 -0800 Subject: [PATCH] Added website limit and show more button. Closes #592. --- assets/gear.svg | 1 + components/helpers/StickyHeader.js | 3 +- components/pages/WebsiteList.js | 49 ++++++++++++------- components/pages/WebsiteList.module.css | 5 ++ .../settings/DashboardSettingsButton.js | 27 ++++++++++ hooks/useDateRange.js | 6 +-- lib/constants.js | 3 +- store/app.js | 19 ++++++- 8 files changed, 87 insertions(+), 26 deletions(-) create mode 100644 assets/gear.svg create mode 100644 components/settings/DashboardSettingsButton.js diff --git a/assets/gear.svg b/assets/gear.svg new file mode 100644 index 00000000..ab97a693 --- /dev/null +++ b/assets/gear.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/helpers/StickyHeader.js b/components/helpers/StickyHeader.js index 477bd393..9c42e4fd 100644 --- a/components/helpers/StickyHeader.js +++ b/components/helpers/StickyHeader.js @@ -25,9 +25,8 @@ export default function StickyHeader({ } }; - checkPosition(); - if (enabled) { + checkPosition(); window.addEventListener('scroll', checkPosition); } diff --git a/components/pages/WebsiteList.js b/components/pages/WebsiteList.js index 0a29d8ed..f2094f03 100644 --- a/components/pages/WebsiteList.js +++ b/components/pages/WebsiteList.js @@ -4,15 +4,23 @@ import Link from 'components/common/Link'; import WebsiteChart from 'components/metrics/WebsiteChart'; import Page from 'components/layout/Page'; import EmptyPlaceholder from 'components/common/EmptyPlaceholder'; -import Button from 'components/common/Button'; import useFetch from 'hooks/useFetch'; +import DashboardSettingsButton from 'components/settings/DashboardSettingsButton'; +import Button from 'components/common/Button'; +import useStore from 'store/app'; import Arrow from 'assets/arrow-right.svg'; -import Chart from 'assets/chart-bar.svg'; import styles from './WebsiteList.module.css'; +const selector = state => state.dashboard; + export default function WebsiteList({ userId }) { const { data } = useFetch('/websites', { params: { user_id: userId } }); - const [showCharts, setShowCharts] = useState(true); + const { showCharts, limit } = useStore(selector); + const [max, setMax] = useState(limit); + + function handleMore() { + setMax(max + limit); + } if (!data) { return null; @@ -40,23 +48,26 @@ export default function WebsiteList({ userId }) { return (
-
- {data.map(({ website_id, name, domain }) => ( -
- -
- ))} + {data.map(({ website_id, name, domain }, index) => + index < max ? ( +
+ +
+ ) : null, + )} + {max < data.length && ( + + )}
); } diff --git a/components/pages/WebsiteList.module.css b/components/pages/WebsiteList.module.css index 4c2952d6..d9899574 100644 --- a/components/pages/WebsiteList.module.css +++ b/components/pages/WebsiteList.module.css @@ -16,3 +16,8 @@ justify-content: flex-end; padding-top: 10px; } + +.button { + align-self: center; + margin-bottom: 40px; +} diff --git a/components/settings/DashboardSettingsButton.js b/components/settings/DashboardSettingsButton.js new file mode 100644 index 00000000..41dc3bf2 --- /dev/null +++ b/components/settings/DashboardSettingsButton.js @@ -0,0 +1,27 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; +import MenuButton from 'components/common/MenuButton'; +import Gear from 'assets/gear.svg'; +import useStore, { setDashboard } from 'store/app'; + +const selector = state => state.dashboard; + +export default function DashboardSettingsButton() { + const settings = useStore(selector); + + const menuOptions = [ + { + label: , + value: 'charts', + }, + ]; + + function handleSelect(value) { + if (value === 'charts') { + setDashboard({ showCharts: !settings.showCharts }); + } + //setDashboard(value); + } + + return } options={menuOptions} onSelect={handleSelect} hideLabel />; +} diff --git a/hooks/useDateRange.js b/hooks/useDateRange.js index 5b2b3a19..81fc6846 100644 --- a/hooks/useDateRange.js +++ b/hooks/useDateRange.js @@ -1,4 +1,4 @@ -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { parseISO } from 'date-fns'; import { getDateRange } from 'lib/date'; import { getItem, setItem } from 'lib/web'; @@ -9,10 +9,10 @@ import useStore, { setDateRange } from 'store/websites'; export default function useDateRange(websiteId) { const { locale } = useLocale(); + const forceUpdate = useForceUpdate(); const selector = useCallback(state => state?.[websiteId]?.dateRange, [websiteId]); const websiteDateRange = useStore(selector); - const forceUpdate = useForceUpdate(); - const defaultDateRange = getDateRange(DEFAULT_DATE_RANGE, locale); + const defaultDateRange = useMemo(() => getDateRange(DEFAULT_DATE_RANGE, locale), [locale]); const globalDefault = getItem(DATE_RANGE_CONFIG); let globalDateRange; diff --git a/lib/constants.js b/lib/constants.js index de9cef20..cdeebf72 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -3,6 +3,7 @@ export const LOCALE_CONFIG = 'umami.locale'; export const TIMEZONE_CONFIG = 'umami.timezone'; export const DATE_RANGE_CONFIG = 'umami.date-range'; export const THEME_CONFIG = 'umami.theme'; +export const DASHBOARD_CONFIG = 'umami.dashboard'; export const VERSION_CHECK = 'umami.version-check'; export const TOKEN_HEADER = 'x-umami-token'; export const HOMEPAGE_URL = 'https://umami.is'; @@ -10,9 +11,9 @@ export const VERSION_URL = 'https://github.com/mikecao/umami/releases'; export const DEFAULT_LOCALE = 'en-US'; export const DEFAULT_THEME = 'light'; -export const DEFAUL_CHART_HEIGHT = 400; export const DEFAULT_ANIMATION_DURATION = 300; export const DEFAULT_DATE_RANGE = '24hour'; +export const DEFAULT_WEBSITE_LIMIT = 10; export const REALTIME_RANGE = 30; export const REALTIME_INTERVAL = 3000; diff --git a/store/app.js b/store/app.js index 0fe8ac02..4182abed 100644 --- a/store/app.js +++ b/store/app.js @@ -1,10 +1,23 @@ import create from 'zustand'; -import { DEFAULT_LOCALE, DEFAULT_THEME, LOCALE_CONFIG, THEME_CONFIG } from 'lib/constants'; +import { + DASHBOARD_CONFIG, + DEFAULT_LOCALE, + DEFAULT_THEME, + LOCALE_CONFIG, + THEME_CONFIG, + DEFAULT_WEBSITE_LIMIT, +} from 'lib/constants'; import { getItem } from 'lib/web'; +const defaultDashboardConfig = { + showCharts: true, + limit: DEFAULT_WEBSITE_LIMIT, +}; + const initialState = { locale: getItem(LOCALE_CONFIG) || DEFAULT_LOCALE, theme: getItem(THEME_CONFIG) || DEFAULT_THEME, + dashboard: getItem(DASHBOARD_CONFIG) || defaultDashboardConfig, shareToken: null, user: null, }; @@ -27,4 +40,8 @@ export function setUser(user) { store.setState({ user }); } +export function setDashboard(dashboard) { + store.setState({ dashboard }); +} + export default store;