Forráskód Böngészése

chore: Add example UI extension plugin

Michael Bromley 2 éve
szülő
commit
1da2edb220

+ 11 - 0
packages/dev-server/example-plugins/ui-extensions-library/ui-extensions-library.plugin.ts

@@ -0,0 +1,11 @@
+import { AdminUiExtension } from '@vendure/ui-devkit/compiler';
+import path from 'path';
+
+export class UiExtensionsLibraryPlugin {
+    static uiExtensions: AdminUiExtension = {
+        id: 'ui-extensions-library',
+        extensionPath: path.join(__dirname, 'ui'),
+        routes: [{ route: 'ui-library', filePath: 'routes.ts' }],
+        providers: ['providers.ts'],
+    };
+}

+ 92 - 0
packages/dev-server/example-plugins/ui-extensions-library/ui/angular-components/angular-ui/angular-ui.component.html

@@ -0,0 +1,92 @@
+<vdr-page-block>
+    <vdr-action-bar>
+        <vdr-ab-left>Action bar left contents</vdr-ab-left>
+        <vdr-ab-right>
+            <button class="button primary" (click)="updateTitle()" [disabled]="pageTitleControl.pristine">Update page title</button>
+        </vdr-ab-right>
+    </vdr-action-bar>
+</vdr-page-block>
+<vdr-page-detail-layout>
+    <vdr-page-detail-sidebar>
+        <vdr-card> Sidebar content </vdr-card>
+    </vdr-page-detail-sidebar>
+    <vdr-page-block>
+        <vdr-card title="Card">
+            This is a card. On a detail page, content should usually be placed inside a card.
+        </vdr-card>
+        <vdr-card title="Form inputs">
+            <div class="form-grid">
+                <vdr-form-field label="Page title">
+                    <input type="text" [formControl]="pageTitleControl" />
+                </vdr-form-field>
+                <vdr-form-field label="Select input">
+                    <select>
+                        <option>Option 1</option>
+                        <option>Option 2</option>
+                    </select>
+                </vdr-form-field>
+                <vdr-form-field label="Checkbox input">
+                    <input type="checkbox" />
+                </vdr-form-field>
+                <vdr-form-field label="Textarea input">
+                    <textarea></textarea>
+                </vdr-form-field>
+                <vdr-form-field label="With tooltip" tooltip="This is a tooltip for the form input">
+                    <input type="text" />
+                </vdr-form-field>
+                <vdr-form-field label="Invalid with error">
+                    <input type="text" [formControl]="invalidFormControl" />
+                </vdr-form-field>
+            </div>
+        </vdr-card>
+
+        <vdr-card title="Icons">
+            <demo-block label="Sizes">
+                <clr-icon shape="star" size="8"></clr-icon>
+                <clr-icon shape="star" size="16"></clr-icon>
+                <clr-icon shape="star" size="24"></clr-icon>
+                <clr-icon shape="star" size="36"></clr-icon>
+                <clr-icon shape="star" size="48"></clr-icon>
+                <clr-icon shape="star" size="56"></clr-icon>
+            </demo-block>
+
+            <demo-block label="Badges">
+                <clr-icon shape="user" class="has-badge--success"></clr-icon>
+                <clr-icon shape="user" class="has-alert"></clr-icon>
+                <clr-icon shape="user" class="has-badge--info"></clr-icon>
+                <clr-icon shape="user" class="has-badge--error"></clr-icon>
+            </demo-block>
+
+            <demo-block label="Status colors">
+                <clr-icon shape="user" class="is-success"></clr-icon>
+                <clr-icon shape="user" class="is-info"></clr-icon>
+                <clr-icon shape="user" class="is-warning"></clr-icon>
+                <clr-icon shape="user" class="is-error"></clr-icon>
+            </demo-block>
+        </vdr-card>
+
+        <vdr-card title="Buttons">
+            <demo-block label="Regular">
+                <button class="button primary">Primary</button>
+                <button class="button secondary">Secondary</button>
+                <button class="button success">Success</button>
+                <button class="button warning">Warning</button>
+                <button class="button danger">Danger</button>
+            </demo-block>
+            <demo-block label="Ghost">
+                <button class="button-ghost">Ghost</button>
+                <a class="button-ghost" [routerLink]="['/extensions/ui-library/angular-ui']">
+                    <clr-icon shape="arrow" dir="right"></clr-icon>
+                    John Smith
+                </a>
+            </demo-block>
+            <demo-block label="Small">
+                <button class="button-small">Small</button>
+                <button class="button-small">
+                    <clr-icon shape="layers"></clr-icon>
+                    Assign to channel
+                </button>
+            </demo-block>
+        </vdr-card>
+    </vdr-page-block>
+</vdr-page-detail-layout>

+ 43 - 0
packages/dev-server/example-plugins/ui-extensions-library/ui/angular-components/angular-ui/angular-ui.component.ts

@@ -0,0 +1,43 @@
+import { Component, Input } from '@angular/core';
+import { FormControl } from '@angular/forms';
+import { NotificationService, PageMetadataService, SharedModule } from '@vendure/admin-ui/core';
+
+@Component({
+    selector: 'demo-block',
+    template: `
+        <div class="mb-4">
+            <label>{{ label }}</label>
+            <div class="mt-1 flex" style="gap: 12px;">
+                <ng-content />
+            </div>
+        </div>
+    `,
+    standalone: true,
+})
+export class DemoBlockComponent {
+    @Input() label: string;
+}
+
+@Component({
+    selector: 'angular-ui',
+    templateUrl: './angular-ui.component.html',
+    standalone: true,
+    imports: [SharedModule, DemoBlockComponent],
+})
+export class AngularUiComponent {
+    pageTitleControl = new FormControl('Angular UI');
+    invalidFormControl = new FormControl('', () => ({ invalid: true }));
+    constructor(
+        private notificationService: NotificationService,
+        private pageMetadataService: PageMetadataService,
+    ) {}
+
+    updateTitle() {
+        const title = this.pageTitleControl.value;
+        if (title) {
+            this.pageMetadataService.setTitle(title);
+            this.notificationService.success(`Updated title to "${title}"`);
+            this.pageTitleControl.markAsPristine();
+        }
+    }
+}

+ 20 - 0
packages/dev-server/example-plugins/ui-extensions-library/ui/providers.ts

@@ -0,0 +1,20 @@
+import { addNavMenuSection } from '@vendure/admin-ui/core';
+
+export default [
+    addNavMenuSection({
+        id: 'ui-extensions-library',
+        label: 'UI Extensions Library',
+        items: [
+            {
+                id: 'react-ui',
+                label: 'React UI',
+                routerLink: ['/extensions/ui-library/react-ui'],
+            },
+            {
+                id: 'angular-ui',
+                label: 'Angular UI',
+                routerLink: ['/extensions/ui-library/angular-ui'],
+            },
+        ],
+    }),
+];

+ 142 - 0
packages/dev-server/example-plugins/ui-extensions-library/ui/react-components/ReactUi.tsx

@@ -0,0 +1,142 @@
+import { arrowIcon, layersIcon, starIcon, userIcon } from '@cds/core/icon';
+import { NotificationService } from '@vendure/admin-ui/core';
+import {
+    ActionBar,
+    Card,
+    CdsIcon,
+    FormField,
+    Link,
+    PageBlock,
+    PageDetailLayout,
+    useInjector,
+    usePageMetadata,
+} from '@vendure/admin-ui/react';
+import React, { PropsWithChildren, useState } from 'react';
+
+export function ReactUi() {
+    const notificationService = useInjector(NotificationService);
+    const { setTitle } = usePageMetadata();
+    const [titleModified, setTitleModified] = useState(false);
+    const [titleValue, setTitleValue] = useState('React UI');
+
+    function updateTitle() {
+        setTitle(titleValue);
+        setTitleModified(false);
+        notificationService.success(`Updated title to "${titleValue}"`);
+    }
+
+    return (
+        <>
+            <PageBlock>
+                <ActionBar leftContent={<div>Action bar left contents</div>}>
+                    <button className="button primary" onClick={updateTitle} disabled={!titleModified}>
+                        Update page title
+                    </button>
+                </ActionBar>
+            </PageBlock>
+
+            <PageDetailLayout
+                sidebar={
+                    <div>
+                        <Card>Sidebar content</Card>
+                    </div>
+                }
+            >
+                <PageBlock>
+                    <Card title="Card">
+                        This is a card. On a detail page, content should usually be placed inside a card.
+                    </Card>
+                    <Card title="Form inputs">
+                        <div className="form-grid">
+                            <FormField label="Page title">
+                                <input
+                                    value={titleValue}
+                                    onInput={e => {
+                                        setTitleValue((e.target as any).value);
+                                        setTitleModified(true);
+                                    }}
+                                />
+                            </FormField>
+                            <FormField label="Select input">
+                                <select>
+                                    <option>Option 1</option>
+                                    <option>Option 2</option>
+                                </select>
+                            </FormField>
+                            <FormField label="Checkbox input">
+                                <input type="checkbox" />
+                            </FormField>
+                            <FormField label="Textarea input">
+                                <textarea></textarea>
+                            </FormField>
+                            <FormField label="With tooltip" tooltip="This is a tooltip for the form input">
+                                <input type="text" />
+                            </FormField>
+                            <FormField label="Invalid with error" invalid={true}>
+                                <input type="text" />
+                            </FormField>
+                        </div>
+                    </Card>
+
+                    <Card title="Icons">
+                        <DemoBlock label="Sizes">
+                            <CdsIcon icon={starIcon} size={'xs'}></CdsIcon>
+                            <CdsIcon icon={starIcon} size={'sm'}></CdsIcon>
+                            <CdsIcon icon={starIcon} size={'md'}></CdsIcon>
+                            <CdsIcon icon={starIcon} size={'lg'}></CdsIcon>
+                            <CdsIcon icon={starIcon} size={'xl'}></CdsIcon>
+                            <CdsIcon icon={starIcon} size={'xxl'}></CdsIcon>
+                        </DemoBlock>
+                        <DemoBlock label="Badges">
+                            <CdsIcon icon={userIcon} badge={'success'}></CdsIcon>
+                            <CdsIcon icon={userIcon} badge={'info'}></CdsIcon>
+                            <CdsIcon icon={userIcon} badge={'warning'}></CdsIcon>
+                            <CdsIcon icon={userIcon} badge={'danger'}></CdsIcon>
+                        </DemoBlock>
+                        <DemoBlock label="Status colors">
+                            <CdsIcon icon={userIcon} status={'success'}></CdsIcon>
+                            <CdsIcon icon={userIcon} status={'info'}></CdsIcon>
+                            <CdsIcon icon={userIcon} status={'warning'}></CdsIcon>
+                            <CdsIcon icon={userIcon} status={'danger'}></CdsIcon>
+                        </DemoBlock>
+                    </Card>
+
+                    <Card title={'Buttons'}>
+                        <DemoBlock label="Regular">
+                            <button className="button primary">Primary</button>
+                            <button className="button secondary">Secondary</button>
+                            <button className="button success">Success</button>
+                            <button className="button warning">Warning</button>
+                            <button className="button danger">Danger</button>
+                        </DemoBlock>
+                        <DemoBlock label="Ghost">
+                            <button className="button-ghost">Ghost</button>
+                            <Link className="button-ghost" href="/extensions/ui-library/react-ui">
+                                <CdsIcon icon={arrowIcon} direction="right" />
+                                John Smith
+                            </Link>
+                        </DemoBlock>
+                        <DemoBlock label="Small">
+                            <button className="button-small">Small</button>
+                            <button className="button-small">
+                                <CdsIcon icon={layersIcon} />
+                                Assign to channel
+                            </button>
+                        </DemoBlock>
+                    </Card>
+                </PageBlock>
+            </PageDetailLayout>
+        </>
+    );
+}
+
+function DemoBlock(props: PropsWithChildren<{ label: string }>) {
+    return (
+        <div className="mb-4">
+            <label>{props.label}</label>
+            <div className="mt-1 flex" style={{ gap: '12px' }}>
+                {props.children}
+            </div>
+        </div>
+    );
+}

+ 18 - 0
packages/dev-server/example-plugins/ui-extensions-library/ui/routes.ts

@@ -0,0 +1,18 @@
+import { registerRouteComponent } from '@vendure/admin-ui/core';
+import { registerReactRouteComponent } from '@vendure/admin-ui/react';
+
+import { AngularUiComponent } from './angular-components/angular-ui/angular-ui.component';
+import { ReactUi } from './react-components/ReactUi';
+
+export default [
+    registerReactRouteComponent({
+        path: 'react-ui',
+        component: ReactUi,
+        title: 'React UI',
+    }),
+    registerRouteComponent({
+        path: 'angular-ui',
+        component: AngularUiComponent,
+        title: 'Angular UI',
+    }),
+];