Skip to content

Commit

Permalink
Merge pull request #1495 from hubmapconsortium/collectionPublish
Browse files Browse the repository at this point in the history
Adds is admin endpoint to ingest api Service, adds Publish Feature to…
  • Loading branch information
yuanzhou authored Oct 23, 2024
2 parents 1031ec0 + b5a32fc commit 14dd971
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 16 deletions.
12 changes: 12 additions & 0 deletions src/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -909,4 +909,16 @@ svg.invalid {
padding: 5px;
border-radius: 5px;
font-size: inherit!important;
}

.title_badge{
align-items: center;
color: rgb(42, 111, 184);
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
font-size: 0.95rem;
font-weight: 300;
gap: 4px;
line-height: 1.5;
}
11 changes: 11 additions & 0 deletions src/src/assets/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -844,4 +844,15 @@ svg.invalid{
padding: 5px;
border-radius: 5px;
font-size: inherit!important;
}
.title_badge{
align-items: center;
color: rgb(42, 111, 184);
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
font-size: 0.95rem;
font-weight: 300;
gap: 4px;
line-height: 1.5;
}
75 changes: 65 additions & 10 deletions src/src/components/collections/collections.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "../../App.css";
import SearchComponent from "../search/SearchComponent";
import {COLUMN_DEF_MIXED,COLUMN_DEF_MIXED_SM} from "../search/table_constants";
import { entity_api_get_entity,entity_api_create_entity, entity_api_update_entity} from '../../service/entity_api';
import {ingest_api_publish_collection,ingest_api_user_admin} from '../../service/ingest_api';
import { getPublishStatusColor } from "../../utils/badgeClasses";
import { generateDisplaySubtypeSimple_UBKG } from "../../utils/display_subtypes";
import Papa from 'papaparse';
Expand All @@ -15,20 +16,20 @@ import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import GroupModal from "../uuid/groupModal";

import LoadingButton from '@mui/lab/LoadingButton';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import {DataGrid,GridToolbar} from "@mui/x-data-grid";

import {ErrBox} from "../../utils/ui_elements";
import Alert from '@mui/material/Alert';
import Collapse from '@mui/material/Collapse';
import LinearProgress from '@material-ui/core/LinearProgress';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQuestionCircle, faSpinner, faTrash, faCheck,faExclamationTriangle, faPlus,faPenToSquare } from "@fortawesome/free-solid-svg-icons";
import { faQuestionCircle, faUpRightFromSquare, faSpinner, faTrash, faCheck,faExclamationTriangle, faPlus,faPenToSquare } from "@fortawesome/free-solid-svg-icons";
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import CancelPresentationIcon from '@mui/icons-material/CancelPresentation';
Expand All @@ -48,20 +49,29 @@ export function CollectionForm (props){
var [associatedEntities, setassociatedEntities] = useState([]);
var [associatedEntitiesInitial, setassociatedEntitiesInitial] = useState([]);
var [selectedSources, setSelectedSources] = useState([]);
var [publishing, setPublishing] = useState(false);
var [fileDetails, setFileDetails] = useState();
var [buttonState, setButtonState] = useState('');
var [warningOpen, setWarningOpen] = React.useState(false);
var [openGroupModal, setOpenGroupModal] = useState(false


);
var [openGroupModal, setOpenGroupModal] = useState(false);
var [lookupShow, setLookupShow] = useState(false);
var [loadingDatasets, setLoadingDatasets] = useState(true);
var [hideUUIDList, setHideUUIDList] = useState(true);
var [loadUUIDList, setLoadUUIDList] = useState(false);
var [validatingSubmitForm, setValidatingSubmitForm] = useState(false);
var [entityInfo, setEntityInfo] = useState();
var [userAdmin, setUserAdmin] = useState(false);
var [pageError, setPageError] = useState("");
// var [publishError, setPublishError] = useState({
// status:"",
// message:"",
// });
// @TODO: See what we can globalize/memoize/notize here
var [errorHandler, setErrorHandler] = useState({
status: "",
message: "",
isError: null
});
var [formWarnings, setFormWarnings] = useState({
bulk_dataset_uuids:""
});
Expand All @@ -87,6 +97,18 @@ export function CollectionForm (props){
var [datatypeList] = useState(props.dtl_all);
var [editingCollection] = useState(props.editingCollection);


useEffect(() => {
ingest_api_user_admin(JSON.parse(localStorage.getItem("info")).groups_token)
.then((results) => {
console.debug('%c◉ ADMINCHECK ', 'color:#3F007b', results);
setUserAdmin(results)
})
.catch((err) => {
console.debug('%c⭗', 'color:#1f005d', "ingest_api_user_admin ERR", err );
})
}, []);

useEffect(() => {
if (editingCollection) {
setassociatedEntities([])
Expand Down Expand Up @@ -456,6 +478,27 @@ export function CollectionForm (props){
});
}

const handlePublish = () => {
setPublishing(true)
ingest_api_publish_collection(props.authToken,editingCollection.uuid)
.then((response) => {
if(response.status === 200){
console.debug('%c◉ Good ingest_api_publish_collection ', 'color:#00ff7b', response);
props.onProcessed(response.results);
}else{
console.debug('%c◉ ingest_api_publish_collection Bad result', 'color:#ff337b', response);
setPublishing(false)
let authMessage = response.status === 401 ? "User must be Authorized" : response.results.error.toString();
setPageError(response.status + " | " + authMessage);
}
})
.catch((error) => {
console.debug('%c⭗ handlePublishErr Broken Result', 'color:#ff005d', error);
setPageError(error.status + " | " + error.message);
setPublishing(false);
});
}

const handleUpdate = (formSubmit) => {
// Need to only pass what's changed now
console.debug('%c◉ formSubmit ', 'color:#00ff7b',formSubmit );
Expand Down Expand Up @@ -588,7 +631,6 @@ export function CollectionForm (props){
</>
)
}

var renderAssociationTable = () => {
var hiddenFields = [];
var uniqueTypes = new Set(associatedEntities.map(obj => obj.entity_type.toLowerCase()));
Expand Down Expand Up @@ -681,6 +723,11 @@ export function CollectionForm (props){
{!props.newForm && (
<h5>{props.editingCollection.title}</h5>
)}
{editingCollection && editingCollection.doi_url && (
<h4 className="title_badge">
doi: <a href={editingCollection.doi_url} target='_blank' >{editingCollection.doi_url} </a><FontAwesomeIcon icon={faUpRightFromSquare}/>
</h4>
)}
</div>
</div>

Expand Down Expand Up @@ -876,6 +923,7 @@ export function CollectionForm (props){
value={formValues.title}
/>
</FormControl>

<FormControl>
<TextField
label="Description"
Expand All @@ -891,15 +939,13 @@ export function CollectionForm (props){
value={formValues.description}
/>
</FormControl>

<FormControl>
<Typography sx={{ color: 'rgba(0, 0, 0.2, 0.6)' }}>
Contributors
</Typography>
{formValues.contributors && formValues.contributors.length > 0 && (
<>{renderContribTable()} </>
)}

<div className="text-right">
<Typography variant='caption'>Please refer to the <a href="https://hubmapconsortium.github.io/ingest-validation-tools/contributors/current/" target='_blank'>contributor file schema information</a>, and this <a href='https://raw.githubusercontent.com/hubmapconsortium/dataset-metadata-spreadsheet/main/contributors/latest/contributors.tsv' target='_blank'>Example TSV File</a> </Typography>
</div>
Expand All @@ -926,6 +972,15 @@ export function CollectionForm (props){

<div className="row">
<div className="buttonWrapRight">
{userAdmin === true && (editingCollection && !editingCollection.doi_url) && (
<LoadingButton
loading={publishing}
onClick={() => handlePublish()}
variant="contained">
Publish
</LoadingButton>
)}

<Button
variant="contained"
onClick={() => handleSubmit()}
Expand Down
71 changes: 66 additions & 5 deletions src/src/components/collections/epicollections.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "../../App.css";
import SearchComponent from "../search/SearchComponent";
import {COLUMN_DEF_MIXED,COLUMN_DEF_MIXED_SM,COLUMN_DEF_COLLECTION} from "../search/table_constants";
import { entity_api_get_entity,entity_api_create_entity, entity_api_update_entity} from '../../service/entity_api';
import {ingest_api_publish_collection,ingest_api_user_admin} from '../../service/ingest_api';
import { getPublishStatusColor } from "../../utils/badgeClasses";
import { generateDisplaySubtypeSimple_UBKG } from "../../utils/display_subtypes";
import Papa from 'papaparse';
Expand All @@ -15,6 +16,8 @@ import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import GroupModal from "../uuid/groupModal";
import LoadingButton from '@mui/lab/LoadingButton';
import {ErrBox} from "../../utils/ui_elements";

import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
Expand All @@ -28,7 +31,7 @@ import Alert from '@mui/material/Alert';
import Collapse from '@mui/material/Collapse';
import LinearProgress from '@material-ui/core/LinearProgress';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faQuestionCircle, faSpinner, faTrash, faExclamationTriangle, faCheck, faPlus,faPenToSquare } from "@fortawesome/free-solid-svg-icons";
import { faQuestionCircle, faSpinner, faUpRightFromSquare, faTrash, faExclamationTriangle, faCheck, faPlus,faPenToSquare } from "@fortawesome/free-solid-svg-icons";
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import CancelPresentationIcon from '@mui/icons-material/CancelPresentation';
Expand All @@ -51,17 +54,26 @@ export function EPICollectionForm (props){
var [fileDetails, setFileDetails] = useState();
var [buttonState, setButtonState] = useState('');
var [warningOpen, setWarningOpen] = React.useState(false);
var [openGroupModal, setOpenGroupModal] = useState(false


);
var [openGroupModal, setOpenGroupModal] = useState(false );
var [lookupShow, setLookupShow] = useState(false);
var [loadingDatasets, setLoadingDatasets] = useState(true);
var [hideUUIDList, setHideUUIDList] = useState(true);
var [loadUUIDList, setLoadUUIDList] = useState(false);
var [validatingSubmitForm, setValidatingSubmitForm] = useState(false);
var [entityInfo, setEntityInfo] = useState();
var [userAdmin, setUserAdmin] = useState(false);
var [pageError, setPageError] = useState("");
var [publishing, setPublishing] = useState(false);
// var [publishError, setPublishError] = useState({
// status:"",
// message:"",
// });
// @TODO: See what we can globalize/memoize/notize here
var [errorHandler, setErrorHandler] = useState({
status: "",
message: "",
isError: null
});
var [formWarnings, setFormWarnings] = useState({
bulk_dataset_uuids:""
});
Expand All @@ -87,6 +99,18 @@ export function EPICollectionForm (props){
var [datatypeList] = useState(props.dtl_all);
var [editingCollection] = useState(props.editingCollection);


useEffect(() => {
ingest_api_user_admin(JSON.parse(localStorage.getItem("info")).groups_token)
.then((results) => {
console.debug('%c◉ ADMINCHECK ', 'color:#3F007b', results);
setUserAdmin(results)
})
.catch((err) => {
console.debug('%c⭗', 'color:#1f005d', "ingest_api_user_admin ERR", err );
})
}, []);

useEffect(() => {
if (editingCollection) {
setassociatedEntities([])
Expand Down Expand Up @@ -462,6 +486,30 @@ export function EPICollectionForm (props){

});
}


const handlePublish = () => {
setPublishing(true)
ingest_api_publish_collection(props.authToken,editingCollection.uuid)
.then((response) => {
console.debug('%c◉ PUBLISHED ', 'color:#00ff7b', );
// props.onProcessed(response);
if(response.status === 200){
console.debug('%c◉ Good ingest_api_publish_collection ', 'color:#00ff7b', response);
props.onProcessed(response.results);
}else{
console.debug('%c◉ ingest_api_publish_collection Bad result', 'color:#ff337b', response);
setPublishing(false)
let authMessage = response.status === 401 ? "User must be Authorized" : response.results.error.toString();
setPageError(response.status + " | " + authMessage);
}
})
.catch((error) => {
console.debug('%c⭗ handlePublishErr Broken Result', 'color:#ff005d', error);
setPageError(error.status + " | " + error.message);
setPublishing(false);
});
}

const handleUpdate = (formSubmit) => {
// Need to only pass what's changed now
Expand Down Expand Up @@ -695,6 +743,11 @@ export function EPICollectionForm (props){
{!props.newForm && (
<h5>{props.editingCollection.title}</h5>
)}
{editingCollection && editingCollection.doi_url && (
<h4 className="title_badge">
doi: <a href={editingCollection.doi_url} target='_blank' >{editingCollection.doi_url} </a><FontAwesomeIcon icon={faUpRightFromSquare}/>
</h4>
)}
</div>
</div>

Expand Down Expand Up @@ -940,6 +993,14 @@ export function EPICollectionForm (props){

<div className="row">
<div className="buttonWrapRight">
{userAdmin === true && (editingCollection && !editingCollection.doi_url) && (
<LoadingButton
loading={publishing}
onClick={() => handlePublish()}
variant="contained">
Publish
</LoadingButton>
)}
<Button
variant="contained"
onClick={() => handleSubmit()}
Expand Down
Loading

0 comments on commit 14dd971

Please sign in to comment.