docbrown/app/javascript/admin/controllers/data_update_script_controller.js
Ridhwana 530e927060
Add ability to re-run a data script from the the data update script page (#12424)
* feat: add an error column to the data update script

* feat: save the error to the error field

* feat: save the error when the script fails

* feat: show the script error on the data update script page

* chore: pass the error to mark_as_failed instead of having its own function

* refactor: use presence

* test: ensure that we test an error case of a data update script

* chore: rename errorneous to failing

* test: update some specs, working on the others

* chore: update tests now that there are two files

* chore: change error from a string to a text to allow for more char

* feat: order the data update scripts by the latest script that ran

* feat: when the script has succeeded reset error to nil

* feat: create a model function that will allow the script to be force run

* chore: oops remove the functions form the worker to the model so it can be re-used

* feat: create an endpoint that will call the model method force run when we hit the api by clicking the button

* feat: ensure that the we add an ajax call that calls the controller endpoint

* chore: remove newline

* refactor: change to a more Restful route

* refactor: use Stimulus

* fix: move the code from the model back into the worker so that we can reuse it in the controller

* feat:call the worker in the force_run action and create a show route

* feat: very first draft of using a polling mechanism on the show method after we kickoff the sidekiq job (still need to error handle)

* chore: some syntax changes and unused variables

* fix: call the method correctly with the paramters

* feat: do some error handling

* feat: error handing on the frontend

* chore: use e instead of err

* refactor: just pass the id instead of the whole script

* chore: remove the button

* fix: allow the id to be passed

* feat: handle errors better

* feat: limit the filename column width

* refactor: use a common function to set the banner error

* test: add a test fro rerun button

* test: v1 of the data update script request

* test: write some specs for the js controller

* Update app/controllers/admin/data_update_scripts_controller.rb

Co-authored-by: Michael Kohl <me@citizen428.net>

* tests: update the data worker spec

* chore: clean up the js controller and its tests

* chore: remove whitespaces

* chore: swap the functions based on the controller

* chore: updates to the UI

* chore: remove the standard error catch

* chore: update the alert and error messages

* chore: remove test for error handling for sidekiq run

Co-authored-by: Michael Kohl <me@citizen428.net>
2021-02-02 17:24:39 +02:00

126 lines
4.3 KiB
JavaScript

import { Controller } from 'stimulus';
export default class DataUpdateScriptController extends Controller {
forceRun(event) {
event.preventDefault();
const id = event.target.dataset.value;
let statusColumn = document.getElementById(`data_update_script_${id}_status`);
let runAtColumn = document.getElementById(`data_update_script_${id}_run_at`);
this.displayLoadingIndicators(statusColumn, runAtColumn);
this.forceRunScript(id, statusColumn, runAtColumn);
}
displayLoadingIndicators(statusColumn, runAtColumn) {
runAtColumn.innerHTML = 'loading..';
statusColumn.innerHTML = '';
}
forceRunScript(id, statusColumn, runAtColumn) {
fetch(`/admin/data_update_scripts/${id}/force_run`, {
method: 'POST',
headers: {
'X-CSRF-Token': document.querySelector("meta[name='csrf-token']").content,
},
credentials: 'same-origin'
})
.then(response => {
if(response.ok) {
this.pollForScriptResponse(id, statusColumn, runAtColumn);
} else {
this.setErrorBanner(
runAtColumn,
statusColumn,
`Data Script ${id} - Something went wrong`,
'alert-danger'
);
}
})
}
pollForScriptResponse(id, statusColumn, runAtColumn) {
let counter = 0;
let pollForStatus = setInterval(() => {
counter++;
this.checkForUpdatedDataScript(id, runAtColumn, statusColumn).then((updatedDataScript) => {
if (updatedDataScript) {
if(updatedDataScript.status) {
// when we've stopped polling because we've received a status
// and not because we've received an error.
runAtColumn.innerHTML = updatedDataScript.run_at;
statusColumn.innerHTML = `${updatedDataScript.status}`;
if(updatedDataScript.error) {
// we need to show the html as text instead of a parsed version,
// hence we manipulate the DOM through this longer process.
let errorElem = document.createElement('div');
errorElem.setAttribute('class', 'fs-xs');
errorElem.setAttribute('id', `data_update_script_${id}_error`);
statusColumn.appendChild(errorElem);
let completedErrorElem = document.getElementById(`data_update_script_${id}_error`);
completedErrorElem.innerText = updatedDataScript.error;
}
if(updatedDataScript.status === "succeeded") {
document.getElementById(`data_update_script_${id}_row`).classList.remove("alert-danger");
if(document.getElementById(`data_update_script_${id}_button`)) {
document.getElementById(`data_update_script_${id}_button`).remove();
}
}
}
clearInterval(pollForStatus);
}
});
if ( counter > 0 ) {
clearInterval(pollForStatus);
this.setErrorBanner(
runAtColumn,
statusColumn,
`Data Script with ${id} may take some time. Please refresh the page to check for the status.`,
'alert-info'
);
}
}, 1000)
}
checkForUpdatedDataScript(id, runAtColumn, statusColumn) {
return fetch(`/admin/data_update_scripts/${id}`, {
method: 'GET',
headers: {
'X-CSRF-Token': document.querySelector("meta[name='csrf-token']").content,
},
credentials: 'same-origin'
}).then((response) => {
if(response.ok) {
return response.json().then(json => {
let script = json.response;
if(script.status === "succeeded" || script.status === "failed") {
return script;
} else {
return false;
}
})
} else {
return response.json().then((response) => {
this.setErrorBanner(
runAtColumn,
statusColumn,
`Data Script ${id} - ${response.error}`,
'alert-danger'
);
return true;
});
}
})
}
setErrorBanner(runAtColumn, statusColumn, error, bannerClass) {
let classList = document.getElementsByClassName('data-update-script__alert')[0].classList
classList.add(bannerClass);
classList.remove('hidden');
document.getElementById('data-update-script__error').innerHTML = error;
runAtColumn.innerHTML = '';
statusColumn.innerHTML = '';
}
}