Skip to content
92 changes: 65 additions & 27 deletions htdocs/js/loris-scripts.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,70 @@
/* eslint new-cap: ["error", {capIsNewExceptions: ["DynamicTable", "FileUpload"]}]*/

/**
* Display the login modal when a request returns a 401 response.
*/
function handleUnauthorized() {
if (!window.$ || !window.loris) {
return;
}

if (!$('#login-modal').length) {
return;
}

if ($('#login-modal').hasClass('in')) {
$('#login-modal-error').show();
return;
}

$('#login-modal').modal('show');
$('#modal-login')
.off('click.lorisFetch')
.on('click.lorisFetch', function(e) {
e.preventDefault();
let data = {
username: $('#modal-username').val(),
password: $('#modal-password').val(),
login: 'Login',
};

window.lorisFetch(window.loris.BaseURL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: new URLSearchParams(data),
})
.then((response) => {
if (!response.ok) {
throw new Error('request_failed');
}
$('#login-modal-error').hide();
$('#login-modal').modal('hide');
})
.catch(() => {
$('#login-modal-error').show();
});
});
}

if (!window.lorisFetch) {
window.lorisFetch = function(input, init) {
const options = Object.assign(
{
credentials: 'same-origin',
},
init || {}
);
return fetch(input, options).then((response) => {
if (response.status === 401) {
handleUnauthorized();
}
return response;
});
};
}

$(document).ready(function() {
$('#menu-toggle').click(function(e) {
e.preventDefault();
Expand All @@ -8,30 +73,3 @@ $(document).ready(function() {
$('.dynamictable').DynamicTable();
$('.fileUpload').FileUpload();
});

$(document).ajaxError(function(event, jqxhr, settings, thrownError) {
if (jqxhr.status === 401) {
if ($('#login-modal').hasClass('in')) {
$('#login-modal-error').show();
} else {
$('#login-modal').modal('show');
$('#modal-login').click(function(e) {
e.preventDefault();
let data = {
username: $('#modal-username').val(),
password: $('#modal-password').val(),
login: 'Login',
};
$.ajax({
type: 'post',
url: loris.BaseURL,
data: data,
success: function() {
$('#login-modal-error').hide();
$('#login-modal').modal('hide');
},
});
});
}
}
});
81 changes: 81 additions & 0 deletions jslib/lorisFetch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* Display the login modal when a request returns a 401 response.
*/
function handleUnauthorized() {
if (typeof window === 'undefined') {
return;
}
if (!window.$ || !window.loris) {
return;
}

const $ = window.$;
if (!$('#login-modal').length) {
return;
}

if ($('#login-modal').hasClass('in')) {
$('#login-modal-error').show();
return;
}

$('#login-modal').modal('show');
$('#modal-login')
.off('click.lorisFetch')
.on('click.lorisFetch', function(e) {
e.preventDefault();
let data = {
username: $('#modal-username').val(),
password: $('#modal-password').val(),
login: 'Login',
};

fetch(window.loris.BaseURL, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: new URLSearchParams(data),
credentials: 'same-origin',
})
.then((response) => {
if (!response.ok) {
throw new Error('request_failed');
}
$('#login-modal-error').hide();
$('#login-modal').modal('hide');
})
.catch(() => {
$('#login-modal-error').show();
});
});
}

/**
* Wrapper around fetch that keeps credentials and handles 401s.
*
* @param {*} input
* @param {object=} init
* @return {Promise<Response>}
*/
function lorisFetch(input, init) {
const options = Object.assign(
{
credentials: 'same-origin',
},
init || {}
);

return fetch(input, options).then((response) => {
if (response.status === 401) {
handleUnauthorized();
}
return response;
});
}

if (typeof window !== 'undefined') {
window.lorisFetch = lorisFetch;
}

export default lorisFetch;
111 changes: 57 additions & 54 deletions modules/candidate_parameters/jsx/CandidateInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
ButtonElement,
TextareaElement,
} from 'jsx/Form';
import CandidateParametersClient from './CandidateParametersClient';
import lorisFetch from 'jslib/lorisFetch';

/**
* Candiate info component
Expand All @@ -35,6 +37,7 @@ class CandidateInfo extends Component {
isLoaded: false,
loadedData: 0,
};
this.client = new CandidateParametersClient();
this.setFormData = this.setFormData.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
Expand All @@ -46,34 +49,28 @@ class CandidateInfo extends Component {
*/
componentDidMount() {
const {t} = this.props;
let that = this;
$.ajax(
this.props.dataURL,
{
dataType: 'json',
success: function(data) {
let formData = {
flaggedCaveatemptor: data.flagged_caveatemptor,
flaggedOther: data.flagged_other,
flaggedReason: data.flagged_reason,
};
this.client.getData(this.props.candID, this.props.tabName)
.then((data) => {
let formData = {
flaggedCaveatemptor: data.flagged_caveatemptor,
flaggedOther: data.flagged_other,
flaggedReason: data.flagged_reason,
};

// Add parameter values to formData
Object.assign(formData, data.parameter_values);
// Add parameter values to formData
Object.assign(formData, data.parameter_values);

that.setState({
Data: data,
isLoaded: true,
formData: formData,
});
},
error: function(data, errorCode, errorMsg) {
that.setState({
error: t('An error occured while loading the page.', {ns: 'loris'}),
});
},
}
);
this.setState({
Data: data,
isLoaded: true,
formData: formData,
});
})
.catch(() => {
this.setState({
error: t('An error occured while loading the page.', {ns: 'loris'}),
});
});
}

/**
Expand Down Expand Up @@ -334,37 +331,43 @@ class CandidateInfo extends Component {

formData.append('tab', this.props.tabName);
formData.append('candID', this.state.Data.candID);
$.ajax(
{
type: 'POST',
url: self.props.action,
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(data) {
lorisFetch(self.props.action, {
method: 'POST',
body: formData,
})
.then(async (response) => {
if (!response.ok) {
let errorMessage = '';
let text = await response.text();
if (text) {
try {
errorMessage = JSON.parse(text).message || '';
} catch (err) {
errorMessage = '';
}
}
let error = new Error('request_failed');
error.lorisMessage = errorMessage;
throw error;
}
self.setState(
{
updateResult: 'success',
}
);
self.showAlertMessage();
})
.catch((err) => {
if (err.lorisMessage !== undefined && err.lorisMessage !== '') {
self.setState(
{
updateResult: 'success',
updateResult: 'error',
errorMessage: err.lorisMessage,
}
);
self.showAlertMessage();
},
error: function(err) {
if (err.responseText !== '') {
let errorMessage = JSON.parse(err.responseText).message;
self.setState(
{
updateResult: 'error',
errorMessage: errorMessage,
}
);
self.showAlertMessage();
}
},

}
);
}
});
}

/**
Expand All @@ -390,8 +393,8 @@ class CandidateInfo extends Component {
}
}
CandidateInfo.propTypes = {
dataURL: PropTypes.string,
tabName: PropTypes.string,
candID: PropTypes.string.isRequired,
tabName: PropTypes.string.isRequired,
action: PropTypes.string,
t: PropTypes.string.isRequired,
};
Expand Down
2 changes: 1 addition & 1 deletion modules/candidate_parameters/jsx/CandidateParameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class CandidateParameters extends Component {
<TabContent
action={actionURL}
dataURL={`${dataURL}&data=${tabList[key].id}`}
candID={this.props.candID}
tabName={tabList[key].id}
/>
</TabPane>
Expand Down Expand Up @@ -161,4 +162,3 @@ window.addEventListener('load', () => {
</div>
);
});

41 changes: 41 additions & 0 deletions modules/candidate_parameters/jsx/CandidateParametersClient.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import lorisFetch from 'jslib/lorisFetch';

/**
* Candidate parameters JSON client.
*/
class CandidateParametersClient {
/**
* @constructor
*/
constructor() {
this.baseURL = new URL(
`${loris.BaseURL}/candidate_parameters/ajax/getData.php`,
window.location.origin
);
}

/**
* Fetch candidate tab JSON data.
*
* @param {string} candID
* @param {string} tabName
* @return {Promise<any>}
*/
getData(candID, tabName) {
const url = new URL(this.baseURL);
url.searchParams.set('candID', candID);
url.searchParams.set('data', tabName);

return lorisFetch(url.toString(), {
method: 'GET',
headers: {'Accept': 'application/json'},
}).then((response) => {
if (!response.ok) {
throw new Error('request_failed');
}
return response.json();
});
}
}

export default CandidateParametersClient;
Loading
Loading