diff --git a/.babelrc b/.babelrc index c13c5f6..32848ab 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,8 @@ { - "presets": ["es2015"] -} + "presets": [ + "es2015" + ], + "plugins": [ + "transform-decorators-legacy" + ] +} \ No newline at end of file diff --git a/assets/js/jquery.mask.min.js b/assets/js/jquery.mask.min.js new file mode 100644 index 0000000..16460bb --- /dev/null +++ b/assets/js/jquery.mask.min.js @@ -0,0 +1,15 @@ +// jQuery Mask Plugin v1.14.0 +// github.com/igorescobar/jQuery-Mask-Plugin +(function(b){"function"===typeof define&&define.amd?define(["jquery"],b):"object"===typeof exports?module.exports=b(require("jquery")):b(jQuery||Zepto)})(function(b){var y=function(a,e,d){var c={invalid:[],getCaret:function(){try{var r,b=0,e=a.get(0),d=document.selection,f=e.selectionStart;if(d&&-1===navigator.appVersion.indexOf("MSIE 10"))r=d.createRange(),r.moveStart("character",-c.val().length),b=r.text.length;else if(f||"0"===f)b=f;return b}catch(g){}},setCaret:function(r){try{if(a.is(":focus")){var c, +b=a.get(0);b.setSelectionRange?(b.focus(),b.setSelectionRange(r,r)):(c=b.createTextRange(),c.collapse(!0),c.moveEnd("character",r),c.moveStart("character",r),c.select())}}catch(e){}},events:function(){a.on("keydown.mask",function(c){a.data("mask-keycode",c.keyCode||c.which)}).on(b.jMaskGlobals.useInput?"input.mask":"keyup.mask",c.behaviour).on("paste.mask drop.mask",function(){setTimeout(function(){a.keydown().keyup()},100)}).on("change.mask",function(){a.data("changed",!0)}).on("blur.mask",function(){n=== +c.val()||a.data("changed")||a.trigger("change");a.data("changed",!1)}).on("blur.mask",function(){n=c.val()}).on("focus.mask",function(a){!0===d.selectOnFocus&&b(a.target).select()}).on("focusout.mask",function(){d.clearIfNotMatch&&!p.test(c.val())&&c.val("")})},getRegexMask:function(){for(var a=[],c,b,d,f,l=0;l\n
\n ' + header + '\n
\n
\n ' + name + '\n
\n \n \n'; }; -var SelectedContainer = function () { +var SelectedContainer = (_class = function () { function SelectedContainer($container, _ref) { var _this = this; @@ -119,6 +156,7 @@ var SelectedContainer = function () { 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); @@ -132,15 +170,27 @@ var SelectedContainer = function () { value: function restoreElements() { var self = this; if (this.$input && this.$input.val()) { - var data = this.$input.val().split(',').filter(function (el) { + console.log(" restore 1) ", this.$input.val()); + console.log(" restore 2) ", this.$input.val().replace(/[\[\]\'\'\"\"]/g, '')); + // console.log(" restore 2) alter ", JSON.parse(this.$input.val())); + + var clearString = this.$input.val().replace(/[\[\]\'\'\"\"]/g, ''); + var data = clearString.split(',').filter(function (el) { return el; }); + console.log(" restore 3) ", data); 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) { @@ -161,6 +211,7 @@ var SelectedContainer = function () { 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(); } }, { @@ -185,10 +236,14 @@ var SelectedContainer = function () { 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) { + console.log("id = ", _id); + // console.log("this = ", this); + // console.log("this.elements_id = ", this.elements_id); var id = Number(_id); var self = this; if (this.onlyOne) { @@ -238,16 +293,16 @@ var SelectedContainer = function () { }]); 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":5,"./data/NoTreeData":6}],3:[function(require,module,exports){ +},{"./data/DataTree":5,"./data/NoTreeData":6,"./decorators":7}],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; }; }(); @@ -341,10 +396,6 @@ var TreeSelect = function (_AbsBaseSelect) { }, { 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(); @@ -1095,6 +1146,86 @@ var NoTreeData = function () { exports.default = NoTreeData; },{}],7:[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}; + +},{}],8:[function(require,module,exports){ 'use strict'; var _SelectedContainer = require('./SelectedContainer'); @@ -1159,9 +1290,33 @@ $(function () { var sb_loc_1 = new _TreeSelect2.default($('#sb-location-2'), { obj: sb_loc_main }); var sb_loc_2 = new _TreeSelect2.default($('#sb-location-3'), { obj: sb_loc_main }); + // Убираем кнопки add-options, блокирем поиск, меняем подсказки + sb_loc_main.dataPromise.then(function () { + sb_loc_1.$buttonAddOptions.remove(); + sb_loc_main.$buttonAddOptions.remove(); + sb_loc_main.$searchInput.prop("readonly", true); + sb_loc_1.$searchInput.prop("readonly", true); + sb_loc_2.$searchInput.prop("readonly", true); + sb_loc_main.$searchInput.prop("placeholder", "Выберите"); + sb_loc_1.$searchInput.prop("placeholder", "Выберите"); + sb_loc_2.$searchInput.prop("placeholder", "Выберите"); + }); + sb_loc_main.setNearbySelectBox(sb_loc_1); sb_loc_1.setNearbySelectBox(sb_loc_2, sb_loc_main); sb_loc_2.setNearbySelectBox("", sb_loc_1); + blockNonEmpty(sb_loc_main, select_loc); + } + + function blockNonEmpty(select, container) { + container.on("add", function () { + select.$searchInput.parent().append("
Местоположение выбрано
"); + select.$searchInput.hide(); + }); + container.on("remove", function () { + select.$searchInput.siblings('div.simple-select').remove(); + select.$searchInput.show(); + }); } createFilterSpecs('/api/specializations_flat'); @@ -1170,4 +1325,4 @@ $(function () { createFilerLocations('/api/locations_flat'); }); -},{"./NoTreeSelect":1,"./SelectedContainer":2,"./TreeSelect":3}]},{},[7]); +},{"./NoTreeSelect":1,"./SelectedContainer":2,"./TreeSelect":3}]},{},[8]); diff --git a/assets/lib/proekton-components/js/src/SelectedContainer.js b/assets/lib/proekton-components/js/src/SelectedContainer.js index 9d9006e..044cd12 100644 --- a/assets/lib/proekton-components/js/src/SelectedContainer.js +++ b/assets/lib/proekton-components/js/src/SelectedContainer.js @@ -1,6 +1,7 @@ // ` import DataTree from './data/DataTree' import NoTreeData from './data/NoTreeData' +import onBind from './decorators' let tmpl_selectedElement = (header, name, id) => ` @@ -22,6 +23,7 @@ export default class SelectedContainer { this.elements_id = []; // [spec_id, spec_id, ...] this.onlyOne = onlyOne; const self = this; + this.$self.hide(); obj.dataPromise .then( @@ -40,8 +42,11 @@ export default class SelectedContainer { restoreElements() { const self = this; if (this.$input && this.$input.val()) { - let data = this.$input.val().split(',').filter((el) => el); + + let clearString = this.$input.val().replace(/[\[\]\'\'\"\"]/g, ''); + let data = clearString.split(',').filter((el) => el); this.elements_id = []; + if (this.$input) this.$input.val(this.elements_id.join(',')); data.forEach((el) => self.add(el)); } } @@ -65,6 +70,10 @@ export default class SelectedContainer { return str_chain; } + on(methodName, func) { + this[methodName] = this[methodName].bind(this, {func, bindFunc: true}); + } + _removeById(id) { let index = this.elements_id.indexOf(id); if (index >= 0) { @@ -77,11 +86,12 @@ export default class SelectedContainer { console.log("Error loading data -->", error); } - + @onBind remove(e) { let 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(); } @@ -104,8 +114,10 @@ export default class SelectedContainer { 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(); } + @onBind add(_id, max_len) { const id = Number(_id); let self = this; diff --git a/assets/lib/proekton-components/js/src/decorators.js b/assets/lib/proekton-components/js/src/decorators.js new file mode 100644 index 0000000..b112c79 --- /dev/null +++ b/assets/lib/proekton-components/js/src/decorators.js @@ -0,0 +1,24 @@ +export default function onBind(target, name, descriptor) { + const method = descriptor.value; + + descriptor.value = function (...args) { + let binds = []; + args = Array.from(args); + for (let arg of args.slice()) { + // 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); + } + } + method.apply(this, args); + for (let bind of binds) { + bind.func.bind(this)(); + } + return this; + } +} + +// export {onBind}; \ No newline at end of file diff --git a/assets/lib/proekton-components/js/src/init_user_profile.js b/assets/lib/proekton-components/js/src/init_user_profile.js index fc9279a..4d9d110 100644 --- a/assets/lib/proekton-components/js/src/init_user_profile.js +++ b/assets/lib/proekton-components/js/src/init_user_profile.js @@ -51,10 +51,34 @@ $(function () { let sb_loc_1 = new TreeSelect($('#sb-location-2'), {obj: sb_loc_main}); let sb_loc_2 = new TreeSelect($('#sb-location-3'), {obj: sb_loc_main}); + // Убираем кнопки add-options, блокирем поиск, меняем подсказки + sb_loc_main.dataPromise.then(()=>{ + sb_loc_1.$buttonAddOptions.remove(); + sb_loc_main.$buttonAddOptions.remove(); + sb_loc_main.$searchInput.prop("readonly", true); + sb_loc_1.$searchInput.prop("readonly", true); + sb_loc_2.$searchInput.prop("readonly", true); + sb_loc_main.$searchInput.prop("placeholder", "Выберите"); + sb_loc_1.$searchInput.prop("placeholder", "Выберите"); + sb_loc_2.$searchInput.prop("placeholder", "Выберите"); + }); + + sb_loc_main.setNearbySelectBox(sb_loc_1); sb_loc_1.setNearbySelectBox(sb_loc_2, sb_loc_main); sb_loc_2.setNearbySelectBox("", sb_loc_1); + blockNonEmpty(sb_loc_main, select_loc); + } + function blockNonEmpty(select, container) { + container.on("add", () => { + select.$searchInput.parent().append("
Местоположение выбрано
"); + select.$searchInput.hide(); + }); + container.on("remove", () => { + select.$searchInput.siblings('div.simple-select').remove(); + select.$searchInput.show(); + }); } createFilterSpecs('/api/specializations_flat'); diff --git a/assets/projects-filter.js b/assets/projects-filter.js index fc12b86..8710af3 100644 --- a/assets/projects-filter.js +++ b/assets/projects-filter.js @@ -15,6 +15,8 @@ $(function () { $slide.toggleClass("active"); }); + //CUSTOM-CHECKBOX + function tuneCheckBoxes($boxes) { let currentState = $boxes.find("input").prop("checked") ? 'checked' : 'not-checked'; $boxes.find("div").hide(); @@ -31,6 +33,40 @@ $(function () { return false; }); + // CUSTOM-SELECT + let $select_container = $('.custom-select'); + let $sc_headers = $select_container.find('.simple-select'); + let $sc_options = $select_container.find('.select-box-options'); + + $sc_options.hide(); + + $sc_headers.on("click", function (e) { + $(e.target).siblings('.select-box-options').show(); + }); + + let $options = $sc_options.find('li'); + $options.on("click", function (e) { + const target = $(e.target); + let header = target.closest('.select-box-options').siblings('.simple-select'); + let data = target.closest('.select-box-options').siblings('input[type=hidden]'); + header.val(target.html()); + data.val(target.data("id")); + // $sc_data.val($(e.target).data("id")); + $sc_options.hide(); + e.preventDefault() + }); + + $(document).click(function (event) { + //FIXME: запомнить на ком был клик, и не закрывать именно его + if ($(event.target).closest($select_container).length) { + return; + } + $sc_options.hide(); + //... + }); + + //* Edn CUSTOM SELECT + // $("#myBtn").click(function () { // $('
' + diff --git a/package.json b/package.json index 64f1d62..ee9f529 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "author": "Booblegum", "license": "ISC", "devDependencies": { + "babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-preset-es2015": "^6.18.0", "babelify": "^7.3.0" } diff --git a/projects/static/css/project_filter.css b/projects/static/css/project_filter.css index 0065f49..e4d5536 100644 --- a/projects/static/css/project_filter.css +++ b/projects/static/css/project_filter.css @@ -22,27 +22,33 @@ body { margin-top: 30px; } -.custom-check{ +.custom-check { cursor: pointer; - display: inline-block + display: inline-block; + width: 100%; } -.header{ +.header { font-size: 12pt; color: black; } -.custom-check .checked{ +.block-header { + display: inline-block; + padding-top: 10px; +} + +.custom-check .checked { background: url("../img/checkbox_Check.png.png") no-repeat center; - background-size: 210px 51px; - width: 210px; + background-size: 100% 51px; + width: 100%; height: 51px; } .custom-check .not-checked { background: url("../img/checkbox_notCheck.png") no-repeat center; - background-size: 210px 51px; - width: 210px; + background-size: 100% 51px; + width: 100%; height: 51px; } @@ -62,15 +68,18 @@ body { transition: all 0.3s ease-out; } -button.resButton:focus {outline:0;} +button.resButton:focus { + outline: 0; +} .flex { display: flex; } -.flex .header{ +.flex .header { padding-right: 10px; } + .header .fa { padding-left: 3px; color: #5e5e5e; diff --git a/users/forms.py b/users/forms.py index 4c6457a..3aa037f 100644 --- a/users/forms.py +++ b/users/forms.py @@ -42,6 +42,78 @@ class ContractorResumeFilesForm(forms.ModelForm): ) +class UserProfileEditFullForm(forms.ModelForm): + gender = forms.ChoiceField( + choices=GENDERS, + widget=forms.RadioSelect, + required=False, + ) + contractor_status = forms.ChoiceField( + choices=User.STATUSES, + widget=forms.RadioSelect, + required=False, + ) + + live_image = forms.ModelChoiceField( + queryset=LiveImageUpload.objects.all(), + required=False, + ) + + class Meta: + model = User + + fields = ( + 'id', + 'avatar', + 'first_name', + 'last_name', + 'patronym', + 'location', + 'contractor_specializations', # Специализации + 'contractor_building_classifications', # Классификация зданий + 'contractor_construction_types', # Вид строительства + 'cro', + # Общая информация + 'date_of_birth', + 'gender', + 'contractor_status', + 'skype', + 'website', + 'phone', + 'phone2', + # Финансовая информация + # ... + ) + + widgets = { + # TODO: Use common format with jQueryUI Datepicker: + 'date_of_birth': forms.TextInput(attrs={'class': 'datepicker box-sizing simple-input'}), + 'contractor_status': forms.Select(attrs={'class': 'simple-select'}) + } + + def __init__(self, *args, **kwargs): + if kwargs.get("request"): self.request = kwargs.pop('request') + super().__init__(*args, **kwargs) + + # def clean_location(self): + # data = self.cleaned_data['location'] + # return data + + def clean_contractor_specializations(self): + data = self.cleaned_data['contractor_specializations'] + return data + + def get_gender_display(self): + for gender in GENDERS: + if gender[0] == self.initial['gender']: + return gender[1] + + def get_status_display(self): + for status in User.STATUSES: + if status[0] == self.initial['contractor_status']: + return status[1] + + class UserProfileEditForm(forms.ModelForm): gender = forms.ChoiceField( choices=GENDERS, diff --git a/users/static/css/user_profile_edit.css b/users/static/css/user_profile_edit.css index bf56acd..bf837e1 100644 --- a/users/static/css/user_profile_edit.css +++ b/users/static/css/user_profile_edit.css @@ -2,7 +2,19 @@ padding: 43px 25px 40px 25px; } -.simple-input { +.avatarInset { + width: 200px; + height: 200px; +} + +.avatar { + width: 220px; + height: 220px; + padding: 10px; + +} + +.simple-input, .simple-select { height: 51px; width: 100%; border: 1px solid #cccccc; @@ -12,6 +24,24 @@ margin-bottom: -1px; } +.simple-select select { + background-color: darkgray; +} + +.simple-select { + display: flex; + align-items: center; + text-align: center; +} + +.simple-select.fill{ + background-color: #F2F2F2; +} + +.simple-select .text{ + color: #a3a3a3; +} + .toggle .btn { padding: 14px 20px; border-radius: 40px; @@ -29,24 +59,22 @@ /* СУПЕР-костыльная кнопка. Не прикасаться!*/ .upload-new { - width: 75%; + width: 60%; height: 30px; overflow: hidden; cursor: pointer; - /*float: left;*/ - /*margin: 0 0 10px 0;*/ border-radius: 40px; border: 1px solid #FF0029; } -.upload-new:hover { +.upload-new:hover, .btn-simple:hover { box-shadow: 0 0 15px rgba(0, 0, 0, 0.2); -webkit-transform: scale(1.04); -moz-transform: scale(1.04); transform: scale(1.04); } -.upload-new { +.upload-new, .btn-simple { transition: all 0.3s; cursor: pointer; } @@ -64,9 +92,9 @@ text-transform: uppercase; margin: -30px 0 0 0; /*padding: 0 5px 0 5px;*/ - font-size: 12px; + font-size: 10px; text-align: center; - font-family: Arial-MT-Regular; + font-family: Miriad; } /** Конец супер-костыля**/ @@ -80,7 +108,7 @@ .info { background-color: #F2F2F2; - padding: 60px 40px; + padding: 50px 40px; margin-top: 20px; } @@ -89,8 +117,28 @@ padding: 10px 15px; border: 1px solid #FF0029; color: black; + background: none; + font-family: Miriad; } +/*.btn-simple:hover {*/ +/*box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);*/ +/*-webkit-transform: scale(1.04);*/ +/*-moz-transform: scale(1.04);*/ +/*transform: scale(1.04);*/ +/*}*/ + .no-margin .selected-element { margin: 0; +} + +.-live-image-avatar-upload-container .-position-relative-parent { + position: relative +} + +.-live-image-avatar-upload-container .-live-image-delete { + position: absolute; + top: 0; + right: 0; + background-color: white; } \ No newline at end of file diff --git a/users/templates/user_profile_edit_new.html b/users/templates/user_profile_edit_new.html index 48dd3a5..a28b268 100644 --- a/users/templates/user_profile_edit_new.html +++ b/users/templates/user_profile_edit_new.html @@ -1,5 +1,6 @@ {% extends 'partials/base.html' %} {% load staticfiles %} +{% load thumbnail %} {% block head_css %} @@ -10,14 +11,9 @@ {% endblock %} -{% load thumbnail %} -{% load thumbnail %} {% block content %} {% include 'partials/header.html' %} - {#
#} - {# {% csrf_token %}#} - {##} {# {% if request.user.is_customer %}#} {# #} @@ -26,232 +22,279 @@ {# {% endif %}#}
+
-
-
-
-
-
- - {# {% thumbnail request.user.avatar "235x224" crop="center" as avatar %}#} - {# {% if request.user.avatar %}#} - {# profile-image#} - {# {% else %}#} - profile-image - {# {% endif %}#} - {# {% endthumbnail %}#} + + {% csrf_token %} + +
+
+
+
+
+ + + {% if request.user.avatar %} + {% thumbnail request.user.avatar "235x224" crop="center" as avatar %} + profile-image + {% endthumbnail %} + {% else %} + profile-image + {% endif %} +
-
-
-
- +
+
+ {#
#} + -

Загрузить фотографию

+

Загрузить фотографию

+ {#
#} +
+
+
+
-
-
-
-
-
+
+
+
+
Параметры заполнения прифиля влияют на фильтр поиска специалистов, ранжирования в списке +
-
-
-
- +
+
+ Личная информация +
-
-
-
- -
-
- -
-
- -
-
-
+
+
+
-
-
-
+
+
-
-
-
+
+
-
-
-
-
 
- +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
 
+ +
-
-
+
-
-
-
-
-
- +
+
+
+
+
+ Мой опыт работы в проектировании / дизайне / сопровождении проектной документации +
-
-
-
-
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
-
- +
+
+
+ +
-
-
-
-
+
+
+
+
+
+
+
+ +
-
+
+
+
+
+ +
-
- +
+
+ Требуется допуск (СРО) + +
+ +
+
+ + +
-
-
-
-
- +
+
+
+
+ -
-
- Требуется допуск (СРО) - +
+
+
Дата рождения
+
+ {{ form.date_of_birth }} +
+
+
+
+
Пол
+
+ + + +
-
-
- - -
-
-
-
-
-
-
-
-
-
- +
+
+
+
Статус
+
+ + +
-
-
-
-
-
Дата рождения
-
- {{ form.date_of_birth }}
-
-
-
Пол
-
- - +
+
Skype
+ +
+
+
+
Сайт
+ +
+
+
Телефон
+ +
+
+
Второй телефон
+ +
+
+
 
+
- -
-
-
Статус
- {{ form.contractor_status }} -
-
-
Skype
- -
-
-
-
Сайт
- -
-
-
Телефон
- -
-
-
Второй телефон
- -
-
- -
-
-
+
+
+
{% include 'partials/footer.html' %} @@ -263,5 +306,11 @@ {% block js_block %} {{ block.super }} - + + + {% endblock %} diff --git a/users/urls.py b/users/urls.py index 1fd26de..3670560 100755 --- a/users/urls.py +++ b/users/urls.py @@ -18,14 +18,14 @@ from .views import ( TeamProfileView, UserFinancialInfoEditView, UserProfileEditView, - UserProfileEditViewPlus, + UserProfileEditViewFull, ) app_name = 'users' urlpatterns = [ urls.url(r'^(?P\d+)/edit/$', UserProfileEditView.as_view(), name='user-profile-edit'), - urls.url(r'^(?P\d+)/edit_plus/$', UserProfileEditViewPlus.as_view(), name='user-profile-edit'), + urls.url(r'^(?P\d+)/edit_full/$', UserProfileEditViewFull.as_view(), name='user-profile-edit'), urls.url(r'^(?P\d+)/financial-info/edit/$', UserFinancialInfoEditView.as_view(), name='user-financial-info-edit'), diff --git a/users/views.py b/users/views.py index 9c9d736..616411b 100644 --- a/users/views.py +++ b/users/views.py @@ -1,5 +1,6 @@ import itertools import json +import re from pprint import pformat import natsort @@ -36,6 +37,7 @@ from .forms import ( UserFinancialInfoEditForm, UserProfileBasicInfoEditForm, UserProfileEditForm, + UserProfileEditFullForm, UserProfileExperienceEditForm, ) @@ -100,25 +102,27 @@ class UserProfileEditView(BaseMixin, View): return render(request, self.template_name, context) -class UserProfileEditViewPlus(BaseMixin, View): - form_class = UserProfileEditForm +class UserProfileEditViewFull(BaseMixin, View): + form_class = UserProfileEditFullForm template_name = 'user_profile_edit_new.html' - # def dispatch(self, request, *args, **kwargs): - # if request.resolver_match.url_name == 'user-experience-edit': - # if not request.user.is_contractor(): - # raise PermissionDenied - # self.form_class = UserProfileExperienceEditForm - # request.experience_edit = True - # if request.user.is_authenticated() and request.user.pk == int(kwargs.get('pk')): - # return super().dispatch(request, *args, **kwargs) - # else: - # raise PermissionDenied + def dispatch(self, request, *args, **kwargs): + if request.resolver_match.url_name == 'user-experience-edit': + if not request.user.is_contractor(): + raise PermissionDenied + self.form_class = UserProfileExperienceEditForm + request.experience_edit = True + if request.user.is_authenticated() and request.user.pk == int(kwargs.get('pk')): + 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, instance=request.user) + form = self.form_class(instance=request.user) + # import code + # code.interact(local=dict(globals(), **locals())) context.update({'form': form}) return render(request, self.template_name, context) @@ -126,8 +130,14 @@ class UserProfileEditViewPlus(BaseMixin, View): def post(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) - specs = request.POST.getlist('contractor_specializations') - request.POST.setlist('contractor_specializations', _.compact(specs)) # Ignore empty input values + specs = tuple(filter(None, re.split(r'\s|,|;', request.POST.get('contractor_specializations')))) + request.POST.setlist('contractor_specializations', specs) + + builds = tuple(filter(None, re.split(r'\s|,|;', request.POST.get('contractor_building_classifications')))) + request.POST.setlist('contractor_building_classifications', builds) + + constructs = tuple(filter(None, re.split(r'\s|,|;', request.POST.get('contractor_construction_types')))) + request.POST.setlist('contractor_construction_types', constructs) form = self.form_class(request.POST, request=request, instance=request.user)