Compare commits
No commits in common. "86d6b52a3989cef0c73404f2a7552db02606485f" and "5a29c54a6ac9a014c814a5663503332cb2247308" have entirely different histories.
86d6b52a39
...
5a29c54a6a
@ -1,14 +1,13 @@
|
|||||||
import React from "react";
|
import React, { useRef } from "react";
|
||||||
import { themes } from '@storybook/theming';
|
import { themes } from '@storybook/theming';
|
||||||
import { ThemeProvider } from "../src/app/[lang]/dashboard/components/client/theme-provider/theme-provider";
|
import { ThemeProvider } from "../src/app/[lang]/dashboard/components/client/theme-provider/theme-provider";
|
||||||
import { DARK_MODE_EVENT_NAME } from 'storybook-dark-mode';
|
import { DARK_MODE_EVENT_NAME, UPDATE_DARK_MODE_EVENT_NAME } from 'storybook-dark-mode';
|
||||||
import { getI18n, LANGS } from "../src/bootstrap/i18n/i18n"
|
import { initI18next, LANGS } from "../src/bootstrap/i18n/i18n"
|
||||||
import { addons } from '@storybook/preview-api';
|
import { addons } from '@storybook/preview-api';
|
||||||
import { i18n } from "i18next";
|
import { i18n } from "i18next";
|
||||||
import { I18nextProvider } from "react-i18next";
|
import { I18nextProvider } from "react-i18next";
|
||||||
const channel = addons.getChannel();
|
const channel = addons.getChannel();
|
||||||
import "../src/app/globals.css"
|
import "../src/app/globals.css"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* This function will expand the object with nested properties
|
* This function will expand the object with nested properties
|
||||||
@ -70,7 +69,7 @@ const preview = {
|
|||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
setI18n((await getI18n({ lng: locale })).i18n);
|
setI18n((await initI18next({ lng: locale })).i18n);
|
||||||
})()
|
})()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import Button from "@/app/components/button/button";
|
||||||
|
import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm";
|
||||||
|
import { useDI } from "@/bootstrap/di/di-context";
|
||||||
|
import { useRef } from "react";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From a parent component Vm and view will be connected together.
|
||||||
|
*/
|
||||||
|
export default function CreateRandomInvoiceContainer() {
|
||||||
|
const di = useDI();
|
||||||
|
const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM));
|
||||||
|
|
||||||
|
return <Button vm={vm.current} />;
|
||||||
|
}
|
@ -1,4 +1,6 @@
|
|||||||
|
import { DocumentIcon } from "@/app/components/icons/document";
|
||||||
import HomeIcon from "@/app/components/icons/home";
|
import HomeIcon from "@/app/components/icons/home";
|
||||||
|
import { UserIcon } from "@/app/components/icons/user";
|
||||||
import { usePathname } from "next/navigation";
|
import { usePathname } from "next/navigation";
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
|
|
||||||
@ -21,9 +23,15 @@ export default function navLinkPersonalVM() {
|
|||||||
// Depending on the size of the application, this would be stored in a database.
|
// Depending on the size of the application, this would be stored in a database.
|
||||||
const links = useRef<LinkItem[]>([
|
const links = useRef<LinkItem[]>([
|
||||||
{ name: "Home", href: "/dashboard", icon: HomeIcon },
|
{ name: "Home", href: "/dashboard", icon: HomeIcon },
|
||||||
|
{
|
||||||
|
name: "Invoices",
|
||||||
|
href: "/dashboard/invoices",
|
||||||
|
icon: DocumentIcon,
|
||||||
|
},
|
||||||
|
{ name: "Customers", href: "/dashboard/customers", icon: UserIcon },
|
||||||
]).current;
|
]).current;
|
||||||
return {
|
return {
|
||||||
links,
|
links,
|
||||||
isLinkActive: (link: LinkItem) => pathname.includes(link.href),
|
isLinkActive: (link: LinkItem) => pathname === link.href,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
|
import CreateRandomInvoiceContainer from "@/app/[lang]/dashboard/components/client/create-random-invoice/create-random-invoice";
|
||||||
import latestInvoicesController from "@/app/[lang]/dashboard/controller/latest-invoices.controller";
|
import latestInvoicesController from "@/app/[lang]/dashboard/controller/latest-invoices.controller";
|
||||||
import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm";
|
|
||||||
import Button from "@/app/components/button/button";
|
|
||||||
import { ArrowPathIcon } from "@heroicons/react/24/outline";
|
import { ArrowPathIcon } from "@heroicons/react/24/outline";
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { isLeft } from "fp-ts/lib/Either";
|
import { isLeft } from "fp-ts/lib/Either";
|
||||||
@ -40,7 +39,6 @@ export default async function LatestInvoices() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full flex-col md:col-span-4">
|
<div className="flex w-full flex-col md:col-span-4">
|
||||||
<h2 className="mb-4 text-xl md:text-2xl">Latest Invoices</h2>
|
<h2 className="mb-4 text-xl md:text-2xl">Latest Invoices</h2>
|
||||||
@ -50,7 +48,7 @@ export default async function LatestInvoices() {
|
|||||||
<ArrowPathIcon className="h-5 w-5 text-gray-500" />
|
<ArrowPathIcon className="h-5 w-5 text-gray-500" />
|
||||||
<h3 className="ml-2 text-sm text-gray-500 ">Updated just now</h3>
|
<h3 className="ml-2 text-sm text-gray-500 ">Updated just now</h3>
|
||||||
</div>
|
</div>
|
||||||
<Button vmKey={CreateRandomInvoiceButtonVM} />
|
<CreateRandomInvoiceContainer />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import createInvoiceController from "@/app/[lang]/dashboard/controller/create-invoice.controller";
|
|
||||||
import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm";
|
import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm";
|
||||||
import di from "@/bootstrap/di/init-di";
|
import di from "@/bootstrap/di/init-di";
|
||||||
|
|
||||||
@ -9,12 +8,8 @@ export default function dashboardAppModule() {
|
|||||||
const dashboardDi = di.createChildContainer();
|
const dashboardDi = di.createChildContainer();
|
||||||
|
|
||||||
dashboardDi.register(
|
dashboardDi.register(
|
||||||
CreateRandomInvoiceButtonVM.name,
|
CreateRandomInvoiceButtonVM,
|
||||||
CreateRandomInvoiceButtonVM,
|
CreateRandomInvoiceButtonVM,
|
||||||
);
|
);
|
||||||
|
|
||||||
dashboardDi.register(createInvoiceController.name, {
|
|
||||||
useValue: createInvoiceController,
|
|
||||||
});
|
|
||||||
return dashboardDi;
|
return dashboardDi;
|
||||||
}
|
}
|
||||||
|
@ -2,13 +2,27 @@ import {
|
|||||||
LatestInvoicesSkeleton,
|
LatestInvoicesSkeleton,
|
||||||
RevenueChartSkeleton,
|
RevenueChartSkeleton,
|
||||||
} from "@/app/[lang]/dashboard/components/server/skeletons";
|
} from "@/app/[lang]/dashboard/components/server/skeletons";
|
||||||
|
import CardWrapper from "@/app/[lang]/dashboard/components/server/cards";
|
||||||
import RevenueChart from "@/app/[lang]/dashboard/components/server/revenue-chart";
|
import RevenueChart from "@/app/[lang]/dashboard/components/server/revenue-chart";
|
||||||
import { Suspense } from "react";
|
import { Suspense } from "react";
|
||||||
|
import { getServerTranslation, LANGS } from "@/bootstrap/i18n/i18n";
|
||||||
|
import langKey from "@/bootstrap/i18n/dictionaries/lang-key";
|
||||||
import LatestInvoices from "@/app/[lang]/dashboard/components/server/latest-invoices";
|
import LatestInvoices from "@/app/[lang]/dashboard/components/server/latest-invoices";
|
||||||
|
|
||||||
export default async function Dashboard() {
|
export default async function Dashboard(props: {
|
||||||
|
params: Promise<{ lang: LANGS }>;
|
||||||
|
}) {
|
||||||
|
const { params } = props;
|
||||||
|
const { lang } = await params;
|
||||||
|
const { t } = await getServerTranslation(lang);
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
|
<h1 className="mb-4 text-xl md:text-2xl">
|
||||||
|
{t(langKey.global.dashboard)}
|
||||||
|
</h1>
|
||||||
|
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-4">
|
||||||
|
<CardWrapper />
|
||||||
|
</div>
|
||||||
<div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8">
|
<div className="mt-6 grid grid-cols-1 gap-6 md:grid-cols-4 lg:grid-cols-8">
|
||||||
<Suspense fallback={<RevenueChartSkeleton />}>
|
<Suspense fallback={<RevenueChartSkeleton />}>
|
||||||
<RevenueChart />
|
<RevenueChart />
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import createInvoiceController from "@/app/[lang]/dashboard/controller/create-invoice.controller";
|
import createInvoiceController from "@/app/[lang]/dashboard/controller/create-invoice.controller";
|
||||||
import ButtonVm from "@/app/components/button/button.i-vm";
|
import ButtonVm from "@/app/components/button/button.i-vm";
|
||||||
import { useServerAction } from "@/bootstrap/helpers/hooks/use-server-action";
|
import { useServerAction } from "@/bootstrap/helpers/hooks/use-server-action";
|
||||||
@ -7,6 +5,7 @@ import useThrottle from "@/bootstrap/helpers/hooks/use-throttle";
|
|||||||
import BaseVM from "@/bootstrap/helpers/vm/base-vm";
|
import BaseVM from "@/bootstrap/helpers/vm/base-vm";
|
||||||
import langKey from "@/bootstrap/i18n/dictionaries/lang-key";
|
import langKey from "@/bootstrap/i18n/dictionaries/lang-key";
|
||||||
import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice.param";
|
import { InvoiceParam } from "@/feature/core/invoice/domain/param/invoice.param";
|
||||||
|
import { CreateInvoiceUsecase } from "@/feature/core/invoice/domain/usecase/create-invoice/create-invoice.usecase";
|
||||||
import { faker } from "@faker-js/faker";
|
import { faker } from "@faker-js/faker";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@ -17,11 +16,11 @@ import { useTranslation } from "react-i18next";
|
|||||||
* in this layer.
|
* in this layer.
|
||||||
*/
|
*/
|
||||||
export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> {
|
export default class CreateRandomInvoiceButtonVM extends BaseVM<ButtonVm> {
|
||||||
private createInvoice: typeof createInvoiceController;
|
private createInvoice: CreateInvoiceUsecase;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.createInvoice = this.di.resolve(createInvoiceController.name);
|
this.createInvoice = createInvoiceController;
|
||||||
}
|
}
|
||||||
|
|
||||||
useVM(): ButtonVm {
|
useVM(): ButtonVm {
|
||||||
|
@ -1,13 +1,4 @@
|
|||||||
import langKey from "@/bootstrap/i18n/dictionaries/lang-key";
|
export default function Home() {
|
||||||
import { getServerTranslation, LANGS } from "@/bootstrap/i18n/i18n";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
export default async function Home(props: {
|
|
||||||
params: Promise<{ lang: LANGS }>;
|
|
||||||
}) {
|
|
||||||
const { params } = props;
|
|
||||||
const { lang } = await params;
|
|
||||||
const { t } = await getServerTranslation(lang);
|
|
||||||
return (
|
return (
|
||||||
<main className="flex min-h-screen flex-col p-6">
|
<main className="flex min-h-screen flex-col p-6">
|
||||||
<div className="mt-4 flex grow flex-col gap-4 md:flex-row">
|
<div className="mt-4 flex grow flex-col gap-4 md:flex-row">
|
||||||
@ -17,12 +8,6 @@ export default async function Home(props: {
|
|||||||
<strong>Welcome to Acme.</strong> This is the example for the ,
|
<strong>Welcome to Acme.</strong> This is the example for the ,
|
||||||
brought to you by Vercel.
|
brought to you by Vercel.
|
||||||
</p>
|
</p>
|
||||||
<Link
|
|
||||||
className="flex rounded-md bg-primary-foreground p-3 ml-auto mr-auto text-white"
|
|
||||||
href="dashboard"
|
|
||||||
>
|
|
||||||
{t(langKey.global.dashboard)}
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
|
import CreateRandomInvoiceButtonVM from "@/app/[lang]/dashboard/vm/create-random-invoice-button-vm";
|
||||||
import Button from "@/app/components/button/button";
|
import Button from "@/app/components/button/button";
|
||||||
|
import { DiContext, useDI } from "@/bootstrap/di/di-context";
|
||||||
|
import mockedModuleDi from "@/bootstrap/di/mocked-module-di";
|
||||||
import Story from "@/bootstrap/helpers/view/storybook-base-template-type";
|
import Story from "@/bootstrap/helpers/view/storybook-base-template-type";
|
||||||
import getArgVM from "@/bootstrap/helpers/view/storybook-with-arg-vm";
|
import getArgVM from "@/bootstrap/helpers/view/storybook-with-arg-vm";
|
||||||
|
import { createInvoiceUsecaseKey } from "@/feature/core/invoice/domain/usecase/create-invoice/create-invoice.usecase";
|
||||||
import type { Meta } from "@storybook/react";
|
import type { Meta } from "@storybook/react";
|
||||||
|
import { useRef } from "react";
|
||||||
|
|
||||||
const meta: Meta = {
|
const meta: Meta = {
|
||||||
title: "general/Button",
|
title: "general/Button",
|
||||||
@ -27,3 +32,36 @@ export const Primary: Story = {
|
|||||||
return <Button vm={vm} memoizedByVM={false} />;
|
return <Button vm={vm} memoizedByVM={false} />;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const WithVM: Story = {
|
||||||
|
decorators: [
|
||||||
|
(Story) => {
|
||||||
|
const di = useRef(
|
||||||
|
mockedModuleDi([
|
||||||
|
{
|
||||||
|
token: CreateRandomInvoiceButtonVM,
|
||||||
|
provider: CreateRandomInvoiceButtonVM,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: createInvoiceUsecaseKey,
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, no-console
|
||||||
|
provider: (args: any) => console.log("clicked", args),
|
||||||
|
},
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
return (
|
||||||
|
<DiContext.Provider value={di.current}>
|
||||||
|
<Story di={di.current} />
|
||||||
|
</DiContext.Provider>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
],
|
||||||
|
render: () => {
|
||||||
|
function Child() {
|
||||||
|
const di = useDI();
|
||||||
|
const vm = useRef(di.resolve(CreateRandomInvoiceButtonVM));
|
||||||
|
return <Button vm={vm.current} memoizedByVM={false} />;
|
||||||
|
}
|
||||||
|
return <Child />;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
/* eslint-disable react-hooks/rules-of-hooks */
|
"use client";
|
||||||
|
|
||||||
|
// import gdi from "@/bootstrap/di/init-di";
|
||||||
/* eslint-disable react/display-name */
|
/* eslint-disable react/display-name */
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
/* eslint-disable react/jsx-props-no-spreading */
|
/* eslint-disable react/jsx-props-no-spreading */
|
||||||
|
|
||||||
"use client";
|
|
||||||
|
|
||||||
import { useDI } from "@/bootstrap/di/di-context";
|
|
||||||
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
|
import IBaseVM from "@/bootstrap/helpers/vm/i-base-vm";
|
||||||
import { Component, ReactNode, FC, PropsWithChildren, memo } from "react";
|
import { Component, ReactNode, FC, PropsWithChildren, memo } from "react";
|
||||||
import { InjectionToken } from "tsyringe";
|
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- */
|
/* -------------------------------------------------------------------------- */
|
||||||
/* Connector Component */
|
/* Connector Component */
|
||||||
@ -26,6 +23,7 @@ interface IVvmConnector<IVM, PROPS> extends PropsWithChildren {
|
|||||||
const VvmConnector = memo(
|
const VvmConnector = memo(
|
||||||
<IVM, PROPS>(props: IVvmConnector<IVM, PROPS>) => {
|
<IVM, PROPS>(props: IVvmConnector<IVM, PROPS>) => {
|
||||||
const { View, Vm, restProps, children } = props;
|
const { View, Vm, restProps, children } = props;
|
||||||
|
|
||||||
const vm = Vm.useVM();
|
const vm = Vm.useVM();
|
||||||
|
|
||||||
const allProps = {
|
const allProps = {
|
||||||
@ -47,7 +45,8 @@ const VvmConnector = memo(
|
|||||||
type IVMParent = Record<string, any>;
|
type IVMParent = Record<string, any>;
|
||||||
type IPropParent = Record<string, any> | undefined;
|
type IPropParent = Record<string, any> | undefined;
|
||||||
|
|
||||||
type BaseProps<PROPS extends IPropParent = undefined> = {
|
type BaseProps<IVM extends IVMParent, PROPS extends IPropParent = undefined> = {
|
||||||
|
vm: IBaseVM<IVM>;
|
||||||
restProps?: PROPS;
|
restProps?: PROPS;
|
||||||
/**
|
/**
|
||||||
* By default it's true.
|
* By default it's true.
|
||||||
@ -58,24 +57,6 @@ type BaseProps<PROPS extends IPropParent = undefined> = {
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
type BasePropsWithVM<
|
|
||||||
IVM extends IVMParent,
|
|
||||||
PROPS extends IPropParent = undefined,
|
|
||||||
> = BaseProps<PROPS> & {
|
|
||||||
/**
|
|
||||||
* Directly instantiated vm
|
|
||||||
*/
|
|
||||||
vm: IBaseVM<IVM>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type BasePropsWithVMKey<PROPS extends IPropParent = undefined> =
|
|
||||||
BaseProps<PROPS> & {
|
|
||||||
/**
|
|
||||||
* TSyringe key for vm to be injected
|
|
||||||
*/
|
|
||||||
vmKey: InjectionToken;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type BuildProps<
|
export type BuildProps<
|
||||||
IVM extends IVMParent,
|
IVM extends IVMParent,
|
||||||
PROPS extends IPropParent = undefined,
|
PROPS extends IPropParent = undefined,
|
||||||
@ -85,11 +66,6 @@ export type BuildProps<
|
|||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ViewProps<
|
|
||||||
IVM extends IVMParent,
|
|
||||||
PROPS extends IPropParent = undefined,
|
|
||||||
> = BasePropsWithVM<IVM, PROPS> | BasePropsWithVMKey<PROPS>;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base view is base component for all views in mvvm architecture which gets
|
* Base view is base component for all views in mvvm architecture which gets
|
||||||
* vm as props and connect it to the view and memoize the component by default
|
* vm as props and connect it to the view and memoize the component by default
|
||||||
@ -98,23 +74,7 @@ export type ViewProps<
|
|||||||
export default abstract class BaseView<
|
export default abstract class BaseView<
|
||||||
IVM extends IVMParent,
|
IVM extends IVMParent,
|
||||||
PROPS extends IPropParent = undefined,
|
PROPS extends IPropParent = undefined,
|
||||||
> extends Component<ViewProps<IVM, PROPS>> {
|
> extends Component<BaseProps<IVM, PROPS>> {
|
||||||
private vm: IBaseVM<IVM> | undefined;
|
|
||||||
|
|
||||||
constructor(props: ViewProps<IVM, PROPS>) {
|
|
||||||
super(props);
|
|
||||||
this.vm = this.initVm;
|
|
||||||
}
|
|
||||||
|
|
||||||
private get initVm() {
|
|
||||||
if (Object.hasOwn(this.props, "vmKey")) {
|
|
||||||
const { vmKey } = this.props as BasePropsWithVMKey<PROPS>;
|
|
||||||
const di = useDI();
|
|
||||||
return di.resolve(vmKey) as IBaseVM<IVM>;
|
|
||||||
}
|
|
||||||
return (this.props as BasePropsWithVM<IVM, PROPS>).vm;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected get componentName() {
|
protected get componentName() {
|
||||||
return this.constructor.name;
|
return this.constructor.name;
|
||||||
}
|
}
|
||||||
@ -122,16 +82,9 @@ export default abstract class BaseView<
|
|||||||
protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode;
|
protected abstract Build(props: BuildProps<IVM, PROPS>): ReactNode;
|
||||||
|
|
||||||
render(): ReactNode {
|
render(): ReactNode {
|
||||||
const { restProps, memoizedByVM, children, ...rest } = this.props;
|
const { vm, restProps, memoizedByVM, children, ...rest } = this.props;
|
||||||
|
|
||||||
VvmConnector.displayName = this.componentName;
|
VvmConnector.displayName = this.componentName;
|
||||||
const vm = memoizedByVM ? this.vm : this.initVm;
|
|
||||||
if (!vm) {
|
|
||||||
const isVmKey = Object.hasOwn(this.props, "vmKey");
|
|
||||||
const message = isVmKey
|
|
||||||
? "vm is not defined, check your di configuration"
|
|
||||||
: "pass correct vm";
|
|
||||||
throw new Error(`Vm is not defined${message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VvmConnector
|
<VvmConnector
|
||||||
@ -144,4 +97,5 @@ export default abstract class BaseView<
|
|||||||
</VvmConnector>
|
</VvmConnector>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
/* -------------------------------------------------------------------------- */
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user