Bookmark group deletion update; Icon updates
This commit is contained in:
@@ -27,10 +27,6 @@ sudo pm2 serve ./dist --no-daemon --spa --port 3000
|
|||||||
sudo pm2 start server.cjs
|
sudo pm2 start server.cjs
|
||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
- Reassign/delete bookmarks when group is deleted
|
|
||||||
|
|
||||||
- Find way to list all available icons in dropdown
|
|
||||||
|
|
||||||
- Expand settings search to fields other than name
|
- Expand settings search to fields other than name
|
||||||
|
|
||||||
- ? Image uploads for backgrounds ?
|
- ? Image uploads for backgrounds ?
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
import { Icon } from '@iconify/react';
|
|
||||||
import { Box, Stack, Text } from '@mantine/core';
|
import { Box, Stack, Text } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import * as fa6 from 'react-icons/fa6';
|
||||||
|
import * as si from 'react-icons/si';
|
||||||
|
import * as vsc from 'react-icons/vsc';
|
||||||
import { stackClasses, textClasses } from 'styles';
|
import { stackClasses, textClasses } from 'styles';
|
||||||
|
|
||||||
function AppItem({ url, icon, name }: any) {
|
function AppItem({ url, icon, name }: any) {
|
||||||
|
const allIcons: any = { ...fa6, ...vsc, ...si };
|
||||||
|
const Icon = allIcons[icon];
|
||||||
const { isMobile } = useCommonHooks();
|
const { isMobile } = useCommonHooks();
|
||||||
const [textDecoration, setTextDecoration] = useState<string>('none');
|
const [textDecoration, setTextDecoration] = useState<string>('none');
|
||||||
const [hover, setHover] = useState<boolean>(false);
|
const [hover, setHover] = useState<boolean>(false);
|
||||||
@@ -45,7 +49,7 @@ function AppItem({ url, icon, name }: any) {
|
|||||||
paddingTop: isMobile ? '0' : '15px',
|
paddingTop: isMobile ? '0' : '15px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon={`mdi:${icon}`} height={32} width={32} />
|
{Icon && <Icon style={{ height: '32px', width: '32px' }} />}
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack
|
<Stack
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Icon } from '@iconify/react';
|
|
||||||
import { ActionIcon, Box, Stack, Text, Tooltip } from '@mantine/core';
|
import { ActionIcon, Box, Stack, Text, Tooltip } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { FiAlertCircle } from 'react-icons/fi';
|
import { FiAlertCircle } from 'react-icons/fi';
|
||||||
import { actionIconClasses, boxClasses, textClasses } from 'styles';
|
import { actionIconClasses, boxClasses, textClasses } from 'styles';
|
||||||
|
|
||||||
function AppSettingsItem({ url, icon, name, enabled }: any) {
|
function AppSettingsItem({ url, icon, name, enabled, allIcons }: any) {
|
||||||
|
const Icon = allIcons[icon];
|
||||||
const [textDecoration, setTextDecoration] = useState<string>('none');
|
const [textDecoration, setTextDecoration] = useState<string>('none');
|
||||||
const [hover, setHover] = useState<boolean>(false);
|
const [hover, setHover] = useState<boolean>(false);
|
||||||
const { isMobile, theme } = useCommonHooks();
|
const { isMobile, theme } = useCommonHooks();
|
||||||
@@ -58,7 +58,7 @@ function AppSettingsItem({ url, icon, name, enabled }: any) {
|
|||||||
paddingTop: isMobile ? '0' : '32px',
|
paddingTop: isMobile ? '0' : '32px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon={`mdi:${icon}`} height={64} width={64} />
|
{Icon && <Icon style={{ height: '64px', width: '64px' }} />}
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack
|
<Stack
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
GridCol,
|
GridCol,
|
||||||
Group,
|
Group,
|
||||||
Popover,
|
Popover,
|
||||||
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
@@ -15,6 +16,9 @@ import {
|
|||||||
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||||
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import * as fa6 from 'react-icons/fa6';
|
||||||
|
import * as si from 'react-icons/si';
|
||||||
|
import * as vsc from 'react-icons/vsc';
|
||||||
import { textInputClasses } from 'styles';
|
import { textInputClasses } from 'styles';
|
||||||
import type { Application } from 'types';
|
import type { Application } from 'types';
|
||||||
import AddItemModal from '../Shared/AddItemModal';
|
import AddItemModal from '../Shared/AddItemModal';
|
||||||
@@ -23,6 +27,7 @@ import AppSettingsItem from './AppSettingsItem';
|
|||||||
import DebouncedApplication from './DebouncedApplication';
|
import DebouncedApplication from './DebouncedApplication';
|
||||||
|
|
||||||
const ApplicationSettings = () => {
|
const ApplicationSettings = () => {
|
||||||
|
const allIcons: any = { ...fa6, ...vsc, ...si };
|
||||||
const defaultApplication: Application = {
|
const defaultApplication: Application = {
|
||||||
id: null,
|
id: null,
|
||||||
name: '',
|
name: '',
|
||||||
@@ -157,18 +162,26 @@ const ApplicationSettings = () => {
|
|||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<Group justify='center'>
|
<Group justify='center'>
|
||||||
<TextInput
|
<Select
|
||||||
label={'Icon'}
|
label={'Icon'}
|
||||||
className={textInputClasses.settingsItem}
|
className={textInputClasses.settingsItem}
|
||||||
pt={16}
|
|
||||||
classNames={textInputClasses}
|
classNames={textInputClasses}
|
||||||
defaultValue={newApplication.icon}
|
data={Object.keys(allIcons).map((icon) => {
|
||||||
onChange={(event) => {
|
return { value: icon, label: icon };
|
||||||
setNewApplication({
|
})}
|
||||||
...newApplication,
|
comboboxProps={{
|
||||||
icon: event.target.value,
|
zIndex: 1000,
|
||||||
});
|
|
||||||
}}
|
}}
|
||||||
|
renderOption={(item: any) => {
|
||||||
|
const Icon = allIcons[item.option.value];
|
||||||
|
return (
|
||||||
|
<Group>
|
||||||
|
{item.option.value}
|
||||||
|
<Icon />
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
searchable
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={'Filter'}
|
label={'Filter'}
|
||||||
@@ -347,6 +360,7 @@ const ApplicationSettings = () => {
|
|||||||
icon={application.icon}
|
icon={application.icon}
|
||||||
name={application.name}
|
name={application.name}
|
||||||
enabled={application.enabled}
|
enabled={application.enabled}
|
||||||
|
allIcons={allIcons}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Popover.Target>
|
</Popover.Target>
|
||||||
@@ -354,6 +368,7 @@ const ApplicationSettings = () => {
|
|||||||
<DebouncedApplication
|
<DebouncedApplication
|
||||||
application={application}
|
application={application}
|
||||||
setIsOpen={setIsOpen}
|
setIsOpen={setIsOpen}
|
||||||
|
allIcons={allIcons}
|
||||||
/>
|
/>
|
||||||
</Popover.Dropdown>
|
</Popover.Dropdown>
|
||||||
</Popover>
|
</Popover>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
Group,
|
Group,
|
||||||
|
Select,
|
||||||
Stack,
|
Stack,
|
||||||
Switch,
|
Switch,
|
||||||
Text,
|
Text,
|
||||||
@@ -20,7 +21,8 @@ import DeleteItemModal from '../Shared/DeleteItemModal';
|
|||||||
function DebouncedApplication({
|
function DebouncedApplication({
|
||||||
application,
|
application,
|
||||||
setIsOpen,
|
setIsOpen,
|
||||||
}: { application: Application; setIsOpen: any }) {
|
allIcons,
|
||||||
|
}: { application: Application; setIsOpen: any; allIcons: any }) {
|
||||||
const { theme, handleDelete } = useCommonHooks();
|
const { theme, handleDelete } = useCommonHooks();
|
||||||
const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);
|
const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false);
|
||||||
const { mutateAsync } = useMutationAPI();
|
const { mutateAsync } = useMutationAPI();
|
||||||
@@ -169,18 +171,35 @@ function DebouncedApplication({
|
|||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<Group w={'100%'} justify='center'>
|
<Group w={'100%'} justify='center'>
|
||||||
<TextInput
|
<Select
|
||||||
label={'Icon'}
|
label={'Icon'}
|
||||||
className={textInputClasses.settingsItem}
|
className={textInputClasses.settingsItem}
|
||||||
pt={16}
|
|
||||||
classNames={textInputClasses}
|
classNames={textInputClasses}
|
||||||
|
data={Object.keys(allIcons).map((icon) => {
|
||||||
|
return { value: icon, label: icon };
|
||||||
|
})}
|
||||||
defaultValue={app.icon}
|
defaultValue={app.icon}
|
||||||
onChange={(event) => {
|
comboboxProps={{
|
||||||
|
zIndex: 3000,
|
||||||
|
}}
|
||||||
|
onChange={(event: any) => {
|
||||||
setUpdate({
|
setUpdate({
|
||||||
...app,
|
...app,
|
||||||
icon: event.target.value,
|
icon: event,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
renderOption={(item: any) => {
|
||||||
|
const Icon = allIcons[item.option.value];
|
||||||
|
return (
|
||||||
|
<Group>
|
||||||
|
{item.option.value}
|
||||||
|
<Icon />
|
||||||
|
</Group>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
searchable
|
||||||
|
onDropdownOpen={() => setIsOpen(true)}
|
||||||
|
onDropdownClose={() => setIsOpen(false)}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={'Filter'}
|
label={'Filter'}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ function DebouncedGroupSettingsItem({
|
|||||||
handleClose={closeModal}
|
handleClose={closeModal}
|
||||||
title='Delete message'
|
title='Delete message'
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'175px'} align='center'>
|
||||||
<Text>Are you sure you want to delete this bookmark group?</Text>
|
<Text>Are you sure you want to delete this bookmark group?</Text>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
@@ -108,12 +108,16 @@ function DebouncedGroupSettingsItem({
|
|||||||
color: 'var(--color-background)',
|
color: 'var(--color-background)',
|
||||||
}}
|
}}
|
||||||
>{`"${group.categoryName}"`}</Text>
|
>{`"${group.categoryName}"`}</Text>
|
||||||
|
<Text style={{ fontWeight: 'bold', textTransform: 'uppercase' }}>
|
||||||
|
This will also delete all bookmarks in this group!
|
||||||
|
</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
<Group pos={'absolute'} bottom={8}>
|
||||||
<Button
|
<Button
|
||||||
color={'red'}
|
color={'red'}
|
||||||
styles={{ label: { color: 'black' } }}
|
styles={{ label: { color: 'black' } }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
handleDelete(bookmarks, 'api/links');
|
||||||
handleDelete(group, 'api/categories');
|
handleDelete(group, 'api/categories');
|
||||||
closeModal();
|
closeModal();
|
||||||
}}
|
}}
|
||||||
@@ -121,8 +125,8 @@ function DebouncedGroupSettingsItem({
|
|||||||
Delete
|
Delete
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
color={'grey'}
|
color={'var(--color-text-acc)'}
|
||||||
styles={{ label: { color: 'black' } }}
|
styles={{ label: { color: 'var(--color-text-pri)' } }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
closeModal();
|
closeModal();
|
||||||
}}
|
}}
|
||||||
|
|||||||
Reference in New Issue
Block a user