mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-14 21:10:34 +01:00
Move reordering of websites onto dashboard
This commit is contained in:
parent
765add71a9
commit
137ff97c07
@ -1,3 +1,4 @@
|
|||||||
|
import { DragDropContext, Draggable, Droppable } from 'react-beautiful-dnd';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import Link from 'components/common/Link';
|
import Link from 'components/common/Link';
|
||||||
import WebsiteChart from 'components/metrics/WebsiteChart';
|
import WebsiteChart from 'components/metrics/WebsiteChart';
|
||||||
@ -7,19 +8,36 @@ import Arrow from 'assets/arrow-right.svg';
|
|||||||
import styles from './WebsiteList.module.css';
|
import styles from './WebsiteList.module.css';
|
||||||
import { orderByWebsiteMap } from 'lib/format';
|
import { orderByWebsiteMap } from 'lib/format';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import useStore from 'store/app';
|
import useStore, { setDashboard } from 'store/app';
|
||||||
|
|
||||||
const selector = state => state.dashboard;
|
const selector = state => state.dashboard;
|
||||||
|
|
||||||
export default function WebsiteList({ websites, showCharts, limit }) {
|
export default function WebsiteList({ websites, showCharts, limit }) {
|
||||||
const store = useStore(selector);
|
const store = useStore(selector);
|
||||||
const { websiteOrdering } = store;
|
const { websiteOrdering, changeOrderMode } = store;
|
||||||
|
|
||||||
const ordered = useMemo(
|
const ordered = useMemo(
|
||||||
() => orderByWebsiteMap(websites, websiteOrdering),
|
() => orderByWebsiteMap(websites, websiteOrdering),
|
||||||
[websites, websiteOrdering],
|
[websites, websiteOrdering],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const dragId = 'dashboard-website-ordering';
|
||||||
|
|
||||||
|
function handleWebsiteDrag({ destination, source }) {
|
||||||
|
if (!destination || destination.index === source.index) return;
|
||||||
|
|
||||||
|
const orderedWebsites = [...ordered];
|
||||||
|
const [removed] = orderedWebsites.splice(source.index, 1);
|
||||||
|
orderedWebsites.splice(destination.index, 0, removed);
|
||||||
|
|
||||||
|
setDashboard({
|
||||||
|
...store,
|
||||||
|
websiteOrdering: orderedWebsites
|
||||||
|
.map((i, k) => ({ [i.website_uuid]: k }))
|
||||||
|
.reduce((a, b) => ({ ...a, ...b })),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (websites.length === 0) {
|
if (websites.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
@ -40,8 +58,45 @@ export default function WebsiteList({ websites, showCharts, limit }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={changeOrderMode && styles.websiteDragActive}>
|
||||||
|
{changeOrderMode ? (
|
||||||
|
<DragDropContext onDragEnd={handleWebsiteDrag}>
|
||||||
|
<Droppable droppableId={dragId}>
|
||||||
|
{provided => (
|
||||||
|
<div {...provided.droppableProps} ref={provided.innerRef}>
|
||||||
{ordered.map(({ website_id, name, domain }, index) =>
|
{ordered.map(({ website_id, name, domain }, index) =>
|
||||||
|
index < limit ? (
|
||||||
|
<div key={website_id} className={styles.website}>
|
||||||
|
<Draggable
|
||||||
|
key={website_id}
|
||||||
|
draggableId={`${dragId}-${website_id}`}
|
||||||
|
index={index}
|
||||||
|
>
|
||||||
|
{provided => (
|
||||||
|
<div
|
||||||
|
ref={provided.innerRef}
|
||||||
|
{...provided.draggableProps}
|
||||||
|
{...provided.dragHandleProps}
|
||||||
|
>
|
||||||
|
<WebsiteChart
|
||||||
|
websiteId={website_id}
|
||||||
|
title={name}
|
||||||
|
domain={domain}
|
||||||
|
showChart={showCharts}
|
||||||
|
showLink
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Draggable>
|
||||||
|
</div>
|
||||||
|
) : null,
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Droppable>
|
||||||
|
</DragDropContext>
|
||||||
|
) : (
|
||||||
|
ordered.map(({ website_id, name, domain }, index) =>
|
||||||
index < limit ? (
|
index < limit ? (
|
||||||
<div key={website_id} className={styles.website}>
|
<div key={website_id} className={styles.website}>
|
||||||
<WebsiteChart
|
<WebsiteChart
|
||||||
@ -53,6 +108,7 @@ export default function WebsiteList({ websites, showCharts, limit }) {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : null,
|
) : null,
|
||||||
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -9,3 +9,12 @@
|
|||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.websiteDragActive {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.websiteDragActive:active {
|
||||||
|
cursor: grabbing;
|
||||||
|
}
|
||||||
|
@ -3,6 +3,9 @@ import { FormattedMessage } from 'react-intl';
|
|||||||
import MenuButton from 'components/common/MenuButton';
|
import MenuButton from 'components/common/MenuButton';
|
||||||
import Gear from 'assets/gear.svg';
|
import Gear from 'assets/gear.svg';
|
||||||
import useStore, { setDashboard } from 'store/app';
|
import useStore, { setDashboard } from 'store/app';
|
||||||
|
import Button from 'components/common/Button';
|
||||||
|
import Check from 'assets/check.svg';
|
||||||
|
import styles from './DashboardSettingsButton.module.css';
|
||||||
|
|
||||||
const selector = state => state.dashboard;
|
const selector = state => state.dashboard;
|
||||||
|
|
||||||
@ -14,14 +17,41 @@ export default function DashboardSettingsButton() {
|
|||||||
label: <FormattedMessage id="message.toggle-charts" defaultMessage="Toggle charts" />,
|
label: <FormattedMessage id="message.toggle-charts" defaultMessage="Toggle charts" />,
|
||||||
value: 'charts',
|
value: 'charts',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: <FormattedMessage id="message.change-order" defaultMessage="Change order" />,
|
||||||
|
value: 'order',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
function handleSelect(value) {
|
function handleSelect(value) {
|
||||||
if (value === 'charts') {
|
if (value === 'charts') {
|
||||||
setDashboard({ ...settings, showCharts: !settings.showCharts });
|
setDashboard({ ...settings, showCharts: !settings.showCharts });
|
||||||
}
|
}
|
||||||
|
if (value === 'order') {
|
||||||
|
setDashboard({ ...settings, changeOrderMode: !settings.changeOrderMode });
|
||||||
|
}
|
||||||
//setDashboard(value);
|
//setDashboard(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleExitChangeOrderMode() {
|
||||||
|
setDashboard({ ...settings, changeOrderMode: !settings.changeOrderMode });
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetWebsiteOrder() {
|
||||||
|
setDashboard({ ...settings, websiteOrdering: {} });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.changeOrderMode)
|
||||||
|
return (
|
||||||
|
<div className={styles.buttonGroup}>
|
||||||
|
<Button onClick={resetWebsiteOrder} size="small">
|
||||||
|
<FormattedMessage id="label.reset-order" defaultMessage="Reset order" />
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleExitChangeOrderMode} size="small" icon={<Check />}>
|
||||||
|
<FormattedMessage id="label.done" defaultMessage="Done" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
return <MenuButton icon={<Gear />} options={menuOptions} onSelect={handleSelect} hideLabel />;
|
return <MenuButton icon={<Gear />} options={menuOptions} onSelect={handleSelect} hideLabel />;
|
||||||
}
|
}
|
||||||
|
5
components/settings/DashboardSettingsButton.module.css
Normal file
5
components/settings/DashboardSettingsButton.module.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.buttonGroup {
|
||||||
|
display: flex;
|
||||||
|
place-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
@ -10,6 +10,7 @@
|
|||||||
"label.back": "Back",
|
"label.back": "Back",
|
||||||
"label.cancel": "Cancel",
|
"label.cancel": "Cancel",
|
||||||
"label.change-password": "Change password",
|
"label.change-password": "Change password",
|
||||||
|
"label.change-order": "Change order",
|
||||||
"label.confirm-password": "Confirm password",
|
"label.confirm-password": "Confirm password",
|
||||||
"label.copy-to-clipboard": "Copy to clipboard",
|
"label.copy-to-clipboard": "Copy to clipboard",
|
||||||
"label.current-password": "Current password",
|
"label.current-password": "Current password",
|
||||||
@ -22,6 +23,7 @@
|
|||||||
"label.delete-website": "Delete website",
|
"label.delete-website": "Delete website",
|
||||||
"label.dismiss": "Dismiss",
|
"label.dismiss": "Dismiss",
|
||||||
"label.domain": "Domain",
|
"label.domain": "Domain",
|
||||||
|
"label.done": "Done",
|
||||||
"label.edit": "Edit",
|
"label.edit": "Edit",
|
||||||
"label.edit-account": "Edit account",
|
"label.edit-account": "Edit account",
|
||||||
"label.edit-website": "Edit website",
|
"label.edit-website": "Edit website",
|
||||||
|
@ -13,6 +13,7 @@ export const defaultDashboardConfig = {
|
|||||||
showCharts: true,
|
showCharts: true,
|
||||||
limit: DEFAULT_WEBSITE_LIMIT,
|
limit: DEFAULT_WEBSITE_LIMIT,
|
||||||
websiteOrdering: {},
|
websiteOrdering: {},
|
||||||
|
changeOrderMode: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
|
Loading…
Reference in New Issue
Block a user