Skip to content
Snippets Groups Projects
Commit dabafbe9 authored by Xiao Gui's avatar Xiao Gui
Browse files

feat: alternative ATP selector

parent 4b728407
No related branches found
No related tags found
No related merge requests found
Showing with 318 additions and 24 deletions
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { MatRippleModule } from "@angular/material/core";
import { MatMenuModule } from "@angular/material/menu";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { SmartChip } from "./component/smartChip.component";
import { HasSubMenuPipe } from "./hasSubmenu.pipe";
import { SmartChipContent } from "./smartChip.content.directive";
import { SmartChipMenu } from "./smartChip.menu.directive";
@NgModule({
imports: [
CommonModule,
MatMenuModule,
BrowserAnimationsModule,
MatRippleModule,
],
declarations: [
SmartChipMenu,
SmartChipContent,
SmartChip,
HasSubMenuPipe,
],
exports: [
SmartChipMenu,
SmartChipContent,
SmartChip,
]
})
export class SmartChipModule{}
import { Directive, Inject, TemplateRef } from "@angular/core";
@Directive({
selector: `ng-template[sxplrSmartChipContent]`
})
export class SmartChipContent {
constructor(@Inject(TemplateRef) public templateRef: TemplateRef<unknown>){}
}
import { Directive, Inject, TemplateRef } from "@angular/core";
@Directive({
selector: `ng-template[sxplrSmartChipMenu]`
})
export class SmartChipMenu {
constructor(@Inject(TemplateRef) public templateRef: TemplateRef<unknown>){}
}
import { CommonModule } from "@angular/common";
import { Component, Pipe, PipeTransform } from "@angular/core";
import { MatDividerModule } from "@angular/material/divider";
import { MatExpansionModule } from "@angular/material/expansion";
import { Meta, moduleMetadata, Story } from "@storybook/angular";
import { provideDarkTheme } from "src/atlasComponents/sapi/stories.base";
import { SmartChipModule } from "./module";
const complex1 = `
<sxplr-smart-chip [color]="color" [items]="inventory">
<span *sxplrSmartChipContent>menu example</span>
<ng-template sxplrSmartChipMenu let-inv>
{{ inv.name }}
</ng-template>
</sxplr-smart-chip>
`
const complex2 = `
<sxplr-smart-chip [color]="color" [items]="categories" [getChildren]="getChildren">
<span *sxplrSmartChipContent>submenu example</span>
<ng-template sxplrSmartChipMenu let-item>
{{ item.categoryName || item.name }}
</ng-template>
</sxplr-smart-chip>
`
const input = {
complex1,
complex2,
}
const getHtmlSnippet = (key: string) => `
<mat-expansion-panel>
<mat-expansion-panel-header>
<mat-panel-title>
Code
</mat-panel-title>
</mat-expansion-panel-header>
<pre>
<code [innerHTML]="input.${key} | showHtmlCode">
</code>
</pre>
</mat-expansion-panel>
${input[key]}
`
@Pipe({
name: 'showHtmlCode',
pure: true
})
class ShowHtmlCode implements PipeTransform {
public transform(input: string) {
return input
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;")
}
}
type Inventory = {
name: string
quantity: number
}
type Category = {
categoryName: string
inventories: Inventory[]
}
@Component({
selector: 'smart-chip-container',
template: `
<div class="container">
${Object.keys(input).map(key => getHtmlSnippet(key)).join('\n<mat-divider></mat-divider>\n')}
</div>
`,
styles: [
`.mat-divider{ margin: 1rem; } .container{ display: flex; flex-direction: column; }`
]
})
class SmartChipContainerCmp{
color:string
inventory: Inventory[] = [{
name: 'banana',
quantity: 10,
}, {
name: 'apple',
quantity: 5,
}]
categories: Category[] = [{
categoryName: 'fruits',
inventories: this.inventory
}, {
categoryName: 'processed food',
inventories: [{
name: 'pizza',
quantity: 1000,
}, {
name: 'kebab',
quantity: 12
}]
}, {
categoryName: 'xmas food',
inventories: []
}]
getChildren(category: Category) {
return category.inventories
}
input = input
}
export default {
component: SmartChipContainerCmp,
decorators: [
moduleMetadata({
imports: [
CommonModule,
SmartChipModule,
MatExpansionModule,
MatDividerModule,
],
declarations: [
ShowHtmlCode,
],
providers: [
...provideDarkTheme,
]
})
]
} as Meta
const Template: Story<SmartChipContainerCmp> = (args: SmartChipContainerCmp) => {
const { color } = args
return ({
props: {
color
}
})
}
export const Default = Template.bind({})
Default.args = {
color: 'rgba(206, 221, 247, 1)',
}
// export const AtlasEtc = Template.bind({})
// AtlasEtc.args = {
// color: 'rgba(206, 221, 247, 1)'
// }
// AtlasEtc.loaders = [
// loadAtlasEtcData
// ]
import { createSelector, select } from "@ngrx/store";
import { forkJoin, pipe } from "rxjs";
import { forkJoin, of, pipe } from "rxjs";
import { distinctUntilChanged, map, switchMap } from "rxjs/operators";
import { SAPI, SapiAtlasModel, SapiParcellationModel, SapiSpaceModel } from "src/atlasComponents/sapi";
import { jsonEqual } from "src/util/json";
import * as selectors from "./selectors"
const allAvailSpaces = (sapi: SAPI) => pipe(
select(selectors.selectedAtlas),
switchMap(atlas => forkJoin(
atlas.spaces.map(spcWId => sapi.getSpaceDetail(atlas["@id"], spcWId["@id"])))
const allAvailSpaces = (sapi: SAPI) => {
return pipe(
select(selectors.selectedAtlas),
switchMap(atlas => atlas
? forkJoin(
atlas.spaces.map(spcWId => sapi.getSpaceDetail(atlas["@id"], spcWId["@id"]))
)
: of([])
)
)
)
}
const allAvailParcs = (sapi: SAPI) => pipe(
select(selectors.selectedAtlas),
switchMap(atlas =>
forkJoin(
switchMap(atlas => atlas
? forkJoin(
atlas.parcellations.map(parcWId => sapi.getParcDetail(atlas["@id"], parcWId["@id"]))
)
: of([])
)
)
const allAvailSpacesParcs = (sapi: SAPI) => pipe(
select(selectors.selectedAtlas),
switchMap(atlas =>
forkJoin({
switchMap(atlas => atlas
? forkJoin({
spaces: atlas.spaces.map(spcWId => sapi.getSpaceDetail(atlas["@id"], spcWId["@id"])),
parcellation: atlas.parcellations.map(parcWId => sapi.getParcDetail(atlas["@id"], parcWId["@id"])),
})
: of({
spaces: [],
parcellation: []
})
)
)
......
import { Directive, HostListener, Input, TemplateRef } from "@angular/core";
import { MatDialog, MatDialogConfig } from "@angular/material/dialog";
import { MatSnackBar } from "@angular/material/snack-bar";
import { DialogFallbackCmp } from "./tmpl/tmpl.component"
type DialogSize = 's' | 'm' | 'l' | 'xl'
......@@ -39,20 +39,13 @@ export class DialogDirective{
@Input('sxplr-dialog-data')
data: unknown
constructor(
private matDialog: MatDialog,
private snackbar: MatSnackBar,
){
}
constructor(private matDialog: MatDialog){}
@HostListener('click')
onClick(){
if (!this.templateRef) {
return this.snackbar.open(`Cannot show dialog. sxplr-dialog template not provided`)
}
this.matDialog.open(this.templateRef, {
this.matDialog.open(this.templateRef || DialogFallbackCmp, {
data: this.data,
...(sizeDict[this.size] || {})
})
}
}
\ No newline at end of file
}
export { DialogDirective } from "./dialog.directive"
\ No newline at end of file
export { DialogDirective } from "./dialog.directive"
export { DialogModule } from "./module"
export { DialogFallbackCmp } from "./tmpl/tmpl.component"
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { MatButtonModule } from "@angular/material/button";
import { MatDialogModule } from "@angular/material/dialog";
import { MatSnackBarModule } from "@angular/material/snack-bar";
import { MarkdownModule } from "src/components/markdown";
import { StrictLocalModule } from "src/strictLocal";
import { DialogDirective } from "./dialog.directive"
import { DialogFallbackCmp } from "./tmpl/tmpl.component";
@NgModule({
imports: [
MatSnackBarModule,
CommonModule,
MatDialogModule,
MatButtonModule,
MarkdownModule,
StrictLocalModule,
],
declarations: [
DialogDirective,
DialogFallbackCmp,
],
exports: [
DialogDirective,
......
import { Component, Inject } from "@angular/core";
import { MAT_DIALOG_DATA } from "@angular/material/dialog";
export type FallBackData = {
title: string
actions?: string[]
desc?: string
descMd?: string
}
@Component({
selector: 'sxplr-dialog-fallback-tmpl',
templateUrl: './tmpl.template.html',
styleUrls: [
'./tmpl.style.css'
],
})
export class DialogFallbackCmp {
constructor(
@Inject(MAT_DIALOG_DATA) public data: FallBackData
){
}
}
mat-dialog-actions a i
{
margin-right: 0.5rem;
}
<h1 *ngIf="data.title" mat-dialog-title>
{{ data.title }}
</h1>
<div *ngIf="data.descMd || data.desc" mat-dialog-content class="mat-body">
<ng-template [ngIf]="data.desc">
{{ data.desc }}
</ng-template>
<markdown-dom *ngIf="data.descMd" [markdown]="data.descMd">
</markdown-dom>
</div>
<mat-dialog-actions align="start">
<ng-template ngFor [ngForOf]="data.actions || []" let-action>
<a *ngIf="action.startsWith('http'); else defaultActionTmpl"
[href]="action"
sxplr-hide-when-local
target="_blank"
mat-raised-button
color="primary">
<i class="fas fa-external-link-alt"></i>
<span>Detail</span>
</a>
<ng-template #defaultActionTmpl>
<button mat-raised-button
color="primary"
[mat-dialog-close]="action">
{{ action }}
</button>
</ng-template>
</ng-template>
<button mat-dialog-close mat-button>
Close
</button>
</mat-dialog-actions>
export type RecursivePartial<T> = Partial<{
[K in keyof T]: RecursivePartial<T[K]>
}>
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment