Compare commits
14 Commits
b8849945b9
...
e9e9611f80
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e9e9611f80 | ||
0c054687ba | |||
3b147e50a1 | |||
![]() |
e94514ed02 | ||
![]() |
0032e51858 | ||
8d6a9ab74c | |||
07c4ae8cbd | |||
a782930d3d | |||
4c1877caa5 | |||
e9324f6c14 | |||
![]() |
9fcee44e0c | ||
![]() |
9939b1c824 | ||
00deb05850 | |||
eff20ae459 |
27
Dockerfile
27
Dockerfile
@ -17,22 +17,25 @@ COPY . .
|
|||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Bundle static assets with nginx
|
# Bundle static assets with nginx
|
||||||
FROM nginx:1.21.6 as production
|
FROM node:16-alpine as production
|
||||||
# Copy built assets from builder
|
# Copy built assets from builder
|
||||||
COPY --from=builder /app/build /usr/share/nginx/html
|
WORKDIR /app
|
||||||
# Add nginx.config
|
COPY --from=builder /app/build .
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
||||||
# Expose ports
|
# Expose ports
|
||||||
EXPOSE 80
|
EXPOSE 3000
|
||||||
|
|
||||||
COPY entrypoint.sh .
|
|
||||||
COPY .env.production .
|
COPY .env.production .
|
||||||
|
|
||||||
ENV NODE_ENV production
|
ENV NODE_ENV production
|
||||||
|
ENV USER_NAME=node_user USER_UID=2000 GROUP_NAME=node_group GROUP_UID=2000
|
||||||
|
|
||||||
# Execute script
|
RUN npm i -g serve \
|
||||||
RUN ["chmod", "+x", "./entrypoint.sh"]
|
&& deluser --remove-home node \
|
||||||
ENTRYPOINT ["./entrypoint.sh"]
|
&& addgroup --g ${GROUP_UID} -S ${GROUP_NAME} \
|
||||||
|
&& adduser -D -S -s /sbin/nologin -u ${USER_UID} -G ${GROUP_NAME} ${USER_NAME}\
|
||||||
|
&& chown -R ${USER_NAME}:${GROUP_NAME} "/app/"
|
||||||
|
|
||||||
# Start serving
|
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
USER "${USER_NAME}"
|
||||||
|
CMD serve -s .
|
96
package-lock.json
generated
96
package-lock.json
generated
@ -35,6 +35,7 @@
|
|||||||
"react-hotkeys": "^2.0.0",
|
"react-hotkeys": "^2.0.0",
|
||||||
"react-i18next": "^11.18.3",
|
"react-i18next": "^11.18.3",
|
||||||
"react-loading-skeleton": "^3.1.0",
|
"react-loading-skeleton": "^3.1.0",
|
||||||
|
"react-lottie": "^1.2.3",
|
||||||
"react-markdown": "^8.0.3",
|
"react-markdown": "^8.0.3",
|
||||||
"react-redux": "^8.0.2",
|
"react-redux": "^8.0.2",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
@ -69,6 +70,7 @@
|
|||||||
"@testing-library/react": "^13.3.0",
|
"@testing-library/react": "^13.3.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/jest": "^27.5.2",
|
"@types/jest": "^27.5.2",
|
||||||
|
"@types/react-lottie": "^1.2.6",
|
||||||
"@types/react-syntax-highlighter": "^15.5.5",
|
"@types/react-syntax-highlighter": "^15.5.5",
|
||||||
"autoprefixer": "^10.4.8",
|
"autoprefixer": "^10.4.8",
|
||||||
"babel-plugin-named-exports-order": "^0.0.2",
|
"babel-plugin-named-exports-order": "^0.0.2",
|
||||||
@ -11558,6 +11560,15 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/react-lottie": {
|
||||||
|
"version": "1.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-lottie/-/react-lottie-1.2.6.tgz",
|
||||||
|
"integrity": "sha512-fvGJHD7SeUdVESHo7f7erRnXkTWaa/6Mo5TB+R0/ieSftKoFspA4sMlF2qMH6BljXI7ehFJbBtrD5bzDxPCkGg==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/react-syntax-highlighter": {
|
"node_modules/@types/react-syntax-highlighter": {
|
||||||
"version": "15.5.5",
|
"version": "15.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.5.tgz",
|
||||||
@ -13600,6 +13611,27 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/babel-runtime": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
|
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": "^2.4.0",
|
||||||
|
"regenerator-runtime": "^0.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/babel-runtime/node_modules/core-js": {
|
||||||
|
"version": "2.6.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
|
||||||
|
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
|
||||||
|
"deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
|
||||||
|
"hasInstallScript": true
|
||||||
|
},
|
||||||
|
"node_modules/babel-runtime/node_modules/regenerator-runtime": {
|
||||||
|
"version": "0.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
|
},
|
||||||
"node_modules/bail": {
|
"node_modules/bail": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
|
||||||
@ -25646,6 +25678,11 @@
|
|||||||
"loose-envify": "cli.js"
|
"loose-envify": "cli.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lottie-web": {
|
||||||
|
"version": "5.9.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.9.6.tgz",
|
||||||
|
"integrity": "sha512-JFs7KsHwflugH5qIXBpB4905yC1Sub2MZWtl/elvO/QC6qj1ApqbUZJyjzJseJUtVpgiDaXQLjBlIJGS7UUUXA=="
|
||||||
|
},
|
||||||
"node_modules/loud-rejection": {
|
"node_modules/loud-rejection": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
||||||
@ -30383,6 +30420,21 @@
|
|||||||
"react": ">=16.8.0"
|
"react": ">=16.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-lottie": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lottie/-/react-lottie-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-qLCERxUr8M+4mm1LU0Ruxw5Y5Fn/OmYkGfnA+JDM/dZb3oKwVAJCjwnjkj9TMHtzR2U6sMEUD3ZZ1RaHagM7kA==",
|
||||||
|
"dependencies": {
|
||||||
|
"babel-runtime": "^6.26.0",
|
||||||
|
"lottie-web": "^5.1.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"npm": "^3.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^0.14.7 || ^15.0.0 || ^16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-markdown": {
|
"node_modules/react-markdown": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.3.tgz",
|
||||||
@ -48597,6 +48649,15 @@
|
|||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@types/react-lottie": {
|
||||||
|
"version": "1.2.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/react-lottie/-/react-lottie-1.2.6.tgz",
|
||||||
|
"integrity": "sha512-fvGJHD7SeUdVESHo7f7erRnXkTWaa/6Mo5TB+R0/ieSftKoFspA4sMlF2qMH6BljXI7ehFJbBtrD5bzDxPCkGg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@types/react": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"@types/react-syntax-highlighter": {
|
"@types/react-syntax-highlighter": {
|
||||||
"version": "15.5.5",
|
"version": "15.5.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.5.tgz",
|
||||||
@ -50205,6 +50266,27 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-runtime": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
|
||||||
|
"integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^2.4.0",
|
||||||
|
"regenerator-runtime": "^0.11.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.6.12",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
|
||||||
|
"integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ=="
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.11.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
|
||||||
|
"integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"bail": {
|
"bail": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/bail/-/bail-1.0.5.tgz",
|
||||||
@ -59330,6 +59412,11 @@
|
|||||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lottie-web": {
|
||||||
|
"version": "5.9.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.9.6.tgz",
|
||||||
|
"integrity": "sha512-JFs7KsHwflugH5qIXBpB4905yC1Sub2MZWtl/elvO/QC6qj1ApqbUZJyjzJseJUtVpgiDaXQLjBlIJGS7UUUXA=="
|
||||||
|
},
|
||||||
"loud-rejection": {
|
"loud-rejection": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
||||||
@ -62603,6 +62690,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-loading-skeleton/-/react-loading-skeleton-3.1.0.tgz",
|
||||||
"integrity": "sha512-j1U1CWWs68nBPOg7tkQqnlFcAMFF6oEK6MgqAo15f8A5p7mjH6xyKn2gHbkcimpwfO0VQXqxAswnSYVr8lWzjw=="
|
"integrity": "sha512-j1U1CWWs68nBPOg7tkQqnlFcAMFF6oEK6MgqAo15f8A5p7mjH6xyKn2gHbkcimpwfO0VQXqxAswnSYVr8lWzjw=="
|
||||||
},
|
},
|
||||||
|
"react-lottie": {
|
||||||
|
"version": "1.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-lottie/-/react-lottie-1.2.3.tgz",
|
||||||
|
"integrity": "sha512-qLCERxUr8M+4mm1LU0Ruxw5Y5Fn/OmYkGfnA+JDM/dZb3oKwVAJCjwnjkj9TMHtzR2U6sMEUD3ZZ1RaHagM7kA==",
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.26.0",
|
||||||
|
"lottie-web": "^5.1.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-markdown": {
|
"react-markdown": {
|
||||||
"version": "8.0.3",
|
"version": "8.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.3.tgz",
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
"react-hotkeys": "^2.0.0",
|
"react-hotkeys": "^2.0.0",
|
||||||
"react-i18next": "^11.18.3",
|
"react-i18next": "^11.18.3",
|
||||||
"react-loading-skeleton": "^3.1.0",
|
"react-loading-skeleton": "^3.1.0",
|
||||||
|
"react-lottie": "^1.2.3",
|
||||||
"react-markdown": "^8.0.3",
|
"react-markdown": "^8.0.3",
|
||||||
"react-redux": "^8.0.2",
|
"react-redux": "^8.0.2",
|
||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
@ -109,6 +110,7 @@
|
|||||||
"@testing-library/react": "^13.3.0",
|
"@testing-library/react": "^13.3.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
"@types/jest": "^27.5.2",
|
"@types/jest": "^27.5.2",
|
||||||
|
"@types/react-lottie": "^1.2.6",
|
||||||
"@types/react-syntax-highlighter": "^15.5.5",
|
"@types/react-syntax-highlighter": "^15.5.5",
|
||||||
"autoprefixer": "^10.4.8",
|
"autoprefixer": "^10.4.8",
|
||||||
"babel-plugin-named-exports-order": "^0.0.2",
|
"babel-plugin-named-exports-order": "^0.0.2",
|
||||||
|
@ -9,12 +9,10 @@ const articleEndpoint = "/papers/"
|
|||||||
|
|
||||||
async function getArticle(id: string): Promise<Article> {
|
async function getArticle(id: string): Promise<Article> {
|
||||||
try {
|
try {
|
||||||
// await new Promise((res, _) => {
|
|
||||||
// setTimeout(() => res(null), 2000);
|
|
||||||
// });
|
|
||||||
const response = await integratorApiClient.get<FetchArticleByIdDTO>(
|
const response = await integratorApiClient.get<FetchArticleByIdDTO>(
|
||||||
// `https://run.mocky.io/v3/62cd4581-d864-4d46-b1d6-02b45b5d1994/${id}`
|
// `https://run.mocky.io/v3/62cd4581-d864-4d46-b1d6-02b45b5d1994/${id}`
|
||||||
// `https://jsonplaceholder.typicode.com/posts/${id}`
|
// `https://jsonplaceholder.typicode.com/posts/${id}`
|
||||||
|
// `https://run.mocky.io/v3/066be3d8-0568-439a-8b20-062deed49a97`
|
||||||
articleEndpoint + id
|
articleEndpoint + id
|
||||||
);
|
);
|
||||||
const dto = response.data;
|
const dto = response.data;
|
||||||
|
1
src/assets/lotties/notFoundAnimation.json
Normal file
1
src/assets/lotties/notFoundAnimation.json
Normal file
File diff suppressed because one or more lines are too long
198
src/components/Burger.tsx
Normal file
198
src/components/Burger.tsx
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
import { Menu, Transition } from "@headlessui/react";
|
||||||
|
import React, { Fragment } from "react";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import { Disclosure } from "@headlessui/react";
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Components */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
import ContextMenuAction from "./drop-down-menu/ContextMenuAction";
|
||||||
|
import ContextMenu from "./drop-down-menu/ContextMenu";
|
||||||
|
import { Button } from "./Button/Button";
|
||||||
|
import Link from "./typography/Link";
|
||||||
|
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
/* Icons */
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
|
import { ReactComponent as SVGFavoriteOutlined } from "assets/svg/favorite-outlined.svg";
|
||||||
|
import { ReactComponent as SVGHamburger } from "assets/svg/hamburger.svg";
|
||||||
|
import { ReactComponent as SVGFolder } from "assets/svg/folder.svg";
|
||||||
|
import { ReactComponent as SVGFile } from "assets/svg/file.svg";
|
||||||
|
import { ReactComponent as SVGEye } from "assets/svg/eye.svg";
|
||||||
|
import { ReactComponent as SVGArrowUp } from "assets/svg/arrow-up.svg";
|
||||||
|
import { ReactComponent as SVGCaretDown } from "assets/svg/caret-down.svg";
|
||||||
|
|
||||||
|
type Props = React.ComponentPropsWithoutRef<"div">;
|
||||||
|
|
||||||
|
const Burger = (props: Props) => {
|
||||||
|
return (
|
||||||
|
<div {...props}>
|
||||||
|
<Menu as="div" className="relative inline-block text-left z-30">
|
||||||
|
<div>
|
||||||
|
<Menu.Button as={Button} emphasis="low">
|
||||||
|
<Button.Icon>
|
||||||
|
<SVGHamburger className="h-6 w-6" />
|
||||||
|
</Button.Icon>
|
||||||
|
</Menu.Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Transition
|
||||||
|
as={Fragment}
|
||||||
|
enter="transition ease-out duration-100"
|
||||||
|
enterFrom="transform opacity-0 scale-95"
|
||||||
|
enterTo="transform opacity-100 scale-100"
|
||||||
|
leave="transition ease-in duration-75"
|
||||||
|
leaveFrom="transform opacity-100 scale-100"
|
||||||
|
leaveTo="transform opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<Menu.Items
|
||||||
|
className="origin-top-right absolute right-0 mt-5 w-44 rounded-md
|
||||||
|
shadow-lg bg-white ring-1 ring-black ring-opacity-5 focus:outline-none"
|
||||||
|
>
|
||||||
|
<div className="py-1">
|
||||||
|
<Disclosure>
|
||||||
|
<Disclosure.Button className="uppercase text-base px-2 py-1">
|
||||||
|
<Link className="text-[#096DD9]">create new</Link>
|
||||||
|
</Disclosure.Button>
|
||||||
|
</Disclosure>
|
||||||
|
<hr />
|
||||||
|
<Disclosure>
|
||||||
|
{({ open }) => (
|
||||||
|
<>
|
||||||
|
<Disclosure.Button
|
||||||
|
className="uppercase px-2 flex justify-between w-full items-center
|
||||||
|
py-1
|
||||||
|
hover:bg-gray-100
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
my library
|
||||||
|
<SVGArrowUp
|
||||||
|
className={`${
|
||||||
|
open ? "rotate-180 transform" : "rotate-360"
|
||||||
|
} h-5 w-5 `}
|
||||||
|
/>
|
||||||
|
</Disclosure.Button>
|
||||||
|
|
||||||
|
<Link to="#" className="w-full">
|
||||||
|
<Disclosure.Panel
|
||||||
|
className="px-2 flex items-center font-normal gap-1 py-1 w-full ease-in-out duration-300
|
||||||
|
rounded
|
||||||
|
hover:bg-gray-200
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<SVGFile className="stroke-black w-4 h-4" />
|
||||||
|
My Publications
|
||||||
|
</Disclosure.Panel>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link to="#" className="w-full">
|
||||||
|
<Disclosure.Panel
|
||||||
|
className="px-2 flex items-center font-normal gap-1 py-1 w-full ease-in-out duration-300
|
||||||
|
rounded
|
||||||
|
hover:bg-gray-200
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<SVGFavoriteOutlined className="stroke-black w-4 h-4" />
|
||||||
|
My Favorites
|
||||||
|
</Disclosure.Panel>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link to="#" className="w-full">
|
||||||
|
<Disclosure.Panel
|
||||||
|
className="px-2 flex items-center font-normal gap-1 py-1 w-full ease-in-out duration-300
|
||||||
|
rounded
|
||||||
|
hover:bg-gray-200
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<SVGFolder className="stroke-black fill-black w-4 h-4" />
|
||||||
|
My Collections
|
||||||
|
</Disclosure.Panel>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link to="#" className="w-full">
|
||||||
|
<Disclosure.Panel
|
||||||
|
className="px-2 flex items-center font-normal gap-1 py-1 w-full ease-in-out duration-300
|
||||||
|
rounded
|
||||||
|
hover:bg-gray-200
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<SVGEye className="stroke-black w-4 h-4" />
|
||||||
|
Recent Viewed
|
||||||
|
</Disclosure.Panel>
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Disclosure>
|
||||||
|
<hr />
|
||||||
|
{/* Third list - start */}
|
||||||
|
<Disclosure>
|
||||||
|
{({ open }) => (
|
||||||
|
<>
|
||||||
|
<Disclosure.Button
|
||||||
|
className="uppercase px-2 flex justify-between w-full items-center
|
||||||
|
py-1
|
||||||
|
hover:bg-gray-100
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
About
|
||||||
|
<SVGArrowUp
|
||||||
|
className={`${
|
||||||
|
open ? "rotate-180 transform" : "rotate-360"
|
||||||
|
} h-5 w-5 `}
|
||||||
|
/>
|
||||||
|
</Disclosure.Button>
|
||||||
|
|
||||||
|
<Link to="#" className="w-full">
|
||||||
|
<Disclosure.Panel
|
||||||
|
className="px-2 flex items-center font-normal gap-1 py-1 w-full ease-in-out duration-300
|
||||||
|
rounded
|
||||||
|
hover:bg-gray-200
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
About Freeland
|
||||||
|
</Disclosure.Panel>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link to="#" className="w-full">
|
||||||
|
<Disclosure.Panel
|
||||||
|
className="px-2 flex items-center font-normal gap-1 py-1 w-full ease-in-out duration-300
|
||||||
|
rounded
|
||||||
|
hover:bg-gray-200
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Contact Us
|
||||||
|
</Disclosure.Panel>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link to="#" className="w-full">
|
||||||
|
<Disclosure.Panel
|
||||||
|
className="px-2 flex items-center font-normal gap-1 py-1 w-full ease-in-out duration-300
|
||||||
|
rounded
|
||||||
|
hover:bg-gray-200
|
||||||
|
text-base
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Help
|
||||||
|
</Disclosure.Panel>
|
||||||
|
</Link>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Disclosure>
|
||||||
|
{/* Third list - end */}
|
||||||
|
</div>
|
||||||
|
</Menu.Items>
|
||||||
|
</Transition>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Burger;
|
@ -53,7 +53,6 @@ const LocalizationButton = (props: Props) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
changeLanguage("en");
|
changeLanguage("en");
|
||||||
}}
|
}}
|
||||||
href="#"
|
|
||||||
className={classNames(
|
className={classNames(
|
||||||
active ? "bg-gray-100 text-gray-900" : "text-gray-700",
|
active ? "bg-gray-100 text-gray-900" : "text-gray-700",
|
||||||
"block px-4 py-2 text-sm"
|
"block px-4 py-2 text-sm"
|
||||||
@ -69,7 +68,7 @@ const LocalizationButton = (props: Props) => {
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
changeLanguage("ru");
|
changeLanguage("ru");
|
||||||
}}
|
}}
|
||||||
href="#"
|
|
||||||
className={classNames(
|
className={classNames(
|
||||||
active ? "bg-gray-100 text-gray-900" : "text-gray-700",
|
active ? "bg-gray-100 text-gray-900" : "text-gray-700",
|
||||||
"block px-4 py-2 text-sm"
|
"block px-4 py-2 text-sm"
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
import React from "react";
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* MarkDown */
|
/* MarkDown */
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
@ -18,33 +16,137 @@ import Heading from "./typography/Heading";
|
|||||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
import { dark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
import { dark } from "react-syntax-highlighter/dist/esm/styles/prism";
|
||||||
import Link from "./typography/Link";
|
import Link from "./typography/Link";
|
||||||
import { indexOf } from "lodash";
|
import style from "react-syntax-highlighter/dist/esm/styles/hljs/a11y-dark";
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
markdown: string;
|
markdown: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Markdown = ({ markdown }: Props) => {
|
const Markdown = ({ markdown }: Props) => {
|
||||||
let newMarkdown = markdown.replace(/\n/g, " \n");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactMarkdown
|
<ReactMarkdown
|
||||||
remarkPlugins={[remarkGfm]}
|
remarkPlugins={[remarkGfm]}
|
||||||
children={newMarkdown}
|
children={markdown}
|
||||||
components={{
|
components={{
|
||||||
h1: Heading,
|
ul: ({ node, ...props }) => (
|
||||||
h2: Typography,
|
<ul
|
||||||
a: (props) => {
|
style={{
|
||||||
return (
|
listStyleType: "disc",
|
||||||
<Link
|
}}
|
||||||
href={props.href}
|
className="mx-8"
|
||||||
className="text-sky-600 font-bold text-base"
|
|
||||||
{...props}
|
{...props}
|
||||||
>
|
/>
|
||||||
{props.children}
|
),
|
||||||
</Link>
|
|
||||||
);
|
ol: ({ node, ...props }) => (
|
||||||
},
|
<ol className="list-decimal mx-8" {...props} />
|
||||||
|
),
|
||||||
|
|
||||||
|
h1: ({ node, ...props }) => (
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
marginInlineEnd: 0,
|
||||||
|
marginInlineStart: 0,
|
||||||
|
marginBlockStart: 11,
|
||||||
|
marginBlockEnd: 11,
|
||||||
|
|
||||||
|
fontSize: 32,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
|
||||||
|
h2: ({ node, ...props }) => (
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
|
||||||
|
marginInlineEnd: 0,
|
||||||
|
marginInlineStart: 0,
|
||||||
|
|
||||||
|
marginBlockStart: 13.28,
|
||||||
|
marginBlockEnd: 13.28,
|
||||||
|
|
||||||
|
fontSize: 24,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
|
||||||
|
h3: ({ node, ...props }) => (
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
|
||||||
|
marginInlineEnd: 0,
|
||||||
|
marginInlineStart: 0,
|
||||||
|
|
||||||
|
marginBlockStart: 16,
|
||||||
|
marginBlockEnd: 16,
|
||||||
|
|
||||||
|
fontSize: 18.72,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
|
||||||
|
h4: ({ node, ...props }) => (
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
|
||||||
|
marginInlineEnd: 0,
|
||||||
|
marginInlineStart: 0,
|
||||||
|
|
||||||
|
marginBlockStart: 21.28,
|
||||||
|
marginBlockEnd: 21.28,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
|
||||||
|
h5: ({ node, ...props }) => (
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
|
||||||
|
marginInlineEnd: 0,
|
||||||
|
marginInlineStart: 0,
|
||||||
|
|
||||||
|
marginBlockStart: 26.72,
|
||||||
|
marginBlockEnd: 26.72,
|
||||||
|
|
||||||
|
fontSize: 13.28,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
|
||||||
|
h6: ({ node, ...props }) => (
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
fontWeight: "bold",
|
||||||
|
|
||||||
|
marginInlineEnd: 0,
|
||||||
|
marginInlineStart: 0,
|
||||||
|
|
||||||
|
marginBlockStart: 37.28,
|
||||||
|
marginBlockEnd: 37.28,
|
||||||
|
|
||||||
|
fontSize: 10.72,
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
p: Typography,
|
||||||
|
|
||||||
|
a: ({ node, ...props }) => (
|
||||||
|
<Link
|
||||||
|
className=" inline-flex text-sm font-bold text-blue-500"
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
|
||||||
code({ node, inline, className, children, ...props }) {
|
code({ node, inline, className, children, ...props }) {
|
||||||
const match = /language-(\w+)/.exec(className || "");
|
const match = /language-(\w+)/.exec(className || "");
|
||||||
|
@ -12,6 +12,7 @@ import * as ArticlePart from "../../components/Article/Article";
|
|||||||
import BaseLayout from "components/BaseLayout";
|
import BaseLayout from "components/BaseLayout";
|
||||||
import Container from "components/Container";
|
import Container from "components/Container";
|
||||||
import NotFound from "./NotFound";
|
import NotFound from "./NotFound";
|
||||||
|
import Markdown from "components/Markdown";
|
||||||
|
|
||||||
const AnArticleBody = () => {
|
const AnArticleBody = () => {
|
||||||
const store = useArticleStore();
|
const store = useArticleStore();
|
||||||
@ -46,7 +47,12 @@ const AnArticleBody = () => {
|
|||||||
<ArticlePart.Article.Title className="text-3xl">
|
<ArticlePart.Article.Title className="text-3xl">
|
||||||
{article?.title}
|
{article?.title}
|
||||||
</ArticlePart.Article.Title>
|
</ArticlePart.Article.Title>
|
||||||
<div className="py-6">{article?.content}</div>
|
|
||||||
|
<div className="py-6">
|
||||||
|
<Markdown
|
||||||
|
markdown={article?.content ?? ''}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -3,7 +3,19 @@ import Container from "components/Container";
|
|||||||
import { Button } from "components/Button/Button";
|
import { Button } from "components/Button/Button";
|
||||||
import Link from "components/typography/Link";
|
import Link from "components/typography/Link";
|
||||||
|
|
||||||
|
import Lottie from "react-lottie";
|
||||||
|
import animationData from "../../assets/lotties/notFoundAnimation.json";
|
||||||
|
|
||||||
const NotFound = () => {
|
const NotFound = () => {
|
||||||
|
const defaultOptions = {
|
||||||
|
loop: true,
|
||||||
|
autoplay: true,
|
||||||
|
animationData: animationData,
|
||||||
|
rendererSettings: {
|
||||||
|
preserveAspectRatio: "xMidYMid slice",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container
|
<Container
|
||||||
variant="straight"
|
variant="straight"
|
||||||
@ -11,13 +23,8 @@ const NotFound = () => {
|
|||||||
font-serif h-screen my-auto
|
font-serif h-screen my-auto
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
<div
|
<Lottie options={defaultOptions} height={200} width={200} />
|
||||||
className="bg-[url('https://cdn.dribbble.com/users/285475/screenshots/2083086/dribbble_1.gif')]
|
<span className="font-bold text-5xl ">404</span>
|
||||||
h-[450px]
|
|
||||||
w-full text-center text-7xl "
|
|
||||||
>
|
|
||||||
404
|
|
||||||
</div>
|
|
||||||
<h3 className="font-bold text-2xl text-center">Page does not exist</h3>
|
<h3 className="font-bold text-2xl text-center">Page does not exist</h3>
|
||||||
<h4 className="text-center">
|
<h4 className="text-center">
|
||||||
Maybe you got a broken link, or maybe you made a misprint in the address
|
Maybe you got a broken link, or maybe you made a misprint in the address
|
||||||
|
@ -27,6 +27,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import Link from "components/typography/Link";
|
import Link from "components/typography/Link";
|
||||||
import LocalizationButton from "components/LocalizationButton";
|
import LocalizationButton from "components/LocalizationButton";
|
||||||
import LogoScipaper from "components/LogoScipaper";
|
import LogoScipaper from "components/LogoScipaper";
|
||||||
|
import Burger from "components/Burger";
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
const [authenticated, setAuthenticated] = useState(false);
|
const [authenticated, setAuthenticated] = useState(false);
|
||||||
@ -173,7 +174,7 @@ const Header = () => {
|
|||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
{/* Burger component will be shown for the small screens */}
|
{/* Burger component will be shown for the small screens */}
|
||||||
<Navbar className="block lg:hidden" />
|
<Burger className="block lg:hidden" />
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
);
|
);
|
||||||
|
@ -51,7 +51,7 @@ export default function Link({
|
|||||||
: style
|
: style
|
||||||
}
|
}
|
||||||
aria-disabled={disabled}
|
aria-disabled={disabled}
|
||||||
className="flex items-center"
|
className={classNames("flex items-center", className)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user