opendash
Version:
open.DASH data visualization framework
244 lines (191 loc) • 6.67 kB
text/typescript
import {
createI18n,
createState,
AppConfigRouteInterface,
WidgetTypeInterface,
AppFactoryLockedError,
AppInterface,
UserService,
UserAdapterInterface,
DataService,
DataAdapterInterface,
DashboardService,
TranslationResolverInterface,
NavigationGroupInterface,
NavigationItemInterface,
ServicesInterface,
DashboardAdapterInterface,
StorageAdapterInterface,
SourceAdapterInterface,
NavigationAdapterInterface,
StorageService,
NavigationService,
SourceService,
AppPluginInterface,
} from "..";
import enTranslation from "../translations/opendash_en";
import antdTranslation from "../translations/antd_en";
type PossibleESModule<T> = T | { default: T };
export class AppFactory {
private locked: boolean = false;
private id: string;
private adapter: {
User?: UserAdapterInterface;
Data?: DataAdapterInterface;
Source?: SourceAdapterInterface;
Navigation?: NavigationAdapterInterface;
Dashboard?: DashboardAdapterInterface;
DeviceStorage?: StorageAdapterInterface;
UserStorage?: StorageAdapterInterface;
} = {};
private routes: AppConfigRouteInterface[] = [];
private widgets: WidgetTypeInterface[] = [];
private languages: { key: string; label: string; fallback: string }[] = [];
private translationResolver: Map<
string,
TranslationResolverInterface
> = new Map();
private staticNavigationGroups: NavigationGroupInterface[] = [];
private staticNavigationItems: NavigationItemInterface[] = [];
constructor(id: string) {
this.id = id;
this.registerTranslationResolver(
"en",
"opendash",
async () => enTranslation
);
this.registerTranslationResolver("en", "antd", async () => antdTranslation);
}
async use(plugin: AppPluginInterface): Promise<void> {
if (this.locked) throw new AppFactoryLockedError("use");
await Promise.resolve(plugin.onFactory(this));
}
registerLanguage(key: string, label: string, fallback: string = "en") {
if (this.locked) throw new AppFactoryLockedError("registerLanguage");
this.languages = this.languages.filter((lang) => lang.key !== key);
this.languages.push({ key, label, fallback });
}
registerTranslationResolver(
language: string,
namespace: string,
resolver: TranslationResolverInterface
) {
if (this.locked)
throw new AppFactoryLockedError("registerTranslationResolver");
this.translationResolver.set([language, namespace].join(","), resolver);
}
registerDataAdapter(adapter: PossibleESModule<DataAdapterInterface>): void {
if (this.locked) throw new AppFactoryLockedError("registerDataAdapter");
this.adapter.Data = this.extractESModule(adapter);
}
registerUserAdapter(adapter: PossibleESModule<UserAdapterInterface>): void {
if (this.locked) throw new AppFactoryLockedError("registerUserAdapter");
this.adapter.User = this.extractESModule(adapter);
}
registerDashboardAdapter(
adapter: PossibleESModule<DashboardAdapterInterface>
): void {
if (this.locked)
throw new AppFactoryLockedError("registerDashboardAdapter");
this.adapter.Dashboard = this.extractESModule(adapter);
}
registerSourceAdapter(
adapter: PossibleESModule<SourceAdapterInterface>
): void {
if (this.locked) throw new AppFactoryLockedError("registerSourceAdapter");
this.adapter.Source = this.extractESModule(adapter);
}
registerNavigationAdapter(
adapter: PossibleESModule<NavigationAdapterInterface>
): void {
if (this.locked)
throw new AppFactoryLockedError("registerNavigationAdapter");
this.adapter.Navigation = this.extractESModule(adapter);
}
registerUserStorageAdapter(
adapter: PossibleESModule<StorageAdapterInterface>
): void {
if (this.locked)
throw new AppFactoryLockedError("registerUserStorageAdapter");
this.adapter.UserStorage = this.extractESModule(adapter);
}
registerDeviceStorageAdapter(
adapter: PossibleESModule<StorageAdapterInterface>
): void {
if (this.locked)
throw new AppFactoryLockedError("registerDeviceStorageAdapter");
this.adapter.DeviceStorage = this.extractESModule(adapter);
}
registerRoute(route: PossibleESModule<AppConfigRouteInterface>): void {
if (this.locked) throw new AppFactoryLockedError("registerRoute");
this.routes.push(this.extractESModule(route));
}
registerWidget(widget: PossibleESModule<WidgetTypeInterface>): void {
if (this.locked) throw new AppFactoryLockedError("registerWidget");
this.widgets.push(this.extractESModule(widget));
}
registerStaticNavigationGroup(group: NavigationGroupInterface): void {
if (this.locked)
throw new AppFactoryLockedError("registerStaticNavigationGroup");
this.staticNavigationGroups.push(group);
}
registerStaticNavigationItem(item: NavigationItemInterface): void {
if (this.locked)
throw new AppFactoryLockedError("registerStaticNavigationItem");
this.staticNavigationItems.push(item);
}
createApp(): AppInterface {
const i18n = createI18n(this.languages, this.translationResolver);
const state = createState();
// @ts-ignore
const services: ServicesInterface = {};
const app: AppInterface = {
id: this.id,
state,
i18n,
routes: this.routes,
widgets: this.widgets,
services,
ui: {
refs: {
headerBeforeMenuLeft: { current: null },
headerAfterMenuLeft: { current: null },
headerBeforeMenuRight: { current: null },
headerAfterMenuRight: { current: null },
headerAfterLogo: { current: null },
},
languages: this.languages,
staticNavigationGroups: this.staticNavigationGroups,
staticNavigationItems: this.staticNavigationItems,
},
};
services.DeviceStorageService = new StorageService(
app,
this.adapter.DeviceStorage
);
services.UserService = new UserService(app, this.adapter.User);
services.UserStorageService = new StorageService(
app,
this.adapter.UserStorage
);
services.SourceService = new SourceService(app, this.adapter.Source);
services.DashboardService = new DashboardService(
app,
this.adapter.Dashboard
);
services.NavigationService = new NavigationService(
app,
this.adapter.Navigation
);
services.DataService = new DataService(app, this.adapter.Data);
return app;
}
private extractESModule<T = any>(input: PossibleESModule<T>): T {
// @ts-ignore
if (input.default) {
// @ts-ignore
return input.default;
}
return input as T;
}
}