mirror of
https://github.com/spacedriveapp/spacedrive
synced 2024-07-13 08:24:04 +00:00
Improve AddLocationButton & Implement UI for indexer rules (#620)
* Improve AddLocationButton + Implement UI for indexer rules * Minor code clean-ups - Remove unused variables and imports * cleanup AddLocationDialog props --------- Co-authored-by: Brendan Allan <brendonovich@outlook.com>
This commit is contained in:
parent
a6a57bbd50
commit
0fd53d1287
|
@ -1,48 +0,0 @@
|
|||
import { useLibraryMutation, usePlausibleEvent } from '@sd/client';
|
||||
import { dialogManager } from '@sd/ui';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
import AddLocationDialog from '../../settings/library/locations/AddDialog';
|
||||
|
||||
export default () => {
|
||||
const platform = usePlatform();
|
||||
const submitPlausibleEvent = usePlausibleEvent({ platformType: platform.platform });
|
||||
const createLocation = useLibraryMutation('locations.create', {
|
||||
onSuccess: () => {
|
||||
submitPlausibleEvent({
|
||||
event: {
|
||||
type: 'locationCreate'
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={() => {
|
||||
if (platform.platform === 'web') {
|
||||
dialogManager.create((dp) => <AddLocationDialog {...dp} />);
|
||||
} else {
|
||||
if (!platform.openDirectoryPickerDialog) {
|
||||
alert('Opening a dialogue is not supported on this platform!');
|
||||
return;
|
||||
}
|
||||
platform.openDirectoryPickerDialog().then((result) => {
|
||||
// TODO: Pass indexer rules ids to create location
|
||||
if (result)
|
||||
createLocation.mutate({
|
||||
path: result as string,
|
||||
indexer_rules_ids: []
|
||||
});
|
||||
});
|
||||
}
|
||||
}}
|
||||
className="
|
||||
border-sidebar-line hover:border-sidebar-selected cursor-normal text-ink-faint mt-1 w-full rounded
|
||||
border border-dashed px-2 py-1 text-center
|
||||
text-xs font-medium transition
|
||||
"
|
||||
>
|
||||
Add Location
|
||||
</button>
|
||||
);
|
||||
};
|
|
@ -22,11 +22,11 @@ import {
|
|||
useOnlineLocations
|
||||
} from '@sd/client';
|
||||
import { Button, ButtonLink, Folder, Loader, Popover, Tooltip } from '@sd/ui';
|
||||
import { AddLocationButton } from '~/app/$libraryId/settings/library/locations/AddLocationButton';
|
||||
import { SubtleButton } from '~/components/SubtleButton';
|
||||
import { MacTrafficLights } from '~/components/TrafficLights';
|
||||
import { useOperatingSystem } from '~/hooks/useOperatingSystem';
|
||||
import { OperatingSystem, usePlatform } from '~/util/Platform';
|
||||
import AddLocationButton from './AddLocationButton';
|
||||
import DebugPopover from './DebugPopover';
|
||||
import Icon from './Icon';
|
||||
import { JobsManager } from './JobManager';
|
||||
|
@ -118,7 +118,13 @@ const LibrarySection = () => {
|
|||
</SidebarLink>
|
||||
);
|
||||
})}
|
||||
{(locations.data?.length || 0) < 4 && <AddLocationButton />}
|
||||
{(locations.data?.length || 0) < 4 && (
|
||||
<AddLocationButton
|
||||
className="border-sidebar-line hover:border-sidebar-selected cursor-normal
|
||||
text-ink-faint mt-1 w-full rounded border border-dashed px-2 py-1
|
||||
text-center text-xs font-medium transition"
|
||||
/>
|
||||
)}
|
||||
</Section>
|
||||
{!!tags.data?.length && (
|
||||
<Section
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
import { useLibraryMutation } from '@sd/client';
|
||||
import { Dialog, UseDialogProps, useDialog } from '@sd/ui';
|
||||
import { Input, useZodForm, z } from '@sd/ui/src/forms';
|
||||
|
||||
const schema = z.object({ path: z.string() });
|
||||
|
||||
type Props = UseDialogProps;
|
||||
|
||||
export default function AddLocationDialog(props: Props) {
|
||||
const dialog = useDialog(props);
|
||||
const createLocation = useLibraryMutation('locations.create');
|
||||
|
||||
const form = useZodForm({
|
||||
schema,
|
||||
defaultValues: {
|
||||
// BEFORE MERGE: Remove default value
|
||||
path: '/Users/jamie/Projects/spacedrive/packages/test-files/files'
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
{...{ dialog, form }}
|
||||
onSubmit={form.handleSubmit(({ path }) =>
|
||||
createLocation.mutateAsync({
|
||||
path,
|
||||
indexer_rules_ids: []
|
||||
})
|
||||
)}
|
||||
title="Add Location URL"
|
||||
description="As you are using the browser version of Spacedrive you will (for now) need to specify an absolute URL of a directory local to the remote node."
|
||||
ctaLabel="Add"
|
||||
>
|
||||
<Input
|
||||
className="mt-3 w-full grow"
|
||||
placeholder="/Users/jamie/Movies"
|
||||
required
|
||||
{...form.register('path')}
|
||||
/>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import { Button, ButtonProps, dialogManager } from '@sd/ui';
|
||||
import { showAlertDialog } from '~/components/AlertDialog';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
import { AddLocationDialog } from './AddLocationDialog';
|
||||
|
||||
export const AddLocationButton = (props: ButtonProps) => {
|
||||
const platform = usePlatform();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
{...props}
|
||||
onClick={async () => {
|
||||
let path = '';
|
||||
if (platform.openDirectoryPickerDialog) {
|
||||
const _path = await platform.openDirectoryPickerDialog();
|
||||
if (!_path) return;
|
||||
if (typeof _path !== 'string') {
|
||||
// TODO: Should support for adding multiple locations simultaneously be added?
|
||||
showAlertDialog({
|
||||
title: 'Error',
|
||||
value: "Can't add multiple locations"
|
||||
});
|
||||
return;
|
||||
}
|
||||
path = _path;
|
||||
}
|
||||
|
||||
await dialogManager.create((dp) => <AddLocationDialog path={path} {...dp} />);
|
||||
}}
|
||||
>
|
||||
Add Location
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -0,0 +1,112 @@
|
|||
import { ChangeEvent } from 'react';
|
||||
import { Controller } from 'react-hook-form';
|
||||
import { useLibraryMutation, useLibraryQuery } from '@sd/client';
|
||||
import { CheckBox, Dialog, UseDialogProps, useDialog } from '@sd/ui';
|
||||
import { Input, useZodForm, z } from '@sd/ui/src/forms';
|
||||
import { showAlertDialog } from '~/components/AlertDialog';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
|
||||
const schema = z.object({ path: z.string(), indexer_rules_ids: z.array(z.number()) });
|
||||
|
||||
interface Props extends UseDialogProps {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export const AddLocationDialog = (props: Props) => {
|
||||
const dialog = useDialog(props);
|
||||
const platform = usePlatform();
|
||||
const createLocation = useLibraryMutation('locations.create');
|
||||
const indexerRulesList = useLibraryQuery(['locations.indexer_rules.list']);
|
||||
|
||||
const form = useZodForm({
|
||||
schema,
|
||||
defaultValues: {
|
||||
path: props.path,
|
||||
indexer_rules_ids: []
|
||||
}
|
||||
});
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
{...{ dialog, form }}
|
||||
title="New Location"
|
||||
description={
|
||||
platform.platform === 'web'
|
||||
? '"As you are using the browser version of Spacedrive you will (for now) need to specify an absolute URL of a directory local to the remote node."'
|
||||
: ''
|
||||
}
|
||||
onSubmit={form.handleSubmit(async ({ path, indexer_rules_ids }) => {
|
||||
try {
|
||||
if (platform.platform === 'tauri') createLocation.mutate({ path, indexer_rules_ids });
|
||||
else await createLocation.mutateAsync({ path, indexer_rules_ids });
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
showAlertDialog({
|
||||
title: 'Error',
|
||||
value: 'Failed to add location'
|
||||
});
|
||||
}
|
||||
})}
|
||||
ctaLabel="Add"
|
||||
>
|
||||
<div className="relative flex flex-col">
|
||||
<p className="mt-2 text-[0.9rem] font-bold">Path:</p>
|
||||
<Input
|
||||
type="text"
|
||||
onClick={async () => {
|
||||
if (!platform.openDirectoryPickerDialog) return;
|
||||
|
||||
const path = await platform.openDirectoryPickerDialog();
|
||||
if (!path) return;
|
||||
if (typeof path !== 'string') {
|
||||
// TODO: Should support for adding multiple locations simultaneously be added?
|
||||
showAlertDialog({
|
||||
title: 'Error',
|
||||
value: "Can't add multiple locations"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
form.setValue('path', path);
|
||||
}}
|
||||
readOnly={platform.platform !== 'web'}
|
||||
required
|
||||
className="mt-3 w-full grow cursor-pointer"
|
||||
{...form.register('path')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="relative flex flex-col">
|
||||
<p className="mt-6 text-[0.9rem] font-bold">File indexing rules:</p>
|
||||
<div className="mt-4 mb-3 grid w-full grid-cols-2 gap-4">
|
||||
<Controller
|
||||
name="indexer_rules_ids"
|
||||
control={form.control}
|
||||
render={({ field }) => (
|
||||
<>
|
||||
{indexerRulesList.data?.map((rule) => (
|
||||
<div className="flex" key={rule.id}>
|
||||
<CheckBox
|
||||
value={rule.id}
|
||||
onChange={(event: ChangeEvent) => {
|
||||
const ref = event.target as HTMLInputElement;
|
||||
if (ref.checked) {
|
||||
field.onChange([...field.value, Number.parseInt(ref.value)]);
|
||||
} else {
|
||||
field.onChange(
|
||||
field.value.filter((value) => value !== Number.parseInt(ref.value))
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<span className="mr-3 ml-0.5 mt-0.5 text-sm font-bold">{rule.name}</span>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
|
@ -1,15 +1,11 @@
|
|||
import { useLibraryMutation, useLibraryQuery } from '@sd/client';
|
||||
import { LocationCreateArgs } from '@sd/client';
|
||||
import { Button, SearchInput, dialogManager } from '@sd/ui';
|
||||
import { usePlatform } from '~/util/Platform';
|
||||
import { useLibraryQuery } from '@sd/client';
|
||||
import { SearchInput } from '@sd/ui';
|
||||
import { Heading } from '../../Layout';
|
||||
import AddDialog from './AddDialog';
|
||||
import { AddLocationButton } from './AddLocationButton';
|
||||
import ListItem from './ListItem';
|
||||
|
||||
export const Component = () => {
|
||||
const platform = usePlatform();
|
||||
const locations = useLibraryQuery(['locations.list']);
|
||||
const createLocation = useLibraryMutation('locations.create');
|
||||
|
||||
return (
|
||||
<>
|
||||
|
@ -19,31 +15,7 @@ export const Component = () => {
|
|||
rightArea={
|
||||
<div className="flex flex-row items-center space-x-5">
|
||||
<SearchInput placeholder="Search locations" />
|
||||
|
||||
<Button
|
||||
variant="accent"
|
||||
size="md"
|
||||
onClick={() => {
|
||||
if (platform.platform === 'web') {
|
||||
dialogManager.create((dp) => <AddDialog {...dp} />);
|
||||
} else {
|
||||
if (!platform.openDirectoryPickerDialog) {
|
||||
alert('Opening a dialogue is not supported on this platform!');
|
||||
return;
|
||||
}
|
||||
platform.openDirectoryPickerDialog().then((result) => {
|
||||
// TODO: Pass indexer rules ids to create location
|
||||
if (result)
|
||||
createLocation.mutate({
|
||||
path: result as string,
|
||||
indexer_rules_ids: []
|
||||
} as LocationCreateArgs);
|
||||
});
|
||||
}
|
||||
}}
|
||||
>
|
||||
Add Location
|
||||
</Button>
|
||||
<AddLocationButton variant="accent" size="md" />
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
|
|
@ -8589,7 +8589,7 @@ packages:
|
|||
/@types/keyv/3.1.4:
|
||||
resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
|
||||
dependencies:
|
||||
'@types/node': 18.11.18
|
||||
'@types/node': 18.15.1
|
||||
dev: true
|
||||
|
||||
/@types/loadable__component/5.13.4:
|
||||
|
@ -8730,7 +8730,7 @@ packages:
|
|||
/@types/responselike/1.0.0:
|
||||
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
|
||||
dependencies:
|
||||
'@types/node': 18.11.18
|
||||
'@types/node': 18.15.1
|
||||
dev: true
|
||||
|
||||
/@types/scheduler/0.16.2:
|
||||
|
@ -8984,7 +8984,7 @@ packages:
|
|||
'@babel/plugin-transform-react-jsx-source': 7.19.6_@babel+core@7.20.12
|
||||
magic-string: 0.26.7
|
||||
react-refresh: 0.14.0
|
||||
vite: 4.1.4_sass@1.57.1
|
||||
vite: 4.1.4_ovmyjmuuyckt3r3gpaexj2onji
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
|
@ -10526,7 +10526,7 @@ packages:
|
|||
dependencies:
|
||||
clone-response: 1.0.3
|
||||
get-stream: 5.2.0
|
||||
http-cache-semantics: 4.1.0
|
||||
http-cache-semantics: 4.1.1
|
||||
keyv: 3.1.0
|
||||
lowercase-keys: 2.0.0
|
||||
normalize-url: 4.5.1
|
||||
|
@ -14065,8 +14065,8 @@ packages:
|
|||
entities: 4.4.0
|
||||
dev: true
|
||||
|
||||
/http-cache-semantics/4.1.0:
|
||||
resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==}
|
||||
/http-cache-semantics/4.1.1:
|
||||
resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
|
||||
dev: true
|
||||
|
||||
/http-errors/2.0.0:
|
||||
|
@ -20658,6 +20658,7 @@ packages:
|
|||
|
||||
/trim/0.0.1:
|
||||
resolution: {integrity: sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==}
|
||||
deprecated: Use String.prototype.trim() instead
|
||||
dev: true
|
||||
|
||||
/trough/1.0.5:
|
||||
|
@ -21847,7 +21848,7 @@ packages:
|
|||
dependencies:
|
||||
'@rollup/pluginutils': 5.0.2
|
||||
'@svgr/core': 6.5.1
|
||||
vite: 4.1.4_sass@1.57.1
|
||||
vite: 4.1.4_ovmyjmuuyckt3r3gpaexj2onji
|
||||
transitivePeerDependencies:
|
||||
- rollup
|
||||
- supports-color
|
||||
|
|
Loading…
Reference in a new issue