@quandis/qbo4.ui 4.0.1-CI-20240403-131518 → 4.0.1-CI-20240405-163539
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/package.json +2 -1
- package/readme.md +79 -417
- package/src/qbo/IApiService.d.ts +12 -0
- package/src/qbo/IApiService.js +8 -0
- package/src/qbo/IApiService.ts +18 -0
- package/src/qbo/IValidate.d.ts +16 -0
- package/src/qbo/IValidate.js +4 -0
- package/src/qbo/IValidate.ts +19 -0
- package/src/qbo/Program.d.ts +6 -2
- package/src/qbo/Program.js +6 -2
- package/src/qbo/Program.ts +6 -2
- package/src/qbo/RestApiService.d.ts +9 -0
- package/src/qbo/RestApiService.js +32 -0
- package/src/qbo/RestApiService.ts +45 -0
- package/src/qbo/Validators.d.ts +22 -0
- package/src/qbo/{qbo-validators.js → Validators.js} +8 -10
- package/src/qbo/{qbo-validators.ts → Validators.ts} +10 -22
- package/src/qbo/qbo-api.d.ts +0 -19
- package/src/qbo/qbo-api.js +3 -36
- package/src/qbo/qbo-api.ts +3 -57
- package/src/qbo/qbo-form-element.d.ts +20 -0
- package/src/qbo/qbo-form-element.js +128 -0
- package/src/qbo/qbo-form-element.ts +121 -0
- package/src/qbo/qbo-json.d.ts +3 -4
- package/src/qbo/qbo-json.js +24 -4
- package/src/qbo/qbo-json.ts +27 -4
- package/src/qbo/qbo-validate.d.ts +25 -7
- package/src/qbo/qbo-validate.js +84 -33
- package/src/qbo/qbo-validate.ts +81 -28
- package/wwwroot/js/qbo4.ui.js +47650 -11977
- package/wwwroot/js/qbo4.ui.min.js +84 -51
- package/wwwroot/js/qbo4.ui.min.js.map +1 -1
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "Quandis, Inc.",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "4.0.1-CI-
|
|
6
|
+
"version": "4.0.1-CI-20240405-163539",
|
|
7
7
|
"workspaces": [
|
|
8
8
|
"code"
|
|
9
9
|
],
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@codemirror/lang-html": "^6.4.6",
|
|
27
27
|
"@joint/core": "^4.0.1",
|
|
28
|
+
"@quandis/qbo4.logging": "^4.0.1-CI-20240328-192659",
|
|
28
29
|
"bootstrap": "^5.3.3",
|
|
29
30
|
"bootstrap-icons": "^1.10.5",
|
|
30
31
|
"codemirror": "^6.0.1",
|
package/readme.md
CHANGED
|
@@ -1,456 +1,118 @@
|
|
|
1
1
|
# Overview
|
|
2
2
|
|
|
3
|
-
The `qbo4.
|
|
3
|
+
The `qbo4.ui` package comprises the following features:
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
# Api Endpoint Registration
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- [HTML Accessiblilty](https://developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML)
|
|
10
|
-
- [Accessible Rich Internet Applications (ARIA)](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA)
|
|
11
|
-
- [Web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) ([examples](https://github.com/mdn/web-components-examples) on Github)
|
|
12
|
-
- [Form validation](https://www.w3.org/TR/2009/WD-html5-20090825/forms.html#attr-input-pattern)
|
|
13
|
-
- [Javascript Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
|
|
14
|
-
- [TSDoc](https://tsdoc.org/) for Typescript comments
|
|
15
|
-
|
|
16
|
-
## Custom Web components
|
|
17
|
-
|
|
18
|
-
There is a [debate](https://github.com/WebKit/standards-positions/issues/97) about customizing standard html elements.
|
|
19
|
-
Apple has refused to support customizing existing elements, and Quandis agrees with this approach.
|
|
20
|
-
|
|
21
|
-
This means that you can do:
|
|
7
|
+
If your web page needs to interface with multiple APIs, you can register them with the `qbo-api` component:
|
|
22
8
|
|
|
23
9
|
```html
|
|
24
|
-
<qbo-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
but you may not do:
|
|
10
|
+
<qbo-api name="myService" method="POST" apiEndpoint="https://api.mysite.com/some/endpoint">
|
|
11
|
+
<header name="Accept">application/json</header>
|
|
12
|
+
</qbo-api>
|
|
28
13
|
|
|
29
|
-
|
|
30
|
-
<
|
|
14
|
+
<qbo-api name="addresses" method="GET" apiEndpoint="https://nominatim.openstreetmap.org/search?q=${value}&format=json">
|
|
15
|
+
<header name="Accept">application/xml</header>
|
|
16
|
+
</qbo-api>
|
|
31
17
|
```
|
|
32
18
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
```javascript
|
|
36
|
-
@customElement('qbo-select')
|
|
37
|
-
export class QboSelect extends QboFetch
|
|
38
|
-
{
|
|
39
|
-
...
|
|
40
|
-
render() {
|
|
41
|
-
...
|
|
42
|
-
return html`
|
|
43
|
-
<select>
|
|
44
|
-
${this.options.map(option => html`...`)}
|
|
45
|
-
</select>`;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
# Project Structure
|
|
51
|
-
|
|
52
|
-
While this project is a `Microsoft.NET.Sdk.Web` project, it does not include any meaningful server-side code.
|
|
53
|
-
|
|
54
|
-
## Technology Components
|
|
55
|
-
|
|
56
|
-
| Technology | Config File | Purpose |
|
|
57
|
-
|-|-|-|
|
|
58
|
-
|Typescript|`tsconfig.json`|Type safe version of Javascript. `tsc --build` is used to compile (transpile) .ts files to .js file.|
|
|
59
|
-
|Node package manager (npm)|`package.json`|Javascript equivalent to Nuget package manager.|
|
|
60
|
-
|Webpack|`webpack.config.cjs`|Javascript equivalent to MSBuild. Webpack products a single `.js` and `.css` file for use by other projects.|
|
|
61
|
-
|Lit|--|Google's web component library. `LitElement` is the base class for most qbo4 web components.|
|
|
62
|
-
|web-test-runner|--|A test runner that runs tests in browser(s)' javascript/DOM engine.|
|
|
19
|
+
Then, in typescript:
|
|
63
20
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|Folder|Purpose|
|
|
67
|
-
|-|-|
|
|
68
|
-
|`wwwroot`|Contains .html pages to enable testing of web components.|
|
|
69
|
-
|`wwwroot/scripts`|Contains `main.js` and `main.css` files to be linked to by `.html` pages.|
|
|
70
|
-
|`package`|Folder containing the files to be packaged by `npm` and pushed to an artifact feed. This is specified in `package.json`|
|
|
71
|
-
|`src`|Source `.ts` files that comprise qbo4.UI.Web's components and libaries.|
|
|
72
|
-
|`tests`|Test `*.test.ts` files for testing components and libraries.|
|
|
73
|
-
|
|
74
|
-
## Typescript (tsconfig.json)
|
|
75
|
-
|
|
76
|
-
This project includes the `Microsoft.Typecript.MSBuild` Nuget package, which includes the `tsc` compiler.
|
|
77
|
-
When the project is built, MSBuild automatically calls `tsc` to compile `.ts` files to `.js` files.
|
|
78
|
-
|
|
79
|
-
It is convention to place `.ts` files in a `src` folder, and `.test.ts` files in a `tests` folder.
|
|
80
|
-
However, when we publish the package, we want to include only the `src` files.
|
|
81
|
-
To address this issue, we have three `tsconfig.json` files:
|
|
82
|
-
|
|
83
|
-
- `tsconfig.json`: in the root folder
|
|
84
|
-
- `src\tsconfig.json`: in the `src` folder, and instructs `tsc` where to output the files (`package` folder)
|
|
85
|
-
- `tests\tsconfig.json`: in the `tests` folder, and instructs `tsc` where to output the files (`tests` (same) folder)
|
|
86
|
-
|
|
87
|
-
The significant takeaway for our use of `tsconfig.json` is that we target `ESNext` for our output,
|
|
88
|
-
meaning that we produce javascript files that use the latest `ECMA` standards, including `import` and `export` of `modules`.
|
|
89
|
-
This means that these libraries will only work with modern browsers, which comprise 94+% of all browsers currently in use.
|
|
90
|
-
**IE is right out**.
|
|
91
|
-
|
|
92
|
-
## Node (package.json)
|
|
93
|
-
|
|
94
|
-
The `package.json` is used instruct `npm` how to behave. While it has many options,
|
|
95
|
-
the most relevent are the defined `scripts` that allow you to execute node command with a shortcut:
|
|
96
|
-
|
|
97
|
-
```console
|
|
98
|
-
// execute the tests using web-test-runner
|
|
99
|
-
npm run test
|
|
100
|
-
// package the files for deployment
|
|
101
|
-
npm run pack
|
|
102
|
-
```
|
|
21
|
+
```typescript
|
|
22
|
+
import { getApiService } from '@quandis/qbo4.ui';
|
|
103
23
|
|
|
104
|
-
|
|
24
|
+
const myApi = getApiService('myService');
|
|
25
|
+
const myResult = await myApi.fetch('/more/route/data', { Foo: 'Bar' });
|
|
105
26
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
npm install
|
|
109
|
-
// install a package and add it to package.json
|
|
110
|
-
npm install <package> --save
|
|
111
|
-
// install a package and add it to package.json as a dev dependency
|
|
112
|
-
npm install <package> --save-dev
|
|
113
|
-
// run any package installed globally
|
|
114
|
-
npx <package>
|
|
27
|
+
const geoApi = getApiService('addresses');
|
|
28
|
+
const address = getApiService('geoApi').fetch('', { value: '1600 Pennsylvania Ave NW, Washington, DC' });
|
|
115
29
|
```
|
|
116
30
|
|
|
117
|
-
|
|
31
|
+
> A few items to point out:
|
|
32
|
+
> - The `IApiService.fetch(relativePath, json)` can substitute against the `apiEndpoint`; useful for a `GET` operation.
|
|
33
|
+
> - `POST` operations will post the `json` object as the body of the request.
|
|
34
|
+
> - The `json` object can be a string, or an object. If it is an object, it will be stringified.
|
|
35
|
+
> - Additional headers can be specified in the `qbo-api` component.
|
|
118
36
|
|
|
119
|
-
|
|
120
|
-
Convention dictates that:
|
|
37
|
+
You can write your own `IApiService` class, and register it to qbo's DI container:
|
|
121
38
|
|
|
122
39
|
```typescript
|
|
123
|
-
import
|
|
124
|
-
import
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Webpack's job is to look a one (or more) 'entry' javascript files, build a dependency graph of all the imports actually in use,
|
|
128
|
-
and create a single Javascript file containing all referenced code (a dependency graph).
|
|
129
|
-
The entry point for qbo modules is `qbo.js`.
|
|
130
|
-
|
|
131
|
-
Webpack uses the following configuration files:
|
|
132
|
-
|
|
133
|
-
- `webpack.config.cjs`: common configuration for both development and production, produces output in `package\dist`
|
|
134
|
-
- `webpack.config.dev.cjs`: does not minify, does copies `package\dist` to `wwwroot\scripts` for testing (merges with `webpack.config.cjs`)
|
|
135
|
-
- `webpack.config.prod.cjs`: minifies javascript and css (merges with `webpack.config.cjs`)
|
|
40
|
+
import { services } from "@quandis/qbo4.logging";
|
|
41
|
+
import { services, IApiService } from "@quandis/qbo4.ui";
|
|
136
42
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
Naming the file with `.cjs` tells `node` that file is `CommonJS`, regardless of what `package.json's` `target` says.
|
|
43
|
+
@injectable()
|
|
44
|
+
export class MyApi implements IApiService {
|
|
140
45
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
<Target Name="NpmRunPack" AfterTargets="Build">
|
|
145
|
-
<Exec Command="npm run packprod" />
|
|
146
|
-
</Target>
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
paired with the `pack` script defined in `pacakge.json`:
|
|
150
|
-
|
|
151
|
-
```json
|
|
152
|
-
{ ...
|
|
153
|
-
"scripts": {
|
|
154
|
-
"packprod": "webpack --config webpack.prod.cjs --no-color"
|
|
155
|
-
},
|
|
156
|
-
...
|
|
46
|
+
async fetch(relativePath: string | null, payload: Record<string, string> | null = null): Promise<any> {
|
|
47
|
+
// implement your own fetch logic here
|
|
48
|
+
}
|
|
157
49
|
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
# HTML Coding Guidelines
|
|
161
|
-
|
|
162
|
-
When creating web pages, features should be implemented with:
|
|
163
|
-
|
|
164
|
-
- HTML, first, if possible,
|
|
165
|
-
- CSS, second, if possible,
|
|
166
|
-
- Javascript, otherwise
|
|
167
|
-
|
|
168
|
-
## Web Components
|
|
169
|
-
|
|
170
|
-
When designing reusable browser-based components, [web components](https://developer.mozilla.org/en-US/docs/Web/Web_Components) should be used.
|
|
171
|
-
Web components use Javascript, HTML and CSS to define new tags ~~or extend existing tags~~ , and scope all functionality to a [shadow DOM](https://developers.google.com/web/fundamentals/web-components/shadowdom).
|
|
172
|
-
This allows a given component to use javascript without worrying that it will interfere with other components.
|
|
173
|
-
|
|
174
|
-
The goal of creating web components is to strive to ensure QBO components can be **mixed into a variety of frameworks**,
|
|
175
|
-
including Angular and React.
|
|
176
|
-
|
|
177
|
-
In most cases, Quandis recommends use of Google's [Lit library](https://lit.dev/) to speed the development of pure web components.
|
|
178
|
-
|
|
179
|
-
A sampling custom components includes:
|
|
180
|
-
|
|
181
|
-
|Component|Purpose|
|
|
182
|
-
|-|-|
|
|
183
|
-
|`qbo-fetch`|Acts as a base class for elements that need to do API calls (via Javascript's `fetch` statement).|
|
|
184
|
-
|`qbo-select`|Renders a `<select>` element with options from the results of an API call.|
|
|
185
|
-
|`qbo-popup`|Renders a popup, with content optionally coming from an API call (via `qbo-fetch`).|
|
|
186
|
-
|`qbo-logging`|Provides UI around handling errors.|
|
|
187
50
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
HTML5 supports [extensive form validation](https://www.w3.org/TR/2009/WD-html5-20090825/forms.html#attr-input-pattern); use it! Examples:
|
|
191
|
-
|
|
192
|
-
```html
|
|
193
|
-
<input name="zipcode" type="text" pattern="\d{5}(-\d{4})?"/>
|
|
194
|
-
<input name="creditcard" type="text" pattern="[0-9]{13,16}"/>
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
# Typescrpit / Javascript Coding Guidelines
|
|
198
|
-
|
|
199
|
-
- Use the [MDN Style Guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide) (which Microsoft also uses)
|
|
200
|
-
- Use `const` and `let` [instead of](https://stackoverflow.com/questions/40070631/v8-javascript-performance-implications-of-const-let-and-var/40070682#40070682) `var`
|
|
201
|
-
- Use camelcase for variables and function names
|
|
202
|
-
|
|
203
|
-
``` javascript
|
|
204
|
-
const myLongVariableName = "foo";
|
|
51
|
+
// Register your service to qbo's DI container
|
|
52
|
+
services.container.registerInstance<IApiService>('myApi', new MyApi());
|
|
205
53
|
```
|
|
206
54
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
``` javascript
|
|
210
|
-
const firstName = "Bob";
|
|
211
|
-
const lastName = "Jones";
|
|
212
|
-
const result = `Hello ${firstName}, ${lastName}`;
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
- Omit the protocol from links to other sites, if possible, to support `http` and `https`
|
|
216
|
-
|
|
217
|
-
``` javascript
|
|
218
|
-
<style src="//maps.googleapis.com/maps/api/js"/>
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
## Namespacing
|
|
222
|
-
|
|
223
|
-
Use [`modules`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) via the `export` and `import` features to build javascript libraries.
|
|
224
|
-
Related classes and functions should be imported as a module. For example, qbo4-related modules:
|
|
225
|
-
|
|
226
|
-
- src
|
|
227
|
-
- qbo.ts
|
|
228
|
-
- qbo-fetch.ts
|
|
229
|
-
- qbo-json.ts
|
|
230
|
-
- qbo-select.ts
|
|
55
|
+
# Form Validation
|
|
231
56
|
|
|
232
|
-
|
|
57
|
+
Modern browers support a very rich set of [form valiation functionality](https://www.w3.org/TR/2009/WD-html5-20090825/forms.html#attr-input-pattern); use it!
|
|
58
|
+
Custom functionality can be introduced as follows:
|
|
233
59
|
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
```
|
|
244
|
-
To use qbo4 from a browser debugger window:
|
|
245
|
-
|
|
246
|
-
```javascript
|
|
247
|
-
const qbo = await import('/scirpts/qbo4.js');
|
|
248
|
-
// now you can access qbo.* functions
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
## Error handling in the browser
|
|
252
|
-
|
|
253
|
-
- Assume our code will fail
|
|
254
|
-
- Log errors to the server
|
|
255
|
-
- Our code, not the browser, should handle errors
|
|
256
|
-
- Identify errors that might occur (arguments, network)
|
|
257
|
-
- use [custom errors](https://medium.com/@iaincollins/error-handling-in-javascript-a6172ccdf9af)
|
|
258
|
-
- `throw` at a low level, `catch` at a high level
|
|
259
|
-
- Distinguish between fatal and non-fatal
|
|
260
|
-
- Global debug mode: help the developer figure out the problem
|
|
261
|
-
|
|
262
|
-
> Credit [Nicholas Zakas](https://www.slideshare.net/nzakas/enterprise-javascript-error-handling-presentation/48-E_tcetera_M_y_blog)
|
|
263
|
-
|
|
264
|
-
## Comments
|
|
265
|
-
|
|
266
|
-
Quandis shall follow the [TSDoc](https://tsdoc.org/) to work with Visual Studio Intellisense.
|
|
267
|
-
|
|
268
|
-
``` javascript
|
|
269
|
-
/* @description These are sample comments
|
|
270
|
-
* @param foo {string} Foo is used to ...
|
|
271
|
-
* @param bar {array} Each item in bar is used to ...
|
|
272
|
-
* @returns {object} An object representing ...
|
|
273
|
-
*/
|
|
274
|
-
qbo4.someMethod = function (foo, bar) {...}
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
## Third Party Libraries
|
|
278
|
-
|
|
279
|
-
- Use native Javascript methods ahead of third party library methods
|
|
280
|
-
- e.g. `document.getElementById(id)` is preferrable to jQuery's `$('#id')[0]`.
|
|
281
|
-
- e.g. `{array}.forEach(...)` is preferable to Mootool's `{array}.each(...)`
|
|
282
|
-
|
|
283
|
-
|Library|qbo3|qbo4|Notes|
|
|
284
|
-
|-|-|-|-|
|
|
285
|
-
|[Mootools](https://mootools.net/)|yes|no|Deprecated; not under development.|
|
|
286
|
-
|[jQuery](https://jquery.com/)|yes|yes|For sugar **not supported by the DOM**. <br/>Use [noconflict](https://api.jquery.com/jQuery.noConflict/); $ shall be used for Mootools in qbo3.|
|
|
287
|
-
|[Google Visualizations](https://developers.google.com/chart/interactive/docs/gallery)|yes|yes|For charting.|
|
|
288
|
-
|[Bootstrap](https://getbootstrap.com/)|yes|yes|For styling and layout.|
|
|
289
|
-
|[Dropzone](https://www.dropzonejs.com/)|yes|yes|For file upload controls.|
|
|
290
|
-
|[Modernizr](https://modernizr.com/)|yes|yes|For older browsers (consumer-facing sites).|
|
|
291
|
-
|
|
292
|
-
## Feature adoption
|
|
293
|
-
|
|
294
|
-
|Feature|qbo3|qbo4|Notes|
|
|
295
|
-
|-|-|-|-|
|
|
296
|
-
|Promises|yes|yes||
|
|
297
|
-
|async/await|yes|yes||
|
|
298
|
-
|
|
299
|
-
> Use new features [only if available](https://caniuse.com/) to 90% or more of global users.
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
# References
|
|
303
|
-
|
|
304
|
-
- [Web components](https://developers.google.com/web/fundamentals/web-components/customelements) *Read this!*
|
|
305
|
-
- [Composing events with the shadow DOM](https://stackoverflow.com/questions/43061417/how-to-listen-for-custom-events-defined-web-component)
|
|
306
|
-
- [Webpack](https://webpack.js.org/)
|
|
307
|
-
- [TypeScript with ASP.NET core](https://www.typescriptlang.org/docs/handbook/asp-net-core.html)
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
# Typescript in a Microsoft Stack
|
|
311
|
-
|
|
312
|
-
A basic Typescript project (`.esproj` file) looks something like this:
|
|
313
|
-
|
|
314
|
-
```xml
|
|
315
|
-
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/0.5.74-alpha">
|
|
316
|
-
<PropertyGroup>
|
|
317
|
-
<!-- Command to run on project build -->
|
|
318
|
-
<BuildCommand>npm run build</BuildCommand>
|
|
319
|
-
<!-- Command to run on project clean -->
|
|
320
|
-
<CleanCommand>npm run clean</CleanCommand>
|
|
321
|
-
</PropertyGroup>
|
|
322
|
-
<ItemGroup>
|
|
323
|
-
<Folder Include="build\" />
|
|
324
|
-
</ItemGroup>
|
|
325
|
-
</Project>
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
The following files are automatically added:
|
|
329
|
-
|
|
330
|
-
|File|Description|
|
|
331
|
-
|-|-|
|
|
332
|
-
|tsconfig.json|Typescript configuration file that provides tsc (a node package that is the Typescript compiler) with it's [build options](https://aka.ms/tsconfig).|
|
|
333
|
-
|package.json|Node.js configuration file that provides npm.exe (the [Node Package Manager](https://docs.npmjs.com/files/package.json)) with the Node packages to include.|
|
|
334
|
-
|nuget.config|Sources to use for Nuget packages.|
|
|
335
|
-
|
|
336
|
-
## Building
|
|
337
|
-
|
|
338
|
-
- When a developer select Project > Build, the `BuildCommand` is executed, which in turn runs `npm run build`.
|
|
339
|
-
- `npm` looks for a `build` script defined in `package.json`, which is defined in by the `scrips` entry in `package.json`:
|
|
340
|
-
|
|
341
|
-
```json
|
|
342
|
-
"scripts": {
|
|
343
|
-
"test": "echo \"Error: no test specified\" && exit 1",
|
|
344
|
-
"build": "tsc --build",
|
|
345
|
-
"clean": "tsc --build --clean"
|
|
346
|
-
},
|
|
60
|
+
```html
|
|
61
|
+
<form>
|
|
62
|
+
<qbo-validate></qbo-validate>
|
|
63
|
+
<div>
|
|
64
|
+
<label for="city">City</label>
|
|
65
|
+
<input type="text" name="address" required data-exists="addresses">
|
|
66
|
+
</div>
|
|
67
|
+
<button type="submit">Submit form</button>
|
|
68
|
+
</form>
|
|
347
69
|
```
|
|
348
70
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
By default, calling `tsc --build` will find any `.ts` files, and compile them to `.js` and `.js.map` files.
|
|
352
|
-
|
|
353
|
-
> The `.js.map` file is a mapping between the generated/transpiled/minified JavaScript file and one or more original source files.
|
|
354
|
-
The main purpose of Sourcemaps is to aid debugging.
|
|
355
|
-
If there is an error in the generated code file, the map can tell you the original source file location.
|
|
356
|
-
That's it.
|
|
71
|
+
> Note that the `data-exists` tag has a value of `addresses`, which corresponds to the `qbo-api` name attribute.
|
|
357
72
|
|
|
358
|
-
This
|
|
73
|
+
This markup, combined with our custom `ExistsValidator` class, will validate that the value entered in the `input` field exists in the `addresses` API.
|
|
359
74
|
|
|
360
|
-
|
|
75
|
+
Here is our `ExistsValidator` class:
|
|
361
76
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
{
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
77
|
+
```typescript
|
|
78
|
+
import { injectable, InjectionToken } from 'tsyringe';
|
|
79
|
+
|
|
80
|
+
@injectable()
|
|
81
|
+
export class ExistsValidator implements IValidate {
|
|
82
|
+
async validate(input: HTMLElement): Promise<boolean> {
|
|
83
|
+
var url = input.getAttribute('data-exists');
|
|
84
|
+
if (!url) return false;
|
|
85
|
+
var path = input.getAttribute('data-exists-path');
|
|
86
|
+
const service: IApiService = container.isRegistered(url) ? container.resolve<IApiService>(url) : new RestApiService(url);
|
|
87
|
+
|
|
88
|
+
if (input instanceof HTMLInputElement || input instanceof HTMLSelectElement || input instanceof HTMLTextAreaElement) {
|
|
89
|
+
const response = await service.fetch(path, { value: input.value });
|
|
90
|
+
const json = getArray(response);
|
|
91
|
+
if (json == null)
|
|
92
|
+
return false;
|
|
93
|
+
return json.length > 0;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
};
|
|
97
|
+
message = 'This value does not appear to exist.';
|
|
98
|
+
selector = '[data-exists]';
|
|
374
99
|
}
|
|
100
|
+
container.register(ValidateToken, { useClass: ExistsValidator });
|
|
375
101
|
```
|
|
376
102
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
[Lit recommends](https://lit.dev/docs/tools/testing/#web-test-runner) using [@web-test-runner](https://modern-web.dev/guides/test-runner/getting-started/) for testing Lit-based web components.
|
|
380
|
-
The `web-test-runner` tests javascript against actual browser javascript engines, rather than Node.js.
|
|
381
|
-
This is important because Node.js does not support the DOM, and Lit is a DOM-based library.
|
|
382
|
-
The `@web/test-runner-playwright` enables testing against Chrome, Safari and Edge.
|
|
383
|
-
|
|
384
|
-
To install `web-test-runner`:
|
|
103
|
+
The `IValidate` interface is:
|
|
385
104
|
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
To run tests, `packages.json` includes:
|
|
392
|
-
```json
|
|
393
|
-
{
|
|
394
|
-
...
|
|
395
|
-
"scripts": {
|
|
396
|
-
"test": "web-test-runner \"js/tests/**/*.test.js\" --node-resolve",
|
|
397
|
-
"test:watch": "web-test-runner \"js/tests/**/*.test.js\" --node-resolve --watch",
|
|
398
|
-
"test:all": "web-test-runner \"js/tests/**/*.test.js\" --node-resolve --playwright --browsers chromium firefox webkit --static-logging",
|
|
399
|
-
},
|
|
400
|
-
...
|
|
105
|
+
```typescript
|
|
106
|
+
export interface IValidate {
|
|
107
|
+
validate(input: HTMLElement): Promise<boolean>;
|
|
108
|
+
message: string;
|
|
109
|
+
selector: string;
|
|
401
110
|
}
|
|
402
111
|
```
|
|
403
112
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
By default, `npm` will publish to the [npmjs.com](https://www.npmjs.com/) registry.
|
|
407
|
-
To publish to a private Azure Devops feed, you will create 2 .npmrc files:
|
|
408
|
-
|
|
409
|
-
- c:\users\your.username\\.npmrc: this will contain authentication info
|
|
410
|
-
- \{project folder}\\.npmrc: this will contain just the feed URL
|
|
411
|
-
|
|
412
|
-
The private `npmrc` file will look something like this:
|
|
413
|
-
|
|
414
|
-
```ini
|
|
415
|
-
qbo4:registry=https://pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/registry/
|
|
416
|
-
always-auth=true
|
|
417
|
-
; begin auth token
|
|
418
|
-
//pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/registry/:username=quandis
|
|
419
|
-
//pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/registry/:_password={your Devops PAT, base64 encoded}
|
|
420
|
-
//pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/registry/:email=npm requires email to be set but doesn't use the value
|
|
421
|
-
//pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/:username=quandis
|
|
422
|
-
//pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/:_password={your Devops PAT, base64 encoded}
|
|
423
|
-
//pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/:email=npm requires email to be set but doesn't use the value
|
|
424
|
-
; end auth token
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
> Yor PAT is an Azure Devops Personal Access Token, which you have configured for Visual Studio to pull Quandis Nuget packages
|
|
428
|
-
> You can use Fiddler's TextWizard to base64 encode your PAT.
|
|
429
|
-
|
|
430
|
-
The project `.npmrc` file will look something like this:
|
|
431
|
-
|
|
432
|
-
```ini
|
|
433
|
-
registry=https://pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/registry/
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
Some useful `npm` commands:
|
|
437
|
-
|
|
438
|
-
```ini
|
|
439
|
-
// list all npm config settings, including registries defined in various .npmrc files
|
|
440
|
-
npm config list
|
|
441
|
-
|
|
442
|
-
// publish to a specific registry
|
|
443
|
-
npm publish --registry=https://pkgs.dev.azure.com/quandis/_packaging/qbo4-Build/npm/registry/
|
|
444
|
-
|
|
445
|
-
// publish to whatever registry is defined in the local .npmrc file
|
|
446
|
-
npm publish
|
|
447
|
-
|
|
448
|
-
// increment the version number in package.json
|
|
449
|
-
npm version patch
|
|
450
|
-
```
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
# Notes
|
|
113
|
+
Paired with the `qbo-validate` component, you can decorate your HTML markup with simple attributes,
|
|
114
|
+
and automatically trigger form validate against any `IValidate` class registered with the DI container.
|
|
454
115
|
|
|
455
|
-
|
|
116
|
+
It's important that your selector be unique amont all registered `IValidate` classes.
|
|
117
|
+
We recommend the selector be [data-{IValidate class name}] for consistency.
|
|
456
118
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { InjectionToken } from "tsyringe";
|
|
2
|
+
/**
|
|
3
|
+
* Defines a contract for API calls.
|
|
4
|
+
*/
|
|
5
|
+
export interface IApiService {
|
|
6
|
+
fetch(relativePath: string | null, payload: Record<string, string> | null): Promise<any>;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Define a token for the IApiService interface
|
|
10
|
+
*/
|
|
11
|
+
export declare const IApiServiceToken: InjectionToken<IApiService>;
|
|
12
|
+
export declare function getApiService(name: string): IApiService;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { services } from "@quandis/qbo4.logging";
|
|
2
|
+
import { InjectionToken } from "tsyringe";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Defines a contract for API calls.
|
|
6
|
+
*/
|
|
7
|
+
export interface IApiService {
|
|
8
|
+
fetch(relativePath: string | null, payload: Record<string, string> | null): Promise<any>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Define a token for the IApiService interface
|
|
13
|
+
*/
|
|
14
|
+
export const IApiServiceToken: InjectionToken<IApiService> = 'ApiServiceToken';
|
|
15
|
+
|
|
16
|
+
export function getApiService(name: string) {
|
|
17
|
+
return services.container.resolve<IApiService>(name);
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { InjectionToken } from "tsyringe";
|
|
2
|
+
/**
|
|
3
|
+
* Defines a contract for form field validation.
|
|
4
|
+
* @remarks
|
|
5
|
+
* External classes may define custom validators by implementing this interface.
|
|
6
|
+
* Register the custom validator with the tsyringe DI container using {@link ValidateToken}.
|
|
7
|
+
*/
|
|
8
|
+
export interface IValidate {
|
|
9
|
+
validate(input: HTMLElement): Promise<boolean>;
|
|
10
|
+
message: string;
|
|
11
|
+
selector: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Define a token for the validators
|
|
15
|
+
*/
|
|
16
|
+
export declare const ValidateToken: InjectionToken<IValidate>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { InjectionToken } from "tsyringe";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Defines a contract for form field validation.
|
|
5
|
+
* @remarks
|
|
6
|
+
* External classes may define custom validators by implementing this interface.
|
|
7
|
+
* Register the custom validator with the tsyringe DI container using {@link ValidateToken}.
|
|
8
|
+
*/
|
|
9
|
+
export interface IValidate {
|
|
10
|
+
validate(input: HTMLElement): Promise<boolean>;
|
|
11
|
+
message: string;
|
|
12
|
+
selector: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Define a token for the validators
|
|
18
|
+
*/
|
|
19
|
+
export const ValidateToken: InjectionToken<IValidate> = 'ValidateToken';
|
package/src/qbo/Program.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import 'reflect-metadata';
|
|
2
|
+
export { services } from '@quandis/qbo4.logging';
|
|
3
|
+
export * from './IApiService.js';
|
|
4
|
+
export * from './IValidate.js';
|
|
5
|
+
export * from './Validators.js';
|
|
6
|
+
export * from './RestApiService.js';
|
|
2
7
|
export * from './qbo-badge.js';
|
|
3
8
|
export * from './qbo-datalist.js';
|
|
4
9
|
export * from './qbo-docviewer.js';
|
|
10
|
+
export * from './qbo-form-element.js';
|
|
5
11
|
export * from './qbo-json.js';
|
|
6
|
-
export * from './qbo-logging.js';
|
|
7
12
|
export * from './qbo-mainmenu.js';
|
|
8
13
|
export * from './qbo-markdown.js';
|
|
9
14
|
export * from './qbo-microphone.js';
|
|
@@ -14,5 +19,4 @@ export * from './qbo-select.js';
|
|
|
14
19
|
export * from './qbo-sidebar.js';
|
|
15
20
|
export * from './qbo-table.js';
|
|
16
21
|
export * from './qbo-validate.js';
|
|
17
|
-
export * from './qbo-validators.js';
|
|
18
22
|
export * from './qbo-api.js';
|