|
|
// Constants -----------------------------------------------
|
|
|
|
|
|
|
|
|
var API_PAGE_SIZE = 100;
|
|
|
var LIVE_IMAGE_UPLOAD_URL = '/common/live-image-upload/create/';
|
|
|
var STUB_IMAGE_URL = '/static/img/profile.jpg';
|
|
|
var DEFAULT_WORK_TYPE = 403;
|
|
|
|
|
|
|
|
|
// Plugins init --------------------------------------------
|
|
|
|
|
|
|
|
|
$('.datepicker').datepicker({
|
|
|
changeMonth: true,
|
|
|
changeYear: true,
|
|
|
})
|
|
|
|
|
|
$('[data-tooltip]').tooltip({
|
|
|
container: 'body', // Remove unwanted side-effects
|
|
|
trigger : 'hover', // Disable tooltip remaining visible after a click
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Specialization select -----------------------------------
|
|
|
|
|
|
|
|
|
;(function() {
|
|
|
var specSelectOptions = {
|
|
|
language: 'ru',
|
|
|
//minimumInputLength: 1, // Commented out to immediately load remote data
|
|
|
placeholder: 'Выберите специализацию', // Required by `allowClear`
|
|
|
allowClear: true,
|
|
|
|
|
|
ajax: {
|
|
|
url: null,
|
|
|
dataType: 'json',
|
|
|
quietMillis: 250,
|
|
|
cache: true,
|
|
|
|
|
|
data: function(term, page) {
|
|
|
return {
|
|
|
name__icontains: term,
|
|
|
page: page,
|
|
|
}
|
|
|
},
|
|
|
|
|
|
results: function(data, page) {
|
|
|
return {
|
|
|
results: _.map(function(item) {
|
|
|
return {
|
|
|
id: item.id,
|
|
|
text: _.repeat(item.level-1, ' ') + item.name,
|
|
|
origItem: item,
|
|
|
}
|
|
|
}, data.results),
|
|
|
|
|
|
more: (page * API_PAGE_SIZE) < data.count,
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
|
|
|
|
|
|
$('.-spec-work-type-combo-container').each(function(i, container) {
|
|
|
var $container = $(container)
|
|
|
var $specSelects = $container.find('.-spec-select')
|
|
|
var $chosenSpecId = $container.find('.-chosen-spec-id').first()
|
|
|
|
|
|
var $specSelect1 = $container.find('.-spec-select-level-1').first()
|
|
|
|
|
|
window.select = $specSelect1
|
|
|
|
|
|
var $specSelect2 = $container.find('.-spec-select-level-2').first()
|
|
|
var $specSelect3 = $container.find('.-spec-select-level-3').first()
|
|
|
var $specSelect4 = $container.find('.-spec-select-level-4').first()
|
|
|
var specSelects = [$specSelect1, $specSelect2, $specSelect3, $specSelect4]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var $workTypeSelect = $container.find('.-project-work-type-select-field').first()
|
|
|
|
|
|
if (!_.isEmpty($workTypeSelect)) {
|
|
|
var workTypeId = Number($workTypeSelect.find('option:selected').first().val()) || DEFAULT_WORK_TYPE;
|
|
|
|
|
|
$workTypeSelect.on('change', function($evt) {
|
|
|
var $that = $(this)
|
|
|
var workTypeId = Number($that.val())
|
|
|
|
|
|
reinitSpecializationsByWorkType(specSelects, workTypeId).then(function(rootSpec) {
|
|
|
updateSpecializationWidgets(workTypeId, $container, $chosenSpecId, specSelects)
|
|
|
})
|
|
|
})
|
|
|
} else {
|
|
|
var $workTypeRadios = $container.find('.-project-work-type-radios-container').first().find('input[type=radio]')
|
|
|
|
|
|
if (!_.isEmpty($workTypeRadios)) {
|
|
|
var workTypeId = Number($workTypeRadios.filter(':checked').val()) || DEFAULT_WORK_TYPE;
|
|
|
|
|
|
$workTypeRadios.on('change', function($evt) {
|
|
|
var $that = $(this)
|
|
|
var workTypeId = Number($that.val())
|
|
|
|
|
|
reinitSpecializationsByWorkType(specSelects, workTypeId).then(function(rootSpec) {
|
|
|
updateSpecializationWidgets(workTypeId, $container, $chosenSpecId, specSelects)
|
|
|
})
|
|
|
})
|
|
|
} else {
|
|
|
var workTypeId = DEFAULT_WORK_TYPE;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
reinitSpecializationsByWorkType(specSelects, workTypeId).then(function(rootSpec_) {
|
|
|
updateSpecializationWidgets(null, $container, $chosenSpecId, specSelects)
|
|
|
})
|
|
|
|
|
|
|
|
|
var chosenSpecId = $chosenSpecId.val()
|
|
|
|
|
|
if (chosenSpecId)
|
|
|
updateSpecializationWidgets(chosenSpecId, $container, $chosenSpecId, specSelects)
|
|
|
|
|
|
$specSelects.on('change', function($evt) {
|
|
|
var specId = $evt.added ? $evt.added.id : null
|
|
|
updateSpecializationWidgets(specId, $container, $chosenSpecId, specSelects)
|
|
|
})
|
|
|
})
|
|
|
|
|
|
|
|
|
function reinitSpecializationsByWorkType(specSelects, workTypeId) {
|
|
|
return $.get('/api/specializations/?parent__id='+workTypeId)
|
|
|
.then(function(res) {
|
|
|
var rootSpecs = res.results;
|
|
|
console.log('workTypeId', workTypeId)
|
|
|
if (workTypeId == null) {
|
|
|
var url = '/api/specializations/';
|
|
|
// var specId = null
|
|
|
} else {
|
|
|
var specializations = {};
|
|
|
$.each(rootSpecs, function(key, spec) {
|
|
|
specializations[spec.id] = spec;
|
|
|
});
|
|
|
// var rootSpec = specializations[workTypeId];
|
|
|
var rootSpec = rootSpecs[0].parent;
|
|
|
console.log('rootSpec', rootSpec);
|
|
|
// var specId = rootSpec.id
|
|
|
var url = format('/api/specializations/?lft__gte=%s&rght__lte=%s', rootSpec.lft, rootSpec.rght)
|
|
|
}
|
|
|
|
|
|
specSelects[0].select2(_.merge(specSelectOptions, {ajax: {url: url}}));
|
|
|
specSelects[1].select2(_.merge(specSelectOptions, {ajax: {url: null}}));
|
|
|
specSelects[2].select2(_.merge(specSelectOptions, {ajax: {url: null}}));
|
|
|
specSelects[3].select2(_.merge(specSelectOptions, {ajax: {url: null}}));
|
|
|
|
|
|
|
|
|
// TODO: Hardcoded:
|
|
|
|
|
|
// specSelects[0].select2('container').closest('.-single-spec-select').css('display', workTypeId === 2 ? 'none' : 'block');
|
|
|
specSelects[1].select2('container').closest('.-single-spec-select').find('.-dynamic-label').first().text(workTypeId === 2 ? 'Перечень услуг' : 'Стадия проекта');
|
|
|
|
|
|
|
|
|
return rootSpec
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
function updateSpecializationWidgets(specId, $container, $chosenSpecId, specSelects) {
|
|
|
return getSpecializationTree(specId).then(function(specs) {
|
|
|
var spec = specs.spec
|
|
|
|
|
|
specSelects[1].select2(_.merge(specSelectOptions, {ajax: {url: specs.urlLevel2}}));
|
|
|
specSelects[2].select2(_.merge(specSelectOptions, {ajax: {url: specs.urlLevel3}}));
|
|
|
specSelects[3].select2(_.merge(specSelectOptions, {ajax: {url: specs.urlLevel4}}));
|
|
|
|
|
|
var specLevel1 = specs.specLevel1;
|
|
|
var specLevel2 = specs.specLevel2;
|
|
|
var specLevel3 = specs.specLevel3;
|
|
|
var specLevel4 = specs.specLevel4;
|
|
|
|
|
|
specSelects[0].select2('data', specLevel1 ? {id: specLevel1.id, text: specLevel1.name, origItem: specLevel1} : null)
|
|
|
specSelects[1].select2('data', specLevel2 ? {id: specLevel2.id, text: specLevel2.name, origItem: specLevel2} : null)
|
|
|
specSelects[2].select2('data', specLevel3 ? {id: specLevel3.id, text: specLevel3.name, origItem: specLevel3} : null)
|
|
|
specSelects[3].select2('data', specLevel4 ? {id: specLevel4.id, text: specLevel4.name, origItem: specLevel4} : null)
|
|
|
|
|
|
$chosenSpecId.val(specId)
|
|
|
|
|
|
specSelects[1].select2('enable', Boolean(specLevel1 && !_.isEmpty(specLevel1.children)))
|
|
|
specSelects[2].select2('enable', Boolean(specLevel2 && !_.isEmpty(specLevel2.children)))
|
|
|
specSelects[3].select2('enable', Boolean(specLevel3 && !_.isEmpty(specLevel3.children)))
|
|
|
|
|
|
specializationTreeHasLevels(specId).then(function(haveLevels) {
|
|
|
specSelects[1].select2('container').closest('.-single-spec-select').css('display', haveLevels.level2 ? 'block' : 'none')
|
|
|
specSelects[2].select2('container').closest('.-single-spec-select').css('display', haveLevels.level3 ? 'block' : 'none')
|
|
|
specSelects[3].select2('container').closest('.-single-spec-select').css('display', haveLevels.level4 ? 'block' : 'none')
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Specialization select (simple) -------------------------------
|
|
|
|
|
|
|
|
|
;(function() {
|
|
|
var simpleSpecSelectsOptions = {
|
|
|
language: 'ru',
|
|
|
placeholder: 'Выберите специализацию', // Required by `allowClear`
|
|
|
allowClear: true,
|
|
|
|
|
|
ajax: {
|
|
|
url: '/api/specializations/',
|
|
|
dataType: 'json',
|
|
|
quietMillis: 250,
|
|
|
cache: true,
|
|
|
|
|
|
data: function(term, page) {
|
|
|
return {
|
|
|
name__icontains: term,
|
|
|
page: page,
|
|
|
}
|
|
|
},
|
|
|
|
|
|
results: function(data, page) {
|
|
|
return {
|
|
|
results: _.map(function(item) {
|
|
|
return {
|
|
|
id: item.id,
|
|
|
text: _.repeat(item.level-1, ' ') + item.name,
|
|
|
origItem: item,
|
|
|
}
|
|
|
}, data.results),
|
|
|
|
|
|
more: (page * API_PAGE_SIZE) < data.count,
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
|
|
|
//initSelection: function(element, callback) {
|
|
|
// var id = $(element).val()
|
|
|
//
|
|
|
// if (id !== '') {
|
|
|
// $.ajax({url: '/api/specializations/' + id + '/', method: 'GET', dataType: 'json'})
|
|
|
// .then(function(data) {callback(data)})
|
|
|
// }
|
|
|
//}
|
|
|
}
|
|
|
|
|
|
var $simpleSpecContainer = $('#simpleSpecContainer')
|
|
|
var $emptySimpleSpecWidget = $simpleSpecContainer.find('.-simple-spec-widget').first()
|
|
|
|
|
|
$simpleSpecContainer.find('.-chosen-simple-spec-id').each(function(i, el) {
|
|
|
var $el = $(el)
|
|
|
var specId = Number($el.val())
|
|
|
|
|
|
if (specId)
|
|
|
initSimpleSpecSelect2($el.closest('.-simple-spec-widget').find('.-simple-spec-select').first(), specId)
|
|
|
})
|
|
|
|
|
|
$('#addSpec').on('click', function($evt) {
|
|
|
var $newSimpleSpecWidget = $emptySimpleSpecWidget.clone()
|
|
|
$simpleSpecContainer.append($newSimpleSpecWidget)
|
|
|
var $newSimpleSpecSelect = $newSimpleSpecWidget.find('.-simple-spec-select').first()
|
|
|
|
|
|
initSimpleSpecSelect2($newSimpleSpecSelect).then(function() {
|
|
|
$newSimpleSpecWidget.css('display', 'block')
|
|
|
})
|
|
|
})
|
|
|
|
|
|
|
|
|
$simpleSpecContainer.on('change', '.-simple-spec-select', function($evt) {
|
|
|
if ($evt.added)
|
|
|
$(this).parent().children('.-chosen-simple-spec-id').first().val($evt.added.id)
|
|
|
})
|
|
|
|
|
|
|
|
|
function initSimpleSpecSelect2($select, specId) {
|
|
|
$select.select2(simpleSpecSelectsOptions)
|
|
|
|
|
|
if (specId) {
|
|
|
return $.get(format('/api/specializations/%s/', specId))
|
|
|
.then(function(spec) {
|
|
|
$select.select2('data', {
|
|
|
id: spec.id,
|
|
|
text: _.repeat(spec.level-1, ' ') + spec.name,
|
|
|
origItem: spec,
|
|
|
})
|
|
|
})
|
|
|
} else {
|
|
|
return $.when()
|
|
|
}
|
|
|
}
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Team invitation contractor select -------------------------------
|
|
|
|
|
|
|
|
|
;(function() {
|
|
|
var contractorSelectOptions = {
|
|
|
language: 'ru',
|
|
|
placeholder: 'Выберите пользователя', // Required by `allowClear`
|
|
|
allowClear: true,
|
|
|
|
|
|
ajax: {
|
|
|
url: '/api/users/',
|
|
|
dataType: 'json',
|
|
|
quietMillis: 250,
|
|
|
cache: true,
|
|
|
|
|
|
data: function(term, page) {
|
|
|
return {
|
|
|
username__icontains: term,
|
|
|
page: page,
|
|
|
is_contractor: 'true',
|
|
|
}
|
|
|
},
|
|
|
|
|
|
results: function(data, page) {
|
|
|
return {
|
|
|
results: _.map(function(item) {
|
|
|
return {
|
|
|
id: item.id,
|
|
|
text: format('%s (%s)', item.username, item.get_full_name),
|
|
|
origItem: item,
|
|
|
}
|
|
|
}, data.results),
|
|
|
|
|
|
more: (page * API_PAGE_SIZE) < data.count,
|
|
|
}
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
|
|
|
function initContractorSelect($select, excludeIds) {
|
|
|
contractorSelectOptions.ajax.url = format('%s?id__in!=%s', contractorSelectOptions.ajax.url, excludeIds.join(','))
|
|
|
return $select.select2(contractorSelectOptions)
|
|
|
}
|
|
|
|
|
|
window.initContractorSelect = initContractorSelect
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Order offer project select ---------------------------------------------
|
|
|
|
|
|
;(function() {
|
|
|
var projectSelectOptions = {
|
|
|
language: 'ru',
|
|
|
placeholder: 'Выберите проект', // Required by `allowClear`
|
|
|
allowClear: true,
|
|
|
}
|
|
|
|
|
|
function initProjectSelect($select, customerId, contractorId) {
|
|
|
var urlObj = new URI('/api/projects/')
|
|
|
|
|
|
urlObj.setQuery({
|
|
|
state: 'active',
|
|
|
customer: customerId,
|
|
|
order__contractor__isnull: true,
|
|
|
order__team__isnull: true,
|
|
|
x_no_contractor_answer: contractorId,
|
|
|
})
|
|
|
|
|
|
return $.get(urlObj.href()).then(function(res) {
|
|
|
var projects = res.results
|
|
|
|
|
|
$select.select2(_.merge(projectSelectOptions, {
|
|
|
data: _.map(function(project) {
|
|
|
return {
|
|
|
id: project.id,
|
|
|
//text: project.name,
|
|
|
text: format('%s (%s)', project.name, project.id), // Tmp
|
|
|
origItem: project,
|
|
|
}
|
|
|
}, projects),
|
|
|
}))
|
|
|
})
|
|
|
}
|
|
|
|
|
|
window.initProjectSelect = initProjectSelect
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Location select ----------------------------------------------
|
|
|
|
|
|
|
|
|
;(function() {
|
|
|
var $locationSelects = $('.-location-select')
|
|
|
|
|
|
var locationSelectOptions = {
|
|
|
language: 'ru',
|
|
|
placeholder: 'Выберите местоположение', // Required by `allowClear`
|
|
|
allowClear: true,
|
|
|
}
|
|
|
|
|
|
|
|
|
var $countrySelect = $('.-location-select-country')
|
|
|
var $regionSelect = $('.-location-select-region')
|
|
|
var $citySelect = $('.-location-select-city')
|
|
|
|
|
|
|
|
|
// Initialize:
|
|
|
|
|
|
getLocationTree(null).then(function(locs) {
|
|
|
$countrySelect.select2(_.merge(locationSelectOptions, {data: locs.countries}))
|
|
|
$regionSelect.select2(_.merge(locationSelectOptions, {data: locs.regions}))
|
|
|
$citySelect.select2(_.merge(locationSelectOptions, {data: locs.cities}))
|
|
|
|
|
|
var chosenLocId = $('#chosenLocationId').val()
|
|
|
|
|
|
if (chosenLocId)
|
|
|
updateLocationWidgets(chosenLocId)
|
|
|
})
|
|
|
|
|
|
|
|
|
$locationSelects.on('change', function($evt) {
|
|
|
updateLocationWidgets($evt.added ? $evt.added.id : null)
|
|
|
})
|
|
|
|
|
|
|
|
|
function updateLocationWidgets(locId) {
|
|
|
return getLocationTree(locId).then(function(locs) {
|
|
|
$countrySelect.select2({data: locs.countries})
|
|
|
$regionSelect.select2({data: locs.regions})
|
|
|
$citySelect.select2({data: locs.cities})
|
|
|
|
|
|
var loc = locs.location
|
|
|
|
|
|
if (loc && loc.level === 1) {
|
|
|
$countrySelect.select2('val', locs.country.id)
|
|
|
} else if (loc && loc.level === 2) {
|
|
|
$regionSelect.select2('val', locs.region.id)
|
|
|
$countrySelect.select2('val', locs.country.id)
|
|
|
} else if (loc && loc.level === 3) {
|
|
|
$citySelect.select2('val', locs.city.id)
|
|
|
$regionSelect.select2('val', locs.region.id)
|
|
|
$countrySelect.select2('val', locs.country.id)
|
|
|
}
|
|
|
|
|
|
if (loc)
|
|
|
$('#chosenLocationId').val(loc.id)
|
|
|
})
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
$('#realtyId').on('change', function($evt) {
|
|
|
var realtyId = Number($(this).val())
|
|
|
|
|
|
if (realtyId) {
|
|
|
loadRealtyDetails(realtyId).then(function(res) {
|
|
|
$('#realtyName').val(res.name)
|
|
|
$('#realtyBuildingClassificationId').val(res.building_classification.id).change()
|
|
|
$('#realtyConstructionTypeId').val(res.construction_type.id).change()
|
|
|
updateLocationWidgets(res.location.id)
|
|
|
})
|
|
|
} else {
|
|
|
$('#realtyName').val('')
|
|
|
$('#realtyBuildingClassificationId').val('').change()
|
|
|
$('#realtyConstructionTypeId').val('').change()
|
|
|
updateLocationWidgets(null)
|
|
|
}
|
|
|
})
|
|
|
|
|
|
function loadRealtyDetails(realtyId) {
|
|
|
return $.ajax({
|
|
|
url: '/api/realties/' + realtyId + '/',
|
|
|
method: 'GET',
|
|
|
dataType: 'json',
|
|
|
})
|
|
|
.then(function(res) {return res})
|
|
|
}
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// File uploading ---------------------------------------
|
|
|
|
|
|
// TODO: Add file number and overall size limit support
|
|
|
|
|
|
;(function() {
|
|
|
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 && 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()
|
|
|
})
|
|
|
|
|
|
$fileUploadContainer.on('click', '.existing-file-remove-btn', function($evt) {
|
|
|
var $btn = $(this)
|
|
|
$btn.closest('.existing-file-widget').remove()
|
|
|
})
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Project answer portfolio selection ----------------------
|
|
|
|
|
|
|
|
|
$('input[type="checkbox"].answer-portfolio-select').on('change', function($evt) {
|
|
|
var $that = $(this)
|
|
|
|
|
|
if ($('input[type="checkbox"].answer-portfolio-select:checked').length > 4) {
|
|
|
$that.prop('checked', false)
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var portfId = $that.val()
|
|
|
|
|
|
var $container = $('#answer-portfolio-photo-widget-container')
|
|
|
|
|
|
if ($that.prop('checked')) {
|
|
|
$.ajax({url: '/api/portfolios/' + portfId + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(portf) {
|
|
|
var photoUrl = portf.photos[0].img
|
|
|
var $newWidget = $container.find('.answer-portfolio-photo-widget').first().clone()
|
|
|
|
|
|
$newWidget.data('portf-id', portfId)
|
|
|
|
|
|
var $newWidgetPhotoCont = $newWidget.find('.answer-portfolio-photo-widget-photo-cont').first()
|
|
|
$newWidgetPhotoCont.css('background', 'url("' + photoUrl + '") no-repeat center')
|
|
|
|
|
|
$container.append($newWidget)
|
|
|
|
|
|
$newWidget.css('display', 'block')
|
|
|
})
|
|
|
} else {
|
|
|
var $widgets = $container.find('.answer-portfolio-photo-widget')
|
|
|
var $widget = _.find(function(el) {return $(el).data('portf-id') === portfId}, $widgets)
|
|
|
$widget.remove()
|
|
|
}
|
|
|
})
|
|
|
|
|
|
|
|
|
var initialPortfIds = $('input[type="checkbox"]:checked.answer-portfolio-select').map(function(i, el) {return $(el).val()})
|
|
|
|
|
|
loadAllPhotos(initialPortfIds)
|
|
|
|
|
|
|
|
|
function loadAllPhotos(portfIds) {
|
|
|
var $container = $('#answer-portfolio-photo-widget-container')
|
|
|
|
|
|
_.each(function(portfId) {
|
|
|
$.ajax({url: '/api/portfolios/' + portfId + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(portf) {
|
|
|
var photoUrl = portf.photos[0].img
|
|
|
var $newWidget = $container.find('.answer-portfolio-photo-widget').first().clone()
|
|
|
|
|
|
$newWidget.data('portf-id', portfId)
|
|
|
|
|
|
var $newWidgetPhotoCont = $newWidget.find('.answer-portfolio-photo-widget-photo-cont').first()
|
|
|
$newWidgetPhotoCont.css('background', 'url("' + photoUrl + '") no-repeat center')
|
|
|
|
|
|
$container.append($newWidget)
|
|
|
|
|
|
$newWidget.css('display', 'block')
|
|
|
})
|
|
|
}, portfIds)
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Live image upload --------------------------------------------
|
|
|
|
|
|
|
|
|
;(function() {
|
|
|
var $container = $('.-live-image-upload-container').first()
|
|
|
|
|
|
var $liveImageUploadField = $container.find('.-live-image-upload-field').first()
|
|
|
var liveImageDeleteClass = '.-live-image-delete'
|
|
|
var $imageDeleteBtns = $('.-image-delete')
|
|
|
|
|
|
var templ = _.template($container.find('.-templ').first().html())
|
|
|
var $res = $container.find('.-res').first()
|
|
|
|
|
|
var images = []
|
|
|
|
|
|
$liveImageUploadField.fileupload({
|
|
|
url: LIVE_IMAGE_UPLOAD_URL,
|
|
|
dataType: 'json',
|
|
|
|
|
|
done: function($evt, data) {
|
|
|
var image = data.result
|
|
|
images.push(image)
|
|
|
render()
|
|
|
}
|
|
|
})
|
|
|
|
|
|
$container.on('click', liveImageDeleteClass, function($evt) {
|
|
|
var $that = $(this)
|
|
|
var image = _.find({id: $that.data('imageId')}, images)
|
|
|
|
|
|
$.post(image.deleteUrl).then(function(res) {
|
|
|
if (res.status == 'success') {
|
|
|
remove(images, image)
|
|
|
render()
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
|
|
|
$imageDeleteBtns.on('click', function($evt) {
|
|
|
$(this).closest('.-image-widget').remove()
|
|
|
})
|
|
|
|
|
|
|
|
|
// Helpers --------------------------------
|
|
|
|
|
|
function render() {
|
|
|
$res.html(templ({images: images}))
|
|
|
}
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Live image avatar (single) upload ---------------------------------
|
|
|
|
|
|
|
|
|
;(function() {
|
|
|
var $container = $('.-live-image-avatar-upload-container').first()
|
|
|
|
|
|
var $avatarImage = $container.find('.-avatar-image').first()
|
|
|
var $liveImageUpload = $container.find('.-live-image-upload').first()
|
|
|
var $liveImageId = $container.find('.-live-image-id').first()
|
|
|
var $liveImageDelete = $container.find('.-live-image-delete').first()
|
|
|
|
|
|
$avatarImage.attr('orig-src', $avatarImage.attr('src'))
|
|
|
|
|
|
$liveImageUpload.fileupload({
|
|
|
url: LIVE_IMAGE_UPLOAD_URL,
|
|
|
dataType: 'json',
|
|
|
|
|
|
done: function($evt, data) {
|
|
|
var image = data.result
|
|
|
|
|
|
$avatarImage.attr('src', image.thumbnailUrl)
|
|
|
$liveImageId.val(image.id)
|
|
|
|
|
|
$liveImageDelete.data('url', image.deleteUrl)
|
|
|
$liveImageDelete.css('display', 'block')
|
|
|
}
|
|
|
})
|
|
|
|
|
|
$liveImageDelete.on('click', function($evt) {
|
|
|
var $that = $(this)
|
|
|
|
|
|
$.post($that.data('url')).then(function(res) {
|
|
|
if (res.status == 'success') {
|
|
|
$avatarImage.attr('src', $avatarImage.attr('orig-src') || STUB_IMAGE_URL)
|
|
|
$liveImageId.val('')
|
|
|
$that.css('display', 'none')
|
|
|
}
|
|
|
})
|
|
|
})
|
|
|
}())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Helpers ---------------------------------------------
|
|
|
|
|
|
|
|
|
function getSpecializationTree(specId) {
|
|
|
var specs = {
|
|
|
spec: null,
|
|
|
specLevel1: null, specLevel2: null, specLevel3: null, specLevel4: null,
|
|
|
urlLevel2: null, urlLevel3: null, urlLevel4: null,
|
|
|
}
|
|
|
|
|
|
if (specId === null) {
|
|
|
return $.when(specs)
|
|
|
} else {
|
|
|
return $.ajax({url: '/api/specializations/' + specId + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(spec) {
|
|
|
if (spec.level === 1) {
|
|
|
return _.merge(specs, {
|
|
|
spec: spec,
|
|
|
specLevel1: spec,
|
|
|
urlLevel2: format('/api/specializations/?lft__gt=%s&rght__lte=%s', spec.lft, spec.rght),
|
|
|
})
|
|
|
} else if (spec.level === 2) {
|
|
|
var specLevel2 = spec
|
|
|
|
|
|
return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(spec) {
|
|
|
var specLevel1 = spec
|
|
|
|
|
|
return _.merge(specs, {
|
|
|
spec: specLevel2,
|
|
|
specLevel1: specLevel1,
|
|
|
urlLevel2: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel1.lft, specLevel1.rght),
|
|
|
specLevel2: specLevel2,
|
|
|
urlLevel3: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel2.lft, specLevel2.rght),
|
|
|
})
|
|
|
})
|
|
|
} else if (spec.level === 3) {
|
|
|
var specLevel3 = spec
|
|
|
|
|
|
return $.ajax({url: '/api/specializations/' + specLevel3.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(spec) {
|
|
|
var specLevel2 = spec
|
|
|
|
|
|
return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(spec) {
|
|
|
var specLevel1 = spec
|
|
|
|
|
|
return _.merge(specs, {
|
|
|
spec: specLevel3,
|
|
|
specLevel1: specLevel1,
|
|
|
urlLevel2: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel1.lft, specLevel1.rght),
|
|
|
specLevel2: specLevel2,
|
|
|
urlLevel3: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel2.lft, specLevel2.rght),
|
|
|
specLevel3: specLevel3,
|
|
|
urlLevel4: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel3.lft, specLevel3.rght),
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
} else if (spec.level === 4) {
|
|
|
var specLevel4 = spec
|
|
|
|
|
|
return $.ajax({url: '/api/specializations/' + specLevel4.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(spec) {
|
|
|
var specLevel3 = spec
|
|
|
|
|
|
return $.ajax({url: '/api/specializations/' + specLevel3.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(spec) {
|
|
|
var specLevel2 = spec
|
|
|
|
|
|
return $.ajax({url: '/api/specializations/' + specLevel2.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(spec) {
|
|
|
var specLevel1 = spec
|
|
|
|
|
|
return _.merge(specs, {
|
|
|
spec: specLevel4,
|
|
|
specLevel1: specLevel1,
|
|
|
urlLevel2: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel1.lft, specLevel1.rght),
|
|
|
specLevel2: specLevel2,
|
|
|
urlLevel3: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel2.lft, specLevel2.rght),
|
|
|
specLevel3: specLevel3,
|
|
|
urlLevel4: format('/api/specializations/?lft__gt=%s&rght__lte=%s', specLevel3.lft, specLevel3.rght),
|
|
|
specLevel4: specLevel4,
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getLocationTree(locId) {
|
|
|
var locations = {
|
|
|
location: null,
|
|
|
country: null, region: null, city: null,
|
|
|
countries: [], regions: [], cities: [],
|
|
|
}
|
|
|
|
|
|
if (locId === null) {
|
|
|
return $.ajax({url: '/api/locations/?level=1', method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {
|
|
|
return _.merge(locations, {
|
|
|
countries: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, res.results),
|
|
|
})
|
|
|
})
|
|
|
} else {
|
|
|
return $.ajax({url: '/api/locations/' + locId + '/', method: 'GET', dataType: 'json'}).then(function(loc) {
|
|
|
locations = _.merge(locations, {location: loc})
|
|
|
|
|
|
if (loc.level === 1) {
|
|
|
var country = loc
|
|
|
|
|
|
return $.when(
|
|
|
$.ajax({url: '/api/locations/?level=1', method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}), // Countries
|
|
|
|
|
|
$.ajax({url: '/api/locations/?level=2&parent=' + country.id, method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}) // Regions
|
|
|
)
|
|
|
.then(function(countries, regions) {
|
|
|
return _.merge(locations, {
|
|
|
country: country,
|
|
|
countries: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, countries),
|
|
|
regions: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, regions),
|
|
|
})
|
|
|
})
|
|
|
} else if (loc.level === 2) {
|
|
|
var region = loc
|
|
|
|
|
|
return $.when(
|
|
|
$.ajax({url: '/api/locations/?level=1', method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}), // Countries
|
|
|
|
|
|
$.ajax({url: '/api/locations/?level=2&parent=' + region.parent.id, method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}), // Regions
|
|
|
|
|
|
$.ajax({url: '/api/locations/' + region.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res}), // Country
|
|
|
|
|
|
$.ajax({url: '/api/locations/?level=3&parent=' + region.id, method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}) // Cities
|
|
|
)
|
|
|
.then(function(countries, regions, country, cities) {
|
|
|
return _.merge(locations, {
|
|
|
country: country,
|
|
|
region: region,
|
|
|
countries: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, countries),
|
|
|
regions: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, regions),
|
|
|
cities: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, cities),
|
|
|
})
|
|
|
})
|
|
|
} else if (loc.level === 3) {
|
|
|
var city = loc
|
|
|
|
|
|
return $.when(
|
|
|
$.ajax({url: '/api/locations/?level=1', method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}), // Countries
|
|
|
|
|
|
$.ajax({url: '/api/locations/' + city.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res}), // Region
|
|
|
|
|
|
$.ajax({url: '/api/locations/?level=3&parent=' + city.parent.id, method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}) // Cities
|
|
|
)
|
|
|
.then(function(countries, region, cities) {
|
|
|
locations = _.merge(locations, {
|
|
|
region: region,
|
|
|
city: city,
|
|
|
countries: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, countries),
|
|
|
cities: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, cities),
|
|
|
})
|
|
|
|
|
|
return $.when(
|
|
|
$.ajax({url: '/api/locations/?level=2&parent=' + region.parent.id, method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res.results}), // Regions
|
|
|
|
|
|
$.ajax({url: '/api/locations/' + region.parent.id + '/', method: 'GET', dataType: 'json'})
|
|
|
.then(function(res) {return res}) // Country
|
|
|
)
|
|
|
.then(function(regions, country) {
|
|
|
return _.merge(locations, {
|
|
|
country: country,
|
|
|
regions: _.map(function(item) {return {text: item.name, id: item.id, origItem: item}}, regions),
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function specializationTreeHasLevels(specId) {
|
|
|
if (specId == null) {
|
|
|
var haveLevels = {
|
|
|
level2: true,
|
|
|
level3: true,
|
|
|
level4: true,
|
|
|
}
|
|
|
|
|
|
return $.when(haveLevels)
|
|
|
} else {
|
|
|
return $.get(format('/api/specializations/%s/', specId)).then(function(spec) {
|
|
|
return $.get(format('/api/specializations/?level=1&lft__lte=%s&rght__gte=%s', spec.lft, spec.rght)).then(function(res) {
|
|
|
var specTreeRoot = res.results[0]
|
|
|
|
|
|
var url_ = format('/api/specializations/?lft__gt=%s&rght__lt=%s&level=%s', specTreeRoot.lft, specTreeRoot.rght)
|
|
|
|
|
|
return $.when(
|
|
|
$.get(format(url_, 2)).then(function(res) {return res}),
|
|
|
$.get(format(url_, 3)).then(function(res) {return res}),
|
|
|
$.get(format(url_, 4)).then(function(res) {return res})
|
|
|
)
|
|
|
.then(function(resLvl1, resLvl2, resLvl3) {
|
|
|
var haveLevels = {
|
|
|
level2: !_.isEmpty(resLvl1.results),
|
|
|
level3: !_.isEmpty(resLvl2.results),
|
|
|
level4: !_.isEmpty(resLvl3.results),
|
|
|
}
|
|
|
|
|
|
return haveLevels
|
|
|
})
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Utils -----------------------------------------------
|
|
|
|
|
|
|
|
|
var _call = Function.prototype.call
|
|
|
var _splice = _call.bind(Array.prototype.splice)
|
|
|
|
|
|
|
|
|
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]
|
|
|
}
|
|
|
|
|
|
|
|
|
function format() {
|
|
|
var str = _.head(arguments)
|
|
|
var args = _.tail(arguments)
|
|
|
|
|
|
var arg
|
|
|
|
|
|
while (true) {
|
|
|
arg = args.shift()
|
|
|
|
|
|
if (arg != null && str.search('%s') !== -1)
|
|
|
str = str.replace('%s', arg)
|
|
|
else
|
|
|
break
|
|
|
}
|
|
|
|
|
|
return str
|
|
|
}
|
|
|
|
|
|
|
|
|
function remove(coll, item) {
|
|
|
_splice(coll, _.indexOf(item, coll), 1)
|
|
|
return coll
|
|
|
}
|
|
|
|
|
|
|
|
|
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;
|
|
|
}
|
|
|
|