Develop
This commit is contained in:
parent
7ca5f2d45a
commit
f901f203b0
302 changed files with 9897 additions and 10332 deletions
|
|
@ -8,14 +8,13 @@ WORKDIR ${APP_DIR}
|
|||
COPY . .
|
||||
RUN turbo prune --scope=@digiresilience/metamigo-frontend --docker
|
||||
|
||||
|
||||
FROM base AS installer
|
||||
ARG APP_DIR=/opt/metamigo-frontend
|
||||
WORKDIR ${APP_DIR}
|
||||
COPY .gitignore .gitignore
|
||||
COPY --from=builder ${APP_DIR}/out/json/ .
|
||||
COPY --from=builder ${APP_DIR}/out/package-lock.json ./package-lock.json
|
||||
RUN npm ci --omit=dev
|
||||
RUN npm i
|
||||
|
||||
COPY --from=builder ${APP_DIR}/out/full/ .
|
||||
RUN npm i -g turbo
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { FC, useEffect } from "react";
|
||||
"use client";
|
||||
|
||||
import { FC, useEffect, PropsWithChildren } from "react";
|
||||
import { CircularProgress, Typography, Grid } from "@mui/material";
|
||||
import { signIn, signOut, getSession } from "next-auth/react";
|
||||
import { useLogin, useTranslate } from "react-admin";
|
||||
|
|
@ -17,7 +19,7 @@ export const authProvider = {
|
|||
checkError(e: any) {
|
||||
if (e.graphQLErrors && e.graphQLErrors.length > 0) {
|
||||
const permDenied = e.graphQLErrors.some((e: any) =>
|
||||
e.message.match(/.*permission denied.*/)
|
||||
e.message.match(/.*permission denied.*/),
|
||||
);
|
||||
if (permDenied)
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { FC, PropsWithChildren, useEffect } from "react";
|
||||
import { CircularProgress } from "@mui/material";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { useRouter } from "next/router";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
export const Auth: FC<PropsWithChildren> = ({ children }) => {
|
||||
const router = useRouter();
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
import { forwardRef } from "react";
|
||||
import useDigitInput, { InputAttributes } from "react-digit-input";
|
||||
|
|
@ -1,12 +1,16 @@
|
|||
// @ts-nocheck
|
||||
|
||||
"use client";
|
||||
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import { Admin, Resource } from "react-admin";
|
||||
import { useApolloClient } from "@apollo/client";
|
||||
import polyglotI18nProvider from "ra-i18n-polyglot";
|
||||
import { ThemeProvider, createTheme } from "@mui/material";
|
||||
import { metamigoDataProvider } from "../lib/dataprovider";
|
||||
import { metamigoDataProvider } from "../_lib/dataprovider";
|
||||
import { theme } from "./layout/themes";
|
||||
import { Layout } from "./layout";
|
||||
import englishMessages from "../i18n/en";
|
||||
import englishMessages from "../_i18n/en";
|
||||
import users from "./users";
|
||||
import accounts from "./accounts";
|
||||
import whatsappBots from "./whatsapp/bots";
|
||||
|
|
@ -20,7 +24,7 @@ import { AdminLogin, authProvider } from "./AdminLogin";
|
|||
|
||||
const i18nProvider = polyglotI18nProvider(
|
||||
(_locale: any) => englishMessages,
|
||||
"en"
|
||||
"en",
|
||||
);
|
||||
|
||||
const MetamigoAdmin: FC = () => {
|
||||
|
|
@ -44,6 +48,7 @@ const MetamigoAdmin: FC = () => {
|
|||
dataProvider={dataProvider}
|
||||
layout={Layout}
|
||||
i18nProvider={i18nProvider}
|
||||
// @ts-ignore
|
||||
loginPage={AdminLogin}
|
||||
// @ts-ignore
|
||||
authProvider={authProvider}
|
||||
8
apps/metamigo-frontend/app/_components/MultiProvider.tsx
Normal file
8
apps/metamigo-frontend/app/_components/MultiProvider.tsx
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
"use client";
|
||||
|
||||
import { FC, PropsWithChildren } from "react";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
|
||||
export const MultiProvider: FC<PropsWithChildren> = ({ children }) => (
|
||||
<SessionProvider>{children}</SessionProvider>
|
||||
);
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import {
|
||||
|
|
@ -25,7 +27,7 @@ type AccountEditToolbarProps = {
|
|||
record?: any;
|
||||
};
|
||||
|
||||
const AccountEditToolbar: FC<AccountEditToolbarProps> = (props: any) => {
|
||||
const AccountEditToolbar: FC<AccountEditToolbarProps> = (props) => {
|
||||
const { data: session } = useSession();
|
||||
const classes = useStyles(props);
|
||||
return (
|
||||
|
|
@ -41,7 +43,7 @@ const AccountTitle = ({ record }: { record?: any }) => {
|
|||
return <span>Account {title}</span>;
|
||||
};
|
||||
|
||||
export const AccountEdit = (props: EditProps) => (
|
||||
export const AccountEdit: FC<EditProps> = (props) => (
|
||||
<Edit title={<AccountTitle />} {...props}>
|
||||
<SimpleForm toolbar={<AccountEditToolbar />}>
|
||||
<TextInput disabled source="id" />
|
||||
|
|
@ -56,4 +58,5 @@ export const AccountEdit = (props: EditProps) => (
|
|||
</SimpleForm>
|
||||
</Edit>
|
||||
);
|
||||
|
||||
export default AccountEdit;
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import {
|
||||
List,
|
||||
|
|
@ -14,7 +16,7 @@ type DeleteNotSelfButtonProps = {
|
|||
record?: any;
|
||||
};
|
||||
|
||||
const DeleteNotSelfButton: FC<DeleteNotSelfButtonProps> = (props: any) => {
|
||||
const DeleteNotSelfButton: FC<DeleteNotSelfButtonProps> = (props) => {
|
||||
const { data: session } = useSession();
|
||||
return (
|
||||
// @ts-ignore
|
||||
|
|
@ -25,7 +27,7 @@ const DeleteNotSelfButton: FC<DeleteNotSelfButtonProps> = (props: any) => {
|
|||
);
|
||||
};
|
||||
|
||||
export const AccountList = (props: ListProps) => (
|
||||
export const AccountList: FC<ListProps> = (props) => (
|
||||
<List {...props} exporter={false}>
|
||||
<Datagrid rowClick="edit">
|
||||
<ReferenceField source="userId" reference="users">
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
/* eslint-disable import/no-named-as-default */
|
||||
/* eslint-disable import/no-anonymous-default-export */
|
||||
import AccountIcon from "@mui/icons-material/AccountTree";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { forwardRef } from "react";
|
||||
import { AppBar, UserMenu, MenuItemLink, useTranslate } from "react-admin";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
|
@ -40,14 +42,19 @@ const CustomUserMenu = (props: any) => (
|
|||
const CustomAppBar = (props: any) => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<AppBar {...props} elevation={1} userMenu={<CustomUserMenu />}>
|
||||
<AppBar
|
||||
{...props}
|
||||
elevation={1}
|
||||
userMenu={<CustomUserMenu />}
|
||||
position="sticky"
|
||||
sx={{ mt: -1 }}
|
||||
>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color="inherit"
|
||||
className={classes.title}
|
||||
id="react-admin-title"
|
||||
/>
|
||||
<span className={classes.spacer} />
|
||||
</AppBar>
|
||||
);
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
/* eslint-disable import/no-named-as-default */
|
||||
"use client";
|
||||
|
||||
import { Layout as RaLayout, LayoutProps, Sidebar } from "react-admin";
|
||||
import AppBar from "./AppBar";
|
||||
import Menu from "./Menu";
|
||||
|
|
@ -6,15 +7,13 @@ import { theme } from "./themes";
|
|||
|
||||
const CustomSidebar = (props: any) => <Sidebar {...props} size={200} />;
|
||||
|
||||
const Layout = (props: LayoutProps) => (
|
||||
export const Layout = (props: LayoutProps) => (
|
||||
<RaLayout
|
||||
{...props}
|
||||
appBar={AppBar}
|
||||
menu={Menu}
|
||||
menu={Menu as any}
|
||||
sidebar={CustomSidebar}
|
||||
// @ts-ignore
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { SVGProps } from "react";
|
||||
|
||||
const Logo = (props: SVGProps<SVGSVGElement>) => (
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
/* eslint-disable camelcase */
|
||||
import { FC, useState } from "react";
|
||||
// import { useSelector } from "react-redux";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { FC, PropsWithChildren, Fragment, ReactElement } from "react";
|
||||
import ExpandMore from "@mui/icons-material/ExpandMore";
|
||||
import List from "@mui/material/List";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
export { default as AppBar } from "./AppBar";
|
||||
export { default as Layout } from "./Layout";
|
||||
export { Layout } from "./Layout";
|
||||
export { default as Menu } from "./Menu";
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import {
|
||||
SimpleForm,
|
||||
Create,
|
||||
|
|
@ -6,9 +9,9 @@ import {
|
|||
CreateProps,
|
||||
} from "react-admin";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { validateE164Number } from "../../../lib/phone-numbers";
|
||||
import { validateE164Number } from "../../../_lib/phone-numbers";
|
||||
|
||||
const SignalBotCreate = (props: CreateProps) => {
|
||||
const SignalBotCreate: FC<CreateProps> = (props) => {
|
||||
const { data: session } = useSession();
|
||||
|
||||
return (
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { SimpleForm, Edit, TextInput, required, EditProps } from "react-admin";
|
||||
|
||||
const SignalBotEdit = (props: EditProps) => (
|
||||
const SignalBotEdit: FC<EditProps> = (props) => (
|
||||
<Edit {...props} title="Edit Bot">
|
||||
<SimpleForm>
|
||||
<TextInput disabled source="phoneNumber" validate={[required()]} />
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import {
|
||||
List,
|
||||
Datagrid,
|
||||
|
|
@ -7,7 +10,7 @@ import {
|
|||
ListProps,
|
||||
} from "react-admin";
|
||||
|
||||
const SignalBotList = (props: ListProps) => (
|
||||
const SignalBotList: FC<ListProps> = (props) => (
|
||||
<List {...props} exporter={false}>
|
||||
<Datagrid rowClick="show">
|
||||
<TextField source="phoneNumber" />
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
import React, { useState } from "react";
|
||||
"use client";
|
||||
|
||||
import { FC, useEffect, useState } from "react";
|
||||
import {
|
||||
Show,
|
||||
SimpleShowLayout,
|
||||
|
|
@ -28,7 +30,7 @@ import { SixDigitInput } from "../../DigitInput";
|
|||
import {
|
||||
sanitizeE164Number,
|
||||
isValidE164Number,
|
||||
} from "../../../lib/phone-numbers";
|
||||
} from "../../../_lib/phone-numbers";
|
||||
|
||||
const Sidebar = ({ record }: any) => {
|
||||
const [phoneNumber, setPhoneNumber] = useState("");
|
||||
|
|
@ -173,7 +175,7 @@ const VerificationCodeRequest = ({
|
|||
onSuccess,
|
||||
onError,
|
||||
}: any) => {
|
||||
React.useEffect(() => {
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
await handleRequestCode({
|
||||
verifyMode,
|
||||
|
|
@ -207,8 +209,8 @@ const VerificationCaptcha = ({
|
|||
onError,
|
||||
handleClose,
|
||||
}: any) => {
|
||||
const [code, setCode] = React.useState(undefined);
|
||||
const [isSubmitting, setSubmitting] = React.useState(false);
|
||||
const [code, setCode] = useState(undefined);
|
||||
const [isSubmitting, setSubmitting] = useState(false);
|
||||
|
||||
const handleSubmitVerification = async () => {
|
||||
setSubmitting(true);
|
||||
|
|
@ -269,10 +271,10 @@ const VerificationCodeInput = ({
|
|||
handleRestartVerification,
|
||||
confirmVerification,
|
||||
}: any) => {
|
||||
const [code, setValue] = React.useState("");
|
||||
const [isSubmitting, setSubmitting] = React.useState(false);
|
||||
const [isValid, setValid] = React.useState(false);
|
||||
const [submissionError, setSubmissionError] = React.useState(undefined);
|
||||
const [code, setValue] = useState("");
|
||||
const [isSubmitting, setSubmitting] = useState(false);
|
||||
const [isValid, setValid] = useState(false);
|
||||
const [submissionError, setSubmissionError] = useState(undefined);
|
||||
const translate = useTranslate();
|
||||
|
||||
const validator = (v: any) => v.trim().length === 6;
|
||||
|
|
@ -359,7 +361,7 @@ const VerificationCodeInput = ({
|
|||
};
|
||||
|
||||
const VerificationCodeDialog = (props: any) => {
|
||||
const [stage, setStage] = React.useState("request");
|
||||
const [stage, setStage] = useState("request");
|
||||
const onRequestSuccess = () => setStage("verify");
|
||||
const onRestartVerification = () => setStage("request");
|
||||
const handleClose = () => {
|
||||
|
|
@ -410,8 +412,8 @@ const VerificationCodeDialog = (props: any) => {
|
|||
};
|
||||
|
||||
const SignalBotShowActions = ({ data }: any) => {
|
||||
const [open, setOpen] = React.useState(false);
|
||||
const [verifyMode, setVerifyMode] = React.useState("");
|
||||
const [open, setOpen] = useState(false);
|
||||
const [verifyMode, setVerifyMode] = useState("");
|
||||
const refresh = useRefresh();
|
||||
|
||||
const handleOpenSMS = () => {
|
||||
|
|
@ -456,7 +458,7 @@ const SignalBotShowActions = ({ data }: any) => {
|
|||
);
|
||||
};
|
||||
|
||||
const SignalBotShow = (props: ShowProps) => (
|
||||
const SignalBotShow: FC<ShowProps> = (props) => (
|
||||
<Show
|
||||
actions={<SignalBotShowActions />}
|
||||
{...props}
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import SignalBotIcon from "@mui/icons-material/ChatOutlined";
|
||||
import SignalBotList from "./SignalBotList";
|
||||
import SignalBotEdit from "./SignalBotEdit";
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
/* eslint-disable react/display-name */
|
||||
import {
|
||||
SelectInput,
|
||||
required,
|
||||
ReferenceInput,
|
||||
ReferenceField,
|
||||
TextField,
|
||||
} from "react-admin";
|
||||
|
||||
export const SignalBotSelectInput =
|
||||
(source: string): FC =>
|
||||
() =>
|
||||
(
|
||||
<ReferenceInput
|
||||
label="Signal Bot"
|
||||
source={source}
|
||||
reference="signalBots"
|
||||
validate={[required()]}
|
||||
>
|
||||
<SelectInput optionText="phoneNumber" />
|
||||
</ReferenceInput>
|
||||
);
|
||||
|
||||
export const SignalBotField =
|
||||
(source: string): FC =>
|
||||
() =>
|
||||
(
|
||||
<ReferenceField label="Signal Bot" reference="signalBots" source={source}>
|
||||
<TextField source="phoneNumber" />
|
||||
</ReferenceField>
|
||||
);
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import {
|
||||
SimpleForm,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import {
|
||||
SimpleForm,
|
||||
|
|
@ -1,3 +1,6 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import {
|
||||
List,
|
||||
Datagrid,
|
||||
|
|
@ -8,7 +11,7 @@ import {
|
|||
BooleanField,
|
||||
} from "react-admin";
|
||||
|
||||
const UserList = () => (
|
||||
const UserList: FC = () => (
|
||||
<List exporter={false}>
|
||||
<Datagrid rowClick="edit">
|
||||
<EmailField source="email" />
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import UserIcon from "@mui/icons-material/People";
|
||||
import UserList from "./UserList";
|
||||
import UserEdit from "./UserEdit";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { SelectInput, useRecordContext } from "react-admin";
|
||||
|
||||
export const UserRoleInput = (props: any) => {
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
SimpleForm,
|
||||
TextInput,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
SimpleForm,
|
||||
TextInput,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { List, Datagrid, DateField, TextField, ListProps } from "react-admin";
|
||||
|
||||
const ProviderList = (props: ListProps) => (
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
/* eslint-disable import/no-anonymous-default-export */
|
||||
import ProviderIcon from "@mui/icons-material/Business";
|
||||
import ProviderList from "./ProviderList";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { SelectInput } from "react-admin";
|
||||
|
||||
export const ProviderKindInput = (props: any) => (
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { useInput } from "react-admin";
|
||||
import React, { useState } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
SimpleForm,
|
||||
Create,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
SimpleForm,
|
||||
TextInput,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
List,
|
||||
ListProps,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import VoiceLineIcon from "@mui/icons-material/PhoneCallback";
|
||||
import VoiceLineList from "./VoiceLineList";
|
||||
import VoiceLineEdit from "./VoiceLineEdit";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
import React, { useState, useEffect } from "react";
|
||||
import PlayIcon from "@mui/icons-material/PlayCircleFilled";
|
||||
|
|
@ -12,7 +14,7 @@ import {
|
|||
TextField,
|
||||
} from "react-admin";
|
||||
import { IconButton, CircularProgress } from "@mui/material";
|
||||
import absoluteUrl from "../../../lib/absolute-url";
|
||||
import absoluteUrl from "../../../_lib/absolute-url";
|
||||
import TwilioLanguages from "./twilio-languages";
|
||||
|
||||
type TTSProvider = (voice: any, language: any, prompt: any) => Promise<void>;
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
SimpleForm,
|
||||
FormDataConsumer,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
SimpleForm,
|
||||
TextInput,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { List, Datagrid, DateField, TextField, ListProps } from "react-admin";
|
||||
import { BackendIdField } from "./shared";
|
||||
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import WebhookIcon from "@mui/icons-material/Send";
|
||||
import WebhookList from "./WebhookList";
|
||||
import WebhookEdit from "./WebhookEdit";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { SelectInput, required } from "react-admin";
|
||||
|
||||
import {
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { List, Datagrid, TextField } from "react-admin";
|
||||
|
||||
const WhatsappAttachmentList = (props: any) => (
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { Show, ShowProps, SimpleShowLayout, TextField } from "react-admin";
|
||||
|
||||
const WhatsappAttachmentShow = (props: ShowProps) => (
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import WhatsappAttachmentIcon from "@mui/icons-material/AttachFile";
|
||||
import WhatsappAttachmentList from "./WhatsappAttachmentList";
|
||||
import WhatsappAttachmentShow from "./WhatsappAttachmentShow";
|
||||
|
|
@ -1,9 +1,18 @@
|
|||
// import dynamic from "next/dynamic";
|
||||
import { SimpleForm, Create, TextInput, required } from "react-admin";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { validateE164Number } from "../../../lib/phone-numbers";
|
||||
"use client";
|
||||
|
||||
const WhatsappBotCreate = (props: any) => {
|
||||
// import dynamic from "next/dynamic";
|
||||
import { FC } from "react";
|
||||
import {
|
||||
SimpleForm,
|
||||
Create,
|
||||
TextInput,
|
||||
required,
|
||||
CreateProps,
|
||||
} from "react-admin";
|
||||
import { useSession } from "next-auth/react";
|
||||
import { validateE164Number } from "../../../_lib/phone-numbers";
|
||||
|
||||
const WhatsappBotCreate: FC<CreateProps> = (props) => {
|
||||
// const MuiPhoneNumber = dynamic(() => import("material-ui-phone-number"), {
|
||||
// ssr: false,
|
||||
// });
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import { SimpleForm, Edit, TextInput, required, EditProps } from "react-admin";
|
||||
|
||||
const WhatsappBotEdit = (props: EditProps) => (
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
List,
|
||||
Datagrid,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import {
|
||||
Card,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import WhatsappBotIcon from "@mui/icons-material/WhatsApp";
|
||||
import WhatsappBotList from "./WhatsappBotList";
|
||||
import WhatsappBotEdit from "./WhatsappBotEdit";
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
/* eslint-disable react/display-name */
|
||||
import {
|
||||
SelectInput,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
List,
|
||||
ListProps,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import {
|
||||
Show,
|
||||
ShowProps,
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
"use client";
|
||||
|
||||
import WhatsappMessageIcon from "@mui/icons-material/Message";
|
||||
import WhatsappMessageList from "./WhatsappMessageList";
|
||||
import WhatsappMessageShow from "./WhatsappMessageShow";
|
||||
16
apps/metamigo-frontend/app/admin/_components/Admin.tsx
Normal file
16
apps/metamigo-frontend/app/admin/_components/Admin.tsx
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { ApolloProvider } from "@apollo/client";
|
||||
import { apolloClient } from "app/_lib/apollo-client";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const MetamigoAdmin = dynamic(() => import("app/_components/MetamigoAdmin"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
export const Admin:FC = () => (
|
||||
<ApolloProvider client={apolloClient}>
|
||||
<MetamigoAdmin />
|
||||
</ApolloProvider>
|
||||
);
|
||||
5
apps/metamigo-frontend/app/admin/page.tsx
Normal file
5
apps/metamigo-frontend/app/admin/page.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { Admin } from "./_components/Admin";
|
||||
|
||||
export default function Home() {
|
||||
return <Admin />
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import { NextApiRequest, NextApiResponse } from "next";
|
||||
import { NextRequest } from "next/server";
|
||||
import NextAuth from "next-auth";
|
||||
import Google from "next-auth/providers/google";
|
||||
import GitHub from "next-auth/providers/github";
|
||||
import GitLab from "next-auth/providers/gitlab";
|
||||
import Cognito from "next-auth/providers/cognito";
|
||||
import { loadConfig, IAppConfig } from "@digiresilience/metamigo-config";
|
||||
import { MetamigoAdapter } from "../../../lib/nextauth-adapter";
|
||||
import { CloudflareAccessProvider } from "../../../lib/cloudflare";
|
||||
import { MetamigoAdapter } from "app/_lib/nextauth-adapter";
|
||||
import { CloudflareAccessProvider } from "app/_lib/cloudflare";
|
||||
|
||||
const nextAuthOptions = (config: IAppConfig, req: NextApiRequest) => {
|
||||
const nextAuthOptions = (config: IAppConfig, req: NextRequest) => {
|
||||
const { nextAuth, cfaccess } = config;
|
||||
const adapter = MetamigoAdapter(config);
|
||||
const providers = [];
|
||||
|
|
@ -16,7 +16,7 @@ const nextAuthOptions = (config: IAppConfig, req: NextApiRequest) => {
|
|||
const { audience, domain } = cfaccess;
|
||||
const cloudflareAccessEnabled = audience && domain;
|
||||
if (cloudflareAccessEnabled)
|
||||
providers.push(CloudflareAccessProvider(audience, domain, adapter, req));
|
||||
providers.push(CloudflareAccessProvider(audience, domain, adapter, req as any));
|
||||
else {
|
||||
if (nextAuth.google?.id)
|
||||
providers.push(
|
||||
|
|
@ -78,11 +78,11 @@ const nextAuthOptions = (config: IAppConfig, req: NextApiRequest) => {
|
|||
};
|
||||
};
|
||||
|
||||
const nextAuth = async (
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
): Promise<void> =>
|
||||
// @ts-expect-error: Type mismatch
|
||||
NextAuth(req, res, nextAuthOptions(await loadConfig(), req));
|
||||
const handler = async (req: NextRequest, context: any) => {
|
||||
const config = await loadConfig();
|
||||
const authOptions = nextAuthOptions(config, req);
|
||||
// @ts-expect-error: non-existent property
|
||||
return NextAuth(req, context, authOptions);
|
||||
};
|
||||
|
||||
export default nextAuth;
|
||||
export { handler as GET, handler as POST };
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { createProxyMiddleware } from "http-proxy-middleware";
|
||||
|
||||
export default createProxyMiddleware({
|
||||
export const POST = createProxyMiddleware({
|
||||
target:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "http://metamigo-api:3001"
|
||||
|
|
@ -28,9 +28,3 @@ export default createProxyMiddleware({
|
|||
}
|
||||
},
|
||||
});
|
||||
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: false,
|
||||
},
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { createProxyMiddleware } from "http-proxy-middleware";
|
||||
|
||||
export default createProxyMiddleware({
|
||||
const handler = createProxyMiddleware({
|
||||
target:
|
||||
process.env.NODE_ENV === "production"
|
||||
? "http://metamigo-api:3001"
|
||||
|
|
@ -30,8 +30,4 @@ export default createProxyMiddleware({
|
|||
},
|
||||
});
|
||||
|
||||
export const config = {
|
||||
api: {
|
||||
bodyParser: false,
|
||||
},
|
||||
};
|
||||
export { handler as GET, handler as POST, handler as PUT, handler as DELETE};
|
||||
20
apps/metamigo-frontend/app/layout.tsx
Normal file
20
apps/metamigo-frontend/app/layout.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { ReactNode } from "react";
|
||||
import "app/_styles/globals.css";
|
||||
import { MultiProvider } from "./_components/MultiProvider";
|
||||
|
||||
type LayoutProps = {
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
export default function Layout({ children }: LayoutProps) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<MultiProvider>
|
||||
{children}
|
||||
</MultiProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
"use client";
|
||||
|
||||
import { FC } from "react";
|
||||
import { Button } from "@mui/material";
|
||||
import { signIn, signOut, useSession } from "next-auth/react";
|
||||
|
||||
const MyComponent: FC = () => {
|
||||
export const Login: FC = () => {
|
||||
const { data: session } = useSession();
|
||||
|
||||
return (
|
||||
|
|
@ -26,5 +28,3 @@ const MyComponent: FC = () => {
|
|||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default MyComponent;
|
||||
5
apps/metamigo-frontend/app/login/page.tsx
Normal file
5
apps/metamigo-frontend/app/login/page.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
import { Login } from "./_components/Login";
|
||||
|
||||
export default function Page() {
|
||||
return <Login />;
|
||||
}
|
||||
3
apps/metamigo-frontend/app/page.tsx
Normal file
3
apps/metamigo-frontend/app/page.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
export default function Page() {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
/* eslint-disable react/display-name */
|
||||
import {
|
||||
SelectInput,
|
||||
required,
|
||||
ReferenceInput,
|
||||
ReferenceField,
|
||||
TextField,
|
||||
} from "react-admin";
|
||||
|
||||
export const SignalBotSelectInput = (source: string) => () =>
|
||||
(
|
||||
<ReferenceInput
|
||||
label="Signal Bot"
|
||||
source={source}
|
||||
reference="signalBots"
|
||||
validate={[required()]}
|
||||
>
|
||||
<SelectInput optionText="phoneNumber" />
|
||||
</ReferenceInput>
|
||||
);
|
||||
|
||||
export const SignalBotField = (source: string) => () =>
|
||||
(
|
||||
<ReferenceField label="Signal Bot" reference="signalBots" source={source}>
|
||||
<TextField source="phoneNumber" />
|
||||
</ReferenceField>
|
||||
);
|
||||
|
|
@ -3,32 +3,32 @@
|
|||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.15",
|
||||
"@apollo/client": "^3.7.17",
|
||||
"@digiresilience/metamigo-config": "*",
|
||||
"@hapi/boom": "^10.0.1",
|
||||
"@hapi/wreck": "^18.0.1",
|
||||
"@mui/icons-material": "^5",
|
||||
"@mui/material": "^5",
|
||||
"@mui/styles": "^5",
|
||||
"@twilio/voice-sdk": "^2.6.0",
|
||||
"@twilio/voice-sdk": "^2.6.1",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"jsonwebtoken": "^9.0.1",
|
||||
"jwks-rsa": "^3.0.1",
|
||||
"next": "13.4.6",
|
||||
"next": "13.4.10",
|
||||
"next-auth": "4.22.1",
|
||||
"ra-data-graphql": "^4.11.3",
|
||||
"ra-i18n-polyglot": "^4.11.3",
|
||||
"ra-input-rich-text": "^4.11.3",
|
||||
"ra-language-english": "^4.11.3",
|
||||
"ra-data-graphql": "^4.12.1",
|
||||
"ra-i18n-polyglot": "^4.12.1",
|
||||
"ra-input-rich-text": "^4.12.1",
|
||||
"ra-language-english": "^4.12.1",
|
||||
"ra-postgraphile": "^6.1.1",
|
||||
"react": "18.2.0",
|
||||
"react-admin": "^4.11.3",
|
||||
"react-admin": "^4.12.1",
|
||||
"react-digit-input": "^2.1.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-qr-code": "^2.0.11",
|
||||
"react-redux": "^8.1.1",
|
||||
"react-timer-hook": "^3.0.6",
|
||||
"swr": "^2.1.5",
|
||||
"swr": "^2.2.0",
|
||||
"twilio-client": "^1.15.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
|
@ -41,15 +41,15 @@
|
|||
"fmt": "prettier --ignore-path .eslintignore \"**/*.{js,jsx,ts,tsx,graphql,md}\" --write"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@next/eslint-plugin-next": "^13.4.6",
|
||||
"@next/eslint-plugin-next": "^13.4.10",
|
||||
"@types/hapi__wreck": "17.0.1",
|
||||
"@types/react": "18.2.13",
|
||||
"@types/react": "18.2.15",
|
||||
"@types/react-mic": "12.4.3",
|
||||
"babel-preset-link": "*",
|
||||
"eslint-config-link": "*",
|
||||
"jest-config-link": "*",
|
||||
"tsconfig-link": "*",
|
||||
"typescript": "5.1.3"
|
||||
"typescript": "5.1.6"
|
||||
},
|
||||
"overrides": {
|
||||
"@mui/styles": {
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
import "../styles/globals.css";
|
||||
import { AppProps } from "next/app";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
|
||||
function MetamigoStarter({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<SessionProvider session={(pageProps as any).session}>
|
||||
<Component {...pageProps} />
|
||||
</SessionProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default MetamigoStarter;
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
import { ApolloProvider } from "@apollo/client";
|
||||
import { apolloClient } from "../lib/apollo-client";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
const MetamigoAdmin = dynamic(() => import("../components/MetamigoAdmin"), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<ApolloProvider client={apolloClient}>
|
||||
<MetamigoAdmin />
|
||||
</ApolloProvider>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import { NextPage } from "next";
|
||||
import { Typography, Box, Button, Grid, Link } from "@mui/material";
|
||||
import { FC, useEffect, PropsWithChildren } from "react";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
export const RedirectToAdmin: FC<PropsWithChildren> = ({ children }) => {
|
||||
const router = useRouter();
|
||||
useEffect(() => {
|
||||
router.push("/admin");
|
||||
});
|
||||
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
const Home: NextPage = () => (
|
||||
<Box>
|
||||
<Typography variant="h3">Metamigo</Typography>
|
||||
<Grid container justifyContent="space-around" style={{ padding: 60 }}>
|
||||
<Grid item>
|
||||
<Link href="/admin">
|
||||
<Button variant="contained">Admin</Button>
|
||||
<RedirectToAdmin />
|
||||
</Link>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default Home;
|
||||
|
|
@ -2,7 +2,11 @@
|
|||
"extends": "tsconfig-link",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
|
|
@ -17,9 +21,24 @@
|
|||
"strict": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./*", "../../node_modules/*"]
|
||||
}
|
||||
"@/*": [
|
||||
"./*",
|
||||
"../../node_modules/*"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
]
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue