From 72cd46f80034679053175d4f916be4d6102dd92e Mon Sep 17 00:00:00 2001
From: Piotr Gawron <p.gawron@atcomp.pl>
Date: Thu, 12 Sep 2024 11:33:40 +0200
Subject: [PATCH] show license for project

---
 .../LicenseModal/LicenseModal.component.tsx   | 19 +++++++++++++++++
 .../Modal/LicenseModal/index.ts               |  1 +
 .../FunctionalArea/Modal/Modal.component.tsx  |  6 ++++++
 .../ProjectInfoDrawer.component.tsx           | 21 ++++++++++++++++++-
 src/models/licenseSchema.ts                   |  1 +
 src/models/projectSchema.ts                   |  6 +++---
 src/redux/modal/modal.reducers.ts             |  6 ++++++
 src/redux/modal/modal.slice.ts                |  3 +++
 src/types/modal.ts                            |  1 +
 9 files changed, 60 insertions(+), 4 deletions(-)
 create mode 100644 src/components/FunctionalArea/Modal/LicenseModal/LicenseModal.component.tsx
 create mode 100644 src/components/FunctionalArea/Modal/LicenseModal/index.ts

diff --git a/src/components/FunctionalArea/Modal/LicenseModal/LicenseModal.component.tsx b/src/components/FunctionalArea/Modal/LicenseModal/LicenseModal.component.tsx
new file mode 100644
index 00000000..bdb79d2d
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LicenseModal/LicenseModal.component.tsx
@@ -0,0 +1,19 @@
+import React from 'react';
+import { useAppSelector } from '@/redux/hooks/useAppSelector';
+import { projectSelector } from '@/redux/project/project.selectors';
+
+export const LicenseModal = (): React.ReactNode => {
+  const project = useAppSelector(projectSelector).data;
+
+  let licenseDescription = '';
+  if (project) {
+    licenseDescription = project.license
+      ? `<a href="${project.license.url}" target="_blank">Link</a><br/><br/>${project.license.content}`
+      : `<a href="${project.customLicenseUrl}" target="_blank">Link: ${project.customLicenseUrl}</a>`;
+  }
+  return (
+    <div className="w-full overflow-auto border border-t-[#E1E0E6] bg-white p-[24px]">
+      <div dangerouslySetInnerHTML={{ __html: licenseDescription }} />
+    </div>
+  );
+};
diff --git a/src/components/FunctionalArea/Modal/LicenseModal/index.ts b/src/components/FunctionalArea/Modal/LicenseModal/index.ts
new file mode 100644
index 00000000..b05258c6
--- /dev/null
+++ b/src/components/FunctionalArea/Modal/LicenseModal/index.ts
@@ -0,0 +1 @@
+export { LicenseModal } from './LicenseModal.component';
diff --git a/src/components/FunctionalArea/Modal/Modal.component.tsx b/src/components/FunctionalArea/Modal/Modal.component.tsx
index 10ee738f..8b97ece7 100644
--- a/src/components/FunctionalArea/Modal/Modal.component.tsx
+++ b/src/components/FunctionalArea/Modal/Modal.component.tsx
@@ -3,6 +3,7 @@ import { modalSelector } from '@/redux/modal/modal.selector';
 import dynamic from 'next/dynamic';
 import { AccessDeniedModal } from '@/components/FunctionalArea/Modal/AccessDeniedModal/AccessDeniedModal.component';
 import { AddCommentModal } from '@/components/FunctionalArea/Modal/AddCommentModal/AddCommentModal.component';
+import { LicenseModal } from '@/components/FunctionalArea/Modal/LicenseModal';
 import { EditOverlayModal } from './EditOverlayModal';
 import { LoginModal } from './LoginModal';
 import { ErrorReportModal } from './ErrorReportModal';
@@ -41,6 +42,11 @@ export const Modal = (): React.ReactNode => {
           <ErrorReportModal />
         </ModalLayout>
       )}
+      {isOpen && modalName === 'license' && (
+        <ModalLayout>
+          <LicenseModal />
+        </ModalLayout>
+      )}
       {isOpen && modalName === 'publications' && <PublicationsModal />}
       {isOpen && modalName === 'edit-overlay' && (
         <ModalLayout>
diff --git a/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx b/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx
index 5a04b6fa..9bf8267c 100644
--- a/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx
+++ b/src/components/Map/Drawer/ProjectInfoDrawer/ProjectInfoDrawer.component.tsx
@@ -1,7 +1,7 @@
 import { apiPath } from '@/redux/apiPath';
 import { useAppDispatch } from '@/redux/hooks/useAppDispatch';
 import { useAppSelector } from '@/redux/hooks/useAppSelector';
-import { openPublicationsModal } from '@/redux/modal/modal.slice';
+import { openLicenseModal, openPublicationsModal } from '@/redux/modal/modal.slice';
 import { mainMapModelDescriptionSelector } from '@/redux/models/models.selectors';
 import {
   diseaseLinkSelector,
@@ -9,6 +9,7 @@ import {
   organismLinkSelector,
   organismNameSelector,
   projectNameSelector,
+  projectSelector,
   versionSelector,
 } from '@/redux/project/project.selectors';
 import { DrawerHeading } from '@/shared/DrawerHeading';
@@ -23,11 +24,18 @@ export const ProjectInfoDrawer = (): JSX.Element => {
   const organismLink = useAppSelector(organismLinkSelector);
   const organismName = useAppSelector(organismNameSelector);
   const projectName = useAppSelector(projectNameSelector);
+  const project = useAppSelector(projectSelector).data;
   const version = useAppSelector(versionSelector);
   const description = useAppSelector(mainMapModelDescriptionSelector);
 
   const sourceDownloadLink = window.location.hostname + apiPath.getSourceFile();
 
+  let licenseName: string = '';
+  if (project) {
+    licenseName = project.license ? project.license.name : project.customLicenseName;
+  }
+  const licenseExists = licenseName !== '';
+
   useEffect(() => {
     // dispatch(getPublications());
   }, [dispatch]);
@@ -36,6 +44,10 @@ export const ProjectInfoDrawer = (): JSX.Element => {
     dispatch(openPublicationsModal());
   };
 
+  const onLicenseClick = (): void => {
+    dispatch(openLicenseModal(licenseName));
+  };
+
   return (
     <div data-testid="export-drawer" className="h-full max-h-full">
       <DrawerHeading title="Project info" />
@@ -76,6 +88,13 @@ export const ProjectInfoDrawer = (): JSX.Element => {
               </a>
             </li>
           )}
+          {licenseExists && (
+            <li className="mt-2 text-hyperlink-blue">
+              <button type="button" onClick={onLicenseClick} className="text-base font-semibold">
+                License: {licenseName}
+              </button>
+            </li>
+          )}
           {organismName && (
             <li className="mt-2 text-hyperlink-blue">
               <span className="text-black">Organism: </span>
diff --git a/src/models/licenseSchema.ts b/src/models/licenseSchema.ts
index 54d6f478..3111314e 100644
--- a/src/models/licenseSchema.ts
+++ b/src/models/licenseSchema.ts
@@ -3,5 +3,6 @@ import { z } from 'zod';
 export const licenseSchema = z.object({
   id: z.number().int().positive(),
   name: z.string(),
+  url: z.string(),
   content: z.string(),
 });
diff --git a/src/models/projectSchema.ts b/src/models/projectSchema.ts
index 5bfb3634..39862947 100644
--- a/src/models/projectSchema.ts
+++ b/src/models/projectSchema.ts
@@ -24,7 +24,7 @@ export const projectSchema = z.object({
   creationDate: z.string(),
   overviewImageViews: z.array(overviewImageView),
   topOverviewImage: overviewImageView.nullable(),
-  license: z.optional(licenseSchema),
-  customLicenseName: z.string().nullable(),
-  customLicenseUrl: z.string().nullable(),
+  license: z.optional(licenseSchema).nullable(),
+  customLicenseName: z.string(),
+  customLicenseUrl: z.string(),
 });
diff --git a/src/redux/modal/modal.reducers.ts b/src/redux/modal/modal.reducers.ts
index f2eecb87..4556c17c 100644
--- a/src/redux/modal/modal.reducers.ts
+++ b/src/redux/modal/modal.reducers.ts
@@ -103,3 +103,9 @@ export const openEditOverlayModalReducer = (
   state.modalTitle = action.payload.name;
   state.editOverlayState = action.payload;
 };
+
+export const openLicenseModalReducer = (state: ModalState, action: PayloadAction<string>): void => {
+  state.isOpen = true;
+  state.modalName = 'license';
+  state.modalTitle = `License: ${action.payload}`;
+};
diff --git a/src/redux/modal/modal.slice.ts b/src/redux/modal/modal.slice.ts
index 33263ed3..3e945e4a 100644
--- a/src/redux/modal/modal.slice.ts
+++ b/src/redux/modal/modal.slice.ts
@@ -14,6 +14,7 @@ import {
   openErrorReportModalReducer,
   openAccessDeniedModalReducer,
   openSelectProjectModalReducer,
+  openLicenseModalReducer,
 } from './modal.reducers';
 
 const modalSlice = createSlice({
@@ -33,6 +34,7 @@ const modalSlice = createSlice({
     openErrorReportModal: openErrorReportModalReducer,
     openAccessDeniedModal: openAccessDeniedModalReducer,
     openSelectProjectModal: openSelectProjectModalReducer,
+    openLicenseModal: openLicenseModalReducer,
   },
 });
 
@@ -50,6 +52,7 @@ export const {
   openErrorReportModal,
   openAccessDeniedModal,
   openSelectProjectModal,
+  openLicenseModal,
 } = modalSlice.actions;
 
 export default modalSlice.reducer;
diff --git a/src/types/modal.ts b/src/types/modal.ts
index 867b764c..1030c46b 100644
--- a/src/types/modal.ts
+++ b/src/types/modal.ts
@@ -4,6 +4,7 @@ export type ModalName =
   | 'overview-images'
   | 'mol-art'
   | 'login'
+  | 'license'
   | 'publications'
   | 'edit-overlay'
   | 'error-report'
-- 
GitLab