diff --git a/package-lock.json b/package-lock.json
index 92a5faa..f5f3af9 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -12,6 +12,7 @@
"@reduxjs/toolkit": "^1.8.3",
"@types/node": "^16.11.47",
"@types/react": "^18.0.15",
+ "@types/react-copy-to-clipboard": "^5.0.4",
"@types/react-dom": "^18.0.6",
"@uiw/react-md-editor": "^3.18.1",
"axios": "^0.27.2",
@@ -25,6 +26,7 @@
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"react": "^18.2.0",
+ "react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.2.0",
"react-hotkeys": "^2.0.0",
"react-i18next": "^11.18.3",
@@ -11479,6 +11481,14 @@
"csstype": "^3.0.2"
}
},
+ "node_modules/@types/react-copy-to-clipboard": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz",
+ "integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-dom": {
"version": "18.0.6",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
@@ -15021,6 +15031,14 @@
"node": ">=0.10.0"
}
},
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz",
+ "integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"node_modules/core-js": {
"version": "3.24.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz",
@@ -30025,6 +30043,18 @@
"node": ">=14"
}
},
+ "node_modules/react-copy-to-clipboard": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz",
+ "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==",
+ "dependencies": {
+ "copy-to-clipboard": "^3.3.1",
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "react": "^15.3.0 || 16 || 17 || 18"
+ }
+ },
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@@ -37574,6 +37604,11 @@
"node": ">=8.0"
}
},
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ },
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -48448,6 +48483,14 @@
"csstype": "^3.0.2"
}
},
+ "@types/react-copy-to-clipboard": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.4.tgz",
+ "integrity": "sha512-otTJsJpofYAeaIeOwV5xBUGpo6exXG2HX7X4nseToCB2VgPEBxGBHCm/FecZ676doNR7HCSTVtmohxfG2b3/yQ==",
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/react-dom": {
"version": "18.0.6",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.6.tgz",
@@ -51233,6 +51276,14 @@
"integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==",
"dev": true
},
+ "copy-to-clipboard": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz",
+ "integrity": "sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==",
+ "requires": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
"core-js": {
"version": "3.24.1",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.24.1.tgz",
@@ -62246,6 +62297,15 @@
"whatwg-fetch": "^3.6.2"
}
},
+ "react-copy-to-clipboard": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.1.0.tgz",
+ "integrity": "sha512-k61RsNgAayIJNoy9yDsYzDe/yAZAzEbEgcz3DZMhF686LEyukcE1hzurxe85JandPUG+yTfGVFzuEw3xt8WP/A==",
+ "requires": {
+ "copy-to-clipboard": "^3.3.1",
+ "prop-types": "^15.8.1"
+ }
+ },
"react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
@@ -67797,6 +67857,11 @@
"is-number": "^7.0.0"
}
},
+ "toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ },
"toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
diff --git a/package.json b/package.json
index 5d32e57..9561c6c 100755
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
"@reduxjs/toolkit": "^1.8.3",
"@types/node": "^16.11.47",
"@types/react": "^18.0.15",
+ "@types/react-copy-to-clipboard": "^5.0.4",
"@types/react-dom": "^18.0.6",
"@uiw/react-md-editor": "^3.18.1",
"axios": "^0.27.2",
@@ -20,6 +21,7 @@
"jwt-decode": "^3.1.2",
"lodash": "^4.17.21",
"react": "^18.2.0",
+ "react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.2.0",
"react-hotkeys": "^2.0.0",
"react-i18next": "^11.18.3",
diff --git a/public/index.html b/public/index.html
index 975ff09..e9784fd 100755
--- a/public/index.html
+++ b/public/index.html
@@ -24,7 +24,7 @@
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
-
Freeland
+ Scipaper
diff --git a/public/locales/ru/translation.json b/public/locales/ru/translation.json
index b568527..38f2720 100755
--- a/public/locales/ru/translation.json
+++ b/public/locales/ru/translation.json
@@ -62,7 +62,15 @@
},
"articlePage": {
"abstract": "Введение",
- "keywords": "Ключевые слова"
+ "keywords": "Ключевые слова",
+ "interactionButtons":{
+ "abstract": "Развернуть",
+ "readFile": "Читать",
+ "download" : "Скачать",
+ "share" : "Поделиться",
+ "cite" : "Цитировать",
+ "copied": "Скопировано"
+ }
},
"navbar": {
"createNew": "Создать статью",
diff --git a/src/article/data/articleAPIService.ts b/src/article/data/articleAPIService.ts
index 9936fd2..d61e3bd 100644
--- a/src/article/data/articleAPIService.ts
+++ b/src/article/data/articleAPIService.ts
@@ -3,16 +3,19 @@ import { Article } from "../domain/articleEntity";
import { create } from "../domain/articleModel";
import { FetchArticleByIdDTO } from "./dto/fetch_article_by_id_dto";
import Failure from "core/failure";
+import { integratorApiClient } from "core/httpClient";
+
+const articleEndpoint = "/papers/"
async function getArticle(id: string): Promise {
try {
// await new Promise((res, _) => {
// setTimeout(() => res(null), 2000);
// });
- const response = await axios.get(
- `https://run.mocky.io/v3/62cd4581-d864-4d46-b1d6-02b45b5d1994/${id}`
+ const response = await integratorApiClient.get(
+ // `https://run.mocky.io/v3/62cd4581-d864-4d46-b1d6-02b45b5d1994/${id}`
// `https://jsonplaceholder.typicode.com/posts/${id}`
- // `http://scipaper.ru/v1/papers/${id}`
+ articleEndpoint + id
);
const dto = response.data;
return create({
diff --git a/src/components/Article/ArticleParts/InteractionButtons/ArticleInteractionButtons.tsx b/src/components/Article/ArticleParts/InteractionButtons/ArticleInteractionButtons.tsx
index 6301918..1de4324 100755
--- a/src/components/Article/ArticleParts/InteractionButtons/ArticleInteractionButtons.tsx
+++ b/src/components/Article/ArticleParts/InteractionButtons/ArticleInteractionButtons.tsx
@@ -13,14 +13,10 @@ import {
import classNames from "classnames";
import { Transition } from "@headlessui/react";
import Link from "components/typography/Link";
+import { useTranslation } from "react-i18next";
+import { ShareButton } from "./ArticleShareButton";
const interactionButtonsStore = [
- {
- icon: ,
- title: "Read file",
- buttonEmphasis: "high",
- iconClassName: "h-6 fill-white stroke-white",
- },
{
icon: ,
title: "Download",
@@ -47,18 +43,22 @@ type ArticleButtonProps = {
children?: React.ReactNode;
className?: string;
emphasis?: "high" | "low";
- articleID?: string,
+ articleID?: string;
} & Omit, "">;
export function ArticleInteractionButtons({
isAbstractOpen = false,
children,
- openAbstract = () => { },
+ openAbstract = () => {},
className,
articleID,
emphasis = "high", //to change displaying of component
...props
}: ArticleButtonProps) {
+ const [t, i18next] = useTranslation("translation", {
+ keyPrefix: "articlePage.interactionButtons",
+ });
+ /* ----------------------------- Abstract Button ---------------------------- */
const abstractButton = (
);
- const fileInteractionButtons = interactionButtonsStore.map((button) => {
- return (
- button.title === 'Read file' ?
-
-
-
- :
-
- );
- });
+
+ /* ---------------------------- Read file button ---------------------------- */
+ const readFileButton = (
+
+
+
+ {emphasis === "high" && {t("readFile")}}
+
+
+ );
+ /* ----------------------------- Download button ---------------------------- */
+ const downLoadButton = (
+
+ );
+
+ /* ------------------------------- Cite button ------------------------------ */
+
+ const citeButton = (
+
+ );
return (
-
- {emphasis === "low" && !children ? abstractButton : null}
- {children ? children : fileInteractionButtons}
+
+ {emphasis != "high" && abstractButton}
+ {readFileButton}
+ {downLoadButton}
+ {citeButton}
+
);
}
diff --git a/src/components/Article/ArticleParts/InteractionButtons/ArticleShareButton.tsx b/src/components/Article/ArticleParts/InteractionButtons/ArticleShareButton.tsx
new file mode 100644
index 0000000..4a5c734
--- /dev/null
+++ b/src/components/Article/ArticleParts/InteractionButtons/ArticleShareButton.tsx
@@ -0,0 +1,87 @@
+import { BASE_URL } from "core/httpClient";
+import { useRef, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { Button } from "../../../Button/Button";
+import { SVGCopy, SVGShare, SVGXmark } from "../../../icons";
+import Typography from "../../../typography/Typography";
+import { CopyToClipboard } from "react-copy-to-clipboard";
+import { Popover } from "@headlessui/react";
+
+type Props = {
+ emphasis?: "high" | "low";
+ linktoCopy?: string;
+};
+
+export function ShareButton({ emphasis, linktoCopy }: Props) {
+ const [t, i18next] = useTranslation("translation", {
+ keyPrefix: "articlePage.interactionButtons",
+ });
+ const [copied, setCopied] = useState(false);
+
+ const copyValue =
+ BASE_URL != undefined && linktoCopy != undefined
+ ? BASE_URL + linktoCopy
+ : t("searchResults.nothingFound");
+
+ function onCopy() {
+ setCopied(true);
+ setTimeout(() => {
+ setCopied(false);
+ }, 1500);
+ };
+
+ const handleFocus = (event: any) => event.target.select();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {copied && (
+
+ {t("copied")}
+
+ )}
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/ArticleSearchResult.tsx b/src/components/ArticleSearchResult.tsx
index c569005..a1571be 100644
--- a/src/components/ArticleSearchResult.tsx
+++ b/src/components/ArticleSearchResult.tsx
@@ -47,10 +47,11 @@ export const ArticleSearchResult = ({ searchItem }: Props) => {
{searchItem.tags}
{
+ return (
+
+ );
+};
+
+export default LogoScipaper;
diff --git a/src/components/Logofreeland.tsx b/src/components/Logofreeland.tsx
deleted file mode 100755
index 2fbcb29..0000000
--- a/src/components/Logofreeland.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from "react";
-import classNames from "classnames";
-export type Props = {
- className?: string;
-};
-
-const Logofreeland = ({ className }: Props) => {
- return (
-
- );
-};
-
-export default Logofreeland;
diff --git a/src/components/MainPage/sections/FeaturedArticlesCards.tsx b/src/components/MainPage/sections/FeaturedArticlesCards.tsx
index 78f10f9..78f0289 100755
--- a/src/components/MainPage/sections/FeaturedArticlesCards.tsx
+++ b/src/components/MainPage/sections/FeaturedArticlesCards.tsx
@@ -169,7 +169,10 @@ const FeaturedArticlesCards = () => {
-
+
{t("mainPage.more")}
diff --git a/src/components/parts/Header.tsx b/src/components/parts/Header.tsx
index cae9eaf..9fbd384 100755
--- a/src/components/parts/Header.tsx
+++ b/src/components/parts/Header.tsx
@@ -5,7 +5,7 @@ import { useState, useTransition } from "react";
/* -------------------------------------------------------------------------- */
import ContextMenuAction from "../drop-down-menu/ContextMenuAction";
import ContextMenu from "../drop-down-menu/ContextMenu";
-import Logofreeland from "../Logofreeland";
+import LogoScipaper from "../LogoScipaper";
import { Button } from "../Button/Button";
import Avatar from "../Avatar";
import Navbar from "../Navbar";
@@ -47,13 +47,13 @@ const Header = () => {
xl:gap-60 xl:px-16"
>
{/* Logo and Menu */}
-
+
{/* Logo - start - className="w-7 sm:w-10 " /> */}
-
diff --git a/src/components/typography/Link.tsx b/src/components/typography/Link.tsx
index 8b55a57..f370d4d 100755
--- a/src/components/typography/Link.tsx
+++ b/src/components/typography/Link.tsx
@@ -57,5 +57,5 @@ export default function Link({
{children}
);
- return
{link}
;
+ return link;
}
diff --git a/src/core/httpClient.ts b/src/core/httpClient.ts
index 3b4d76b..83f7924 100755
--- a/src/core/httpClient.ts
+++ b/src/core/httpClient.ts
@@ -1,5 +1,5 @@
import axios from "axios";
-const BASE_URL = process.env.REACT_APP_INTEGRATOR_URL;
+export const BASE_URL = process.env.REACT_APP_INTEGRATOR_URL;
export const GRAPHQL_URL = process.env.REACT_APP_GRAPHQL_URL ?? "";
const instance = axios.create({
diff --git a/src/pages/SearchResultsPage.tsx b/src/pages/SearchResultsPage.tsx
index e6d3f35..00f7833 100644
--- a/src/pages/SearchResultsPage.tsx
+++ b/src/pages/SearchResultsPage.tsx
@@ -3,9 +3,6 @@ import BaseLayout from "components/BaseLayout";
import { SearchSection } from "components/SearchSection";
import { ColumnLayout } from "components/layouts/ThreeColumn/ColumnLayout";
import { SearchResultSection } from "components/SearchResultsSection";
-import { useSearchStoreImplementation } from "searchResults/data/searchStoreImplementation";
-import { useSearchViewModel } from "searchResults/controller/searchResultsViewModel";
-import { Loader } from "components/Loader/Loader";
import Fiter from "components/Filters/Filter";
export const SearchResultsPage = () => {
@@ -14,7 +11,7 @@ export const SearchResultsPage = () => {
-
+
diff --git a/src/searchResults/data/searchService.ts b/src/searchResults/data/searchService.ts
index dbf0cf6..ba4a75d 100755
--- a/src/searchResults/data/searchService.ts
+++ b/src/searchResults/data/searchService.ts
@@ -10,8 +10,8 @@ const searchEndpoint = "/papers/search";
async function search(request: string): Promise {
try {
const response = await integratorApiClient.get(
- // searchEndpoint + `?query=` + request + `&limit=10&offset=0`
- "https://run.mocky.io/v3/ea705665-2479-4039-8b81-412e011fc145"
+ searchEndpoint + `?query=` + request
+ // "https://run.mocky.io/v3/ea705665-2479-4039-8b81-412e011fc145"
);
const dto = response.data;
return create({