Fix build errors

This commit is contained in:
Darren Clarke 2023-03-14 17:40:24 +00:00
parent 785d0965e3
commit d0f1c1337c
28 changed files with 268 additions and 112 deletions

View file

@ -25,7 +25,7 @@ LeafcutterDocument.getInitialProps = async (ctx) => {
ctx.renderPage = () => ctx.renderPage = () =>
originalRenderPage({ originalRenderPage({
enhanceApp: (App: any) => (props) => enhanceApp: (App: any) => (props: any) =>
<App emotionCache={cache} {...props} />, <App emotionCache={cache} {...props} />,
}); });

View file

@ -25,7 +25,7 @@ LinkDocument.getInitialProps = async (ctx) => {
ctx.renderPage = () => ctx.renderPage = () =>
originalRenderPage({ originalRenderPage({
enhanceApp: (App: any) => (props) => enhanceApp: (App: any) => (props: any) =>
<App emotionCache={cache} {...props} />, <App emotionCache={cache} {...props} />,
}); });

View file

@ -28,12 +28,16 @@ export const authProvider = {
if (e.networkError && e.networkError.statusCode === 401) { if (e.networkError && e.networkError.statusCode === 401) {
return Promise.reject(); return Promise.reject();
} }
return Promise.resolve();
}, },
checkAuth: async () => { checkAuth: async () => {
const session = await getSession(); const session = await getSession();
if (!session) { if (!session) {
return Promise.reject(); return Promise.reject();
} }
return Promise.resolve();
}, },
getIdentity: async () => { getIdentity: async () => {
const session = await getSession(); const session = await getSession();

View file

@ -1,9 +1,9 @@
import { FC, PropsWithChildren, useEffect } from "react"; import { FC, useEffect } from "react";
import { CircularProgress } from "@material-ui/core"; import { CircularProgress } from "@material-ui/core";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
export const Auth: FC<PropsWithChildren> = ({ children }) => { export const Auth: FC = ({ children }) => {
const router = useRouter(); const router = useRouter();
const { data: session, status: loading } = useSession(); const { data: session, status: loading } = useSession();
useEffect(() => { useEffect(() => {

View file

@ -25,7 +25,7 @@ type AccountEditToolbarProps = {
record?: any; record?: any;
}; };
const AccountEditToolbar: FC<AccountEditToolbarProps> = (props) => { const AccountEditToolbar: FC<AccountEditToolbarProps> = (props: any) => {
const { data: session } = useSession(); const { data: session } = useSession();
const classes = useStyles(props); const classes = useStyles(props);
return ( return (

View file

@ -14,9 +14,10 @@ type DeleteNotSelfButtonProps = {
record?: any; record?: any;
}; };
const DeleteNotSelfButton: FC<DeleteNotSelfButtonProps> = (props) => { const DeleteNotSelfButton: FC<DeleteNotSelfButtonProps> = (props: any) => {
const { data: session } = useSession(); const { data: session } = useSession();
return ( return (
// @ts-ignore
<DeleteButton <DeleteButton
disabled={session?.user?.email === props.record.userId} disabled={session?.user?.email === props.record.userId}
{...props} {...props}

View file

@ -105,7 +105,7 @@ const Sidebar = ({ record }: any) => {
variant="outlined" variant="outlined"
label="Message" label="Message"
multiline multiline
rows={3} minRows={3}
fullWidth fullWidth
size="small" size="small"
value={message} value={message}
@ -156,15 +156,15 @@ const handleRequestCode = async ({
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
}); });
if (response && response.ok) {
onSuccess();
} else {
onFailure(response.status || 400);
}
} catch (error: any) { } catch (error: any) {
console.error("Failed to request verification code:", error); console.error("Failed to request verification code:", error);
} }
if (response && response.ok) {
onSuccess();
} else {
onFailure(response.status || 400);
}
}; };
const VerificationCodeRequest = ({ const VerificationCodeRequest = ({
@ -222,7 +222,7 @@ const VerificationCaptcha = ({
setSubmitting(false); setSubmitting(false);
}; };
const handleCaptchaChange = (value) => { const handleCaptchaChange = (value: any) => {
if (value) if (value)
setCode( setCode(
value value
@ -268,16 +268,16 @@ const VerificationCodeInput = ({
handleClose, handleClose,
handleRestartVerification, handleRestartVerification,
confirmVerification, confirmVerification,
}) => { }: any) => {
const [code, setValue] = React.useState(""); const [code, setValue] = React.useState("");
const [isSubmitting, setSubmitting] = React.useState(false); const [isSubmitting, setSubmitting] = React.useState(false);
const [isValid, setValid] = React.useState(false); const [isValid, setValid] = React.useState(false);
const [submissionError, setSubmissionError] = React.useState(undefined); const [submissionError, setSubmissionError] = React.useState(undefined);
const translate = useTranslate(); const translate = useTranslate();
const validator = (v) => v.trim().length === 6; const validator = (v: any) => v.trim().length === 6;
const handleValueChange = (newValue) => { const handleValueChange = (newValue: any) => {
setValue(newValue); setValue(newValue);
setValid(validator(newValue)); setValid(validator(newValue));
}; };
@ -300,11 +300,14 @@ const VerificationCodeInput = ({
if (response.status === 200) { if (response.status === 200) {
confirmVerification(); confirmVerification();
} else if (responseBody.message) } else if (responseBody.message)
// @ts-expect-error
setSubmissionError(`Error: ${responseBody.message}`); setSubmissionError(`Error: ${responseBody.message}`);
else else {
setSubmissionError( setSubmissionError(
// @ts-expect-error
"There was an error, sorry about that. Please try again later or contact support." "There was an error, sorry about that. Please try again later or contact support."
); );
}
}; };
const title = const title =
@ -355,7 +358,7 @@ const VerificationCodeInput = ({
); );
}; };
const VerificationCodeDialog = (props) => { const VerificationCodeDialog = (props: any) => {
const [stage, setStage] = React.useState("request"); const [stage, setStage] = React.useState("request");
const onRequestSuccess = () => setStage("verify"); const onRequestSuccess = () => setStage("verify");
const onRestartVerification = () => setStage("request"); const onRestartVerification = () => setStage("request");
@ -406,7 +409,7 @@ const VerificationCodeDialog = (props) => {
); );
}; };
const SignalBotShowActions = ({ basePath, data }) => { const SignalBotShowActions = ({ basePath, data }: any) => {
const [open, setOpen] = React.useState(false); const [open, setOpen] = React.useState(false);
const [verifyMode, setVerifyMode] = React.useState(""); const [verifyMode, setVerifyMode] = React.useState("");
const refresh = useRefresh(); const refresh = useRefresh();
@ -429,7 +432,7 @@ const SignalBotShowActions = ({ basePath, data }) => {
return ( return (
<TopToolbar> <TopToolbar>
<EditButton basePath={basePath} record={data} /> <EditButton record={data} />
{data && !data.isVerified && ( {data && !data.isVerified && (
<Button onClick={handleOpenSMS} color="primary"> <Button onClick={handleOpenSMS} color="primary">
Verify with SMS Verify with SMS
@ -455,11 +458,9 @@ const SignalBotShowActions = ({ basePath, data }) => {
const SignalBotShow = (props: ShowProps) => ( const SignalBotShow = (props: ShowProps) => (
<Show <Show
// @ts-expect-error: Missing props
actions={<SignalBotShowActions />} actions={<SignalBotShowActions />}
{...props} {...props}
title="Signal Bot" title="Signal Bot"
// @ts-expect-error: Missing props
aside={<Sidebar />} aside={<Sidebar />}
> >
<SimpleShowLayout> <SimpleShowLayout>

View file

@ -9,7 +9,7 @@ import {
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { UserRoleInput } from "./shared"; import { UserRoleInput } from "./shared";
const UserCreate: FC<CreateProps> = (props) => { const UserCreate: FC<CreateProps> = (props: any) => {
const { data: session } = useSession(); const { data: session } = useSession();
return ( return (
<Create {...props} title="Create Users"> <Create {...props} title="Create Users">
@ -18,7 +18,7 @@ const UserCreate: FC<CreateProps> = (props) => {
<TextInput source="name" /> <TextInput source="name" />
<UserRoleInput session={session} initialValue="NONE" /> <UserRoleInput session={session} initialValue="NONE" />
<BooleanInput source="isActive" defaultValue={true} /> <BooleanInput source="isActive" defaultValue={true} />
<TextInput source="createdBy" defaultValue={session.user.name} /> <TextInput source="createdBy" defaultValue={session?.user?.name} />
</SimpleForm> </SimpleForm>
</Create> </Create>
); );

View file

@ -22,7 +22,7 @@ const useStyles = makeStyles((_theme) => ({
}, },
})); }));
const UserEditToolbar = (props) => { const UserEditToolbar = (props: any) => {
const classes = useStyles(props); const classes = useStyles(props);
const redirect = useRedirect(); const redirect = useRedirect();

View file

@ -1,6 +1,6 @@
import { SelectInput } from "react-admin"; import { SelectInput } from "react-admin";
export const UserRoleInput = (props) => ( export const UserRoleInput = (props: any) => (
<SelectInput <SelectInput
source="userRole" source="userRole"
choices={[ choices={[

View file

@ -1,6 +1,6 @@
import { SelectInput } from "react-admin"; import { SelectInput } from "react-admin";
export const ProviderKindInput = (props) => ( export const ProviderKindInput = (props: any) => (
<SelectInput <SelectInput
source="kind" source="kind"
choices={[{ id: "TWILIO", name: "Twilio" }]} choices={[{ id: "TWILIO", name: "Twilio" }]}

View file

@ -10,13 +10,17 @@ import { useStopwatch } from "react-timer-hook";
import style from "./MicInput.module.css"; import style from "./MicInput.module.css";
//import type { ReactMicProps } from "react-mic"; //import type { ReactMicProps } from "react-mic";
const ReactMic = dynamic<ReactMicProps>( const ReactMic = dynamic<any>(
// eslint-disable-next-line promise/prefer-await-to-then // eslint-disable-next-line promise/prefer-await-to-then
() => { throw new Error("MIC INPUT FEATURE IS DISABLED"); /*return import("react-mic").then((mod) => mod.ReactMic);*/ } , () => {
throw new Error(
"MIC INPUT FEATURE IS DISABLED"
); /*return import("react-mic").then((mod) => mod.ReactMic);*/
},
{ ssr: false } { ssr: false }
); );
const blobToDataUri = (blob) => { const blobToDataUri = (blob: Blob) => {
const reader = new FileReader(); const reader = new FileReader();
reader.readAsDataURL(blob); reader.readAsDataURL(blob);
return new Promise((resolve) => { return new Promise((resolve) => {
@ -26,32 +30,32 @@ const blobToDataUri = (blob) => {
}); });
}; };
const dataUriToObj = (dataUri) => { const dataUriToObj = (dataUri: string) => {
const [prefix, base64] = dataUri.split(","); const [prefix, base64] = dataUri.split(",");
const mime = prefix.slice(5, prefix.indexOf(";")); const mime = prefix.slice(5, prefix.indexOf(";"));
const result = {}; const result: any = {};
result[mime] = base64; result[mime] = base64;
return result; return result;
}; };
const blobToResult = async (blob) => { const blobToResult = async (blob: Blob) => {
const result = dataUriToObj(await blobToDataUri(blob)); const result = dataUriToObj((await blobToDataUri(blob)) as string);
return result; return result;
}; };
const resultToDataUri = (result): string => { const resultToDataUri = (result: Record<string, any>): string => {
if (!result || !result["audio/webm"]) return ""; if (!result || !result["audio/webm"]) return "";
const base64 = result["audio/webm"]; const base64 = result["audio/webm"];
const r = `data:audio/webm;base64,${base64}`; const r = `data:audio/webm;base64,${base64}`;
return r; return r;
}; };
const MicInput = (props) => { const MicInput = (props: any) => {
const { seconds, minutes, hours, start, reset, pause } = useStopwatch(); const { seconds, minutes, hours, start, reset, pause } = useStopwatch();
const theme = useTheme(); const theme = useTheme();
const { const {
input: { value, onChange }, field: { value, onChange },
} = useInput(props); } = useInput(props);
let [record, setRecorder] = useState({ record: false }); let [record, setRecorder] = useState({ record: false });
@ -67,18 +71,16 @@ const MicInput = (props) => {
pause(); pause();
}; };
async function onData(recordedBlob) {} async function onData(recordedBlob: any) {}
async function onStop(recordedBlob) { async function onStop(recordedBlob: any) {
const result = await blobToResult(recordedBlob.blob); const result = await blobToResult(recordedBlob.blob);
onChange(result); onChange(result);
} }
const isRecording = record.record; const isRecording = record.record;
const canPlay = !isRecording && decodedValue; const canPlay = !isRecording && decodedValue;
const duration = `${hours const duration = `${hours.toString().padStart(2, "0")}:${minutes
.toString()
.padStart(2, "0")}:${minutes
.toString() .toString()
.padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`; .padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;

View file

@ -16,7 +16,7 @@ const VoiceLineList = (props: ListProps) => (
source="providerId" source="providerId"
reference="providers" reference="providers"
> >
<FunctionField render={(p) => `${p.kind}: ${p.name}`} /> <FunctionField render={(p: any) => `${p.kind}: ${p.name}`} />
</ReferenceField> </ReferenceField>
<TextField source="number" /> <TextField source="number" />
<TextField source="language" /> <TextField source="language" />

View file

@ -16,7 +16,7 @@ import TwilioLanguages from "./twilio-languages";
type TTSProvider = (voice: any, language: any, prompt: any) => Promise<void>; type TTSProvider = (voice: any, language: any, prompt: any) => Promise<void>;
const tts = async (providerId): Promise<TTSProvider> => { const tts = async (providerId: any): Promise<TTSProvider> => {
const r = await fetch( const r = await fetch(
`/api/v1/voice/twilio/text-to-speech-token/${providerId}` `/api/v1/voice/twilio/text-to-speech-token/${providerId}`
); );
@ -39,7 +39,7 @@ const tts = async (providerId): Promise<TTSProvider> => {
outgoing: silence, outgoing: silence,
}, },
}); });
device.on("ready", function (device) { device.on("ready", function (device: any) {
device.connect({ language, voice, prompt }); device.connect({ language, voice, prompt });
}); });
device.on("disconnect", () => resolve()); device.on("disconnect", () => resolve());
@ -47,7 +47,7 @@ const tts = async (providerId): Promise<TTSProvider> => {
}); });
}; };
export const TextToSpeechButton = ({ form }) => { export const TextToSpeechButton = ({ form }: any) => {
const { providerId, language, voice, promptText: prompt } = form.formData; const { providerId, language, voice, promptText: prompt } = form.formData;
const [loading, setLoading] = useState<boolean>(false); const [loading, setLoading] = useState<boolean>(false);
const [ttsProvider, setTTSProvider] = useState< const [ttsProvider, setTTSProvider] = useState<
@ -90,7 +90,7 @@ export const TextToSpeechButton = ({ form }) => {
); );
}; };
export const PromptInput = (form, ...rest) => { export const PromptInput = (form: any, ...rest: any[]) => {
return ( return (
<TextInput <TextInput
source="promptText" source="promptText"
@ -102,19 +102,23 @@ export const PromptInput = (form, ...rest) => {
); );
}; };
const validateVoice = (args, values) => { const validateVoice = (args: any, values: any) => {
if (!values.language) return "validation.language"; if (!values.language) return "validation.language";
if (!values.voice) return "validation.voice"; if (!values.voice) return "validation.voice";
// @ts-expect-error
const availableVoices = TwilioLanguages.voices[values.language]; const availableVoices = TwilioLanguages.voices[values.language];
const found = const found =
availableVoices.filter((v) => v.id === values.voice).length === 1; availableVoices.filter((v: any) => v.id === values.voice).length === 1;
if (!found) return "validation.voice"; if (!found) return "validation.voice";
return undefined;
}; };
export const VoiceInput = (form, ...rest) => { export const VoiceInput = (form: any, ...rest: any[]) => {
// @ts-expect-error
const voice = TwilioLanguages.voices[form.formData.language] || []; const voice = TwilioLanguages.voices[form.formData.language] || [];
return ( return (
// @ts-expect-error
<SelectInput <SelectInput
source="voice" source="voice"
choices={voice} choices={voice}
@ -125,9 +129,9 @@ export const VoiceInput = (form, ...rest) => {
}; };
let noAvailableNumbers = false; let noAvailableNumbers = false;
let availableNumbers = []; let availableNumbers: any[] = [];
const getAvailableNumbers = async (providerId) => { const getAvailableNumbers = async (providerId: string) => {
try { try {
const r = await fetch(`/api/v1/voice/providers/${providerId}/freeNumbers`); const r = await fetch(`/api/v1/voice/providers/${providerId}/freeNumbers`);
availableNumbers = await r.json(); availableNumbers = await r.json();
@ -141,24 +145,32 @@ const getAvailableNumbers = async (providerId) => {
} }
}; };
const sidToNumber = (sid) => { const sidToNumber = (sid: any) => {
return availableNumbers return availableNumbers
.filter(({ id }) => id === sid) .filter(({ id }) => id === sid)
.map(({ name }) => name)[0]; .map(({ name }) => name)[0];
}; };
export const populateNumber = (data) => { export const populateNumber = (data: any) => {
return { return {
...data, ...data,
number: sidToNumber(data.providerLineSid), number: sidToNumber(data.providerLineSid),
}; };
}; };
const hasNumbers = (args, value, values, translate, ...props) => { const hasNumbers = (
args: any,
value: any,
values: any,
translate: any,
...props: any[]
) => {
if (noAvailableNumbers) return "validation.noAvailableNumbers"; if (noAvailableNumbers) return "validation.noAvailableNumbers";
return undefined;
}; };
export const AvailableNumbersInput = (form, ...rest) => { export const AvailableNumbersInput = (form: any, ...rest: any[]) => {
const { const {
// @ts-expect-error: non-existent property // @ts-expect-error: non-existent property
meta: { touched, error } = {}, meta: { touched, error } = {},
@ -181,7 +193,8 @@ export const AvailableNumbersInput = (form, ...rest) => {
? translate("validation.noAvailableNumbers") ? translate("validation.noAvailableNumbers")
: "", : "",
}); });
if (noAvailableNumbers) notify("validation.noAvailableNumbers", "error"); if (noAvailableNumbers)
notify("validation.noAvailableNumbers", { type: "error" });
setLoading(false); setLoading(false);
} }
}, [form && form.formData ? form.formData.providerId : undefined]); }, [form && form.formData ? form.formData.providerId : undefined]);
@ -278,19 +291,21 @@ export const AsyncSelectInput = (choiceLoader: () => Promise<any[]>, label, sour
export const VoiceLineSelectInput = AsyncSelectInput(getVoiceLineChoices, "Voice Line", "backendId", "validation.noVoiceLines" ) export const VoiceLineSelectInput = AsyncSelectInput(getVoiceLineChoices, "Voice Line", "backendId", "validation.noVoiceLines" )
*/ */
export const VoiceLineSelectInput = (source: string) => () => ( export const VoiceLineSelectInput = (source: string) => () =>
<ReferenceInput (
label="Voice Line" <ReferenceInput
source={source} label="Voice Line"
reference="voiceLines" source={source}
validate={[required()]} reference="voiceLines"
> validate={[required()]}
<SelectInput optionText="number" /> >
</ReferenceInput> <SelectInput optionText="number" />
); </ReferenceInput>
);
export const VoiceLineField = (source: string) => () => ( export const VoiceLineField = (source: string) => () =>
<ReferenceField label="Voice Line" source={source} reference="voiceLines"> (
<TextField source="number" /> <ReferenceField label="Voice Line" source={source} reference="voiceLines">
</ReferenceField> <TextField source="number" />
); </ReferenceField>
);

View file

@ -11,7 +11,7 @@ import {
} from "react-admin"; } from "react-admin";
import { BackendTypeInput, BackendIdInput, HttpMethodInput } from "./shared"; import { BackendTypeInput, BackendIdInput, HttpMethodInput } from "./shared";
const WebhookTitle = ({ record }) => { const WebhookTitle = ({ record }: any) => {
let title = ""; let title = "";
if (record) title = record.name ? record.name : record.email; if (record) title = record.name ? record.name : record.email;
return <span>Webhook {title}</span>; return <span>Webhook {title}</span>;
@ -19,7 +19,6 @@ const WebhookTitle = ({ record }) => {
const WebhookEdit = (props: EditProps) => { const WebhookEdit = (props: EditProps) => {
return ( return (
// @ts-expect-error: Missing props
<Edit title={<WebhookTitle />} {...props}> <Edit title={<WebhookTitle />} {...props}>
<SimpleForm> <SimpleForm>
<TextInput source="name" validate={[required()]} /> <TextInput source="name" validate={[required()]} />

View file

@ -14,7 +14,7 @@ const httpChoices = [
{ id: "post", name: "POST" }, { id: "post", name: "POST" },
{ id: "put", name: "PUT" }, { id: "put", name: "PUT" },
]; ];
export const HttpMethodInput = (props) => ( export const HttpMethodInput = (props: any) => (
<SelectInput <SelectInput
source="httpMethod" source="httpMethod"
choices={httpChoices} choices={httpChoices}
@ -42,7 +42,7 @@ const backendFieldComponents = {
voice: VoiceLineField("backendId"), voice: VoiceLineField("backendId"),
}; };
export const BackendTypeInput = (props) => ( export const BackendTypeInput = (props: any) => (
<SelectInput <SelectInput
source="backendType" source="backendType"
choices={backendChoices} choices={backendChoices}
@ -51,18 +51,20 @@ export const BackendTypeInput = (props) => (
/> />
); );
export const BackendIdInput = (form, ...rest) => { export const BackendIdInput = (form: any, ...rest: any[]) => {
const Component = form.formData.backendType const Component = form.formData.backendType
? backendInputComponents[form.formData.backendType] ? // @ts-expect-error
backendInputComponents[form.formData.backendType]
: false; : false;
return <>{Component && <Component form={form} {...rest} />}</>; return <>{Component && <Component form={form} {...rest} />}</>;
}; };
export const BackendIdField = (form, ...rest) => { export const BackendIdField = (form: any, ...rest: any[]) => {
console.log(form); console.log(form);
const Component = form.record.backendType const Component = form.record.backendType
? backendFieldComponents[form.record.backendType] ? // @ts-expect-error
backendFieldComponents[form.record.backendType]
: false; : false;
return <>{Component && <Component form={form} {...rest} />}</>; return <>{Component && <Component form={form} {...rest} />}</>;
}; };

View file

@ -1,6 +1,6 @@
import { List, Datagrid, TextField } from "react-admin"; import { List, Datagrid, TextField } from "react-admin";
const WhatsappAttachmentList = (props) => ( const WhatsappAttachmentList = (props: any) => (
<List {...props} exporter={false}> <List {...props} exporter={false}>
<Datagrid rowClick="show"> <Datagrid rowClick="show">
<TextField source="id" /> <TextField source="id" />

View file

@ -3,7 +3,7 @@ import { SimpleForm, Create, TextInput, required } from "react-admin";
import { useSession } from "next-auth/react"; import { useSession } from "next-auth/react";
import { validateE164Number } from "../../../lib/phone-numbers"; import { validateE164Number } from "../../../lib/phone-numbers";
const WhatsappBotCreate = (props) => { const WhatsappBotCreate = (props: any) => {
// const MuiPhoneNumber = dynamic(() => import("material-ui-phone-number"), { // const MuiPhoneNumber = dynamic(() => import("material-ui-phone-number"), {
// ssr: false, // ssr: false,
// }); // });

View file

@ -6,7 +6,7 @@ import {
BooleanField, BooleanField,
} from "react-admin"; } from "react-admin";
const WhatsappBotList = (props) => ( const WhatsappBotList = (props: any) => (
<List {...props} exporter={false}> <List {...props} exporter={false}>
<Datagrid rowClick="show"> <Datagrid rowClick="show">
<TextField source="phoneNumber" /> <TextField source="phoneNumber" />

View file

@ -12,8 +12,7 @@ import {
SimpleShowLayout, SimpleShowLayout,
TextField, TextField,
ShowProps, ShowProps,
useQuery, useGetOne,
useMutation,
useRefresh, useRefresh,
BooleanField, BooleanField,
} from "react-admin"; } from "react-admin";
@ -21,7 +20,7 @@ import QRCode from "react-qr-code";
import useSWR from "swr"; import useSWR from "swr";
import RefreshIcon from "@material-ui/icons/Refresh"; import RefreshIcon from "@material-ui/icons/Refresh";
const Sidebar = ({ record }) => { const Sidebar = ({ record }: any) => {
const [receivedMessages, setReceivedMessages] = useState([]); const [receivedMessages, setReceivedMessages] = useState([]);
const [phoneNumber, setPhoneNumber] = useState(""); const [phoneNumber, setPhoneNumber] = useState("");
const handlePhoneNumberChange = (event: any) => { const handlePhoneNumberChange = (event: any) => {
@ -101,7 +100,7 @@ const Sidebar = ({ record }) => {
</IconButton> </IconButton>
</Grid> </Grid>
</Grid> </Grid>
{receivedMessages.map((receivedMessage, index) => ( {receivedMessages.map((receivedMessage: any, index: number) => (
<Grid key={index} item container direction="column" spacing={1}> <Grid key={index} item container direction="column" spacing={1}>
<Grid item style={{ fontWeight: "bold", color: "#999" }}> <Grid item style={{ fontWeight: "bold", color: "#999" }}>
{receivedMessage.key.remoteJid.replace("@s.whatsapp.net", "")} {receivedMessage.key.remoteJid.replace("@s.whatsapp.net", "")}
@ -118,11 +117,7 @@ const Sidebar = ({ record }) => {
const WhatsappBotShow = (props: ShowProps) => { const WhatsappBotShow = (props: ShowProps) => {
const refresh = useRefresh(); const refresh = useRefresh();
const { data } = useQuery({ const { data } = useGetOne("whatsappBots", props.id as any);
type: "getOne",
resource: "whatsappBots",
payload: { id: props.id },
});
const { data: registerData, error: registerError } = useSWR( const { data: registerData, error: registerError } = useSWR(
data && !data?.isVerified data && !data?.isVerified
@ -150,10 +145,10 @@ const WhatsappBotShow = (props: ShowProps) => {
}, 10000); }, 10000);
return () => clearInterval(interval); return () => clearInterval(interval);
} }
return undefined;
}, [refresh, data]); }, [refresh, data]);
return ( return (
// @ts-expect-error: Missing props
<Show {...props} title="Bot" aside={<Sidebar />}> <Show {...props} title="Bot" aside={<Sidebar />}>
<SimpleShowLayout> <SimpleShowLayout>
<TextField source="phoneNumber" /> <TextField source="phoneNumber" />

View file

@ -29,8 +29,8 @@ export const cfVerifier = (audience: string, domain: string): VerifyFn => {
}); });
return async (token) => { return async (token) => {
const getKey = (header, callback) => { const getKey = (header: any, callback: any) => {
client.getSigningKey(header.kid, function (err, key) { client.getSigningKey(header.kid, function (err: any, key: any) {
if (err) if (err)
throw Boom.serverUnavailable( throw Boom.serverUnavailable(
"failed to fetch cloudflare access jwks" "failed to fetch cloudflare access jwks"
@ -201,6 +201,7 @@ export const CloudflareAccessProvider = (
req: IncomingMessage req: IncomingMessage
) => { ) => {
const verifier = cfVerifier(audience, domain); const verifier = cfVerifier(audience, domain);
// @ts-expect-error
return Providers.Credentials({ return Providers.Credentials({
id: cloudflareAccountProvider, id: cloudflareAccountProvider,
name: "Cloudflare Access", name: "Cloudflare Access",

View file

@ -1,7 +1,7 @@
import pgDataProvider from "ra-postgraphile"; import pgDataProvider from "ra-postgraphile";
import schema from "./graphql-schema.json"; import schema from "./graphql-schema.json";
export const metamigoDataProvider = async (client) => { export const metamigoDataProvider = async (client: any) => {
const graphqlDataProvider = await pgDataProvider( const graphqlDataProvider = await pgDataProvider(
client, client,
// @ts-expect-error: Missing property // @ts-expect-error: Missing property
@ -9,7 +9,7 @@ export const metamigoDataProvider = async (client) => {
{ introspection: { schema: schema.data.__schema } } { introspection: { schema: schema.data.__schema } }
); );
const dataProvider = async (type, resource, params) => { const dataProvider = async (type: any, resource: any, params: any) => {
return graphqlDataProvider(type, resource, params); return graphqlDataProvider(type, resource, params);
}; };

View file

@ -3,8 +3,8 @@
"version": "0.2.0", "version": "0.2.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@digiresilience/metamigo-config": "*",
"@apollo/client": "^3.7.4", "@apollo/client": "^3.7.4",
"@digiresilience/metamigo-config": "*",
"@hapi/boom": "^10.0.0", "@hapi/boom": "^10.0.0",
"@hapi/wreck": "^18.0.0", "@hapi/wreck": "^18.0.0",
"@mui/icons-material": "^5", "@mui/icons-material": "^5",
@ -27,8 +27,10 @@
"react-digit-input": "^2.1.0", "react-digit-input": "^2.1.0",
"react-dom": "^17", "react-dom": "^17",
"react-qr-code": "^2.0.11", "react-qr-code": "^2.0.11",
"react-redux": "^8.0.5",
"react-timer-hook": "^3.0.5", "react-timer-hook": "^3.0.5",
"swr": "^2.0.0" "swr": "^2.0.0",
"twilio-client": "^1.15.0"
}, },
"scripts": { "scripts": {
"serve": "next dev -p 2999", "serve": "next dev -p 2999",
@ -44,10 +46,10 @@
"@types/hapi__wreck": "17.0.1", "@types/hapi__wreck": "17.0.1",
"@types/react": "^17", "@types/react": "^17",
"@types/react-mic": "12.4.3", "@types/react-mic": "12.4.3",
"typescript": "^4.9.5", "babel-preset-link": "*",
"tsconfig-link": "*",
"eslint-config-link": "*", "eslint-config-link": "*",
"jest-config-link": "*", "jest-config-link": "*",
"babel-preset-link": "*" "tsconfig-link": "*",
"typescript": "^4.9.5"
} }
} }

View file

@ -3,7 +3,7 @@ import { Typography, Box, Button, Grid, Link } from "@material-ui/core";
import { FC, PropsWithChildren, useEffect } from "react"; import { FC, PropsWithChildren, useEffect } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
export const RedirectToAdmin: FC<PropsWithChildren> = ({ children }) => { export const RedirectToAdmin: FC = ({ children }) => {
const router = useRouter(); const router = useRouter();
useEffect(() => { useEffect(() => {
router.push("/admin"); router.push("/admin");
@ -15,7 +15,7 @@ export const RedirectToAdmin: FC<PropsWithChildren> = ({ children }) => {
const Home: NextPage = () => ( const Home: NextPage = () => (
<Box> <Box>
<Typography variant="h3">Metamigo</Typography> <Typography variant="h3">Metamigo</Typography>
<Grid container justify="space-around" style={{ padding: 60 }}> <Grid container justifyContent="space-around" style={{ padding: 60 }}>
<Grid item> <Grid item>
<Link href="/admin"> <Link href="/admin">
<Button variant="contained">Admin</Button> <Button variant="contained">Admin</Button>

View file

@ -1,6 +1,6 @@
/* eslint-disable camelcase */ /* eslint-disable camelcase */
import logger from "../logger"; import logger from "../logger";
import { IncomingMessagev1 } from "@digiresilience/node-signald/dist/generated"; import { IncomingMessagev1 } from "@digiresilience/node-signald/build/main/generated";
import { withDb, AppDatabase } from "../db"; import { withDb, AppDatabase } from "../db";
import workerUtils from "../utils"; import workerUtils from "../utils";

View file

@ -5,5 +5,5 @@
"esModuleInterop": true "esModuleInterop": true
}, },
"include": ["**/*.ts", "**/.*.ts"], "include": ["**/*.ts", "**/.*.ts"],
"exclude": ["node_modules"] "exclude": ["node_modules", "build"]
} }

View file

@ -1,6 +1,6 @@
FROM zammad/zammad-docker-compose:5.3.1-53 AS builder FROM zammad/zammad-docker-compose:5.4.0 AS builder
COPY auto_install ${ZAMMAD_TMP_DIR}/auto_install COPY auto_install ${ZAMMAD_TMP_DIR}/auto_install
RUN sed -i "s/# create install ready file/bundle exec rake zammad:package:migrate/g" contrib/docker/docker-entrypoint.sh # RUN sed -i "s/# create install ready file/bundle exec rake zammad:package:migrate/g" contrib/docker/docker-entrypoint.sh
FROM zammad/zammad-docker-compose:5.3.1-53 FROM zammad/zammad-docker-compose:5.4.0
COPY --from=builder ${ZAMMAD_TMP_DIR} ${ZAMMAD_TMP_DIR} COPY --from=builder ${ZAMMAD_TMP_DIR} ${ZAMMAD_TMP_DIR}

136
package-lock.json generated
View file

@ -637,8 +637,10 @@
"react-digit-input": "^2.1.0", "react-digit-input": "^2.1.0",
"react-dom": "^17", "react-dom": "^17",
"react-qr-code": "^2.0.11", "react-qr-code": "^2.0.11",
"react-redux": "^8.0.5",
"react-timer-hook": "^3.0.5", "react-timer-hook": "^3.0.5",
"swr": "^2.0.0" "swr": "^2.0.0",
"twilio-client": "^1.15.0"
}, },
"devDependencies": { "devDependencies": {
"@next/eslint-plugin-next": "^13.1.2", "@next/eslint-plugin-next": "^13.1.2",
@ -6441,6 +6443,11 @@
"version": "2.0.6", "version": "2.0.6",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"node_modules/@types/uuid": { "node_modules/@types/uuid": {
"version": "9.0.1", "version": "9.0.1",
"dev": true, "dev": true,
@ -18394,6 +18401,44 @@
} }
} }
}, },
"node_modules/react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"dependencies": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
},
"peerDependencies": {
"@types/react": "^16.8 || ^17.0 || ^18.0",
"@types/react-dom": "^16.8 || ^17.0 || ^18.0",
"react": "^16.8 || ^17.0 || ^18.0",
"react-dom": "^16.8 || ^17.0 || ^18.0",
"react-native": ">=0.59",
"redux": "^4"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
},
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
},
"redux": {
"optional": true
}
}
},
"node_modules/react-router": { "node_modules/react-router": {
"version": "6.8.2", "version": "6.8.2",
"license": "MIT", "license": "MIT",
@ -20235,6 +20280,48 @@
"node": ">=6.0" "node": ">=6.0"
} }
}, },
"node_modules/twilio-client": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/twilio-client/-/twilio-client-1.15.0.tgz",
"integrity": "sha512-7JlyDZSDPVH1pwh7OwiZbUVKw+PFjW7h+Xy1thM+IDSdug7qXWpVyvxwaz3+SVHazZBNnz8DxHJTlsdbYkxN9g==",
"dependencies": {
"@twilio/audioplayer": "1.0.6",
"@twilio/voice-errors": "1.0.1",
"backoff": "2.5.0",
"loglevel": "1.6.7",
"rtcpeerconnection-shim": "1.2.8",
"ws": "7.4.6",
"xmlhttprequest": "1.8.0"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/twilio-client/node_modules/@twilio/voice-errors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@twilio/voice-errors/-/voice-errors-1.0.1.tgz",
"integrity": "sha512-iXzCuiOhNMhrr8DVjRRzI14YwGUIBM83kWSWcDktxmXim0Tz9xoCth4QFAQcMkNL2h9DlfXlob6noH+3h2iA4A=="
},
"node_modules/twilio-client/node_modules/ws": {
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"engines": {
"node": ">=8.3.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/twilio/node_modules/axios": { "node_modules/twilio/node_modules/axios": {
"version": "0.26.1", "version": "0.26.1",
"license": "MIT", "license": "MIT",
@ -28207,6 +28294,11 @@
"@types/unist": { "@types/unist": {
"version": "2.0.6" "version": "2.0.6"
}, },
"@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
"@types/uuid": { "@types/uuid": {
"version": "9.0.1", "version": "9.0.1",
"dev": true "dev": true
@ -35543,9 +35635,11 @@
"react-digit-input": "^2.1.0", "react-digit-input": "^2.1.0",
"react-dom": "^17", "react-dom": "^17",
"react-qr-code": "^2.0.11", "react-qr-code": "^2.0.11",
"react-redux": "^8.0.5",
"react-timer-hook": "^3.0.5", "react-timer-hook": "^3.0.5",
"swr": "^2.0.0", "swr": "^2.0.0",
"tsconfig-link": "*", "tsconfig-link": "*",
"twilio-client": "*",
"typescript": "^4.9.5" "typescript": "^4.9.5"
}, },
"dependencies": { "dependencies": {
@ -37380,6 +37474,19 @@
"match-sorter": "^6.0.2" "match-sorter": "^6.0.2"
} }
}, },
"react-redux": {
"version": "8.0.5",
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz",
"integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==",
"requires": {
"@babel/runtime": "^7.12.1",
"@types/hoist-non-react-statics": "^3.3.1",
"@types/use-sync-external-store": "^0.0.3",
"hoist-non-react-statics": "^3.3.2",
"react-is": "^18.0.0",
"use-sync-external-store": "^1.0.0"
}
},
"react-router": { "react-router": {
"version": "6.8.2", "version": "6.8.2",
"requires": { "requires": {
@ -38524,6 +38631,33 @@
} }
} }
}, },
"twilio-client": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/twilio-client/-/twilio-client-1.15.0.tgz",
"integrity": "sha512-7JlyDZSDPVH1pwh7OwiZbUVKw+PFjW7h+Xy1thM+IDSdug7qXWpVyvxwaz3+SVHazZBNnz8DxHJTlsdbYkxN9g==",
"requires": {
"@twilio/audioplayer": "1.0.6",
"@twilio/voice-errors": "1.0.1",
"backoff": "2.5.0",
"loglevel": "1.6.7",
"rtcpeerconnection-shim": "1.2.8",
"ws": "7.4.6",
"xmlhttprequest": "1.8.0"
},
"dependencies": {
"@twilio/voice-errors": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@twilio/voice-errors/-/voice-errors-1.0.1.tgz",
"integrity": "sha512-iXzCuiOhNMhrr8DVjRRzI14YwGUIBM83kWSWcDktxmXim0Tz9xoCth4QFAQcMkNL2h9DlfXlob6noH+3h2iA4A=="
},
"ws": {
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==",
"requires": {}
}
}
},
"type": { "type": {
"version": "1.2.0" "version": "1.2.0"
}, },