Merge branch 'dev' into drop-cache

This commit is contained in:
Thomas Camlong
2023-05-16 13:54:43 +09:00
committed by GitHub
90 changed files with 2106 additions and 1350 deletions

View File

@@ -19,6 +19,9 @@ env:
REGISTRY: ghcr.io REGISTRY: ghcr.io
# github.repository as <account>/<repo> # github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }} IMAGE_NAME: ${{ github.repository }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
jobs: jobs:
# Push image to GitHub Packages. # Push image to GitHub Packages.

View File

@@ -1,8 +1,5 @@
name: Development CI name: Development CI
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
on: on:
push: push:
branches: [dev] branches: [dev]
@@ -19,6 +16,10 @@ on:
required: true required: true
description: 'Tag to deploy to' description: 'Tag to deploy to'
defaults:
run:
working-directory: ./
env: env:
# Use docker.io for Docker Hub if empty # Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io REGISTRY: ghcr.io
@@ -27,6 +28,10 @@ env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
permissions:
contents: read # for checkout repository
actions: read # for fetching base branch bundle stats
pull-requests: write # for comments
jobs: jobs:
# Push image to GitHub Packages. # Push image to GitHub Packages.
@@ -56,17 +61,14 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-yarn- ${{ runner.os }}-yarn-
- name: Restore NextJS cache - name: Restore next build
uses: actions/cache@v2 uses: actions/cache@v3
id: restore-build-cache
env:
cache-name: cache-next-build
with: with:
# See here for caching with `yarn` https://github.com/actions/cache/blob/main/examples.md#node---yarn or you can leverage caching with actions/setup-node https://github.com/actions/setup-node path: .next/cache
path: | key: ${{ runner.os }}-build-${{ env.cache-name }}
${{ github.workspace }}/.next/cache
# Generate a new cache whenever packages or source files change.
key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }}
# If source files changed but packages didn't, rebuild from a prior cache.
restore-keys: |
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
- run: yarn install --immutable - run: yarn install --immutable
@@ -110,3 +112,95 @@ jobs:
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha cache-from: type=gha
cache-to: type=gha,mode=max cache-to: type=gha,mode=max
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn config get cacheFolder)"
- uses: actions/cache@v3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Restore next build
uses: actions/cache@v3
id: restore-build-cache
env:
cache-name: cache-next-build
with:
# if you use a custom build directory, replace all instances of `.next` in this file with your build directory
# ex: if your app builds to `dist`, replace `.next` with `dist`
path: .next/cache
# change this if you prefer a more strict cache
key: ${{ runner.os }}-build-${{ env.cache-name }}
- run: yarn install
- name: Build next.js app
# change this if your site requires a custom build command
run: yarn turbo build
# Here's the first place where next-bundle-analysis' own script is used
# This step pulls the raw bundle stats for the current bundle
- name: Analyze bundle
run: npx -p nextjs-bundle-analysis report
- name: Upload bundle
uses: actions/upload-artifact@v3
with:
name: bundle
path: .next/analyze/__bundle_analysis.json
- name: Download base branch bundle stats
uses: dawidd6/action-download-artifact@v2
continue-on-error: true
if: success() && github.event.number
with:
workflow: nextjs_bundle_analysis.yml
branch: ${{ github.event.pull_request.base.ref }}
path: .next/analyze/base
# And here's the second place - this runs after we have both the current and
# base branch bundle stats, and will compare them to determine what changed.
# There are two configurable arguments that come from package.json:
#
# - budget: optional, set a budget (bytes) against which size changes are measured
# it's set to 350kb here by default, as informed by the following piece:
# https://infrequently.org/2021/03/the-performance-inequality-gap/
#
# - red-status-percentage: sets the percent size increase where you get a red
# status indicator, defaults to 20%
#
# Either of these arguments can be changed or removed by editing the `nextBundleAnalysis`
# entry in your package.json file.
- name: Compare with base branch bundle
if: success() && github.event.number
run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare
- name: Get Comment Body
id: get-comment-body
if: success() && github.event.number
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
run: |
echo "body<<EOF" >> $GITHUB_OUTPUT
echo "$(cat .next/analyze/__bundle_analysis_comment.txt)" >> $GITHUB_OUTPUT
echo EOF >> $GITHUB_OUTPUT
- name: Comment
uses: marocchino/sticky-pull-request-comment@v2
with:
header: next-touched-pages
message: ${{ steps.get-comment-body.outputs.body }}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

873
.yarn/releases/yarn-3.5.1.cjs vendored Executable file

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,3 @@
nodeLinker: node-modules nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-3.2.1.cjs yarnPath: .yarn/releases/yarn-3.5.1.cjs

View File

@@ -25,7 +25,7 @@
}, },
"dependencies": { "dependencies": {
"@ctrl/deluge": "^4.1.0", "@ctrl/deluge": "^4.1.0",
"@ctrl/qbittorrent": "^4.1.0", "@ctrl/qbittorrent": "^6.0.0",
"@ctrl/shared-torrent": "^4.1.1", "@ctrl/shared-torrent": "^4.1.1",
"@ctrl/transmission": "^4.1.1", "@ctrl/transmission": "^4.1.1",
"@emotion/react": "^11.10.6", "@emotion/react": "^11.10.6",
@@ -42,14 +42,14 @@
"@nivo/core": "^0.80.0", "@nivo/core": "^0.80.0",
"@nivo/line": "^0.80.0", "@nivo/line": "^0.80.0",
"@react-native-async-storage/async-storage": "^1.18.1", "@react-native-async-storage/async-storage": "^1.18.1",
"@tabler/icons": "^1.106.0", "@tabler/icons-react": "^2.18.0",
"@tanstack/query-async-storage-persister": "^4.27.1", "@tanstack/query-async-storage-persister": "^4.27.1",
"@tanstack/query-sync-storage-persister": "^4.27.1", "@tanstack/query-sync-storage-persister": "^4.27.1",
"@tanstack/react-query": "^4.2.1", "@tanstack/react-query": "^4.2.1",
"@tanstack/react-query-devtools": "^4.24.4", "@tanstack/react-query-devtools": "^4.24.4",
"@tanstack/react-query-persist-client": "^4.28.0", "@tanstack/react-query-persist-client": "^4.28.0",
"@vitejs/plugin-react": "^3.1.0", "@vitejs/plugin-react": "^3.1.0",
"axios": "^0.27.2", "axios": "^1.0.0",
"consola": "^2.15.3", "consola": "^2.15.3",
"cookies-next": "^2.1.1", "cookies-next": "^2.1.1",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
@@ -75,8 +75,8 @@
"zustand": "^4.3.7" "zustand": "^4.3.7"
}, },
"devDependencies": { "devDependencies": {
"@next/bundle-analyzer": "^12.1.4", "@next/bundle-analyzer": "^13.0.0",
"@next/eslint-plugin-next": "^12.1.4", "@next/eslint-plugin-next": "^13.0.0",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0", "@testing-library/react": "^14.0.0",
"@types/dockerode": "^3.3.9", "@types/dockerode": "^3.3.9",
@@ -105,7 +105,7 @@
"prettier": "^2.7.1", "prettier": "^2.7.1",
"sass": "^1.56.1", "sass": "^1.56.1",
"turbo": "latest", "turbo": "latest",
"typescript": "^4.7.4", "typescript": "^5.0.0",
"video.js": "^8.0.3", "video.js": "^8.0.3",
"vitest": "^0.29.3", "vitest": "^0.29.3",
"vitest-fetch-mock": "^0.2.2" "vitest-fetch-mock": "^0.2.2"
@@ -114,5 +114,11 @@
"@types/react": "17.0.2", "@types/react": "17.0.2",
"@types/react-dom": "17.0.2" "@types/react-dom": "17.0.2"
}, },
"packageManager": "yarn@3.2.1" "packageManager": "yarn@3.5.1",
"nextBundleAnalysis": {
"budget": null,
"budgetPercentIncreaseRed": 20,
"minimumChangeThreshold": 0,
"showDetails": true
}
} }

View File

@@ -0,0 +1,21 @@
{
"descriptor": {
"name": "Bookmark",
"description": "Displays a static list of strings or links",
"settings": {
"title": "Bookmark settings",
"items": {
"label": "Items"
},
"layout": {
"label": "Layout"
}
}
},
"card": {
"noneFound": {
"title": "Bookmark list empty",
"text": "Add new items to this list in the edit mode"
}
}
}

View File

@@ -0,0 +1,7 @@
{
"noEntries": {
"title": "No entries",
"text": "Use the buttons below to add more entries"
},
"buttonAdd": "Add"
}

6
renovate.json Normal file
View File

@@ -0,0 +1,6 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base"
]
}

View File

@@ -1,7 +1,7 @@
import { Group, Stack, Text, Title, useMantineTheme } from '@mantine/core'; import { Group, Stack, Text, Title, useMantineTheme } from '@mantine/core';
import { Dropzone } from '@mantine/dropzone'; import { Dropzone } from '@mantine/dropzone';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconCheck as Check, IconPhoto, IconUpload, IconX, IconX as X } from '@tabler/icons'; import { IconCheck as Check, IconPhoto, IconUpload, IconX, IconX as X } from '@tabler/icons-react';
import { setCookie } from 'cookies-next'; import { setCookie } from 'cookies-next';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useConfigStore } from '../../config/store'; import { useConfigStore } from '../../config/store';

View File

@@ -1,6 +1,6 @@
import { ActionIcon, createStyles, Space } from '@mantine/core'; import { ActionIcon, createStyles, Space } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks'; import { useDisclosure } from '@mantine/hooks';
import { IconChevronLeft, IconChevronRight } from '@tabler/icons'; import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';
import { useScreenLargerThan } from '../../../../hooks/useScreenLargerThan'; import { useScreenLargerThan } from '../../../../hooks/useScreenLargerThan';
import { MobileRibbonSidebarDrawer } from './MobileRibbonSidebarDrawer'; import { MobileRibbonSidebarDrawer } from './MobileRibbonSidebarDrawer';

View File

@@ -26,7 +26,7 @@ import {
IconVersions, IconVersions,
IconVocabulary, IconVocabulary,
IconWorldWww, IconWorldWww,
} from '@tabler/icons'; } from '@tabler/icons-react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { InitOptions } from 'i18next'; import { InitOptions } from 'i18next';
import { i18n, Trans, useTranslation } from 'next-i18next'; import { i18n, Trans, useTranslation } from 'next-i18next';

View File

@@ -9,19 +9,19 @@ import {
IconBrush, IconBrush,
IconClick, IconClick,
IconPlug, IconPlug,
} from '@tabler/icons'; } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useState } from 'react'; import { useState } from 'react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';
import { useConfigStore } from '../../../../config/store'; import { useConfigStore } from '../../../../config/store';
import { AppType } from '../../../../types/app'; import { AppType } from '../../../../types/app';
import { DebouncedImage } from '../../../IconSelector/DebouncedImage';
import { useEditModeStore } from '../../Views/useEditModeStore'; import { useEditModeStore } from '../../Views/useEditModeStore';
import { AppearanceTab } from './Tabs/AppereanceTab/AppereanceTab'; import { AppearanceTab } from './Tabs/AppereanceTab/AppereanceTab';
import { BehaviourTab } from './Tabs/BehaviourTab/BehaviourTab'; import { BehaviourTab } from './Tabs/BehaviourTab/BehaviourTab';
import { GeneralTab } from './Tabs/GeneralTab/GeneralTab'; import { GeneralTab } from './Tabs/GeneralTab/GeneralTab';
import { IntegrationTab } from './Tabs/IntegrationTab/IntegrationTab'; import { IntegrationTab } from './Tabs/IntegrationTab/IntegrationTab';
import { NetworkTab } from './Tabs/NetworkTab/NetworkTab'; import { NetworkTab } from './Tabs/NetworkTab/NetworkTab';
import { DebouncedAppIcon } from './Tabs/Shared/DebouncedAppIcon';
import { EditAppModalTab } from './Tabs/type'; import { EditAppModalTab } from './Tabs/type';
const appUrlRegex = const appUrlRegex =
@@ -138,7 +138,7 @@ export const EditAppModal = ({
</Alert> </Alert>
))} ))}
<Stack spacing={0} align="center" my="lg"> <Stack spacing={0} align="center" my="lg">
<DebouncedAppIcon form={form} width={120} height={120} /> <DebouncedImage src={form.values.appearance.iconUrl} width={120} height={120} />
<Text align="center" weight="bold" size="lg" mt="md"> <Text align="center" weight="bold" size="lg" mt="md">
{form.values.name ?? 'New App'} {form.values.name ?? 'New App'}

View File

@@ -1,10 +1,9 @@
import { Flex, Tabs } from '@mantine/core'; import { Flex, Tabs } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form'; import { UseFormReturnType } from '@mantine/form';
import { useDebouncedValue } from '@mantine/hooks'; import { useDebouncedValue } from '@mantine/hooks';
import { useEffect } from 'react'; import { useEffect, useRef } from 'react';
import { useGetDashboardIcons } from '../../../../../../hooks/icons/useGetDashboardIcons';
import { AppType } from '../../../../../../types/app'; import { AppType } from '../../../../../../types/app';
import { IconSelector } from './IconSelector'; import { IconSelector } from '../../../../../IconSelector/IconSelector';
interface AppearanceTabProps { interface AppearanceTabProps {
form: UseFormReturnType<AppType, (values: AppType) => AppType>; form: UseFormReturnType<AppType, (values: AppType) => AppType>;
@@ -17,8 +16,7 @@ export const AppearanceTab = ({
disallowAppNameProgagation, disallowAppNameProgagation,
allowAppNamePropagation, allowAppNamePropagation,
}: AppearanceTabProps) => { }: AppearanceTabProps) => {
const { data, isLoading } = useGetDashboardIcons(); const iconSelectorRef = useRef();
const [debouncedValue] = useDebouncedValue(form.values.name, 500); const [debouncedValue] = useDebouncedValue(form.values.name, 500);
useEffect(() => { useEffect(() => {
@@ -26,26 +24,28 @@ export const AppearanceTab = ({
return; return;
} }
const matchingDebouncedIcon = data if (!iconSelectorRef.current) {
?.flatMap((x) => x.entries)
.find((x) => replaceCharacters(x.name.split('.')[0]) === replaceCharacters(debouncedValue));
if (!matchingDebouncedIcon) {
return; return;
} }
form.setFieldValue('appearance.iconUrl', matchingDebouncedIcon.url); const currentRef = iconSelectorRef.current as {
chooseFirstOrDefault: (debouncedValue: string) => void;
};
currentRef.chooseFirstOrDefault(debouncedValue);
}, [debouncedValue]); }, [debouncedValue]);
return ( return (
<Tabs.Panel value="appearance" pt="lg"> <Tabs.Panel value="appearance" pt="lg">
<Flex gap={5}> <Flex gap={5}>
<IconSelector <IconSelector
form={form} defaultValue={form.values.appearance.iconUrl}
data={data} onChange={(value) => {
isLoading={isLoading} form.setFieldValue('appearance.iconUrl', value);
allowAppNamePropagation={allowAppNamePropagation} disallowAppNameProgagation();
disallowAppNameProgagation={disallowAppNameProgagation} }}
value={form.values.appearance.iconUrl}
ref={iconSelectorRef}
/> />
</Flex> </Flex>
</Tabs.Panel> </Tabs.Panel>

View File

@@ -1,164 +0,0 @@
import {
Autocomplete,
Box,
CloseButton,
createStyles,
Group,
Image,
Loader,
ScrollArea,
SelectItemProps,
Stack,
Text,
Title,
} from '@mantine/core';
import { UseFormReturnType } from '@mantine/form';
import { IconSearch } from '@tabler/icons';
import { useTranslation } from 'next-i18next';
import { forwardRef } from 'react';
import { humanFileSize } from '../../../../../../tools/humanFileSize';
import { NormalizedIconRepositoryResult } from '../../../../../../tools/server/images/abstract-icons-repository';
import { AppType } from '../../../../../../types/app';
import { DebouncedAppIcon } from '../Shared/DebouncedAppIcon';
interface IconSelectorProps {
form: UseFormReturnType<AppType, (values: AppType) => AppType>;
data: NormalizedIconRepositoryResult[] | undefined;
isLoading: boolean;
disallowAppNameProgagation: () => void;
allowAppNamePropagation: boolean;
}
export const IconSelector = ({
form,
data,
isLoading,
allowAppNamePropagation,
disallowAppNameProgagation,
}: IconSelectorProps) => {
const { t } = useTranslation('layout/modals/add-app');
const { classes } = useStyles();
const a =
data === undefined
? []
: data.flatMap((repository) =>
repository.entries.map((entry) => ({
url: entry.url,
label: entry.name,
size: entry.size,
value: entry.url,
group: repository.name,
copyright: repository.copyright,
}))
);
return (
<Stack w="100%">
<Autocomplete
nothingFound={
<Stack align="center" spacing="xs" my="lg">
<IconSearch />
<Title order={6} align="center">
{t('appearance.icon.autocomplete.title')}
</Title>
<Text align="center" maw={350}>
{t('appearance.icon.autocomplete.text')}
</Text>
</Stack>
}
icon={<DebouncedAppIcon form={form} width={20} height={20} />}
rightSection={
form.values.appearance.iconUrl.length > 0 ? (
<CloseButton onClick={() => form.setFieldValue('appearance.iconUrl', '')} />
) : null
}
itemComponent={AutoCompleteItem}
className={classes.textInput}
data={a}
limit={25}
label={t('appearance.icon.label')}
description={t('appearance.icon.description', {
suggestionsCount: data?.reduce((a, b) => a + b.count, 0) ?? 0,
})}
filter={(search, item) =>
item.value
.toLowerCase()
.replaceAll('_', '')
.replaceAll(' ', '-')
.includes(search.toLowerCase().replaceAll('_', '').replaceAll(' ', '-'))
}
variant="default"
withAsterisk
dropdownComponent={(props: any) => <ScrollArea {...props} mah={250} />}
dropdownPosition="bottom"
required
onChange={(event) => {
if (allowAppNamePropagation) {
disallowAppNameProgagation();
}
form.setFieldValue('appearance.iconUrl', event);
}}
value={form.values.appearance.iconUrl}
/>
{(!data || isLoading) && (
<Group>
<Loader variant="oval" size="sm" />
<Stack spacing={0}>
<Text size="xs" weight="bold">
{t('appearance.icon.noItems.title')}
</Text>
<Text color="dimmed" size="xs">
{t('appearance.icon.noItems.text')}
</Text>
</Stack>
</Group>
)}
</Stack>
);
};
const useStyles = createStyles(() => ({
textInput: {
flexGrow: 1,
},
}));
const AutoCompleteItem = forwardRef<HTMLDivElement, ItemProps>(
({ label, size, copyright, url, ...others }: ItemProps, ref) => (
<div ref={ref} {...others}>
<Group noWrap>
<Box
sx={(theme) => ({
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2],
borderRadius: theme.radius.md,
})}
p={2}
>
<Image src={url} width={30} height={30} fit="contain" />
</Box>
<Stack spacing={0}>
<Text>{label}</Text>
<Group>
<Text color="dimmed" size="xs">
{humanFileSize(size, false)}
</Text>
{copyright && (
<Text color="dimmed" size="xs">
© {copyright}
</Text>
)}
</Group>
</Stack>
</Group>
</div>
)
);
interface ItemProps extends SelectItemProps {
url: string;
group: string;
size: number;
copyright: string | undefined;
}

View File

@@ -1,6 +1,6 @@
import { Tabs, TextInput } from '@mantine/core'; import { Tabs, TextInput } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form'; import { UseFormReturnType } from '@mantine/form';
import { IconClick, IconCursorText, IconLink } from '@tabler/icons'; import { IconClick, IconCursorText, IconLink } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { AppType } from '../../../../../../types/app'; import { AppType } from '../../../../../../types/app';
import { EditAppModalTab } from '../type'; import { EditAppModalTab } from '../type';

View File

@@ -12,7 +12,7 @@ import {
Badge, Badge,
Tooltip, Tooltip,
} from '@mantine/core'; } from '@mantine/core';
import { TablerIcon } from '@tabler/icons'; import { Icon } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useState } from 'react'; import { useState } from 'react';
import { AppIntegrationPropertyAccessabilityType } from '../../../../../../../../types/app'; import { AppIntegrationPropertyAccessabilityType } from '../../../../../../../../types/app';
@@ -20,7 +20,7 @@ import { AppIntegrationPropertyAccessabilityType } from '../../../../../../../..
interface GenericSecretInputProps { interface GenericSecretInputProps {
label: string; label: string;
value: string; value: string;
setIcon: TablerIcon; setIcon: Icon;
secretIsPresent: boolean; secretIsPresent: boolean;
type: AppIntegrationPropertyAccessabilityType; type: AppIntegrationPropertyAccessabilityType;
onClickUpdateButton: (value: string | undefined) => void; onClickUpdateButton: (value: string | undefined) => void;

View File

@@ -1,6 +1,6 @@
import { Stack } from '@mantine/core'; import { Stack } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form'; import { UseFormReturnType } from '@mantine/form';
import { IconKey } from '@tabler/icons'; import { IconKey } from '@tabler/icons-react';
import { import {
IntegrationField, IntegrationField,
integrationFieldDefinitions, integrationFieldDefinitions,

View File

@@ -1,6 +1,6 @@
import { Alert, Divider, Tabs, Text } from '@mantine/core'; import { Alert, Divider, Tabs, Text } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form'; import { UseFormReturnType } from '@mantine/form';
import { IconAlertTriangle } from '@tabler/icons'; import { IconAlertTriangle } from '@tabler/icons-react';
import { Trans, useTranslation } from 'next-i18next'; import { Trans, useTranslation } from 'next-i18next';
import { AppType } from '../../../../../../types/app'; import { AppType } from '../../../../../../types/app';
import { IntegrationSelector } from './Components/InputElements/IntegrationSelector'; import { IntegrationSelector } from './Components/InputElements/IntegrationSelector';

View File

@@ -1,7 +1,7 @@
import { Group, Space, Stack, Text, UnstyledButton } from '@mantine/core'; import { Group, Space, Stack, Text, UnstyledButton } from '@mantine/core';
import { closeModal } from '@mantine/modals'; import { closeModal } from '@mantine/modals';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconBox, IconBoxAlignTop, IconStack } from '@tabler/icons'; import { IconBox, IconBoxAlignTop, IconStack } from '@tabler/icons-react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { ReactNode } from 'react'; import { ReactNode } from 'react';

View File

@@ -1,5 +1,5 @@
import { Button, Card, Center, Grid, Stack, Text } from '@mantine/core'; import { Button, Card, Center, Grid, Stack, Text } from '@mantine/core';
import { TablerIcon } from '@tabler/icons'; import { Icon } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import Image from 'next/image'; import Image from 'next/image';
import React from 'react'; import React from 'react';
@@ -9,7 +9,7 @@ interface GenericAvailableElementTypeProps {
name: string; name: string;
handleAddition: () => Promise<void>; handleAddition: () => Promise<void>;
description?: string; description?: string;
image: string | TablerIcon; image: string | Icon;
disabled?: boolean; disabled?: boolean;
} }

View File

@@ -1,5 +1,5 @@
import { Button, Text } from '@mantine/core'; import { Button, Text } from '@mantine/core';
import { IconArrowNarrowLeft } from '@tabler/icons'; import { IconArrowNarrowLeft } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
interface SelectorBackArrowProps { interface SelectorBackArrowProps {

View File

@@ -1,5 +1,5 @@
import { Grid, Text } from '@mantine/core'; import { Grid, Text } from '@mantine/core';
import { IconCursorText } from '@tabler/icons'; import { IconCursorText } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { GenericAvailableElementType } from '../Shared/GenericElementType'; import { GenericAvailableElementType } from '../Shared/GenericElementType';
import { SelectorBackArrow } from '../Shared/SelectorBackArrow'; import { SelectorBackArrow } from '../Shared/SelectorBackArrow';

View File

@@ -1,6 +1,6 @@
import { useModals } from '@mantine/modals'; import { useModals } from '@mantine/modals';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconChecks, TablerIcon } from '@tabler/icons'; import { IconChecks, Icon } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
import { useConfigContext } from '../../../../../../config/provider'; import { useConfigContext } from '../../../../../../config/provider';
@@ -11,7 +11,7 @@ import { GenericAvailableElementType } from '../Shared/GenericElementType';
interface WidgetElementTypeProps { interface WidgetElementTypeProps {
id: string; id: string;
image: string | TablerIcon; image: string | Icon;
disabled?: boolean; disabled?: boolean;
widget: IWidgetDefinition; widget: IWidgetDefinition;
} }

View File

@@ -1,5 +1,5 @@
import { ActionIcon, Menu } from '@mantine/core'; import { ActionIcon, Menu } from '@mantine/core';
import { IconDots, IconLayoutKanban, IconPencil, IconTrash } from '@tabler/icons'; import { IconDots, IconLayoutKanban, IconPencil, IconTrash } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useEditModeStore } from '../Views/useEditModeStore'; import { useEditModeStore } from '../Views/useEditModeStore';

View File

@@ -0,0 +1,138 @@
import { Collapse, Flex, Stack, Text, createStyles } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { IconChevronDown, IconGripVertical } from '@tabler/icons-react';
import { Reorder, useDragControls } from 'framer-motion';
import { FC, useEffect, useRef } from 'react';
import { IDraggableEditableListInputValue } from '../../../../../widgets/widgets';
interface DraggableListProps {
items: {
data: { id: string } & any;
}[];
value: IDraggableEditableListInputValue<any>['defaultValue'];
onChange: (value: IDraggableEditableListInputValue<any>['defaultValue']) => void;
options: IDraggableEditableListInputValue<any>;
}
export const DraggableList = ({ items, value, onChange, options }: DraggableListProps) => (
<div>
<Reorder.Group
axis="y"
values={items.map((x) => x.data.id)}
onReorder={(order) => onChange(order.map((id) => value.find((v) => v.id === id)!))}
as="div"
>
{items.map(({ data }) => (
<ListItem key={data.id} item={data} label={options.getLabel(data)}>
<options.itemComponent
data={data}
onChange={(data: any) => {
onChange(
items.map((item) => {
if (item.data.id === data.id) return data;
return item.data;
})
);
}}
delete={() => {
onChange(items.filter((item) => item.data.id !== data.id).map((item) => item.data));
}}
/>
</ListItem>
))}
</Reorder.Group>
</div>
);
const ListItem: FC<{
item: any;
label: string | JSX.Element;
}> = ({ item, label, children }) => {
const [opened, handlers] = useDisclosure(false);
const { classes, cx } = useStyles();
const controls = useDragControls();
// Workaround for mobile drag controls not working
// https://github.com/framer/motion/issues/1597#issuecomment-1235026724
const dragRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const touchHandler: EventListener = (e) => e.preventDefault();
const dragItem = dragRef.current;
if (dragItem) {
dragItem.addEventListener('touchstart', touchHandler, { passive: false });
return () => {
dragItem.removeEventListener('touchstart', touchHandler);
};
}
return undefined;
}, [dragRef]);
return (
<Reorder.Item value={item.id} dragListener={false} dragControls={controls} as="div">
<div className={classes.container}>
<div className={classes.row}>
<Flex ref={dragRef} onPointerDown={(e) => controls.start(e)}>
<IconGripVertical className={classes.clickableIcons} size={18} stroke={1.5} />
</Flex>
<div className={classes.middle}>
<Text className={classes.symbol}>{label}</Text>
</div>
<IconChevronDown
className={cx(classes.clickableIcons, { [classes.rotate]: opened })}
onClick={() => handlers.toggle()}
size={18}
stroke={1.5}
/>
</div>
<Collapse in={opened}>
<Stack className={classes.collapseContent}>{children}</Stack>
</Collapse>
</div>
</Reorder.Item>
);
};
const useStyles = createStyles((theme) => ({
container: {
display: 'flex',
flexDirection: 'column',
borderRadius: theme.radius.md,
border: `1px solid ${
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2]
}`,
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.white,
marginBottom: theme.spacing.xs,
},
row: {
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
padding: '12px 16px',
gap: theme.spacing.sm,
},
middle: {
flexGrow: 1,
},
symbol: {
fontSize: 16,
},
clickableIcons: {
color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[6],
cursor: 'pointer',
userSelect: 'none',
transition: 'transform .3s ease-in-out',
},
rotate: {
transform: 'rotate(180deg)',
},
collapseContent: {
padding: '12px 16px',
},
}));

View File

@@ -1,9 +1,9 @@
import { Collapse, createStyles, Flex, Stack, Text } from '@mantine/core'; import { Collapse, createStyles, Flex, Stack, Text } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks'; import { useDisclosure } from '@mantine/hooks';
import { IconChevronDown, IconGripVertical } from '@tabler/icons'; import { IconChevronDown, IconGripVertical } from '@tabler/icons-react';
import { Reorder, useDragControls } from 'framer-motion'; import { Reorder, useDragControls } from 'framer-motion';
import { FC, ReactNode, useEffect, useRef } from 'react'; import { FC, ReactNode, useEffect, useRef } from 'react';
import { IDraggableListInputValue } from '../../../../widgets/widgets'; import { IDraggableListInputValue } from '../../../../../widgets/widgets';
const useStyles = createStyles((theme) => ({ const useStyles = createStyles((theme) => ({
container: { container: {
@@ -43,14 +43,14 @@ const useStyles = createStyles((theme) => ({
}, },
})); }));
type DraggableListParams = { type StaticDraggableListParams = {
value: IDraggableListInputValue['defaultValue']; value: IDraggableListInputValue['defaultValue'];
onChange: (value: IDraggableListInputValue['defaultValue']) => void; onChange: (value: IDraggableListInputValue['defaultValue']) => void;
labels: Record<string, string>; labels: Record<string, string>;
children?: Record<string, ReactNode>; children?: Record<string, ReactNode>;
}; };
export const DraggableList: FC<DraggableListParams> = (props) => { export const StaticDraggableList: FC<StaticDraggableListParams> = (props) => {
const keys = props.value.map((v) => v.key); const keys = props.value.map((v) => v.key);
return ( return (
@@ -64,10 +64,10 @@ export const DraggableList: FC<DraggableListParams> = (props) => {
as="div" as="div"
> >
{props.value.map((item) => ( {props.value.map((item) => (
<ListItem key={item.key} item={item} label={props.labels[item.key]}> <ListItem key={item.key} item={item} label={props.labels[item.key]}>
{props.children?.[item.key]} {props.children?.[item.key]}
</ListItem> </ListItem>
))} ))}
</Reorder.Group> </Reorder.Group>
</div> </div>
); );

View File

@@ -1,6 +1,8 @@
import { import {
Alert, Alert,
Button, Button,
Card,
Flex,
Group, Group,
MultiSelect, MultiSelect,
NumberInput, NumberInput,
@@ -10,9 +12,10 @@ import {
Switch, Switch,
Text, Text,
TextInput, TextInput,
Title,
} from '@mantine/core'; } from '@mantine/core';
import { ContextModalProps } from '@mantine/modals'; import { ContextModalProps } from '@mantine/modals';
import { IconAlertTriangle } from '@tabler/icons'; import { IconAlertTriangle, IconPlaylistX, IconPlus } from '@tabler/icons-react';
import { Trans, useTranslation } from 'next-i18next'; import { Trans, useTranslation } from 'next-i18next';
import { FC, useState } from 'react'; import { FC, useState } from 'react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';
@@ -22,7 +25,8 @@ import { useColorTheme } from '../../../../tools/color';
import Widgets from '../../../../widgets'; import Widgets from '../../../../widgets';
import type { IDraggableListInputValue, IWidgetOptionValue } from '../../../../widgets/widgets'; import type { IDraggableListInputValue, IWidgetOptionValue } from '../../../../widgets/widgets';
import { IWidget } from '../../../../widgets/widgets'; import { IWidget } from '../../../../widgets/widgets';
import { DraggableList } from './DraggableList'; import { DraggableList } from './Inputs/DraggableList';
import { StaticDraggableList } from './Inputs/StaticDraggableList';
export type WidgetEditModalInnerProps = { export type WidgetEditModalInnerProps = {
widgetId: string; widgetId: string;
@@ -222,7 +226,7 @@ const WidgetOptionTypeSwitch: FC<{
return ( return (
<Stack spacing="xs"> <Stack spacing="xs">
<Text>{t(`descriptor.settings.${key}.label`)}</Text> <Text>{t(`descriptor.settings.${key}.label`)}</Text>
<DraggableList <StaticDraggableList
value={typedVal} value={typedVal}
onChange={(v) => handleChange(key, v)} onChange={(v) => handleChange(key, v)}
labels={mapObject(option.items, (liName) => labels={mapObject(option.items, (liName) =>
@@ -241,7 +245,7 @@ const WidgetOptionTypeSwitch: FC<{
/> />
)) ))
)} )}
</DraggableList> </StaticDraggableList>
</Stack> </Stack>
); );
case 'multiple-text': case 'multiple-text':
@@ -263,6 +267,46 @@ const WidgetOptionTypeSwitch: FC<{
} }
/> />
); );
case 'draggable-editable-list':
const { t: translateDraggableList } = useTranslation('widgets/draggable-list');
return (
<Stack spacing="xs">
<Text>{t(`descriptor.settings.${key}.label`)}</Text>
<DraggableList
items={Array.from(value).map((v: any) => ({
data: v,
}))}
value={value}
onChange={(v) => handleChange(key, v)}
options={option}
/>
{Array.from(value).length === 0 && (
<Card>
<Stack align="center">
<IconPlaylistX size="2rem" />
<Stack align="center" spacing={0}>
<Title order={5}>{translateDraggableList('noEntries.title')}</Title>
<Text>{translateDraggableList('noEntries.text')}</Text>
</Stack>
</Stack>
</Card>
)}
<Flex gap="md">
<Button
onClick={() => {
handleChange('items', [...value, option.create()]);
}}
leftIcon={<IconPlus size={16} />}
variant="default"
fullWidth
>
{translateDraggableList('buttonAdd')}
</Button>
</Flex>
</Stack>
);
/* eslint-enable no-case-declarations */ /* eslint-enable no-case-declarations */
default: default:
return null; return null;

View File

@@ -1,5 +1,5 @@
import { ActionIcon, Button, Text, Tooltip } from '@mantine/core'; import { ActionIcon, Button, Text, Tooltip } from '@mantine/core';
import { IconEdit, IconEditOff } from '@tabler/icons'; import { IconEdit, IconEditOff } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useScreenLargerThan } from '../../../hooks/useScreenLargerThan'; import { useScreenLargerThan } from '../../../hooks/useScreenLargerThan';
import { useEditModeStore } from './useEditModeStore'; import { useEditModeStore } from './useEditModeStore';

View File

@@ -7,7 +7,7 @@ import {
IconRowInsertBottom, IconRowInsertBottom,
IconEdit, IconEdit,
IconTrash, IconTrash,
} from '@tabler/icons'; } from '@tabler/icons-react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';
import { CategoryType } from '../../../../types/category'; import { CategoryType } from '../../../../types/category';
import { useCategoryActions } from './useCategoryActions'; import { useCategoryActions } from './useCategoryActions';

View File

@@ -1,42 +1,38 @@
// disabled due to too many dynamic targets for next image cache import { Image, Loader, createStyles } from '@mantine/core';
/* eslint-disable @next/next/no-img-element */
import Image from 'next/image';
import { createStyles, Loader } from '@mantine/core';
import { UseFormReturnType } from '@mantine/form';
import { useDebouncedValue } from '@mantine/hooks'; import { useDebouncedValue } from '@mantine/hooks';
import { AppType } from '../../../../../../types/app'; import { IconPhotoOff } from '@tabler/icons-react';
interface DebouncedAppIconProps { interface DebouncedImageProps {
width: number; width: number;
height: number; height: number;
form: UseFormReturnType<AppType, (values: AppType) => AppType>; src: string;
debouncedWaitPeriod?: number; debouncedWaitPeriod?: number;
} }
export const DebouncedAppIcon = ({ export const DebouncedImage = ({
form, src,
width, width,
height, height,
debouncedWaitPeriod = 1000, debouncedWaitPeriod = 1000,
}: DebouncedAppIconProps) => { }: DebouncedImageProps) => {
const { classes } = useStyles(); const { classes } = useStyles();
const [debouncedIconImageUrl] = useDebouncedValue( const [debouncedIconImageUrl] = useDebouncedValue(src, debouncedWaitPeriod);
form.values.appearance.iconUrl,
debouncedWaitPeriod
);
if (debouncedIconImageUrl !== form.values.appearance.iconUrl) { if (debouncedIconImageUrl !== src) {
return <Loader width={width} height={height} />; return <Loader width={width} height={height} />;
} }
if (debouncedIconImageUrl.length > 0) { if (debouncedIconImageUrl.length > 0) {
return ( return (
<img <Image
placeholder={<IconPhotoOff />}
className={classes.iconImage} className={classes.iconImage}
src={debouncedIconImageUrl} src={debouncedIconImageUrl}
width={width} width={width}
height={height} height={height}
fit="contain"
alt="" alt=""
withPlaceholder
/> />
); );
} }
@@ -47,7 +43,9 @@ export const DebouncedAppIcon = ({
src="/imgs/logo/logo.png" src="/imgs/logo/logo.png"
width={width} width={width}
height={height} height={height}
fit="contain"
alt="" alt=""
withPlaceholder
/> />
); );
}; };

View File

@@ -0,0 +1,177 @@
import { forwardRef, useImperativeHandle, useState } from 'react';
import {
Autocomplete,
CloseButton,
Stack,
Title,
Text,
Group,
Loader,
createStyles,
Box,
Image,
SelectItemProps,
ScrollArea,
} from '@mantine/core';
import { IconSearch } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import { useGetDashboardIcons } from '../../hooks/icons/useGetDashboardIcons';
import { humanFileSize } from '../../tools/humanFileSize';
import { DebouncedImage } from './DebouncedImage';
export const IconSelector = forwardRef(
(
{
defaultValue,
value,
onChange,
}: {
defaultValue: string;
value?: string;
onChange: (debouncedValue: string | undefined) => void;
},
ref
) => {
const { t } = useTranslation('layout/modals/add-app');
const { classes } = useStyles();
const { data, isLoading } = useGetDashboardIcons();
const [currentValue, setValue] = useState(value ?? defaultValue);
const flatIcons =
data === undefined
? []
: data.flatMap((repository) =>
repository.entries.map((entry) => ({
url: entry.url,
label: entry.name,
size: entry.size,
value: entry.url,
group: repository.name,
copyright: repository.copyright,
}))
);
useImperativeHandle(ref, () => ({
chooseFirstOrDefault(searchTerm: string) {
const match = flatIcons.find((icon) =>
icon.label.toLowerCase().includes(searchTerm.toLowerCase())
);
if (!match) {
return;
}
onChange(match.url);
},
}));
return (
<Stack w="100%">
<Autocomplete
nothingFound={
<Stack align="center" spacing="xs" my="lg">
<IconSearch />
<Title order={6} align="center">
{t('appearance.icon.autocomplete.title')}
</Title>
<Text align="center" maw={350}>
{t('appearance.icon.autocomplete.text')}
</Text>
</Stack>
}
icon={<DebouncedImage src={value ?? currentValue} width={20} height={20} />}
rightSection={
(value ?? currentValue).length > 0 ? (
<CloseButton onClick={() => onChange(undefined)} />
) : null
}
itemComponent={AutoCompleteItem}
className={classes.textInput}
data={flatIcons}
limit={25}
label={t('appearance.icon.label')}
description={t('appearance.icon.description', {
suggestionsCount: data?.reduce((a, b) => a + b.count, 0) ?? 0,
})}
filter={(search, item) =>
item.value
.toLowerCase()
.replaceAll('_', '')
.replaceAll(' ', '-')
.includes(search.toLowerCase().replaceAll('_', '').replaceAll(' ', '-'))
}
dropdownComponent={(props: any) => <ScrollArea {...props} mah={250} />}
onChange={(event) => {
onChange(event);
setValue(event);
}}
dropdownPosition="bottom"
variant="default"
value={value}
withAsterisk
withinPortal
required
/>
{(!data || isLoading) && (
<Group>
<Loader variant="oval" size="sm" />
<Stack spacing={0}>
<Text size="xs" weight="bold">
{t('appearance.icon.noItems.title')}
</Text>
<Text color="dimmed" size="xs">
{t('appearance.icon.noItems.text')}
</Text>
</Stack>
</Group>
)}
</Stack>
);
}
);
const useStyles = createStyles(() => ({
textInput: {
flexGrow: 1,
},
}));
const AutoCompleteItem = forwardRef<HTMLDivElement, ItemProps>(
({ label, size, copyright, url, ...others }: ItemProps, ref) => (
<div ref={ref} {...others}>
<Group noWrap>
<Box
sx={(theme) => ({
backgroundColor:
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2],
borderRadius: theme.radius.md,
})}
p={2}
>
<Image src={url} width={30} height={30} fit="contain" />
</Box>
<Stack spacing={0}>
<Text>{label}</Text>
<Group>
<Text color="dimmed" size="xs">
{humanFileSize(size, false)}
</Text>
{copyright && (
<Text color="dimmed" size="xs">
© {copyright}
</Text>
)}
</Group>
</Stack>
</Group>
</div>
)
);
interface ItemProps extends SelectItemProps {
url: string;
group: string;
size: number;
copyright: string | undefined;
}

View File

@@ -1,7 +1,7 @@
import { Button, Group, MultiSelect, Stack, Title } from '@mantine/core'; import { Button, Group, MultiSelect, Stack, Title } from '@mantine/core';
import { useState } from 'react'; import { useState } from 'react';
import { notifications } from '@mantine/notifications'; import { notifications } from '@mantine/notifications';
import { IconTrash } from '@tabler/icons'; import { IconTrash } from '@tabler/icons-react';
import { queryClient } from '../../../tools/server/configurations/tanstack/queryClient.tool'; import { queryClient } from '../../../tools/server/configurations/tanstack/queryClient.tool';
const data = [ const data = [

View File

@@ -10,7 +10,7 @@ import {
import { useDisclosure } from '@mantine/hooks'; import { useDisclosure } from '@mantine/hooks';
import { openConfirmModal } from '@mantine/modals'; import { openConfirmModal } from '@mantine/modals';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconAlertTriangle, IconCheck, IconCopy, IconDownload, IconTrash } from '@tabler/icons'; import { IconAlertTriangle, IconCheck, IconCopy, IconDownload, IconTrash } from '@tabler/icons-react';
import fileDownload from 'js-file-download'; import fileDownload from 'js-file-download';
import { Trans, useTranslation } from 'next-i18next'; import { Trans, useTranslation } from 'next-i18next';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';

View File

@@ -1,5 +1,5 @@
import { Alert, Paper, SegmentedControl, Space, Stack, TextInput, Title } from '@mantine/core'; import { Alert, Paper, SegmentedControl, Space, Stack, TextInput, Title } from '@mantine/core';
import { IconInfoCircle } from '@tabler/icons'; import { IconInfoCircle } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { ChangeEventHandler, useState } from 'react'; import { ChangeEventHandler, useState } from 'react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';

View File

@@ -1,5 +1,5 @@
import { Accordion, Checkbox, Grid, Group, Stack, Text } from '@mantine/core'; import { Accordion, Checkbox, Grid, Group, Stack, Text } from '@mantine/core';
import { IconBrush, IconChartCandle, IconCode, IconDragDrop, IconLayout } from '@tabler/icons'; import { IconBrush, IconChartCandle, IconCode, IconDragDrop, IconLayout } from '@tabler/icons-react';
import { i18n, useTranslation } from 'next-i18next'; import { i18n, useTranslation } from 'next-i18next';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { GridstackConfiguration } from './Layout/GridstackConfiguration'; import { GridstackConfiguration } from './Layout/GridstackConfiguration';

View File

@@ -1,6 +1,6 @@
import { Alert, Button, Grid, Input, LoadingOverlay, Slider } from '@mantine/core'; import { Alert, Button, Grid, Input, LoadingOverlay, Slider } from '@mantine/core';
import { useForm } from '@mantine/form'; import { useForm } from '@mantine/form';
import { IconCheck, IconReload } from '@tabler/icons'; import { IconCheck, IconReload } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useState } from 'react'; import { useState } from 'react';
import { useConfigContext } from '../../../../config/provider'; import { useConfigContext } from '../../../../config/provider';

View File

@@ -1,6 +1,6 @@
import { ActionIcon, Button, Tooltip } from '@mantine/core'; import { ActionIcon, Button, Tooltip } from '@mantine/core';
import { openContextModal } from '@mantine/modals'; import { openContextModal } from '@mantine/modals';
import { IconApps } from '@tabler/icons'; import { IconApps } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useCardStyles } from '../../../useCardStyles'; import { useCardStyles } from '../../../useCardStyles';

View File

@@ -1,7 +1,7 @@
import { ActionIcon, Button, Group, Text, Title, Tooltip } from '@mantine/core'; import { ActionIcon, Button, Group, Text, Title, Tooltip } from '@mantine/core';
import { useHotkeys, useWindowEvent } from '@mantine/hooks'; import { useHotkeys, useWindowEvent } from '@mantine/hooks';
import { hideNotification, showNotification } from '@mantine/notifications'; import { hideNotification, showNotification } from '@mantine/notifications';
import { IconEditCircle, IconEditCircleOff } from '@tabler/icons'; import { IconEditCircle, IconEditCircleOff } from '@tabler/icons-react';
import axios from 'axios'; import axios from 'axios';
import Consola from 'consola'; import Consola from 'consola';
import { getCookie } from 'cookies-next'; import { getCookie } from 'cookies-next';

View File

@@ -12,7 +12,7 @@ import {
} from '@mantine/core'; } from '@mantine/core';
import { useDebouncedValue, useHotkeys } from '@mantine/hooks'; import { useDebouncedValue, useHotkeys } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconBrandYoutube, IconDownload, IconMovie, IconSearch } from '@tabler/icons'; import { IconBrandYoutube, IconDownload, IconMovie, IconSearch } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import axios from 'axios'; import axios from 'axios';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -1,6 +1,6 @@
import { Badge, Button, Menu } from '@mantine/core'; import { Badge, Button, Menu } from '@mantine/core';
import { useDisclosure } from '@mantine/hooks'; import { useDisclosure } from '@mantine/hooks';
import { IconInfoCircle, IconMenu2, IconSettings } from '@tabler/icons'; import { IconInfoCircle, IconMenu2, IconSettings } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useEditModeInformationStore } from '../../../hooks/useEditModeInformation'; import { useEditModeInformationStore } from '../../../hooks/useEditModeInformation';
import { AboutModal } from '../../Dashboard/Modals/AboutModal/AboutModal'; import { AboutModal } from '../../Dashboard/Modals/AboutModal/AboutModal';

View File

@@ -1,5 +1,5 @@
import { Menu, useMantineColorScheme } from '@mantine/core'; import { Menu, useMantineColorScheme } from '@mantine/core';
import { IconMoonStars, IconSun } from '@tabler/icons'; import { IconMoonStars, IconSun } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
export const ColorSchemeSwitch = () => { export const ColorSchemeSwitch = () => {

View File

@@ -2,7 +2,7 @@ import { Button, Code, Menu, PasswordInput, Stack, Text } from '@mantine/core';
import { useForm } from '@mantine/form'; import { useForm } from '@mantine/form';
import { openModal } from '@mantine/modals'; import { openModal } from '@mantine/modals';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconEdit, IconEditOff } from '@tabler/icons'; import { IconEdit, IconEditOff } from '@tabler/icons-react';
import axios from 'axios'; import axios from 'axios';
import { useEditModeInformationStore } from '../../../../hooks/useEditModeInformation'; import { useEditModeInformationStore } from '../../../../hooks/useEditModeInformation';

View File

@@ -9,7 +9,7 @@ import {
IconRefresh, IconRefresh,
IconRotateClockwise, IconRotateClockwise,
IconTrash, IconTrash,
} from '@tabler/icons'; } from '@tabler/icons-react';
import axios from 'axios'; import axios from 'axios';
import Dockerode from 'dockerode'; import Dockerode from 'dockerode';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -1,7 +1,7 @@
import { ActionIcon, Drawer, Text, Tooltip } from '@mantine/core'; import { ActionIcon, Drawer, Text, Tooltip } from '@mantine/core';
import { useHotkeys } from '@mantine/hooks'; import { useHotkeys } from '@mantine/hooks';
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconBrandDocker, IconX } from '@tabler/icons'; import { IconBrandDocker, IconX } from '@tabler/icons-react';
import axios from 'axios'; import axios from 'axios';
import Docker from 'dockerode'; import Docker from 'dockerode';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -9,7 +9,7 @@ import {
TextInput, TextInput,
} from '@mantine/core'; } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconSearch } from '@tabler/icons'; import { IconSearch } from '@tabler/icons-react';
import Dockerode from 'dockerode'; import Dockerode from 'dockerode';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';

View File

@@ -2,14 +2,14 @@
// Each module should have its own interface and call the following function: // Each module should have its own interface and call the following function:
// TODO: Add a function to register a module // TODO: Add a function to register a module
import { TablerIcon } from '@tabler/icons'; import { Icon } from '@tabler/icons-react';
// Note: Maybe use context to keep track of the modules // Note: Maybe use context to keep track of the modules
// TODO: Remove this old component and the entire file // TODO: Remove this old component and the entire file
export interface IModule { export interface IModule {
id: string; id: string;
title: string; title: string;
icon: TablerIcon; icon: Icon;
component: React.ComponentType; component: React.ComponentType;
options?: Option; options?: Option;
padding?: PaddingOptions = { padding?: PaddingOptions = {

View File

@@ -1,5 +1,5 @@
import { Badge, Button, Group, Image, Stack, Text, Title } from '@mantine/core'; import { Badge, Button, Group, Image, Stack, Text, Title } from '@mantine/core';
import { IconDownload, IconExternalLink, IconPlayerPlay } from '@tabler/icons'; import { IconDownload, IconExternalLink, IconPlayerPlay } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useState } from 'react'; import { useState } from 'react';
import { useConfigContext } from '../../config/provider'; import { useConfigContext } from '../../config/provider';

View File

@@ -1,4 +1,4 @@
import { IconEyeglass } from '@tabler/icons'; import { IconEyeglass } from '@tabler/icons-react';
import { OverseerrMediaDisplay } from '../common'; import { OverseerrMediaDisplay } from '../common';
import { IModule } from '../ModuleTypes'; import { IModule } from '../ModuleTypes';

View File

@@ -1,6 +1,6 @@
import { Alert, Button, Checkbox, createStyles, Group, Modal, Stack, Table } from '@mantine/core'; import { Alert, Button, Checkbox, createStyles, Group, Modal, Stack, Table } from '@mantine/core';
import { showNotification, updateNotification } from '@mantine/notifications'; import { showNotification, updateNotification } from '@mantine/notifications';
import { IconAlertCircle, IconCheck, IconDownload } from '@tabler/icons'; import { IconAlertCircle, IconCheck, IconDownload } from '@tabler/icons-react';
import axios from 'axios'; import axios from 'axios';
import Consola from 'consola'; import Consola from 'consola';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -1,5 +1,5 @@
import { Indicator, Tooltip } from '@mantine/core'; import { Indicator, Tooltip } from '@mantine/core';
import { IconPlug as Plug } from '@tabler/icons'; import { IconPlug as Plug } from '@tabler/icons-react';
import axios, { AxiosResponse } from 'axios'; import axios, { AxiosResponse } from 'axios';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -110,7 +110,8 @@ async function Get(req: NextApiRequest, res: NextApiResponse) {
}) })
); );
const countFailed = medias.filter((x) => !x.success).length; const results = await Promise.all(medias);
const countFailed = results.filter((x) => !x.success).length;
if (countFailed > 0) { if (countFailed > 0) {
Consola.warn(`A total of ${countFailed} apps for the calendar widget failed`); Consola.warn(`A total of ${countFailed} apps for the calendar widget failed`);
} }

View File

@@ -1,4 +1,4 @@
import axios from 'axios'; import axios, { AxiosError } from 'axios';
import https from 'https'; import https from 'https';
import Consola from 'consola'; import Consola from 'consola';
import { NextApiRequest, NextApiResponse } from 'next'; import { NextApiRequest, NextApiResponse } from 'next';
@@ -12,14 +12,15 @@ async function Get(req: NextApiRequest, res: NextApiResponse) {
.then((response) => { .then((response) => {
res.status(response.status).json(response.statusText); res.status(response.status).json(response.statusText);
}) })
.catch((error) => { .catch((error: AxiosError) => {
if (error.response) { if (error.response) {
Consola.error(`Unexpected response: ${error.response.data}`); Consola.warn(`Unexpected response: ${error.message}`);
res.status(error.response.status).json(error.response.statusText); res.status(error.response.status).json(error.response.statusText);
} else if (error.code === 'ECONNABORTED') { } else if (error.code === 'ECONNABORTED') {
res.status(408).json('Request Timeout'); res.status(408).json('Request Timeout');
} else { } else {
res.status(error.response ? error.response.status : 500).json('Server Error'); Consola.error(`Unexpected error: ${error.message}`);
res.status(500).json('Internal Server Error');
} }
}); });
// // Make a request to the URL // // Make a request to the URL

View File

@@ -3,7 +3,7 @@ import { PasswordInput, Paper, Title, Text, Container, Button } from '@mantine/c
import { setCookie } from 'cookies-next'; import { setCookie } from 'cookies-next';
import { showNotification, updateNotification } from '@mantine/notifications'; import { showNotification, updateNotification } from '@mantine/notifications';
import axios from 'axios'; import axios from 'axios';
import { IconCheck, IconX } from '@tabler/icons'; import { IconCheck, IconX } from '@tabler/icons-react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useForm } from '@mantine/form'; import { useForm } from '@mantine/form';

View File

@@ -35,7 +35,7 @@ import {
IconCircleCheck, IconCircleCheck,
IconMoonStars, IconMoonStars,
IconSun, IconSun,
} from '@tabler/icons'; } from '@tabler/icons-react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import axios from 'axios'; import axios from 'axios';
import { Logo } from '../components/layout/Logo'; import { Logo } from '../components/layout/Logo';

View File

@@ -1,5 +1,5 @@
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconCheck, IconX } from '@tabler/icons'; import { IconCheck, IconX } from '@tabler/icons-react';
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useConfigContext } from '../../../config/provider'; import { useConfigContext } from '../../../config/provider';

View File

@@ -1,5 +1,5 @@
import { showNotification } from '@mantine/notifications'; import { showNotification } from '@mantine/notifications';
import { IconX } from '@tabler/icons'; import { IconX } from '@tabler/icons-react';
import { useMutation } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -40,7 +40,9 @@ export const dashboardNamespaces = [
'modules/media-requests-stats', 'modules/media-requests-stats',
'modules/dns-hole-summary', 'modules/dns-hole-summary',
'modules/dns-hole-controls', 'modules/dns-hole-controls',
'modules/bookmark',
'widgets/error-boundary', 'widgets/error-boundary',
'widgets/draggable-list',
]; ];
export const loginNamespaces = ['authentication/login']; export const loginNamespaces = ['authentication/login'];

View File

@@ -1,4 +1,4 @@
import { IconKey, IconPassword, IconUser, TablerIcon } from '@tabler/icons'; import { IconKey, IconPassword, IconUser, Icon } from '@tabler/icons-react';
import { TileBaseType } from './tile'; import { TileBaseType } from './tile';
@@ -90,7 +90,7 @@ export const integrationFieldProperties: {
export type IntegrationFieldDefinitionType = { export type IntegrationFieldDefinitionType = {
type: 'private' | 'public'; type: 'private' | 'public';
icon: TablerIcon; icon: Icon;
label: string; label: string;
}; };

View File

@@ -0,0 +1,260 @@
import {
Alert,
Box,
Button,
Card,
Flex,
Group,
Image,
ScrollArea,
Stack,
Text,
TextInput,
Title,
createStyles,
} from '@mantine/core';
import { useForm } from '@mantine/form';
import {
IconAlertTriangle,
IconBookmark,
IconLink,
IconPlaylistX,
IconTrash,
IconTypography,
} from '@tabler/icons-react';
import { useTranslation } from 'next-i18next';
import { useEffect } from 'react';
import { v4 } from 'uuid';
import { z } from 'zod';
import { IconSelector } from '../../components/IconSelector/IconSelector';
import { defineWidget } from '../helper';
import { IDraggableEditableListInputValue, IWidget } from '../widgets';
interface BookmarkItem {
id: string;
name: string;
href: string;
iconUrl: string;
}
const definition = defineWidget({
id: 'bookmark',
icon: IconBookmark,
options: {
items: {
type: 'draggable-editable-list',
defaultValue: [],
getLabel(data) {
return data.name;
},
create() {
return {
id: v4(),
name: 'Homarr Documentation',
href: 'https://homarr.dev',
iconUrl: '/imgs/logo/logo.png',
};
},
itemComponent({ data, onChange, delete: deleteData }) {
const form = useForm({
initialValues: data,
validate: {
name: (value) => {
const validation = z.string().min(1).max(100).safeParse(value);
if (validation.success) {
return undefined;
}
return 'Length must be between 1 and 100';
},
href: (value) => {
if (!z.string().min(1).max(200).safeParse(value).success) {
return 'Length must be between 1 and 200';
}
if (!z.string().url().safeParse(value).success) {
return 'Not a valid link';
}
return undefined;
},
iconUrl: (value) => {
if (z.string().min(1).max(400).safeParse(value).success) {
return undefined;
}
return 'Length must be between 1 and 100';
},
},
validateInputOnChange: true,
validateInputOnBlur: true,
});
useEffect(() => {
if (!form.isValid()) {
return;
}
onChange(form.values);
}, [form.values]);
return (
<form>
<Stack>
<TextInput
icon={<IconTypography size="1rem" />}
{...form.getInputProps('name')}
label="Name"
withAsterisk
/>
<TextInput
icon={<IconLink size="1rem" />}
{...form.getInputProps('href')}
label="URL"
withAsterisk
/>
<IconSelector
defaultValue={data.iconUrl}
value={form.values.iconUrl}
onChange={(value) => {
form.setFieldValue('iconUrl', value ?? '');
}}
/>
<Button
onClick={() => deleteData()}
leftIcon={<IconTrash size="1rem" />}
variant="light"
type="button"
>
Delete
</Button>
{!form.isValid() && (
<Alert color="red" icon={<IconAlertTriangle size="1rem" />}>
Did not save, because there were validation errors. Please adust your inputs
</Alert>
)}
</Stack>
</form>
);
},
} satisfies IDraggableEditableListInputValue<BookmarkItem>,
layout: {
type: 'select',
data: [
{
label: 'Auto Grid',
value: 'autoGrid',
},
{
label: 'Horizontal',
value: 'horizontal',
},
{
label: 'Vertical',
value: 'vertical',
},
],
defaultValue: 'autoGrid',
},
},
gridstack: {
minWidth: 1,
minHeight: 1,
maxWidth: 24,
maxHeight: 24,
},
component: BookmarkWidgetTile,
});
export type IBookmarkWidget = IWidget<(typeof definition)['id'], typeof definition>;
interface BookmarkWidgetTileProps {
widget: IBookmarkWidget;
}
function BookmarkWidgetTile({ widget }: BookmarkWidgetTileProps) {
const { t } = useTranslation('modules/bookmark');
const { classes } = useStyles();
if (widget.properties.items.length === 0) {
return (
<Stack align="center">
<IconPlaylistX />
<Stack spacing={0}>
<Title order={5} align="center">{t('card.noneFound.title')}</Title>
<Text align="center" size="sm">{t('card.noneFound.text')}</Text>
</Stack>
</Stack>
);
}
switch (widget.properties.layout) {
case 'autoGrid':
return (
<Box className={classes.grid} display="grid">
{widget.properties.items.map((item: BookmarkItem, index) => (
<Card
className={classes.autoGridItem}
key={index}
px="xl"
component="a"
href={item.href}
withBorder
>
<BookmarkItemContent item={item} />
</Card>
))}
</Box>
);
case 'horizontal':
case 'vertical':
return (
<ScrollArea offsetScrollbars type="always" h="100%">
<Flex
style={{ flexDirection: widget.properties.layout === 'vertical' ? 'column' : 'row' }}
gap="md"
>
{widget.properties.items.map((item: BookmarkItem, index) => (
<Card
key={index}
w={widget.properties.layout === 'vertical' ? '100%' : undefined}
px="xl"
component="a"
href={item.href}
withBorder
>
<BookmarkItemContent item={item} />
</Card>
))}
</Flex>
</ScrollArea>
);
default:
return null;
}
}
const BookmarkItemContent = ({ item }: { item: BookmarkItem }) => (
<Group>
<Image src={item.iconUrl} width={30} height={30} fit="contain" withPlaceholder />
<Stack spacing={0}>
<Text>{item.name}</Text>
<Text color="dimmed" size="sm">
{new URL(item.href).hostname}
</Text>
</Stack>
</Group>
);
const useStyles = createStyles(() => ({
grid: {
display: 'grid',
gap: 20,
gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',
},
autoGridItem: {
flex: '1 1 auto',
},
}));
export default definition;

View File

@@ -3,7 +3,7 @@ import React, { ReactNode } from 'react';
import { openModal } from '@mantine/modals'; import { openModal } from '@mantine/modals';
import { withTranslation } from 'next-i18next'; import { withTranslation } from 'next-i18next';
import { Button, Card, Center, Code, Group, Stack, Text, Title } from '@mantine/core'; import { Button, Card, Center, Code, Group, Stack, Text, Title } from '@mantine/core';
import { IconBrandGithub, IconBug, IconInfoCircle, IconRefresh } from '@tabler/icons'; import { IconBrandGithub, IconBug, IconInfoCircle, IconRefresh } from '@tabler/icons-react';
type ErrorBoundaryState = { type ErrorBoundaryState = {
hasError: boolean; hasError: boolean;

View File

@@ -1,6 +1,6 @@
import { useMantineTheme } from '@mantine/core'; import { useMantineTheme } from '@mantine/core';
import { Calendar } from '@mantine/dates'; import { Calendar } from '@mantine/dates';
import { IconCalendarTime } from '@tabler/icons'; import { IconCalendarTime } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { i18n } from 'next-i18next'; import { i18n } from 'next-i18next';
import { useState } from 'react'; import { useState } from 'react';

View File

@@ -1,5 +1,5 @@
import { Group, Stack, Text } from '@mantine/core'; import { Group, Stack, Text } from '@mantine/core';
import { IconArrowNarrowDown, IconArrowNarrowUp } from '@tabler/icons'; import { IconArrowNarrowDown, IconArrowNarrowUp } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { bytes } from '../../tools/bytesHelper'; import { bytes } from '../../tools/bytesHelper';

View File

@@ -1,5 +1,5 @@
import { Center, createStyles, Grid, Stack, Text, Title } from '@mantine/core'; import { Center, createStyles, Grid, Stack, Text, Title } from '@mantine/core';
import { IconUnlink } from '@tabler/icons'; import { IconUnlink } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import axios from 'axios'; import axios from 'axios';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -1,6 +1,6 @@
import { Stack, Text, Title } from '@mantine/core'; import { Stack, Text, Title } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconClock } from '@tabler/icons'; import { IconClock } from '@tabler/icons-react';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { useSetSafeInterval } from '../../hooks/useSetSafeInterval'; import { useSetSafeInterval } from '../../hooks/useSetSafeInterval';

View File

@@ -1,6 +1,6 @@
import { Badge, Box, Button, Card, Group, Image, Stack, Text } from '@mantine/core'; import { Badge, Box, Button, Card, Group, Image, Stack, Text } from '@mantine/core';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { IconDeviceGamepad, IconPlayerPlay, IconPlayerStop } from '@tabler/icons'; import { IconDeviceGamepad, IconPlayerPlay, IconPlayerStop } from '@tabler/icons-react';
import { useConfigContext } from '../../config/provider'; import { useConfigContext } from '../../config/provider';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { WidgetLoading } from '../loading'; import { WidgetLoading } from '../loading';

View File

@@ -1,6 +1,6 @@
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { Card, Center, Container, Stack, Text } from '@mantine/core'; import { Card, Center, Container, Stack, Text } from '@mantine/core';
import { IconAd, IconBarrierBlock, IconPercentage, IconSearch, IconWorldWww } from '@tabler/icons'; import { IconAd, IconBarrierBlock, IconPercentage, IconSearch, IconWorldWww } from '@tabler/icons-react';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { WidgetLoading } from '../loading'; import { WidgetLoading } from '../loading';
import { IWidget } from '../widgets'; import { IWidget } from '../widgets';

View File

@@ -12,7 +12,7 @@ import {
import { useElementSize, useListState } from '@mantine/hooks'; import { useElementSize, useListState } from '@mantine/hooks';
import { linearGradientDef } from '@nivo/core'; import { linearGradientDef } from '@nivo/core';
import { Serie, Datum, ResponsiveLine } from '@nivo/line'; import { Serie, Datum, ResponsiveLine } from '@nivo/line';
import { IconDownload, IconUpload } from '@tabler/icons'; import { IconDownload, IconUpload } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { AppAvatar } from '../../components/AppAvatar'; import { AppAvatar } from '../../components/AppAvatar';

View File

@@ -1,4 +1,4 @@
import { IconArrowsUpDown } from '@tabler/icons'; import { IconArrowsUpDown } from '@tabler/icons-react';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';

View File

@@ -1,5 +1,5 @@
import { Center, createStyles, Stack, Title, Text, Container } from '@mantine/core'; import { Center, createStyles, Stack, Title, Text, Container } from '@mantine/core';
import { IconBrowser, IconUnlink } from '@tabler/icons'; import { IconBrowser, IconUnlink } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { IWidget } from '../widgets'; import { IWidget } from '../widgets';

View File

@@ -13,6 +13,7 @@ import mediaRequestsList from './media-requests/MediaRequestListTile';
import mediaRequestsStats from './media-requests/MediaRequestStatsTile'; import mediaRequestsStats from './media-requests/MediaRequestStatsTile';
import dnsHoleSummary from './dnshole/DnsHoleSummary'; import dnsHoleSummary from './dnshole/DnsHoleSummary';
import dnsHoleControls from './dnshole/DnsHoleControls'; import dnsHoleControls from './dnshole/DnsHoleControls';
import bookmark from './bookmark/BookmarkWidgetTile';
export default { export default {
calendar, calendar,
@@ -30,4 +31,5 @@ export default {
'media-requests-stats': mediaRequestsStats, 'media-requests-stats': mediaRequestsStats,
'dns-hole-summary': dnsHoleSummary, 'dns-hole-summary': dnsHoleSummary,
'dns-hole-controls': dnsHoleControls, 'dns-hole-controls': dnsHoleControls,
bookmark,
}; };

View File

@@ -1,6 +1,6 @@
import { Badge, Card, Center, Flex, Group, Image, Stack, Text } from '@mantine/core'; import { Badge, Card, Center, Flex, Group, Image, Stack, Text } from '@mantine/core';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { IconGitPullRequest } from '@tabler/icons'; import { IconGitPullRequest } from '@tabler/icons-react';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { WidgetLoading } from '../loading'; import { WidgetLoading } from '../loading';
import { IWidget } from '../widgets'; import { IWidget } from '../widgets';

View File

@@ -1,5 +1,5 @@
import { Card, Center, Flex, Stack, Text } from '@mantine/core'; import { Card, Center, Flex, Stack, Text } from '@mantine/core';
import { IconChartBar } from '@tabler/icons'; import { IconChartBar } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { WidgetLoading } from '../loading'; import { WidgetLoading } from '../loading';

View File

@@ -1,5 +1,5 @@
import { Card, Divider, Flex, Grid, Group, Text } from '@mantine/core'; import { Card, Divider, Flex, Grid, Group, Text } from '@mantine/core';
import { IconDeviceMobile, IconId } from '@tabler/icons'; import { IconDeviceMobile, IconId } from '@tabler/icons-react';
import { GenericSessionInfo } from '../../types/api/media-server/session-info'; import { GenericSessionInfo } from '../../types/api/media-server/session-info';
export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) => { export const DetailCollapseable = ({ session }: { session: GenericSessionInfo }) => {

View File

@@ -9,7 +9,7 @@ import {
Text, Text,
Title, Title,
} from '@mantine/core'; } from '@mantine/core';
import { IconAlertTriangle, IconMovie } from '@tabler/icons'; import { IconAlertTriangle, IconMovie } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { AppAvatar } from '../../components/AppAvatar'; import { AppAvatar } from '../../components/AppAvatar';
import { useEditModeStore } from '../../components/Dashboard/Views/useEditModeStore'; import { useEditModeStore } from '../../components/Dashboard/Views/useEditModeStore';

View File

@@ -4,8 +4,8 @@ import {
IconHeadphones, IconHeadphones,
IconQuestionMark, IconQuestionMark,
IconVideo, IconVideo,
TablerIcon, Icon,
} from '@tabler/icons'; } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { GenericSessionInfo } from '../../types/api/media-server/session-info'; import { GenericSessionInfo } from '../../types/api/media-server/session-info';
@@ -16,7 +16,7 @@ export const NowPlayingDisplay = ({ session }: { session: GenericSessionInfo })
return null; return null;
} }
const Icon = (): TablerIcon => { const Icon = (): Icon => {
switch (session.currentlyPlaying?.type) { switch (session.currentlyPlaying?.type) {
case 'audio': case 'audio':
return IconHeadphones; return IconHeadphones;

View File

@@ -15,7 +15,7 @@ import {
Title, Title,
createStyles, createStyles,
} from '@mantine/core'; } from '@mantine/core';
import { IconClock, IconRefresh, IconRss } from '@tabler/icons'; import { IconClock, IconRefresh, IconRss } from '@tabler/icons-react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';

View File

@@ -22,7 +22,7 @@ import {
IconPercentage, IconPercentage,
IconSortDescending, IconSortDescending,
IconUpload, IconUpload,
} from '@tabler/icons'; } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { calculateETA } from '../../tools/client/calculateEta'; import { calculateETA } from '../../tools/client/calculateEta';
import { humanFileSize } from '../../tools/humanFileSize'; import { humanFileSize } from '../../tools/humanFileSize';

View File

@@ -14,7 +14,7 @@ import {
} from '@mantine/core'; } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconFileDownload, IconInfoCircle } from '@tabler/icons'; import { IconFileDownload, IconInfoCircle } from '@tabler/icons-react';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration'; import duration from 'dayjs/plugin/duration';

View File

@@ -1,5 +1,5 @@
import { Badge, Button, Group, Select, Stack, Tabs, Text, Title } from '@mantine/core'; import { Badge, Button, Group, Select, Stack, Tabs, Text, Title } from '@mantine/core';
import { IconFileDownload, IconPlayerPause, IconPlayerPlay } from '@tabler/icons'; import { IconFileDownload, IconPlayerPause, IconPlayerPlay } from '@tabler/icons-react';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';

View File

@@ -12,7 +12,7 @@ import {
Tooltip, Tooltip,
} from '@mantine/core'; } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconAlertCircle } from '@tabler/icons'; import { IconAlertCircle } from '@tabler/icons-react';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration'; import duration from 'dayjs/plugin/duration';

View File

@@ -15,7 +15,7 @@ import {
useMantineTheme, useMantineTheme,
} from '@mantine/core'; } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconAlertCircle, IconPlayerPause, IconPlayerPlay } from '@tabler/icons'; import { IconAlertCircle, IconPlayerPause, IconPlayerPlay } from '@tabler/icons-react';
import { AxiosError } from 'axios'; import { AxiosError } from 'axios';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration'; import duration from 'dayjs/plugin/duration';

View File

@@ -1,5 +1,5 @@
import { Center, Group, Stack, Title } from '@mantine/core'; import { Center, Group, Stack, Title } from '@mantine/core';
import { IconDeviceCctv, IconHeartBroken } from '@tabler/icons'; import { IconDeviceCctv, IconHeartBroken } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import dynamic from 'next/dynamic'; import dynamic from 'next/dynamic';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';

View File

@@ -8,8 +8,8 @@ import {
IconQuestionMark, IconQuestionMark,
IconSnowflake, IconSnowflake,
IconSun, IconSun,
TablerIcon, Icon,
} from '@tabler/icons'; } from '@tabler/icons-react';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
interface WeatherIconProps { interface WeatherIconProps {
@@ -36,7 +36,7 @@ export const WeatherIcon = ({ code }: WeatherIconProps) => {
); );
}; };
type WeatherDefinitionType = { icon: TablerIcon; name: string; codes: number[] }; type WeatherDefinitionType = { icon: Icon; name: string; codes: number[] };
// 0 Clear sky // 0 Clear sky
// 1, 2, 3 Mainly clear, partly cloudy, and overcast // 1, 2, 3 Mainly clear, partly cloudy, and overcast

View File

@@ -1,6 +1,6 @@
import { Center, Group, Skeleton, Stack, Text, Title } from '@mantine/core'; import { Center, Group, Skeleton, Stack, Text, Title } from '@mantine/core';
import { useElementSize } from '@mantine/hooks'; import { useElementSize } from '@mantine/hooks';
import { IconArrowDownRight, IconArrowUpRight, IconCloudRain } from '@tabler/icons'; import { IconArrowDownRight, IconArrowUpRight, IconCloudRain } from '@tabler/icons-react';
import { defineWidget } from '../helper'; import { defineWidget } from '../helper';
import { IWidget } from '../widgets'; import { IWidget } from '../widgets';
import { useWeatherForCity } from './useWeatherForCity'; import { useWeatherForCity } from './useWeatherForCity';

View File

@@ -7,7 +7,7 @@ import {
SwitchProps, SwitchProps,
TextInputProps, TextInputProps,
} from '@mantine/core'; } from '@mantine/core';
import { TablerIcon } from '@tabler/icons'; import { Icon } from '@tabler/icons-react';
import { AreaType } from '../types/area'; import { AreaType } from '../types/area';
import { ShapeType } from '../types/shape'; import { ShapeType } from '../types/shape';
@@ -39,6 +39,7 @@ export type IWidgetOptionValue =
| ISelectOptionValue | ISelectOptionValue
| INumberInputOptionValue | INumberInputOptionValue
| IDraggableListInputValue | IDraggableListInputValue
| IDraggableEditableListInputValue<any>
| IMultipleTextInputOptionValue; | IMultipleTextInputOptionValue;
// Interface for data type // Interface for data type
@@ -107,6 +108,18 @@ export type IDraggableListInputValue = {
>; >;
}; };
export type IDraggableEditableListInputValue<TData extends { id: string }> = {
type: 'draggable-editable-list';
defaultValue: TData[];
create: () => TData;
getLabel: (data: TData) => string | JSX.Element;
itemComponent: (props: {
data: TData;
onChange: (data: TData) => void;
delete: () => void;
}) => JSX.Element;
};
// will show a text-input with a button to add a new line // will show a text-input with a button to add a new line
export type IMultipleTextInputOptionValue = { export type IMultipleTextInputOptionValue = {
type: 'multiple-text'; type: 'multiple-text';
@@ -117,7 +130,7 @@ export type IMultipleTextInputOptionValue = {
// is used to type the widget definitions which will be used to display all widgets // is used to type the widget definitions which will be used to display all widgets
export type IWidgetDefinition<TKey extends string = string> = { export type IWidgetDefinition<TKey extends string = string> = {
id: TKey; id: TKey;
icon: TablerIcon | string; icon: Icon | string;
options: { options: {
[key: string]: IWidgetOptionValue; [key: string]: IWidgetOptionValue;
}; };

View File

@@ -1,6 +0,0 @@
{
"env": {
"EDIT_MODE_PASSWORD": "edit",
"DISABLE_EDIT_MODE": "TRUE"
}
}

478
yarn.lock
View File

@@ -324,18 +324,18 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@ctrl/qbittorrent@npm:^4.1.0": "@ctrl/qbittorrent@npm:^6.0.0":
version: 4.1.0 version: 6.1.0
resolution: "@ctrl/qbittorrent@npm:4.1.0" resolution: "@ctrl/qbittorrent@npm:6.1.0"
dependencies: dependencies:
"@ctrl/magnet-link": ^3.1.1 "@ctrl/magnet-link": ^3.1.1
"@ctrl/shared-torrent": ^4.1.1 "@ctrl/shared-torrent": ^4.3.2
"@ctrl/torrent-file": ^2.0.2 "@ctrl/torrent-file": ^2.0.2
"@ctrl/url-join": ^2.0.2 "@ctrl/url-join": ^2.0.2
formdata-node: ^4.3.3 formdata-node: ^5.0.0
got: ^12.1.0 got: ^12.6.0
tough-cookie: ^4.0.0 tough-cookie: ^4.1.2
checksum: 0860100151785a661f30da50849dd18d2d057a6dd939afb351fdfc7c32daa99b2e621bfc35ce4fb3ec535cd4b76c489052ab60e8236f8aeca2a2b5d560fdce02 checksum: 6b40d46cdce31d8a5bea3dbc15705057ecfde45dd7ea2521fcec87d76d170d66aceaea7facda815fa0f62308a1189d9a5f029e4eed4fed1f652ac614eaf7d9d6
languageName: node languageName: node
linkType: hard linkType: hard
@@ -905,134 +905,134 @@ __metadata:
linkType: hard linkType: hard
"@mantine/core@npm:^6.0.0": "@mantine/core@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/core@npm:6.0.5" resolution: "@mantine/core@npm:6.0.10"
dependencies: dependencies:
"@floating-ui/react": ^0.19.1 "@floating-ui/react": ^0.19.1
"@mantine/styles": 6.0.5 "@mantine/styles": 6.0.10
"@mantine/utils": 6.0.5 "@mantine/utils": 6.0.10
"@radix-ui/react-scroll-area": 1.0.2 "@radix-ui/react-scroll-area": 1.0.2
react-remove-scroll: ^2.5.5 react-remove-scroll: ^2.5.5
react-textarea-autosize: 8.3.4 react-textarea-autosize: 8.3.4
peerDependencies: peerDependencies:
"@mantine/hooks": 6.0.5 "@mantine/hooks": 6.0.10
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: 3192610907952ecd02ceded8f5979b594eedc6ef149bc17656c66bc8ad553454867bb7a3fe8c206ed628ba149dc4a7733c0e316eb50d0069cf8bc6169582b75c checksum: 9ef041357599584eed7cc23b68d5cb4d9fc88db1f9942c2f51360bbaeec5a02b66bf87a3f11ac2f40180aef8f098512d325b4df26c5328239011102f34800f13
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/dates@npm:^6.0.0": "@mantine/dates@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/dates@npm:6.0.5" resolution: "@mantine/dates@npm:6.0.10"
dependencies: dependencies:
"@mantine/utils": 6.0.5 "@mantine/utils": 6.0.10
peerDependencies: peerDependencies:
"@mantine/core": 6.0.5 "@mantine/core": 6.0.10
"@mantine/hooks": 6.0.5 "@mantine/hooks": 6.0.10
dayjs: ">=1.0.0" dayjs: ">=1.0.0"
react: ">=16.8.0" react: ">=16.8.0"
checksum: 9b50a4d1c527602633a356d02739a0f798b1da92b9eb2e1ed095732aeab9a4a136c0a014df35edc586a78e9721eabd4979d6cea1befaaf8d49d0ee2f7eb5c175 checksum: 461f68437bba5e8ae40a132ff3d8bb562fc5a896366dfa913e8b2ba3c47a615957852540ed6d5569910a6cff57d95e9c8b05bd38be86d1e762c9bbf33d6c520b
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/dropzone@npm:^6.0.0": "@mantine/dropzone@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/dropzone@npm:6.0.5" resolution: "@mantine/dropzone@npm:6.0.10"
dependencies: dependencies:
"@mantine/utils": 6.0.5 "@mantine/utils": 6.0.10
react-dropzone: 14.2.3 react-dropzone: 14.2.3
peerDependencies: peerDependencies:
"@mantine/core": 6.0.5 "@mantine/core": 6.0.10
"@mantine/hooks": 6.0.5 "@mantine/hooks": 6.0.10
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: d5063297b0042d05519427fab145c1f47f3e20ba5bcf71546f504dad512d418fe5f0ed08e0c3118c9c5ce727fb33cda81946659c38c1e34af4d1a0d8fbfc86e1 checksum: 3a3758f2b603d085f70c7df62407ae55114e7c33c99a0a57a0adce9a05515663baac9bab04753442e48688a2517465e61288902aa3cab77912f8dba2330bfd3a
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/form@npm:^6.0.0": "@mantine/form@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/form@npm:6.0.5" resolution: "@mantine/form@npm:6.0.10"
dependencies: dependencies:
fast-deep-equal: ^3.1.3 fast-deep-equal: ^3.1.3
klona: ^2.0.5 klona: ^2.0.5
peerDependencies: peerDependencies:
react: ">=16.8.0" react: ">=16.8.0"
checksum: 49af767bdd5598953a30d55aea6f9eadbcda95df78db32c209e576a489469a0d86eefa155ed6199c662f2a8ab2a9bd05eb7ac1fb255b3c06d40f720fa5ea01d0 checksum: 2d792413d047a510790093e66478e4bceaaa258a4b88775c79a79a7800cb3ad0de7ab726e5a9e5c93b9cf66175c255f14077f4ff5961e4dcfd633f58420a64dc
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/hooks@npm:^6.0.0": "@mantine/hooks@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/hooks@npm:6.0.5" resolution: "@mantine/hooks@npm:6.0.10"
peerDependencies: peerDependencies:
react: ">=16.8.0" react: ">=16.8.0"
checksum: 2f8a1f155bf5e457484282d1ee1ab6e8d3356f48b01291820f828ac7978c8f960d711a576b4636753e604e4058e241b210f348e32adb2960be22aee84137ab63 checksum: 95c634f8e391b5ade9b4fa68b8fb8341e41db123703606647809260016471147e2fbf5b6c5266f557e5f260ef65d21c9d5048a98c9040fbb59df390fe1f6a014
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/modals@npm:^6.0.0": "@mantine/modals@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/modals@npm:6.0.5" resolution: "@mantine/modals@npm:6.0.10"
dependencies: dependencies:
"@mantine/utils": 6.0.5 "@mantine/utils": 6.0.10
peerDependencies: peerDependencies:
"@mantine/core": 6.0.5 "@mantine/core": 6.0.10
"@mantine/hooks": 6.0.5 "@mantine/hooks": 6.0.10
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: 1e78a8ef68db0a62a0a348b3a54cccacff4b700c095f1492c8f2f01e17dc138767e2e88eda0a81c4d39258691926cf83456b99c4de73d06578881e9f483bc147 checksum: 21747bc53c082fa289f3d2b8c8ab6b58230dd64984d89d594e3ef178f0d9097a84d8ccde5b2a5d1a2c7f7ac15c26bd5ad465a49ea4a269645ea7c480673a9189
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/next@npm:^6.0.0": "@mantine/next@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/next@npm:6.0.5" resolution: "@mantine/next@npm:6.0.10"
dependencies: dependencies:
"@mantine/ssr": 6.0.5 "@mantine/ssr": 6.0.10
"@mantine/styles": 6.0.5 "@mantine/styles": 6.0.10
peerDependencies: peerDependencies:
next: "*" next: "*"
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: de5768668e63a19f879a9b87e8df52e74ab80f3e53ea01935f0771ed56fd386ee8209735beecd898bf57c83df3de82a1e0dd821049a7604b85f8f431880d1cf9 checksum: 445a14e22731fa03724f9bcd04229f0b9730bc2a23136cb6a1c01f28778be653af71728e4098d7e4f38640ea943c71498acd13fe09c1b7b81f627fc9271a1fa2
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/notifications@npm:^6.0.0": "@mantine/notifications@npm:^6.0.0":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/notifications@npm:6.0.5" resolution: "@mantine/notifications@npm:6.0.10"
dependencies: dependencies:
"@mantine/utils": 6.0.5 "@mantine/utils": 6.0.10
react-transition-group: 4.4.2 react-transition-group: 4.4.2
peerDependencies: peerDependencies:
"@mantine/core": 6.0.5 "@mantine/core": 6.0.10
"@mantine/hooks": 6.0.5 "@mantine/hooks": 6.0.10
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: e39083e7d019f4d51de55e21406d2f601e08ee3450504829d4c15afac687eb2229741ad4d505b6868cba880f0f5d28715bc151b16cb575363d7eb94b74b2db48 checksum: 5b2d789b43547f18f06c7c39d65fa1e40df32529e6b83c85654d43f6cdd4def12f081ef71107789b26ece74a03c20880d7ed689d84d351ceabfad7a2731ba716
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/ssr@npm:6.0.5": "@mantine/ssr@npm:6.0.10":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/ssr@npm:6.0.5" resolution: "@mantine/ssr@npm:6.0.10"
dependencies: dependencies:
"@mantine/styles": 6.0.5 "@mantine/styles": 6.0.10
html-react-parser: 1.4.12 html-react-parser: 1.4.12
peerDependencies: peerDependencies:
"@emotion/react": ">=11.9.0" "@emotion/react": ">=11.9.0"
"@emotion/server": ">=11.4.0" "@emotion/server": ">=11.4.0"
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: d5546bc47df8cdaa059e03680c64f0a75551b77515e1dc0fce1b083043e10881e00dc968782b4a57efffa6e6e1288b008a578ee3223e79b87e76699ceca6a4ca checksum: 0340d04c5245fd2faf271e66918050c5259f48d02286f1f6a86d1c02b562cacc8b6782fe076e2b71e7167f7e08c02d2c976a21440e162b138800ff2b27d62433
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/styles@npm:6.0.5": "@mantine/styles@npm:6.0.10":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/styles@npm:6.0.5" resolution: "@mantine/styles@npm:6.0.10"
dependencies: dependencies:
clsx: 1.1.1 clsx: 1.1.1
csstype: 3.0.9 csstype: 3.0.9
@@ -1040,131 +1040,103 @@ __metadata:
"@emotion/react": ">=11.9.0" "@emotion/react": ">=11.9.0"
react: ">=16.8.0" react: ">=16.8.0"
react-dom: ">=16.8.0" react-dom: ">=16.8.0"
checksum: 074012e4899516cd701dbfa032c5eb9865f6a1460fc6ebdfb934d703283a0e9229b18f93ef54d8e9127ba63390e46429cf51a1fbea6ddb77cc1f815d36072797 checksum: b88de24de6d56cdd3734efff97590cc8beb2439c01e486a78f984866fdc4d11126432ffd4423cc1c8b8337609ff9114b5acfe54ddea2b968e550edd78116d141
languageName: node languageName: node
linkType: hard linkType: hard
"@mantine/utils@npm:6.0.5": "@mantine/utils@npm:6.0.10":
version: 6.0.5 version: 6.0.10
resolution: "@mantine/utils@npm:6.0.5" resolution: "@mantine/utils@npm:6.0.10"
peerDependencies: peerDependencies:
react: ">=16.8.0" react: ">=16.8.0"
checksum: cdaeb818b40f63136ccdcd3572866c681ad881b5a2dfa790c259f72a133a849678914e8a3b9fb146dab27e1494394a1c6fbb3a497ae767ddb884fd37eff2de50 checksum: 945e9a409ec74eb5cf811d87fd5859c6c5a520a36add1c90e9a7b50cc15dcc5a412f3f405f8be73a15e3c33682131c5aeb2b252809c1f32d2a6967970089ad3c
languageName: node languageName: node
linkType: hard linkType: hard
"@next/bundle-analyzer@npm:^12.1.4": "@next/bundle-analyzer@npm:^13.0.0":
version: 12.3.4 version: 13.4.2
resolution: "@next/bundle-analyzer@npm:12.3.4" resolution: "@next/bundle-analyzer@npm:13.4.2"
dependencies: dependencies:
webpack-bundle-analyzer: 4.3.0 webpack-bundle-analyzer: 4.7.0
checksum: 611cc07194a5cdd4aa0d1db5bae2de807cb2388d2c623f8d7ab8d581f8d01ec1510bd73ae3977334f7957278540ec0e2b2ebd48f9476235bd7b65055c560dc44 checksum: 2c17ec675139ee7f8b2388756c95a6c458db3c1a926c6b2192c409b955290f489ae070b630caaf2515293f77ded934c450dd7204677ccf5707bc768320293a3d
languageName: node languageName: node
linkType: hard linkType: hard
"@next/env@npm:13.2.4": "@next/env@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/env@npm:13.2.4" resolution: "@next/env@npm:13.4.2"
checksum: 4123e08a79e66d6144006972027a9ceb8f3fdd782c4a869df1eb3b91b59ad9f4a44082d3f8e421f4df5214c6bc7190b52b94881369452d65eb4580485f33b9e6 checksum: 103f0e836c16f69067410d780a411668c640b93cb380ba5a13a5d014f5e83bc9b4745c8840e319aebffc31b3cddeb9804e96ccca1411a11de0de6056c3d99f0a
languageName: node languageName: node
linkType: hard linkType: hard
"@next/eslint-plugin-next@npm:^12.1.4": "@next/eslint-plugin-next@npm:^13.0.0":
version: 12.3.4 version: 13.4.2
resolution: "@next/eslint-plugin-next@npm:12.3.4" resolution: "@next/eslint-plugin-next@npm:13.4.2"
dependencies: dependencies:
glob: 7.1.7 glob: 7.1.7
checksum: e4ae97062f3efe8f70904cf0da296ab501a2924423273352d01b18d8ffff1eb2e9a65c47dd6f9cfa0d696eada272486a3f519b2786918d0a9ab735b93f5ce4b3 checksum: be6d258eedeb52c120796076b0243d3b2f051e84b43990a4a61ab2e26e143982641e97c71ad7c657e9bb1054a7fe12eebb91e4b76dfc99953c859eff01ee9c89
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-android-arm-eabi@npm:13.2.4": "@next/swc-darwin-arm64@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-android-arm-eabi@npm:13.2.4" resolution: "@next/swc-darwin-arm64@npm:13.4.2"
conditions: os=android & cpu=arm
languageName: node
linkType: hard
"@next/swc-android-arm64@npm:13.2.4":
version: 13.2.4
resolution: "@next/swc-android-arm64@npm:13.2.4"
conditions: os=android & cpu=arm64
languageName: node
linkType: hard
"@next/swc-darwin-arm64@npm:13.2.4":
version: 13.2.4
resolution: "@next/swc-darwin-arm64@npm:13.2.4"
conditions: os=darwin & cpu=arm64 conditions: os=darwin & cpu=arm64
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-darwin-x64@npm:13.2.4": "@next/swc-darwin-x64@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-darwin-x64@npm:13.2.4" resolution: "@next/swc-darwin-x64@npm:13.4.2"
conditions: os=darwin & cpu=x64 conditions: os=darwin & cpu=x64
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-freebsd-x64@npm:13.2.4": "@next/swc-linux-arm64-gnu@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-freebsd-x64@npm:13.2.4" resolution: "@next/swc-linux-arm64-gnu@npm:13.4.2"
conditions: os=freebsd & cpu=x64
languageName: node
linkType: hard
"@next/swc-linux-arm-gnueabihf@npm:13.2.4":
version: 13.2.4
resolution: "@next/swc-linux-arm-gnueabihf@npm:13.2.4"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@next/swc-linux-arm64-gnu@npm:13.2.4":
version: 13.2.4
resolution: "@next/swc-linux-arm64-gnu@npm:13.2.4"
conditions: os=linux & cpu=arm64 & libc=glibc conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-linux-arm64-musl@npm:13.2.4": "@next/swc-linux-arm64-musl@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-linux-arm64-musl@npm:13.2.4" resolution: "@next/swc-linux-arm64-musl@npm:13.4.2"
conditions: os=linux & cpu=arm64 & libc=musl conditions: os=linux & cpu=arm64 & libc=musl
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-linux-x64-gnu@npm:13.2.4": "@next/swc-linux-x64-gnu@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-linux-x64-gnu@npm:13.2.4" resolution: "@next/swc-linux-x64-gnu@npm:13.4.2"
conditions: os=linux & cpu=x64 & libc=glibc conditions: os=linux & cpu=x64 & libc=glibc
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-linux-x64-musl@npm:13.2.4": "@next/swc-linux-x64-musl@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-linux-x64-musl@npm:13.2.4" resolution: "@next/swc-linux-x64-musl@npm:13.4.2"
conditions: os=linux & cpu=x64 & libc=musl conditions: os=linux & cpu=x64 & libc=musl
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-win32-arm64-msvc@npm:13.2.4": "@next/swc-win32-arm64-msvc@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-win32-arm64-msvc@npm:13.2.4" resolution: "@next/swc-win32-arm64-msvc@npm:13.4.2"
conditions: os=win32 & cpu=arm64 conditions: os=win32 & cpu=arm64
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-win32-ia32-msvc@npm:13.2.4": "@next/swc-win32-ia32-msvc@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-win32-ia32-msvc@npm:13.2.4" resolution: "@next/swc-win32-ia32-msvc@npm:13.4.2"
conditions: os=win32 & cpu=ia32 conditions: os=win32 & cpu=ia32
languageName: node languageName: node
linkType: hard linkType: hard
"@next/swc-win32-x64-msvc@npm:13.2.4": "@next/swc-win32-x64-msvc@npm:13.4.2":
version: 13.2.4 version: 13.4.2
resolution: "@next/swc-win32-x64-msvc@npm:13.2.4" resolution: "@next/swc-win32-x64-msvc@npm:13.4.2"
conditions: os=win32 & cpu=x64 conditions: os=win32 & cpu=x64
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1602,12 +1574,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@swc/helpers@npm:0.4.14": "@swc/helpers@npm:0.5.1":
version: 0.4.14 version: 0.5.1
resolution: "@swc/helpers@npm:0.4.14" resolution: "@swc/helpers@npm:0.5.1"
dependencies: dependencies:
tslib: ^2.4.0 tslib: ^2.4.0
checksum: 273fd3f3fc461a92f3790cc551ea054745c6d6959afbe1232e6d7aa1c722bbc114d308aab96bef5c78fc0303c85c7b472ef00e2253251cc89737f3b1af56e5a5 checksum: 71e0e27234590435e4c62b97ef5e796f88e786841a38c7116a5e27a3eafa7b9ead7cdec5249b32165902076de78446945311c973e59bddf77c1e24f33a8f272a
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1629,18 +1601,22 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@tabler/icons@npm:^1.106.0": "@tabler/icons-react@npm:^2.18.0":
version: 1.119.0 version: 2.18.0
resolution: "@tabler/icons@npm:1.119.0" resolution: "@tabler/icons-react@npm:2.18.0"
dependencies:
"@tabler/icons": 2.18.0
prop-types: ^15.7.2
peerDependencies: peerDependencies:
react: ^16.x || 17.x || 18.x react: ^16.5.1 || ^17.0.0 || ^18.0.0
react-dom: ^16.x || 17.x || 18.x checksum: 9a3d3121811b0e63ce6a4748d0ef306c394b7d7c5ac861e643928f2e3d36b40c7f53981672d6bcdc1245cfb02fc3114360390ed7f4e60e2abb05641f1a12aed9
peerDependenciesMeta: languageName: node
react: linkType: hard
optional: true
react-dom: "@tabler/icons@npm:2.18.0":
optional: true version: 2.18.0
checksum: ef1ac50c1a47b2205cb86ca43c28d69c7b8f547ad9c2c5545190fc4a455e9767f49cb511a6f9e8dc45b046ee7d2dab3d2c87af4fd5bbb1694832a15698158753 resolution: "@tabler/icons@npm:2.18.0"
checksum: 2257b5f39c570e3e87d1c6d9cfb2a1b6326600d39c42a077c491f584f9769efc9d9c361df1d3099243774d18cdaa5506075595a3fd626c82e812dd2b43700e34
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1654,70 +1630,70 @@ __metadata:
linkType: hard linkType: hard
"@tanstack/query-async-storage-persister@npm:^4.27.1": "@tanstack/query-async-storage-persister@npm:^4.27.1":
version: 4.27.1 version: 4.29.7
resolution: "@tanstack/query-async-storage-persister@npm:4.27.1" resolution: "@tanstack/query-async-storage-persister@npm:4.29.7"
dependencies: dependencies:
"@tanstack/query-persist-client-core": 4.27.0 "@tanstack/query-persist-client-core": 4.29.7
checksum: f98da672c6a61c65a58dc3d1b6e4416800bbd61747f806cc8cfceecb9f8bf4fa6be4133036f0b2efd5177e6f93031bb84e2ee53d888e9d6c34cc11f8aede97f4 checksum: 836998442e6cb24705c7c17e35c49d200ff774bcdb9363655b17ec4df7e9c0eba85ce8e4449085017de17baa9a8348d3ff645431459e9dc04bb9bbe4a86aee55
languageName: node languageName: node
linkType: hard linkType: hard
"@tanstack/query-core@npm:4.27.0": "@tanstack/query-core@npm:4.29.7":
version: 4.27.0 version: 4.29.7
resolution: "@tanstack/query-core@npm:4.27.0" resolution: "@tanstack/query-core@npm:4.29.7"
checksum: 914b4f01ac75632f4603b650e9105f64c739b79250baf76aad16cee216f7bad6060c04eda0c70838fe61a5f6c17883e19fcc3075b2433a906539da95ce785796 checksum: f28441a1fc17881d770ebacbe3a2fcf58bd065ac0cf58f8dc544d367f00d7f65213e09a1a1280e021eef25a50b307cac6884173b5acf32570e755baf29b741aa
languageName: node languageName: node
linkType: hard linkType: hard
"@tanstack/query-persist-client-core@npm:4.27.0": "@tanstack/query-persist-client-core@npm:4.29.7":
version: 4.27.0 version: 4.29.7
resolution: "@tanstack/query-persist-client-core@npm:4.27.0" resolution: "@tanstack/query-persist-client-core@npm:4.29.7"
dependencies: dependencies:
"@tanstack/query-core": 4.27.0 "@tanstack/query-core": 4.29.7
checksum: 9a2df41744269d666bc0c1a5684a1d9d327e7994b57f9c1a71ea86d169dbde94f9d4af4b4ebe258d0085e0aa2cd563460b06513eccc4b016c0c5d416122d0275 checksum: d9ca2ad0fcec2e11f9189ac5d3544eaff3b6c31b8e8b00fb973222a5618c91d95e24c8e0397b552b714a76af5232cda061a4cf8ed7816acacfc4c0dfc8f1b303
languageName: node languageName: node
linkType: hard linkType: hard
"@tanstack/query-sync-storage-persister@npm:^4.27.1": "@tanstack/query-sync-storage-persister@npm:^4.27.1":
version: 4.27.1 version: 4.29.7
resolution: "@tanstack/query-sync-storage-persister@npm:4.27.1" resolution: "@tanstack/query-sync-storage-persister@npm:4.29.7"
dependencies: dependencies:
"@tanstack/query-persist-client-core": 4.27.0 "@tanstack/query-persist-client-core": 4.29.7
checksum: 16cdef50af43cf854ec1244f43609c04f9a9fcb7bbb36c763ce3146aeb85095c62da098fb4c4876d76496fa5830d54c6e79691d2b353919b1e5f274a3c34a97e checksum: 135d50e4afc43e3a362a4dfaaeb3abf4b39102af9e4b6077f523d6722b94948f3791397618a9c6a0175dbd8ec2e60edf6a008e9541f1e0f792b518ce1ae4b423
languageName: node languageName: node
linkType: hard linkType: hard
"@tanstack/react-query-devtools@npm:^4.24.4": "@tanstack/react-query-devtools@npm:^4.24.4":
version: 4.28.0 version: 4.29.7
resolution: "@tanstack/react-query-devtools@npm:4.28.0" resolution: "@tanstack/react-query-devtools@npm:4.29.7"
dependencies: dependencies:
"@tanstack/match-sorter-utils": ^8.7.0 "@tanstack/match-sorter-utils": ^8.7.0
superjson: ^1.10.0 superjson: ^1.10.0
use-sync-external-store: ^1.2.0 use-sync-external-store: ^1.2.0
peerDependencies: peerDependencies:
"@tanstack/react-query": 4.28.0 "@tanstack/react-query": 4.29.7
react: ^16.8.0 || ^17.0.0 || ^18.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: 76d39c4f5d2a884e6b7af9dee39f1f2427da515cd6bd3ddc99d1d97ec5fa01db5c134ac0d0fab57cdc860a736a3aa0443cc35295e302e9ff119b023663d073a6 checksum: deb28b3d7d614d5bede33b2b643903aaaff8b215ba0620d48b9b4dd32fcdd88947879afab883f8ac0347656be0c9448d850d6e962307314e903074ac51e802b5
languageName: node languageName: node
linkType: hard linkType: hard
"@tanstack/react-query-persist-client@npm:^4.28.0": "@tanstack/react-query-persist-client@npm:^4.28.0":
version: 4.28.0 version: 4.29.7
resolution: "@tanstack/react-query-persist-client@npm:4.28.0" resolution: "@tanstack/react-query-persist-client@npm:4.29.7"
dependencies: dependencies:
"@tanstack/query-persist-client-core": 4.27.0 "@tanstack/query-persist-client-core": 4.29.7
peerDependencies: peerDependencies:
"@tanstack/react-query": 4.28.0 "@tanstack/react-query": 4.29.7
checksum: 8177b41ae644774f380154ec09588cce21b6bf75f45d58691cc86fd58002927989f47e278170a1ae9c3c02638a7e26d67a29106c768d325a54cef9219115839d checksum: 6e005cd27946e6977fa0371d8316b9f0c0ac97b95a127785ffb8dec8946403d98c82f47c9e8c659732ffe544069a792d95950d393ed480a1ec5d37f6b272e5b6
languageName: node languageName: node
linkType: hard linkType: hard
"@tanstack/react-query@npm:^4.2.1": "@tanstack/react-query@npm:^4.2.1":
version: 4.28.0 version: 4.29.7
resolution: "@tanstack/react-query@npm:4.28.0" resolution: "@tanstack/react-query@npm:4.29.7"
dependencies: dependencies:
"@tanstack/query-core": 4.27.0 "@tanstack/query-core": 4.29.7
use-sync-external-store: ^1.2.0 use-sync-external-store: ^1.2.0
peerDependencies: peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 react: ^16.8.0 || ^17.0.0 || ^18.0.0
@@ -1728,7 +1704,7 @@ __metadata:
optional: true optional: true
react-native: react-native:
optional: true optional: true
checksum: 7baa70d22b55cfa22f8a1d92ba9f8379c5436ee81fce3f0e7df4a8c29bb26bfef4a83759cf10f752b40ae2940099fcce88ce91a773240f4999ae91136980c6e3 checksum: 9db2fb78e18f299c0e58f3c177261f6010fdea63a5f950e4c93a7cf7a46da019aa3171c77759fa7b327e35763e3379f0a885c71dafd9aa99bf2ddda9f264de90
languageName: node languageName: node
linkType: hard linkType: hard
@@ -2630,7 +2606,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"axios@npm:0.27.2, axios@npm:^0.27.2": "axios@npm:0.27.2":
version: 0.27.2 version: 0.27.2
resolution: "axios@npm:0.27.2" resolution: "axios@npm:0.27.2"
dependencies: dependencies:
@@ -2640,6 +2616,17 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"axios@npm:^1.0.0":
version: 1.4.0
resolution: "axios@npm:1.4.0"
dependencies:
follow-redirects: ^1.15.0
form-data: ^4.0.0
proxy-from-env: ^1.1.0
checksum: 7fb6a4313bae7f45e89d62c70a800913c303df653f19eafec88e56cea2e3821066b8409bc68be1930ecca80e861c52aa787659df0ffec6ad4d451c7816b9386b
languageName: node
linkType: hard
"axobject-query@npm:^3.1.1": "axobject-query@npm:^3.1.1":
version: 3.1.1 version: 3.1.1
resolution: "axobject-query@npm:3.1.1" resolution: "axobject-query@npm:3.1.1"
@@ -2767,6 +2754,15 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"busboy@npm:1.6.0":
version: 1.6.0
resolution: "busboy@npm:1.6.0"
dependencies:
streamsearch: ^1.1.0
checksum: 32801e2c0164e12106bf236291a00795c3c4e4b709ae02132883fe8478ba2ae23743b11c5735a0aae8afe65ac4b6ca4568b91f0d9fed1fdbc32ede824a73746e
languageName: node
linkType: hard
"c8@npm:^7.13.0": "c8@npm:^7.13.0":
version: 7.13.0 version: 7.13.0
resolution: "c8@npm:7.13.0" resolution: "c8@npm:7.13.0"
@@ -3084,10 +3080,10 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"commander@npm:^6.2.0": "commander@npm:^7.2.0":
version: 6.2.1 version: 7.2.0
resolution: "commander@npm:6.2.1" resolution: "commander@npm:7.2.0"
checksum: d7090410c0de6bc5c67d3ca41c41760d6d268f3c799e530aafb73b7437d1826bbf0d2a3edac33f8b57cc9887b4a986dce307fa5557e109be40eadb7c43b21742 checksum: 53501cbeee61d5157546c0bef0fedb6cdfc763a882136284bed9a07225f09a14b82d2a84e7637edfd1a679fb35ed9502fd58ef1d091e6287f60d790147f68ddc
languageName: node languageName: node
linkType: hard linkType: hard
@@ -4397,7 +4393,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"follow-redirects@npm:^1.14.9": "follow-redirects@npm:^1.14.9, follow-redirects@npm:^1.15.0":
version: 1.15.2 version: 1.15.2
resolution: "follow-redirects@npm:1.15.2" resolution: "follow-redirects@npm:1.15.2"
peerDependenciesMeta: peerDependenciesMeta:
@@ -4444,16 +4440,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"formdata-node@npm:^4.3.3":
version: 4.4.1
resolution: "formdata-node@npm:4.4.1"
dependencies:
node-domexception: 1.0.0
web-streams-polyfill: 4.0.0-beta.3
checksum: d91d4f667cfed74827fc281594102c0dabddd03c9f8b426fc97123eedbf73f5060ee43205d89284d6854e2fc5827e030cd352ef68b93beda8decc2d72128c576
languageName: node
linkType: hard
"formdata-node@npm:^5.0.0": "formdata-node@npm:^5.0.0":
version: 5.0.0 version: 5.0.0
resolution: "formdata-node@npm:5.0.0" resolution: "formdata-node@npm:5.0.0"
@@ -4522,7 +4508,7 @@ __metadata:
"fsevents@patch:fsevents@~2.3.2#~builtin<compat/fsevents>": "fsevents@patch:fsevents@~2.3.2#~builtin<compat/fsevents>":
version: 2.3.2 version: 2.3.2
resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin<compat/fsevents>::version=2.3.2&hash=18f3a7" resolution: "fsevents@patch:fsevents@npm%3A2.3.2#~builtin<compat/fsevents>::version=2.3.2&hash=df0bf1"
dependencies: dependencies:
node-gyp: latest node-gyp: latest
conditions: os=darwin conditions: os=darwin
@@ -4772,7 +4758,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"got@npm:^12.1.0, got@npm:^12.5.0, got@npm:^12.5.2, got@npm:^12.6.0": "got@npm:^12.5.0, got@npm:^12.5.2, got@npm:^12.6.0":
version: 12.6.0 version: 12.6.0
resolution: "got@npm:12.6.0" resolution: "got@npm:12.6.0"
dependencies: dependencies:
@@ -4921,7 +4907,7 @@ __metadata:
resolution: "homarr@workspace:." resolution: "homarr@workspace:."
dependencies: dependencies:
"@ctrl/deluge": ^4.1.0 "@ctrl/deluge": ^4.1.0
"@ctrl/qbittorrent": ^4.1.0 "@ctrl/qbittorrent": ^6.0.0
"@ctrl/shared-torrent": ^4.1.1 "@ctrl/shared-torrent": ^4.1.1
"@ctrl/transmission": ^4.1.1 "@ctrl/transmission": ^4.1.1
"@emotion/react": ^11.10.6 "@emotion/react": ^11.10.6
@@ -4935,12 +4921,12 @@ __metadata:
"@mantine/modals": ^6.0.0 "@mantine/modals": ^6.0.0
"@mantine/next": ^6.0.0 "@mantine/next": ^6.0.0
"@mantine/notifications": ^6.0.0 "@mantine/notifications": ^6.0.0
"@next/bundle-analyzer": ^12.1.4 "@next/bundle-analyzer": ^13.0.0
"@next/eslint-plugin-next": ^12.1.4 "@next/eslint-plugin-next": ^13.0.0
"@nivo/core": ^0.80.0 "@nivo/core": ^0.80.0
"@nivo/line": ^0.80.0 "@nivo/line": ^0.80.0
"@react-native-async-storage/async-storage": ^1.18.1 "@react-native-async-storage/async-storage": ^1.18.1
"@tabler/icons": ^1.106.0 "@tabler/icons-react": ^2.18.0
"@tanstack/query-async-storage-persister": ^4.27.1 "@tanstack/query-async-storage-persister": ^4.27.1
"@tanstack/query-sync-storage-persister": ^4.27.1 "@tanstack/query-sync-storage-persister": ^4.27.1
"@tanstack/react-query": ^4.2.1 "@tanstack/react-query": ^4.2.1
@@ -4959,7 +4945,7 @@ __metadata:
"@vitejs/plugin-react": ^3.1.0 "@vitejs/plugin-react": ^3.1.0
"@vitest/coverage-c8": ^0.29.3 "@vitest/coverage-c8": ^0.29.3
"@vitest/ui": ^0.29.3 "@vitest/ui": ^0.29.3
axios: ^0.27.2 axios: ^1.0.0
consola: ^2.15.3 consola: ^2.15.3
cookies-next: ^2.1.1 cookies-next: ^2.1.1
dayjs: ^1.11.7 dayjs: ^1.11.7
@@ -4994,7 +4980,7 @@ __metadata:
sabnzbd-api: ^1.5.0 sabnzbd-api: ^1.5.0
sass: ^1.56.1 sass: ^1.56.1
turbo: latest turbo: latest
typescript: ^4.7.4 typescript: ^5.0.0
uuid: ^8.3.2 uuid: ^8.3.2
video.js: ^8.0.3 video.js: ^8.0.3
vitest: ^0.29.3 vitest: ^0.29.3
@@ -6323,47 +6309,37 @@ __metadata:
linkType: hard linkType: hard
"next@npm:^13.2.1": "next@npm:^13.2.1":
version: 13.2.4 version: 13.4.2
resolution: "next@npm:13.2.4" resolution: "next@npm:13.4.2"
dependencies: dependencies:
"@next/env": 13.2.4 "@next/env": 13.4.2
"@next/swc-android-arm-eabi": 13.2.4 "@next/swc-darwin-arm64": 13.4.2
"@next/swc-android-arm64": 13.2.4 "@next/swc-darwin-x64": 13.4.2
"@next/swc-darwin-arm64": 13.2.4 "@next/swc-linux-arm64-gnu": 13.4.2
"@next/swc-darwin-x64": 13.2.4 "@next/swc-linux-arm64-musl": 13.4.2
"@next/swc-freebsd-x64": 13.2.4 "@next/swc-linux-x64-gnu": 13.4.2
"@next/swc-linux-arm-gnueabihf": 13.2.4 "@next/swc-linux-x64-musl": 13.4.2
"@next/swc-linux-arm64-gnu": 13.2.4 "@next/swc-win32-arm64-msvc": 13.4.2
"@next/swc-linux-arm64-musl": 13.2.4 "@next/swc-win32-ia32-msvc": 13.4.2
"@next/swc-linux-x64-gnu": 13.2.4 "@next/swc-win32-x64-msvc": 13.4.2
"@next/swc-linux-x64-musl": 13.2.4 "@swc/helpers": 0.5.1
"@next/swc-win32-arm64-msvc": 13.2.4 busboy: 1.6.0
"@next/swc-win32-ia32-msvc": 13.2.4
"@next/swc-win32-x64-msvc": 13.2.4
"@swc/helpers": 0.4.14
caniuse-lite: ^1.0.30001406 caniuse-lite: ^1.0.30001406
postcss: 8.4.14 postcss: 8.4.14
styled-jsx: 5.1.1 styled-jsx: 5.1.1
zod: 3.21.4
peerDependencies: peerDependencies:
"@opentelemetry/api": ^1.4.0 "@opentelemetry/api": ^1.1.0
fibers: ">= 3.1.0" fibers: ">= 3.1.0"
node-sass: ^6.0.0 || ^7.0.0 node-sass: ^6.0.0 || ^7.0.0
react: ^18.2.0 react: ^18.2.0
react-dom: ^18.2.0 react-dom: ^18.2.0
sass: ^1.3.0 sass: ^1.3.0
dependenciesMeta: dependenciesMeta:
"@next/swc-android-arm-eabi":
optional: true
"@next/swc-android-arm64":
optional: true
"@next/swc-darwin-arm64": "@next/swc-darwin-arm64":
optional: true optional: true
"@next/swc-darwin-x64": "@next/swc-darwin-x64":
optional: true optional: true
"@next/swc-freebsd-x64":
optional: true
"@next/swc-linux-arm-gnueabihf":
optional: true
"@next/swc-linux-arm64-gnu": "@next/swc-linux-arm64-gnu":
optional: true optional: true
"@next/swc-linux-arm64-musl": "@next/swc-linux-arm64-musl":
@@ -6389,7 +6365,7 @@ __metadata:
optional: true optional: true
bin: bin:
next: dist/bin/next next: dist/bin/next
checksum: 8531dee41b60181b582f5ee80858907b102f083ef8808ff9352d589dd39e6b3a96f7a11b3776a03eef3a28430cff768336fa2e3ff2c6f8fcd699fbc891749051 checksum: 73b9da0d72b54720791ec3e3a3c79922172de5df01d5157507bd095033c33cd611f35da3310d859b3a75456977a4a9a4ef311074517b172dddc92dc769e03e49
languageName: node languageName: node
linkType: hard linkType: hard
@@ -6921,7 +6897,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"prop-types@npm:^15.6.2, prop-types@npm:^15.8.1": "prop-types@npm:^15.6.2, prop-types@npm:^15.7.2, prop-types@npm:^15.8.1":
version: 15.8.1 version: 15.8.1
resolution: "prop-types@npm:15.8.1" resolution: "prop-types@npm:15.8.1"
dependencies: dependencies:
@@ -6932,6 +6908,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"proxy-from-env@npm:^1.1.0":
version: 1.1.0
resolution: "proxy-from-env@npm:1.1.0"
checksum: ed7fcc2ba0a33404958e34d95d18638249a68c430e30fcb6c478497d72739ba64ce9810a24f53a7d921d0c065e5b78e3822759800698167256b04659366ca4d4
languageName: node
linkType: hard
"psl@npm:^1.1.33": "psl@npm:^1.1.33":
version: 1.9.0 version: 1.9.0
resolution: "psl@npm:1.9.0" resolution: "psl@npm:1.9.0"
@@ -7313,7 +7296,7 @@ __metadata:
"resolve@patch:resolve@^1.19.0#~builtin<compat/resolve>, resolve@patch:resolve@^1.22.1#~builtin<compat/resolve>": "resolve@patch:resolve@^1.19.0#~builtin<compat/resolve>, resolve@patch:resolve@^1.22.1#~builtin<compat/resolve>":
version: 1.22.1 version: 1.22.1
resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin<compat/resolve>::version=1.22.1&hash=07638b" resolution: "resolve@patch:resolve@npm%3A1.22.1#~builtin<compat/resolve>::version=1.22.1&hash=c3c19d"
dependencies: dependencies:
is-core-module: ^2.9.0 is-core-module: ^2.9.0
path-parse: ^1.0.7 path-parse: ^1.0.7
@@ -7326,7 +7309,7 @@ __metadata:
"resolve@patch:resolve@^2.0.0-next.4#~builtin<compat/resolve>": "resolve@patch:resolve@^2.0.0-next.4#~builtin<compat/resolve>":
version: 2.0.0-next.4 version: 2.0.0-next.4
resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin<compat/resolve>::version=2.0.0-next.4&hash=07638b" resolution: "resolve@patch:resolve@npm%3A2.0.0-next.4#~builtin<compat/resolve>::version=2.0.0-next.4&hash=c3c19d"
dependencies: dependencies:
is-core-module: ^2.9.0 is-core-module: ^2.9.0
path-parse: ^1.0.7 path-parse: ^1.0.7
@@ -7723,6 +7706,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"streamsearch@npm:^1.1.0":
version: 1.1.0
resolution: "streamsearch@npm:1.1.0"
checksum: 1cce16cea8405d7a233d32ca5e00a00169cc0e19fbc02aa839959985f267335d435c07f96e5e0edd0eadc6d39c98d5435fb5bbbdefc62c41834eadc5622ad942
languageName: node
linkType: hard
"string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": "string-width@npm:^1.0.2 || 2 || 3 || 4, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3":
version: 4.2.3 version: 4.2.3
resolution: "string-width@npm:4.2.3" resolution: "string-width@npm:4.2.3"
@@ -8076,7 +8066,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"tough-cookie@npm:^4.0.0, tough-cookie@npm:^4.1.2": "tough-cookie@npm:^4.1.2":
version: 4.1.2 version: 4.1.2
resolution: "tough-cookie@npm:4.1.2" resolution: "tough-cookie@npm:4.1.2"
dependencies: dependencies:
@@ -8254,23 +8244,23 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"typescript@npm:^4.7.4": "typescript@npm:^5.0.0":
version: 4.9.5 version: 5.0.4
resolution: "typescript@npm:4.9.5" resolution: "typescript@npm:5.0.4"
bin: bin:
tsc: bin/tsc tsc: bin/tsc
tsserver: bin/tsserver tsserver: bin/tsserver
checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db checksum: 82b94da3f4604a8946da585f7d6c3025fff8410779e5bde2855ab130d05e4fd08938b9e593b6ebed165bda6ad9292b230984f10952cf82f0a0ca07bbeaa08172
languageName: node languageName: node
linkType: hard linkType: hard
"typescript@patch:typescript@^4.7.4#~builtin<compat/typescript>": "typescript@patch:typescript@^5.0.0#~builtin<compat/typescript>":
version: 4.9.5 version: 5.0.4
resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin<compat/typescript>::version=4.9.5&hash=7ad353" resolution: "typescript@patch:typescript@npm%3A5.0.4#~builtin<compat/typescript>::version=5.0.4&hash=b5f058"
bin: bin:
tsc: bin/tsc tsc: bin/tsc
tsserver: bin/tsserver tsserver: bin/tsserver
checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 checksum: d26b6ba97b6d163c55dbdffd9bbb4c211667ebebc743accfeb2c8c0154aace7afd097b51165a72a5bad2cf65a4612259344ff60f8e642362aa1695c760d303ac
languageName: node languageName: node
linkType: hard linkType: hard
@@ -8662,14 +8652,14 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"webpack-bundle-analyzer@npm:4.3.0": "webpack-bundle-analyzer@npm:4.7.0":
version: 4.3.0 version: 4.7.0
resolution: "webpack-bundle-analyzer@npm:4.3.0" resolution: "webpack-bundle-analyzer@npm:4.7.0"
dependencies: dependencies:
acorn: ^8.0.4 acorn: ^8.0.4
acorn-walk: ^8.0.0 acorn-walk: ^8.0.0
chalk: ^4.1.0 chalk: ^4.1.0
commander: ^6.2.0 commander: ^7.2.0
gzip-size: ^6.0.0 gzip-size: ^6.0.0
lodash: ^4.17.20 lodash: ^4.17.20
opener: ^1.5.2 opener: ^1.5.2
@@ -8677,7 +8667,7 @@ __metadata:
ws: ^7.3.1 ws: ^7.3.1
bin: bin:
webpack-bundle-analyzer: lib/bin/analyzer.js webpack-bundle-analyzer: lib/bin/analyzer.js
checksum: 00b7bf4ac9fca17062b66b6897145b94e87153d3ec8815f0e0c05a3b8a1ca75320262db01a5fa634f604ee3d41aecde1ee59838d05b6d03cd5be62eb1addbcf8 checksum: 4ce3b379c61ce16b2219756843407cc99f2b82cd191f653043f1b705a3e32b3af03834af0dfded98ab852313a892a148bed1a8effaacd6440f028c19f41581f3
languageName: node languageName: node
linkType: hard linkType: hard
@@ -8936,7 +8926,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"zod@npm:^3.21.4": "zod@npm:3.21.4, zod@npm:^3.21.4":
version: 3.21.4 version: 3.21.4
resolution: "zod@npm:3.21.4" resolution: "zod@npm:3.21.4"
checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f checksum: f185ba87342ff16f7a06686767c2b2a7af41110c7edf7c1974095d8db7a73792696bcb4a00853de0d2edeb34a5b2ea6a55871bc864227dace682a0a28de33e1f