diff --git a/projects/fusio-sdk/package.json b/projects/fusio-sdk/package.json index ab434ef..3d38fcd 100644 --- a/projects/fusio-sdk/package.json +++ b/projects/fusio-sdk/package.json @@ -1,6 +1,6 @@ { "name": "ngx-fusio-sdk", - "version": "5.1.3", + "version": "6.0.0", "description": "SDK to integrate Fusio into an Angular app", "keywords": [ "Fusio", diff --git a/projects/fusio-sdk/src/lib/abstract/detail.ts b/projects/fusio-sdk/src/lib/abstract/detail.ts index a0ff834..b9dbbd6 100644 --- a/projects/fusio-sdk/src/lib/abstract/detail.ts +++ b/projects/fusio-sdk/src/lib/abstract/detail.ts @@ -1,32 +1,66 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {Component, OnInit} from '@angular/core'; +import {ActivatedRoute, Router} from "@angular/router"; +import {CommonMessage} from "fusio-sdk"; +import {ErrorService} from "../service/error.service"; +import {Service} from "./service"; /** - * This component is only a basic view component which renders a provided entity. It should only render the provided - * JSON data it should not contain any additional logic to request data from an endpoint + * Base component to show a detail page of a single entity */ @Component({ template: '', }) export abstract class Detail implements OnInit { - @Input() - selected!: T; - @Output() - updateClick: EventEmitter = new EventEmitter(); - @Output() - deleteClick: EventEmitter = new EventEmitter(); + public selected?: T; + public response?: CommonMessage; - jsonView: boolean = false; + protected constructor(protected route: ActivatedRoute, public router: Router, protected error: ErrorService) { + } + + async ngOnInit(): Promise { + this.route.paramMap.subscribe(async params => { + const id = params.get('id'); + if (id) { + await this.doGet(id); + } + }); + } + + async doGet(id: string) { + try { + this.selected = await this.getService().get(id); - async ngOnInit() { + this.onLoad(); + } catch (error) { + this.response = this.error.convert(error); + } } - doUpdateClick() { - this.updateClick.emit(); + public getListLink(): Array + { + return this.getService().getLink(); } - doDeleteClick() { - this.deleteClick.emit(); + public getEditLink(id: any): Array + { + const link = this.getService().getLink(); + link.push('' + id) + link.push('edit') + return link; } + public getDeleteLink(id: any): Array + { + const link = this.getService().getLink(); + link.push('' + id) + link.push('delete') + return link; + } + + protected abstract getService(): Service; + + protected onLoad(): void + { + } } diff --git a/projects/fusio-sdk/src/lib/abstract/form.ts b/projects/fusio-sdk/src/lib/abstract/form.ts new file mode 100644 index 0000000..fa4b768 --- /dev/null +++ b/projects/fusio-sdk/src/lib/abstract/form.ts @@ -0,0 +1,97 @@ +import {Component, OnInit} from '@angular/core'; +import {ActivatedRoute, Router} from "@angular/router"; +import {CommonMessage} from "fusio-sdk"; +import {ErrorService} from "../service/error.service"; +import {Service} from "./service"; + +/** + * Base component to provide a form to create, update or delete an entity + */ +@Component({ + template: '', +}) +export abstract class Form implements OnInit { + + public entity?: T; + public response?: CommonMessage; + public mode: Mode = Mode.Create; + + protected constructor(protected route: ActivatedRoute, public router: Router, protected error: ErrorService) { + } + + async ngOnInit(): Promise { + this.entity = this.getService().newEntity(); + + this.route.data.subscribe((data) => { + this.mode = data['mode']; + }); + + this.route.paramMap.subscribe(async params => { + const id = params.get('id'); + if (id) { + await this.doGet(id); + } + }); + } + + async doGet(id: string) { + try { + this.entity = await this.getService().get(id); + + this.onLoad(); + } catch (error) { + this.response = this.error.convert(error); + } + } + + async doCreate(entity: T) { + try { + this.response = await this.getService().create(entity); + + this.onSubmit(); + } catch (error) { + this.response = this.error.convert(error); + } + } + + async doUpdate(entity: T) { + try { + this.response = await this.getService().update(entity); + + this.onSubmit(); + } catch (error) { + this.response = this.error.convert(error); + } + } + + async doDelete(entity: T) { + try { + this.response = await this.getService().delete(entity); + + this.onSubmit(); + } catch (error) { + this.response = this.error.convert(error); + } + } + + public getListLink(): Array + { + return this.getService().getLink(); + } + + protected abstract getService(): Service; + + protected onLoad(): void + { + } + + protected onSubmit(): void + { + } +} + +export enum Mode { + Create = 1, + Update, + Delete, +} diff --git a/projects/fusio-sdk/src/lib/abstract/list.ts b/projects/fusio-sdk/src/lib/abstract/list.ts index 2179518..479ce7c 100644 --- a/projects/fusio-sdk/src/lib/abstract/list.ts +++ b/projects/fusio-sdk/src/lib/abstract/list.ts @@ -1,82 +1,125 @@ -import {Component} from '@angular/core'; +import {Component, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from "@angular/router"; -import {NgbModal} from "@ng-bootstrap/ng-bootstrap"; -import {ClientAbstract} from "sdkgen-client"; -import {ApiService} from "../service/api.service"; +import {CommonMessage} from "fusio-sdk"; import {ErrorService} from "../service/error.service"; -import {EventService} from "../service/event.service"; -import {Result} from "./modal"; -import {ModelId, Query} from "./query"; +import {Service} from "./service"; /** - * List panel which uses a modal to CRUD entities. Note it depends on ng-bootstrap so you can use it only if your - * project also uses ng-bootstrap + * Base component to list entities, with a pagination and a search */ @Component({ template: '', }) -export abstract class List extends Query { +export abstract class List implements OnInit { - protected modalService: NgbModal; + public search: string = ''; + public totalResults: number = 0; + public entries: Array = []; + public page: number = 1; + public pageSize: number = 16; + public response?: CommonMessage; - constructor(fusio: ApiService, route: ActivatedRoute, router: Router, event: EventService, error: ErrorService, modalService: NgbModal) { - super(fusio, route, router, event, error); - this.modalService = modalService; + protected constructor(protected route: ActivatedRoute, public router: Router, protected error: ErrorService) { } - openCreateDialog() { - const modalRef = this.modalService.open(this.getDetailComponent(), { - size: 'lg' - }); - modalRef.componentInstance.mode = Mode.Create; - modalRef.closed.subscribe(async (result: Result) => { - this.response = result.response; - if (result.response.success) { - this.event.dispatchModelCreated(result.entity, this.getRoute()); + async ngOnInit(): Promise { + this.route.queryParams.subscribe(async params => { + let page, search; + if (params['page']) { + page = parseInt(params['page']); + } + if (params['search']) { + search = params['search']; + } - await this.doList(); + if (!this.hasQueryParamsChange(page, search)) { + return; } + + this.page = page || 1; + this.search = search || ''; + + await this.doList(); }); } - openUpdateDialog(entity: T) { - const modalRef = this.modalService.open(this.getDetailComponent(), { - size: 'lg' - }); - modalRef.componentInstance.mode = Mode.Update; - modalRef.componentInstance.entity = entity; - modalRef.closed.subscribe(async (result: Result) => { - this.response = result.response; - if (result.response.success) { - this.event.dispatchModelUpdated(result.entity, this.getRoute()); - - await this.doList(); - } - }); + async doList() { + try { + const response = await this.getService().getAll(this.getCollectionQuery()); + + this.totalResults = response.totalResults || 0; + this.entries = response.entry || []; + + this.onLoad(); + } catch (error) { + this.response = this.error.convert(error); + } } - openDeleteDialog(entity: T) { - const modalRef = this.modalService.open(this.getDetailComponent(), { - size: 'lg' - }); - modalRef.componentInstance.mode = Mode.Delete; - modalRef.componentInstance.entity = entity; - modalRef.closed.subscribe(async (result: Result) => { - this.response = result.response; - if (result.response.success) { - this.event.dispatchModelDeleted(result.entity, this.getRoute()); - - await this.doList(); - } - }); + async doSearch(page?: number, search?: string) { + if (!this.hasQueryParamsChange(page, search)) { + return; + } + + if (page !== undefined) { + this.page = page; + } + + if (search !== undefined) { + this.search = search; + } + + await this.doList(); } - protected abstract getDetailComponent(): any; + public getDetailLink(id: any): Array + { + const link = this.getService().getLink(); + link.push('' + id) + return link; + } -} + public getNewLink(): Array + { + const link = this.getService().getLink(); + link.push('-') + link.push('new') + return link; + } + + public getEditLink(id: any): Array + { + const link = this.getService().getLink(); + link.push('' + id) + link.push('edit') + return link; + } + + public getDeleteLink(id: any): Array + { + const link = this.getService().getLink(); + link.push('' + id) + link.push('delete') + return link; + } + + protected getCollectionQuery(): Array { + let query: Array = []; + query.push((this.page - 1) * this.pageSize); + query.push(this.pageSize); + if (this.search) { + query.push(this.search); + } + return query; + } -export enum Mode { - Create = 1, - Update, - Delete, + protected hasQueryParamsChange(page?: number, search?: string): boolean { + return this.page !== page || this.search !== search; + } + + protected abstract getService(): Service; + + protected onLoad(): void + { + } } diff --git a/projects/fusio-sdk/src/lib/abstract/manipulation.ts b/projects/fusio-sdk/src/lib/abstract/manipulation.ts deleted file mode 100644 index e256b8b..0000000 --- a/projects/fusio-sdk/src/lib/abstract/manipulation.ts +++ /dev/null @@ -1,74 +0,0 @@ -import {Component, Input, OnInit} from "@angular/core"; -import {CommonMessage} from "fusio-sdk"; -import {ClientAbstract} from "sdkgen-client"; -import {Mode} from "./list"; -import {ApiService} from "../service/api.service"; -import {ErrorService} from "../service/error.service"; -import {ModelId} from "./query"; - -/** - * Base component if you want to create a panel to create, update or delete an entity. If you extend this class you - * need to implement the {@see create}, {@see update} and {@see delete} method. This class only uses native angular - * components so you can use it independently of your UI framework - */ -@Component({ - template: '', -}) -export abstract class Manipulation implements OnInit { - - response?: CommonMessage; - loading: boolean = false; - - @Input() mode: Mode = Mode.Create; - @Input() entity: T = this.newEntity(); - - protected fusio: ApiService; - protected error: ErrorService; - - constructor(fusio: ApiService, error: ErrorService) { - this.fusio = fusio; - this.error = error; - } - - ngOnInit(): void { - } - - async submit() { - if (!this.entity) { - return; - } - - this.loading = true; - - const data = this.entity; - - try { - let response; - if (this.mode === Mode.Create) { - response = await this.create(data); - } else if (this.mode === Mode.Update) { - response = await this.update(data); - } else if (this.mode === Mode.Delete) { - response = await this.delete(data); - } - - this.loading = false; - - if (response) { - this.onResponse(response, data); - } - } catch (error) { - this.loading = false; - this.response = this.error.convert(error); - } - } - - protected onResponse(response: CommonMessage, entity: T): void { - } - - protected abstract create(entity: T): Promise; - protected abstract update(entity: T): Promise; - protected abstract delete(entity: T): Promise; - protected abstract newEntity(): T; - -} diff --git a/projects/fusio-sdk/src/lib/abstract/modal.ts b/projects/fusio-sdk/src/lib/abstract/modal.ts deleted file mode 100644 index 806e051..0000000 --- a/projects/fusio-sdk/src/lib/abstract/modal.ts +++ /dev/null @@ -1,40 +0,0 @@ -import {Component} from "@angular/core"; -import {CommonMessage} from "fusio-sdk"; -import {NgbActiveModal, NgbModal} from "@ng-bootstrap/ng-bootstrap"; -import {ClientAbstract} from "sdkgen-client"; -import {ApiService} from "../service/api.service"; -import {ErrorService} from "../service/error.service"; -import {Manipulation} from "./manipulation"; -import {ModelId} from "./query"; - -/** - * Manipulation panel which uses a modal to create, update or delete an entity. Note it depends on ng-bootstrap so you - * can use it only if your project also uses ng-bootstrap - */ -@Component({ - template: '', -}) -export abstract class Modal extends Manipulation { - - protected modalService: NgbModal; - public modal: NgbActiveModal; - - constructor(fusio: ApiService, error: ErrorService, modalService: NgbModal, modal: NgbActiveModal) { - super(fusio, error); - this.modalService = modalService; - this.modal = modal; - } - - protected override onResponse(response: CommonMessage, entity: T) { - this.modal.close({ - entity: entity, - response: response, - }); - } - -} - -export interface Result { - entity: T, - response: CommonMessage, -} diff --git a/projects/fusio-sdk/src/lib/abstract/object-selector.ts b/projects/fusio-sdk/src/lib/abstract/object-selector.ts deleted file mode 100644 index 9ddcc62..0000000 --- a/projects/fusio-sdk/src/lib/abstract/object-selector.ts +++ /dev/null @@ -1,113 +0,0 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {catchError, debounceTime, distinctUntilChanged, map, merge, Observable, of, OperatorFunction, Subject, switchMap, tap} from "rxjs"; -import {fromPromise} from "rxjs/internal/observable/innerFrom"; -import {CommonCollection} from "fusio-sdk"; - -/** - * Object selector - */ -@Component({ - template: '', -}) -export abstract class ObjectSelector implements OnInit { - - @Input() name!: string; - @Input() disabled: boolean = false; - @Input() data?: R = undefined; - @Output() dataChange = new EventEmitter(); - - focus$ = new Subject(); - - searching = false; - searchFailed = false; - - selected?: T - - objectFormatter = (object: T): string => { - const name = this.getNameProperty(object); - if (name) { - return name; - } - - const id = this.getIdProperty(object); - if (id) { - return '' + id; - } - - return '-'; - }; - - objectSearch: OperatorFunction> = (text$: Observable) => { - const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged()); - const inputFocus$ = this.focus$; - - return merge(debouncedText$, inputFocus$).pipe( - tap(() => (this.searching = true)), - switchMap((term) => - fromPromise(this.getAll([0, 16, term])).pipe( - map((response) => { - return response.entry ? response.entry : []; - }), - tap(() => (this.searchFailed = false)), - catchError(() => { - this.searchFailed = true; - return of([]); - }), - ), - ), - tap(() => (this.searching = false)), - ); - } - - async ngOnInit(): Promise { - if (this.data) { - this.selected = await this.get('' + this.data); - } - } - - changeValue() { - if (this.disabled || !this.selected) { - return; - } - - const id = this.getIdProperty(this.selected); - if (!id) { - return; - } - - this.dataChange.emit(id); - } - - protected getIdKey(): string - { - return 'id'; - } - - protected getNameKey(): string - { - return 'name'; - } - - protected abstract getAll(parameters: Array): Promise>; - - protected abstract get(id: string): Promise; - - private getIdProperty(object: T): R|undefined - { - if (typeof object === 'object' && object && object.hasOwnProperty(this.getIdKey())) { - return (object as any)[this.getIdKey()]; - } - - return undefined; - } - - private getNameProperty(object: T): string|undefined - { - if (typeof object === 'object' && object && object.hasOwnProperty(this.getNameKey())) { - return (object as any)[this.getNameKey()]; - } - - return undefined; - } - -} diff --git a/projects/fusio-sdk/src/lib/abstract/query.ts b/projects/fusio-sdk/src/lib/abstract/query.ts deleted file mode 100644 index 73a6c62..0000000 --- a/projects/fusio-sdk/src/lib/abstract/query.ts +++ /dev/null @@ -1,189 +0,0 @@ -import {Component, OnInit} from '@angular/core'; -import {ActivatedRoute, Router} from "@angular/router"; -import {ClientAbstract} from "sdkgen-client"; -import {CommonCollection, CommonMessage} from "fusio-sdk"; -import {ApiService} from "../service/api.service"; -import {ErrorService} from "../service/error.service"; -import {EventService} from "../service/event.service"; - -/** - * Base component to create a list panel to show and browse entities. If you extend this component you need to implement - * the {@see openCreateDialog}, {@see openUpdateDialog} and {@see openDeleteDialog} method which are called in case the - * user clicks on the new, edit or delete button. This class only uses native angular components so you can use it - * independently of your UI framework - */ -@Component({ - template: '', -}) -export abstract class Query implements OnInit { - - public search: string = ''; - public totalResults: number = 0; - public entries: Array = []; - public selected?: T; - public page: number = 1; - public pageSize: number = 16; - public response?: CommonMessage; - public loading: boolean = true; - - protected fusio: ApiService; - protected route: ActivatedRoute; - protected router: Router; - protected event: EventService; - protected error: ErrorService; - - constructor(fusio: ApiService, route: ActivatedRoute, router: Router, event: EventService, error: ErrorService) { - this.fusio = fusio; - this.route = route; - this.router = router; - this.event = event; - this.error = error; - } - - async ngOnInit(): Promise { - this.startLoading(); - this.route.queryParams.subscribe(async params => { - let page, search; - if (params['page']) { - page = parseInt(params['page']); - } - if (params['search']) { - search = params['search']; - } - if (!this.hasQueryParamsChange(page, search)) { - return; - } - this.startLoading(); - this.page = page || 1; - this.search = search || ''; - await this.doList(); - }); - - this.route.paramMap.subscribe(async params => { - const id = params.get('id'); - if (id) { - this.startLoading(); - await this.doGet(id); - } - }); - } - - async doList() { - try { - const response = await this.getAll(this.getCollectionQuery()); - - this.totalResults = response.totalResults || 0; - this.entries = response.entry || []; - - this.onList(); - } catch (error) { - this.response = this.error.convert(error); - } - - // in case we are not at a specific route redirect to the first - const isDetailRoute: boolean|undefined = this.route.routeConfig?.path?.endsWith(':id'); - if (this.entries.length > 0 && this.entries[0].id && isDetailRoute === false && !this.selected) { - await this.doGet('' + this.entries[0].id); - } - - this.finishLoading(); - } - - protected getCollectionQuery(): Array { - let query: Array = []; - query.push((this.page - 1) * this.pageSize); - query.push(this.pageSize); - if (this.search) { - query.push(this.search); - } - return query; - } - - async doGet(id: string) { - try { - this.selected = await this.get(id); - this.onGet(); - } catch (error) { - this.response = this.error.convert(error); - } - - this.finishLoading(); - } - - async doSearch(page?: number, search?: string) { - if (!this.hasQueryParamsChange(page, search) || this.loading) { - return; - } - if (this.selected) { - await this.router.navigate([this.getRoute(), this.selected.id], { - queryParams: this.getQueryParams(page, search) - }); - } else { - await this.router.navigate([this.getRoute()], { - queryParams: this.getQueryParams(page, search) - }); - } - return false; - } - - async doSelect(entry: T) { - await this.router.navigate([this.getRoute(), entry.id], { - queryParams: this.getQueryParams(this.page, this.search) - }); - } - - abstract openCreateDialog(): void; - - abstract openUpdateDialog(entity: T): void; - - abstract openDeleteDialog(entity: T): void; - - getQueryParams(page?: number, search?: string): QueryParams { - const queryParams: QueryParams = {}; - if (page) { - queryParams.page = page; - } - if (search) { - queryParams.search = search; - } - return queryParams; - } - - hasQueryParamsChange(page?: number, search?: string): boolean { - return this.page !== page || this.search !== search; - } - - private startLoading(): void { - this.loading = true; - } - - private finishLoading(): void { - setTimeout(() => { - this.loading = false; - }, 100); - } - - protected abstract getAll(parameters: Array): Promise>; - protected abstract get(id: string): Promise; - protected abstract getRoute(): string; - - protected onList(): void - { - this.event.dispatchModelList(this.getRoute()); - } - - protected onGet(): void - { - this.event.dispatchModelDetail(this.selected, this.getRoute()); - } - -} - -export interface QueryParams { - page?: number - search?: string -} - -export interface ModelId { - id?: number|string -} diff --git a/projects/fusio-sdk/src/lib/abstract/service.ts b/projects/fusio-sdk/src/lib/abstract/service.ts new file mode 100644 index 0000000..4770b6c --- /dev/null +++ b/projects/fusio-sdk/src/lib/abstract/service.ts @@ -0,0 +1,119 @@ +import {CommonCollection, CommonMessage} from "fusio-sdk"; + +/** + * A general service to access CRUD operations, this service can be reused at different components + */ +export abstract class Service { + + abstract getAll(parameters: Array): Promise>; + + abstract get(id: string): Promise; + + abstract create(entity: E): Promise; + + abstract update(entity: E): Promise; + + abstract delete(entity: E): Promise; + + /** + * Returns an empty new entity + */ + abstract newEntity(): E; + + /** + * Returns the base link + */ + abstract getLink(): Array; + + public async getAllWithIdAndName(parameters: Array): Promise>> + { + const result = await this.getAll(parameters); + + const entries: Array> = []; + result.entry?.forEach((entry) => { + entries.push(this.convert(entry)); + }); + + return { + totalResults: result.totalResults, + startIndex: result.startIndex, + itemsPerPage: result.itemsPerPage, + entry: entries, + }; + } + + public async getWithIdAndName(id: string): Promise> + { + return this.convert(await this.get(id)); + } + + /** + * Returns the id key of the entity, normally this is the property "id" + */ + protected getIdKey(): string + { + return 'id'; + } + + /** + * Returns the display name key, normally a property like "name" or "title" + */ + protected getNameKey(): string + { + return 'name'; + } + + private convert(entity: E): IdAndName + { + const id = this.getIdValue(entity); + if (id === undefined) { + throw new Error('Configured id value does not exist, available properties: ' + Object.getOwnPropertyNames(entity).join(',')); + } + + const name = this.getNameValue(entity); + if (name === undefined) { + throw new Error('Configured name value does not exist, available properties: ' + Object.getOwnPropertyNames(entity).join(',')); + } + + return { + id: id, + name: name, + raw: entity + }; + } + + private getIdValue(entity: E): string|undefined + { + if (typeof entity === 'object' && entity && entity.hasOwnProperty(this.getIdKey())) { + const id = (entity as any)[this.getIdKey()]; + if (id === undefined || id === null) { + return undefined; + } + + return '' + id; + } + + return undefined; + } + + private getNameValue(entity: E): string|undefined + { + if (typeof entity === 'object' && entity && entity.hasOwnProperty(this.getNameKey())) { + const name = (entity as any)[this.getNameKey()]; + if (name === undefined || name === null) { + return undefined; + } + + return '' + name; + } + + return undefined; + } + +} + +export interface IdAndName { + id: string + name: string + raw: T +} diff --git a/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.html b/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.html index 5d05a05..c377e18 100644 --- a/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.html +++ b/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.html @@ -2,8 +2,9 @@
{{selected.name}}
- - + Back + Update + Delete
diff --git a/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.ts b/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.ts index e4eaf02..0c27c5f 100644 --- a/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.ts +++ b/projects/fusio-sdk/src/lib/component/app/detail/app-detail.component.ts @@ -1,6 +1,9 @@ import {Component} from '@angular/core'; import {ConsumerApp} from "fusio-sdk"; import {Detail} from "../../../abstract/detail"; +import {ActivatedRoute, Router} from "@angular/router"; +import {ErrorService} from "../../../service/error.service"; +import {AppService} from "../../../service/app.service"; @Component({ selector: 'fusio-app-detail', @@ -11,4 +14,12 @@ export class AppDetailComponent extends Detail { hideSecret = true; + constructor(private app: AppService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); + } + + protected getService(): AppService { + return this.app; + } + } diff --git a/projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.css b/projects/fusio-sdk/src/lib/component/app/form/app-form.component.css similarity index 100% rename from projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.css rename to projects/fusio-sdk/src/lib/component/app/form/app-form.component.css diff --git a/projects/fusio-sdk/src/lib/component/app/form/app-form.component.html b/projects/fusio-sdk/src/lib/component/app/form/app-form.component.html new file mode 100644 index 0000000..e48b8fc --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/app/form/app-form.component.html @@ -0,0 +1,44 @@ +
+
+ Create + Update + Delete +
+
+ +
+
+ +
+
+ + + Name of the app +
+
+
+
+ +
+
+ + + Url of the app +
+
+
+
+ +
+ +
+
+
+ + + + +
+
+
+
diff --git a/projects/fusio-sdk/src/lib/component/app/form/app-form.component.ts b/projects/fusio-sdk/src/lib/component/app/form/app-form.component.ts new file mode 100644 index 0000000..1653983 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/app/form/app-form.component.ts @@ -0,0 +1,26 @@ +import {Component} from '@angular/core'; +import {ConsumerApp, ConsumerScope} from "fusio-sdk"; +import {ErrorService} from "../../../service/error.service"; +import {Form} from "../../../abstract/form"; +import {ActivatedRoute, Router} from "@angular/router"; +import {AppService} from "../../../service/app.service"; +import {ScopeService} from "../../../service/scope.service"; + +@Component({ + selector: 'fusio-app-form', + templateUrl: './app-form.component.html', + styleUrls: ['./app-form.component.css'] +}) +export class AppFormComponent extends Form { + + scopes?: Array; + + constructor(private app: AppService, public scope: ScopeService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); + } + + protected getService(): AppService { + return this.app; + } + +} diff --git a/projects/fusio-sdk/src/lib/component/app/list/app-list.component.html b/projects/fusio-sdk/src/lib/component/app/list/app-list.component.html index 6bfad2c..65eacab 100644 --- a/projects/fusio-sdk/src/lib/component/app/list/app-list.component.html +++ b/projects/fusio-sdk/src/lib/component/app/list/app-list.component.html @@ -1,33 +1,47 @@ - - - - - - -
-
- +
Apps
+
+ + + + + + + + + + + + + + + + + + + +
StatusNameInsert-Date
+ Active + Pending + Deactivated + Deleted + {{entry.name}}{{entry.date|date:'short'}} +
+ + + +
+
+ - -
-
- - - + [collectionSize]="totalResults" + [maxSize]="4" + [ellipses]="false" + (pageChange)="doSearch($event)">
diff --git a/projects/fusio-sdk/src/lib/component/app/list/app-list.component.ts b/projects/fusio-sdk/src/lib/component/app/list/app-list.component.ts index aacdca3..4ce8c2b 100644 --- a/projects/fusio-sdk/src/lib/component/app/list/app-list.component.ts +++ b/projects/fusio-sdk/src/lib/component/app/list/app-list.component.ts @@ -1,38 +1,23 @@ import {Component} from '@angular/core'; import {ActivatedRoute, Router} from "@angular/router"; -import {NgbModal} from "@ng-bootstrap/ng-bootstrap"; -import {Client, CommonCollection, ConsumerApp} from "fusio-sdk"; +import {ConsumerApp} from "fusio-sdk"; import {List} from "../../../abstract/list"; -import {AppModalComponent} from "../modal/app-modal.component"; -import {FusioService} from "../../../service/fusio.service"; -import {EventService} from "../../../service/event.service"; import {ErrorService} from "../../../service/error.service"; +import {AppService} from "../../../service/app.service"; @Component({ selector: 'fusio-app-list', templateUrl: './app-list.component.html', styleUrls: ['./app-list.component.css'] }) -export class AppListComponent extends List { +export class AppListComponent extends List { - constructor(fusio: FusioService, route: ActivatedRoute, router: Router, event: EventService, error: ErrorService, modalService: NgbModal) { - super(fusio, route, router, event, error, modalService); + constructor(private app: AppService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); } - protected async getAll(parameters: Array): Promise> { - return this.fusio.getClient().consumer().app().getAll(...parameters); - } - - protected async get(id: string): Promise { - return this.fusio.getClient().consumer().app().get(id); - } - - protected getDetailComponent(): any { - return AppModalComponent; - } - - protected getRoute(): any { - return '/account/app'; + protected getService(): AppService { + return this.app; } } diff --git a/projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.html b/projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.html deleted file mode 100644 index 351ba66..0000000 --- a/projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - diff --git a/projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.ts b/projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.ts deleted file mode 100644 index 2c42f66..0000000 --- a/projects/fusio-sdk/src/lib/component/app/modal/app-modal.component.ts +++ /dev/null @@ -1,69 +0,0 @@ -import {Component} from '@angular/core'; -import {Client, CommonMessage, ConsumerApp, ConsumerAppCreate, ConsumerAppUpdate, ConsumerScope} from "fusio-sdk"; -import {NgbActiveModal, NgbModal} from "@ng-bootstrap/ng-bootstrap"; -import {Modal} from "../../../abstract/modal"; -import {FusioService} from "../../../service/fusio.service"; -import {ErrorService} from "../../../service/error.service"; - -@Component({ - selector: 'fusio-app-modal', - templateUrl: './app-modal.component.html', - styleUrls: ['./app-modal.component.css'] -}) -export class AppModalComponent extends Modal { - - scopes?: Array; - - constructor(fusio: FusioService, error: ErrorService, modalService: NgbModal, modal: NgbActiveModal) { - super(fusio, error, modalService, modal); - } - - override async ngOnInit(): Promise { - const response = await this.fusio.getClient().consumer().scope().getAll(0, 1024); - this.scopes = response.entry; - } - - protected async create(entity: ConsumerApp): Promise { - return this.fusio.getClient().consumer().app().create( entity); - } - - protected async update(entity: ConsumerApp): Promise { - return this.fusio.getClient().consumer().app().update('' + entity.id, entity); - } - - protected async delete(entity: ConsumerApp): Promise { - return this.fusio.getClient().consumer().app().delete('' + entity.id); - } - - protected newEntity(): ConsumerApp { - return { - name: '', - url: '', - scopes: [] - }; - } - - scopeSelect(event: any, scope?: string) { - const selected = event.target.checked; - if (!scope) { - return; - } - - if (selected) { - this.addScope(scope); - } else { - this.removeScope(scope); - } - } - - private addScope(scope: string) { - this.entity.scopes?.push(scope) - } - - private removeScope(scope: string) { - this.entity.scopes = this.entity.scopes?.filter((value) => { - return value !== scope; - }); - } - -} diff --git a/projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.css b/projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.css similarity index 100% rename from projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.css rename to projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.css diff --git a/projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.html b/projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.html new file mode 100644 index 0000000..61e733f --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.html @@ -0,0 +1,22 @@ + +
+ + + +
diff --git a/projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.ts b/projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.ts new file mode 100644 index 0000000..99cd5a1 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/autocomplete/form-autocomplete.component.ts @@ -0,0 +1,72 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {IdAndName, Service} from "../../../abstract/service"; +import {catchError, debounceTime, distinctUntilChanged, map, merge, Observable, of, OperatorFunction, Subject, switchMap, tap} from "rxjs"; +import {fromPromise} from "rxjs/internal/observable/innerFrom"; + +@Component({ + selector: 'fusio-form-autocomplete', + templateUrl: './form-autocomplete.component.html', + styleUrls: ['./form-autocomplete.component.css'] +}) +export class FormAutocompleteComponent implements OnInit { + + @Input() name!: string; + @Input() disabled: boolean = false; + @Input() data?: string = undefined; + @Input() service!: Service; + @Input() useName: boolean = false; + @Output() dataChange = new EventEmitter(); + + focus$ = new Subject(); + + searching = false; + searchFailed = false; + + selected?: IdAndName + + objectFormatter = (object: IdAndName): string => { + return object.name; + }; + + objectSearch: OperatorFunction>> = (text$: Observable) => { + const debouncedText$ = text$.pipe(debounceTime(200), distinctUntilChanged()); + const inputFocus$ = this.focus$; + + return merge(debouncedText$, inputFocus$).pipe( + tap(() => (this.searching = true)), + switchMap((term) => + fromPromise(this.service.getAllWithIdAndName([0, 16, term])).pipe( + map((response) => { + return response.entry ? response.entry : []; + }), + tap(() => (this.searchFailed = false)), + catchError(() => { + this.searchFailed = true; + return of([]); + }), + ), + ), + tap(() => (this.searching = false)), + ); + } + + async ngOnInit(): Promise { + if (this.data) { + this.selected = await this.service.getWithIdAndName('' + this.data); + } + } + + changeValue() { + if (this.disabled || !this.selected) { + return; + } + + const value = this.useName ? this.selected.name : this.selected.id; + if (!value) { + return; + } + + this.dataChange.emit(value); + } + +} diff --git a/projects/fusio-sdk/src/lib/component/webhook/modal/webhook-modal.component.css b/projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.css similarity index 100% rename from projects/fusio-sdk/src/lib/component/webhook/modal/webhook-modal.component.css rename to projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.css diff --git a/projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.html b/projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.html new file mode 100644 index 0000000..e462b29 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.html @@ -0,0 +1,13 @@ + + +
+ + +
+
+ +
+ + +
+
diff --git a/projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.ts b/projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.ts new file mode 100644 index 0000000..a7fe1f3 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/checkbox-list/form-checkbox-list.component.ts @@ -0,0 +1,50 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {IdAndName, Service} from "../../../abstract/service"; + +@Component({ + selector: 'fusio-checkbox-list', + templateUrl: './form-checkbox-list.component.html', + styleUrls: ['./form-checkbox-list.component.css'] +}) +export class FormCheckboxListComponent implements OnInit { + + @Input() name!: string; + @Input() disabled: boolean = false; + @Input() data?: Array = undefined; + @Input() service!: Service; + @Input() useName: boolean = true; + @Output() dataChange = new EventEmitter>(); + + entries?: Array> + + async ngOnInit(): Promise { + const response = await this.service.getAllWithIdAndName([0, 1024]); + this.entries = response.entry; + } + + scopeSelect(event: any, scope?: string) { + const selected = event.target.checked; + if (!scope) { + return; + } + + if (selected) { + this.addScope(scope); + } else { + this.removeScope(scope); + } + } + + private addScope(scope: string) { + this.data?.push(scope) + this.dataChange.emit(this.data); + } + + private removeScope(scope: string) { + this.data = this.data?.filter((value) => { + return value !== scope; + }); + this.dataChange.emit(this.data); + } + +} diff --git a/projects/fusio-sdk/src/lib/component/form/list/form-list.component.css b/projects/fusio-sdk/src/lib/component/form/list/form-list.component.css new file mode 100644 index 0000000..e69de29 diff --git a/projects/fusio-sdk/src/lib/component/form/list/form-list.component.html b/projects/fusio-sdk/src/lib/component/form/list/form-list.component.html new file mode 100644 index 0000000..a20a851 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/list/form-list.component.html @@ -0,0 +1,22 @@ + +
+
+
+ + + + + + + +
+
+
+
+
+
+ + +
+
+
diff --git a/projects/fusio-sdk/src/lib/component/form/list/form-list.component.ts b/projects/fusio-sdk/src/lib/component/form/list/form-list.component.ts new file mode 100644 index 0000000..c81ac8a --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/list/form-list.component.ts @@ -0,0 +1,77 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {Service} from "../../../abstract/service"; + +@Component({ + selector: 'fusio-form-list', + templateUrl: './form-list.component.html', + styleUrls: ['./form-list.component.css'] +}) +export class FormListComponent implements OnInit { + + @Input() name: string = 'list'; + @Input() type: string = 'text'; + @Input() data: Array = []; + @Input() service?: Service; + @Output() dataChange = new EventEmitter>(); + + local: Array = []; + newValue: any = ''; + + constructor() { } + + ngOnInit(): void { + if (this.data) { + this.local = this.toLocal(this.data); + } + } + + doChange(index: number, value?: any) { + this.local[index].value = value; + this.dataChange.emit(this.fromLocal()); + } + + doAdd() { + if (!this.newValue) { + return; + } + + let newValue = this.newValue; + if (this.type === 'number') { + newValue = parseInt(newValue); + } + + this.local.push({ + value: newValue + }); + this.newValue = ''; + this.dataChange.emit(this.fromLocal()); + } + + doRemove(index: number) { + this.local.splice(index, 1); + this.dataChange.emit(this.fromLocal()); + } + + toLocal(data: Array): Array { + let local: Array = []; + data.forEach((value) => { + local.push({ + value: value + }); + }) + return local; + } + + fromLocal(): Array { + let data: Array = []; + this.local.forEach((entry: Entry) => { + data.push(entry.value); + }); + return data; + } + +} + +interface Entry { + value: string +} diff --git a/projects/fusio-sdk/src/lib/component/form/map/form-map.component.css b/projects/fusio-sdk/src/lib/component/form/map/form-map.component.css new file mode 100644 index 0000000..e69de29 diff --git a/projects/fusio-sdk/src/lib/component/form/map/form-map.component.html b/projects/fusio-sdk/src/lib/component/form/map/form-map.component.html new file mode 100644 index 0000000..e973bb2 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/map/form-map.component.html @@ -0,0 +1,26 @@ + +
+ +
+
+ + + + + + + +
+
+
+
+
+ +
+
+
+ + +
+
+
diff --git a/projects/fusio-sdk/src/lib/component/form/map/form-map.component.ts b/projects/fusio-sdk/src/lib/component/form/map/form-map.component.ts new file mode 100644 index 0000000..1d49b85 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/map/form-map.component.ts @@ -0,0 +1,83 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {Service} from "../../../abstract/service"; + +@Component({ + selector: 'fusio-form-map', + templateUrl: './form-map.component.html', + styleUrls: ['./form-map.component.css'] +}) +export class FormMapComponent implements OnInit { + + @Input() name: string = 'map'; + @Input() type: string = 'text'; + @Input() data: Record = {}; + @Input() service?: Service; + @Output() dataChange = new EventEmitter>(); + + local: Array = []; + newKey: string = ''; + newValue: any = ''; + + constructor() { } + + ngOnInit(): void { + if (this.data) { + this.local = this.toLocal(this.data); + } + } + + doChange(index: number, value?: any) { + this.local[index].value = value; + this.dataChange.emit(this.fromLocal()); + } + + doAdd() { + if (!this.newKey || !this.newValue) { + return; + } + + let newValue = this.newValue; + if (this.type === 'number') { + newValue = parseInt(newValue); + } + + this.local.push({ + key: this.newKey, + value: newValue, + }); + + this.newKey = ''; + this.newValue = ''; + this.dataChange.emit(this.fromLocal()); + } + + doRemove(index: number) { + this.local.splice(index, 1); + this.dataChange.emit(this.fromLocal()); + } + + toLocal(data: Record): Array { + let local = []; + for (const [key, value] of Object.entries(data)) { + local.push({ + key: key, + value: value + }); + } + return local; + } + + fromLocal(): Record { + let data: Record = {}; + this.local.forEach((entry: Entry) => { + data[entry.key] = entry.value; + }); + return data; + } + +} + +interface Entry { + key: string + value: string +} diff --git a/projects/fusio-sdk/src/lib/component/form/select/form-select.component.css b/projects/fusio-sdk/src/lib/component/form/select/form-select.component.css new file mode 100644 index 0000000..e69de29 diff --git a/projects/fusio-sdk/src/lib/component/form/select/form-select.component.html b/projects/fusio-sdk/src/lib/component/form/select/form-select.component.html new file mode 100644 index 0000000..eab0dc5 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/select/form-select.component.html @@ -0,0 +1,13 @@ + +
+ + + + + + +
diff --git a/projects/fusio-sdk/src/lib/component/form/select/form-select.component.ts b/projects/fusio-sdk/src/lib/component/form/select/form-select.component.ts new file mode 100644 index 0000000..4ea1f37 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/form/select/form-select.component.ts @@ -0,0 +1,33 @@ +import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {IdAndName, Service} from "../../../abstract/service"; + +@Component({ + selector: 'fusio-select', + templateUrl: './form-select.component.html', + styleUrls: ['./form-select.component.css'] +}) +export class FormSelectComponent implements OnInit { + + @Input() name!: string; + @Input() disabled: boolean = false; + @Input() data?: string = undefined; + @Input() service!: Service; + @Input() useName: boolean = true; + @Output() dataChange = new EventEmitter(); + + entries?: Array> + + async ngOnInit(): Promise { + const response = await this.service.getAllWithIdAndName([0, 1024]); + this.entries = response.entry; + } + + changeValue(value: string) { + if (!value) { + return; + } + + this.dataChange.emit(value); + } + +} diff --git a/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.html b/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.html index 6b1c23d..8d1e7b9 100644 --- a/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.html +++ b/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.html @@ -1,6 +1,9 @@
{{selected.path}}
+
+ Back +
IP
diff --git a/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.ts b/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.ts index 2dec83a..b85c9a6 100644 --- a/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.ts +++ b/projects/fusio-sdk/src/lib/component/log/detail/log-detail.component.ts @@ -1,6 +1,9 @@ import {Component} from '@angular/core'; import {ConsumerLog} from "fusio-sdk"; import {Detail} from "../../../abstract/detail"; +import {ActivatedRoute, Router} from "@angular/router"; +import {ErrorService} from "../../../service/error.service"; +import {LogService} from "../../../service/log.service"; @Component({ selector: 'fusio-log-detail', @@ -9,4 +12,12 @@ import {Detail} from "../../../abstract/detail"; }) export class LogDetailComponent extends Detail { + constructor(private log: LogService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); + } + + protected getService(): LogService { + return this.log; + } + } diff --git a/projects/fusio-sdk/src/lib/component/log/list/log-list.component.html b/projects/fusio-sdk/src/lib/component/log/list/log-list.component.html index a2bbbc4..0b54c68 100644 --- a/projects/fusio-sdk/src/lib/component/log/list/log-list.component.html +++ b/projects/fusio-sdk/src/lib/component/log/list/log-list.component.html @@ -1,28 +1,41 @@ - - - - - - -
-
- +
Log
+
+ + + + + + + + + + + + + + + + + + + + + +
MethodPathIPInsert-Date
{{entry.method}}{{entry.path}}{{entry.ip}}{{entry.date|date:'short'}} +
+ +
+
+ - -
-
- - + [collectionSize]="totalResults" + [maxSize]="4" + [ellipses]="false" + (pageChange)="doSearch($event)">
diff --git a/projects/fusio-sdk/src/lib/component/log/list/log-list.component.ts b/projects/fusio-sdk/src/lib/component/log/list/log-list.component.ts index 21d4b33..c1dbe6d 100644 --- a/projects/fusio-sdk/src/lib/component/log/list/log-list.component.ts +++ b/projects/fusio-sdk/src/lib/component/log/list/log-list.component.ts @@ -1,28 +1,23 @@ import {Component} from '@angular/core'; -import {Client, ConsumerLog, ConsumerLogCollection} from "fusio-sdk"; import {List} from "../../../abstract/list"; +import {ConsumerLog} from "fusio-sdk"; +import {ActivatedRoute, Router} from "@angular/router"; +import {ErrorService} from "../../../service/error.service"; +import {LogService} from "../../../service/log.service"; @Component({ selector: 'fusio-log-list', templateUrl: './log-list.component.html', styleUrls: ['./log-list.component.css'] }) -export class LogListComponent extends List { +export class LogListComponent extends List { - protected async getAll(parameters: Array): Promise { - return this.fusio.getClient().consumer().log().getAll(...parameters); + constructor(private log: LogService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); } - protected async get(id: string): Promise { - return this.fusio.getClient().consumer().log().get('' + id); - } - - protected getDetailComponent(): any { - return null; - } - - protected getRoute(): any { - return '/account/log'; + protected getService(): LogService { + return this.log; } } diff --git a/projects/fusio-sdk/src/lib/component/register/activate/activate.component.ts b/projects/fusio-sdk/src/lib/component/register/activate/activate.component.ts index 9bbf3f4..55be9e5 100644 --- a/projects/fusio-sdk/src/lib/component/register/activate/activate.component.ts +++ b/projects/fusio-sdk/src/lib/component/register/activate/activate.component.ts @@ -14,7 +14,7 @@ export class ActivateComponent implements OnInit { response?: CommonMessage; - constructor(private fusio: FusioService, private event: EventService, private error: ErrorService, protected route: ActivatedRoute) { + constructor(private fusio: FusioService, private error: ErrorService, protected route: ActivatedRoute) { } async ngOnInit(): Promise { @@ -33,8 +33,6 @@ export class ActivateComponent implements OnInit { try { this.response = await this.fusio.getClientAnonymous().consumer().account().activate(activate); - - this.event.dispatchRegisterActivate(); } catch (error) { this.response = this.error.convert(error); } diff --git a/projects/fusio-sdk/src/lib/component/register/register.component.ts b/projects/fusio-sdk/src/lib/component/register/register.component.ts index b8fc8cf..2806857 100644 --- a/projects/fusio-sdk/src/lib/component/register/register.component.ts +++ b/projects/fusio-sdk/src/lib/component/register/register.component.ts @@ -24,7 +24,7 @@ export class RegisterComponent implements OnInit { response?: CommonMessage; loading = false - constructor(private fusio: FusioService, private event: EventService, private error: ErrorService, private config: ConfigService) { + constructor(private fusio: FusioService, private error: ErrorService, private config: ConfigService) { } ngOnInit(): void { @@ -54,8 +54,6 @@ export class RegisterComponent implements OnInit { this.response = await this.fusio.getClientAnonymous().consumer().account().register(this.credentials); this.loading = false; - this.event.dispatchRegister(this.credentials.name, this.credentials.email); - this.resetForm(); } catch (error) { this.loading = false; diff --git a/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.css b/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.css deleted file mode 100644 index 583938b..0000000 --- a/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.css +++ /dev/null @@ -1,35 +0,0 @@ - -.fusio-sidebar -{ - min-height:600px; -} - -.fusio-sidebar ul -{ - list-style-type:none; - margin:0; - padding:0; -} - -.fusio-sidebar li -{ - margin:0; - padding:0; -} - -.fusio-sidebar a -{ - font-family:monospace; - font-size: 14px; - cursor:pointer; - padding:8px 0; - display:block; - overflow:hidden; - white-space:nowrap; - text-decoration:none; -} - -.fusio-sidebar a:hover -{ - background-color:#eee; -} diff --git a/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.html b/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.html deleted file mode 100644 index 83970e5..0000000 --- a/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.html +++ /dev/null @@ -1,23 +0,0 @@ - -
-
{{name | titlecase}}
- -
diff --git a/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.ts b/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.ts deleted file mode 100644 index 1a2fdfe..0000000 --- a/projects/fusio-sdk/src/lib/component/sidebar/sidebar.component.ts +++ /dev/null @@ -1,47 +0,0 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; -import {ModelId} from "../../abstract/query"; - -@Component({ - selector: 'fusio-sidebar', - templateUrl: './sidebar.component.html', - styleUrls: ['./sidebar.component.css'] -}) -export class SidebarComponent implements OnInit { - - @Input() - public name!: string; - @Input() - public nameKey!: string; - @Input() - public totalResults: number = 0; - @Input() - public entries: Array = []; - @Input() - public selected?: T; - @Input() - public page!: number; - @Input() - public pageSize!: number; - @Output() - pageChange: EventEmitter = new EventEmitter(); - @Output() - entrySelect: EventEmitter = new EventEmitter(); - - constructor() { } - - ngOnInit(): void { - } - - doPageChange(page: number): void { - this.pageChange.emit(page); - } - - doEntrySelect(entry: T): void { - this.entrySelect.emit(entry); - } - -} - -interface Properties { - [key: string]: any -} diff --git a/projects/fusio-sdk/src/lib/component/subscription/callback/callback.component.ts b/projects/fusio-sdk/src/lib/component/subscription/callback/callback.component.ts index fa381d4..ba92b94 100644 --- a/projects/fusio-sdk/src/lib/component/subscription/callback/callback.component.ts +++ b/projects/fusio-sdk/src/lib/component/subscription/callback/callback.component.ts @@ -17,7 +17,7 @@ export class CallbackComponent implements OnInit { plan?: ConsumerPlan; response?: CommonMessage; - constructor(private fusio: FusioService, private event: EventService, private error: ErrorService, private config: ConfigService, private route: ActivatedRoute) { } + constructor(private fusio: FusioService, private error: ErrorService, private config: ConfigService, private route: ActivatedRoute) { } async ngOnInit(): Promise { this.homePath = this.config.getHomePath(); @@ -33,8 +33,6 @@ export class CallbackComponent implements OnInit { async loadPlan(id: string) { try { this.plan = await this.fusio.getClient().consumer().plan().get(id); - - this.event.dispatchPurchase(this.plan); } catch (error) { this.response = this.error.convert(error); } diff --git a/projects/fusio-sdk/src/lib/component/subscription/subscription.component.ts b/projects/fusio-sdk/src/lib/component/subscription/subscription.component.ts index 304c7b5..7d01f39 100644 --- a/projects/fusio-sdk/src/lib/component/subscription/subscription.component.ts +++ b/projects/fusio-sdk/src/lib/component/subscription/subscription.component.ts @@ -17,7 +17,7 @@ export class SubscriptionComponent implements OnInit { plans?: Array response?: CommonMessage; - constructor(private fusio: FusioService, private location: LocationStrategy, private event: EventService, private error: ErrorService, private config: ConfigService) { } + constructor(private fusio: FusioService, private location: LocationStrategy, private error: ErrorService, private config: ConfigService) { } async ngOnInit(): Promise { const response = await this.fusio.getClient().consumer().plan().getAll(0, 1024); @@ -55,8 +55,6 @@ export class SubscriptionComponent implements OnInit { }); if (response.approvalUrl) { - this.event.dispatchCheckout(plan); - location.href = response.approvalUrl; } } catch (error) { diff --git a/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.html b/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.html index 1b67ece..4c3e6b6 100644 --- a/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.html +++ b/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.html @@ -2,8 +2,9 @@
{{selected.name}}
- - + Back + Update + Delete
diff --git a/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.ts b/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.ts index 6a7f93b..3ceb460 100644 --- a/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.ts +++ b/projects/fusio-sdk/src/lib/component/token/detail/token-detail.component.ts @@ -1,6 +1,9 @@ import {Component} from '@angular/core'; import {ConsumerToken} from "fusio-sdk"; import {Detail} from "../../../abstract/detail"; +import {ActivatedRoute, Router} from "@angular/router"; +import {ErrorService} from "../../../service/error.service"; +import {TokenService} from "../../../service/token.service"; @Component({ selector: 'fusio-token-detail', @@ -9,4 +12,12 @@ import {Detail} from "../../../abstract/detail"; }) export class TokenDetailComponent extends Detail { + constructor(private token: TokenService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); + } + + protected getService(): TokenService { + return this.token; + } + } diff --git a/projects/fusio-sdk/src/lib/component/token/form/token-form.component.css b/projects/fusio-sdk/src/lib/component/token/form/token-form.component.css new file mode 100644 index 0000000..e69de29 diff --git a/projects/fusio-sdk/src/lib/component/token/form/token-form.component.html b/projects/fusio-sdk/src/lib/component/token/form/token-form.component.html new file mode 100644 index 0000000..70935ff --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/token/form/token-form.component.html @@ -0,0 +1,51 @@ +
+
+ Create + Update + Delete +
+
+ +
+

Make sure to copy your personal access token now as you will not be able to see this again.

+
+ + +
+
+
+
+ +
+
+ + + The name of the token +
+
+
+
+ +
+
+ + + Date at which the token expires +
+
+
+
+ +
+ +
+
+
+ + + + +
+
+
+
diff --git a/projects/fusio-sdk/src/lib/component/token/form/token-form.component.ts b/projects/fusio-sdk/src/lib/component/token/form/token-form.component.ts new file mode 100644 index 0000000..fb101e3 --- /dev/null +++ b/projects/fusio-sdk/src/lib/component/token/form/token-form.component.ts @@ -0,0 +1,31 @@ +import {Component} from '@angular/core'; +import {ConsumerToken, ConsumerTokenAccessToken} from "fusio-sdk"; +import {ErrorService} from "../../../service/error.service"; +import {ActivatedRoute, Router} from "@angular/router"; +import {Form} from "../../../abstract/form"; +import {TokenService} from "../../../service/token.service"; +import {ScopeService} from "../../../service/scope.service"; +import {error} from "ng-packagr/lib/utils/log"; + +@Component({ + selector: 'fusio-token-form', + templateUrl: './token-form.component.html', + styleUrls: ['./token-form.component.css'] +}) +export class TokenFormComponent extends Form { + + accessToken?: ConsumerTokenAccessToken; + + constructor(private token: TokenService, public scope: ScopeService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); + } + + protected getService(): TokenService { + return this.token; + } + + protected override onSubmit() { + this.accessToken = this.token.getToken(); + } + +} diff --git a/projects/fusio-sdk/src/lib/component/token/list/token-list.component.html b/projects/fusio-sdk/src/lib/component/token/list/token-list.component.html index 8642d8d..d4ffbae 100644 --- a/projects/fusio-sdk/src/lib/component/token/list/token-list.component.html +++ b/projects/fusio-sdk/src/lib/component/token/list/token-list.component.html @@ -1,33 +1,40 @@ - - - - - - -
-
- +
Token
+
+ + + + + + + + + + + + + + + + + +
NameScopes
{{entry.name}} +
+ + + +
+
+ - -
-
- - - + [collectionSize]="totalResults" + [maxSize]="4" + [ellipses]="false" + (pageChange)="doSearch($event)">
diff --git a/projects/fusio-sdk/src/lib/component/token/list/token-list.component.ts b/projects/fusio-sdk/src/lib/component/token/list/token-list.component.ts index 9d9dfaf..21ad977 100644 --- a/projects/fusio-sdk/src/lib/component/token/list/token-list.component.ts +++ b/projects/fusio-sdk/src/lib/component/token/list/token-list.component.ts @@ -1,29 +1,23 @@ import {Component} from '@angular/core'; -import {Client, ConsumerToken, ConsumerTokenCollection} from "fusio-sdk"; +import {ConsumerToken} from "fusio-sdk"; import {List} from "../../../abstract/list"; -import {TokenModalComponent} from "../modal/token-modal.component"; +import {ActivatedRoute, Router} from "@angular/router"; +import {ErrorService} from "../../../service/error.service"; +import {TokenService} from "../../../service/token.service"; @Component({ selector: 'fusio-token-list', templateUrl: './token-list.component.html', styleUrls: ['./token-list.component.css'] }) -export class TokenListComponent extends List { +export class TokenListComponent extends List { - protected async getAll(parameters: Array): Promise { - return this.fusio.getClient().consumer().token().getAll(...parameters); + constructor(private token: TokenService, route: ActivatedRoute, router: Router, error: ErrorService) { + super(route, router, error); } - protected async get(id: string): Promise { - return this.fusio.getClient().consumer().token().get('' + id); - } - - protected getDetailComponent(): any { - return TokenModalComponent; - } - - protected getRoute(): any { - return '/account/token'; + protected getService(): TokenService { + return this.token; } } diff --git a/projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.html b/projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.html deleted file mode 100644 index 151a67f..0000000 --- a/projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.html +++ /dev/null @@ -1,49 +0,0 @@ - - - - diff --git a/projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.ts b/projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.ts deleted file mode 100644 index 1be790d..0000000 --- a/projects/fusio-sdk/src/lib/component/token/modal/token-modal.component.ts +++ /dev/null @@ -1,89 +0,0 @@ -import {Component} from '@angular/core'; -import {Client, CommonMessage, ConsumerScope, ConsumerToken, ConsumerTokenCreate, ConsumerTokenUpdate} from "fusio-sdk"; -import {Modal} from "../../../abstract/modal"; -import {FusioService} from "../../../service/fusio.service"; -import {ErrorService} from "../../../service/error.service"; -import {NgbActiveModal, NgbModal} from "@ng-bootstrap/ng-bootstrap"; -import {TokenShowComponent} from "../show/token-show.component"; - -@Component({ - selector: 'fusio-token-modal', - templateUrl: './token-modal.component.html', - styleUrls: ['./token-modal.component.css'] -}) -export class TokenModalComponent extends Modal { - - scopes?: Array; - - constructor(fusio: FusioService, error: ErrorService, modalService: NgbModal, modal: NgbActiveModal) { - super(fusio, error, modalService, modal); - } - - override async ngOnInit(): Promise { - const response = await this.fusio.getClient().consumer().scope().getAll(0, 1024); - this.scopes = response.entry; - } - - protected async create(entity: ConsumerToken): Promise { - const accessToken = await this.fusio.getClient().consumer().token().create( entity); - - const modalRef = this.modalService.open(TokenShowComponent, { - size: 'md' - }); - modalRef.componentInstance.token = accessToken; - - return { - success: true, - message: 'Token successfully generated', - }; - } - - protected async update(entity: ConsumerToken): Promise { - const accessToken = await this.fusio.getClient().consumer().token().update('' + entity.id, entity); - - const modalRef = this.modalService.open(TokenShowComponent, { - size: 'md' - }); - modalRef.componentInstance.token = accessToken; - - return { - success: true, - message: 'Token successfully updated', - }; - } - - protected async delete(entity: ConsumerToken): Promise { - return this.fusio.getClient().consumer().token().delete('' + entity.id); - } - - protected newEntity(): ConsumerToken { - return { - name: '', - scopes: [], - }; - } - - scopeSelect(event: any, scope?: string) { - const selected = event.target.checked; - if (!scope) { - return; - } - - if (selected) { - this.addScope(scope); - } else { - this.removeScope(scope); - } - } - - private addScope(scope: string) { - this.entity.scopes?.push(scope) - } - - private removeScope(scope: string) { - this.entity.scopes = this.entity.scopes?.filter((value) => { - return value !== scope; - }); - } - -} diff --git a/projects/fusio-sdk/src/lib/component/token/show/token-show.component.html b/projects/fusio-sdk/src/lib/component/token/show/token-show.component.html index 16fb98f..e9d34f0 100644 --- a/projects/fusio-sdk/src/lib/component/token/show/token-show.component.html +++ b/projects/fusio-sdk/src/lib/component/token/show/token-show.component.html @@ -4,12 +4,7 @@