saasufy-components 2.5.0 → 2.6.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/app-router.js CHANGED
@@ -2,6 +2,7 @@ import { toSafeHTML, renderTemplate, debouncer } from './utils.js';
2
2
  import { SocketConsumer } from './socket.js';
3
3
 
4
4
  const DEFAULT_DEBOUNCE_DELAY = 100;
5
+ const DEFAULT_MAX_REDIRECTS = 5;
5
6
 
6
7
  export class AppRouter extends SocketConsumer {
7
8
  constructor() {
@@ -52,7 +53,8 @@ export class AppRouter extends SocketConsumer {
52
53
  static get observedAttributes() {
53
54
  return [
54
55
  'default-page',
55
- 'debounce-delay'
56
+ 'debounce-delay',
57
+ 'max-redirects'
56
58
  ];
57
59
  }
58
60
 
@@ -106,52 +108,114 @@ export class AppRouter extends SocketConsumer {
106
108
  this.connectConsumer.kill();
107
109
  }
108
110
 
111
+ getMatchingRouteInfo(pagePath) {
112
+ return this.pageRouteInfos.find(
113
+ ({ regExp }) => pagePath.match(regExp)
114
+ ) || {};
115
+ }
116
+
117
+ getMatchingPage(pagePath, routeType, noThrow) {
118
+ let { route, regExp, params } = this.getMatchingRouteInfo(pagePath);
119
+ let pageTemplate = this.pages[route];
120
+ if (!pageTemplate && !noThrow) {
121
+ throw new Error(`The specified ${routeType}${pagePath ? ` ${pagePath}` : ''} did not match any route`);
122
+ }
123
+ return { pageTemplate, route, regExp, params };
124
+ }
125
+
126
+ substituteRouteAgs(route, routeArgs) {
127
+ for (let [ key, value ] of Object.entries(routeArgs || {})) {
128
+ route = route.replace(new RegExp(`:${key}\\b`, 'g'), value);
129
+ }
130
+ return route;
131
+ }
132
+
109
133
  renderCurrentPage() {
110
134
  let routerViewport = this.shadowRoot.querySelector('slot[name="viewport"]').assignedNodes()[0];
111
135
  if (!routerViewport) return;
112
136
 
113
- let { hash } = location;
114
- let pagePath = hash.replace(this.hashStartRegex, '');
115
-
116
- let { route, regExp, params } = this.pageRouteInfos.find(
117
- ({ regExp }) => pagePath.match(regExp)
118
- ) || {};
137
+ let routeArgs;
138
+ let pagePath = location.hash.replace(this.hashStartRegex, '');
139
+ let { pageTemplate, route, regExp, params } = this.getMatchingPage(pagePath, 'path', true);
119
140
 
120
- let pageTemplate = this.pages[route];
121
141
  if (!pageTemplate) {
122
142
  let defaultPage = this.getAttribute('default-page');
123
143
  if (!defaultPage) return;
124
- pageTemplate = this.pages[defaultPage];
144
+ routeArgs = this.computeRouteArgs(pagePath, regExp, params);
145
+ pagePath = this.substituteRouteAgs(defaultPage, routeArgs);
146
+ let result = this.getMatchingPage(pagePath, 'default-page');
147
+ pageTemplate = result.pageTemplate;
148
+ route = result.route;
149
+ regExp = result.regExp;
150
+ params = result.params;
125
151
  };
126
152
 
127
- let noAuthRedirect = pageTemplate.getAttribute('no-auth-redirect');
128
- let authRedirect = pageTemplate.getAttribute('auth-redirect');
129
- let hardRedirect = pageTemplate.hasAttribute('hard-redirect');
153
+ let maxRedirects = Number(this.getAttribute('max-redirects') || DEFAULT_MAX_REDIRECTS);
130
154
 
131
- if (this.socket && (authRedirect || noAuthRedirect)) {
132
- if (this.socket.authState === 'authenticated') {
133
- if (authRedirect) {
134
- if (hardRedirect) {
135
- location.hash = authRedirect;
136
- return;
137
- } else {
138
- pageTemplate = this.pages[authRedirect];
139
- }
155
+ let redirectCount;
156
+ for (redirectCount = 0; redirectCount < maxRedirects; redirectCount++) {
157
+ let redirect = pageTemplate.getAttribute('redirect');
158
+ let noAuthRedirect = pageTemplate.getAttribute('no-auth-redirect');
159
+ let authRedirect = pageTemplate.getAttribute('auth-redirect');
160
+
161
+ if (!redirect && !noAuthRedirect && !authRedirect) break;
162
+
163
+ let hardRedirect = pageTemplate.hasAttribute('hard-redirect');
164
+
165
+ if (redirect) {
166
+ if (hardRedirect) {
167
+ location.hash = redirect;
168
+ return;
140
169
  }
170
+ routeArgs = this.computeRouteArgs(pagePath, regExp, params);
171
+ pagePath = this.substituteRouteAgs(redirect, routeArgs);
172
+ let result = this.getMatchingPage(pagePath, 'redirect');
173
+ pageTemplate = result.pageTemplate;
174
+ route = result.route;
175
+ regExp = result.regExp;
176
+ params = result.params;
141
177
  } else {
142
- if (this.socket.state !== this.socket.OPEN) return;
143
- if (noAuthRedirect) {
144
- if (hardRedirect) {
145
- location.hash = noAuthRedirect;
146
- return;
178
+ if (this.socket && (authRedirect || noAuthRedirect)) {
179
+ if (this.socket.authState === 'authenticated') {
180
+ if (authRedirect) {
181
+ if (hardRedirect) {
182
+ location.hash = authRedirect;
183
+ return;
184
+ }
185
+ routeArgs = this.computeRouteArgs(pagePath, regExp, params);
186
+ pagePath = this.substituteRouteAgs(authRedirect, routeArgs);
187
+ let result = this.getMatchingPage(pagePath, 'auth-redirect');
188
+ pageTemplate = result.pageTemplate;
189
+ route = result.route;
190
+ regExp = result.regExp;
191
+ params = result.params;
192
+ }
147
193
  } else {
148
- pageTemplate = this.pages[noAuthRedirect];
194
+ if (this.socket.state !== this.socket.OPEN) return;
195
+ if (noAuthRedirect) {
196
+ if (hardRedirect) {
197
+ location.hash = noAuthRedirect;
198
+ return;
199
+ }
200
+ routeArgs = this.computeRouteArgs(pagePath, regExp, params);
201
+ pagePath = this.substituteRouteAgs(noAuthRedirect, routeArgs);
202
+ let result = this.getMatchingPage(pagePath, 'no-auth-redirect');
203
+ pageTemplate = result.pageTemplate;
204
+ route = result.route;
205
+ regExp = result.regExp;
206
+ params = result.params;
207
+ }
149
208
  }
150
209
  }
151
210
  }
152
211
  }
153
212
 
154
- let routeArgs;
213
+ if (redirectCount >= maxRedirects) {
214
+ throw new Error(
215
+ `The number of redirects exceeded the maximum amount of ${maxRedirects}`
216
+ );
217
+ }
218
+
155
219
  if (route) {
156
220
  routeArgs = this.computeRouteArgs(pagePath, regExp, params);
157
221
  } else {
package/model-viewer.js CHANGED
@@ -161,6 +161,8 @@ class ModelViewer extends SocketConsumer {
161
161
  (async () => {
162
162
  this.modelChangeConsumer = this.model.listener('change').createConsumer();
163
163
  for await (let event of this.modelChangeConsumer) {
164
+ // Ignore change events which originate from this collection instance.
165
+ if (!event.isRemote) continue;
164
166
  this.renderItem();
165
167
  }
166
168
  })();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "saasufy-components",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "Components for Saasufy.",
5
5
  "main": "index.js",
6
6
  "scripts": {