Skip to content

Commit

Permalink
Merge pull request #89 from perimetre/dev
Browse files Browse the repository at this point in the history
Promoting Dev
  • Loading branch information
AssisrMatheus authored Feb 17, 2022
2 parents 43d9cfd + 7980e06 commit 4a5be73
Show file tree
Hide file tree
Showing 13 changed files with 252 additions and 62 deletions.
9 changes: 6 additions & 3 deletions .env.development
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Backend
NEXT_PUBLIC_GRAPHQL_URI="https://dev.api.marathon.perimetre.co/graphql"
#NEXT_PUBLIC_GRAPHQL_URI="http://localhost:3001/graphql"
#NEXT_PUBLIC_STATUS_URI="http://localhost:3001/v1/status"
NEXT_PUBLIC_STATUS_URI="https://dev.api.marathon.perimetre.co/v1/status"

# Unity
NEXT_PUBLIC_UNITY_PUBLIC_FOLDER="unity"
Expand All @@ -18,4 +17,8 @@ NEXT_PUBLIC_UNITY_PUBLIC_MEDIA_URI="https://marathon-media-dev01.nyc3.digitaloce
NEXT_PUBLIC_UNITY_ASSET_BUNDLE_FOLDER="asset-bundles"
NEXT_PUBLIC_UNITY_DEFAULT_PLATFORM="webgl"
NEXT_PUBLIC_UNITY_MODULE_MATERIALS_FOLDER="materials/modules"
NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME="WebGL"
NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME="WebGL"

# Marathon
NEXT_PUBLIC_MARATHON_API="http://new-web.marathonhardware.com"
NEXT_PUBLIC_MARATHON_API_LIST="/action/account/listdetail"
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ ARG NEXT_PUBLIC_UNITY_MODULE_MATERIALS_FOLDER
ENV NEXT_PUBLIC_UNITY_MODULE_MATERIALS_FOLDER=${NEXT_PUBLIC_UNITY_MODULE_MATERIALS_FOLDER}
ARG NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME
ENV NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME=${NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME}
ARG NEXT_PUBLIC_MARATHON_API
ENV NEXT_PUBLIC_MARATHON_API=${NEXT_PUBLIC_MARATHON_API}
ARG NEXT_PUBLIC_MARATHON_API_LIST
ENV NEXT_PUBLIC_MARATHON_API_LIST=${NEXT_PUBLIC_MARATHON_API_LIST}

WORKDIR /build

Expand Down
9 changes: 6 additions & 3 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
"ECONNREFUSED": "Could not contact the server. The server might be down or your internet is turned off. Please try again later.",
"unauthorized": "You are not permitted to do this action",
"wrongCredentials": "Email or password is incorrect",
"unreachableService": "An error has occurred. Please try again later. (Unreachable service)"
"unreachableService": "An error has occurred. Please try again later. (Unreachable service)",
"createListNoExternalId": "An error has occurred and a list could not be created (No external id)",
"createListCannotComplete": "An error has occurred. Could not complete the request."
},
"build": {
"loadingModule": "Please wait...",
Expand Down Expand Up @@ -121,7 +123,8 @@
"headers": {
"product": "Product",
"quantity": "Qty"
}
},
"listCreatedSuccessfully": "Your list <bold>{name}</bold> was successfully created. <url>Click here</url> to open it in a new tab"
},
"help": {
"selectModule": "Select module",
Expand All @@ -131,4 +134,4 @@
"rotateModule": "Rotate module",
"moveModule": "Move module"
}
}
}
1 change: 1 addition & 0 deletions src/apollo/cart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const CREATE_LIST = gql`
mutation CreateList($projectId: Int!) {
createList(id: $projectId) {
id
externalId
name
project {
id
Expand Down
2 changes: 2 additions & 0 deletions src/apollo/generated/graphql.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5618,6 +5618,7 @@ export type CreateListMutation = {
| {
__typename?: 'List';
id: number;
externalId?: string | null | undefined;
name?: string | null | undefined;
project?: { __typename?: 'Project'; id: number } | null | undefined;
}
Expand Down Expand Up @@ -7573,6 +7574,7 @@ export const CreateListDocument = gql`
mutation CreateList($projectId: Int!) {
createList(id: $projectId) {
id
externalId
name
project {
id
Expand Down
121 changes: 121 additions & 0 deletions src/components/Elements/CreateListButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { FilePlus, X } from 'react-feather';
import { FormattedMessage } from 'react-intl';
import { CreateListMutation, useCreateListMutation } from '../../../apollo/generated/graphql';
import env from '../../../env';
import { CatchGraphqlError, getLocaleIdFromGraphqlError } from '../../../lib/apollo/exceptions';
import Button from '../../UI/Button';
import ReactPortal from '../../UI/ReactPortal';
import Spinner from '../../UI/Spinner';
import Toastr, { ToastrRef } from '../../UI/Toastr';

type CreateListButtonProps = {
projectId: number;
};

const CreateListButton: React.FC<CreateListButtonProps> = ({ projectId }) => {
// ***********
// ** Grapqhl declarations
// ***********

// ** Mutations
const [createList, { loading: createListLoading }] = useCreateListMutation();

// ***********
// ** Business logic
// ***********

const { NEXT_PUBLIC_MARATHON_API, NEXT_PUBLIC_MARATHON_API_LIST } = useMemo(env, []);

const [createListError, setCreateListError] = useState<string | undefined>();
const [lastCreatedList, setLastCreatedList] = useState<CreateListMutation | undefined>(undefined);
const toastRef = useRef<ToastrRef>(null);

const listUrl = useMemo(() => {
if (!NEXT_PUBLIC_MARATHON_API_LIST || !NEXT_PUBLIC_MARATHON_API) return;

const url = new URL(NEXT_PUBLIC_MARATHON_API_LIST, NEXT_PUBLIC_MARATHON_API);

if (lastCreatedList?.createList?.externalId) {
url.searchParams.append('oid', lastCreatedList.createList.externalId);
}

return url.toString();
}, [NEXT_PUBLIC_MARATHON_API, NEXT_PUBLIC_MARATHON_API_LIST, lastCreatedList]);

const handleCreateList = useCallback(async () => {
setLastCreatedList(undefined);
if (projectId) {
try {
const { data: result } = await createList({
variables: {
projectId
}
});

setLastCreatedList(result || undefined);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
const { graphQLErrors, networkError }: CatchGraphqlError = err;
// If failed we'll get here
// Get the locale id for the error
const error = getLocaleIdFromGraphqlError(graphQLErrors, networkError);

// Update the error state, which will display the error
if (error) {
toastRef.current?.open(3, () => {
setCreateListError(undefined);
});
setCreateListError(error);
}
}
}
}, [createList, projectId]);

return (
<>
<Button className="whitespace-pre group" onClick={handleCreateList} disabled={createListLoading}>
{createListLoading ? (
<Spinner className="w-6 h-6" />
) : (
<>
<span>
<FormattedMessage id="cart.createList" />
</span>
<FilePlus className="text-2xl" />
</>
)}
</Button>
<ReactPortal selector="#cart-header">
{!!lastCreatedList && (
<div className="container p-4 mx-auto mt-12 bg-white border border-gray-200 border-solid rounded print:hidden">
<div className="flex items-center justify-between w-full">
<p>
<FormattedMessage
id="cart.listCreatedSuccessfully"
values={{
name: lastCreatedList?.createList?.name,
bold: (msg: string) => <span className="font-bold">{msg}</span>,
url: (msg: string) => (
<a className="text-mui-primary hover:underline" href={listUrl} target="_blank" rel="noreferrer">
{msg}
</a>
)
}}
/>
</p>
<button className="p-4 mui-btn-icon text-mui-paragraph-900" onClick={() => setLastCreatedList(undefined)}>
<X className="mui-animate-scaleHover-target" />
</button>
</div>
</div>
)}
</ReactPortal>
<Toastr ref={toastRef} variant="error">
{createListError && <FormattedMessage id={createListError} />}
</Toastr>
</>
);
};

export default CreateListButton;
37 changes: 13 additions & 24 deletions src/components/Templates/Cart/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import classNames from 'classnames';
import Head from 'next/head';
import Link from 'next/link';
import React from 'react';
import { ChevronLeft, File } from 'react-feather';
import { FormattedMessage, useIntl } from 'react-intl';
import { CartQuery } from '../../../apollo/generated/graphql';
import CreateListButton from '../../Elements/CreateListButton';
import AppLayout from '../../Layouts/AppLayout';
import Head from 'next/head';
import { FormattedMessage, useIntl } from 'react-intl';
import SkeletonImage from '../../UI/SkeletonImage';
import classNames from 'classnames';
import Button from '../../UI/Button';
import Link from 'next/link';
import ErrorMessage from '../../UI/ErrorMessage';
import Skeleton from '../../UI/Skeleton';
import { ChevronLeft, File } from 'react-feather';
import NavbarButton from '../../UI/NavbarButton';
import Skeleton from '../../UI/Skeleton';
import SkeletonImage from '../../UI/SkeletonImage';

type CartProjectModulesProps = {
cart: NonNullable<NonNullable<CartQuery['project']>['cart']>;
Expand Down Expand Up @@ -70,17 +71,9 @@ type CartTemplateProps = {
loading: boolean;
error?: string;
handleTryAgain: () => void;
handleCreateList: () => void;
};

const CartTemplate: React.FC<CartTemplateProps> = ({
data,
slug,
error,
loading,
handleTryAgain
// handleCreateList
}) => {
const CartTemplate: React.FC<CartTemplateProps> = ({ data, slug, error, loading, handleTryAgain }) => {
const intl = useIntl();

return (
Expand Down Expand Up @@ -111,6 +104,7 @@ const CartTemplate: React.FC<CartTemplateProps> = ({
</title>
</Head>
<div>
<div id="cart-header"></div>
<div className="no-print:mx-auto no-print:container no-print:my-12 no-print:bg-white no-print:shadow-md no-print:p-8">
{!error ? (
!loading ? (
Expand All @@ -130,14 +124,9 @@ const CartTemplate: React.FC<CartTemplateProps> = ({
<File className="text-2xl" />
</Button>
</div>
{/*<div className="print:hidden">*/}
{/* <Button className="whitespace-pre group" onClick={handleCreateList}>*/}
{/* <span>*/}
{/* <FormattedMessage id="cart.createList" />*/}
{/* </span>*/}
{/* <FilePlus className="text-2xl" />*/}
{/* </Button>*/}
{/*</div>*/}
<div className="print:hidden">
{data?.project?.id && <CreateListButton projectId={data.project.id} />}
</div>
</div>
<hr className="my-4" />
{data?.project?.cart && (
Expand Down
76 changes: 76 additions & 0 deletions src/components/UI/Toastr/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { forwardRef, useImperativeHandle, useState } from 'react';
import ReactPortal from '../ReactPortal';
import classnames from 'classnames';

const placementClassnameMap = {
// top: 'top-0',
'top-start': 'top-0 left-0',
'top-end': 'top-0 right-0',
// right: '',
'right-start': 'top-0 right-0',
'right-end': 'bottom-0 right-0',
// bottom: '',
'bottom-start': 'bottom-0 left-0',
'bottom-end': 'bottom-0 right-0',
// left: '',
'left-start': 'top-0 left-0',
'left-end': 'bottom-0 left-0'
};

const variantClassnameMap = {
default: 'bg-white border-gray-200',
error: 'bg-mui-error font-bold text-white'
};

export type ToastrRef = {
open: (timer?: number, done?: () => void) => void;
};

export type ToastrProps = {
placement?: keyof typeof placementClassnameMap;
variant?: keyof typeof variantClassnameMap;
timer?: number;
className?: string;
children?: React.ReactNode | string;
};

const Toastr = forwardRef<ToastrRef, ToastrProps>(function Toastr(
{ placement = 'bottom-end', variant = 'default', timer = 3, className, children },
ref
) {
const [isOpen, setIsOpen] = useState(false);

useImperativeHandle(
ref,
() => ({
open: (newTimer, done) => {
setIsOpen(true);
setTimeout(() => {
setIsOpen(false);

if (done) done();
}, (newTimer || timer) * 1000);
}
}),
[timer]
);

return (
<ReactPortal selector="#toast-root">
{isOpen && (
<div
className={classnames(
placementClassnameMap[placement],
variantClassnameMap[variant],
'rounded-md absolute z-50 p-8 m-4 max-w-md shadow-md border border-solid mui-animate-fade-up duration-100',
className
)}
>
{children}
</div>
)}
</ReactPortal>
);
});

export default Toastr;
5 changes: 4 additions & 1 deletion src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ const env = () => {
NEXT_PUBLIC_UNITY_ASSET_BUNDLE_FOLDER: process.env.NEXT_PUBLIC_UNITY_ASSET_BUNDLE_FOLDER,
NEXT_PUBLIC_UNITY_DEFAULT_PLATFORM: process.env.NEXT_PUBLIC_UNITY_DEFAULT_PLATFORM,
NEXT_PUBLIC_UNITY_MODULE_MATERIALS_FOLDER: process.env.NEXT_PUBLIC_UNITY_MODULE_MATERIALS_FOLDER,
NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME: process.env.NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME
NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME: process.env.NEXT_PUBLIC_UNITY_MANIFEST_ASSET_NAME,
// Marathon
NEXT_PUBLIC_MARATHON_API: process.env.NEXT_PUBLIC_MARATHON_API,
NEXT_PUBLIC_MARATHON_API_LIST: process.env.NEXT_PUBLIC_MARATHON_API_LIST
};
};

Expand Down
12 changes: 8 additions & 4 deletions src/lib/apollo/exceptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,14 @@ import logging from '../logging';

const codesToIgnoreOnLogging: string[] = [];

export const getLocaleIdFromGraphqlError = (
graphQLErrors?: readonly GraphQLError[] | null,
networkError?: Error | ServerError | ServerParseError | null
) => {
export type GraphQLErrors = readonly GraphQLError[] | null | undefined;
export type NetworkError = Error | ServerError | ServerParseError | null | undefined;
export type CatchGraphqlError = {
graphQLErrors?: GraphQLErrors;
networkError?: NetworkError;
};

export const getLocaleIdFromGraphqlError = (graphQLErrors?: GraphQLErrors, networkError?: NetworkError) => {
if (
networkError?.message === 'Failed to fetch' ||
(networkError as any)?.code === 'ECONNREFUSED' ||
Expand Down
1 change: 1 addition & 0 deletions src/pages/_document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class MyDocument extends Document {
/>
</Head>
<body>
<div id="toast-root"></div>
<div id="modal-root"></div>
<Main />
<NextScript />
Expand Down
Loading

0 comments on commit 4a5be73

Please sign in to comment.