@soleil-se/app-util 1.2.4 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [2.1.0] - 2020-02-14
8
+ ### Added
9
+ - App data import in client, `@soleil-api/webapp-util/app-data`.
10
+ - `getViewUri` to get the URI that also renders the page.
11
+ - `isOnline` to see if the app is online.
12
+
13
+ ### Changed
14
+ - `vue` is now an optional depedency.
15
+
16
+ ## [2.0.0] - 2020-02-12
17
+ ### Changed
18
+ - Now using `currentScript` to reference the script element the app is running in to pass data when using `renderApp`.
19
+ - `renderApp` is no longer using appName.
20
+ - `render` is now called directly in `./app_src/client/index.js`.
21
+ - `render` and `App` no longer needs to be exported from `./app_src/client/index.js`.
22
+
23
+ ## [1.2.4] - 2020-12-12
24
+ ### Fixed
25
+ - `TypeError: Cannot call method getIdentifier of null` when app is viewed in Addons.
26
+
27
+ ## [1.2.2] - 2019-05-20
28
+ ### Fixed
29
+ - Removed `_sitePage` from `currentPageId` in `getRouteUri`.
30
+
31
+ ## [1.2.1] - 2019-05-09
32
+ ### Added
33
+ - Added timestamp to WebApp script tag to prevent cache when uploading a new version.
34
+
35
+ ## [1.2.0] - 2019-05-07
36
+ ### Changed
37
+ - `getRouteUri` now returns the standalone route.
38
+ - HTML comment to not include this.name in `renderApp`.
39
+
package/README.md CHANGED
@@ -1,108 +1,157 @@
1
- # Webapp Util
2
- Utility functions for Webapps.
3
- ## Install
4
- `yarn add @soleil-se/webapp-util`
5
-
6
- ## Usage
7
- ```javascript
8
- import { renderApp, getRouteUri, getResourceUri, renderTemplate, isOffline } from '@soleil-se/webapp-util';
9
- ```
10
- ### `renderApp(name, [data], [settings])` ⇒ `String`
11
- Get HTML string for rendering an application.
12
- To be used together with `@soleil-se/webapp-util/render-vue` or a custom render function in the client code.
13
-
14
- **Returns**: <code>String</code> - HTML for rendering an application.
15
-
16
- | Param | Type | Default | Description |
17
- | --- | --- | --- | --- |
18
- | name | <code>String</code> | | Name of the app, has to match the name of the application. |
19
- | [data] | <code>Object</code> | <code>{}</code> | Server data that will be available in the app. In Vue it will be available in the `$options` object. |
20
- | [settings] | <code>Object</code> | <code>{}</code> | Settings object. |
21
- | [settings.noScript] | <code>String</code> | <code>&#x27;&#x27;</code> | HTML that will be rendered when JavaScript is not available. |
22
- | [settings.selector] | <code>String</code> | <code>&#x60;[data-portlet-id&#x3D;&quot;${portletId}&quot;]&#x60;</code> | Query selector for where the app should be mounted. |
23
- | [settings.async] | <code>Boolean</code> | <code>true</code> | If the app script should be loaded asynchronously. [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/) |
24
- | [settings.defer] | <code>Boolean</code> | <code>false</code> | If the app script should be loaded after DOM is ready. [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/) |
25
-
26
- #### Example
27
- In `app_src/server/index.js`.
28
- ```javascript
29
- router.get('/', (req, res) => {
30
- // Most common usage.
31
- res.send(renderApp('AppName', data));
32
-
33
- // With all settings.
34
- res.send(renderApp('AppName', data, {
35
- noScript: 'You need JS for this!',
36
- selector: '#mount_me_here',
37
- async: false,
38
- defer: true,
39
- }));
40
- });
41
- ```
42
- ##### **Vue**
43
- In `app_src/client/index.js`.
44
- ```javascript
45
- import render from '@soleil-se/webapp-util/render-vue';
46
- import App from './App.vue';
47
-
48
- window.Soleil.webapps[App.name] = {
49
- App,
50
- render,
51
- };
52
-
53
- // If your application name matches the folder name of your Webapp you can use the default export.
54
- export default {
55
- App,
56
- render,
57
- };
58
- ```
59
- ### `getRouteUri(route)` ⇒ `String`
60
- Get URI for a route.
61
-
62
- **Returns**: `String` - URI for route.
63
-
64
- | Param | Type | Description |
65
- | --- | --- | --- |
66
- | route | `String` | A route. |
67
-
68
- #### Example
69
- ```javascript
70
- const routeUri = getRouteUri('/my-route');
71
- ```
72
- ### `getResourceUri(resource)` `String`
73
- Get URI for a resource.
74
-
75
- **Returns**: `String` - URI for a resource.
76
-
77
- | Param | Type | Description |
78
- | --- | --- | --- |
79
- | resource | `String` | A resource. |
80
-
81
- #### Example
82
- ```javascript
83
- const resourceUri = getResourceUri('file/in/resource.png');
84
- ```
85
- ### `renderTemplate(template, [values])` `String`
86
- Renders a Underscore template and returns a string.
87
-
88
- **Returns**: `String` - Rendered template
89
-
90
- | Param | Type | Default | Description |
91
- | --- | --- | --- | --- |
92
- | template | `String` | | Underscore template. |
93
- | [values] | `Object` | `{}` | Values. |
94
-
95
- #### Example
96
- ```javascript
97
- const string = renderTemplate('<div><%= foo %></div>', {
98
- foo: 'bar',
99
- });
100
- ```
101
- ### `isOffline`
102
- If the webapp is running in offline mode or not.
103
-
104
- ```javascript
105
- if(isOffline) {
106
- // Do something
107
- }
108
- ```
1
+ # Webapp Util
2
+ Utility functions for Webapps.
3
+ ## Install
4
+ `yarn add @soleil-se/webapp-util`
5
+
6
+ ## Changelog
7
+ [See changelog](CHANGELOG.md).
8
+
9
+ ## Migration 1.x.x to 2.x.x
10
+
11
+ Now using `currentScript` to reference the script element the app is running in to pass data.
12
+
13
+ Remove appName from the `renderApp` call in `./app_src/server/index.js`.
14
+ Remove export of `App` and `render` and replace with a call to `render(App)` in `./app_src/client/index.js`.
15
+
16
+ See [example](#example).
17
+
18
+ ## Usage
19
+ ```javascript
20
+ import { renderApp, getRouteUri, getResourceUri, renderTemplate, isOffline } from '@soleil-se/webapp-util';
21
+ ```
22
+ ### `renderApp([config], [settings])` `String`
23
+ Get HTML string for rendering an application.
24
+ Can be used together with `@soleil-se/webapp-util/render-vue` or a custom render function in the client code.
25
+
26
+ **Returns**: <code>String</code> - HTML for rendering an application.
27
+
28
+ | Param | Type | Default | Description |
29
+ | --- | --- | --- | --- |
30
+ | [config] | <code>Object</code> | <code>{}</code> | Server config or data that will be available in the attribute `data-app` on currentScript. In Vue it will also be available in the `$options` object. |
31
+ | [settings] | <code>Object</code> | <code>{}</code> | Settings object. |
32
+ | [settings.noScript] | <code>String</code> | <code>&#x27;&#x27;</code> | HTML that will be rendered when JavaScript is not available. |
33
+ | [settings.selector] | <code>String</code> | <code>&#x60;[data-portlet-id&#x3D;&quot;${portletId}&quot;]&#x60;</code> | Query selector for where the app should be mounted. |
34
+ | [settings.async] | <code>Boolean</code> | <code>false</code> | If the app script should be loaded asynchronously. [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/) |
35
+ | [settings.defer] | <code>Boolean</code> | <code>true</code> | If the app script should be loaded after DOM is ready. [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/) |
36
+
37
+ #### Example
38
+ In `app_src/server/index.js`.
39
+ ```javascript
40
+ router.get('/', (req, res) => {
41
+ const data = { foo: 'bar' };
42
+ // Most common usage.
43
+ res.send(renderApp(data));
44
+
45
+ // With all settings.
46
+ res.send(renderApp(data, {
47
+ noScript: 'You need JS for this!',
48
+ selector: '#mount_me_here',
49
+ async: false,
50
+ defer: true,
51
+ }));
52
+ });
53
+ ```
54
+ ##### **Vue**
55
+ In `app_src/client/index.js`.
56
+ ```javascript
57
+ import render from '@soleil-se/webapp-util/render-vue';
58
+ import App from './App.vue';
59
+
60
+ render(App);
61
+ ```
62
+
63
+ ##### **App data**
64
+ If you need to use the data that is available for the App you can use `@soleil-se/webapp-util/app-data`.
65
+
66
+ For example when you need a route URI from the server:
67
+ ```javascript
68
+ import AppData from '@soleil-se/webapp-util/app-data';
69
+ import superagent from 'superagent';
70
+
71
+ const searchThings = async (query) => {
72
+ const { body } = await superagent
73
+ .get(AppData.searchRoute)
74
+ .query({ query });
75
+ return body;
76
+ };
77
+
78
+ export default searchThings;
79
+ ```
80
+
81
+ ## `getRouteUri(route)` ⇒ `String`
82
+ Get URI for a route, same as `getStandaloneUrl` in SiteVision template.
83
+ https://developer.sitevision.se/docs/webapps/template#h-Methods
84
+
85
+ **Returns**: <code>String</code> - URI for route.
86
+
87
+ | Param | Type | Description |
88
+ | --- | --- | --- |
89
+ | route | <code>String</code> | A route. |
90
+
91
+
92
+ #### Example
93
+ ```javascript
94
+ const routeUri = getRouteUri('/my-route');
95
+ ```
96
+ ## `getViewUri(route)` ⇒ `String`
97
+ Get URI for a view, same as `getUrl` in SiteVision template.
98
+ https://developer.sitevision.se/docs/webapps/template#h-Methods
99
+
100
+ **Returns**: <code>String</code> - URI for view.
101
+
102
+ | Param | Type | Description |
103
+ | --- | --- | --- |
104
+ | route | <code>String</code> | A route. |
105
+
106
+ #### Example
107
+ ```javascript
108
+ const viewUri = getViewUri('/my-route');
109
+ ```
110
+
111
+ ### `getResourceUri(resource)` ⇒ `String`
112
+ Get URI for a resource.
113
+
114
+ **Returns**: `String` - URI for a resource.
115
+
116
+ | Param | Type | Description |
117
+ | --- | --- | --- |
118
+ | resource | `String` | A resource. |
119
+
120
+
121
+ #### Example
122
+ ```javascript
123
+ const resourceUri = getResourceUri('file/in/resource.png');
124
+ ```
125
+ ### `renderTemplate(template, [values])` ⇒ `String`
126
+ Renders a Underscore template and returns a string.
127
+
128
+ **Returns**: `String` - Rendered template
129
+
130
+ | Param | Type | Default | Description |
131
+ | --- | --- | --- | --- |
132
+ | template | `String` | | Underscore template. |
133
+ | [values] | `Object` | `{}` | Values. |
134
+
135
+ #### Example
136
+ ```javascript
137
+ const string = renderTemplate('<div><%= foo %></div>', {
138
+ foo: 'bar',
139
+ });
140
+ ```
141
+ ### `isOffline`
142
+ If the webapp is running in offline mode or not.
143
+
144
+ ```javascript
145
+ if(isOffline) {
146
+ // Do something
147
+ }
148
+ ```
149
+
150
+ ### `isOnline`
151
+ If the webapp is running in online mode or not.
152
+
153
+ ```javascript
154
+ if(isOnline) {
155
+ // Do something
156
+ }
157
+ ```
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "@soleil/eslint-config-sitevision/client",
3
+ "root": true
4
+ }
@@ -0,0 +1,7 @@
1
+ import { parseAttribute } from '../attribute-util';
2
+
3
+ /**
4
+ * Get appData from the currentScript element.
5
+ * @returns {Object} AppData.
6
+ */
7
+ export default parseAttribute('data-app');
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "@soleil/eslint-config-sitevision/client",
3
+ "root": true
4
+ }
@@ -0,0 +1,22 @@
1
+ const { currentScript } = document;
2
+ /**
3
+ * JSON decode an attribute on the currentScript element.
4
+ * Use if attribute contains a JSON-object.
5
+ * @param {String} attribute Attribute to decode.
6
+ * @returns {Object} Decoded JSON object.
7
+ */
8
+ export const decodeAttribute = (attribute) => {
9
+ const encoded = currentScript.getAttribute(attribute);
10
+ if (encoded) {
11
+ return decodeURIComponent(encoded);
12
+ }
13
+ return undefined;
14
+ };
15
+
16
+ /**
17
+ * Parse an attribute on the currentScript element.
18
+ * Us if the attribute is a String.
19
+ * @param {String} attribute
20
+ * @returns {String} Parsed attribute value.
21
+ */
22
+ export const parseAttribute = (attribute) => JSON.parse(decodeAttribute(attribute));
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@soleil-se/app-util",
3
- "version": "1.2.4",
3
+ "version": "2.1.0",
4
4
  "description": "Utility functions for Webapps.",
5
- "main": "./dist/index.js",
5
+ "main": "./src/index.js",
6
6
  "author": "Soleil AB",
7
7
  "contributors": [
8
8
  "Kimmy Monassar",
@@ -11,11 +11,11 @@
11
11
  "license": "UNLICENSED",
12
12
  "private": false,
13
13
  "homepage": "https://github.com/soleilit/server-monorepo/tree/master/packages/app-util",
14
- "scripts": {
15
- "build": "yarn build-server && yarn build-render-vue",
16
- "build-server": "npx buble ./src/index.js --output ./dist/index.js --no modules,arrow --objectAssign=Object.assign",
17
- "build-render-vue": "npx buble ./render-vue/src/index.js --output ./render-vue/index.js --no modules --objectAssign=Object.assign"
14
+ "dependencies": {
15
+ "current-script-polyfill": "^1.0.0"
16
+ },
17
+ "optionalDependencies": {
18
+ "vue": "^2.6.11"
18
19
  },
19
- "dependencies": {},
20
20
  "devDependencies": {}
21
21
  }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "@soleil/eslint-config-sitevision/client",
3
+ "root": true
4
+ }
@@ -1,43 +1,41 @@
1
- /* eslint-disable-next-line import/no-unresolved */
2
- import Vue from 'vue';
3
-
4
- window.Soleil = window.Soleil || {};
5
- window.Soleil.webapps = window.Soleil.webapps || {};
6
-
7
- var offlineModeMixin = {
8
- mounted: function mounted() {
9
- if (this.$options.isOffline) {
10
- var $anchors = this.$el.querySelectorAll('a');
11
- $anchors.forEach(function ($anchor) {
12
- $anchor.addEventListener('click', function (e) {
13
- e.preventDefault();
14
- window.$svjq($anchor).trigger('click');
15
- }, false);
16
- });
17
- }
18
- },
19
- };
20
- /**
21
- * Render a Vue application
22
- * @param {String} name Name of the application, has to match both on server and client.
23
- * @param {String} selector Selector for element where the app should be mounted.
24
- * @param {Object} [options={}] Options for `$options`.
25
- */
26
- export default function render(name, selector, options) {
27
- if ( options === void 0 ) options = {};
28
-
29
- var ref = window.Soleil.webapps[name];
30
- var App = ref.App;
31
- Object.assign(App, options, {
32
- mixins: [offlineModeMixin],
33
- });
34
-
35
- var mountElementExists = !!document.querySelector(selector);
36
- if (mountElementExists) {
37
- new Vue(App).$mount(selector);
38
- } else {
39
- document.addEventListener('DOMContentLoaded', function () {
40
- new Vue(App).$mount(selector);
41
- });
42
- }
43
- }
1
+ import 'current-script-polyfill';
2
+ import Vue from 'vue';
3
+
4
+ import { decodeAttribute } from '../attribute-util';
5
+ import appData from '../app-data';
6
+
7
+ const offlineModeMixin = {
8
+ mounted() {
9
+ if (this.$options.isOffline) {
10
+ const $anchors = this.$el.querySelectorAll('a');
11
+ $anchors.forEach(($anchor) => {
12
+ $anchor.addEventListener('click', (e) => {
13
+ e.preventDefault();
14
+ window.$svjq($anchor).trigger('click');
15
+ }, false);
16
+ });
17
+ }
18
+ },
19
+ };
20
+ /**
21
+ * Render a Vue application
22
+ * @param {Vue} App Vue application to be started.
23
+ */
24
+ export default function render(App) {
25
+ const selector = decodeAttribute('data-selector');
26
+ const options = appData;
27
+
28
+ Object.assign(App, options, {
29
+ mixins: [offlineModeMixin],
30
+ });
31
+
32
+ const mountElementExists = !!document.querySelector(selector);
33
+
34
+ if (mountElementExists) {
35
+ new Vue(App).$mount(selector);
36
+ } else {
37
+ document.addEventListener('DOMContentLoaded', () => {
38
+ new Vue(App).$mount(selector);
39
+ });
40
+ }
41
+ }
package/src/index.js CHANGED
@@ -1,100 +1,117 @@
1
- import PortletContextUtil from 'PortletContextUtil';
2
- import VersionUtil from 'VersionUtil';
3
- import appInfo from 'appInfo';
4
- /* Underscore is provided by SiteVision */
5
- /* eslint-disable-next-line import/no-extraneous-dependencies */
6
- import _ from 'underscore';
7
-
8
- /** If the webapp is running in offline mode or not. */
9
- export const isOffline = VersionUtil.getCurrentVersion() === VersionUtil.OFFLINE_VERSION;
10
-
11
- const currentPortlet = PortletContextUtil.getCurrentPortlet();
12
- const portletId = currentPortlet ? currentPortlet.getIdentifier().replace('.', '_') : '';
13
-
14
- /**
15
- * Get URI for a resource.
16
- * @param {String} resource A resource.
17
- * @returns {String} URI for a resource.
18
- */
19
- export function getResourceUri(resource) {
20
- return `/webapp-files/${appInfo.appIdentifier}/${appInfo.appVersion}/${resource}`;
21
- }
22
-
23
- /**
24
- * Renders a Underscore template and returns a string.
25
- * @param {String} template Underscore template.
26
- * @param {Object} [values={}] Values.
27
- * @returns {String} Rendered template
28
- */
29
- export function renderTemplate(template, values = {}) {
30
- if (typeof template === 'function') {
31
- return template(values);
32
- }
33
- return _.template(template)(values);
34
- }
35
-
36
- /**
37
- * Get HTML string for rendering an application.
38
- * @param {String} name Name of the app, has to match the name of the application.
39
- * @param {Object} [data={}] Server data that will be available in the app.
40
- * In Vue it will be available in the `$options` object.
41
- * @param {Object} [settings={}] Settings object.
42
- * @param {String} [settings.noScript=''] HTML that will be rendered when JavaScript
43
- * is not available.
44
- * @param {String} [settings.selector=`[data-portlet-id="${portletId}"]`] Query selector for
45
- * where the app should be mounted.
46
- * @param {Boolean} [settings.async=true] If the app script should be loaded asynchronously.
47
- * [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
48
- * @param {Boolean} [settings.defer=false] If the app script should be loaded after DOM is ready.
49
- * [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
50
- * @returns {String} HTML for rendering an application.
51
- */
52
- export function renderApp(name, data, {
53
- noScript = '',
54
- selector = `[data-portlet-id="${portletId}"]`,
55
- async = true,
56
- defer = false,
57
- } = {}) {
58
- const options = { ...data, isOffline };
59
- const clientUri = getResourceUri('client/index.js');
60
-
61
- if (isOffline) {
62
- return `
63
- <!-- Generated by WebappUtil.renderApp() -->
64
- <div data-portlet-id="${portletId}">${noScript}</div>
65
- <script src="${clientUri}?${appInfo.appImportDate}"></script>
66
- <script>
67
- Soleil.webapps['${name}'].render('${name}', '${selector}', ${JSON.stringify(options)});
68
- </script>
69
- `;
70
- }
71
- return `
72
- <!-- Generated by WebappUtil.renderApp() -->
73
- <div data-portlet-id="${portletId}">${noScript}</div>
74
- <script>
75
- function renderApp${portletId}() {
76
- Soleil.webapps['${name}'].render('${name}', '${selector}', ${JSON.stringify(options)});
77
- }
78
- </script>
79
- <script src="${clientUri}?${appInfo.appImportDate}" ${async && !defer ? 'async' : ''} ${defer ? 'defer' : ''} onload="renderApp${portletId}();"></script>
80
- `;
81
- }
82
-
83
- /**
84
- * Get URI for a route.
85
- * @param {String} route A route.
86
- * @returns {String} URI for route.
87
- */
88
- export function getRouteUri(route) {
89
- const currentPageId = PortletContextUtil.getCurrentPage().getIdentifier().replace('_sitePage', '');
90
- const currentPortletId = PortletContextUtil.getCurrentPortlet().getIdentifier();
91
- return `/appresource/${currentPageId}/${currentPortletId}/${route}`.replace(/\/\//g, '/');
92
- }
93
-
94
- export default {
95
- getRouteUri,
96
- getResourceUri,
97
- renderApp,
98
- renderTemplate,
99
- isOffline,
100
- };
1
+ import PortletContextUtil from 'PortletContextUtil';
2
+ import PropertyUtil from 'PropertyUtil';
3
+ import VersionUtil from 'VersionUtil';
4
+ import appInfo from 'appInfo';
5
+ /* Underscore is provided by SiteVision */
6
+ /* eslint-disable-next-line import/no-extraneous-dependencies */
7
+ import _ from 'underscore';
8
+
9
+ /** If the webapp is running in offline mode or not. */
10
+ export const isOffline = VersionUtil.getCurrentVersion() === VersionUtil.OFFLINE_VERSION;
11
+ /** If the webapp is running in online mode or not. */
12
+ export const isOnline = !isOffline;
13
+
14
+ const currentPortlet = PortletContextUtil.getCurrentPortlet();
15
+ const portletId = currentPortlet ? currentPortlet.getIdentifier().replace('.', '_') : '';
16
+
17
+ /**
18
+ * Get URI for a resource.
19
+ * @param {String} resource A resource.
20
+ * @returns {String} URI for a resource.
21
+ */
22
+ export function getResourceUri(resource) {
23
+ return `/webapp-files/${appInfo.appIdentifier}/${appInfo.appVersion}/${resource}`;
24
+ }
25
+
26
+ /**
27
+ * Renders a Underscore template and returns a string.
28
+ * @param {String} template Underscore template.
29
+ * @param {Object} [values={}] Values.
30
+ * @returns {String} Rendered template
31
+ */
32
+ export function renderTemplate(template, values = {}) {
33
+ if (typeof template === 'function') {
34
+ return template(values);
35
+ }
36
+ return _.template(template)(values);
37
+ }
38
+
39
+ /**
40
+ * Get a HTML string for rendering an application.
41
+ * @param {Object} [data={}] Server config or data that will be available in the attribute
42
+ * `data-app` on currentScript. In Vue it will also be available in the `$options` object.
43
+ * @param {Object} [settings={}] Settings object.
44
+ * @param {String} [settings.noScript=''] HTML that will be rendered when JavaScript
45
+ * is not available.
46
+ * @param {String} [settings.selector=`[data-portlet-id="${portletId}"]`] Query selector for
47
+ * where the app should be mounted.
48
+ * @param {Boolean} [settings.async=false] If the app script should be loaded asynchronously.
49
+ * [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
50
+ * @param {Boolean} [settings.defer=true] If the app script should be loaded after DOM is ready.
51
+ * [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
52
+ * @returns {String} HTML for rendering an application.
53
+ */
54
+ export function renderApp(data, {
55
+ noScript = '',
56
+ selector = `[data-portlet-id="${portletId}"]`,
57
+ async = false,
58
+ defer = true,
59
+ } = {}) {
60
+ if (typeof data === 'string') {
61
+ throw new Error('As of version 2 renderApp no longer needs the application name.');
62
+ }
63
+ if (isOffline) {
64
+ return `
65
+ <div data-portlet-id="${portletId}">${noScript}</div>
66
+ <script>
67
+ (function(){
68
+ var targetElement = document.querySelector('[data-portlet-id="${portletId}"]');
69
+ var script = document.createElement('script');
70
+ script.src = '${getResourceUri('client/index.js')}?${portletId.replace('_', '')}';
71
+ script.setAttribute('data-app', '${encodeURIComponent(JSON.stringify({ ...data, isOffline }))}');
72
+ script.setAttribute('data-selector', '${encodeURIComponent(selector)}');
73
+ targetElement.parentNode.insertBefore(script, targetElement.nextSibling);
74
+ })();
75
+ </script>`;
76
+ }
77
+ return `
78
+ <div data-portlet-id="${portletId}">${noScript}</div>
79
+ <script
80
+ src="${getResourceUri('client/index.js')}?${appInfo.appImportDate}${portletId.replace('_', '')}"
81
+ data-app="${encodeURIComponent(JSON.stringify({ ...data, isOffline }))}"
82
+ data-selector="${encodeURIComponent(selector)}"
83
+ ${async && !defer ? 'async' : ''}
84
+ ${defer ? 'defer' : ''}>
85
+ </script>`;
86
+ }
87
+
88
+ /**
89
+ * Get URI for a route, same as `getStandaloneUrl` in SiteVision template.
90
+ * @param {String} route A route.
91
+ * @returns {String} URI for route.
92
+ */
93
+ export function getRouteUri(route) {
94
+ const currentPageId = PortletContextUtil.getCurrentPage().getIdentifier().replace('_sitePage', '');
95
+ const currentPortletId = PortletContextUtil.getCurrentPortlet().getIdentifier();
96
+ return `/appresource/${currentPageId}/${currentPortletId}/${route}`.replace(/\/\//g, '/');
97
+ }
98
+
99
+ /**
100
+ * Get URI for a view, same as `getUrl` in SiteVision template.
101
+ * @param {String} route A route.
102
+ * @returns {String} URI for view.
103
+ */
104
+ export function getViewUri(route) {
105
+ const currentPageUri = PropertyUtil.getString(PortletContextUtil.getCurrentPage(), 'URI');
106
+ return `${currentPageUri}?sv.${portletId}.route=${encodeURI(route)}&sv.target=${portletId}`;
107
+ }
108
+
109
+ export default {
110
+ getRouteUri,
111
+ getViewUri,
112
+ getResourceUri,
113
+ renderApp,
114
+ renderTemplate,
115
+ isOffline,
116
+ isOnline,
117
+ };
package/dist/index.js DELETED
@@ -1,87 +0,0 @@
1
- import PortletContextUtil from 'PortletContextUtil';
2
- import VersionUtil from 'VersionUtil';
3
- import appInfo from 'appInfo';
4
- /* Underscore is provided by SiteVision */
5
- /* eslint-disable-next-line import/no-extraneous-dependencies */
6
- import _ from 'underscore';
7
-
8
- /** If the webapp is running in offline mode or not. */
9
- export var isOffline = VersionUtil.getCurrentVersion() === VersionUtil.OFFLINE_VERSION;
10
-
11
- var currentPortlet = PortletContextUtil.getCurrentPortlet();
12
- var portletId = currentPortlet ? currentPortlet.getIdentifier().replace('.', '_') : '';
13
-
14
- /**
15
- * Get URI for a resource.
16
- * @param {String} resource A resource.
17
- * @returns {String} URI for a resource.
18
- */
19
- export function getResourceUri(resource) {
20
- return ("/webapp-files/" + (appInfo.appIdentifier) + "/" + (appInfo.appVersion) + "/" + resource);
21
- }
22
-
23
- /**
24
- * Renders a Underscore template and returns a string.
25
- * @param {String} template Underscore template.
26
- * @param {Object} [values={}] Values.
27
- * @returns {String} Rendered template
28
- */
29
- export function renderTemplate(template, values) {
30
- if ( values === void 0 ) values = {};
31
-
32
- if (typeof template === 'function') {
33
- return template(values);
34
- }
35
- return _.template(template)(values);
36
- }
37
-
38
- /**
39
- * Get HTML string for rendering an application.
40
- * @param {String} name Name of the app, has to match the name of the application.
41
- * @param {Object} [data={}] Server data that will be available in the app.
42
- * In Vue it will be available in the `$options` object.
43
- * @param {Object} [settings={}] Settings object.
44
- * @param {String} [settings.noScript=''] HTML that will be rendered when JavaScript
45
- * is not available.
46
- * @param {String} [settings.selector=`[data-portlet-id="${portletId}"]`] Query selector for
47
- * where the app should be mounted.
48
- * @param {Boolean} [settings.async=true] If the app script should be loaded asynchronously.
49
- * [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
50
- * @param {Boolean} [settings.defer=false] If the app script should be loaded after DOM is ready.
51
- * [Read more about async and defer.](https://flaviocopes.com/javascript-async-defer/)
52
- * @returns {String} HTML for rendering an application.
53
- */
54
- export function renderApp(name, data, ref) {
55
- if ( ref === void 0 ) ref = {};
56
- var noScript = ref.noScript; if ( noScript === void 0 ) noScript = '';
57
- var selector = ref.selector; if ( selector === void 0 ) selector = "[data-portlet-id=\"" + portletId + "\"]";
58
- var async = ref.async; if ( async === void 0 ) async = true;
59
- var defer = ref.defer; if ( defer === void 0 ) defer = false;
60
-
61
- var options = Object.assign({}, data, {isOffline: isOffline});
62
- var clientUri = getResourceUri('client/index.js');
63
-
64
- if (isOffline) {
65
- return ("\n<!-- Generated by WebappUtil.renderApp() -->\n<div data-portlet-id=\"" + portletId + "\">" + noScript + "</div>\n<script src=\"" + clientUri + "?" + (appInfo.appImportDate) + "\"></script>\n<script> \n Soleil.webapps['" + name + "'].render('" + name + "', '" + selector + "', " + (JSON.stringify(options)) + ");\n</script>\n");
66
- }
67
- return ("\n<!-- Generated by WebappUtil.renderApp() -->\n<div data-portlet-id=\"" + portletId + "\">" + noScript + "</div>\n<script>\n function renderApp" + portletId + "() {\n Soleil.webapps['" + name + "'].render('" + name + "', '" + selector + "', " + (JSON.stringify(options)) + ");\n } \n</script>\n<script src=\"" + clientUri + "?" + (appInfo.appImportDate) + "\" " + (async && !defer ? 'async' : '') + " " + (defer ? 'defer' : '') + " onload=\"renderApp" + portletId + "();\"></script>\n");
68
- }
69
-
70
- /**
71
- * Get URI for a route.
72
- * @param {String} route A route.
73
- * @returns {String} URI for route.
74
- */
75
- export function getRouteUri(route) {
76
- var currentPageId = PortletContextUtil.getCurrentPage().getIdentifier().replace('_sitePage', '');
77
- var currentPortletId = PortletContextUtil.getCurrentPortlet().getIdentifier();
78
- return ("/appresource/" + currentPageId + "/" + currentPortletId + "/" + route).replace(/\/\//g, '/');
79
- }
80
-
81
- export default {
82
- getRouteUri: getRouteUri,
83
- getResourceUri: getResourceUri,
84
- renderApp: renderApp,
85
- renderTemplate: renderTemplate,
86
- isOffline: isOffline,
87
- };
@@ -1,3 +0,0 @@
1
- {
2
- "extends": "@soleil/eslint-config-sitevision/client"
3
- }
@@ -1,42 +0,0 @@
1
- /* eslint-disable-next-line import/no-unresolved */
2
- import Vue from 'vue';
3
-
4
- window.Soleil = window.Soleil || {};
5
- window.Soleil.webapps = window.Soleil.webapps || {};
6
-
7
- const offlineModeMixin = {
8
- mounted() {
9
- if (this.$options.isOffline) {
10
- const $anchors = this.$el.querySelectorAll('a');
11
- $anchors.forEach(($anchor) => {
12
- $anchor.addEventListener('click', (e) => {
13
- e.preventDefault();
14
- window.$svjq($anchor).trigger('click');
15
- }, false);
16
- });
17
- }
18
- },
19
- };
20
- /**
21
- * Render a Vue application
22
- * @param {String} name Name of the application, has to match both on server and client.
23
- * @param {String} selector Selector for element where the app should be mounted.
24
- * @param {Object} [options={}] Options for `$options`.
25
- */
26
- export default function render(name, selector, options = {}) {
27
- const {
28
- App,
29
- } = window.Soleil.webapps[name];
30
- Object.assign(App, options, {
31
- mixins: [offlineModeMixin],
32
- });
33
-
34
- const mountElementExists = !!document.querySelector(selector);
35
- if (mountElementExists) {
36
- new Vue(App).$mount(selector);
37
- } else {
38
- document.addEventListener('DOMContentLoaded', () => {
39
- new Vue(App).$mount(selector);
40
- });
41
- }
42
- }