From 3fa1f40314f972c17cb91f6ff39570e16ba874c2 Mon Sep 17 00:00:00 2001 From: booblegum Date: Thu, 24 Nov 2016 13:15:08 +0300 Subject: [PATCH] =?UTF-8?q?PR-41=20=D0=A4=D0=BE=D1=80=D0=BC=D0=B8=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=BA=D0=B0?= =?UTF-8?q?=D0=B7=D0=B0=20=D0=97=D0=B0=D0=BA=D0=B0=D0=B7=D1=87=D0=B8=D0=BA?= =?UTF-8?q?=D0=BE=D0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit in progress... --- archilance/settings/base.py | 1 + .../proekton-components/bash/browserify.sh | 5 +- .../js/build/init_customer_project_create.js | 1402 +++++++++++++++++ .../js/src/init_customer_project_create.js | 66 + projects/models.py | 21 +- .../static/css/customer_project_create.css | 62 + projects/static/img/circle_cross.svg | 74 + projects/static/img/paper-clip_icon._g.png | Bin 0 -> 2132 bytes projects/static/img/paper-clip_icon.png | Bin 0 -> 30195 bytes projects/static/js/textarea_additional.js | 14 + .../templates/customer_project_create.html | 1 + .../customer_project_create_new.html | 276 ++++ projects/urls.py | 2 + projects/views.py | 82 + wallets/admin.py | 9 +- 15 files changed, 2001 insertions(+), 14 deletions(-) create mode 100644 assets/lib/proekton-components/js/build/init_customer_project_create.js create mode 100644 assets/lib/proekton-components/js/src/init_customer_project_create.js create mode 100644 projects/static/css/customer_project_create.css create mode 100644 projects/static/img/circle_cross.svg create mode 100644 projects/static/img/paper-clip_icon._g.png create mode 100644 projects/static/img/paper-clip_icon.png create mode 100644 projects/static/js/textarea_additional.js create mode 100644 projects/templates/customer_project_create_new.html diff --git a/archilance/settings/base.py b/archilance/settings/base.py index bdaa9cf..1c5bbe7 100644 --- a/archilance/settings/base.py +++ b/archilance/settings/base.py @@ -128,6 +128,7 @@ TEMPLATES = [ 'mathfilters.templatetags.mathfilters', ], + 'debug': DEBUG, # 'loaders': [ # ('django.template.loaders.cached.Loader', [ # 'django.template.loaders.filesystem.Loader', diff --git a/assets/lib/proekton-components/bash/browserify.sh b/assets/lib/proekton-components/bash/browserify.sh index 8dae6c2..23b9365 100644 --- a/assets/lib/proekton-components/bash/browserify.sh +++ b/assets/lib/proekton-components/bash/browserify.sh @@ -2,6 +2,7 @@ echo "run browserify" cd .. source ~/venv/proekton/bin/activate -browserify ./js/src/init.js -o ./js/build/init.js -t babelify -browserify ./js/src/init_user_profile.js -o ./js/build/init_user_profile.js -t babelify +#browserify ./js/src/init.js -o ./js/build/init.js -t babelify +#browserify ./js/src/init_user_profile.js -o ./js/build/init_user_profile.js -t babelify +browserify ./js/src/init_customer_project_create.js -o ./js/build/init_customer_project_create.js -t babelify #watchify ./js/src/init.js -t babelify -o ./js/build/init.js \ No newline at end of file diff --git a/assets/lib/proekton-components/js/build/init_customer_project_create.js b/assets/lib/proekton-components/js/build/init_customer_project_create.js new file mode 100644 index 0000000..68adfcf --- /dev/null +++ b/assets/lib/proekton-components/js/build/init_customer_project_create.js @@ -0,0 +1,1402 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o\n
\n ' + header + '\n
\n
\n ' + name + '\n
\n \n \n'; +}; + +var SelectedContainer = (_class = function () { + function SelectedContainer($container, _ref) { + var _this = this; + + var obj = _ref.obj, + _ref$noTree = _ref.noTree, + noTree = _ref$noTree === undefined ? false : _ref$noTree, + _ref$onlyOne = _ref.onlyOne, + onlyOne = _ref$onlyOne === undefined ? false : _ref$onlyOne; + + _classCallCheck(this, SelectedContainer); + + // TODO: rename variables to camelCase + this.$self = $container; + this.elements_id = []; // [spec_id, spec_id, ...] + this.onlyOne = onlyOne; + var self = this; + this.$self.hide(); + + obj.dataPromise.then(function (data) { + _this.dataTree = noTree ? new _NoTreeData2.default(data.results) : new _DataTree2.default(data.results); + _this.$input = _this.$self.find('input[type="hidden"]'); + _this.restoreElements(); + }).catch(self._onLoadDataError.bind(self)); + } + + _createClass(SelectedContainer, [{ + key: 'restoreElements', + value: function restoreElements() { + var self = this; + if (this.$input && this.$input.val()) { + + var clearString = this.$input.val().replace(/[\[\]\'\'\"\"]/g, ''); + var data = clearString.split(',').filter(function (el) { + return el; + }); + this.elements_id = []; + if (this.$input) this.$input.val(this.elements_id.join(',')); + data.forEach(function (el) { + return self.add(el); + }); + } + } + }, { + key: 'on', + value: function on(methodName, func) { + this[methodName] = this[methodName].bind(this, { func: func, bindFunc: true }); + } + }, { + key: '_removeById', + value: function _removeById(id) { + var index = this.elements_id.indexOf(id); + if (index >= 0) { + this.elements_id.splice(index, 1); + } + this.$self.find('span[data-id=\'' + id + '\']').parents('.selected-element').remove(); + } + }, { + key: '_onLoadDataError', + value: function _onLoadDataError(error) { + console.log("Error loading data -->", error); + } + }, { + key: 'remove', + value: function remove(e) { + var spec_id = $(e.target).data("id"); + this._removeById(spec_id); + if (this.$input) this.$input.val(this.elements_id.join(',')); + if (!this.elements_id.length) this.$self.hide(); + e.preventDefault(); + } + }, { + key: 'replace', + value: function replace(_id, max_len) { + var id = Number(_id); + if (this.elements_id.length > 1) throw new RangeError("Replace error: more than one element"); + // Remove old + this._removeById(this.elements_id[0]); + //Add new + this._addElementToHtml(id, max_len); + this.elements_id = [id]; + } + }, { + key: '_addElementToHtml', + value: function _addElementToHtml(id, max_len) { + var self = this; + var header = SelectedContainer.getHeader(this.dataTree.getSpecChain(id), "", max_len); + var name = this.dataTree.getElementById(id).name; + this.elements_id.push(id); + if (this.$input) this.$input.val(this.elements_id.join(',')); + this.$self.append(SelectedContainer.getTemplate(header || " ", name, id)); + this.btn_remove = this.$self.find('.icon-remove'); + this.btn_remove.on("click", this.remove.bind(self)); + if (this.elements_id.length) this.$self.show(); + } + }, { + key: 'add', + value: function add(_id, max_len) { + var id = Number(_id); + var self = this; + if (this.onlyOne) { + this.replace(_id, max_len); + return; + } + + var has_already = this.elements_id.filter(function (el) { + return self.dataTree.isChild(el, id); + }); + + if (has_already.length || this.elements_id.indexOf(Number(id)) != -1) { + //TODO: do popup messages + return; + } + + var not_valid = this.elements_id.filter(function (el) { + return self.dataTree.isChild(id, el); + }); + + not_valid.forEach(function (el) { + self._removeById(el); + }); + this._addElementToHtml(id, max_len); + } + }], [{ + key: 'getTemplate', + value: function getTemplate(header, name, id) { + return tmpl_selectedElement(header, name, id); + } + }, { + key: 'getHeader', + value: function getHeader(spec_chain, separator, max_len) { + function toShortString(string, max_len) { + return string.slice(0, max_len) + (string.length > max_len ? "..." : ""); + } + + separator = separator || ' / '; + var str_chain = ""; + + spec_chain.forEach(function (el) { + str_chain = (max_len ? toShortString(el.name, max_len) : el.name) + (str_chain ? separator : "") + str_chain; + }); + + return str_chain; + } + }]); + + return SelectedContainer; +}(), (_applyDecoratedDescriptor(_class.prototype, 'remove', [_decorators2.default], Object.getOwnPropertyDescriptor(_class.prototype, 'remove'), _class.prototype), _applyDecoratedDescriptor(_class.prototype, 'add', [_decorators2.default], Object.getOwnPropertyDescriptor(_class.prototype, 'add'), _class.prototype)), _class); +exports.default = SelectedContainer; + +},{"./data/DataTree":6,"./data/NoTreeData":7,"./decorators":8}],3:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _AbsBaseSelect = require('./base/AbsBaseSelect'); + +var _TreeSelect2 = require('./TreeSelect'); + +var _TreeSelect3 = _interopRequireDefault(_TreeSelect2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var tmpl_selectBoxResults = function tmpl_selectBoxResults() { + return '\n
\n
\n
\n
    \n
\n
\n
\n
\n'; +}; + +var tmpl_elementResult = function tmpl_elementResult(el, id, header) { + return '
  • \n ' + el + '\n
  • '; +}; + +var SingleTreeSelect = function (_TreeSelect) { + _inherits(SingleTreeSelect, _TreeSelect); + + function SingleTreeSelect() { + _classCallCheck(this, SingleTreeSelect); + + return _possibleConstructorReturn(this, (SingleTreeSelect.__proto__ || Object.getPrototypeOf(SingleTreeSelect)).apply(this, arguments)); + } + + _createClass(SingleTreeSelect, [{ + key: 'getTemplate', + value: function getTemplate(classes) { + var selectBox = this.hasEditableContainer ? (0, _AbsBaseSelect.tmpl_selectBoxEditCont)() : (0, _AbsBaseSelect.tmpl_selectBox)(); + classes = classes ? classes.join(" ") : ""; + return (0, _AbsBaseSelect.htmlTemplate)({ + header: "TestHeader", selectBox: selectBox, id: this.containerId, classes: classes, + tmpl_selectBoxOptions: _AbsBaseSelect.tmpl_selectBoxOptions, tmpl_selectBoxResults: tmpl_selectBoxResults + }); + } + }, { + key: '_fillResultsData', + value: function _fillResultsData(searchText) { + var self = this; + // FILL RESULTS + // MAIN PART + var $container = this.$resultsBox.find('.main-part ul'); + this._fillContainer($container, tmpl_elementResult, { searchText: searchText, parentCategoryId: self.parentId, attached: false }); + + this.$resultsBox.find('li').on("click", function (e) { + var id = $(e.target).data("id"); + self.selectedEl.id = id; + self.selectedEl.value = self.dataTree.getElementById(id).name; + self.$searchInput.val(self.selectedEl.value); + self.updateEditableContainer(id); + if (self.$buttonAddOptions) self.$buttonAddOptions.show(); + self.$resultsBox.hide(); + + //TODO: duplicate code + if (self.nextSelectBox && self.dataTree.hasChildren(self.selectedEl.id)) { + self.nextSelectBox.setParent(self.selectedEl.id); + self.nextSelectBox.setHeader(self.selectedEl.value); + self.nextSelectBox.show(); + } + if (self.prevSelectBox) { + self.prevSelectBox.$buttonAddOptions.hide(); + self.prevSelectBox.$searchInput.removeClass("active"); + } + self.$searchInput.addClass('active'); + }); + } + }]); + + return SingleTreeSelect; +}(_TreeSelect3.default); + +exports.default = SingleTreeSelect; + +},{"./TreeSelect":4,"./base/AbsBaseSelect":5}],4:[function(require,module,exports){ +'use strict'; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = undefined; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } }; + +var _AbsBaseSelect2 = require('./base/AbsBaseSelect'); + +var _DataTree = require('./data/DataTree'); + +var _DataTree2 = _interopRequireDefault(_DataTree); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } + +function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } + +var TreeSelect = function (_AbsBaseSelect) { + _inherits(TreeSelect, _AbsBaseSelect); + + function TreeSelect($container, _ref) { + var url = _ref.url, + obj = _ref.obj, + _ref$hasEditableConta = _ref.hasEditableContainer, + hasEditableContainer = _ref$hasEditableConta === undefined ? false : _ref$hasEditableConta, + _ref$visible = _ref.visible, + visible = _ref$visible === undefined ? hasEditableContainer : _ref$visible; + + _classCallCheck(this, TreeSelect); + + //TODO: сделать автоматическую передачу всех параметров родителю + return _possibleConstructorReturn(this, (TreeSelect.__proto__ || Object.getPrototypeOf(TreeSelect)).call(this, $container, { url: url, obj: obj, hasEditableContainer: hasEditableContainer, visible: visible })); + } + + _createClass(TreeSelect, [{ + key: 'setNearbySelectBox', + value: function setNearbySelectBox(next, prev) { + this.nextSelectBox = next; + this.prevSelectBox = prev; + } + }, { + key: 'clearAllNext', + value: function clearAllNext() { + this.clear(); + if (this.nextSelectBox) { + this.nextSelectBox.hide(); + this.nextSelectBox.clearAllNext(); + } + } + }, { + key: 'clearAllPrev', + value: function clearAllPrev() { + this.clear(); + if (this.prevSelectBox) { + this.clear(); + this.hide(); + this.prevSelectBox.clearAllPrev(); + } + } + }, { + key: '_buildComponents', + value: function _buildComponents(data) { + _get(TreeSelect.prototype.__proto__ || Object.getPrototypeOf(TreeSelect.prototype), '_buildComponents', this).call(this, data); + //TODO: Изменять свойство visible при show/hide + if (!this.visible) this.hide(); + if (this.hasEditableContainer) this.$editableContainer.hide(); + this.dataTree = this.dataTree || new _DataTree2.default(data.results); + this._fillOptionsData(); + this._bindEvents(); + } + }, { + key: '_onclickOptionsElement', + value: function _onclickOptionsElement(e) { + this.clearAllNext(); + _get(TreeSelect.prototype.__proto__ || Object.getPrototypeOf(TreeSelect.prototype), '_onclickOptionsElement', this).call(this, e); + if (this.nextSelectBox && this.dataTree.hasChildren(this.selectedEl.id)) { + this.nextSelectBox.setParent(this.selectedEl.id); + this.nextSelectBox.setHeader(this.selectedEl.value); + this.nextSelectBox.show(); + } + if (this.prevSelectBox) { + this.prevSelectBox.$buttonAddOptions.hide(); + this.prevSelectBox.$searchInput.removeClass("active"); + } + this.$searchInput.addClass('active'); + } + }, { + key: '_onButtonAddOptions', + value: function _onButtonAddOptions(e) { + // this._addToSelectedContainer(this.selectedEl.id); + // this.clear(); + // e.preventDefault(); + // return false; + _get(TreeSelect.prototype.__proto__ || Object.getPrototypeOf(TreeSelect.prototype), '_onButtonAddOptions', this).call(this, e); + this.clearAllNext(); + this.clearAllPrev(); + } + }, { + key: '_onButtonAdd', + value: function _onButtonAdd(e) { + _get(TreeSelect.prototype.__proto__ || Object.getPrototypeOf(TreeSelect.prototype), '_onButtonAdd', this).call(this, e); + this.clearAllNext(); + this.clearAllPrev(); + } + }, { + key: '_addToSelectedContainer', + value: function _addToSelectedContainer(id) { + if (this.selectedContainer) { + this.selectedContainer.add(id); + return; + } + + this.prevSelectBox._addToSelectedContainer(id); + } + }]); + + return TreeSelect; +}(_AbsBaseSelect2.AbsBaseSelect); + +exports.default = TreeSelect; + +},{"./base/AbsBaseSelect":5,"./data/DataTree":6}],5:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +//TEMPLATES ` +var tmpl_selectBoxEditCont = function tmpl_selectBoxEditCont() { + var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref$preloaderTemplat = _ref.preloaderTemplate, + preloaderTemplate = _ref$preloaderTemplat === undefined ? "" : _ref$preloaderTemplat; + + return "\n
    \n
    \n \n
    \n " + preloaderTemplate + "\n \n \n
    \n
    \n
    \n \n
    \n
    \n"; +}; + +var tmpl_selectBox = function tmpl_selectBox() { + var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, + _ref2$preloaderTempla = _ref2.preloaderTemplate, + preloaderTemplate = _ref2$preloaderTempla === undefined ? "" : _ref2$preloaderTempla; + + return " \n " + preloaderTemplate + "\n \n \n"; +}; + +var tmpl_elementResult = function tmpl_elementResult(el, id, header) { + return "
  • "; +}; + +var tmpl_elementOption = function tmpl_elementOption(el) { + return "
  • " + el.name + "
  • "; +}; + +var tmpl_plug = function tmpl_plug(_ref3) { + var header = _ref3.header, + selectBox = _ref3.selectBox; + return htmlTemplate({ header: header, selectBox: selectBox }); +}; + +var tmpl_selectBoxOptions = function tmpl_selectBoxOptions() { + return "\n
    \n
    \n
      \n \n
    \n
    \n
    \n"; +}; + +var tmpl_selectBoxResults = function tmpl_selectBoxResults() { + return "\n
    \n
    \n
    \n
      \n
    \n
    \n
    \n \u0418\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0439\n
      \n
    \n
    \n
    \n
    \n \n
    \n
    \n"; +}; + +var htmlTemplate = function htmlTemplate(_ref4) { + var header = _ref4.header, + selectBox = _ref4.selectBox, + _ref4$id = _ref4.id, + id = _ref4$id === undefined ? "" : _ref4$id, + _ref4$classes = _ref4.classes, + classes = _ref4$classes === undefined ? "" : _ref4$classes, + _ref4$tmpl_selectBoxO = _ref4.tmpl_selectBoxOptions, + tmpl_selectBoxOptions = _ref4$tmpl_selectBoxO === undefined ? function () { + return ""; + } : _ref4$tmpl_selectBoxO, + _ref4$tmpl_selectBoxR = _ref4.tmpl_selectBoxResults, + tmpl_selectBoxResults = _ref4$tmpl_selectBoxR === undefined ? function () { + return ""; + } : _ref4$tmpl_selectBoxR; + return "\n
    \n
    \n
    " + header + "
    \n \n
    \n
    \n " + selectBox + "\n
    \n \n " + tmpl_selectBoxOptions() + "\n " + tmpl_selectBoxResults() + "\n \n
    \n"; +}; +var tmpl_light = function tmpl_light(el) { + return "" + el + ""; +}; + +var tmpl_preloader = function tmpl_preloader() { + return "
    "; +}; + +var AbsBaseSelect = function () { + function AbsBaseSelect($container, _ref5) { + var url = _ref5.url, + obj = _ref5.obj, + _ref5$hasEditableCont = _ref5.hasEditableContainer, + hasEditableContainer = _ref5$hasEditableCont === undefined ? false : _ref5$hasEditableCont, + _ref5$visible = _ref5.visible, + visible = _ref5$visible === undefined ? false : _ref5$visible; + + _classCallCheck(this, AbsBaseSelect); + + if (new.target === AbsBaseSelect) { + throw new TypeError("Cannot construct Abstract instances directly"); + } + if (obj && url) { + throw new URIError("Must be either the date or url"); + } + + var self = this; + //TODO: проверка наличия id контейнера + this.containerId = $container.attr("id"); + this.$container = $container; + this.hasEditableContainer = hasEditableContainer; + this.visible = visible; + // Быстрая заглушка, до отображения данных + if (visible) { + var preloaderTemplate = tmpl_preloader(); + var selectBox = this.hasEditableContainer ? tmpl_selectBoxEditCont({ preloaderTemplate: preloaderTemplate }) : tmpl_selectBox({ preloaderTemplate: preloaderTemplate }); + var plugTemplate = tmpl_plug({ header: "Loading...", selectBox: selectBox }); + $container.html(plugTemplate); + + this.$preloader = $container.find('#component-preloader'); + this.$spinner = this.$preloader.find('.spinner'); + } + if (url) this.dataPromise = this.getData(url); + var _dataPromise = void 0; + if (url) { + _dataPromise = this.dataPromise; + } else { + _dataPromise = obj.dataPromise; + } + // if (dataTree) this.dataTree = dataTree; + _dataPromise.then(self._buildComponents.bind(self)).catch(self._onLoadDataError.bind(self)); + + // INIT EMPTY PROP + this.selectedEl = { id: undefined, value: undefined }; + this.parentId = undefined; + } + + _createClass(AbsBaseSelect, [{ + key: "getTemplate", + value: function getTemplate(classes) { + var selectBox = this.hasEditableContainer ? tmpl_selectBoxEditCont() : tmpl_selectBox(); + classes = classes ? classes.join(" ") : ""; + return htmlTemplate({ + header: "TestHeader", selectBox: selectBox, id: this.containerId, classes: classes, + tmpl_selectBoxOptions: tmpl_selectBoxOptions, tmpl_selectBoxResults: tmpl_selectBoxResults + }); + } + }, { + key: "getData", + value: function getData(url) { + var data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var self = this; + return Promise.resolve($.ajax({ + url: url, + dataType: 'json', + data: data + })); + } + }, { + key: "hidePreloader", + value: function hidePreloader() { + // console.log("hide preloader ", this.$preloader); + this.$spinner.fadeOut(); + return Promise.resolve(this.$preloader.delay(500).fadeOut(2000)); + } + }, { + key: "clear", + value: function clear() { + this.$searchInput.val(""); + this.$optionsBox.hide(); + this.$resultsBox.hide(); + this.$buttonAdd.hide(); + this.$buttonAddOptions.hide(); + this.selectedEl = { id: undefined, value: undefined }; + if (this.hasEditableContainer) { + this.$editableContainer.html(""); + this.$editableContainer.hide(); + } + this.$searchInput.removeClass("active"); + } + }, { + key: "hide", + value: function hide() { + this.$selectBox.hide(); + } + }, { + key: "show", + value: function show() { + this.$selectBox.show(); + } + }, { + key: "setHeader", + value: function setHeader(header) { + + if (this.$header) { + this.$header.html(header); + } else { + this.header = header; + } + // default hide + // this.show(); + } + }, { + key: "setParent", + value: function setParent(parentId) { + this.parentId = parentId; + this._fillOptionsData(); + } + }, { + key: "connectSelectedContainer", + value: function connectSelectedContainer(selectedContainer) { + this.selectedContainer = selectedContainer; + } + }, { + key: "getIdsSelectedElements", + value: function getIdsSelectedElements() { + var allChecked = this.$resultsBox.find(":checked"); + return allChecked.map(function () { + return $(this).data("id"); + }); + } + }, { + key: "updateEditableContainer", + value: function updateEditableContainer(elId) { + // Если нет контейнера для отображения ... + if (this.$editableContainer.length) { + var separator = ' / '; + var chainHeader = AbsBaseSelect.getHeader(this.dataTree.getSpecChain(elId, true), { separator: separator }); + chainHeader = AbsBaseSelect.highlight(chainHeader, separator, true); + var elTemplate = "" + chainHeader + ""; + this.$editableContainer.html(elTemplate); + this.$editableContainer.show(); + return; + } + //..., передаем отображение предыдущему selectBox + if (this.prevSelectBox) this.prevSelectBox.updateEditableContainer(elId); + } + }, { + key: "_buildComponents", + value: function _buildComponents(data) { + // AFTER PRELOAD + // this.hidePreloader().then(() => console.log("END -)")); + var classes = this.$container.attr('class'); + if (classes) classes = classes.split(/\s+/); + var template = this.getTemplate(classes); + this.$container.replaceWith(template); + + this.$selectBox = $("#" + this.containerId); + this.$header = this.$selectBox.find('.select-box-header .header'); + this.$header.html(this.header); + this.$resultsBox = this.$selectBox.find('.select-box-results'); + this.$optionsBox = this.$selectBox.find('.select-box-options'); + this.$searchInput = this.$selectBox.find('input.select-box-search'); + this.$buttonAdd = this.$selectBox.find('.button-add.results'); + this.$buttonAddOptions = this.$selectBox.find('.button-add.options'); + this.$editableContainer = this.$selectBox.find('.editable-container'); + this.$resultsBox.hide(); + this.$optionsBox.hide(); + this.$buttonAddOptions.hide(); + // TODO: сделать проверку на наличие всех нужных элементов и их корректый jq select + + // REDEFINE IN CHILD + // this.dataTree = data; + // this._bindEvents(); + } + }, { + key: "_fillOptionsData", + value: function _fillOptionsData() { + var self = this; + var dataList = this.dataTree.dataToList(this.parentId); + var $container = this.$optionsBox.find('ul'); + $container.html(""); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = dataList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var el = _step.value; + + $container.append($(tmpl_elementOption(el))); + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + this.$selectBox.find('li').on("click", this._onclickOptionsElement.bind(self)); + } + }, { + key: "_search", + value: function _search(_ref6) { + var searchText = _ref6.searchText, + _ref6$parentCategoryI = _ref6.parentCategoryId, + parentCategoryId = _ref6$parentCategoryI === undefined ? null : _ref6$parentCategoryI, + _ref6$attached = _ref6.attached, + attached = _ref6$attached === undefined ? true : _ref6$attached, + _ref6$excludeCategory = _ref6.excludeCategoryId, + excludeCategoryId = _ref6$excludeCategory === undefined ? null : _ref6$excludeCategory; + + // :FORMAT spec_list [{name, id}, ...] + var specList = this.dataTree.dataToList(parentCategoryId, attached, excludeCategoryId); + return specList.filter(function (el) { + return el.name.toLowerCase().indexOf(searchText.toLowerCase()) !== -1; + }); + } + }, { + key: "_fillContainer", + value: function _fillContainer($container, template, _ref7) { + var _ref7$searchText = _ref7.searchText, + searchText = _ref7$searchText === undefined ? "" : _ref7$searchText, + _ref7$parentCategoryI = _ref7.parentCategoryId, + parentCategoryId = _ref7$parentCategoryI === undefined ? null : _ref7$parentCategoryI, + _ref7$attached = _ref7.attached, + attached = _ref7$attached === undefined ? true : _ref7$attached, + _ref7$excludeCategory = _ref7.excludeCategoryId, + excludeCategoryId = _ref7$excludeCategory === undefined ? null : _ref7$excludeCategory; + + $container.html(""); + $('.other-part').show(); + var searchRes = this._search({ searchText: searchText, parentCategoryId: parentCategoryId, attached: attached, excludeCategoryId: excludeCategoryId }); + if (!searchRes.length) { + if ($container.closest('div').hasClass('main-part')) { + $container.append('
  • Ничего не найдено
  • '); + this.$resultsBox.find('.button-add.results').hide(); + } else { + $('.other-part').hide(); + } + return; + } + this.$resultsBox.find('.button-add.results').show(); + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = searchRes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var el = _step2.value; + + var header = AbsBaseSelect.getHeader(this.dataTree.getSpecChain(el.id), {}); + $container.append(template(AbsBaseSelect.highlight(el.name, searchText), el.id, header)); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + } + }, { + key: "_fillResultsData", + value: function _fillResultsData(searchText) { + var self = this; + // FILL RESULTS + // MAIN PART + var $container = this.$resultsBox.find('.main-part ul'); + this._fillContainer($container, tmpl_elementResult, { searchText: searchText, parentCategoryId: self.parentId }); + + // OTHER PART + // Если нет parentId, не нужно искать в других категориях + if (!this.parentId) { + $('.other-part').hide(); + } else { + $container = this.$resultsBox.find('.other-part ul'); + this._fillContainer($container, tmpl_elementResult, { searchText: searchText, excludeCategoryId: self.parentId }); + } + this.$resultsBox.find('div.header').hide(); + this.$resultsBox.find('li').on("mouseover", function (e) { + $(e.target).children('.header').show(300); + e.preventDefault(); + }); + + this.$resultsBox.find('li').on("mouseout", function (event) { + var e = event.toElement || event.relatedTarget; + if (e.parentNode == this || e == this) { + return; + } + $(this).find('.header').hide(); + }); + } + }, { + key: "_onclickOptionsElement", + value: function _onclickOptionsElement(e) { + this.selectedEl.id = $(e.target).data("id"); + this.selectedEl.value = $(e.target).html(); + this.$searchInput.val($(e.target).html()); + this.updateEditableContainer($(e.target).data("id")); + this.$buttonAddOptions.show(); + this.$optionsBox.hide(); + } + }, { + key: "_onButtonAddOptions", + value: function _onButtonAddOptions(e) { + this._addToSelectedContainer(this.selectedEl.id); + this.clear(); + e.preventDefault(); + return false; + } + }, { + key: "_onButtonAdd", + value: function _onButtonAdd(e) { + var self = this; + + this.getIdsSelectedElements().each(function () { + self._addToSelectedContainer(this); + }); + this.clear(); + e.preventDefault(); + return false; + } + }, { + key: "_onLoadDataError", + value: function _onLoadDataError(error) { + console.log("Error loading data -->", error); + } + }, { + key: "_addToSelectedContainer", + value: function _addToSelectedContainer(id) { + this.selectedContainer.add(id); + } + }, { + key: "_bindEvents", + value: function _bindEvents() { + var self = this; + $(document).click(function (event) { + if ($(event.target).closest("#" + self.containerId).length) { + return; + } + self._looseFocus(); + }); + // RESULTS BOX + this.$searchInput.on("input", function (e) { + self._fillResultsData(self.$searchInput.val()); + self.$resultsBox.show(); + self.$optionsBox.hide(); + }); + // OPTIONS BOX + this.$searchInput.on("click", function (e) { + self.$optionsBox.show(); + self.$resultsBox.hide(); + self.$searchInput.val(""); + }); + + this.$buttonAdd.on("click", function (e) { + self._onButtonAdd(e); + }); + + this.$buttonAddOptions.on("click", this._onButtonAddOptions.bind(self)); + } + }, { + key: "_looseFocus", + value: function _looseFocus() { + this.$resultsBox.hide(); + this.$optionsBox.hide(); + if (!this.selectedEl.id) { + this.$searchInput.val(""); + } else { + this.$searchInput.val(this.selectedEl.value); + } + } + }], [{ + key: "getHeader", + value: function getHeader(catChain, _ref8) { + var _ref8$separator = _ref8.separator, + separator = _ref8$separator === undefined ? " / " : _ref8$separator, + _ref8$maxLen = _ref8.maxLen, + maxLen = _ref8$maxLen === undefined ? 60 : _ref8$maxLen; + + function toShortString(string, maxLen) { + return string.slice(0, maxLen) + (string.length > maxLen ? "..." : ""); + } + + var strChain = ""; + + catChain.forEach(function (el) { + strChain = (maxLen ? toShortString(el.name, maxLen) : el.name) + (strChain ? separator : "") + strChain; + }); + + return strChain; + } + }, { + key: "highlight", + value: function highlight(string, sub_string) { + var lastIndex = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + var index = lastIndex ? string.toLowerCase().lastIndexOf(sub_string.toLowerCase()) : string.toLowerCase().indexOf(sub_string.toLowerCase()); + if (index === -1) return string; + var before = void 0, + select = void 0, + after = void 0; + if (lastIndex) { + var _ref9 = [string.slice(0, index), string.slice(index, string.length), ""]; + before = _ref9[0]; + select = _ref9[1]; + after = _ref9[2]; + } else { + var _ref10 = [string.slice(0, index), string.slice(index, index + sub_string.length), string.slice(index + sub_string.length)]; + before = _ref10[0]; + select = _ref10[1]; + after = _ref10[2]; + } + + return "" + before + tmpl_light(select) + after; + } + }]); + + return AbsBaseSelect; +}(); + +exports.default = AbsBaseSelect; +exports.htmlTemplate = htmlTemplate; +exports.tmpl_plug = tmpl_plug; +exports.tmpl_elementOption = tmpl_elementOption; +exports.tmpl_preloader = tmpl_preloader; +exports.tmpl_light = tmpl_light; +exports.tmpl_elementResult = tmpl_elementResult; +exports.tmpl_selectBox = tmpl_selectBox; +exports.tmpl_selectBoxEditCont = tmpl_selectBoxEditCont; +exports.tmpl_selectBoxResults = tmpl_selectBoxResults; +exports.tmpl_selectBoxOptions = tmpl_selectBoxOptions; +exports.AbsBaseSelect = AbsBaseSelect; + +},{}],6:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Node = function Node(data, tree) { + _classCallCheck(this, Node); + + this.name = data.name; + this.id = data.id; + if (data.parent === null) { + this.parent = "root"; + data.parent = { id: "root" }; + this.name = ""; + } + if (data.parent.id && data.parent.id !== 'root') { + var el = tree._getElementById(data.parent.id); + this.parent = el.node || new Node(el, tree); + } + data.node = this; + this.children = data.children.map(function (el_obj) { + var el = tree._getElementById(el_obj.id); + if (el.node) return el.node; + el.node = new Node(el, tree); + return el.node; + }); + + this.children = this.children || []; +}; + +var DataTree = function () { + function DataTree(data) { + _classCallCheck(this, DataTree); + + this.baseData = data; + this._root = new Node(data[0], this); + } + + /** + * получить element в базовой структуре + */ + + + _createClass(DataTree, [{ + key: "_getElementById", + value: function _getElementById(id) { + for (var i = 0; i < this.baseData.length; i++) { + if (this.baseData[i].id == id) return this.baseData[i]; + } + } + + /** + * получить element в дереве + */ + + }, { + key: "getElementById", + value: function getElementById(id) { + function searchInChildren(children) { + for (var i = 0; i < children.length; i++) { + if (children[i].id == id) return children[i]; + var res = searchInChildren(children[i].children); + if (res) return res; + } + } + + return searchInChildren(this._root.children); + } + + /** + * Является ли узел c el_id дочерним для parent_id + * @param el_id + * @param parent_id + */ + + }, { + key: "isChild", + value: function isChild(elId, parent_id) { + function checkParent(el, parent) { + if (el.parent == parent) return true; + if (el.parent && el.parent != 'root') return checkParent(el.parent, parent); + return false; + } + return checkParent(this.getElementById(elId), this.getElementById(parent_id)); + } + }, { + key: "hasChildren", + value: function hasChildren(elId) { + return this.getElementById(elId).children.length ? true : false; + } + + /** + * @param start_parent_id(number) - начиная с + * @param attached(bool) - включая вложенные/дочерние + * @param exclude_id - исключая узел c exclude_id и всеми его вложенными узлами + * @returns [{name, id}, ...] + */ + + }, { + key: "dataToList", + value: function dataToList(start_parent_id, attached, exclude_id) { + var data_list = []; + + function goInChildren(children) { + for (var i = 0; i < children.length; i++) { + if (children[i].id == exclude_id) continue; + data_list.push({ name: children[i].name, id: children[i].id }); + if (attached) goInChildren(children[i].children); + } + } + var start = start_parent_id ? this.getElementById(start_parent_id) : this._root; + goInChildren(start.children); + return data_list; + } + + /** + * + * @param id + * @param incl(bool) - исключая сам элемент + * @returns {Array} всех узлов/элементов от элемента с id до корня + */ + + }, { + key: "getSpecChain", + value: function getSpecChain(id) { + var incl = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + var chain = []; + var el = this.getElementById(id); + function getParent(el) { + if (el.parent && el.parent != "root") { + chain.push(el.parent); + getParent(el.parent); + } + } + getParent(el); + if (incl) chain.unshift(el); + return chain; + } + }]); + + return DataTree; +}(); + +exports.default = DataTree; + +},{}],7:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var NoTreeData = function () { + function NoTreeData(data) { + _classCallCheck(this, NoTreeData); + + this.data = data; + this.specChain = []; + } + + _createClass(NoTreeData, [{ + key: "getElementById", + value: function getElementById(id) { + for (var i = 0; i < this.data.length; i++) { + if (this.data[i].id == id) return this.data[i]; + } + } + }, { + key: "getSpecChain", + value: function getSpecChain(id, incl) { + return this.specChain; + } + }, { + key: "isChild", + value: function isChild(el_id, parent_id) { + return false; + } + }, { + key: "hasChildren", + value: function hasChildren() { + return false; + } + }, { + key: "dataToList", + value: function dataToList() { + return this.data; + } + }]); + + return NoTreeData; +}(); + +exports.default = NoTreeData; + +},{}],8:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = onBind; +function onBind(target, name, descriptor) { + var method = descriptor.value; + + descriptor.value = function () { + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var binds = []; + args = Array.from(args); + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = args.slice()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var arg = _step.value; + + // console.log("onBind -->", typeof arg, "arg = ", arg); + // console.log("arg.func -->", typeof arg.originalEvent); + // typeof arg === 'object' && !(arg.originalEvent) + if (arg.bindFunc) { + binds.push(arg); + args.splice(args.indexOf(arg), 1); + } + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + + method.apply(this, args); + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = binds[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var bind = _step2.value; + + bind.func.bind(this)(); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + + return this; + }; +} + +// export {onBind}; + +},{}],9:[function(require,module,exports){ +'use strict'; + +var _SelectedContainer = require('./SelectedContainer'); + +var _SelectedContainer2 = _interopRequireDefault(_SelectedContainer); + +var _NoTreeSelect = require('./NoTreeSelect'); + +var _NoTreeSelect2 = _interopRequireDefault(_NoTreeSelect); + +var _TreeSelect = require('./TreeSelect'); + +var _TreeSelect2 = _interopRequireDefault(_TreeSelect); + +var _SingleTreeSelect = require('./SingleTreeSelect'); + +var _SingleTreeSelect2 = _interopRequireDefault(_SingleTreeSelect); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +$(function () { + function createFilterSpecs(url) { + // SPECIALIZATIONS FILTER + var sb_main = new _TreeSelect2.default($('#select-box-1'), { url: url, visible: true }); + sb_main.setHeader("Специальность"); + var select_container = new _SelectedContainer2.default($('#selected-spec'), { obj: sb_main }); + sb_main.connectSelectedContainer(select_container); + var sb_1 = new _TreeSelect2.default($('#select-box-2'), { obj: sb_main }); + var sb_2 = new _TreeSelect2.default($('#select-box-3'), { obj: sb_main }); + var sb_3 = new _TreeSelect2.default($('#select-box-4'), { obj: sb_main }); + var sb_4 = new _TreeSelect2.default($('#select-box-5'), { obj: sb_main }); + + sb_main.setNearbySelectBox(sb_1); + sb_1.setNearbySelectBox(sb_2, sb_main); + sb_2.setNearbySelectBox(sb_3, sb_1); + sb_3.setNearbySelectBox(sb_4, sb_2); + sb_4.setNearbySelectBox("", sb_3); + } + + function createFilterBuildingClass(url) { + // BUILDING-CLASSIFICATION FILTER + var sb_build_main = new _TreeSelect2.default($('#sb-building-classification'), { url: url, visible: true }); + sb_build_main.setHeader("Классификация здания"); + + var sb_build_1 = new _TreeSelect2.default($('#sb-building-sub-classification'), { obj: sb_build_main }); + + var select_build_container = new _SelectedContainer2.default($('#selected-building-classification'), { obj: sb_build_main }); + sb_build_main.connectSelectedContainer(select_build_container); + + sb_build_main.setNearbySelectBox(sb_build_1); + sb_build_1.setNearbySelectBox("", sb_build_main); + } + + function createFilterConstructionType(url) { + var sb_constr_main = new _NoTreeSelect2.default($('#sb-construction-type'), { url: url, visible: true }); + sb_constr_main.setHeader("Вид строительства"); + var select_constr_type = new _SelectedContainer2.default($('#selected-construction-type'), { obj: sb_constr_main, noTree: true }); + sb_constr_main.connectSelectedContainer(select_constr_type); + } + + function createFilerLocations(url) { + var sb_loc_main = new _SingleTreeSelect2.default($('#sb-location-1'), { url: url, visible: true }); + sb_loc_main.setHeader("Местоположение"); + var select_loc = new _SelectedContainer2.default($('#selected-location'), { obj: sb_loc_main, onlyOne: true }); + sb_loc_main.connectSelectedContainer(select_loc); + var sb_loc_1 = new _SingleTreeSelect2.default($('#sb-location-2'), { obj: sb_loc_main }); + var sb_loc_2 = new _SingleTreeSelect2.default($('#sb-location-3'), { obj: sb_loc_main }); + + sb_loc_main.setNearbySelectBox(sb_loc_1); + sb_loc_1.setNearbySelectBox(sb_loc_2, sb_loc_main); + sb_loc_2.setNearbySelectBox("", sb_loc_1); + } + + createFilterSpecs('/api/specializations_flat'); + createFilterBuildingClass('/api/building_classifications'); + createFilterConstructionType('/api/construction_type'); + createFilerLocations('/api/locations_flat'); +}); + +},{"./NoTreeSelect":1,"./SelectedContainer":2,"./SingleTreeSelect":3,"./TreeSelect":4}]},{},[9]); diff --git a/assets/lib/proekton-components/js/src/init_customer_project_create.js b/assets/lib/proekton-components/js/src/init_customer_project_create.js new file mode 100644 index 0000000..0e06f48 --- /dev/null +++ b/assets/lib/proekton-components/js/src/init_customer_project_create.js @@ -0,0 +1,66 @@ +import SelectedContainer from './SelectedContainer'; +import NoTreeSelect from './NoTreeSelect'; +import TreeSelect from './TreeSelect'; +import SingleTreeSelect from './SingleTreeSelect' + +$(function () { + function createFilterSpecs(url) { + // SPECIALIZATIONS FILTER + let sb_main = new TreeSelect($('#select-box-1'), {url, visible: true}); + sb_main.setHeader("Специальность"); + let select_container = new SelectedContainer($('#selected-spec'), {obj: sb_main}); + sb_main.connectSelectedContainer(select_container); + let sb_1 = new TreeSelect($('#select-box-2'), {obj: sb_main}); + let sb_2 = new TreeSelect($('#select-box-3'), {obj: sb_main}); + let sb_3 = new TreeSelect($('#select-box-4'), {obj: sb_main}); + let sb_4 = new TreeSelect($('#select-box-5'), {obj: sb_main}); + + sb_main.setNearbySelectBox(sb_1); + sb_1.setNearbySelectBox(sb_2, sb_main); + sb_2.setNearbySelectBox(sb_3, sb_1); + sb_3.setNearbySelectBox(sb_4, sb_2); + sb_4.setNearbySelectBox("", sb_3); + + } + + function createFilterBuildingClass(url) { + // BUILDING-CLASSIFICATION FILTER + let sb_build_main = new TreeSelect($('#sb-building-classification'), {url, visible:true}); + sb_build_main.setHeader("Классификация здания"); + + let sb_build_1 = new TreeSelect($('#sb-building-sub-classification'), {obj: sb_build_main}); + + let select_build_container = new SelectedContainer($('#selected-building-classification'), {obj: sb_build_main}); + sb_build_main.connectSelectedContainer(select_build_container); + + sb_build_main.setNearbySelectBox(sb_build_1); + sb_build_1.setNearbySelectBox("", sb_build_main); + } + + function createFilterConstructionType(url) { + let sb_constr_main = new NoTreeSelect($('#sb-construction-type'), {url, visible:true}); + sb_constr_main.setHeader("Вид строительства"); + let select_constr_type = new SelectedContainer($('#selected-construction-type'), {obj:sb_constr_main, noTree: true}); + sb_constr_main.connectSelectedContainer(select_constr_type); + } + + function createFilerLocations(url) { + let sb_loc_main = new SingleTreeSelect($('#sb-location-1'), {url, visible:true}); + sb_loc_main.setHeader("Местоположение"); + let select_loc = new SelectedContainer($('#selected-location'), {obj: sb_loc_main, onlyOne: true}); + sb_loc_main.connectSelectedContainer(select_loc); + let sb_loc_1 = new SingleTreeSelect($('#sb-location-2'), {obj: sb_loc_main}); + let sb_loc_2 = new SingleTreeSelect($('#sb-location-3'), {obj: sb_loc_main}); + + sb_loc_main.setNearbySelectBox(sb_loc_1); + sb_loc_1.setNearbySelectBox(sb_loc_2, sb_loc_main); + sb_loc_2.setNearbySelectBox("", sb_loc_1); + } + + + createFilterSpecs('/api/specializations_flat'); + createFilterBuildingClass('/api/building_classifications'); + createFilterConstructionType('/api/construction_type'); + createFilerLocations('/api/locations_flat'); + +}); \ No newline at end of file diff --git a/projects/models.py b/projects/models.py index d5ed112..1e03752 100644 --- a/projects/models.py +++ b/projects/models.py @@ -97,21 +97,26 @@ class Project(models.Model, HitCountMixin): ('deleted', 'Удален'), ) + name = models.CharField(max_length=255) + text = models.TextField(blank=True) + customer = models.ForeignKey(User, related_name='customer_projects') + state = models.CharField(default='active', max_length=20, choices=STATES) + specialization = TreeForeignKey(Specialization, related_name='projects') + budget = models.DecimalField(max_digits=10, decimal_places=0) budget_by_agreement = models.BooleanField(default=False) - created = models.DateTimeField(default=timezone.now) - cro = models.BooleanField(default=False) currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES) - customer = models.ForeignKey(User, related_name='customer_projects') + deal_type = models.CharField(max_length=20, default='secure_deal', choices=DEAL_TYPES) - name = models.CharField(max_length=255) price_and_term_required = models.BooleanField(default=False) - realty = models.ForeignKey(Realty, blank=True, null=True, related_name='projects') - specialization = TreeForeignKey(Specialization, related_name='projects') - state = models.CharField(default='active', max_length=20, choices=STATES) + term = models.IntegerField(default=0) term_type = models.CharField(max_length=20, choices=TERM_TYPES, default='hour') - text = models.TextField(blank=True) + + realty = models.ForeignKey(Realty, blank=True, null=True, related_name='projects') + + cro = models.BooleanField(default=False) + created = models.DateTimeField(default=timezone.now) # FIXME: set deprecated http://djbook.ru/rel1.8/topics/migrations.html#considerations-when-removing-model-fields work_type = models.IntegerField(default=1, choices=WORK_TYPES) diff --git a/projects/static/css/customer_project_create.css b/projects/static/css/customer_project_create.css new file mode 100644 index 0000000..dcf462e --- /dev/null +++ b/projects/static/css/customer_project_create.css @@ -0,0 +1,62 @@ +.description { + overflow: hidden; + text-overflow: ellipsis; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 4; /* number of lines to show */ + line-height: 1.8em; /* fallback */ + max-height: 7.2em; /* fallback */ +} + +textarea.description { + width: 100%; + min-height: 200px; +} + +textarea.auto-hint { + color: darkgray; +} + +.btn-plus { + /*width: 300px;*/ + /*text-overflow: clip;*/ + white-space: normal; + padding-left: 18%; + color: #FF0029; + /*height: 80%;*/ + line-height: 1em; + font-family: Arial-MT-Regular; + font-size: 12pt; +} + +.btn-plus:hover { + color: #FF0029; +} + +.btn-plus { + background: url("../img/circle_cross.svg") no-repeat left; + background-position-x: 5px; +} + +.upload-new.paper-clip { + padding-left: 45px; + padding-right: 5px; + background: url("../img/paper-clip_icon._g.png") no-repeat left; + background-size: 30px 30px; + width: auto; +} + +.upload-new.paper-clip p { + font-size: 12pt; + width: auto; + text-align: right; +} + +.documentsChat.mod { + width: auto; + float: none; + display: inline-block; + vertical-align: inherit; + padding: 0; + margin: 0; +} \ No newline at end of file diff --git a/projects/static/img/circle_cross.svg b/projects/static/img/circle_cross.svg new file mode 100644 index 0000000..b3489c3 --- /dev/null +++ b/projects/static/img/circle_cross.svg @@ -0,0 +1,74 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/projects/static/img/paper-clip_icon._g.png b/projects/static/img/paper-clip_icon._g.png new file mode 100644 index 0000000000000000000000000000000000000000..4c8826319a331fb54ef808ba8ca3ad2de500b2ca GIT binary patch literal 2132 zcmai$`#%$m7suyeGxzB0+Ji!o`<|&Vm(1pth+KzIn7e%&Hs&sqDBa|4LOf`QMlKt< zU*?tvxhsT>rD$r4NB_Y0dtR^4=lwe8bzbMkb57bd8*?Fk8GZl&AY^HQus^2LZ-GI_ z?&##rItC9GZs`C%ju^1d-Q%1OW8sQD?w|fGF1SiQ{-ko`5cg7>U_wf{6&Z?fG19R7Sw%Th`W3zdU@XY9>gsO6o-* zGh|FpSeg0@K&h;qU#u=Y+@}$YJT$}v#A0^&jKq;CM`%*R_n9rY!XpbMu{6a0f-wXC z;4ELmO$)xa@Al`?U5q3neo{(;*Y@W+?M7SdD`Qmh+B?&R72*)@&x15;vx>=o^C@&b zJ@wRexBcEgWtRx|nLCsr9=|Bp#g4l_E=Q?V4(WV!Tlaf~8TKwLX^eHO7&8}S)sJC` zbFBdr?4ruaK!Kof^l;~*J2~`wy&F$9H?34v^1LS{UCkn;y-*D|GkBwCA9C|$2oMKt zlW*{NaF85Ljl)pPoRMTFEL)^4QvMy@E_|%c6Pa$SyJ`DaSbrT}Jt>ya0e=5TafHy$ zcqDKJstX6_MlIR52IHmR;Hj@SXlvr|I(32c!zfaAk2+K)Di^EKlk?luq4G&7jZ_d` zUcHwNAQJy$3ZBxz0*vq!_WH_t0t&H`|mZnm{wD6$s_!$f8U?n^%Q z2zh@iRfH6|U1a#n^CJaC-WyEhp3Y&Y)@3Hz(1Xeh-sP;l0!nZXDxjR4+5#OND#7|r zx|$jf(t>ygI?Z5S5{Z8$G2Ecg>zN{X%+tM9C&iz9zI@VmeUv`Wj%kW?Z8uTP8jKvM z0Ugf!(>e8n1+Q$`{=JKhv0LsUDW!KARqNm zwR?mQdd(zewQnO0+hQ->Zc#V?_`sSWB`YiYW^h_3r8^qRs`kTH|-sA0Gd6$w@kN= zE%783rD|sl9{lZ<{dQtv;yOvrCnh-fs{(d6yMs5O3nY?6aQL`(B8f;mjn|S-LX8aY zRxFo}`;)SwO_Di^7mwV9dU69QWGzLXji9NlKng05#BN0WsKBZXt>$0#buCW;N=YXk zo7@O{lv^1vTrR1;Om&71bsON9`pceA&_AX~dGZ+X7Jw1-ot#Q$Tf{>-!<2>kST-M8 zXT{hA4W847QNN*+LDdeb=%M-8yBfcGce+py_|hN0P_&5fai+h7<|is`HADo@ZNHxW zq0^LLUa~U6t|%|^7)JcGp}ET~-P^tH)h=pmWN7#+b5bz+TX#25B3xrb>`91rR~pAX za#O`Nq>tQ>5%(1~oeB-}dyJ8#$utv3{`?W(v#8gOKz_ceHrjj7!H%tBUjv?X?7VU)tpAi)Z6eO6Sw& zLR*IcffTp1ukZ`$DDt^z1c#zKKWb9#pd2R{Bh3Kn-5;^JY8devbmY0wYM#QeGl-q& z-4Y@I!i$h`9-6lF1zn@V54g^^`-6FZSU00&%_Fs8NBZL5UoMKQ%=wB?`GQ)TRf(cWj4Lf$yh2>v=U zT0;6y)Q!tYnpsyNx2g<6#lAm3irro;V)P-|?> tT$=ImDqru%IiMhjl(dwJfOMxY3?VIuNXH;4 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 literal 0 HcmV?d00001 diff --git a/projects/static/js/textarea_additional.js b/projects/static/js/textarea_additional.js new file mode 100644 index 0000000..07b762a --- /dev/null +++ b/projects/static/js/textarea_additional.js @@ -0,0 +1,14 @@ +$(function () { + let $area = $('#with-placeholder'); + let placeholder = $area.prop("placeholder"); + let changed = false; + $area.addClass("auto-hint"); + $area.html(placeholder); + $area.on("click", function (e) { + // if (changed) return + console.log("click"); + $(e.target).removeClass("auto-hit"); + $(e.target).html(""); + return true + }) +}); \ No newline at end of file diff --git a/projects/templates/customer_project_create.html b/projects/templates/customer_project_create.html index 9a8131a..792fe67 100644 --- a/projects/templates/customer_project_create.html +++ b/projects/templates/customer_project_create.html @@ -107,6 +107,7 @@
    {% trans 'project_stage1' %} diff --git a/projects/templates/customer_project_create_new.html b/projects/templates/customer_project_create_new.html new file mode 100644 index 0000000..5715212 --- /dev/null +++ b/projects/templates/customer_project_create_new.html @@ -0,0 +1,276 @@ +{% extends 'partials/base.html' %} +{% load i18n %} +{% load staticfiles %} +{% block head_css %} + + + + + {# other #} + + + + +{% endblock %} + +{% block content %} + {% include 'partials/modals/project_work_type_suggestion.html' %} + {% include 'partials/header.html' %} +
    +
    +
    +
    +

    Новый заказ

    +
    +
    +
    +
    +
    Название заказа + +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    Нет нужной специальности хочу добавить +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + Подобно опишите задание для / ... + Обязательно +
    + + + {#
    #} + {#

    прикрепить файл

    до 100 файлов#} + {#
    #} + +
    +
    +
    +

    прикрепить файл

    +
    + (до 100 файлов) +
    + +
      + +
    +
    + + +
    +
    + +
    +
    +
    + Показать расширенные настройки + +
    +
    +
    +
    + +
    +
    +
    +
    Способ оплаты
    +
    +
    +
    +
    + +
    + Безопасная сделка – это сервис, с помощью которого: + -Заказчики - полностью избавляются от всех финансовых рисков при сотрудничестве с + Исполнителями; + -Исполнители - получают гарантию своевременной оплаты своей работы (выполненной по заданию + точно в срок). + + Это сервис и тип оплаты в заказах, в котором сумма оплаты резервируется (перечисляется на + сайт) Заказчиком до начала работы и выплачивается Исполнителю только после успешного + выполнения задания. А в случае некачественного и/или несвоевременного выполнения – + возвращается Заказчику. + + Сайт выступает в Безопасных сделках хранителем и гарантом сохранности средств. А в случае + возникновения конфликтов в заказе - Арбитром, независимой третьей Стороной, помогающей + решить проблемы при сотрудничестве и справедливо распорядиться зарезервированной суммой: + -выплатить ее Исполнителю, если работа выполнена своевременно и в полном соответствии с + заданием; + -вернуть Заказчику, если работа не выполнена или нарушены сроки выполнения; + -разделить сумму между Заказчиком и Исполнителем, если работа выполнена частично и без + нарушения сроков. +
    +
    +
    + +
    + Прямая оплата - это оплата без помощи сайта. Оплаты заказов происходят напрямую исполнителю + на его личный счет или кошелек. + + В данном случае сайт не выступает гарантом сохранности средств и не является Арбитром при + спорных вопросах. +
    +
    +
    +
    +
    +
    Бюджет + +
    + +
    +
    +
    Срок + +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + Создать/выбрать объект, прикрепить объект к заказу + +
    +
    +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + Требуется допуск (СРО) + +
    + +
    +
    + + +
    +
    +
    +
    +
    +
     
    + +
    +
    +
     
    + +
    +
    +
    + +
    +
    +{% endblock %} +{% block js_block %} + +{% endblock %} \ No newline at end of file diff --git a/projects/urls.py b/projects/urls.py index d5a452a..74218d1 100644 --- a/projects/urls.py +++ b/projects/urls.py @@ -12,6 +12,7 @@ from .views import ( ContractorPortfolioUpdateView, CustomerOfferOrderView, CustomerProjectCreateView, + CustomerProjectCreateViewNew, CustomerProjectDeleteView, CustomerProjectEditView, CustomerProjectRestoreView, @@ -33,6 +34,7 @@ urlpatterns = [ urls.url(r'^$', ProjectFilterView.as_view(), name='project-filter'), urls.url(r'^create/$', CustomerProjectCreateView.as_view(), name='customer-project-create'), + urls.url(r'^create_new/$', CustomerProjectCreateViewNew.as_view(), name='customer-project-create'), urls.url(r'^(?P\d+)/$', ProjectDetailWithAnswerView.as_view(), name='detail'), urls.url(r'^(?P\d+)/edit/$', CustomerProjectEditView.as_view(), name='customer-project-edit'), urls.url(r'^(?P\d+)/trash/$', CustomerProjectTrashView.as_view(), name='customer-project-trash'), diff --git a/projects/views.py b/projects/views.py index c721b8f..c4f3bd6 100644 --- a/projects/views.py +++ b/projects/views.py @@ -481,6 +481,88 @@ class CustomerProjectCreateView(BaseMixin, View): return render(request, self.template_name, context) +class CustomerProjectCreateViewNew(BaseMixin, View): + form_class = CustomerProjectEditForm + realty_form = RealtyForm + work_type_suggestion_form = ProjectWorkTypeSuggestionForm + template_name = 'customer_project_create_new.html' + + def dispatch(self, request, *args, **kwargs): + if request.user.is_authenticated() and request.user.is_customer(): + return super().dispatch(request, *args, **kwargs) + else: + raise PermissionDenied + + def get(self, request, *args, **kwargs): + context = self.get_context_data(**_.merge({}, request.GET, kwargs)) + + form = self.form_class(request=request) + realty_form = self.realty_form(request=request, prefix='realty_form') + work_type_suggestion_form = self.work_type_suggestion_form(request=request, prefix='work_type_suggestion') + + context.update({ + 'form': form, + 'realty_form': realty_form, + 'work_type_suggestion_form': work_type_suggestion_form, + }) + + return render(request, self.template_name, context) + + def post(self, request, *args, **kwargs): + form = self.form_class(request.POST, + request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below + + form.is_valid() + realty = form.cleaned_data.get('realty') + + if realty: + realty_form = self.realty_form(request.POST, instance=realty, request=request, prefix='realty_form') + else: + realty_form = self.realty_form(request.POST, request=request, prefix='realty_form') + + if form.is_valid() and realty_form.is_valid(): + project = form.save(commit=False) + project.customer = request.user + project.save() + form.save_m2m() + + Order.objects.create(project=project, secure=project.deal_type == 'secure_deal') + + for file in request.FILES.getlist('new_files'): + ProjectFile.objects.create(file=file, project=project) + + if realty: + realty_form.save() + else: + realty = realty_form.save(commit=False) + realty.user = request.user + realty.save() + realty_form.save_m2m() + + project.realty = realty # Connect a realty with a project + project.save() + + messages.info(request, 'Проект успешно создан') + redirect_to = reverse('projects:detail', kwargs={'pk': project.pk}) + return redirect(redirect_to) + else: + if form.errors: + messages.info(request, ( + '

    Произошла ошибка (form)

    ' + '
    {form}
    ' + ).format(form=pformat(form.errors))) + + if realty_form and realty_form.errors: + messages.info(request, ( + '

    Произошла ошибка (realty_form)

    ' + '
    {realty_form}
    ' + ).format(realty_form=pformat(realty_form.errors))) + + context = self.get_context_data(**kwargs) + context.update({'form': form, 'realty_form': realty_form}) + return render(request, self.template_name, context) + + class CustomerProjectEditView(BaseMixin, View): form_class = CustomerProjectEditForm realty_form = RealtyForm diff --git a/wallets/admin.py b/wallets/admin.py index f822946..b0a88cb 100644 --- a/wallets/admin.py +++ b/wallets/admin.py @@ -6,7 +6,7 @@ from .models import InvoiceHistory, WithDraw, Transaction, Wallet, PayFromScore class InvoiceHistoryAdmin(admin.ModelAdmin): list_display = ('comment', 'sum', 'user', 'balance',) - readonly_fields = InvoiceHistory._meta.get_all_field_names() + readonly_fields = list(map(lambda obj: obj.name, InvoiceHistory._meta.get_fields())) class WithDrawAdmin(ImportExportModelAdmin): @@ -16,17 +16,18 @@ class WithDrawAdmin(ImportExportModelAdmin): class WalletAdmin(admin.ModelAdmin): list_display = ('customer', 'balance', ) - readonly_fields = Wallet._meta.get_all_field_names() + # readonly_fields = Wallet._meta.get_all_field_names() + readonly_fields = list(map(lambda obj: obj.name, Wallet._meta.get_fields())) class TransactionAdmin(admin.ModelAdmin): list_display = ('customer', 'complete',) - readonly_fields = Transaction._meta.get_all_field_names() + readonly_fields = list(map(lambda obj: obj.name, Transaction._meta.get_fields())) class PayFromScoreAdmin(admin.ModelAdmin): list_display = ('customer', 'sum', 'created_at') - readonly_fields = PayFromScore._meta.get_all_field_names() + readonly_fields = list(map(lambda obj: obj.name, PayFromScore._meta.get_fields())) admin.site.register(InvoiceHistory, InvoiceHistoryAdmin)