Merge branch 'PR-20'

remotes/origin/PR-41
booblegum 9 years ago
commit 3e0d7c8bef
  1. 9
      .babelrc
  2. 12
      assets/css/reset.css
  3. BIN
      assets/img/avatar_default.png
  4. 15
      assets/js/jquery.mask.min.js
  5. 7
      assets/lib/proekton-components/bash/browserify.sh
  6. 5
      assets/lib/proekton-components/bash/watchify.sh
  7. 24
      assets/lib/proekton-components/css/select-box.css
  8. 2
      assets/lib/proekton-components/css/selected-container.css
  9. 208
      assets/lib/proekton-components/js/build/init.js
  10. 1325
      assets/lib/proekton-components/js/build/init_user_profile.js
  11. 59
      assets/lib/proekton-components/js/src/SelectedContainer.js
  12. 7
      assets/lib/proekton-components/js/src/TreeSelect.js
  13. 10
      assets/lib/proekton-components/js/src/base/AbsBaseSelect.js
  14. 24
      assets/lib/proekton-components/js/src/decorators.js
  15. 2
      assets/lib/proekton-components/js/src/init.js
  16. 90
      assets/lib/proekton-components/js/src/init_user_profile.js
  17. 42
      assets/projects-filter.js
  18. 1
      package.json
  19. 45
      projects/static/css/project_filter.css
  20. 1
      projects/templates/partials/inc-projects-filter.html
  21. 2
      templates/partials/base.html
  22. 74
      users/forms.py
  23. 41
      users/static/css/custom-checkboxes.css
  24. 144
      users/static/css/user_profile_edit.css
  25. 413
      users/templates/user_profile_edit.html
  26. 220
      users/templates/user_profile_edit_old.html
  27. 10
      users/urls.py
  28. 70
      users/views.py

@ -1,3 +1,8 @@
{
"presets": ["es2015"]
}
"presets": [
"es2015"
],
"plugins": [
"transform-decorators-legacy"
]
}

@ -17,17 +17,17 @@ body, code, dl, dd, form, pre {
margin: 0;
}
a:link {
color: #009;
}
/*a:link {*/
/*color: #009;*/
/*}*/
a:link, a:visited, ins {
text-decoration: none;
}
a:visited {
color: #505;
}
/*a:visited {*/
/*color: #505;*/
/*}*/
a:link img, a:visited img, object, fieldset, abbr, acronym {
border: none;

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

@ -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<e.length;l++)(c=g.translation[e.charAt(l)])?(b=c.pattern.toString().replace(/.{1}$|^.{1}/g,""),d=c.optional,(c=c.recursive)?(a.push(e.charAt(l)),f={digit:e.charAt(l),pattern:b}):a.push(d||
c?b+"?":b)):a.push(e.charAt(l).replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&"));a=a.join("");f&&(a=a.replace(new RegExp("("+f.digit+"(.*"+f.digit+")?)"),"($1)?").replace(new RegExp(f.digit,"g"),f.pattern));return new RegExp(a)},destroyEvents:function(){a.off("input keydown keyup paste drop blur focusout ".split(" ").join(".mask "))},val:function(c){var b=a.is("input")?"val":"text";if(0<arguments.length){if(a[b]()!==c)a[b](c);b=a}else b=a[b]();return b},getMCharsBeforeCount:function(a,c){for(var b=0,d=0,
f=e.length;d<f&&d<a;d++)g.translation[e.charAt(d)]||(a=c?a+1:a,b++);return b},caretPos:function(a,b,d,h){return g.translation[e.charAt(Math.min(a-1,e.length-1))]?Math.min(a+d-b-h,d):c.caretPos(a+1,b,d,h)},behaviour:function(d){d=d||window.event;c.invalid=[];var e=a.data("mask-keycode");if(-1===b.inArray(e,g.byPassKeys)){var m=c.getCaret(),h=c.val().length,f=c.getMasked(),l=f.length,k=c.getMCharsBeforeCount(l-1)-c.getMCharsBeforeCount(h-1),n=m<h;c.val(f);n&&(8!==e&&46!==e&&(m=c.caretPos(m,h,l,k)),
c.setCaret(m));return c.callbacks(d)}},getMasked:function(a,b){var m=[],h=void 0===b?c.val():b+"",f=0,l=e.length,k=0,n=h.length,q=1,p="push",u=-1,t,w;d.reverse?(p="unshift",q=-1,t=0,f=l-1,k=n-1,w=function(){return-1<f&&-1<k}):(t=l-1,w=function(){return f<l&&k<n});for(;w();){var x=e.charAt(f),v=h.charAt(k),s=g.translation[x];if(s)v.match(s.pattern)?(m[p](v),s.recursive&&(-1===u?u=f:f===t&&(f=u-q),t===u&&(f-=q)),f+=q):s.optional?(f+=q,k-=q):s.fallback?(m[p](s.fallback),f+=q,k-=q):c.invalid.push({p:k,
v:v,e:s.pattern}),k+=q;else{if(!a)m[p](x);v===x&&(k+=q);f+=q}}h=e.charAt(t);l!==n+1||g.translation[h]||m.push(h);return m.join("")},callbacks:function(b){var g=c.val(),m=g!==n,h=[g,b,a,d],f=function(a,b,c){"function"===typeof d[a]&&b&&d[a].apply(this,c)};f("onChange",!0===m,h);f("onKeyPress",!0===m,h);f("onComplete",g.length===e.length,h);f("onInvalid",0<c.invalid.length,[g,b,a,c.invalid,d])}};a=b(a);var g=this,n=c.val(),p;e="function"===typeof e?e(c.val(),void 0,a,d):e;g.mask=e;g.options=d;g.remove=
function(){var b=c.getCaret();c.destroyEvents();c.val(g.getCleanVal());c.setCaret(b-c.getMCharsBeforeCount(b));return a};g.getCleanVal=function(){return c.getMasked(!0)};g.getMaskedVal=function(a){return c.getMasked(!1,a)};g.init=function(e){e=e||!1;d=d||{};g.clearIfNotMatch=b.jMaskGlobals.clearIfNotMatch;g.byPassKeys=b.jMaskGlobals.byPassKeys;g.translation=b.extend({},b.jMaskGlobals.translation,d.translation);g=b.extend(!0,{},g,d);p=c.getRegexMask();!1===e?(d.placeholder&&a.attr("placeholder",d.placeholder),
a.data("mask")&&a.attr("autocomplete","off"),c.destroyEvents(),c.events(),e=c.getCaret(),c.val(c.getMasked()),c.setCaret(e+c.getMCharsBeforeCount(e,!0))):(c.events(),c.val(c.getMasked()))};g.init(!a.is("input"))};b.maskWatchers={};var A=function(){var a=b(this),e={},d=a.attr("data-mask");a.attr("data-mask-reverse")&&(e.reverse=!0);a.attr("data-mask-clearifnotmatch")&&(e.clearIfNotMatch=!0);"true"===a.attr("data-mask-selectonfocus")&&(e.selectOnFocus=!0);if(z(a,d,e))return a.data("mask",new y(this,
d,e))},z=function(a,e,d){d=d||{};var c=b(a).data("mask"),g=JSON.stringify;a=b(a).val()||b(a).text();try{return"function"===typeof e&&(e=e(a)),"object"!==typeof c||g(c.options)!==g(d)||c.mask!==e}catch(n){}};b.fn.mask=function(a,e){e=e||{};var d=this.selector,c=b.jMaskGlobals,g=c.watchInterval,c=e.watchInputs||c.watchInputs,n=function(){if(z(this,a,e))return b(this).data("mask",new y(this,a,e))};b(this).each(n);d&&""!==d&&c&&(clearInterval(b.maskWatchers[d]),b.maskWatchers[d]=setInterval(function(){b(document).find(d).each(n)},
g));return this};b.fn.masked=function(a){return this.data("mask").getMaskedVal(a)};b.fn.unmask=function(){clearInterval(b.maskWatchers[this.selector]);delete b.maskWatchers[this.selector];return this.each(function(){var a=b(this).data("mask");a&&a.remove().removeData("mask")})};b.fn.cleanVal=function(){return this.data("mask").getCleanVal()};b.applyDataMask=function(a){a=a||b.jMaskGlobals.maskElements;(a instanceof b?a:b(a)).filter(b.jMaskGlobals.dataMaskAttr).each(A)};var p={maskElements:"input,td,span,div",
dataMaskAttr:"*[data-mask]",dataMask:!0,watchInterval:300,watchInputs:!0,useInput:function(a){var b=document.createElement("div"),d;a="on"+a;d=a in b;d||(b.setAttribute(a,"return;"),d="function"===typeof b[a]);return d}("input"),watchDataMask:!1,byPassKeys:[9,16,17,18,36,37,38,39,40,91],translation:{0:{pattern:/\d/},9:{pattern:/\d/,optional:!0},"#":{pattern:/\d/,recursive:!0},A:{pattern:/[a-zA-Z0-9]/},S:{pattern:/[a-zA-Z]/}}};b.jMaskGlobals=b.jMaskGlobals||{};p=b.jMaskGlobals=b.extend(!0,{},p,b.jMaskGlobals);
p.dataMask&&b.applyDataMask();setInterval(function(){b.jMaskGlobals.watchDataMask&&b.applyDataMask()},p.watchInterval)});

@ -0,0 +1,7 @@
#!/usr/bin/env bash
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
#watchify ./js/src/init.js -t babelify -o ./js/build/init.js

@ -1,5 +0,0 @@
#!/usr/bin/env bash
echo "run watchify"
cd ..
source ~/venv/proekton/bin/activate
watchify ./js/src/init.js -t babelify -o ./js/build/init.js

@ -11,24 +11,28 @@
}
.select-box-header {
font-size: 12pt;
white-space: nowrap;
word-wrap: break-word;
}
.header{
font-size: 12pt;
color: black;
}
.select-box-header .header {
display: inline-block;
color: black;
text-overflow: ellipsis;
overflow: hidden;
word-wrap: break-word;
vertical-align: bottom;
max-width: 220px;
}
.select-box-header .fa {
color: #5e5e5e;
position: relative;
top: -3px;
/*top: -3px;*/
}
.select-box-header .fa:hover {
@ -58,6 +62,7 @@
.select-box-results input[type=checkbox] {
margin: 0 5px 0 5px;
pointer-events: none;
}
.select-box-results .header {
@ -113,6 +118,7 @@ input.select-box-search {
background-size: 40px 40px;
background-color: white;
margin-bottom: -1px;
color: #494546;
}
input.select-box-search.active{
@ -135,6 +141,7 @@ input.select-box-search:-webkit-autofill {
}
.select-box-results .other-part {
border-right: 1px solid #cccccc;
border-top: 1px solid #000000;
color: darkgray;
}
@ -157,9 +164,9 @@ button.button-add {
}
.button-add {
position: relative;
top: 3px;
float: right;
position: absolute;
bottom: -30px;
right: 0;
z-index: 999;
font-family: Myriad;
font-weight: normal;
@ -175,8 +182,13 @@ button.button-add {
}
.select-box-results .button-add{
bottom: inherit;
}
.highlight {
color: #FF0029;
pointer-events: none;
}
#component-preloader {

@ -1,6 +1,6 @@
.selected-container {
min-height: 40px;
padding-bottom: 20px;
/*padding-bottom: 20px;*/
}
.selected-container .selected-element {

@ -4,6 +4,7 @@
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; }; }();
@ -82,8 +83,11 @@ exports.default = NoTreeSelect;
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 _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 _desc, _value, _class; // `
var _DataTree = require('./data/DataTree');
@ -94,28 +98,65 @@ var _NoTreeData = require('./data/NoTreeData');
var _NoTreeData2 = _interopRequireDefault(_NoTreeData);
var _decorators = require('./decorators');
var _decorators2 = _interopRequireDefault(_decorators);
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 _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
var desc = {};
Object['ke' + 'ys'](descriptor).forEach(function (key) {
desc[key] = descriptor[key];
});
desc.enumerable = !!desc.enumerable;
desc.configurable = !!desc.configurable;
if ('value' in desc || desc.initializer) {
desc.writable = true;
}
desc = decorators.slice().reverse().reduce(function (desc, decorator) {
return decorator(target, property, desc) || desc;
}, desc);
if (context && desc.initializer !== void 0) {
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
desc.initializer = undefined;
}
if (desc.initializer === void 0) {
Object['define' + 'Property'](target, property, desc);
desc = null;
}
return desc;
}
var tmpl_selectedElement = function tmpl_selectedElement(header, name, id) {
return '\n <div class="selected-element">\n <div class="header">\n ' + header + '\n </div>\n <div class="name">\n ' + name + '\n </div>\n <span data-id="' + id + '" class="icon-remove"></span>\n </div>\n';
};
var SelectedContainer = function () {
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;
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);
@ -129,23 +170,31 @@ var SelectedContainer = function () {
value: function restoreElements() {
var self = this;
if (this.$input && this.$input.val()) {
var data = this.$input.val().split(',').filter(function (el) {
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(spec_id) {
var index = this.elements_id.indexOf(spec_id);
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=\'' + spec_id + '\']').parents('.selected-element').remove();
this.$self.find('span[data-id=\'' + id + '\']').parents('.selected-element').remove();
}
}, {
key: '_onLoadDataError',
@ -158,13 +207,42 @@ 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();
}
}, {
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 || "&nbsp;", 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);
@ -182,14 +260,7 @@ var SelectedContainer = function () {
not_valid.forEach(function (el) {
self._removeById(el);
});
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 || "&nbsp;", name, id));
this.btn_remove = this.$self.find('.icon-remove');
this.btn_remove.on("click", this.remove.bind(self));
this._addElementToHtml(id, max_len);
}
}], [{
key: 'getTemplate',
@ -215,16 +286,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; }; }();
@ -304,13 +375,16 @@ var TreeSelect = function (_AbsBaseSelect) {
value: function _onclickOptionsElement(e) {
this.clearAllNext();
_get(TreeSelect.prototype.__proto__ || Object.getPrototypeOf(TreeSelect.prototype), '_onclickOptionsElement', this).call(this, e);
if (this.prevSelectBox && this.dataTree.hasChildren(this.selectedEl.id)) this.$searchInput.removeClass('active');
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();
if (this.prevSelectBox) {
this.prevSelectBox.$buttonAddOptions.hide();
this.prevSelectBox.$searchInput.removeClass("active");
}
this.$searchInput.addClass('active');
}
}, {
key: '_onButtonAddOptions',
@ -364,7 +438,7 @@ var tmpl_selectBoxEditCont = function tmpl_selectBoxEditCont() {
_ref$preloaderTemplat = _ref.preloaderTemplate,
preloaderTemplate = _ref$preloaderTemplat === undefined ? "" : _ref$preloaderTemplat;
return "\n <div class=\"row\">\n <div class=\"col-lg-3\">\n \n <div style=\"width: 100%; position: relative\">\n " + preloaderTemplate + "\n <input class=\"select-box-search\" type=\"text\" placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435/\u041F\u043E\u0438\u0441\u043A\">\n <button style=\"display: none\" class=\"button-add options\">\u0414\u041E\u0411\u0410\u0412\u0418\u0422\u042C</button>\n </div>\n </div>\n <div class=\"col-lg-9\">\n <span style=\"display: none\" class=\"editable-container\"></span>\n </div>\n </div>\n";
return "\n <div class=\"row\">\n <div class=\"col-lg-3\">\n \n <div style=\"width: 100%; position: relative\">\n " + preloaderTemplate + "\n <input class=\"select-box-search\" type=\"text\" placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435/\u041F\u043E\u0438\u0441\u043A\">\n <button style=\"display: none\" class=\"button-add options\">\u041F\u0420\u0418\u041C\u0415\u041D\u0418\u0422\u042C</button>\n </div>\n </div>\n <div class=\"col-lg-9\">\n <span style=\"display: none\" class=\"editable-container\"></span>\n </div>\n </div>\n";
};
var tmpl_selectBox = function tmpl_selectBox() {
@ -372,7 +446,7 @@ var tmpl_selectBox = function tmpl_selectBox() {
_ref2$preloaderTempla = _ref2.preloaderTemplate,
preloaderTemplate = _ref2$preloaderTempla === undefined ? "" : _ref2$preloaderTempla;
return " \n " + preloaderTemplate + "\n <input class=\"select-box-search\" type=\"text\" placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435/\u041F\u043E\u0438\u0441\u043A\">\n <button style=\"display: none\" class=\"button-add options\">\u0414\u041E\u0411\u0410\u0412\u0418\u0422\u042C</button>\n";
return " \n " + preloaderTemplate + "\n <input class=\"select-box-search\" type=\"text\" placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435/\u041F\u043E\u0438\u0441\u043A\">\n <button style=\"display: none\" class=\"button-add options\">\u041F\u0420\u0418\u041C\u0415\u041D\u0418\u0422\u042C</button>\n";
};
var tmpl_elementResult = function tmpl_elementResult(el, id, header) {
@ -394,7 +468,7 @@ var tmpl_selectBoxOptions = function tmpl_selectBoxOptions() {
};
var tmpl_selectBoxResults = function tmpl_selectBoxResults() {
return "\n <div class=\"select-box-results\">\n <div class=\"box-wrapper\">\n <div class=\"main-part\">\n <ul>\n </ul>\n </div>\n <div class=\"other-part\">\n <span class=\"other-header\">\u0418\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0439</span>\n <ul>\n </ul>\n </div>\n </div>\n <button class=\"button-add results\">\u0414\u041E\u0411\u0410\u0412\u0418\u0422\u042C</button>\n </div>\n";
return "\n <div class=\"select-box-results\">\n <div class=\"box-wrapper\">\n <div class=\"main-part\">\n <ul>\n </ul>\n </div>\n <div class=\"other-part\">\n <span class=\"other-header\">\u0418\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043A\u0430\u0442\u0435\u0433\u043E\u0440\u0438\u0439</span>\n <ul>\n </ul>\n </div>\n </div>\n <button class=\"button-add results\">\u041F\u0420\u0418\u041C\u0415\u041D\u0418\u0422\u042C</button>\n </div>\n";
};
var htmlTemplate = function htmlTemplate(_ref4) {
@ -516,6 +590,7 @@ var AbsBaseSelect = function () {
this.$editableContainer.html("");
this.$editableContainer.hide();
}
this.$searchInput.removeClass("active");
}
}, {
key: "hide",
@ -544,7 +619,6 @@ var AbsBaseSelect = function () {
value: function setParent(parentId) {
this.parentId = parentId;
this._fillOptionsData();
this.$searchInput.addClass('active');
}
}, {
key: "connectSelectedContainer",
@ -747,7 +821,6 @@ var AbsBaseSelect = function () {
value: function _onButtonAddOptions(e) {
this._addToSelectedContainer(this.selectedEl.id);
this.clear();
this.$searchInput.removeClass('active');
e.preventDefault();
return false;
}
@ -793,7 +866,6 @@ var AbsBaseSelect = function () {
this.$searchInput.on("click", function (e) {
self.$optionsBox.show();
self.$resultsBox.hide();
self.$buttonAddOptions.hide();
self.$searchInput.val("");
});
@ -1071,6 +1143,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');
@ -1091,7 +1243,7 @@ $(function () {
function createFilterSpecs(url) {
// SPECIALIZATIONS FILTER
var sb_main = new _TreeSelect2.default($('#select-box-1'), { url: url, hasEditableContainer: true });
sb_main.setHeader("Специализации");
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 });
@ -1169,4 +1321,4 @@ $(function () {
// fullData({next: '/api/locations_flat', results: []});
}); // `
},{"./NoTreeSelect":1,"./SelectedContainer":2,"./TreeSelect":3}]},{},[7]);
},{"./NoTreeSelect":1,"./SelectedContainer":2,"./TreeSelect":3}]},{},[8]);

File diff suppressed because it is too large Load Diff

@ -1,6 +1,7 @@
// `
import DataTree from './data/DataTree'
import NoTreeData from './data/NoTreeData'
import onBind from './decorators'
let tmpl_selectedElement = (header, name, id) =>
`
@ -16,11 +17,13 @@ let tmpl_selectedElement = (header, name, id) =>
`;
export default class SelectedContainer {
constructor($container, {obj, noTree = false}) {
constructor($container, {obj, noTree = false, onlyOne = false}) {
// TODO: rename variables to camelCase
this.$self = $container;
this.elements_id = []; // [spec_id, spec_id, ...]
this.onlyOne = onlyOne;
const self = this;
this.$self.hide();
obj.dataPromise
.then(
@ -39,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));
}
}
@ -64,29 +70,61 @@ export default class SelectedContainer {
return str_chain;
}
_removeById(spec_id) {
let index = this.elements_id.indexOf(spec_id);
on(methodName, func) {
this[methodName] = this[methodName].bind(this, {func, bindFunc: true});
}
_removeById(id) {
let index = this.elements_id.indexOf(id);
if (index >= 0) {
this.elements_id.splice(index, 1);
}
this.$self.find(`span[data-id='${spec_id}']`).parents('.selected-element').remove();
this.$self.find(`span[data-id='${id}']`).parents('.selected-element').remove();
}
_onLoadDataError(error) {
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();
}
replace(_id, max_len) {
const 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];
}
_addElementToHtml(id, max_len) {
let self = this;
const header = SelectedContainer.getHeader(this.dataTree.getSpecChain(id), "", max_len);
const 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 || "&nbsp;", 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;
if (this.onlyOne) {
this.replace(_id, max_len);
return
}
let has_already = this.elements_id.filter(function (el) {
return self.dataTree.isChild(el, id)
@ -104,13 +142,6 @@ export default class SelectedContainer {
not_valid.forEach(function (el) {
self._removeById(el);
});
const header = SelectedContainer.getHeader(this.dataTree.getSpecChain(id), "", max_len);
const 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 || "&nbsp;", name, id));
this.btn_remove = this.$self.find('.icon-remove');
this.btn_remove.on("click", this.remove.bind(self));
this._addElementToHtml(id, max_len);
}
}

@ -42,13 +42,16 @@ export default class TreeSelect extends AbsBaseSelect{
_onclickOptionsElement(e) {
this.clearAllNext();
super._onclickOptionsElement(e);
if (this.prevSelectBox && this.dataTree.hasChildren(this.selectedEl.id)) this.$searchInput.removeClass('active');
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();
if (this.prevSelectBox) {
this.prevSelectBox.$buttonAddOptions.hide();
this.prevSelectBox.$searchInput.removeClass("active");
}
this.$searchInput.addClass('active');
}
_onButtonAddOptions(e) {

@ -7,7 +7,7 @@ const tmpl_selectBoxEditCont = ({preloaderTemplate = ""}={}) =>
<div style="width: 100%; position: relative">
${preloaderTemplate}
<input class="select-box-search" type="text" placeholder="Выберите/Поиск">
<button style="display: none" class="button-add options">ДОБАВИТЬ</button>
<button style="display: none" class="button-add options">ПРИМЕНИТЬ</button>
</div>
</div>
<div class="col-lg-9">
@ -20,7 +20,7 @@ const tmpl_selectBox = ({preloaderTemplate = ""}={}) =>
`
${preloaderTemplate}
<input class="select-box-search" type="text" placeholder="Выберите/Поиск">
<button style="display: none" class="button-add options">ДОБАВИТЬ</button>
<button style="display: none" class="button-add options">ПРИМЕНИТЬ</button>
`;
const tmpl_elementResult = (el, id, header) =>
@ -59,7 +59,7 @@ const tmpl_selectBoxResults = () =>
</ul>
</div>
</div>
<button class="button-add results">ДОБАВИТЬ</button>
<button class="button-add results">ПРИМЕНИТЬ</button>
</div>
`;
@ -203,6 +203,7 @@ export default class AbsBaseSelect {
this.$editableContainer.html("");
this.$editableContainer.hide()
}
this.$searchInput.removeClass("active");
}
hide() {
@ -223,7 +224,6 @@ export default class AbsBaseSelect {
setParent(parentId) {
this.parentId = parentId;
this._fillOptionsData();
this.$searchInput.addClass('active');
}
connectSelectedContainer(selectedContainer) {
@ -368,7 +368,6 @@ export default class AbsBaseSelect {
_onButtonAddOptions(e) {
this._addToSelectedContainer(this.selectedEl.id);
this.clear();
this.$searchInput.removeClass('active');
e.preventDefault();
return false;
}
@ -411,7 +410,6 @@ export default class AbsBaseSelect {
this.$searchInput.on("click", function (e) {
self.$optionsBox.show();
self.$resultsBox.hide();
self.$buttonAddOptions.hide();
self.$searchInput.val("");
});

@ -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};

@ -7,7 +7,7 @@ $(function () {
function createFilterSpecs(url) {
// SPECIALIZATIONS FILTER
let sb_main = new TreeSelect($('#select-box-1'), {url, hasEditableContainer: true});
sb_main.setHeader("Специализации");
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});

@ -0,0 +1,90 @@
import SelectedContainer from './SelectedContainer';
import NoTreeSelect from './NoTreeSelect';
import TreeSelect from './TreeSelect';
$(function () {
function createFilterSpecs(url) {
// SPECIALIZATIONS FILTER
let sb_main = new TreeSelect($('#select-box-1'), {url, hasEditableContainer: 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 TreeSelect($('#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 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("<div class='simple-select fill'>Местоположение выбрано</div>");
select.$searchInput.hide();
});
container.on("remove", () => {
select.$searchInput.siblings('div.simple-select').remove();
select.$searchInput.show();
});
}
createFilterSpecs('/api/specializations_flat');
createFilterBuildingClass('/api/building_classifications');
createFilterConstructionType('/api/construction_type');
createFilerLocations('/api/locations_flat');
});

@ -1,20 +1,22 @@
$(function () {
let $buttonF1 = $('.resButton');
if ($('.slide').hasClass("active")) $buttonF1.css('transform', 'rotate(180deg)');
if ($('.slide').hasClass("active")) $buttonF1.css('transform', 'rotate(0deg)');
$buttonF1.on("click", function (e) {
e.preventDefault();
let $slide = $('.slide');
if ($slide.hasClass("active")) {
$buttonF1.css('transform', 'rotate(0deg)');
$buttonF1.css('transform', 'rotate(180deg)');
$slide.slideUp(300);
} else {
$buttonF1.css('transform', 'rotate(180deg)');
$buttonF1.css('transform', 'rotate(0deg)');
$slide.slideDown(300);
}
$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 () {
// $('<div class="alert alert-success alert-dismissable">' +

@ -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"
}

@ -22,26 +22,39 @@ body {
margin-top: 30px;
}
.custom-check{
.custom-check {
cursor: pointer;
display: inline-block
display: inline-block;
width: 100%;
}
.custom-check .checked{
.header {
font-size: 12pt;
color: black;
}
.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;
}
.resButton {
position: relative;
top: -15px;
width: 50px;
height: 50px;
background-color: white;
@ -51,22 +64,26 @@ body {
font-size: 16px;
float: left;
border-radius: 100%;
margin: -15px 20px 0 28px;
/* margin: -15px 20px 0 28px; */
margin-left: 25px;
-webkit-transition: all 0.3s ease-out;
-moz-transition: all 0.3s ease-out;
transition: all 0.3s ease-out;
transform: rotate(180deg);
}
button.resButton:focus {outline:0;}
button.resButton:focus {
outline: 0;
}
.flex {
display: flex;
}
.flex .header{
font-size: 12pt;
padding-right: 10px;
}
/*.flex .header {*/
/*padding-right: 10px;*/
/*}*/
.header .fa {
padding-left: 3px;
color: #5e5e5e;
@ -77,7 +94,7 @@ button.resButton:focus {outline:0;}
.border {
flex: 1 1 auto;
float: left;
margin: 10px 0 0 0;
margin: 10px 0 0 25px;
border-top: 1px solid #CFCFCF;
}

@ -1,7 +1,6 @@
<form id="filter-form" action="/projects" method="GET" novalidate xmlns="http://www.w3.org/1999/html">
<div class="filter form-container">
{# <div id="page-preloader"><span class="spinner"></span></div>#}
<div class="triangle1"></div>
<div class="row">
<div class="col-lg-12">

@ -12,10 +12,10 @@
<title>PROEKTON</title>
{# {% compress css %}#}
<link rel='stylesheet' href='{% static "css/reset.css" %}'>
<link rel='stylesheet' href='{% static "lib/jquery-ui/jquery-ui.css" %}'>
<link rel='stylesheet' href='{% static "css/bootstrap.css" %}'>
<link rel='stylesheet' href='{% static "css/font-awesome.min.css" %}'>
<link rel='stylesheet' href='{% static "css/reset.css" %}'>
<link rel='stylesheet' href='{% static "lib/bootstrap-select/css/bootstrap-select.css" %}'>
<link rel='stylesheet' href='{% static "lib/select2/select2.css" %}'> <!-- Tmp -->
<link rel='stylesheet' href='{% static "css/swiper.min.css" %}'>

@ -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,
@ -75,7 +147,7 @@ class UserProfileEditForm(forms.ModelForm):
widgets = {
# TODO: Use common format with jQueryUI Datepicker:
'date_of_birth': forms.TextInput(attrs={'class': 'datepicker box-sizing surr surr2'}),
'date_of_birth': forms.TextInput(attrs={'class': 'datepicker box-sizing simple-input'}),
}
def __init__(self, *args, **kwargs):

@ -0,0 +1,41 @@
.rad {
cursor: pointer;
user-select: none;
-webkit-user-select: none;
-webkit-touch-callout: none;
}
.rad > input { /* HIDE ORG RADIO & CHECKBOX */
visibility: hidden;
position: absolute;
}
/* RADIO & CHECKBOX STYLES */
.rad > i { /* DEFAULT <i> STYLE */
display: inline-block;
vertical-align: middle;
width: 24px;
height: 24px;
border-radius: 50%;
transition: 0.2s;
box-shadow: inset 0 0 0 16px #fff;
border: 1px solid #cccccc;
background: #cccccc;
margin-right: 5px;
}
/* CHECKBOX OVERWRITE STYLES */
.rad:hover > i { /* HOVER <i> STYLE */
box-shadow: inset 0 0 0 3px #fff;
background: #cccccc;
}
.rad > input:checked + i { /* (RADIO CHECKED) <i> STYLE */
box-shadow: inset 0 0 0 3px #fff;
background: #cccccc;
}
label.rad {
font-style: italic;
color: #606060;
}

@ -0,0 +1,144 @@
.mainContent {
padding: 43px 25px 40px 25px;
}
.avatarInset {
width: 200px;
height: 200px;
}
.avatar {
width: 220px;
height: 220px;
padding: 10px;
}
.simple-input, .simple-select {
height: 51px;
width: 100%;
border: 1px solid #cccccc;
outline: none;
padding: 5px 40px 5px 20px;
background-color: white;
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;
}
.bottom-line {
padding-bottom: 10px;
border-bottom: 1px solid #cccccc;
}
.top-line {
/*padding-bottom: 10px;*/
border-top: 1px solid #cccccc;
}
/* СУПЕР-костыльная кнопка. Не прикасаться!*/
.upload-new {
width: 60%;
height: 30px;
overflow: hidden;
cursor: pointer;
border-radius: 40px;
border: 1px solid #FF0029;
}
.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, .btn-simple {
transition: all 0.3s;
cursor: pointer;
}
.upload-new input {
display: block !important;
width: 100% !important;
height: 30px !important;
opacity: 0 !important;
cursor: pointer;
}
.upload-new p {
line-height: 30px;
text-transform: uppercase;
margin: -30px 0 0 0;
/*padding: 0 5px 0 5px;*/
font-size: 10px;
text-align: center;
font-family: Miriad;
}
/** Конец супер-костыля**/
.row-eq-height {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.info {
background-color: #F2F2F2;
padding: 50px 40px;
margin-top: 20px;
}
.btn-simple {
border-radius: 40px;
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;
}

@ -1,220 +1,317 @@
{% extends 'partials/base.html' %}
{% load staticfiles %}
{% load thumbnail %}
{% block head_css %}
<style>
.-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;
}
</style>
<link rel='stylesheet' href='{% static "lib/proekton-components/css/fonts.css" %}'>
<link rel='stylesheet' href='{% static "lib/proekton-components/css/selected-container.css" %}'>
<link rel='stylesheet' href='{% static "lib/proekton-components/css/editable-container.css" %}'>
<link rel='stylesheet' href='{% static "lib/proekton-components/css/select-box.css" %}'>
<link rel='stylesheet' href='{% static "css/project_filter.css" %}'>{# other #}
<link rel='stylesheet' href='{% static "css/font-awesome.min.css" %}'>
<link rel='stylesheet' href='{% static "css/user_profile_edit.css" %}'>
<link rel='stylesheet' href='{% static "css/custom-checkboxes.css" %}'>
{% endblock %}
{% block content %}
{% include 'partials/header.html' %}
{# {% if request.user.is_customer %}#}
{# <input type="hidden" name="next"#}
{# value="{% url 'users:customer-profile-open-projects' pk=pk %}">#}
{# {% elif request.user.is_contractor %}#}
{# <input type="hidden" name="next" value="{% url 'users:contractor-profile' pk=pk %}">#}
{# {% endif %}#}
<div class="container mainScore">
<div class="row">
<div class="row mainContent">
<form method="POST" enctype="multipart/form-data" novalidate>
{% csrf_token %}
{% if request.user.is_customer %}
<input type="hidden" name="next" value="{% url 'users:customer-profile-open-projects' pk=pk %}">
{% elif request.user.is_contractor %}
<input type="hidden" name="next" value="{% url 'users:contractor-profile' pk=pk %}">
{% endif %}
<div class="projectsBlock disTab">
<div class="col-lg-12">
<div class="col-lg-3 divCol3 -live-image-avatar-upload-container">
<div class="avatar">
<input type="hidden" name="next" value="{% url 'users:contractor-profile' pk=pk %}">
<div class="col-lg-12">
<div class="row row-eq-height">
<div class="col-lg-3 -live-image-avatar-upload-container">
<div class="avatar" style="float: none">
<div class="avatarInset -position-relative-parent">
<a href="#" onclick="return false" class="btn close -live-image-delete" style="display: none">&times;</a>
<a href="#" onclick="return false" class="btn close -live-image-delete"
style="display: none">&times;</a>
{% if request.user.avatar %}
{% thumbnail request.user.avatar "235x224" crop="center" as avatar %}
<img src="{{ avatar.url }}" alt="profile-image" class="-avatar-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="profile-image" class="-avatar-image">
<img src="{% static 'img/profile.jpg' %}" alt="profile-image"
class="-avatar-image">
{% endif %}
</div>
</div>
<div class="menuUser upload-img disTab">
<div class="upload2 up-l1">
<div style="margin-top: 15px">
<div class="upload-new">
{# <div class="upload2 up-l1">#}
<input type="file" name="image" class="-live-image-upload">
<p>Загрузить фотографию</p>
{# </div>#}
</div>
</div>
<div {% if not TESTING %}style="display: none"{% endif %}>
<input type="text" name="live_image" class="-live-image-id">
</div>
</div>
<div class="col-lg-9 divCol9">
<div class="col-lg-4">
<p class="name-edit-p">ФИО</p>
<input type="text" value="{{ form.last_name.value }}" name="{{ form.last_name.html_name }}" class="box-sizing inp-edit">
<input type="text" value="{{ form.first_name.value }}" name="{{ form.first_name.html_name }}" class="box-sizing inp-edit">
<input type="text" value="{{ form.patronym.value }}" name="{{ form.patronym.html_name }}" class="box-sizing inp-edit">
</div>
{% if request.user.is_contractor %}
<div class="col-lg-4">
<p class="name-edit-p">Специализации</p>
<div id="simpleSpecContainer">
<div class="polsF1 pols-edit disTab -simple-spec-widget" style="display: none">
<input type="hidden" class="-simple-spec-select" style="width: 100%">
<input type="hidden" class="-chosen-simple-spec-id" name="{{ form.contractor_specializations.html_name }}">
</div>
{% for spec_id in form.contractor_specializations.value %}
<div class="polsF1 pols-edit disTab -simple-spec-widget">
<input type="hidden" class="-simple-spec-select" style="width: 100%">
<input type="hidden" class="-chosen-simple-spec-id" name="{{ form.contractor_specializations.html_name }}" value="{{ spec_id }}">
</div>
{% endfor %}
</div>
<a href="#" onclick="return false" class="add-edit" id="addSpec">
Добавить еще
</a>
</div>
{% endif %}
<div class="col-lg-4">
<p class="name-edit-p">Местоположение</p>
<div class="polsF1 pols-edit disTab">
<div><input type="hidden" class="-location-select -location-select-country" style="width: 100%"></div>
<div><input type="hidden" class="-location-select -location-select-region" style="width: 100%"></div>
<div><input type="hidden" class="-location-select -location-select-city" style="width: 100%"></div>
<input type="hidden" id="chosenLocationId" name="{{ form.location.html_name }}" value="{{ form.location.value }}">
<div class="col-lg-9">
<div class="row">
<div class="col-lg-12">
<div class="bottom-line">
<span class="header">
Параметры заполнения прифиля влияют на фильтр поиска специалистов, ранжирования в списке
<i class="fa fa-question-circle-o" aria-hidden="true" title=""></i>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="buttonGP btn-edit disTab">
<div class="btn-group valProject valProject2" role="group">
<a href="{% url 'users:user-profile-edit' pk=pk %}"
class="btn btn-default {% if not request.experience_edit %}active{% endif %}">Общая информация</a>
<a href="{% url 'users:user-financial-info-edit' pk=pk %}" class="btn btn-default">Финансовая информация</a>
{% if request.user.is_contractor %}
<a href="{% url 'users:user-experience-edit' pk=pk %}"
class="btn btn-default {% if request.experience_edit %}active{% endif %}">Опыт</a>
{% endif %}
</div>
</div>
<div class="col-lg-12 col12 new-filter">
<div class="filter clearfix">
{% if request.experience_edit %}
<div class="titleF1 disTab">
<div class="col-lg-6">Классификация зданий</div>
<div class="col-lg-6">Виды строительства</div>
<div class="row">
<div class="col-lg-12" style="padding-bottom: 10px">
<span class="header block-header">
Личная информация <i class="fa fa-question-circle-o" aria-hidden="true"
title=""></i>
</span>
</div>
</div>
<div class="polsF1 disTab new-doubt">
<div class="col-lg-6 profile-building-classifications">
{{ form.contractor_building_classifications }}
<div class="row">
<div class="col-lg-4">
<input value="{{ form.last_name.value }}" name="{{ form.last_name.html_name }}"
class="simple-input" placeholder="Фамилия">
</div>
<div class="col-lg-6 profile-construction-types">
{{ form.contractor_construction_types }}
<div class="col-lg-4">
<input value="{{ form.first_name.value }}" name="{{ form.first_name.html_name }}"
class="simple-input" placeholder="Имя">
</div>
<div class="col-lg-4">
<input value="{{ form.patronym.value }}" name="{{ form.patronym.html_name }}"
class="simple-input" placeholder="Отчество">
</div>
<div class="col-lg-4">
<div class="vertical-child" id="sb-location-1">
</div>
</div>
<div class="col-lg-4">
<div class="vertical-child" id="sb-location-2">
</div>
</div>
<div class="col-lg-4">
<div class="vertical-child" id="sb-location-3">
</div>
</div>
<div class="col-lg-8">
<div class="selected-container horizontal vertical-child no-margin"
id="selected-location">
<div class="header">&nbsp;</div>
<input type="hidden" name="location"
value="{{ form.location.value }}">
</div>
</div>
</div>
</div>
</div> <!-- top -->
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить">
<div class="row">
<div style="padding-bottom: 10px" class="col-lg-12">
<div class="row">
<div class="col-lg-offset-3 col-lg-9">
<div class="top-line">
<span class="header block-header">
Мой опыт работы в проектировании / дизайне / сопровождении проектной документации
<i class="fa fa-question-circle-o" aria-hidden="true" title=""></i>
</span>
</div>
</div>
</div>
{% else %}
<div class="titleF1 disTab">
<div class="col-lg-3">Дата рождения</div>
<div class="col-lg-3">Пол</div>
<div class="col-lg-3">Статус</div>
<div class="row">
<div class="col-lg-12">
<div class="" id="select-box-1">
</div>
</div>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3 birth_edit_dat">
{{ form.date_of_birth }}
<div class="row">
<div class="col-lg-3">
<div class="vertical-child" id="select-box-2">
</div>
</div>
<div class="col-lg-3 dog-new ed-new">
{% for id, text in form.gender.field.choices %}
<label>
<input
type="radio"
name="{{ form.gender.html_name }}"
value="{{ id }}"
{% if form.gender.value == id %}checked{% endif %}>
<span></span>
</label>
<p>{{ text }}&nbsp;&nbsp;&nbsp;&nbsp;</p>
{% endfor %}
<div class="col-lg-3">
<div class="vertical-child" id="select-box-3">
</div>
</div>
<div class="col-lg-3">
<div class="vertical-child" id="select-box-4">
</div>
</div>
<div class="col-lg-3">
{{ form.contractor_status }}
<div class="vertical-child" id="select-box-5">
</div>
</div>
</div>
<div class="titleF1 titleF2 disTab">
<div class="col-lg-3">Сайт</div>
<div class="col-lg-3">Skype</div>
<div class="col-lg-3">Телефон</div>
<div class="col-lg-3">Второй телефон</div>
<div class="row">
<div class="col-lg-12">
<div class="selected-container horizontal" id="selected-spec">
<input type="hidden" name="{{ form.contractor_specializations.html_name }}"
value="{{ form.contractor_specializations.value }}">
</div>
</div>
</div>
<div class="searchF1 polsF1 polsFF polsF3">
<div class="row">
<div class="col-lg-3">
<input type="text" name="{{ form.website.html_name }}" value="{{ form.website.value }}" class="box-sizing surr surr2" placeholder="beeg.com">
<div class="vertical-child" id="sb-building-classification">
</div>
<div class="vertical-child" id="sb-building-sub-classification">
</div>
<div class="selected-container" id="selected-building-classification">
<input type="hidden"
name="{{ form.contractor_building_classifications.html_name }}"
value="{{ form.contractor_building_classifications.value }}">
</div>
</div>
<div class="col-lg-3">
<input type="text" name="{{ form.skype.html_name }}" value="{{ form.skype.value }}" class="box-sizing surr surr2" placeholder="nokia770">
<div class="vertical-child" id="sb-construction-type">
</div>
<div class="selected-container" id="selected-construction-type">
<input type="hidden" name="{{ form.contractor_construction_types.html_name }}"
value="{{ form.contractor_construction_types.value }}">
</div>
</div>
<div class="col-lg-3">
<div class="select-box-header vertical-child">
<span style="width: 180px" class="header">Требуется допуск (СРО)</span>
<i class="fa fa-question-circle-o" aria-hidden="true"
title="bla-bla-bla..."></i>
</div>
<div class="custom-check">
<div class="checked"></div>
<div style="display: none" class="not-checked"></div>
<input name="{{ form.cro.html_name }}" type="checkbox" hidden
{% if form.cro.value %} checked{% endif %}>
</div>
</div>
</div>
</div>
</div> <!-- center -->
<div class="row">
<div class="col-lg-12">
<div class="row">
<div class="col-lg-12">
<div class="top-line" style="padding-top: 15px">
<div class="btn-group toggle" role="group" aria-label="...">
<a style="z-index: 0" href="#"
{# <a style="z-index: 0" href="{% url 'users:user-profile-edit' pk=pk %}"#}
role="button"
class="btn btn-default active">Общая информация</a>
<a href="#"
class="btn btn-default" role="button">Финансовая информация</a>
</div>
</div>
</div>
</div>
<div class="row info">
<div class="col-lg-3">
<input type="text" name="{{ form.phone.html_name }}" value="{{ form.phone.value }}" class="box-sizing surr surr2" placeholder="+7 999 999 44 02">
<div class="header"> Дата рождения</div>
<div class="birth_edit_dat">
{{ form.date_of_birth }}
</div>
</div>
<div class="col-lg-3">
<div style="position: relative" class="select-box-container custom-select"
id="gender">
<div class="select-box-header">
<div class="header">Пол</div>
</div>
<input class="simple-select" placeholder="Выберите"
value="{{ form.get_gender_display }}" readonly>
<input type="hidden" name="{{ form.gender.html_name }}" value="{{ form.gender.value }}">
<div class="select-box-options" style="width: 100%; display: none">
<div style="min-width: inherit" class="box-wrapper">
<ul>
{% for id, text in form.gender.field.choices %}
<li data-id="{{ id }}">{{ text }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
<div class="col-lg-3">
<input type="text" name="{{ form.phone2.html_name }}" value="{{ form.phone2.value }}" class="box-sizing surr surr2" placeholder="+7 999 999 44 02">
<div style="position: relative" class="select-box-container custom-select"
id="gender">
<div class="select-box-header">
<div class="header">Статус</div>
</div>
<input class="simple-select" placeholder="Выберите"
value="{{ form.get_status_display }}" readonly>
<input type="hidden" name="{{ form.contractor_status.html_name }}" value="{{ form.contractor_status.value }}">
<div class="select-box-options" style="width: 100%; display: none">
<div style="min-width: inherit" class="box-wrapper">
<ul>
{% for id, text in form.contractor_status.field.choices %}
<li data-id="{{ id }}">{{ text }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="col-lg-12 make-new make-eed">
<label>{{ form.cro }}<span></span></label>
<p>Есть допуск СРО</p>
<div class="col-lg-3">
<div class="header">Skype</div>
<input name="{{ form.skype.html_name }}" class="simple-input" placeholder="skype id"
value="{{ form.skype.value }}">
</div>
<div class="clearfix visible-lg"></div>
<div class="col-lg-3 vertical-child">
<div class="header">Сайт</div>
<input name="{{ form.website.html_name }}" class="simple-input"
placeholder="example.com"
value="{{ form.website.value }}">
</div>
<div class="col-lg-3 vertical-child">
<div class="header">Телефон</div>
<input name="{{ form.phone.html_name }}" class="simple-input phone"
placeholder="+7 909 999 00 00"
value="{{ form.phone.value }}"
type="tel">
</div>
<div class="col-lg-3 vertical-child">
<div class="header">Второй телефон</div>
<input name="{{ form.phone2.html_name }}" class="simple-input phone"
placeholder="+7 909 999 00 00"
value="{{ form.phone2.value }}"
type="tel">
</div>
<div class="col-lg-3 vertical-child" style="text-align: center">
<div class="header">&nbsp;</div>
<input type="submit" class="btn btn-simple" value="СОХРАНИТЬ">
</div>
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить">
</div>
{% endif %}
</div>
</div>
</div> <!-- bottom -->
</div>
</form>
</div>
<div class="row">
{% include 'partials/footer.html' %}
</div>
</div>
{% endblock %}
{% block js_block %}
{{ block.super }}
<script src='{% static "lib/proekton-components/js/build/init_user_profile.js" %}'></script>
<script src='{% static "projects-filter.js" %}'></script>
<script src='{% static "js/jquery.mask.min.js" %}'></script>
<script>
$(function () {
$('.phone').mask('+7(000)000-00-00');
})
</script>
{% endblock %}

@ -0,0 +1,220 @@
{% extends 'partials/base.html' %}
{% load thumbnail %}
{% block head_css %}
<style>
.-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;
}
</style>
{% endblock %}
{% block content %}
{% include 'partials/header.html' %}
<div class="container mainScore">
<div class="row">
<form method="POST" enctype="multipart/form-data" novalidate>
{% csrf_token %}
{% if request.user.is_customer %}
<input type="hidden" name="next" value="{% url 'users:customer-profile-open-projects' pk=pk %}">
{% elif request.user.is_contractor %}
<input type="hidden" name="next" value="{% url 'users:contractor-profile' pk=pk %}">
{% endif %}
<div class="projectsBlock disTab">
<div class="col-lg-12">
<div class="col-lg-3 divCol3 -live-image-avatar-upload-container">
<div class="avatar">
<div class="avatarInset -position-relative-parent">
<a href="#" onclick="return false" class="btn close -live-image-delete" style="display: none">&times;</a>
{% if request.user.avatar %}
{% thumbnail request.user.avatar "235x224" crop="center" as avatar %}
<img src="{{ avatar.url }}" alt="profile-image" class="-avatar-image">
{% endthumbnail %}
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="profile-image" class="-avatar-image">
{% endif %}
</div>
</div>
<div class="menuUser upload-img disTab">
<div class="upload2 up-l1">
<input type="file" name="image" class="-live-image-upload">
<p>Загрузить фотографию</p>
</div>
</div>
<div {% if not TESTING %}style="display: none"{% endif %}>
<input type="text" name="live_image" class="-live-image-id">
</div>
</div>
<div class="col-lg-9 divCol9">
<div class="col-lg-4">
<p class="name-edit-p">ФИО</p>
<input type="text" value="{{ form.last_name.value }}" name="{{ form.last_name.html_name }}" class="box-sizing inp-edit">
<input type="text" value="{{ form.first_name.value }}" name="{{ form.first_name.html_name }}" class="box-sizing inp-edit">
<input type="text" value="{{ form.patronym.value }}" name="{{ form.patronym.html_name }}" class="box-sizing inp-edit">
</div>
{% if request.user.is_contractor %}
<div class="col-lg-4">
<p class="name-edit-p">Специализации</p>
<div id="simpleSpecContainer">
<div class="polsF1 pols-edit disTab -simple-spec-widget" style="display: none">
<input type="hidden" class="-simple-spec-select" style="width: 100%">
<input type="hidden" class="-chosen-simple-spec-id" name="{{ form.contractor_specializations.html_name }}">
</div>
{% for spec_id in form.contractor_specializations.value %}
<div class="polsF1 pols-edit disTab -simple-spec-widget">
<input type="hidden" class="-simple-spec-select" style="width: 100%">
<input type="hidden" class="-chosen-simple-spec-id" name="{{ form.contractor_specializations.html_name }}" value="{{ spec_id }}">
</div>
{% endfor %}
</div>
<a href="#" onclick="return false" class="add-edit" id="addSpec">
Добавить еще
</a>
</div>
{% endif %}
<div class="col-lg-4">
<p class="name-edit-p">Местоположение</p>
<div class="polsF1 pols-edit disTab">
<div><input type="hidden" class="-location-select -location-select-country" style="width: 100%"></div>
<div><input type="hidden" class="-location-select -location-select-region" style="width: 100%"></div>
<div><input type="hidden" class="-location-select -location-select-city" style="width: 100%"></div>
<input type="hidden" id="chosenLocationId" name="{{ form.location.html_name }}" value="{{ form.location.value }}">
</div>
</div>
</div>
</div>
</div>
<div class="buttonGP btn-edit disTab">
<div class="btn-group valProject valProject2" role="group">
<a href="{% url 'users:user-profile-edit' pk=pk %}"
class="btn btn-default {% if not request.experience_edit %}active{% endif %}">Общая информация</a>
<a href="{% url 'users:user-financial-info-edit' pk=pk %}" class="btn btn-default">Финансовая информация</a>
{% if request.user.is_contractor %}
<a href="{% url 'users:user-experience-edit' pk=pk %}"
class="btn btn-default {% if request.experience_edit %}active{% endif %}">Опыт</a>
{% endif %}
</div>
</div>
<div class="col-lg-12 col12 new-filter">
<div class="filter clearfix">
{% if request.experience_edit %}
<div class="titleF1 disTab">
<div class="col-lg-6">Классификация зданий</div>
<div class="col-lg-6">Виды строительства</div>
</div>
<div class="polsF1 disTab new-doubt">
<div class="col-lg-6 profile-building-classifications">
{{ form.contractor_building_classifications }}
</div>
<div class="col-lg-6 profile-construction-types">
{{ form.contractor_construction_types }}
</div>
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить">
</div>
{% else %}
<div class="titleF1 disTab">
<div class="col-lg-3">Дата рождения</div>
<div class="col-lg-3">Пол</div>
<div class="col-lg-3">Статус</div>
</div>
<div class="polsF1 disTab">
<div class="col-lg-3 birth_edit_dat">
{{ form.date_of_birth }}
</div>
<div class="col-lg-3 dog-new ed-new">
{% for id, text in form.gender.field.choices %}
<label>
<input
type="radio"
name="{{ form.gender.html_name }}"
value="{{ id }}"
{% if form.gender.value == id %}checked{% endif %}>
<span></span>
</label>
<p>{{ text }}&nbsp;&nbsp;&nbsp;&nbsp;</p>
{% endfor %}
</div>
<div class="col-lg-3">
{{ form.contractor_status }}
</div>
</div>
<div class="titleF1 titleF2 disTab">
<div class="col-lg-3">Сайт</div>
<div class="col-lg-3">Skype</div>
<div class="col-lg-3">Телефон</div>
<div class="col-lg-3">Второй телефон</div>
</div>
<div class="searchF1 polsF1 polsFF polsF3">
<div class="col-lg-3">
<input type="text" name="{{ form.website.html_name }}" value="{{ form.website.value }}" class="box-sizing surr surr2" placeholder="beeg.com">
</div>
<div class="col-lg-3">
<input type="text" name="{{ form.skype.html_name }}" value="{{ form.skype.value }}" class="box-sizing surr surr2" placeholder="nokia770">
</div>
<div class="col-lg-3">
<input type="text" name="{{ form.phone.html_name }}" value="{{ form.phone.value }}" class="box-sizing surr surr2" placeholder="+7 999 999 44 02">
</div>
<div class="col-lg-3">
<input type="text" name="{{ form.phone2.html_name }}" value="{{ form.phone2.value }}" class="box-sizing surr surr2" placeholder="+7 999 999 44 02">
</div>
</div>
<div class="col-lg-12">
<div class="col-lg-12 make-new make-eed">
<label>{{ form.cro }}<span></span></label>
<p>Есть допуск СРО</p>
</div>
</div>
<div class="searchF1 polsF1 polsFF links-filter">
<input class="btn-submit-link" type="submit" value="Сохранить">
</div>
{% endif %}
</div>
</div>
</form>
{% include 'partials/footer.html' %}
</div>
</div>
{% endblock %}

@ -18,16 +18,18 @@ from .views import (
TeamProfileView,
UserFinancialInfoEditView,
UserProfileEditView,
UserProfileEditViewFull,
)
app_name = 'users'
urlpatterns = [
urls.url(r'^(?P<pk>\d+)/edit/$', UserProfileEditView.as_view(), name='user-profile-edit'),
urls.url(r'^(?P<pk>\d+)/financial-info/edit/$', UserFinancialInfoEditView.as_view(),
name='user-financial-info-edit'),
# urls.url(r'^(?P<pk>\d+)/edit/$', UserProfileEditView.as_view(), name='user-profile-edit'),
urls.url(r'^(?P<pk>\d+)/edit/$', UserProfileEditViewFull.as_view(), name='user-profile-edit'),
# urls.url(r'^(?P<pk>\d+)/financial-info/edit/$', UserFinancialInfoEditView.as_view(),
# name='user-financial-info-edit'),
urls.url(r'^(?P<pk>\d+)/experience/edit/$', UserProfileEditView.as_view(), name='user-experience-edit'),
# urls.url(r'^(?P<pk>\d+)/experience/edit/$', UserProfileEditView.as_view(), name='user-experience-edit'),
urls.url(r'^customers/(?P<pk>\d+)/$', CustomerProfileOpenProjectsView.as_view(),
name='customer-profile-open-projects'),

@ -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,6 +102,74 @@ class UserProfileEditView(BaseMixin, View):
return render(request, self.template_name, context)
class UserProfileEditViewFull(BaseMixin, View):
form_class = UserProfileEditFullForm
template_name = 'user_profile_edit.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 get(self, request, *args, **kwargs):
context = self.get_context_data(**_.merge({}, request.GET, kwargs))
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)
def post(self, request, *args, **kwargs):
context = self.get_context_data(**kwargs)
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)
if form.is_valid():
user = form.save()
live_image = form.cleaned_data.get('live_image')
if live_image:
new_image = ContentFile(live_image.file.read())
new_image.name = live_image.file.name
user.avatar = new_image
user.save()
live_image.file.delete()
live_image.delete()
messages.info(request, 'Пользователь успешно отредактирован')
redirect_to = request.POST.get('next')
return redirect(redirect_to)
else:
if form.errors:
messages.info(request, (
'<p>Произошла ошибка (form)</p>'
'<pre>{form}</pre>'
).format(form=pformat(form.errors)))
context.update({'form': form})
return render(request, self.template_name, context)
class UserFinancialInfoEditView(BaseMixin, View):
form_class = UserProfileBasicInfoEditForm
fin_info_form_class = UserFinancialInfoEditForm

Loading…
Cancel
Save