mirror of https://github.com/mue/mue.git
refactor(widgets): Move to new layout of widgets and options
This commit is contained in:
parent
9a9d7bb136
commit
7e78465406
|
@ -76,4 +76,5 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(AddModal);
|
const MemoizedAddModal = memo(AddModal);
|
||||||
|
export { MemoizedAddModal as default, MemoizedAddModal as AddModal}
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './AddModal';
|
|
@ -1,3 +1,4 @@
|
||||||
export * from './Button';
|
export * from './Button';
|
||||||
export * from './Tooltip';
|
export * from './Tooltip';
|
||||||
export * from './ShareModal';
|
export * from './ShareModal';
|
||||||
|
export * from './AddModal';
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useState, memo } from 'react';
|
||||||
import Modal from 'react-modal';
|
import Modal from 'react-modal';
|
||||||
import { MdAddLink } from 'react-icons/md';
|
import { MdAddLink } from 'react-icons/md';
|
||||||
|
|
||||||
import AddModal from './quicklinks/AddModal';
|
import { AddModal } from 'components/Elements/AddModal';
|
||||||
|
|
||||||
import Checkbox from '../../../../../components/Form/Settings/Checkbox/Checkbox';
|
import Checkbox from '../../../../../components/Form/Settings/Checkbox/Checkbox';
|
||||||
import Dropdown from '../../../../../components/Form/Settings/Dropdown/Dropdown';
|
import Dropdown from '../../../../../components/Form/Settings/Dropdown/Dropdown';
|
||||||
|
@ -14,7 +14,7 @@ import { Button } from 'components/Elements';
|
||||||
import { Row, Content, Action } from '../../../../../components/Layout/Settings/Item/SettingsItem';
|
import { Row, Content, Action } from '../../../../../components/Layout/Settings/Item/SettingsItem';
|
||||||
import { Header } from 'components/Layout/Settings';
|
import { Header } from 'components/Layout/Settings';
|
||||||
import { getTitleFromUrl, isValidUrl } from 'utils/links';
|
import { getTitleFromUrl, isValidUrl } from 'utils/links';
|
||||||
import QuickLink from './quicklinks/QuickLink';
|
import { QuickLinks } from 'features/widgets/quicklinks';
|
||||||
|
|
||||||
function Navbar() {
|
function Navbar() {
|
||||||
const [showRefreshOptions, setShowRefreshOptions] = useState(
|
const [showRefreshOptions, setShowRefreshOptions] = useState(
|
||||||
|
@ -240,7 +240,7 @@ function Navbar() {
|
||||||
|
|
||||||
<div className="messagesContainer">
|
<div className="messagesContainer">
|
||||||
{appsModalInfo.items.map((item, i) => (
|
{appsModalInfo.items.map((item, i) => (
|
||||||
<QuickLink
|
<QuickLinks
|
||||||
key={i}
|
key={i}
|
||||||
item={item}
|
item={item}
|
||||||
startEditLink={() => startEditLink(item)}
|
startEditLink={() => startEditLink(item)}
|
||||||
|
|
|
@ -270,4 +270,4 @@ export default class QuickLinks extends PureComponent {
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,68 +0,0 @@
|
||||||
import variables from 'config/variables';
|
|
||||||
|
|
||||||
import { MdEdit, MdCancel } from 'react-icons/md';
|
|
||||||
|
|
||||||
const QuickLink = ({ item, deleteLink, startEditLink }) => {
|
|
||||||
let target,
|
|
||||||
rel = null;
|
|
||||||
if (localStorage.getItem('quicklinksnewtab') === 'true') {
|
|
||||||
target = '_blank';
|
|
||||||
rel = 'noopener noreferrer';
|
|
||||||
}
|
|
||||||
|
|
||||||
const useText = localStorage.getItem('quicklinksText') === 'true';
|
|
||||||
|
|
||||||
if (useText) {
|
|
||||||
return (
|
|
||||||
<a
|
|
||||||
className="quicklinkstext"
|
|
||||||
onContextMenu={(e) => deleteLink(item.key, e)}
|
|
||||||
href={item.url}
|
|
||||||
target={target}
|
|
||||||
rel={rel}
|
|
||||||
draggable={false}
|
|
||||||
>
|
|
||||||
{item.name}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const img =
|
|
||||||
item.icon ||
|
|
||||||
'https://icon.horse/icon/ ' + item.url.replace('https://', '').replace('http://', '');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="messageMap">
|
|
||||||
<div className="icon">
|
|
||||||
<img
|
|
||||||
src={img}
|
|
||||||
alt={item.name}
|
|
||||||
draggable={false}
|
|
||||||
style={{ height: '30px', width: '30px' }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="messageText">
|
|
||||||
<div className="title">{item.name}</div>
|
|
||||||
<div className="subtitle">
|
|
||||||
<a className="quicklinknostyle" target="_blank" rel="noopener noreferrer" href={item.url}>
|
|
||||||
{item.url}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div className="messageAction">
|
|
||||||
<button className="deleteButton" onClick={() => startEditLink(item)}>
|
|
||||||
{variables.getMessage('modals.main.settings.sections.quicklinks.edit')}
|
|
||||||
<MdEdit />
|
|
||||||
</button>
|
|
||||||
<button className="deleteButton" onClick={(e) => deleteLink(item.key, e)}>
|
|
||||||
{variables.getMessage('modals.main.marketplace.product.buttons.remove')}
|
|
||||||
<MdCancel />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default QuickLink;
|
|
|
@ -5,15 +5,15 @@ import Tabs from './backend/Tabs';
|
||||||
|
|
||||||
import Overview from '../settings/sections/Overview';
|
import Overview from '../settings/sections/Overview';
|
||||||
import Navbar from '../settings/sections/Navbar';
|
import Navbar from '../settings/sections/Navbar';
|
||||||
import Greeting from '../settings/sections/Greeting';
|
import { GreetingOptions } from 'features/widgets/greeting';
|
||||||
import Time from '../settings/sections/Time';
|
import Time from '../settings/sections/Time';
|
||||||
import QuickLinks from '../settings/sections/QuickLinks';
|
import { QuickLinksOptions } from 'features/widgets/quicklinks';
|
||||||
import Quote from '../settings/sections/Quote';
|
import Quote from '../settings/sections/Quote';
|
||||||
import Date from '../settings/sections/Date';
|
import Date from '../settings/sections/Date';
|
||||||
import Message from '../settings/sections/Message';
|
import { MessageOptions } from 'features/widgets/message';
|
||||||
import Background from '../settings/sections/background/Background';
|
import Background from '../settings/sections/background/Background';
|
||||||
import Search from '../settings/sections/Search';
|
import { SearchOptions } from 'features/widgets/search';
|
||||||
import Weather from '../settings/sections/Weather';
|
import { WeatherOptions } from 'features/widgets/weather';
|
||||||
import Appearance from '../settings/sections/Appearance';
|
import Appearance from '../settings/sections/Appearance';
|
||||||
import Language from '../settings/sections/Language';
|
import Language from '../settings/sections/Language';
|
||||||
import Advanced from '../settings/sections/Advanced';
|
import Advanced from '../settings/sections/Advanced';
|
||||||
|
@ -22,98 +22,37 @@ import Experimental from '../settings/sections/Experimental';
|
||||||
import Changelog from '../settings/sections/Changelog';
|
import Changelog from '../settings/sections/Changelog';
|
||||||
import About from '../settings/sections/About';
|
import About from '../settings/sections/About';
|
||||||
|
|
||||||
|
const sections = [
|
||||||
|
{ label: 'modals.main.marketplace.product.overview', name: 'order', component: Overview },
|
||||||
|
{ label: 'modals.main.settings.sections.appearance.navbar.title', name: 'navbar', component: Navbar },
|
||||||
|
{ label: 'modals.main.settings.sections.greeting.title', name: 'greeting', component: GreetingOptions },
|
||||||
|
{ label: 'modals.main.settings.sections.time.title', name: 'time', component: Time },
|
||||||
|
{ label: 'modals.main.settings.sections.quicklinks.title', name: 'quicklinks', component: QuickLinksOptions },
|
||||||
|
{ label: 'modals.main.settings.sections.quote.title', name: 'quote', component: Quote },
|
||||||
|
{ label: 'modals.main.settings.sections.date.title', name: 'date', component: Date },
|
||||||
|
{ label: 'modals.main.settings.sections.message.title', name: 'message', component: MessageOptions },
|
||||||
|
{ label: 'modals.main.settings.sections.background.title', name: 'background', component: Background },
|
||||||
|
{ label: 'modals.main.settings.sections.search.title', name: 'search', component: SearchOptions },
|
||||||
|
{ label: 'modals.main.settings.sections.weather.title', name: 'weather', component: WeatherOptions },
|
||||||
|
{ label: 'modals.main.settings.sections.appearance.title', name: 'appearance', component: Appearance },
|
||||||
|
{ label: 'modals.main.settings.sections.language.title', name: 'language', component: Language },
|
||||||
|
{ label: 'modals.main.settings.sections.advanced.title', name: 'advanced', component: Advanced },
|
||||||
|
{ label: 'modals.main.settings.sections.stats.title', name: 'stats', component: Stats },
|
||||||
|
{ label: 'modals.main.settings.sections.experimental.title', name: 'experimental', component: Experimental },
|
||||||
|
{ label: 'modals.main.settings.sections.changelog.title', name: 'changelog', component: Changelog },
|
||||||
|
{ label: 'modals.main.settings.sections.about.title', name: 'about', component: About },
|
||||||
|
];
|
||||||
|
|
||||||
function Settings(props) {
|
function Settings(props) {
|
||||||
return (
|
return (
|
||||||
<Tabs changeTab={(type) => props.changeTab(type)} current="settings">
|
<Tabs changeTab={(type) => props.changeTab(type)} current="settings">
|
||||||
<div label={variables.getMessage('modals.main.marketplace.product.overview')} name="order">
|
{sections.map(({ label, name, component: Component }) => (
|
||||||
<Overview />
|
<div key={name} label={variables.getMessage(label)} name={name}>
|
||||||
</div>
|
<Component />
|
||||||
<div
|
</div>
|
||||||
label={variables.getMessage('modals.main.settings.sections.appearance.navbar.title')}
|
))}
|
||||||
name="navbar"
|
|
||||||
>
|
|
||||||
<Navbar />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.greeting.title')}
|
|
||||||
name="greeting"
|
|
||||||
>
|
|
||||||
<Greeting />
|
|
||||||
</div>
|
|
||||||
<div label={variables.getMessage('modals.main.settings.sections.time.title')} name="time">
|
|
||||||
<Time />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.quicklinks.title')}
|
|
||||||
name="quicklinks"
|
|
||||||
>
|
|
||||||
<QuickLinks />
|
|
||||||
</div>
|
|
||||||
<div label={variables.getMessage('modals.main.settings.sections.quote.title')} name="quote">
|
|
||||||
<Quote />
|
|
||||||
</div>
|
|
||||||
<div label={variables.getMessage('modals.main.settings.sections.date.title')} name="date">
|
|
||||||
<Date />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.message.title')}
|
|
||||||
name="message"
|
|
||||||
>
|
|
||||||
<Message />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.background.title')}
|
|
||||||
name="background"
|
|
||||||
>
|
|
||||||
<Background />
|
|
||||||
</div>
|
|
||||||
<div label={variables.getMessage('modals.main.settings.sections.search.title')} name="search">
|
|
||||||
<Search />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.weather.title')}
|
|
||||||
name="weather"
|
|
||||||
>
|
|
||||||
<Weather />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.appearance.title')}
|
|
||||||
name="appearance"
|
|
||||||
>
|
|
||||||
<Appearance />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.language.title')}
|
|
||||||
name="language"
|
|
||||||
>
|
|
||||||
<Language />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.advanced.title')}
|
|
||||||
name="advanced"
|
|
||||||
>
|
|
||||||
<Advanced />
|
|
||||||
</div>
|
|
||||||
<div label={variables.getMessage('modals.main.settings.sections.stats.title')} name="stats">
|
|
||||||
<Stats />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.experimental.title')}
|
|
||||||
name="experimental"
|
|
||||||
>
|
|
||||||
<Experimental />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
label={variables.getMessage('modals.main.settings.sections.changelog.title')}
|
|
||||||
name="changelog"
|
|
||||||
>
|
|
||||||
<Changelog />
|
|
||||||
</div>
|
|
||||||
<div label={variables.getMessage('modals.main.settings.sections.about.title')} name="about">
|
|
||||||
<About />
|
|
||||||
</div>
|
|
||||||
</Tabs>
|
</Tabs>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default memo(Settings);
|
export default memo(Settings);
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './options';
|
||||||
|
export * from './Greeting';
|
|
@ -0,0 +1,100 @@
|
||||||
|
import variables from 'config/variables';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Layout/Settings';
|
||||||
|
import { Checkbox, Switch, Text } from 'components/Form/Settings';
|
||||||
|
|
||||||
|
const GreetingOptions = () => {
|
||||||
|
const [birthday, setBirthday] = useState(
|
||||||
|
new Date(localStorage.getItem('birthday')) || new Date(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const changeDate = (e) => {
|
||||||
|
const newDate = e.target.value ? new Date(e.target.value) : new Date();
|
||||||
|
localStorage.setItem('birthday', newDate);
|
||||||
|
setBirthday(newDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GREETING_SECTION = 'modals.main.settings.sections.greeting';
|
||||||
|
|
||||||
|
const AdditionalOptions = () => {
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Content
|
||||||
|
title={variables.getMessage('modals.main.settings.additional_settings')}
|
||||||
|
subtitle={variables.getMessage(`${GREETING_SECTION}.additional`)}
|
||||||
|
/>
|
||||||
|
<Action>
|
||||||
|
<Checkbox
|
||||||
|
name="events"
|
||||||
|
text={variables.getMessage(`${GREETING_SECTION}.events`)}
|
||||||
|
category="greeting"
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
name="defaultGreetingMessage"
|
||||||
|
text={variables.getMessage(`${GREETING_SECTION}.default`)}
|
||||||
|
category="greeting"
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
title={variables.getMessage(`${GREETING_SECTION}.name`)}
|
||||||
|
name="greetingName"
|
||||||
|
category="greeting"
|
||||||
|
/>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const BirthdayOptions = () => {
|
||||||
|
return (
|
||||||
|
<Row final={true}>
|
||||||
|
<Content
|
||||||
|
title={variables.getMessage(`${GREETING_SECTION}.birthday`)}
|
||||||
|
subtitle={variables.getMessage(
|
||||||
|
'modals.main.settings.sections.greeting.birthday_subtitle',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Action>
|
||||||
|
<Switch
|
||||||
|
name="birthdayenabled"
|
||||||
|
text={variables.getMessage('modals.main.settings.enabled')}
|
||||||
|
category="greeting"
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
name="birthdayage"
|
||||||
|
text={variables.getMessage(`${GREETING_SECTION}.birthday_age`)}
|
||||||
|
category="greeting"
|
||||||
|
/>
|
||||||
|
<p style={{ marginRight: 'auto' }}>
|
||||||
|
{variables.getMessage(`${GREETING_SECTION}.birthday_date`)}
|
||||||
|
</p>
|
||||||
|
<input
|
||||||
|
type="date"
|
||||||
|
onChange={changeDate}
|
||||||
|
value={birthday.toISOString().substring(0, 10)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header
|
||||||
|
title={variables.getMessage(`${GREETING_SECTION}.title`)}
|
||||||
|
setting="greeting"
|
||||||
|
category="greeting"
|
||||||
|
element=".greeting"
|
||||||
|
zoomSetting="zoomGreeting"
|
||||||
|
visibilityToggle={true}
|
||||||
|
/>
|
||||||
|
<PreferencesWrapper setting="greeting" zoomSetting="zoomGreeting" visibilityToggle={true}>
|
||||||
|
<AdditionalOptions />
|
||||||
|
{BirthdayOptions()}
|
||||||
|
</PreferencesWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { GreetingOptions as default, GreetingOptions };
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './GreetingOptions';
|
|
@ -42,4 +42,4 @@ const Message = () => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Message;
|
export { Message as default, Message };
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './Message';
|
||||||
|
export * from './options';
|
|
@ -8,7 +8,7 @@ import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Lay
|
||||||
import { Button } from 'components/Elements';
|
import { Button } from 'components/Elements';
|
||||||
import EventBus from 'utils/eventbus';
|
import EventBus from 'utils/eventbus';
|
||||||
|
|
||||||
export default class Message extends PureComponent {
|
class MessageOptions extends PureComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -141,3 +141,5 @@ export default class Message extends PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { MessageOptions as default, MessageOptions };
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './MessageOptions';
|
|
@ -5,7 +5,7 @@ import EventBus from 'utils/eventbus';
|
||||||
|
|
||||||
import './quicklinks.scss';
|
import './quicklinks.scss';
|
||||||
|
|
||||||
export default class QuickLinks extends PureComponent {
|
class QuickLinks extends PureComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -119,3 +119,5 @@ export default class QuickLinks extends PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { QuickLinks as default, QuickLinks };
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './options';
|
||||||
|
export * from './QuickLinks';
|
|
@ -0,0 +1,275 @@
|
||||||
|
import variables from 'config/variables';
|
||||||
|
import { PureComponent, createRef } from 'react';
|
||||||
|
import { MdAddLink, MdLinkOff } from 'react-icons/md';
|
||||||
|
import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Layout/Settings';
|
||||||
|
import { Checkbox, Dropdown } from 'components/Form/Settings';
|
||||||
|
import { Button } from 'components/Elements';
|
||||||
|
import Modal from 'react-modal';
|
||||||
|
|
||||||
|
import { AddModal } from 'components/Elements/AddModal';
|
||||||
|
|
||||||
|
import EventBus from 'utils/eventbus';
|
||||||
|
import { QuickLink } from '../QuickLinks';
|
||||||
|
import { getTitleFromUrl, isValidUrl } from 'utils/links';
|
||||||
|
|
||||||
|
class QuickLinksOptions extends PureComponent {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
items: JSON.parse(localStorage.getItem('quicklinks')),
|
||||||
|
showAddModal: false,
|
||||||
|
urlError: '',
|
||||||
|
iconError: '',
|
||||||
|
edit: false,
|
||||||
|
editData: '',
|
||||||
|
};
|
||||||
|
this.quicklinksContainer = createRef();
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteLink(key, event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// remove link from array
|
||||||
|
const data = JSON.parse(localStorage.getItem('quicklinks')).filter((i) => i.key !== key);
|
||||||
|
|
||||||
|
localStorage.setItem('quicklinks', JSON.stringify(data));
|
||||||
|
this.setState({
|
||||||
|
items: data,
|
||||||
|
});
|
||||||
|
|
||||||
|
variables.stats.postEvent('feature', 'Quicklink delete');
|
||||||
|
}
|
||||||
|
|
||||||
|
async addLink(name, url, icon) {
|
||||||
|
const data = JSON.parse(localStorage.getItem('quicklinks'));
|
||||||
|
|
||||||
|
if (!url.startsWith('http://') && !url.startsWith('https://')) {
|
||||||
|
url = 'http://' + url;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.length <= 0 || isValidUrl(url) === false) {
|
||||||
|
return this.setState({
|
||||||
|
urlError: variables.getMessage('widgets.quicklinks.url_error'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (icon.length > 0 && isValidUrl(icon) === false) {
|
||||||
|
return this.setState({
|
||||||
|
iconError: variables.getMessage('widgets.quicklinks.url_error'),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
data.push({
|
||||||
|
name: name || (await getTitleFromUrl(url)),
|
||||||
|
url,
|
||||||
|
icon: icon || '',
|
||||||
|
key: Math.random().toString(36).substring(7) + 1,
|
||||||
|
});
|
||||||
|
|
||||||
|
localStorage.setItem('quicklinks', JSON.stringify(data));
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
items: data,
|
||||||
|
showAddModal: false,
|
||||||
|
urlError: '',
|
||||||
|
iconError: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
variables.stats.postEvent('feature', 'Quicklink add');
|
||||||
|
}
|
||||||
|
|
||||||
|
startEditLink(data) {
|
||||||
|
this.setState({
|
||||||
|
edit: true,
|
||||||
|
editData: data,
|
||||||
|
showAddModal: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async editLink(og, name, url, icon) {
|
||||||
|
const data = JSON.parse(localStorage.getItem('quicklinks'));
|
||||||
|
const dataobj = data.find((i) => i.key === og.key);
|
||||||
|
dataobj.name = name || (await getTitleFromUrl(url));
|
||||||
|
dataobj.url = url;
|
||||||
|
dataobj.icon = icon || '';
|
||||||
|
|
||||||
|
localStorage.setItem('quicklinks', JSON.stringify(data));
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
items: data,
|
||||||
|
showAddModal: false,
|
||||||
|
edit: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
EventBus.on('refresh', (data) => {
|
||||||
|
if (data === 'quicklinks') {
|
||||||
|
if (localStorage.getItem('quicklinksenabled') === 'false') {
|
||||||
|
return (this.quicklinksContainer.current.style.display = 'none');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.quicklinksContainer.current.style.display = 'block';
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
items: JSON.parse(localStorage.getItem('quicklinks')),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
EventBus.off('refresh');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const QUICKLINKS_SECTION = 'modals.main.settings.sections.quicklinks';
|
||||||
|
|
||||||
|
const AdditionalSettings = () => {
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Content
|
||||||
|
title={variables.getMessage('modals.main.settings.additional_settings')}
|
||||||
|
subtitle={variables.getMessage(`${QUICKLINKS_SECTION}.additional`)}
|
||||||
|
/>
|
||||||
|
<Action>
|
||||||
|
<Checkbox
|
||||||
|
name="quicklinksnewtab"
|
||||||
|
text={variables.getMessage(`${QUICKLINKS_SECTION}.open_new`)}
|
||||||
|
category="quicklinks"
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
name="quicklinkstooltip"
|
||||||
|
text={variables.getMessage(`${QUICKLINKS_SECTION}.tooltip`)}
|
||||||
|
category="quicklinks"
|
||||||
|
/>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const StylingOptions = () => {
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Content
|
||||||
|
title={variables.getMessage(`${QUICKLINKS_SECTION}.styling`)}
|
||||||
|
subtitle={variables.getMessage(
|
||||||
|
'modals.main.settings.sections.quicklinks.styling_description',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Action>
|
||||||
|
<Dropdown
|
||||||
|
label={variables.getMessage(`${QUICKLINKS_SECTION}.style`)}
|
||||||
|
name="quickLinksStyle"
|
||||||
|
category="quicklinks"
|
||||||
|
items={[
|
||||||
|
{
|
||||||
|
value: 'icon',
|
||||||
|
text: variables.getMessage(`${QUICKLINKS_SECTION}.options.icon`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'text',
|
||||||
|
text: variables.getMessage(`${QUICKLINKS_SECTION}.options.text_only`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 'metro',
|
||||||
|
text: variables.getMessage(`${QUICKLINKS_SECTION}.options.metro`),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const AddLink = () => {
|
||||||
|
return (
|
||||||
|
<Row final={true}>
|
||||||
|
<Content title={variables.getMessage(`${QUICKLINKS_SECTION}.title`)} />
|
||||||
|
<Action>
|
||||||
|
<Button
|
||||||
|
type="settings"
|
||||||
|
onClick={() => this.setState({ showAddModal: true })}
|
||||||
|
icon={<MdAddLink />}
|
||||||
|
label={variables.getMessage(`${QUICKLINKS_SECTION}.add_link`)}
|
||||||
|
/>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header
|
||||||
|
title={variables.getMessage(`${QUICKLINKS_SECTION}.title`)}
|
||||||
|
setting="quicklinksenabled"
|
||||||
|
category="quicklinks"
|
||||||
|
element=".quicklinks-container"
|
||||||
|
zoomSetting="zoomQuicklinks"
|
||||||
|
visibilityToggle={true}
|
||||||
|
/>
|
||||||
|
<PreferencesWrapper
|
||||||
|
setting="quicklinksenabled"
|
||||||
|
visibilityToggle={true}
|
||||||
|
zoomSetting="zoomQuicklinks"
|
||||||
|
>
|
||||||
|
<AdditionalSettings />
|
||||||
|
<StylingOptions />
|
||||||
|
<AddLink />
|
||||||
|
|
||||||
|
{this.state.items.length === 0 && (
|
||||||
|
<div className="photosEmpty">
|
||||||
|
<div className="emptyNewMessage">
|
||||||
|
<MdLinkOff />
|
||||||
|
<span className="title">
|
||||||
|
{variables.getMessage(`${QUICKLINKS_SECTION}.no_quicklinks`)}
|
||||||
|
</span>
|
||||||
|
<span className="subtitle">
|
||||||
|
{variables.getMessage('modals.main.settings.sections.message.add_some')}
|
||||||
|
</span>
|
||||||
|
<Button
|
||||||
|
type="settings"
|
||||||
|
onClick={() => this.setState({ showAddModal: true })}
|
||||||
|
icon={<MdAddLink />}
|
||||||
|
label={variables.getMessage(`${QUICKLINKS_SECTION}.add_link`)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</PreferencesWrapper>
|
||||||
|
|
||||||
|
<div className="messagesContainer" ref={this.quicklinksContainer}>
|
||||||
|
{this.state.items.map((item, i) => (
|
||||||
|
<QuickLink
|
||||||
|
key={i}
|
||||||
|
item={item}
|
||||||
|
startEditLink={() => this.startEditLink(item)}
|
||||||
|
deleteLink={(key, e) => this.deleteLink(key, e)}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Modal
|
||||||
|
closeTimeoutMS={100}
|
||||||
|
onRequestClose={() => this.setState({ showAddModal: false, urlError: '', iconError: '' })}
|
||||||
|
isOpen={this.state.showAddModal}
|
||||||
|
className="Modal resetmodal mainModal"
|
||||||
|
overlayClassName="Overlay resetoverlay"
|
||||||
|
ariaHideApp={false}
|
||||||
|
>
|
||||||
|
<AddModal
|
||||||
|
urlError={this.state.urlError}
|
||||||
|
addLink={(name, url, icon) => this.addLink(name, url, icon)}
|
||||||
|
editLink={(og, name, url, icon) => this.editLink(og, name, url, icon)}
|
||||||
|
edit={this.state.edit}
|
||||||
|
editData={this.state.editData}
|
||||||
|
closeModal={() =>
|
||||||
|
this.setState({ showAddModal: false, urlError: '', iconError: '', edit: false })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { QuickLinksOptions as default, QuickLinksOptions };
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './QuickLinksOptions';
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './options';
|
||||||
|
export * from './Search';
|
|
@ -0,0 +1,174 @@
|
||||||
|
import variables from 'config/variables';
|
||||||
|
import { PureComponent } from 'react';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
import { MenuItem, TextField } from '@mui/material';
|
||||||
|
|
||||||
|
import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Layout/Settings';
|
||||||
|
import { Dropdown, Checkbox } from 'components/Form/Settings';
|
||||||
|
|
||||||
|
import EventBus from 'utils/eventbus';
|
||||||
|
|
||||||
|
import searchEngines from 'features/widgets/search/search_engines.json';
|
||||||
|
|
||||||
|
class SearchOptions extends PureComponent {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = {
|
||||||
|
customEnabled: false,
|
||||||
|
customValue: localStorage.getItem('customSearchEngine') || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSearch() {
|
||||||
|
localStorage.removeItem('customSearchEngine');
|
||||||
|
this.setState({
|
||||||
|
customValue: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
toast(variables.getMessage('toasts.reset'));
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (localStorage.getItem('searchEngine') === 'custom') {
|
||||||
|
this.setState({
|
||||||
|
customEnabled: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
localStorage.removeItem('customSearchEngine');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
if (this.state.customEnabled === true && this.state.customValue !== '') {
|
||||||
|
localStorage.setItem('customSearchEngine', this.state.customValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBus.emit('refresh', 'search');
|
||||||
|
}
|
||||||
|
|
||||||
|
setSearchEngine(input) {
|
||||||
|
if (input === 'custom') {
|
||||||
|
this.setState({
|
||||||
|
customEnabled: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
customEnabled: false,
|
||||||
|
});
|
||||||
|
localStorage.setItem('searchEngine', input);
|
||||||
|
}
|
||||||
|
|
||||||
|
EventBus.emit('refresh', 'search');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const SEARCH_SECTION = 'modals.main.settings.sections.search';
|
||||||
|
|
||||||
|
const AdditionalOptions = () => {
|
||||||
|
return (
|
||||||
|
<Row>
|
||||||
|
<Content
|
||||||
|
title={variables.getMessage('modals.main.settings.additional_settings')}
|
||||||
|
subtitle={variables.getMessage(`${SEARCH_SECTION}.additional`)}
|
||||||
|
/>
|
||||||
|
<Action>
|
||||||
|
{/* not supported on firefox */}
|
||||||
|
{navigator.userAgent.includes('Chrome') && typeof InstallTrigger === 'undefined' ? (
|
||||||
|
<Checkbox
|
||||||
|
name="voiceSearch"
|
||||||
|
text={variables.getMessage(`${SEARCH_SECTION}.voice_search`)}
|
||||||
|
category="search"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
<Checkbox
|
||||||
|
name="searchDropdown"
|
||||||
|
text={variables.getMessage(`${SEARCH_SECTION}.dropdown`)}
|
||||||
|
category="search"
|
||||||
|
element=".other"
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
name="searchFocus"
|
||||||
|
text={variables.getMessage(`${SEARCH_SECTION}.focus`)}
|
||||||
|
category="search"
|
||||||
|
element=".other"
|
||||||
|
/>
|
||||||
|
<Checkbox
|
||||||
|
name="autocomplete"
|
||||||
|
text={variables.getMessage(`${SEARCH_SECTION}.autocomplete`)}
|
||||||
|
category="search"
|
||||||
|
/>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const SearchEngineSelection = () => {
|
||||||
|
return (
|
||||||
|
<Row final={!this.state.customEnabled}>
|
||||||
|
<Content
|
||||||
|
title={variables.getMessage(`${SEARCH_SECTION}.search_engine`)}
|
||||||
|
subtitle={variables.getMessage(
|
||||||
|
'modals.main.settings.sections.search.search_engine_subtitle',
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<Action>
|
||||||
|
<Dropdown
|
||||||
|
name="searchEngine"
|
||||||
|
onChange={(value) => this.setSearchEngine(value)}
|
||||||
|
items={[
|
||||||
|
searchEngines.map((engine) => ({
|
||||||
|
value: engine.settingsName,
|
||||||
|
text: engine.name,
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
value: 'custom',
|
||||||
|
text: variables.getMessage(`${SEARCH_SECTION}.custom`),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CustomOptions = () => {
|
||||||
|
return (
|
||||||
|
<Row final={true}>
|
||||||
|
<Content title={variables.getMessage(`${SEARCH_SECTION}.custom`)} />
|
||||||
|
<Action>
|
||||||
|
<TextField
|
||||||
|
label={variables.getMessage(`${SEARCH_SECTION}.custom`)}
|
||||||
|
value={this.state.customValue}
|
||||||
|
onInput={(e) => this.setState({ customValue: e.target.value })}
|
||||||
|
varient="outlined"
|
||||||
|
InputLabelProps={{ shrink: true }}
|
||||||
|
/>
|
||||||
|
<p style={{ marginTop: '0px' }}>
|
||||||
|
<span className="link" onClick={() => this.resetSearch()}>
|
||||||
|
{variables.getMessage('modals.main.settings.buttons.reset')}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</Action>
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header
|
||||||
|
title={variables.getMessage(`${SEARCH_SECTION}.title`)}
|
||||||
|
setting="searchBar"
|
||||||
|
category="widgets"
|
||||||
|
visibilityToggle={true}
|
||||||
|
/>
|
||||||
|
<PreferencesWrapper setting="searchBar" category="widgets" visibilityToggle={true}>
|
||||||
|
<AdditionalOptions />
|
||||||
|
<SearchEngineSelection />
|
||||||
|
{this.state.customEnabled && CustomOptions()}
|
||||||
|
</PreferencesWrapper>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { SearchOptions as default, SearchOptions };
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './SearchOptions';
|
|
@ -10,7 +10,7 @@ import { getWeather } from './api/WeatherAPI.js';
|
||||||
|
|
||||||
import './weather.scss';
|
import './weather.scss';
|
||||||
|
|
||||||
export default class WeatherSettings extends PureComponent {
|
class WeatherWidget extends PureComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -84,3 +84,5 @@ export default class WeatherSettings extends PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { WeatherWidget as default, WeatherWidget };
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './options';
|
||||||
|
export * from './Weather';
|
|
@ -7,7 +7,7 @@ import { Header, Row, Content, Action, PreferencesWrapper } from 'components/Lay
|
||||||
import { Radio, Dropdown, Checkbox } from 'components/Form/Settings';
|
import { Radio, Dropdown, Checkbox } from 'components/Form/Settings';
|
||||||
import { TextField } from '@mui/material';
|
import { TextField } from '@mui/material';
|
||||||
|
|
||||||
export default class WeatherSettings extends PureComponent {
|
class WeatherOptions extends PureComponent {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -220,3 +220,5 @@ export default class WeatherSettings extends PureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { WeatherOptions as default, WeatherOptions };
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './WeatherOptions';
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue