From cb43e60ae92cc4edb853958fd1a70a3a99c10bb6 Mon Sep 17 00:00:00 2001 From: Yuri Kuznetsov Date: Sat, 18 Jun 2022 19:14:09 +0300 Subject: [PATCH] jsdoc --- client/src/ui.js | 8 +- client/src/view.js | 4 +- client/src/views/modal.js | 276 +++++++++++++++++++++++++++++++++++--- 3 files changed, 269 insertions(+), 19 deletions(-) diff --git a/client/src/ui.js b/client/src/ui.js index b41f31e5c6..699b3bb607 100644 --- a/client/src/ui.js +++ b/client/src/ui.js @@ -55,22 +55,24 @@ define('ui', [], function () { */ /** - * A button or a dropdown action item. + * A button or dropdown action item. * * @typedef {Object} module:ui.Dialog~Button * - * @property {boolean} [hidden] Is hidden. * @property {string} name A name. * @property {boolean} [pullLeft=false] To put the button to the other side. * @property {string} [html] HTML. * @property {string} [text] A title. * @property {boolean} [disabled=false] Disabled. + * @property {boolean} [hidden=false] Hidden. * @property {'default'|'danger'|'success'|'warning'} [style='default'] A style. - * @property {Function} [onClick] An on-click callback. + * @property {function():void} [onClick] An on-click callback. */ /** * @class + * @name Espo.Ui.Dialog + * * @param {module:ui.Dialog~Params} options Options. */ let Dialog = function (options) { diff --git a/client/src/view.js b/client/src/view.js index f932ae328e..1b64d6a39c 100644 --- a/client/src/view.js +++ b/client/src/view.js @@ -31,12 +31,14 @@ define('view', [], function () { /** * A base view. * + * @see {@link https://docs.espocrm.com/development/view/} + * * @class * @name Class * @extends Bull.View * @memberOf module:view */ - return Bull.View.extend(/** @lends module:view.Class.prototype */{ + return Bull.View.extend(/** @lends module:view.Class# */{ /** * @callback module:view.Class~actionHandlerCallback diff --git a/client/src/views/modal.js b/client/src/views/modal.js index 1076b86e9a..092b1b557c 100644 --- a/client/src/views/modal.js +++ b/client/src/views/modal.js @@ -28,52 +28,199 @@ define('views/modal', ['view'], function (Dep) { - return Dep.extend({ + /** + * A base modal view. Can be extended or used directly. + * + * Options: + * - `headerHtml` + * - `headerText` + * - `$header` + * - `backdrop` + * - `buttonList` + * - `dropdownItemList` + * + * @see {@link https://docs.espocrm.com/development/modal/} + * + * @class + * @name Class + * @extends module:view.Class + * @memberOf module:views/modal + */ + return Dep.extend(/** @lends module:views/modal.Class# */{ + /** + * A button or dropdown action item. + * + * @typedef {Object} module:views/modal.Class~Button + * + * @property {string} name A name. + * @property {string} [label] A label. To be translated + * (with a scope defined in the `scope` class property). + * @property {string} [text] A text (not translated). + * @property {string} [html] HTML. + * @property {boolean} [pullLeft=false] To put the button to the other side. + * @property {'default'|'danger'|'success'|'warning'} [style='default'] A style. + * @property {boolean} [hidden=false] Is hidden. + * @property {boolean} [disabled=false] Disabled. + * @property {function():void} [onClick] Called on click. If not defined, then + * the `action` class method will be called. + */ + + /** + * A CSS name. + * + * @protected + */ cssName: 'modal-dialog', + /** + * A class-name. Use `'dialog dialog-record'` for modals containing a record form. + * + * @protected + */ className: 'dialog', + /** + * @protected + * @deprecated Use `headerHtml` + */ header: false, + /** + * A header HTML. + * + * @protected + * @type {string} + */ headerHtml: null, + /** + * A dialog instance. + * + * @protected + * @type {Espo.Ui.Dialog} + */ dialog: null, + /** + * A container selector. + * + * @protected + * @type {string} + */ containerSelector: null, + /** + * A scope name. Used when translating button labels. + * + * @protected + * @type {string|null} + */ scope: null, + /** + * A backdrop. + * + * @protected + * @type {'static'|boolean} + */ backdrop: 'static', + /** + * Buttons. + * + * @protected + * @type {module:views/modal.Class~Button[]} + */ buttonList: [], + /** + * Dropdown action items. + * + * @protected + * @type {module:views/modal.Class~Button[]} + */ dropdownItemList: [], - // @todo Remove it as deprecated. + /** + * @deprecated Use `buttonList`. + * @protected + * @todo Remove. + */ buttons: [], - width: false, + /** + * A width. + * + * @protected + * @type {number|null} + */ + width: null, + /** + * Not used. + * + * @deprecated + */ fitHeight: false, + /** + * To disable fitting to a window height. + * + * @protected + * @type {boolean} + */ + noFullHeight: false, + + /** + * Disable the ability to close by pressing the `Esc` key. + * + * @protected + * @type {boolean} + */ escapeDisabled: false, + /** + * Is draggable. + * + * @protected + * @type {boolean} + */ isDraggable: false, + /** + * Is collapsable. + * + * @protected + * @type {boolean} + */ isCollapsable: false, + /** + * Is collapsed. Do not change value. Only for reading. + * + * @protected + * @type {boolean} + */ isCollapsed: false, + /** + * @inheritDoc + */ events: { + /** @this module:views/modal.Class */ 'click .action': function (e) { Espo.Utils.handleAction(this, e); }, + /** @this module:views/modal.Class */ 'click [data-action="collapseModal"]': function () { this.collapse(); }, }, + /** + * @inheritDoc + */ init: function () { var id = this.cssName + '-container-' + Math.floor((Math.random() * 10000) + 1).toString(); var containerSelector = this.containerSelector = '#' + id; @@ -86,8 +233,6 @@ define('views/modal', ['view'], function (Dep) { this.headerHtml = Handlebars.Utils.escapeExpression(this.options.headerText); } - this.options = this.options || {}; - this.backdrop = this.options.backdrop || this.backdrop; this.setSelector(this.containerSelector); @@ -173,11 +318,17 @@ define('views/modal', ['view'], function (Dep) { }); }, + /** + * Get a button list for a dialog. + * + * @private + * @return {module:ui.Dialog~Button[]} + */ getDialogButtonList: function () { var buttonListExt = []; // TODO remove it as deprecated - this.buttons.forEach((item) => { + this.buttons.forEach(item => { var o = Espo.Utils.clone(item); if (!('text' in o) && ('label' in o)) { @@ -187,8 +338,7 @@ define('views/modal', ['view'], function (Dep) { buttonListExt.push(o); }); - - this.buttonList.forEach((item) => { + this.buttonList.forEach(item => { var o = {}; if (typeof item === 'string') { @@ -219,6 +369,12 @@ define('views/modal', ['view'], function (Dep) { return buttonListExt; }, + /** + * Get a dropdown item list for a dialog. + * + * @private + * @return {module:ui.Dialog~Button[]} + */ getDialogDropdownItemList: function () { var dropdownItemListExt = []; @@ -253,6 +409,9 @@ define('views/modal', ['view'], function (Dep) { return dropdownItemListExt; }, + /** + * @private + */ updateDialog: function () { if (!this.dialog) { return; @@ -262,6 +421,9 @@ define('views/modal', ['view'], function (Dep) { this.dialog.dropdownItemList = this.getDialogDropdownItemList(); }, + /** + * @private + */ onDialogClose: function () { if (!this.isBeingRendered() && !this.isCollapsed) { this.trigger('close'); @@ -269,20 +431,34 @@ define('views/modal', ['view'], function (Dep) { } }, + /** + * A `cancel` action. + */ actionCancel: function () { this.trigger('cancel'); this.dialog.close(); }, + /** + * A `close` action. + */ actionClose: function () { this.trigger('cancel'); this.dialog.close(); }, + /** + * Close a dialog. + */ close: function () { this.dialog.close(); }, + /** + * Disable a button. + * + * @param {string} name A button name. + */ disableButton: function (name) { this.buttonList.forEach((d) => { if (d.name !== name) { @@ -301,6 +477,11 @@ define('views/modal', ['view'], function (Dep) { .attr('disabled', 'disabled'); }, + /** + * Enable a button. + * + * @param {string} name A button name. + */ enableButton: function (name) { this.buttonList.forEach((d) => { if (d.name !== name) { @@ -319,6 +500,14 @@ define('views/modal', ['view'], function (Dep) { .removeAttr('disabled'); }, + /** + * Add a button. + * + * @param {module:ui.Dialog~Button} o Button definitions. + * @param {boolean|string} [position=false] True prepends, false appends. If a string, + * then will be added after a button with a corresponding name. + * @param {boolean} [doNotReRender=false] Do not re-render. + */ addButton: function (o, position, doNotReRender) { var index = -1; @@ -359,6 +548,13 @@ define('views/modal', ['view'], function (Dep) { } }, + /** + * Add a dropdown item. + * + * @param {module:ui.Dialog~Button} o Button definitions. + * @param {boolean} [toBeginning=false] To prepend. + * @param {boolean} [doNotReRender=false] Do not re-render. + */ addDropdownItem: function (o, toBeginning, doNotReRender) { var method = toBeginning ? 'unshift' : 'push'; @@ -387,6 +583,9 @@ define('views/modal', ['view'], function (Dep) { } }, + /** + * @private + */ reRenderFooter: function () { if (!this.dialog) { return; @@ -401,6 +600,12 @@ define('views/modal', ['view'], function (Dep) { this.dialog.initButtonEvents(); }, + /** + * Remove a button or a dropdown action item. + * + * @param {string} name A name. + * @param {boolean} [doNotReRender=false] Do not re-render. + */ removeButton: function (name, doNotReRender) { var index = -1; @@ -431,6 +636,12 @@ define('views/modal', ['view'], function (Dep) { } }, + /** + * @deprecated Use `showActionItem`. + * + * @protected + * @param {string} name + */ showButton: function (name) { this.buttonList.forEach((d) => { if (d.name !== name) { @@ -447,6 +658,12 @@ define('views/modal', ['view'], function (Dep) { this.$el.find('footer button[data-name="'+name+'"]').removeClass('hidden'); }, + /** + * @deprecated Use `hideActionItem`. + * + * @protected + * @param {string} name + */ hideButton: function (name) { this.buttonList.forEach((d) => { if (d.name !== name) { @@ -463,8 +680,13 @@ define('views/modal', ['view'], function (Dep) { this.$el.find('footer button[data-name="'+name+'"]').addClass('hidden'); }, + /** + * Show an action item (button or dropdown item). + * + * @param {string} name A name. + */ showActionItem: function (name) { - this.buttonList.forEach((d) => { + this.buttonList.forEach(d => { if (d.name !== name) { return; } @@ -472,7 +694,7 @@ define('views/modal', ['view'], function (Dep) { d.hidden = false; }); - this.dropdownItemList.forEach((d) => { + this.dropdownItemList.forEach(d => { if (d.name !== name) { return; } @@ -492,15 +714,20 @@ define('views/modal', ['view'], function (Dep) { } }, + /** + * Hide an action item (button or dropdown item). + * + * @param {string} name A name. + */ hideActionItem: function (name) { - this.buttonList.forEach((d) => { + this.buttonList.forEach(d => { if (d.name !== name) { return; } d.hidden = true; }); - this.dropdownItemList.forEach((d) => { + this.dropdownItemList.forEach(d => { if (d.name !== name) { return; } @@ -520,6 +747,10 @@ define('views/modal', ['view'], function (Dep) { } }, + /** + * @private + * @return {boolean} + */ isDropdownItemListEmpty: function () { if (this.dropdownItemList.length === 0) { return true; @@ -536,15 +767,20 @@ define('views/modal', ['view'], function (Dep) { return isEmpty; }, + /** + * @private + * @param {number} [step=0] + */ adjustHeaderFontSize: function (step) { step = step || 0; - if (!step) this.fontSizePercentage = 100; + if (!step) { + this.fontSizePercentage = 100; + } var $titleText = this.$el.find('.modal-title > .modal-title-text'); var containerWidth = $titleText.parent().width(); - var textWidth = 0; $titleText.children().each((i, el) => { @@ -567,12 +803,16 @@ define('views/modal', ['view'], function (Dep) { var fontSizePercentage = this.fontSizePercentage -= 4; - this.$el.find('.modal-title .font-size-flexible').css('font-size', this.fontSizePercentage + '%'); + this.$el.find('.modal-title .font-size-flexible') + .css('font-size', this.fontSizePercentage + '%'); this.adjustHeaderFontSize(step + 1); } }, + /** + * Collapse. + */ collapse: function () { this.beforeCollapse().then(data => { if (!this.getParentView()) { @@ -629,6 +869,12 @@ define('views/modal', ['view'], function (Dep) { }); }, + /** + * Called before collapse. Can be extended to execute some logic, e.g. save form data. + * + * @protected + * @return {Promise} + */ beforeCollapse: function () { return new Promise(resolve => resolve()); },