selectbox improvement
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
Espo.define('crm:views/meeting/fields/attendees', 'views/fields/link-multiple-with-role', function (Dep) {
|
||||
define('crm:views/meeting/fields/attendees', ['views/fields/link-multiple-with-role'], function (Dep) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -34,8 +34,6 @@ Espo.define('crm:views/meeting/fields/attendees', 'views/fields/link-multiple-wi
|
||||
|
||||
roleFieldIsForeign: false,
|
||||
|
||||
emptyRoleValue: 'None'
|
||||
|
||||
emptyRoleValue: 'None',
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -26,14 +26,13 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('crm:views/meeting/fields/reminders', ['views/fields/base'], function (Dep) {
|
||||
define('crm:views/meeting/fields/reminders', ['views/fields/base', 'ui/select'],
|
||||
function (Dep, /** module:ui/select*/Select) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
detailTemplate: 'crm:meeting/fields/reminders/detail',
|
||||
|
||||
listTemplate: 'crm:meeting/fields/reminders/detail',
|
||||
|
||||
editTemplate: 'crm:meeting/fields/reminders/edit',
|
||||
|
||||
events: {
|
||||
@@ -118,7 +117,8 @@ define('crm:views/meeting/fields/reminders', ['views/fields/base'], function (De
|
||||
$type.append($o);
|
||||
});
|
||||
|
||||
$type.val(item.type);
|
||||
$type.val(item.type)
|
||||
.addClass('radius-left');
|
||||
|
||||
$type.on('change', () => {
|
||||
this.updateType($type.val(), $type.closest('.reminder').index());
|
||||
@@ -152,11 +152,14 @@ define('crm:views/meeting/fields/reminders', ['views/fields/base'], function (De
|
||||
.html('<span class="fas fa-times"></span>');
|
||||
|
||||
$item
|
||||
.append($('<div class="input-group-btn">').append($type))
|
||||
.append($seconds)
|
||||
.append($('<div class="input-group-item">').append($type))
|
||||
.append($('<div class="input-group-item">').append($seconds))
|
||||
.append($('<div class="input-group-btn">').append($remove));
|
||||
|
||||
this.$container.append($item);
|
||||
|
||||
Select.init($type, {});
|
||||
Select.init($seconds, {});
|
||||
},
|
||||
|
||||
stringifySeconds: function (seconds) {
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
<div class="input-group">
|
||||
<input type="text" class="main-element form-control" data-name="{{name}}" value="{{value}}" autocomplete="espo-{{name}}" pattern="[\-]?[0-9,.]*" {{#if params.maxLength}} maxlength="{{params.maxLength}}"{{/if}}>
|
||||
<span class="input-group-btn">
|
||||
<select data-name="{{currencyFieldName}}" class="form-control">
|
||||
{{{options currencyList currencyValue}}}
|
||||
</select>
|
||||
<div class="input-group input-group-currency">
|
||||
<span class="input-group-item">
|
||||
<input
|
||||
type="text"
|
||||
class="main-element form-control radius-left"
|
||||
data-name="{{name}}"
|
||||
value="{{value}}"
|
||||
autocomplete="espo-{{name}}"
|
||||
pattern="[\-]?[0-9,.]*"
|
||||
{{#if params.maxLength}} maxlength="{{params.maxLength}}"{{/if}}
|
||||
>
|
||||
</span>
|
||||
<span class="input-group-item">
|
||||
<select
|
||||
data-name="{{currencyFieldName}}"
|
||||
class="form-control radius-right"
|
||||
>{{{options currencyList currencyValue}}}</select>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
<div class="input-group input-group-link-parent">
|
||||
{{#if foreignScopeList.length}}
|
||||
<span class="input-group-btn">
|
||||
<select class="form-control" data-name="{{typeName}}">
|
||||
<span class="input-group-item">
|
||||
<select class="form-control radius-left" data-name="{{typeName}}">
|
||||
{{options foreignScopeList foreignScope category='scopeNames'}}
|
||||
</select>
|
||||
</span>
|
||||
<input
|
||||
class="main-element form-control middle-element"
|
||||
type="text"
|
||||
data-name="{{nameName}}"
|
||||
value="{{nameValue}}"
|
||||
autocomplete="espo-{{name}}"
|
||||
placeholder="{{translate 'Select'}}"
|
||||
spellcheck="false"
|
||||
>
|
||||
<span class="input-group-item input-group-item-middle">
|
||||
<input
|
||||
class="main-element form-control"
|
||||
type="text"
|
||||
data-name="{{nameName}}"
|
||||
value="{{nameValue}}"
|
||||
autocomplete="espo-{{name}}"
|
||||
placeholder="{{translate 'Select'}}"
|
||||
spellcheck="false"
|
||||
>
|
||||
</span>
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
data-action="selectLink"
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
|
||||
<div>
|
||||
<div class="phone-number-block-container">
|
||||
{{#each phoneNumberData}}
|
||||
<div class="input-group phone-number-block">
|
||||
<span class="input-group-btn">
|
||||
<span class="input-group-item">
|
||||
<select
|
||||
data-property-type="type"
|
||||
class="form-control"
|
||||
class="form-control radius-left"
|
||||
>{{options ../params.typeList type scope=../scope field=../name}}</select>
|
||||
</span>
|
||||
<input
|
||||
type="input"
|
||||
class="form-control phone-number no-margin-shifting"
|
||||
value="{{phoneNumber}}"
|
||||
autocomplete="espo-{{../name}}"
|
||||
maxlength={{../itemMaxLength}}
|
||||
>
|
||||
<span class="input-group-item input-group-item-middle">
|
||||
<input
|
||||
type="input"
|
||||
class="form-control phone-number no-margin-shifting"
|
||||
value="{{phoneNumber}}"
|
||||
autocomplete="espo-{{../name}}"
|
||||
maxlength={{../itemMaxLength}}
|
||||
>
|
||||
</span>
|
||||
<span class="input-group-btn">
|
||||
<button
|
||||
class="btn btn-default btn-icon phone-property{{#if primary}} active{{/if}} hidden"
|
||||
|
||||
@@ -0,0 +1,368 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM - Open Source CRM application.
|
||||
* Copyright (C) 2014-2022 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* EspoCRM is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* EspoCRM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with EspoCRM. If not, see http://www.gnu.org/licenses/.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('ui/select', ['lib!Selectize'], (Selectize) => {
|
||||
|
||||
/**
|
||||
* @typedef module:ui/select~Options
|
||||
* @type {Object}
|
||||
* @property {boolean} [selectOnTab=false]
|
||||
* @property {boolean} [matchAnyWord=false]
|
||||
*/
|
||||
|
||||
/**
|
||||
* @module ui/select
|
||||
*/
|
||||
let Select = {
|
||||
/**
|
||||
* @param {JQuery} $el An element.
|
||||
* @param {module:ui/select~Options} [options] Options.
|
||||
*/
|
||||
init: function ($el, options) {
|
||||
options = Select.applyDefaultOptions(options || {});
|
||||
|
||||
let plugins = [];
|
||||
|
||||
Select.loadEspoSelectPlugin();
|
||||
plugins.push('espo_select');
|
||||
plugins.push('auto_position');
|
||||
|
||||
let itemClasses = {};
|
||||
|
||||
let allowedValues = $el.children().toArray().map(item => {
|
||||
let value = item.getAttributeNode('value').value;
|
||||
|
||||
if (item.classList) {
|
||||
itemClasses[value] = item.classList.toString();
|
||||
}
|
||||
|
||||
return value;
|
||||
});
|
||||
|
||||
let selectizeOptions = {
|
||||
plugins: plugins,
|
||||
highlight: false,
|
||||
selectOnTab: options.selectOnTab,
|
||||
copyClassesToDropdown: false,
|
||||
allowEmptyOption: allowedValues.includes(''),
|
||||
showEmptyOptionInDropdown: true,
|
||||
render: {
|
||||
item: function (data) {
|
||||
return $('<div>')
|
||||
.addClass('item')
|
||||
.addClass(itemClasses[data.value] || '')
|
||||
.text(data.text)
|
||||
.get(0).outerHTML;
|
||||
},
|
||||
option: function (data) {
|
||||
let $div = $('<div>')
|
||||
.addClass('option')
|
||||
.addClass(data.value === '' ? 'selectize-dropdown-emptyoptionlabel' : '')
|
||||
.addClass(itemClasses[data.value] || '')
|
||||
.val(data.value)
|
||||
.text(data.text);
|
||||
|
||||
if (data.text === '') {
|
||||
$div.html(' ');
|
||||
}
|
||||
|
||||
return $div.get(0).outerHTML;
|
||||
},
|
||||
},
|
||||
onDelete: function (values) {
|
||||
while (values.length) {
|
||||
this.removeItem(values.pop(), true);
|
||||
}
|
||||
|
||||
this.showInput();
|
||||
this.positionDropdown();
|
||||
this.refreshOptions(true);
|
||||
},
|
||||
};
|
||||
|
||||
if (!options.matchAnyWord) {
|
||||
/** @this Selectize */
|
||||
selectizeOptions.score = function (search) {
|
||||
let score = this.getScoreFunction(search);
|
||||
|
||||
search = search.toLowerCase();
|
||||
|
||||
return function (item) {
|
||||
if (item.text.toLowerCase().indexOf(search) === 0) {
|
||||
return score(item);
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
$el.selectize(selectizeOptions);
|
||||
},
|
||||
|
||||
/**
|
||||
* Focus.
|
||||
*
|
||||
* @param {JQuery} $el An element.
|
||||
* @param {{noTrigger?: boolean}} [options] Options.
|
||||
*/
|
||||
focus: function ($el, options) {
|
||||
options = options || {};
|
||||
|
||||
let selectize = $el.get(0).selectize;
|
||||
|
||||
if (options.noTrigger) {
|
||||
selectize.focusNoTrigger = true;
|
||||
}
|
||||
|
||||
selectize.focus();
|
||||
|
||||
setTimeout(() => selectize.focusNoTrigger = false, 100);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set options.
|
||||
*
|
||||
* @param {JQuery} $el An element.
|
||||
* @param {{value: string, label: string}[]} options Options.
|
||||
*/
|
||||
setOptions: function ($el, options) {
|
||||
let selectize = $el.get(0).selectize;
|
||||
|
||||
selectize.clearOptions(true);
|
||||
selectize.load(callback => {
|
||||
callback(
|
||||
options.map(item => {
|
||||
return {
|
||||
value: item.value,
|
||||
text: item.label,
|
||||
};
|
||||
})
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Set value.
|
||||
*
|
||||
* @param {JQuery} $el An element.
|
||||
* @param {string} value A value.
|
||||
*/
|
||||
setValue: function ($el, value) {
|
||||
let selectize = $el.get(0).selectize;
|
||||
|
||||
selectize.setValue(value, true);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {module:ui/select~Options} options
|
||||
* @return {module:ui/select~Options}
|
||||
*/
|
||||
applyDefaultOptions: function (options) {
|
||||
options = Espo.Utils.clone(options);
|
||||
|
||||
let defaults = {
|
||||
selectOnTab: false,
|
||||
matchAnyWord: false,
|
||||
};
|
||||
|
||||
for (let key in defaults) {
|
||||
if (key in options) {
|
||||
continue;
|
||||
}
|
||||
|
||||
options[key] = defaults[key];
|
||||
}
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
loadEspoSelectPlugin: function () {
|
||||
if ('espo_select' in Selectize.plugins) {
|
||||
return;
|
||||
}
|
||||
|
||||
const IS_MAC = /Mac/.test(navigator.userAgent);
|
||||
const KEY_BACKSPACE = 8;
|
||||
|
||||
Selectize.define('espo_select', function () {
|
||||
let self = this;
|
||||
|
||||
this.refreshOptions = (function () {
|
||||
let original = self.refreshOptions;
|
||||
|
||||
return function () {
|
||||
if (self.focusNoTrigger) {
|
||||
original.apply(this, [false]);
|
||||
return;
|
||||
}
|
||||
|
||||
original.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
this.onOptionSelect = (function () {
|
||||
let original = self.onOptionSelect;
|
||||
|
||||
return function (e) {
|
||||
original.apply(this, arguments);
|
||||
|
||||
self.selectedValue = $(e.currentTarget).attr('data-value');
|
||||
};
|
||||
})();
|
||||
|
||||
this.open = (function() {
|
||||
let original = self.open;
|
||||
|
||||
return function () {
|
||||
let toProcess = !(self.isLocked || self.isOpen);
|
||||
|
||||
original.apply(this, arguments);
|
||||
|
||||
if (!toProcess) {
|
||||
return;
|
||||
}
|
||||
|
||||
let $selected = self.$dropdown.find('.selected');
|
||||
|
||||
if (!$selected.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
self.$dropdown
|
||||
.find('.selectize-dropdown-content')
|
||||
.scrollTop($selected.get(0).offsetTop);
|
||||
};
|
||||
})();
|
||||
|
||||
this.onMouseDown = (function() {
|
||||
let original = self.onMouseDown;
|
||||
|
||||
return function (e) {
|
||||
if (self.isOpen) {
|
||||
self.closedByMouseDown = true;
|
||||
}
|
||||
|
||||
return original.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
this.onFocus = (function() {
|
||||
let original = self.onFocus;
|
||||
|
||||
return function (e) {
|
||||
self.selectedValue = self.getValue();
|
||||
|
||||
if (self.closedByMouseDown) {
|
||||
self.closedByMouseDown = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
self.closedByMouseDown = false;
|
||||
|
||||
return original.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
this.revertValue = function () {
|
||||
if (this.selectedValue !== null) {
|
||||
this.setValue(this.selectedValue, true);
|
||||
}
|
||||
|
||||
this.selectedValue = null;
|
||||
};
|
||||
|
||||
this.onBlur = (function() {
|
||||
let original = self.onBlur;
|
||||
|
||||
return function () {
|
||||
self.revertValue();
|
||||
|
||||
self.$control_input.css({width: '4px'});
|
||||
|
||||
return original.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
this.onKeyDown = (function() {
|
||||
let original = self.onKeyDown;
|
||||
|
||||
return function (e) {
|
||||
if (e.code === 'Enter' && (IS_MAC ? e.metaKey : e.ctrlKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.code === 'Escape') {
|
||||
if (self.isOpen || !self.isInputHidden) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
|
||||
if (self.isOpen) {
|
||||
self.close();
|
||||
}
|
||||
|
||||
if (!self.isInputHidden) {
|
||||
self.hideInput();
|
||||
}
|
||||
|
||||
self.addItem(this.selectedValue, true);
|
||||
}
|
||||
|
||||
if (self.isFull() || self.isInputHidden) {
|
||||
if (
|
||||
e.key.length === 1 &&
|
||||
(
|
||||
e.key.match(/[a-z]/i) ||
|
||||
e.key.match(/[0-9]/)
|
||||
)
|
||||
) {
|
||||
let keyCode = e.keyCode;
|
||||
e.keyCode = KEY_BACKSPACE;
|
||||
|
||||
self.deleteSelection(e);
|
||||
|
||||
//self.clear();
|
||||
|
||||
e.keyCode = keyCode;
|
||||
}
|
||||
}
|
||||
|
||||
return original.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
return Select;
|
||||
});
|
||||
@@ -26,7 +26,7 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/base', ['view'], function (Dep) {
|
||||
define('views/fields/base', ['view', 'ui/select'], function (Dep, /** module:ui/select*/Select) {
|
||||
|
||||
/**
|
||||
* A base field view. Can be in different modes. Each mode uses a separate template.
|
||||
@@ -780,6 +780,14 @@ define('views/fields/base', ['view'], function (Dep) {
|
||||
if (this.hasRequiredMarker()) {
|
||||
this.hideRequiredSign();
|
||||
}
|
||||
|
||||
if (this.isSearchMode()) {
|
||||
let $searchType = this.$el.find('select.search-type');
|
||||
|
||||
if ($searchType.length) {
|
||||
Select.init($searchType, {matchAnyWord: true});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if ((this.isDetailMode() || this.isEditMode()) && this.tooltip) {
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
define('views/fields/currency', ['views/fields/float', 'ui/select'],
|
||||
function (Dep, /** module:ui/select*/Select) {
|
||||
|
||||
/**
|
||||
* @class
|
||||
@@ -39,23 +40,14 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
type: 'currency',
|
||||
|
||||
editTemplate: 'fields/currency/edit',
|
||||
|
||||
detailTemplate: 'fields/currency/detail',
|
||||
|
||||
detailTemplate1: 'fields/currency/detail-1',
|
||||
|
||||
detailTemplate2: 'fields/currency/detail-2',
|
||||
|
||||
detailTemplate3: 'fields/currency/detail-3',
|
||||
|
||||
listTemplate: 'fields/currency/list',
|
||||
|
||||
listTemplate1: 'fields/currency/list-1',
|
||||
|
||||
listTemplate2: 'fields/currency/list-2',
|
||||
|
||||
listTemplate3: 'fields/currency/list-3',
|
||||
|
||||
detailTemplateNoCurrency: 'fields/currency/detail-no-currency',
|
||||
|
||||
maxDecimalPlaces: 3,
|
||||
@@ -64,7 +56,7 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
* @inheritDoc
|
||||
*/
|
||||
data: function () {
|
||||
var currencyValue = this.model.get(this.currencyFieldName) ||
|
||||
let currencyValue = this.model.get(this.currencyFieldName) ||
|
||||
this.getPreferences().get('defaultCurrency') ||
|
||||
this.getConfig().get('defaultCurrency');
|
||||
|
||||
@@ -93,7 +85,7 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
|
||||
this.isSingleCurrency = this.currencyList.length <= 1;
|
||||
|
||||
var currencyValue = this.currencyValue = this.model.get(this.currencyFieldName) ||
|
||||
let currencyValue = this.currencyValue = this.model.get(this.currencyFieldName) ||
|
||||
this.defaultCurrency;
|
||||
|
||||
if (!~this.currencyList.indexOf(currencyValue)) {
|
||||
@@ -107,10 +99,10 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
},
|
||||
|
||||
_getTemplateName: function () {
|
||||
if (this.mode === 'detail' || this.mode === 'list') {
|
||||
if (this.mode === this.MODE_DETAIL || this.mode === this.MODE_LIST) {
|
||||
var prop;
|
||||
|
||||
if (this.mode === 'list') {
|
||||
if (this.mode === this.MODE_LIST) {
|
||||
prop = 'listTemplate' + this.getCurrencyFormat().toString();
|
||||
}
|
||||
else {
|
||||
@@ -138,7 +130,7 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
},
|
||||
|
||||
formatNumberEdit: function (value) {
|
||||
var currencyDecimalPlaces = this.getConfig().get('currencyDecimalPlaces');
|
||||
let currencyDecimalPlaces = this.getConfig().get('currencyDecimalPlaces');
|
||||
|
||||
if (value !== null) {
|
||||
var parts = value.toString().split(".");
|
||||
@@ -163,7 +155,7 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
|
||||
formatNumberDetail: function (value) {
|
||||
if (value !== null) {
|
||||
var currencyDecimalPlaces = this.getConfig().get('currencyDecimalPlaces');
|
||||
let currencyDecimalPlaces = this.getConfig().get('currencyDecimalPlaces');
|
||||
|
||||
if (currencyDecimalPlaces === 0) {
|
||||
value = Math.round(value);
|
||||
@@ -179,7 +171,7 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
);
|
||||
}
|
||||
|
||||
var parts = value.toString().split(".");
|
||||
let parts = value.toString().split(".");
|
||||
|
||||
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, this.thousandSeparator);
|
||||
|
||||
@@ -187,7 +179,7 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
return parts[0];
|
||||
}
|
||||
else if (currencyDecimalPlaces) {
|
||||
var decimalPartLength = 0;
|
||||
let decimalPartLength = 0;
|
||||
|
||||
if (parts.length > 1) {
|
||||
decimalPartLength = parts[1].length;
|
||||
@@ -196,9 +188,9 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
}
|
||||
|
||||
if (currencyDecimalPlaces && decimalPartLength < currencyDecimalPlaces) {
|
||||
var limit = currencyDecimalPlaces - decimalPartLength;
|
||||
let limit = currencyDecimalPlaces - decimalPartLength;
|
||||
|
||||
for (var i = 0; i < limit; i++) {
|
||||
for (let i = 0; i < limit; i++) {
|
||||
parts[1] += '0';
|
||||
}
|
||||
}
|
||||
@@ -213,23 +205,25 @@ define('views/fields/currency', ['views/fields/float'], function (Dep) {
|
||||
afterRender: function () {
|
||||
Dep.prototype.afterRender.call(this);
|
||||
|
||||
if (this.mode === 'edit') {
|
||||
if (this.mode === this.MODE_EDIT) {
|
||||
this.$currency = this.$el.find('[data-name="' + this.currencyFieldName + '"]');
|
||||
|
||||
this.$currency.on('change', () => {
|
||||
this.model.set(this.currencyFieldName, this.$currency.val(), {ui: true});
|
||||
});
|
||||
|
||||
Select.init(this.$currency);
|
||||
}
|
||||
},
|
||||
|
||||
fetch: function () {
|
||||
var value = this.$element.val();
|
||||
let value = this.$element.val();
|
||||
|
||||
value = this.parse(value);
|
||||
|
||||
var data = {};
|
||||
let data = {};
|
||||
|
||||
var currencyValue = this.$currency.val();
|
||||
let currencyValue = this.$currency.val();
|
||||
|
||||
if (value === null) {
|
||||
currencyValue = null;
|
||||
|
||||
@@ -26,9 +26,16 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
define('views/fields/duration', ['views/fields/enum', 'ui/select'],
|
||||
function (Dep, /** module:ui/select*/Select) {
|
||||
|
||||
return Dep.extend({
|
||||
/**
|
||||
* @class
|
||||
* @name Class
|
||||
* @memberOf module:views/fields/duration
|
||||
* @extends module:views/fields/enum.Class
|
||||
*/
|
||||
return Dep.extend(/** @lends module:views/fields/duration.Class# */{
|
||||
|
||||
type: 'duration',
|
||||
|
||||
@@ -39,10 +46,11 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
data: function () {
|
||||
let valueIsSet = this.model.has(this.startField) && this.model.has(this.endField);
|
||||
|
||||
return _.extend({
|
||||
return {
|
||||
valueIsSet: valueIsSet,
|
||||
durationOptions: this.durationOptions,
|
||||
}, Dep.prototype.data.call(this));
|
||||
...Dep.prototype.data.call(this),
|
||||
};
|
||||
},
|
||||
|
||||
calculateSeconds: function () {
|
||||
@@ -88,30 +96,39 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
this.listenTo(this, 'render', () => {
|
||||
this.calculateSeconds();
|
||||
|
||||
let durationOptions = '';
|
||||
this.durationOptions = '';
|
||||
|
||||
let options = this.defaultOptions = _.clone(this.model.getFieldParam(this.name, 'options'));
|
||||
this.getOptions().forEach(d => {
|
||||
let $o = $('<option>')
|
||||
.val(d)
|
||||
.text(this.stringifyDuration(d));
|
||||
|
||||
if (!this.model.get('isAllDay') && options.indexOf(this.seconds) === -1) {
|
||||
options.push(this.seconds);
|
||||
}
|
||||
if (d === this.seconds) {
|
||||
$o.attr('selected', 'selected')
|
||||
}
|
||||
|
||||
options.sort((a, b) => {
|
||||
return a - b;
|
||||
this.durationOptions += $o.get(0).outerHTML;
|
||||
});
|
||||
|
||||
options.forEach((d) => {
|
||||
durationOptions += '<option value="' + d + '" ' +
|
||||
(d === this.seconds ? 'selected' : '') + '>' +
|
||||
this.stringifyDuration(d) + '</option>';
|
||||
});
|
||||
|
||||
this.durationOptions = durationOptions;
|
||||
|
||||
this.stringValue = this.stringifyDuration(this.seconds);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {Number[]}
|
||||
*/
|
||||
getOptions: function () {
|
||||
let options = Espo.Utils.clone(this.model.getFieldParam(this.name, 'options') ?? []);
|
||||
|
||||
if (!this.model.get('isAllDay') && options.indexOf(this.seconds) === -1) {
|
||||
options.push(this.seconds);
|
||||
}
|
||||
|
||||
options.sort((a, b) => a - b);
|
||||
|
||||
return options;
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
this.startField = this.model.getFieldParam(this.name, 'start');
|
||||
this.endField = this.model.getFieldParam(this.name, 'end');
|
||||
@@ -124,7 +141,7 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
|
||||
this.blockDateEndChangeListener = false;
|
||||
|
||||
this.listenTo(this.model, 'change:' + this.endField, () => {
|
||||
this.listenTo(this.model, 'change:' + this.endField, (m, v, o) => {
|
||||
if (this.blockDateEndChangeListener) {
|
||||
return;
|
||||
}
|
||||
@@ -138,6 +155,10 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
|
||||
this.seconds = moment(end).unix() - moment(start).unix();
|
||||
|
||||
if (o.updatedByDuration) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateDuration();
|
||||
});
|
||||
|
||||
@@ -205,11 +226,14 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
return parts.join(' ');
|
||||
},
|
||||
|
||||
focusOnInlineEdit: function () {
|
||||
Select.focus(this.$duration);
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
let parentView = this.getParentView();
|
||||
|
||||
if (parentView && 'getView' in parentView) {
|
||||
this.startFieldView = parentView.getView(this.startField);
|
||||
this.endFieldView = parentView.getView(this.endField);
|
||||
}
|
||||
|
||||
@@ -220,8 +244,6 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
this.seconds = parseInt(this.$duration.val());
|
||||
|
||||
this.updateDateEnd();
|
||||
|
||||
this.$duration.find('option.custom').remove();
|
||||
});
|
||||
|
||||
let start = this.model.get(this.startField);
|
||||
@@ -241,6 +263,8 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Select.init(this.$duration, {});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -311,49 +335,23 @@ define('views/fields/duration', ['views/fields/enum'], function (Dep) {
|
||||
updateDuration: function () {
|
||||
let seconds = this.seconds;
|
||||
|
||||
if (seconds < 0) {
|
||||
if (this.mode === 'edit') {
|
||||
this.$duration.val('');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.setup();
|
||||
this.render();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isEditMode() && this.$duration && this.$duration.length) {
|
||||
this.$duration.find('option.custom').remove();
|
||||
let options = this.getOptions().map(value => {
|
||||
return {
|
||||
value: value.toString(),
|
||||
label: this.stringifyDuration(value),
|
||||
};
|
||||
});
|
||||
|
||||
let $o = $('<option>')
|
||||
.val(seconds)
|
||||
.text(this.stringifyDuration(seconds))
|
||||
.addClass('custom');
|
||||
|
||||
let $found = this.$duration.find('option')
|
||||
.filter((i, el) => {
|
||||
return $(el).val() >= seconds;
|
||||
})
|
||||
.first();
|
||||
|
||||
if ($found.length) {
|
||||
if (parseInt($found.val()) !== seconds) {
|
||||
$o.insertBefore($found);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$o.appendTo(this.$duration);
|
||||
}
|
||||
|
||||
this.$duration.val(seconds);
|
||||
Select.setValue(this.$duration, '');
|
||||
Select.setOptions(this.$duration, options);
|
||||
Select.setValue(this.$duration, seconds.toString());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.setup();
|
||||
this.render();
|
||||
//this.setup();
|
||||
this.reRender();
|
||||
},
|
||||
|
||||
fetch: function () {
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/enum', ['views/fields/base', 'ui/multi-select'],
|
||||
function (Dep, /** module:ui/multi-select*/MultiSelect) {
|
||||
define('views/fields/enum', ['views/fields/base', 'ui/multi-select', 'ui/select'],
|
||||
function (Dep, /** module:ui/multi-select*/MultiSelect, /** module:ui/select*/Select) {
|
||||
|
||||
/**
|
||||
* An enum field (select-box).
|
||||
@@ -42,13 +42,9 @@ function (Dep, /** module:ui/multi-select*/MultiSelect) {
|
||||
type: 'enum',
|
||||
|
||||
listTemplate: 'fields/enum/list',
|
||||
|
||||
listLinkTemplate: 'fields/enum/list-link',
|
||||
|
||||
detailTemplate: 'fields/enum/detail',
|
||||
|
||||
editTemplate: 'fields/enum/edit',
|
||||
|
||||
searchTemplate: 'fields/enum/search',
|
||||
|
||||
translatedOptions: null,
|
||||
@@ -330,6 +326,14 @@ function (Dep, /** module:ui/multi-select*/MultiSelect) {
|
||||
this.$el.find('select.search-type').on('change', () => this.trigger('change'));
|
||||
this.$element.on('change', () => this.trigger('change'));
|
||||
}
|
||||
|
||||
if (this.isEditMode() || this.isSearchMode()) {
|
||||
Select.init(this.$element, {matchAnyWord: true});
|
||||
}
|
||||
},
|
||||
|
||||
focusOnInlineEdit: function () {
|
||||
Select.focus(this.$element);
|
||||
},
|
||||
|
||||
validateRequired: function () {
|
||||
|
||||
@@ -26,8 +26,9 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/link-multiple-with-columns', ['views/fields/link-multiple', 'helpers/reg-exp-pattern'],
|
||||
function (Dep, RegExpPattern) {
|
||||
define('views/fields/link-multiple-with-columns',
|
||||
['views/fields/link-multiple', 'helpers/reg-exp-pattern', 'ui/select'],
|
||||
function (Dep, RegExpPattern, /** module:ui/select*/Select) {
|
||||
|
||||
/**
|
||||
* A link-multiple field with relation column(s).
|
||||
@@ -317,7 +318,7 @@ function (Dep, RegExpPattern) {
|
||||
let options = this.columnsDefs[column].options || [];
|
||||
|
||||
let $select = $('<select>')
|
||||
.addClass('role form-control input-sm pull-right')
|
||||
.addClass('role form-control input-sm')
|
||||
.attr('data-id', id)
|
||||
.attr('data-column', column);
|
||||
|
||||
@@ -354,7 +355,7 @@ function (Dep, RegExpPattern) {
|
||||
let text = this.translate(field, 'fields', scope);
|
||||
|
||||
let $input = $('<input>')
|
||||
.addClass('role form-control input-sm pull-right')
|
||||
.addClass('role form-control input-sm')
|
||||
.attr('data-column', column)
|
||||
.attr('placeholder', text)
|
||||
.attr('data-id', id)
|
||||
@@ -466,7 +467,12 @@ function (Dep, RegExpPattern) {
|
||||
let $left = $('<div>');
|
||||
let $right = $('<div>');
|
||||
|
||||
$columnList.forEach($item => $left.append($item));
|
||||
$columnList.forEach($item => $left.append(
|
||||
$('<span>')
|
||||
.addClass('link-item-column')
|
||||
.addClass('link-item-column-' + $item.get(0).tagName.toLowerCase())
|
||||
.append($item)
|
||||
));
|
||||
|
||||
if ($liList.length) {
|
||||
let $ul = $('<ul>').addClass('dropdown-menu');
|
||||
@@ -499,6 +505,11 @@ function (Dep, RegExpPattern) {
|
||||
|
||||
if (this.isEditMode()) {
|
||||
$columnList.forEach($column => {
|
||||
|
||||
if ($column.get(0).tagName === 'SELECT') {
|
||||
Select.init($column);
|
||||
}
|
||||
|
||||
let fetch = ($target) => {
|
||||
if (!$target || !$target.length) {
|
||||
return;
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/link-multiple-with-role', ['views/fields/link-multiple'], function (Dep) {
|
||||
define('views/fields/link-multiple-with-role', ['views/fields/link-multiple', 'ui/select'],
|
||||
function (Dep, /** module:ui/select*/Select) {
|
||||
|
||||
/**
|
||||
* A link-multiple field with a relation column.
|
||||
@@ -247,7 +248,7 @@ define('views/fields/link-multiple-with-role', ['views/fields/link-multiple'], f
|
||||
// Do not use the `html` method to avoid XSS.
|
||||
|
||||
let $role = $('<select>')
|
||||
.addClass('role form-control input-sm pull-right')
|
||||
.addClass('role form-control input-sm')
|
||||
.attr('data-id', id);
|
||||
|
||||
this.roleList.forEach(role => {
|
||||
@@ -315,7 +316,7 @@ define('views/fields/link-multiple-with-role', ['views/fields/link-multiple'], f
|
||||
let text = this.rolePlaceholderText || this.translate(this.roleField, 'fields', this.roleFieldScope);
|
||||
|
||||
$role = $('<input>')
|
||||
.addClass('role form-control input-sm pull-right')
|
||||
.addClass('role form-control input-sm')
|
||||
.attr('maxlength', this.roleMaxLength) // @todo Get the value from metadata.
|
||||
.attr('placeholder', text)
|
||||
.attr('data-id', id)
|
||||
@@ -323,15 +324,21 @@ define('views/fields/link-multiple-with-role', ['views/fields/link-multiple'], f
|
||||
}
|
||||
|
||||
if ($role) {
|
||||
$left.append($role);
|
||||
$left.append($('<span>')
|
||||
.addClass('link-item-column')
|
||||
.addClass('link-item-column-' + $role.get(0).tagName.toLowerCase())
|
||||
.append($role)
|
||||
);
|
||||
}
|
||||
|
||||
$left.append($name);
|
||||
|
||||
$el.append($left).append($right);
|
||||
|
||||
$container.append($el);
|
||||
|
||||
if ($role && $role.get(0).tagName === 'SELECT') {
|
||||
Select.init($role);
|
||||
}
|
||||
|
||||
if (this.isEditMode() && $role) {
|
||||
let fetch = ($target) => {
|
||||
if (!$target || !$target.length) {
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/link-parent', ['views/fields/base', 'helpers/record-modal'], function (Dep, RecordModal) {
|
||||
define('views/fields/link-parent', ['views/fields/base', 'helpers/record-modal', 'ui/select'],
|
||||
function (Dep, RecordModal, /** module:ui/select*/Select) {
|
||||
|
||||
/**
|
||||
* A link-parent field (belongs-to-parent relation).
|
||||
@@ -41,13 +42,9 @@ define('views/fields/link-parent', ['views/fields/base', 'helpers/record-modal']
|
||||
type: 'linkParent',
|
||||
|
||||
listTemplate: 'fields/link-parent/list',
|
||||
|
||||
detailTemplate: 'fields/link-parent/detail',
|
||||
|
||||
editTemplate: 'fields/link-parent/edit',
|
||||
|
||||
searchTemplate: 'fields/link-parent/search',
|
||||
|
||||
listLinkTemplate: 'fields/link-parent/list-link',
|
||||
|
||||
/**
|
||||
@@ -211,8 +208,8 @@ define('views/fields/link-parent', ['views/fields/base', 'helpers/record-modal']
|
||||
|
||||
if (
|
||||
(
|
||||
this.mode === 'detail' ||
|
||||
this.mode === 'list' && this.displayScopeColorInListMode
|
||||
this.mode === this.MODE_DETAIL ||
|
||||
this.mode === this.MODE_LIST && this.displayScopeColorInListMode
|
||||
) &&
|
||||
this.foreignScope
|
||||
) {
|
||||
@@ -345,7 +342,7 @@ define('views/fields/link-parent', ['views/fields/base', 'helpers/record-modal']
|
||||
this.addActionHandler('clearLink', () => {
|
||||
if (this.foreignScopeList.length) {
|
||||
this.foreignScope = this.foreignScopeList[0];
|
||||
this.$elementType.val(this.foreignScope);
|
||||
Select.setValue(this.$elementType, this.foreignScope);
|
||||
}
|
||||
|
||||
this.$elementName.val('');
|
||||
@@ -505,7 +502,7 @@ define('views/fields/link-parent', ['views/fields/base', 'helpers/record-modal']
|
||||
|
||||
this.$elementName.on('blur', e => {
|
||||
setTimeout(() => {
|
||||
if (this.mode === 'edit') {
|
||||
if (this.mode === this.MODE_EDIT) {
|
||||
e.currentTarget.value = this.model.get(this.nameName) || '';
|
||||
}
|
||||
}, 100);
|
||||
@@ -563,6 +560,8 @@ define('views/fields/link-parent', ['views/fields/base', 'helpers/record-modal']
|
||||
this.$elementName.on('focus', () => this.$elementName.get(0).select());
|
||||
|
||||
this.$elementName.attr('autocomplete', 'espo-' + this.name);
|
||||
|
||||
Select.init(this.$elementType, {});
|
||||
}
|
||||
|
||||
var $elementName = this.$elementName;
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/person-name', ['views/fields/varchar'], function (Dep) {
|
||||
define('views/fields/person-name', ['views/fields/varchar', 'ui/select'],
|
||||
function (Dep, /** module:ui/select*/Select) {
|
||||
|
||||
/**
|
||||
* @class
|
||||
@@ -39,13 +40,9 @@ define('views/fields/person-name', ['views/fields/varchar'], function (Dep) {
|
||||
type: 'personName',
|
||||
|
||||
detailTemplate: 'fields/person-name/detail',
|
||||
|
||||
editTemplate: 'fields/person-name/edit',
|
||||
|
||||
editTemplateLastFirst: 'fields/person-name/edit-last-first',
|
||||
|
||||
editTemplateLastFirstMiddle: 'fields/person-name/edit-last-first-middle',
|
||||
|
||||
editTemplateFirstMiddleLast: 'fields/person-name/edit-first-middle-last',
|
||||
|
||||
/**
|
||||
@@ -57,7 +54,7 @@ define('views/fields/person-name', ['views/fields/varchar'], function (Dep) {
|
||||
],
|
||||
|
||||
data: function () {
|
||||
var data = Dep.prototype.data.call(this);
|
||||
let data = Dep.prototype.data.call(this);
|
||||
|
||||
data.ucName = Espo.Utils.upperCaseFirst(this.name);
|
||||
data.salutationValue = this.model.get(this.salutationField);
|
||||
@@ -125,6 +122,8 @@ define('views/fields/person-name', ['views/fields/varchar'], function (Dep) {
|
||||
this.$last.on('change', () => {
|
||||
this.trigger('change');
|
||||
});
|
||||
|
||||
Select.init(this.$salutation);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -26,16 +26,21 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
define('views/fields/phone', ['views/fields/varchar', 'ui/select'],
|
||||
function (Dep, /** module:ui/select*/Select) {
|
||||
|
||||
return Dep.extend({
|
||||
/**
|
||||
* @class
|
||||
* @name Class
|
||||
* @memberOf module:views/fields/phone
|
||||
* @extends module:views/fields/varchar.Class
|
||||
*/
|
||||
return Dep.extend(/** @lends module:views/fields/phone.Class */{
|
||||
|
||||
type: 'phone',
|
||||
|
||||
editTemplate: 'fields/phone/edit',
|
||||
|
||||
detailTemplate: 'fields/phone/detail',
|
||||
|
||||
listTemplate: 'fields/phone/list',
|
||||
|
||||
validations: ['required', 'phoneData'],
|
||||
@@ -43,7 +48,7 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
validateRequired: function () {
|
||||
if (this.isRequired()) {
|
||||
if (!this.model.get(this.name)) {
|
||||
var msg = this.translate('fieldIsRequired', 'messages')
|
||||
let msg = this.translate('fieldIsRequired', 'messages')
|
||||
.replace('{field}', this.getLabelText());
|
||||
|
||||
this.showValidationMessage(msg, 'div.phone-number-block:nth-child(1) input');
|
||||
@@ -103,14 +108,14 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
},
|
||||
|
||||
data: function () {
|
||||
var phoneNumberData;
|
||||
let phoneNumberData;
|
||||
|
||||
if (this.mode === 'edit') {
|
||||
if (this.mode === this.MODE_EDIT) {
|
||||
phoneNumberData = Espo.Utils.cloneDeep(this.model.get(this.dataFieldName));
|
||||
|
||||
if (this.model.isNew() || !this.model.get(this.name)) {
|
||||
if (!phoneNumberData || !phoneNumberData.length) {
|
||||
var optOut = false;
|
||||
let optOut;
|
||||
|
||||
if (this.model.isNew()) {
|
||||
optOut = this.phoneNumberOptedOutByDefault && this.model.name !== 'User';
|
||||
@@ -135,7 +140,7 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
phoneNumberData = Espo.Utils.cloneDeep(phoneNumberData);
|
||||
|
||||
phoneNumberData.forEach((item) => {
|
||||
var number = item.phoneNumber || '';
|
||||
let number = item.phoneNumber || '';
|
||||
|
||||
item.erased = number.indexOf(this.erasedPlaceholder) === 0;
|
||||
|
||||
@@ -148,9 +153,9 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
}
|
||||
|
||||
if ((!phoneNumberData || phoneNumberData.length === 0) && this.model.get(this.name)) {
|
||||
var number = this.model.get(this.name);
|
||||
let number = this.model.get(this.name);
|
||||
|
||||
var o = {
|
||||
let o = {
|
||||
phoneNumber: number,
|
||||
primary: true,
|
||||
valueForLink: number.replace(/ /g, ''),
|
||||
@@ -163,7 +168,7 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
phoneNumberData = [o];
|
||||
}
|
||||
|
||||
var data = _.extend({
|
||||
let data = _.extend({
|
||||
phoneNumberData: phoneNumberData,
|
||||
doNotCall: this.model.get('doNotCall'),
|
||||
lineThrough: this.model.get('doNotCall') || this.model.get(this.isOptedOutFieldName),
|
||||
@@ -190,9 +195,9 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
|
||||
events: {
|
||||
'click [data-action="switchPhoneProperty"]': function (e) {
|
||||
var $target = $(e.currentTarget);
|
||||
var $block = $(e.currentTarget).closest('div.phone-number-block');
|
||||
var property = $target.data('property-type');
|
||||
let $target = $(e.currentTarget);
|
||||
let $block = $(e.currentTarget).closest('div.phone-number-block');
|
||||
let property = $target.data('property-type');
|
||||
|
||||
if (property === 'primary') {
|
||||
if (!$target.hasClass('active')) {
|
||||
@@ -216,7 +221,7 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
},
|
||||
|
||||
'click [data-action="removePhoneNumber"]': function (e) {
|
||||
var $block = $(e.currentTarget).closest('div.phone-number-block');
|
||||
let $block = $(e.currentTarget).closest('div.phone-number-block');
|
||||
|
||||
if ($block.parent().children().length === 1) {
|
||||
$block.find('input.phone-number').val('');
|
||||
@@ -228,10 +233,10 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
},
|
||||
|
||||
'change input.phone-number': function (e) {
|
||||
var $input = $(e.currentTarget);
|
||||
var $block = $input.closest('div.phone-number-block');
|
||||
let $input = $(e.currentTarget);
|
||||
let $block = $input.closest('div.phone-number-block');
|
||||
|
||||
if ($input.val() == '') {
|
||||
if ($input.val() === '') {
|
||||
if ($block.parent().children().length === 1) {
|
||||
$block.find('input.phone-number').val('');
|
||||
} else {
|
||||
@@ -249,13 +254,11 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
},
|
||||
|
||||
'paste input.phone-number': function (e) {
|
||||
setTimeout(function () {
|
||||
this.manageAddButton();
|
||||
}.bind(this), 10);
|
||||
setTimeout(() => this.manageAddButton(), 10);
|
||||
},
|
||||
|
||||
'click [data-action="addPhoneNumber"]': function () {
|
||||
var data = Espo.Utils.cloneDeep(this.fetchPhoneNumberData());
|
||||
let data = Espo.Utils.cloneDeep(this.fetchPhoneNumberData());
|
||||
|
||||
let o = {
|
||||
phoneNumber: '',
|
||||
@@ -268,21 +271,31 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
data.push(o);
|
||||
|
||||
this.model.set(this.dataFieldName, data, {silent: true});
|
||||
this.render();
|
||||
|
||||
this.reRender();
|
||||
},
|
||||
},
|
||||
|
||||
afterRender: function () {
|
||||
Dep.prototype.afterRender.call(this);
|
||||
|
||||
this.manageButtonsVisibility();
|
||||
this.manageAddButton();
|
||||
|
||||
if (this.mode === this.MODE_EDIT) {
|
||||
this.$el.find('select').toArray().forEach(selectElement => {
|
||||
Select.init($(selectElement));
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
removePhoneNumberBlock: function ($block) {
|
||||
var changePrimary = false;
|
||||
let changePrimary = false;
|
||||
|
||||
if ($block.find('button[data-property-type="primary"]').hasClass('active')) {
|
||||
changePrimary = true;
|
||||
}
|
||||
|
||||
$block.remove();
|
||||
|
||||
if (changePrimary) {
|
||||
@@ -321,16 +334,21 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
},
|
||||
|
||||
manageButtonsVisibility: function () {
|
||||
var $primary = this.$el.find('button[data-property-type="primary"]');
|
||||
var $remove = this.$el.find('button[data-action="removePhoneNumber"]');
|
||||
let $primary = this.$el.find('button[data-property-type="primary"]');
|
||||
let $remove = this.$el.find('button[data-action="removePhoneNumber"]');
|
||||
let $container = this.$el.find('.phone-number-block-container');
|
||||
|
||||
if ($primary.length > 1) {
|
||||
$primary.removeClass('hidden');
|
||||
$remove.removeClass('hidden');
|
||||
} else {
|
||||
$primary.addClass('hidden');
|
||||
$remove.addClass('hidden');
|
||||
$container.addClass('many')
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$container.removeClass('many')
|
||||
$primary.addClass('hidden');
|
||||
$remove.addClass('hidden');
|
||||
},
|
||||
|
||||
setup: function () {
|
||||
@@ -364,18 +382,18 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
},
|
||||
|
||||
fetchPhoneNumberData: function () {
|
||||
var data = [];
|
||||
let data = [];
|
||||
|
||||
var $list = this.$el.find('div.phone-number-block');
|
||||
let $list = this.$el.find('div.phone-number-block');
|
||||
|
||||
if ($list.length) {
|
||||
$list.each((i, d) => {
|
||||
var row = {};
|
||||
var $d = $(d);
|
||||
let row = {};
|
||||
let $d = $(d);
|
||||
|
||||
row.phoneNumber = $d.find('input.phone-number').val().trim();
|
||||
|
||||
if (row.phoneNumber == '') {
|
||||
if (row.phoneNumber === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -392,14 +410,15 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
},
|
||||
|
||||
fetch: function () {
|
||||
var data = {};
|
||||
let data = {};
|
||||
|
||||
let addressData = this.fetchPhoneNumberData() || [];
|
||||
|
||||
var addressData = this.fetchPhoneNumberData() || [];
|
||||
data[this.dataFieldName] = addressData;
|
||||
data[this.name] = null;
|
||||
data[this.isOptedOutFieldName] = false;
|
||||
|
||||
var primaryIndex = 0;
|
||||
let primaryIndex = 0;
|
||||
|
||||
addressData.forEach((item, i) => {
|
||||
if (item.primary) {
|
||||
@@ -412,7 +431,7 @@ define('views/fields/phone', ['views/fields/varchar'], function (Dep) {
|
||||
});
|
||||
|
||||
if (addressData.length && primaryIndex > 0) {
|
||||
var t = addressData[0];
|
||||
let t = addressData[0];
|
||||
|
||||
addressData[0] = addressData[primaryIndex];
|
||||
addressData[primaryIndex] = t;
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/settings/fields/theme', ['views/fields/enum', 'theme-manager'], function (Dep, ThemeManager) {
|
||||
define('views/settings/fields/theme', ['views/fields/enum', 'theme-manager', 'ui/select'],
|
||||
function (Dep, ThemeManager, /** module:ui/select*/Select) {
|
||||
|
||||
return Dep.extend({
|
||||
|
||||
@@ -78,7 +79,7 @@ define('views/settings/fields/theme', ['views/fields/enum', 'theme-manager'], fu
|
||||
|
||||
if (o.ui) {
|
||||
this.reRender()
|
||||
.then(() => this.$element.get(0).focus({preventScroll: true}));
|
||||
.then(() => Select.focus(this.$element, {noTrigger: true}));
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -87,6 +88,8 @@ define('views/settings/fields/theme', ['views/fields/enum', 'theme-manager'], fu
|
||||
this.$navbar = this.$el.find('[data-name="themeNavbar"]');
|
||||
|
||||
this.$navbar.on('change', () => this.trigger('change'));
|
||||
|
||||
Select.init(this.$navbar);
|
||||
},
|
||||
|
||||
getNavbarValue: function () {
|
||||
|
||||
@@ -447,3 +447,16 @@ table.table-admin-panel tr > td:first-child > div > a {
|
||||
margin-left: 0;
|
||||
margin-right: -20px;
|
||||
}
|
||||
|
||||
.selectize-control.single {
|
||||
.selectize-input {
|
||||
padding-left: 19px;
|
||||
padding-right: 10px;
|
||||
|
||||
&.dropdown-active:after,
|
||||
&:after {
|
||||
left: 8px;
|
||||
right: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1135,6 +1135,19 @@ input.global-search-input {
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.link-container {
|
||||
> .list-group-item {
|
||||
.link-item-column {
|
||||
float: right;
|
||||
display: inline-block;
|
||||
width: 40%;
|
||||
> .selectize-control {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.field .link-container .list-group-item a {
|
||||
margin-top: 1px;
|
||||
}
|
||||
@@ -3592,14 +3605,68 @@ a.close:hover {
|
||||
|
||||
.reminders-container {
|
||||
> .reminder {
|
||||
select[data-name="type"] {
|
||||
@media screen and (min-width: @screen-desktop) {
|
||||
min-width: 160px;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
|
||||
> .input-group-item:first-child {
|
||||
width: 40%;
|
||||
}
|
||||
|
||||
> .input-group-btn {
|
||||
width: 35px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-link-parent {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
|
||||
> .input-group-item:first-child {
|
||||
width: 34%;
|
||||
}
|
||||
|
||||
> .input-group-btn {
|
||||
width: calc(35px * 2);
|
||||
}
|
||||
}
|
||||
|
||||
.phone-number-block-container {
|
||||
.input-group.phone-number-block {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
|
||||
> .input-group-item:first-child {
|
||||
width: 24%;
|
||||
}
|
||||
|
||||
> .input-group-btn {
|
||||
.btn.phone-property.active {
|
||||
z-index: unset;
|
||||
}
|
||||
|
||||
width: calc(35px * 2 + 1px);
|
||||
}
|
||||
}
|
||||
|
||||
&.many {
|
||||
.input-group.phone-number-block {
|
||||
> .input-group-btn {
|
||||
width: calc(35px * 4 + 1px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-currency {
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
|
||||
> .input-group-item:last-child {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@import "elements/site.less";
|
||||
@import "elements/modal.less";
|
||||
@import "elements/buttons.less";
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
|
||||
.autocomplete-suggestion {
|
||||
padding: 4px 5px;
|
||||
padding: 4px 10px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
.popover,
|
||||
.dropdown-menu,
|
||||
.selectize-dropdown,
|
||||
.selectize-dropdown.form-control,
|
||||
.autocomplete-suggestions,
|
||||
.ui-timepicker-wrapper {
|
||||
border: var(--dropdown-border-width) solid var(--dropdown-border);
|
||||
|
||||
@@ -58,6 +58,62 @@
|
||||
border-bottom-right-radius: var(--border-radius) !important;
|
||||
}
|
||||
|
||||
.input-group > .input-group-item {
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
|
||||
+ .input-group-item {
|
||||
> .selectize-control {
|
||||
> .selectize-input {
|
||||
margin-left: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ input.form-control {
|
||||
margin-left: -1px;
|
||||
}
|
||||
|
||||
&.input-group-item-middle {
|
||||
> input {
|
||||
margin-left: -2px;
|
||||
right: -1px;
|
||||
width: calc(100% + 1px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-group > .input-group-item,
|
||||
.input-group {
|
||||
> .selectize-control {
|
||||
position: unset;
|
||||
|
||||
> .selectize-input {
|
||||
border-radius: 0;
|
||||
float: left;
|
||||
|
||||
&.focus {
|
||||
z-index: 4;
|
||||
}
|
||||
}
|
||||
|
||||
&.radius-right {
|
||||
> .selectize-input {
|
||||
border-top-right-radius: var(--border-radius);
|
||||
border-bottom-right-radius: var(--border-radius);
|
||||
}
|
||||
}
|
||||
|
||||
&.radius-left {
|
||||
> .selectize-input {
|
||||
border-top-left-radius: var(--border-radius);
|
||||
border-bottom-left-radius: var(--border-radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-group:not(:empty) + div,
|
||||
.list-group:not(:empty) + div > div.input-group {
|
||||
> .form-control,
|
||||
@@ -100,8 +156,12 @@
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.input-group .form-control:focus {
|
||||
z-index: 3;
|
||||
.input-group .form-control {
|
||||
z-index: unset;
|
||||
|
||||
&:focus {
|
||||
z-index: 3;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-container-2 {
|
||||
|
||||
@@ -1,8 +1,56 @@
|
||||
.filter > .form-group .field {
|
||||
.selectize-control {
|
||||
.filter > .form-group .field .selectize-control,
|
||||
.selectize-control.input-sm.form-control {
|
||||
&.multi {
|
||||
.selectize-input {
|
||||
font-size: @font-size-small;
|
||||
padding: 4px 5px 0;
|
||||
padding: 4px 7px 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.single {
|
||||
.selectize-input {
|
||||
font-size: @font-size-small;
|
||||
padding: 4px 19px 4px 10px;
|
||||
min-height: @input-height-small;
|
||||
}
|
||||
|
||||
height: @input-height-small;
|
||||
}
|
||||
|
||||
.selectize-dropdown-content {
|
||||
max-height: 198px;
|
||||
}
|
||||
}
|
||||
|
||||
.selectize-input {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.selectize-dropdown {
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.form-control.selectize-control.single {
|
||||
height: @input-height-base;
|
||||
}
|
||||
|
||||
.selectize-control {
|
||||
.selectize-dropdown-content {
|
||||
> .option {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
&.single {
|
||||
> .selectize-input {
|
||||
> .item {
|
||||
width: 100%;
|
||||
height: @line-height-computed;
|
||||
overflow: hidden;
|
||||
vertical-align: top;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,3 +59,64 @@
|
||||
border-radius: var(--border-radius);
|
||||
padding: 1px 4px;
|
||||
}
|
||||
|
||||
.selectize-control.single {
|
||||
.selectize-dropdown {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.selectize-input {
|
||||
padding-right: 19px;
|
||||
|
||||
&.dropdown-active:after,
|
||||
&:after {
|
||||
color: var(--text-muted-color);
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 15px;
|
||||
right: 8px;
|
||||
margin-left: 2px;
|
||||
vertical-align: middle;
|
||||
border-top: 4px dashed;
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
> .item + input {
|
||||
caret-color: transparent;
|
||||
margin-right: -4px !important; // Prevent select changing width on focus.
|
||||
}
|
||||
}
|
||||
|
||||
&.input-sm {
|
||||
.selectize-input {
|
||||
&.dropdown-active:after,
|
||||
&:after {
|
||||
top: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selectize-dropdown .active {
|
||||
&.text-success {
|
||||
color: var(--state-success-text);
|
||||
}
|
||||
&.text-danger {
|
||||
color: var(--state-danger-text);
|
||||
}
|
||||
&.text-warning {
|
||||
color: var(--state-warning-text);
|
||||
}
|
||||
&.text-warning {
|
||||
color: var(--state-warning-text);
|
||||
}
|
||||
&.text-info {
|
||||
color: var(--state-info-text);
|
||||
}
|
||||
&.text-primary {
|
||||
color: var(--state-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
&, input { cursor: pointer; }
|
||||
&.input-active, &.input-active input { cursor: text; }
|
||||
|
||||
&:after {
|
||||
/*&:after {
|
||||
content: ' ';
|
||||
display: block;
|
||||
position: absolute;
|
||||
@@ -287,14 +287,14 @@
|
||||
margin-top: @selectize-arrow-size * -0.8;
|
||||
border-width: 0 @selectize-arrow-size @selectize-arrow-size @selectize-arrow-size;
|
||||
border-color: transparent transparent @selectize-arrow-color transparent;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
.selectize-control.rtl {
|
||||
&.single .selectize-input:after {
|
||||
/*&.single .selectize-input:after {
|
||||
left: @selectize-arrow-offset;
|
||||
right: auto;
|
||||
}
|
||||
}*/
|
||||
.selectize-input > input {
|
||||
margin: @selectize-caret-margin-rtl !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user