import { Component, ViewChild, TemplateRef, ChangeDetectionStrategy, } from '@angular/core'; import { XRef, nameof, isFunction, getFieldNames, isNullOrUndefined, isNullOrEmptyString, XResourceIdentifier, getComponentSelector, } from 'x-framework-core'; import { XFileDto, XPersonDto, XWebinarDto, XWebinarType, } from 'x-saherelm-api-sdk'; import { XListItem, XSlotName, XButtonType, XFabButtonSide, XListItemOptionSlot, } from 'x-framework-components'; import { Observable, Subject } from 'rxjs'; import { VBaseDtoAction, VModelFieldTypes, VBaseDtoActionModel, VBaseDtoModelAction, VBaseDtoPresentType, VModelFieldDescriptor, VBaseDtoModelFiredActionModel, } from 'src/app/views/v-dto/v-dto.typings'; import { Validators } from '@angular/forms'; import { defaultEditFabButton, defaultCloseFabButton, defaultOptionsFabItem, defaultRemoveFabButton, defaultConnectFabButton, } from 'src/app/views/constants/fab.defaults'; import { ToWebinarDto, ToWebinarViewDto, getWebinarResourceID, getWebinarTypeValues, } from 'src/app/views/webinar/v-webinar.tools'; import { VWebinarViewDto, defaultVWebinarViewDto, } from 'src/app/views/webinar/v-webinar.typings'; import { toSimpleFabItems, XSimpleFabButton, } from 'src/app/views/typings/simple.fab.typings'; import { XSimpleFormSelectControlConfig, XSimpleFormSelectControlOption, } from 'src/app/views/typings/simple.form.typings'; import { defaultEditSlideOption, defaultCloseSlideOption, defaultRemoveSlideOption, defaultConnectSlideOption, defaultDetailsSlideOption, } from 'src/app/views/constants/slide.options.defaults'; import { processFilledItems, VQueryPresenterTabs, VQueryPresenterAction, VQueryPresenterActionModel, VQueryPresenterActionIdentifier, VQueryFilledItemsProcessingResult, } from 'src/app/views/v-query-presenter/v-query-presenter.typings'; import { XQueryDto, XQueryResultDto } from 'x-framework-identity-sdk'; import { VTagsPresenterModelState, VTagsPresenterPresentType, } from 'src/app/views/tags/v-tags-presenter/v-tags-presenter.typings'; import { sendAction } from 'src/app/views/tools/action-provider.tools'; import { VFilesPresenterModelState, VFilesPresenterPresentType, } from 'src/app/views/files/v-files-presenter/v-files-presenter.typings'; import { getPersonFullName } from 'src/app/views/v-person/v-person.tools'; import { PersonPresentType } from 'src/app/views/v-person/v-person.typings'; import { VDtoCommonProperties } from 'src/app/views/typings/dto.common.typings'; import { VPagePresenter } from 'src/app/views/v-page-presenter/v-page-presenter.component'; import { getQuerySelectorOfSpecifiedAttribute } from 'src/app/views/typings/common.typings'; import { XSimpleListItemSlideOption } from 'src/app/views/typings/simple.list-item.typings'; import { VQueryPresenterBasePage } from 'src/app/views/v-query-presenter/v-query-presenter.base.page'; import { VWebinarViewComponent } from 'src/app/views/webinar/v-webinar-view/v-webinar-view.component'; import { VWebinarModalContext } from 'src/app/views/webinar/v-webinar-connect/v-webinar-connect.typings'; import { VWebinarConnectComponent } from 'src/app/views/webinar/v-webinar-connect/v-webinar-connect.component'; @Component({ template: '', changeDetection: ChangeDetectionStrategy.OnPush, }) export abstract class WebinarsBaseProviderPage extends VQueryPresenterBasePage { // //#region Props ... toolbarShowTitle = true; toolbarShowSubTitle = true; titleRes = this.ResourceIDs.app_name; toolbarSubTitle = this.resourceProvider( this.AppResourceIDs.webinars_management_page_title, ); toolbarTitle = this.resourceProvider(this.titleRes); // @ViewChild('pagePresenter') pagePresenter!: VPagePresenter; // readonly TagsPresenterPresertTypes = Object.assign( VTagsPresenterPresentType, {}, ); readonly FilesPresenterPresertTypes = Object.assign( {}, VFilesPresenterPresentType, ); readonly ButtonTypes = Object.assign(XButtonType, {}); readonly ModelFieldTypes = Object.assign(VModelFieldTypes); readonly ModelFieldNames = getFieldNames(defaultVWebinarViewDto); readonly PersonPresentTypes = Object.assign(PersonPresentType, {}); readonly BasePresentTypes = Object.assign(VBaseDtoPresentType, {}); // // Prepare Commonly Used Properties for Dto Actions ... // we can Override this for other Purposes ... commonViewsProperties: VDtoCommonProperties = { isInPage: false, wrapWithCard: false, labelColor: undefined, valueColor: undefined, fieldFormButtonPosition: undefined, fieldFormIcon: undefined, fieldFormIconColor: undefined, fieldFormApplyIcon: undefined, fieldFormApplyIconColor: undefined, fieldFormCancelIcon: undefined, fieldFormCancelIconColor: undefined, removeCardMargin: undefined, cardForegroundColor: undefined, cardCssClass: undefined, cardColor: undefined, cardActionProvider: undefined, formAppearance: undefined, formActionProvider: undefined, formRegularColor: undefined, formAccentColor: undefined, formHintColor: undefined, formActiveColor: undefined, formValidColor: undefined, formInvalidColor: undefined, formPendingColor: undefined, formFillColor: undefined, formDisabledColor: undefined, formDisabledFillColor: undefined, showFormCancelButton: undefined, formCancelButtonResource: undefined, formCancelButtonColor: undefined, formResetButtonResource: undefined, formResetButtonColor: undefined, formActionButtonAddResource: undefined, formActionButtonUpdateResource: undefined, formActionButtonColor: undefined, }; // //#region Query Presenter Props ... modelIdentifier: string = nameof('id'); listTabCardTitle: XResourceIdentifier = this.AppResourceIDs.webinars; /** * Presenter Component Action Provider ... */ queryPresenterActionProvider = new Subject(); //#endregion //#endregion /** * Specified How to get Specific Item using Model Identifier ... */ abstract getModelTask(identifier: string): Observable; /** * Specified How to Query Items ... */ abstract queryModelTask(query: XQueryDto): Observable>; /** * Param Recieved Action ... */ paramAction: string = undefined; // tagsState: VTagsPresenterModelState; filesState: VFilesPresenterModelState; // //#region LifeCycles ... async afterViewInit(): Promise { await super.afterViewInit(); // this.applyTakeUntilWrapper( this.managerService.settingsService.isMobile$, ).subscribe((res) => { // if (!isNullOrUndefined(this.activeTab)) { // switch (this.activeTab) { // case VQueryPresenterTabs.List: sendAction({ provider: this.listItemActionProvider, action: VBaseDtoAction.Refresh, }); break; } } }); // await this.handleConnectPushService(); } //#endregion // //#region Providers ... //#endregion // //#region List ... /** * Provides List Item Template ... */ @ViewChild('itemTemplate') itemTemplate!: TemplateRef; /** * Provides List Item Template ... */ @ViewChild('listItemTemplate') listItemTemplate!: TemplateRef; // //#region Owner Custom Template for List Item View ... private LIST_OWNER_REF: TemplateRef; @ViewChild('listOwnerRef') set listOwnerRef(v: TemplateRef) { // this.LIST_OWNER_REF = v; this.applyListOwnerRef(); } get listOwnerRef() { return this.LIST_OWNER_REF; } //#endregion /** * Query Object for Fetching Data ... */ query: XQueryDto = { page: 1, filter: '', pageSize: this.config.defaultPageSize, sortBy: nameof('createdOn'), }; /** * a Flag for Detect Has Query result or not ... */ hasQueryResultError: boolean = false; /** * Fetching Data Result Model ... */ dtoQueryResult: XQueryResultDto = undefined; /** * Specified Action Provider ... */ listItemActionProvider = new Subject(); /** * Specified View Properties ... */ listItemViewProperties: VDtoCommonProperties = { ...this.commonViewsProperties, }; /** * Specified Field Descriptors for List Items ... */ listItemViewFieldDescriptors: VModelFieldDescriptor[] = [ // // Type ... { hide: false, hideLabel: false, allowFieldForm: false, key: this.ModelFieldNames.type, value: defaultVWebinarViewDto.type, label: this.AppResourceIDs.type, type: this.ModelFieldTypes.Number, valueProvider: (value) => { return this.resourceProvider(getWebinarResourceID(value)); }, } as VModelFieldDescriptor, // // Title ... { hide: false, hideLabel: false, allowFieldForm: false, key: this.ModelFieldNames.title, value: defaultVWebinarViewDto.title, label: this.AppResourceIDs.title, type: this.ModelFieldTypes.String, } as VModelFieldDescriptor, // // Description ... { hide: false, hideLabel: false, allowFieldForm: false, key: this.ModelFieldNames.description, value: defaultVWebinarViewDto.description, label: this.AppResourceIDs.description, type: this.ModelFieldTypes.String, } as VModelFieldDescriptor, // // Owner ... { hide: false, hideLabel: false, showContentBelowLabel: false, key: this.ModelFieldNames.owner, value: defaultVWebinarViewDto.owner, label: this.AppResourceIDs.author, type: this.ModelFieldTypes.Object, template: this.listOwnerRef, hasCustomTemplate: true, } as VModelFieldDescriptor, ]; /** * Get Webinar Owner Full Name ... * * @param model * @returns */ getOwnerFullName(model: XPersonDto) { return getPersonFullName(model); } /** * Hold each Items Provided Actions based on Identifier ... */ itemsActions = new Map>>(); /** * Prepare Item Actions based on Slot ... */ getSlottedItemActions(slot: XSlotName, model: VWebinarViewDto) { // let result: Array = []; // if ( isNullOrUndefined(model) || isNullOrEmptyString(slot) || isNullOrEmptyString(model.id) || isNullOrUndefined(this.itemsActions) || !this.itemsActions.has(model.id) ) { return result; } // let _slot: XListItemOptionSlot = slot === XSlotName.START || slot === XSlotName.TOP ? 'start' : 'end'; // result = this.itemsActions .get(model.id) .value.filter((a) => a.slot === _slot); // return result; } /** * Handle Non As List Item's Action ... * * @param id * @param data */ async handleItemAction(id: string, data: VWebinarViewDto) { // // Validate ... if ( this.loading || this.uiDisabled || isNullOrEmptyString(id) || isNullOrUndefined(data) ) { return; } // await this.doItemActions({ id, data }); } /** * Apply List Owner Template to Descriptors ... * * @returns */ applyListOwnerRef() { // if (isNullOrUndefined(this.LIST_OWNER_REF)) { return; } // this.listItemViewFieldDescriptors = this.listItemViewFieldDescriptors.map( (fd) => { // return { ...fd, template: fd.key === this.ModelFieldNames.owner ? this.LIST_OWNER_REF : fd.template, }; }, ); } /** * Handle Retrieve Data based on XQuery ... * * @param query * @returns */ async handleGetQueryResult( query: XQueryDto, ): Promise> { // let result: XQueryResultDto = undefined; // // Start Loading ... this.hasQueryResultError = false; await this.setLoadingState(true); // // Try to Prepare Result ... try { // // Retrieve Webinar Dto Result ... this.dtoQueryResult = await this.getValueAsync( this.queryModelTask(query), ); // // Prepare Result ... result = { ...result, page: this.dtoQueryResult.page, pageSize: this.dtoQueryResult.pageSize, totalItems: this.dtoQueryResult.totalItems, totalPages: this.dtoQueryResult.totalPages, totalFilteredItems: this.dtoQueryResult.totalFilteredItems, totalFilteredPages: this.dtoQueryResult.totalFilteredPages, }; // // Converts XWebinarDto to VWebinarViewDto ... result.items = this.dtoQueryResult.items.map((i) => ToWebinarViewDto(i, this.managerService.currentLocale), ); // // Remove Scrolling Info ... if ( !isNullOrUndefined(this.query) && this.query.filter !== query.filter ) { // this.removeScrollingInfo(); this.infinityScrollDisabled = true; } // this.query = query; } catch { // this.hasQueryResultError = true; await this.handleCustomError('QueryWebinarsError'); return result; } // // Stop Loading ... await this.setLoadingState(false); // return result; } /** * Get Specified Model Based on Identifier ... * * @param identifier * @param applyState * @returns */ async handleGetSpecifiedModel(identifier: string, applyState = false) { // if (isNullOrEmptyString(identifier)) { return; } // let response: any = undefined; try { // if (applyState) { await this.setLoadingState(true); } // response = await this.getValueAsync(this.getModelTask(identifier)); // } catch { // await this.handleCustomError('GetWebinarError'); return; } // if (applyState) { await this.setLoadingState(false); } // return response; } /** * Provide List Actions for Specific Model ... * * @param model * @returns */ async prepareListActions(model: VWebinarViewDto) { // const userId = await this.getValueAsync(this.sharedService.userId$); const isAdmin = await this.getValueAsync(this.sharedService.isAdmin$); // return this.provideItemOptions(userId, isAdmin, model); } /** * Validate List Items ... * * @param items * @returns */ async validateAndPrepareListItems( items: Array>, ): Promise>> { // let result: Array> = []; // // Preparing Slide Options ... result = await Promise.all([ ...items.map(async (i) => { return { ...i, slideOptions: [...(await this.prepareListActions(i.data))], }; }), ]); // return result; } /** * Prepare Result for Non As List Presenting Items ... * * @param current * @param recieved */ async requestFillingItems( exists: Array, recieved: Array, ): Promise> { // let result: VQueryFilledItemsProcessingResult = processFilledItems(exists, recieved, 'id'); // // Filling Actions ... if (!isNullOrUndefined(result)) { // // News Items Actions ... if (!isNullOrUndefined(result.news) && this.hasChild(result.news)) { // result.news.forEach(async (i) => { // const actions = await this.prepareListActions(i); this.itemsActions.set(i.id, { value: actions }); }); } // // Changed Items Actions ... if (!isNullOrUndefined(result.changed) && this.hasChild(result.changed)) { // result.changed.forEach(async (i) => { // if (this.itemsActions.has(i.identifier)) { // const actions = await this.prepareListActions(i.data); this.itemsActions.set(i.identifier, { value: actions }); } }); } } // return result; } /** * When Non as List Items Filled, this method call for Change Detection ... * * @param ids */ async handleRefreshViews(ids: Array): Promise { await super.handleRefreshViews(ids); // if (isNullOrUndefined(ids) || !this.hasChild(ids)) { return; } // const selector = getComponentSelector(VWebinarViewComponent); ids.forEach((id) => { // const iSelector = `${selector}[${nameof( 'id', )}="${id}"][${nameof('presentType')}="${ VBaseDtoPresentType.AsView }"]`; this.waitForElement(iSelector).then((el) => { this.listItemActionProvider.next({ action: VBaseDtoAction.Refresh }); }); }); } //#endregion // //#region Add ... /** * Provides Template for Adding Items ... */ @ViewChild('addItemTemplate') addItemTemplate!: TemplateRef; /** * a Model for Providing to Add ... */ addModel: VWebinarViewDto = { ...defaultVWebinarViewDto, language: this.managerService.currentLocale, }; /** * Specified Action Provider ... */ addItemActionProvider = new Subject(); /** * Specify View Properties for Add ... */ addModelViewProperties: VDtoCommonProperties = { ...this.commonViewsProperties, isInPage: true, wrapWithCard: true, }; /** * Describe Add Model Fields ... */ addModelViewFieldDescriptors: VModelFieldDescriptor[] = [ // // ID ... { hide: true, hideLabel: true, allowFieldForm: false, key: this.ModelFieldNames.id, label: this.ResourceIDs.id, value: defaultVWebinarViewDto.id, type: this.ModelFieldTypes.String, } as VModelFieldDescriptor, // // Language ... { hide: true, hideLabel: true, allowFieldForm: false, key: this.ModelFieldNames.language, label: this.ResourceIDs.language, value: defaultVWebinarViewDto.language, type: this.ModelFieldTypes.String, } as VModelFieldDescriptor, // // Owner ID ... { hide: true, hideLabel: true, allowFieldForm: false, key: this.ModelFieldNames.ownerId, label: this.AppResourceIDs.author_id, value: defaultVWebinarViewDto.ownerId, type: this.ModelFieldTypes.String, } as VModelFieldDescriptor, // // Type ... { hide: false, hideLabel: false, allowFieldForm: true, key: this.ModelFieldNames.type, value: defaultVWebinarViewDto.type, label: this.AppResourceIDs.type, type: this.ModelFieldTypes.Number, valueProvider: (value) => { return this.resourceProvider(getWebinarResourceID(value)); }, formControlConfig: { index: 0, propName: this.ModelFieldNames.type, type: { type: this.FormControlTypes.Select, config: { multiple: false, options: getWebinarTypeValues().map((k) => { return { value: k, viewValue: this.resourceProvider(getWebinarResourceID(k)), } as XSimpleFormSelectControlOption; }), } as XSimpleFormSelectControlConfig, }, validators: { validators: [Validators.required], }, eventHandlers: {}, appearance: { hidden: false, disabled: false, label: this.AppResourceIDs.type, placeholder: this.AppResourceIDs.type, appearance: this.FormControlAppearances.Outline, icons: { prefix: { applyStateColor: true, name: this.IconNames.label, color: this.ColorNames.Tertiary, }, }, }, }, } as VModelFieldDescriptor, // // Title ... { hide: false, hideLabel: false, allowFieldForm: true, key: this.ModelFieldNames.title, value: defaultVWebinarViewDto.title, label: this.AppResourceIDs.title, type: this.ModelFieldTypes.String, formControlConfig: { index: 1, propName: this.ModelFieldNames.title, type: { type: this.FormControlTypes.Text, config: {}, }, validators: { validators: [Validators.required], }, eventHandlers: {}, focusHandler: new Subject(), appearance: { hidden: false, disabled: false, placeholder: this.AppResourceIDs.title, appearance: this.FormControlAppearances.Outline, icons: { prefix: { applyStateColor: true, name: this.IconNames.label, color: this.ColorNames.Tertiary, }, }, }, }, } as VModelFieldDescriptor, // // Description ... { hide: false, hideLabel: false, allowFieldForm: true, key: this.ModelFieldNames.description, value: defaultVWebinarViewDto.description, label: this.AppResourceIDs.description, type: this.ModelFieldTypes.String, formControlConfig: { index: 2, propName: this.ModelFieldNames.description, type: { type: this.FormControlTypes.Text, config: {}, }, validators: { validators: [Validators.required], }, eventHandlers: {}, appearance: { hidden: false, disabled: false, placeholder: this.AppResourceIDs.description, appearance: this.FormControlAppearances.Outline, icons: { prefix: { applyStateColor: true, name: this.IconNames.label, color: this.ColorNames.Tertiary, }, }, }, }, } as VModelFieldDescriptor, ]; /** * Handle Locking Page when a Form Lock Content ... * * @param event */ handleAddViewLockNotifier(event: { id: string; state: boolean }) { this.lock = event.state; } /** * Handle Cancel Add Form View ... * * @param event */ async handleAddViewActionFired(event: VBaseDtoModelFiredActionModel) { // // Cancel Form ... if (event.action === VBaseDtoModelAction.Cancel) { // // Since Cancel only Fired when Lock Breaked, here we do not need to handle it ... this.sendQueryPresenterAction( VQueryPresenterAction.ChangeTab, this.prevTab || VQueryPresenterTabs.List, ); } // // Reset Form ... else if (event.action === VBaseDtoModelAction.Reset) { } // // Add Or Update Form ... else if (event.action === VBaseDtoModelAction.AddOrUpdate) { // const pModel: Required = { ...event.payload.model, } as Required; await this.handleAddModel(pModel); } } /** * Do Add Model ... * * @param model * @returns */ async handleAddModel( model: VWebinarViewDto, tags?: Array, files?: Array, ) { // if (isNullOrUndefined(model)) { return; } // await this.setLoadingState(true); // let response: XWebinarDto = undefined; try { // // Prepare Dto Model to Add ... const dtoModel = ToWebinarDto(model); // // Remove ID ... delete dtoModel.id; // // Preparing Tags ... let pTags: Array = []; if (!isNullOrUndefined(tags) && this.hasChild(tags)) { pTags = [...tags]; } // // Preparing Files ... let pFiles: Array = []; if (!isNullOrUndefined(files) && this.hasChild(files)) { pFiles = [...files]; } // // Retrieve Connection ID ... const connectionId = this.sharedService.saherElmAPIService.webinars.webinarEntityPushService .connectionId; // // Filling Owner ID ... dtoModel.ownerId = await this.getValueAsync(this.sharedService.userId$); // // Issue Task ... response = await this.getValueAsync( this.sharedService.saherElmAPIService.webinars.webinarProviderService.create( dtoModel, // Model ... pTags, // Tags ... pFiles, // Files ... connectionId, // Connection Id ... ), ); } catch (ex) { // await this.handleCustomError('AddModelError'); return; } // this.lock = false; this.addModel = undefined; this.showSuccess(); await this.setLoadingState(false); this.sendQueryPresenterAction(VQueryPresenterAction.ResetQuery, true); } //#endregion // //#region Update ... /** * Provides Template for Update Items ... */ @ViewChild('updateItemTemplate') updateItemTemplate!: TemplateRef; /** * a Model for Providing to Update ... */ updateModel: VWebinarViewDto = undefined; /** * Specified Action Provider ... */ updateItemActionProvider = new Subject(); /** * Specify View Properties for Update ... */ updateModelViewProperties: VDtoCommonProperties = { ...this.commonViewsProperties, isInPage: true, wrapWithCard: true, }; /** * Describe Update Model Fields ... */ updateModelViewFieldDescriptors: VModelFieldDescriptor[] = [ // // ID ... { hide: true, hideLabel: true, allowFieldForm: false, label: this.ResourceIDs.id, key: this.ModelFieldNames.id, value: defaultVWebinarViewDto.id, type: this.ModelFieldTypes.String, } as VModelFieldDescriptor, // // Language ... { hide: true, hideLabel: true, allowFieldForm: false, label: this.ResourceIDs.language, type: this.ModelFieldTypes.String, key: this.ModelFieldNames.language, value: defaultVWebinarViewDto.language, } as VModelFieldDescriptor, // // Type ... { hide: false, hideLabel: false, allowFieldForm: true, key: this.ModelFieldNames.type, label: this.AppResourceIDs.type, type: this.ModelFieldTypes.Number, value: defaultVWebinarViewDto.type, valueProvider: (value) => { return this.resourceProvider(getWebinarResourceID(value)); }, formControlConfig: { index: 0, propName: this.ModelFieldNames.type, type: { type: this.FormControlTypes.Select, config: { multiple: false, options: getWebinarTypeValues().map((k) => { return { value: k, viewValue: this.resourceProvider(getWebinarResourceID(k)), } as XSimpleFormSelectControlOption; }), } as XSimpleFormSelectControlConfig, }, validators: { validators: [Validators.required], }, eventHandlers: {}, appearance: { hidden: false, disabled: false, label: this.AppResourceIDs.type, placeholder: this.AppResourceIDs.type, appearance: this.FormControlAppearances.Outline, icons: { prefix: { applyStateColor: true, name: this.IconNames.label, color: this.ColorNames.Tertiary, }, }, }, }, } as VModelFieldDescriptor, // // Title ... { hide: false, hideLabel: false, allowFieldForm: true, key: this.ModelFieldNames.title, label: this.AppResourceIDs.title, type: this.ModelFieldTypes.String, value: defaultVWebinarViewDto.title, formControlConfig: { index: 1, propName: this.ModelFieldNames.title, type: { type: this.FormControlTypes.Text, config: {}, }, validators: { validators: [Validators.required], }, eventHandlers: {}, focusHandler: new Subject(), appearance: { hidden: false, disabled: false, placeholder: this.AppResourceIDs.title, appearance: this.FormControlAppearances.Outline, icons: { prefix: { applyStateColor: true, name: this.IconNames.label, color: this.ColorNames.Tertiary, }, }, }, }, } as VModelFieldDescriptor, // // Description ... { hide: false, hideLabel: false, allowFieldForm: true, type: this.ModelFieldTypes.String, key: this.ModelFieldNames.description, label: this.AppResourceIDs.description, value: defaultVWebinarViewDto.description, formControlConfig: { index: 2, propName: this.ModelFieldNames.description, type: { type: this.FormControlTypes.Text, config: {}, }, validators: { validators: [Validators.required], }, eventHandlers: {}, appearance: { hidden: false, disabled: false, placeholder: this.AppResourceIDs.description, appearance: this.FormControlAppearances.Outline, icons: { prefix: { applyStateColor: true, name: this.IconNames.label, color: this.ColorNames.Tertiary, }, }, }, }, } as VModelFieldDescriptor, ]; /** * Handle Locking Page when a Form Lock Content ... * * @param event */ handleUpdateViewLockNotifier(event: { id: string; state: boolean }) { this.lock = event.state; } /** * Tags Actions Provider for Details Section ... * * @param t * @returns */ detailsTagsActionsProvider: (t: string) => Array = (t) => { return []; }; /** * Files Actions Provider for Details Section ... * * @param f * @returns */ detailsFilesActionsProvider: ( f: XFileDto | File, ) => Array = (f) => { return []; }; /** * Handle Cancel Update Form View ... * * @param event */ async handleUpdateViewActionFired(event: VBaseDtoModelFiredActionModel) { // // Cancel Form ... if (event.action === VBaseDtoModelAction.Cancel) { // // Since Cancel only Fired when Lock Breaked, here we do not need to handle it ... this.sendQueryPresenterAction( VQueryPresenterAction.ChangeTab, this.prevTab || VQueryPresenterTabs.List, ); } // // Reset Form ... else if (event.action === VBaseDtoModelAction.Reset) { } // // Add Or Update Form ... else if (event.action === VBaseDtoModelAction.AddOrUpdate) { // const pModel: Required = { ...event.payload.model, } as Required; await this.handleUpdateModel(pModel); } } /** * Do Update Model ... * * @param model * @returns */ async handleUpdateModel(model: VWebinarViewDto) { // const prevTab = this.prevTab; // if (isNullOrUndefined(model)) { return; } // await this.setLoadingState(true); // let response: XWebinarDto = undefined; try { // // Prepare Dto Model to Add ... const dto = !isNullOrUndefined(this.dtoQueryResult) && !isNullOrUndefined(this.dtoQueryResult.items) && this.hasChild(this.dtoQueryResult.items) ? this.dtoQueryResult.items.find((i) => i.id === model.id) : undefined; if (isNullOrUndefined(dto)) { throw 'UpdateModelError'; } // // Preparing Update Model ... const dtoModel = ToWebinarDto(model, dto); // // Retrieve Connection ID ... const connectionId = this.sharedService.saherElmAPIService.webinars.webinarEntityPushService .connectionId; // // Filling Owner ID ... dtoModel.ownerId = await this.getValueAsync(this.sharedService.userId$); // // Issue Task ... response = await this.getValueAsync( this.sharedService.saherElmAPIService.webinars.webinarProviderService.update( dtoModel, connectionId, ), ); } catch (ex) { // await this.handleCustomError('UpdateModelError'); return; } // if (isNullOrUndefined(response)) { // await this.handleCustomError('UpdateModelError'); return; } // this.lock = false; this.updateModel = undefined; await this.setLoadingState(false); this.showSuccess(); // this.prevTab = prevTab; model = ToWebinarViewDto(response, this.managerService.currentLocale); const actions = await this.prepareListActions(model); // if (this.prevTab === VQueryPresenterTabs.Details) { // this.detailsModel = { ...model, }; } // this.sendQueryPresenterAction(VQueryPresenterAction.UpdateModel, { model, actions, key: nameof('id'), }); // // Check Handle Back ... if ( this.toolbarHasBack && this.toolbarShowBack && isFunction(this.toolbarBackHandler) ) { await this.toolbarBackHandler(); } } //#endregion // //#region Details ... /** * Provides Template for Details Items ... */ @ViewChild('detailsItemTemplate') detailsItemTemplate!: TemplateRef; /** * a Model for Providing to Details ... */ detailsModel: VWebinarViewDto = undefined; /** * Specified Action Provider ... */ detailsItemActionProvider = new Subject(); /** * Specify View Properties for Details ... */ detailsModelViewProperties: VDtoCommonProperties = { ...this.commonViewsProperties, isInPage: true, wrapWithCard: true, }; /** * Describe Details Model Fields ... */ detailsModelViewFieldDescriptors: VModelFieldDescriptor[] = []; /** * Provides Card Title for Specified Model ... * * @param model * @returns */ getModelCardTitle(model: VWebinarViewDto) { // // Since card title's are Rescource ID's ... return this.applyLocale(`${model.title} `); } //#endregion // //#region Handlers ... /** * Handle Errors ... * * @param error */ async handleCustomError( error?: VQueryPresenterActionIdentifier, ): Promise { // await this.setLoadingState(false); // // TODO: Implement this ... console.log('handle Custom Error: ', error); } /** * Override this for adding additional futures ... * * @param tab */ async handleStateAfterTabOpen(tab: number) { await super.handleStateAfterTabOpen(tab); // let selector: string = undefined; let fabs: XSimpleFabButton[] = []; let model: VWebinarViewDto = undefined; // let actions = await toSimpleFabItems(this.actions); this.closeActions(); this.actions = undefined; // const userId = await this.getValueAsync(this.sharedService.userId$); const isAdmin = await this.getValueAsync(this.sharedService.isAdmin$); const isAgent = await this.getValueAsync(this.sharedService.isAgent$); const isAdminAgent = isAdmin || isAgent; // switch (tab) { // case VQueryPresenterTabs.List: // // if Show Items as List ... if (this.showItemsAsList) { // sendAction({ provider: this.listItemActionProvider, action: VBaseDtoAction.SetProperties, payload: { props: { ...this.listItemViewProperties }, }, }); } else { // // Call each Items Action Provider Separately ... // // Prepare Non As List Items Properties ... const properties: VDtoCommonProperties = { ...this.listItemViewProperties, isInPage: true, wrapWithCard: true, cardShowActions: true, // Since Each Items has Separate Actions ... }; // sendAction({ provider: this.listItemActionProvider, action: VBaseDtoAction.SetProperties, payload: { props: { ...properties }, }, }); } // break; // case VQueryPresenterTabs.Add: // this.addModel = { ...defaultVWebinarViewDto, language: this.managerService.currentLocale, }; // sendAction({ provider: this.addItemActionProvider, action: VBaseDtoAction.SetProperties, payload: { props: { ...this.addModelViewProperties }, }, }); break; // case VQueryPresenterTabs.Update: // model = { ...this.updateModel }; // sendAction({ provider: this.updateItemActionProvider, action: VBaseDtoAction.SetProperties, payload: { props: { ...this.updateModelViewProperties }, }, }); break; // case VQueryPresenterTabs.Details: // model = { ...this.detailsModel }; // sendAction({ provider: this.detailsItemActionProvider, action: VBaseDtoAction.SetProperties, payload: { props: { ...this.detailsModelViewProperties }, }, }); // // Adding Custom Actions ... // let isOwner = this.detailsModel.ownerId === userId; let canConnect = isOwner || this.detailsModel.enabled; let canClose = (isOwner || isAdmin) && this.detailsModel.enabled; // // Connect ... if (canConnect) { // fabs = [ ...fabs, { ...defaultConnectFabButton, index: 1, side: XFabButtonSide.TOP, handler: async () => { await this.doItemActions({ id: defaultConnectFabButton.id, data: { ...this.detailsModel }, }); }, }, ]; } // // Close ... if (canClose) { // fabs = [ ...fabs, { ...defaultCloseFabButton, index: 1, side: XFabButtonSide.START, handler: async () => { await this.doItemActions({ id: defaultCloseFabButton.id, data: { ...this.detailsModel }, }); }, }, ]; } // // Actions Preparing ... actions = { ...(!isNullOrUndefined(actions) ? actions : defaultOptionsFabItem), childs: [ ...(!isNullOrUndefined(actions) && this.hasChild(actions.childs) ? actions.childs : []), ...fabs, ], }; // // Issue Action if Waiting for Details ... if (!isNullOrEmptyString(this.paramAction)) { // const action = this.paramAction; this.paramAction = undefined; // await this.doItemActions({ id: action, data: { ...this.detailsModel }, }); } break; } // // Here can Handle Actions Permissions and States ... if (!isNullOrUndefined(actions)) { // // Only if model Exists ... if (!isNullOrUndefined(model)) { // // Retrieve Requirements ... // const isOwner = model.ownerId === userId; // const canEdit = isOwner || isAdmin; const canRemove = isOwner || isAdmin; const canClose = (isOwner || isAdmin) && model.enabled; const canConnect = isOwner || model.enabled; // // Edit ... if ( actions.id === defaultEditFabButton.id || (!isNullOrUndefined(actions.childs) && this.hasChild(actions.childs) && actions.childs.findIndex( (a) => a.id === defaultEditFabButton.id, )) >= 0 ) { // if (actions.id === defaultEditFabButton.id) { actions.disabled = !canEdit || actions.disabled || this.loading || this.uiDisabled; } else { // actions.childs = [ ...actions.childs.map((ch) => { return { ...ch, disabled: ch.id === defaultEditFabButton.id ? !canEdit || ch.disabled || this.loading || this.uiDisabled : ch.disabled, }; }), ]; } } // // Remove ... if ( actions.id === defaultRemoveFabButton.id || (!isNullOrUndefined(actions.childs) && this.hasChild(actions.childs) && actions.childs.findIndex( (a) => a.id === defaultRemoveFabButton.id, )) >= 0 ) { // if (actions.id === defaultRemoveFabButton.id) { actions.disabled = !canRemove || actions.disabled || this.loading || this.uiDisabled; } else { // actions.childs = [ ...actions.childs.map((ch) => { return { ...ch, disabled: ch.id === defaultRemoveFabButton.id ? !canRemove || ch.disabled || this.loading || this.uiDisabled : ch.disabled, }; }), ]; } } // // Close ... if ( actions.id === defaultCloseFabButton.id || (!isNullOrUndefined(actions.childs) && this.hasChild(actions.childs) && actions.childs.findIndex( (a) => a.id === defaultCloseFabButton.id, )) >= 0 ) { // if (actions.id === defaultCloseFabButton.id) { actions.disabled = !canClose || actions.disabled || this.loading || this.uiDisabled; } else { // actions.childs = [ ...actions.childs.map((ch) => { return { ...ch, disabled: ch.id === defaultCloseFabButton.id ? !canClose || ch.disabled || this.loading || this.uiDisabled : ch.disabled, }; }), ]; } } // // Connect ... if ( actions.id === defaultConnectFabButton.id || (!isNullOrUndefined(actions.childs) && this.hasChild(actions.childs) && actions.childs.findIndex( (a) => a.id === defaultConnectFabButton.id, )) >= 0 ) { // if (actions.id === defaultConnectFabButton.id) { actions.disabled = !canConnect || actions.disabled || this.loading || this.uiDisabled; } else { // actions.childs = [ ...actions.childs.map((ch) => { return { ...ch, disabled: ch.id === defaultConnectFabButton.id ? !canConnect || ch.disabled || this.loading || this.uiDisabled : ch.disabled, }; }), ]; } } } // // Update Actions ... this.actions = { ...actions, }; } } /** * Override this for adding additional futures ... * * @param from * @param to */ async handleStateBeforeTabOpen(from: number, to: number) { await super.handleStateBeforeTabOpen(from, to); // this.closeActions(); // switch (to) { // case VQueryPresenterTabs.List: // this.addModel = undefined; this.updateModel = undefined; this.detailsModel = undefined; break; // case VQueryPresenterTabs.Add: // this.updateModel = undefined; this.detailsModel = undefined; break; // case VQueryPresenterTabs.Update: // this.addModel = undefined; this.detailsModel = undefined; break; // case VQueryPresenterTabs.Details: // if ( isNullOrUndefined(this.detailsModel) && !isNullOrUndefined(this.updateModel) && from === VQueryPresenterTabs.Update ) { // this.detailsModel = { ...this.updateModel, }; } // this.addModel = undefined; this.updateModel = undefined; break; } } /** * Here We Do All Items Based Actions ... * * @param info * @returns */ async doItemActions(info: { id: string; data: VWebinarViewDto; }): Promise { // if (isNullOrUndefined(info) || isNullOrEmptyString(info.id)) { return; } // let isKnown = false; // // Close ... isKnown = info.id === defaultCloseSlideOption.id || info.id === defaultCloseFabButton.id; if (isKnown) { // if ( isNullOrUndefined(info.data) && !isNullOrUndefined(this.detailsModel) && this.activeTab === VQueryPresenterTabs.Details ) { // info.data = { ...this.detailsModel, }; } // if (!isNullOrUndefined(info.data)) { await this.handleCloseWebinar(info.data); } } // // Conect ... isKnown = info.id === defaultConnectSlideOption.id || info.id === defaultConnectFabButton.id; if (isKnown) { // if ( isNullOrUndefined(info.data) && !isNullOrUndefined(this.detailsModel) && this.activeTab === VQueryPresenterTabs.Details ) { // info.data = { ...this.detailsModel, }; } // if (!isNullOrUndefined(info.data)) { await this.handleConnectWebinar(info.data); } } // // Details ... isKnown = info.id === defaultDetailsSlideOption.id; if (isKnown) { // this.detailsModel = { ...info.data, }; // this.sendQueryPresenterAction( VQueryPresenterAction.ChangeTab, VQueryPresenterTabs.Details, ); } // // Edit ... isKnown = info.id === defaultEditSlideOption.id || info.id === defaultEditFabButton.id; if (isKnown) { // if (!isNullOrUndefined(info.data)) { // this.updateModel = { ...info.data, }; } else if ( !isNullOrUndefined(this.detailsModel) && this.activeTab === VQueryPresenterTabs.Details ) { // this.updateModel = { ...this.detailsModel, }; } // if (!isNullOrUndefined(this.updateModel)) { // this.sendQueryPresenterAction( VQueryPresenterAction.ChangeTab, VQueryPresenterTabs.Update, ); } } // // Remove ... isKnown = info.id === defaultRemoveSlideOption.id || info.id === defaultRemoveFabButton.id; if (isKnown) { // if ( isNullOrUndefined(info.data) && !isNullOrUndefined(this.detailsModel) && this.activeTab === VQueryPresenterTabs.Details ) { // info.data = { ...this.detailsModel, }; } // if (!isNullOrUndefined(info.data)) { await this.handleRemoveWebinar(info.data); } } } /** * Handle Specified Param ... * * @param identifier * @param acttion */ async handleParamAction(identifier: string, action: string): Promise { await super.handleParamAction(identifier, action); // if (isNullOrEmptyString(identifier) || isNullOrEmptyString(action)) { // this.hasParams = false; return; } // let model = await this.handleGetSpecifiedModel(identifier, true); if (!isNullOrUndefined(model)) { // this.paramAction = action; this.detailsModel = { ...model }; this.activeTab = VQueryPresenterTabs.Details; this.sendQueryPresenterAction( VQueryPresenterAction.ChangeTab, this.activeTab, ); } else { this.hasParams = false; } } /** * Close Specified Webinar if it's Open ... * * @param model * @returns */ async handleCloseWebinar(model: VWebinarViewDto) { // if (isNullOrUndefined(model) || !model.enabled) { return; } // model = { ...model, enabled: false, }; const dto = this.dtoQueryResult.items.find((dto) => dto.id === model.id); const dtoModel = ToWebinarDto(model, dto); if (isNullOrUndefined(dto) || isNullOrUndefined(dtoModel)) { return; } // // Do Based on Confirm ... await this.doConfirmedAction(async () => { // await this.setLoadingState(true); // let response: XWebinarDto = undefined; try { // const connectionId = this.sharedService.saherElmAPIService.webinars .webinarEntityPushService.connectionId; response = await this.getValueAsync( this.sharedService.saherElmAPIService.webinars.webinarProviderService.update( dtoModel, connectionId, ), ); } catch { // await this.handleCustomError('CloseWebinarError'); return; } // await this.setLoadingState(false); // // Check if Response Provided ... // Update Contents ... if (!isNullOrUndefined(response)) { // const updateVDto = ToWebinarViewDto( response, this.managerService.currentLocale, ); const actions = await this.prepareListActions(updateVDto); this.sendQueryPresenterAction(VQueryPresenterAction.UpdateModel, { actions, model: updateVDto, key: nameof('id'), }); await this.handleStateAfterTabOpen(this.activeTab); } }); } /** * Handle Connecting to Webinar ... * * @param model */ async handleConnectWebinar(model: VWebinarViewDto) { // // Validate ... if (isNullOrUndefined(model) || isNullOrEmptyString(model.id)) { return; } // // Present Webinar Connect Model ... let modal = await this.managerService.dialogService.presentModal({ autoHeight: true, fullScreen: true, backdropDismiss: false, component: VWebinarConnectComponent, componentProps: { // context: VWebinarModalContext.Modal, model: { ...model }, toolbarTitle: this.AppResourceIDs.webinar, }, }); if (!isNullOrUndefined(model)) { this.lock = true; } /** * wait for Model Result ... */ const data = await modal.onDidDismiss(); modal.remove(); modal.dismiss(); this.lock = false; } /** * Handle Removing Webinar ... * * @param model */ async handleRemoveWebinar(model: VWebinarViewDto) { // await this.doConfirmedAction(async () => { // await this.setLoadingState(true); // try { // const connectionId = this.sharedService.saherElmAPIService.webinars .webinarEntityPushService.connectionId; // await this.getValueAsync( this.sharedService.saherElmAPIService.webinars.webinarProviderService.remove( model.id, connectionId, ), ); } catch { // await this.handleCustomError('RemoveModelError'); return; } // this.sendQueryPresenterAction(VQueryPresenterAction.RemoveModel, { model, actions: [], key: nameof('id'), }); // this.showSuccess(); await this.setLoadingState(false); // // Handle Change Tabs if in Details ... if ( this.activeTab === VQueryPresenterTabs.List || this.activeTab === VQueryPresenterTabs.Details ) { // this.prevTab = undefined; this.sendQueryPresenterAction( VQueryPresenterAction.ChangeTab, VQueryPresenterTabs.List, ); } }); } /** * Handle Running toolbar Back Handler on Specified Case * when User Pressed Escape Button ... * * @param event * @returns */ async handleGlobalEscapePressed(event: any) { // if ( this.lock || !this.toolbarHasBack || !this.toolbarShowBack || !isFunction(this.toolbarBackHandler) || [VQueryPresenterTabs.Add, VQueryPresenterTabs.Update].includes( this.activeTab, ) ) { return; } // await this.toolbarBackHandler(); } /** * Handle Tags State ... * * @param event * @returns */ handleTagsStateChanged(event: VTagsPresenterModelState) { // if (isNullOrUndefined(event)) { return; } // this.tagsState = { ...event, }; } /** * Handle Files State ... * * @param event * @returns */ handleFilesStateChanged(event: VFilesPresenterModelState) { // if (isNullOrUndefined(event)) { return; } // this.filesState = { ...event, }; } //#endregion // //#region Private ... private provideItemOptions( userId: string, isAdmin: boolean, item: VWebinarViewDto, ) { // let result: Array = []; // // Validate ... if (!isNullOrUndefined(item) && !isNullOrEmptyString(userId)) { // const isOwner = item.ownerId === userId; // const canEdit = isOwner || isAdmin; const canRemove = isOwner || isAdmin; const canClose = (isOwner || isAdmin) && item.enabled; // // Close ... if (canClose) { // result.push({ ...defaultCloseSlideOption, slot: 'start', disabled: this.loading || this.uiDisabled, } as XSimpleListItemSlideOption); } // // Join ... result.push({ ...defaultConnectSlideOption, slot: 'start', icon: this.IconNames.live_tv, disabled: this.loading || this.uiDisabled || (!isOwner && !item.enabled), } as XSimpleListItemSlideOption); // // Details ... result.push({ ...defaultDetailsSlideOption, slot: 'start', disabled: this.loading || this.uiDisabled, } as XSimpleListItemSlideOption); // // Edit ... result.push({ ...defaultEditSlideOption, slot: 'start', disabled: this.loading || this.uiDisabled || !canEdit, } as XSimpleListItemSlideOption); // // Remove ... result.push({ ...defaultRemoveSlideOption, slot: 'end', disabled: this.loading || this.uiDisabled || !canRemove, } as XSimpleListItemSlideOption); } // return result; } isPushServiceConnected = false; private async handleConnectPushService() { // // Preparing Connections ... try { // // Check Connected Before ... if ( this.sharedService.saherElmAPIService.webinars.webinarEntityPushService.isConnected() ) { this.isPushServiceConnected = true; } else { // this.isPushServiceConnected = true; await this.sharedService.saherElmAPIService.webinars.webinarEntityPushService.connect(); } } catch { // await this.handleCustomError('PushServiceConnection'); return; } // // Check Connected ... if (!this.isPushServiceConnected) { return; } // // On Added ... this.applyTakeUntilWrapper( this.sharedService.saherElmAPIService.webinars.webinarEntityPushService .onAdded$, ).subscribe(async (event) => { // if (isNullOrUndefined(event)) { return; } // // Only Notify when a new Open Webinar Created ... // Since here is Management Page ... // TODO: Use this if necessary ... // if (this.activeTab === VQueryPresenterTabs.List) { // // // await this.managerService.notificationService.presentInfoNotification({ // dissmissable: true, // message: this.resourceProvider( // this.AppResourceIDs.new_webinar_created // ), // opt: { // duration: 5000, // buttons: [ // { // icon: this.IconNames.refresh, // side: 'end', // handler: async () => { // this.sendQueryPresenterAction( // VQueryPresenterAction.ResetQuery // ); // }, // } as ToastButton, // ], // }, // }); // } }); // // On Removed ... this.applyTakeUntilWrapper( this.sharedService.saherElmAPIService.webinars.webinarEntityPushService .onDeleted$, ).subscribe(async (event) => { // if (isNullOrUndefined(event) && isNullOrUndefined(this.dtoQueryResult)) { return; } // // Check if Model Exists in Current Context or not ... let model = this.dtoQueryResult.items.find( (i) => i.id === event.model.id, ); const modelP = ToWebinarViewDto(model, this.managerService.currentLocale); if (!isNullOrUndefined(model) && !isNullOrUndefined(modelP)) { // const actions = await this.prepareListActions(modelP); // this.sendQueryPresenterAction(VQueryPresenterAction.RemoveModel, { actions, model: modelP, key: nameof('id'), }); } // // Check Details or Edit Tab ... if ( (!isNullOrUndefined(model) && !isNullOrUndefined(this.detailsModel) && this.detailsModel.id === model.id && this.activeTab === VQueryPresenterTabs.Details) || (!isNullOrUndefined(model) && !isNullOrUndefined(this.updateModel) && this.updateModel.id === model.id && this.activeTab === VQueryPresenterTabs.Update) ) { // // Force Unlock ... this.lock = false; // this.sendQueryPresenterAction( VQueryPresenterAction.ChangeTab, VQueryPresenterTabs.List, ); } }); // // On Updated ... this.applyTakeUntilWrapper( this.sharedService.saherElmAPIService.webinars.webinarEntityPushService .onUpdated$, ).subscribe(async (event) => { // if (isNullOrUndefined(event) || isNullOrUndefined(this.dtoQueryResult)) { return; } // // Check if Model Exists in Current Context or not ... let model = this.dtoQueryResult.items.find( (i) => i.id === event.model.id, ); if (isNullOrUndefined(model)) { return; } // let fromEntity: XWebinarDto = undefined; try { fromEntity = await this.getValueAsync( this.sharedService.saherElmAPIService.webinars.webinarProviderService.get( event.model.id, ), ); } catch { return; } // if (isNullOrUndefined(fromEntity)) { return; } // const modelP = ToWebinarViewDto( fromEntity, this.managerService.currentLocale, ); // if (isNullOrUndefined(modelP)) { return; } // // Preparing Model List Actions ... const actions = await this.prepareListActions(modelP); // // Updating Model on Query Presenter ... this.sendQueryPresenterAction(VQueryPresenterAction.UpdateModel, { actions, model: { ...modelP }, key: nameof('id'), }); // // Update Tab ... if ( !isNullOrUndefined(this.updateModel) && modelP.id === this.updateModel.id && this.activeTab === VQueryPresenterTabs.Update ) { // this.updateModel = { ...modelP, }; // const selector = getQuerySelectorOfSpecifiedAttribute( VWebinarViewComponent, this.ModelFieldNames.id, this.updateModel.id, ); await this.waitForElement(selector).then(async (el) => { // this.updateItemActionProvider.next({ action: VBaseDtoAction.RenewModel, payload: { ...this.updateModel }, }); // const prevTab = this.prevTab; await this.handleStateAfterTabOpen(this.activeTab); this.prevTab = prevTab; }); } // // Details Tab ... if ( !isNullOrUndefined(this.detailsModel) && modelP.id === this.detailsModel.id && this.activeTab === VQueryPresenterTabs.Details ) { // this.detailsModel = { ...modelP, }; // const selector = getQuerySelectorOfSpecifiedAttribute( VWebinarViewComponent, this.ModelFieldNames.id, this.detailsModel.id, ); await this.waitForElement(selector).then(async (el) => { // this.detailsItemActionProvider.next({ action: VBaseDtoAction.RenewModel, payload: { ...this.detailsModel }, }); // const prevTab = this.prevTab; await this.handleStateAfterTabOpen(this.activeTab); this.prevTab = prevTab; }); } }); } //#endregion }