UNPKG

@bennerinformatics/ember-fw-gc

Version:

A set of components, controllers, routes, and helpers used in all Group-Control managed FW App System applications

190 lines (170 loc) 6.38 kB
import Component from '@ember/component'; import EmberError from '@ember/error'; import {computed} from '@ember/object'; import {inject} from '@ember/service'; import {isEmpty, isNone} from '@ember/utils'; import layout from '../templates/components/fw-app-link'; /** * This component is used to create a link to another FW app. It is used similarly to the Ember `LinkTo` helper. * * To use inline, parameters must be provided for the link name, the app ID, and the route name. * An optional query parameters object can be added at the end. See the [Ember docs](https://guides.emberjs.com/v3.12.0/templates/links/#toc_setting-query-params) for more information on query params * * ```handlebars * <FwAppLink @title='Link Text' @appId='appId' @route='route.name' /> * <FwAppLink @title='Link Text' @appId='appId' @route='route.name' @query={{hash key=value}} /> * ``` * * When used in block format, the block contents are used in place of link text, so the first parameter is the app ID. * An optional block parameter is passed containing the app metadata: * * ```handlebars * <FwAppLink @appId='appId' @route='route.name' as |app|> * <i>{{app.name}}</i> * </FwAppLink> * <FwAppLink @appId='appId' @route='route.name' @query={{hash key=value}}> * <i>Block text</i> * </FwAppLink> * ``` * * If the app is missing or the user does not have access to the app, no HTML will be rendered. * Use the `has-app` helper to show content when the app is missing. * * @public * @class FwAppLink * @extends Ember.Component * @module Components */ const FWAppLink = Component.extend({ layout, tagName: '', appMeta: inject(), currentUser: inject(), /** * Dynamic parameters array. ***This is deprecated and should not be used. Specify all your parameters*** * @property params * @type {Array} * @deprecated */ /** * Link title, will be null in block form * @property title * @type {String} */ title: null, /** * Shortcode of app * @property appId * @type {String} */ appId: null, /** * Route within the app you are linking to * @property route * @type {String} */ route: '', /** * App meta object for the related app. Will be null if the app is not found. Set by `didReceiveAttrs`. * @property app * @type {EmberObject} * @private */ app: null, /** * This is deprecated. Query parameters for the link. It was set if using the params array and * passed query params using the `query-params` helper, but the preferred method is using the `@query` * property, as is described [here](https://guides.emberjs.com/release/routing/query-params/#toc_linkto--component) * * @property queryParams * @type {Object} * @deprecated * @private */ queryParams: null, /** * Computed property of URL encoded query params. This is again deprecated as it relies on the `params` order of the old way * rather than specified values, as is with the new syntax. * @property queryString * @type {Computed String} * @deprecated * @private */ queryString: computed('queryParams', function() { // make sure we have a query object and its not empty let query = this.get('queryParams'); if (isNone(query)) { return ''; } let keys = Object.keys(query); if (isEmpty(keys)) { return ''; } // convert all query params into a query string return `?${keys.map((key) => `${key}=${encodeURIComponent(query[key])}`).join('&')}`; }), /** * Computed property of link URL within the other app. * @property url * @type {Computed String} * @private */ url: computed('route', 'app.urlClean', 'queryString', function() { if (!this.get('app')) { return null; } let route = this.get('route').replace(/\./g, '/'); return `${this.get('app.urlClean')}/#/${route}${this.get('queryString')}`; }), /** * All this stuff about params is deprecated and just there for backwards compatibility. Don't remove, * but you really shouldn't be using the params attribute in any other app. */ didReceiveAttrs() { this._super(...arguments); let appId = this.get('appId'); if (appId && this.get('currentUser.apps').includes(appId)) { this.get('appMeta').findMeta(appId).then((meta) => { this.set('app', meta); }); } // parse params let params = this.get('params'); if (params) { let len = params.length; // query params is the last parameter, fetch that first let lastParam = params[len - 1]; if (lastParam && lastParam.isQueryParams) { len--; this.set('queryParams', lastParam.values); } // no parameters remaining means no app if (len === 0) { throw new EmberError('App must be defined for FW App Link'); } // if we have 3 parameters, the first is the title // ideally would check for HAS_BLOCK here, but Ember does not give access to that let next = 0; if (len >= 3) { this.set('title', params[next++]); } // next, fetch the app off the params, always defined let appId = params[next++]; // skip fetching if we lack permissions, link will be no good if (this.get('currentUser.apps').includes(appId)) { this.get('appMeta').findMeta(appId).then((meta) => { this.set('app', meta); }); } // finally, fetch the route if provided // this is optional in block format, but required in inline due to no HAS_BLOCK if (len >= 2) { this.set('route', params[next++]); } } } }); FWAppLink.reopenClass({ positionalParams: 'params' }); export default FWAppLink;