From 92bed0aaeb4adbbd7acbdd799a21f4853cfefc7b Mon Sep 17 00:00:00 2001 From: Oleg Nechiporenko Date: Tue, 19 Jun 2018 17:43:58 +0300 Subject: [PATCH] v1.4.0 --- addon/services/modals-manager.js | 724 +++++++++++++++++++++++++++++++ app/services/modals-manager.js | 724 ------------------------------- package-lock.json | 2 +- package.json | 4 +- 4 files changed, 728 insertions(+), 726 deletions(-) diff --git a/addon/services/modals-manager.js b/addon/services/modals-manager.js index 7896e8f..98db881 100644 --- a/addon/services/modals-manager.js +++ b/addon/services/modals-manager.js @@ -1,2 +1,726 @@ import ModalsManager from 'ember-modals-manager-internal/services/modals-manager'; + +/** + * ## About + * + * `ember-bootstrap-modals-manager` is an Ember-addon that provides a simple mechanism for interaction with user using modals. This addon is based on modals from `ember-bootstrap`. + * + * **Restriction** from the [Bootstrap#modals](https://getbootstrap.com/docs/3.3/javascript/#modals): + * + * > ##### Multiple open modals not supported + * + * ## Demo + * + * You can check how this addon works on [demo-page](https://onechiporenko.github.io/ember-bootstrap-modals-manager/). + * + * ## Install + * + * **Firstly:** + * + * ```bash + * ember i ember-bootstrap-modals-manager + * ``` + * + * **Secondly:** + * + * Add component `modals-container` to the `application.hbs`: + * + * ```hbs + * {{outlet}} + * {{modals-container}} + * ``` + * + * **Thirdly:** + * + * Inject a service `modals-manager` where you want to use modals: + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * + * export default Controller.extend({ + * modalsManager: service() + * }); + * ``` + * + * That's it. Now you are able to use predefined modals from `modals-manager`. More detailed below. + * + * ### Predefined modals + * + * Every modal described below takes a single parameter. It's a POJO with properties: + * + * * `title` - modals title + * * `body` - modals body message + * * `footer` - text shown near the footer buttons (empty string by default) + * * `confirm` - text for "submit"-button + * * `decline` - text for "decline"-button + * + * You may set default options for all modals with: + * + * ```js + * set(modalsManager, 'defaultOptions', {...}); + * ``` + * + * ### `alert` + * + * Similar to the `window.alert`. It shows modal with a single button. + * + * It's used to notify user about something. + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showAlert() { + * get(this, 'modalsManager') + * .alert({title: 'Alert Title', body: 'Alert Body'}) + * .then(() => { + * // called after user clicks "Yes" in the modal + * }); + * } + * } + * }); + * ``` + * + * ### `confirm` + * + * Similar to the `window.confirm`. It shows modal with two buttons ("Yes" and "No"). + * + * It's used to the ask user about confirmation for some action. + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showConfirm() { + * get(this, 'modalsManager') + * .confirm({title: 'Confirm Title', body: 'Confirm Body'}) + * .then(() => { + * // called after user clicks "Yes" in the modal + * }) + * .catch(() => { + * // called after user clicks "No" in the modal + * }); + * } + * } + * }); + * ``` + * + * ### `prompt` + * + * Similar to the `window.prompt`. It shows modal with two buttons and single input-field. + * + * It's used to get some input from user. + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showPrompt() { + * get(this, 'modalsManager') + * .prompt({title: 'Prompt Title', body: 'Prompt Body'}) + * .then(promptValue => { + * // called after user clicks "Yes" in the modal + * // takes a single argument with user's input value + * }) + * .catch(() => { + * // called after user clicks "No" in the modal + * }); + * } + * } + * }); + * ``` + * + * Extra option `disallowEmpty` with `true`-value will disable Confirm-button until user input at least something: + * + * ```js + * modalsManager.prompt({disallowEmpty: true, title: '', body: ''}); + * ``` + * + * ### `promptConfirm` + * + * Almost the same as `prompt`, however its "Yes"-button is disabled until user write needed value to the input-field. + * + * As a `confirm` it's used to the ask user about confirmation for some action, but it's more demanding. + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showPromptConfirm() { + * get(this, 'modalsManager') + * .promptConfirm({ + * title: 'Prompt Confirm Title', + * body: 'Say "password" and come in', + * promptValue: 'password' // it's required + * }) + * .then(promptValue => { + * // called after user clicks "Yes" in the modal + * // "Yes" will be active only when user prints "password" in the input-field + * // takes a single argument with user input value + * }) + * .catch(() => { + * // called after user clicks "No" in the modal + * }); + * } + * } + * }); + * ``` + * + * ### `checkConfirm` + * + * Almost same as `promptConfirm` however it contains a checkbox instead of text-field. "Yes"-button is disabled until checkbox is not checked. + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showCheckConfirmModal() { + * get(this, 'modalsManager') + * .checkConfirm({ + * title: 'Confirm Title', + * body: 'Confirm your suggestion', + * inputLabel: 'Input Label' + * }) + * .then(() => { + * // called after user clicks "Yes" in the modal + * }) + * .catch(() => { + * // called after user clicks "No" in the modal + * }); + * } + * } + * }); + * ``` + * + * ### `progress` + * + * This modal used to show a progress-bar for chain of Promises executed one by one. This modal doesn't have any controls like confirm/decline-buttons in the footer or "×" in the header and can't be closed by pressing `Esc` or clicking somewhere outside a modal. Modal will be confirmed and self-closed after all promises are fulfilled or it will be declined (and self-closed) if at least one promise becomes rejected. + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * import {Promise} from 'rsvp'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showPromptConfirm() { + * const modalsManager = get(this, 'modalsManager'); + * modalsManager + * .progress({ + * body: '', + * promises: [ // this is required + * () => new Promise(resolve => setTimeout(resolve(1), 100)), + * () => new Promise(resolve => setTimeout(resolve(2), 100)), + * () => new Promise(resolve => setTimeout(resolve(3), 100)) + * ] + * }) + * .then(result => { + * // called after chain of `promises` is executed. + * // here "result" is an array of values for fulfilled promises + * }) + * .catch(([result, error]) => { + * // called when at least one promise is rejected + * // here "result" is an array of already fulfilled promises + * // here "error" is a reason why last promise was rejected + * return modalsManager + * .alert({ + * title: 'Something goes wrong', + * body: `Fulfilled - ${result}. Error - ${JSON.stringify(error)}` + * }); + * }); + * } + * } + * }); + * ``` + * + * Options `striped`, `animate`, `type` and `showLabel` will be passed to the progress-bar. See docs for [ember-bootstrap#progress](http://www.ember-bootstrap.com/#/components/progress) + * + * **IMPORTANT** Here `options.promises` is a list of _FUNCTIONS_ that returns Promises! + * + * ### `process` + * + * This modal is used to show a "placeholder" while some process is running. This modal doesn't have any controls like confirm/decline-buttons in the footer or "×" in the header and can't be closed by pressing Esc or clicking somewhere outside a modal. Modal will be confirmed and self-closed after provided promise (`process`) is fulfilled or it will be declined (and self-closed) if it becomes rejected. + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * import {Promise} from 'rsvp'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showProcessModal() { + * get(this, 'modalsManager') + * .process({ + * body: 'Some text goes here', + * iconClass: 'text-center fa fa-spinner fa-spin fa-3x fa-fw', + * title: '', + * // this is required + * process: () => new Promise(resolve => setTimeout(resolve(1), 100)) + * }) + * .then(result => { + * // called after `process` is resolved + * // here "result" is value of fulfilled Promise + * }) + * .catch(error => { + * // called after `process` is rejected + * // here "error" is a reason why last promise was rejected + * }); + * } + * } + * }); + * ``` + * + * **IMPORTANT** Here `options.process` is a _FUNCTION_ that return Promise! + * + * ## Go Pro + * + * ### Custom components for `title`, `body` and `footer` + * + * Every modal-port like header, body and footer may be customized not only with message and even with a Component. + * + * ### `alert` + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showAlert() { + * get(this, 'modalsManager') + * .alert({ + * titleComponent: 'custom-alert-title', + * title: 'Title', + * bodyComponent: 'custom-alert-body', + * body: 'Body', + * footerComponent: 'custom-alert-footer', + * footer: 'Footer' + * }) + * .then(() => {}); + * } + * } + * }); + * ``` + * + * #### Title Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.alert`. + * + * ```hbs + * {{! components/custom-alert-header.hbs}} + * + * ``` + * + * #### Body Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.alert`. + * + * ```hbs + * {{! components/custom-alert-body.hbs}} + *

{{options.body}}

+ * ``` + * + * #### Footer Component + * + * It takes two parameters. First one is an `options` described before. Second one is an action `confirm` used to confirm modal. It may be used like: + * + * ```hbs + * {{! components/custom-alert-footer.hbs}} + * {{options.footer}} + * {{#bs-button onClick=(action confirm)}}Confirm{{/bs-button}} + * ``` + * + * ### `confirm` + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showConfirm() { + * get(this, 'modalsManager') + * .confirm({ + * title: 'Confirm Title', + * body: 'Confirm Body', + * footer: 'Confirm Footer', + * titleComponent: 'custom-confirm-title', + * bodyComponent: 'custom-confirm-body', + * footerComponent: 'custom-confirm-footer' + * }) + * .then(() => {}) + * .catch(() => {}); + * } + * } + * }); + * ``` + * + * #### Title Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.confirm`. + * + * ```hbs + * {{! components/custom-confirm-title.hbs}} + * + * ``` + * + * #### Body Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.confirm`. + * + * ```hbs + * {{! components/custom-confirm-body.hbs}} + *

{{options.body}}

+ * ``` + * + * #### Footer Component + * + * It takes three parameters. First on is an `options` described before. Second one is an action `confirm` used to confirm modal. Third one is an action `decline` used to decline modal. Both of them may be used like: + * + * ```hbs + * {{! components/custom-confirm-footer.hbs}} + * {{options.footer}} + * {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} + * {{#bs-button onClick=(action confirm)}}Confirm{{/bs-button}} + * ``` + * + * ### `prompt` + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showPrompt() { + * get(this, 'modalsManager') + * .prompt({ + * title: 'Prompt Title', + * body: 'Prompt Body', + * footer: 'Prompt Footer', + * titleComponent: 'custom-prompt-header', + * bodyComponent: 'custom-prompt-body', + * footerComponent: 'custom-prompt-footer' + * }) + * .then(promptValue => {}) + * .catch(() => {}); + * } + * } + * }); + * ``` + * + * #### Title Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.prompt`. + * + * ```hbs + * {{! component/custom-prompt-header.hbs}} + * + * ``` + * + * #### Body Component + * + * It takes two parameters. First one is an `options` described before. Second one is an action `updatePromptValue`. It's used to update prompted value in the modal-scope. Usage example: + * + * ```hbs + * {{! components/custom-prompt-body.hbs}} + *

{{options.body}}

+ * + * ``` + * + * #### Footer Component + * + * It takes three parameters. First on is an `options` described before. Second one is an action `confirm` used to confirm modal. Third one is an action `decline` used to decline modal. Both of them may be used like: + * + * ```hbs + * {{! components/custom-prompt-footer.hbs}} + * {{options.footer}} + * {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} + * {{#bs-button onClick=(action confirm)}}Confirm{{/bs-button}} + * ``` + * + * ### `checkConfirm` + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showCheckConfirm() { + * get(this, 'modalsManager') + * .checkConfirm({ + * title: 'Check Confirm Title', + * footer: 'Prompt Confirm Footer', + * titleComponent: 'custom-check-confirm-header', + * bodyComponent: 'custom-check-confirm-body', + * footerComponent: 'custom-check-confirm-footer' + * }) + * .then(() => {}) + * .catch(() => {}); + * } + * } + * }); + * ``` + * + * #### Title Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.prompt`. + * + * ```hbs + * {{! component/custom-check-confirm-header.hbs}} + * + * ``` + * + * #### Body Component + * + * It takes two parameters. First one is an `options` described before. Second one is an action `updatePromptValue`. It's used to update prompted value in the modal-scope. Usage example: + * + * ```hbs + * {{! components/custom-check-confirm-body.hbs}} + *

Custom Check Confirm Body Component

+ *
+ *
+ * + *
+ *
+ * ``` + * + * #### Footer Component + * + * It takes four parameters. First one is an `options` described before. Second one is a `confirmDisabled`. This flag determines if confirm-button should be disabled. Last two are actions `confirm` and `decline` used as click-handler for "Yes" and "No" buttons. Usage example: + * + * ```hbs + * {{! components/custom-check-confirm-footer.hbs}} + * Custom Check Confirm Footer Component {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} {{#bs-button + * disabled=confirmDisabled onClick=(action confirm) type="primary"}}Confirm{{/bs-button}} + * ``` + * + * ### `promptConfirm` + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showPromptConfirm() { + * get(this, 'modalsManager') + * .promptConfirm({ + * title: 'Prompt Confirm Title', + * body: 'Say "password" and come in', + * footer: 'Prompt Confirm Footer', + * titleComponent: 'custom-prompt-confirm-header', + * bodyComponent: 'custom-prompt-confirm-body', + * footerComponent: 'custom-prompt-confirm-footer', + * promptValue: 'password' // it's required + * }) + * .then(promptValue => {}) + * .catch(() => {}); + * } + * } + * }); + * ``` + * + * #### Title Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.promptConfirm`. + * + * ```hbs + * + * ``` + * + * #### Body Component + * + * It takes two parameters. First one is an `options` described before. Second one is an action `updatePromptValue`. It's used to update prompted value in the modal-scope. Usage example: + * + * ```hbs + * {{! components/custom-prompt-confirm-body.hbs}} + *

+ * {{options.body}} + * Please enter a "{{options.promptValue}}" without quotes + *

+ * + * ``` + * + * #### Footer Component + * + * It takes four parameters. First one is an `options` described before. Second one is a `confirmDisabled`. This flag determines if confirm-button should be disabled. Last two are actions `confirm` and `decline` used as click-handler for "Yes" and "No" buttons. Usage example: + * + * ```hbs + * {{! components/custom-prompt-confirm-footer.hbs}} + * {{options.footer}} + * {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} + * {{#bs-button disabled=confirmDisabled onClick=(action confirm)}}Confirm{{/bs-button}} + * ``` + * + * ### `progress` + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * import {Promise} from 'rsvp'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showPromptConfirm() { + * const modalsManager = get(this, 'modalsManager'); + * modalsManager + * .progress({ + * body: '', + * titleComponent: 'custom-progress-header', + * bodyComponent: 'custom-progress-body', + * footerComponent: 'custom-progress-footer', + * promises: [ // this is required + * () => new Promise(resolve => setTimeout(resolve(1), 100)), + * () => new Promise(resolve => setTimeout(resolve(2), 100)), + * () => new Promise(resolve => setTimeout(resolve(3), 100)) + * ] + * }) + * .then(result => { + * // called after chain of `promises` is executed. + * // here "result" is an array of values for fulfilled promises + * }) + * .catch(([result, error]) => { + * // called when at least one promise is rejected + * // here "result" is an array of already fulfilled promises + * // here "error" is a reason why last promise was rejected + * return modalsManager + * .alert({ + * title: 'Something goes wrong', + * body: `Fulfilled - ${result}. Error - ${JSON.stringify(error)}` + * }); + * }); + * } + * } + * }); + * ``` + * + * #### Title Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.progress`. + * + * ```hbs + * + * ``` + * + * #### Body Component + * + * It takes four parameters. First one is an options described before. Second one is an `overall` - number of `promises` passed to the modal. Third one is a `done` - number of already fulfilled promises. Fourth one is a `progress` - calculated percentage value of the fulfilled promises that me be used in the progress-bar. Usage example: + * + * ```hbs + *

Custom Progress Body Component {{done}} / {{overall}}

+ *{{#bs-progress as |p|}} + * {{p.bar + * value=progress + * showLabel=options.showLabel + * striped=options.striped + * animate=options.animate + * type=options.type + * }} + *{{/bs-progress}} + * ``` + * + * #### Footer Component + * + * It takes one parameter called `options`. It was described before. There are no action-handlers because progress-modal is auto-closed and triggers `decline` and `confirm` by itself and not with user's interaction. + * + * ```hbs + *

Custom Progress Footer Component

+ * ``` + * + * ### `process` + * + * ```js + * import Controller from '@ember/controller'; + * import {inject as service} from '@ember/service'; + * import {get} from '@ember/object'; + * import {Promise} from 'rsvp'; + * + * export default Controller.extend({ + * modalsManager: service(), + * + * actions: { + * showProcessModal() { + * get(this, 'modalsManager') + * .process({ + * bodyComponent: 'custom-process-body', + * headerComponent: 'custom-process-footer', + * footerComponent: 'custom-process-header', + * process: () => new Promise(resolve => setTimeout(resolve(1), 100)) + * }) + * .then(result => {}) + * .catch(error => {}); + * } + * } + * }); + * ``` + * + * #### Title Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.process`. + * + * #### Body Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.process`. + * + * #### Footer Component + * + * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.process`. + * + * @module EmberBootstrapModalsManager + * @main EmberBootstrapModalsManager + */ export default ModalsManager.extend({}); diff --git a/app/services/modals-manager.js b/app/services/modals-manager.js index 8d10abc..9ef56e9 100644 --- a/app/services/modals-manager.js +++ b/app/services/modals-manager.js @@ -1,725 +1 @@ -/** - * ## About - * - * `ember-bootstrap-modals-manager` is an Ember-addon that provides a simple mechanism for interaction with user using modals. This addon is based on modals from `ember-bootstrap`. - * - * **Restriction** from the [Bootstrap#modals](https://getbootstrap.com/docs/3.3/javascript/#modals): - * - * > ##### Multiple open modals not supported - * - * ## Demo - * - * You can check how this addon works on [demo-page](https://onechiporenko.github.io/ember-bootstrap-modals-manager/). - * - * ## Install - * - * **Firstly:** - * - * ```bash - * ember i ember-bootstrap-modals-manager - * ``` - * - * **Secondly:** - * - * Add component `modals-container` to the `application.hbs`: - * - * ```hbs - * {{outlet}} - * {{modals-container}} - * ``` - * - * **Thirdly:** - * - * Inject a service `modals-manager` where you want to use modals: - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * - * export default Controller.extend({ - * modalsManager: service() - * }); - * ``` - * - * That's it. Now you are able to use predefined modals from `modals-manager`. More detailed below. - * - * ### Predefined modals - * - * Every modal described below takes a single parameter. It's a POJO with properties: - * - * * `title` - modals title - * * `body` - modals body message - * * `footer` - text shown near the footer buttons (empty string by default) - * * `confirm` - text for "submit"-button - * * `decline` - text for "decline"-button - * - * You may set default options for all modals with: - * - * ```js - * set(modalsManager, 'defaultOptions', {...}); - * ``` - * - * ### `alert` - * - * Similar to the `window.alert`. It shows modal with a single button. - * - * It's used to notify user about something. - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showAlert() { - * get(this, 'modalsManager') - * .alert({title: 'Alert Title', body: 'Alert Body'}) - * .then(() => { - * // called after user clicks "Yes" in the modal - * }); - * } - * } - * }); - * ``` - * - * ### `confirm` - * - * Similar to the `window.confirm`. It shows modal with two buttons ("Yes" and "No"). - * - * It's used to the ask user about confirmation for some action. - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showConfirm() { - * get(this, 'modalsManager') - * .confirm({title: 'Confirm Title', body: 'Confirm Body'}) - * .then(() => { - * // called after user clicks "Yes" in the modal - * }) - * .catch(() => { - * // called after user clicks "No" in the modal - * }); - * } - * } - * }); - * ``` - * - * ### `prompt` - * - * Similar to the `window.prompt`. It shows modal with two buttons and single input-field. - * - * It's used to get some input from user. - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showPrompt() { - * get(this, 'modalsManager') - * .prompt({title: 'Prompt Title', body: 'Prompt Body'}) - * .then(promptValue => { - * // called after user clicks "Yes" in the modal - * // takes a single argument with user's input value - * }) - * .catch(() => { - * // called after user clicks "No" in the modal - * }); - * } - * } - * }); - * ``` - * - * Extra option `disallowEmpty` with `true`-value will disable Confirm-button until user input at least something: - * - * ```js - * modalsManager.prompt({disallowEmpty: true, title: '', body: ''}); - * ``` - * - * ### `promptConfirm` - * - * Almost the same as `prompt`, however its "Yes"-button is disabled until user write needed value to the input-field. - * - * As a `confirm` it's used to the ask user about confirmation for some action, but it's more demanding. - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showPromptConfirm() { - * get(this, 'modalsManager') - * .promptConfirm({ - * title: 'Prompt Confirm Title', - * body: 'Say "password" and come in', - * promptValue: 'password' // it's required - * }) - * .then(promptValue => { - * // called after user clicks "Yes" in the modal - * // "Yes" will be active only when user prints "password" in the input-field - * // takes a single argument with user input value - * }) - * .catch(() => { - * // called after user clicks "No" in the modal - * }); - * } - * } - * }); - * ``` - * - * ### `checkConfirm` - * - * Almost same as `promptConfirm` however it contains a checkbox instead of text-field. "Yes"-button is disabled until checkbox is not checked. - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showCheckConfirmModal() { - * get(this, 'modalsManager') - * .checkConfirm({ - * title: 'Confirm Title', - * body: 'Confirm your suggestion', - * inputLabel: 'Input Label' - * }) - * .then(() => { - * // called after user clicks "Yes" in the modal - * }) - * .catch(() => { - * // called after user clicks "No" in the modal - * }); - * } - * } - * }); - * ``` - * - * ### `progress` - * - * This modal used to show a progress-bar for chain of Promises executed one by one. This modal doesn't have any controls like confirm/decline-buttons in the footer or "×" in the header and can't be closed by pressing `Esc` or clicking somewhere outside a modal. Modal will be confirmed and self-closed after all promises are fulfilled or it will be declined (and self-closed) if at least one promise becomes rejected. - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * import {Promise} from 'rsvp'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showPromptConfirm() { - * const modalsManager = get(this, 'modalsManager'); - * modalsManager - * .progress({ - * body: '', - * promises: [ // this is required - * () => new Promise(resolve => setTimeout(resolve(1), 100)), - * () => new Promise(resolve => setTimeout(resolve(2), 100)), - * () => new Promise(resolve => setTimeout(resolve(3), 100)) - * ] - * }) - * .then(result => { - * // called after chain of `promises` is executed. - * // here "result" is an array of values for fulfilled promises - * }) - * .catch(([result, error]) => { - * // called when at least one promise is rejected - * // here "result" is an array of already fulfilled promises - * // here "error" is a reason why last promise was rejected - * return modalsManager - * .alert({ - * title: 'Something goes wrong', - * body: `Fulfilled - ${result}. Error - ${JSON.stringify(error)}` - * }); - * }); - * } - * } - * }); - * ``` - * - * Options `striped`, `animate`, `type` and `showLabel` will be passed to the progress-bar. See docs for [ember-bootstrap#progress](http://www.ember-bootstrap.com/#/components/progress) - * - * **IMPORTANT** Here `options.promises` is a list of _FUNCTIONS_ that returns Promises! - * - * ### `process` - * - * This modal is used to show a "placeholder" while some process is running. This modal doesn't have any controls like confirm/decline-buttons in the footer or "×" in the header and can't be closed by pressing Esc or clicking somewhere outside a modal. Modal will be confirmed and self-closed after provided promise (`process`) is fulfilled or it will be declined (and self-closed) if it becomes rejected. - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * import {Promise} from 'rsvp'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showProcessModal() { - * get(this, 'modalsManager') - * .process({ - * body: 'Some text goes here', - * iconClass: 'text-center fa fa-spinner fa-spin fa-3x fa-fw', - * title: '', - * // this is required - * process: () => new Promise(resolve => setTimeout(resolve(1), 100)) - * }) - * .then(result => { - * // called after `process` is resolved - * // here "result" is value of fulfilled Promise - * }) - * .catch(error => { - * // called after `process` is rejected - * // here "error" is a reason why last promise was rejected - * }); - * } - * } - * }); - * ``` - * - * **IMPORTANT** Here `options.process` is a _FUNCTION_ that return Promise! - * - * ## Go Pro - * - * ### Custom components for `title`, `body` and `footer` - * - * Every modal-port like header, body and footer may be customized not only with message and even with a Component. - * - * ### `alert` - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showAlert() { - * get(this, 'modalsManager') - * .alert({ - * titleComponent: 'custom-alert-title', - * title: 'Title', - * bodyComponent: 'custom-alert-body', - * body: 'Body', - * footerComponent: 'custom-alert-footer', - * footer: 'Footer' - * }) - * .then(() => {}); - * } - * } - * }); - * ``` - * - * #### Title Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.alert`. - * - * ```hbs - * {{! components/custom-alert-header.hbs}} - * - * ``` - * - * #### Body Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.alert`. - * - * ```hbs - * {{! components/custom-alert-body.hbs}} - *

{{options.body}}

- * ``` - * - * #### Footer Component - * - * It takes two parameters. First one is an `options` described before. Second one is an action `confirm` used to confirm modal. It may be used like: - * - * ```hbs - * {{! components/custom-alert-footer.hbs}} - * {{options.footer}} - * {{#bs-button onClick=(action confirm)}}Confirm{{/bs-button}} - * ``` - * - * ### `confirm` - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showConfirm() { - * get(this, 'modalsManager') - * .confirm({ - * title: 'Confirm Title', - * body: 'Confirm Body', - * footer: 'Confirm Footer', - * titleComponent: 'custom-confirm-title', - * bodyComponent: 'custom-confirm-body', - * footerComponent: 'custom-confirm-footer' - * }) - * .then(() => {}) - * .catch(() => {}); - * } - * } - * }); - * ``` - * - * #### Title Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.confirm`. - * - * ```hbs - * {{! components/custom-confirm-title.hbs}} - * - * ``` - * - * #### Body Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.confirm`. - * - * ```hbs - * {{! components/custom-confirm-body.hbs}} - *

{{options.body}}

- * ``` - * - * #### Footer Component - * - * It takes three parameters. First on is an `options` described before. Second one is an action `confirm` used to confirm modal. Third one is an action `decline` used to decline modal. Both of them may be used like: - * - * ```hbs - * {{! components/custom-confirm-footer.hbs}} - * {{options.footer}} - * {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} - * {{#bs-button onClick=(action confirm)}}Confirm{{/bs-button}} - * ``` - * - * ### `prompt` - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showPrompt() { - * get(this, 'modalsManager') - * .prompt({ - * title: 'Prompt Title', - * body: 'Prompt Body', - * footer: 'Prompt Footer', - * titleComponent: 'custom-prompt-header', - * bodyComponent: 'custom-prompt-body', - * footerComponent: 'custom-prompt-footer' - * }) - * .then(promptValue => {}) - * .catch(() => {}); - * } - * } - * }); - * ``` - * - * #### Title Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.prompt`. - * - * ```hbs - * {{! component/custom-prompt-header.hbs}} - * - * ``` - * - * #### Body Component - * - * It takes two parameters. First one is an `options` described before. Second one is an action `updatePromptValue`. It's used to update prompted value in the modal-scope. Usage example: - * - * ```hbs - * {{! components/custom-prompt-body.hbs}} - *

{{options.body}}

- * - * ``` - * - * #### Footer Component - * - * It takes three parameters. First on is an `options` described before. Second one is an action `confirm` used to confirm modal. Third one is an action `decline` used to decline modal. Both of them may be used like: - * - * ```hbs - * {{! components/custom-prompt-footer.hbs}} - * {{options.footer}} - * {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} - * {{#bs-button onClick=(action confirm)}}Confirm{{/bs-button}} - * ``` - * - * ### `checkConfirm` - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showCheckConfirm() { - * get(this, 'modalsManager') - * .checkConfirm({ - * title: 'Check Confirm Title', - * footer: 'Prompt Confirm Footer', - * titleComponent: 'custom-check-confirm-header', - * bodyComponent: 'custom-check-confirm-body', - * footerComponent: 'custom-check-confirm-footer' - * }) - * .then(() => {}) - * .catch(() => {}); - * } - * } - * }); - * ``` - * - * #### Title Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.prompt`. - * - * ```hbs - * {{! component/custom-check-confirm-header.hbs}} - * - * ``` - * - * #### Body Component - * - * It takes two parameters. First one is an `options` described before. Second one is an action `updatePromptValue`. It's used to update prompted value in the modal-scope. Usage example: - * - * ```hbs - * {{! components/custom-check-confirm-body.hbs}} - *

Custom Check Confirm Body Component

- *
- *
- * - *
- *
- * ``` - * - * #### Footer Component - * - * It takes four parameters. First one is an `options` described before. Second one is a `confirmDisabled`. This flag determines if confirm-button should be disabled. Last two are actions `confirm` and `decline` used as click-handler for "Yes" and "No" buttons. Usage example: - * - * ```hbs - * {{! components/custom-check-confirm-footer.hbs}} - * Custom Check Confirm Footer Component {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} {{#bs-button - * disabled=confirmDisabled onClick=(action confirm) type="primary"}}Confirm{{/bs-button}} - * ``` - * - * ### `promptConfirm` - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showPromptConfirm() { - * get(this, 'modalsManager') - * .promptConfirm({ - * title: 'Prompt Confirm Title', - * body: 'Say "password" and come in', - * footer: 'Prompt Confirm Footer', - * titleComponent: 'custom-prompt-confirm-header', - * bodyComponent: 'custom-prompt-confirm-body', - * footerComponent: 'custom-prompt-confirm-footer', - * promptValue: 'password' // it's required - * }) - * .then(promptValue => {}) - * .catch(() => {}); - * } - * } - * }); - * ``` - * - * #### Title Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.promptConfirm`. - * - * ```hbs - * - * ``` - * - * #### Body Component - * - * It takes two parameters. First one is an `options` described before. Second one is an action `updatePromptValue`. It's used to update prompted value in the modal-scope. Usage example: - * - * ```hbs - * {{! components/custom-prompt-confirm-body.hbs}} - *

- * {{options.body}} - * Please enter a "{{options.promptValue}}" without quotes - *

- * - * ``` - * - * #### Footer Component - * - * It takes four parameters. First one is an `options` described before. Second one is a `confirmDisabled`. This flag determines if confirm-button should be disabled. Last two are actions `confirm` and `decline` used as click-handler for "Yes" and "No" buttons. Usage example: - * - * ```hbs - * {{! components/custom-prompt-confirm-footer.hbs}} - * {{options.footer}} - * {{#bs-button onClick=(action decline)}}Decline{{/bs-button}} - * {{#bs-button disabled=confirmDisabled onClick=(action confirm)}}Confirm{{/bs-button}} - * ``` - * - * ### `progress` - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * import {Promise} from 'rsvp'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showPromptConfirm() { - * const modalsManager = get(this, 'modalsManager'); - * modalsManager - * .progress({ - * body: '', - * titleComponent: 'custom-progress-header', - * bodyComponent: 'custom-progress-body', - * footerComponent: 'custom-progress-footer', - * promises: [ // this is required - * () => new Promise(resolve => setTimeout(resolve(1), 100)), - * () => new Promise(resolve => setTimeout(resolve(2), 100)), - * () => new Promise(resolve => setTimeout(resolve(3), 100)) - * ] - * }) - * .then(result => { - * // called after chain of `promises` is executed. - * // here "result" is an array of values for fulfilled promises - * }) - * .catch(([result, error]) => { - * // called when at least one promise is rejected - * // here "result" is an array of already fulfilled promises - * // here "error" is a reason why last promise was rejected - * return modalsManager - * .alert({ - * title: 'Something goes wrong', - * body: `Fulfilled - ${result}. Error - ${JSON.stringify(error)}` - * }); - * }); - * } - * } - * }); - * ``` - * - * #### Title Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.progress`. - * - * ```hbs - * - * ``` - * - * #### Body Component - * - * It takes four parameters. First one is an options described before. Second one is an `overall` - number of `promises` passed to the modal. Third one is a `done` - number of already fulfilled promises. Fourth one is a `progress` - calculated percentage value of the fulfilled promises that me be used in the progress-bar. Usage example: - * - * ```hbs - *

Custom Progress Body Component {{done}} / {{overall}}

- *{{#bs-progress as |p|}} - * {{p.bar - * value=progress - * showLabel=options.showLabel - * striped=options.striped - * animate=options.animate - * type=options.type - * }} - *{{/bs-progress}} - * ``` - * - * #### Footer Component - * - * It takes one parameter called `options`. It was described before. There are no action-handlers because progress-modal is auto-closed and triggers `decline` and `confirm` by itself and not with user's interaction. - * - * ```hbs - *

Custom Progress Footer Component

- * ``` - * - * ### `process` - * - * ```js - * import Controller from '@ember/controller'; - * import {inject as service} from '@ember/service'; - * import {get} from '@ember/object'; - * import {Promise} from 'rsvp'; - * - * export default Controller.extend({ - * modalsManager: service(), - * - * actions: { - * showProcessModal() { - * get(this, 'modalsManager') - * .process({ - * bodyComponent: 'custom-process-body', - * headerComponent: 'custom-process-footer', - * footerComponent: 'custom-process-header', - * process: () => new Promise(resolve => setTimeout(resolve(1), 100)) - * }) - * .then(result => {}) - * .catch(error => {}); - * } - * } - * }); - * ``` - * - * #### Title Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.process`. - * - * #### Body Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.process`. - * - * #### Footer Component - * - * It takes a single parameter `options`. Its value is an object passed to the `modalsManager.process`. - * - * @module EmberBootstrapModalsManager - * @main EmberBootstrapModalsManager - */ - export { default } from 'ember-bootstrap-modals-manager/services/modals-manager'; diff --git a/package-lock.json b/package-lock.json index ae9531d..c39adcd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ember-bootstrap-modals-manager", - "version": "1.4.0-alpha.3", + "version": "1.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d75aaf4..db699b6 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,10 @@ { "name": "ember-bootstrap-modals-manager", - "version": "1.4.0-alpha.3", + "version": "1.4.0", "description": "Modals-manager for modals from ember-bootstrap", "keywords": [ + "bootstrap", + "modal", "ember-addon" ], "license": "MIT",