Skip to content

Commit 11bc5a8

Browse files
authored
Merge pull request #1880 from ProcessMaker/bugfix/FOUR-28371
FOUR-28371: Submit information > watcher variables are not displaying
2 parents 2f44bf5 + ab027fb commit 11bc5a8

File tree

1 file changed

+113
-26
lines changed

1 file changed

+113
-26
lines changed

src/components/inspector/variables-to-submit.vue

Lines changed: 113 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,16 @@
4343

4444
<!-- Select All and Search Section -->
4545
<div class="controls-section">
46-
<button
47-
type="button"
48-
class="select-all-button"
49-
@click="selectAll"
50-
:disabled="filteredVariables.length === 0 || selectedVariables.length === filteredVariables.length"
46+
<b-form-checkbox
47+
:checked="allSelected"
48+
:indeterminate="someSelected"
49+
@change="toggleSelectAll"
50+
:disabled="filteredVariables.length === 0"
51+
class="select-all-checkbox"
5152
data-cy="variables-to-submit-select-all"
5253
>
5354
{{ $t('Select All') }}
54-
</button>
55+
</b-form-checkbox>
5556
<button
5657
type="button"
5758
class="search-button"
@@ -164,10 +165,13 @@ export default {
164165
165166
// Extract calculated variables (computed properties)
166167
Object.assign(variables, this.extractCalculatedVariables());
168+
169+
// Extract watcher output variables
170+
Object.assign(variables, this.extractWatcherVariables());
167171
168-
// Filter: exclude _parent variables, include all others
172+
// Filter: exclude _parent variables and invalid variable names
169173
return Object.keys(variables)
170-
.filter(variable => !variable.startsWith('_parent.'))
174+
.filter(variable => this.isValidVariableName(variable))
171175
.sort();
172176
},
173177
@@ -211,6 +215,22 @@ export default {
211215
return this.requiredVariables.filter(
212216
variable => !this.selectedVariables.includes(variable)
213217
);
218+
},
219+
220+
/**
221+
* Check if all filtered variables are selected
222+
*/
223+
allSelected() {
224+
return this.filteredVariables.length > 0 &&
225+
this.filteredVariables.every(v => this.selectedVariables.includes(v));
226+
},
227+
228+
/**
229+
* Check if some (but not all) filtered variables are selected
230+
*/
231+
someSelected() {
232+
const selectedCount = this.filteredVariables.filter(v => this.selectedVariables.includes(v)).length;
233+
return selectedCount > 0 && selectedCount < this.filteredVariables.length;
214234
}
215235
},
216236
watch: {
@@ -231,8 +251,13 @@ export default {
231251
this.$emit('change', []);
232252
}
233253
},
234-
isEnabled(newValue) {
235-
if (!newValue) {
254+
isEnabled(newValue, oldValue) {
255+
if (newValue && !oldValue) {
256+
// When enabled for the first time, select all variables
257+
this.selectedVariables = [...this.availableVariables];
258+
this.$emit('input', this.selectedVariables);
259+
this.$emit('change', this.selectedVariables);
260+
} else if (!newValue) {
236261
// When disabled, clear selection to submit all variables
237262
this.selectedVariables = [];
238263
this.$emit('input', []);
@@ -250,6 +275,11 @@ export default {
250275
'$root.computed'() {
251276
// Force recomputation when computed properties change
252277
this.$forceUpdate();
278+
},
279+
// Watch for watchers changes in App.vue
280+
'$root.watchers'() {
281+
// Force recomputation when watchers change
282+
this.$forceUpdate();
253283
}
254284
},
255285
methods: {
@@ -289,13 +319,38 @@ export default {
289319
this.selectedVariables = this.selectedVariables.filter(v => !filteredSet.has(v));
290320
},
291321
322+
toggleSelectAll(checked) {
323+
if (checked) {
324+
this.selectAll();
325+
} else {
326+
this.deselectAll();
327+
}
328+
},
329+
292330
toggleSearch() {
293331
this.showSearch = !this.showSearch;
294332
if (!this.showSearch) {
295333
this.searchQuery = '';
296334
}
297335
},
298336
337+
/**
338+
* Check if a variable name is valid
339+
* Uses same logic as dot_notation validation rule
340+
*/
341+
isValidVariableName(name) {
342+
if (!name || typeof name !== 'string') {
343+
return false;
344+
}
345+
if (name.startsWith('_parent.')) {
346+
return false;
347+
}
348+
// Same regex as dot_notation: starts with letter, followed by letters, numbers, or underscores
349+
const validPartRegex = /^[a-zA-Z][a-zA-Z0-9_]*$/;
350+
const parts = name.split('.');
351+
return parts.every(part => validPartRegex.test(part));
352+
},
353+
299354
/**
300355
* Extract calculated variables (computed properties) from the screen
301356
* Searches in multiple locations: App.vue, builder, or parent components
@@ -348,6 +403,47 @@ export default {
348403
349404
return [];
350405
},
406+
407+
/**
408+
* Extract watcher output variables from the screen
409+
*/
410+
extractWatcherVariables() {
411+
const watcherVars = {};
412+
const watchers = this.getWatchers() || [];
413+
414+
watchers.forEach(watcher => {
415+
if (watcher.byPass) return;
416+
417+
// Output variable (for scripts)
418+
if (watcher.output_variable) {
419+
watcherVars[watcher.output_variable] = null;
420+
}
421+
422+
// Data mapping variables (for data sources)
423+
try {
424+
const config = typeof watcher.script_configuration === 'string'
425+
? JSON.parse(watcher.script_configuration)
426+
: watcher.script_configuration;
427+
(config?.dataMapping || []).forEach(m => {
428+
if (m.key) watcherVars[m.key] = null;
429+
});
430+
} catch {
431+
console.error('Invalid JSON in script_configuration for watcher:', watcher.name);
432+
}
433+
});
434+
435+
return watcherVars;
436+
},
437+
438+
/**
439+
* Get watchers from various sources
440+
*/
441+
getWatchers() {
442+
return this.$root?.$data?.watchers
443+
|| this.$root?.$children?.[0]?.watchers
444+
|| this.$root?.$children?.[0]?.$data?.watchers
445+
|| [];
446+
},
351447
352448
/**
353449
* Extract variables from form config
@@ -634,25 +730,16 @@ export default {
634730
margin-top: 0;
635731
}
636732
637-
.select-all-button {
638-
background: none;
639-
border: none;
640-
padding: 0;
641-
color: #0d6efd;
642-
font-size: 15px;
733+
.select-all-checkbox {
734+
margin: 0;
735+
font-size: 14px;
643736
font-weight: 600;
644-
cursor: pointer;
645-
text-decoration: none;
646-
}
647-
648-
.select-all-button:hover:not(:disabled) {
649-
color: #0a58ca;
650-
text-decoration: none;
737+
color: #495057;
651738
}
652739
653-
.select-all-button:disabled {
654-
color: #adb5bd;
655-
cursor: not-allowed;
740+
.select-all-checkbox >>> .custom-control-label {
741+
cursor: pointer;
742+
user-select: none;
656743
}
657744
658745
.search-button {

0 commit comments

Comments
 (0)