Skip to content

Commit

Permalink
#362 added possibility to enable scheduling via admin UI
Browse files Browse the repository at this point in the history
  • Loading branch information
bugy committed Feb 17, 2023
1 parent 52e3449 commit 413d96e
Show file tree
Hide file tree
Showing 10 changed files with 233 additions and 49 deletions.
1 change: 1 addition & 0 deletions src/model/script_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,7 @@ def get_sorted_config(config):
'output_files',
'requires_terminal',
'output_format',
'scheduling',
'parameters']

def get_order(key):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default {
height: 100%;
}
.script-config h5 {
.script-config >>> h5 {
margin-left: 0.75rem;
margin-top: 0.5rem;
margin-bottom: 2rem;
Expand Down
121 changes: 81 additions & 40 deletions web-src/src/admin/components/scripts-config/ScriptConfigForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,6 @@
<div class="row">
<TextArea v-model="description" :config="descriptionField" class="col s12"/>
</div>
<div class="row">
<div v-if="allowAllUsers" class="input-field col s9">
<input id="allowed_users_disabled" disabled type="text" value="All users">
<label class="active" for="allowed_users_disabled">Allowed users</label>
</div>
<ChipsList v-else v-model="allowedUsers" class="col s9" title="Allowed users"/>
<CheckBox v-model="allowAllUsers" :config="allowAllField"
class="col s2 offset-s1 checkbox-field"/>
</div>

<div class="row">
<div v-if="allowAllAdmins" class="input-field col s9">
<input id="admin_users_disabled" disabled type="text" value="Any admin">
<label class="active" for="admin_users_disabled">Admin users</label>
</div>
<ChipsList v-else v-model="adminUsers" class="col s9" title="Admin users"/>
<CheckBox v-model="allowAllAdmins" :config="allowAllAdminsField"
class="col s2 offset-s1 checkbox-field"/>
</div>

<div class="row">
<Combobox v-model="outputFormat" :config="outputFormatField" class="col s3"/>
Expand All @@ -39,36 +20,74 @@
<TextField v-model="includeScript" :config="includeScriptField" class="col s5 offset-s1"/>
</div>

<div class="row">
<CheckBox v-model="globalInstances" :config="globalInstancesField"
class="col s3 checkbox-field"/>
<div>
<h5>Access</h5>
<div class="row">
<div v-if="allowAllUsers" class="input-field col s9">
<input id="allowed_users_disabled" disabled type="text" value="All users">
<label class="active" for="allowed_users_disabled">Allowed users</label>
</div>
<ChipsList v-else v-model="allowedUsers" class="col s9" title="Allowed users"/>
<CheckBox v-model="allowAllUsers" :config="allowAllField"
class="col s2 offset-s1 checkbox-field"/>
</div>
<div class="row">
<div v-if="allowAllAdmins" class="input-field col s9">
<input id="admin_users_disabled" disabled type="text" value="Any admin">
<label class="active" for="admin_users_disabled">Admin users</label>
</div>
<ChipsList v-else v-model="adminUsers" class="col s9" title="Admin users"/>
<CheckBox v-model="allowAllAdmins" :config="allowAllAdminsField"
class="col s2 offset-s1 checkbox-field"/>
</div>
<div class="row">
<CheckBox v-model="globalInstances" :config="globalInstancesField"
class="col s3 checkbox-field"/>
</div>
</div>

<div>
<h5>Scheduling</h5>
<div class="row">
<div class="col s12">This section allows users to schedule scripts to be executed in the future.</div>
</div>
<div class="row">
<CheckBox v-model="schedulingEnabled" :config="schedulingEnabledField"
class="col s3 checkbox-field"/>
<CheckBox v-model="schedulingAutoCleanup" :config="schedulingAutoCleanupField"
:disabled="schedulingAutoCleanupDisabled || !schedulingEnabled"
class="col s3 checkbox-field"/>
</div>
</div>

</form>
</template>

<script>
import ScriptPathField from '@/admin/components/scripts-config/script-edit/ScriptField'
import {allowAllAdminsField} from '@/admin/components/scripts-config/script-fields';
import {NEW_SCRIPT} from '@/admin/store/script-config-module'
import CheckBox from '@/common/components/checkbox';
import ChipsList from '@/common/components/ChipsList';
import Combobox from '@/common/components/combobox'
import TextArea from '@/common/components/TextArea';
import TextField from '@/common/components/textfield'
import {forEachKeyValue, isEmptyArray, isEmptyString, isNull} from '@/common/utils/common';
import get from 'lodash/get';
import {
allowAllField,
descriptionField,
globalInstancesField,
groupField,
includeScriptField,
nameField,
outputFormatField,
requiresTerminalField,
globalInstancesField,
schedulingAutoCleanupField,
schedulingEnabledField,
scriptPathField,
workDirField
} from './script-fields';
import {allowAllAdminsField} from '@/admin/components/scripts-config/script-fields';
import Combobox from '@/common/components/combobox'
import ScriptPathField from '@/admin/components/scripts-config/script-edit/ScriptField'
import {NEW_SCRIPT} from '@/admin/store/script-config-module'
export default {
Expand All @@ -93,6 +112,9 @@ export default {
workingDirectory: null,
requiresTerminal: null,
globalInstances: null,
schedulingEnabled: null,
schedulingAutoCleanup: null,
schedulingAutoCleanupDisabled: null,
includeScript: null,
outputFormat: null,
allowedUsers: [],
Expand All @@ -109,6 +131,8 @@ export default {
outputFormatField,
requiresTerminalField,
globalInstancesField,
schedulingEnabledField,
schedulingAutoCleanupField,
includeScriptField
}
},
Expand All @@ -133,15 +157,6 @@ export default {
}
});
});
this.$watch('globalInstances', (globalInstances) => {
if (globalInstances) {
this.$set(this.value, 'access', {'shared_access': {'type': 'ALL_USERS'}});
} else {
this.$delete(this.value, 'access');
}
});
},
watch: {
Expand All @@ -153,12 +168,14 @@ export default {
this.description = config['description'];
this.workingDirectory = config['working_directory'];
this.requiresTerminal = get(config, 'requires_terminal', true);
this.globalInstances = false;
if (config?.access?.shared_access?.type == "ALL_USERS"){
this.globalInstances = true;
}
this.globalInstances = config?.access?.shared_access?.type === 'ALL_USERS';
this.includeScript = config['include'];
this.outputFormat = config['output_format'];
this.schedulingEnabled = config.scheduling?.enabled === true
this.schedulingAutoCleanupDisabled = !isEmptyArray(config['output_files'])
this.schedulingAutoCleanup = this.schedulingAutoCleanupDisabled ? false : config.scheduling?.['auto_cleanup']
this.updateAccessFieldInVm(config,
'allowedUsers',
'allowAllUsers',
Expand All @@ -180,6 +197,19 @@ export default {
},
adminUsers() {
this.updateAdminUsers();
},
globalInstances() {
if (this.globalInstances) {
this.$set(this.value, 'access', {'shared_access': {'type': 'ALL_USERS'}});
} else {
this.$delete(this.value, 'access');
}
},
schedulingEnabled() {
this.updateScheduling()
},
schedulingAutoCleanup() {
this.updateScheduling()
}
},
Expand Down Expand Up @@ -217,6 +247,17 @@ export default {
}
this[vmPropertyName] = users.filter(u => u !== '*');
this[vmAllowAllPropertyName] = isNull(config[valuePropertyName]) || users.includes('*');
},
updateScheduling() {
if (this.schedulingEnabled) {
const schedulingConf = {'enabled': this.schedulingEnabled}
if (!isNull(this.schedulingAutoCleanup) && (!this.schedulingAutoCleanupDisabled)) {
schedulingConf['auto_cleanup'] = this.schedulingAutoCleanup
}
this.$set(this.value, 'scheduling', schedulingConf)
} else {
this.$delete(this.value, 'scheduling')
}
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions web-src/src/admin/components/scripts-config/script-fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,15 @@ export const includeScriptField = {
export const globalInstancesField = {
name: 'Shared Script Instances',
description: 'Allows script instances to be shared by all users'
};

export const schedulingEnabledField = {
name: 'Enabled',
description: 'Enables possibility to schedule scripts'
};

export const schedulingAutoCleanupField = {
name: 'Auto cleanup',
description: 'Mark finished scripts as seen by user, i.e. remove from active tabs. '
+ 'Always disabled when output_files are specified'
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.script-server [type=checkbox]:not(:checked):disabled + span:not(.lever):before {
.script-server [type=checkbox]:not(:checked):not(:indeterminate):disabled + span:not(.lever):before {
background: none;
border: 2px solid var(--font-color-disabled);
}
14 changes: 12 additions & 2 deletions web-src/src/common/components/checkbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,24 @@
ref="checkbox"
:checked="boolValue"
type="checkbox"
:disabled="disabled"
@input="emitValueChange"/>
<span>{{ config.name }}</span>
</label>
</template>

<script>
import {toBoolean} from '@/common/utils/common';
import {isNull, toBoolean} from '@/common/utils/common';
export default {
props: {
'value': {
type: [Boolean, String, Number]
},
'config': Object
'config': Object,
'disabled': {
type: [Boolean]
}
},
computed: {
Expand All @@ -27,11 +31,17 @@ export default {
},
mounted: function () {
this.$refs.checkbox.indeterminate = isNull(this.value)
this.emitValueChange();
},
methods: {
emitValueChange() {
if (this.$refs.checkbox.indeterminate) {
this.$emit('input', undefined);
return;
}
this.$emit('input', this.$refs.checkbox.checked);
}
},
Expand Down
1 change: 1 addition & 0 deletions web-src/src/common/utils/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ export function setInputValue(inputField, value, triggerEvent) {

if (inputField.type === 'checkbox') {
inputField.checked = value;
inputField.indeterminate = isNull(value)
} else {
inputField.value = value;
}
Expand Down
2 changes: 0 additions & 2 deletions web-src/src/login/login.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,6 @@ function processCurrentOauthState() {
var queryStateToken = getQueryParameter('state');
if (oauthState || oauthResponseCode) {
if (!oauthState && oauthResponseCode) {
console.log('oauth_state=' + oauthState);
console.log('oauthResponseCode=' + oauthResponseCode);
showError('Invalid client state. Please try to relogin');
return;
}
Expand Down
18 changes: 16 additions & 2 deletions web-src/src/main-app/components/scripts/script-parameters-view.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
:is="getComponentType(parameter)"
:key="parameter.name"
:config="parameter"
:value="parameterValues[parameter.name]"
:value="getParameterValue(parameter)"
:class="{'inline': isInline(parameter)}"
class="parameter"
:forceValue="forcedValueParameters.includes(parameter.name)"
Expand All @@ -20,10 +20,11 @@ import Checkbox from '@/common/components/checkbox'
import Combobox from '@/common/components/combobox'
import FileUpload from '@/common/components/file_upload'
import ServerFileField from '@/common/components/server_file_field'
import TextArea from '@/common/components/TextArea'
import Textfield from '@/common/components/textfield'
import {isNull} from '@/common/utils/common';
import {mapActions, mapState} from 'vuex'
import {comboboxTypes, isRecursiveFileParameter} from '../../utils/model_helper'
import TextArea from '@/common/components/TextArea'
export default {
name: 'script-parameters-view',
Expand Down Expand Up @@ -69,6 +70,19 @@ export default {
setParameterValue(parameterName, value) {
this.setParameterValueInStore({parameterName, value});
},
getParameterValue(parameter) {
const value = this.parameterValues[parameter.name];
if (!isNull(value)) {
return value;
}
if (parameter.withoutValue) {
return false;
}
return value;
}
}
}
Expand Down
Loading

0 comments on commit 413d96e

Please sign in to comment.