Updated names for uniformity
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import { Group, Stack, Text } from '@mantine/core';
|
import { Group, SimpleGrid, Stack, Text } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
|
||||||
import { textClasses } from 'styles';
|
import { textClasses } from 'styles';
|
||||||
import type { ExtendedForecast } from 'types';
|
import type { ExtendedForecast } from 'types';
|
||||||
import WeatherIcon from './WeatherIcon';
|
import WeatherIcon from './WeatherIcon';
|
||||||
@@ -9,8 +8,6 @@ export default function ExtendedForecastCard({
|
|||||||
}: { forecast: ExtendedForecast[] }) {
|
}: { forecast: ExtendedForecast[] }) {
|
||||||
const day = forecast.slice(2, 14).filter((item: ExtendedForecast) => item.isDaytime);
|
const day = forecast.slice(2, 14).filter((item: ExtendedForecast) => item.isDaytime);
|
||||||
const night = forecast.slice(2, 14).filter((item: ExtendedForecast) => !item.isDaytime);
|
const night = forecast.slice(2, 14).filter((item: ExtendedForecast) => !item.isDaytime);
|
||||||
|
|
||||||
const { isMobile } = useCommonHooks();
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
gap={0}
|
gap={0}
|
||||||
@@ -33,7 +30,7 @@ export default function ExtendedForecastCard({
|
|||||||
Extended Forecast
|
Extended Forecast
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group w={'100%'} align='center' justify='space-between'>
|
<SimpleGrid w={'100%'} cols={6}>
|
||||||
{day.map((item: ExtendedForecast, index: number) => {
|
{day.map((item: ExtendedForecast, index: number) => {
|
||||||
const short = item.shortForecast.includes('And')
|
const short = item.shortForecast.includes('And')
|
||||||
? item.shortForecast.substring(0, item.shortForecast.indexOf('And'))
|
? item.shortForecast.substring(0, item.shortForecast.indexOf('And'))
|
||||||
@@ -43,7 +40,6 @@ export default function ExtendedForecastCard({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
w={isMobile ? '30%' : '15%'}
|
|
||||||
key={item.name}
|
key={item.name}
|
||||||
gap={0}
|
gap={0}
|
||||||
align='center'
|
align='center'
|
||||||
@@ -78,7 +74,7 @@ export default function ExtendedForecastCard({
|
|||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</Group>
|
</SimpleGrid>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -127,10 +127,10 @@ export function useMutationAPI() {
|
|||||||
queryClient.refetchQueries({
|
queryClient.refetchQueries({
|
||||||
queryKey: ['GET', endpoint],
|
queryKey: ['GET', endpoint],
|
||||||
});
|
});
|
||||||
endpoint === 'api/linkOrder' &&
|
endpoint === 'api/bookmarkOrder' &&
|
||||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/links'] });
|
queryClient.refetchQueries({ queryKey: ['GET', 'api/bookmarks'] });
|
||||||
endpoint === 'api/categoryOrder' &&
|
endpoint === 'api/bookmarkCategoryOrder' &&
|
||||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/categories'] });
|
queryClient.refetchQueries({ queryKey: ['GET', 'api/bookmarkCategories'] });
|
||||||
endpoint === 'api/applicationOrder' &&
|
endpoint === 'api/applicationOrder' &&
|
||||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/applicationOrder'] });
|
queryClient.refetchQueries({ queryKey: ['GET', 'api/applicationOrder'] });
|
||||||
},
|
},
|
||||||
@@ -138,10 +138,10 @@ export function useMutationAPI() {
|
|||||||
queryClient.refetchQueries({
|
queryClient.refetchQueries({
|
||||||
queryKey: ['GET', endpoint],
|
queryKey: ['GET', endpoint],
|
||||||
});
|
});
|
||||||
endpoint === 'api/linkOrder' &&
|
endpoint === 'api/bookmarkOrder' &&
|
||||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/links'] });
|
queryClient.refetchQueries({ queryKey: ['GET', 'api/bookmarks'] });
|
||||||
endpoint === 'api/categoryOrder' &&
|
endpoint === 'api/bookmarkCategoryOrder' &&
|
||||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/categories'] });
|
queryClient.refetchQueries({ queryKey: ['GET', 'api/bookmarkCategories'] });
|
||||||
endpoint === 'api/applicationOrder' &&
|
endpoint === 'api/applicationOrder' &&
|
||||||
queryClient.refetchQueries({ queryKey: ['GET', 'api/applicationOrder'] });
|
queryClient.refetchQueries({ queryKey: ['GET', 'api/applicationOrder'] });
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import Search from './components/Search/Search';
|
|||||||
import SettingsButton from './components/SettingsButton/SettingsButton';
|
import SettingsButton from './components/SettingsButton/SettingsButton';
|
||||||
|
|
||||||
export function Homepage() {
|
export function Homepage() {
|
||||||
const { data: personal, isFetched: personalIsFetched } = useQueryAPI({
|
const { data: personalData, isFetched: personalIsFetched } = useQueryAPI({
|
||||||
endpoint: 'api/personalData',
|
endpoint: 'api/personalData',
|
||||||
});
|
});
|
||||||
const {
|
const {
|
||||||
@@ -27,7 +27,7 @@ export function Homepage() {
|
|||||||
isFetching: isMessagesFetching,
|
isFetching: isMessagesFetching,
|
||||||
isFetched: isMessagesFetched,
|
isFetched: isMessagesFetched,
|
||||||
} = useQueryAPI({
|
} = useQueryAPI({
|
||||||
endpoint: 'api/messages',
|
endpoint: 'api/displayedGreeting',
|
||||||
});
|
});
|
||||||
const {
|
const {
|
||||||
appFilter,
|
appFilter,
|
||||||
@@ -37,8 +37,8 @@ export function Homepage() {
|
|||||||
currentLocation,
|
currentLocation,
|
||||||
setCurrentLocation,
|
setCurrentLocation,
|
||||||
} = useCommonHooks();
|
} = useCommonHooks();
|
||||||
const [personalData, setPersonalData] = useState<PersonalData>();
|
const [personal, setPersonal] = useState<PersonalData>();
|
||||||
const [messages, setMessages] = useState<Message[]>([]);
|
const [message, setMessage] = useState<Message>();
|
||||||
const [displayedGreeting, setDisplayedGreeting] = useState('');
|
const [displayedGreeting, setDisplayedGreeting] = useState('');
|
||||||
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
|
const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] =
|
||||||
useDisclosure(false);
|
useDisclosure(false);
|
||||||
@@ -53,36 +53,36 @@ export function Homepage() {
|
|||||||
const date = new Date().toLocaleDateString('en-US', dateOptions);
|
const date = new Date().toLocaleDateString('en-US', dateOptions);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (messageData && isMessagesFetched) {
|
if (messageData && isMessagesFetched) {
|
||||||
setMessages(messageData);
|
setMessage(messageData[0]);
|
||||||
}
|
}
|
||||||
}, [messageData, isMessagesFetched]);
|
}, [messageData, isMessagesFetched]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (personal && personalIsFetched) {
|
if (personalData && personalIsFetched) {
|
||||||
setCurrentUser(personal[0]);
|
setCurrentUser(personalData[0]);
|
||||||
setPersonalData(personal[0]);
|
setPersonal(personalData[0]);
|
||||||
}
|
}
|
||||||
}, [personal, personalIsFetched]);
|
}, [personalData, personalIsFetched]);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (messages && personalData) {
|
if (message !== undefined && personal) {
|
||||||
setDisplayedGreeting(() => {
|
setDisplayedGreeting(() => {
|
||||||
if (Math.floor(Math.random() * 100) > 10 || messages.length === 0) {
|
if (Math.floor(Math.random() * 100) > 10 || message === undefined) {
|
||||||
switch (Math.floor(new Date().getHours() / 6)) {
|
switch (Math.floor(new Date().getHours() / 6)) {
|
||||||
case 0:
|
case 0:
|
||||||
return `Good night, ${personalData?.firstName}!`;
|
return `Good night, ${personal?.firstName}!`;
|
||||||
case 1:
|
case 1:
|
||||||
return `Good morning, ${personalData?.firstName}!`;
|
return `Good morning, ${personal?.firstName}!`;
|
||||||
case 2:
|
case 2:
|
||||||
return `Good afternoon, ${personalData?.firstName}!`;
|
return `Good afternoon, ${personal?.firstName}!`;
|
||||||
case 3:
|
case 3:
|
||||||
return `Good evening, ${personalData?.firstName}!`;
|
return `Good evening, ${personal?.firstName}!`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return messages[Math.floor(Math.random() * messages.length)].message;
|
return message.message;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [messages, personalData, isMessagesFetching]);
|
}, [message, personal, isMessagesFetching]);
|
||||||
const { data: weatherMetadata } = useOSMAPI({
|
const { data: weatherMetadata } = useOSMAPI({
|
||||||
address: personal?.[0]?.physicalAddress,
|
address: personalData?.[0]?.physicalAddress,
|
||||||
});
|
});
|
||||||
const { data: points } = useWeatherAPI({
|
const { data: points } = useWeatherAPI({
|
||||||
endpoint: 'points',
|
endpoint: 'points',
|
||||||
|
|||||||
@@ -6,18 +6,16 @@ import type { Application } from 'types';
|
|||||||
import AppItem from './AppItem';
|
import AppItem from './AppItem';
|
||||||
|
|
||||||
function Applications({ contentType }: { contentType: string[] }) {
|
function Applications({ contentType }: { contentType: string[] }) {
|
||||||
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
|
const { data: applicationData, isFetching: isApplicationDataFetching } = useQueryAPI({
|
||||||
endpoint: 'api/apps',
|
endpoint: 'api/enabledApplications',
|
||||||
});
|
});
|
||||||
const { isMobile, appSort, appDensity } = useCommonHooks();
|
const { isMobile, appSort, appDensity } = useCommonHooks();
|
||||||
const [applicationData, setApplicationData] = useState<Application[]>([]);
|
const [applications, setApplications] = useState<Application[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (apps && !isAppsFetching) {
|
if (applicationData && !isApplicationDataFetching) {
|
||||||
setApplicationData(
|
setApplications(
|
||||||
apps
|
applicationData.sort((a: Application, b: Application) => {
|
||||||
.filter((a: Application) => a.enabled === 1)
|
|
||||||
.sort((a: Application, b: Application) => {
|
|
||||||
switch (appSort) {
|
switch (appSort) {
|
||||||
case 'A>Z':
|
case 'A>Z':
|
||||||
return a.name > b.name ? 1 : -1;
|
return a.name > b.name ? 1 : -1;
|
||||||
@@ -27,13 +25,11 @@ function Applications({ contentType }: { contentType: string[] }) {
|
|||||||
if (a.id && b.id) {
|
if (a.id && b.id) {
|
||||||
return a.id < b.id ? 1 : -1;
|
return a.id < b.id ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
case 'Oldest':
|
case 'Oldest':
|
||||||
if (a.id && b.id) {
|
if (a.id && b.id) {
|
||||||
return a.id > b.id ? 1 : -1;
|
return a.id > b.id ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
case 'Custom':
|
case 'Custom':
|
||||||
return a.index > b.index ? 1 : -1;
|
return a.index > b.index ? 1 : -1;
|
||||||
@@ -41,11 +37,11 @@ function Applications({ contentType }: { contentType: string[] }) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [apps, isAppsFetching, appSort]);
|
}, [applicationData, isApplicationDataFetching, appSort]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{applicationData.length > 0 && contentType.length > 0 && (
|
{applications.length > 0 && contentType.length > 0 && (
|
||||||
<Stack id='apps' style={{ gap: 0 }}>
|
<Stack style={{ gap: 0 }}>
|
||||||
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
||||||
Applications
|
Applications
|
||||||
</Text>
|
</Text>
|
||||||
@@ -63,7 +59,7 @@ function Applications({ contentType }: { contentType: string[] }) {
|
|||||||
gridTemplateRows: '64px',
|
gridTemplateRows: '64px',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{applicationData
|
{applications
|
||||||
?.filter(
|
?.filter(
|
||||||
(application: Application) =>
|
(application: Application) =>
|
||||||
contentType.includes(application.filterName) ||
|
contentType.includes(application.filterName) ||
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
import { Stack, Text } from '@mantine/core';
|
import { Stack, Text } from '@mantine/core';
|
||||||
import { textClasses } from 'styles';
|
import { textClasses } from 'styles';
|
||||||
import type { Bookmark } from 'types';
|
import type { Bookmark } from 'types';
|
||||||
import LinkItem from './LinkItem';
|
import BookmarkItem from './BookmarkItem';
|
||||||
|
|
||||||
function LinkGroups({ links, category }: { links: Bookmark[]; category: string }) {
|
function BookmarkGroups({
|
||||||
|
bookmarks,
|
||||||
|
category,
|
||||||
|
}: { bookmarks: Bookmark[]; category: string }) {
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
style={{
|
style={{
|
||||||
@@ -14,16 +17,16 @@ function LinkGroups({ links, category }: { links: Bookmark[]; category: string }
|
|||||||
whiteSpace: 'nowrap',
|
whiteSpace: 'nowrap',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text className={textClasses.linkCategory} classNames={textClasses}>
|
<Text className={textClasses.bookmarkCategory} classNames={textClasses}>
|
||||||
{category}
|
{category}
|
||||||
</Text>
|
</Text>
|
||||||
{links
|
{bookmarks
|
||||||
?.toSorted((a: Bookmark, b: Bookmark) => (a.index > b.index ? 1 : -1))
|
?.toSorted((a: Bookmark, b: Bookmark) => (a.index > b.index ? 1 : -1))
|
||||||
.map((link: Bookmark) => (
|
.map((bookmark: Bookmark) => (
|
||||||
<LinkItem key={link.name} link={link} />
|
<BookmarkItem key={bookmark.name} bookmark={bookmark} />
|
||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LinkGroups;
|
export default BookmarkGroups;
|
||||||
@@ -2,17 +2,17 @@ import { Text } from '@mantine/core';
|
|||||||
import { textClasses } from 'styles';
|
import { textClasses } from 'styles';
|
||||||
import type { Bookmark } from 'types';
|
import type { Bookmark } from 'types';
|
||||||
|
|
||||||
function LinkItem({ link }: { link: Bookmark }) {
|
function BookmarkItem({ bookmark }: { bookmark: Bookmark }) {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
className={textClasses.linkItem}
|
className={textClasses.bookmarkItem}
|
||||||
classNames={textClasses}
|
classNames={textClasses}
|
||||||
component='a'
|
component='a'
|
||||||
href={link.url}
|
href={bookmark.url}
|
||||||
>
|
>
|
||||||
{link.name}
|
{bookmark.name}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default LinkItem;
|
export default BookmarkItem;
|
||||||
@@ -3,24 +3,24 @@ import { useCommonHooks, useQueryAPI } from 'hooks';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { textClasses } from 'styles';
|
import { textClasses } from 'styles';
|
||||||
import type { Bookmark, BookmarkGroup } from 'types';
|
import type { Bookmark, BookmarkGroup } from 'types';
|
||||||
import LinkGroups from './LinkGroups';
|
import BookmarkGroups from './BookmarkGroups';
|
||||||
|
|
||||||
function Links({ contentType }: { contentType: string[] }) {
|
function Bookmarks({ contentType }: { contentType: string[] }) {
|
||||||
const { data: linkData, isFetched: linksIsFetched } = useQueryAPI({
|
const { data: bookmarkData, isFetched: bookmarksIsFetched } = useQueryAPI({
|
||||||
endpoint: 'api/links',
|
endpoint: 'api/bookmarks',
|
||||||
});
|
});
|
||||||
const { data: groupData, isFetched: groupsIsFetched } = useQueryAPI({
|
const { data: groupData, isFetched: groupsIsFetched } = useQueryAPI({
|
||||||
endpoint: 'api/categories',
|
endpoint: 'api/bookmarkCategories',
|
||||||
});
|
});
|
||||||
const { isMobile, bookmarkSort, bookmarkDensity } = useCommonHooks();
|
const { isMobile, bookmarkSort, bookmarkDensity } = useCommonHooks();
|
||||||
const [bookmarkData, setBookmarkData] = useState<Bookmark[]>([]);
|
const [bookmarks, setBookmarks] = useState<Bookmark[]>([]);
|
||||||
const [groups, setGroups] = useState<BookmarkGroup[]>([]);
|
const [groups, setGroups] = useState<BookmarkGroup[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (linkData && linksIsFetched) {
|
if (bookmarkData && bookmarksIsFetched) {
|
||||||
setBookmarkData(linkData);
|
setBookmarks(bookmarkData);
|
||||||
}
|
}
|
||||||
}, [linksIsFetched, linkData]);
|
}, [bookmarksIsFetched, bookmarkData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupData && groupsIsFetched) {
|
if (groupData && groupsIsFetched) {
|
||||||
@@ -57,10 +57,10 @@ function Links({ contentType }: { contentType: string[] }) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{groupsIsFetched &&
|
{groupsIsFetched &&
|
||||||
linksIsFetched &&
|
bookmarksIsFetched &&
|
||||||
groups?.length > 0 &&
|
groups?.length > 0 &&
|
||||||
contentType.length > 0 && (
|
contentType.length > 0 && (
|
||||||
<Stack id='links' style={{ gap: 0 }}>
|
<Stack style={{ gap: 0 }}>
|
||||||
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
<Text className={textClasses.sectionTitle} classNames={textClasses}>
|
||||||
Bookmarks
|
Bookmarks
|
||||||
</Text>
|
</Text>
|
||||||
@@ -85,10 +85,10 @@ function Links({ contentType }: { contentType: string[] }) {
|
|||||||
|
|
||||||
.map((category: BookmarkGroup) => {
|
.map((category: BookmarkGroup) => {
|
||||||
return (
|
return (
|
||||||
<LinkGroups
|
<BookmarkGroups
|
||||||
key={category.categoryName}
|
key={category.categoryName}
|
||||||
category={category.categoryName}
|
category={category.categoryName}
|
||||||
links={bookmarkData.filter(
|
bookmarks={bookmarks.filter(
|
||||||
(bookmark: Bookmark) =>
|
(bookmark: Bookmark) =>
|
||||||
bookmark.category === category.categoryName,
|
bookmark.category === category.categoryName,
|
||||||
)}
|
)}
|
||||||
@@ -102,4 +102,4 @@ function Links({ contentType }: { contentType: string[] }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Links;
|
export default Bookmarks;
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ function Header({
|
|||||||
setTime(newDate);
|
setTime(newDate);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (weather !== undefined && basicWeather !== undefined) {
|
if (weather !== undefined && basicWeather !== undefined) {
|
||||||
setCurrent({
|
setCurrent({
|
||||||
@@ -92,7 +91,7 @@ function Header({
|
|||||||
fz={isMobile ? 24 : undefined}
|
fz={isMobile ? 24 : undefined}
|
||||||
>
|
>
|
||||||
{greet
|
{greet
|
||||||
.replace('$firstName', currentUser.firstName)
|
?.replace('$firstName', currentUser.firstName)
|
||||||
.replace('$lastName', currentUser.lastName)
|
.replace('$lastName', currentUser.lastName)
|
||||||
.replace('$^firstName', currentUser.firstName.toUpperCase())
|
.replace('$^firstName', currentUser.firstName.toUpperCase())
|
||||||
.replace('$^lastName', currentUser.lastName.toUpperCase())}
|
.replace('$^lastName', currentUser.lastName.toUpperCase())}
|
||||||
|
|||||||
@@ -33,16 +33,17 @@ export default function Search({
|
|||||||
closeWeatherModal: () => void;
|
closeWeatherModal: () => void;
|
||||||
openWeatherModal: () => void;
|
openWeatherModal: () => void;
|
||||||
}) {
|
}) {
|
||||||
const { data: providers, isFetched: providersIsFetched } = useQueryAPI({
|
const { data: providerData, isFetched: providerDataIsFetched } = useQueryAPI({
|
||||||
endpoint: 'api/providers',
|
endpoint: 'api/providers',
|
||||||
});
|
});
|
||||||
const [providerData, setProviderData] = useState<Provider[]>([]);
|
const [providers, setProviders] = useState<Provider[]>([]);
|
||||||
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
|
const { data: applicationData, isFetching: isApplicationDataFetching } = useQueryAPI({
|
||||||
endpoint: 'api/apps',
|
endpoint: 'api/enabledApplications',
|
||||||
});
|
});
|
||||||
const [applicationData, setApplicationData] = useState<Application[]>([]);
|
const [applications, setApplications] = useState<Application[]>([]);
|
||||||
const { data: history, isFetched: historyIsFetched } = useQueryAPI({
|
const searchEndpoint = 'api/searchHistory';
|
||||||
endpoint: 'api/searchHistory',
|
const { data: historyData, isFetched: historyDataIsFetched } = useQueryAPI({
|
||||||
|
endpoint: searchEndpoint,
|
||||||
});
|
});
|
||||||
const [searchHistory, setSearchHistory] = useState<SearchHistoryItem[]>([]);
|
const [searchHistory, setSearchHistory] = useState<SearchHistoryItem[]>([]);
|
||||||
const [filteredHistory, setFilteredHistory] = useState<SearchHistoryItem[]>([]);
|
const [filteredHistory, setFilteredHistory] = useState<SearchHistoryItem[]>([]);
|
||||||
@@ -69,7 +70,7 @@ export default function Search({
|
|||||||
|
|
||||||
const handleSearchHistoryItem = ({ option }: { option: SearchHistoryItem }) => {
|
const handleSearchHistoryItem = ({ option }: { option: SearchHistoryItem }) => {
|
||||||
const url =
|
const url =
|
||||||
providers.find((provider: Provider) => provider.prefix === option.prefix)?.url ??
|
providerData.find((provider: Provider) => provider.prefix === option.prefix)?.url ??
|
||||||
'https://www.google.com/search?q=';
|
'https://www.google.com/search?q=';
|
||||||
open(`${url}${option.searchTerm}`, '_self');
|
open(`${url}${option.searchTerm}`, '_self');
|
||||||
};
|
};
|
||||||
@@ -99,7 +100,7 @@ export default function Search({
|
|||||||
} else if (item.target.value.startsWith('/')) {
|
} else if (item.target.value.startsWith('/')) {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
endpoint: 'api/searchHistory',
|
endpoint: searchEndpoint,
|
||||||
body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext },
|
body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext },
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
open(`${providerURL}${subtext}`, '_self');
|
open(`${providerURL}${subtext}`, '_self');
|
||||||
@@ -107,7 +108,7 @@ export default function Search({
|
|||||||
} else if (providerLabel === 'Show weather') {
|
} else if (providerLabel === 'Show weather') {
|
||||||
openWeatherModal();
|
openWeatherModal();
|
||||||
} else if (providerLabel.startsWith('Launch')) {
|
} else if (providerLabel.startsWith('Launch')) {
|
||||||
const url = applicationData.find(
|
const url = applications.find(
|
||||||
(app: Application) =>
|
(app: Application) =>
|
||||||
app.baseUrl.substring(1).toLowerCase() === item.target.value.substr(1),
|
app.baseUrl.substring(1).toLowerCase() === item.target.value.substr(1),
|
||||||
)?.url;
|
)?.url;
|
||||||
@@ -123,7 +124,7 @@ export default function Search({
|
|||||||
} else {
|
} else {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
endpoint: 'api/searchHistory',
|
endpoint: searchEndpoint,
|
||||||
body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext },
|
body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext },
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
open(`${providerURL}${subtext}`, '_self');
|
open(`${providerURL}${subtext}`, '_self');
|
||||||
@@ -221,7 +222,7 @@ export default function Search({
|
|||||||
setProviderURL('https://www.google.com/search?q=');
|
setProviderURL('https://www.google.com/search?q=');
|
||||||
setProviderPrefix('/g');
|
setProviderPrefix('/g');
|
||||||
} else if (item.target.value.startsWith('/')) {
|
} else if (item.target.value.startsWith('/')) {
|
||||||
const provider = providerData?.find(
|
const provider = providers?.find(
|
||||||
(p: Provider) => p.prefix === item.target.value.split(' ')[0],
|
(p: Provider) => p.prefix === item.target.value.split(' ')[0],
|
||||||
);
|
);
|
||||||
setProviderLabel(provider?.name ?? 'Invalid Search');
|
setProviderLabel(provider?.name ?? 'Invalid Search');
|
||||||
@@ -231,7 +232,7 @@ export default function Search({
|
|||||||
if (item.target.value === '!w' || item.target.value === '!weather') {
|
if (item.target.value === '!w' || item.target.value === '!weather') {
|
||||||
setProviderLabel('Show weather');
|
setProviderLabel('Show weather');
|
||||||
} else if (
|
} else if (
|
||||||
applicationData?.find(
|
applications?.find(
|
||||||
(app: Application) =>
|
(app: Application) =>
|
||||||
app.baseUrl.substring(1).toLowerCase() === item.target.value.substr(1),
|
app.baseUrl.substring(1).toLowerCase() === item.target.value.substr(1),
|
||||||
)
|
)
|
||||||
@@ -250,7 +251,7 @@ export default function Search({
|
|||||||
const optionsFilter: OptionsFilter = ({ options, search }) => {
|
const optionsFilter: OptionsFilter = ({ options, search }) => {
|
||||||
const splittedSearch = search.toLowerCase().trim().split(' ');
|
const splittedSearch = search.toLowerCase().trim().split(' ');
|
||||||
if (splittedSearch[0].startsWith('!')) {
|
if (splittedSearch[0].startsWith('!')) {
|
||||||
return apps
|
return applicationData
|
||||||
.filter((app: Application) =>
|
.filter((app: Application) =>
|
||||||
app.name.toLowerCase().includes(splittedSearch[0].substring(1).toLowerCase()),
|
app.name.toLowerCase().includes(splittedSearch[0].substring(1).toLowerCase()),
|
||||||
)
|
)
|
||||||
@@ -341,7 +342,7 @@ export default function Search({
|
|||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
endpoint: 'api/searchHistory',
|
endpoint: searchEndpoint,
|
||||||
body: { id: item.option.id },
|
body: { id: item.option.id },
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -392,25 +393,25 @@ export default function Search({
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (providers && providersIsFetched) {
|
if (providerData && providerDataIsFetched) {
|
||||||
setProviderData(providers);
|
setProviders(providerData);
|
||||||
}
|
}
|
||||||
}, [providers, providersIsFetched]);
|
}, [providerData, providerDataIsFetched]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (apps && !isAppsFetching) {
|
if (applicationData && !isApplicationDataFetching) {
|
||||||
setApplicationData(apps);
|
setApplications(applicationData);
|
||||||
}
|
}
|
||||||
}, [apps, isAppsFetching]);
|
}, [applicationData, isApplicationDataFetching]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (history && historyIsFetched) {
|
if (historyData && historyDataIsFetched) {
|
||||||
setSearchHistory(history);
|
setSearchHistory(historyData);
|
||||||
if (filteredHistory.length === 0) {
|
if (filteredHistory.length === 0) {
|
||||||
setFilteredHistory(history.slice(0, 10));
|
setFilteredHistory(historyData.slice(0, 10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [history, historyIsFetched]);
|
}, [historyData, historyDataIsFetched]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dropdownOpened) {
|
if (dropdownOpened) {
|
||||||
@@ -494,8 +495,8 @@ export default function Search({
|
|||||||
setSearchValue={setSearchValue}
|
setSearchValue={setSearchValue}
|
||||||
setProviderLabel={setProviderLabel}
|
setProviderLabel={setProviderLabel}
|
||||||
setProviderURL={setProviderURL}
|
setProviderURL={setProviderURL}
|
||||||
applicationData={applicationData}
|
applicationData={applications}
|
||||||
providerData={providerData}
|
providerData={providers}
|
||||||
providerModalOpened={providerModalOpened}
|
providerModalOpened={providerModalOpened}
|
||||||
closeProviderModal={closeProviderModal}
|
closeProviderModal={closeProviderModal}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -31,21 +31,23 @@ import {
|
|||||||
import type { AppCategory, Theme, ThemePlaylist, WolClient } from 'types';
|
import type { AppCategory, Theme, ThemePlaylist, WolClient } from 'types';
|
||||||
|
|
||||||
function SettingsButton() {
|
function SettingsButton() {
|
||||||
const { data, isFetched } = useQueryAPI({ endpoint: 'api/appCategories' });
|
const { data: appCategoryData, isFetched: appCategoryDataIsFetched } = useQueryAPI({
|
||||||
const { data: wolClients, isFetched: wolClientsIsFetched } = useQueryAPI({
|
endpoint: 'api/appCategories',
|
||||||
|
});
|
||||||
|
const { data: wolClientData, isFetched: wolClientDataIsFetched } = useQueryAPI({
|
||||||
endpoint: 'api/wolClients',
|
endpoint: 'api/wolClients',
|
||||||
});
|
});
|
||||||
const [wolClientsData, setWolClientsData] = useState<WolClient[]>([]);
|
const [wolClients, setWolClients] = useState<WolClient[]>([]);
|
||||||
const { data: allThemes, isFetched: isAllThemesFetched } = useQueryAPI({
|
const { data: allThemeData, isFetched: allThemeDataIsFetched } = useQueryAPI({
|
||||||
endpoint: 'api/themes',
|
endpoint: 'api/themes',
|
||||||
});
|
});
|
||||||
const { data: themePlaylists } = useQueryAPI({
|
const { data: themePlaylistData } = useQueryAPI({
|
||||||
endpoint: 'api/themePlaylists',
|
endpoint: 'api/themePlaylists',
|
||||||
});
|
});
|
||||||
const { mutateAsync } = useMutationAPI();
|
const { mutateAsync } = useMutationAPI();
|
||||||
const [allThemeData, setAllThemeData] = useState<Theme[]>([]);
|
const [allThemes, setAllThemes] = useState<Theme[]>([]);
|
||||||
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
|
const [categories, setCategories] = useState([{ value: 'All', label: 'All' }]);
|
||||||
const [selectedClient, setSelectedClient] = useState<WolClient>(wolClients?.[0]);
|
const [selectedClient] = useState<WolClient>(wolClientData?.[0]);
|
||||||
const [overlayOpened, setOverlayOpened] = useState(false);
|
const [overlayOpened, setOverlayOpened] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const notify = (notification: any) => toast(notification, { position: 'bottom-right' });
|
const notify = (notification: any) => toast(notification, { position: 'bottom-right' });
|
||||||
@@ -75,7 +77,7 @@ function SettingsButton() {
|
|||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
endpoint: 'api/wakeClient',
|
endpoint: 'api/wakeClient',
|
||||||
body: selectedClient || wolClients?.[0],
|
body: selectedClient || wolClientData?.[0],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,26 +88,26 @@ function SettingsButton() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data) {
|
if (appCategoryData) {
|
||||||
const list: [any] = data.map((category: AppCategory) => {
|
const list: [any] = appCategoryData.map((category: AppCategory) => {
|
||||||
return { value: category.filterName, label: category.filterName };
|
return { value: category.filterName, label: category.filterName };
|
||||||
});
|
});
|
||||||
list.unshift({ value: 'All', label: 'All' });
|
list.unshift({ value: 'All', label: 'All' });
|
||||||
setCategories(list);
|
setCategories(list);
|
||||||
}
|
}
|
||||||
}, [data, isFetched]);
|
}, [appCategoryData, appCategoryDataIsFetched]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (wolClients && wolClientsIsFetched) {
|
if (wolClientData && wolClientDataIsFetched) {
|
||||||
setWolClientsData(wolClients);
|
setWolClients(wolClientData);
|
||||||
}
|
}
|
||||||
}, [wolClients, wolClientsIsFetched]);
|
}, [wolClientData, wolClientDataIsFetched]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (allThemes && isAllThemesFetched) {
|
if (allThemeData && allThemeDataIsFetched) {
|
||||||
setAllThemeData(allThemes);
|
setAllThemes(allThemeData);
|
||||||
}
|
}
|
||||||
}, [allThemes, isAllThemesFetched]);
|
}, [allThemeData, allThemeDataIsFetched]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{overlayOpened && <Overlay pos={'fixed'} />}
|
{overlayOpened && <Overlay pos={'fixed'} />}
|
||||||
@@ -146,7 +148,7 @@ function SettingsButton() {
|
|||||||
<Button
|
<Button
|
||||||
classNames={buttonClasses}
|
classNames={buttonClasses}
|
||||||
className={buttonClasses.wakeButton}
|
className={buttonClasses.wakeButton}
|
||||||
disabled={!wolClientsData?.length || selectedClient === null}
|
disabled={!wolClients?.length || selectedClient === null}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleWakeRequest();
|
handleWakeRequest();
|
||||||
notify('Wake command sent');
|
notify('Wake command sent');
|
||||||
@@ -159,9 +161,9 @@ function SettingsButton() {
|
|||||||
<Select
|
<Select
|
||||||
labelProps={{ display: 'none' }}
|
labelProps={{ display: 'none' }}
|
||||||
placeholder='Pick a host...'
|
placeholder='Pick a host...'
|
||||||
defaultValue={wolClientsData?.[0]?.hostname}
|
defaultValue={wolClients?.[0]?.hostname}
|
||||||
data={
|
data={
|
||||||
wolClientsData
|
wolClients
|
||||||
?.map((wolClient: WolClient) => {
|
?.map((wolClient: WolClient) => {
|
||||||
return {
|
return {
|
||||||
value: wolClient.hostname,
|
value: wolClient.hostname,
|
||||||
@@ -227,7 +229,7 @@ function SettingsButton() {
|
|||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setCurrentThemePlaylist('All');
|
setCurrentThemePlaylist('All');
|
||||||
handleThemeChange(allThemeData, true);
|
handleThemeChange(allThemes, true);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<FaDice />
|
<FaDice />
|
||||||
@@ -246,7 +248,7 @@ function SettingsButton() {
|
|||||||
placeholder='Pick a playlist...'
|
placeholder='Pick a playlist...'
|
||||||
value={currentThemePlaylist}
|
value={currentThemePlaylist}
|
||||||
data={
|
data={
|
||||||
themePlaylists
|
themePlaylistData
|
||||||
?.map((playlist: ThemePlaylist) => {
|
?.map((playlist: ThemePlaylist) => {
|
||||||
return {
|
return {
|
||||||
value: playlist.name,
|
value: playlist.name,
|
||||||
@@ -271,12 +273,12 @@ function SettingsButton() {
|
|||||||
setThemeName('random');
|
setThemeName('random');
|
||||||
} else {
|
} else {
|
||||||
const themeList = JSON.parse(
|
const themeList = JSON.parse(
|
||||||
themePlaylists.find(
|
themePlaylistData.find(
|
||||||
(t: ThemePlaylist) => t.name === 'Time of Day',
|
(t: ThemePlaylist) => t.name === 'Time of Day',
|
||||||
).themeList,
|
).themeList,
|
||||||
);
|
);
|
||||||
setThemeName(
|
setThemeName(
|
||||||
allThemes.find(
|
allThemeData.find(
|
||||||
(t: Theme) =>
|
(t: Theme) =>
|
||||||
t.id ===
|
t.id ===
|
||||||
Number(themeList[Math.floor(new Date().getHours() / 6)]),
|
Number(themeList[Math.floor(new Date().getHours() / 6)]),
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ const ApplicationSettings = () => {
|
|||||||
index: 0,
|
index: 0,
|
||||||
enabled: 1,
|
enabled: 1,
|
||||||
};
|
};
|
||||||
const appsEndpoint = 'api/apps';
|
const appsEndpoint = 'api/applications';
|
||||||
const appsOrderEndpoint = 'api/applicationOrder';
|
const appsOrderEndpoint = 'api/applicationOrder';
|
||||||
const { data: apps, isFetching: isAppsFetching } = useQueryAPI({
|
const { data: applicationData, isFetching: isAppsFetching } = useQueryAPI({
|
||||||
endpoint: appsEndpoint,
|
endpoint: appsEndpoint,
|
||||||
});
|
});
|
||||||
const [applicationData, setApplicationData] = useState<Application[]>([]);
|
const [applications, setApplications] = useState<Application[]>([]);
|
||||||
const [applicationList, setApplicationList] = useState<Application[]>([]);
|
const [applicationList, setApplicationList] = useState<Application[]>([]);
|
||||||
const { theme, isMobile, reorder } = useCommonHooks();
|
const { theme, isMobile, reorder } = useCommonHooks();
|
||||||
const [newApplication, setNewApplication] = useState<Application>(defaultApplication);
|
const [newApplication, setNewApplication] = useState<Application>(defaultApplication);
|
||||||
@@ -64,7 +64,7 @@ const ApplicationSettings = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const items = reorder(applicationData, result.source.index, result.destination.index);
|
const items = reorder(applications, result.source.index, result.destination.index);
|
||||||
setApplicationList(
|
setApplicationList(
|
||||||
items.map((item: any, index: number) => {
|
items.map((item: any, index: number) => {
|
||||||
return {
|
return {
|
||||||
@@ -83,19 +83,19 @@ const ApplicationSettings = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (apps && !isAppsFetching) {
|
if (applicationData && !isAppsFetching) {
|
||||||
setApplicationData(
|
setApplications(
|
||||||
apps
|
applicationData
|
||||||
.filter((a: Application) =>
|
.filter((a: Application) =>
|
||||||
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
||||||
)
|
)
|
||||||
.sort((a: Application, b: Application) => (a.index > b.index ? 1 : -1)),
|
.sort((a: Application, b: Application) => (a.index > b.index ? 1 : -1)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [apps, isAppsFetching, debouncedSearch]);
|
}, [applicationData, isAppsFetching, debouncedSearch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (applicationList.length > 0 && applicationList !== applicationData) {
|
if (applicationList.length > 0 && applicationList !== applications) {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
endpoint: appsOrderEndpoint,
|
endpoint: appsOrderEndpoint,
|
||||||
@@ -229,7 +229,7 @@ const ApplicationSettings = () => {
|
|||||||
endpoint: appsEndpoint,
|
endpoint: appsEndpoint,
|
||||||
body: {
|
body: {
|
||||||
...newApplication,
|
...newApplication,
|
||||||
index: applicationData.length,
|
index: applications.length,
|
||||||
},
|
},
|
||||||
}).then(handleClose);
|
}).then(handleClose);
|
||||||
}
|
}
|
||||||
@@ -253,10 +253,11 @@ const ApplicationSettings = () => {
|
|||||||
openModal={openModal}
|
openModal={openModal}
|
||||||
title={'Applications'}
|
title={'Applications'}
|
||||||
tooltip={{
|
tooltip={{
|
||||||
title: 'Applications are the apps that will be displayed on the homepage.',
|
title:
|
||||||
|
'Applications are the applicationData that will be displayed on the homepage.',
|
||||||
highlightList: [
|
highlightList: [
|
||||||
'Applications',
|
'Applications',
|
||||||
'apps',
|
'applicationData',
|
||||||
'application',
|
'application',
|
||||||
'name',
|
'name',
|
||||||
'base url',
|
'base url',
|
||||||
@@ -288,7 +289,7 @@ const ApplicationSettings = () => {
|
|||||||
ref={provided.innerRef}
|
ref={provided.innerRef}
|
||||||
{...provided.droppableProps}
|
{...provided.droppableProps}
|
||||||
>
|
>
|
||||||
{applicationData?.map((app: Application) => (
|
{applications?.map((app: Application) => (
|
||||||
<Draggable
|
<Draggable
|
||||||
key={app.id}
|
key={app.id}
|
||||||
draggableId={`${app.id}`}
|
draggableId={`${app.id}`}
|
||||||
@@ -361,7 +362,7 @@ const ApplicationSettings = () => {
|
|||||||
align='center'
|
align='center'
|
||||||
>
|
>
|
||||||
<Grid columns={18} w={'75%'}>
|
<Grid columns={18} w={'75%'}>
|
||||||
{applicationData?.map((application: Application) => (
|
{applications?.map((application: Application) => (
|
||||||
<GridCol span={6} key={application.id}>
|
<GridCol span={6} key={application.id}>
|
||||||
<Popover
|
<Popover
|
||||||
withArrow
|
withArrow
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
Button,
|
|
||||||
Card,
|
Card,
|
||||||
type ComboboxItem,
|
type ComboboxItem,
|
||||||
type ComboboxLikeRenderOptionInput,
|
type ComboboxLikeRenderOptionInput,
|
||||||
@@ -38,7 +37,7 @@ function DebouncedApplication({
|
|||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (debounced && Object.keys(debounced).length > 0) {
|
if (debounced && Object.keys(debounced).length > 0) {
|
||||||
mutateAsync({ method: 'PATCH', endpoint: 'api/apps', body: debounced });
|
mutateAsync({ method: 'PATCH', endpoint: 'api/applications', body: debounced });
|
||||||
}
|
}
|
||||||
}, [debounced]);
|
}, [debounced]);
|
||||||
|
|
||||||
@@ -52,6 +51,7 @@ function DebouncedApplication({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
|
handleDelete={() => handleDelete(app, 'api/applications')}
|
||||||
title='Delete Application'
|
title='Delete Application'
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
||||||
@@ -68,25 +68,6 @@ function DebouncedApplication({
|
|||||||
}}
|
}}
|
||||||
>{`"${app.name}"`}</Text>
|
>{`"${app.name}"`}</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(app, 'api/apps');
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'grey'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={handleClose}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ const BookmarkSettings = () => {
|
|||||||
categoryIndex: 0,
|
categoryIndex: 0,
|
||||||
filterName: '',
|
filterName: '',
|
||||||
};
|
};
|
||||||
const linksEndpoint = 'api/links';
|
const bookmarksEndpoint = 'api/bookmarks';
|
||||||
const { data: linkData, isFetched: linksIsFetched } = useQueryAPI({
|
const { data: bookmarkData, isFetched: bookmarksIsFetched } = useQueryAPI({
|
||||||
endpoint: linksEndpoint,
|
endpoint: bookmarksEndpoint,
|
||||||
});
|
});
|
||||||
const [bookmarks, setBookmarks] = useState<Bookmark[]>([]);
|
const [bookmarks, setBookmarks] = useState<Bookmark[]>([]);
|
||||||
const categoriesEndpoint = 'api/categories';
|
const categoriesEndpoint = 'api/bookmarkCategories';
|
||||||
const { data: groupData, isFetched: groupsIsFetched } = useQueryAPI({
|
const { data: groupData, isFetched: groupsIsFetched } = useQueryAPI({
|
||||||
endpoint: categoriesEndpoint,
|
endpoint: categoriesEndpoint,
|
||||||
});
|
});
|
||||||
@@ -60,10 +60,10 @@ const BookmarkSettings = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (linkData && linksIsFetched) {
|
if (bookmarkData && bookmarksIsFetched) {
|
||||||
setBookmarks(linkData);
|
setBookmarks(bookmarkData);
|
||||||
}
|
}
|
||||||
}, [linksIsFetched, linkData]);
|
}, [bookmarksIsFetched, bookmarkData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupData && groupsIsFetched) {
|
if (groupData && groupsIsFetched) {
|
||||||
@@ -98,7 +98,11 @@ const BookmarkSettings = () => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (groupList.length > 0 && groupList !== groups) {
|
if (groupList.length > 0 && groupList !== groups) {
|
||||||
mutateAsync({ method: 'PATCH', endpoint: 'api/categoryOrder', body: groupList });
|
mutateAsync({
|
||||||
|
method: 'PATCH',
|
||||||
|
endpoint: 'api/bookmarkCategoryOrder',
|
||||||
|
body: groupList,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}, [groupList]);
|
}, [groupList]);
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
import {
|
import { ActionIcon, Card, Group, Stack, Text, TextInput, Tooltip } from '@mantine/core';
|
||||||
ActionIcon,
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Group,
|
|
||||||
Stack,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
|
||||||
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||||
import { useCommonHooks, useMutationAPI } from 'hooks';
|
import { useCommonHooks, useMutationAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -33,7 +24,7 @@ function DebouncedBookmarkItem({
|
|||||||
};
|
};
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Object.keys(debounced).length) {
|
if (Object.keys(debounced).length) {
|
||||||
mutateAsync({ method: 'PATCH', endpoint: 'api/links', body: debounced });
|
mutateAsync({ method: 'PATCH', endpoint: 'api/bookmarks', body: debounced });
|
||||||
}
|
}
|
||||||
}, [debounced]);
|
}, [debounced]);
|
||||||
|
|
||||||
@@ -48,6 +39,7 @@ function DebouncedBookmarkItem({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
|
handleDelete={() => handleDelete(bookmark, 'api/bookmarks')}
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
||||||
<Text>Are you sure you want to delete this bookmark?</Text>
|
<Text>Are you sure you want to delete this bookmark?</Text>
|
||||||
@@ -63,25 +55,6 @@ function DebouncedBookmarkItem({
|
|||||||
}}
|
}}
|
||||||
>{`"${bookmark.name}"`}</Text>
|
>{`"${bookmark.name}"`}</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(bookmark, 'api/links');
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'grey'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={handleClose}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
title='Delete Bookmark'
|
title='Delete Bookmark'
|
||||||
|
|||||||
@@ -72,7 +72,11 @@ function DebouncedGroupSettingsItem({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Object.keys(debounced).length) {
|
if (Object.keys(debounced).length) {
|
||||||
mutateAsync({ method: 'PATCH', endpoint: 'api/categories', body: debounced });
|
mutateAsync({
|
||||||
|
method: 'PATCH',
|
||||||
|
endpoint: 'api/bookmarkCategories',
|
||||||
|
body: debounced,
|
||||||
|
});
|
||||||
setUpdate({});
|
setUpdate({});
|
||||||
}
|
}
|
||||||
}, [debounced]);
|
}, [debounced]);
|
||||||
@@ -85,7 +89,7 @@ function DebouncedGroupSettingsItem({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (bookmarkList && bookmarkList !== bookmarks) {
|
if (bookmarkList && bookmarkList !== bookmarks) {
|
||||||
mutateAsync({ method: 'PATCH', endpoint: 'api/linkOrder', body: bookmarkList });
|
mutateAsync({ method: 'PATCH', endpoint: 'api/bookmarkOrder', body: bookmarkList });
|
||||||
}
|
}
|
||||||
}, [bookmarkList]);
|
}, [bookmarkList]);
|
||||||
|
|
||||||
@@ -94,6 +98,10 @@ function DebouncedGroupSettingsItem({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={closeModal}
|
handleClose={closeModal}
|
||||||
|
handleDelete={() => {
|
||||||
|
handleDelete(bookmarks, 'api/bookmarks');
|
||||||
|
handleDelete(group, 'api/bookmarkCategories');
|
||||||
|
}}
|
||||||
title='Delete message'
|
title='Delete message'
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'175px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'175px'} align='center'>
|
||||||
@@ -113,28 +121,6 @@ function DebouncedGroupSettingsItem({
|
|||||||
This will also delete all bookmarks in this group!
|
This will also delete all bookmarks in this group!
|
||||||
</Text>
|
</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(bookmarks, 'api/links');
|
|
||||||
handleDelete(group, 'api/categories');
|
|
||||||
closeModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'var(--color-text-acc)'}
|
|
||||||
styles={{ label: { color: 'var(--color-text-pri)' } }}
|
|
||||||
onClick={() => {
|
|
||||||
closeModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -401,7 +387,7 @@ function DebouncedGroupSettingsItem({
|
|||||||
if (newBookmark) {
|
if (newBookmark) {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
endpoint: 'api/links',
|
endpoint: 'api/bookmarks',
|
||||||
body: { ...newBookmark, index: bookmarks.length },
|
body: { ...newBookmark, index: bookmarks.length },
|
||||||
});
|
});
|
||||||
setPopoverOpened(false);
|
setPopoverOpened(false);
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
import {
|
import { ActionIcon, Card, Stack, Text, TextInput, Tooltip } from '@mantine/core';
|
||||||
ActionIcon,
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Group,
|
|
||||||
Stack,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
|
||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { FiTrash } from 'react-icons/fi';
|
import { FiTrash } from 'react-icons/fi';
|
||||||
@@ -31,6 +22,7 @@ function DebouncedMessage({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={closeModal}
|
handleClose={closeModal}
|
||||||
|
handleDelete={() => handleDelete(message, 'api/messages')}
|
||||||
title='Delete message'
|
title='Delete message'
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
||||||
@@ -47,25 +39,6 @@ function DebouncedMessage({
|
|||||||
}}
|
}}
|
||||||
>{`"${message.message}"`}</Text>
|
>{`"${message.message}"`}</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(message, 'api/messages');
|
|
||||||
closeModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'grey'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={closeModal}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
import {
|
import { ActionIcon, Card, Group, Stack, Text, TextInput, Tooltip } from '@mantine/core';
|
||||||
ActionIcon,
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Group,
|
|
||||||
Stack,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
|
||||||
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||||
import { useCommonHooks, useMutationAPI } from 'hooks';
|
import { useCommonHooks, useMutationAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -53,6 +44,7 @@ function DebouncedSearchProvider({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
|
handleDelete={() => handleDelete(provider, 'api/providers')}
|
||||||
title={'Delete Search Provider'}
|
title={'Delete Search Provider'}
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
||||||
@@ -69,25 +61,6 @@ function DebouncedSearchProvider({
|
|||||||
}}
|
}}
|
||||||
>{`"${provider.name}"`}</Text>
|
>{`"${provider.name}"`}</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(provider, 'api/providers');
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'grey'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={handleClose}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ const SearchProviderSettings = () => {
|
|||||||
prefix: '',
|
prefix: '',
|
||||||
};
|
};
|
||||||
const endpoint = 'api/providers';
|
const endpoint = 'api/providers';
|
||||||
const { data: providers, isFetched: providersIsFetched } = useQueryAPI({
|
const { data: providerData, isFetched: providerDataIsFetched } = useQueryAPI({
|
||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
});
|
});
|
||||||
const [providerData, setProviderData] = useState<Provider[]>([]);
|
const [providers, setProviders] = useState<Provider[]>([]);
|
||||||
const { isMobile } = useCommonHooks();
|
const { isMobile } = useCommonHooks();
|
||||||
const { mutateAsync } = useMutationAPI();
|
const { mutateAsync } = useMutationAPI();
|
||||||
const [newProvider, setNewProvider] = useState<Provider>(defaultProvider);
|
const [newProvider, setNewProvider] = useState<Provider>(defaultProvider);
|
||||||
@@ -45,16 +45,16 @@ const SearchProviderSettings = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (providers && providersIsFetched) {
|
if (providerData && providerDataIsFetched) {
|
||||||
setProviderData(
|
setProviders(
|
||||||
providers
|
providerData
|
||||||
.filter((a: Provider) =>
|
.filter((a: Provider) =>
|
||||||
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
||||||
)
|
)
|
||||||
.sort((a: Provider, b: Provider) => (a.prefix > b.prefix ? 1 : -1)),
|
.sort((a: Provider, b: Provider) => (a.prefix > b.prefix ? 1 : -1)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [providers, providersIsFetched, debouncedSearch]);
|
}, [providerData, providerDataIsFetched, debouncedSearch]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack>
|
<Stack>
|
||||||
@@ -138,16 +138,16 @@ const SearchProviderSettings = () => {
|
|||||||
<SettingsHeader
|
<SettingsHeader
|
||||||
setDragging={undefined}
|
setDragging={undefined}
|
||||||
openModal={openModal}
|
openModal={openModal}
|
||||||
title={'Search Providers'}
|
title={'Search providerData'}
|
||||||
tooltip={{
|
tooltip={{
|
||||||
title: 'Search providers and shortcuts can be configured here.',
|
title: 'Search providerData and shortcuts can be configured here.',
|
||||||
highlightList: ['Providers', 'search', 'provider', 'prefix'],
|
highlightList: ['providerData', 'search', 'provider', 'prefix'],
|
||||||
description:
|
description:
|
||||||
'Providers can be used in the search bar. By starting a search with the prefix, it will be redirected to the url of the provider to complete the search.',
|
'providerData can be used in the search bar. By starting a search with the prefix, it will be redirected to the url of the provider to complete the search.',
|
||||||
}}
|
}}
|
||||||
searchValue={searchValue}
|
searchValue={searchValue}
|
||||||
setSearchValue={setSearchValue}
|
setSearchValue={setSearchValue}
|
||||||
searchPlaceholder={'Search Search Providers...'}
|
searchPlaceholder={'Search Search providerData...'}
|
||||||
/>
|
/>
|
||||||
<Stack
|
<Stack
|
||||||
mt={isMobile ? '9rem' : '6rem'}
|
mt={isMobile ? '9rem' : '6rem'}
|
||||||
@@ -156,7 +156,7 @@ const SearchProviderSettings = () => {
|
|||||||
align='center'
|
align='center'
|
||||||
>
|
>
|
||||||
<Grid columns={18} w={'75%'}>
|
<Grid columns={18} w={'75%'}>
|
||||||
{providerData?.map((provider: Provider) => (
|
{providers?.map((provider: Provider) => (
|
||||||
<GridCol span={isMobile ? 18 : 6} key={provider.id}>
|
<GridCol span={isMobile ? 18 : 6} key={provider.id}>
|
||||||
<Popover
|
<Popover
|
||||||
withArrow
|
withArrow
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { Card, Modal } from '@mantine/core';
|
import { Button, Card, Group, Modal } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { cardClasses, modalClasses } from 'styles';
|
import { cardClasses, modalClasses } from 'styles';
|
||||||
|
|
||||||
function DeleteItemModal({
|
function DeleteItemModal({
|
||||||
modalOpened,
|
modalOpened,
|
||||||
handleClose,
|
handleClose,
|
||||||
|
handleDelete,
|
||||||
body,
|
body,
|
||||||
title,
|
title,
|
||||||
}: {
|
}: {
|
||||||
modalOpened: boolean;
|
modalOpened: boolean;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
|
handleDelete: () => void;
|
||||||
body: React.ReactNode;
|
body: React.ReactNode;
|
||||||
title: string;
|
title: string;
|
||||||
}) {
|
}) {
|
||||||
@@ -36,6 +38,25 @@ function DeleteItemModal({
|
|||||||
<Modal.Body pb={'2rem'}>
|
<Modal.Body pb={'2rem'}>
|
||||||
<Card className={cardClasses.settingsItem} classNames={cardClasses}>
|
<Card className={cardClasses.settingsItem} classNames={cardClasses}>
|
||||||
{body}
|
{body}
|
||||||
|
<Group w={'100%'} justify='center' bottom={8}>
|
||||||
|
<Button
|
||||||
|
color={'red'}
|
||||||
|
styles={{ label: { color: 'black' } }}
|
||||||
|
onClick={() => {
|
||||||
|
handleDelete();
|
||||||
|
handleClose();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
color={'grey'}
|
||||||
|
styles={{ label: { color: 'white' } }}
|
||||||
|
onClick={handleClose}
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
</Card>
|
</Card>
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ function ThemeCard({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={closeModal}
|
handleClose={closeModal}
|
||||||
|
handleDelete={() => handleDelete(cardTheme, 'api/themes')}
|
||||||
title={'Delete Theme'}
|
title={'Delete Theme'}
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
||||||
@@ -62,27 +63,6 @@ function ThemeCard({
|
|||||||
}}
|
}}
|
||||||
>{`"${cardTheme.name}"`}</Text>
|
>{`"${cardTheme.name}"`}</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(cardTheme, 'api/themes');
|
|
||||||
closeModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'grey'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
closeModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
|
|||||||
}}
|
}}
|
||||||
component='a'
|
component='a'
|
||||||
>
|
>
|
||||||
{'Link 1'}
|
{'Bookmark 1'}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
@@ -199,7 +199,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
|
|||||||
}}
|
}}
|
||||||
component='a'
|
component='a'
|
||||||
>
|
>
|
||||||
{'Link 2'}
|
{'Bookmark 2'}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack
|
<Stack
|
||||||
@@ -235,7 +235,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
|
|||||||
}}
|
}}
|
||||||
component='a'
|
component='a'
|
||||||
>
|
>
|
||||||
{'Link 1'}
|
{'Bookmark 1'}
|
||||||
</Text>
|
</Text>
|
||||||
<Text
|
<Text
|
||||||
style={{
|
style={{
|
||||||
@@ -246,7 +246,7 @@ export default function ThemeModalContent({ selectedTheme }: { selectedTheme: Th
|
|||||||
}}
|
}}
|
||||||
component='a'
|
component='a'
|
||||||
>
|
>
|
||||||
{'Link 2'}
|
{'Bookmark 2'}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ function ThemePlaylistCard({
|
|||||||
handleOpen: (cardPlaylist: ThemePlaylist) => void;
|
handleOpen: (cardPlaylist: ThemePlaylist) => void;
|
||||||
allThemes: Theme[];
|
allThemes: Theme[];
|
||||||
}) {
|
}) {
|
||||||
|
const themePlaylistEndpoint = 'api/themePlaylists';
|
||||||
const [hover, setHover] = useState(false);
|
const [hover, setHover] = useState(false);
|
||||||
const { setThemeName, setCurrentThemePlaylist, theme, handleDelete } = useCommonHooks();
|
const { setThemeName, setCurrentThemePlaylist, theme, handleDelete } = useCommonHooks();
|
||||||
const syncableLists = ['All', 'Backgrounds', 'No Backgrounds'];
|
const syncableLists = ['All', 'Backgrounds', 'No Backgrounds'];
|
||||||
@@ -45,6 +46,7 @@ function ThemePlaylistCard({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={closeModal}
|
handleClose={closeModal}
|
||||||
|
handleDelete={() => handleDelete(cardPlaylist, 'api/themePlaylists')}
|
||||||
title='Delete Theme Playlist'
|
title='Delete Theme Playlist'
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
||||||
@@ -61,27 +63,6 @@ function ThemePlaylistCard({
|
|||||||
}}
|
}}
|
||||||
>{`"${cardPlaylist.name}"`}</Text>
|
>{`"${cardPlaylist.name}"`}</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(cardPlaylist, 'api/themePlaylists');
|
|
||||||
closeModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'grey'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
closeModal();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
@@ -124,7 +105,7 @@ function ThemePlaylistCard({
|
|||||||
if (cardPlaylist.name === 'All') {
|
if (cardPlaylist.name === 'All') {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
endpoint: 'api/themePlaylists',
|
endpoint: themePlaylistEndpoint,
|
||||||
body: {
|
body: {
|
||||||
id: cardPlaylist.id,
|
id: cardPlaylist.id,
|
||||||
name: 'All',
|
name: 'All',
|
||||||
@@ -135,7 +116,7 @@ function ThemePlaylistCard({
|
|||||||
if (cardPlaylist.name === 'Backgrounds') {
|
if (cardPlaylist.name === 'Backgrounds') {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
endpoint: 'api/themePlaylists',
|
endpoint: themePlaylistEndpoint,
|
||||||
body: {
|
body: {
|
||||||
id: cardPlaylist.id,
|
id: cardPlaylist.id,
|
||||||
name: 'Backgrounds',
|
name: 'Backgrounds',
|
||||||
@@ -152,7 +133,7 @@ function ThemePlaylistCard({
|
|||||||
if (cardPlaylist.name === 'No Backgrounds') {
|
if (cardPlaylist.name === 'No Backgrounds') {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
endpoint: 'api/themePlaylists',
|
endpoint: themePlaylistEndpoint,
|
||||||
body: {
|
body: {
|
||||||
id: cardPlaylist.id,
|
id: cardPlaylist.id,
|
||||||
name: 'No Backgrounds',
|
name: 'No Backgrounds',
|
||||||
|
|||||||
@@ -11,11 +11,11 @@ import ThemePlaylistModal from './ThemePlaylistModal';
|
|||||||
|
|
||||||
function ThemePlaylists() {
|
function ThemePlaylists() {
|
||||||
const themesEndpoint = 'api/themes';
|
const themesEndpoint = 'api/themes';
|
||||||
const { data: allThemes } = useQueryAPI({
|
const { data: allThemeData } = useQueryAPI({
|
||||||
endpoint: themesEndpoint,
|
endpoint: themesEndpoint,
|
||||||
});
|
});
|
||||||
const themePlaylistsEndpoint = 'api/themePlaylists';
|
const themePlaylistsEndpoint = 'api/themePlaylists';
|
||||||
const { data: themePlaylists } = useQueryAPI({
|
const { data: themePlaylistData } = useQueryAPI({
|
||||||
endpoint: themePlaylistsEndpoint,
|
endpoint: themePlaylistsEndpoint,
|
||||||
});
|
});
|
||||||
const defaultPlaylist = {
|
const defaultPlaylist = {
|
||||||
@@ -60,7 +60,7 @@ function ThemePlaylists() {
|
|||||||
defaultPlaylist={defaultPlaylist}
|
defaultPlaylist={defaultPlaylist}
|
||||||
setSelectedPlaylist={setSelectedPlaylist}
|
setSelectedPlaylist={setSelectedPlaylist}
|
||||||
handleSavePlaylist={handleSavePlaylist}
|
handleSavePlaylist={handleSavePlaylist}
|
||||||
allThemes={allThemes}
|
allThemes={allThemeData}
|
||||||
createPlaylist={mutateAsync}
|
createPlaylist={mutateAsync}
|
||||||
/>
|
/>
|
||||||
<Stack h={'100%'} w={'100%'}>
|
<Stack h={'100%'} w={'100%'}>
|
||||||
@@ -84,7 +84,7 @@ function ThemePlaylists() {
|
|||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group justify='center' align='center' pos={'relative'}>
|
<Group justify='center' align='center' pos={'relative'}>
|
||||||
{themePlaylists
|
{themePlaylistData
|
||||||
?.filter((playlist: ThemePlaylist) => playlist.default === 1)
|
?.filter((playlist: ThemePlaylist) => playlist.default === 1)
|
||||||
?.filter((a: ThemePlaylist) =>
|
?.filter((a: ThemePlaylist) =>
|
||||||
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
||||||
@@ -113,7 +113,7 @@ function ThemePlaylists() {
|
|||||||
<ThemePlaylistCard
|
<ThemePlaylistCard
|
||||||
cardPlaylist={cardPlaylist}
|
cardPlaylist={cardPlaylist}
|
||||||
handleOpen={handleOpen}
|
handleOpen={handleOpen}
|
||||||
allThemes={allThemes}
|
allThemes={allThemeData}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Group>
|
</Group>
|
||||||
@@ -131,7 +131,7 @@ function ThemePlaylists() {
|
|||||||
pos={'relative'}
|
pos={'relative'}
|
||||||
mb={isMobile ? '6rem' : undefined}
|
mb={isMobile ? '6rem' : undefined}
|
||||||
>
|
>
|
||||||
{themePlaylists
|
{themePlaylistData
|
||||||
?.filter((playlist: ThemePlaylist) => playlist.default === 0)
|
?.filter((playlist: ThemePlaylist) => playlist.default === 0)
|
||||||
?.filter((a: ThemePlaylist) =>
|
?.filter((a: ThemePlaylist) =>
|
||||||
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
||||||
@@ -161,7 +161,7 @@ function ThemePlaylists() {
|
|||||||
<ThemePlaylistCard
|
<ThemePlaylistCard
|
||||||
cardPlaylist={cardPlaylist}
|
cardPlaylist={cardPlaylist}
|
||||||
handleOpen={handleOpen}
|
handleOpen={handleOpen}
|
||||||
allThemes={allThemes}
|
allThemes={allThemeData}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import ThemeModal from './ThemeModal';
|
|||||||
function ThemesSettings() {
|
function ThemesSettings() {
|
||||||
const themesEndpoint = 'api/themes';
|
const themesEndpoint = 'api/themes';
|
||||||
const backgroundsEndpoint = 'api/backgrounds';
|
const backgroundsEndpoint = 'api/backgrounds';
|
||||||
const { data: allThemes } = useQueryAPI({
|
const { data: allThemeData } = useQueryAPI({
|
||||||
endpoint: 'api/themes',
|
endpoint: 'api/themes',
|
||||||
});
|
});
|
||||||
const { data: backgroundData, isFetched: isBackgroundFetched } = useQueryAPI({
|
const { data: backgroundData, isFetched: isBackgroundFetched } = useQueryAPI({
|
||||||
@@ -161,7 +161,7 @@ function ThemesSettings() {
|
|||||||
}}
|
}}
|
||||||
pos={'absolute'}
|
pos={'absolute'}
|
||||||
/>
|
/>
|
||||||
{allThemes
|
{allThemeData
|
||||||
?.filter((a: Theme) =>
|
?.filter((a: Theme) =>
|
||||||
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
a.name.toLowerCase().includes(debouncedSearch.toLowerCase()),
|
||||||
)
|
)
|
||||||
@@ -191,7 +191,7 @@ function ThemesSettings() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ThemeCard
|
<ThemeCard
|
||||||
allThemes={allThemes}
|
allThemes={allThemeData}
|
||||||
cardTheme={cardTheme}
|
cardTheme={cardTheme}
|
||||||
handleOpen={handleOpen}
|
handleOpen={handleOpen}
|
||||||
themePlaylists={themePlaylists}
|
themePlaylists={themePlaylists}
|
||||||
|
|||||||
@@ -1,13 +1,4 @@
|
|||||||
import {
|
import { ActionIcon, Card, Group, Stack, Text, TextInput, Tooltip } from '@mantine/core';
|
||||||
ActionIcon,
|
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Group,
|
|
||||||
Stack,
|
|
||||||
Text,
|
|
||||||
TextInput,
|
|
||||||
Tooltip,
|
|
||||||
} from '@mantine/core';
|
|
||||||
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
import { useDebouncedValue, useDisclosure } from '@mantine/hooks';
|
||||||
import { useCommonHooks, useMutationAPI } from 'hooks';
|
import { useCommonHooks, useMutationAPI } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
@@ -52,6 +43,7 @@ function DebouncedWolClient({
|
|||||||
<DeleteItemModal
|
<DeleteItemModal
|
||||||
modalOpened={modalOpened}
|
modalOpened={modalOpened}
|
||||||
handleClose={handleClose}
|
handleClose={handleClose}
|
||||||
|
handleDelete={() => handleDelete(client, 'api/WolClients')}
|
||||||
title={'Delete WoL Client'}
|
title={'Delete WoL Client'}
|
||||||
body={
|
body={
|
||||||
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
<Stack gap={0} w={'100%'} h={'150px'} align='center'>
|
||||||
@@ -68,25 +60,6 @@ function DebouncedWolClient({
|
|||||||
}}
|
}}
|
||||||
>{`"${client.hostname}"`}</Text>
|
>{`"${client.hostname}"`}</Text>
|
||||||
<Text c='red'>This action cannot be undone!</Text>
|
<Text c='red'>This action cannot be undone!</Text>
|
||||||
<Group pos={'absolute'} bottom={8}>
|
|
||||||
<Button
|
|
||||||
color={'red'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={() => {
|
|
||||||
handleDelete(client, 'api/WolClients');
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Delete
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color={'grey'}
|
|
||||||
styles={{ label: { color: 'black' } }}
|
|
||||||
onClick={handleClose}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.linkCategory {
|
.bookmarkCategory {
|
||||||
&.root {
|
&.root {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.linkItem {
|
.bookmarkItem {
|
||||||
&.root {
|
&.root {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
|||||||
Reference in New Issue
Block a user