Skip to content

Commit

Permalink
Merge pull request #607 from SynBioHub/addeditdeletesource
Browse files Browse the repository at this point in the history
added fix for issue for chris manage submissions crashing, added code…
  • Loading branch information
cjmyers authored Jan 13, 2024
2 parents 97d7367 + 65528de commit fd15b37
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 101 deletions.
159 changes: 102 additions & 57 deletions frontend/components/Viewing/MetadataInfo.js
Original file line number Diff line number Diff line change
@@ -1,53 +1,100 @@
import React, { useState } from 'react';
import Link from 'next/link';

import styles from '../../styles/view.module.css';
import { useSelector } from 'react-redux';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faPlus } from '@fortawesome/free-solid-svg-icons';
import RenderIcon from './PageJSON/Rendering/RenderIcon';

import styles from '../../styles/view.module.css';
import { useTheme } from '../Admin/Theme';
import React, { useState } from 'react';
import axios from 'axios';
import getConfig from "next/config";

/**
* Component container for displaying metadata information about the object.
*
* @param {Any} properties Information from the parent component.
*/
export default function MetadataInfo({ title, link, label, icon, specific }) {
//If the metadata doesn't contain the title nothing should be rendered.
if (!title || (Array.isArray(title) && title.length === 0)) {
return null;
}
const { theme, loading } = useTheme();
import { getAfterThirdSlash } from './ViewHeader';

const { publicRuntimeConfig } = getConfig();

export default function MetadataInfo({ title, link, label, icon, specific, uri }) {
console.log(label);
const { theme } = useTheme();
const [isHovered, setIsHovered] = useState(false);
const [isEditingSource, setIsEditingSource] = useState(false);
const [newSource, setNewSource] = useState('');
const token = useSelector(state => state.user.token);

const hoverStyle = {
backgroundColor: isHovered ? (theme?.hoverColor || '#00A1E4') : (theme?.themeParameters?.[0]?.value || styles.infoheader.backgroundColor)
};
if (label === "Source" || label === "Generated By") {
if (typeof title === 'string') {
const tempTitle = title;
const parts = title.split('/');
if (parts.length >= 2) {
const lastPart = parts[parts.length - 1];

if (/^1(\.0+)*$/.test(lastPart)) {
title = parts[parts.length - 2];
} else {
const delimiters = ['#', '%', '/'];
const lastPartSegments = lastPart.split(new RegExp(`[${delimiters.join('')}]`));
const handleAddSource = () => {
const objectUriParts = getAfterThirdSlash(uri);
const objectUri = `${publicRuntimeConfig.backend}/${objectUriParts}`;
const editedText = newSource;
console.log(newSource);
console.log(objectUri);

title = lastPartSegments.pop();
}
}
if(title === "")
{
title = tempTitle;
axios.post(`${objectUri}/add/wasDerivedFrom`, {
object: editedText
}, {
headers: {
"Accept": "text/plain; charset=UTF-8",
"X-authorization": token
}
}
})
.then(response => {
// Handle response here
// Refresh the page after successful update
window.location.reload();
})
.catch(error => {
// Handle error here
console.error('Error adding source:', error);
});
};

// Rendered label with plus icon
const renderedLabel = (
<div className={styles.infolabel}>
{label}
{(label === "Source") && (
<>
<span style={{ marginRight: '0.5rem' }}></span> {/* Add space */}
<FontAwesomeIcon
icon={faPlus}
onClick={() => setIsEditingSource(true)}
className={styles.plusIcon}
/>
</>
)}
</div>
);

// Check if title is a string and contains commas, then split into an array
const sources = typeof title === 'string' && title.includes(',') ? title.split(',').map(s => s.trim()) : [title];

// Rendered content for the title with each source as a hyperlink
const renderedTitle = (
<div className={specific ? styles.infotitlegeneric : styles.infotitle}>
<table>
<tbody>
{typeof title === 'string' && title.includes(',')
? title.split(',').map((source, index) => (
<tr key={index}>
<td>
<Link href={source.trim()}>
<a target="_blank">{source.trim()}</a>
</Link>
</td>
</tr>
))
: <tr><td>{title}</td></tr>
}
</tbody>
</table>
</div>
);

}

// Rendered section including the header and the title (with or without link)
const renderedSection = (
<div className={styles.info}>
<div
Expand All @@ -58,34 +105,32 @@ export default function MetadataInfo({ title, link, label, icon, specific }) {
>
<div className={styles.infoiconcontainer}>
{!specific ? (
<FontAwesomeIcon
icon={icon}
size="1x"
className={styles.infoicon}
/>
<FontAwesomeIcon icon={icon} size="1x" className={styles.infoicon} />
) : (
<RenderIcon icon={icon} color="#fff" style={styles.infoicon} />
)}
</div>
<div className={styles.infolabel}>{label}</div>
</div>
<div className={specific ? styles.infotitlegeneric : styles.infotitle}>
<table>
<tbody>
{/* Check if 'title' contains table rows and render them directly here */}
{Array.isArray(title) ? title : <tr><td>{title}</td></tr>}
</tbody>
</table>
{renderedLabel}
</div>


{isEditingSource ? (
<div>
<input
type="text"
value={newSource}
onChange={(e) => setNewSource(e.target.value)}
/>
<button type="button" onClick={handleAddSource}>Save</button>
<button type="button" onClick={() => {
setIsEditingSource(false);
setNewSource(''); // Optional: Clear the input if needed
}}>Cancel</button>
</div>
) : link ? (
<Link href={link}><a target="_blank">{renderedTitle}</a></Link>
) : renderedTitle}
</div>

);
if (link) {
return (
<Link href={link}>
<a target="_blank">{renderedSection}</a>
</Link>
);
} else return renderedSection;

return renderedSection;
}
9 changes: 5 additions & 4 deletions frontend/components/Viewing/Shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import MasterJSON from './PageJSON/MasterJSON';
// import { useDispatch } from 'react-redux';

export default function Shell(properties) {
console.log(properties);
const plugins = properties.plugins;
const metadata = properties.metadata;

const json = MasterJSON[properties.metadata.type];
const json = MasterJSON[properties.metadata.types];

// const [content, setContent] = useState();

Expand Down Expand Up @@ -51,12 +52,12 @@ export default function Shell(properties) {
name={metadata.name}
displayId={metadata.displayId}
description={metadata.description}
type={metadata.type}
type={metadata.types}
uri={metadata.persistentIdentity}
/>
<div className={styles.sections}>
<div>
No structure defined for type "{properties.metadata.type}"
No structure defined for type "{properties.metadata.types}"
</div>
</div>
</div>
Expand All @@ -79,7 +80,7 @@ export default function Shell(properties) {
name={metadata.name}
displayId={metadata.displayId}
description={metadata.description}
type={metadata.type}
type={metadata.types}
uri={`${metadata.persistentIdentity}/${metadata.version}`}
/>
<div className={styles.sections}>
Expand Down
56 changes: 34 additions & 22 deletions frontend/components/Viewing/SidePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ const { publicRuntimeConfig } = getConfig();
* @param {Any} properties Information from the parent component.
*/
export default function SidePanel({ metadata, type, json, uri, plugins }) {

console.log(metadata);
console.log(plugins);
const [translation, setTranslation] = useState(0);
const [processedUrl, setProcessedUrl] = useState({ original: uri });
const dateCreated = metadata.created.replace('T', ' ').replace('Z', '');
const dateModified = metadata.modified.replace('T', ' ').replace('Z', '');
const dateCreated = metadata.createdDates.split(", ")[0].replace('T', ' ').replace('Z', '');
const dateModified = metadata.modifiedDates.replace('T', ' ').replace('Z', '');

const token = useSelector(state => state.user.token);
const dispatch = useDispatch();
Expand Down Expand Up @@ -105,7 +108,7 @@ export default function SidePanel({ metadata, type, json, uri, plugins }) {
}}
>
<SidePanelTools
creator={metadata.creator}
creator={metadata.creators}
type={type}
displayId={metadata.displayId}
name={metadata.name}
Expand All @@ -121,20 +124,22 @@ export default function SidePanel({ metadata, type, json, uri, plugins }) {
<MetadataInfo
icon={faQuoteLeft}
label="Source"
title={metadata.wasDerivedFrom}
link={metadata.wasDerivedFrom}
title={metadata.wasDerivedFroms}
link={metadata.wasDerivedFroms}
uri={uri}
/>
<MetadataInfo
icon={faHammer}
label="Generated By"
title={metadata.wasGeneratedBy}
link={metadata.wasGeneratedBy}
title={metadata.wasGeneratedBys}
link={metadata.wasGeneratedBys}
uri={uri}
/>
<MetadataInfo
icon={faUserEdit}
label="Creator"
title={metadata.creator}
link={`/user/${metadata.creator.replace(' ', '')}`}
title={metadata.creators}
link={`/user/${metadata.creators.replace(' ', '')}`}
/>
<MetadataInfo
icon={faCalendarPlus}
Expand Down Expand Up @@ -172,31 +177,38 @@ export default function SidePanel({ metadata, type, json, uri, plugins }) {
function getPagesInfo(type, json, plugins) {
if (json === null) return { type: type, order: [] };
if (localStorage.getItem(type) === null) {
const order = json.pages
const order = json.pages;

for (let plugin of plugins.rendering) {
order.push('PLUGIN: ' + plugin.name)
if (plugins && plugins.rendering) {
for (let plugin of plugins.rendering) {
order.push('PLUGIN: ' + plugin.name);
}
}

return { type: type, order: order };
}

const order = JSON.parse(localStorage.getItem(type)).order
const order = JSON.parse(localStorage.getItem(type)).order;

const orderUpdated = order.filter(page => {
if (page.startsWith('PLUGIN: ')) {
for (let plugin of plugins.rendering) {
if (plugin.name === page.substring(8, page.length)) {
return true;
if (plugins && plugins.rendering) {
for (let plugin of plugins.rendering) {
if (plugin.name === page.substring(8, page.length)) {
return true;
}
}
}
return false
return false;
}
return true
})
for (let plugin of plugins.rendering) {
if (!orderUpdated.includes('PLUGIN: ' + plugin.name)) {
orderUpdated.push('PLUGIN: ' + plugin.name)
return true;
});

if (plugins && plugins.rendering) {
for (let plugin of plugins.rendering) {
if (!orderUpdated.includes('PLUGIN: ' + plugin.name)) {
orderUpdated.push('PLUGIN: ' + plugin.name);
}
}
}

Expand Down
12 changes: 6 additions & 6 deletions frontend/components/Viewing/ViewHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import getConfig from "next/config";
const { publicRuntimeConfig } = getConfig();

export default function ViewHeader(properties) {
console.log(properties);
var displayTitle = properties.type;
if (properties.type.includes('#')) {
displayTitle = properties.type.split('#')[1];
Expand All @@ -39,12 +40,6 @@ export default function ViewHeader(properties) {
}
};

function getAfterThirdSlash(uri) {
const parts = uri.split('/');
const afterThirdSlashParts = parts.slice(3);
return afterThirdSlashParts.join('/');
}

const objectUriParts = getAfterThirdSlash(properties.uri);

const token = useSelector(state => state.user.token);
Expand Down Expand Up @@ -173,4 +168,9 @@ export default function ViewHeader(properties) {
);
}

export function getAfterThirdSlash(uri) {
const parts = uri.split('/');
const afterThirdSlashParts = parts.slice(3);
return afterThirdSlashParts.join('/');
}

9 changes: 7 additions & 2 deletions frontend/pages/[...view].js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ export default function View({ data, error }) {
);
}, [metadata, token]);

console.log(metadata);

// validate part
if (!url || !metadata)
return (
Expand All @@ -51,7 +53,7 @@ export default function View({ data, error }) {
<Shell
plugins={data}
metadata={metadata[0]}
type={getType(metadata[0].type)}
type={getType(metadata[0].types)}
uri={uri}
/>
</TopLevel>
Expand Down Expand Up @@ -93,5 +95,8 @@ export async function getServerSideProps() {
}

const getType = type => {
return type.replace('http://sbols.org/v2#', '');
if (type) {
return type.replace('http://sbols.org/v2#', '');
}
return type;
};
Loading

0 comments on commit fd15b37

Please sign in to comment.