Flex layout replacements. Switch to tailwind.css.
This commit is contained in:
parent
3a5ab479f0
commit
26f0028294
@ -35,7 +35,6 @@ import { TbMissingTranslationHandler } from './translate/missing-translate-handl
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MAT_DIALOG_DEFAULT_OPTIONS, MatDialogConfig, MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { TranslateDefaultCompiler } from '@core/translate/translate-default-compiler';
|
||||
import { WINDOW_PROVIDERS } from '@core/services/window.service';
|
||||
import { HotkeyModule } from 'angular2-hotkeys';
|
||||
@ -44,7 +43,6 @@ import { TranslateDefaultLoader } from '@core/translate/translate-default-loader
|
||||
import { EntityConflictInterceptor } from '@core/interceptors/entity-conflict.interceptor';
|
||||
|
||||
@NgModule({ exports: [], imports: [CommonModule,
|
||||
FlexLayoutModule.withConfig({ addFlexToParent: false }),
|
||||
MatDialogModule,
|
||||
MatButtonModule,
|
||||
MatSnackBarModule,
|
||||
|
||||
@ -15,10 +15,11 @@
|
||||
///
|
||||
|
||||
import { Component, Injectable, Type, ɵComponentDef, ɵNG_COMP_DEF } from '@angular/core';
|
||||
import { from, Observable, of } from 'rxjs';
|
||||
import { forkJoin, from, Observable, of } from 'rxjs';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { mergeMap } from 'rxjs/operators';
|
||||
import { guid } from '@core/utils';
|
||||
import { getFlexLayoutModule } from '@shared/legacy/flex-layout.models';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -34,9 +35,9 @@ export class DynamicComponentFactoryService {
|
||||
imports?: Type<any>[],
|
||||
preserveWhitespaces?: boolean,
|
||||
styles?: string[]): Observable<Type<T>> {
|
||||
return from(import('@angular/compiler')).pipe(
|
||||
mergeMap(() => {
|
||||
let componentImports: Type<any>[] = [CommonModule];
|
||||
return forkJoin({flexLayoutModule: getFlexLayoutModule(), compiler: from(import('@angular/compiler'))}).pipe(
|
||||
mergeMap((data) => {
|
||||
let componentImports: Type<any>[] = [CommonModule, data.flexLayoutModule];
|
||||
if (imports) {
|
||||
componentImports = [...componentImports, ...imports];
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ import {
|
||||
ɵNgModuleDef
|
||||
} from '@angular/core';
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Observable, ReplaySubject, throwError } from 'rxjs';
|
||||
import { forkJoin, from, Observable, ReplaySubject, throwError } from 'rxjs';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { IModulesMap } from '@modules/common/modules-map.models';
|
||||
import { TbResourceId } from '@shared/models/id/tb-resource-id';
|
||||
@ -38,6 +38,7 @@ import { selectIsAuthenticated } from '@core/auth/auth.selectors';
|
||||
import { AppState } from '@core/core.state';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { RequestConfig } from '@core/http/http-utils';
|
||||
import { getFlexLayoutModule } from '@app/shared/legacy/flex-layout.models';
|
||||
|
||||
export interface ModuleInfo {
|
||||
module: ɵNgModuleDef<any>;
|
||||
@ -187,26 +188,46 @@ export class ResourcesService {
|
||||
if (this.loadedModulesWithComponents[url]) {
|
||||
return this.loadedModulesWithComponents[url].asObservable();
|
||||
}
|
||||
modulesMap.init();
|
||||
const meta = this.getMetaInfo(resourceId);
|
||||
const subject = new ReplaySubject<ModulesWithComponents>();
|
||||
this.loadedModulesWithComponents[url] = subject;
|
||||
import('@angular/compiler').then(
|
||||
|
||||
forkJoin(
|
||||
[
|
||||
modulesMap.init(),
|
||||
from(import('@angular/compiler'))
|
||||
]
|
||||
).subscribe(
|
||||
() => {
|
||||
// @ts-ignore
|
||||
System.import(url, undefined, meta).then(
|
||||
(module: any) => {
|
||||
try {
|
||||
const modulesWithComponents = this.extractModulesWithComponents(module);
|
||||
if (modulesWithComponents.modules.length || modulesWithComponents.standaloneComponents.length) {
|
||||
for (const module of modulesWithComponents.modules) {
|
||||
this.patchModulesWithFlexLayout(modulesWithComponents).subscribe(
|
||||
{
|
||||
next: modules => {
|
||||
if (modules.modules.length || modules.standaloneComponents.length) {
|
||||
try {
|
||||
for (const module of modules.modules) {
|
||||
createNgModule(module.module.type, this.injector);
|
||||
}
|
||||
this.loadedModulesWithComponents[url].next(modulesWithComponents);
|
||||
this.loadedModulesWithComponents[url].complete();
|
||||
} catch (e) {
|
||||
console.log(`Unable to parse module from url: ${url}`, e);
|
||||
this.loadedModulesWithComponents[url].error(new Error(`Unable to parse module from url: ${url}`));
|
||||
}
|
||||
} else {
|
||||
this.loadedModulesWithComponents[url].error(new Error(`Module '${url}' doesn't have exported modules or components!`));
|
||||
}
|
||||
},
|
||||
error: err => {
|
||||
console.log(`Unable to patch module with flexLayout, module url: ${url}`, err);
|
||||
this.loadedModulesWithComponents[url].error(new Error(`Unable to patch module with flexLayout, module url: ${url}`));
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(`Unable to parse module from url: ${url}`, e);
|
||||
this.loadedModulesWithComponents[url].error(new Error(`Unable to parse module from url: ${url}`));
|
||||
@ -284,6 +305,40 @@ export class ResourcesService {
|
||||
return modulesWithComponents;
|
||||
}
|
||||
|
||||
private patchModulesWithFlexLayout(modulesWithComponents: ModulesWithComponents): Observable<ModulesWithComponents> {
|
||||
return getFlexLayoutModule().pipe(
|
||||
map((flexLayoutModule) => {
|
||||
modulesWithComponents.modules.forEach(m => {
|
||||
if (Array.isArray(m.module.imports)) {
|
||||
if (!m.module.imports.includes(flexLayoutModule)) {
|
||||
m.module.imports.push(flexLayoutModule);
|
||||
}
|
||||
} else {
|
||||
const imports = m.module.imports();
|
||||
if (!imports.includes(flexLayoutModule)) {
|
||||
imports.push(flexLayoutModule);
|
||||
m.module.imports = imports;
|
||||
}
|
||||
}
|
||||
});
|
||||
modulesWithComponents.standaloneComponents.forEach(c => {
|
||||
if (Array.isArray(c.dependencies)) {
|
||||
if (!c.dependencies.includes(flexLayoutModule)) {
|
||||
c.dependencies.push(flexLayoutModule);
|
||||
}
|
||||
} else {
|
||||
const dependencies = c.dependencies();
|
||||
if (!dependencies.includes(flexLayoutModule)) {
|
||||
dependencies.push(flexLayoutModule);
|
||||
c.dependencies = dependencies;
|
||||
}
|
||||
}
|
||||
});
|
||||
return modulesWithComponents;
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
private loadResourceByType(type: 'css' | 'js', url: string): Observable<any> {
|
||||
const subject = new ReplaySubject<void>();
|
||||
this.loadedResources[url] = subject;
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
export interface IModulesMap {
|
||||
init(): void;
|
||||
init(): Observable<any>;
|
||||
}
|
||||
|
||||
@ -20,10 +20,6 @@ import * as AngularAnimations from '@angular/animations';
|
||||
import * as AngularCore from '@angular/core';
|
||||
import * as AngularCommon from '@angular/common';
|
||||
import * as AngularForms from '@angular/forms';
|
||||
import * as AngularFlexLayout from '@angular/flex-layout';
|
||||
import * as AngularFlexLayoutFlex from '@angular/flex-layout/flex';
|
||||
import * as AngularFlexLayoutGrid from '@angular/flex-layout/grid';
|
||||
import * as AngularFlexLayoutExtended from '@angular/flex-layout/extended';
|
||||
import * as AngularPlatformBrowser from '@angular/platform-browser';
|
||||
import * as AngularPlatformBrowserAnimations from '@angular/platform-browser/animations';
|
||||
import * as AngularRouter from '@angular/router';
|
||||
@ -338,6 +334,8 @@ import { IModulesMap } from '@modules/common/modules-map.models';
|
||||
import { TimezoneComponent } from '@shared/components/time/timezone.component';
|
||||
import { TimezonePanelComponent } from '@shared/components/time/timezone-panel.component';
|
||||
import { DatapointsLimitComponent } from '@shared/components/time/datapoints-limit.component';
|
||||
import { Observable, map, of } from 'rxjs';
|
||||
import { getFlexLayout } from '@shared/legacy/flex-layout.models';
|
||||
|
||||
class ModulesMap implements IModulesMap {
|
||||
|
||||
@ -349,10 +347,10 @@ class ModulesMap implements IModulesMap {
|
||||
'@angular/common': AngularCommon,
|
||||
'@angular/common/http': HttpClientModule,
|
||||
'@angular/forms': AngularForms,
|
||||
'@angular/flex-layout': AngularFlexLayout,
|
||||
'@angular/flex-layout/flex': AngularFlexLayoutFlex,
|
||||
'@angular/flex-layout/grid': AngularFlexLayoutGrid,
|
||||
'@angular/flex-layout/extended': AngularFlexLayoutExtended,
|
||||
'@angular/flex-layout': {},
|
||||
'@angular/flex-layout/flex': {},
|
||||
'@angular/flex-layout/grid': {},
|
||||
'@angular/flex-layout/extended': {},
|
||||
'@angular/platform-browser': AngularPlatformBrowser,
|
||||
'@angular/platform-browser/animations': AngularPlatformBrowserAnimations,
|
||||
'@angular/router': AngularRouter,
|
||||
@ -669,8 +667,14 @@ class ModulesMap implements IModulesMap {
|
||||
'@home/components/queue/queue-form.component': QueueFormComponent
|
||||
};
|
||||
|
||||
init() {
|
||||
init(): Observable<any> {
|
||||
if (!this.initialized) {
|
||||
return getFlexLayout().pipe(
|
||||
map((flexLayout) => {
|
||||
this.modulesMap['@angular/flex-layout'] = flexLayout;
|
||||
this.modulesMap['@angular/flex-layout/flex'] = flexLayout;
|
||||
this.modulesMap['@angular/flex-layout/grid'] = flexLayout;
|
||||
this.modulesMap['@angular/flex-layout/extended'] = flexLayout;
|
||||
System.constructor.prototype.resolve = (id: string) => {
|
||||
try {
|
||||
if (this.modulesMap[id]) {
|
||||
@ -693,6 +697,10 @@ class ModulesMap implements IModulesMap {
|
||||
return fetch(url, options);
|
||||
};
|
||||
this.initialized = true;
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return of(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,85 +0,0 @@
|
||||
///
|
||||
/// Copyright © 2016-2024 The Thingsboard Authors
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import { Directive } from '@angular/core';
|
||||
import { BREAKPOINT, LayoutAlignDirective, LayoutDirective, LayoutGapDirective, ShowHideDirective } from '@angular/flex-layout';
|
||||
|
||||
const TB_BREAKPOINTS = [
|
||||
{
|
||||
alias: 'md-lg',
|
||||
mediaQuery: 'screen and (min-width: 960px) and (max-width: 1819px)',
|
||||
priority: 750
|
||||
},
|
||||
{
|
||||
alias: 'gt-md-lg',
|
||||
mediaQuery: 'screen and (min-width: 1820px)',
|
||||
priority: -600
|
||||
}
|
||||
];
|
||||
|
||||
export const TbBreakPointsProvider = {
|
||||
provide: BREAKPOINT,
|
||||
useValue: TB_BREAKPOINTS,
|
||||
multi: true
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxLayout.md-lg]', inputs: ['fxLayout.md-lg']})
|
||||
export class MdLgLayoutDirective extends LayoutDirective {
|
||||
protected inputs = ['fxLayout.md-lg'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxLayoutAlign.md-lg]', inputs: ['fxLayoutAlign.md-lg']})
|
||||
export class MdLgLayoutAlignDirective extends LayoutAlignDirective {
|
||||
protected inputs = ['fxLayoutAlign.md-lg'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxLayoutGap.md-lg]', inputs: ['fxLayoutGap.md-lg']})
|
||||
export class MdLgLayoutGapDirective extends LayoutGapDirective {
|
||||
protected inputs = ['fxLayoutGap.md-lg'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxHide.md-lg]', inputs: ['fxHide.md-lg']})
|
||||
export class MdLgShowHideDirective extends ShowHideDirective {
|
||||
protected inputs = ['fxHide.md-lg'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxLayout.gt-md-lg]', inputs: ['fxLayout.gt-md-lg']})
|
||||
export class GtMdLgLayoutDirective extends LayoutDirective {
|
||||
protected inputs = ['fxLayout.gt-md-lg'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxLayoutAlign.gt-md-lg]', inputs: ['fxLayoutAlign.gt-md-lg']})
|
||||
export class GtMdLgLayoutAlignDirective extends LayoutAlignDirective {
|
||||
protected inputs = ['fxLayoutAlign.gt-md-lg'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxLayoutGap.gt-md-lg]', inputs: ['fxLayoutGap.gt-md-lg']})
|
||||
export class GtMdLgLayoutGapDirective extends LayoutGapDirective {
|
||||
protected inputs = ['fxLayoutGap.gt-md-lg'];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property,@angular-eslint/directive-selector
|
||||
@Directive({selector: '[fxHide.gt-md-lg]', inputs: ['fxHide.gt-md-lg']})
|
||||
export class GtMdLgShowHideDirective extends ShowHideDirective {
|
||||
protected inputs = ['fxHide.gt-md-lg'];
|
||||
}
|
||||
41
ui-ngx/src/app/shared/legacy/flex-layout.models.ts
Normal file
41
ui-ngx/src/app/shared/legacy/flex-layout.models.ts
Normal file
@ -0,0 +1,41 @@
|
||||
///
|
||||
/// Copyright © 2016-2024 The Thingsboard Authors
|
||||
///
|
||||
/// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
/// you may not use this file except in compliance with the License.
|
||||
/// You may obtain a copy of the License at
|
||||
///
|
||||
/// http://www.apache.org/licenses/LICENSE-2.0
|
||||
///
|
||||
/// Unless required by applicable law or agreed to in writing, software
|
||||
/// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
/// See the License for the specific language governing permissions and
|
||||
/// limitations under the License.
|
||||
///
|
||||
|
||||
import { Observable } from 'rxjs/internal/Observable';
|
||||
import { from, of } from 'rxjs';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { Type } from '@angular/core';
|
||||
|
||||
let flexLayoutModule: any;
|
||||
|
||||
export function getFlexLayout(): Observable<any> {
|
||||
if (flexLayoutModule) {
|
||||
return of(flexLayoutModule);
|
||||
} else {
|
||||
return from(import('@angular/flex-layout')).pipe(
|
||||
tap((module) => {
|
||||
module.DEFAULT_CONFIG.addFlexToParent = false;
|
||||
flexLayoutModule = module;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function getFlexLayoutModule(): Observable<Type<any>> {
|
||||
return getFlexLayout().pipe(
|
||||
map(module => module.FlexLayoutModule)
|
||||
);
|
||||
}
|
||||
@ -58,7 +58,6 @@ import { MatListModule } from '@angular/material/list';
|
||||
import { DatetimeAdapter, MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core';
|
||||
import { NgxDaterangepickerMd } from 'ngx-daterangepicker-material';
|
||||
import { GridsterModule } from 'angular-gridster2';
|
||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { ShareButtonDirective } from 'ngx-sharebuttons';
|
||||
@ -179,17 +178,6 @@ import { NotificationComponent } from '@shared/components/notification/notificat
|
||||
import { TemplateAutocompleteComponent } from '@shared/components/notification/template-autocomplete.component';
|
||||
import { SlackConversationAutocompleteComponent } from '@shared/components/slack-conversation-autocomplete.component';
|
||||
import { DateAgoPipe } from '@shared/pipe/date-ago.pipe';
|
||||
import {
|
||||
GtMdLgLayoutAlignDirective,
|
||||
GtMdLgLayoutDirective,
|
||||
GtMdLgLayoutGapDirective,
|
||||
GtMdLgShowHideDirective,
|
||||
MdLgLayoutAlignDirective,
|
||||
MdLgLayoutDirective,
|
||||
MdLgLayoutGapDirective,
|
||||
MdLgShowHideDirective,
|
||||
TbBreakPointsProvider
|
||||
} from '@shared/layout/layout.directives';
|
||||
import { ColorPickerComponent } from '@shared/components/color-picker/color-picker.component';
|
||||
import { ResourceAutocompleteComponent } from '@shared/components/resource/resource-autocomplete.component';
|
||||
import { ShortNumberPipe } from '@shared/pipe/short-number.pipe';
|
||||
@ -286,7 +274,6 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
disableTooltipInteractivity: true
|
||||
}
|
||||
},
|
||||
TbBreakPointsProvider,
|
||||
CountryData
|
||||
],
|
||||
declarations: [
|
||||
@ -404,14 +391,6 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
NotificationComponent,
|
||||
TemplateAutocompleteComponent,
|
||||
SlackConversationAutocompleteComponent,
|
||||
MdLgLayoutDirective,
|
||||
MdLgLayoutAlignDirective,
|
||||
MdLgLayoutGapDirective,
|
||||
MdLgShowHideDirective,
|
||||
GtMdLgLayoutDirective,
|
||||
GtMdLgLayoutAlignDirective,
|
||||
GtMdLgLayoutGapDirective,
|
||||
GtMdLgShowHideDirective,
|
||||
ColorPickerComponent,
|
||||
ColorPickerPanelComponent,
|
||||
ResourceAutocompleteComponent,
|
||||
@ -484,7 +463,6 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
DragDropModule,
|
||||
GridsterModule,
|
||||
ClipboardModule,
|
||||
FlexLayoutModule.withConfig({addFlexToParent: false}),
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
OverlayModule,
|
||||
@ -606,7 +584,6 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
DragDropModule,
|
||||
GridsterModule,
|
||||
ClipboardModule,
|
||||
FlexLayoutModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
OverlayModule,
|
||||
@ -671,14 +648,6 @@ export function MarkedOptionsFactory(markedOptionsService: MarkedOptionsService)
|
||||
NotificationComponent,
|
||||
TemplateAutocompleteComponent,
|
||||
SlackConversationAutocompleteComponent,
|
||||
MdLgLayoutDirective,
|
||||
MdLgLayoutAlignDirective,
|
||||
MdLgLayoutGapDirective,
|
||||
MdLgShowHideDirective,
|
||||
GtMdLgLayoutDirective,
|
||||
GtMdLgLayoutAlignDirective,
|
||||
GtMdLgLayoutGapDirective,
|
||||
GtMdLgShowHideDirective,
|
||||
ColorPickerComponent,
|
||||
ColorPickerPanelComponent,
|
||||
ResourceAutocompleteComponent,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user