Merge branch 'storybook-v7-upgrade' into docs/add-draft-concept-docs

This commit is contained in:
Mads Rasmussen
2023-02-23 20:11:11 +01:00
9 changed files with 33736 additions and 51609 deletions

View File

@@ -1,22 +0,0 @@
const tsconfigPaths = require('vite-tsconfig-paths').default;
const { mergeConfig } = require('vite');
module.exports = {
stories: ['../@(src|libs|apps)/**/*.stories.@(js|jsx|ts|tsx|mdx)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-a11y'],
framework: '@storybook/web-components',
features: {
previewMdx2: true,
storyStoreV7: true,
},
core: {
builder: '@storybook/builder-vite',
},
staticDirs: ['../public-assets'],
async viteFinal(config, { configType }) {
return mergeConfig(config, {
// customize the Vite config here
plugins: [tsconfigPaths()],
});
},
};

View File

@@ -0,0 +1,21 @@
import { StorybookConfig } from '@storybook/web-components-vite';
const config: StorybookConfig = {
stories: ['../@(src|libs|apps)/**/*.stories.mdx', '../@(src|libs|apps)/**/*.stories.@(js|jsx|ts|tsx)'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-a11y'],
framework: {
name: '@storybook/web-components-vite',
options: {}
},
features: {
storyStoreV7: true
},
staticDirs: ['../public-assets'],
typescript: {
check: true,
},
docs: {
autodocs: true
}
};
export default config;

File diff suppressed because it is too large Load Diff

View File

@@ -1,126 +1,129 @@
{
"name": "umbraco-cms-backoffice",
"license": "MIT",
"private": true,
"version": "0.0.0",
"type": "module",
"main": "dist/main.js",
"exports": {
".": "./dist/main.js"
},
"types": "types/src/app.d.ts",
"files": [
"dist",
"types"
],
"repository": {
"url": "https://github.com/umbraco/Umbraco.CMS.Backoffice",
"type": "git"
},
"bugs": {
"url": "https://github.com/umbraco/Umbraco.CMS.Backoffice/issues"
},
"author": {
"name": "Umbraco A/S",
"email": "backoffice@umbraco.com",
"url": "https://umbraco.com"
},
"scripts": {
"dev": "vite",
"build": "tsc && vite build --mode staging",
"build:for:static": "tsc && vite build",
"build:for:cms": "tsc && vite build -c vite.cms.config.ts",
"build:for:cms:watch": "npm run build:for:cms -- --watch",
"preview": "vite preview --open",
"test": "web-test-runner --coverage",
"test:watch": "web-test-runner --watch",
"auth:test:e2e": "npx playwright test --config apps/auth/",
"backoffice:test:e2e": "npx playwright test",
"test:e2e": "npm run auth:test:e2e && npm run backoffice:test:e2e",
"lint": "eslint src apps libs e2e",
"lint:fix": "npm run lint -- --fix",
"format": "prettier 'src/**/*.ts'",
"format:fix": "npm run format -- --write",
"generate:api": "openapi --input https://raw.githubusercontent.com/umbraco/Umbraco-CMS/v13/dev/src/Umbraco.Cms.Api.Management/OpenApi.json --output libs/backend-api/src --postfix Resource --useOptions",
"generate:api-dev": "openapi --input http://localhost:11000/umbraco/swagger/v1/swagger.json --output libs/backend-api/src --postfix Resource --useOptions",
"storybook": "npm run wc-analyze && start-storybook -p 6006",
"storybook:build": "npm run wc-analyze && build-storybook",
"build-storybook": "npm run wc-analyze && build-storybook",
"generate:icons": "node ./devops/icons/index.js",
"wc-analyze": "wca **/*.element.ts --outFile custom-elements.json",
"new-extension": "plop --plopfile ./devops/plop/plop.js",
"compile": "tsc",
"check": "npm run lint && npm run compile && npm run build-storybook"
},
"engines": {
"node": ">=16.0.0 <17",
"npm": ">=8.0.0 < 9"
},
"dependencies": {
"@umbraco-ui/uui": "^1.2.0-rc.0",
"@umbraco-ui/uui-css": "^1.2.0-rc.0",
"@umbraco-ui/uui-modal": "file:umbraco-ui-uui-modal-0.0.0.tgz",
"@umbraco-ui/uui-modal-container": "file:umbraco-ui-uui-modal-container-0.0.0.tgz",
"@umbraco-ui/uui-modal-dialog": "file:umbraco-ui-uui-modal-dialog-0.0.0.tgz",
"@umbraco-ui/uui-modal-sidebar": "file:umbraco-ui-uui-modal-sidebar-0.0.0.tgz",
"element-internals-polyfill": "^1.1.19",
"lit": "^2.6.1",
"lodash-es": "4.17.21",
"router-slot": "^1.5.5",
"rxjs": "^7.8.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"@babel/core": "^7.20.12",
"@mdx-js/react": "^2.2.1",
"@open-wc/testing": "^3.1.7",
"@playwright/test": "^1.30.0",
"@storybook/addon-a11y": "^6.5.15",
"@storybook/addon-actions": "^6.5.14",
"@storybook/addon-essentials": "^6.5.15",
"@storybook/addon-links": "^6.5.15",
"@storybook/builder-vite": "^0.3.0",
"@storybook/mdx2-csf": "^0.0.3",
"@storybook/web-components": "^6.5.15",
"@types/chai": "^4.3.4",
"@types/lodash-es": "^4.17.6",
"@types/mocha": "^10.0.0",
"@types/uuid": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^5.50.0",
"@typescript-eslint/parser": "^5.50.0",
"@web/dev-server-esbuild": "^0.3.3",
"@web/dev-server-import-maps": "^0.0.7",
"@web/dev-server-rollup": "^0.3.21",
"@web/test-runner": "^0.15.0",
"@web/test-runner-playwright": "^0.9.0",
"babel-loader": "^9.1.2",
"eslint": "^8.32.0",
"eslint-config-prettier": "^8.6.0",
"eslint-import-resolver-typescript": "^3.5.3",
"eslint-plugin-import": "^2.27.4",
"eslint-plugin-lit": "^1.8.2",
"eslint-plugin-lit-a11y": "^2.3.0",
"eslint-plugin-local-rules": "^1.3.2",
"eslint-plugin-storybook": "^0.6.10",
"eslint-plugin-wc": "^1.4.0",
"lit-html": "^2.6.1",
"msw": "^0.49.2",
"msw-storybook-addon": "^1.7.0",
"openapi-typescript-codegen": "^0.23.0",
"playwright-msw": "^2.1.0",
"plop": "^3.1.1",
"prettier": "2.8.3",
"rollup": "^3.10.0",
"rollup-plugin-esbuild": "^5.0.0",
"rollup-plugin-url": "^3.0.1",
"tiny-glob": "^0.2.9",
"typescript": "^4.9.5",
"vite": "^4.0.4",
"vite-plugin-static-copy": "^0.13.0",
"vite-tsconfig-paths": "^4.0.3",
"web-component-analyzer": "^2.0.0-next.4"
},
"msw": {
"workerDirectory": "public"
}
"name": "umbraco-cms-backoffice",
"license": "MIT",
"private": true,
"version": "0.0.0",
"type": "module",
"main": "dist/main.js",
"exports": {
".": "./dist/main.js"
},
"types": "types/src/app.d.ts",
"files": [
"dist",
"types"
],
"repository": {
"url": "https://github.com/umbraco/Umbraco.CMS.Backoffice",
"type": "git"
},
"bugs": {
"url": "https://github.com/umbraco/Umbraco.CMS.Backoffice/issues"
},
"author": {
"name": "Umbraco A/S",
"email": "backoffice@umbraco.com",
"url": "https://umbraco.com"
},
"scripts": {
"dev": "vite",
"build": "tsc && vite build --mode staging",
"build:for:static": "tsc && vite build",
"build:for:cms": "tsc && vite build -c vite.cms.config.ts",
"build:for:cms:watch": "npm run build:for:cms -- --watch",
"preview": "vite preview --open",
"test": "web-test-runner --coverage",
"test:watch": "web-test-runner --watch",
"auth:test:e2e": "npx playwright test --config apps/auth/",
"backoffice:test:e2e": "npx playwright test",
"test:e2e": "npm run auth:test:e2e && npm run backoffice:test:e2e",
"lint": "eslint src apps libs e2e",
"lint:fix": "npm run lint -- --fix",
"format": "prettier 'src/**/*.ts'",
"format:fix": "npm run format -- --write",
"generate:api": "openapi --input https://raw.githubusercontent.com/umbraco/Umbraco-CMS/v13/dev/src/Umbraco.Cms.Api.Management/OpenApi.json --output libs/backend-api/src --postfix Resource --useOptions",
"generate:api-dev": "openapi --input http://localhost:11000/umbraco/swagger/v1/swagger.json --output libs/backend-api/src --postfix Resource --useOptions",
"storybook": "npm run wc-analyze && storybook dev -p 6006",
"storybook:build": "npm run wc-analyze && storybook build",
"build-storybook": "npm run wc-analyze && storybook build",
"generate:icons": "node ./devops/icons/index.js",
"wc-analyze": "wca **/*.element.ts --outFile custom-elements.json",
"new-extension": "plop --plopfile ./devops/plop/plop.js",
"compile": "tsc",
"check": "npm run lint && npm run compile && npm run build-storybook"
},
"engines": {
"node": ">=16.0.0 <17",
"npm": ">=8.0.0 < 9"
},
"dependencies": {
"@umbraco-ui/uui": "^1.2.0-rc.0",
"@umbraco-ui/uui-css": "^1.2.0-rc.0",
"@umbraco-ui/uui-modal": "file:umbraco-ui-uui-modal-0.0.0.tgz",
"@umbraco-ui/uui-modal-container": "file:umbraco-ui-uui-modal-container-0.0.0.tgz",
"@umbraco-ui/uui-modal-dialog": "file:umbraco-ui-uui-modal-dialog-0.0.0.tgz",
"@umbraco-ui/uui-modal-sidebar": "file:umbraco-ui-uui-modal-sidebar-0.0.0.tgz",
"element-internals-polyfill": "^1.1.19",
"lit": "^2.6.1",
"lodash-es": "4.17.21",
"router-slot": "^1.5.5",
"rxjs": "^7.8.0",
"uuid": "^9.0.0"
},
"devDependencies": {
"@babel/core": "^7.20.12",
"@mdx-js/react": "^2.2.1",
"@open-wc/testing": "^3.1.7",
"@playwright/test": "^1.30.0",
"@storybook/addon-a11y": "^7.0.0-beta.53",
"@storybook/addon-actions": "^7.0.0-beta.53",
"@storybook/addon-essentials": "^7.0.0-beta.53",
"@storybook/addon-links": "^7.0.0-beta.53",
"@storybook/mdx2-csf": "^1.0.0-next.5",
"@storybook/web-components": "^7.0.0-beta.53",
"@storybook/web-components-vite": "^7.0.0-beta.53",
"@types/chai": "^4.3.4",
"@types/lodash-es": "^4.17.6",
"@types/mocha": "^10.0.0",
"@types/uuid": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^5.50.0",
"@typescript-eslint/parser": "^5.50.0",
"@web/dev-server-esbuild": "^0.3.3",
"@web/dev-server-import-maps": "^0.0.7",
"@web/dev-server-rollup": "^0.3.21",
"@web/test-runner": "^0.15.0",
"@web/test-runner-playwright": "^0.9.0",
"babel-loader": "^9.1.2",
"eslint": "^8.32.0",
"eslint-config-prettier": "^8.6.0",
"eslint-import-resolver-typescript": "^3.5.3",
"eslint-plugin-import": "^2.27.4",
"eslint-plugin-lit": "^1.8.2",
"eslint-plugin-lit-a11y": "^2.3.0",
"eslint-plugin-local-rules": "^1.3.2",
"eslint-plugin-storybook": "^0.6.11",
"eslint-plugin-wc": "^1.4.0",
"lit-html": "^2.6.1",
"msw": "^0.49.2",
"msw-storybook-addon": "^1.7.0",
"openapi-typescript-codegen": "^0.23.0",
"playwright-msw": "^2.1.0",
"plop": "^3.1.1",
"prettier": "2.8.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rollup": "^3.10.0",
"rollup-plugin-esbuild": "^5.0.0",
"rollup-plugin-url": "^3.0.1",
"storybook": "^7.0.0-beta.53",
"tiny-glob": "^0.2.9",
"typescript": "^4.9.5",
"vite": "^4.0.4",
"vite-plugin-static-copy": "^0.13.0",
"vite-tsconfig-paths": "^4.0.3",
"web-component-analyzer": "^2.0.0-next.4"
},
"msw": {
"workerDirectory": "public"
}
}

View File

@@ -7,8 +7,8 @@ import type { UmbDashboardMembersWelcomeElement } from './dashboard-members-welc
export default {
title: 'Dashboards/Welcome',
component: 'umb-dashboard-welcome',
id: 'umb-dashboard-welcome',
component: 'dashboard-members-welcome',
id: 'umb-dashboard-members-welcome',
} as Meta;
export const AAAOverview: Story<UmbDashboardMembersWelcomeElement> = () =>

View File

@@ -10,8 +10,8 @@ import type { UmbWorkspaceViewMemberGroupInfoElement } from './workspace-view-me
export default {
title: 'Workspaces/Data Type/Views/Info',
component: 'umb-workspace-view-data-type-info',
id: 'umb-workspace-view-data-type-info',
component: 'umb-workspace-view-member-group-info',
id: 'umb-workspace-view-member-group-info',
decorators: [
(story) => {
return html`TODO: make use of mocked workspace context??`;

View File

@@ -1,6 +1,6 @@
import { Meta } from '@storybook/addon-docs';
import { Meta } from '@storybook/blocks';
<Meta title="Guides/Context API" parameters={{ previewTabs: { canvas: { hidden: true } } }} />
<Meta title="Guides/Context API" />
# Context API
@@ -9,36 +9,14 @@ This element can be used as the base of any Element.
Do this if you need to Observe Data, Consume or Provide a Context API or use a Resource.
The Element implements the Controller Host and provides a few shortcut methods for initializing some Controllers.
The methods are (*note this can be out of date, we need to look into how we can ensure this Doc originates from code.*)
The methods are *note this can be out of date, we need to look into how we can ensure this Doc originates from code.*
### Consume a Context API.
From a Umbraco Element:
````
```typescript
this.consumeContext('requestThisContextAlias', (context) => {
// Notice this is a subscription, as context might change or a new one appears.
console.log("I've got the context", context);
});
````
Or with a Controller using a Controller Host(Umbraco Element):
````
new UmbContextConsumerController(hostElement, 'requestThisContextAlias', (context) => {
// Notice this is a subscription, as context might change or a new one appears.
console.log("I've got the context", context);
});
````
### Provide a Context API.
From a Umbraco Element:
````
this.provideContext('myContextAlias', new MyContextApi());
````
Or with a Controller using a Controller Host(Umbraco Element):
````
new UmbContextProviderController(hostElement, 'myContextAlias', new MyContextApi());
````
```

View File

@@ -1,31 +1,13 @@
import { Meta } from '@storybook/addon-docs';
import { Meta } from '@storybook/blocks';
<Meta title="Guides/Getting started" parameters={{ previewTabs: { canvas: { hidden: true } } }} />
<Meta title="Guides/Getting Started" />
# Getting started
This section contains a set of guide which will ease the learning of the Umbraco CMS (Backoffice).
In this document you will get a overview of the articles — Enabling you to get started with the parts that makes sense for you.
# Terminology
There is a few words that covers certain concepts, which is good to learn to easilier decode the purpose of code.
- **Resource** A API enabling communication with a server. [Go to Resource Guide](/?path=/story/guides-resource--page)
- **Store** A API representing data, generally coming from the server. Most stores would talk with one or more resources. [Go to Store Guide](/?path=/story/guides-store--page)
- **State** A reactive container holding data, when data is changed all its Observables will be notified.
- **Observable** An observable is the hook for others to subscribe to the data or part of the data of a State.
- **Observe** Observe is the term of what we do when subscriping to a Observable, We observe and observable.
- **Context-API** The name of the system used to serve APIs(instances/classes) that for a certain context in the DOM. An API that is served via the Context-API is called a Context [Go to Context API Guide](/?path=/story/guides-umbraco-element--page)
- **Context Provider** One that provides a class instance as a Context API.
- **Context Consumer** One that consumer/subscripes to a class instance as a Context API.
- **Controller** An abstract term for a things that hooks into the lifecycle of a element. Many things in our system is Controllers, As a example notice these controllers:
- **Context Provider Controller** A Context Provider as a Controller, this make its easy to implement a Context Provider.
- **Context Consumer Controller** A Context Consumer as a Controller, this make its easy to implement a Context Consumer.
- **Observer Controller** A Controller for handling the observe subscription for a Observable.
- **Controller Host** The element that can host one or more controllers.
- **Umbraco Element** The UmbLitElement or UmbElemenMixin is a implementation of the Controller Host as an element. Using this as your base element provides a few methods that makes life easier. [Go to Umbraco Element Guide](/?path=/story/guides-umbraco-element--page)
[Go to Resource Guide](/?path=/story/guides-resource--page)

View File

@@ -4,15 +4,13 @@ import { Meta } from '@storybook/addon-docs';
# Store
A store is the link between a Resource and a data implementation. A store is mainly taken form as a Context, In other words we will have to Consume the Context(Store) to get the Store.
Generally a Store will be holding one or more RxJS Subjects, each Subject is made available for Subscription via a RxJS Observable.
### A Simple Store:
````
```typescript
class MyProductStore {
#products = new ArrayState(<Array<MyProductType>>[], (product) => product.key);
public readonly products = this.#products.asObservable();
@@ -24,18 +22,16 @@ class MyProductStore {
// The Store provides it self as a Context-API.
new UmbContextProviderController(_host, 'MyStoreContextAlias', this);
}
}
````
```
In this example we created a ArrayState, A State which is specific to Arrays.
This holds the data for one or more Observables to convey for outsiders.
This example shows how to use the store:
````
```typescript
class MyImplementation extends UmbLitElement {
private _myProductStore?: MyProductStore;
constructor() {
@@ -49,27 +45,22 @@ class MyImplementation extends UmbLitElement {
});
}
private _observeAllProducts() {
if (!this._myProductStore) return;
// Notice this callback will be triggered initially and each time the products change:
this.observe(this._myProductStore.products, (products) => {
console.log("The data of all products is:", products);
console.log('The data of all products is:', products);
});
}
}
````
```
### A bit more meaningful Store:
Here we added a method that returns an Observable that is specific to the requested product.
````
```typescript
class MyProductStore {
...
@@ -89,14 +80,12 @@ class MyProductStore {
);
}
}
````
```
An example using this method:
````
```typescript
class MyImplementation extends UmbLitElement {
private _myProductStore?: MyProductStore;
constructor() {
@@ -115,14 +104,11 @@ class MyImplementation extends UmbLitElement {
// Notice this callback will be triggered initially and each time the specific product change:
this.observe(this._myProductStore.getByKey('1234'), (product) => {
console.log("The data of product `1234`` is:", product);
console.log('The data of product `1234`` is:', product);
});
}
}
````
```
### Create many Observables:
@@ -130,37 +116,29 @@ A Store must hold different Observables some very general and others specific. A
This example give some inspiration to how fine grained this can become:
````
```typescript
class MyProductStore {
#products = new ArrayState(<Array<MyProductType>>[]);
#products = new ArrayState(<Array<MyProductType>>[]);
public readonly products = this.#products.asObservable();
public readonly amountOfProducts = this.#products.getObservablePart((products) => products.length);
public readonly topTenRatedProducts = this.#products.getObservablePart((products) => products.sort((a, b) => b.rating - a.rating).slice(0, 10));
...
public readonly products = this.#products.asObservable();
public readonly amountOfProducts = this.#products.getObservablePart((products) => products.length);
public readonly topTenRatedProducts = this.#products.getObservablePart((products) => products.sort((a, b) => b.rating - a.rating).slice(0, 10));
...
}
````
```
An observer of an Observable will only be triggered if the specific part of that data has changed.
With this we can make a high performant application, only triggering the parts that needs to update when data is changed.
### Ensure unique data:
For incoming data to replace existing data, we need to clarify what makes a entry of the array unique.
In the examples of this guide each product has a key, and we have clarified this to the State by giving it the little method `(product) => product.key` as part of the its creation:
````
```typescript
class MyProductStore {
#products = new ArrayState(<Array<MyProductType>>[], (product) => product.key);
...
#products = new ArrayState(<Array<MyProductType>>[], (product) => product.key);
...
}
````
```