Skip to content

Commit

Permalink
Issue 136 (#156) - Resubmit function
Browse files Browse the repository at this point in the history
* resubmit button added

* rough backend done

* resubmit form set

* resubmit works from statusTab

* resubmit working for pending exps

* sorting grants table

* Dockerfiles update

* fixing submit test

* fixing submitter issues
  • Loading branch information
tomlebl authored Nov 6, 2024
1 parent 0d5fac6 commit 4168385
Show file tree
Hide file tree
Showing 24 changed files with 676 additions and 300 deletions.
2 changes: 1 addition & 1 deletion Dockerfile.api
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:20.11.0-slim
FROM node:20.13.1-bookworm-slim

WORKDIR /app

Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.serv
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
FROM node:20.11.0-slim as frontend
FROM node:20.13.1-bookworm-slim as frontend

WORKDIR /app

COPY ./nomad-front-end/package.json .

RUN npm install --force
RUN npm install

COPY ./nomad-front-end .

Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.serv-tls
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
FROM node:20.11.0-slim as frontend
FROM node:20.13.1-bookworm-slim as frontend

WORKDIR /app

COPY ./nomad-front-end/package.json .

RUN npm install --force
RUN npm install

COPY ./nomad-front-end .

Expand Down
2 changes: 1 addition & 1 deletion nomad-front-end/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM node:20.11.0-slim
FROM node:20.13.1-bookworm-slim

WORKDIR /app

Expand Down
2 changes: 1 addition & 1 deletion nomad-front-end/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nomad-front-end",
"private": false,
"version": "3.5.3",
"version": "3.5.4-beta",
"type": "module",
"scripts": {
"start": "env-cmd -f ../env/frontend.env vite",
Expand Down
11 changes: 11 additions & 0 deletions nomad-front-end/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import Error404 from './components/Errors/Error404'
import Error403 from './components/Errors/Error403'
import Credits from './components/Credits/Credits'
import Reset from './containers/Reset/Reset'
import Resubmit from './containers/Resubmit/Resubmit'

const { Header, Sider, Content, Footer } = Layout

Expand Down Expand Up @@ -184,6 +185,16 @@ const App = props => {
)
}
/>
<Route
path='/resubmit'
element={
import.meta.env.VITE_BATCH_SUBMIT_ON === 'true' ? (
<Resubmit />
) : (
<Navigate to='/dashboard' />
)
}
/>
<Route
path='/search-experiment'
element={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const GrantsCostsTable = props => {
},
{
title: 'Description',
dataIndex: 'description'
dataIndex: 'description',
sorter: (a, b) => a.description.localeCompare(b.description)
},
{
title: 'Cost [£]',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
message,
Modal,
Checkbox,
Tooltip
Tooltip,
Popconfirm
} from 'antd'
import moment from 'moment'

Expand All @@ -23,6 +24,7 @@ import EditParamsModal from '../../Modals/EditParamsModal/EditPramsModal'
import nightIcon from '../../../assets/night-mode.svg'

import classes from './BookExperimentsForm.module.css'
import { all } from 'axios'

const { Option } = Select

Expand All @@ -45,9 +47,22 @@ const BookExperimentsForm = props => {
const [exptState, setExptState] = useState({})
const [totalExptState, setTotalExptState] = useState({})

const { inputData, allowanceData, fetchAllowance, token, accessLevel } = props
const { inputData, allowanceData, fetchAllowance, token, accessLevel, formValues } = props

const priorityAccess = accessLevel === 'user-a' || accessLevel === 'admin'
const resubmit = formValues

//This hook is used to cancel booked holders on the form component dismount
// It uses deleteHolders function in submit controller at the backend which has
// 120s timeout to allow for iconNMR to pickup submit file
useEffect(() => {
return () => {
props.cancelHolders(
token,
inputData.map(i => i.key)
)
}
}, [])

//Hook to create state for dynamic ExpNo part of form from inputData
//InputData gets updated every time new holder is booked
Expand All @@ -62,7 +77,7 @@ const BookExperimentsForm = props => {
} else {
newFormState.push({
key: i.key,
expCount: 1
expCount: resubmit ? i.expCount : 1
})
}
})
Expand All @@ -72,23 +87,56 @@ const BookExperimentsForm = props => {
if (instrIds.size !== 0) {
fetchAllowance(token, Array.from(instrIds))
}

//setting up form values and expTime if form used for resubmit
if (resubmit) {
form.setFieldsValue(formValues)
}

// formState can't be dependency as it gets updated in the hook. That would trigger loop.
// eslint-disable-next-line
}, [inputData])
}, [inputData, formValues])

//This hook creates initial totalExpT state with overhead time for each entry
useEffect(() => {
const newTotalExptState = { ...totalExptState }
if (allowanceData.length !== 0) {
formState.forEach(entry => {
const instrId = entry.key.split('-')[0]
const { overheadTime } = allowanceData.find(i => i.instrId === instrId)
if (!newTotalExptState[entry.key]) {
newTotalExptState[entry.key] = overheadTime
if (resubmit) {
const expTimeStateEntries = []
const totalExpTimeStateEntries = []

if (allowanceData.length > 0) {
for (let sampleKey in formValues) {
let expTimeSum = allowanceData[0].overheadTime
//selecting first element of allowanceData array works as
//only holders on one instrument can be selected for resubmit
for (let expNo in formValues[sampleKey].exps) {
expTimeStateEntries.push([
sampleKey + '#' + expNo,
formValues[sampleKey].exps[expNo].expTime
])
expTimeSum += moment
.duration(formValues[sampleKey].exps[expNo].expTime, 'HH:mm:ss')
.asSeconds()
}
totalExpTimeStateEntries.push([sampleKey, expTimeSum])
}
})
}

setExptState(Object.fromEntries(expTimeStateEntries))
setTotalExptState(Object.fromEntries(totalExpTimeStateEntries))
} else {
const newTotalExptState = { ...totalExptState }
if (allowanceData.length !== 0 && !resubmit) {
formState.forEach(entry => {
const instrId = entry.key.split('-')[0]
const { overheadTime } = allowanceData.find(i => i.instrId === instrId)
if (!newTotalExptState[entry.key]) {
newTotalExptState[entry.key] = overheadTime
}
})
}
setTotalExptState(newTotalExptState)
}
setTotalExptState(newTotalExptState)

// eslint-disable-next-line
}, [allowanceData])

Expand Down Expand Up @@ -129,7 +177,6 @@ const BookExperimentsForm = props => {
const onParamSetChange = (sampleKey, expNo, paramSetName) => {
form.resetFields([[sampleKey, 'exps', expNo, 'params']])
const key = sampleKey + '#' + expNo

const paramSet = props.paramSetsData.find(paramSet => paramSet.name === paramSetName)

if (paramSet.defaultParams.length < 4) {
Expand Down Expand Up @@ -453,19 +500,22 @@ const BookExperimentsForm = props => {
))}
</Col>
{priorityAccess && checkBoxes}
<Col span={1}>
<button
className={classes.CancelButton}
value={key}
onClick={e => {
e.preventDefault()
props.onCancelHolder(props.token, e.target.value)
form.resetFields([e.target.value])
}}
>
Cancel
</button>
</Col>
{!resubmit && (
<Col span={1}>
<button
className={classes.CancelButton}
disabled={resubmit}
value={key}
onClick={e => {
e.preventDefault()
props.onCancelHolder(props.token, e.target.value)
form.resetFields([e.target.value])
}}
>
Cancel
</button>
</Col>
)}
</Row>
<Row gutter={16}>
<Col
Expand Down Expand Up @@ -523,11 +573,25 @@ const BookExperimentsForm = props => {
) : (
<Form form={form} ref={props.formRef} size='small' onFinish={onFinishHandler}>
{formItems}
<Form.Item>
<Button type='primary' size='middle' htmlType='submit'>
Continue
</Button>
</Form.Item>
<Space>
<Form.Item>
<Button type='primary' size='middle' htmlType='submit'>
Continue
</Button>
</Form.Item>
{resubmit && (
<Form.Item>
<Popconfirm
title='Cancel holders'
description='Booked holders will be canceled '
onConfirm={() => navigate('/dashboard')}
>
<Button size='middle'>Cancel</Button>
</Popconfirm>
</Form.Item>
)}
</Space>

<EditParamsModal
visible={modalVisible}
closeModal={closeModalHandler}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,11 @@ const PageHeaderEl = props => {
avatarSrc = submitIcon
break

case location.pathname === '/resubmit':
headerTitle = 'Resubmit Experiments'
avatarSrc = submitIcon
break

case location.pathname === '/batch-submit':
headerTitle = 'Batch Submit'
avatarSrc = batchSubmitIcon
Expand Down
63 changes: 47 additions & 16 deletions nomad-front-end/src/components/StatusDrawer/StatusDrawer.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useState } from 'react'
import { Drawer, Button, Row, Col, message } from 'antd'
import { Drawer, Button, Space, message } from 'antd'
import { connect } from 'react-redux'
import { useNavigate } from 'react-router-dom'

import DrawerTable from './DrawerTable/DrawerTable'
import SubmitModal from '../Modals/SubmitModal/SubmitModal'
import { postPending, signOutHandler, postPendingAuth } from '../../store/actions'
import { postPending, signOutHandler, postPendingAuth, resubmitHolders } from '../../store/actions'

const StatusDrawer = props => {
const { id, visible, tableData, dataLoading } = props.status
Expand All @@ -13,6 +14,8 @@ const StatusDrawer = props => {
const [modalVisible, setModalVisible] = useState(false)
const [modalData, setModalData] = useState({})

const navigate = useNavigate()

let title = ''
let buttons = null
const headerClass = {
Expand All @@ -22,9 +25,6 @@ const StatusDrawer = props => {
}

const btnClickHandler = type => {
if (selectedHolders.length === 0) {
return message.warning('No holders selected!')
}
if (authToken) {
pendingHandler(authToken, type, selectedHolders)
if (accessLvl !== 'admin') {
Expand All @@ -42,6 +42,28 @@ const StatusDrawer = props => {
}
}

const editHandler = () => {
console.log(selectedHolders)
const usernames = new Set()
const instrIds = new Set()
selectedHolders.map(row => {
usernames.add(row.username)
instrIds.add(row).instrIds
})

if (usernames.size !== 1 || instrIds.size !== 1) {
return message.error('Holders for multiple users or instruments selected!')
}

props.resubmitHandler(authToken, {
username: selectedHolders[0].username,
checkedHolders: selectedHolders.map(i => i.holder),
instrId: selectedHolders[0].instrId
})

navigate('/resubmit')
}

switch (id) {
case 'errors':
title = 'Errors'
Expand All @@ -58,16 +80,24 @@ const StatusDrawer = props => {
headerClass.backgroundColor = '#ffffb8'
headerClass.borderBottom += '#fadb14'
buttons = (
<Row>
<Col span={2} style={{ textAlign: 'left' }}>
<Button onClick={() => btnClickHandler('delete')}>Cancel Selected</Button>
</Col>
<Col span={20} style={{ textAlign: 'center' }}>
<Button type='primary' onClick={() => btnClickHandler('submit')}>
Submit
</Button>
</Col>
</Row>
<Space size={'large'}>
<Button disabled={selectedHolders.length === 0} onClick={() => btnClickHandler('delete')}>
Cancel Selected
</Button>
<Button
disabled={selectedHolders.length === 0 || !authToken}
onClick={() => editHandler()}
>
Edit Selected
</Button>
<Button
type='primary'
disabled={selectedHolders.length === 0}
onClick={() => btnClickHandler('submit')}
>
Submit
</Button>
</Space>
)
break
default:
Expand Down Expand Up @@ -116,7 +146,8 @@ const mapDispatchToProps = dispatch => {
return {
pendingHandler: (token, type, data) => dispatch(postPending(token, type, data)),
pendingAuthHandler: (type, data) => dispatch(postPendingAuth(type, data)),
logoutHandler: token => dispatch(signOutHandler(token))
logoutHandler: token => dispatch(signOutHandler(token)),
resubmitHandler: (token, data) => dispatch(resubmitHolders(token, data))
}
}

Expand Down
Loading

0 comments on commit 4168385

Please sign in to comment.