Skip to content

Commit

Permalink
Fix ui and some bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
mboudet committed Nov 2, 2023
1 parent 3c7a372 commit 448b36c
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ This changelog was started for release 4.2.0.
- "askomics:instancesLabel" predicate can be defined at the entity-level, to set a specific attribute URI as the 'label' (ie, visible by default)
- Play the same role as 'askomics:instancesHaveNoLabels', except a specific attribute is visible instead of the URI attribute.
- Added the *TIMEOUT* env variable, which will set the web workers tiemout value. Default 300s
- Added the 'skip_rdf_preview' config option. This will skip loading RDF files in memory to get the location and remote graph. Warning: This means you must enter the values at the integration step yourself.

### Changed

- Now pre-process files to store integration parameters (column, entities, etc...) in DB, to avoid re-processing every time.
- Rewrote the ontology part. Instead of specifying 'children of' and other values, users can tick the 'recursive' button to customize the query. While this is less intuitive, this change is more flexible for the various types of ontological relations

## [4.5.0] - 2023-10-20
Expand Down
4 changes: 3 additions & 1 deletion askomics/api/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,17 @@ def get_preview():

errorMessage = ''
error = False
errorCode = 200
if not results:
errorMessage = "None of the selected files are in an integrable state"
error = True
errorCode = 400

return jsonify({
'previewFiles': results,
'error': error,
'errorMessage': errorMessage
})
}), errorCode


@file_bp.route('/api/files/delete', methods=['POST'])
Expand Down
2 changes: 1 addition & 1 deletion askomics/libaskomics/GffFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def save_preview(self):
if self.error:
error = self.error_message
else:
data = {'entities': self.entity_name}
data = {'entities': self.entities}
self.save_preview_in_db(data, error)

def get_preview(self):
Expand Down
4 changes: 4 additions & 0 deletions askomics/libaskomics/RdfFile.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def get_location_and_remote_graph(self):
str
Location
"""

if self.settings.get('skip_rdf_preview', False):
return "", ""

graph = RdfGraph(self.app, self.session)
graph.parse(self.path, format=self.type_dict[self.type])
triple_loc = (None, self.prov.atLocation, None)
Expand Down
10 changes: 8 additions & 2 deletions askomics/react/src/routes/error/error.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default class ErrorDiv extends Component {
}

let error

if (Array.isArray(this.props.errorMessage)) {
error = (
<Alert color="danger">
Expand All @@ -48,12 +48,18 @@ export default class ErrorDiv extends Component {
))}
</Alert>
)
} else {
} else if (! this.props.errorMessage){
error = (
<Alert color="danger">
<div><i className="fas fa-exclamation-circle"></i> {messages[this.props.status.toString()]}</div>
</Alert>
)
} else {
error = (
<Alert color="danger">
<div><i className="fas fa-exclamation-circle"></i> {this.props.errorMessage}</div>
</Alert>
)
}

return (
Expand Down
44 changes: 42 additions & 2 deletions askomics/react/src/routes/upload/filestable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,26 @@ import axios from 'axios'
import BootstrapTable from 'react-bootstrap-table-next'
import paginationFactory from 'react-bootstrap-table2-paginator'
import cellEditFactory from 'react-bootstrap-table2-editor'
import {Badge} from 'reactstrap'
import {Badge, Modal, ModalHeader, ModalBody, ModalFooter, Button} from 'reactstrap'
import WaitingDiv from '../../components/waiting'
import Utils from '../../classes/utils'
import SyntaxHighlighter from 'react-syntax-highlighter'
import { monokai } from 'react-syntax-highlighter/dist/esm/styles/hljs'
import PropTypes from 'prop-types'

export default class FilesTable extends Component {
constructor (props) {
super(props)
this.state = {
modalTracebackTitle: "",
modalTracebackContent: "",
modalTraceback: false
}
this.utils = new Utils()
this.handleSelection = this.handleSelection.bind(this)
this.handleSelectionAll = this.handleSelectionAll.bind(this)
this.handleClickError = this.handleClickError.bind(this)
this.toggleModalTraceback = this.toggleModalTraceback.bind(this)
}

handleSelection (row, isSelect) {
Expand Down Expand Up @@ -41,6 +50,24 @@ export default class FilesTable extends Component {
}
}

handleClickError(event) {
this.props.files.forEach(file => {
if (file.id == event.target.id) {
this.setState({
modalTracebackTitle: "File processing error",
modalTracebackContent: file.preview_error ? file.preview_error : "Internal server error",
modalTraceback: true
})
}
})
}

toggleModalTraceback () {
this.setState({
modalTraceback: !this.state.modalTraceback
})
}

editFileName (oldValue, newValue, row) {

if (newValue === oldValue) {return}
Expand Down Expand Up @@ -102,7 +129,7 @@ export default class FilesTable extends Component {
if (cell == 'processing') {
return <Badge color="secondary">Processing</Badge>
}
return <Badge color="danger">Error</Badge>
return <Badge style={{cursor: "pointer"}} id={row.id} color="danger" onClick={this.handleClickError}>Error</Badge>
},
sort: true,
editable: false
Expand Down Expand Up @@ -147,6 +174,19 @@ export default class FilesTable extends Component {
})}
/>
</div>
<Modal size="lg" isOpen={this.state.modalTraceback} toggle={this.toggleModalTraceback}>
<ModalHeader toggle={this.toggleModalTraceback}>{this.state.modalTracebackTitle.substring(0, 100)}</ModalHeader>
<ModalBody>
<div>
<SyntaxHighlighter language="python" style={monokai}>
{this.state.modalTracebackContent}
</SyntaxHighlighter>
</div>
</ModalBody>
<ModalFooter>
<Button color="secondary" onClick={this.toggleModalTraceback }>Close</Button>
</ModalFooter>
</Modal>
</div>
)
}
Expand Down
55 changes: 34 additions & 21 deletions askomics/react/src/routes/upload/upload.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,10 @@ export default class Upload extends Component {

componentDidMount () {
if (!this.props.waitForStart) {
let requestUrl = '/api/files'
axios.get(requestUrl, { baseURL: this.props.config.proxyPath, cancelToken: new axios.CancelToken((c) => { this.cancelRequest = c }) })
.then(response => {
console.log(requestUrl, response.data)
this.setState({
diskSpace: response.data.diskSpace,
exceededQuota: this.props.config.user.quota > 0 && response.data.diskSpace >= this.props.config.user.quota,
files: response.data.files,
waiting: false
})
})
.catch(error => {
console.log(error, error.response.data.errorMessage)
this.setState({
error: true,
errorMessage: error.response.data.errorMessage,
status: error.response.status,
waiting: false
})
})
this.getFiles()
this.interval = setInterval(() => {
this.getFiles()
}, 5000)
}
}

Expand All @@ -57,6 +41,31 @@ export default class Upload extends Component {
}
}


getFiles() {
let requestUrl = '/api/files'
axios.get(requestUrl, { baseURL: this.props.config.proxyPath, cancelToken: new axios.CancelToken((c) => { this.cancelRequest = c }) })
.then(response => {
console.log(requestUrl, response.data)
this.setState({
diskSpace: response.data.diskSpace,
exceededQuota: this.props.config.user.quota > 0 && response.data.diskSpace >= this.props.config.user.quota,
files: response.data.files,
waiting: false
})
})
.catch(error => {
console.log(error, error.response.data.errorMessage)
this.setState({
error: true,
errorMessage: error.response.data.errorMessage,
status: error.response.status,
waiting: false
})
})
}


deleteSelectedFiles () {
let requestUrl = '/api/files/delete'
let data = {
Expand Down Expand Up @@ -94,6 +103,10 @@ export default class Upload extends Component {
return this.state.selected.length == 0
}

isDisabledIntegrate () {
return this.state.selected.length == 0 || this.state.files.some(file => this.state.selected.includes(file.id) && file.status == "error")
}

render () {
let redirectLogin
if (this.state.status == 401) {
Expand Down Expand Up @@ -138,7 +151,7 @@ export default class Upload extends Component {
<br />
<ButtonGroup>
<Button disabled={this.isDisabled()} onClick={this.deleteSelectedFiles} color="danger"><i className="fas fa-trash-alt"></i> Delete</Button>
<Button disabled={this.isDisabled()} onClick={this.integrateSelectedFiles} color="secondary"><i className="fas fa-database"></i> Integrate</Button>
<Button disabled={this.isDisabledIntegrate()} onClick={this.integrateSelectedFiles} color="secondary"><i className="fas fa-database"></i> Integrate</Button>
</ButtonGroup>
<ErrorDiv status={this.state.status} error={this.state.error} errorMessage={this.state.errorMessage} />
</div>
Expand Down
2 changes: 1 addition & 1 deletion askomics/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
celery = create_celery(app)


@celery.task(bind=True, name="set_preview")
@celery.task(bind=True, name="save_preview")
def save_preview(self, session, fileId):
"""Compute the file preview in backend and store it in DB
Expand Down
3 changes: 3 additions & 0 deletions config/askomics.ini.template
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,9 @@ autocomplete_max_results = 10
anonymous_query = false
anonymous_query_cleanup = 60

skip_rdf_preview = false


[triplestore]
# name of the triplestore, can be virtuoso or fuseki
triplestore = virtuoso
Expand Down

0 comments on commit 448b36c

Please sign in to comment.