-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Instrument manager] Reactify Menu Filters (#4142)
Update the instrument manager to use the React menu filter template.
- Loading branch information
Showing
7 changed files
with
8,532 additions
and
338 deletions.
There are no files selected for viewing
173 changes: 173 additions & 0 deletions
173
modules/instrument_manager/jsx/instrumentManagerIndex.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
import React, {Component} from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import {Tabs, TabPane} from 'Tabs'; | ||
import Loader from 'Loader'; | ||
import FilterableDataTable from 'FilterableDataTable'; | ||
|
||
import InstrumentUploadForm from './uploadForm'; | ||
|
||
class InstrumentManagerIndex extends Component { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
data: {}, | ||
error: false, | ||
isLoaded: false, | ||
}; | ||
|
||
this.fetchData = this.fetchData.bind(this); | ||
this.formatColumn = this.formatColumn.bind(this); | ||
} | ||
|
||
componentDidMount() { | ||
this.fetchData() | ||
.then(() => this.setState({isLoaded: true})); | ||
} | ||
|
||
/** | ||
* Retrieve data from the provided URL and save it in state | ||
* Additionally add hiddenHeaders to global loris variable | ||
* for easy access by columnFormatter. | ||
* | ||
* @return {object} | ||
*/ | ||
fetchData() { | ||
return fetch(this.props.dataURL, {credentials: 'same-origin'}) | ||
.then((resp) => resp.json()) | ||
.then((data) => this.setState({data})) | ||
.catch((error) => { | ||
this.setState({error: true}); | ||
console.error(error); | ||
}); | ||
} | ||
|
||
/** | ||
* Modify behaviour of specified column cells in the Data Table component | ||
* | ||
* @param {string} column - column name | ||
* @param {string} cell - cell content | ||
* @param {object} row - row content indexed by column | ||
* | ||
* @return {*} a formated table cell for a given column | ||
*/ | ||
formatColumn(column, cell, row) { | ||
return ( | ||
<td>{cell}</td> | ||
); | ||
} | ||
|
||
render() { | ||
// If error occurs, return a message. | ||
// XXX: Replace this with a UI component for 500 errors. | ||
if (this.state.error) { | ||
return <h3>An error occured while loading the page.</h3>; | ||
} | ||
|
||
// Waiting for async data to load | ||
if (!this.state.isLoaded) { | ||
return <Loader/>; | ||
} | ||
|
||
const fields = [ | ||
{label: 'Instrument', show: true, filter: { | ||
name: 'instrument', | ||
type: 'text', | ||
}}, | ||
{label: 'Instrument Type', show: true, filter: { | ||
name: 'instrumentType', | ||
type: 'select', | ||
options: { | ||
'Instrument Builder': 'Instrument Builder', | ||
'PHP': 'PHP', | ||
'Missing': 'Missing', | ||
}, | ||
}}, | ||
{label: 'Table Installed', show: true, filter: { | ||
name: 'tableInstalled', | ||
type: 'select', | ||
options: { | ||
'Exists': 'Exists', | ||
'Missing': 'Missing', | ||
}, | ||
}}, | ||
{label: 'Table Valid', show: true, filter: { | ||
name: 'tableValid', | ||
type: 'text', | ||
}}, | ||
{label: 'Pages Valid', show: true, filter: { | ||
name: 'pagesValid', | ||
type: 'text', | ||
}}, | ||
]; | ||
|
||
const tabs = [ | ||
{id: 'browse', label: 'Browse'}, | ||
{id: 'upload', label: 'Upload'}, | ||
]; | ||
|
||
const feedback = () => { | ||
if (!this.state.data.caninstall) { | ||
return ( | ||
<div className='alert alert-warning'> | ||
Instrument installation is not possible given the current server | ||
configuration; the LORIS 'quatUser' is not configured properly. | ||
File upload is still possible but instruments will need to be | ||
installed manually | ||
</div> | ||
); | ||
} | ||
}; | ||
|
||
const uploadTab = () => { | ||
let content = null; | ||
if (this.state.data.writable) { | ||
let url = loris.BaseURL.concat('/instrument_manager/?format=json'); | ||
content = ( | ||
<InstrumentUploadForm action={url}/> | ||
); | ||
} else { | ||
content = ( | ||
<div className='alert alert-warning'> | ||
Installation is not possible given the current server configuration. | ||
Please contact your administrator if you require this functionality | ||
</div> | ||
); | ||
} | ||
return content; | ||
}; | ||
|
||
return ( | ||
<Tabs tabs={tabs} defaultTab="browse" updateURL={true}> | ||
<TabPane TabId={tabs[0].id}> | ||
<FilterableDataTable | ||
name="instrument_manager" | ||
data={this.state.data.Data} | ||
fields={fields} | ||
getFormattedCell={this.formatColumn} | ||
/> | ||
</TabPane> | ||
<TabPane TabId='upload'> | ||
{feedback()} | ||
{uploadTab()} | ||
</TabPane> | ||
</Tabs> | ||
); | ||
} | ||
} | ||
|
||
InstrumentManagerIndex.propTypes = { | ||
dataURL: PropTypes.string.isRequired, | ||
hasPermission: PropTypes.func.isRequired, | ||
}; | ||
|
||
window.addEventListener('load', () => { | ||
ReactDOM.render( | ||
<InstrumentManagerIndex | ||
dataURL={`${loris.BaseURL}/instrument_manager/?format=json`} | ||
hasPermission={loris.userHasPermission} | ||
/>, | ||
document.getElementById('lorisworkspace') | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import React, {Component} from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
class InstrumentUploadForm extends Component { | ||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
data: {}, | ||
selectedFile: null, | ||
}; | ||
|
||
this.fileSelected = this.fileSelected.bind(this); | ||
this.upload = this.upload.bind(this); | ||
} | ||
|
||
fileSelected(element, file) { | ||
this.setState({ | ||
selectedFile: file, | ||
}); | ||
} | ||
|
||
upload() { | ||
const data = new FormData(); | ||
data.append('install_file', this.state.selectedFile); | ||
|
||
fetch(this.props.action, { | ||
method: 'POST', | ||
credentials: 'same-origin', | ||
body: data, | ||
}) | ||
.then((resp) => { | ||
if (resp.status == 201) { | ||
swal({ | ||
title: 'Installation Successful!', | ||
type: 'success', | ||
}, function() { | ||
window.location.assign(loris.BaseURL + '/instrument_manager/'); | ||
}); | ||
} | ||
return resp.json(); | ||
}) | ||
.then((data) => { | ||
if (data.message) { | ||
swal({ | ||
title: 'Upload Successful!', | ||
type: 'success', | ||
text: data.message, | ||
}, function() { | ||
window.location.assign(loris.BaseURL + '/instrument_manager/'); | ||
}); | ||
} | ||
if (data.error) { | ||
swal({ | ||
title: 'An error occured', | ||
type: 'error', | ||
text: data.error, | ||
}); | ||
} | ||
}) | ||
.catch((error) => { | ||
this.setState({error: true}); | ||
console.error(error); | ||
}); | ||
} | ||
|
||
render() { | ||
const disabled = () => this.state.selectedFile === null; | ||
|
||
return ( | ||
<div className="row"> | ||
<div className="col-xs-4"> | ||
<div className="panel panel-primary"> | ||
<div className="panel-heading">Upload Instrument</div> | ||
<div className="panel-body"> | ||
<div className="col-xs-12"> | ||
<FileElement | ||
name='install_file' | ||
label='Instrument file' | ||
onUserInput={this.fileSelected} | ||
value={this.state.selectedFile} | ||
/> | ||
<button className="btn btn-default" onClick={this.upload} disabled={disabled()}>Install</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
InstrumentUploadForm.propTypes = { | ||
action: PropTypes.string.isRequired, | ||
}; | ||
|
||
export default InstrumentUploadForm; |
Oops, something went wrong.