PR-16 Исправление формы заполнения готовых проектов

Изменение model WorkSell
Форма создания готовых проектов закончена
remotes/origin/PR-49
booblegum 9 years ago
parent 0b8c803dad
commit 96745cc2fa
  1. 6
      api/urls.py
  2. 10
      api/views.py
  3. BIN
      assets/img/aui-icon-close.png
  4. BIN
      assets/img/close-img-icon.png
  5. 95
      assets/js/build/create_project.js
  6. 212
      assets/js/build/create_worksell.js
  7. 1905
      assets/js/build/init_create_worksell.js
  8. 65
      assets/js/build/init_customer_project_create.js
  9. 7
      assets/js/src/create_worksell.js
  10. 2
      assets/js/src/customer_project_create.js
  11. 104
      assets/js/src/init_create_worksell.js
  12. 28
      assets/js/src/seeds/file_upload.js
  13. 47
      assets/js/src/seeds/image_upload.js
  14. 16
      assets/js/src/seeds/textareas_max-rows.js
  15. 36
      assets/js/src/utils.js
  16. 7
      assets/lib/proekton-components/sass/parts/_selected-container.sass
  17. 29
      assets/sass/components/custom-components.sass
  18. 14
      common/serializers.py
  19. 6
      projects/templates/customer_project_create.html
  20. 59
      templates/partials/sass/header.sass
  21. 46
      users/templates/contractor_profile.html
  22. 7
      webpack.config.js
  23. 3
      work_sell/admin.py
  24. 75
      work_sell/forms.py
  25. 30
      work_sell/migrations/0020_auto_20161207_0034.py
  26. 27
      work_sell/migrations/0021_auto_20161207_1210.py
  27. 37
      work_sell/migrations/0022_auto_20161207_1213.py
  28. 25
      work_sell/models.py
  29. 261
      work_sell/templates/worksell_create.html
  30. 7
      work_sell/urls.py
  31. 100
      work_sell/views.py

@ -5,6 +5,7 @@ from .views import (
ContractorResumeFilesViewSet,
ContractorResumeViewSet,
DocumentViewSet,
ElFormatViewSet,
LocationViewSet,
LocationViewSetFlat,
MessageViewSet,
@ -29,9 +30,12 @@ from .views import (
router = routers.DefaultRouter()
router.register(r'answers', AnswerViewSet)
router.register(r'building_classifications', BuildingClassificationViewSet)
router.register(r'construction_type', ConstructionTypeViewSet)
router.register(r'contractorresume', ContractorResumeViewSet)
router.register(r'contractorresumefiles', ContractorResumeFilesViewSet)
router.register(r'documents', DocumentViewSet)
router.register(r'el_format', ElFormatViewSet)
router.register(r'locations', LocationViewSet)
router.register(r'locations_flat', LocationViewSetFlat)
router.register(r'message', MessageViewSet, base_name='Message')
@ -41,8 +45,6 @@ router.register(r'portfolio-photos', PortfolioPhotoViewSet)
router.register(r'portfolios', PortfolioViewSet)
router.register(r'projects', ProjectViewSet)
router.register(r'realties', RealtyViewSet)
router.register(r'building_classifications', BuildingClassificationViewSet)
router.register(r'construction_type', ConstructionTypeViewSet)
router.register(r'reviews', ReviewViewSet)
router.register(r'specializations', SpecializationViewSet)
router.register(r'specializations_flat', SpecializationViewSetFlat)

@ -11,7 +11,7 @@ from chat.models import Message, Notes, Documents, NewMessage
from chat.serializers import MessageSerializer, NoteSerializer, DocumentsSerializer
from common.filters import LocationFilterSet
from common.models import Location
from common.serializers import LocationSerializer, LocationSerializerFlat
from common.serializers import LocationSerializer, LocationSerializerFlat, ElFormatSerializer
from projects.filters import (
ProjectFilterSet, RealtyFilterSet, StageFilterSet, PortfolioFilterSet, OrderFilterSet,
PortfolioPhotoFilterSet, AnswerFilterSet, BuildingClassficationFilterSet, ConstructionTypeFilterSet
@ -33,7 +33,7 @@ from users.models import User, ContractorResumeFiles, ContractorResume, Team
from users.serializers import UserSerializer, ContractorResumeFilesSerializer, ContractorResumeSerializer, \
TeamSerializer
from work_sell.filters import WorkSellFilterSet, WorkSellPhotoFilterSet
from work_sell.models import WorkSell, WorkSellPhoto
from work_sell.models import WorkSell, WorkSellPhoto, ElFormat
from work_sell.serializers import WorkSellSerializer, WorkSellPhotoSerializer
@ -230,6 +230,12 @@ class LocationViewSetFlat(ModelViewSet):
filter_class = LocationFilterSet
class ElFormatViewSet(ModelViewSet):
queryset = ElFormat.objects.all().order_by('name')
serializer_class = ElFormatSerializer
# filter_class = LocationFilterSet
class PortfolioPagination(PageNumberPagination):
page_size = settings.API_PAGE_SIZE # Default page size
page_size_query_param = 'page_size' # Provide custom page size through a query param

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

@ -48,19 +48,15 @@
var _file_upload = __webpack_require__(1);
var _file_upload2 = _interopRequireDefault(_file_upload);
var _extended_field = __webpack_require__(3);
var _extended_field = __webpack_require__(2);
var _custom_check = __webpack_require__(4);
var _custom_check = __webpack_require__(3);
var _read_more = __webpack_require__(5);
var _read_more = __webpack_require__(4);
var _only_one_checkbox = __webpack_require__(6);
var _only_one_checkbox = __webpack_require__(5);
var _test_seeds = __webpack_require__(6);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var _test_seeds = __webpack_require__(7);
function showHideRealry() {
var check = $('#checkbox-sb-realty');
@ -75,7 +71,7 @@
}
$(function () {
(0, _file_upload2.default)();
(0, _file_upload.fileUploadInit)();
(0, _extended_field.extendedFieldInit)();
(0, _custom_check.customCheckInit)();
showHideRealry();
@ -85,30 +81,16 @@
/***/ },
/* 1 */
/***/ function(module, exports) {
/***/ function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = fileUploadInit;
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) return bytes + ' B';
var units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
var u = -1;
do {
bytes /= thresh;
++u;
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
exports.fileUploadInit = undefined;
return bytes.toFixed(1) + ' ' + units[u];
}
var _utils = __webpack_require__(2);
function fileUploadInit() {
var $fileUploadContainer = $('#fileUploadContainer');
@ -123,7 +105,7 @@
var filePath = $fileInput.val().replace(/\\/g, '/');
var fileName = path.basename(filePath);
//var fileExt = path.extname(filePath)
var fileSize = $fileInput.get(0).files && humanFileSize($fileInput.get(0).files[0].size);
var fileSize = $fileInput.get(0).files && (0, _utils.humanFileSize)($fileInput.get(0).files[0].size);
if (fileName) {
$fileUploadWidget.find('.file-upload-label').text(fileName + ' ' + fileSize);
@ -141,15 +123,56 @@
var $btn = $(this);
$btn.closest('.file-upload-widget').remove();
});
}
$fileUploadContainer.on('click', '.existing-file-remove-btn', function ($evt) {
var $btn = $(this);
$btn.closest('.existing-file-widget').remove();
exports.fileUploadInit = fileUploadInit;
/***/ },
/* 2 */
/***/ function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == name + '=') {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) return bytes + ' B';
var units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
var u = -1;
do {
bytes /= thresh;
++u;
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1) + ' ' + units[u];
}
exports.humanFileSize = humanFileSize;
exports.getCookie = getCookie;
/***/ },
/* 2 */
/* 3 */
/***/ function(module, exports) {
'use strict';
@ -179,7 +202,7 @@
exports.extendedFieldInit = extendedFieldInit;
/***/ },
/* 3 */
/* 4 */
/***/ function(module, exports) {
"use strict";
@ -208,7 +231,7 @@
exports.customCheckInit = customCheckInit;
/***/ },
/* 4 */
/* 5 */
/***/ function(module, exports) {
"use strict";
@ -234,7 +257,7 @@
exports.readMoreInit = readMoreInit;
/***/ },
/* 5 */
/* 6 */
/***/ function(module, exports) {
"use strict";
@ -265,7 +288,7 @@
exports.onlyOneCheckboxInit = onlyOneCheckboxInit;
/***/ },
/* 6 */
/* 7 */
/***/ function(module, exports) {
"use strict";

@ -0,0 +1,212 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId])
/******/ return installedModules[moduleId].exports;
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ exports: {},
/******/ id: moduleId,
/******/ loaded: false
/******/ };
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ // Flag the module as loaded
/******/ module.loaded = true;
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/ // Load entry module and return exports
/******/ return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
var _file_upload = __webpack_require__(1);
var _image_upload = __webpack_require__(8);
$(function () {
// fileUploadInit();
(0, _image_upload.imageUploadInit)();
});
/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.fileUploadInit = undefined;
var _utils = __webpack_require__(2);
function fileUploadInit() {
var $fileUploadContainer = $('#fileUploadContainer');
$('#fileUploadAddBtn').on('click', function ($evt) {
$fileUploadContainer.find('.file-upload-widget').last().find('.file-upload-input').click();
});
$fileUploadContainer.on('change', '.file-upload-input', function ($evt) {
var $fileInput = $(this);
var $fileUploadWidget = $fileInput.closest('.file-upload-widget');
var filePath = $fileInput.val().replace(/\\/g, '/');
var fileName = path.basename(filePath);
//var fileExt = path.extname(filePath)
var fileSize = $fileInput.get(0).files && (0, _utils.humanFileSize)($fileInput.get(0).files[0].size);
if (fileName) {
$fileUploadWidget.find('.file-upload-label').text(fileName + ' ' + fileSize);
var $newFileUploadWidget = $fileUploadWidget.clone();
$newFileUploadWidget.find('.file-upload-label').text('');
$fileUploadContainer.find('ul').first().append($newFileUploadWidget);
$fileUploadWidget.css('display', 'block');
}
});
$fileUploadContainer.on('click', '.file-upload-remove-btn', function ($evt) {
var $btn = $(this);
$btn.closest('.file-upload-widget').remove();
});
}
exports.fileUploadInit = fileUploadInit;
/***/ },
/* 2 */
/***/ function(module, exports) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == name + '=') {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) return bytes + ' B';
var units = si ? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] : ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
var u = -1;
do {
bytes /= thresh;
++u;
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1) + ' ' + units[u];
}
exports.humanFileSize = humanFileSize;
exports.getCookie = getCookie;
/***/ },
/* 3 */,
/* 4 */,
/* 5 */,
/* 6 */,
/* 7 */,
/* 8 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.imageUploadInit = undefined;
var _utils = __webpack_require__(2);
function imageUploadInit() {
var $fileUploadContainer = $('#fileUploadContainer');
$('#fileUploadAddBtn').on('click', function ($evt) {
$fileUploadContainer.find('.file-upload-widget').last().find('.file-upload-input').click();
});
$fileUploadContainer.on('change', '.file-upload-input', function ($evt) {
var $fileInput = $(this);
var $fileUploadWidget = $fileInput.closest('.file-upload-widget');
var $fileImg = $fileUploadWidget.find('img');
var filePath = $fileInput.val().replace(/\\/g, '/');
var fileName = path.basename(filePath);
var fileSize = $fileInput.get(0).files && (0, _utils.humanFileSize)($fileInput.get(0).files[0].size);
if (fileName) {
$fileUploadWidget.find('.file-upload-label').text(fileName + ' ' + fileSize);
var $newFileUploadWidget = $fileUploadWidget.clone();
$newFileUploadWidget.find('.file-upload-label').text('');
$fileUploadContainer.find('.list-new-new').append($newFileUploadWidget);
$fileUploadWidget.css('display', 'block');
if ($fileImg) {
var reader = new FileReader();
reader.onload = function (e) {
$fileImg.attr('src', e.target.result);
};
reader.readAsDataURL($fileInput[0].files[0]);
}
}
});
$fileUploadContainer.on('click', '.file-upload-remove-img-btn', function ($evt) {
var $btn = $(this);
$btn.closest('.file-upload-widget').remove();
});
} //TODO: оформить Upload'еры в виде классов
exports.imageUploadInit = imageUploadInit;
/***/ }
/******/ ]);

File diff suppressed because it is too large Load Diff

@ -46,27 +46,27 @@
'use strict';
var _SelectedContainer = __webpack_require__(7);
var _SelectedContainer = __webpack_require__(10);
var _SelectedContainer2 = _interopRequireDefault(_SelectedContainer);
var _SelectedContainerCreate = __webpack_require__(11);
var _SelectedContainerCreate = __webpack_require__(14);
var _SelectedContainerCreate2 = _interopRequireDefault(_SelectedContainerCreate);
var _NoTreeSelect = __webpack_require__(12);
var _NoTreeSelect = __webpack_require__(15);
var _NoTreeSelect2 = _interopRequireDefault(_NoTreeSelect);
var _TreeSelect = __webpack_require__(14);
var _TreeSelect = __webpack_require__(17);
var _TreeSelect2 = _interopRequireDefault(_TreeSelect);
var _SingleTreeSelect = __webpack_require__(15);
var _SingleTreeSelect = __webpack_require__(18);
var _SingleTreeSelect2 = _interopRequireDefault(_SingleTreeSelect);
var _SelectOrCreate = __webpack_require__(16);
var _SelectOrCreate = __webpack_require__(19);
var _SelectOrCreate2 = _interopRequireDefault(_SelectOrCreate);
@ -174,19 +174,15 @@
if (!sb_realty_top.dataTree.data.length) sb_realty_top.hide();
});
select_realty.on("add", function (args) {
// console.log("add args = ", args);
console.log('on add');
//TODO: Костыли!!!
$('#checkbox-sb-realty').prop("checked", true);
sb_realty.show();
var id = args[0];
if (id.text) return;
console.log("id = ", id);
var el = sb_realty.dataTree.getElementById(id);
sb_realty_top.$searchInput.val(el.name);
sb_realty_top.selectedEl.id = id;
sb_realty_top.selectedEl.value = el.name;
// sb_realty_top.show();
sb_realty.selectedEl.id = id;
sb_realty._fillBoxes();
});
@ -212,7 +208,10 @@
/* 4 */,
/* 5 */,
/* 6 */,
/* 7 */
/* 7 */,
/* 8 */,
/* 9 */,
/* 10 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
@ -227,15 +226,15 @@
var _desc, _value, _class; // `
var _DataTree = __webpack_require__(8);
var _DataTree = __webpack_require__(11);
var _DataTree2 = _interopRequireDefault(_DataTree);
var _NoTreeData = __webpack_require__(9);
var _NoTreeData = __webpack_require__(12);
var _NoTreeData2 = _interopRequireDefault(_NoTreeData);
var _decorators = __webpack_require__(10);
var _decorators = __webpack_require__(13);
var _decorators2 = _interopRequireDefault(_decorators);
@ -466,7 +465,7 @@
exports.default = SelectedContainer;
/***/ },
/* 8 */
/* 11 */
/***/ function(module, exports) {
"use strict";
@ -621,7 +620,7 @@
exports.default = DataTree;
/***/ },
/* 9 */
/* 12 */
/***/ function(module, exports) {
"use strict";
@ -677,7 +676,7 @@
exports.default = NoTreeData;
/***/ },
/* 10 */
/* 13 */
/***/ function(module, exports) {
"use strict";
@ -761,7 +760,7 @@
// export {onBind};
/***/ },
/* 11 */
/* 14 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
@ -777,11 +776,11 @@
var _desc, _value, _class;
var _SelectedContainer2 = __webpack_require__(7);
var _SelectedContainer2 = __webpack_require__(10);
var _SelectedContainer3 = _interopRequireDefault(_SelectedContainer2);
var _decorators = __webpack_require__(10);
var _decorators = __webpack_require__(13);
var _decorators2 = _interopRequireDefault(_decorators);
@ -862,7 +861,7 @@
exports.default = SelectedContainerCreate;
/***/ },
/* 12 */
/* 15 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
@ -876,9 +875,9 @@
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _AbsBaseSelect2 = __webpack_require__(13);
var _AbsBaseSelect2 = __webpack_require__(16);
var _NoTreeData = __webpack_require__(9);
var _NoTreeData = __webpack_require__(12);
var _NoTreeData2 = _interopRequireDefault(_NoTreeData);
@ -945,7 +944,7 @@
exports.default = NoTreeSelect;
/***/ },
/* 13 */
/* 16 */
/***/ function(module, exports) {
"use strict";
@ -1487,7 +1486,7 @@
exports.AbsBaseSelect = AbsBaseSelect;
/***/ },
/* 14 */
/* 17 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
@ -1501,9 +1500,9 @@
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _AbsBaseSelect2 = __webpack_require__(13);
var _AbsBaseSelect2 = __webpack_require__(16);
var _DataTree = __webpack_require__(8);
var _DataTree = __webpack_require__(11);
var _DataTree2 = _interopRequireDefault(_DataTree);
@ -1612,7 +1611,7 @@
exports.default = TreeSelect;
/***/ },
/* 15 */
/* 18 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
@ -1624,9 +1623,9 @@
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
var _AbsBaseSelect = __webpack_require__(13);
var _AbsBaseSelect = __webpack_require__(16);
var _TreeSelect2 = __webpack_require__(14);
var _TreeSelect2 = __webpack_require__(17);
var _TreeSelect3 = _interopRequireDefault(_TreeSelect2);
@ -1707,7 +1706,7 @@
exports.default = SingleTreeSelect;
/***/ },
/* 16 */
/* 19 */
/***/ function(module, exports, __webpack_require__) {
'use strict';
@ -1721,9 +1720,9 @@
var _get = function get(object, property, receiver) { if (object === null) object = Function.prototype; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { return get(parent, property, receiver); } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } };
var _AbsBaseSelect2 = __webpack_require__(13);
var _AbsBaseSelect2 = __webpack_require__(16);
var _NoTreeData = __webpack_require__(9);
var _NoTreeData = __webpack_require__(12);
var _NoTreeData2 = _interopRequireDefault(_NoTreeData);

@ -0,0 +1,7 @@
import {fileUploadInit} from './seeds/file_upload'
import {imageUploadInit} from './seeds/image_upload'
$(function () {
// fileUploadInit();
imageUploadInit();
});

@ -1,4 +1,4 @@
import fileUploadInit from './seeds/file_upload'
import {fileUploadInit} from './seeds/file_upload'
import {extendedFieldInit} from './seeds/extended_field'
import {customCheckInit} from './seeds/custom_check'
import {readMoreInit} from './seeds/read_more'

@ -0,0 +1,104 @@
import SelectedContainer from 'components/SelectedContainer';
import SelectedContainerCreate from 'components/SelectedContainerCreate';
import NoTreeSelect from 'components/NoTreeSelect';
import TreeSelect from 'components/TreeSelect';
import SingleTreeSelect from 'components/SingleTreeSelect'
import SelectOrCreate from 'components/SelectOrCreate'
$(function () {
function createSpecs(url) {
// SPECIALIZATIONS
let sb_main = new TreeSelect($('#select-box-1'), {url, visible: true, required: 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});
// select_container.on("add", () => {
// let $container = $('#spec-value');
// $container.html($('#selected-spec').find(".selected-element").find(".name").html());
// });
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 createBuildingClass(url) {
// BUILDING-CLASSIFICATION
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,
onlyOne: true
});
sb_build_main.connectSelectedContainer(select_build_container);
sb_build_main.setNearbySelectBox(sb_build_1);
sb_build_1.setNearbySelectBox("", sb_build_main);
}
function createConstructionType(url) {
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,
onlyOne: true
});
sb_constr_main.connectSelectedContainer(select_constr_type);
}
function createLocations(url) {
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});
sb_loc_main.setNearbySelectBox(sb_loc_1);
sb_loc_1.setNearbySelectBox(sb_loc_2, sb_loc_main);
sb_loc_2.setNearbySelectBox("", sb_loc_1);
}
function createFormat(url) {
let sb_format_main = new NoTreeSelect($('#sb-format'), {url, visible: true});
sb_format_main.setHeader("Формат электронной версии");
let select_format = new SelectedContainer($('#selected-format'), {
obj: sb_format_main,
noTree: true,
// onlyOne: true
});
sb_format_main.connectSelectedContainer(select_format);
}
let sb_loc_main, sb_constr_main, sb_build_main;
createSpecs('/api/specializations_flat');
createBuildingClass('/api/building_classifications');
createConstructionType('/api/construction_type');
createLocations('/api/locations_flat');
createFormat('/api/el_format');
// createRealty('/api/realties/current_user')
});

@ -1,24 +1,6 @@
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
import {humanFileSize} from '../utils'
if (Math.abs(bytes) < thresh)
return bytes + ' B';
var units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
var u = -1;
do {
bytes /= thresh;
++u
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1) + ' ' + units[u]
}
export default function fileUploadInit() {
function fileUploadInit() {
var $fileUploadContainer = $('#fileUploadContainer');
$('#fileUploadAddBtn').on('click', function ($evt) {
@ -50,8 +32,6 @@ export default function fileUploadInit() {
$btn.closest('.file-upload-widget').remove()
});
$fileUploadContainer.on('click', '.existing-file-remove-btn', function ($evt) {
var $btn = $(this);
$btn.closest('.existing-file-widget').remove()
});
}
export {fileUploadInit}

@ -0,0 +1,47 @@
//TODO: оформить Upload'еры в виде классов
import {humanFileSize} from '../utils'
function imageUploadInit() {
var $fileUploadContainer = $('#fileUploadContainer');
$('#fileUploadAddBtn').on('click', function ($evt) {
$fileUploadContainer.find('.file-upload-widget').last().find('.file-upload-input').click()
});
$fileUploadContainer.on('change', '.file-upload-input', function ($evt) {
var $fileInput = $(this);
var $fileUploadWidget = $fileInput.closest('.file-upload-widget');
let $fileImg = $fileUploadWidget.find('img');
var filePath = $fileInput.val().replace(/\\/g, '/');
var fileName = path.basename(filePath);
var fileSize = $fileInput.get(0).files && humanFileSize($fileInput.get(0).files[0].size);
if (fileName) {
$fileUploadWidget.find('.file-upload-label').text(fileName + ' ' + fileSize);
var $newFileUploadWidget = $fileUploadWidget.clone();
$newFileUploadWidget.find('.file-upload-label').text('');
$fileUploadContainer.find('.list-new-new').append($newFileUploadWidget);
$fileUploadWidget.css('display', 'block');
if ($fileImg) {
let reader = new FileReader();
reader.onload = function (e) {
$fileImg.attr('src', e.target.result);
};
reader.readAsDataURL($fileInput[0].files[0]);
}
}
});
$fileUploadContainer.on('click', '.file-upload-remove-img-btn', function ($evt) {
var $btn = $(this);
$btn.closest('.file-upload-widget').remove()
});
}
export {imageUploadInit}

@ -0,0 +1,16 @@
function textareasMaxRowsInit() {
$('textarea[data-limit-rows=true]')
.on('keypress', function (event) {
console.log("work");
var textarea = $(this),
text = textarea.val(),
numberOfLines = (text.match(/\n/g) || []).length + 1,
maxRows = parseInt(textarea.attr('rows'));
if (event.which === 13 && numberOfLines === maxRows) {
return false;
}
});
}
export {textareasMaxRowsInit}

@ -0,0 +1,36 @@
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function humanFileSize(bytes, si) {
var thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh)
return bytes + ' B';
var units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
var u = -1;
do {
bytes /= thresh;
++u
} while (Math.abs(bytes) >= thresh && u < units.length - 1);
return bytes.toFixed(1) + ' ' + units[u]
}
export {humanFileSize, getCookie}

@ -38,7 +38,10 @@
.horizontal
&.selected-container
display: inline-block
max-width: 300px
//display: inline-block
.header, .name
//max-width: 300px
display: inline-block
.selected-element
max-width: 300px
display: inline-block

@ -135,6 +135,12 @@ textarea.description
width: auto
text-align: right
.file-upload-widget
.preview
width: 100%
height: 200px
margin-bottom: 10px
.separator
margin-top: 35px
margin-bottom: 15px
@ -209,14 +215,29 @@ textarea.description
color: darkgray
.file-upload-remove-btn
display: inline-block
//position: absolute
width: 11px
height: 11px
background: url('#{$static}/img/delDoc.png') no-repeat center
//background-size: cover
//right: -20px !important
//top: 2px
cursor: pointer
.file-upload-remove-img-btn
width: 16px
height: 16px
background: url('#{$static}/img/aui-icon-close.png') no-repeat center
cursor: pointer
//padding: px
.preview-container
position: relative
display: inline-block
.file-upload-remove-img-btn
position: absolute
top: 0
right: 0
textarea.description
font-size: 9pt
color: darkgray
resize: vertical
max-height: 68px
.complete
display: none

@ -2,6 +2,7 @@ from django.contrib.contenttypes.models import ContentType
from rest_framework.serializers import ModelSerializer
from .models import Location
from work_sell.models import ElFormat
class NestedLocationSerializer(ModelSerializer):
@ -64,6 +65,19 @@ class LocationSerializerFlat(ModelSerializer):
'parent')
class ElFormatSerializer(ModelSerializer):
# children = NestedLocationSerializerFlat(many=True)
# parent = NestedLocationSerializerFlat()
class Meta:
model = Location
fields = (
'id',
'name',
)
class ContentTypeSerializer(ModelSerializer):
class Meta:
model = ContentType

@ -85,18 +85,18 @@
<div style="margin-top: 45px" class="row">
<div class="col-lg-12">
<div class="simple-field">
<div class="header">Подобно опишите задание для /
<div class="header">Подробно опишите задание для /
<span class="select-text" id="spec-value"></span>
</div>
<i class="fa fa-question-circle-o" aria-hidden="true" title=""></i>
<span class="required">Обязательно</span>
<textarea class="description" rows="6" placeholder=
<textarea name="{{ form.description.html_name }}" class="description" rows="6" placeholder=
" Пример №1
Разработать архиьектурные решения для жилого дома на основании эскизной проработки
Пример №2
Разработать проект по електроснабжению и освещению гаража"></textarea>
Разработать проект по електроснабжению и освещению гаража">{{ form.description.value }}</textarea>
</div>
<div class="documentsChat mod" id="fileUploadContainer">

@ -74,6 +74,20 @@ $static: '/static'
background-size: cover
background: url('#{$static}/img/listMain.png') no-repeat -48px 0
.icon_tml span
content: ''
position: absolute
width: 27px
height: 24px
//left: -35px
top: 0
background: url('#{$static}/img/list4.png') no-repeat center !important
background-size: cover !important
.icon_tml:hover span
background: url('#{$static}/img/list4tml.png') no-repeat center !important
background-size: cover !important
.icon_tm1:hover span
width: 26px
background: url('#{$static}/img/listMain2.png') no-repeat left !important
@ -92,6 +106,42 @@ $static: '/static'
background-size: cover
background-position: -49px 0 !important
.rating
width: 46px
height: 46px
float: right
border-radius: 100%
background-color: #4D4D4D
margin: 15px 0 0 10px
position: relative
.ratingInset
width: 46px
height: 46px
border-radius: 100%
background-color: #FF0027
position: absolute
/*left:-1.859px;*/
/*bottom: 3px;*/
clip: rect(0, 22px, 50px, 0)
transform: rotate(-90deg)
.iconRating
width: 100%
height: 100%
position: absolute
left: 0
top: 0
background: url('#{$static}/img/button12.png') no-repeat center
.ratingPer
color: #ff2c2c
font-size: 18px
font-family: 'pfdintextcomppro-regular', sans-serif
float: right
margin: 28px 0 0 9px
cursor: pointer
.mainMenu li
&:last-child
padding-right: 0
@ -111,6 +161,15 @@ $static: '/static'
&.icon_tm3.active span
background: url('#{$static}/img/listMain2.png') no-repeat right !important
li.officeList.icon_tml > a > p
display: inline-block
padding: 5px 7px 3px 7px
background: #ff0000
border-radius: 35px
position: absolute
right: -34px
top: -4px
.changeBlock
width: 485px
overflow: hidden

@ -247,43 +247,25 @@
</div>
</div>
<div id="tab12" class="tab-pane fade">
{% if contractor.pk == request.user.pk %}
<div class="col-lg-9">
<p class="addWork">
<a href="#" data-toggle="modal" data-target="#worksell-modal">Добавить проект</a>
<a href="{% url 'work_sell:create'%}">Добавить проект</a>
</p>
</div>
<div id="worksell-modal" class="modal fade">
<div class="modal-dialog" style="width: 900px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title">Добавить готовую работу</h4>
</div>
{% include 'worksell_create_form.html' %}
</div>
</div>
</div>
{# <div id="worksell-modal" class="modal fade">#}
{# <div class="modal-dialog" style="width: 900px;">#}
{# <div class="modal-content">#}
{# <div class="modal-header">#}
{# <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>#}
{# <h4 class="modal-title">Добавить готовую работу</h4>#}
{# </div>#}
{##}
{# {% include 'worksell_create_form.html' %}#}
{# </div>#}
{# </div>#}
{# </div>#}
{% endif %}
<div class="galleryWork2 disTab -work-sells-container">
@ -817,7 +799,7 @@
data: dataSerializer,
dataType: 'json',
success: function (data) {
console.log(data);
consoCoole.log(data);
if (data.status == 'ok') {
$("#resume-text-out").html(data.text);
$("#resume-text-edit").modal('hide');

@ -8,9 +8,12 @@ module.exports = {
// context: path.join(__dirname, "static", "js"),
entry: {
// user: "./user",
// projects
create_project: "./assets/js/src/customer_project_create.js",
init_customer_project_create: './assets/js/src/init_customer_project_create.js'
init_customer_project_create: './assets/js/src/init_customer_project_create.js',
//worksell
create_worksell: "./assets/js/src/create_worksell.js",
init_create_worksell: './assets/js/src/init_create_worksell.js',
},

@ -1,7 +1,8 @@
from django.contrib import admin
from .models import WorkSell, WorkSellPhoto, Picture
from .models import WorkSell, WorkSellPhoto, Picture, ElFormat
admin.site.register(WorkSell)
admin.site.register(ElFormat)
admin.site.register(Picture)
admin.site.register(WorkSellPhoto)

@ -20,26 +20,26 @@ class ContractorWorkSellTrashForm(forms.Form):
class WorkSellForm(forms.ModelForm):
# Define a form field manually for a reverse model vield:
photos = forms.ModelMultipleChoiceField(
queryset=WorkSellPhoto.objects.none(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
live_images = forms.ModelMultipleChoiceField(
queryset=LiveImageUpload.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=False,
)
building_classification = TreeNodeChoiceField(
BuildingClassfication.objects.exclude(name='_root'),
widget=forms.Select(attrs={
'class': 'selectpicker'
}),
required=False,
level_indicator='',
)
# photos = forms.ModelMultipleChoiceField(
# queryset=WorkSellPhoto.objects.none(),
# widget=forms.CheckboxSelectMultiple,
# required=False,
# )
#
# live_images = forms.ModelMultipleChoiceField(
# queryset=LiveImageUpload.objects.all(),
# widget=forms.CheckboxSelectMultiple,
# required=False,
# )
#
# building_classification = TreeNodeChoiceField(
# BuildingClassfication.objects.exclude(name='_root'),
# widget=forms.Select(attrs={
# 'class': 'selectpicker'
# }),
# required=False,
# level_indicator='',
# )
class Meta:
model = WorkSell
@ -48,28 +48,45 @@ class WorkSellForm(forms.ModelForm):
'building_classification',
'construction_type',
'specialization',
'specializations',
'contractor',
'location',
'budget',
'currency',
'description',
'el_format',
'name',
'term',
'term_type',
'work_type',
)
widgets = {
'construction_type': forms.Select(attrs={'class': 'selectpicker'}),
'currency': forms.Select(attrs={'class': 'selectpicker'}),
'term_type': forms.Select(attrs={'class': 'selectpicker'}),
'work_type': forms.Select(attrs={'class': 'selectpicker -project-work-type-select-field'}),
}
# widgets = {
# 'construction_type': forms.Select(attrs={'class': 'selectpicker'}),
# 'currency': forms.Select(attrs={'class': 'selectpicker'}),
# 'term_type': forms.Select(attrs={'class': 'selectpicker'}),
# 'work_type': forms.Select(attrs={'class': 'selectpicker -project-work-type-select-field'}),
# }
# def clean(self):
# print("CLEAN", self.cleaned_data)
# data = self.cleaned_data.get('specialization')
# print("before data = ", data)
# # print('spec = ', data.split(','))
# # self.cleaned_data['specialization'] = data.split(',')
# super().clean()
# def clean_specialization(self):
# data = self.cleaned_data['specialization']
# print("before data = ", data)
# data = data.split(',')
# print("after data = ", data)
# return data
def __init__(self, *args, **kwargs):
# self.request = kwargs.pop('request')
self.request = kwargs.pop('request')
super().__init__(*args, **kwargs)
self.fields['photos'].queryset = self.instance.photos.all()
# self.fields['photos'].queryset = self.instance.photos.all()
class WorkSellFilterForm(forms.ModelForm):

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-12-06 21:34
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('work_sell', '0019_auto_20161201_2003'),
]
operations = [
migrations.CreateModel(
name='ElFormat',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32)),
],
options={
'verbose_name': 'Формат электронной версии',
},
),
migrations.AddField(
model_name='worksell',
name='el_format',
field=models.ManyToManyField(blank=True, related_name='work_sell', to='work_sell.ElFormat'),
),
]

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-12-07 09:10
from __future__ import unicode_literals
from django.db import migrations, models
import mptt.fields
class Migration(migrations.Migration):
dependencies = [
('specializations', '0004_auto_20161014_2344'),
('work_sell', '0020_auto_20161207_0034'),
]
operations = [
migrations.AddField(
model_name='worksell',
name='specializations',
field=mptt.fields.TreeManyToManyField(blank=True, to='specializations.Specialization'),
),
migrations.AlterField(
model_name='worksell',
name='work_type',
field=models.IntegerField(blank=True, choices=[(403, 'Проектирование777'), (87, 'Техническое сопровождение666')], default=1),
),
]

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-12-07 09:13
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import mptt.fields
class Migration(migrations.Migration):
dependencies = [
('work_sell', '0021_auto_20161207_1210'),
]
operations = [
migrations.AlterField(
model_name='worksell',
name='building_classification',
field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_sells', to='projects.BuildingClassfication'),
),
migrations.AlterField(
model_name='worksell',
name='construction_type',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_sells', to='projects.ConstructionType'),
),
migrations.AlterField(
model_name='worksell',
name='location',
field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_sells', to='common.Location'),
),
migrations.AlterField(
model_name='worksell',
name='specialization',
field=mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='work_sells', to='specializations.Specialization'),
),
]

@ -1,5 +1,5 @@
from django.db import models
from mptt.models import TreeForeignKey
from mptt.models import TreeForeignKey, TreeManyToManyField
from sorl.thumbnail import ImageField
from projects.models import BuildingClassfication, ConstructionType, TERM_TYPES, CURRENCIES, Project
@ -11,20 +11,23 @@ class WorkSell(models.Model):
# TODO: Add consistency ("work_sell" vs "worksell"):
budget = models.DecimalField(max_digits=10, decimal_places=0, default=0, null=True, blank=True)
building_classification = TreeForeignKey(BuildingClassfication, related_name='worksells', null=True, blank=True)
construction_type = models.ForeignKey(ConstructionType, related_name='worksells', null=True, blank=True)
building_classification = TreeForeignKey(BuildingClassfication, related_name='work_sells', null=True, blank=True)
construction_type = models.ForeignKey(ConstructionType, related_name='work_sells', null=True, blank=True)
contractor = models.ForeignKey(User, related_name='work_sell', null=True,
blank=True) # TODO: Pluralize related name
created = models.DateTimeField(auto_now_add=True)
currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES, null=True, blank=True)
description = models.TextField(blank=True)
location = TreeForeignKey('common.Location', related_name='worksells', null=True, blank=True)
el_format = models.ManyToManyField('ElFormat', related_name='work_sell', blank=True)
location = TreeForeignKey('common.Location', related_name='work_sells', null=True, blank=True)
name = models.CharField(max_length=255)
specialization = TreeForeignKey(Specialization, related_name='worksells', null=True, blank=True)
# deprecated
specialization = TreeForeignKey(Specialization, related_name='work_sells', null=True, blank=True)
specializations = TreeManyToManyField(Specialization, blank=True)
team = models.ForeignKey(Team, related_name='work_sells', null=True, blank=True)
term = models.IntegerField(default=0, null=True, blank=True)
term_type = models.CharField(max_length=20, choices=TERM_TYPES, default='hour', null=True, blank=True)
work_type = models.IntegerField(default=1, choices=Project.WORK_TYPES)
work_type = models.IntegerField(default=1, choices=Project.WORK_TYPES, blank=True)
def __str__(self):
return self.name
@ -80,3 +83,13 @@ class Picture(models.Model):
def delete(self, *args, **kwargs):
self.file.delete(False)
super().delete(*args, **kwargs)
class ElFormat(models.Model):
name = models.CharField(max_length=32)
def __str__(self):
return self.name
class Meta:
verbose_name = 'Формат электронной версии'

@ -1,55 +1,224 @@
{% extends 'partials/base.html' %}
{% block content %}
<form method="post" enctype="multipart/form-data">{% csrf_token %}
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input type="file" name="files[]" multiple>
</span>
</div>
<input type="submit" value="Save12"/>
</form>
{% load staticfiles %}
{% load sass_tags %}
{% load thumbnail %}
{% block old_css %}{% endblock %}
{% block head_css %}
<link rel='stylesheet' href='{% static "css/font-awesome.min.css" %}'>
<link rel='stylesheet' href='{% sass_src "sass/main.sass" %}'>
<link rel='stylesheet' href='{% sass_src "sass/components/custom-components.sass" %}'>
<link rel='stylesheet' href='{% sass_src "lib/proekton-components/sass/components.sass" %}'>
{# <style>#}
{# .-live-image-upload-container .-position-relative-parent {#}
{# position: relative#}
{# }#}
{##}
{# .-live-image-upload-container .-image-delete,#}
{# .-live-image-upload-container .-live-image-delete {#}
{# position: absolute;#}
{# top: 0;#}
{# right: 0;#}
{# background-color: white;#}
{# }#}
{# </style>#}
{% endblock %}
{% block js_block %}
<script type="text/javascript">
{% block content %}
{% include 'partials/modals/project_work_type_suggestion.html' %}
{% include 'partials/header.html' %}
<div class="container main-scope">
<div class="row title-scope">
<div class="col-lg-12">
{# <div class="title-scope">#}
<h1>Добавить готовую работу</h1>
{# </div>#}
</div>
</div>
<div class="row main-content">
<div class="col-lg-12">
<form action="{% url 'work_sell:create' %}" method="POST"
enctype="multipart/form-data" novalidate>
{% csrf_token %}
<div class="row">
<div class="col-lg-9">
<div class="simple-field">
<div class="header">Название проекта</div>
<i class="fa fa-question-circle-o" aria-hidden="true"></i>
<span class="required">Обязательно</span>
<input value="{{ form.name.value }}" name="{{ form.name.html_name }}"
class="simple-input italic"
placeholder="Пример: Дизайн проект квартиры, Армирование фундамента, Конструкции перекрытия и т.д."
autocomplete="off"
required>
</div>
</div>
<div class="col-lg-3">
<div class="header ">Стоимость готового проекта
<i class="fa fa-question-circle-o" aria-hidden="true" title=""></i>
</div>
<input name="{{ form.budget.html_name }}" class="simple-input icon-rub js-number-format"
placeholder="Введите сумму"
value="{{ form.budget.value }}"
autocomplete="off">
</div>
</div>
<div class="row vertical-child mod-align-bottom">
<div class="col-lg-9">
<div class="" id="select-box-1"></div>
</div>
<div class="col-lg-3">
<div href="#" onclick="return false" data-toggle="modal"
data-target="#projectWorkTypeSuggestionModal"
class="btn btn-simple btn-plus">Нет нужной специальности хочу добавить
</div>
</div>
</div>
<div class="row">
<div class="col-lg-3">
<div class="vertical-child" id="select-box-2">
</div>
</div>
<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">
<div class="vertical-child" id="select-box-5">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 vertical-child">
<div class="selected-container horizontal" id="selected-spec">
<input type="hidden" name="{{ form.specializations.html_name }}"
value="{{ form.specializations.value }}">
</div>
</div>
</div>
<div style="margin-top: 45px" class="row">
<div class="col-lg-12">
<div class="simple-field">
<div class="header">Подробно опишите проект
<span class="select-text" id="spec-value"></span>
</div>
<i class="fa fa-question-circle-o" aria-hidden="true" title=""></i>
<span class="required">Обязательно</span>
<textarea name="{{ form.description.html_name }}" class="description" rows="8">{{ form.description.value }}</textarea>
$(function(){
$.ajax({
url : '/work_sell/test/',
</div>
<div class="documentsChat mod" id="fileUploadContainer">
<div style="display: inline-block;vertical-align: middle;">
<div style="display: inline-block;vertical-align: inherit;"
class="upload-new paper-clip">
<p id="fileUploadAddBtn" style="margin: 0">прикрепить файл</p>
</div>
<span style="display: inline-block;vertical-align: inherit;">ДО 100 ФАЙЛОВ</span>
</div>
success:function(data){
alert(data);
console.log(data);
}
});
});
<div class="row list-new-new" style="margin-top: 10px">
<div class="col-lg-3 file-upload-widget" style="display: none">
<input type="file" name="new_files" class="file-upload-input"
style="position: absolute; top: -1000px; left: -1000px">
<div class="preview-container">
<div class="file-upload-remove-img-btn"></div>
<img class="preview" src="#" alt="your image"/>
<textarea rows="2" data-limit-rows="true" class="description">
{# $(function(){#}
{# var files;#}
{# $('input[type=file]').on('change', prepareUpload);#}
{# $('form').on('submit', uploadFiles);#}
{##}
{# function uploadFiles(e){#}
{# console.log('submit');#}
{# e.stopPropagation();#}
{# e.preventDefault();#}
{# var data = new FormData();#}
{# $.each(files, function(k,v){#}
{# console.log(k);#}
{# console.log(v);#}
{# data.append(k, v);#}
{# });#}
{# console.log(data);#}
{# }#}
{# function prepareUpload(e){#}
{# files = e.target.files;#}
{# }#}
{##}
{# });#}
</textarea>
</div>
<span style="display:none" class="file-upload-label"></span>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-3">
<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.building_classification.html_name }}"
value="{{ form.building_classification.value }}">
</div>
</div>
<div class="col-lg-3">
<div class="vertical-child" id="sb-construction-type">
</div>
<div class="selected-container" id="selected-construction-type">
<input type="hidden"
name="{{ form.construction_type.html_name }}"
value="{{ form.construction_type.value }}">
</div>
</div>
<div class="col-lg-3">
<div class="vertical-child" id="sb-location-1"></div>
<div class="vertical-child" id="sb-location-2"></div>
<div class="vertical-child" id="sb-location-3"></div>
<div class="selected-container" id="selected-location">
<input type="hidden"
name="{{ form.location.html_name }}"
value="{{ form.location.value }}">
</div>
</div>
<div class="col-lg-3">
<div class="vertical-child" id="sb-format"></div>
<div class="selected-container" id="selected-format">
<input type="hidden"
name="{{ form.el_format.html_name }}"
value="{{ form.el_format.value }}">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="separator">
<div class="border"></div>
</div>
</div>
</div>
<div class="row top-line">
<div class="col-lg-3" style="text-align: center">
<div class="header">&nbsp;</div>
<input style="width: 100%" type="submit" class="btn btn-simple"
value="РАЗМЕСТИТЬ ЗАКАЗ">
</div>
<div class="col-lg-3 col-lg-offset-6" style="text-align: center">
<div class="header">&nbsp;</div>
<input style="width: 100%" type="button" class="btn btn-simple"
value="ПРЕДВАРИТЕЛЬНЫЙ ПРОСМОТР">
</div>
</div>
</form>
</div>
</div>
{% include 'partials/footer.html' %}
</div>
{% endblock %}
{% block old_js %}
<script src='{% static "lib/jquery.fileupload/js/vendor/jquery.ui.widget.js" %}'></script>
<script src='{% static "lib/jquery.fileupload/js/jquery.iframe-transport.js" %}'></script>
<script src='{% static "lib/jquery.fileupload/js/jquery.fileupload.js" %}'></script>
<script src='{% static "lib/jquery.fileupload/js/jquery.fileupload-process.js" %}'></script>
<script src='{% static "lib/lodash/lodash.js" %}'></script>
<script src='{% static "my-libs.js" %}'></script>
{% endblock %}
{% block js_block %}
<script src='{% static "js/bootstrap.min.js" %}'></script>
<script src='{% static "js/build/init_create_worksell.js" %}'></script>
<script src='{% static "js/build/create_worksell.js" %}'></script>
<script src='{% static "js/jquery.mask.min.js" %}'></script>
<script>
$(function () {
$('.js-number-format').mask('0000000000');
})
</script>
{% endblock %}

@ -5,7 +5,8 @@ from .views import (
WorkSellUpdateView,
WorkSellDeleteView,
UploadView,
work_sell_create,
# work_sell_create,
WorkSellCreateView,
BasicCreateView,
PictureCreateView,
ContractorWorkSellTrashView,
@ -17,12 +18,12 @@ app_name = 'work_sell'
urlpatterns = [
urls.url(r'^$', WorkSellFilterView.as_view(), name='list'),
# urls.url(r'^create/$', WorkSellCreateView.as_view(), name='create'),
urls.url(r'^create/$', WorkSellCreateView.as_view(), name='create'),
urls.url(r'^upload/$', UploadView.as_view(), name='upload'),
urls.url(r'^(?P<pk>\d+)/edit/$', WorkSellUpdateView.as_view(), name='edit'),
urls.url(r'^(?P<pk>\d+)/delete/$', WorkSellDeleteView.as_view(), name='delete'),
urls.url(r'^(?P<pk>\d+)/trash/$', ContractorWorkSellTrashView.as_view(), name='contractor-worksell-trash'),
urls.url(r'^create/$', work_sell_create, name='create'),
# urls.url(r'^create/$', work_sell_create, name='create'),
urls.url(r'^basic/$', BasicCreateView.as_view(), name='upload-basic'),
urls.url(r'^new/$', PictureCreateView.as_view(), name='upload-new'),
urls.url(r'^(?P<pk>\d+)/$', WorkSellDetail.as_view(), name='detail'),

@ -12,13 +12,15 @@ from django.contrib import messages
from django.db.models import Q
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.core.exceptions import PermissionDenied
from django.http import JsonResponse, HttpResponse, HttpResponseForbidden
from django.core.files.base import ContentFile
from django.views.generic import ListView, DetailView, CreateView, View, \
UpdateView, DeleteView, TemplateView
from projects.models import BuildingClassfication, ConstructionType
from .models import WorkSell, Picture, WorkSellPhoto
from projects.forms import ProjectWorkTypeSuggestionForm
from .models import WorkSell, Picture, WorkSellPhoto, WorkSellPhoto
from .forms import WorkSellForm, WorkSellFilterForm, ContractorWorkSellTrashForm
from .serialize import serialize
from .response import JSONResponse, response_mimetype
@ -143,33 +145,83 @@ class WorkSellDetail(DetailView):
return context
def work_sell_create(request):
if request.is_ajax():
form = WorkSellForm(data=request.POST)
# def work_sell_create(request):
# if request.is_ajax():
# form = WorkSellForm(data=request.POST)
# if form.is_valid():
# instance = form.save(commit=False)
# # import code; code.interact(local=dict(globals(), **locals()))
# instance.save()
# form.save_m2m()
# images_ids = request.POST.get('images-ids').split(';')[:-1]
# for pk in images_ids:
# picture = Picture.objects.get(pk=pk)
# temp_file = ContentFile(picture.file.read())
# temp_file.name = picture.file.name
# w_photo = WorkSellPhoto()
# w_photo.img = temp_file
# w_photo.worksell = instance
# w_photo.save()
# data = {'status': 'ok'}
# else:
# data = {'status': 'no', 'form_errors': form.errors}
# return HttpResponse(json.dumps(data), content_type='application/json')
class WorkSellCreateView(BaseMixin, View):
model = WorkSell
form_class = WorkSellForm
work_type_suggestion_form = ProjectWorkTypeSuggestionForm
template_name = 'worksell_create.html'
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated() and request.user.is_contractor():
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)
work_type_suggestion_form = self.work_type_suggestion_form(request=request, prefix='work_type_suggestion')
context.update({
'form': form,
'work_type_suggestion_form': work_type_suggestion_form,
})
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below
# TODO: fix it on front
request.POST.setlist('specializations', request.POST.get('specializations').split(','))
request.POST.setlist('el_format', request.POST.get('el_format').split(','))
print("POST before = ", request.POST)
if form.is_valid():
instance = form.save(commit=False)
# import code; code.interact(local=dict(globals(), **locals()))
instance.save()
work_sell = form.save(commit=False)
work_sell.contractor = request.user
work_sell.save()
form.save_m2m()
images_ids = request.POST.get('images-ids').split(';')[:-1]
for pk in images_ids:
picture = Picture.objects.get(pk=pk)
temp_file = ContentFile(picture.file.read())
temp_file.name = picture.file.name
w_photo = WorkSellPhoto()
w_photo.img = temp_file
w_photo.worksell = instance
w_photo.save()
data = {'status': 'ok'}
else:
data = {'status': 'no', 'form_errors': form.errors}
return HttpResponse(json.dumps(data), content_type='application/json')
for file in request.FILES.getlist('new_files'):
WorkSellPhoto.objects.create(img=file, worksell=work_sell)
class WorkSellCreateView(CreateView):
model = WorkSell
form_class = WorkSellForm
template_name = 'worksell_create.html'
messages.info(request, 'Работа успешно создана')
redirect_to = reverse('work_sell:detail', kwargs={'pk': work_sell.pk})
return redirect(redirect_to)
else:
if form.errors:
messages.info(request, (
'<p>Произошла ошибка (form)</p>'
'<pre>{form}</pre>'
).format(form=pformat(form.errors)))
context = self.get_context_data(**kwargs)
context.update({'form': form})
# context.update({'photos': WorkSellPhoto.objects.filter(worksell__id=)})
return render(request, self.template_name, context)
class WorkSellUpdateView(UpdateView):

Loading…
Cancel
Save