aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/classes/StudipController.php29
-rw-r--r--lib/classes/forms/Form.php12
-rw-r--r--resources/assets/javascripts/lib/forms.js40
-rw-r--r--resources/vue/apps/StudipWizard.vue44
4 files changed, 80 insertions, 45 deletions
diff --git a/lib/classes/StudipController.php b/lib/classes/StudipController.php
index 3ac80e8..00e086e 100644
--- a/lib/classes/StudipController.php
+++ b/lib/classes/StudipController.php
@@ -14,6 +14,7 @@ use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Studip\WizardPart;
+use Studip\Forms\Form;
/**
* @property StudipResponse $response
@@ -608,14 +609,26 @@ abstract class StudipController extends Trails\Controller
*/
public function render_wizard(array $steps, bool $showAllSteps = true): void
{
- $this->render_vue_app(
- Studip\VueApp::create('StudipWizard')
- ->withProps([
- 'steps' => $steps,
- 'showAllSteps' => $showAllSteps
- ])
- ->withStore('wizardStore', 'useWizardStore')
- );
+ if (Request::get('step_id', null) !== null && Request::isXhr()) {
+ $step = array_find($steps, fn ($entry) => $entry->getId() === Request::get('step_id'));
+
+ if ($step && $step->getType() === Form::class) {
+ $validated = $step->getContent()->validate(true);
+ $this->render_json($validated);
+ } else {
+ $this->set_status(404);
+ $this->render_nothing();
+ }
+
+ } else {
+ $this->render_vue_app(
+ Studip\VueApp::create('StudipWizard')
+ ->withProps([
+ 'steps' => $steps,
+ 'showAllSteps' => $showAllSteps
+ ])
+ );
+ }
}
diff --git a/lib/classes/forms/Form.php b/lib/classes/forms/Form.php
index f34b68d..58ff72d 100644
--- a/lib/classes/forms/Form.php
+++ b/lib/classes/forms/Form.php
@@ -314,7 +314,7 @@ class Form extends Part
return $this;
}
- public function validate()
+ public function validate(bool $return = false)
{
if (\Request::isPost() && \Request::submitted('STUDIPFORM_SERVERVALIDATION')) {
//verify the user input:
@@ -333,10 +333,14 @@ class Form extends Part
}
}
}
- header('Content-Type: application/json');
- echo json_encode($output);
sess()->save();
- die();
+ if ($return) {
+ return $output;
+ } else {
+ header('Content-Type: application/json');
+ echo json_encode($output);
+ die();
+ }
}
return $this;
}
diff --git a/resources/assets/javascripts/lib/forms.js b/resources/assets/javascripts/lib/forms.js
index 125c7d8..9f9aae3 100644
--- a/resources/assets/javascripts/lib/forms.js
+++ b/resources/assets/javascripts/lib/forms.js
@@ -80,6 +80,9 @@ const Forms = {
params.STUDIPFORM_SELECTEDLANGUAGES = {};
params.STUDIPFORM_EMIT_VALUES = f.dataset.emit;
params.STUDIPFORM_USE_STORE = f.dataset.useStore === 'true';
+ if (params.STUDIPFORM_USE_STORE) {
+ params.store = useFormsStore();
+ }
params.STUDIPFORM_FORM_ID = f.dataset.formId;
for (let i in JSON.parse(f.dataset.inputs)) {
params.STUDIPFORM_INPUTS_ORDER.push(i);
@@ -87,20 +90,25 @@ const Forms = {
return params;
},
methods: {
- submit: function (e) {
+ submit: async function (e) {
if (this.STUDIPFORM_VALIDATED) {
- return;
+ return Promise.resolve();
}
this.STUDIPFORM_VALIDATIONNOTES = [];
this.STUDIPFORM_DISPLAYVALIDATION = true;
+ if (e) {
+ e.preventDefault();
+ }
+
// validation:
- this.validate()
+ return this.validate()
.then(() => {
if (this.STUDIPFORM_USE_STORE) {
- const store = useFormsStore();
- store.initialize();
- store.setData(this.STUDIPFORM_FORM_ID, this.getFormValues());
+ this.store.setData(this.STUDIPFORM_FORM_ID, this.getFormValues());
+ this.STUDIPFORM_VALIDATED = true;
+ //this.$el.submit();
+ return Promise.resolve();
} else {
if (this.STUDIPFORM_AUTOSAVEURL) {
let params = this.getFormValues();
@@ -110,21 +118,24 @@ const Forms = {
if (output === 'STUDIPFORM_STORE_SUCCESS' && this.STUDIPFORM_REDIRECTURL) {
//The form has been stored successfully:
window.location.href = this.STUDIPFORM_REDIRECTURL;
+ return Promise.resolve([]);
} else if (output !== 'STUDIPFORM_STORE_SUCCESS') {
Report.error($gettext('Es ist ein Fehler aufgetreten.'), output);
+ return Promise.reject(output);
}
});
} else {
this.STUDIPFORM_VALIDATED = true;
this.$el.submit();
+ return Promise.resolve();
}
}
}).catch(errors => {
this.STUDIPFORM_VALIDATIONNOTES = errors;
this.$el.scrollIntoView({behavior: 'smooth'});
+ return Promise.reject(errors);
}
);
- e.preventDefault();
},
getFormValues() {
let params = {
@@ -179,7 +190,7 @@ const Forms = {
});
// Optional server validation
- if (this.STUDIPFORM_SERVERVALIDATION && !this.STUDIPFORM_USE_STORE) {
+ if (this.STUDIPFORM_SERVERVALIDATION) {
let params = this.getFormValues();
if (this.STUDIPFORM_AUTOSAVEURL) {
params.STUDIPFORM_AUTOSTORE = 1;
@@ -187,6 +198,10 @@ const Forms = {
params.STUDIPFORM_SERVERVALIDATION = 1;
params.STUDIPFORM_FORM_ID = this.STUDIPFORM_FORM_ID;
+ if (this.STUDIPFORM_USE_STORE) {
+ params.step_id = this.STUDIPFORM_FORM_ID;
+ }
+
const output = await fetch(this.STUDIPFORM_VALIDATION_URL, {
method: 'POST',
body: new URLSearchParams(params),
@@ -252,11 +267,12 @@ const Forms = {
}
}
- STUDIP.Vue.on('form.submit', id => {
- if (this.STUDIPFORM_FORM_ID === id) {
- this.submit(new Event('submit'));
+ if (this.STUDIPFORM_USE_STORE) {
+ const storedData = this.store.getData(this.STUDIPFORM_FORM_ID);
+ if (storedData) {
+ this.setInputs(storedData);
}
- });
+ }
}
});
const instance = app.mount(f);
diff --git a/resources/vue/apps/StudipWizard.vue b/resources/vue/apps/StudipWizard.vue
index 941f1a8..5acca93 100644
--- a/resources/vue/apps/StudipWizard.vue
+++ b/resources/vue/apps/StudipWizard.vue
@@ -113,32 +113,41 @@ const currentStep = ref(0);
// HTML content of current step
let stepContent = ref('');
let mountedApp = null;
+let appInstance = null;
const currentStepType = ref(null);
const visibleSteps = ref(props.showAllSteps ? props.steps : [props.steps[0]]);
-const checkValidity = () => {
+const validate = async () => {
if (currentStepType.value === 'form') {
- STUDIP.Vue.emit('form.submit', props.steps[currentStep.value].id);
+ return appInstance.submit()
+ .then(() => {
+ return true;
+ }).catch(errors => {
+ return false;
+ });
+ } else {
+ return true;
}
};
-const jumpToStep = (number) => {
- checkValidity();
-
- if (mountedApp !== null) {
- mountedApp.unmount();
- }
+const jumpToStep = async (number) => {
+ const success = await validate();
+ if (success) {
+ if (mountedApp !== null) {
+ mountedApp.unmount();
+ }
- if (!visibleSteps.value.includes(props.steps[number])) {
- visibleSteps.value[number] = props.steps[number];
+ if (!visibleSteps.value.includes(props.steps[number])) {
+ console.log('Visible steps', visibleSteps.value);
+ visibleSteps.value[number] = props.steps[number];
+ }
+ currentStep.value = number;
+ initializeContent(number);
}
- currentStep.value = number;
- initializeContent(number);
};
const finishWizard = () => {
- checkValidity();
};
const initializeContent = async (stepNumber) => {
@@ -165,20 +174,13 @@ onMounted(() => {
STUDIP.Vue.on('form.mounted', (mounted) => {
mountedApp = mounted.app;
+ appInstance = mounted.instance;
});
STUDIP.Vue.on('vueApp.mounted', (mounted) => {
if (mounted.config.appPath === stepContent.value.appPath) {
mountedApp = mounted.app;
}
});
-
- visibleSteps.value.push({
- type: 'Vue',
- id: 'stock-images',
- title: 'Bilderpool',
- content: StockImages,
- icon: 'block-gallery'
- });
});
</script>