disabled logic for event_queue
This commit is contained in:
parent
d0f146b99e
commit
fecac3428d
15 changed files with 119 additions and 37 deletions
6
apps/db/migrations/55_nulla_fatto_flag.up.sql
Normal file
6
apps/db/migrations/55_nulla_fatto_flag.up.sql
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
-- 55_nulla_fatto_flag.up.sql
|
||||||
|
ALTER TABLE IF EXISTS public.servizio
|
||||||
|
ADD COLUMN IF NOT EXISTS "isDisabled" boolean NOT NULL DEFAULT false;
|
||||||
|
|
||||||
|
ALTER TABLE IF EXISTS public.event_queue
|
||||||
|
ADD COLUMN IF NOT EXISTS "isActive" boolean NOT NULL DEFAULT true;
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
-- nulla_fatto_flag.up.sql
|
|
||||||
ALTER TABLE IF EXISTS public.servizio
|
|
||||||
ADD COLUMN IF NOT EXISTS "isDisabled" boolean NOT NULL DEFAULT false;
|
|
||||||
|
|
@ -5,8 +5,8 @@ import Base from "./base";
|
||||||
|
|
||||||
export const GenericMailTag = "generic";
|
export const GenericMailTag = "generic";
|
||||||
|
|
||||||
const props_base = z.object({
|
export const GenericPropsSchema = z.object({
|
||||||
title: z.string(),
|
title: z.string({error:"Il campo non può essere vuoto"}).nonempty("Il campo non può essere vuoto"),
|
||||||
noreply: z.boolean().optional(),
|
noreply: z.boolean().optional(),
|
||||||
link: z
|
link: z
|
||||||
.object({
|
.object({
|
||||||
|
|
@ -14,21 +14,10 @@ const props_base = z.object({
|
||||||
label: z.string().optional(),
|
label: z.string().optional(),
|
||||||
})
|
})
|
||||||
.optional(),
|
.optional(),
|
||||||
|
corpo: z.custom<ReactNode>().optional(),
|
||||||
|
testo: z.string({error:"Il campo non può essere vuoto"}).nonempty("Il campo non può essere vuoto"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const props_content = z.union([
|
|
||||||
z.object({
|
|
||||||
corpo: z.custom<ReactNode>(),
|
|
||||||
testo: z.undefined().optional(),
|
|
||||||
}),
|
|
||||||
z.object({
|
|
||||||
testo: z.string(),
|
|
||||||
corpo: z.undefined().optional(),
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
export const GenericPropsSchema = props_base.and(props_content);
|
|
||||||
|
|
||||||
const Generic = ({
|
const Generic = ({
|
||||||
title,
|
title,
|
||||||
noreply = false,
|
noreply = false,
|
||||||
|
|
@ -41,9 +30,7 @@ const Generic = ({
|
||||||
<>
|
<>
|
||||||
<Heading className="text-center text-3xl leading-8">{title}</Heading>
|
<Heading className="text-center text-3xl leading-8">{title}</Heading>
|
||||||
<Section className="px-5 text-left text-base md:px-12">
|
<Section className="px-5 text-left text-base md:px-12">
|
||||||
{corpo ? (
|
{corpo || (
|
||||||
corpo
|
|
||||||
) : (
|
|
||||||
<Row>
|
<Row>
|
||||||
<Text>{testo}</Text>
|
<Text>{testo}</Text>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,7 @@ export const AdminComunicazioni = () => {
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
|
{!email.isActive && <div className="text-sm">(Disattivata)</div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import ReactSelect, {
|
||||||
type MenuListProps,
|
type MenuListProps,
|
||||||
} from "react-select";
|
} from "react-select";
|
||||||
import type {} from "react-select/base";
|
import type {} from "react-select/base";
|
||||||
import { cn } from "~/lib/utils";
|
import { cn, passwordManagerIgnore } from "~/lib/utils";
|
||||||
|
|
||||||
declare module "react-select/base" {
|
declare module "react-select/base" {
|
||||||
export interface Props<
|
export interface Props<
|
||||||
|
|
@ -37,7 +37,7 @@ type BaseProps = {
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
menuPlacement?: "auto" | "bottom" | "top";
|
menuPlacement?: "auto" | "bottom" | "top";
|
||||||
defaultValue?: ListOption | ListOption[];
|
defaultValue?: ListOption | ListOption[];
|
||||||
autoComplete?: HTMLInputAutoCompleteAttribute;
|
//autoComplete?: HTMLInputAutoCompleteAttribute;
|
||||||
};
|
};
|
||||||
|
|
||||||
type MultiProps = {
|
type MultiProps = {
|
||||||
|
|
@ -119,8 +119,8 @@ const CustomInput = (
|
||||||
<components.Input
|
<components.Input
|
||||||
{...props}
|
{...props}
|
||||||
// This pulls the value from the main ReactSelect wrapper
|
// This pulls the value from the main ReactSelect wrapper
|
||||||
|
|
||||||
autoComplete={props.selectProps.autoComplete}
|
autoComplete={props.selectProps.autoComplete}
|
||||||
|
{...passwordManagerIgnore}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
@ -154,13 +154,13 @@ export const MultiSelect = ({
|
||||||
placeholder,
|
placeholder,
|
||||||
disabled,
|
disabled,
|
||||||
menuPlacement,
|
menuPlacement,
|
||||||
autoComplete,
|
//autoComplete,
|
||||||
}: MultiSelectProps) => {
|
}: MultiSelectProps) => {
|
||||||
const [menuOpen, setMenuOpen] = useState(false);
|
const [menuOpen, setMenuOpen] = useState(false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactSelect
|
<ReactSelect
|
||||||
autoComplete={autoComplete}
|
//autoComplete={autoComplete}
|
||||||
classNamePrefix="select"
|
classNamePrefix="select"
|
||||||
classNames={{
|
classNames={{
|
||||||
control: () =>
|
control: () =>
|
||||||
|
|
@ -197,6 +197,7 @@ export const MultiSelect = ({
|
||||||
MenuList: VirtualizedMenuList,
|
MenuList: VirtualizedMenuList,
|
||||||
Input: CustomInput,
|
Input: CustomInput,
|
||||||
}}
|
}}
|
||||||
|
data-bitwarden-ignore
|
||||||
defaultValue={defaultValue}
|
defaultValue={defaultValue}
|
||||||
inputId={elementId}
|
inputId={elementId}
|
||||||
instanceId={elementId}
|
instanceId={elementId}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import {
|
||||||
import { DateInput } from "~/components/custom_ui/inputDate";
|
import { DateInput } from "~/components/custom_ui/inputDate";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import Input from "~/components/ui/input";
|
import Input from "~/components/ui/input";
|
||||||
|
import { Switch } from "~/components/ui/switch";
|
||||||
import { Textarea } from "~/components/ui/textarea";
|
import { Textarea } from "~/components/ui/textarea";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import { useTranslation } from "~/providers/I18nProvider";
|
import { useTranslation } from "~/providers/I18nProvider";
|
||||||
|
|
@ -22,6 +23,7 @@ const Schema = z.object({
|
||||||
lock_date: z.date(),
|
lock_date: z.date(),
|
||||||
lock_time: z.string(),
|
lock_time: z.string(),
|
||||||
data: z.string(),
|
data: z.string(),
|
||||||
|
isActive: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
type FormValues = z.infer<typeof Schema>;
|
type FormValues = z.infer<typeof Schema>;
|
||||||
|
|
@ -43,6 +45,7 @@ export const FormEditQueueMail = ({
|
||||||
lock_date: new Date(data.lock_expires),
|
lock_date: new Date(data.lock_expires),
|
||||||
lock_time: format(new Date(data.lock_expires), "HH:mm:ss"),
|
lock_time: format(new Date(data.lock_expires), "HH:mm:ss"),
|
||||||
data: JSON.stringify(data.data, null, 2),
|
data: JSON.stringify(data.data, null, 2),
|
||||||
|
isActive: data.isActive,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -54,6 +57,7 @@ export const FormEditQueueMail = ({
|
||||||
"T" +
|
"T" +
|
||||||
fields.lock_time,
|
fields.lock_time,
|
||||||
),
|
),
|
||||||
|
isActive: fields.isActive,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,6 +123,26 @@ export const FormEditQueueMail = ({
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="isActive"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
<FormLabel htmlFor="attivo">Attivo</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Switch
|
||||||
|
className="data-[state=checked]:bg-neutral-700"
|
||||||
|
defaultChecked={field.value}
|
||||||
|
id="attivo"
|
||||||
|
onCheckedChange={field.onChange}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
<div className="flex w-full justify-end gap-2">
|
<div className="flex w-full justify-end gap-2">
|
||||||
<Button type="submit">Salva</Button>
|
<Button type="submit">Salva</Button>
|
||||||
<Confirm
|
<Confirm
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ import { DateInput } from "~/components/custom_ui/inputDate";
|
||||||
import { MultiSelect } from "~/components/custom_ui/multiselect";
|
import { MultiSelect } from "~/components/custom_ui/multiselect";
|
||||||
import { Button } from "~/components/ui/button";
|
import { Button } from "~/components/ui/button";
|
||||||
import Input from "~/components/ui/input";
|
import Input from "~/components/ui/input";
|
||||||
|
import { Switch } from "~/components/ui/switch";
|
||||||
import { useZodForm } from "~/lib/zodForm";
|
import { useZodForm } from "~/lib/zodForm";
|
||||||
import {
|
import {
|
||||||
type MailsTemplates,
|
type MailsTemplates,
|
||||||
|
|
@ -27,6 +28,7 @@ type FormProps = {
|
||||||
lock_expires: Date;
|
lock_expires: Date;
|
||||||
template: MailsTemplates;
|
template: MailsTemplates;
|
||||||
subject: string;
|
subject: string;
|
||||||
|
isActive: boolean;
|
||||||
}) => void;
|
}) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -45,7 +47,8 @@ const Schema = z
|
||||||
expires_time: z.string(),
|
expires_time: z.string(),
|
||||||
mailType: z.enum(TemplateKeys),
|
mailType: z.enum(TemplateKeys),
|
||||||
mailProps: z.record(z.string(), z.unknown()).optional(),
|
mailProps: z.record(z.string(), z.unknown()).optional(),
|
||||||
subject: z.string(),
|
subject: z.string().nonempty("Il campo non può essere vuoto"),
|
||||||
|
isActive: z.boolean(),
|
||||||
})
|
})
|
||||||
.superRefine((data, ctx) => {
|
.superRefine((data, ctx) => {
|
||||||
const propsSchema = Templates[data.mailType as TemplateType].props;
|
const propsSchema = Templates[data.mailType as TemplateType].props;
|
||||||
|
|
@ -55,7 +58,7 @@ const Schema = z
|
||||||
for (const issue of result.error.issues) {
|
for (const issue of result.error.issues) {
|
||||||
ctx.addIssue({
|
ctx.addIssue({
|
||||||
...issue,
|
...issue,
|
||||||
path: ["mailProps", ...(issue.path ?? [])],
|
path: ["mailProps", ...issue.path],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -71,6 +74,7 @@ export const FormAddCodaEmail = ({ submitMutation }: FormProps) => {
|
||||||
mailType: TemplateKeys[0],
|
mailType: TemplateKeys[0],
|
||||||
mailProps: undefined,
|
mailProps: undefined,
|
||||||
subject: "",
|
subject: "",
|
||||||
|
isActive: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -84,12 +88,14 @@ export const FormAddCodaEmail = ({ submitMutation }: FormProps) => {
|
||||||
lock_expires: Date;
|
lock_expires: Date;
|
||||||
template: MailsTemplates;
|
template: MailsTemplates;
|
||||||
subject: string;
|
subject: string;
|
||||||
|
isActive: boolean;
|
||||||
} = {
|
} = {
|
||||||
lock_expires: new Date(
|
lock_expires: new Date(
|
||||||
`${fields.expires_date.toISOString().split("T")[0]}T${fields.expires_time}`,
|
`${fields.expires_date.toISOString().split("T")[0]}T${fields.expires_time}`,
|
||||||
),
|
),
|
||||||
template,
|
template,
|
||||||
subject: fields.subject,
|
subject: fields.subject,
|
||||||
|
isActive: fields.isActive,
|
||||||
};
|
};
|
||||||
submitMutation(values);
|
submitMutation(values);
|
||||||
}
|
}
|
||||||
|
|
@ -103,10 +109,11 @@ export const FormAddCodaEmail = ({ submitMutation }: FormProps) => {
|
||||||
useWatch({
|
useWatch({
|
||||||
name: "mailProps",
|
name: "mailProps",
|
||||||
control: form.control,
|
control: form.control,
|
||||||
compute: (props) => {
|
compute: async (props) => {
|
||||||
if (!props) return;
|
if (!props) return;
|
||||||
if ("title" in props) {
|
if ("title" in props) {
|
||||||
form.setValue("subject", props.title as string);
|
form.setValue("subject", props.title as string);
|
||||||
|
await form.trigger("subject");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -216,6 +223,26 @@ export const FormAddCodaEmail = ({ submitMutation }: FormProps) => {
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="isActive"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
|
<FormLabel htmlFor="attivo">Attivo</FormLabel>
|
||||||
|
<FormControl>
|
||||||
|
<Switch
|
||||||
|
className="data-[state=checked]:bg-neutral-700"
|
||||||
|
defaultChecked={field.value}
|
||||||
|
id="attivo"
|
||||||
|
onCheckedChange={field.onChange}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
<Button type="submit">Salva</Button>
|
<Button type="submit">Salva</Button>
|
||||||
</form>
|
</form>
|
||||||
|
|
@ -332,12 +359,11 @@ const FieldRenderer = ({
|
||||||
return (
|
return (
|
||||||
<FormField
|
<FormField
|
||||||
control={control}
|
control={control}
|
||||||
// biome-ignore lint/suspicious/noExplicitAny: dynamic field name
|
name={name}
|
||||||
name={name as any}
|
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<div className="flex flex-wrap items-center gap-x-2">
|
<div className="flex flex-wrap items-center gap-x-2">
|
||||||
<FormLabel>
|
<FormLabel htmlFor={`${name}-input`}>
|
||||||
{label}
|
{label}
|
||||||
{optional && (
|
{optional && (
|
||||||
<span className="ml-1 text-muted-foreground text-xs">
|
<span className="ml-1 text-muted-foreground text-xs">
|
||||||
|
|
@ -352,11 +378,13 @@ const FieldRenderer = ({
|
||||||
<input
|
<input
|
||||||
checked={!!(field.value as boolean)}
|
checked={!!(field.value as boolean)}
|
||||||
className="h-4 w-4"
|
className="h-4 w-4"
|
||||||
|
id={`${name}-input`}
|
||||||
onChange={(e) => field.onChange(e.target.checked)}
|
onChange={(e) => field.onChange(e.target.checked)}
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Input
|
<Input
|
||||||
|
id={`${name}-input`}
|
||||||
onChange={
|
onChange={
|
||||||
fieldType === "number"
|
fieldType === "number"
|
||||||
? (e) => field.onChange(Number(e.target.value))
|
? (e) => field.onChange(Number(e.target.value))
|
||||||
|
|
|
||||||
|
|
@ -69,3 +69,11 @@ export const debounce = <T extends unknown[]>(
|
||||||
}, delay);
|
}, delay);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const passwordManagerIgnore = {
|
||||||
|
autocomplete: "off",
|
||||||
|
"data-1p-ignore": true, // 1Password
|
||||||
|
"data-lpignore": "true", // LastPass
|
||||||
|
"data-protonpass-ignore": "true", // ProtonPass
|
||||||
|
"data-bwignore": "1", // Bitwarden
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -279,6 +279,7 @@ const Coda = ({ userId }: { userId: UsersId }) => {
|
||||||
minute: "2-digit",
|
minute: "2-digit",
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
{!email.isActive && <div className="text-sm">(Disattivata)</div>}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ export default interface EventQueueTable {
|
||||||
lock_expires: ColumnType<Date, Date | string, Date | string>;
|
lock_expires: ColumnType<Date, Date | string, Date | string>;
|
||||||
|
|
||||||
data: ColumnType<unknown | null, unknown | null, unknown | null>;
|
data: ColumnType<unknown | null, unknown | null, unknown | null>;
|
||||||
|
|
||||||
|
isActive: ColumnType<boolean, boolean | undefined, boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type EventQueue = Selectable<EventQueueTable>;
|
export type EventQueue = Selectable<EventQueueTable>;
|
||||||
|
|
@ -25,16 +27,19 @@ export const EventQueueSchema = z.object({
|
||||||
event_id: eventQueueEventId,
|
event_id: eventQueueEventId,
|
||||||
lock_expires: z.date(),
|
lock_expires: z.date(),
|
||||||
data: z.unknown().nullable(),
|
data: z.unknown().nullable(),
|
||||||
|
isActive: z.boolean(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const NewEventQueueSchema = z.object({
|
export const NewEventQueueSchema = z.object({
|
||||||
event_id: eventQueueEventId.optional(),
|
event_id: eventQueueEventId.optional(),
|
||||||
lock_expires: z.union([z.date(), z.string()]).pipe(z.coerce.date()),
|
lock_expires: z.union([z.date(), z.string()]).pipe(z.coerce.date()),
|
||||||
data: z.unknown().optional().nullable(),
|
data: z.unknown().optional().nullable(),
|
||||||
|
isActive: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const EventQueueUpdateSchema = z.object({
|
export const EventQueueUpdateSchema = z.object({
|
||||||
event_id: eventQueueEventId.optional(),
|
event_id: eventQueueEventId.optional(),
|
||||||
lock_expires: z.union([z.date(), z.string()]).pipe(z.coerce.date()).optional(),
|
lock_expires: z.union([z.date(), z.string()]).pipe(z.coerce.date()).optional(),
|
||||||
data: z.unknown().optional().nullable(),
|
data: z.unknown().optional().nullable(),
|
||||||
|
isActive: z.boolean().optional(),
|
||||||
});
|
});
|
||||||
|
|
@ -236,6 +236,7 @@ export const comunicazioniRouter = createTRPCRouter({
|
||||||
userId: usersId,
|
userId: usersId,
|
||||||
template: z.custom<MailsTemplates>(),
|
template: z.custom<MailsTemplates>(),
|
||||||
subject: z.string(),
|
subject: z.string(),
|
||||||
|
isActive: z.boolean(),
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
|
|
@ -260,6 +261,7 @@ export const comunicazioniRouter = createTRPCRouter({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
lock_expires: input.lock_expires,
|
lock_expires: input.lock_expires,
|
||||||
|
isActive: input.isActive,
|
||||||
});
|
});
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -298,6 +300,7 @@ export const comunicazioniRouter = createTRPCRouter({
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.mutation(async ({ input }) => {
|
.mutation(async ({ input }) => {
|
||||||
|
console.log(input.data);
|
||||||
return await updateEvent(input.eventId, input.data);
|
return await updateEvent(input.eventId, input.data);
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -129,6 +129,7 @@ const getEventsFromQueue = async () => {
|
||||||
const events = await db
|
const events = await db
|
||||||
.selectFrom("event_queue")
|
.selectFrom("event_queue")
|
||||||
.selectAll()
|
.selectAll()
|
||||||
|
.where("event_queue.isActive", "=", true)
|
||||||
.where("event_queue.lock_expires", "<=", new Date())
|
.where("event_queue.lock_expires", "<=", new Date())
|
||||||
.execute();
|
.execute();
|
||||||
return events;
|
return events;
|
||||||
|
|
@ -213,6 +214,7 @@ export const getEmailQueue = async () => {
|
||||||
.as("username"),
|
.as("username"),
|
||||||
])
|
])
|
||||||
.where(sql`data->>'tipo'`, "=", "email")
|
.where(sql`data->>'tipo'`, "=", "email")
|
||||||
|
|
||||||
.execute();
|
.execute();
|
||||||
return events;
|
return events;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -286,6 +288,23 @@ export const clearUserEmailQueue = async (userId: UsersId) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const disableUserEmailQueue = async (userId: UsersId) => {
|
||||||
|
try {
|
||||||
|
await db
|
||||||
|
.updateTable("event_queue")
|
||||||
|
.set({ isActive: false })
|
||||||
|
.where(sql`data->>'tipo'`, "=", "email")
|
||||||
|
.where(sql`data->'data'->>'userId'`, "=", userId)
|
||||||
|
.execute();
|
||||||
|
} catch (e) {
|
||||||
|
throw new TRPCError({
|
||||||
|
code: "INTERNAL_SERVER_ERROR",
|
||||||
|
message: `Error while disabling user events from queue, ${(e as Error).message}`,
|
||||||
|
cause: e,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const updateEvent = async (
|
export const updateEvent = async (
|
||||||
eventId: EventQueueEventId,
|
eventId: EventQueueEventId,
|
||||||
data: EventQueueUpdate,
|
data: EventQueueUpdate,
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import type { UsersStorageUserStorageId } from "~/schemas/public/UsersStorage";
|
||||||
import {
|
import {
|
||||||
addEventToQueue,
|
addEventToQueue,
|
||||||
canSendNotification,
|
canSendNotification,
|
||||||
clearUserEmailQueue,
|
disableUserEmailQueue,
|
||||||
nextTimeForNotification,
|
nextTimeForNotification,
|
||||||
} from "~/server/controllers/event_queue.controller";
|
} from "~/server/controllers/event_queue.controller";
|
||||||
import {
|
import {
|
||||||
|
|
@ -927,8 +927,8 @@ export const interruzioneServizio = async (
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// cleanup coda notifiche: rimuove notifiche future relative a questo servizio
|
// disabilita coda notifiche: rimuove notifiche future relative a questo servizio
|
||||||
await clearUserEmailQueue(utente.id);
|
await disableUserEmailQueue(utente.id);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import type {
|
||||||
ServizioUpdate,
|
ServizioUpdate,
|
||||||
} from "~/schemas/public/Servizio";
|
} from "~/schemas/public/Servizio";
|
||||||
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
|
import type { ServizioAnnunciUpdate } from "~/schemas/public/ServizioAnnunci";
|
||||||
import { clearUserEmailQueue } from "~/server/controllers/event_queue.controller";
|
import { disableUserEmailQueue } from "~/server/controllers/event_queue.controller";
|
||||||
import { db } from "../db";
|
import { db } from "../db";
|
||||||
|
|
||||||
export const addServizio = async (data: NewServizio) => {
|
export const addServizio = async (data: NewServizio) => {
|
||||||
|
|
@ -97,7 +97,7 @@ export const updateServizio = async ({
|
||||||
);
|
);
|
||||||
if (!isDisabledPrev.isDisabled && updated.isDisabled) {
|
if (!isDisabledPrev.isDisabled && updated.isDisabled) {
|
||||||
// Only the on isDisabled false->true change
|
// Only the on isDisabled false->true change
|
||||||
await clearUserEmailQueue(updated.user_id);
|
await disableUserEmailQueue(updated.user_id);
|
||||||
}
|
}
|
||||||
return updated;
|
return updated;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@
|
||||||
"moduleResolution": "Bundler",
|
"moduleResolution": "Bundler",
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"noUncheckedIndexedAccess": true,
|
"noUncheckedIndexedAccess": true,
|
||||||
|
"allowUnreachableCode": false,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
"rootDir": ".",
|
"rootDir": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
"~/*": ["./src/*"],
|
"~/*": ["./src/*"],
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue