Skip to content

Commit

Permalink
Merge pull request #618 from SynBioHub/federate
Browse files Browse the repository at this point in the history
Federate
  • Loading branch information
danielfang97 authored Mar 21, 2024
2 parents e29b11b + 896fcdb commit 46d1da7
Show file tree
Hide file tree
Showing 9 changed files with 216 additions and 38 deletions.
70 changes: 70 additions & 0 deletions frontend/components/Admin/Registries.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default function Registries() {

return (
<div className={styles.plugintable}>
<RegistryActions />
<Table
data={registries ? registries.registries : undefined}
loading={loading}
Expand Down Expand Up @@ -179,6 +180,75 @@ function RegistryDisplay(properties) {
);
}

function RegistryActions() {
const [inputOne, setInputOne] = useState('');
const [inputTwo, setInputTwo] = useState('');
const token = useSelector(state => state.user.token);
const dispatch = useDispatch();

const url = `${publicRuntimeConfig.backend}/admin/deleteRegistry`;

const handleFederate = async () => {
try {
await axios.post(`${publicRuntimeConfig.backend}/admin/federate`, {
administratorEmail: inputTwo,
webOfRegistries: inputOne
}, {
headers: {
'Accept': 'application/json',
'X-authorization': token
}
});
// Add additional logic here if needed after successful POST
} catch (error) {
console.error('Error with federate: ', error);
// Handle errors here
}
};

const handleRetrieve = async () => {
try {
const response = await axios.post(`${publicRuntimeConfig.backend}/admin/retrieveFromWebOfRegistries`, {}, {
headers: {
'Accept': 'application/json',
'X-authorization': token
}
});

if (response.data && Array.isArray(response.data.registries)) {
// Assuming 'registries' is the correct key in response and it's an array of registry objects
mutate([
`${publicRuntimeConfig.backend}/admin/registries`,
token,
dispatch
]);
}
} catch (error) {
console.error('Error with retrieving from Web Of Registries: ', error);
// Handle errors here
}
};

return (
<div className={styles.registryActionsContainer}>
<input
type="text"
value={inputOne}
onChange={(e) => setInputOne(e.target.value)}
placeholder="Web of Registries URL"
/>
<input
type="text"
value={inputTwo}
onChange={(e) => setInputTwo(e.target.value)}
placeholder="Administrator Email"
/>
<button onClick={handleFederate}>Federate</button>
<button onClick={handleRetrieve}>Retrieve</button>
</div>
);
}

const deleteRegistry = async (uri, token, dispatch) => {
const url = `${publicRuntimeConfig.backend}/admin/deleteRegistry`;
const headers = {
Expand Down
26 changes: 17 additions & 9 deletions frontend/components/Error/ErrorClearer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ export default function ErrorClearer({ index, setIndex, size }) {
const router = useRouter();
if (size === 'relog') {
return (
<div
className={styles.clearButton}
onClick={() => {
dispatch(clearErrors());
dispatch(logoutUser());
router.push('/');
}}
>
Return to Login
<div>
<div
className={styles.clearAllButton}
onClick={() => dispatch(clearErrors())}
>
Clear All
</div>
<div
className={styles.clearButton}
onClick={() => {
dispatch(clearErrors());
dispatch(logoutUser());
router.push('/');
}}
>
Return to Login
</div>
</div>
);
}
Expand Down
84 changes: 65 additions & 19 deletions frontend/components/Viewing/Collection/Members.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import loadTemplate from '../../../sparql/tools/loadTemplate';
import { shortName } from '../../../namespace/namespace';
import lookupRole from '../../../namespace/lookupRole';
import Link from 'next/link';
import { addError } from '../../../redux/actions';
import { addError, logoutUser } from '../../../redux/actions';
import { processUrl, processUrlReverse } from '../../Admin/Registries';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTrash, faUnlink } from '@fortawesome/free-solid-svg-icons';
Expand Down Expand Up @@ -95,18 +95,29 @@ export default function Members(properties) {
? useMembers(query, parameters, token, dispatch)
: useMembers(query, parameters, dispatch);

const { count: totalMemberCount } = useCount(
const { count: totalMemberCount } = privateGraph
? useCount(
CountMembersTotal,
{ ...parameters, search: '' },
privateGraph ? token : undefined, // Pass token only if privateGraph is true
dispatch
);
)
: useCount(
CountMembersTotal,
{ ...parameters, search: '' },
dispatch);

const { count: currentMemberCount } = useCount(
const { count: currentMemberCount } = privateGraph
? useCount(
searchQuery ? CountMembersTotal : CountMembers,
parameters,
privateGraph ? token : undefined, // Pass token only if privateGraph is true
dispatch
)
: useCount(
searchQuery ? CountMembersTotal : CountMembers,
parameters,
dispatch
);

useEffect(() => {
Expand All @@ -116,11 +127,17 @@ export default function Members(properties) {
}
}, [properties.refreshMembers, mutate]);

const { filters } = useFilters(
const { filters } = privateGraph
? useFilters(
getTypesRoles,
{ uri: properties.uri },
token,
dispatch
)
: useFilters(
getTypesRoles,
{ uri: properties.uri },
dispatch
);

const outOfBoundsHandle = offset => {
Expand Down Expand Up @@ -245,9 +262,10 @@ function FilterHeader(properties) {

function MemberTable(properties) {
const [processedMembers, setProcessedMembers] = useState([]);

const isPublicCollection = properties.uri.includes("/public/");
const token = useSelector(state => state.user.token);
const dispatch = useDispatch();

useEffect(() => {
async function processMembers() {
if (properties.members) {
Expand Down Expand Up @@ -278,6 +296,12 @@ function MemberTable(properties) {
Number(properties.totalMembers).toLocaleString() +
')';
}

const headers = ['Name', 'Identifier', 'Type', 'Description'];
if (!isPublicCollection) {
headers.push('Remove');
}

return (
<Table
data={processedMembers}
Expand All @@ -290,7 +314,7 @@ function MemberTable(properties) {
customSearch={properties.customSearch}
hideFilter={true}
searchable={[]}
headers={['Name', 'Identifier', 'Type', 'Description', 'Remove']}
headers={headers}
sortOptions={sortOptions}
sortMethods={sortMethods}
defaultSortOption={properties.defaultSortOption}
Expand Down Expand Up @@ -319,7 +343,7 @@ function MemberTable(properties) {
}
};



const handleDelete = async (member) => {
if (member.uri && window.confirm("Would you like to remove this item from the collection?")) {
Expand Down Expand Up @@ -375,9 +399,11 @@ function MemberTable(properties) {
</td>
<td>{getType(member)}</td>
<td>{member.description}</td>
<td onClick={() => handleIconClick(member)}>
<FontAwesomeIcon icon={icon} />
</td>
{!isPublicCollection && (
<td onClick={() => handleIconClick(member)}>
<FontAwesomeIcon icon={icon} />
</td>
)}
</tr>
);
}}
Expand Down Expand Up @@ -431,7 +457,13 @@ const createUrl = (query, options) => {

const useCount = (query, options, token, dispatch) => {
const url = createUrl(query, options, token);
const { data, error } = useSWR([url, token, dispatch], fetcher);
let data, error;

if (typeof token === 'string') {
({ data, error } = useSWR([url, token, dispatch], fetcher));
} else {
({ data, error } = useSWR([url, dispatch], fetcher));
}

let processedData = data ? processResults(data)[0].count : undefined;
return {
Expand All @@ -441,10 +473,15 @@ const useCount = (query, options, token, dispatch) => {

const useMembers = (query, options, token, dispatch) => {
const url = createUrl(query, options);
const { data, error, mutate } = useSWR([url, token, dispatch], fetcher);
let data, error, mutate;

let processedData = data ? processResults(data) : undefined;
if (typeof token === 'string') {
({ data, error, mutate } = useSWR([url, token, dispatch], fetcher));
} else {
({ data, error, mutate } = useSWR([url, dispatch], fetcher));
}

let processedData = data ? processResults(data) : undefined;
return {
members: processedData,
mutate
Expand All @@ -453,12 +490,20 @@ const useMembers = (query, options, token, dispatch) => {

const useFilters = (query, options, token, dispatch) => {
const url = createUrl(query, options);
const { data, error } = useSWR([url, token, dispatch], fetcher);

let data, error, mutate;

if (typeof token === 'string') {
({ data, error, mutate } = useSWR([url, token, dispatch], fetcher));
} else {
({ data, error, mutate } = useSWR([url, dispatch], fetcher));
}

let processedData = data ? processResults(data) : undefined;

return {
filters: processedData
filters: processedData,
mutate
};
};

Expand All @@ -479,12 +524,13 @@ const fetcher = (url, token, dispatch) =>
// Check if the error is 401 Unauthorized or 400 Bad Request
if (error.response && (error.response.status === 401 || error.response.status === 400)) {
// Check if the user is logged in by looking for 'userToken' in local storage
console.log(localStorage);
console.log(error.response);
if (!localStorage.getItem('userToken')) {
console.log('Missing user token');
// User is not logged in, redirect to the login page
// window.location.href = '/login';
dispatch(logoutUser());
window.location.href = '/login';
} else {
console.error(error);
}
}

Expand Down
9 changes: 9 additions & 0 deletions frontend/components/Viewing/ViewHeader.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import React, { useRef } from 'react';
import { useSelector } from 'react-redux';
import { useState } from 'react';

import SearchHeader from '../Search/SearchHeader/SearchHeader';
import ResultTable from '../Search/StandardSearch/ResultTable/ResultTable';

import axios from 'axios';

import Link from 'next/link';
Expand Down Expand Up @@ -71,6 +74,12 @@ export default function ViewHeader(properties) {
})
.then(response => {
console.log(response.data);
return (
<div className={styles.searchContent}>
<SearchHeader selected="Standard Search" />
<ResultTable count={response.data.count} data={response.data} />
</div>
)
})
.catch(error => {
console.error('Error fetching twins: ', error);
Expand Down
Loading

0 comments on commit 46d1da7

Please sign in to comment.