[ENG-650] - Blacklist/whitelist each rule (#872)

* Blacklist/whitelist each rule

* update tooltip wording

* tweaks

* get rid of 'magic string' value
This commit is contained in:
ameer2468
2023-05-27 00:13:04 +03:00
committed by GitHub
parent 1b4ec50519
commit 7dff20cbde
5 changed files with 56 additions and 54 deletions

View File

@@ -207,7 +207,7 @@ export const Component = () => {
field={field}
label="Indexer rules"
editable={true}
infoText="Indexer rules allow you to specify paths to ignore using RegEx."
infoText="Indexer rules allow you to specify paths to ignore using globs."
className="flex flex-col rounded-md border border-app-line bg-app-overlay p-5"
/>
)}

View File

@@ -51,13 +51,13 @@ function RuleButton<T extends IndexerRuleIdFieldType>({
})
}
className={clsx(
'hover:brightness-125',
ruleEnabled ? '!text-green-500' : 'text-red-500'
'px-2 hover:brightness-110',
ruleEnabled ? '!bg-accent !text-white' : 'text-ink'
)}
>
{ruleEnabled ? 'Enabled' : 'Disabled'}
</InfoPill>
{rule.default && <InfoPill className="text-ink-faint">System</InfoPill>}
{rule.default && <InfoPill className="px-2 text-ink-faint">System</InfoPill>}
</div>
</div>
</div>

View File

@@ -22,11 +22,11 @@ const ruleKindEnum = z.enum(ruleKinds);
const schema = z.object({
name: z.string().min(3),
kind: ruleKindEnum,
rules: z.array(
z.object({
type: z.string(),
value: z.string().min(1, { message: 'Value required' })
value: z.string().min(1, { message: 'Value required' }),
kind: ruleKindEnum
})
)
});
@@ -42,17 +42,21 @@ const RulesForm = ({ onSubmitted }: Props) => {
const REMOTE_ERROR_FORM_FIELD = 'root.serverError';
const createIndexerRules = useLibraryMutation(['locations.indexer_rules.create']);
const formId = useId();
const modeOptions: { value: RuleKind; label: string }[] = [
{ value: 'RejectFilesByGlob', label: 'Reject files by glob' },
{ value: 'AcceptFilesByGlob', label: 'Accept files by glob' }
];
const form = useZodForm({
schema,
mode: 'onBlur',
reValidateMode: 'onBlur',
defaultValues: {
name: '',
kind: 'RejectFilesByGlob',
rules: [
{
type: selectValues[0],
value: ''
value: '',
kind: modeOptions[0]?.value
}
]
}
@@ -91,15 +95,15 @@ const RulesForm = ({ onSubmitted }: Props) => {
const formatData = {
name: data.name,
dry_run: false,
rules: data.rules.map(({ type, value }) => {
rules: data.rules.map(({ type, value, kind }) => {
switch (type) {
case 'Name':
return [data.kind, [`**/${value}`]];
return [kind, [`**/${value}`]];
case 'Extension':
// .tar should work for .tar.gz, .tar.bz2, etc.
return [data.kind, [`**/*${value}`, `**/*${value}.*`]];
return [kind, [`**/*${value}`, `**/*${value}.*`]];
default:
return [data.kind, [value]];
return [kind, [value]];
}
})
} as IndexerRuleCreateArgs;
@@ -139,17 +143,23 @@ const RulesForm = ({ onSubmitted }: Props) => {
<h3 className="mb-[15px] mt-[20px] w-full text-sm font-semibold">Rules</h3>
<div
className={
'grid space-y-1 rounded-md border border-app-line/60 bg-app-input p-2 pb-0'
'grid space-y-1 rounded-md border border-app-line/60 bg-app-input p-2'
}
>
<div className="mb-4 grid grid-cols-3 px-3 pt-4 text-sm font-bold">
<h3 className="pl-2">Type</h3>
<h3 className="pl-2">Value</h3>
<div className="mb-2 grid w-full grid-cols-4 items-center pt-2 text-center text-[11px] font-bold">
<h3>Type</h3>
<h3>Value</h3>
<h3 className="flex items-center justify-center gap-1">
Mode
<Tooltip label="By default, an indexer rule functions as a Reject, resulting in the exclusion of any files that match its criteria. Enabling this option will transform it into a Allow, allowing the location to solely index files that meet its specified rules.">
<Info />
</Tooltip>
</h3>
</div>
{fields.map((field, index) => {
return (
<Card
className="grid w-full grid-cols-3 gap-3 border-app-line p-0 !px-2 hover:bg-app-box/70"
className="grid w-full grid-cols-4 gap-3 border-app-line p-0 !px-2 hover:bg-app-box/70"
key={field.id}
>
<Controller
@@ -158,7 +168,7 @@ const RulesForm = ({ onSubmitted }: Props) => {
render={({ field }) => (
<Select
{...field}
className="w-full"
className="!h-[30px] w-full"
onChange={(value) => {
field.onChange(value);
form.resetField(`rules.${index}.value`);
@@ -177,7 +187,7 @@ const RulesForm = ({ onSubmitted }: Props) => {
control={form.control}
render={({ field }) => {
return (
<div className="flex flex-col">
<div className="flex w-full flex-col">
<RuleInput
className={clsx(
'!h-[30px]',
@@ -211,11 +221,28 @@ const RulesForm = ({ onSubmitted }: Props) => {
);
}}
/>
<Controller
name={`rules.${index}.kind` as const}
render={({ field }) => (
<Select
{...field}
className="!h-[30px] w-full"
onChange={(value) => {
field.onChange(value);
}}
>
{modeOptions.map(({ label, value }) => (
<SelectOption key={value} value={value}>
{label}
</SelectOption>
))}
</Select>
)}
control={form.control}
/>
{index !== 0 && (
<Button
className="flex h-[32px] w-[32px] items-center
justify-self-end"
className="flex h-[32px] w-[32px] items-center justify-self-end"
variant="gray"
onClick={() => remove(index)}
>
@@ -230,7 +257,11 @@ const RulesForm = ({ onSubmitted }: Props) => {
<Button
onClick={() =>
append(
{ type: selectValues[0] as string, value: '' },
{
type: selectValues[0] as string,
value: '',
kind: 'RejectFilesByGlob'
},
{ shouldFocus: false }
)
}
@@ -242,35 +273,6 @@ const RulesForm = ({ onSubmitted }: Props) => {
</Button>
</div>
<Divider className="my-[25px]" />
<div className="flex w-full justify-center">
<div className="mb-5 flex items-center gap-2">
<p className="text-sm text-ink-faint">Blacklist</p>
<Controller
name="kind"
render={({ field }) => (
<Switch
onCheckedChange={(checked) => {
// TODO: These rule kinds are broken right now in the backend and this UI doesn't make much sense for them
// kind.AcceptIfChildrenDirectoriesArePresent
// kind.RejectIfChildrenDirectoriesArePresent
const kind = ruleKindEnum.enum;
field.onChange(
checked
? kind.AcceptFilesByGlob
: kind.RejectFilesByGlob
);
}}
size="md"
/>
)}
control={form.control}
/>
<p className="text-sm text-ink-faint">Whitelist</p>
<Tooltip label="By default, an indexer rule acts as a deny list, causing a location to ignore any file that match its rules. Enabling this will make it act as an allow list, and the location will only display files that match its rules.">
<Info />
</Tooltip>
</div>
</div>
<Button form={formId} type="submit" variant="accent" className="mx-auto w-[90px]">
Save
</Button>

View File

@@ -34,7 +34,7 @@ export default function IndexerRuleEditor<T extends IndexerRuleIdFieldType>({
const [toggleNewRule, setToggleNewRule] = useState(false);
const deleteIndexerRule = useLibraryMutation(['locations.indexer_rules.delete']);
const deleteRule: MouseEventHandler<HTMLButtonElement> = (e) => {
const deleteRule: MouseEventHandler<HTMLButtonElement> = () => {
if (!selectedRule) return;
showAlertDialog({
@@ -43,7 +43,6 @@ export default function IndexerRuleEditor<T extends IndexerRuleIdFieldType>({
label: 'Confirm',
onSubmit: async () => {
setIsDeleting(true);
try {
await deleteIndexerRule.mutateAsync(selectedRule.id);
} catch (error) {

View File

@@ -167,6 +167,7 @@ export function Dialog<S extends FieldValues>({
<Form
form={form}
onSubmit={async (e) => {
e?.preventDefault();
await onSubmit?.(e);
dialog.onSubmit?.();
setOpen(false);