* feat: add widgets (#2034)

* feat: add Taiga UI library (#1992)

* feat: add widgets

* update patchdb

* right resizable sidebar with widgets

* feat: add resizing directive

* chore: remove unused code

* chore: remove unnecessary dep

* feat: `ResponsiveCol` add directive for responsive grid

* feat: add widgets edit mode and dialogs

* feat: add widgets model and modal

* chore: fix import

* chore: hide mobile widgets behind flag

* chore: add dummy widgets

* chore: start working on heath widget and implement other comments

* feat: health widget

* feat: add saving widgets and sidebar params to patch

* feat: preemptive UI update for widgets

* update health widget with more accurate states and styling (#2127)

* feat: `ResponsiveCol` add directive for responsive grid

* chore: some changes after merge

Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>
Co-authored-by: Lucy C <12953208+elvece@users.noreply.github.com>

* fix(shared): `ElasticContainer` fix collapsing margin (#2150)

* fix(shared): `ElasticContainer` fix collapsing margin

* fix toolbar height so titles not chopped

---------

Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>

* feat: make widgets sidebar width togglable (#2146)

* feat: make widgets sidebar width togglable

* feat: move widgets under header

* chore: fix wide layout

* fix(shared): `ResponsiveCol` fix missing grid steps (#2153)

* fix widget flag and refactor for non-persistence

* default widget flag to false

* fix(shared): fix responsive column size (#2159)

* fix(shared): fix responsive column size

* fix: add responsiveness to all pages

* fix responsiveness on more pages

* fix: comments

* revert some padding changes

---------

Co-authored-by: Lucy Cifferello <12953208+elvece@users.noreply.github.com>
Co-authored-by: Matt Hill <matthewonthemoon@gmail.com>

* chore: add analyzer (#2165)

* fix list styling to previous default (#2173)

* fix list styling to previous default

* dont need important flag

---------

Co-authored-by: Alex Inkin <alexander@inkin.ru>
Co-authored-by: Lucy C <12953208+elvece@users.noreply.github.com>
This commit is contained in:
Matt Hill
2023-03-02 15:21:03 -07:00
committed by Aiden McClelland
parent aeb6da111b
commit e867f31c31
113 changed files with 2452 additions and 295 deletions

View File

@@ -8,7 +8,8 @@
"@ionic/angular": ">=6.0.0",
"@ng-web-apis/mutation-observer": ">=2.0.0",
"@ng-web-apis/resize-observer": ">=2.0.0",
"@start9labs/emver": "^0.1.5"
"@start9labs/emver": "^0.1.5",
"@taiga-ui/cdk": ">=3.0.0"
},
"exports": {
"./assets/": "./assets/"

View File

@@ -1,3 +1,3 @@
<div (elasticContainer)="height = $event">
<div class="wrapper" (elasticContainer)="height = $event">
<ng-content></ng-content>
</div>

View File

@@ -3,3 +3,8 @@
overflow: hidden;
transition: height 0.25s;
}
.wrapper {
padding-top: 1px;
margin-top: -1px;
}

View File

@@ -29,7 +29,7 @@ export class ElasticContainerDirective {
inject(ResizeObserverService),
inject(MutationObserverService),
).pipe(
map(() => this.elementRef.nativeElement.clientHeight),
map(() => this.elementRef.nativeElement.clientHeight - 1), // Compensate for padding
distinctUntilChanged(),
)
}

View File

@@ -1,11 +0,0 @@
import { Directive, ElementRef, Inject } from '@angular/core'
@Directive({
selector: '[elementRef]',
exportAs: 'elementRef',
})
export class ElementDirective<T extends Element> extends ElementRef<T> {
constructor(@Inject(ElementRef) { nativeElement }: ElementRef<T>) {
super(nativeElement)
}
}

View File

@@ -1,9 +0,0 @@
import { NgModule } from '@angular/core'
import { ElementDirective } from './element.directive'
@NgModule({
declarations: [ElementDirective],
exports: [ElementDirective],
})
export class ElementModule {}

View File

@@ -0,0 +1,68 @@
import {
Directive,
ElementRef,
Inject,
InjectionToken,
Input,
NgZone,
} from '@angular/core'
import { ResizeObserverService } from '@ng-web-apis/resize-observer'
import { distinctUntilChanged, Observable } from 'rxjs'
import { map } from 'rxjs/operators'
import { tuiZonefree } from '@taiga-ui/cdk'
export type Step = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
/**
* Not exported:
* https://github.com/ionic-team/ionic-framework/blob/main/core/src/utils/media.ts
*
* export const SIZE_TO_MEDIA: any = {
* xs: '(min-width: 0px)',
* sm: '(min-width: 576px)',
* md: '(min-width: 768px)',
* lg: '(min-width: 992px)',
* xl: '(min-width: 1200px)',
* };
*/
export const BREAKPOINTS = new InjectionToken<readonly [number, Step][]>(
'BREAKPOINTS',
{
factory: () => [
[1200, 'xl'],
[992, 'lg'],
[768, 'md'],
[576, 'sm'],
[0, 'xs'],
],
},
)
@Directive({
selector: '[responsiveColViewport]',
exportAs: 'viewport',
providers: [ResizeObserverService],
})
export class ResponsiveColViewportDirective extends Observable<Step> {
@Input()
responsiveColViewport: Observable<Step> | '' = ''
private readonly stream$ = this.resize$.pipe(
map(() => this.elementRef.nativeElement.clientWidth),
map(width => this.breakpoints.find(([step]) => width >= step)?.[1] || 'xs'),
distinctUntilChanged(),
tuiZonefree(this.zone),
)
constructor(
@Inject(BREAKPOINTS)
private readonly breakpoints: readonly [number, Step][],
private readonly resize$: ResizeObserverService,
private readonly elementRef: ElementRef<HTMLElement>,
private readonly zone: NgZone,
) {
super(subscriber =>
(this.responsiveColViewport || this.stream$).subscribe(subscriber),
)
}
}

View File

@@ -0,0 +1,56 @@
import { Directive, OnInit, Optional } from '@angular/core'
import { TuiDestroyService } from '@taiga-ui/cdk'
import {
ResponsiveColViewportDirective,
Step,
} from './responsive-col-viewport.directive'
import { IonCol } from '@ionic/angular'
import { takeUntil } from 'rxjs'
const SIZE: readonly Step[] = ['xl', 'lg', 'md', 'sm', 'xs']
@Directive({
selector: 'ion-col[responsiveCol]',
providers: [TuiDestroyService],
})
export class ResponsiveColDirective implements OnInit {
readonly size: Record<Step, string | undefined> = {
xs: '12',
sm: '6',
md: '4',
lg: '3',
xl: '2',
}
constructor(
@Optional()
viewport$: ResponsiveColViewportDirective | null,
destroy$: TuiDestroyService,
private readonly col: IonCol,
) {
viewport$?.pipe(takeUntil(destroy$)).subscribe(size => {
const max = this.size[size] || this.findMax(size)
this.col.sizeLg = max
this.col.sizeMd = max
this.col.sizeSm = max
this.col.sizeXl = max
this.col.sizeXs = max
})
}
ngOnInit() {
this.size.lg = this.col.sizeLg
this.size.md = this.col.sizeMd
this.size.sm = this.col.sizeSm
this.size.xl = this.col.sizeXl
this.size.xs = this.col.sizeXs
}
private findMax(current: Step): string | undefined {
const start = SIZE.indexOf(current) - 1
const max = SIZE.find((size, i) => i > start && this.size[size]) || current
return this.size[max]
}
}

View File

@@ -0,0 +1,10 @@
import { NgModule } from '@angular/core'
import { ResponsiveColViewportDirective } from './responsive-col-viewport.directive'
import { ResponsiveColDirective } from './responsive-col.directive'
@NgModule({
declarations: [ResponsiveColDirective, ResponsiveColViewportDirective],
exports: [ResponsiveColDirective, ResponsiveColViewportDirective],
})
export class ResponsiveColModule {}

View File

@@ -22,8 +22,9 @@ export * from './components/toast/toast.component'
export * from './components/toast/toast.module'
export * from './components/toast/toast-button.directive'
export * from './directives/element/element.directive'
export * from './directives/element/element.module'
export * from './directives/responsive-col/responsive-col.directive'
export * from './directives/responsive-col/responsive-col.module'
export * from './directives/responsive-col/responsive-col-viewport.directive'
export * from './directives/safe-links/safe-links.directive'
export * from './directives/safe-links/safe-links.module'
@@ -40,7 +41,6 @@ export * from './pipes/shared/trust.pipe'
export * from './pipes/unit-conversion/unit-conversion.module'
export * from './pipes/unit-conversion/unit-conversion.pipe'
export * from './services/destroy.service'
export * from './services/download-html.service'
export * from './services/emver.service'
export * from './services/error-toast.service'

View File

@@ -1,13 +0,0 @@
import { Injectable, OnDestroy } from '@angular/core'
import { ReplaySubject } from 'rxjs'
/**
* Observable abstraction over ngOnDestroy to use with takeUntil
*/
@Injectable()
export class DestroyService extends ReplaySubject<void> implements OnDestroy {
ngOnDestroy() {
this.next()
this.complete()
}
}

View File

@@ -3,6 +3,7 @@ export type WorkspaceConfig = {
osArch: 'aarch64' | 'x86_64' | 'raspberrypi'
gitHash: string
useMocks: boolean
enableWidgets: boolean
// each key corresponds to a project and values adjust settings for that project, eg: ui, install-wizard, setup-wizard, diagnostic-ui
ui: {
api: {