mirror of
https://github.com/kremalicious/umami.git
synced 2024-11-26 12:29:05 +01:00
Updated profile settings. Refactored locale saving.
This commit is contained in:
parent
814589f6a5
commit
7f598fa84d
@ -1,12 +1,13 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import Head from 'next/head';
|
||||
import Globe from 'assets/globe.svg';
|
||||
import useDocumentClick from 'hooks/useDocumentClick';
|
||||
import Menu from './Menu';
|
||||
import Button from './Button';
|
||||
import { menuOptions } from 'lib/lang';
|
||||
import { setItem } from 'lib/web';
|
||||
import useLocale from 'hooks/useLocale';
|
||||
import useDocumentClick from 'hooks/useDocumentClick';
|
||||
import Globe from 'assets/globe.svg';
|
||||
import styles from './LanguageButton.module.css';
|
||||
import useLocale from '../../hooks/useLocale';
|
||||
|
||||
export default function LanguageButton({ menuPosition = 'bottom', menuAlign = 'left' }) {
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
@ -16,7 +17,7 @@ export default function LanguageButton({ menuPosition = 'bottom', menuAlign = 'l
|
||||
|
||||
function handleSelect(value) {
|
||||
setLocale(value);
|
||||
window.localStorage.setItem('locale', value);
|
||||
setItem('umami.locale', value);
|
||||
setShowMenu(false);
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,8 @@ export default function WebsiteChart({
|
||||
const dateRange = useDateRange(websiteId);
|
||||
const { startDate, endDate, unit, value, modified } = dateRange;
|
||||
|
||||
console.log({ websiteId, dateRange });
|
||||
|
||||
const { data } = useFetch(
|
||||
`/api/website/${websiteId}/pageviews`,
|
||||
{
|
||||
|
@ -1,24 +1,39 @@
|
||||
import React, { useState } from 'react';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import PageHeader from 'components/layout/PageHeader';
|
||||
import Button from 'components/common/Button';
|
||||
import Modal from 'components/common/Modal';
|
||||
import Toast from 'components/common/Toast';
|
||||
import ChangePasswordForm from 'components/forms/ChangePasswordForm';
|
||||
import DateFilter from 'components/common/DateFilter';
|
||||
import Dots from 'assets/ellipsis-h.svg';
|
||||
import { getTimezone } from 'lib/date';
|
||||
import { setItem } from 'lib/web';
|
||||
import { useDateRange } from 'hooks/useDateRange';
|
||||
import { setDateRange } from 'redux/actions/websites';
|
||||
import styles from './ProfileSettings.module.css';
|
||||
|
||||
export default function ProfileSettings() {
|
||||
const dispatch = useDispatch();
|
||||
const user = useSelector(state => state.user);
|
||||
const [changePassword, setChangePassword] = useState(false);
|
||||
const [message, setMessage] = useState();
|
||||
const { user_id } = user;
|
||||
const timezone = getTimezone();
|
||||
const dateRange = useDateRange(0);
|
||||
const { startDate, endDate, value } = dateRange;
|
||||
|
||||
function handleSave() {
|
||||
setChangePassword(false);
|
||||
setMessage(<FormattedMessage id="message.save-success" defaultMessage="Saved successfully." />);
|
||||
}
|
||||
|
||||
function handleDateChange(values) {
|
||||
setItem(`umami.date-range`, values);
|
||||
dispatch(setDateRange(0, values));
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader>
|
||||
@ -36,6 +51,21 @@ export default function ProfileSettings() {
|
||||
<FormattedMessage id="label.username" defaultMessage="Username" />
|
||||
</dt>
|
||||
<dd>{user.username}</dd>
|
||||
<dt>
|
||||
<FormattedMessage id="label.timezone" defaultMessage="Timezone" />
|
||||
</dt>
|
||||
<dd>{timezone}</dd>
|
||||
<dt>
|
||||
<FormattedMessage id="label.default-date-range" defaultMessage="Default date range" />
|
||||
</dt>
|
||||
<dd className={styles.date}>
|
||||
<DateFilter
|
||||
value={value}
|
||||
startDate={startDate}
|
||||
endDate={endDate}
|
||||
onChange={handleDateChange}
|
||||
/>
|
||||
</dd>
|
||||
</dl>
|
||||
{changePassword && (
|
||||
<Modal
|
||||
|
3
components/settings/ProfileSettings.module.css
Normal file
3
components/settings/ProfileSettings.module.css
Normal file
@ -0,0 +1,3 @@
|
||||
.date {
|
||||
display: flex;
|
||||
}
|
@ -1,8 +1,18 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { parseISO } from 'date-fns';
|
||||
import { getDateRange } from 'lib/date';
|
||||
import { getItem } from 'lib/web';
|
||||
|
||||
export function useDateRange(websiteId, defaultDateRange = '7day') {
|
||||
const globalDefault = getItem('umami.date-range');
|
||||
|
||||
if (globalDefault) {
|
||||
globalDefault.startDate = parseISO(globalDefault.startDate);
|
||||
globalDefault.endDate = parseISO(globalDefault.endDate);
|
||||
}
|
||||
|
||||
return useSelector(
|
||||
state => state.websites[websiteId]?.dateRange || getDateRange(defaultDateRange),
|
||||
state =>
|
||||
state.websites[websiteId]?.dateRange || globalDefault || getDateRange(defaultDateRange),
|
||||
);
|
||||
}
|
||||
|
15
lib/web.js
15
lib/web.js
@ -19,7 +19,7 @@ export const apiRequest = (method, url, body) =>
|
||||
return null;
|
||||
});
|
||||
|
||||
function parseQuery(url, params = {}) {
|
||||
const parseQuery = (url, params = {}) => {
|
||||
const query = Object.keys(params).reduce((values, key) => {
|
||||
if (params[key] !== undefined) {
|
||||
return values.concat(`${key}=${encodeURIComponent(params[key])}`);
|
||||
@ -27,7 +27,7 @@ function parseQuery(url, params = {}) {
|
||||
return values;
|
||||
}, []);
|
||||
return query.length ? `${url}?${query.join('&')}` : url;
|
||||
}
|
||||
};
|
||||
|
||||
export const get = (url, params) => apiRequest('get', parseQuery(url, params));
|
||||
|
||||
@ -62,3 +62,14 @@ export const doNotTrack = () => {
|
||||
|
||||
return dnt === true || dnt === 1 || dnt === 'yes' || dnt === '1';
|
||||
};
|
||||
|
||||
export const setItem = (key, data, session) => {
|
||||
if (typeof window !== 'undefined') {
|
||||
(session ? sessionStorage : localStorage).setItem(key, JSON.stringify(data));
|
||||
}
|
||||
};
|
||||
|
||||
export const getItem = (key, session) =>
|
||||
typeof window !== 'undefined'
|
||||
? JSON.parse((session ? sessionStorage : localStorage).getItem(key))
|
||||
: null;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import { IntlProvider } from 'react-intl';
|
||||
import { Provider } from 'react-redux';
|
||||
import { useStore } from 'redux/store';
|
||||
@ -9,17 +9,10 @@ import 'styles/bootstrap-grid.css';
|
||||
import 'styles/index.css';
|
||||
|
||||
const Intl = ({ children }) => {
|
||||
const [locale, setLocale] = useLocale();
|
||||
const [locale] = useLocale();
|
||||
|
||||
const Wrapper = ({ children }) => <span className={locale}>{children}</span>;
|
||||
|
||||
useEffect(() => {
|
||||
const saved = localStorage.getItem('locale');
|
||||
if (saved) {
|
||||
setLocale(saved);
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<IntlProvider locale={locale} messages={messages[locale]} textComponent={Wrapper}>
|
||||
{children}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import { getItem } from 'lib/web';
|
||||
|
||||
const app = createSlice({
|
||||
name: 'app',
|
||||
initialState: { locale: 'en-US' },
|
||||
initialState: { locale: getItem('umami.locale') || 'en-US' },
|
||||
reducers: {
|
||||
updateApp(state, action) {
|
||||
state = action.payload;
|
||||
|
@ -36,17 +36,6 @@ h6 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
#__next {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#__modals {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
select {
|
||||
@ -87,16 +76,28 @@ label:empty {
|
||||
|
||||
dt {
|
||||
font-weight: 600;
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0 0 10px 0;
|
||||
margin: 0 0 30px 0;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
#__next {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#__modals {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user