Initial Commit ...

This commit is contained in:
2026-04-17 17:04:44 +03:30
commit a986295e19
842 changed files with 97431 additions and 0 deletions
+129
View File
@@ -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 {}
+3
View File
@@ -0,0 +1,3 @@
<ion-app>
<ion-router-outlet></ion-router-outlet>
</ion-app>
View File
+17
View File
@@ -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(() => {});
}
}
+157
View File
@@ -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 { }
+209
View File
@@ -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,
};
+16
View File
@@ -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
+483
View File
@@ -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
+13
View File
@@ -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,
});
+9
View File
@@ -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');
+134
View File
@@ -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 {}
+5
View File
@@ -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>
+350
View File
@@ -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
}
+22
View File
@@ -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>
View File
+79
View File
@@ -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
}
+46
View File
@@ -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 {}
+13
View File
@@ -0,0 +1,13 @@
<!-- -->
<!-- Page Presenter -->
<!-- -->
<v-page-presenter
[containerBase]="this"
[contentTemplate]="contentTemplate"
></v-page-presenter>
<!-- -->
<!-- Page Content -->
<!-- -->
<ng-template #contentTemplate>
</ng-template>
View File
+56
View File
@@ -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
}
+13
View File
@@ -0,0 +1,13 @@
<!-- -->
<!-- Page Presenter -->
<!-- -->
<v-page-presenter
[containerBase]="this"
[contentTemplate]="contentTemplate"
></v-page-presenter>
<!-- -->
<!-- Page Content -->
<!-- -->
<ng-template #contentTemplate>
</ng-template>
+67
View File
@@ -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
}
+13
View File
@@ -0,0 +1,13 @@
<!-- -->
<!-- Page Presenter -->
<!-- -->
<v-page-presenter
[containerBase]="this"
[contentTemplate]="contentTemplate"
></v-page-presenter>
<!-- -->
<!-- Page Content -->
<!-- -->
<ng-template #contentTemplate>
</ng-template>
+180
View File
@@ -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
}
+46
View File
@@ -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 {}
+14
View File
@@ -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 {}
View File
+19
View File
@@ -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';
+261
View File
@@ -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;
}
}
+9
View File
@@ -0,0 +1,9 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
@NgModule({
declarations: [],
imports: [CommonModule],
exports: [CommonModule],
})
export class SharedModule {}
+3
View File
@@ -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;
}
View File
+756
View File
@@ -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