Initial Commit ...
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { HomePage } from './pages/home/home.page';
|
||||
import { ErrorPage } from './pages/error/error.page';
|
||||
import { AuthGuard } from 'x-framework-identity-sdk';
|
||||
import { XCanDeactivateGuard } from 'x-framework-core';
|
||||
import { Pages, BaseRoutes } from './config/page.config';
|
||||
import { StartupPage } from './pages/startup/startup.page';
|
||||
import { LandingPage } from './pages/landing/landing.page';
|
||||
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
|
||||
import { NotAuthorizedPage } from './pages/not-authorized/not-authorized.page';
|
||||
|
||||
const routes: Routes = [
|
||||
//
|
||||
//#region Default ...
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Default,
|
||||
redirectTo: Pages.Startup.baseRoute,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Startup ...
|
||||
{
|
||||
component: StartupPage,
|
||||
path: Pages.Startup.baseRoute,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Landing ...
|
||||
{
|
||||
component: LandingPage,
|
||||
path: Pages.Landing.baseRoute,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Home ...
|
||||
{
|
||||
component: HomePage,
|
||||
canActivate: [AuthGuard],
|
||||
path: Pages.Home.baseRoute,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Webinars ...
|
||||
{
|
||||
path: Pages.Webinars.baseRoute,
|
||||
loadChildren: () =>
|
||||
import('./pages/webinars/webinars-page.module').then(
|
||||
(m) => m.WebinarsPageModule
|
||||
),
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Tags ...
|
||||
{
|
||||
path: Pages.Tags.baseRoute,
|
||||
loadChildren: () =>
|
||||
import('./pages/tags/tags-page.module').then(
|
||||
(m) => m.TagsPageModule
|
||||
),
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Files ...
|
||||
{
|
||||
path: Pages.Files.baseRoute,
|
||||
loadChildren: () =>
|
||||
import('./pages/files/files-page.module').then(
|
||||
(m) => m.FilesPageModule
|
||||
),
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Account ...
|
||||
{
|
||||
path: Pages.Account.baseRoute,
|
||||
loadChildren: () =>
|
||||
import('./pages/account/account.module').then((m) => m.AccountPageModule),
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Not Authorized ...
|
||||
{
|
||||
component: NotAuthorizedPage,
|
||||
path: Pages.NotAuthorized.baseRoute,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Error ...
|
||||
{
|
||||
component: ErrorPage,
|
||||
path: Pages.Error.baseRoute,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UnKnown Routes ...
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Unknown,
|
||||
redirectTo: Pages.Startup.baseRoute,
|
||||
},
|
||||
//#endregion
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(routes, {
|
||||
preloadingStrategy: PreloadAllModules,
|
||||
scrollPositionRestoration: 'enabled',
|
||||
}),
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
||||
@@ -0,0 +1,3 @@
|
||||
<ion-app>
|
||||
<ion-router-outlet></ion-router-outlet>
|
||||
</ion-app>
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Platform } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: 'app.component.html',
|
||||
styleUrls: ['app.component.scss']
|
||||
})
|
||||
export class AppComponent {
|
||||
constructor(private platform: Platform) {
|
||||
this.initializeApp();
|
||||
}
|
||||
|
||||
initializeApp() {
|
||||
this.platform.ready().then(() => {});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
import {
|
||||
UserGuard,
|
||||
AgentGuard,
|
||||
AdminGuard,
|
||||
AdminOrAgentGuard,
|
||||
XMabsutApiSdkModule,
|
||||
X_MABSUT_API_SDK_CONFIG,
|
||||
XPushTokenFetcherService,
|
||||
} from 'x-mabsut-api-sdk';
|
||||
import {
|
||||
XCanDeactivateGuard,
|
||||
XFrameworkCoreModule,
|
||||
X_FRAMEWORK_CORE_CONFIG,
|
||||
} from 'x-framework-core';
|
||||
import {
|
||||
XManagerService,
|
||||
XFrameworkServicesModule,
|
||||
X_FRAMEWORK_SERVICES_CONFIG,
|
||||
} from 'x-framework-services';
|
||||
import {
|
||||
XFrameworkComponentsModule,
|
||||
X_FRAMEWORK_COMPONENTS_CONFIG,
|
||||
} from 'x-framework-components';
|
||||
import {
|
||||
AuthGuard,
|
||||
X_API_CONFIG,
|
||||
NotAuthGuard,
|
||||
ApiHttpInterceptorService,
|
||||
XFrameworkIdentitySdkModule,
|
||||
X_FRAMEWORK_IDENTITY_SDK_CONFIG,
|
||||
} from 'x-framework-identity-sdk';
|
||||
import {
|
||||
XFrameworkPushServiceModule,
|
||||
X_FRAMEWORK_PUSH_SERVICE_CONFIG,
|
||||
X_FRAMEWORK_PUSH_SERVICE_TOKEN_FETCHER,
|
||||
} from 'x-framework-push-service';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { AppComponent } from './app.component';
|
||||
import { HomePage } from './pages/home/home.page';
|
||||
import { ViewsModule } from './views/views.module';
|
||||
import { XAPI_CONFIG } from './config/x-api.config';
|
||||
import { ErrorPage } from './pages/error/error.page';
|
||||
import { RouteReuseStrategy } from '@angular/router';
|
||||
import { X_CONFIG, XCONFIG } from './config/x.config';
|
||||
import { SharedModule } from './shared/shared.module';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { environment } from '../environments/environment';
|
||||
import { StartupPage } from './pages/startup/startup.page';
|
||||
import { LandingPage } from './pages/landing/landing.page';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
|
||||
import { NotAuthorizedPage } from './pages/not-authorized/not-authorized.page';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
HomePage,
|
||||
ErrorPage,
|
||||
StartupPage,
|
||||
LandingPage,
|
||||
AppComponent,
|
||||
NotAuthorizedPage,
|
||||
],
|
||||
imports: [
|
||||
ViewsModule,
|
||||
SharedModule,
|
||||
BrowserModule,
|
||||
AppRoutingModule,
|
||||
XMabsutApiSdkModule,
|
||||
XFrameworkCoreModule,
|
||||
IonicModule.forRoot(),
|
||||
BrowserAnimationsModule,
|
||||
XFrameworkServicesModule,
|
||||
XFrameworkComponentsModule,
|
||||
XFrameworkPushServiceModule,
|
||||
XFrameworkIdentitySdkModule,
|
||||
ServiceWorkerModule.register('ngsw-worker.js', {
|
||||
enabled: environment.production,
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
//
|
||||
// Ionic Routing ...
|
||||
{
|
||||
provide: RouteReuseStrategy,
|
||||
useClass: IonicRouteStrategy,
|
||||
},
|
||||
//
|
||||
// Manager Service ...
|
||||
XManagerService,
|
||||
//
|
||||
// Provide Guards ...
|
||||
AuthGuard,
|
||||
UserGuard,
|
||||
AdminGuard,
|
||||
AgentGuard,
|
||||
NotAuthGuard,
|
||||
AdminOrAgentGuard,
|
||||
XCanDeactivateGuard,
|
||||
//
|
||||
//#region Configs ...
|
||||
{
|
||||
provide: X_FRAMEWORK_CORE_CONFIG,
|
||||
useValue: XCONFIG,
|
||||
},
|
||||
{
|
||||
provide: X_FRAMEWORK_SERVICES_CONFIG,
|
||||
useValue: XCONFIG,
|
||||
},
|
||||
{
|
||||
provide: X_FRAMEWORK_COMPONENTS_CONFIG,
|
||||
useValue: XCONFIG,
|
||||
},
|
||||
{
|
||||
provide: X_FRAMEWORK_IDENTITY_SDK_CONFIG,
|
||||
useValue: XCONFIG,
|
||||
},
|
||||
{
|
||||
provide: X_FRAMEWORK_PUSH_SERVICE_CONFIG,
|
||||
useValue: XCONFIG,
|
||||
},
|
||||
{
|
||||
provide: X_MABSUT_API_SDK_CONFIG,
|
||||
useValue: XCONFIG,
|
||||
},
|
||||
{
|
||||
provide: X_API_CONFIG,
|
||||
useValue: XAPI_CONFIG,
|
||||
},
|
||||
{
|
||||
provide: X_CONFIG,
|
||||
useValue: XCONFIG,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Push ...
|
||||
{
|
||||
provide: X_FRAMEWORK_PUSH_SERVICE_TOKEN_FETCHER,
|
||||
useClass: XPushTokenFetcherService,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Register Http Interceptor ...
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: ApiHttpInterceptorService,
|
||||
multi: true,
|
||||
},
|
||||
//#endregion
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule { }
|
||||
@@ -0,0 +1,209 @@
|
||||
import {
|
||||
DefaultLocale,
|
||||
AppResourceIDs,
|
||||
AvailableTranslationResources,
|
||||
} from './localization.config';
|
||||
import {
|
||||
RegistrationStep,
|
||||
XFrameworkIdentitySDKConfig,
|
||||
} from 'x-framework-identity-sdk';
|
||||
import { Pages } from './page.config';
|
||||
import { LogLevel } from '@microsoft/signalr';
|
||||
import { XMabsutApiSDKConfig } from 'x-mabsut-api-sdk';
|
||||
import { NotificationAudioSources } from './audio.config';
|
||||
import { XFrameworkCoreConfig, XPage } from 'x-framework-core';
|
||||
import { XFrameworkServicesConfig } from 'x-framework-services';
|
||||
import { XFrameworkComponentsConfig } from 'x-framework-components';
|
||||
import { XFrameworkPushServiceConfig } from 'x-framework-push-service';
|
||||
|
||||
// tslint:disable-next-line:no-empty-interface
|
||||
export interface AppConfig {
|
||||
//
|
||||
defaultLandingPage?: XPage;
|
||||
defaultBlogPage?: XPage;
|
||||
forceLogin: boolean;
|
||||
|
||||
//
|
||||
refreshTokensDelay?: number;
|
||||
|
||||
//
|
||||
// Content Configurations ...
|
||||
seeMoreResourceId: string;
|
||||
}
|
||||
|
||||
export type XFrameworkCoreSharedConfig = Partial<XFrameworkCoreConfig>;
|
||||
export type XFrameworkServicesSharedConfig = Partial<XFrameworkServicesConfig>;
|
||||
export type XFrameworkComponentsSharedConfig =
|
||||
Partial<XFrameworkComponentsConfig>;
|
||||
export type XFrameworkIdentitySDKSharedConfig =
|
||||
Partial<XFrameworkIdentitySDKConfig>;
|
||||
export type XFrameworkPushServiceSharedConfig =
|
||||
Partial<XFrameworkPushServiceConfig>;
|
||||
export type XMabsutApiSDKSharedConfig = Partial<XMabsutApiSDKConfig>;
|
||||
export type XAppSharedConfig = Partial<AppConfig>;
|
||||
|
||||
export type XConfig = XFrameworkCoreConfig &
|
||||
XFrameworkServicesConfig &
|
||||
XFrameworkComponentsConfig &
|
||||
XFrameworkIdentitySDKConfig &
|
||||
XFrameworkPushServiceConfig &
|
||||
XMabsutApiSDKConfig &
|
||||
AppConfig;
|
||||
export type XSharedConfig = Partial<XConfig>;
|
||||
|
||||
export const xFrameworkCoreSharedConfig: XFrameworkCoreSharedConfig = {
|
||||
appInstanceName: 'xMabsutClient',
|
||||
appNameResource: 'app_name',
|
||||
appCompanyResource: 'company',
|
||||
appVersion: 'v1.1',
|
||||
defaultNotificationDelay: 2000,
|
||||
notificationAudioSources: NotificationAudioSources,
|
||||
availableLanguages: AvailableTranslationResources,
|
||||
defaultLanguage: DefaultLocale,
|
||||
minAllowedImageSize: 512,
|
||||
maxAllowedImageSize: 5242880,
|
||||
minAllowedImageCroppableSize: 512,
|
||||
allowedImageExtensions: ['.png', '.jpg', '.jpeg'],
|
||||
maxProfileImageSize: 5242880,
|
||||
maxProfileImagesUploadFiles: 10,
|
||||
defaultCountryCode: 'IR',
|
||||
defaultPageSize: 5,
|
||||
pageSizes: [5, 10, 20, 40, 50, 100, 200],
|
||||
defaultActionDelay: 500,
|
||||
poweredValue: 'SaherElmITCenter',
|
||||
secretKey: 'SaherElm@09121694056@Hadi_Khazaee_Asl@yahoo.com',
|
||||
};
|
||||
|
||||
export const xFrameworkServicesSharedConfig: XFrameworkServicesSharedConfig = {
|
||||
geoLocationConfig: {
|
||||
enableHighAccuracy: true,
|
||||
timeout: 5000,
|
||||
},
|
||||
};
|
||||
|
||||
export const xFrameworkComponentsSharedConfig: XFrameworkComponentsSharedConfig =
|
||||
{
|
||||
minAllowedFileSize: 512,
|
||||
maxAllowedFileSize: 20971520,
|
||||
maxAllowedSize: 966367641,
|
||||
maxUploadFiles: 10,
|
||||
defaultSearchDebounceTime: 500,
|
||||
};
|
||||
|
||||
export const xFrameworkIdentitySDKSharedConfig: XFrameworkIdentitySDKSharedConfig =
|
||||
{
|
||||
//
|
||||
// Pages,
|
||||
Pages,
|
||||
|
||||
//
|
||||
minAvailableDateConst: 100 * 365 * 24 * 60 * 60 * 1000,
|
||||
maxAvailableDateConst: 18 * 365 * 24 * 60 * 60 * 1000,
|
||||
|
||||
//
|
||||
// Registration Type ...
|
||||
registrationType: [
|
||||
RegistrationStep.Terms,
|
||||
RegistrationStep.Info,
|
||||
RegistrationStep.Avatar,
|
||||
RegistrationStep.EmailConfirmation,
|
||||
RegistrationStep.Finish,
|
||||
],
|
||||
|
||||
//
|
||||
debounceTime: 500,
|
||||
|
||||
//
|
||||
nameMinLength: 3,
|
||||
nameMaxLength: 20,
|
||||
|
||||
//
|
||||
registrationOnlyWithInvitation: false,
|
||||
|
||||
//
|
||||
userNameMinLength: 4,
|
||||
userNameMaxLength: 20,
|
||||
|
||||
//
|
||||
passwordPolicies: {
|
||||
requireDigit: true,
|
||||
requiredLength: 6,
|
||||
requiredUniqueChars: 1,
|
||||
requireLowercase: true,
|
||||
requireNonAlphanumeric: true,
|
||||
requireUppercase: true,
|
||||
},
|
||||
|
||||
//
|
||||
passwordMinLength: 6,
|
||||
passwordMaxLength: 20,
|
||||
|
||||
//
|
||||
verificationCodeLength: 6,
|
||||
delayBetweenTwoVerificationCode: 180,
|
||||
};
|
||||
|
||||
export const xFrameworkPushServiceSharedConfig: XFrameworkPushServiceSharedConfig =
|
||||
{
|
||||
//
|
||||
// Push Notifications ...
|
||||
hubsBaseRoute: 'hubs',
|
||||
pushConnectionMaxRetry: 10,
|
||||
addSupportMessageProtocol: false,
|
||||
connectionLogLevel: LogLevel.None,
|
||||
pushConnectionReconnectDelay: 30000,
|
||||
|
||||
//
|
||||
// Stun Servers ...
|
||||
iceServers: [
|
||||
{
|
||||
urls: [
|
||||
'stun:stun.l.google.com:19302',
|
||||
'stun:stun1.l.google.com:19302',
|
||||
'stun:stun2.l.google.com:19302',
|
||||
],
|
||||
},
|
||||
{
|
||||
urls: ['turn:turn.saherelmhub.ir:3478'],
|
||||
username: 'saherelm',
|
||||
credential: 's@H@1694056',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export const xMabsutApiSDKSharedConfig: XMabsutApiSDKSharedConfig = {
|
||||
//
|
||||
// Configure API ...
|
||||
apiIdentifier: 'api',
|
||||
apiVersion: 'v1.0',
|
||||
|
||||
//
|
||||
// Push Notifications ...
|
||||
pushManagerReconnectDelay: 20000,
|
||||
pushServiceRoute: 'push',
|
||||
pushMessageAction: 'PushMessageAsync',
|
||||
};
|
||||
|
||||
export const xAppSharedConfig: XAppSharedConfig = {
|
||||
//
|
||||
defaultLandingPage: Pages.Landing,
|
||||
forceLogin: false,
|
||||
|
||||
//
|
||||
// Refresh Tokens in MilliSeconds ...
|
||||
refreshTokensDelay: 1 * 15 * 1000,
|
||||
|
||||
//
|
||||
// Contents Configurations ...
|
||||
seeMoreResourceId: AppResourceIDs.see_more,
|
||||
};
|
||||
|
||||
export const xSharedConfig: XSharedConfig = {
|
||||
...xFrameworkCoreSharedConfig,
|
||||
...xFrameworkServicesSharedConfig,
|
||||
...xFrameworkComponentsSharedConfig,
|
||||
...xFrameworkIdentitySDKSharedConfig,
|
||||
...xFrameworkPushServiceSharedConfig,
|
||||
...xMabsutApiSDKSharedConfig,
|
||||
...xAppSharedConfig,
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
import { XNotificationSound, XActionType } from 'x-framework-core';
|
||||
|
||||
export const NotificationAudioSources: XNotificationSound[] = [
|
||||
{
|
||||
type: XActionType.User,
|
||||
resourcePath: './assets/audio/user_notification.wav',
|
||||
},
|
||||
{
|
||||
type: XActionType.System,
|
||||
resourcePath: './assets/audio/system_notification.wav',
|
||||
},
|
||||
{
|
||||
type: XActionType.Capture,
|
||||
resourcePath: './assets/audio/capture_notification.wav',
|
||||
},
|
||||
];
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,483 @@
|
||||
import {
|
||||
XUserRoleInfo,
|
||||
XAvailableRoles,
|
||||
getTopRoleByRoleInfo,
|
||||
} from 'x-mabsut-api-sdk';
|
||||
import {
|
||||
XIconNames,
|
||||
XNavigatorListItem,
|
||||
toNavigatiorListItem,
|
||||
} from 'x-framework-components';
|
||||
import { AppResourceIDs } from './localization.config';
|
||||
import { TagRoutes, Tags } from '../views/tags/v-tag.configs';
|
||||
import { toArray, XPage, XResourceIDs } from 'x-framework-core';
|
||||
import { FileRoutes, Files } from '../views/files/v-file.configs';
|
||||
import { XSimplePage } from '../views/typings/simple.page.typings';
|
||||
import { Account, AccountRoutes } from '../views/account/account.configs';
|
||||
import { WebinarRoutes, Webinars } from '../views/webinar/v-webinar.configs';
|
||||
|
||||
//
|
||||
//#region Route Config ...
|
||||
export enum BaseRoutes {
|
||||
Default = '',
|
||||
Unknown = '**',
|
||||
}
|
||||
|
||||
export enum StartupRoutes {
|
||||
Default = 'startup',
|
||||
}
|
||||
|
||||
export enum LandingRoutes {
|
||||
Default = '#',
|
||||
}
|
||||
|
||||
export enum NotAuthorizedRoutes {
|
||||
Default = 'not-authorized',
|
||||
}
|
||||
|
||||
export enum ErrorRoutes {
|
||||
Default = 'error',
|
||||
}
|
||||
|
||||
export enum HomeRoutes {
|
||||
Default = 'home',
|
||||
}
|
||||
|
||||
export enum AppRoutes {
|
||||
Default = BaseRoutes.Default,
|
||||
Startup = StartupRoutes.Default,
|
||||
Landing = LandingRoutes.Default,
|
||||
Home = HomeRoutes.Default,
|
||||
Webinars = WebinarRoutes.Default,
|
||||
Tags = TagRoutes.Default,
|
||||
Files = FileRoutes.Default,
|
||||
Account = AccountRoutes.Default,
|
||||
NotAuthorized = NotAuthorizedRoutes.Default,
|
||||
Error = ErrorRoutes.Default,
|
||||
Unknown = BaseRoutes.Unknown,
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Page Configs ...
|
||||
export enum PageName {
|
||||
//
|
||||
//#region Startup ...
|
||||
Startup = AppRoutes.Startup,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Landing ...
|
||||
Landing = AppRoutes.Landing,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Home ...
|
||||
Home = AppRoutes.Home,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Webinar ...
|
||||
Webinars = AppRoutes.Webinars,
|
||||
WebinarsExplorer = WebinarRoutes.WebinarsExplorer,
|
||||
WebinarsManagement = WebinarRoutes.WebinarsManagement,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Tag ...
|
||||
Tags = AppRoutes.Tags,
|
||||
TagsExplorer = TagRoutes.TagsExplorer,
|
||||
TagsManagement = TagRoutes.TagsManagement,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region File ...
|
||||
Files = AppRoutes.Files,
|
||||
FilesExplorer = FileRoutes.FilesExplorer,
|
||||
FilesManagement = FileRoutes.FilesManagement,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Account ...
|
||||
Account = AppRoutes.Account,
|
||||
Login = AccountRoutes.Login,
|
||||
Logout = AccountRoutes.Logout,
|
||||
Profile = AccountRoutes.Profile,
|
||||
Register = AccountRoutes.Register,
|
||||
EmailConfirm = AccountRoutes.EmailConfirm,
|
||||
PhoneConfirm = AccountRoutes.PhoneConfirm,
|
||||
ResetPassword = AccountRoutes.ResetPassword,
|
||||
ChangePassword = AccountRoutes.ChangePassword,
|
||||
SearchProfiles = AccountRoutes.SearchProfiles,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region NotAuthorized ...
|
||||
NotAuthorized = AppRoutes.NotAuthorized,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Error ...
|
||||
Error = AppRoutes.Error,
|
||||
//#endregion
|
||||
}
|
||||
|
||||
export type PageNames = keyof typeof PageName;
|
||||
|
||||
export type PageNameIdentifier = PageName | PageNames | string;
|
||||
|
||||
export type PageIndexType = {
|
||||
[key in PageNames]?: XPage | XSimplePage;
|
||||
};
|
||||
|
||||
export const PageIndex: PageIndexType = {
|
||||
//
|
||||
//#region Startup ...
|
||||
Startup: {
|
||||
id: `${PageName.Startup}`,
|
||||
name: `${PageName.Startup}`,
|
||||
title: AppResourceIDs.startup_page_title,
|
||||
description: AppResourceIDs.startup_page_description,
|
||||
baseRoute: `${AppRoutes.Startup}`,
|
||||
route: ['/', `${AppRoutes.Startup}`],
|
||||
icon: XIconNames.friendship_unknown,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Landing ...
|
||||
Landing: {
|
||||
id: `${PageName.Landing}`,
|
||||
name: `${PageName.Landing}`,
|
||||
title: XResourceIDs.app_name,
|
||||
description: XResourceIDs.company,
|
||||
baseRoute: `${AppRoutes.Landing}`,
|
||||
route: ['/', `${AppRoutes.Landing}`],
|
||||
icon: XIconNames.posts,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Home ...
|
||||
Home: {
|
||||
icon: XIconNames.home,
|
||||
id: `${PageName.Home}`,
|
||||
name: `${PageName.Home}`,
|
||||
baseRoute: `${AppRoutes.Home}`,
|
||||
route: ['/', `${AppRoutes.Home}`],
|
||||
title: AppResourceIDs.home_page_title,
|
||||
description: AppResourceIDs.home_page_description,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Webinars ...
|
||||
Webinars: {
|
||||
...Webinars,
|
||||
},
|
||||
|
||||
//
|
||||
// Tags ...
|
||||
Tags: {
|
||||
...Tags,
|
||||
},
|
||||
|
||||
//
|
||||
// Files ...
|
||||
Files: {
|
||||
...Files,
|
||||
},
|
||||
|
||||
//
|
||||
// Account ...
|
||||
Account: {
|
||||
...Account,
|
||||
},
|
||||
|
||||
//
|
||||
//#region Error Page ...
|
||||
Error: {
|
||||
id: `${PageName.Error}`,
|
||||
name: `${PageName.Error}`,
|
||||
title: AppResourceIDs.error_page_title,
|
||||
description: AppResourceIDs.error_page_description,
|
||||
baseRoute: `${AppRoutes.Error}`,
|
||||
route: ['/', `${AppRoutes.Error}`],
|
||||
icon: XIconNames.error,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Not Authorized Page ...
|
||||
NotAuthorized: {
|
||||
id: `${PageName.NotAuthorized}`,
|
||||
name: `${PageName.NotAuthorized}`,
|
||||
title: AppResourceIDs.not_authorized_page_title,
|
||||
description: AppResourceIDs.not_authorized_page_description,
|
||||
baseRoute: `${AppRoutes.NotAuthorized}`,
|
||||
route: ['/', `${AppRoutes.NotAuthorized}`],
|
||||
icon: XIconNames.friendship_block,
|
||||
},
|
||||
//#endregion
|
||||
};
|
||||
|
||||
//
|
||||
// a Const of Available Pages ...
|
||||
const accountChilds = toArray(PageIndex.Account.childs);
|
||||
export const Pages: any = {
|
||||
//
|
||||
//#region Startup ...
|
||||
Startup: PageIndex.Startup,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Landing ...
|
||||
Landing: PageIndex.Landing,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Home ...
|
||||
Home: PageIndex.Home,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Webinars ...
|
||||
Webinars: PageIndex.Webinars,
|
||||
WebinarsExplorer: Webinars.childs[1],
|
||||
WebinarsManagement: Webinars.childs[0],
|
||||
|
||||
//
|
||||
// Tags ...
|
||||
Tags: PageIndex.Tags,
|
||||
TagsExplorer: Tags.childs[1],
|
||||
TagsManagement: Tags.childs[0],
|
||||
|
||||
//
|
||||
// Files ...
|
||||
Files: PageIndex.Files,
|
||||
FilesExplorer: Files.childs[1],
|
||||
FilesManagement: Files.childs[0],
|
||||
|
||||
//
|
||||
//#region Account ...
|
||||
Account: PageIndex.Account,
|
||||
Login: Account.childs[0],
|
||||
Logout: Account.childs[1],
|
||||
Profile: Account.childs[2],
|
||||
Register: Account.childs[3],
|
||||
EmailConfirm: Account.childs[4],
|
||||
PhoneConfirm: Account.childs[5],
|
||||
ResetPassword: Account.childs[6],
|
||||
ChangePassword: Account.childs[7],
|
||||
SearchProfiles: Account.childs[8],
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Error ...
|
||||
Error: PageIndex.Error,
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Notuthorized ...
|
||||
NotAuthorized: PageIndex.NotAuthorized,
|
||||
//#endregion
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Navigator Pages ...
|
||||
//
|
||||
//#region Navigation Items ...
|
||||
//
|
||||
// Admin Naigator Pages ...
|
||||
const AdminNavPageItems: XNavigatorListItem[] = [
|
||||
//
|
||||
// Home ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Home),
|
||||
},
|
||||
|
||||
//
|
||||
// Webinars ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Webinars),
|
||||
},
|
||||
|
||||
//
|
||||
// Tags ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Tags),
|
||||
},
|
||||
|
||||
//
|
||||
// Files ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Files),
|
||||
},
|
||||
|
||||
//
|
||||
// Account ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Account),
|
||||
childs: [
|
||||
//
|
||||
// Profile ...
|
||||
{ ...toNavigatiorListItem(Pages.Profile) },
|
||||
//
|
||||
// Change Password ...
|
||||
{ ...toNavigatiorListItem(Pages.ChangePassword) },
|
||||
//
|
||||
// Search Profiles ...
|
||||
{ ...toNavigatiorListItem(Pages.SearchProfiles) },
|
||||
],
|
||||
href: '',
|
||||
},
|
||||
|
||||
//
|
||||
// Logout ...
|
||||
{
|
||||
...toNavigatiorListItem(Pages.Logout),
|
||||
href: '',
|
||||
},
|
||||
];
|
||||
|
||||
//
|
||||
// Agent Navigator Pages ...
|
||||
const AgentNavPageItems: XNavigatorListItem[] = [
|
||||
//
|
||||
// Home ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Home),
|
||||
},
|
||||
|
||||
//
|
||||
// Webinars ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Webinars),
|
||||
},
|
||||
|
||||
//
|
||||
// Account ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Account),
|
||||
childs: [
|
||||
//
|
||||
// Profile ...
|
||||
{ ...toNavigatiorListItem(Pages.Profile) },
|
||||
//
|
||||
// Change Password ...
|
||||
{ ...toNavigatiorListItem(Pages.ChangePassword) },
|
||||
//
|
||||
// Search Profiles ...
|
||||
{ ...toNavigatiorListItem(Pages.SearchProfiles) },
|
||||
],
|
||||
href: '',
|
||||
},
|
||||
|
||||
//
|
||||
// Logout ...
|
||||
{
|
||||
...toNavigatiorListItem(Pages.Logout),
|
||||
href: '',
|
||||
},
|
||||
];
|
||||
|
||||
//
|
||||
// Users Navigator Pages ...
|
||||
const UserNavPageItems: XNavigatorListItem[] = [
|
||||
//
|
||||
// Home ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Home),
|
||||
},
|
||||
|
||||
//
|
||||
// Webinars ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Webinars),
|
||||
childs: [
|
||||
//
|
||||
// Webinars Explorer ...
|
||||
{ ...toNavigatiorListItem(Pages.WebinarsExplorer) },
|
||||
],
|
||||
},
|
||||
|
||||
//
|
||||
// Account ...
|
||||
{
|
||||
...toNavigatiorListItem(PageIndex.Account),
|
||||
childs: [
|
||||
//
|
||||
// Profile ...
|
||||
{ ...toNavigatiorListItem(Pages.Profile) },
|
||||
//
|
||||
// Change Password ...
|
||||
{ ...toNavigatiorListItem(Pages.ChangePassword) },
|
||||
//
|
||||
// Search Profiles ...
|
||||
{ ...toNavigatiorListItem(Pages.SearchProfiles) },
|
||||
],
|
||||
},
|
||||
|
||||
//
|
||||
// Logout ...
|
||||
{
|
||||
...toNavigatiorListItem(Pages.Logout),
|
||||
href: '',
|
||||
},
|
||||
];
|
||||
|
||||
//
|
||||
// Guest ...
|
||||
const GuestNavPageItems: XNavigatorListItem[] = [
|
||||
//
|
||||
// Register ...
|
||||
{
|
||||
...toNavigatiorListItem(Pages.Register),
|
||||
// href: '',
|
||||
},
|
||||
//
|
||||
// Login ...
|
||||
{
|
||||
...toNavigatiorListItem(Pages.Login),
|
||||
// href: '',
|
||||
},
|
||||
];
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Navigator Pages Provider ...
|
||||
export async function getNavPages(
|
||||
roleInfo: XUserRoleInfo
|
||||
): Promise<XNavigatorListItem[]> {
|
||||
//
|
||||
if (!roleInfo) {
|
||||
//
|
||||
// Guest Users ...
|
||||
return GuestNavPageItems;
|
||||
}
|
||||
|
||||
//
|
||||
// TODO: Fix these ...
|
||||
const topRole = getTopRoleByRoleInfo(roleInfo);
|
||||
switch (topRole) {
|
||||
//
|
||||
case XAvailableRoles.Admin:
|
||||
return AdminNavPageItems;
|
||||
|
||||
//
|
||||
case XAvailableRoles.Agent:
|
||||
return AgentNavPageItems;
|
||||
|
||||
//
|
||||
// TODO: Fix this ...
|
||||
case XAvailableRoles.User:
|
||||
return UserNavPageItems;
|
||||
|
||||
//
|
||||
default:
|
||||
return GuestNavPageItems;
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
//#endregion
|
||||
@@ -0,0 +1,13 @@
|
||||
import { XCONFIG } from './x.config';
|
||||
import { XApiConfiguration } from 'x-framework-identity-sdk';
|
||||
|
||||
/**
|
||||
* Api Configuration
|
||||
*/
|
||||
export const XAPI_CONFIG = new XApiConfiguration({
|
||||
//
|
||||
baseApiPath: XCONFIG.baseUrl,
|
||||
apiVersion: XCONFIG.apiVersion,
|
||||
poweredByValue: XCONFIG.poweredValue,
|
||||
revisionSecretKey: XCONFIG.secretKey,
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
import { XConfig } from './app.config';
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
export const XCONFIG: XConfig = JSON.parse(
|
||||
JSON.stringify(environment.configurations)
|
||||
);
|
||||
|
||||
export const X_CONFIG = new InjectionToken<XConfig>('x_config');
|
||||
@@ -0,0 +1,134 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { AdminGuard } from 'x-mabsut-api-sdk';
|
||||
import { LoginPage } from './login/login.page';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { LogoutPage } from './logout/logout.page';
|
||||
import { ProfilePage } from './profile/profile.page';
|
||||
import { XCanDeactivateGuard } from 'x-framework-core';
|
||||
import { ViewsModule } from 'src/app/views/public-api';
|
||||
import { RegisterPage } from './register/register.page';
|
||||
import { BaseRoutes } from 'src/app/config/page.config';
|
||||
import { AuthGuard, NotAuthGuard } from 'x-framework-identity-sdk';
|
||||
import { AccountRoutes } from 'src/app/views/account/account.configs';
|
||||
import { EmailConfirmPage } from './email-confirm/email-confirm.page';
|
||||
import { PhoneConfirmPage } from './phone-confirm/phone-confirm.page';
|
||||
import { ResetPasswordPage } from './reset-password/reset-password.page';
|
||||
import { ChangePasswordPage } from './change-password/change-password.page';
|
||||
import { SearchProfilesPage } from './search-profiles/search-profiles.page';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
LoginPage,
|
||||
LogoutPage,
|
||||
ProfilePage,
|
||||
RegisterPage,
|
||||
PhoneConfirmPage,
|
||||
EmailConfirmPage,
|
||||
ResetPasswordPage,
|
||||
ChangePasswordPage,
|
||||
SearchProfilesPage,
|
||||
],
|
||||
imports: [
|
||||
ViewsModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: BaseRoutes.Default,
|
||||
redirectTo: AccountRoutes.Profile,
|
||||
pathMatch: 'full',
|
||||
},
|
||||
//
|
||||
// Login ...
|
||||
{
|
||||
path: AccountRoutes.Login,
|
||||
component: LoginPage,
|
||||
canActivate: [NotAuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Logout ...
|
||||
{
|
||||
path: AccountRoutes.Logout,
|
||||
component: LogoutPage,
|
||||
canActivate: [AuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Profile ...
|
||||
{
|
||||
path: AccountRoutes.Profile,
|
||||
component: ProfilePage,
|
||||
canActivate: [AuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Register ...
|
||||
{
|
||||
path: AccountRoutes.Register,
|
||||
component: RegisterPage,
|
||||
canActivate: [NotAuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Email Confirm ...
|
||||
{
|
||||
path: AccountRoutes.EmailConfirm,
|
||||
component: EmailConfirmPage,
|
||||
canActivate: [NotAuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Phone Confirm ...
|
||||
{
|
||||
path: AccountRoutes.PhoneConfirm,
|
||||
component: PhoneConfirmPage,
|
||||
canActivate: [NotAuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Reset Password ...
|
||||
{
|
||||
path: AccountRoutes.ResetPassword,
|
||||
component: ResetPasswordPage,
|
||||
canActivate: [NotAuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Change Password ...
|
||||
{
|
||||
path: AccountRoutes.ChangePassword,
|
||||
component: ChangePasswordPage,
|
||||
canActivate: [AuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
//
|
||||
// Search Profiles ...
|
||||
{
|
||||
path: AccountRoutes.SearchProfiles,
|
||||
component: SearchProfilesPage,
|
||||
canActivate: [AuthGuard],
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
},
|
||||
{
|
||||
path: BaseRoutes.Unknown,
|
||||
pathMatch: 'full',
|
||||
redirectTo: AccountRoutes.Default,
|
||||
},
|
||||
]),
|
||||
],
|
||||
exports: [
|
||||
//
|
||||
ViewsModule,
|
||||
RouterModule,
|
||||
//
|
||||
LoginPage,
|
||||
LogoutPage,
|
||||
ProfilePage,
|
||||
RegisterPage,
|
||||
PhoneConfirmPage,
|
||||
EmailConfirmPage,
|
||||
ResetPasswordPage,
|
||||
ChangePasswordPage,
|
||||
SearchProfilesPage,
|
||||
],
|
||||
})
|
||||
export class AccountPageModule {}
|
||||
@@ -0,0 +1,5 @@
|
||||
export const LoginTasks = {
|
||||
Login: 'login',
|
||||
RequestResetPassword: 'request_reset_password',
|
||||
ResendEmailVerificationLink: 'resend_email_verification_link',
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate> Change Password ... </ng-template>
|
||||
@@ -0,0 +1,20 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-change-password',
|
||||
templateUrl: './change-password.page.html',
|
||||
styleUrls: ['./change-password.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ChangePasswordPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = true;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.change_password_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate> Email Confirm ... </ng-template>
|
||||
@@ -0,0 +1,27 @@
|
||||
import { XSideType } from 'x-framework-components';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-email-confirm',
|
||||
templateUrl: './email-confirm.page.html',
|
||||
styleUrls: ['./email-confirm.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class EmailConfirmPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = true;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.email_confirm_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
/**
|
||||
* use this for Menu always Visible ...
|
||||
*/
|
||||
toggleMenuWhen = '';
|
||||
sideType = XSideType.Overlay;
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
<v-login
|
||||
[model]="model"
|
||||
[loading]="loading"
|
||||
(login)="handleLogin()"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
(lockNotifier)="handleLockStateChanged($event)"
|
||||
(changeNotifier)="handleModelStateChange($event)"
|
||||
></v-login>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,350 @@
|
||||
import {
|
||||
XTask,
|
||||
XParam,
|
||||
getTaskName,
|
||||
isNullOrUndefined,
|
||||
} from 'x-framework-core';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { LoginTasks } from '../account.typings';
|
||||
import { Pages } from 'src/app/config/page.config';
|
||||
import { XSideType } from 'x-framework-components';
|
||||
import { XLoginRequestDto } from 'x-framework-identity-sdk';
|
||||
import { VModelState } from 'src/app/views/v-dto/v-dto.typings';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
templateUrl: './login.page.html',
|
||||
styleUrls: ['./login.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line:component-class-suffix
|
||||
export class LoginPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
//
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = true;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.login_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
/**
|
||||
* use this for Menu always Visible ...
|
||||
*/
|
||||
toggleMenuWhen = '';
|
||||
sideType = XSideType.Overlay;
|
||||
|
||||
//
|
||||
showEmailConfirm = false;
|
||||
showResetPassword = false;
|
||||
|
||||
//
|
||||
model: XLoginRequestDto = {
|
||||
userSelectBy: '',
|
||||
password: '',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Register Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Task Handlers ...
|
||||
async onTaskStart(name: string, task: XTask<any>) {
|
||||
super.onTaskStart(name, task);
|
||||
|
||||
//
|
||||
// Prevent Moving Forward ...
|
||||
if (!this.isPageTask(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Loading State ...
|
||||
await this.setLoadingState(true);
|
||||
|
||||
//
|
||||
// Handle Flags for Confirm Email and Reset Password ...
|
||||
// TODO: Complete this ...
|
||||
|
||||
//
|
||||
if (name === LoginTasks.ResendEmailVerificationLink) {
|
||||
this.showEmailConfirm = false;
|
||||
}
|
||||
|
||||
//
|
||||
if (name === LoginTasks.RequestResetPassword) {
|
||||
this.showResetPassword = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Apply Changes ...
|
||||
this.detectChanges();
|
||||
}
|
||||
|
||||
async onTaskFinished(name: string, task: XTask<any>) {
|
||||
super.onTaskFinished(name, task);
|
||||
|
||||
//
|
||||
// Prevent Moving Forward ...
|
||||
if (!this.isPageTask(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Loading State ...
|
||||
await this.setLoadingState(false);
|
||||
|
||||
//
|
||||
// Handle User Authenticated ...
|
||||
if (name === LoginTasks.Login) {
|
||||
this.handleUserAuthenticated();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// If Email Verification is Passed ...
|
||||
if (
|
||||
name === LoginTasks.ResendEmailVerificationLink ||
|
||||
name === LoginTasks.RequestResetPassword
|
||||
) {
|
||||
//
|
||||
await this.managerService.notificationService.presentSuccessNotification({
|
||||
message: this.resourceProvider(this.AppResourceIDs.check_mail),
|
||||
dissmissable: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async onTaskFailed(name: string, task: XTask<any>) {
|
||||
super.onTaskFailed(name, task);
|
||||
|
||||
//
|
||||
// Prevent Moving Forward ...
|
||||
if (!this.isPageTask(name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Loading State ...
|
||||
await this.setLoadingState(false);
|
||||
|
||||
//
|
||||
// Retrieve Exception ...
|
||||
const exception = task.error;
|
||||
await this.handleErrorState(exception, true);
|
||||
|
||||
//
|
||||
// Handle Email Verification Error ...
|
||||
if (task.name === LoginTasks.ResendEmailVerificationLink) {
|
||||
//
|
||||
this.uiDisabled = true;
|
||||
this.showEmailConfirm = true;
|
||||
|
||||
//
|
||||
this.detectChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle Request Reset Password Error ...
|
||||
if (task.name === LoginTasks.RequestResetPassword) {
|
||||
//
|
||||
this.uiDisabled = true;
|
||||
this.showResetPassword = true;
|
||||
|
||||
//
|
||||
this.detectChanges();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle Other Errors ...
|
||||
switch (exception.id) {
|
||||
//
|
||||
// Email Not Confirmed ...
|
||||
case 135:
|
||||
//
|
||||
this.uiDisabled = true;
|
||||
this.showEmailConfirm = true;
|
||||
break;
|
||||
|
||||
//
|
||||
// User Disabled ...
|
||||
case 117:
|
||||
//
|
||||
this.uiDisabled = true;
|
||||
this.showEmailConfirm = true;
|
||||
break;
|
||||
//
|
||||
// Login Failed (Username is Ok ... Password Mistmatch ...) ...
|
||||
case 106:
|
||||
//
|
||||
this.uiDisabled = true;
|
||||
this.showResetPassword = true;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Apply Changes ...
|
||||
this.detectChanges();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Providers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Handlers ...
|
||||
/**
|
||||
* Handle Login ...
|
||||
*/
|
||||
async handleLogin() {
|
||||
//
|
||||
// Prevent Moving Forward when Context is Busy ...
|
||||
if (this.loading || this.uiDisabled || isNullOrUndefined(this.model)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (this.lock) {
|
||||
this.lock = false;
|
||||
}
|
||||
|
||||
//
|
||||
// Prepare User Select By ...
|
||||
const model = {
|
||||
...this.model,
|
||||
userSelectBy: this.model.userSelectBy.toLowerCase(),
|
||||
};
|
||||
|
||||
//
|
||||
// Prepare Task Requirements ...
|
||||
const mTaskName = LoginTasks.Login;
|
||||
const mTask = this.sharedService.authService.login(model);
|
||||
|
||||
//
|
||||
// Add or Update Task to Queue ...
|
||||
await this.addOrUpdateTask({
|
||||
name: mTaskName,
|
||||
priority: 0,
|
||||
affectLoading: true,
|
||||
task: mTask,
|
||||
});
|
||||
|
||||
//
|
||||
// Dispatch Task ...
|
||||
await this.dispatchTask(mTaskName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Model ...
|
||||
*
|
||||
* @param state
|
||||
*/
|
||||
async handleModelStateChange(state: VModelState<XLoginRequestDto>) {
|
||||
//
|
||||
// Update Model Fields ...
|
||||
this.model.device = state.model.device;
|
||||
this.model.language = state.model.language;
|
||||
this.model.password = state.model.password;
|
||||
this.model.userSelectBy = state.model.userSelectBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handling Lock State ...
|
||||
*
|
||||
* @param event
|
||||
* @returns
|
||||
*/
|
||||
handleLockStateChanged(event: { id: string; state: boolean }) {
|
||||
//
|
||||
if (isNullOrUndefined(event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
this.lock = event.state;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private Actions ...
|
||||
//
|
||||
//#region Task Providers ...
|
||||
private getTaskNames() {
|
||||
return [
|
||||
//
|
||||
LoginTasks.Login,
|
||||
LoginTasks.RequestResetPassword,
|
||||
LoginTasks.ResendEmailVerificationLink,
|
||||
];
|
||||
}
|
||||
|
||||
private async isPageTask(key: string | any) {
|
||||
//
|
||||
const pageTasks = this.getTaskNames();
|
||||
const mTaskKey = getTaskName(key);
|
||||
const result = pageTasks.includes(mTaskKey);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Task Handlers ...
|
||||
private handleUserAuthenticated() {
|
||||
//
|
||||
const hasAfterLoginRedirectPage = !isNullOrUndefined(
|
||||
this.config.afterLoginRedirectPage
|
||||
);
|
||||
|
||||
//
|
||||
const url = this.managerService.isContainQueryParam(XParam.ReturnUrl)
|
||||
? this.managerService.getQueryParamValOfType<string>(XParam.ReturnUrl)
|
||||
: hasAfterLoginRedirectPage
|
||||
? this.managerService.getPageRoute(this.config.afterLoginRedirectPage)
|
||||
: this.managerService.getPageRoute(Pages.Home);
|
||||
|
||||
//
|
||||
const mSubscription = this.sharedService.state$
|
||||
.asObservable()
|
||||
.pipe(filter((res) => !isNullOrUndefined(res) && res.isLoggedIn === true))
|
||||
// tslint:disable-next-line: deprecation
|
||||
.subscribe(async () => {
|
||||
//
|
||||
this.runTimedOut(async () => {
|
||||
//
|
||||
if (this.lock) {
|
||||
this.lock = false;
|
||||
}
|
||||
|
||||
//
|
||||
await this.managerService.navigateByUrlReplace(url);
|
||||
});
|
||||
|
||||
//
|
||||
mSubscription.unsubscribe();
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[containerBase]="this"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,74 @@
|
||||
import { Pages } from 'src/app/config/page.config';
|
||||
import { XSideType } from 'x-framework-components';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
const LogoutKeys = {
|
||||
LoggingOutID: 'logging_out',
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'app-logout',
|
||||
templateUrl: './logout.page.html',
|
||||
styleUrls: ['./logout.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line:component-class-suffix
|
||||
export class LogoutPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = false;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.logout_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
/**
|
||||
* use this for Menu always Visible ...
|
||||
*/
|
||||
toggleMenuWhen = '';
|
||||
sideType = XSideType.Overlay;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
async afterViewInit() {
|
||||
super.afterViewInit();
|
||||
|
||||
//
|
||||
await this.handleLogoutAction();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private Actions ...
|
||||
private async handleLogoutAction() {
|
||||
//
|
||||
await this.managerService.dialogService.presentLoading({
|
||||
id: LogoutKeys.LoggingOutID,
|
||||
message: this.resourceProvider(this.AppResourceIDs.logging_out),
|
||||
});
|
||||
|
||||
//
|
||||
this.loading = true;
|
||||
|
||||
//
|
||||
await this.sharedService.authService.logout();
|
||||
this.managerService.settingsService.restart();
|
||||
|
||||
//
|
||||
this.loading = false;
|
||||
this.managerService.dialogService.loadingController.dismiss(
|
||||
LogoutKeys.LoggingOutID
|
||||
);
|
||||
|
||||
//
|
||||
await this.managerService.navigateByPageReplace(Pages.Startup);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate> Phone Confirm ... </ng-template>
|
||||
@@ -0,0 +1,27 @@
|
||||
import { XSideType } from 'x-framework-components';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-phone-confirm',
|
||||
templateUrl: './phone-confirm.page.html',
|
||||
styleUrls: ['./phone-confirm.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class PhoneConfirmPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = true;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.phone_confirm_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
/**
|
||||
* use this for Menu always Visible ...
|
||||
*/
|
||||
toggleMenuWhen = '';
|
||||
sideType = XSideType.Overlay;
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate> Profile ... </ng-template>
|
||||
@@ -0,0 +1,20 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-profile',
|
||||
templateUrl: './profile.page.html',
|
||||
styleUrls: ['./profile.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ProfilePage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = true;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.profile_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
<!-- Register -->
|
||||
<v-register
|
||||
[isInPage]="true"
|
||||
[wrapWithCard]="true"
|
||||
[cardTitle]="AppResourceIDs.register"
|
||||
></v-register>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,62 @@
|
||||
import { XSideType } from 'x-framework-components';
|
||||
import { VPageComponent } from 'src/app/views/public-api';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-register',
|
||||
templateUrl: './register.page.html',
|
||||
styleUrls: ['./register.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line: component-class-suffix
|
||||
export class RegisterPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
titleRes = this.AppResourceIDs.register_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
/**
|
||||
* use this for Menu always Visible ...
|
||||
*/
|
||||
toggleMenuWhen = '';
|
||||
sideType = XSideType.Overlay;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Register Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Task Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Providers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate> Reset Password ... </ng-template>
|
||||
@@ -0,0 +1,27 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
import { XSideType } from 'x-framework-components';
|
||||
|
||||
@Component({
|
||||
selector: 'app-reset-password',
|
||||
templateUrl: './reset-password.page.html',
|
||||
styleUrls: ['./reset-password.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ResetPasswordPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = true;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.reset_password_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
/**
|
||||
* use this for Menu always Visible ...
|
||||
*/
|
||||
toggleMenuWhen = '';
|
||||
sideType = XSideType.Overlay;
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate> Search Profiles ... </ng-template>
|
||||
@@ -0,0 +1,20 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-search-profiles',
|
||||
templateUrl: './search-profiles.page.html',
|
||||
styleUrls: ['./search-profiles.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class SearchProfilesPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
toolbarShowSubTitle = true;
|
||||
showToolbarEndSlot = true;
|
||||
showToolbarContent = false;
|
||||
titleRes = this.AppResourceIDs.search_profiles_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[containerBase]="this"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
<v-error
|
||||
[isInPage]="true"
|
||||
[errorTitle]="''"
|
||||
[wrapWithCard]="true"
|
||||
*ngIf="hasChildValue(errors) | async"
|
||||
[errors]="getArrayValue(errors) | async"
|
||||
[cardTitle]="AppResourceIDs.error_page_title"
|
||||
>
|
||||
</v-error>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,79 @@
|
||||
import { Pages } from 'src/app/config/page.config';
|
||||
import { XButtonType } from 'x-framework-components';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
import { toArray, XOneOrManyType, XParam } from 'x-framework-core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-error',
|
||||
templateUrl: './error.page.html',
|
||||
styleUrls: ['./error.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line: component-class-suffix
|
||||
export class ErrorPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = false;
|
||||
toolbarHasBack = true;
|
||||
toolbarShowBack = true;
|
||||
showToolbarEndSlot = false;
|
||||
showToolbarContent = false;
|
||||
toolbarShowSubTitle = true;
|
||||
titleRes = this.AppResourceIDs.error_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
//
|
||||
errors: XOneOrManyType<string>;
|
||||
returnUrl = this.managerService.getPageRoute(Pages.Startup);
|
||||
|
||||
//
|
||||
toolbarBackHandler = () => {
|
||||
this.managerService.navigateByUrlReplace(this.returnUrl);
|
||||
};
|
||||
|
||||
//
|
||||
//#region Private/ReadOnly ...
|
||||
readonly ButtonTypes = Object.assign({}, XButtonType);
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycle ...
|
||||
parseParams(): void {
|
||||
super.parseParams();
|
||||
|
||||
//
|
||||
this.errors = [
|
||||
...toArray(
|
||||
this.managerService.getStateValOfType<XOneOrManyType<string>>(
|
||||
XParam.Errors
|
||||
)
|
||||
),
|
||||
];
|
||||
|
||||
//
|
||||
const isContainsReturnUrl = this.managerService.isContainState(
|
||||
XParam.ReturnUrl
|
||||
);
|
||||
if (isContainsReturnUrl) {
|
||||
this.returnUrl = this.managerService.getStateValOfType<string>(
|
||||
XParam.ReturnUrl
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
if (this.hasChild(this.errors)) {
|
||||
this.detectChanges();
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Action Handlers ...
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
#pagePresenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
(xOnEscapeGlobal)="handleGlobalEscapePressed($event)"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
<!-- Query Presenter -->
|
||||
<v-query-presenter
|
||||
[loading]="loading"
|
||||
[tabsLock]="tabsLock"
|
||||
[tabsColor]="tabsColor"
|
||||
[showEmpty]="showEmpty"
|
||||
[emptyColor]="emptyColor"
|
||||
[addTabTitle]="addTabTitle"
|
||||
[itemTemplate]="itemTemplate"
|
||||
[emptyMessage]="emptyMessage"
|
||||
[tabsCssClass]="tabsCssClass"
|
||||
[tabsLoopTabs]="tabsLoopTabs"
|
||||
[tabsSwipable]="tabsSwipable"
|
||||
[listTabTitle]="listTabTitle"
|
||||
[emptyCssClass]="emptyCssClass"
|
||||
[showPaginator]="showPaginator"
|
||||
[tabsAlignTabs]="tabsAlignTabs"
|
||||
[showSearchBar]="showSearchBar"
|
||||
[searchBarType]="searchBarType"
|
||||
[searchBarValue]="searchBarValue"
|
||||
[searchBarTitle]="searchBarTitle"
|
||||
[searchBarColor]="searchBarColor"
|
||||
[updateTabTitle]="updateTabTitle"
|
||||
[paginatorColor]="paginatorColor"
|
||||
[tabsShowHeader]="tabsShowHeader"
|
||||
[addItemTemplate]="addItemTemplate"
|
||||
[emptyHasRefresh]="emptyHasRefresh"
|
||||
[detailsTabTitle]="detailsTabTitle"
|
||||
[tabsHeaderColor]="tabsHeaderColor"
|
||||
[showItemsAsList]="showItemsAsList"
|
||||
[modelIdentifier]="modelIdentifier"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[listItemTemplate]="listItemTemplate"
|
||||
[listTabCardTitle]="listTabCardTitle"
|
||||
[listTabCardColor]="listTabCardColor"
|
||||
[emptyRefreshIcon]="emptyRefreshIcon"
|
||||
[emptyMessageColor]="emptyMessageColor"
|
||||
[paginatorPosition]="paginatorPosition"
|
||||
[tabsSelectedIndex]="tabsSelectedIndex"
|
||||
[tabsDynamicHeight]="tabsDynamicHeight"
|
||||
[tabsDisableRipple]="tabsDisableRipple"
|
||||
[searchBarDebounce]="searchBarDebounce"
|
||||
[searchBarCssClass]="searchBarCssClass"
|
||||
[updateItemTemplate]="updateItemTemplate"
|
||||
[tabsHeaderPosition]="tabsHeaderPosition"
|
||||
[tabsActiveTabColor]="tabsActiveTabColor"
|
||||
[searchBarSpellcheck]="searchBarSpellcheck"
|
||||
[detailsItemTemplate]="detailsItemTemplate"
|
||||
[wrapListTabWithCard]="wrapListTabWithCard"
|
||||
[listTabCardIsInPage]="listTabCardIsInPage"
|
||||
[listTabCardSubTitle]="listTabCardSubTitle"
|
||||
[emptyForegroundColor]="emptyForegroundColor"
|
||||
[actionProvider]="queryPresenterActionProvider"
|
||||
[tabsDisablePagination]="tabsDisablePagination"
|
||||
[tabsAnimationDuration]="tabsAnimationDuration"
|
||||
[tabsTabIndicatorColor]="tabsTabIndicatorColor"
|
||||
[tabsTabPaginatorColor]="tabsTabPaginatorColor"
|
||||
[searchBarKeyboardType]="searchBarKeyboardType"
|
||||
[searchBarEnterKeyHint]="searchBarEnterKeyHint"
|
||||
[emptyRefreshButtonColor]="emptyRefreshButtonColor"
|
||||
[searchBarForegroundColor]="searchBarForegroundColor"
|
||||
[searchBarShowClearButton]="searchBarShowClearButton"
|
||||
[searchBarClearButtonIcon]="searchBarClearButtonIcon"
|
||||
[searchBarCancelButtonIcon]="searchBarCancelButtonIcon"
|
||||
[searchBarSearchButtonIcon]="searchBarSearchButtonIcon"
|
||||
[searchBarSearchInputColor]="searchBarSearchInputColor"
|
||||
[searchBarShowCancelButton]="searchBarShowCancelButton"
|
||||
[searchBarCancelButtonTitle]="searchBarCancelButtonTitle"
|
||||
[emptyForegroundMessageColor]="emptyForegroundMessageColor"
|
||||
[searchBarClearButtonIconColor]="searchBarClearButtonIconColor"
|
||||
[searchBarCancelButtonIconColor]="searchBarCancelButtonIconColor"
|
||||
[searchBarSearchButtonIconColor]="searchBarSearchButtonIconColor"
|
||||
[emptyForegroundRefreshButtonColor]="emptyForegroundRefreshButtonColor"
|
||||
[searchBarForegroundSearchInputColor]="searchBarForegroundSearchInputColor"
|
||||
>
|
||||
</v-query-presenter>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #itemTemplate let-item="item">
|
||||
<v-file
|
||||
[model]="item"
|
||||
class="v-item"
|
||||
[loading]="loading"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[cardTitle]="getModelCardTitle(item)"
|
||||
[presentType]="BasePresentTypes.AsView"
|
||||
[actionProvider]="listItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(item) | async"
|
||||
[providedFieldDescriptors]="listItemViewFieldDescriptors"
|
||||
>
|
||||
<div actions *ngIf="(notNullOrUndefinedValue(item) | async)">
|
||||
<ng-container *ngIf="itemsActions.has(item.id)">
|
||||
<!-- Slotting Actions -->
|
||||
<x-slotter [hasCenterSlot]="false" [layout]="SlotLayouts.HORIZONTAL">
|
||||
<!-- START -->
|
||||
<x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
|
||||
<ng-container
|
||||
*ngFor="let action of getSlottedItemActions(SlotNames.START, item)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<ng-container
|
||||
*ngTemplateOutlet="itemActionTemplate; context: {action: action, data: item}"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
</x-slot>
|
||||
|
||||
<!-- END -->
|
||||
<x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
|
||||
<ng-container
|
||||
*ngFor="let action of getSlottedItemActions(SlotNames.END, item)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<ng-container
|
||||
*ngTemplateOutlet="itemActionTemplate; context: {action: action, data: item}"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
</x-slot>
|
||||
</x-slotter>
|
||||
</ng-container>
|
||||
</div>
|
||||
</v-file>
|
||||
</ng-template>
|
||||
|
||||
<!-- Item Action Presenter -->
|
||||
<ng-template #itemActionTemplate let-action="action" let-data="data">
|
||||
<!-- Validate -->
|
||||
<ng-container
|
||||
*ngIf="(notNullOrUndefinedValue(data) | async) && (notNullOrUndefinedValue(action) | async)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<x-button
|
||||
[loading]="loading"
|
||||
[icon]="action.icon"
|
||||
[title]="action.title"
|
||||
[color]="action.color"
|
||||
[foregroundColor]="true"
|
||||
[type]="ButtonTypes.Icon"
|
||||
[iconColor]="ColorNames.Transparent"
|
||||
(clicked)="handleItemAction(action.id, data)"
|
||||
[uiDisabled]="loading || uiDisabled || action.disabled"
|
||||
>
|
||||
</x-button>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- List Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #listItemTemplate let-item="item">
|
||||
<v-file
|
||||
class="v-list-item"
|
||||
[model]="item.data"
|
||||
[loading]="loading"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[presentType]="FilePresentTypes.AsItem"
|
||||
[actionProvider]="listItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(item) | async"
|
||||
[providedFieldDescriptors]="listItemViewFieldDescriptors"
|
||||
></v-file>
|
||||
</ng-template>
|
||||
|
||||
<!-- Owner Name in Lists Template -->
|
||||
<ng-template
|
||||
#listOwnerRef
|
||||
let-key="key"
|
||||
let-index="index"
|
||||
let-value="value"
|
||||
let-props="props"
|
||||
>
|
||||
{{ getOwnerFullName(value) }}
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Add Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #addItemTemplate>
|
||||
<v-file
|
||||
[model]="addModel"
|
||||
[loading]="loading"
|
||||
class="v-input-item"
|
||||
[showValidationErrors]="true"
|
||||
[cardTitle]="ResourceIDs.upload"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[actionProvider]="addItemActionProvider"
|
||||
[presentType]="FilePresentTypes.AsFileUpload"
|
||||
*ngIf="notNullOrUndefinedValue(addModel) | async"
|
||||
(lockNotifier)="handleAddViewLockNotifier($event)"
|
||||
(fileUploadActionFired)="handleFileUploadActionFired($event)"
|
||||
(fileUploadFilesChanged)="handleFileUploadFilesChanged($event)"
|
||||
>
|
||||
</v-file>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Update Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #updateItemTemplate>
|
||||
<v-file
|
||||
[loading]="loading"
|
||||
class="v-input-item"
|
||||
[model]="updateModel"
|
||||
[showValidationErrors]="true"
|
||||
[cardTitle]="ResourceIDs.update"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsForm"
|
||||
[actionProvider]="updateItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(updateModel) | async"
|
||||
(lockNotifier)="handleUpdateViewLockNotifier($event)"
|
||||
(dtoModelActionFired)="handleUpdateViewActionFired($event)"
|
||||
[providedFieldDescriptors]="updateModelViewFieldDescriptors"
|
||||
>
|
||||
</v-file>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Details Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #detailsItemTemplate>
|
||||
<v-file
|
||||
[loading]="loading"
|
||||
class="v-detail-item"
|
||||
[model]="detailsModel"
|
||||
[showValidationErrors]="false"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsView"
|
||||
[actionProvider]="detailsItemActionProvider"
|
||||
[cardTitle]="getModelCardTitle(detailsModel)"
|
||||
*ngIf="notNullOrUndefinedValue(detailsModel) | async"
|
||||
[providedFieldDescriptors]="detailsModelViewFieldDescriptors"
|
||||
>
|
||||
</v-file>
|
||||
</ng-template>
|
||||
|
||||
<!-- Detail File Name Template -->
|
||||
<ng-template
|
||||
#fileNameRef
|
||||
let-key="key"
|
||||
let-index="index"
|
||||
let-value="value"
|
||||
let-props="props"
|
||||
>
|
||||
<v-media
|
||||
[src]="value"
|
||||
style="--thumbnail-size: 128px;"
|
||||
[presentType]="MediaPresentTypes.AsThumbnail"
|
||||
></v-media>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,20 @@
|
||||
.v-item,
|
||||
.v-list-item,
|
||||
.v-input-item,
|
||||
.v-detail-item {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.v-media-thumbnail-present {
|
||||
margin: {
|
||||
left: auto;
|
||||
right: auto;
|
||||
}
|
||||
}
|
||||
|
||||
:host ::ng-deep .v-media-thumbnail-present {
|
||||
margin: {
|
||||
left: auto !important;
|
||||
right: auto !important;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
@import '../files-base//files-base.provider.page.scss';
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { XQueryDto, XQueryResultDto } from 'x-framework-identity-sdk';
|
||||
import { FilesBaseProviderPage } from '../files-base/files-base.provider.page';
|
||||
|
||||
@Component({
|
||||
selector: 'files-explorer',
|
||||
styleUrls: ['./files-explorer.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: '../files-base/files-base.provider.page.html',
|
||||
})
|
||||
export class FilesExplorerPage extends FilesBaseProviderPage {
|
||||
//
|
||||
//#region Props ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
onInit(): void {
|
||||
super.onInit();
|
||||
|
||||
//
|
||||
this.configureAsExplorerPage();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Abstractions ...
|
||||
getModelTask(identifier: string): Observable<any> {
|
||||
//
|
||||
return this.sharedService.mabsutAPIService.files.fileProviderService.get(
|
||||
identifier
|
||||
);
|
||||
}
|
||||
|
||||
queryModelTask(query: XQueryDto): Observable<XQueryResultDto<any>> {
|
||||
return this.sharedService.mabsutAPIService.files.fileProviderService.query(
|
||||
query
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
@import '../files-base//files-base.provider.page.scss';
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { XQueryDto, XQueryResultDto } from 'x-framework-identity-sdk';
|
||||
import { FilesBaseProviderPage } from '../files-base/files-base.provider.page';
|
||||
|
||||
@Component({
|
||||
selector: 'files-management',
|
||||
styleUrls: ['./files-management.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: '../files-base/files-base.provider.page.html',
|
||||
})
|
||||
export class FilesManagementPage extends FilesBaseProviderPage {
|
||||
//
|
||||
//#region Props ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
onInit(): void {
|
||||
super.onInit();
|
||||
|
||||
//
|
||||
this.configureAsManagementPage();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Abstractions ...
|
||||
getModelTask(identifier: string): Observable<any> {
|
||||
//
|
||||
return this.sharedService.mabsutAPIService.files.fileProviderService.get(
|
||||
identifier
|
||||
);
|
||||
}
|
||||
|
||||
queryModelTask(query: XQueryDto): Observable<XQueryResultDto<any>> {
|
||||
return this.sharedService.mabsutAPIService.files.fileProviderService.query(
|
||||
query
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AuthGuard } from 'x-framework-identity-sdk';
|
||||
import { XCanDeactivateGuard } from 'x-framework-core';
|
||||
import { BaseRoutes } from 'src/app/config/page.config';
|
||||
import { ViewsModule } from 'src/app/views/views.module';
|
||||
import { FileRoutes } from 'src/app/views/files/v-file.configs';
|
||||
import { FilesExplorerPage } from './files-explorer/files-explorer.page';
|
||||
import { FilesManagementPage } from './files-management/files-management.page';
|
||||
|
||||
@NgModule({
|
||||
declarations: [FilesExplorerPage, FilesManagementPage],
|
||||
imports: [
|
||||
ViewsModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Default,
|
||||
redirectTo: FileRoutes.FilesExplorer,
|
||||
},
|
||||
//
|
||||
// Explorer ...
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: FilesExplorerPage,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
path: FileRoutes.FilesExplorer,
|
||||
},
|
||||
//
|
||||
// Management ...
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: FilesManagementPage,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
path: FileRoutes.FilesManagement,
|
||||
},
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Unknown,
|
||||
redirectTo: FileRoutes.Default,
|
||||
},
|
||||
]),
|
||||
],
|
||||
exports: [ViewsModule, RouterModule, FilesExplorerPage, FilesManagementPage],
|
||||
})
|
||||
export class FilesPageModule {}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[containerBase]="this"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,56 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-components-home',
|
||||
templateUrl: './home.page.html',
|
||||
styleUrls: ['./home.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line:component-class-suffix
|
||||
export class HomePage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
toolbarShowTitle = true;
|
||||
toolbarShowSubTitle = true;
|
||||
titleRes = this.ResourceIDs.app_name;
|
||||
toolbarSubTitle = this.resourceProvider(this.AppResourceIDs.home_page_title);
|
||||
toolbarTitle = this.resourceProvider(this.titleRes);
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Register Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Task Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Providers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Abstracts ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[containerBase]="this"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,67 @@
|
||||
import { XStandardType } from 'x-framework-core';
|
||||
import { XSideType } from 'x-framework-components';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-landing',
|
||||
templateUrl: './landing.page.html',
|
||||
styleUrls: ['./landing.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line: component-class-suffix
|
||||
export class LandingPage extends VPageComponent {
|
||||
//
|
||||
//#region Props ...
|
||||
hasSide = true;
|
||||
showFooter = true;
|
||||
toolbarShowSubTitle = true;
|
||||
titleRes = this.AppResourceIDs.landing_page_title;
|
||||
toolbarSubTitle = this.resourceProvider(
|
||||
this.AppResourceIDs.landing_page_description
|
||||
);
|
||||
toolbarTitle = this.resourceProvider(this.titleRes);
|
||||
|
||||
/**
|
||||
* use this for Menu always Visible ...
|
||||
*/
|
||||
toggleMenuWhen = '';
|
||||
sideType: XStandardType<string> = XSideType.Overlay;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Register Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Task Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Providers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region UI Handlers ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[containerBase]="this"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,35 @@
|
||||
import { Pages } from 'src/app/config/page.config';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-not-authorized',
|
||||
templateUrl: './not-authorized.page.html',
|
||||
styleUrls: ['./not-authorized.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line: component-class-suffix
|
||||
export class NotAuthorizedPage extends VPageComponent {
|
||||
//
|
||||
//#region Page Props ...
|
||||
hasSide = false;
|
||||
toolbarHasBack = true;
|
||||
toolbarShowBack = true;
|
||||
showToolbarEndSlot = false;
|
||||
showToolbarContent = false;
|
||||
toolbarShowSubTitle = true;
|
||||
toolbarSubTitle = this.resourceProvider(this.titleRes);
|
||||
titleRes = this.AppResourceIDs.not_authorized_page_title;
|
||||
|
||||
//
|
||||
toolbarBackHandler = () => {
|
||||
//
|
||||
// TODO: Fix this ...
|
||||
// this.managerService.navigateByPageReplace(Pages.);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
[containerBase]="this"
|
||||
[contentTemplate]="contentTemplate"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,180 @@
|
||||
import {
|
||||
XPage,
|
||||
XExceptionIDs,
|
||||
isNullOrUndefined,
|
||||
} from 'x-framework-core';
|
||||
import { Pages } from 'src/app/config/page.config';
|
||||
import { VPageComponent } from 'src/app/views/v-page/v-page.component';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
|
||||
const StartupKeys = {
|
||||
AuthLoadingID: 'auth_loading',
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'app-startup',
|
||||
templateUrl: './startup.page.html',
|
||||
styleUrls: ['./startup.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
// tslint:disable-next-line: component-class-suffix
|
||||
export class StartupPage extends VPageComponent {
|
||||
//
|
||||
//#region Configuration Props ...
|
||||
//
|
||||
hasSide = false;
|
||||
showToolbarEndSlot = false;
|
||||
showToolbarContent = false;
|
||||
|
||||
//
|
||||
hasBlogPage = !isNullOrUndefined(this.config.defaultBlogPage);
|
||||
hasLandingPage = !isNullOrUndefined(this.config.defaultLandingPage);
|
||||
|
||||
//
|
||||
private loadingModal: HTMLIonLoadingElement;
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycle ...
|
||||
async onInit() {
|
||||
super.onInit();
|
||||
|
||||
//
|
||||
await this.handleStartUp();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
private async handleStartUp() {
|
||||
//
|
||||
await this.presentLoading(
|
||||
StartupKeys.AuthLoadingID,
|
||||
this.resourceProvider(this.AppResourceIDs.default_loading)
|
||||
);
|
||||
|
||||
//
|
||||
// Retrieve Account State ...
|
||||
const xAccountState = await this.sharedService.authService.currentState();
|
||||
const isAuthenticated = xAccountState ? xAccountState.isLoggedIn : false;
|
||||
if (!isAuthenticated) {
|
||||
//
|
||||
if (!this.hasBlogPage && !this.hasLandingPage) {
|
||||
//
|
||||
await this.dismissLoading(StartupKeys.AuthLoadingID);
|
||||
this.showError(XExceptionIDs.NotAuthorized);
|
||||
}
|
||||
|
||||
//
|
||||
await this.finishAction(Pages.Login);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Check Token Expiration ...
|
||||
const isExpiredToken = await this.sharedService.authService.isExpired();
|
||||
if (isExpiredToken) {
|
||||
//
|
||||
try {
|
||||
//
|
||||
const mTask = this.sharedService.authService.refreshTokens();
|
||||
|
||||
//
|
||||
const newTokens = await this.getValueAsync(mTask);
|
||||
|
||||
//
|
||||
await this.sharedService.authService.updateUserTokens(
|
||||
xAccountState,
|
||||
newTokens
|
||||
);
|
||||
|
||||
//
|
||||
await this.finishAction(Pages.Home);
|
||||
} catch {
|
||||
//
|
||||
if (!this.hasBlogPage && !this.hasLandingPage) {
|
||||
await this.handleErrorState(XExceptionIDs.LoginFailed, true);
|
||||
}
|
||||
|
||||
//
|
||||
await this.sharedService.authService.logout();
|
||||
await this.finishAction(Pages.Login);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (!this.hasBlogPage && !this.hasLandingPage) {
|
||||
//
|
||||
await this.finishAction(Pages.Login);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
await this.finishAction(Pages.Home);
|
||||
return;
|
||||
}
|
||||
|
||||
private async finishAction(dest?: XPage) {
|
||||
//
|
||||
await this.dismissLoading(StartupKeys.AuthLoadingID);
|
||||
|
||||
//
|
||||
if (this.hasBlogPage && !this.hasLandingPage) {
|
||||
//
|
||||
await this.managerService.navigateByPageReplace(
|
||||
this.config.defaultBlogPage
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (this.hasLandingPage) {
|
||||
//
|
||||
await this.managerService.navigateByPageReplace(
|
||||
this.config.defaultLandingPage
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (!isNullOrUndefined(dest)) {
|
||||
await this.managerService.navigateByPageReplace(dest);
|
||||
}
|
||||
}
|
||||
|
||||
private async presentLoading(id: string, message: string) {
|
||||
//
|
||||
if (!isNullOrUndefined(this.loadingModal) && this.loadingModal) {
|
||||
await this.dismissLoading(StartupKeys.AuthLoadingID);
|
||||
}
|
||||
|
||||
//
|
||||
this.loadingModal = await this.managerService.dialogService.presentLoading({
|
||||
id,
|
||||
message,
|
||||
});
|
||||
}
|
||||
|
||||
private async dismissLoading(id: string) {
|
||||
//
|
||||
if (isNullOrUndefined(this.loadingModal)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
const result =
|
||||
await this.managerService.dialogService.loadingController.dismiss(id);
|
||||
if (!!result) {
|
||||
this.loadingModal = undefined;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
#pagePresenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
(xOnEscapeGlobal)="handleGlobalEscapePressed($event)"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
<!-- Query Presenter -->
|
||||
<v-query-presenter
|
||||
[loading]="loading"
|
||||
[tabsLock]="tabsLock"
|
||||
[tabsColor]="tabsColor"
|
||||
[showEmpty]="showEmpty"
|
||||
[emptyColor]="emptyColor"
|
||||
[addTabTitle]="addTabTitle"
|
||||
[itemTemplate]="itemTemplate"
|
||||
[emptyMessage]="emptyMessage"
|
||||
[tabsCssClass]="tabsCssClass"
|
||||
[tabsLoopTabs]="tabsLoopTabs"
|
||||
[tabsSwipable]="tabsSwipable"
|
||||
[listTabTitle]="listTabTitle"
|
||||
[emptyCssClass]="emptyCssClass"
|
||||
[showPaginator]="showPaginator"
|
||||
[tabsAlignTabs]="tabsAlignTabs"
|
||||
[showSearchBar]="showSearchBar"
|
||||
[searchBarType]="searchBarType"
|
||||
[searchBarValue]="searchBarValue"
|
||||
[searchBarTitle]="searchBarTitle"
|
||||
[searchBarColor]="searchBarColor"
|
||||
[updateTabTitle]="updateTabTitle"
|
||||
[paginatorColor]="paginatorColor"
|
||||
[tabsShowHeader]="tabsShowHeader"
|
||||
[addItemTemplate]="addItemTemplate"
|
||||
[emptyHasRefresh]="emptyHasRefresh"
|
||||
[detailsTabTitle]="detailsTabTitle"
|
||||
[tabsHeaderColor]="tabsHeaderColor"
|
||||
[showItemsAsList]="showItemsAsList"
|
||||
[modelIdentifier]="modelIdentifier"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[listItemTemplate]="listItemTemplate"
|
||||
[listTabCardTitle]="listTabCardTitle"
|
||||
[listTabCardColor]="listTabCardColor"
|
||||
[emptyRefreshIcon]="emptyRefreshIcon"
|
||||
[emptyMessageColor]="emptyMessageColor"
|
||||
[paginatorPosition]="paginatorPosition"
|
||||
[tabsSelectedIndex]="tabsSelectedIndex"
|
||||
[tabsDynamicHeight]="tabsDynamicHeight"
|
||||
[tabsDisableRipple]="tabsDisableRipple"
|
||||
[searchBarDebounce]="searchBarDebounce"
|
||||
[searchBarCssClass]="searchBarCssClass"
|
||||
[updateItemTemplate]="updateItemTemplate"
|
||||
[tabsHeaderPosition]="tabsHeaderPosition"
|
||||
[tabsActiveTabColor]="tabsActiveTabColor"
|
||||
[searchBarSpellcheck]="searchBarSpellcheck"
|
||||
[detailsItemTemplate]="detailsItemTemplate"
|
||||
[wrapListTabWithCard]="wrapListTabWithCard"
|
||||
[listTabCardIsInPage]="listTabCardIsInPage"
|
||||
[listTabCardSubTitle]="listTabCardSubTitle"
|
||||
[emptyForegroundColor]="emptyForegroundColor"
|
||||
[actionProvider]="queryPresenterActionProvider"
|
||||
[tabsDisablePagination]="tabsDisablePagination"
|
||||
[tabsAnimationDuration]="tabsAnimationDuration"
|
||||
[tabsTabIndicatorColor]="tabsTabIndicatorColor"
|
||||
[tabsTabPaginatorColor]="tabsTabPaginatorColor"
|
||||
[searchBarKeyboardType]="searchBarKeyboardType"
|
||||
[searchBarEnterKeyHint]="searchBarEnterKeyHint"
|
||||
[emptyRefreshButtonColor]="emptyRefreshButtonColor"
|
||||
[searchBarForegroundColor]="searchBarForegroundColor"
|
||||
[searchBarShowClearButton]="searchBarShowClearButton"
|
||||
[searchBarClearButtonIcon]="searchBarClearButtonIcon"
|
||||
[searchBarCancelButtonIcon]="searchBarCancelButtonIcon"
|
||||
[searchBarSearchButtonIcon]="searchBarSearchButtonIcon"
|
||||
[searchBarSearchInputColor]="searchBarSearchInputColor"
|
||||
[searchBarShowCancelButton]="searchBarShowCancelButton"
|
||||
[searchBarCancelButtonTitle]="searchBarCancelButtonTitle"
|
||||
[emptyForegroundMessageColor]="emptyForegroundMessageColor"
|
||||
[searchBarClearButtonIconColor]="searchBarClearButtonIconColor"
|
||||
[searchBarCancelButtonIconColor]="searchBarCancelButtonIconColor"
|
||||
[searchBarSearchButtonIconColor]="searchBarSearchButtonIconColor"
|
||||
[emptyForegroundRefreshButtonColor]="emptyForegroundRefreshButtonColor"
|
||||
[searchBarForegroundSearchInputColor]="searchBarForegroundSearchInputColor"
|
||||
>
|
||||
</v-query-presenter>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #itemTemplate let-item="item">
|
||||
<v-tag
|
||||
[model]="item"
|
||||
class="v-item"
|
||||
[loading]="loading"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[cardTitle]="getModelCardTitle(item)"
|
||||
[presentType]="BasePresentTypes.AsView"
|
||||
[actionProvider]="listItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(item) | async"
|
||||
[providedFieldDescriptors]="listItemViewFieldDescriptors"
|
||||
>
|
||||
<div actions *ngIf="(notNullOrUndefinedValue(item) | async)">
|
||||
<ng-container *ngIf="itemsActions.has(item.id.toString())">
|
||||
<!-- Slotting Actions -->
|
||||
<x-slotter [hasCenterSlot]="false" [layout]="SlotLayouts.HORIZONTAL">
|
||||
<!-- START -->
|
||||
<x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
|
||||
<ng-container
|
||||
*ngFor="let action of getSlottedItemActions(SlotNames.START, item)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<ng-container
|
||||
*ngTemplateOutlet="itemActionTemplate; context: {action: action, data: item}"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
</x-slot>
|
||||
|
||||
<!-- END -->
|
||||
<x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
|
||||
<ng-container
|
||||
*ngFor="let action of getSlottedItemActions(SlotNames.END, item)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<ng-container
|
||||
*ngTemplateOutlet="itemActionTemplate; context: {action: action, data: item}"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
</x-slot>
|
||||
</x-slotter>
|
||||
</ng-container>
|
||||
</div>
|
||||
</v-tag>
|
||||
</ng-template>
|
||||
|
||||
<!-- Item Action Presenter -->
|
||||
<ng-template #itemActionTemplate let-action="action" let-data="data">
|
||||
<!-- Validate -->
|
||||
<ng-container
|
||||
*ngIf="(notNullOrUndefinedValue(data) | async) && (notNullOrUndefinedValue(action) | async)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<x-button
|
||||
[loading]="loading"
|
||||
[icon]="action.icon"
|
||||
[title]="action.title"
|
||||
[color]="action.color"
|
||||
[foregroundColor]="true"
|
||||
[type]="ButtonTypes.Icon"
|
||||
[iconColor]="ColorNames.Transparent"
|
||||
(clicked)="handleItemAction(action.id, data)"
|
||||
[uiDisabled]="loading || uiDisabled || action.disabled"
|
||||
>
|
||||
</x-button>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- List Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #listItemTemplate let-item="item">
|
||||
<v-tag
|
||||
class="v-list-item"
|
||||
[model]="item.data"
|
||||
[loading]="loading"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[presentType]="TagPresentTypes.AsView"
|
||||
[actionProvider]="listItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(item) | async"
|
||||
[providedFieldDescriptors]="listItemViewFieldDescriptors"
|
||||
></v-tag>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Add Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #addItemTemplate>
|
||||
<v-tag
|
||||
[model]="addModel"
|
||||
[loading]="loading"
|
||||
class="v-input-item"
|
||||
[showValidationErrors]="true"
|
||||
[cardTitle]="ResourceIDs.add"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsForm"
|
||||
[actionProvider]="addItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(addModel) | async"
|
||||
(lockNotifier)="handleAddViewLockNotifier($event)"
|
||||
(dtoModelActionFired)="handleAddViewActionFired($event)"
|
||||
[providedFieldDescriptors]="addModelViewFieldDescriptors"
|
||||
>
|
||||
</v-tag>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Update Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #updateItemTemplate>
|
||||
<v-tag
|
||||
[loading]="loading"
|
||||
class="v-input-item"
|
||||
[model]="updateModel"
|
||||
[showValidationErrors]="true"
|
||||
[cardTitle]="ResourceIDs.update"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsForm"
|
||||
[actionProvider]="updateItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(updateModel) | async"
|
||||
(lockNotifier)="handleUpdateViewLockNotifier($event)"
|
||||
(dtoModelActionFired)="handleUpdateViewActionFired($event)"
|
||||
[providedFieldDescriptors]="updateModelViewFieldDescriptors"
|
||||
>
|
||||
</v-tag>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Details Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #detailsItemTemplate>
|
||||
<v-tag
|
||||
[loading]="loading"
|
||||
class="v-detail-item"
|
||||
[model]="detailsModel"
|
||||
[showValidationErrors]="false"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsView"
|
||||
[actionProvider]="detailsItemActionProvider"
|
||||
[cardTitle]="getModelCardTitle(detailsModel)"
|
||||
*ngIf="notNullOrUndefinedValue(detailsModel) | async"
|
||||
[providedFieldDescriptors]="detailsModelViewFieldDescriptors"
|
||||
>
|
||||
</v-tag>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,7 @@
|
||||
.v-item,
|
||||
.v-list-item,
|
||||
.v-input-item,
|
||||
.v-detail-item
|
||||
{
|
||||
width: 100%;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
||||
@import '../tags-base/tags-base.provider.page.scss';
|
||||
@@ -0,0 +1,42 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { toNumber } from 'x-framework-core';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { XQueryDto, XQueryResultDto } from 'x-framework-identity-sdk';
|
||||
import { TagsBaseProviderPage } from '../tags-base/tags-base.provider.page';
|
||||
|
||||
@Component({
|
||||
selector: 'tags-explorer',
|
||||
styleUrls: ['./tags-explorer.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: '../tags-base/tags-base.provider.page.html',
|
||||
})
|
||||
export class TagsExplorerPage extends TagsBaseProviderPage {
|
||||
//
|
||||
//#region Props ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
onInit(): void {
|
||||
super.onInit();
|
||||
|
||||
//
|
||||
this.configureAsExplorerPage();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Abstractions ...
|
||||
getModelTask(identifier: string): Observable<any> {
|
||||
//
|
||||
return this.sharedService.mabsutAPIService.tags.tagProviderService
|
||||
.get(toNumber(identifier));
|
||||
}
|
||||
|
||||
queryModelTask(query: XQueryDto): Observable<XQueryResultDto<any>> {
|
||||
return this.sharedService.mabsutAPIService.tags.tagProviderService.query(
|
||||
query
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
@import '../tags-base/tags-base.provider.page.scss';
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { toNumber } from 'x-framework-core';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { XQueryDto, XQueryResultDto } from 'x-framework-identity-sdk';
|
||||
import { TagsBaseProviderPage } from '../tags-base/tags-base.provider.page';
|
||||
|
||||
@Component({
|
||||
selector: 'tags-management',
|
||||
styleUrls: ['./tags-management.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: '../tags-base/tags-base.provider.page.html',
|
||||
})
|
||||
export class TagsManagementPage extends TagsBaseProviderPage {
|
||||
//
|
||||
//#region Props ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
onInit(): void {
|
||||
super.onInit();
|
||||
|
||||
//
|
||||
this.configureAsManagementPage();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Abstractions ...
|
||||
getModelTask(identifier: string): Observable<any> {
|
||||
//
|
||||
return this.sharedService.mabsutAPIService.tags.tagProviderService.get(
|
||||
toNumber(identifier)
|
||||
);
|
||||
}
|
||||
|
||||
queryModelTask(query: XQueryDto): Observable<XQueryResultDto<any>> {
|
||||
return this.sharedService.mabsutAPIService.tags.tagProviderService.query(
|
||||
query
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AuthGuard } from 'x-framework-identity-sdk';
|
||||
import { XCanDeactivateGuard } from 'x-framework-core';
|
||||
import { BaseRoutes } from 'src/app/config/page.config';
|
||||
import { ViewsModule } from 'src/app/views/views.module';
|
||||
import { TagRoutes } from 'src/app/views/tags/v-tag.configs';
|
||||
import { TagsExplorerPage } from './tags-explorer/tags-explorer.page';
|
||||
import { TagsManagementPage } from './tags-management/tags-management.page';
|
||||
|
||||
@NgModule({
|
||||
declarations: [TagsExplorerPage, TagsManagementPage],
|
||||
imports: [
|
||||
ViewsModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Default,
|
||||
redirectTo: TagRoutes.TagsExplorer,
|
||||
},
|
||||
//
|
||||
// Tags Explorer ...
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: TagsExplorerPage,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
path: TagRoutes.TagsExplorer,
|
||||
},
|
||||
//
|
||||
// Tags Management ...
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: TagsManagementPage,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
path: TagRoutes.TagsManagement,
|
||||
},
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Unknown,
|
||||
redirectTo: TagRoutes.Default,
|
||||
},
|
||||
]),
|
||||
],
|
||||
exports: [ViewsModule, RouterModule, TagsExplorerPage, TagsManagementPage],
|
||||
})
|
||||
export class TagsPageModule {}
|
||||
@@ -0,0 +1,14 @@
|
||||
import { XLocale } from 'x-framework-core';
|
||||
import { AppResourceIDs } from 'src/app/config/localization.config';
|
||||
|
||||
export function getLocaleResourceID(locale: XLocale) {
|
||||
//
|
||||
if (locale === 'en-US') {
|
||||
return AppResourceIDs.english;
|
||||
} else if (locale === 'fa-IR') {
|
||||
return AppResourceIDs.persian;
|
||||
}
|
||||
|
||||
//
|
||||
return locale;
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
<!-- -->
|
||||
<!-- Page Presenter -->
|
||||
<!-- -->
|
||||
<v-page-presenter
|
||||
#pagePresenter
|
||||
[loading]="loading"
|
||||
[containerBase]="this"
|
||||
[uiDisabled]="uiDisabled"
|
||||
[contentTemplate]="contentTemplate"
|
||||
(xOnEscapeGlobal)="handleGlobalEscapePressed($event)"
|
||||
></v-page-presenter>
|
||||
|
||||
<!-- -->
|
||||
<!-- Page Content -->
|
||||
<!-- -->
|
||||
<ng-template #contentTemplate>
|
||||
<!-- Item List -->
|
||||
<v-query-presenter
|
||||
[loading]="loading"
|
||||
[tabsLock]="tabsLock"
|
||||
[tabsColor]="tabsColor"
|
||||
[showEmpty]="showEmpty"
|
||||
[emptyColor]="emptyColor"
|
||||
[addTabTitle]="addTabTitle"
|
||||
[itemTemplate]="itemTemplate"
|
||||
[emptyMessage]="emptyMessage"
|
||||
[tabsCssClass]="tabsCssClass"
|
||||
[tabsLoopTabs]="tabsLoopTabs"
|
||||
[tabsSwipable]="tabsSwipable"
|
||||
[listTabTitle]="listTabTitle"
|
||||
[emptyCssClass]="emptyCssClass"
|
||||
[showPaginator]="showPaginator"
|
||||
[tabsAlignTabs]="tabsAlignTabs"
|
||||
[showSearchBar]="showSearchBar"
|
||||
[searchBarType]="searchBarType"
|
||||
[searchBarValue]="searchBarValue"
|
||||
[searchBarTitle]="searchBarTitle"
|
||||
[searchBarColor]="searchBarColor"
|
||||
[updateTabTitle]="updateTabTitle"
|
||||
[paginatorColor]="paginatorColor"
|
||||
[tabsShowHeader]="tabsShowHeader"
|
||||
[addItemTemplate]="addItemTemplate"
|
||||
[emptyHasRefresh]="emptyHasRefresh"
|
||||
[detailsTabTitle]="detailsTabTitle"
|
||||
[tabsHeaderColor]="tabsHeaderColor"
|
||||
[showItemsAsList]="showItemsAsList"
|
||||
[modelIdentifier]="modelIdentifier"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[listItemTemplate]="listItemTemplate"
|
||||
[listTabCardTitle]="listTabCardTitle"
|
||||
[listTabCardColor]="listTabCardColor"
|
||||
[emptyRefreshIcon]="emptyRefreshIcon"
|
||||
[emptyMessageColor]="emptyMessageColor"
|
||||
[paginatorPosition]="paginatorPosition"
|
||||
[tabsSelectedIndex]="tabsSelectedIndex"
|
||||
[tabsDynamicHeight]="tabsDynamicHeight"
|
||||
[tabsDisableRipple]="tabsDisableRipple"
|
||||
[searchBarDebounce]="searchBarDebounce"
|
||||
[searchBarCssClass]="searchBarCssClass"
|
||||
[updateItemTemplate]="updateItemTemplate"
|
||||
[tabsHeaderPosition]="tabsHeaderPosition"
|
||||
[tabsActiveTabColor]="tabsActiveTabColor"
|
||||
[searchBarSpellcheck]="searchBarSpellcheck"
|
||||
[detailsItemTemplate]="detailsItemTemplate"
|
||||
[wrapListTabWithCard]="wrapListTabWithCard"
|
||||
[listTabCardIsInPage]="listTabCardIsInPage"
|
||||
[listTabCardSubTitle]="listTabCardSubTitle"
|
||||
[emptyForegroundColor]="emptyForegroundColor"
|
||||
[actionProvider]="queryPresenterActionProvider"
|
||||
[tabsDisablePagination]="tabsDisablePagination"
|
||||
[tabsAnimationDuration]="tabsAnimationDuration"
|
||||
[tabsTabIndicatorColor]="tabsTabIndicatorColor"
|
||||
[tabsTabPaginatorColor]="tabsTabPaginatorColor"
|
||||
[searchBarKeyboardType]="searchBarKeyboardType"
|
||||
[searchBarEnterKeyHint]="searchBarEnterKeyHint"
|
||||
[emptyRefreshButtonColor]="emptyRefreshButtonColor"
|
||||
[searchBarForegroundColor]="searchBarForegroundColor"
|
||||
[searchBarShowClearButton]="searchBarShowClearButton"
|
||||
[searchBarClearButtonIcon]="searchBarClearButtonIcon"
|
||||
[searchBarCancelButtonIcon]="searchBarCancelButtonIcon"
|
||||
[searchBarSearchButtonIcon]="searchBarSearchButtonIcon"
|
||||
[searchBarSearchInputColor]="searchBarSearchInputColor"
|
||||
[searchBarShowCancelButton]="searchBarShowCancelButton"
|
||||
[searchBarCancelButtonTitle]="searchBarCancelButtonTitle"
|
||||
[emptyForegroundMessageColor]="emptyForegroundMessageColor"
|
||||
[searchBarClearButtonIconColor]="searchBarClearButtonIconColor"
|
||||
[searchBarCancelButtonIconColor]="searchBarCancelButtonIconColor"
|
||||
[searchBarSearchButtonIconColor]="searchBarSearchButtonIconColor"
|
||||
[emptyForegroundRefreshButtonColor]="emptyForegroundRefreshButtonColor"
|
||||
[searchBarForegroundSearchInputColor]="searchBarForegroundSearchInputColor"
|
||||
>
|
||||
</v-query-presenter>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #itemTemplate let-item="item">
|
||||
<v-webinar-view
|
||||
[model]="item"
|
||||
[showTags]="false"
|
||||
[loading]="loading"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[cardTitle]="getModelCardTitle(item)"
|
||||
[presentType]="BasePresentTypes.AsView"
|
||||
[actionProvider]="listItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(item) | async"
|
||||
[providedFieldDescriptors]="listItemViewFieldDescriptors"
|
||||
>
|
||||
<div actions *ngIf="(notNullOrUndefinedValue(item) | async)">
|
||||
<ng-container *ngIf="itemsActions.has(item.id)">
|
||||
<!-- Slotting Actions -->
|
||||
<x-slotter [hasCenterSlot]="false" [layout]="SlotLayouts.HORIZONTAL">
|
||||
<!-- START -->
|
||||
<x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
|
||||
<ng-container
|
||||
*ngFor="let action of getSlottedItemActions(SlotNames.START, item)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<ng-container
|
||||
*ngTemplateOutlet="itemActionTemplate; context: {action: action, data: item}"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
</x-slot>
|
||||
|
||||
<!-- END -->
|
||||
<x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
|
||||
<ng-container
|
||||
*ngFor="let action of getSlottedItemActions(SlotNames.END, item)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<ng-container
|
||||
*ngTemplateOutlet="itemActionTemplate; context: {action: action, data: item}"
|
||||
></ng-container>
|
||||
</ng-container>
|
||||
</x-slot>
|
||||
</x-slotter>
|
||||
</ng-container>
|
||||
</div>
|
||||
</v-webinar-view>
|
||||
</ng-template>
|
||||
|
||||
<!-- Item Action Presenter -->
|
||||
<ng-template #itemActionTemplate let-action="action" let-data="data">
|
||||
<!-- Validate -->
|
||||
<ng-container
|
||||
*ngIf="(notNullOrUndefinedValue(data) | async) && (notNullOrUndefinedValue(action) | async)"
|
||||
>
|
||||
<!-- Present Action -->
|
||||
<x-button
|
||||
[loading]="loading"
|
||||
[icon]="action.icon"
|
||||
[title]="action.title"
|
||||
[color]="action.color"
|
||||
[foregroundColor]="true"
|
||||
[type]="ButtonTypes.Icon"
|
||||
[iconColor]="ColorNames.Transparent"
|
||||
(clicked)="handleItemAction(action.id, data)"
|
||||
[uiDisabled]="loading || uiDisabled || action.disabled"
|
||||
>
|
||||
</x-button>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- List Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #listItemTemplate let-item="item">
|
||||
<v-webinar-view
|
||||
[showTags]="false"
|
||||
[model]="item.data"
|
||||
[loading]="loading"
|
||||
[uiDisabled]="loading || uiDisabled"
|
||||
[presentType]="BasePresentTypes.AsView"
|
||||
[actionProvider]="listItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(item) | async"
|
||||
[providedFieldDescriptors]="listItemViewFieldDescriptors"
|
||||
></v-webinar-view>
|
||||
</ng-template>
|
||||
|
||||
<!-- Webinar Owner Name in Lists Template -->
|
||||
<ng-template
|
||||
#listOwnerRef
|
||||
let-key="key"
|
||||
let-index="index"
|
||||
let-value="value"
|
||||
let-props="props"
|
||||
>
|
||||
{{ getOwnerFullName(value) }}
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Add Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #addItemTemplate>
|
||||
<v-webinar-view
|
||||
[showTags]="true"
|
||||
[showFiles]="true"
|
||||
[model]="addModel"
|
||||
[loading]="loading"
|
||||
[showTagsLabel]="true"
|
||||
[showFilesLabel]="true"
|
||||
[showValidationErrors]="true"
|
||||
[cardTitle]="ResourceIDs.add"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsForm"
|
||||
[actionProvider]="addItemActionProvider"
|
||||
*ngIf="notNullOrUndefinedValue(addModel) | async"
|
||||
(lockNotifier)="handleAddViewLockNotifier($event)"
|
||||
(tagsStateChanged)="handleTagsStateChanged($event)"
|
||||
(filesStateChanged)="handleFilesStateChanged($event)"
|
||||
(dtoModelActionFired)="handleAddViewActionFired($event)"
|
||||
[providedFieldDescriptors]="addModelViewFieldDescriptors"
|
||||
>
|
||||
</v-webinar-view>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Update Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #updateItemTemplate>
|
||||
<v-webinar-view
|
||||
[showTags]="true"
|
||||
[showFiles]="true"
|
||||
[loading]="loading"
|
||||
[model]="updateModel"
|
||||
[showTagsLabel]="true"
|
||||
[showFilesLabel]="true"
|
||||
[showValidationErrors]="true"
|
||||
[cardTitle]="ResourceIDs.update"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsForm"
|
||||
[actionProvider]="updateItemActionProvider"
|
||||
(tagsStateChanged)="handleTagsStateChanged($event)"
|
||||
(filesStateChanged)="handleFilesStateChanged($event)"
|
||||
*ngIf="notNullOrUndefinedValue(updateModel) | async"
|
||||
(lockNotifier)="handleUpdateViewLockNotifier($event)"
|
||||
(dtoModelActionFired)="handleUpdateViewActionFired($event)"
|
||||
[providedFieldDescriptors]="updateModelViewFieldDescriptors"
|
||||
>
|
||||
</v-webinar-view>
|
||||
</ng-template>
|
||||
|
||||
<!-- -->
|
||||
<!-- Details Item Template -->
|
||||
<!-- -->
|
||||
<ng-template #detailsItemTemplate>
|
||||
<v-webinar-view
|
||||
[showTags]="true"
|
||||
[showFiles]="true"
|
||||
[loading]="loading"
|
||||
[showTagsLabel]="true"
|
||||
[showFilesLabel]="true"
|
||||
[model]="detailsModel"
|
||||
[showValidationErrors]="false"
|
||||
[uiDisabled]="uiDisabled || loading"
|
||||
[presentType]="BasePresentTypes.AsView"
|
||||
[actionProvider]="detailsItemActionProvider"
|
||||
[cardTitle]="getModelCardTitle(detailsModel)"
|
||||
[tagActionsProvider]="detailsTagsActionsProvider"
|
||||
[fileActionsProvider]="detailsFilesActionsProvider"
|
||||
*ngIf="notNullOrUndefinedValue(detailsModel) | async"
|
||||
[tagsPresentType]="TagsPresenterPresertTypes.AsChips"
|
||||
[filesPresentType]="FilesPresenterPresertTypes.AsThumbnails"
|
||||
[providedFieldDescriptors]="detailsModelViewFieldDescriptors"
|
||||
>
|
||||
</v-webinar-view>
|
||||
</ng-template>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { concatMap } from 'rxjs/operators';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { XQueryDto, XQueryResultDto } from 'x-framework-identity-sdk';
|
||||
import { ToWebinarViewDto } from 'src/app/views/webinar/v-webinar.tools';
|
||||
import { WebinarsBaseProviderPage } from '../webinars-base/webinars-base.provider.page';
|
||||
|
||||
@Component({
|
||||
selector: 'webinars-explorer',
|
||||
styleUrls: ['./webinars-explorer.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: '../webinars-base/webinars-base.provider.page.html',
|
||||
})
|
||||
export class WebinarsExplorerPage extends WebinarsBaseProviderPage {
|
||||
//
|
||||
//#region Props ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
onInit(): void {
|
||||
super.onInit();
|
||||
|
||||
//
|
||||
this.configureAsExplorerPage();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Abstractions ...
|
||||
getModelTask(identifier: string): Observable<any> {
|
||||
//
|
||||
return this.sharedService.mabsutAPIService.webinars.webinarProviderService
|
||||
.get(identifier)
|
||||
.pipe(
|
||||
concatMap((m) =>
|
||||
this.getValue(ToWebinarViewDto(m, this.managerService.currentLocale))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
queryModelTask(query: XQueryDto): Observable<XQueryResultDto<any>> {
|
||||
return this.sharedService.mabsutAPIService.webinars.webinarProviderService.query(
|
||||
query
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Observable } from 'rxjs';
|
||||
import { concatMap } from 'rxjs/operators';
|
||||
import { Component, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { XQueryDto, XQueryResultDto } from 'x-framework-identity-sdk';
|
||||
import { ToWebinarViewDto } from 'src/app/views/webinar/v-webinar.tools';
|
||||
import { WebinarsBaseProviderPage } from '../webinars-base/webinars-base.provider.page';
|
||||
|
||||
@Component({
|
||||
selector: 'webinars-management',
|
||||
styleUrls: ['./webinars-management.page.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
templateUrl: '../webinars-base/webinars-base.provider.page.html',
|
||||
})
|
||||
export class WebinarsManagementPage extends WebinarsBaseProviderPage {
|
||||
//
|
||||
//#region Props ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region LifeCycles ...
|
||||
onInit(): void {
|
||||
super.onInit();
|
||||
|
||||
//
|
||||
this.configureAsManagementPage();
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Abstractions ...
|
||||
getModelTask(identifier: string): Observable<any> {
|
||||
//
|
||||
return this.sharedService.mabsutAPIService.webinars.webinarProviderService
|
||||
.get(identifier)
|
||||
.pipe(
|
||||
concatMap((m) =>
|
||||
this.getValue(ToWebinarViewDto(m, this.managerService.currentLocale))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
queryModelTask(query: XQueryDto): Observable<XQueryResultDto<any>> {
|
||||
return this.sharedService.mabsutAPIService.webinars.webinarProviderService.query(
|
||||
query
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { isValueInEnum } from 'src/app/views/public-api';
|
||||
|
||||
export enum WebinarsManagementTask {
|
||||
Create = 'Create_Webinar',
|
||||
Remove = 'Remove_Webinar',
|
||||
Update = 'Update_Webinar',
|
||||
QueryList = 'QueryList_Webinars',
|
||||
}
|
||||
|
||||
export function isWebinarsManagementTask(value: string, forceExactSames: boolean = true) {
|
||||
return isValueInEnum(value, Object.assign(WebinarsManagementTask, {}), forceExactSames);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { AuthGuard } from 'x-framework-identity-sdk';
|
||||
import { XCanDeactivateGuard } from 'x-framework-core';
|
||||
import { BaseRoutes } from 'src/app/config/page.config';
|
||||
import { ViewsModule } from 'src/app/views/views.module';
|
||||
import { WebinarRoutes } from 'src/app/views/webinar/v-webinar.configs';
|
||||
import { WebinarsExplorerPage } from './webinars-explorer/webinars-explorer.page';
|
||||
import { WebinarsManagementPage } from './webinars-management/webinars-management.page';
|
||||
|
||||
@NgModule({
|
||||
declarations: [WebinarsExplorerPage, WebinarsManagementPage],
|
||||
imports: [
|
||||
ViewsModule,
|
||||
RouterModule.forChild([
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Default,
|
||||
redirectTo: WebinarRoutes.WebinarsExplorer,
|
||||
},
|
||||
//
|
||||
// Webinars Explorer ...
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: WebinarsExplorerPage,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
path: WebinarRoutes.WebinarsExplorer,
|
||||
},
|
||||
//
|
||||
// Webinars Management ...
|
||||
{
|
||||
canActivate: [AuthGuard],
|
||||
component: WebinarsManagementPage,
|
||||
canDeactivate: [XCanDeactivateGuard],
|
||||
path: WebinarRoutes.WebinarsManagement,
|
||||
},
|
||||
{
|
||||
pathMatch: 'full',
|
||||
path: BaseRoutes.Unknown,
|
||||
redirectTo: WebinarRoutes.Default,
|
||||
},
|
||||
]),
|
||||
],
|
||||
exports: [
|
||||
ViewsModule,
|
||||
RouterModule,
|
||||
WebinarsExplorerPage,
|
||||
WebinarsManagementPage,
|
||||
],
|
||||
})
|
||||
export class WebinarsPageModule {}
|
||||
@@ -0,0 +1,19 @@
|
||||
//
|
||||
//#region Services ...
|
||||
export * from './services/shared.service';
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Typings ...
|
||||
export * from './typings/shared.typings';
|
||||
export * from './typings/x-electron.typings';
|
||||
export * from './services/x-scrolling-provider.service'
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Tools ...
|
||||
//#endregion
|
||||
|
||||
//
|
||||
// Module ...
|
||||
export * from './shared.module';
|
||||
@@ -0,0 +1,261 @@
|
||||
import {
|
||||
XUserRoleInfo,
|
||||
XMabsutAPIService,
|
||||
toRoleInfoByRoles,
|
||||
} from 'x-mabsut-api-sdk';
|
||||
import {
|
||||
XParam,
|
||||
XLoggable,
|
||||
toPromise,
|
||||
isNullOrUndefined,
|
||||
isNullOrEmptyString,
|
||||
} from 'x-framework-core';
|
||||
import { timer } from 'rxjs';
|
||||
import {
|
||||
ApiValidators,
|
||||
XAccountService,
|
||||
XLoginResponseDto,
|
||||
prepareUserProfileDtoFields,
|
||||
} from 'x-framework-identity-sdk';
|
||||
import { X_CONFIG } from 'src/app/config/x.config';
|
||||
import { Pages } from 'src/app/config/page.config';
|
||||
import { XConfig } from 'src/app/config/app.config';
|
||||
import { XManagerService } from 'x-framework-services';
|
||||
import { XElectronService } from './x-electron.service';
|
||||
import { concatMap, filter, map } from 'rxjs/operators';
|
||||
import { EventEmitter, Inject, Injectable } from '@angular/core';
|
||||
import { XContentShareService } from './x-content-share-service';
|
||||
import { XMediaDevicesService } from './x-media-devices.service';
|
||||
import { XScrollingProviderService } from './x-scrolling-provider.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class SharedService extends XLoggable {
|
||||
//
|
||||
//#region Props ...
|
||||
//
|
||||
//#region User/Role/Token Helpers ...
|
||||
/**
|
||||
* XAccountState retriever ...
|
||||
*/
|
||||
state$ = this.authService.state$;
|
||||
|
||||
/**
|
||||
* check if a user logged in or not ...
|
||||
*/
|
||||
isAuthenticated$ = this.state$.pipe(
|
||||
map((res) => {
|
||||
//
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
return res.isLoggedIn;
|
||||
})
|
||||
);
|
||||
|
||||
/**
|
||||
* user profile retriever ...
|
||||
*/
|
||||
user$ = this.state$.pipe(
|
||||
filter((res) => !!res),
|
||||
map((state) => prepareUserProfileDtoFields(state.profile))
|
||||
);
|
||||
|
||||
/**
|
||||
* user id retriever ...
|
||||
*/
|
||||
userId$ = this.user$.pipe(map((user) => user.userId));
|
||||
|
||||
/**
|
||||
* user name retriever ...
|
||||
*/
|
||||
userName$ = this.user$.pipe(map((user) => user.userName));
|
||||
|
||||
/**
|
||||
* token retriever ...
|
||||
*/
|
||||
token$ = this.state$.pipe(
|
||||
filter((res) => !!res),
|
||||
map((state) => state.accessToken)
|
||||
);
|
||||
|
||||
/**
|
||||
* retrieve role ...
|
||||
*/
|
||||
roles$ = this.user$.pipe(map((user) => user.roles));
|
||||
|
||||
/**
|
||||
* retrieve userRoleInfo ...
|
||||
*/
|
||||
userRoleInfo$ = this.roles$.pipe(
|
||||
map((roles) => {
|
||||
//
|
||||
const result: XUserRoleInfo = toRoleInfoByRoles(roles);
|
||||
|
||||
//
|
||||
return result;
|
||||
})
|
||||
);
|
||||
|
||||
//
|
||||
isAdmin$ = this.userRoleInfo$.pipe(map((info) => info && !!info.isAdmin));
|
||||
isAgent$ = this.userRoleInfo$.pipe(map((info) => info && !!info.isAgent));
|
||||
isUser$ = this.userRoleInfo$.pipe(map((info) => info && !!info.isUser));
|
||||
isAdminOrAgent$ = this.isAdmin$.pipe(
|
||||
concatMap((isAdmin) =>
|
||||
this.isAgent$.pipe(
|
||||
map((isAgent) => {
|
||||
return isAdmin || isAgent;
|
||||
})
|
||||
)
|
||||
)
|
||||
);
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region App Event Emmitters ...
|
||||
public BeforeAppUnload = new EventEmitter();
|
||||
public AppUnload = new EventEmitter();
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
constructor(
|
||||
@Inject(X_CONFIG)
|
||||
public config: XConfig,
|
||||
public authService: XAccountService,
|
||||
public apiValidators: ApiValidators,
|
||||
public managerService: XManagerService,
|
||||
public accountsService: XAccountService,
|
||||
public electronService: XElectronService,
|
||||
public mabsutAPIService: XMabsutAPIService,
|
||||
public mediaDevicesService: XMediaDevicesService,
|
||||
public contentShareService: XContentShareService,
|
||||
public scrollingInfoProvider: XScrollingProviderService
|
||||
) {
|
||||
super(config);
|
||||
|
||||
//
|
||||
// Check Refresh Token is Avaialble ...
|
||||
if (
|
||||
!isNullOrUndefined(config.refreshTokensDelay) &&
|
||||
config.refreshTokensDelay > 0
|
||||
) {
|
||||
//
|
||||
// Setting Timer ...
|
||||
timer(0, config.refreshTokensDelay).subscribe(async (counter) => {
|
||||
//
|
||||
// Check is User Logged in or not ...
|
||||
const isLoggedIn = await this.authService.isLoggedIn();
|
||||
if (isLoggedIn) {
|
||||
//
|
||||
// Retrieve User State ...
|
||||
const state = await toPromise(this.authService.state$);
|
||||
if (!isNullOrUndefined(state)) {
|
||||
//
|
||||
// Check User Token Expiration ...
|
||||
const isExpired = await this.authService.isExpired();
|
||||
if (isExpired) {
|
||||
//
|
||||
// Try to Refresh Tokens if Expired ...
|
||||
const tokens = await toPromise(
|
||||
this.authService.refreshTokensOnly()
|
||||
);
|
||||
if (!isNullOrUndefined(tokens)) {
|
||||
//
|
||||
// Update User Tokens ...
|
||||
let oldInfo: XLoginResponseDto = {
|
||||
accessToken: state.accessToken,
|
||||
refreshToken: state.refreshToken,
|
||||
expiresAt: state.expiresAt,
|
||||
profile: { ...state.profile },
|
||||
};
|
||||
|
||||
//
|
||||
await this.authService.updateUserTokens(oldInfo, tokens);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
isMe(userId: string) {
|
||||
return this.user$.pipe(
|
||||
map(
|
||||
(profile) =>
|
||||
!isNullOrUndefined(profile) &&
|
||||
!isNullOrEmptyString(userId) &&
|
||||
(userId === profile.email ||
|
||||
userId === profile.userId ||
|
||||
userId === profile.userName ||
|
||||
userId === profile.phoneNumber)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Specified User identifier is point to current user or not ...
|
||||
*
|
||||
* @param userId
|
||||
* @returns
|
||||
*/
|
||||
isNotMe(userId: string) {
|
||||
//
|
||||
return this.user$.pipe(
|
||||
map(
|
||||
(profile) =>
|
||||
!isNullOrUndefined(profile) &&
|
||||
!isNullOrEmptyString(userId) &&
|
||||
userId !== profile.email &&
|
||||
userId !== profile.userId &&
|
||||
userId !== profile.userName &&
|
||||
userId !== profile.phoneNumber
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate and Retrieve Specified User's Profile View Page URL ...
|
||||
*
|
||||
* @param userID
|
||||
* @param returnURL
|
||||
* @returns
|
||||
*/
|
||||
getUserProfileURL(userID: string, returnURL?: string) {
|
||||
//
|
||||
let result = '';
|
||||
|
||||
//
|
||||
// Normalize Args ...
|
||||
if (isNullOrEmptyString(userID)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
const profileURL = this.managerService.getPageRoute(Pages.ProfileView);
|
||||
const profileFullURL = this.managerService.getFullUrl(profileURL);
|
||||
|
||||
//
|
||||
result = `${profileFullURL}?${XParam.Id}=${userID}`;
|
||||
if (!isNullOrEmptyString(returnURL)) {
|
||||
result = `${result}&${XParam.ReturnUrl}=${returnURL}`;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { isNullOrUndefined, XBaseService } from 'x-framework-core';
|
||||
|
||||
/**
|
||||
* a Model for Sharng ...
|
||||
*/
|
||||
export interface XShrableDto {
|
||||
title: string;
|
||||
content: string;
|
||||
link?: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class XContentShareService extends XBaseService {
|
||||
/**
|
||||
* Check Share Content is Supported or not ...
|
||||
*/
|
||||
isShareSupport() {
|
||||
return !isNullOrUndefined(navigator.share);
|
||||
}
|
||||
|
||||
/**
|
||||
* Share Specific Data ...
|
||||
*
|
||||
* @param model XSharableDto instance
|
||||
* @returns boolean
|
||||
*/
|
||||
async share(model: XShrableDto) {
|
||||
//
|
||||
// Validate State and Args ...
|
||||
if (isNullOrUndefined(model) || !this.isShareSupport()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
await navigator.share({
|
||||
title: model.title,
|
||||
text: model.content,
|
||||
url: model.link,
|
||||
});
|
||||
|
||||
//
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,262 @@
|
||||
import {
|
||||
getMills,
|
||||
parseJson,
|
||||
XBaseService,
|
||||
throwException,
|
||||
isNullOrUndefined,
|
||||
isNullOrEmptyString,
|
||||
} from 'x-framework-core';
|
||||
import { Subject } from 'rxjs';
|
||||
import {
|
||||
XElectronChannel,
|
||||
XElectronChannelIdentifier,
|
||||
XElectronMessageDto,
|
||||
} from '../typings/x-electron.typings';
|
||||
import { IpcRenderer } from 'electron';
|
||||
import { Inject, Injectable } from '@angular/core';
|
||||
import { X_CONFIG } from 'src/app/config/x.config';
|
||||
import { XConfig } from 'src/app/config/app.config';
|
||||
import { filter, first, map } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class XElectronService extends XBaseService {
|
||||
//
|
||||
//#region Props ...
|
||||
//
|
||||
private IPC_RENDERER: IpcRenderer;
|
||||
private ELECTRON_WINDOW_ID: string;
|
||||
private MESSAGE_SUBJECT = new Subject<XElectronMessageDto>();
|
||||
|
||||
//
|
||||
readonly message$ = this.MESSAGE_SUBJECT.asObservable();
|
||||
|
||||
//
|
||||
//#region Getters ...
|
||||
get windowId() {
|
||||
return this.ELECTRON_WINDOW_ID;
|
||||
}
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Constructor ...
|
||||
constructor(
|
||||
@Inject(X_CONFIG)
|
||||
config: XConfig
|
||||
) {
|
||||
super(config);
|
||||
|
||||
//
|
||||
this.initialService();
|
||||
this.logDebug('initialElectron');
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Actions ...
|
||||
/**
|
||||
* init service ...
|
||||
*
|
||||
* @param force re initial if initialized before ...
|
||||
*/
|
||||
init(force?: boolean) {
|
||||
this.initialService(force);
|
||||
}
|
||||
|
||||
/**
|
||||
* determines an application is Electron app or not ...
|
||||
*
|
||||
* @returns a boolean value
|
||||
*/
|
||||
isElectron() {
|
||||
//
|
||||
// Find Electron in User Agent ...
|
||||
const result =
|
||||
!isNullOrUndefined(window) &&
|
||||
!isNullOrUndefined(window.navigator) &&
|
||||
!isNullOrEmptyString(window.navigator.userAgent)
|
||||
? window.navigator.userAgent.toLowerCase().includes('electron')
|
||||
: false;
|
||||
|
||||
//
|
||||
// Return result ...
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* sending message to window of Electron ...
|
||||
*
|
||||
* @param message an instance of XElectronMessageDto for sending to window ...
|
||||
*/
|
||||
send(message: XElectronMessageDto) {
|
||||
//
|
||||
if (
|
||||
isNullOrUndefined(message) ||
|
||||
isNullOrUndefined(this.IPC_RENDERER) ||
|
||||
(isNullOrEmptyString(this.ELECTRON_WINDOW_ID) &&
|
||||
isNullOrEmptyString(message.sender))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (isNullOrEmptyString(message.sender)) {
|
||||
message.sender = this.ELECTRON_WINDOW_ID;
|
||||
}
|
||||
|
||||
//
|
||||
if (isNullOrEmptyString(message.channel)) {
|
||||
message.channel = XElectronChannel.Default;
|
||||
}
|
||||
|
||||
//
|
||||
if (isNullOrUndefined(message.timestamp)) {
|
||||
message.timestamp = getMills();
|
||||
}
|
||||
|
||||
//
|
||||
this.IPC_RENDERER.send(message.channel, message);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Protected ...
|
||||
actionHandler<TReturn>(
|
||||
channel: XElectronChannelIdentifier,
|
||||
actionName: string,
|
||||
payload?: any
|
||||
) {
|
||||
//
|
||||
if (!this.isElectron()) {
|
||||
throwException('NotAllowed');
|
||||
}
|
||||
|
||||
//
|
||||
this.send({
|
||||
channel,
|
||||
message: actionName,
|
||||
payload,
|
||||
});
|
||||
|
||||
//
|
||||
return this.message$.pipe(
|
||||
filter((msg) => msg.channel === channel && msg.message === actionName),
|
||||
map((msg) => msg.payload as TReturn),
|
||||
first()
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
actionHandlerForFileChannel<TReturn>(actionName: string, payload?: any) {
|
||||
return this.actionHandler<TReturn>(
|
||||
XElectronChannel.FileService,
|
||||
actionName,
|
||||
payload
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
actionHandlerForProjectChannel<TReturn>(actionName: string, payload?: any) {
|
||||
return this.actionHandler<TReturn>(
|
||||
XElectronChannel.ProjectsService,
|
||||
actionName,
|
||||
payload
|
||||
);
|
||||
}
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Private ...
|
||||
private initialService(force?: boolean) {
|
||||
//
|
||||
if (!!force) {
|
||||
this.IPC_RENDERER = null;
|
||||
}
|
||||
|
||||
//
|
||||
if (!isNullOrUndefined(this.IPC_RENDERER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
if (!isNullOrUndefined(window.require)) {
|
||||
//
|
||||
try {
|
||||
//
|
||||
this.IPC_RENDERER = window.require('electron').ipcRenderer;
|
||||
this.registerMessageListener();
|
||||
|
||||
//
|
||||
this.logDebug('Electron loaded successfully ...');
|
||||
} catch (e) {
|
||||
//
|
||||
this.logWarn('Electron not loaded ...');
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
this.logWarn('Electron not loaded ...');
|
||||
}
|
||||
}
|
||||
|
||||
private registerMessageListener() {
|
||||
//
|
||||
if (isNullOrUndefined(this.IPC_RENDERER)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Register Handshake Reciever ...
|
||||
this.IPC_RENDERER.on(XElectronChannel.Handshak, (event, message) => {
|
||||
//
|
||||
if (isNullOrUndefined(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const mMessage: XElectronMessageDto =
|
||||
parseJson<XElectronMessageDto>(message);
|
||||
|
||||
//
|
||||
this.ELECTRON_WINDOW_ID = mMessage.reciever;
|
||||
|
||||
//
|
||||
const handshakeReplyMessag: XElectronMessageDto = {
|
||||
sender: mMessage.reciever,
|
||||
reciever: mMessage.sender,
|
||||
channel: XElectronChannel.Handshak,
|
||||
};
|
||||
|
||||
//
|
||||
this.send(handshakeReplyMessag);
|
||||
this.logDebug('Handshake Events: ', message, mMessage);
|
||||
});
|
||||
|
||||
//
|
||||
let channels = { ...Object.assign({}, XElectronChannel) };
|
||||
delete channels.Handshak;
|
||||
|
||||
//
|
||||
// Register Non Handshake Events ...
|
||||
Object.keys(channels).forEach((channel) => {
|
||||
this.IPC_RENDERER.on(channels[channel], (event, message) => {
|
||||
//
|
||||
if (isNullOrUndefined(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
const mMessage: XElectronMessageDto =
|
||||
parseJson<XElectronMessageDto>(message);
|
||||
|
||||
//
|
||||
this.MESSAGE_SUBJECT.next(mMessage);
|
||||
|
||||
//
|
||||
this.logDebug('Message Events: ', mMessage);
|
||||
});
|
||||
});
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { isValueInEnum } from 'src/app/views/tools/v-base.tools';
|
||||
import { isNullOrUndefined, XLoggable } from 'x-framework-core';
|
||||
|
||||
//
|
||||
//#region Definitions ...
|
||||
export enum XCameraFacing {
|
||||
User = 'user',
|
||||
Screen = 'screen',
|
||||
Environment = 'environment',
|
||||
}
|
||||
export type XCameraFacingIdentifier = XCameraFacing | string;
|
||||
export function isXCameraFacing(value: string) {
|
||||
return isValueInEnum(value, Object.assign(XCameraFacing, {}));
|
||||
}
|
||||
//#endregion
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class XMediaDevicesService extends XLoggable {
|
||||
//
|
||||
//#region Media Devices ...
|
||||
/**
|
||||
* Enumerate Media Devices ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async getMediaDevices() {
|
||||
return await navigator.mediaDevices.enumerateDevices();
|
||||
}
|
||||
|
||||
/**
|
||||
* retrieve Requested Media Stream ...
|
||||
*
|
||||
* @param mode
|
||||
* @returns
|
||||
*/
|
||||
async getMediaDevice(mode: XCameraFacing = XCameraFacing.User) {
|
||||
//
|
||||
let result: MediaStream = undefined;
|
||||
|
||||
//
|
||||
if (!isXCameraFacing(mode)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
if (mode === XCameraFacing.User) {
|
||||
result = await this.getFrontCameraDevice();
|
||||
} else if (mode === XCameraFacing.Environment) {
|
||||
result = await this.getBackCameraDevice();
|
||||
} else if (mode === XCameraFacing.Screen) {
|
||||
result = await this.getDisplayMediaDevice();
|
||||
}
|
||||
} catch {}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Video Input Devices ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async getVideoInputMediaDevices() {
|
||||
//
|
||||
return (await this.getMediaDevices()).filter(
|
||||
(device) => device.kind === 'videoinput'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Audio Input Devices ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async getAudioInputDevices() {
|
||||
//
|
||||
return (await this.getMediaDevices()).filter(
|
||||
(device) => device.kind === 'audioinput'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Audio Output Devices ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async getAudioOutputDevices() {
|
||||
//
|
||||
return (await this.getMediaDevices()).filter(
|
||||
(device) => device.kind === 'audiooutput'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Front Camera Device ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async getFrontCameraDevice() {
|
||||
//
|
||||
return await navigator.mediaDevices.getUserMedia({
|
||||
video: { facingMode: XCameraFacing.User },
|
||||
audio: true, // front camera
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Back Camera Device ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async getBackCameraDevice() {
|
||||
//
|
||||
return await navigator.mediaDevices.getUserMedia({
|
||||
video: { facingMode: { exact: XCameraFacing.Environment } },
|
||||
audio: true, // back camera
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Display Media Device for Screen Sharing ...
|
||||
*
|
||||
* @param options
|
||||
* @returns
|
||||
*/
|
||||
async getDisplayMediaDevice(options?: any) {
|
||||
//
|
||||
if (isNullOrUndefined(options)) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
//
|
||||
// Always Pass Video ...
|
||||
options = {
|
||||
video: { cursor: 'always' },
|
||||
};
|
||||
|
||||
//
|
||||
return await (navigator.mediaDevices as any).getDisplayMedia(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Has Camera Facing or not ...
|
||||
*
|
||||
* @param facingMode
|
||||
* @returns
|
||||
*/
|
||||
async hasCameraFacing(facingMode: XCameraFacingIdentifier) {
|
||||
//
|
||||
let result =
|
||||
isXCameraFacing(facingMode) && facingMode !== XCameraFacing.Screen;
|
||||
if (!result) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
try {
|
||||
//
|
||||
const stream = await navigator.mediaDevices.getUserMedia({
|
||||
video: { facingMode: { exact: facingMode } },
|
||||
});
|
||||
|
||||
//
|
||||
stream.getTracks().forEach((track) => track.stop()); // stop after test
|
||||
|
||||
//
|
||||
result = true;
|
||||
} catch (err) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check has Front Camera ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async hasFrontCamera() {
|
||||
return await this.hasCameraFacing(XCameraFacing.User);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check has Back Camera ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async hasBackCamera() {
|
||||
//
|
||||
const devices = await navigator.mediaDevices.enumerateDevices();
|
||||
var result = devices.some(
|
||||
(d) =>
|
||||
d.kind === 'videoinput' &&
|
||||
(d.label.toLowerCase().includes('back') ||
|
||||
d.label.toLowerCase().includes('rear'))
|
||||
);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Can Switch Camera ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async canSwitchCamera() {
|
||||
//
|
||||
const hasBack = await this.hasBackCamera();
|
||||
|
||||
//
|
||||
return hasBack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Default Media Devices ...
|
||||
*
|
||||
* @returns
|
||||
*/
|
||||
async getDefaultCamera() {
|
||||
//
|
||||
const hasFront = await this.hasFrontCamera();
|
||||
if (hasFront) {
|
||||
return await this.getFrontCameraDevice();
|
||||
}
|
||||
|
||||
//
|
||||
return navigator.mediaDevices.getUserMedia();
|
||||
}
|
||||
//#endregion
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
isNullOrEmptyString,
|
||||
isNullOrUndefined,
|
||||
XLoggable,
|
||||
} from 'x-framework-core';
|
||||
|
||||
export interface XScrollingHoldInfo {
|
||||
identifier: string;
|
||||
yOffset: number;
|
||||
xOffset: number;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class XScrollingProviderService extends XLoggable {
|
||||
//
|
||||
private holdeds = new Map<string, XScrollingHoldInfo>();
|
||||
|
||||
/**
|
||||
* Check Has Specified Scrolling Info or not ...
|
||||
*
|
||||
* @param identifier
|
||||
* @returns
|
||||
*/
|
||||
has(identifier: string) {
|
||||
return this.holdeds.has(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Specified Identifier Scrolling Info ...
|
||||
*
|
||||
* @param identifier
|
||||
* @returns
|
||||
*/
|
||||
get(identifier: string) {
|
||||
return this.holdeds.get(identifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Specified Identifier Scrolling Info ...
|
||||
*
|
||||
* @param identifier
|
||||
* @returns
|
||||
*/
|
||||
remove(identifier: string) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
result = this.holdeds.has(identifier);
|
||||
if (result) {
|
||||
result = this.holdeds.delete(identifier);
|
||||
}
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Specified Model info to Holds ...
|
||||
*
|
||||
* @param info
|
||||
* @returns
|
||||
*/
|
||||
set(info: XScrollingHoldInfo) {
|
||||
//
|
||||
let result = false;
|
||||
|
||||
//
|
||||
// Validate ...
|
||||
if (isNullOrUndefined(info) || isNullOrEmptyString(info.identifier)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
this.holdeds.set(info.identifier, info);
|
||||
result = this.has(info.identifier);
|
||||
|
||||
//
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [CommonModule],
|
||||
exports: [CommonModule],
|
||||
})
|
||||
export class SharedModule {}
|
||||
@@ -0,0 +1,3 @@
|
||||
export const XSharedServiceKeys = {
|
||||
PushConnectionID: 'PCID',
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as Electron from 'electron';
|
||||
import { XBaseDto } from 'x-framework-core';
|
||||
|
||||
export enum XElectronChannel {
|
||||
Handshak = 'xHandshake',
|
||||
Default = 'xMessage',
|
||||
FileService = 'xFileService',
|
||||
ProjectsService = 'xProjectsService',
|
||||
}
|
||||
|
||||
export type XElectronChannelIdentifier = XElectronChannel | string;
|
||||
|
||||
export interface XElectronMessageDto extends XBaseDto {
|
||||
payload?: any;
|
||||
sender?: string;
|
||||
message?: string;
|
||||
reciever?: string;
|
||||
timestamp?: number;
|
||||
channel?: XElectronChannelIdentifier;
|
||||
}
|
||||
@@ -0,0 +1,756 @@
|
||||
import { XIconNames } from 'x-framework-components';
|
||||
import { XSimplePage } from '../typings/simple.page.typings';
|
||||
|
||||
//
|
||||
//#region Localization Configuration ...
|
||||
export enum AccountResourceIDs {
|
||||
account = 'account',
|
||||
accounts = 'accounts',
|
||||
profile = 'profile',
|
||||
profiles = 'profiles',
|
||||
avatar = 'avatar',
|
||||
avatars = 'avatars',
|
||||
register = 'register',
|
||||
accept_terms = 'accept_terms',
|
||||
email_confirmation = 'email_confirmation',
|
||||
input_user_info = 'input_user_info',
|
||||
input_user_avatar = 'input_user_avatar',
|
||||
finish_registration = 'finish_registration',
|
||||
account_page_title = 'account_page_title',
|
||||
account_page_description = 'account_page_description',
|
||||
profile_page_title = 'profile_page_title',
|
||||
profile_page_description = 'profile_page_description',
|
||||
login_page_title = 'login_page_title',
|
||||
login_page_description = 'login_page_description',
|
||||
logout_page_title = 'logout_page_title',
|
||||
logout_page_description = 'logout_page_description',
|
||||
register_page_title = 'register_page_title',
|
||||
register_page_description = 'register_page_description',
|
||||
email_confirm_page_title = 'email_confirm_page_title',
|
||||
email_confirm_page_description = 'email_confirm_page_description',
|
||||
phone_confirm_page_title = 'phone_confirm_page_title',
|
||||
phone_confirm_page_description = 'phone_confirm_page_description',
|
||||
reset_password_page_title = 'reset_password_page_title',
|
||||
reset_password_page_description = 'reset_password_page_description',
|
||||
change_password_page_title = 'change_password_page_title',
|
||||
change_password_page_description = 'change_password_page_description',
|
||||
search_profiles_page_title = 'search_profiles_page_title',
|
||||
search_profiles_page_description = 'search_profiles_page_description',
|
||||
}
|
||||
|
||||
//
|
||||
//#region Signle Resources ...
|
||||
//
|
||||
//#region account ...
|
||||
export const account_fa = {
|
||||
id: 'account',
|
||||
value: 'حساب',
|
||||
};
|
||||
|
||||
export const account_en = {
|
||||
id: 'account',
|
||||
value: 'Account',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region accounts ...
|
||||
export const accounts_fa = {
|
||||
id: 'accounts',
|
||||
value: 'حساب ها',
|
||||
};
|
||||
|
||||
export const accounts_en = {
|
||||
id: 'accounts',
|
||||
value: 'Accounts',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region profile ...
|
||||
export const profile_fa = {
|
||||
id: 'profile',
|
||||
value: 'نمایه',
|
||||
};
|
||||
|
||||
export const profile_en = {
|
||||
id: 'profile',
|
||||
value: 'Profile',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region profiles ...
|
||||
export const profiles_fa = {
|
||||
id: 'profiles',
|
||||
value: 'نمایه ها',
|
||||
};
|
||||
|
||||
export const profiles_en = {
|
||||
id: 'profiles',
|
||||
value: 'Profiles',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region avatar ...
|
||||
export const avatar_fa = {
|
||||
id: 'avatar',
|
||||
value: 'تصویر نمایه',
|
||||
};
|
||||
|
||||
export const avatar_en = {
|
||||
id: 'avatar',
|
||||
value: 'Profile Image',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region avatars ...
|
||||
export const avatars_fa = {
|
||||
id: 'avatars',
|
||||
value: 'تصاویر نمایه ها',
|
||||
};
|
||||
|
||||
export const avatars_en = {
|
||||
id: 'avatars',
|
||||
value: 'Profile Images',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region register ...
|
||||
export const register_fa = {
|
||||
id: 'register',
|
||||
value: 'ثبت نام',
|
||||
};
|
||||
|
||||
export const register_en = {
|
||||
id: 'register',
|
||||
value: 'Register',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region accept_terms ...
|
||||
export const accept_terms_fa = {
|
||||
id: 'accept_terms',
|
||||
value: 'شرایط و ضوابط ثبت نام',
|
||||
};
|
||||
|
||||
export const accept_terms_en = {
|
||||
id: 'accept_terms',
|
||||
value: 'Terms and Conditions',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region email_confirmation ...
|
||||
export const email_confirmation_fa = {
|
||||
id: 'email_confirmation',
|
||||
value: 'تایید آدرس پست الکترونیک',
|
||||
};
|
||||
|
||||
export const email_confirmation_en = {
|
||||
id: 'email_confirmation',
|
||||
value: 'Email Confirmation',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region input_user_info ...
|
||||
export const input_user_info_fa = {
|
||||
id: 'input_user_info',
|
||||
value: 'دریافت اطلاعات کاربر',
|
||||
};
|
||||
|
||||
export const input_user_info_en = {
|
||||
id: 'input_user_info',
|
||||
value: 'Get User Info',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region input_user_avatar ...
|
||||
export const input_user_avatar_fa = {
|
||||
id: 'input_user_avatar',
|
||||
value: 'دریافت تصویر نمایه',
|
||||
};
|
||||
|
||||
export const input_user_avatar_en = {
|
||||
id: 'input_user_avatar',
|
||||
value: 'Get User Avatar',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region finish_registration ...
|
||||
export const finish_registration_fa = {
|
||||
id: 'finish_registration',
|
||||
value: 'اتمام ثبت نام',
|
||||
};
|
||||
|
||||
export const finish_registration_en = {
|
||||
id: 'finish_registration',
|
||||
value: 'Finish Registration',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region account_page_title ...
|
||||
export const account_page_title_fa = {
|
||||
id: 'account_page_title',
|
||||
value: 'حساب کاربری',
|
||||
};
|
||||
|
||||
export const account_page_title_en = {
|
||||
id: 'account_page_title',
|
||||
value: 'User Account',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region account_page_description ...
|
||||
export const account_page_description_fa = {
|
||||
id: 'account_page_description',
|
||||
value: 'مدیریت حساب کاربری',
|
||||
};
|
||||
|
||||
export const account_page_description_en = {
|
||||
id: 'account_page_description',
|
||||
value: 'Manage Account',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region profile_page_title ...
|
||||
export const profile_page_title_fa = {
|
||||
id: 'profile_page_title',
|
||||
value: 'نمایه کاربر',
|
||||
};
|
||||
|
||||
export const profile_page_title_en = {
|
||||
id: 'profile_page_title',
|
||||
value: 'User Profile',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region profile_page_description ...
|
||||
export const profile_page_description_fa = {
|
||||
id: 'profile_page_description',
|
||||
value: 'اطلاعات مربوط به حساب کاربری',
|
||||
};
|
||||
|
||||
export const profile_page_description_en = {
|
||||
id: 'profile_page_description',
|
||||
value: 'User Account Info',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region login_page_title ...
|
||||
export const login_page_title_fa = {
|
||||
id: 'login_page_title',
|
||||
value: 'ورود به سامانه',
|
||||
};
|
||||
|
||||
export const login_page_title_en = {
|
||||
id: 'login_page_title',
|
||||
value: 'Login to System',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region login_page_description ...
|
||||
export const login_page_description_fa = {
|
||||
id: 'login_page_description',
|
||||
value: 'ورود به سامانه و بهره مندی از خدمات',
|
||||
};
|
||||
|
||||
export const login_page_description_en = {
|
||||
id: 'login_page_description',
|
||||
value: 'Login to System for use Services',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region logout_page_title ...
|
||||
export const logout_page_title_fa = {
|
||||
id: 'logout_page_title',
|
||||
value: 'خروج از سامانه',
|
||||
};
|
||||
|
||||
export const logout_page_title_en = {
|
||||
id: 'logout_page_title',
|
||||
value: 'Logout from System',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region logout_page_description ...
|
||||
export const logout_page_description_fa = {
|
||||
id: 'logout_page_description',
|
||||
value: 'خروج از سامانه و بازگشت به صفحه نخست',
|
||||
};
|
||||
|
||||
export const logout_page_description_en = {
|
||||
id: 'logout_page_description',
|
||||
value: 'Logout from System and go back to First',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region register_page_title ...
|
||||
export const register_page_title_fa = {
|
||||
id: 'register_page_title',
|
||||
value: 'ثبت نام در سامانه',
|
||||
};
|
||||
|
||||
export const register_page_title_en = {
|
||||
id: 'register_page_title',
|
||||
value: 'Register in System',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region register_page_description ...
|
||||
export const register_page_description_fa = {
|
||||
id: 'register_page_description',
|
||||
value: 'ثبت نام و عضویت در سامانه',
|
||||
};
|
||||
|
||||
export const register_page_description_en = {
|
||||
id: 'register_page_description',
|
||||
value: 'Signup and Register in System',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region email_confirm_page_title ...
|
||||
export const email_confirm_page_title_fa = {
|
||||
id: 'email_confirm_page_title',
|
||||
value: 'تایید آدرس پست الکترونیک',
|
||||
};
|
||||
|
||||
export const email_confirm_page_title_en = {
|
||||
id: 'email_confirm_page_title',
|
||||
value: 'Confirm Email Address',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region email_confirm_page_description ...
|
||||
export const email_confirm_page_description_fa = {
|
||||
id: 'email_confirm_page_description',
|
||||
value: 'اعتبار سنجی آدرس پست الکترونیک',
|
||||
};
|
||||
|
||||
export const email_confirm_page_description_en = {
|
||||
id: 'email_confirm_page_description',
|
||||
value: 'Verification of Email Address',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region phone_confirm_page_title ...
|
||||
export const phone_confirm_page_title_fa = {
|
||||
id: 'phone_confirm_page_title',
|
||||
value: 'تایید شماره تلفن همراه',
|
||||
};
|
||||
|
||||
export const phone_confirm_page_title_en = {
|
||||
id: 'phone_confirm_page_title',
|
||||
value: 'Confirm Mobile Number',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region phone_confirm_page_description ...
|
||||
export const phone_confirm_page_description_fa = {
|
||||
id: 'phone_confirm_page_description',
|
||||
value: 'اعتبار سنجی شماره تلفن همراه',
|
||||
};
|
||||
|
||||
export const phone_confirm_page_description_en = {
|
||||
id: 'phone_confirm_page_description',
|
||||
value: 'Verification of Mobile Phone Number',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region reset_password_page_title ...
|
||||
export const reset_password_page_title_fa = {
|
||||
id: 'reset_password_page_title',
|
||||
value: 'بازنشانی کلمه عبور',
|
||||
};
|
||||
|
||||
export const reset_password_page_title_en = {
|
||||
id: 'reset_password_page_title',
|
||||
value: 'Password Reset',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region reset_password_page_description ...
|
||||
export const reset_password_page_description_fa = {
|
||||
id: 'reset_password_page_description',
|
||||
value: 'بازنشانی کلمه عبور فراموش شده',
|
||||
};
|
||||
|
||||
export const reset_password_page_description_en = {
|
||||
id: 'reset_password_page_description',
|
||||
value: 'Resetting Forgotten Passwor',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region change_password_page_title ...
|
||||
export const change_password_page_title_fa = {
|
||||
id: 'change_password_page_title',
|
||||
value: 'تغییر کلمه عبور',
|
||||
};
|
||||
|
||||
export const change_password_page_title_en = {
|
||||
id: 'change_password_page_title',
|
||||
value: 'Password Change',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region change_password_page_description ...
|
||||
export const change_password_page_description_fa = {
|
||||
id: 'change_password_page_description',
|
||||
value: 'تغییر کلمه عبور کاربر',
|
||||
};
|
||||
|
||||
export const change_password_page_description_en = {
|
||||
id: 'change_password_page_description',
|
||||
value: "Change User's Password",
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region search_profiles_page_title ...
|
||||
export const search_profiles_page_title_fa = {
|
||||
id: 'search_profiles_page_title',
|
||||
value: 'جستجوی کاربران',
|
||||
};
|
||||
|
||||
export const search_profiles_page_title_en = {
|
||||
id: 'search_profiles_page_title',
|
||||
value: 'Users Search',
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region search_profiles_page_description ...
|
||||
export const search_profiles_page_description_fa = {
|
||||
id: 'search_profiles_page_description',
|
||||
value: 'جستجوی کاربران جهت برقراری ارتباط',
|
||||
};
|
||||
|
||||
export const search_profiles_page_description_en = {
|
||||
id: 'search_profiles_page_description',
|
||||
value: 'Search Users to Lookup Connection',
|
||||
};
|
||||
//#endregion
|
||||
//#endregion
|
||||
|
||||
//
|
||||
export const AccountLocalizationResourceIDs = Object.assign(
|
||||
AccountResourceIDs,
|
||||
{}
|
||||
);
|
||||
|
||||
//
|
||||
export const AccountLocalizationResources = {
|
||||
//
|
||||
account: {
|
||||
fa: { ...account_fa },
|
||||
en: { ...account_en },
|
||||
},
|
||||
accounts: {
|
||||
fa: { ...accounts_fa },
|
||||
en: { ...accounts_en },
|
||||
},
|
||||
profile: {
|
||||
fa: { ...profile_fa },
|
||||
en: { ...profile_en },
|
||||
},
|
||||
profiles: {
|
||||
fa: { ...profiles_fa },
|
||||
en: { ...profiles_en },
|
||||
},
|
||||
avatar: {
|
||||
fa: { ...avatar_fa },
|
||||
en: { ...avatar_en },
|
||||
},
|
||||
avatars: {
|
||||
fa: { ...avatars_fa },
|
||||
en: { ...avatars_en },
|
||||
},
|
||||
register: {
|
||||
fa: { ...register_fa },
|
||||
en: { ...register_en },
|
||||
},
|
||||
accept_terms: {
|
||||
fa: { ...accept_terms_fa },
|
||||
en: { ...accept_terms_en },
|
||||
},
|
||||
email_confirmation: {
|
||||
fa: { ...email_confirmation_fa },
|
||||
en: { ...email_confirmation_en },
|
||||
},
|
||||
input_user_info: {
|
||||
fa: { ...input_user_info_fa },
|
||||
en: { ...input_user_info_en },
|
||||
},
|
||||
input_user_avatar: {
|
||||
fa: { ...input_user_avatar_fa },
|
||||
en: { ...input_user_avatar_en },
|
||||
},
|
||||
finish_registration: {
|
||||
fa: { ...finish_registration_fa },
|
||||
en: { ...finish_registration_en },
|
||||
},
|
||||
account_page_title: {
|
||||
fa: { ...account_page_title_fa },
|
||||
en: { ...account_page_title_en },
|
||||
},
|
||||
account_page_description: {
|
||||
fa: { ...account_page_description_fa },
|
||||
en: { ...account_page_description_en },
|
||||
},
|
||||
profile_page_title: {
|
||||
fa: { ...profile_page_title_fa },
|
||||
en: { ...profile_page_title_en },
|
||||
},
|
||||
profile_page_description: {
|
||||
fa: { ...profile_page_description_fa },
|
||||
en: { ...profile_page_description_en },
|
||||
},
|
||||
login_page_title: {
|
||||
fa: { ...login_page_title_fa },
|
||||
en: { ...login_page_title_en },
|
||||
},
|
||||
login_page_description: {
|
||||
fa: { ...login_page_description_fa },
|
||||
en: { ...login_page_description_en },
|
||||
},
|
||||
logout_page_title: {
|
||||
fa: { ...logout_page_title_fa },
|
||||
en: { ...logout_page_title_en },
|
||||
},
|
||||
logout_page_description: {
|
||||
fa: { ...logout_page_description_fa },
|
||||
en: { ...logout_page_description_en },
|
||||
},
|
||||
register_page_title: {
|
||||
fa: { ...register_page_title_fa },
|
||||
en: { ...register_page_title_en },
|
||||
},
|
||||
register_page_description: {
|
||||
fa: { ...register_page_description_fa },
|
||||
en: { ...register_page_description_en },
|
||||
},
|
||||
email_confirm_page_title: {
|
||||
fa: { ...email_confirm_page_title_fa },
|
||||
en: { ...email_confirm_page_title_en },
|
||||
},
|
||||
email_confirm_page_description: {
|
||||
fa: { ...email_confirm_page_description_fa },
|
||||
en: { ...email_confirm_page_description_en },
|
||||
},
|
||||
phone_confirm_page_title: {
|
||||
fa: { ...phone_confirm_page_title_fa },
|
||||
en: { ...phone_confirm_page_title_en },
|
||||
},
|
||||
phone_confirm_page_description: {
|
||||
fa: { ...phone_confirm_page_description_fa },
|
||||
en: { ...phone_confirm_page_description_en },
|
||||
},
|
||||
reset_password_page_title: {
|
||||
fa: { ...reset_password_page_title_fa },
|
||||
en: { ...reset_password_page_title_en },
|
||||
},
|
||||
reset_password_page_description: {
|
||||
fa: { ...reset_password_page_description_fa },
|
||||
en: { ...reset_password_page_description_en },
|
||||
},
|
||||
change_password_page_title: {
|
||||
fa: { ...change_password_page_title_fa },
|
||||
en: { ...change_password_page_title_en },
|
||||
},
|
||||
change_password_page_description: {
|
||||
fa: { ...change_password_page_description_fa },
|
||||
en: { ...change_password_page_description_en },
|
||||
},
|
||||
search_profiles_page_title: {
|
||||
fa: { ...search_profiles_page_title_fa },
|
||||
en: { ...search_profiles_page_title_en },
|
||||
},
|
||||
search_profiles_page_description: {
|
||||
fa: { ...search_profiles_page_description_fa },
|
||||
en: { ...search_profiles_page_description_en },
|
||||
},
|
||||
};
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Page Configuration ...
|
||||
//
|
||||
export enum AccountRoutes {
|
||||
Login = 'login',
|
||||
Logout = 'logout',
|
||||
Default = 'account',
|
||||
Profile = 'profile',
|
||||
Register = 'register',
|
||||
EmailConfirm = 'email_confirm',
|
||||
PhoneConfirm = 'phone_confirm',
|
||||
ResetPassword = 'reset_password',
|
||||
ChangePassword = 'change_password',
|
||||
SearchProfiles = 'search_profiles',
|
||||
}
|
||||
|
||||
//
|
||||
export const Account: XSimplePage = {
|
||||
id: `${AccountRoutes.Default}`,
|
||||
name: `${AccountRoutes.Default}`,
|
||||
title: AccountResourceIDs.account_page_title,
|
||||
description: AccountResourceIDs.account_page_description,
|
||||
baseRoute: `${AccountRoutes.Default}`,
|
||||
route: ['/', `${AccountRoutes.Default}`],
|
||||
icon: XIconNames.collapse,
|
||||
childs: [
|
||||
//
|
||||
//#region Login ...
|
||||
{
|
||||
id: `${AccountRoutes.Login}`,
|
||||
name: `${AccountRoutes.Login}`,
|
||||
title: AccountResourceIDs.login_page_title,
|
||||
description: AccountResourceIDs.login_page_description,
|
||||
baseRoute: `${AccountRoutes.Login}`,
|
||||
route: ['/', `${AccountRoutes.Default}`, `${AccountRoutes.Login}`],
|
||||
icon: XIconNames.login,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Logout ...
|
||||
{
|
||||
id: `${AccountRoutes.Logout}`,
|
||||
name: `${AccountRoutes.Logout}`,
|
||||
title: AccountResourceIDs.logout_page_title,
|
||||
description: AccountResourceIDs.logout_page_description,
|
||||
baseRoute: `${AccountRoutes.Logout}`,
|
||||
route: ['/', `${AccountRoutes.Default}`, `${AccountRoutes.Logout}`],
|
||||
icon: XIconNames.logout,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Profile ...
|
||||
{
|
||||
id: `${AccountRoutes.Profile}`,
|
||||
name: `${AccountRoutes.Profile}`,
|
||||
title: AccountResourceIDs.profile_page_title,
|
||||
description: AccountResourceIDs.profile_page_description,
|
||||
baseRoute: `${AccountRoutes.Profile}`,
|
||||
route: ['/', `${AccountRoutes.Default}`, `${AccountRoutes.Profile}`],
|
||||
icon: XIconNames.register,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region Register ...
|
||||
{
|
||||
id: `${AccountRoutes.Register}`,
|
||||
name: `${AccountRoutes.Register}`,
|
||||
title: AccountResourceIDs.register_page_title,
|
||||
description: AccountResourceIDs.register_page_description,
|
||||
baseRoute: `${AccountRoutes.Register}`,
|
||||
route: ['/', `${AccountRoutes.Default}`, `${AccountRoutes.Register}`],
|
||||
icon: XIconNames.register,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region EmailConfirm ...
|
||||
{
|
||||
id: `${AccountRoutes.EmailConfirm}`,
|
||||
name: `${AccountRoutes.EmailConfirm}`,
|
||||
title: AccountResourceIDs.email_confirm_page_title,
|
||||
description: AccountResourceIDs.email_confirm_page_description,
|
||||
baseRoute: `${AccountRoutes.EmailConfirm}`,
|
||||
route: ['/', `${AccountRoutes.Default}`, `${AccountRoutes.EmailConfirm}`],
|
||||
icon: XIconNames.register,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region PhoneConfirm ...
|
||||
{
|
||||
id: `${AccountRoutes.PhoneConfirm}`,
|
||||
name: `${AccountRoutes.PhoneConfirm}`,
|
||||
title: AccountResourceIDs.phone_confirm_page_title,
|
||||
description: AccountResourceIDs.phone_confirm_page_description,
|
||||
baseRoute: `${AccountRoutes.PhoneConfirm}`,
|
||||
route: ['/', `${AccountRoutes.Default}`, `${AccountRoutes.PhoneConfirm}`],
|
||||
icon: XIconNames.register,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region ResetPassword ...
|
||||
{
|
||||
id: `${AccountRoutes.ResetPassword}`,
|
||||
name: `${AccountRoutes.ResetPassword}`,
|
||||
title: AccountResourceIDs.reset_password_page_title,
|
||||
description: AccountResourceIDs.reset_password_page_description,
|
||||
baseRoute: `${AccountRoutes.ResetPassword}`,
|
||||
route: [
|
||||
'/',
|
||||
`${AccountRoutes.Default}`,
|
||||
`${AccountRoutes.ResetPassword}`,
|
||||
],
|
||||
icon: XIconNames.register,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region ChangePassword ...
|
||||
{
|
||||
id: `${AccountRoutes.ChangePassword}`,
|
||||
name: `${AccountRoutes.ChangePassword}`,
|
||||
title: AccountResourceIDs.change_password_page_title,
|
||||
description: AccountResourceIDs.change_password_page_description,
|
||||
baseRoute: `${AccountRoutes.ChangePassword}`,
|
||||
route: [
|
||||
'/',
|
||||
`${AccountRoutes.Default}`,
|
||||
`${AccountRoutes.ChangePassword}`,
|
||||
],
|
||||
icon: XIconNames.register,
|
||||
},
|
||||
//#endregion
|
||||
|
||||
//
|
||||
//#region SearchProfiles ...
|
||||
{
|
||||
id: `${AccountRoutes.SearchProfiles}`,
|
||||
name: `${AccountRoutes.SearchProfiles}`,
|
||||
title: AccountResourceIDs.search_profiles_page_title,
|
||||
description: AccountResourceIDs.search_profiles_page_description,
|
||||
baseRoute: `${AccountRoutes.SearchProfiles}`,
|
||||
route: [
|
||||
'/',
|
||||
`${AccountRoutes.Default}`,
|
||||
`${AccountRoutes.SearchProfiles}`,
|
||||
],
|
||||
icon: XIconNames.register,
|
||||
},
|
||||
//#endregion
|
||||
],
|
||||
};
|
||||
//#endregion
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user