From d6c8559db2bd9109b58b28d405f5102bf70b05ca Mon Sep 17 00:00:00 2001 From: Sergey Klyuykov Date: Wed, 4 Sep 2019 17:54:57 +1000 Subject: [PATCH 01/11] Update documentation and add extras for installation with mysql or pgsql --- doc/api_schema.yaml | 10 +++++----- doc/conf.py | 2 +- doc/installation.rst | 2 +- polemarch/__init__.py | 2 +- setup.py | 2 ++ 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/api_schema.yaml b/doc/api_schema.yaml index 0d4b4b55..d0244c3a 100755 --- a/doc/api_schema.yaml +++ b/doc/api_schema.yaml @@ -19,9 +19,9 @@ info: url: https://gitlab.com/vstconsulting/polemarch.git Request: - name: Question - url: https://gitlab.com/vstconsulting/polemarch/issues/new?issuable_template%5D=Ask&issue%5Btitle%5D=Ask%20about%20version%201.4.3 + url: https://gitlab.com/vstconsulting/polemarch/issues/new?issuable_template%5D=Ask&issue%5Btitle%5D=Ask%20about%20version%201.4.4 - name: Bug report - url: https://gitlab.com/vstconsulting/polemarch/issues/new?issuable_template%5D=Bug&issue%5Btitle%5D=Bug%20in%20version%201.4.3 + url: https://gitlab.com/vstconsulting/polemarch/issues/new?issuable_template%5D=Bug&issue%5Btitle%5D=Bug%20in%20version%201.4.4 - name: Feature request url: https://gitlab.com/vstconsulting/polemarch/issues/new?issuable_template%5D=Feature%20request&issue%5Btitle%5D= x-menu: @@ -54,9 +54,9 @@ info: span_class: fa fa-plug url: /hook x-versions: - application: 1.4.3 - library: 1.4.3 - vstutils: 2.6.3 + application: 1.4.4 + library: 1.4.4 + vstutils: 2.6.6 django: 2.2.4 ansible: 2.8.4 version: v2 diff --git a/doc/conf.py b/doc/conf.py index ab97eb5c..b927b691 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -53,7 +53,7 @@ # General information about the project. project = 'Polemarch' -copyright = '2018, VST Consulting' +copyright = '2019, VST Consulting' author = 'VST Consulting' # The version info for the project you're documenting, acts as replacement for diff --git a/doc/installation.rst b/doc/installation.rst index 1c8cb353..374f726c 100644 --- a/doc/installation.rst +++ b/doc/installation.rst @@ -46,7 +46,7 @@ Install from PyPI .. sourcecode:: bash - pip install -U polemarch mysqlclient + pip install -U polemarch[mysql] #. Edit config file: diff --git a/polemarch/__init__.py b/polemarch/__init__.py index 9a9b1b7c..81ad951e 100644 --- a/polemarch/__init__.py +++ b/polemarch/__init__.py @@ -31,6 +31,6 @@ "VST_ROOT_URLCONF": os.getenv("VST_ROOT_URLCONF", 'vstutils.urls'), } -__version__ = "1.4.3" +__version__ = "1.4.4" prepare_environment(**default_settings) diff --git a/setup.py b/setup.py index 54cd2242..ed7a3a8f 100644 --- a/setup.py +++ b/setup.py @@ -359,6 +359,8 @@ def make_setup(**opts): load_requirements('requirements.txt', os.getcwd()), extras_require={ 'test': load_requirements('requirements-test.txt', os.getcwd()), + 'mysql': ['mysqlclient'], + 'postgresql': ['psycopg2'], }, dependency_links=[ ] + load_requirements('requirements-git.txt', os.getcwd()), From eb9e65ba22e497e327b79660ebf5fcea23e18e8c Mon Sep 17 00:00:00 2001 From: Roman Date: Mon, 9 Sep 2019 11:50:19 +1000 Subject: [PATCH 02/11] Fix one_history_date_time field. polemarch/ce#225 --- polemarch/static/js/pmFields.js | 3 +-- polemarch/static/js/tests/pmFields.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/polemarch/static/js/pmFields.js b/polemarch/static/js/pmFields.js index 42ef771e..4161b16a 100644 --- a/polemarch/static/js/pmFields.js +++ b/polemarch/static/js/pmFields.js @@ -295,8 +295,7 @@ guiFields.one_history_date_time = class OneHistoryDateTime extends guiFields.dat return; } - return moment(value).tz(window.timeZone).format("YYYY-MM-DD") + - ' ' + moment(value).tz(window.timeZone).format("HH:mm:ss"); + return moment(moment.tz(value, window.timeZone)).tz(moment.tz.guess()).format("YYYY-MM-DD HH:mm:ss"); }; }; diff --git a/polemarch/static/js/tests/pmFields.js b/polemarch/static/js/tests/pmFields.js index ea66aaac..b84702ba 100644 --- a/polemarch/static/js/tests/pmFields.js +++ b/polemarch/static/js/tests/pmFields.js @@ -139,7 +139,7 @@ window.qunitTestsArray['guiFields[field].{toInner, toRepresent}() - PM'] = { input: {test_field: '2019-05-08T07:08:07'}, output: { toInner: '2019-05-08T07:08:07' + (window.timeZone == 'UTC' ? 'Z' : moment.tz(window.timeZone).format('Z')), - toRepresent: '2019-05-08 07:08:07', + toRepresent: moment(moment.tz('2019-05-08T07:08:07', window.timeZone)).tz(moment.tz.guess()).format('YYYY-MM-DD HH:mm:ss'), }, } ], From 7d1440ca981383f2b518b34d9736827be3227a56 Mon Sep 17 00:00:00 2001 From: Sergey Klyuykov Date: Mon, 9 Sep 2019 12:19:14 +1000 Subject: [PATCH 03/11] Update vstutils version --- requirements-doc.txt | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-doc.txt b/requirements-doc.txt index 00bbdcfb..7704600d 100644 --- a/requirements-doc.txt +++ b/requirements-doc.txt @@ -1,2 +1,2 @@ # Docs -vstutils[doc]~=2.6.3 +vstutils[doc]~=2.7.0 diff --git a/requirements.txt b/requirements.txt index 2908bb12..0f261a39 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main -vstutils[rpc,ldap,doc,prod]~=2.6.3 +vstutils[rpc,ldap,doc,prod]~=2.7.0 docutils==0.15.2 markdown2==2.3.8 From 4a8c45a1c26da347ee22390f6c9ecf60770a39ad Mon Sep 17 00:00:00 2001 From: Kirill Bychkov Date: Mon, 9 Sep 2019 21:11:40 +1000 Subject: [PATCH 04/11] Add jshint support --- .gitlab-ci.yml | 2 +- .jshintrc | 69 +++++++ polemarch/static/js/pmCustomizer.js | 4 +- polemarch/static/js/pmDashboard.js | 236 ++++++++++++----------- polemarch/static/js/pmFields.js | 44 +++-- polemarch/static/js/pmFieldsMixins.js | 98 +++++----- polemarch/static/js/pmGroups.js | 10 +- polemarch/static/js/pmHistory.js | 254 +++++++++++++------------ polemarch/static/js/pmHosts.js | 14 +- polemarch/static/js/pmInventories.js | 6 +- polemarch/static/js/pmItems.js | 8 +- polemarch/static/js/pmPeriodicTasks.js | 55 +++--- polemarch/static/js/pmProjects.js | 60 +++--- polemarch/static/js/pmTemplates.js | 197 ++++++++++--------- polemarch/static/js/pmUsers.js | 96 +++++----- tox.ini | 9 + 16 files changed, 649 insertions(+), 513 deletions(-) create mode 100644 .jshintrc diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 36f8987d..bc89ba13 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -63,7 +63,7 @@ code_style: variables: TOX_ARGS: "--workdir /cache/.tox_polemarch_code" script: - - make test ENVS=flake,pylint + - make test ENVS=flake,pylint,jshint except: refs: - tags diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..0156441a --- /dev/null +++ b/.jshintrc @@ -0,0 +1,69 @@ +{ + "maxerr": 99999, + "curly": true, + "esversion": 9, + "forin": true, + "freeze": true, + "latedef": true, + "leanswitch": true, + "maxdepth": 5, + "undef": true, + "unused": "strict", + "debug": true, + "varstmt": true, + "loopfunc": true, + + "browser": true, + "devel": true, + + "globals": { + "addCssClassesToElement": true, + "ApiConnector": true, + "api_connector_config": true, + "app": true, + "BaseEntityConstructor": true, + "base_field_content_readonly_mixin": true, + "base_field_label_mixin": true, + "capitalizeString": true, + "current_view": true, + "deepEqual": true, + "ErrorHandler": true, + "fieldsRegistrator": true, + "field_fk_content_readonly_mixin": true, + "findClosestPath": true, + "guiFields": true, + "guiLocalSettings": true, + "guiPopUp": true, + "guiSkins": true, + "guiWidgets": true, + "gui_fields_mixins": true, + "guiCustomizer": true, + "guiDashboard": true, + "guiModels": true, + "guiQuerySets": true, + "hostname": true, + "IMask": true, + "isEmptyObject": true, + "iziToast": true, + "modal_window_and_button_mixin": true, + "moment": true, + "my_user_id": true, + "onLoadingErrorHandler": true, + "openapi_dictionary": true, + "path_pk_key": true, + "pop_up_msg": true, + "project_connected_models_dict": true, + "StatusError": true, + "SubViewWithOutApiPathConstructor": true, + "table_row_mixin": true, + "tabSignal": true, + "trim": true, + "View": true, + "ViewConstructor": true, + "view_with_autoupdate_mixin": true, + "vst_vue_components": true, + "Vue": true, + "XRegExp": true, + "$": true + } +} \ No newline at end of file diff --git a/polemarch/static/js/pmCustomizer.js b/polemarch/static/js/pmCustomizer.js index 91f9a344..e310b8d1 100644 --- a/polemarch/static/js/pmCustomizer.js +++ b/polemarch/static/js/pmCustomizer.js @@ -1,7 +1,7 @@ /** * Mixin, that extends guiSkins.default. */ -var pmSkinDefaultMixin = { +const pmSkinDefaultMixin = { history_status_ok: { color_var:"--history-status-ok", title:'History status ok', @@ -121,7 +121,7 @@ guiSkins.default = $.extend(true, guiSkins.default, pmSkinDefaultMixin); /** * Mixin, that extends guiSkins.dark. */ -var pmSkinDarkMixin = { +const pmSkinDarkMixin = { history_status_ok: { default:"#56E401", }, diff --git a/polemarch/static/js/pmDashboard.js b/polemarch/static/js/pmDashboard.js index 3e62b0a1..a4bff778 100644 --- a/polemarch/static/js/pmDashboard.js +++ b/polemarch/static/js/pmDashboard.js @@ -1,3 +1,67 @@ + +/** + * Function, that returns QuerySet for profile/setting page. + */ +function getProfileSettingQsFromStore() { + let qs = app.application.$store.getters.getQuerySet('user/' + my_user_id + '/settings'); + + if(!qs) { + return; + } + + return qs.copy(); +} + +/** + * Function, that updates data of QuerySet for profile/setting page + * and saves updated queryset in store. + * @param {object} qs QuerySet for profile/setting page + */ +function updateProfileSettingsQsAndSave(qs) { + qs.formQueryAndSend('post', qs.cache.data).then(response => { /* jshint unused: false */ + app.application.$store.commit('setQuerySet', { + url: qs.url, + queryset: qs, + }); + }).catch(error => { /* jshint unused: false */ + debugger; + }); +} + +/** + * This function is supposed to be called from 'GuiCustomizer.skin.name.changed' tabSignal. + * This function updates selected skin and saves ProfileSettings QuerySet. + * @param {object} customizer GuiCustomizer instance. + */ +function guiCustomizerSkinOnChangeHandler(customizer) { + let qs = getProfileSettingQsFromStore(); + + if(!qs) { + return; + } + + qs.cache.data.selectedSkin = customizer.skin.name; + + return updateProfileSettingsQsAndSave(qs); +} + +/** + * This function is supposed to be called from 'GuiCustomizer.skins_custom_settings.saved' tabSignal. + * This function updates skins_custom_settings and saves ProfileSettings QuerySet. + * @param {object} customizer GuiCustomizer instance. + */ +function guiCustomizerCustomSettingsOnSaveHandler(customizer) { + let qs = getProfileSettingQsFromStore(); + + if(!qs) { + return; + } + + qs.cache.data.skinsSettings = customizer.skins_custom_settings; + + return updateProfileSettingsQsAndSave(qs); +} + /** * Class of history chart widget. */ @@ -79,7 +143,7 @@ guiWidgets.history_chart = class HistoryChart extends guiWidgets.line_chart { * @returns {Array} * @private */ - _formChartDataLabels(raw_data) { + _formChartDataLabels(raw_data) { /* jshint unused: false */ let labels = []; let start_time = this._getChartStartTime(); @@ -99,11 +163,11 @@ guiWidgets.history_chart = class HistoryChart extends guiWidgets.line_chart { _formChartDataDatasets_oneLine(line, raw_data, labels) { let data = {}; - for(let index in labels) { + for(let index = 0; index < labels.length; index++) { data[labels[index]] = 0; } - for(let index in raw_data[this.period.type]) { + for(let index = 0; index < raw_data[this.period.type].length; index++) { let item = raw_data[this.period.type][index]; let time =+ moment(item[this.period.type]).tz(window.timeZone).format("x"); @@ -132,17 +196,21 @@ guiWidgets.history_chart = class HistoryChart extends guiWidgets.line_chart { _formChartDataDatasets(raw_data, labels) { let datasets = []; - for(let index in this.lines) { - let line = this.lines[index]; + for(let key in this.lines) { + if(this.lines.hasOwnProperty(key)) { + let line = this.lines[key]; - if(!line.active) continue; + if (!line.active) { + continue; + } - datasets.push({ - label: line.title || line.name, - data: this._formChartDataDatasets_oneLine(line, raw_data, labels), - borderColor: this._getChartLineColor(line), - backgroundColor: this._getChartLineColor(line, true), - }); + datasets.push({ + label: line.title || line.name, + data: this._formChartDataDatasets_oneLine(line, raw_data, labels), + borderColor: this._getChartLineColor(line), + backgroundColor: this._getChartLineColor(line, true), + }); + } } return datasets; @@ -166,8 +234,8 @@ guiWidgets.history_chart = class HistoryChart extends guiWidgets.line_chart { if(skin['history_status_' + line.name]) { if(skin['history_status_' + line.name][0] == "#") { - let color = hexToRgbA(skin['history_status_' + line.name], alpha); - return color + let color = hexToRgbA(skin['history_status_' + line.name], alpha); /* globals hexToRgbA */ + return color; } return skin['history_status_' + line.name]; @@ -184,22 +252,26 @@ guiWidgets.history_chart = class HistoryChart extends guiWidgets.line_chart { let all = 0; let data = {}; - for(let index in this.lines) { - let line = this.lines[index]; + for(let key in this.lines) { + if(this.lines.hasOwnProperty(key)) { + let line = this.lines[key]; - if(line.name == 'all_tasks') continue; + if (line.name == 'all_tasks') { + continue; + } - data[line.name] = { - all: all, - sum: 0, - status: line.name.toUpperCase(), + data[line.name] = { + all: all, + sum: 0, + status: line.name.toUpperCase(), + }; } } if(raw_data && raw_data.year) { let stats = raw_data.year; - for(let index in stats) { + for(let index = 0; index < stats.length; index++) { let record = stats[index]; let status = record.status.toLowerCase(); @@ -211,11 +283,15 @@ guiWidgets.history_chart = class HistoryChart extends guiWidgets.line_chart { } for(let key in data) { - all += data[key].sum; + if(data.hasOwnProperty(key)){ + all += data[key].sum; + } } for(let key in data) { - data[key].all = all; + if(data.hasOwnProperty(key)){ + data[key].all = all; + } } } @@ -273,9 +349,9 @@ guiWidgets.history_chart = class HistoryChart extends guiWidgets.line_chart { }); /** - * Sets Dashboard history chart widget. + * Sets Dashboard history `chart` widget. */ -guiDashboard.widgets['pmwChartWidget'] = new guiWidgets.history_chart( +guiDashboard.widgets.pmwChartWidget = new guiWidgets.history_chart( { name: 'pmwChartWidget', title:'Tasks history', sort:7, lines: { @@ -346,14 +422,18 @@ guiDashboard.widgets['pmwChartWidget'] = new guiWidgets.history_chart( */ guiDashboard.updateWidgetSettings = function(settings) { for(let key in settings) { - let s_item = settings[key]; + if(settings.hasOwnProperty(key)) { + let s_item = settings[key]; - if(!this.widgets[key]) { - continue; - } + if (!this.widgets[key]) { + continue; + } - for(let prop in s_item) { - this.widgets[key][prop] = s_item[prop]; + for (let prop in s_item) { + if(s_item.hasOwnProperty(prop)) { + this.widgets[key][prop] = s_item[prop]; + } + } } } }; @@ -364,15 +444,16 @@ guiDashboard.updateWidgetSettings = function(settings) { */ guiDashboard.updateChartLineSettings = function(settings) { for(let key in settings) { - if(!this.widgets['pmwChartWidget'].lines[key]) { + if(!this.widgets.pmwChartWidget.lines[key]) { continue; } let s_item = settings[key]; for(let prop in s_item) { - this.widgets['pmwChartWidget'].lines[key][prop] = s_item[prop]; - } + if(s_item.hasOwnProperty(prop)) { + this.widgets.pmwChartWidget.lines[key][prop] = s_item[prop]; + }} } }; @@ -401,7 +482,7 @@ guiDashboard.updateSettings = function(settings) { guiDashboard.updateWidgetSettings(settings.widgetSettings); } - if(settings.chartLineSettings && guiDashboard.widgets['pmwChartWidget']) { + if(settings.chartLineSettings && guiDashboard.widgets.pmwChartWidget) { guiLocalSettings.set('chart_line_settings', settings.chartLineSettings); guiDashboard.updateChartLineSettings(settings.chartLineSettings); } @@ -419,8 +500,8 @@ if(guiLocalSettings.get('chart_period')) { guiDashboard.widgets.pmwChartWidget.setChartPeriod(guiLocalSettings.get('chart_period')); } -customRoutesComponentsTemplates.home = { - mixins: [the_basest_view_mixin, view_with_autoupdate_mixin], +customRoutesComponentsTemplates.home = { /* globals customRoutesComponentsTemplates */ + mixins: [the_basest_view_mixin, view_with_autoupdate_mixin], /* globals the_basest_view_mixin */ template: "#template_pm_dashboard", data() { return { @@ -439,7 +520,7 @@ customRoutesComponentsTemplates.home = { * Updates widgets' data, when chart widget period was changed. * @param value */ - 'widgets.pmwChartWidget.period': function(value) { + 'widgets.pmwChartWidget.period': function(value) { /* jshint unused: false */ this.setWidgetsData().then(data => { this.widgets_data = data; }); @@ -517,11 +598,13 @@ customRoutesComponentsTemplates.home = { let w_data = {}; for(let key in response.data) { - if(exclude_stats.includes(key)) { - w_data['pmwChartWidget'] = response.data[key]; - } + if (response.data.hasOwnProperty(key)) { + if (exclude_stats.includes(key)) { + w_data.pmwChartWidget = response.data[key]; + } - w_data['pmw' + capitalizeString(key) + 'Counter'] = response.data[key]; + w_data['pmw' + capitalizeString(key) + 'Counter'] = response.data[key]; + } } this.$store.commit('setWidgets', { @@ -568,74 +651,11 @@ tabSignal.connect('app.afterInit', (obj) => { app.application.$store.commit('setQuerySet', { url: qs.url, queryset: qs, - }) + }); } tabSignal.connect('GuiCustomizer.skin.name.changed', guiCustomizerSkinOnChangeHandler); tabSignal.connect('GuiCustomizer.skins_custom_settings.saved', guiCustomizerCustomSettingsOnSaveHandler); tabSignal.connect('GuiCustomizer.skins_custom_settings.reseted', guiCustomizerCustomSettingsOnSaveHandler); }); -}); - -/** - * Function, that returns QuerySet for profile/setting page. - */ -function getProfileSettingQsFromStore() { - let qs = app.application.$store.getters.getQuerySet('user/' + my_user_id + '/settings'); - - if(!qs) { - return; - } - - return qs.copy(); -} - -/** - * Function, that updates data of QuerySet for profile/setting page - * and saves updated queryset in store. - * @param {object} qs QuerySet for profile/setting page - */ -function updateProfileSettingsQsAndSave(qs) { - qs.formQueryAndSend('post', qs.cache.data).then(response => { - app.application.$store.commit('setQuerySet', { - url: qs.url, - queryset: qs, - }); - }).catch(error => { - debugger; - }); -} - -/** - * This function is supposed to be called from 'GuiCustomizer.skin.name.changed' tabSignal. - * This function updates selected skin and saves ProfileSettings QuerySet. - * @param {object} customizer GuiCustomizer instance. - */ -function guiCustomizerSkinOnChangeHandler(customizer) { - let qs = getProfileSettingQsFromStore(); - - if(!qs) { - return; - } - - qs.cache.data.selectedSkin = customizer.skin.name; - - return updateProfileSettingsQsAndSave(qs); -} - -/** - * This function is supposed to be called from 'GuiCustomizer.skins_custom_settings.saved' tabSignal. - * This function updates skins_custom_settings and saves ProfileSettings QuerySet. - * @param {object} customizer GuiCustomizer instance. - */ -function guiCustomizerCustomSettingsOnSaveHandler(customizer) { - let qs = getProfileSettingQsFromStore(); - - if(!qs) { - return; - } - - qs.cache.data.skinsSettings = customizer.skins_custom_settings; - - return updateProfileSettingsQsAndSave(qs); -} \ No newline at end of file +}); \ No newline at end of file diff --git a/polemarch/static/js/pmFields.js b/polemarch/static/js/pmFields.js index 4161b16a..0cb94197 100644 --- a/polemarch/static/js/pmFields.js +++ b/polemarch/static/js/pmFields.js @@ -77,7 +77,7 @@ guiFields.playbook_autocomplete = class PlaybookAutocompleteField extends guiFie * @return {boolean} * @private */ - _prefetchDataOrNot(data) { + _prefetchDataOrNot(data) { /* jshint unused: false */ return false; } /** @@ -109,12 +109,12 @@ guiFields.group_autocomplete = class GroupAutocompleteField extends guiFields.pl */ guiFields.history_initiator = class HistoryInitiatorField extends guiFields.fk { static get initiatorTypes() { - return history_initiator_types; + return history_initiator_types; /* globals history_initiator_types */ } /** * Redefinition of 'getAppropriateQuerySet' method of fk guiField. */ - getAppropriateQuerySet(data={}, querysets) { + getAppropriateQuerySet(data={}, querysets=null) { let qs = querysets; if(!qs) { @@ -131,7 +131,7 @@ guiFields.history_initiator = class HistoryInitiatorField extends guiFields.fk { return selected; } - for(let index in qs) { + for(let index = 0; index < qs.length; index++) { let item = qs[index]; let p1 = item.url.replace(/^\/|\/$/g, "").split("/"); @@ -147,12 +147,12 @@ guiFields.history_initiator = class HistoryInitiatorField extends guiFields.fk { /** * Redefinition of 'formatQuerySetUrl' method of fk guiField. */ - formatQuerySetUrl(url="", data={}, params={}) { + formatQuerySetUrl(url="", data={}, params={}) { /* jshint unused: false */ if(url.indexOf('{') == -1) { return url; } - let project = data['project'] || app.application.$route.params[path_pk_key]; + let project = data.project || app.application.$route.params[path_pk_key]; if(project && typeof project == 'object' && project.value) { project = project.value; @@ -183,7 +183,7 @@ guiFields.history_executor = class HistoryExecutorField extends guiFields.fk { * @param {object} data */ makeLinkOrNot(data={}) { - if(data['initiator_type'] == 'scheduler') { + if(data.initiator_type == 'scheduler') { return false; } @@ -194,7 +194,7 @@ guiFields.history_executor = class HistoryExecutorField extends guiFields.fk { * @param {object} data */ prefetchDataOrNot(data={}) { - if(data['initiator_type'] == 'scheduler') { + if(data.initiator_type == 'scheduler') { return false; } @@ -205,7 +205,7 @@ guiFields.history_executor = class HistoryExecutorField extends guiFields.fk { * @param {object} data */ toRepresent(data={}) { - if(data['initiator_type'] == 'scheduler') { + if(data.initiator_type == 'scheduler') { return 'system'; } @@ -241,7 +241,7 @@ guiFields.ansible_json = class AnsibleJsonField extends guiFields.base { * Redefinition of base guiField static property 'mixins'. */ static get mixins() { - return super.mixins.concat(gui_fields_mixins.ansible_json) + return super.mixins.concat(gui_fields_mixins.ansible_json); } }; @@ -296,7 +296,7 @@ guiFields.one_history_date_time = class OneHistoryDateTime extends guiFields.dat } return moment(moment.tz(value, window.timeZone)).tz(moment.tz.guess()).format("YYYY-MM-DD HH:mm:ss"); - }; + } }; @@ -372,19 +372,21 @@ guiFields.one_history_execute_args = class OneHistoryExecuteArgsField extends gu let realFields = {}; for(let field in value) { - let opt = { - name: field, - readOnly: this.options.readOnly || false, - title: field, - format: 'one_history_string', - }; + if(value.hasOwnProperty(field)) { + let opt = { + name: field, + readOnly: this.options.readOnly || false, + title: field, + format: 'one_history_string', + }; - if(typeof value[field] == 'boolean') { - opt.format = 'one_history_boolean'; - } + if (typeof value[field] == 'boolean') { + opt.format = 'one_history_boolean'; + } - realFields[field] = new guiFields[opt.format](opt); + realFields[field] = new guiFields[opt.format](opt); + } } return realFields; diff --git a/polemarch/static/js/pmFieldsMixins.js b/polemarch/static/js/pmFieldsMixins.js index 9eb75178..1c01da47 100644 --- a/polemarch/static/js/pmFieldsMixins.js +++ b/polemarch/static/js/pmFieldsMixins.js @@ -1,14 +1,14 @@ /** * Mixin for 'field_content_read_only' of json gui_field. */ -var ansible_json_field_content_read_only_mixin = { +const ansible_json_field_content_read_only_mixin = { template: "#template_field_content_readonly_json", data() { return { real_elements: {}, real_elements_values: {}, realField: {}, - } + }; }, created() { if(!this.value) { @@ -29,7 +29,7 @@ var ansible_json_field_content_read_only_mixin = { 'requirements', 'extends_documentation_fragment', 'options', 'notes', 'author', ]; - for(let i in sorted_keys) { + for(let i = 0; i < sorted_keys.length; i++) { let field = sorted_keys[i]; if(this.realFields[field] !== undefined) { sorted_values[field] = this.realFields[field]; @@ -60,53 +60,57 @@ var ansible_json_field_content_read_only_mixin = { let options_child_fields_subtitle = "Option: "; for(let field in this.value) { - let options = { - name: field, - readOnly: this.field.options.readOnly || true, - title: capitalizeString(field.replace(/_/g, " ")), - format: 'string', - }; + if(this.value.hasOwnProperty(field)) { + let options = { + name: field, + readOnly: this.field.options.readOnly || true, + title: capitalizeString(field.replace(/_/g, " ")), + format: 'string', + }; - if(fields_types[field] && options.title != options_field_title) { - options.format = fields_types[field]; + if (fields_types[field] && options.title != options_field_title) { + options.format = fields_types[field]; - if(this.field.options.title && options.title.search(options_child_fields_subtitle) != -1) { - options.hide_title = true; - } - } else if (typeof this.value[field] == "string" && this.value[field].length > 50) { - options.format = 'textarea'; - } else if (typeof this.value[field] == 'boolean') { - options.format = 'boolean'; - } else if (typeof this.value[field] == 'object') { - if(Array.isArray(this.value[field])) { + if (this.field.options.title && options.title.search(options_child_fields_subtitle) != -1) { + options.hide_title = true; + } + } else if (typeof this.value[field] == "string" && this.value[field].length > 50) { options.format = 'textarea'; - } else if (this.value[field] === null) { - options.format = 'null'; - } else { - options.format = 'ansible_json'; - if(allPropertiesIsObjects(this.value[field])) { - options.divider = true; - options.title += ":"; + } else if (typeof this.value[field] == 'boolean') { + options.format = 'boolean'; + } else if (typeof this.value[field] == 'object') { + if (Array.isArray(this.value[field])) { + options.format = 'textarea'; + } else if (this.value[field] === null) { + options.format = 'null'; } else { - if(this.field.options.title == options_field_title) { - options.title = options_child_fields_subtitle + field; + options.format = 'ansible_json'; + if (allPropertiesIsObjects(this.value[field])) { /* globals allPropertiesIsObjects */ + options.divider = true; + options.title += ":"; + } else { + /* jshint maxdepth: false */ + if (this.field.options.title == options_field_title) { + options.title = options_child_fields_subtitle + field; + } } } } - } - if (( + if (( typeof this.value[field] == "string" && this.value[field] == "") || - (Array.isArray(this.value[field]) && this.value[field].length == 0) || - ( - typeof this.value[field] == "object" && this.value[field] !== null - && Array.isArray(this.value[field]) == false - && Object.keys(this.value[field]).length == 0 - )) { - options.format = 'hidden'; - } + (Array.isArray(this.value[field]) && this.value[field].length == 0) || + ( + typeof this.value[field] == "object" && + this.value[field] !== null && + Array.isArray(this.value[field]) == false && + Object.keys(this.value[field]).length == 0 + )) { + options.format = 'hidden'; + } - realElements[field] = new guiFields[options.format](options); + realElements[field] = new guiFields[options.format](options); + } } return realElements; @@ -117,7 +121,7 @@ var ansible_json_field_content_read_only_mixin = { /** * Mixin for 'one_history_fk' fields. */ -var one_history_fk_mixin = { +const one_history_fk_mixin = { components: { field_content_readonly: { mixins: [ @@ -145,7 +149,7 @@ gui_fields_mixins.ansible_json = { base: "form-group guiField", grid: "col-lg-12 col-xs-12 col-sm-12 col-md-12", }, - } + }; }, components: { field_content_readonly: { @@ -190,7 +194,7 @@ gui_fields_mixins.one_history_string = { ), grid: "col-lg-12 col-xs-12 col-sm-12 col-md-12", }, - } + }; }, components: { field_label: { @@ -240,7 +244,7 @@ gui_fields_mixins.one_history_initiator = { gui_fields_mixins.one_history_choices = { components: { field_content_readonly: { - mixins: [choices_field_content_readonly_mixin], + mixins: [choices_field_content_readonly_mixin], /* globals choices_field_content_readonly_mixin */ template: "#template_field_content_readonly_one_history_choices", data() { return { @@ -258,7 +262,7 @@ gui_fields_mixins.one_history_choices = { gui_fields_mixins.one_history_boolean = { components: { field_content_readonly: { - mixins: [base_field_content_edit_mixin, boolean_field_content_mixin], + mixins: [base_field_content_edit_mixin, boolean_field_content_mixin], /* globals base_field_content_edit_mixin, boolean_field_content_mixin */ template: "#template_field_content_read_only_one_history_boolean", data() { return { @@ -286,7 +290,7 @@ gui_fields_mixins.one_history_execute_args = { data: function () { return { execute_args_toggle: false, - } + }; }, components: { field_label: { @@ -315,7 +319,7 @@ gui_fields_mixins.one_history_raw_inventory = { gui_fields_mixins.history_executor = { components: { field_list_view: { - mixins: [base_field_list_view_mixin, field_fk_content_readonly_mixin], + mixins: [base_field_list_view_mixin, field_fk_content_readonly_mixin], /* globals base_field_list_view_mixin */ template: "#template_field_part_list_view_fk", computed: { text() { diff --git a/polemarch/static/js/pmGroups.js b/polemarch/static/js/pmGroups.js index 204537b8..085b7e74 100644 --- a/polemarch/static/js/pmGroups.js +++ b/polemarch/static/js/pmGroups.js @@ -55,17 +55,17 @@ tabSignal.connect('allViews.inited', obj => { if(type == 'sublinks' || type == 'child_links') { if(data.children) { - if(btns['host']) { - btns['host'].hidden = true; + if(btns.host) { + btns.host.hidden = true; } } else { - if(btns['group']) { - btns['group'].hidden = true; + if(btns.group) { + btns.group.hidden = true; } } } return btns; - } + }; }); }); \ No newline at end of file diff --git a/polemarch/static/js/pmHistory.js b/polemarch/static/js/pmHistory.js index 79cd67fd..c162cfad 100644 --- a/polemarch/static/js/pmHistory.js +++ b/polemarch/static/js/pmHistory.js @@ -1,3 +1,31 @@ +/** + * Variable, that stores array with History Models names, + * fields of those should be changed in the tabSignal. + */ +const history_models = ['History', 'OneHistory', 'ProjectHistory']; + +/** + * Variable, that stores pairs (key, value), where: + * - key - value of initiator_type field; + * - value - path from which should be loaded prefetch data. + */ +const history_initiator_types = { + project: '/project/', + template: '/project/{' + path_pk_key + '}/template/', + scheduler: '/project/{' + path_pk_key + '}/periodic_task/', +}; + +/** + * Variable, that stores array with History paths, + * options of those should be changed in the tabSignal. + */ +const history_paths = [ + '/history/', + '/history/{' + path_pk_key + '}/', + '/project/{' + path_pk_key + '}/history/', + '/project/{' + path_pk_key + '}/history/{history_id}/', +]; + /** * Function, that adds signal for some history model's fields. * @param {string} model @@ -59,6 +87,22 @@ function historyModelsFieldsHandler(model) { }); } +/** + * Function - onchange callback of dynamic field - OneHistory.fields.mode. + */ +function OneHistory_kind_mode_callback(parent_values={}) { + let obj = { + format: 'one_history_string', + save_value: true, + }; + + if(parent_values.kind) { + obj.title = parent_values.kind.toLowerCase(); + } + + return obj; +} + /** * Function, that adds signal for some OneHistory model's fields. * @param {string} model @@ -66,12 +110,14 @@ function historyModelsFieldsHandler(model) { function OneHistoryFieldsHandler(model) { tabSignal.connect("models[" + model + "].fields.beforeInit", (fields) => { for(let field in fields) { - fields[field].format = 'one_history_string'; + if(fields.hasOwnProperty(field)) { + fields[field].format = 'one_history_string'; - if(['kind', 'raw_args', 'raw_stdout', 'initiator_type'].includes(field)) { - fields[field].format = 'hidden'; - } else if(['start_time', 'stop_time'].includes(field)) { - fields[field].format = 'one_history_date_time'; + if (['kind', 'raw_args', 'raw_stdout', 'initiator_type'].includes(field)) { + fields[field].format = 'hidden'; + } else if (['start_time', 'stop_time'].includes(field)) { + fields[field].format = 'one_history_date_time'; + } } } @@ -96,106 +142,10 @@ function OneHistoryFieldsHandler(model) { }); } -/** - * Function, that adds signal for some history view's filters. - * @param {string} path - */ -function historyPathsFiltersHandler(path) { - /** - * Changes 'status' filter type to 'choices'. - */ - tabSignal.connect("views[" + path + "].filters.beforeInit", filters => { - for(let index in filters) { - let filter = filters[index]; - - if(filter.name == 'status') { - filter.type = 'choices'; - filter.enum = app.models['History'].fields.status.options.enum; - } - } - }); -} - -/** - * Function, that adds signal for some history view modification. - * @param {string} path - */ -function historyPathsViewsHandler(path) { - tabSignal.connect("views[" + path + "].afterInit", (obj) => { - if(obj.view.schema.type == 'page') { - obj.view.mixins = obj.view.mixins.concat(history_pk_mixin); - obj.view.template = '#template_view_history_one'; - } - }); - - tabSignal.connect('views[' + path + '].created', obj => { - if(obj.view.schema.type == 'list' && obj.view.schema.operations && obj.view.schema.operations.add) { - delete obj.view.schema.operations.add; - } - }); -} - -/** - * Function - onchange callback of dynamic field - OneHistory.fields.mode. - */ -function OneHistory_kind_mode_callback(parent_values={}) { - let obj = { - format: 'one_history_string', - save_value: true, - }; - - if(parent_values['kind']) { - obj.title = parent_values['kind'].toLowerCase(); - } - - return obj; -} - -/** - * Function, that adds signals for history models and history views. - */ -function addHistorySignals() { - history_models.forEach(historyModelsFieldsHandler); - - history_paths.forEach(historyPathsViewsHandler); - - history_paths.forEach(historyPathsFiltersHandler); - - OneHistoryFieldsHandler('OneHistory'); -} - -/** - * Variable, that stores array with History Models names, - * fields of those should be changed in the tabSignal. - */ -var history_models = ['History', 'OneHistory', 'ProjectHistory']; - -/** - * Variable, that stores pairs (key, value), where: - * - key - value of initiator_type field; - * - value - path from which should be loaded prefetch data. - */ -var history_initiator_types = { - project: '/project/', - template: '/project/{' + path_pk_key + '}/template/', - scheduler: '/project/{' + path_pk_key + '}/periodic_task/', -}; - -/** - * Variable, that stores array with History paths, - * options of those should be changed in the tabSignal. - */ -var history_paths = [ - '/history/', - '/history/{' + path_pk_key + '}/', - '/project/{' + path_pk_key + '}/history/', - '/project/{' + path_pk_key + '}/history/{history_id}/', -]; - /** * Mixin for /history/{pk}/ view. */ -var history_pk_mixin = { +const history_pk_mixin = { data: function () { return { inventory_toggle: false, @@ -203,12 +153,12 @@ var history_pk_mixin = { information_toggle: true, was_cleared: undefined, - } + }; }, /** * Redefinition of 'beforeRouteUpdate' hook of view_with_autoupdate_mixin. */ - beforeRouteUpdate(to, from, next) { + beforeRouteUpdate(to, from, next) { /* jshint unused: false */ this.stopChildrenAutoUpdate(); this.stopAutoUpdate(); next(); @@ -216,7 +166,7 @@ var history_pk_mixin = { /** * Redefinition of 'beforeRouteUpdate' hook of view_with_autoupdate_mixin. */ - beforeRouteLeave(to, from, next) { + beforeRouteLeave(to, from, next) { /* jshint unused: false */ this.stopChildrenAutoUpdate(); this.stopAutoUpdate(); this.$destroy(); @@ -275,7 +225,7 @@ var history_pk_mixin = { clear_button_options() { return { name: 'clear', - } + }; }, /** * Property, that returns object with look options for clear button. @@ -305,7 +255,7 @@ var history_pk_mixin = { clearInstance() { let qs = this.getQuerySet(this.view, this.qs_url).clone({url: this.qs_url + '/clear'}); - qs.formQueryAndSend('delete').then(response => { + qs.formQueryAndSend('delete').then(response => { /* jshint unused: false */ guiPopUp.success(pop_up_msg.instance.success.execute.format( ['clear', this.view.schema.name] )); @@ -327,7 +277,7 @@ var history_pk_mixin = { * Component for clear history stdout button. */ clear_button: { - mixins: [base_button_mixin], + mixins: [base_button_mixin], /* globals base_button_mixin */ }, /** * Component, that is responsible for loading and showing history stdout output. @@ -384,7 +334,7 @@ var history_pk_mixin = { raw_stdout_link() { let url = this.url.replace(/^\/|\/$/g, ""); - return '/api/' + api_version + '/' + url + '/raw'; + return '/api/' + api_version + '/' + url + '/raw'; /* globals api_version */ }, /** * Property, that returns url for getting stdout lines. @@ -401,7 +351,7 @@ var history_pk_mixin = { gluedLines() { let obj = {}; - for(let index in this.lines) { + for(let index = 0; index < this.lines.length; index++) { let subline = this.lines[index]; if(!obj[subline.line_gnumber]) { @@ -423,7 +373,9 @@ var history_pk_mixin = { let html = []; for(let key in this.gluedLines) { - html.push(this.ansiUp(this.gluedLines[key].text)); + if(this.gluedLines.hasOwnProperty(key)) { + html.push(this.ansiUp(this.gluedLines[key].text)); + } } return html.join(""); @@ -451,7 +403,7 @@ var history_pk_mixin = { created() { this.lines_qs = new guiQuerySets.QuerySet(app.models.OneHistory, this.lines_url); - this.getLines().then(responce => { + this.getLines().then(response => { /* jshint unused: false */ setTimeout(() => { $(this.stdout_el).scrollTop($(this.stdout_el).prop('scrollHeight')); }, 300); @@ -473,7 +425,7 @@ var history_pk_mixin = { if(["RUN", "DELAY"].includes(instance_data.status)) { this.last_status = instance_data.status; - return this.loadLinesFromBeginning().then(response => { + return this.loadLinesFromBeginning().then(response => { /* jshint unused: false */ setTimeout(() => { $(this.stdout_el).scrollTop($(this.stdout_el).prop('scrollHeight')); }, 300); @@ -501,7 +453,7 @@ var history_pk_mixin = { if(this.needLoadAdditionalData) { let height = $(this.stdout_el).prop('scrollHeight'); - return this.loadLinesFromEnd().then(response => { + return this.loadLinesFromEnd().then(response => { /* jshint unused: false */ setTimeout(() => { $(this.stdout_el).scrollTop($(this.stdout_el).prop('scrollHeight') - height); }, 300); @@ -594,7 +546,7 @@ var history_pk_mixin = { * @param {array} new_lines Array with potential new lines. */ saveNewLines(new_lines=[]) { - for(let index in new_lines) { + for(let index = 0; index < new_lines.length; index++) { let new_line = new_lines[index]; let filtered = this.lines.filter(line => { @@ -618,10 +570,10 @@ var history_pk_mixin = { let comments = []; // Array to collect all comments let strings = []; // Array to collect all line let res = []; // Array to collect all RegEx - let all = {'C': comments, 'S': strings, 'R': res}; - let safe = {'<': '<', '>': '>', '&': '&'}; + let all = {'C': comments, 'S': strings, 'R': res}; /* jshint unused: false */ /* TODO check can we delete this variables */ + let safe = {'<': '<', '>': '>', '&': '&'}; /* jshint unused: false */ - let ansi_up = new AnsiUp; + let ansi_up = AnsiUp(); /* globals AnsiUp */ ansi_up.use_classes = true; let html = ansi_up.ansi_to_html(line_content); @@ -632,6 +584,60 @@ var history_pk_mixin = { }, }; + +/** + * Function, that adds signal for some history view's filters. + * @param {string} path + */ +function historyPathsFiltersHandler(path) { + /** + * Changes 'status' filter type to 'choices'. + */ + tabSignal.connect("views[" + path + "].filters.beforeInit", filters => { + for(let key in filters) { + if(filters.hasOwnProperty(key)) { + let filter = filters[key]; + + if (filter.name == 'status') { + filter.type = 'choices'; + filter.enum = app.models.History.fields.status.options.enum; + } + } + } + }); +} + +/** + * Function, that adds signal for some history view modification. + * @param {string} path + */ +function historyPathsViewsHandler(path) { + tabSignal.connect("views[" + path + "].afterInit", (obj) => { + if(obj.view.schema.type == 'page') { + obj.view.mixins = obj.view.mixins.concat(history_pk_mixin); + obj.view.template = '#template_view_history_one'; + } + }); + + tabSignal.connect('views[' + path + '].created', obj => { + if(obj.view.schema.type == 'list' && obj.view.schema.operations && obj.view.schema.operations.add) { + delete obj.view.schema.operations.add; + } + }); +} + +/** + * Function, that adds signals for history models and history views. + */ +function addHistorySignals() { + history_models.forEach(historyModelsFieldsHandler); + + history_paths.forEach(historyPathsViewsHandler); + + history_paths.forEach(historyPathsFiltersHandler); + + OneHistoryFieldsHandler('OneHistory'); +} // adds signal for history models and views. addHistorySignals(); @@ -648,18 +654,18 @@ tabSignal.connect('allViews.inited', obj => { } if(type == 'actions' || type == 'child_links') { - if(!['RUN', 'DELAY'].includes(data['status'])) { - btns['cancel'].hidden = true; + if(!['RUN', 'DELAY'].includes(data.status)) { + btns.cancel.hidden = true; } - if(!(data['status'] == 'OK' && data['kind'] == 'MODULE' && data['mode'] == 'setup')) { - btns['facts'].hidden = true; + if(!(data.status == 'OK' && data.kind == 'MODULE' && data.mode == 'setup')) { + btns.facts.hidden = true; } - btns['clear'].hidden = true; + btns.clear.hidden = true; } return btns; - } + }; }); }); \ No newline at end of file diff --git a/polemarch/static/js/pmHosts.js b/polemarch/static/js/pmHosts.js index 5e90d6bf..187bf57a 100644 --- a/polemarch/static/js/pmHosts.js +++ b/polemarch/static/js/pmHosts.js @@ -14,7 +14,7 @@ function addSignalOwnerReadOnly(model) { * Variable, that stores array with Host paths, * options of those should be changed in the tabSignal. */ -var host_paths = [ +const host_paths = [ '/host/', '/group/{' + path_pk_key + '}/host/', '/inventory/{' + path_pk_key + '}/host/', '/inventory/{' + path_pk_key + '}/group/{group_id}/host/', '/project/{' + path_pk_key + '}/inventory/{inventory_id}/host/', @@ -25,12 +25,14 @@ var host_paths = [ */ host_paths.forEach(path => { tabSignal.connect("views[" + path + "].filters.beforeInit", filters => { - for(let index in filters) { - let filter = filters[index]; + for(let key in filters) { + if(filters.hasOwnProperty(key)) { + let filter = filters[key]; - if(filter.name == 'type') { - filter.type = 'choices'; - filter.enum = [''].concat(app.models['Host'].fields.type.options.enum); + if (filter.name == 'type') { + filter.type = 'choices'; + filter.enum = [''].concat(app.models.Host.fields.type.options.enum); + } } } }); diff --git a/polemarch/static/js/pmInventories.js b/polemarch/static/js/pmInventories.js index b3a94215..08e1ebd7 100644 --- a/polemarch/static/js/pmInventories.js +++ b/polemarch/static/js/pmInventories.js @@ -2,7 +2,7 @@ * Changes options of InventoryImport Model's fields. */ tabSignal.connect("models[InventoryImport].fields.beforeInit", fields => { - fields['inventory_id'].hidden = true; - fields['raw_data'].format = 'file'; - fields['raw_data'].title = 'Inventory file'; + fields.inventory_id.hidden = true; + fields.raw_data.format = 'file'; + fields.raw_data.title = 'Inventory file'; }); \ No newline at end of file diff --git a/polemarch/static/js/pmItems.js b/polemarch/static/js/pmItems.js index 02ab8afe..d5720cd6 100644 --- a/polemarch/static/js/pmItems.js +++ b/polemarch/static/js/pmItems.js @@ -19,7 +19,7 @@ vst_vue_components.items.logo = Vue.component('logo', { * Component for guiWidgets.history_chart. */ vst_vue_components.widgets.w_history_chart = Vue.component('w_history_chart', { - mixins: [w_line_chart_mixin], + mixins: [w_line_chart_mixin], /* globals w_line_chart_mixin */ data() { return { with_content_header: true, @@ -27,7 +27,7 @@ vst_vue_components.widgets.w_history_chart = Vue.component('w_history_chart', { }, components: { content_header: { - mixins: [base_widget_mixin], + mixins: [base_widget_mixin], /* globals base_widget_mixin */ template: "#template_w_history_chart_content_header", data() { return { @@ -61,7 +61,7 @@ vst_vue_components.widgets.w_history_chart = Vue.component('w_history_chart', { }, }, content_body: { - mixins: [w_line_chart_content_body_mixin], + mixins: [w_line_chart_content_body_mixin], /* globals w_line_chart_content_body_mixin */ template: "#template_w_history_chart_content_body", data() { return { @@ -70,7 +70,7 @@ vst_vue_components.widgets.w_history_chart = Vue.component('w_history_chart', { }; }, watch: { - 'customizer.skin.name': function(value) { + 'customizer.skin.name': function(value) { /* jshint unused: false */ /* TODO ask about args*/ this.generateChart(); } }, diff --git a/polemarch/static/js/pmPeriodicTasks.js b/polemarch/static/js/pmPeriodicTasks.js index d484f592..77fe16a5 100644 --- a/polemarch/static/js/pmPeriodicTasks.js +++ b/polemarch/static/js/pmPeriodicTasks.js @@ -3,7 +3,7 @@ * @param {object} parent_values Values of parent fields. */ function OnePeriodictask_inventory_callback(parent_values={}) { - let kind = parent_values['kind']; + let kind = parent_values.kind; if(kind && (kind.toLowerCase() == "playbook" || kind.toLowerCase() == "module")) { return { @@ -14,7 +14,7 @@ function OnePeriodictask_inventory_callback(parent_values={}) { list_paths: ['/project/{' + path_pk_key + '}/inventory/'], }, save_value: true, - } + }; } } @@ -23,7 +23,7 @@ function OnePeriodictask_inventory_callback(parent_values={}) { * @param {object} parent_values Values of parent fields. */ function OnePeriodictask_mode_callback(parent_values={}) { - let kind = parent_values['kind']; + let kind = parent_values.kind; if(kind) { kind = kind.toLowerCase(); @@ -38,7 +38,7 @@ function OnePeriodictask_mode_callback(parent_values={}) { list_paths: ['/project/{' + path_pk_key + '}/playbook/'], }, required: true, - } + }; } else if(kind == "module") { return { format: 'module_autocomplete', @@ -49,7 +49,7 @@ function OnePeriodictask_mode_callback(parent_values={}) { list_paths: ['/project/{' + path_pk_key + '}/module/'], }, required: true, - } + }; } } @@ -58,7 +58,7 @@ function OnePeriodictask_mode_callback(parent_values={}) { * @param {object} parent_values Values of parent fields. */ function OnePeriodictask_template_callback(parent_values={}) { - let kind = parent_values['kind']; + let kind = parent_values.kind; if(kind) { kind = kind.toLowerCase(); @@ -96,7 +96,7 @@ function OnePeriodictask_template_opt_callback() { * @param {object} parent_values Values of parent fields. */ return function(parent_values) { - let kind = parent_values['kind']; + let kind = parent_values.kind; if(kind && kind.toLowerCase() !== 'template') { return { @@ -104,7 +104,7 @@ function OnePeriodictask_template_opt_callback() { }; } - let template = parent_values['template']; + let template = parent_values.template; if(template && typeof template == 'object' && template.value !== undefined) { template = template.value; @@ -171,12 +171,14 @@ function OnePeriodictask_template_opt_callback() { * Changes 'kind' filter type to 'choices'. */ tabSignal.connect("views[/project/{" + path_pk_key + "}/periodic_task/].filters.beforeInit", filters => { - for(let index in filters) { - let filter = filters[index]; + for(let key in filters) { + if(filters.hasOwnProperty(key)) { + let filter = filters[key]; - if(filter.name == 'kind') { - filter.type = 'choices'; - filter.enum = [''].concat(app.models['Periodictask'].fields.kind.options.enum); + if (filter.name == 'kind') { + filter.type = 'choices'; + filter.enum = [''].concat(app.models.Periodictask.fields.kind.options.enum); + } } } }); @@ -191,7 +193,7 @@ tabSignal.connect('allViews.inited', obj => { '/project/{' + path_pk_key + '}/periodic_task/', '/project/{' + path_pk_key + '}/periodic_task/{periodic_task_id}/', ].forEach(path => { - views[path].getViewSublinkButtons = function(type, buttons, instance) { + views[path].getViewSublinkButtons = function(type, buttons, instance) { /* jshint unused: false */ let data = instance.data; let btns = $.extend(true, {}, buttons); @@ -199,12 +201,12 @@ tabSignal.connect('allViews.inited', obj => { return btns; } - if(data['kind'] == 'TEMPLATE' && btns['variables']) { - btns['variables'].hidden = true; + if(data.kind == 'TEMPLATE' && btns.variables) { + btns.variables.hidden = true; } return btns; - } + }; }); }); //////////////////////////////////////////////////////////////////////////////////// @@ -247,7 +249,7 @@ guiModels.OnePeriodicTaskVariableModel = class OnePeriodicTaskVariableModel exte debugger; throw error; }); - }; + } }; /** @@ -260,7 +262,7 @@ guiQuerySets.OnePeriodicTaskVariableQuerySet = class OnePeriodicTaskVariableQuer getParentInstanceDataType() { return this.url.replace(/^\/|\/$/g, "") .replace(/\/variables([A-z,0-9,_,\/]*)$/, "").split("/"); - }; + } /** * Method, that returns promise, that returns parent instance. */ @@ -275,15 +277,16 @@ guiQuerySets.OnePeriodicTaskVariableQuerySet = class OnePeriodicTaskVariableQuer }; return this.sendQuery(bulk).then(response => { - return this.parent_instance = app.models.OnePeriodictask.getInstance( + this.parent_instance = app.models.OnePeriodictask.getInstance( response.data, this.clone({url: this.url.replace(/\/variables([A-z,0-9,_,\/]*)$/, "") }), ); + return this.parent_instance; }).catch(error => { debugger; throw error; }); - }; + } /** * Redefinition of 'get' method of guiQuerySets.QuerySet class. */ @@ -307,7 +310,7 @@ guiQuerySets.OnePeriodicTaskVariableQuerySet = class OnePeriodicTaskVariableQuer debugger; throw error; }); - }; + } /** * Method, that returns periodic task variable data object. * @param {object} parent_data Data of periodic task instance. @@ -318,7 +321,7 @@ guiQuerySets.OnePeriodicTaskVariableQuerySet = class OnePeriodicTaskVariableQuer return Object.assign( {}, instance_data, {kind: parent_data.kind, inventory: parent_data.inventory}, ); - }; + } }; tabSignal.connect('openapi.loaded', (openapi) => { @@ -356,14 +359,14 @@ tabSignal.connect("models[OnePeriodicTaskVariable].fields.beforeInit", function( fields.key.format = 'dynamic'; fields.key.additionalProperties = { field: ['kind'], - callback: OneTemplateVariable_key_callback, + callback: OneTemplateVariable_key_callback, /* globals OneTemplateVariable_key_callback */ }; fields.value.format = 'dynamic'; fields.value.additionalProperties = { field: ['inventory', 'key'], - types: template_vars.value.types, - callback: OneTemplateVariable_value_callback(), + types: template_vars.value.types, /* globals template_vars */ + callback: OneTemplateVariable_value_callback(), /* globals OneTemplateVariable_value_callback */ }; }); diff --git a/polemarch/static/js/pmProjects.js b/polemarch/static/js/pmProjects.js index 249ba197..46eec49a 100644 --- a/polemarch/static/js/pmProjects.js +++ b/polemarch/static/js/pmProjects.js @@ -10,7 +10,7 @@ function ExecuteModulePlaybook_group_limit_callback() { * @param {object} parent_values Values of parent fields. */ return function (parent_values = {}) { - let inventory = parent_values['inventory']; + let inventory = parent_values.inventory; if (inventory && typeof inventory == 'object' && inventory.value !== undefined) { inventory = inventory.value; @@ -62,7 +62,7 @@ function ExecuteModulePlaybook_group_limit_callback() { save_value: save_value, }; } - } + }; } /** @@ -110,8 +110,8 @@ function ansiblePlaybookAndAnsibleModuleModelsFieldsHandler(model) { /** * Vue component of 'Run playbook form'. */ -var gui_project_page_additional = Vue.component('gui_project_page_additional', { - mixins: [base_page_type_mixin, collapsable_card_mixin], +const gui_project_page_additional = Vue.component('gui_project_page_additional', { /* jshint unused: false */ + mixins: [base_page_type_mixin, collapsable_card_mixin], /* globals base_page_type_mixin, collapsable_card_mixin */ template: "#template_project_page_additional", data() { return { @@ -205,7 +205,7 @@ var gui_project_page_additional = Vue.component('gui_project_page_additional', { title: "Additional execute parameters", format: 'form', form: data.fields, - } + }; } return {form: {}}; @@ -223,17 +223,19 @@ var gui_project_page_additional = Vue.component('gui_project_page_additional', { let buttons = {}; for(let key in data.playbooks) { - let val = data.playbooks[key]; - - buttons[key] = { - name: key, - title: val.title, - description: val.help || val.description, - format:'button', - onclick: () => { - this.executePlaybook(key); - }, - } + if(data.playbook.hasOwnProperty(key)) { + let val = data.playbooks[key]; + + buttons[key] = { + name: key, + title: val.title, + description: val.help || val.description, + format: 'button', + onclick: () => { + this.executePlaybook(key); + }, + }; + } } return {name: 'buttons', title: ' ', form: buttons}; @@ -253,7 +255,7 @@ var gui_project_page_additional = Vue.component('gui_project_page_additional', { let extra_vars = this.extra_vars.validateValue({extra_vars: val_extra_vars}); if(!isEmptyObject(extra_vars)) { - valid_data['extra_vars'] = extra_vars; + valid_data.extra_vars = extra_vars; } return valid_data; @@ -319,7 +321,7 @@ var gui_project_page_additional = Vue.component('gui_project_page_additional', { /** * Mixin for '/project/{pk}/' view. */ -var project_pk_mixin = { +const project_pk_mixin = { watch: { 'hasPolemarchYamlForm': function(value) { if(value && this.card_collapsed == false && @@ -352,7 +354,7 @@ var project_pk_mixin = { * Variable, that stores names of models, connected with project. * This is needed for easy redefinition in EE version. */ -var project_connected_models_dict = { +let project_connected_models_dict = { module: 'AnsibleModule', playbook: 'AnsiblePlaybook', }; @@ -366,7 +368,7 @@ tabSignal.connect("models[OneProject].fields.beforeInit", (fields) => { }); tabSignal.connect("models[OneModule].fields.beforeInit", (fields) => { - fields['data'].format = 'ansible_json'; + fields.data.format = 'ansible_json'; }); /** @@ -386,12 +388,14 @@ addSignalsForAnsibleModuleAndAnsiblePlaybookModels(); * Changes 'status' filter type to 'choices'. */ tabSignal.connect("views[/project/].filters.beforeInit", filters => { - for(let index in filters) { - let filter = filters[index]; + for(let key in filters) { + if(filters.hasOwnProperty(key)) { + let filter = filters[key]; - if(filter.name == 'status' || filter.name == 'status__not') { - filter.type = 'choices'; - filter.enum = [''].concat(app.models['Project'].fields.status.options.enum); + if (filter.name == 'status' || filter.name == 'status__not') { + filter.type = 'choices'; + filter.enum = [''].concat(app.models.Project.fields.status.options.enum); + } } } }); @@ -401,7 +405,7 @@ tabSignal.connect("views[/project/].filters.beforeInit", filters => { * - key - value of the 'key' field of ProjectVariable model; * - value - value of the 'value' field of ProjectVariable model. */ -var ProjectVariable_value_from_key = { +const ProjectVariable_value_from_key = { ci_template: { additionalProperties: { list_paths: ["/project/{" + path_pk_key + "}/template/"], @@ -427,7 +431,7 @@ function ProjectVariable_value_callback(parent_values={}) { * Adds callback for dynamic 'value' field of ProjectVariable model. */ tabSignal.connect("models[ProjectVariable].fields.beforeInit", (fields) => { - if(fields['value'] && fields['value'].additionalProperties) { - fields['value'].additionalProperties.callback = ProjectVariable_value_callback; + if(fields.value && fields.value.additionalProperties) { + fields.value.additionalProperties.callback = ProjectVariable_value_callback; } }); \ No newline at end of file diff --git a/polemarch/static/js/pmTemplates.js b/polemarch/static/js/pmTemplates.js index dc158020..401745de 100644 --- a/polemarch/static/js/pmTemplates.js +++ b/polemarch/static/js/pmTemplates.js @@ -1,16 +1,24 @@ +/** + * Variable, that stores properties for callbacks of OneTemplateVariable dynamic fields. + */ +const template_vars = { + key: {}, + value: {}, +}; + /** * Mixin for template sublinks' Model classes. * @param Class_name */ -var template_sublink_model_mixin = (Class_name) => class extends Class_name { +const template_sublink_model_mixin = (Class_name) => class extends Class_name { /** * Redefinition of 'save' method of guiModels.Model class. */ - save(method="patch") { + save(method="patch") { /* jshint unused: false */ return this.queryset.getTemplateInstance().then(template_instance => { this._onSave(template_instance.data, this.toInner(this.data)); - return this.queryset.formQueryAndSend('patch', template_instance.data).then(response => { + return this.queryset.formQueryAndSend('patch', template_instance.data).then(response => { /* jshint unused: false */ return this.queryset.model.getInstance( this.queryset._formInstanceData( template_instance.data, this.getPkValue(), @@ -22,14 +30,14 @@ var template_sublink_model_mixin = (Class_name) => class extends Class_name { debugger; throw error; }); - }; + } /** * Method - 'save' method callback. * @param {object} template_data Template instance data. * @param {object} instance_data Instance data. * @private */ - _onSave(template_data, instance_data) {}; + _onSave(template_data, instance_data) {} /* jshint unused: false */ /** * Redefinition of 'delete' method of guiModels.Model class. */ @@ -41,20 +49,20 @@ var template_sublink_model_mixin = (Class_name) => class extends Class_name { return response; }); }); - }; + } /** * Method - 'delete' method callback. * @param {object} template_data Template instance data. * @private */ - _onDelete(template_data) {}; + _onDelete(template_data) {} /* jshint unused: false */ }; /** * Mixin for template sublinks' QuerySet classes. * @param Class_name */ -var template_sublink_qs_mixin = (Class_name) => class extends Class_name { +const template_sublink_qs_mixin = (Class_name) => class extends Class_name { /** * Redefinition of 'makeQueryString' method of guiQuerySets.QuerySet class. */ @@ -62,11 +70,13 @@ var template_sublink_qs_mixin = (Class_name) => class extends Class_name { let filters = []; let allowed_filters = ['limit']; for(let key in query) { - if(!allowed_filters.includes(key)) continue; + if(!allowed_filters.includes(key)) { + continue; + } filters.push([key, query[key]].join('=')); } return filters.join("&"); - }; + } /** * Redefinition of 'items' method of guiQuerySets.QuerySet class. */ @@ -97,8 +107,8 @@ var template_sublink_qs_mixin = (Class_name) => class extends Class_name { }).catch(error => { debugger; throw error; - }) - }; + }); + } /** * Redefinition of 'get' method of guiQuerySets.QuerySet class. */ @@ -124,7 +134,7 @@ var template_sublink_qs_mixin = (Class_name) => class extends Class_name { debugger; throw error; }); - }; + } /** * Method, that returns promise, that returns parent template instance. * @param {boolean} reload Means, that data should be updated or not. @@ -143,7 +153,7 @@ var template_sublink_qs_mixin = (Class_name) => class extends Class_name { debugger; throw error; }); - }; + } /** * Method, that filters instances and returns them and their api_count. * @param {array} instances Array of instances objects. @@ -167,7 +177,7 @@ var template_sublink_qs_mixin = (Class_name) => class extends Class_name { } } else { if(typeof instance.data[filter] == 'boolean' && typeof filter_value == 'string') { - filter_value = stringToBoolean(filter_value); + filter_value = stringToBoolean(filter_value); /* globals stringToBoolean */ } if(instance.data[filter] == filter_value) { @@ -188,7 +198,7 @@ var template_sublink_qs_mixin = (Class_name) => class extends Class_name { } return {filtered_instances: filtered_instances, api_count: api_count}; - }; + } /** * Method, that returns Array with names of allowed filters. * @returns {array} @@ -196,7 +206,7 @@ var template_sublink_qs_mixin = (Class_name) => class extends Class_name { */ _getFilterNames() { return ['name']; - }; + } }; /** @@ -209,16 +219,16 @@ function OneTemplate_group_callback(required=false) { * @param {object} parent_values Values of parent fields. */ return function(parent_values={}) { - let kind = parent_values['kind']; + let kind = parent_values.kind; if(kind && kind.toLowerCase() == 'task') { return { format: 'hidden', required: false, - } + }; } - let inventory = parent_values['inventory']; + let inventory = parent_values.inventory; if(inventory && typeof inventory == 'object' && inventory.value !== undefined) { inventory = inventory.value; @@ -333,7 +343,7 @@ function OneTemplateVariable_key_callback(parent_values={}) { save_value: true, }; - let p_v = parent_values['kind']; + let p_v = parent_values.kind; if(p_v) { p_v = p_v.toLowerCase(); @@ -356,8 +366,8 @@ function OneTemplateVariable_value_callback() { * @param {object} parent_values Values of parent fields. */ return function(parent_values={}) { - let key = parent_values['key']; - let inventory = parent_values['inventory']; + let key = parent_values.key; + let inventory = parent_values.inventory; if(key && (key.toLowerCase() == 'group' || key.toLowerCase() == 'limit') && inventory && !isNaN(Number(inventory))) { @@ -579,8 +589,12 @@ function formEnumForVariables(openapi) { let types = {}; for(let key in obj) { - if(exclude_keys.includes(key)) continue; - types[key] = obj[key].format || obj[key].type; + if(obj.hasOwnProperty(key)) { + if (exclude_keys.includes(key)) { + continue; + } + types[key] = obj[key].format || obj[key].type; + } } return types; @@ -710,18 +724,10 @@ function getFiltersForTemplateVariable() { ]; } -/** - * Variable, that stores properties for callbacks of OneTemplateVariable dynamic fields. - */ -var template_vars = { - key: {}, - value: {}, -}; - /** * Mixin for Vue component of TemplateVariable 'list' View. */ -var tmp_vars_list_mixin = { +const tmp_vars_list_mixin = { methods: { /** * Redefinition of 'removeInstances' method of list view. @@ -737,14 +743,16 @@ var tmp_vars_list_mixin = { let selected = []; for(let key in selections) { - if(!selections[key]) continue; + if(!selections[key]) { + continue; + } selected.push(key); this._removeInstance(template_instance, key); } return qs.formQueryAndSend('patch', template_instance.data) - .then(response => { + .then(response => { /* jshint unused: false */ return this.removeInstances_callback(selected); }); }).catch(error => { @@ -789,7 +797,7 @@ var tmp_vars_list_mixin = { return; } - for(let index in new_qs.cache) { + for(let index = 0; index < new_qs.cache.length; index++) { let list_instance = new_qs.cache[index]; if(list_instance.getPkValue() == item) { @@ -811,7 +819,7 @@ var tmp_vars_list_mixin = { /** * Mixin for Vue component of TemplateVariable 'page_new' View. */ -var tmp_vars_new_mixin = { +const tmp_vars_new_mixin = { methods: { fetchData() { this.initLoading(); @@ -924,7 +932,7 @@ guiModels.OneTemplateModel = class OneTemplateModel extends guiModels.Model { debugger; throw error; }); - }; + } }; /** @@ -978,7 +986,7 @@ guiQuerySets.OneTemplateQuerySet = class OneTemplateQuerySet extends guiQuerySet debugger; throw error; }); - }; + } }; tabSignal.connect("models[Template].fields.beforeInit", function(fields) { @@ -1031,9 +1039,9 @@ tabSignal.connect("models[TemplateExec].fields.beforeInit", function(fields) { */ tabSignal.connect("views[/project/{" + path_pk_key + "}/template/{template_id}/edit/].afterInit", (obj) => { let mixins = [...obj.view.mixins].reverse(); - let baseSaveInstance = routesComponentsTemplates.page_edit.methods.saveInstance; + let baseSaveInstance = routesComponentsTemplates.page_edit.methods.saveInstance; /* globals routesComponentsTemplates */ - for(let index in mixins) { + for(let index = 0; index < mixins.length; index++) { let item = mixins[index]; if(item.methods && item.methods.saveInstance) { @@ -1079,11 +1087,13 @@ tabSignal.connect("views[/project/{" + path_pk_key + "}/template/{template_id}/e */ tabSignal.connect("views[/project/{" + path_pk_key + "}/template/].filters.beforeInit", filters => { for(let index in filters) { - let filter = filters[index]; + if(filters.hasOwnProperty(index)) { + let filter = filters[index]; - if(filter.name == 'kind') { - filter.type = 'choices'; - filter.enum = [''].concat(app.models['Template'].fields.kind.options.enum); + if (filter.name == 'kind') { + filter.type = 'choices'; + filter.enum = [''].concat(app.models.Template.fields.kind.options.enum); + } } } }); @@ -1119,7 +1129,7 @@ guiModels.TemplateVariableModel = class TemplateVariableModel } template_data.data.vars[instance_data.key] = instance_data.value; - }; + } /** * Redefinition of '_onDelete' method of template_sublink_model_mixin. @@ -1129,7 +1139,7 @@ guiModels.TemplateVariableModel = class TemplateVariableModel template_data.data.vars) { delete template_data.data.vars[this.getPkValue()]; } - }; + } }; /** @@ -1143,7 +1153,7 @@ guiQuerySets.TemplateVariableQuerySet = class TemplateVariableQuerySet getDataType() { return this.url.replace(/^\/|\/$/g, "") .replace(/\/variables([A-z,0-9,_,\/]*)$/, "").split("/"); - }; + } /** * Method, that forms instances, based on data. * @param {object} data Template instance data. @@ -1158,19 +1168,21 @@ guiQuerySets.TemplateVariableQuerySet = class TemplateVariableQuerySet } for(let item in data.data.vars) { - instances.push( - this.model.getInstance( - { - kind: data.kind, inventory: data.data.inventory, - key: item, value: data.data.vars[item] - }, - this.clone(), - ), - ); + if(data.data.vars.hasOwnProperty(item)) { + instances.push( + this.model.getInstance( + { + kind: data.kind, inventory: data.data.inventory, + key: item, value: data.data.vars[item] + }, + this.clone(), + ), + ); + } } return instances; - }; + } /** * Method, that checks existence of instance. * @param {object} template_instance Template instance. @@ -1186,7 +1198,7 @@ guiQuerySets.TemplateVariableQuerySet = class TemplateVariableQuerySet } return false; - }; + } /** * Method, that returns option data object. * @param {object} template_data Data of template instance. @@ -1200,7 +1212,7 @@ guiQuerySets.TemplateVariableQuerySet = class TemplateVariableQuerySet key: instance_name, value: template_data.data.vars[instance_name], }; - }; + } /** * Method, that returns Array with names of allowed filters. * @returns {array} @@ -1208,7 +1220,7 @@ guiQuerySets.TemplateVariableQuerySet = class TemplateVariableQuerySet */ _getFilterNames() { return ['key', 'value']; - }; + } }; /** @@ -1283,7 +1295,7 @@ guiModels.TemplateOptionModel = class TemplateOptionModel super(name, fields); this.pk_name = 'name'; - }; + } /** * Redefinition of '_onSave' method of template_sublink_model_mixin. */ @@ -1297,7 +1309,7 @@ guiModels.TemplateOptionModel = class TemplateOptionModel } template_data.options[this.getPkValue()] = instance_data; - }; + } /** * Redefinition of '_onDelete' method of template_sublink_model_mixin. */ @@ -1305,7 +1317,7 @@ guiModels.TemplateOptionModel = class TemplateOptionModel if(template_data && template_data.options) { delete template_data.options[this.getPkValue()]; } - }; + } }; /** @@ -1319,7 +1331,7 @@ guiQuerySets.TemplateOptionQuerySet = class TemplateOptionQuerySet getDataType() { return this.url.replace(/^\/|\/$/g, "") .replace(/\/option([A-z,0-9,_,\/]*)$/, "").split("/"); - }; + } /** * Method, that forms instances, based on data. * @param {object} data Template instance data. @@ -1334,13 +1346,15 @@ guiQuerySets.TemplateOptionQuerySet = class TemplateOptionQuerySet } for(let item in data.options) { - instances.push( - this.model.getInstance({name: item}, this.clone()), - ); + if(data.options.hasOwnProperty(item)) { + instances.push( + this.model.getInstance({name: item}, this.clone()), + ); + } } return instances; - }; + } /** * Method, that checks existence of instance. * @param {object} template_instance Template instance. @@ -1355,7 +1369,7 @@ guiQuerySets.TemplateOptionQuerySet = class TemplateOptionQuerySet } return false; - }; + } /** * Method, that returns Array with names of allowed filters. * @returns {array} @@ -1363,7 +1377,7 @@ guiQuerySets.TemplateOptionQuerySet = class TemplateOptionQuerySet */ _getFilterNames() { return ['name']; - }; + } /** * Method, that returns option data object. * @param {object} template_data Data of template instance. @@ -1382,7 +1396,7 @@ guiQuerySets.TemplateOptionQuerySet = class TemplateOptionQuerySet } return $.extend(true, {}, option_data, tmp, {name: option_name}); - }; + } }; /** @@ -1534,7 +1548,7 @@ guiModels.TemplateOptionVariableModel = class TemplateOptionVariableModel } template_data.options[option].vars[instance_data.key] = instance_data.value; - }; + } /** * Redefinition of '_onDelete' method of template_sublink_model_mixin. */ @@ -1547,7 +1561,7 @@ guiModels.TemplateOptionVariableModel = class TemplateOptionVariableModel template_data.options[option].vars) { delete template_data.options[option].vars[this.getPkValue()]; } - }; + } }; /** @@ -1562,7 +1576,7 @@ guiQuerySets.TemplateOptionVariableQuerySet = class TemplateOptionVariableQueryS return this.url.replace(/^\/|\/$/g, "") .replace(/\/option([A-z,0-9,_,\/]+)\/variables([A-z,0-9,_,\/]*)$/, "") .split("/"); - }; + } getOptionName() { try { return this.url.split("/option")[1].split("/")[1]; @@ -1570,7 +1584,7 @@ guiQuerySets.TemplateOptionVariableQuerySet = class TemplateOptionVariableQueryS debugger; throw new StatusError(404, 'Instance was not found'); } - }; + } /** * Method, that forms instances, based on data. * @param {object} data Template instance data. @@ -1586,20 +1600,23 @@ guiQuerySets.TemplateOptionVariableQuerySet = class TemplateOptionVariableQueryS return instances; } + debugger; for(let item in data.options[option_name].vars) { - instances.push( - this.model.getInstance( - { - kind: data.kind, inventory: data.data.inventory, - key: item, value: data.options[option_name].vars[item], - }, - this.clone(), - ), - ); + if(data.options[option_name].vars.hasOwnProperty(item)) { + instances.push( + this.model.getInstance( + { + kind: data.kind, inventory: data.data.inventory, + key: item, value: data.options[option_name].vars[item], + }, + this.clone(), + ), + ); + } } return instances; - }; + } /** * Method, that checks existence of instance. * @param {object} template_instance Template instance. @@ -1618,7 +1635,7 @@ guiQuerySets.TemplateOptionVariableQuerySet = class TemplateOptionVariableQueryS } return false; - }; + } /** * Method, that returns option data object. * @param {object} template_data Data of template instance. @@ -1634,7 +1651,7 @@ guiQuerySets.TemplateOptionVariableQuerySet = class TemplateOptionVariableQueryS key: instance_name, value: template_data.options[option_name].vars[instance_name], }; - }; + } /** * Method, that returns Array with names of allowed filters. * @returns {array} @@ -1642,7 +1659,7 @@ guiQuerySets.TemplateOptionVariableQuerySet = class TemplateOptionVariableQueryS */ _getFilterNames() { return ['key', 'value']; - }; + } }; /** diff --git a/polemarch/static/js/pmUsers.js b/polemarch/static/js/pmUsers.js index 8f7560aa..ee7d83cd 100644 --- a/polemarch/static/js/pmUsers.js +++ b/polemarch/static/js/pmUsers.js @@ -1,54 +1,7 @@ -/** - * Function emits signal, that edits UserSettings page view. - * @param {string} path /user/{pk}/settings/. - */ -function editUserSettingsPageInOpenApi(path) { - tabSignal.connect('openapi.loaded', (openapi) => { - let path_obj = openapi.paths[path]; - path_obj.post.operationId = path_obj.post.operationId.replace('_add', '_edit'); - }); -} - -/** - * Function emits signal, that edits UserSettings page_edit view. - * @param {string} path /user/{pk}/settings/edit/. - */ -function editUserSettingsPageEditView(path) { - tabSignal.connect("views[" + path + "].beforeInit", function(obj){ - obj.schema.query_type = "post"; - }); - - tabSignal.connect("views[" + path + "].afterInit", function(obj) { - obj.view.mixins.push(user_settings_page_edit_mixin); - }); -} - -/** - * Function emits signal, that deletes UserSettings page_new view. - * @param {string} path /user/{pk}/settings/new/. - */ -function deleteUserSettingsPageNewView(path) { - tabSignal.connect("allViews.inited", function(obj){ - delete obj.views[path]; - }); -} - -/** - * Function, that emits signals for UserSettings views. - * @param {string} base_path /user/{pk}/settings/. - */ -function prepareUserSettingsViews(base_path) { - editUserSettingsPageInOpenApi(base_path); - - editUserSettingsPageEditView(base_path + 'edit/'); - - deleteUserSettingsPageNewView(base_path + 'new/'); -} - /** * Mixin for UserSettings page_edit view. */ -var user_settings_page_edit_mixin = { +const user_settings_page_edit_mixin = { methods: { saveInstance() { let data = this.getValidData(); @@ -95,6 +48,53 @@ var user_settings_page_edit_mixin = { }, }; +/** + * Function emits signal, that edits UserSettings page view. + * @param {string} path /user/{pk}/settings/. + */ +function editUserSettingsPageInOpenApi(path) { + tabSignal.connect('openapi.loaded', (openapi) => { + let path_obj = openapi.paths[path]; + path_obj.post.operationId = path_obj.post.operationId.replace('_add', '_edit'); + }); +} + +/** + * Function emits signal, that edits UserSettings page_edit view. + * @param {string} path /user/{pk}/settings/edit/. + */ +function editUserSettingsPageEditView(path) { + tabSignal.connect("views[" + path + "].beforeInit", function(obj){ + obj.schema.query_type = "post"; + }); + + tabSignal.connect("views[" + path + "].afterInit", function(obj) { + obj.view.mixins.push(user_settings_page_edit_mixin); + }); +} + +/** + * Function emits signal, that deletes UserSettings page_new view. + * @param {string} path /user/{pk}/settings/new/. + */ +function deleteUserSettingsPageNewView(path) { + tabSignal.connect("allViews.inited", function(obj){ + delete obj.views[path]; + }); +} + +/** + * Function, that emits signals for UserSettings views. + * @param {string} base_path /user/{pk}/settings/. + */ +function prepareUserSettingsViews(base_path) { + editUserSettingsPageInOpenApi(base_path); + + editUserSettingsPageEditView(base_path + 'edit/'); + + deleteUserSettingsPageNewView(base_path + 'new/'); +} + /** * Signal, that edits options of UserSettings model's fields. */ diff --git a/tox.ini b/tox.ini index b0d7e6aa..db0f8f14 100644 --- a/tox.ini +++ b/tox.ini @@ -55,6 +55,15 @@ deps = commands = flake8 --config=.pep8 polemarch +[testenv:jshint] +changedir = ./ +deps = +commands = + bash -c 'jshint polemarch/static/js/*.js' +whitelist_externals = + jshint + bash + [testenv:pylint] basepython = python3.6 deps = From 1f682b16f1dabd0169ad64fd9f6f5ad181354fc8 Mon Sep 17 00:00:00 2001 From: Sergey Klyuykov Date: Mon, 9 Sep 2019 21:22:47 +1000 Subject: [PATCH 05/11] Update requirements.txt, requirements-doc.txt files --- requirements-doc.txt | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-doc.txt b/requirements-doc.txt index 7704600d..cca1418d 100644 --- a/requirements-doc.txt +++ b/requirements-doc.txt @@ -1,2 +1,2 @@ # Docs -vstutils[doc]~=2.7.0 +vstutils[doc]~=2.7.1 diff --git a/requirements.txt b/requirements.txt index 0f261a39..fdce5c86 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main -vstutils[rpc,ldap,doc,prod]~=2.7.0 +vstutils[rpc,ldap,doc,prod]~=2.7.1 docutils==0.15.2 markdown2==2.3.8 From 767471a5067198b810d8477abcf11da891930581 Mon Sep 17 00:00:00 2001 From: Sergey Klyuykov Date: Mon, 9 Sep 2019 21:31:02 +1000 Subject: [PATCH 06/11] Update PM version to 1.4.5 --- polemarch/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polemarch/__init__.py b/polemarch/__init__.py index 81ad951e..bfc792d5 100644 --- a/polemarch/__init__.py +++ b/polemarch/__init__.py @@ -31,6 +31,6 @@ "VST_ROOT_URLCONF": os.getenv("VST_ROOT_URLCONF", 'vstutils.urls'), } -__version__ = "1.4.4" +__version__ = "1.4.5" prepare_environment(**default_settings) From 10de671608a53fb73a78b85c9a5d3430f1e9e364 Mon Sep 17 00:00:00 2001 From: Sergey Klyuykov Date: Mon, 9 Sep 2019 21:36:33 +1000 Subject: [PATCH 07/11] Allow to run codestyle on js changes --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bc89ba13..09bbb105 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,6 +75,7 @@ code_style: changes: - polemarch/main/**/* - polemarch/api/**/* + - polemarch/static/js/* - requirements.txt - Makefile - tox.ini From 4dc11c21c97d8bb95cb4d7a066970088dbd2c12e Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 12 Sep 2019 11:33:17 +1000 Subject: [PATCH 08/11] Fix OneTemplate_group_callback(). polemarch/ce#227 --- polemarch/static/js/pmTemplates.js | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/polemarch/static/js/pmTemplates.js b/polemarch/static/js/pmTemplates.js index 401745de..79bc4089 100644 --- a/polemarch/static/js/pmTemplates.js +++ b/polemarch/static/js/pmTemplates.js @@ -214,7 +214,9 @@ const template_sublink_qs_mixin = (Class_name) => class extends Class_name { * @param {boolean} required Required field or not. */ function OneTemplate_group_callback(required=false) { - /** + let previous_inventory; + + /** * Function - onchange callback of dynamic field - OneTemplate.fields.group. * @param {object} parent_values Values of parent fields. */ @@ -234,10 +236,19 @@ function OneTemplate_group_callback(required=false) { inventory = inventory.value; } + let save_value = false; + + if(previous_inventory === undefined || previous_inventory == inventory) { + save_value = true; + } + + previous_inventory = inventory; + if(inventory && !isNaN(Number(inventory))) { return { format: 'group_autocomplete', required: required, + save_value: save_value, additionalProperties: { list_paths: [ '/project/{' + path_pk_key + '}/inventory/{inventory_id}/all_groups/', @@ -250,6 +261,7 @@ function OneTemplate_group_callback(required=false) { }; } else { return { + save_value: save_value, format: 'autocomplete', required: required, }; @@ -1596,11 +1608,10 @@ guiQuerySets.TemplateOptionVariableQuerySet = class TemplateOptionVariableQueryS let option_name = this.getOptionName(); if(!(data && data.options && data.options[option_name] && - data.options[option_name].vars)) { + data.options[option_name].vars)) { return instances; } - debugger; for(let item in data.options[option_name].vars) { if(data.options[option_name].vars.hasOwnProperty(item)) { instances.push( From 4f0a4045b4278a864eb74b046dcd90992140bce9 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 12 Sep 2019 12:07:47 +1000 Subject: [PATCH 09/11] Fix history StdOut. --- polemarch/static/js/pmHistory.js | 8 +------- polemarch/static/js/pmUsers.js | 3 +++ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/polemarch/static/js/pmHistory.js b/polemarch/static/js/pmHistory.js index c162cfad..8bee5b3e 100644 --- a/polemarch/static/js/pmHistory.js +++ b/polemarch/static/js/pmHistory.js @@ -567,13 +567,7 @@ const history_pk_mixin = { * @param {string} line_content Content of line. */ ansiUp(line_content) { - let comments = []; // Array to collect all comments - let strings = []; // Array to collect all line - let res = []; // Array to collect all RegEx - let all = {'C': comments, 'S': strings, 'R': res}; /* jshint unused: false */ /* TODO check can we delete this variables */ - let safe = {'<': '<', '>': '>', '&': '&'}; /* jshint unused: false */ - - let ansi_up = AnsiUp(); /* globals AnsiUp */ + let ansi_up = new AnsiUp(); /* globals AnsiUp */ ansi_up.use_classes = true; let html = ansi_up.ansi_to_html(line_content); diff --git a/polemarch/static/js/pmUsers.js b/polemarch/static/js/pmUsers.js index ee7d83cd..a220c51f 100644 --- a/polemarch/static/js/pmUsers.js +++ b/polemarch/static/js/pmUsers.js @@ -17,7 +17,9 @@ const user_settings_page_edit_mixin = { let instance = this.data.instance; instance.data = data; let method = this.view.schema.query_type; + this.loading = true; instance.save(method).then(instance => { + this.loading = false; let qs = this.getQuerySet(this.view, this.qs_url).clone(); qs.cache = instance; this.setQuerySet(this.view, this.qs_url, qs); @@ -31,6 +33,7 @@ const user_settings_page_edit_mixin = { this.$router.push({path: url}); }).catch(error => { + this.loading = false; let str = app.error_handler.errorToString(error); let srt_to_show = pop_up_msg.instance.error.save.format( From a3bcb1cf2c93ebde8559fc08f9b37b0a258d3fc6 Mon Sep 17 00:00:00 2001 From: Roman Date: Thu, 12 Sep 2019 14:47:08 +1000 Subject: [PATCH 10/11] Update VSTUtils version in requirements. --- requirements-doc.txt | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements-doc.txt b/requirements-doc.txt index cca1418d..fc513649 100644 --- a/requirements-doc.txt +++ b/requirements-doc.txt @@ -1,2 +1,2 @@ # Docs -vstutils[doc]~=2.7.1 +vstutils[doc]~=2.8.1 diff --git a/requirements.txt b/requirements.txt index fdce5c86..b64abcdc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main -vstutils[rpc,ldap,doc,prod]~=2.7.1 +vstutils[rpc,ldap,doc,prod]~=2.8.1 docutils==0.15.2 markdown2==2.3.8 From 6e46eb3b1e038c309aaf16f938d2699885365f43 Mon Sep 17 00:00:00 2001 From: Sergey Klyuykov Date: Mon, 16 Sep 2019 16:37:16 +1000 Subject: [PATCH 11/11] Fix `dockerrun` command for uwsgi usage --- polemarch/__init__.py | 2 +- polemarch/main/settings.py | 2 ++ polemarch/web.ini | 6 ++++++ requirements-doc.txt | 2 +- requirements.txt | 2 +- 5 files changed, 11 insertions(+), 3 deletions(-) diff --git a/polemarch/__init__.py b/polemarch/__init__.py index bfc792d5..81ad951e 100644 --- a/polemarch/__init__.py +++ b/polemarch/__init__.py @@ -31,6 +31,6 @@ "VST_ROOT_URLCONF": os.getenv("VST_ROOT_URLCONF", 'vstutils.urls'), } -__version__ = "1.4.5" +__version__ = "1.4.4" prepare_environment(**default_settings) diff --git a/polemarch/main/settings.py b/polemarch/main/settings.py index 9805c807..7eebf4c7 100644 --- a/polemarch/main/settings.py +++ b/polemarch/main/settings.py @@ -1,6 +1,8 @@ from collections import OrderedDict from vstutils.settings import * +WEBSERVER_COMMAND = 'webserver' + POLEMARCH_VERSION = PROJECT_VERSION APACHE = False if ("runserver" in sys.argv) else True diff --git a/polemarch/web.ini b/polemarch/web.ini index 04330a6b..5f893488 100755 --- a/polemarch/web.ini +++ b/polemarch/web.ini @@ -7,13 +7,19 @@ program_name = %(lib_name) module = %(program_name).wsgi:application # number of workers +if-not-opt = processes processes = %k +endif= # number of threads per worker +if-not-opt = threads threads = 2 +endif= # PID-file for service +if-not-opt = pidfile pidfile = /var/run/%(program_name)/web.pid +endif= # Fix mime types mimefile = /etc/mime.types diff --git a/requirements-doc.txt b/requirements-doc.txt index fc513649..bdb227de 100644 --- a/requirements-doc.txt +++ b/requirements-doc.txt @@ -1,2 +1,2 @@ # Docs -vstutils[doc]~=2.8.1 +vstutils[doc]~=2.8.2 diff --git a/requirements.txt b/requirements.txt index b64abcdc..0045d8d6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ # Main -vstutils[rpc,ldap,doc,prod]~=2.8.1 +vstutils[rpc,ldap,doc,prod]~=2.8.2 docutils==0.15.2 markdown2==2.3.8