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
+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
@@ -0,0 +1,98 @@
<section
#vBaseDialogContainer
class="v-base-dialog"
[isForeground]="false"
[xColor]="getValue(backgroundColor) | async"
>
<!-- Title Toolbar -->
<section #vBaseDialogToolbar>
<!-- Toolbar -->
<ion-toolbar
#vToolbar
class="v-base-dialog-toolbar"
[xColor]="getValue(toolbarColor) | async"
>
<!-- Slots -->
<div class="v-base-dialog-toolbar-area">
<x-slotter>
<!-- Start -->
<x-slot
[name]="SlotNames.START"
[cssClass]="['ion-text-start', 'ion-float-start']"
>
<div
matRipple
(click)="handleClosePopup()"
[matTooltip]="getResourceValue(ResourceIDs.back) | async"
class="v-base-dialog-toolbar-item v-base-dialog-toolbar-button center-vertical-flex"
>
<x-icon
[name]="backIcon"
[loading]="loading"
[color]="'cb-inherit'"
[uiDisabled]="uiDisabled"
></x-icon>
</div>
</x-slot>
<!-- Center -->
<x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
<ion-title class="v-base-dialog-toolbar-item center-vertical-flex">
<h3>{{ getValue(fullName) | async }}</h3>
</ion-title>
</x-slot>
<!-- End -->
<x-slot
[name]="SlotNames.END"
[cssClass]="['ion-text-end', 'ion-float-end']"
>
<div
matRipple
(click)="handleSelectAction()"
*ngIf="
(notEmptyValue(userId) | async) &&
(sharedService.isNotMe(userId) | async) &&
(sharedService.isAuthenticated$ | async)
"
class="v-base-dialog-toolbar-item v-base-dialog-toolbar-button center-vertical-flex"
>
<x-icon
[name]="selectIcon"
[loading]="loading"
[color]="'cb-inherit'"
[uiDisabled]="uiDisabled"
[matTooltip]="getResourceValue(AppResourceIDs.profile) | async"
></x-icon>
</div>
</x-slot>
</x-slotter>
</div>
</ion-toolbar>
<!-- Progressbar -->
<ion-progress-bar
type="indeterminate"
*ngIf="getValue(showProgrssbar) | async"
[color]="getValue(progressbarColor) | async"
></ion-progress-bar>
</section>
<!-- Components -->
<section class="v-base-dialog-content">
<!-- Content -->
<ng-container *ngTemplateOutlet="contentRef"></ng-container>
</section>
</section>
<!-- -->
<!-- Template -->
<!-- -->
<!-- Content Template -->
<ng-template #contentRef>
<img
class="v-avatar-image animated zoomIn center-vertical"
[src]="getValue(avatarUrl) | async"
/>
</ng-template>
@@ -0,0 +1,63 @@
@import "../../../../theme/theme.scss";
:host {
--dialog-toolbar-height: 0px;
--background: var(-x-color-light);
}
x-icon {
--size: 24px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0 !important;
}
.v-base-dialog {
width: 100%;
height: 100%;
// height: calc(100% - var(--dialog-toolbar-height));
// margin-bottom: var(--dialog-toolbar-height);
}
.v-base-dialog-content {
height: 100%;
//
padding-bottom: var(--dialog-toolbar-height);
}
.v-base-dialog-toolbar-area {
margin: 8px;
}
.v-base-dialog-toolbar-item {
width: auto;
height: 48px;
}
.v-base-dialog-toolbar-button {
width: 32px;
margin: {
left: 4px;
right: 4px;
}
}
//
// Non Global ...
.v-avatar-image {
//
margin: auto;
display: block;
max-width: 100%;
max-height: 100%;
//
clip-path: circle();
}
@@ -0,0 +1,179 @@
import {
Input,
Component,
ViewChild,
ElementRef,
ChangeDetectionStrategy,
} from '@angular/core';
import {
XColorIdentifier,
isNullOrUndefined,
isNullOrEmptyString,
XColorWithBrightness,
} from 'x-framework-core';
import {
VAvatarCssVar,
VAvatarModalContext,
VAvatarReturnAction,
VAvatarModalContextIdentifier,
VAvatarReturnActionIdentifier,
} from './v-avatar.typings';
import { VBaseComponent } from '../../classes/v-base.component';
import { XIconNames, XSlotLayout, XSlotName } from 'x-framework-components';
/**
* a Component to Show User Avatar as Model ...
*/
@Component({
selector: 'v-avatar',
templateUrl: './v-avatar.component.html',
styleUrls: ['./v-avatar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VAvatarComponent extends VBaseComponent {
//
//#region Properties ...
//
readonly SlotNames = Object.assign({}, XSlotName);
readonly SlotLayouts = Object.assign({}, XSlotLayout);
/**
* retrieve Toolbar container ViewChild
* to Calculate Toolbar Height ...
*/
@ViewChild('vBaseDialogToolbar')
vBaseDialogToolbarContainer!: ElementRef;
/**
* Specified Modal Type ...
*/
@Input()
context: VAvatarModalContextIdentifier;
/**
* user Id ...
*/
@Input()
userId: string;
/**
* Specified Avatar Image Url ...
*/
@Input()
avatarUrl: string;
/**
* Specified User's Full Name ...
*/
@Input()
fullName: string;
/**
* Background Color of Component ...
*/
@Input()
backgroundColor: XColorIdentifier = XColorWithBrightness.Light;
/**
* Toolbar Color ...
*/
@Input()
toolbarColor: XColorIdentifier = XColorWithBrightness.PrimaryTint;
/**
* Progressbar Color ...
*/
@Input()
progressbarColor: XColorIdentifier = XColorWithBrightness.Warning;
showProgrssbar = false;
/**
* Action Icon Names Specifiecations ...
*/
@Input()
cancelIcon = XIconNames.close;
@Input()
selectIcon = XIconNames.profile;
@Input()
backIcon = XIconNames.arrow_back;
//#endregion
//
//#region LifeCycles ...
afterViewInit(): void {
super.afterViewInit();
//
this.applyContentSize();
}
/**
* Register Required Handlers ...
*/
registerInstanceHandlers(): void {
super.registerInstanceHandlers();
}
//#endregion
//
//#region UI Handlers ...
/**
* Use for Handle Modela Closing Action based on Context ...
* @returns
*/
async handleClosePopup(action?: VAvatarReturnActionIdentifier) {
//
if (isNullOrUndefined(this.context) || isNullOrEmptyString(this.context)) {
return;
}
//
switch (this.context) {
//
case VAvatarModalContext.Modal:
await this.managerService.dialogService.modalController.dismiss(action);
break;
//
case VAvatarModalContext.PopOver:
await this.managerService.dialogService.popoverController.dismiss(
action
);
break;
}
}
/**
* When User Clicked on Select Icon ...
*/
async handleSelectAction() {
await this.handleClosePopup(VAvatarReturnAction.OpenProfile);
}
//#endregion
//
//#region Private ...
/**
* Calculate Toolbar Height and add a CSSVar to
* use it for Content Sizing ...
*
* @returns
*/
private async applyContentSize() {
//
const height =
this.vBaseDialogToolbarContainer.nativeElement.getBoundingClientRect()
.height;
if (height === 0) {
setTimeout(() => this.applyContentSize(), 100);
return;
}
//
this.setCssVar(VAvatarCssVar.DialogToolbarHeight, `${height}px`);
this.detectChanges();
}
//#endregion
}
@@ -0,0 +1,16 @@
export enum VAvatarModalContext {
Modal = 'modal',
PopOver = 'pop_over',
}
export type VAvatarModalContextIdentifier = VAvatarModalContext | string;
export enum VAvatarCssVar {
DialogToolbarHeight = 'dialog-toolbar-height',
}
export enum VAvatarReturnAction {
OpenProfile = 'open_profile',
}
export type VAvatarReturnActionIdentifier = VAvatarReturnAction | string;
@@ -0,0 +1,191 @@
<div
class="v-friendship"
[xColor]="getValue(color) | async"
[ngClass]="getArrayValue(cssClass) | async"
[isForeground]="getValue(foregroundColor) | async"
>
<!-- Component -->
<section
[xColor]="getValue(color) | async"
[isForeground]="getValue(foregroundColor) | async"
*ngIf="(canShowInfo() | async) && (notNullOrUndefinedValue(model) | async)"
>
<!-- Friendship Info -->
<ng-container>
<!-- Follower/Following(s) -->
<ion-grid>
<ion-row class="ion-align-items-center">
<ion-col size="6" class="ion-text-center">
<h5
class="x-title"
[isForeground]="true"
[xColor]="getValue(labelColor) | async"
>
{{ resourceProvider(AppResourceIDs.followers) }}
</h5>
<h4
class="x-description"
[isForeground]="true"
[xColor]="getValue(valueColor) | async"
>
{{ getFollowersCount() | async }}
</h4>
</ion-col>
<ion-col size="6" class="ion-text-center">
<h5
class="x-title"
[isForeground]="true"
[xColor]="getValue(labelColor) | async"
>
{{ resourceProvider(AppResourceIDs.followings) }}
</h5>
<h4
class="x-description"
[isForeground]="true"
[xColor]="getValue(valueColor) | async"
>
{{ getFollowingsCount() | async }}
</h4>
</ion-col>
</ion-row>
</ion-grid>
<!-- Friendship State -->
<ng-container *ngIf="canShowState() | async">
<dl
*ngIf="isNotMe() | async"
class="v-friendship-state ion-no-margin"
[class.inline]="isNotMobileUi$ | async"
>
<!-- Friendship State -->
<dt
class="x-title"
[isForeground]="true"
[xColor]="getValue(labelColor) | async"
>
{{ resourceProvider(AppResourceIDs.friendship_state) }}
</dt>
<dd
class="x-description"
[isForeground]="true"
[xColor]="getValue(valueColor) | async"
>
{{ getValue(friendshipState) | async }}
</dd>
</dl>
</ng-container>
</ng-container>
</section>
<!-- Friendship Actions -->
<section
[xColor]="getValue(color) | async"
*ngIf="
(canShowActions() | async) &&
(notEmptyValue(actionType) | async) &&
(hasChildValue(friendshipActions) | async)
"
[isForeground]="getValue(foregroundColor) | async"
class="v-friendship-actions-container center-vertical-flex"
>
<x-slotter
[hasCenterSlot]="false"
[layout]="SlotLayouts.HORIZONTAL"
[endBottomSlotCssClass]="'dynamic-slot'"
>
<!-- START -->
<!-- Button/Fab(s) -->
<x-slot [name]="SlotNames.START" [cssClass]="'ion-text-start'">
<!-- AsButton -->
<section
[class.mobile]="isMobileUi$ | async"
*ngIf="canShowFriendshipActions() | async"
class="v-friendship-actions ion-text-center"
>
<!-- Loop through Actions -->
<ng-container
*ngFor="let ad of getArrayValue(friendshipActions) | async"
>
<ng-container
*ngTemplateOutlet="
actionButtonRef;
context: {
descriptor: ad,
buttonType:
actionType === FriendshipActionsPresentTypes.AsFAB ||
(actionType ===
FriendshipActionsPresentTypes.AsMenuAndFab &&
(isNotMobileUi$ | async))
? ButtonTypes.Icon
: actionType === FriendshipActionsPresentTypes.AsButton ||
(actionType ===
FriendshipActionsPresentTypes.AsMenuAndButton &&
(isNotMobileUi$ | async))
? ButtonTypes.Raised
: ButtonTypes.Icon
}
"
></ng-container>
</ng-container>
</section>
</x-slot>
<!-- END -->
<!-- Menu -->
<x-slot [name]="SlotNames.END" [cssClass]="'ion-text-end'">
<!-- Menu Only Used when -->
<ng-container
*ngIf="
actionType === FriendshipActionsPresentTypes.AsMenu ||
((actionType === FriendshipActionsPresentTypes.AsMenuAndFab ||
actionType === FriendshipActionsPresentTypes.AsMenuAndButton) &&
(isMobileUi$ | async))
"
>
<x-button
[type]="'icon'"
[loading]="loading"
[color]="'cb-inherit'"
[uiDisabled]="uiDisabled || loading"
(click)="handleFriendshipActionsMenuClicked($event)"
>
<x-icon
[loading]="loading"
[foregroundColor]="true"
[color]="ColorNames.Dark"
[name]="IconNames.menu_vertical"
[uiDisabled]="uiDisabled || loading"
></x-icon>
</x-button>
</ng-container>
</x-slot>
</x-slotter>
</section>
</div>
<!-- Nothing Template -->
<ng-template #nothingRef></ng-template>
<!-- -->
<!-- Actions Templates -->
<!-- -->
<!-- Button Template -->
<ng-template
#actionButtonRef
let-descriptor="descriptor"
let-buttonType="buttonType"
>
<x-button
[type]="buttonType"
[loading]="loading"
(click)="descriptor.handler()"
class="v-friendship-action-button"
[class.mobile]="isMobileUi$ | async"
[uiDisabled]="uiDisabled || loading"
[iconColor]="getValue(descriptor.color) | async"
[icon]="getValue(descriptor.icon) | async"
[color]="getValue(descriptor.color) | async"
[title]="getResourceValue(descriptor.title) | async"
></x-button>
</ng-template>
@@ -0,0 +1,43 @@
@import "../../../../theme/theme.scss";
//
.v-friendship {
width: 100%;
display: inline-block;
}
//
.v-friendship-actions,
.v-friendship-actions-container,
.v-friendship-actions-menu-button {
display: inline-block;
}
//
.v-friendship-state,
.v-friendship-actions-container {
width: 100%;
margin: {
top: 6px;
bottom: 6px;
}
}
//
.v-friendship-state {
text-align: center;
}
//
.v-friendship-action-button {
margin: {
left: 3px;
right: 3px;
}
}
//
.x-title,
.x-description {
display: block;
}
@@ -0,0 +1,627 @@
import {
Input,
Output,
Component,
EventEmitter,
ChangeDetectionStrategy,
} from '@angular/core';
import {
nameof,
XOneOrManyType,
XColorIdentifier,
isNullOrUndefined,
isNullOrEmptyString,
XColorWithBrightness,
} from 'x-framework-core';
import {
FriendshipAction,
VFriendshipEventModel,
FriendshipActionDescriptor,
FriendshipActionsPresentType,
defaultFriendshipBlockDescriptor,
defaultFriendshipRejectDescriptor,
defaultFriendshipCancelDescriptor,
defaultFriendshipAcceptDescriptor,
defaultFriendshipUnblockDescriptor,
defaultFriendshipUnFollowDescriptor,
FriendshipActionsPresentTypeIdentifier,
defaultFriendshipFollowActionDescriptor,
} from './v-friendship.typings';
import {
XSlotName,
XButtonType,
XSlotLayout,
XPopoverOption,
XPopoverItemOptionSlot,
} from 'x-framework-components';
import {
XFriendshipType,
XFriendshipState,
XFriendshipInfoDto,
} from 'x-framework-identity-sdk';
import { concatMap, filter, map } from 'rxjs/operators';
import { FriendshipPresentType } from './v-friendship.typings';
import { VBaseComponent } from '../../classes/v-base.component';
/**
* Represent Friendship Info ...
*/
@Component({
// tslint:disable-next-line:component-selector
selector: 'v-friendship',
templateUrl: './v-friendship.component.html',
styleUrls: ['./v-friendship.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VFriendshipComponent extends VBaseComponent {
//
//#region Props ...
//
readonly SlotNames = Object.assign({}, XSlotName);
readonly SlotLayouts = Object.assign({}, XSlotLayout);
readonly ButtonTypes = Object.assign({}, XButtonType);
readonly FriendshipActionsPresentTypes = Object.assign(
{},
FriendshipActionsPresentType
);
readonly PresentTypes = Object.assign({}, FriendshipPresentType);
//
friendshipState: string;
friendshipActions: Array<FriendshipActionDescriptor> = [];
//
@Input()
cssClass: XOneOrManyType<string> = [];
//
@Input()
color: XColorIdentifier = XColorWithBrightness.Light;
@Input()
foregroundColor: boolean = false;
@Input()
labelColor: XColorIdentifier = XColorWithBrightness.Primary;
@Input()
valueColor: XColorIdentifier = XColorWithBrightness.Dark;
//
@Input()
showFriendshipState: boolean = true;
//
@Input()
presentType: FriendshipPresentType = FriendshipPresentType.AsProfile;
//
@Input()
actionType: FriendshipActionsPresentTypeIdentifier =
FriendshipActionsPresentType.AsButton;
//
@Input()
model: XFriendshipInfoDto;
//
//#region Events ...
@Output()
actionFired = new EventEmitter<VFriendshipEventModel>();
//#endregion
//#endregion
//
//#region Constructor ...
onChange(changeKeys: string[]) {
super.onChange(changeKeys);
//
//#region Model Changed ...
const isModelChanged = changeKeys.includes(
nameof<VFriendshipComponent>('model')
);
const isPresentTypeChanged = changeKeys.includes(
nameof<VFriendshipComponent>('presentType')
);
if (isModelChanged || isPresentTypeChanged) {
this.handlePrepareView();
}
//#endregion
}
//#endregion
//
//#region LifeCycles ...
//#endregion
//
//#region Handlers ...
//#endregion
//
//#region Task Handlers ...
//#endregion
//
//#region UI Providers ...
//
canShowInfo() {
return this.getValue(this.presentType).pipe(
map(
(pt) =>
pt === this.PresentTypes.AsProfile || pt === this.PresentTypes.AsInfo
)
);
}
//
canShowState() {
return this.getValue(this.presentType).pipe(
map(
(pt) =>
pt === this.PresentTypes.AsProfile || pt === this.PresentTypes.AsState
),
map(
(canShow) =>
canShow &&
this.showFriendshipState &&
!isNullOrEmptyString(this.friendshipState)
)
);
}
//
canShowActions() {
return this.getValue(this.presentType).pipe(
map(
(pt) =>
pt === this.PresentTypes.AsProfile ||
pt === this.PresentTypes.AsFullActions ||
pt === this.PresentTypes.AsFollowerActions ||
pt === this.PresentTypes.AsFollowingActions
)
);
}
//
canShowFriendshipActions() {
return this.getValue(this.canShowActions()).pipe(
map(
(canShow) =>
canShow &&
this.actionType !== this.FriendshipActionsPresentTypes.AsMenu
)
);
}
//
canShowFollowerActions() {
return this.getValue(this.presentType).pipe(
map(
(pt) =>
pt === this.PresentTypes.AsProfile ||
pt === this.PresentTypes.AsFullActions ||
pt === this.PresentTypes.AsFollowerActions
)
);
}
//
canShowFollowingActions() {
return this.getValue(this.presentType).pipe(
map(
(pt) =>
pt === this.PresentTypes.AsProfile ||
pt === this.PresentTypes.AsFullActions ||
pt === this.PresentTypes.AsFollowingActions
)
);
}
/**
* Friendship Info not for Current User ...
*/
isNotMe() {
return this.getValue(this.model).pipe(
filter((info) => !!info),
concatMap((info) => this.sharedService.authService.isNotMe(info.userId))
);
}
/**
* get Followers Count in current locale ...
*/
getFollowersCount() {
return this.getValue(this.model).pipe(
map((info) => {
return this.applyLocale(info ? info.followers.toString() : '0');
})
);
}
/**
* get Followings count in current locale ...
*/
getFollowingsCount() {
return this.getValue(this.model).pipe(
map((info) => {
return this.applyLocale(info ? info.followings.toString() : '0');
})
);
}
//#endregion
//
//#region UI Handlers ...
/**
* when user Click on friendship actions menu item ...
*
* @param event
*/
async handleFriendshipActionsMenuClicked(event: any) {
//
// Common Options ...
const onlyIcon = false;
const slot: XPopoverItemOptionSlot = 'start';
//
// Menu Popover Actions ...
const options: XPopoverOption[] = this.friendshipActions.map((fd) => {
return {
slot,
icon: fd.icon,
color: fd.color,
title: fd.title,
id: fd.identifier,
onlyIcon: onlyIcon,
handler: fd.handler,
disabled: this.uiDisabled || this.loading,
} as XPopoverOption;
});
//
if (!this.hasChild(options)) {
return;
}
//
// Present Context Menu ...
await this.popoverService.presentContextMenu(options, event);
}
//#endregion
//
//#region Overrides ...
/**
* Handle Loading Event ...
*
* @param loading
*/
onLoading(loading: boolean): void {
super.onLoading(loading);
//
if (loading) {
this.handleUiState(true);
} else {
this.handleUiState(false);
}
}
/**
* Handle Disabled Event ...
*
* @param isDisabled
*/
onUiDisabled(isDisabled: boolean): void {
super.onUiDisabled(isDisabled);
//
if (isDisabled) {
this.handleUiState(true);
} else {
this.handleUiState(false);
}
}
//#endregion
//
//#region Actions ...
//#endregion
//
//#region Private ...
/**
* do all requirement preparation when a model
* attached to view ...
*/
private handlePrepareView() {
//
// Check Model Exists ...
if (isNullOrUndefined(this.model)) {
return;
}
//
// Generate Friendship State ...
if (this.model.isFollower && this.model.isFollowing) {
this.friendshipState = this.resourceProvider(this.AppResourceIDs.friend);
} else if (this.model.isFollower) {
this.friendshipState = this.resourceProvider(
this.AppResourceIDs.follower
);
} else if (this.model.isFollowing) {
this.friendshipState = this.resourceProvider(
this.AppResourceIDs.following
);
}
//
// Checking Actions ...
const hasActions = [
this.PresentTypes.AsProfile,
this.PresentTypes.AsFullActions,
this.PresentTypes.AsFollowerActions,
this.PresentTypes.AsFollowingActions,
].includes(this.presentType);
const hasFollowerActions =
hasActions &&
[
this.PresentTypes.AsProfile,
this.PresentTypes.AsFullActions,
this.PresentTypes.AsFollowerActions,
].includes(this.presentType);
const hasFollowingActions =
hasActions &&
[
this.PresentTypes.AsProfile,
this.PresentTypes.AsFullActions,
this.PresentTypes.AsFollowingActions,
].includes(this.presentType);
//
// Check Allow Actions Preparation or not ...
if (hasActions) {
//
const followerActions: Array<FriendshipAction> = [];
const followingActions: Array<FriendshipAction> = [];
//
// Check and Prepare Following Actions ...
if (hasFollowingActions) {
//
// Follow Action ...
const canFollow = [
XFriendshipState.None,
XFriendshipState.Rejected,
].includes(this.model.followingState);
if (canFollow) {
followingActions.push(FriendshipAction.Follow);
}
//
// Cancel Action ...
const canCancel = [
XFriendshipState.Pending,
XFriendshipState.Rejected,
].includes(this.model.followingState);
if (canCancel) {
followingActions.push(FriendshipAction.Cancel);
}
//
// UnFollow ...
const canUnfollow =
this.model.followingState === XFriendshipState.Accepted;
if (canUnfollow) {
followingActions.push(FriendshipAction.UnFollow);
}
}
//
// Check and Prepare Follower Actions ...
if (hasFollowerActions) {
//
// Handle Accept Action ...
const canAccept = this.model.followerState === XFriendshipState.Pending;
if (canAccept) {
followerActions.push(FriendshipAction.Accept);
}
//
// Handle Reject Action ...
const canReject = this.model.followerState === XFriendshipState.Pending;
if (canReject) {
followerActions.push(FriendshipAction.Reject);
}
//
// Handle Block Action ...
const canBlock = this.model.followerState === XFriendshipState.Accepted;
if (canBlock) {
followerActions.push(FriendshipAction.Block);
}
//
// Handle UnBlock Action .../
const canUnblock =
this.model.followerState === XFriendshipState.Blocked;
if (canUnblock) {
followerActions.push(FriendshipAction.UnBlock);
}
//
// Handle UnFollow Action ...
const canUnfollow =
this.model.followerState === XFriendshipState.Accepted;
if (canUnfollow) {
followerActions.push(FriendshipAction.UnFollow);
}
}
//
// Check Actions ...
if (this.hasChild(followerActions) || this.hasChild(followingActions)) {
this.prepareActions(followerActions, followingActions);
}
}
}
/**
* Preparing Require Action Descriptors ...
*
* @param follower
* @param following
* @returns
*/
private prepareActions(
follower: Array<FriendshipAction>,
following: Array<FriendshipAction>
) {
//
this.friendshipActions = [];
if (isNullOrUndefined(this.model)) {
this.detectChanges();
return;
}
//
let actions: Array<FriendshipActionDescriptor> = [];
//
// Prepare Follower Actions ...
if (this.hasChild(follower)) {
//
actions = [
...actions,
...follower.map((identifier) =>
this.getActionDescriptor(XFriendshipType.Follower, identifier)
),
];
}
//
// Prepare Following Actions ...
if (this.hasChild(following)) {
//
actions = [
...actions,
...following.map((identifier) =>
this.getActionDescriptor(XFriendshipType.Following, identifier)
),
];
}
//
if (this.hasChild(actions)) {
this.friendshipActions = [...actions];
}
//
this.detectChanges();
}
/**
* Prepare and Retrieve Specified Action Desxcriptor ...
*
* @param type
* @param action
* @returns
*/
private getActionDescriptor(type: XFriendshipType, action: FriendshipAction) {
let result: FriendshipActionDescriptor;
switch (action) {
//
case FriendshipAction.Accept:
result = {
...defaultFriendshipAcceptDescriptor,
};
break;
//
case FriendshipAction.Reject:
result = {
...defaultFriendshipRejectDescriptor,
};
break;
//
case FriendshipAction.Block:
result = {
...defaultFriendshipBlockDescriptor,
};
break;
//
case FriendshipAction.UnBlock:
result = {
...defaultFriendshipUnblockDescriptor,
};
break;
//
case FriendshipAction.Cancel:
result = {
...defaultFriendshipCancelDescriptor,
};
break;
//
case FriendshipAction.Follow:
result = {
...defaultFriendshipFollowActionDescriptor,
};
break;
//
case FriendshipAction.UnFollow:
//
// Here we have to Change Title of
// Default action based on Given Type ...
result = {
...defaultFriendshipUnFollowDescriptor,
//
title:
type === XFriendshipType.Follower
? this.AppResourceIDs.unfollow_follower
: type === XFriendshipType.Following
? this.AppResourceIDs.unfollow_following
: defaultFriendshipFollowActionDescriptor.title,
};
break;
}
//
// Attach Requirements to Default Descriptors ...
//
// Set Friendship Type ...
result.type = type;
//
// Prepare Action Model ...
const actionModel: VFriendshipEventModel = {
type,
action: action,
destUser: this.model.userId,
};
//
// Set Handler to Fire Event ...
result.handler = () => {
this.actionFired.emit(actionModel);
};
//
return result;
}
/**
* handle ui state changed event ...
*
* @param disabled
*/
private async handleUiState(disabled: boolean) {}
//#endregion
}
@@ -0,0 +1,416 @@
import {
isNullOrUndefined,
XResourceIdentifier,
isNullOrEmptyString,
hasTaskId,
} from 'x-framework-core';
import {
FriendshipActionDescriptor,
defaultFriendshipBlockDescriptor,
defaultFriendshipCancelDescriptor,
defaultFriendshipAcceptDescriptor,
defaultFriendshipRejectDescriptor,
defaultFriendshipUnblockDescriptor,
defaultFriendshipUnFollowDescriptor,
defaultFriendshipFollowActionDescriptor,
} from './v-friendship.typings';
import {
XFriendDto,
XUserProfileDto,
XFriendshipType,
XFriendshipState,
XFriendshipInfoDto,
} from 'x-framework-identity-sdk';
import { AppResourceIDs } from 'src/app/config/localization.config';
const defaultUserProfileFullName = '...';
const defaultUserAvatar = '/assets/image/default-user-image.png';
const defaultPlaceHolderImage = '/assets/image/img-placeholder.png';
/**
* retrieve a XFriendshipInfoDto instance Object's Friendship state Resource ID ...
*
* @param model
* @returns
*/
export function getFriendshipStateResourceID(model: XFriendshipInfoDto) {
//
let result: XResourceIdentifier = undefined;
//
if (isNullOrUndefined(model)) {
return result;
}
//
if (!!model.isFollower && !!model.isFollowing) {
result = AppResourceIDs.friend;
} else if (!!model.isFollower) {
result = AppResourceIDs.follower;
} else if (!!model.isFollowing) {
result = AppResourceIDs.following;
}
//
return result;
}
/**
* Prepare User Profile Full Name ...
*
* @param model
* @returns
*/
export function getFullName(model: XUserProfileDto) {
//
if (
isNullOrUndefined(model) ||
((isNullOrUndefined(model.firstName) ||
isNullOrEmptyString(model.firstName)) &&
(isNullOrUndefined(model.lastName) ||
isNullOrEmptyString(model.lastName)))
) {
return defaultUserProfileFullName;
}
//
return `${model.firstName} ${model.lastName}`;
}
/**
* Retrieve Specified FriendshipType's Resource ID ...
*
* @param type
* @returns
*/
export function getFriendshipTypeResourceID(type: XFriendshipType) {
//
let result: XResourceIdentifier;
//
// Validate Arg ...
if (isNullOrUndefined(type)) {
return result;
}
//
switch (type) {
//
case XFriendshipType.Follower:
result = AppResourceIDs.follower;
break;
//
case XFriendshipType.Following:
result = AppResourceIDs.following;
break;
}
//
return result;
}
/**
* Retrieve Specified FrindshipState's Resource ID ...
* (also based on FriendshipType if provided)
*
* @param state
* @param type
* @returns
*/
export function getFriendshipStateByTypeResourceID(
state: XFriendshipState,
type?: XFriendshipType
) {
//
let result: XResourceIdentifier;
//
// Validate Arg ...
if (isNullOrUndefined(state)) {
return result;
}
//
switch (state) {
//
case XFriendshipState.None:
result = AppResourceIDs.unknown;
break;
//
case XFriendshipState.Accepted:
//
if (isNullOrUndefined(type)) {
result = AppResourceIDs.accepted;
} else if (type === XFriendshipType.Follower) {
result = AppResourceIDs.follower;
} else if (type === XFriendshipType.Following) {
result = AppResourceIDs.following;
} else {
result = AppResourceIDs.accepted;
}
break;
//
case XFriendshipState.Rejected:
result = AppResourceIDs.rejected;
break;
//
case XFriendshipState.Pending:
//
if (isNullOrUndefined(type)) {
result = AppResourceIDs.pending;
} else if (type === XFriendshipType.Follower) {
result = AppResourceIDs.pending_follower;
} else if (type === XFriendshipType.Following) {
result = AppResourceIDs.pending_following;
} else {
result = AppResourceIDs.pending;
}
break;
//
case XFriendshipState.Blocked:
result = AppResourceIDs.blocked;
break;
}
//
return result;
}
/**
* retrieve a XUserProfileDto instance Object's Friendship state Resource ID ...
*
* @param model
* @returns
*/
export function getProfileFriendshipStateResourceID(model: XUserProfileDto) {
//
let result: XResourceIdentifier = undefined;
//
if (!isNullOrUndefined(model) && !isNullOrUndefined(model.friendshipInfo)) {
result = getFriendshipStateResourceID(model.friendshipInfo);
}
//
return result;
}
/**
* Retrieve Required Actions Descriptors based on FriendDto ...
* these are Default Actions and Must be reviewed ...
*
* @param item
* @returns
*/
export function parseFriendAction(item: XFriendDto) {
//
const result: Array<FriendshipActionDescriptor> = [];
//
// Collect Default Actions Based On Friendship Type ...
if (item.type === XFriendshipType.Follower) {
//
// Accept ...
if (canAcceptFriendshipState(item.state)) {
result.push({ ...defaultFriendshipAcceptDescriptor });
}
//
// Reject ...
if (canRejectFriendshipState(item.state)) {
result.push({ ...defaultFriendshipRejectDescriptor });
}
//
// Block ...
if (canBlockFriendshipState(item.state)) {
result.push({ ...defaultFriendshipBlockDescriptor });
}
//
// Unblock ...
if (canUnblockFriendshipState(item.state)) {
result.push({ ...defaultFriendshipUnblockDescriptor });
}
//
// UnFollow ...
if (canUnFollowFriendshipState(item.state)) {
result.push({ ...defaultFriendshipUnFollowDescriptor });
}
} else if (item.type === XFriendshipType.Following) {
//
// Follow ...
if (canFollowFriendshipState(item.state)) {
result.push({ ...defaultFriendshipFollowActionDescriptor });
}
//
// Cancel ...
if (canCancelFriendshipState(item.state)) {
result.push({ ...defaultFriendshipCancelDescriptor });
}
//
// UnFollow ...
if (canUnFollowFriendshipState(item.state)) {
result.push({ ...defaultFriendshipUnFollowDescriptor });
}
}
//
return result;
}
/**
* get Model Full Name ...
*
* @param model
* @returns
*/
export function getFullNameOfFriend(model: XFriendDto) {
//
let result = '';
//
if (isNullOrUndefined(model)) {
return result;
}
//
result = `${model.firstname} ${model.lastname}`;
//
return result;
}
/**
* Check Can Follow or not ...
*
* @param state
* @returns
*/
export function canFollowFriendshipState(state: XFriendshipState) {
return [XFriendshipState.None, XFriendshipState.Rejected].includes(state);
}
/**
* Check Can Cancel or not ...
*
* @param state
* @returns
*/
export function canCancelFriendshipState(state: XFriendshipState) {
return [XFriendshipState.Pending, XFriendshipState.Rejected].includes(state);
}
/**
* Check Can UnFollow or not ...
*
* @param state
* @returns
*/
export function canUnFollowFriendshipState(state: XFriendshipState) {
return [XFriendshipState.Accepted].includes(state);
}
/**
* Check Can Block or not ...
*
* @param state
* @returns
*/
export function canBlockFriendshipState(state: XFriendshipState) {
return [XFriendshipState.Accepted].includes(state);
}
/**
* Check Can UnBlock or not ...
*
* @param state
* @returns
*/
export function canUnblockFriendshipState(state: XFriendshipState) {
return [XFriendshipState.Blocked].includes(state);
}
/**
* Check Can Accept or not ...
*
* @param state
* @returns
*/
export function canAcceptFriendshipState(state: XFriendshipState) {
return [XFriendshipState.Pending].includes(state);
}
/**
* Check Can Reject or not ...
*
* @param state
* @returns
*/
export function canRejectFriendshipState(state: XFriendshipState) {
return [XFriendshipState.Pending].includes(state);
}
//
//#region Friendship Tasks ...
/**
* All Available Friendship Tasks ...
*/
export enum XFriendshipTasks {
Block = 'block',
Follow = 'follow',
Accept = 'accept',
Reject = 'reject',
Cancel = 'cancel',
UnBlock = 'un_block',
LoadProfile = 'load_profile',
UnFollowFollower = 'un_follow_follower',
UnFollowFollowing = 'un_follow_following',
}
export type XFriendshipTasksIdentifier = XFriendshipTasks | string;
/**
* export an array of all available Friendship Tasks ...
*
* @returns
*/
export function getFriendshipTasks() {
return [
XFriendshipTasks.Block,
XFriendshipTasks.Follow,
XFriendshipTasks.Accept,
XFriendshipTasks.Reject,
XFriendshipTasks.Cancel,
XFriendshipTasks.UnBlock,
XFriendshipTasks.LoadProfile,
XFriendshipTasks.UnFollowFollower,
XFriendshipTasks.UnFollowFollowing,
];
}
/**
* Check a Task Name is Friendship Task or not ...
*
* @param name
* @returns
*/
export function isFriendshipTask(name: XFriendshipTasksIdentifier) {
//
const allTasks = getFriendshipTasks();
const result = allTasks.find(
(t) => name === t || (hasTaskId(name) && name.includes(t))
);
//
return result;
}
//#endregion
@@ -0,0 +1,175 @@
import {
XColorIdentifier,
XResourceIdentifier,
XColorWithBrightness,
} from 'x-framework-core';
import { XIconNames } from 'x-framework-components';
import { XFriendshipType } from 'x-framework-identity-sdk';
import { AppResourceIDs } from 'src/app/config/localization.config';
/**
* Represent a Frendship Action Descriptor ...
*/
export interface FriendshipActionDescriptor {
icon: string;
payload?: string;
handler?: () => void;
type: XFriendshipType;
color: XColorIdentifier;
title: XResourceIdentifier;
identifier: FriendshipAction;
}
export type FriendshipTypeIdentifier = XFriendshipType | string;
/**
* Represent Friendship Actions ...
*/
export enum FriendshipAction {
Follow = 'follow',
Cancel = 'cancel',
Accept = 'accept',
Reject = 'reject',
Block = 'block',
UnBlock = 'unblock',
UnFollow = 'unfollow',
}
export type FriendshipActionIdentifier = FriendshipAction | string;
/**
* How to Represent Actions in Friendship View ...
*/
export enum FriendshipActionsPresentType {
AsFAB = 'AsFAB',
AsMenu = 'AsMenu',
AsButton = 'AsButton',
AsMenuAndFab = 'AsMenuAndFab',
AsMenuAndButton = 'AsMenuAndButton',
}
export type FriendshipActionsPresentTypeIdentifier =
| FriendshipActionsPresentType
| string;
/**
* Action Event Model ...
*/
export interface VFriendshipEventModel {
destUser: string;
type: FriendshipTypeIdentifier;
action: FriendshipActionIdentifier;
}
/**
* All Available Present Types for Friendship View ...
*/
export enum FriendshipPresentType {
/**
* only shown follwer/following(s) count ...
*/
AsInfo = 'as_info',
/**
* represent current friendship state ...
*/
AsState = 'as_state',
/**
* contains all available actions ...
*/
AsProfile = 'as_profile',
/**
* contains only actions ...
*/
AsFullActions = 'as_full_actions',
/**
* contains only follower actions ...
*/
AsFollowerActions = 'as_follower_actions',
/**
* contains only following actions ...
*/
AsFollowingActions = 'as_following_actions',
}
export type FriendshipPresentTypeIdentifier = FriendshipPresentType | string;
//
// Here we implemenmt all required Default Action Descriptors ...
/**
* Default Follow Action ...
*/
export const defaultFriendshipFollowActionDescriptor: FriendshipActionDescriptor =
{
title: AppResourceIDs.follow,
type: XFriendshipType.Following,
icon: XIconNames.friendship_reuest,
identifier: FriendshipAction.Follow,
color: XColorWithBrightness.PrimaryShade,
};
/**
* Default Cancel Action ...
*/
export const defaultFriendshipCancelDescriptor: FriendshipActionDescriptor = {
title: AppResourceIDs.cancel_request,
type: XFriendshipType.Follower,
icon: XIconNames.friendship_cancel,
identifier: FriendshipAction.Cancel,
color: XColorWithBrightness.WarningShade,
};
/**
* Default UnFollow Action ...
*/
export const defaultFriendshipUnFollowDescriptor: FriendshipActionDescriptor = {
title: AppResourceIDs.unfollow,
type: XFriendshipType.Follower,
icon: XIconNames.friendship_unfollow,
identifier: FriendshipAction.UnFollow,
color: XColorWithBrightness.DangerShade,
};
/**
* Default Accept Action ...
*/
export const defaultFriendshipAcceptDescriptor: FriendshipActionDescriptor = {
title: AppResourceIDs.accept_request,
type: XFriendshipType.Follower,
icon: XIconNames.friendship_accept,
identifier: FriendshipAction.Accept,
color: XColorWithBrightness.SuccessShade,
};
/**
* Default Reject Action ...
*/
export const defaultFriendshipRejectDescriptor: FriendshipActionDescriptor = {
title: AppResourceIDs.cancel_request,
type: XFriendshipType.Follower,
icon: XIconNames.friendship_reject,
identifier: FriendshipAction.Reject,
color: XColorWithBrightness.DangerShade,
};
/**
* Default Block Action ...
*/
export const defaultFriendshipBlockDescriptor: FriendshipActionDescriptor = {
title: AppResourceIDs.block,
type: XFriendshipType.Follower,
icon: XIconNames.friendship_block,
identifier: FriendshipAction.Block,
color: XColorWithBrightness.DangerShade,
};
/**
* Default Unblock Action ...
*/
export const defaultFriendshipUnblockDescriptor: FriendshipActionDescriptor = {
title: AppResourceIDs.unblock,
type: XFriendshipType.Follower,
icon: XIconNames.friendship_unblock,
identifier: FriendshipAction.UnBlock,
color: XColorWithBrightness.PrimaryShade,
};
@@ -0,0 +1 @@
<v-dto [loading]="loading" [uiDisabled]="uiDisabled" #dtoPresenter [dtoContainer]="this"></v-dto>
@@ -0,0 +1 @@
@@ -0,0 +1,379 @@
import {
Output,
Component,
EventEmitter,
ChangeDetectionStrategy,
} from '@angular/core';
import {
getFieldNames,
XStandardType,
XExceptionIDs,
isNullOrUndefined,
isNullOrEmptyString,
} from 'x-framework-core';
import {
XFormControlType,
XFormControlConfig,
XFormControlAppearance,
} from 'x-framework-components';
import { Validators } from '@angular/forms';
import { XLoginRequestDto } from 'x-framework-identity-sdk';
import {
VBaseDtoComponent,
VBaseDtoModelAction,
VBaseDtoModelFiredActionModel,
VBaseDtoPresentType,
VModelFieldDescriptor,
VModelValidationResult,
} from '../../v-dto/v-dto.typings';
import { Subject } from 'rxjs';
@Component({
// tslint:disable-next-line:component-selector
selector: 'v-login',
templateUrl: './v-login.component.html',
styleUrls: ['./v-login.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VLoginComponent extends VBaseDtoComponent<XLoginRequestDto> {
//
//#region Props ...
//
@Output()
login: EventEmitter<void> = new EventEmitter<void>();
//
readonly FormControlTypes = Object.assign({}, XFormControlType);
readonly FormControlAppearances = Object.assign({}, XFormControlAppearance);
readonly title = this.resourceProvider(this.AppResourceIDs.login_page_title);
//
isInPage = true;
wrapWithCard = true;
showFieldsForm = false;
cardShowActions = true;
passwordVisible = false;
showValidationErrors = false;
showFormCancelButton = false;
presentType = VBaseDtoPresentType.AsForm;
cardTitle = this.AppResourceIDs.login_page_title;
formActionButtonAddResource = this.AppResourceIDs.login;
formActionButtonUpdateResource = this.AppResourceIDs.login;
//
defaultModel: XLoginRequestDto = {
userSelectBy: '',
password: '',
device: undefined,
language: undefined,
};
readonly FieldNames = getFieldNames(this.defaultModel);
/**
* Describe Model ...
*/
defaultFieldDescriptors: VModelFieldDescriptor<any>[] = [
//
// UserSelect By ...
{
hide: false,
hideLabel: false,
allowFieldForm: true,
key: this.FieldNames.userSelectBy,
type: this.ModelFieldTypes.String,
value: this.defaultModel.userSelectBy,
label: this.AppResourceIDs.user_identifier,
formControlConfig: {
index: 0,
propName: this.FieldNames.userSelectBy,
type: {
type: this.FormControlTypes.Text,
config: {},
},
validators: {
validators: [Validators.required],
},
focusHandler: new Subject(),
eventHandlers: {},
appearance: {
hidden: false,
disabled: false,
// label: this.AppResourceIDs.user_identifier,
appearance: this.FormControlAppearances.Outline,
placeholder: this.AppResourceIDs.user_identifier,
tooltip: this.AppResourceIDs.user_identifier_description,
icons: {
prefix: {
applyStateColor: true,
name: this.IconNames.user,
},
},
},
} as XFormControlConfig<any>,
} as VModelFieldDescriptor<string>,
//
// Password ...
{
hide: false,
hideLabel: false,
allowFieldForm: true,
key: this.FieldNames.password,
value: this.defaultModel.password,
type: this.ModelFieldTypes.String,
label: this.AppResourceIDs.password,
formControlConfig: {
index: 1,
propName: this.FieldNames.password,
type: {
type: this.FormControlTypes.Password,
config: {},
},
validators: {
validators: [Validators.required],
},
eventHandlers: {},
appearance: {
hidden: false,
disabled: false,
tooltip: this.AppResourceIDs.password,
// label: this.AppResourceIDs.password,
placeholder: this.AppResourceIDs.password,
appearance: this.FormControlAppearances.Outline,
icons: {
prefix: {
applyStateColor: true,
name: this.IconNames.verified,
},
suffix: {
handler: () => {
this.togglePasswordVisible();
},
applyStateColor: false,
color: this.ColorNames.PrimaryShade,
name: this.passwordVisible
? this.IconNames.visible_off
: this.IconNames.visible,
},
},
},
} as XFormControlConfig<any>,
} as VModelFieldDescriptor<string>,
];
//#endregion
//
//#region LifeCycles ...
registerViewHandlers(): void {
super.registerViewHandlers();
//
// Handle Fire Login Event ...
this.applyTakeUntilWrapper(
this.dtoModelActionFired.asObservable()
).subscribe((action: VBaseDtoModelFiredActionModel) => {
//
// Handle Login Action ...
if (action.action === VBaseDtoModelAction.AddOrUpdate) {
//
if (this.lock) {
this.lock = false;
}
//
this.login.emit();
}
});
}
//#endregion
//
//#region Abstract ...
/**
* Validate Model ...
*
* @param model
* @returns
*/
validate(
model?: Partial<XLoginRequestDto>
): VModelValidationResult<XLoginRequestDto> {
//
let result: VModelValidationResult<XLoginRequestDto>;
//
let isValid = false;
const validationErrors: string[] = [];
//
model = {
...this.model,
...model,
};
const normalized = this.normalize(model);
//
// Handle Validations ...
//
// Model Not Null or Undefined ...
isValid =
!isNullOrUndefined(normalized) && !this.isSameAsDefault(normalized);
if (!isValid) {
//
validationErrors.push(
this.getExceptionMessage(XExceptionIDs.InvalidArgs)
);
} else {
//
// Check Other Validations ...
//
// User Select By ...
isValid = !isNullOrEmptyString(normalized.userSelectBy);
if (!isValid) {
//
validationErrors.push(
this.getExceptionMessage(XExceptionIDs.InvalidUserSelector)
);
}
//
// Password ...
isValid = !isNullOrEmptyString(normalized.password);
if (!isValid) {
//
validationErrors.push(
this.getExceptionMessage(XExceptionIDs.InvalidPassword)
);
}
}
//
isValid = !this.hasChild(validationErrors);
//
// Prepare Result ...
result = {
isValid,
normalized,
validationErrors,
isValidForAdd: true,
isValidForUpdate: true,
};
//
return result;
}
/**
* Prepare Model for Actions ...
*
* @param model XLoginRequestDto Model ...
* @returns
*/
prepare(model?: XLoginRequestDto): XLoginRequestDto {
//
if (isNullOrUndefined(model)) {
model = {
...this.defaultModel,
};
}
//
// Preparing Model Filesd ...
model = {
userSelectBy: !isNullOrEmptyString(model.userSelectBy)
? model.userSelectBy
: this.defaultModel.userSelectBy,
password: !isNullOrEmptyString(model.password)
? model.password
: this.defaultModel.password,
device: !isNullOrUndefined(model.device)
? model.device
: this.managerService.settingsService.device,
language: !isNullOrEmptyString(model.language)
? model.language
: this.managerService.localizationService.locale,
};
//
return model;
}
/**
* Handle Register Focus Handler for User Select By ...
*
* @param to
* @param from
*/
onPresentTypeChanged(to: string, from: string): void {
//
if (to === this.PresentTypes.AsForm) {
//
// Make Sure runs when Model Form Config Prepared ...
if (isNullOrUndefined(this.modelFormConfig)) {
//
setTimeout(() => this.onPresentTypeChanged(to, from), 100);
return;
}
//
this.registerFocusHandler(
this.modelFormConfig.name,
this.FieldNames.userSelectBy
);
}
}
//#endregion
//
//#region Constructor ...
//#endregion
//
//#region Overrides ...
//#endregion
//
//#region Private ...
private async togglePasswordVisible() {
//
// Toggle Password Visibility ...
this.passwordVisible = !this.passwordVisible;
//
// Apply Changes on Password based on Flag ...
this.defaultFieldDescriptors[1] = {
...this.fieldDescriptors[1],
formControlConfig: {
...this.fieldDescriptors[1].formControlConfig,
type: {
...this.fieldDescriptors[1].formControlConfig.type,
type: this.passwordVisible
? this.FormControlTypes.Text
: this.FormControlTypes.Password,
},
appearance: {
...this.fieldDescriptors[1].formControlConfig.appearance,
icons: {
...this.fieldDescriptors[1].formControlConfig.appearance.icons,
suffix: {
...this.fieldDescriptors[1].formControlConfig.appearance.icons
.suffix,
applyStateColor: false,
color: this.ColorNames.PrimaryShade,
name: this.passwordVisible
? this.IconNames.visible_off
: this.IconNames.visible,
},
},
},
},
};
//
// Reset From Model Config to Apply Changes ...
this.modelFormConfig = undefined;
}
//#endregion
}
@@ -0,0 +1,99 @@
<section
#vBaseDialogContainer
class="v-base-dialog"
[isForeground]="false"
[xColor]="getValue(backgroundColor) | async"
>
<!-- Title Toolbar -->
<section #vBaseDialogToolbar>
<!-- Toolbar -->
<ion-toolbar
#vToolbar
class="v-base-dialog-toolbar"
[xColor]="getValue(toolbarColor) | async"
>
<!-- Slots -->
<div class="v-base-dialog-toolbar-area">
<x-slotter>
<!-- Start -->
<x-slot
[name]="SlotNames.START"
[cssClass]="['ion-text-start', 'ion-float-start']"
>
<div
matRipple
(click)="handleClosePopup()"
[matTooltip]="getResourceValue(ResourceIDs.back) | async"
class="v-base-dialog-toolbar-item v-base-dialog-toolbar-button center-vertical-flex"
>
<x-icon
[name]="backIcon"
[loading]="loading"
[color]="'cb-inherit'"
[uiDisabled]="uiDisabled"
></x-icon>
</div>
</x-slot>
<!-- Center -->
<x-slot [name]="SlotNames.CENTER" [cssClass]="'ion-text-center'">
<ion-title class="v-base-dialog-toolbar-item center-vertical-flex">
<h3>{{ getResourceValue(AppResourceIDs.profile) | async }}</h3>
</ion-title>
</x-slot>
<!-- End -->
<x-slot
[name]="SlotNames.END"
[cssClass]="['ion-text-end', 'ion-float-end']"
>
<div
matRipple
*ngIf="false"
class="v-base-dialog-toolbar-item v-base-dialog-toolbar-button center-vertical-flex"
>
<x-icon
[name]="selectIcon"
[loading]="loading"
[color]="'cb-inherit'"
[uiDisabled]="uiDisabled"
[matTooltip]="getResourceValue(AppResourceIDs.profile) | async"
></x-icon>
</div>
</x-slot>
</x-slotter>
</div>
</ion-toolbar>
<!-- Progressbar -->
<ion-progress-bar
type="indeterminate"
*ngIf="getValue(showProgrssbar) | async"
[color]="getValue(progressbarColor) | async"
></ion-progress-bar>
</section>
<!-- Components -->
<section class="v-base-dialog-content">
<!-- Content -->
<ng-container *ngTemplateOutlet="contentRef"></ng-container>
</section>
</section>
<!-- -->
<!-- Template -->
<!-- -->
<!-- Content Template -->
<ng-template #contentRef>
<!-- Implement User View -->
<ng-container *ngIf="notNullOrUndefinedValue(profile) | async">
<div class="v-user-profile-container">
<v-user
[model]="profile"
[supportEdit]="false"
[presentType]="UserPresentTypes.AsProfile"
></v-user>
</div>
</ng-container>
</ng-template>
@@ -0,0 +1,63 @@
@import "../../../../theme/theme.scss";
:host {
--dialog-toolbar-height: 0px;
--background: var(-x-color-light);
}
x-icon {
--size: 24px;
}
h1,
h2,
h3,
h4,
h5,
h6 {
margin: 0 !important;
}
.v-base-dialog {
width: 100%;
height: 100%;
// height: calc(100% - var(--dialog-toolbar-height));
// margin-bottom: var(--dialog-toolbar-height);
}
.v-base-dialog-content {
height: 100%;
//
padding-bottom: var(--dialog-toolbar-height);
}
.v-base-dialog-toolbar-area {
margin: 8px;
}
.v-base-dialog-toolbar-item {
width: auto;
height: 48px;
}
.v-base-dialog-toolbar-button {
width: 32px;
margin: {
left: 4px;
right: 4px;
}
}
//
// Non Global ...
.v-avatar-image {
//
margin: auto;
display: block;
max-width: 100%;
max-height: 100%;
//
clip-path: circle();
}
@@ -0,0 +1,283 @@
import {
Input,
Component,
ViewChild,
ElementRef,
ChangeDetectionStrategy,
} from '@angular/core';
import {
XTask,
nameof,
XColorIdentifier,
isNullOrUndefined,
isNullOrEmptyString,
XColorWithBrightness,
} from 'x-framework-core';
import {
VProfileCssVar,
VProfileModalContext,
VProfileComponentTasks,
VProfileModalContextIdentifier,
} from './v-profile.typings';
import { XUserProfileDto } from 'x-framework-identity-sdk';
import { VUserPresentType } from '../v-user/v-user.typings';
import { VBaseComponent } from '../../classes/v-base.component';
import { XIconNames, XSlotLayout, XSlotName } from 'x-framework-components';
/**
* a Component For Use to Show User Profile as Model ...
*/
@Component({
selector: 'v-profile',
templateUrl: './v-profile.component.html',
styleUrls: ['./v-profile.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VProfileComponent extends VBaseComponent {
//
//#region Properties ...
//
readonly SlotNames = Object.assign({}, XSlotName);
readonly SlotLayouts = Object.assign({}, XSlotLayout);
readonly UserPresentTypes = Object.assign({}, VUserPresentType);
/**
* retrieve Toolbar container ViewChild
* to Calculate Toolbar Height ...
*/
@ViewChild('vBaseDialogToolbar')
vBaseDialogToolbarContainer!: ElementRef;
/**
* Specified Modal Type ...
*/
@Input()
context: VProfileModalContextIdentifier;
@Input()
userId: string;
/**
* Specified User's Full Name ...
*/
@Input()
fullName: string;
/**
* User Profile Info ...
*/
profile: XUserProfileDto;
/**
* Background Color of Component ...
*/
@Input()
backgroundColor: XColorIdentifier = XColorWithBrightness.Light;
/**
* Toolbar Color ...
*/
@Input()
toolbarColor: XColorIdentifier = XColorWithBrightness.PrimaryTint;
/**
* Progressbar Color ...
*/
@Input()
progressbarColor: XColorIdentifier = XColorWithBrightness.Warning;
showProgrssbar = false;
/**
* Action Icon Names Specifiecations ...
*/
@Input()
cancelIcon = XIconNames.close;
@Input()
selectIcon = XIconNames.profile;
@Input()
backIcon = XIconNames.arrow_back;
//#endregion
//
//#region LifeCycles ...
async onInit() {
super.onInit();
//
if (!isNullOrEmptyString(this.userId)) {
await this.issueGetProfileTask();
}
}
async onChange(changeKeys: string[]): Promise<void> {
super.onChange(changeKeys);
//
const isUserIdChanged = changeKeys.includes(
nameof<VProfileComponent>('userId')
);
if (isUserIdChanged && !isNullOrEmptyString(this.userId)) {
await this.issueGetProfileTask();
}
}
afterViewInit(): void {
super.afterViewInit();
//
this.applyContentSize();
}
/**
* Register Required Handlers ...
*/
registerInstanceHandlers(): void {
super.registerInstanceHandlers();
}
//#endregion
//
//#region Task Handlers ...
async onTaskStart(name: string, task: XTask<any>): Promise<void> {
super.onTaskStart(name, task);
//
if (name === VProfileComponentTasks.GetProfile) {
//
this.showProgrssbar = true;
await this.setLoadingState(true);
}
}
async onTaskFinished(name: string, task: XTask<any>): Promise<void> {
super.onTaskFinished(name, task);
//
if (name === VProfileComponentTasks.GetProfile) {
//
this.showProgrssbar = false;
await this.setLoadingState(false);
}
//
if (name === VProfileComponentTasks.GetProfile) {
this.handleGetProfileTaskFinished(task.result);
}
}
async onTaskFailed(name: string, task: XTask<any>): Promise<void> {
super.onTaskFailed(name, task);
//
if (name === VProfileComponentTasks.GetProfile) {
//
this.showProgrssbar = false;
await this.setLoadingState(false);
}
}
//#endregion
//
//#region UI Handlers ...
/**
* Use for Handle Modela Closing Action based on Context ...
* @returns
*/
async handleClosePopup() {
//
if (isNullOrUndefined(this.context) || isNullOrEmptyString(this.context)) {
return;
}
//
switch (this.context) {
//
case VProfileModalContext.Modal:
await this.managerService.dialogService.modalController.dismiss();
break;
//
case VProfileModalContext.PopOver:
await this.managerService.dialogService.popoverController.dismiss();
break;
}
}
//#endregion
//
//#region Overrides ...
onLoading(loading: boolean): void {
super.onLoading(loading);
//
this.showProgrssbar = loading;
this.detectChanges();
}
//#endregion
//
//#region Private ...
/**
* issue task to get user profile ...
*/
private async issueGetProfileTask() {
//
if (isNullOrEmptyString(this.userId)) {
return;
}
//
const mTaskName = VProfileComponentTasks.GetProfile;
const mTask = this.sharedService.authService.getProfile(this.userId);
//
await this.addOrUpdateTask({
priority: 0,
affectLoading: true,
name: mTaskName,
task: mTask,
});
//
await this.dispatchTask(mTaskName);
}
/**
* Handle User Profiile Recieived ...
*
* @param profile
*/
private handleGetProfileTaskFinished(profile: XUserProfileDto) {
//
this.profile = {
...profile,
};
//
this.detectChanges();
}
/**
* Calculate Toolbar Height and add a CSSVar to
* use it for Content Sizing ...
*
* @returns
*/
private async applyContentSize() {
//
const height =
this.vBaseDialogToolbarContainer.nativeElement.getBoundingClientRect()
.height;
if (height === 0) {
setTimeout(() => this.applyContentSize(), 100);
return;
}
//
this.setCssVar(VProfileCssVar.DialogToolbarHeight, `${height}px`);
this.detectChanges();
}
//#endregion
}
@@ -0,0 +1,14 @@
export enum VProfileModalContext {
Modal = 'modal',
PopOver = 'pop_over',
}
export type VProfileModalContextIdentifier = VProfileModalContext | string;
export enum VProfileCssVar {
DialogToolbarHeight = 'dialog-toolbar-height',
}
export enum VProfileComponentTasks {
GetProfile = 'egt_profile',
}
@@ -0,0 +1,72 @@
<!-- Component Template -->
<ng-container *ngIf="getValue(wrapWithCard) | async; else componentsRef">
<x-card
class="v-card v-dto-card"
[avatarUrl]="getCardAvatar()"
[actionProvider]="cardActionProvider"
[color]="getValue(cardColor) | async"
[isInPage]="getValue(isInPage) | async"
[showHeader]="
(notEmptyValue(cardTitle) | async) ||
(notEmptyValue(cardSubTitle) | async)
"
[cssClass]="getValue(cardCssClass) | async"
[title]="getResourceValue(cardTitle) | async"
[showFooter]="getValue(cardShowFooter) | async"
[showActions]="getValue(cardShowActions) | async"
[subTitle]="getResourceValue(cardSubTitle) | async"
[foregroundColor]="getValue(cardForegroundColor) | async"
[class.v-no-margin-card]="getValue(removeCardMargin) | async"
>
<!-- Content -->
<ng-container *ngTemplateOutlet="componentsRef"></ng-container>
<!-- Actions -->
<div class="x-actions" actions *ngIf="getValue(cardShowActions) | async">
<ng-content select="[actions]"></ng-content>
</div>
<!-- Header -->
<div
header
class="x-header"
[isForeground]="true"
[xColor]="getValue(cardColor) | async"
></div>
<!-- Footer -->
<div class="x-footer" footer *ngIf="getValue(cardShowFooter) | async">
<ng-content select="[footer]"></ng-content>
</div>
</x-card>
</ng-container>
<!-- Component's itSelf Template -->
<ng-template #componentsRef>
<section
class="v-dto v-component-wrapper"
[ngClass]="getArrayValue(cssClass) | async"
>
<!-- Component Data -->
<ng-container *ngIf="getValue(step) | async as rStep">
<!-- Present Registration Steps Template -->
<ng-container
*ngTemplateOutlet="
rStep === RegistrationSteps.Terms
? termsAndConditionsStepRef
: unknownStepRef
"
></ng-container>
</ng-container>
</section>
</ng-template>
<!-- -->
<!-- Present Types Templates -->
<!-- -->
<!-- Unknow Template -->
<ng-template #unknownStepRef> </ng-template>
<!-- Terms and Conditions Template -->
<ng-template #termsAndConditionsStepRef> Terms and Conditions ... </ng-template>
@@ -0,0 +1,383 @@
import {
XTask,
isFunction,
XTaskPriority,
nameofInstance,
XOneOrManyType,
isNullOrUndefined,
isNullOrEmptyString,
} from 'x-framework-core';
import {
RegistrationKeys,
RegistrationTaks,
VRegistrationSteps,
isContainsRegistrationTask,
} from './v-register.typings';
import {
XActionRequestDto,
XActionResponseDto,
} from 'x-framework-identity-sdk';
import { Observable } from 'rxjs';
import { Component, Input } from '@angular/core';
import { getRegistrationStepResourceID } from './v-register.tools';
import { VBaseInCardComponent } from '../../classes/v-base.component';
@Component({
selector: 'v-register',
templateUrl: './v-register.component.html',
styleUrls: ['./v-register.component.scss'],
})
export class VRegisterComponent extends VBaseInCardComponent {
//
//#region Props ...
readonly RegistrationSteps = Object.assign({}, VRegistrationSteps);
readonly RegistrationTaskNames = Object.assign({}, RegistrationTaks);
/**
* Custom CSS Classes ...
*/
cssClass: XOneOrManyType<string> = [];
/**
* Remove Card Marigin ...
*/
removeCardMargin: boolean = false;
//
@Input()
getTermsAndConditionsTask: (lang: string) => Observable<string> = undefined;
//
step: VRegistrationSteps;
actionRequest: XActionRequestDto;
actionResponse: XActionResponseDto;
//#endregion
//
//#region LifeCycles ...
afterViewInit(): void {
super.afterViewInit();
//
this.loadStepInfo();
}
async onChange(changeKeys: string[]) {
super.onChange(changeKeys);
//
let isChanged = false;
let applyChanged = false;
//
// getTermsAndConditionsTask ...
isChanged = changeKeys.includes(
nameofInstance(this, 'getTermsAndConditionsTask')
);
if (isChanged) {
//
let isValid =
!isNullOrUndefined(this.getTermsAndConditionsTask) &&
isFunction(this.getTermsAndConditionsTask);
if (!isValid) {
//
this.getTermsAndConditionsTask = (lang: string) => {
return this.sharedService.mabsutAPIService.terms.termsProviderService.get(
lang
);
};
}
}
//
if (applyChanged) {
this.detectChanges();
}
}
//#endregion
//
//#region Task Handlers ...
/**
* Handle Task Start ...
*
* @param name
* @param task
*/
async onTaskStart(name: string, task: XTask<any>) {
super.onTaskStart(name, task);
//
// Validate Task Name ...
let isValid = isContainsRegistrationTask(name);
if (!isValid) {
return;
}
//
await this.setLoadingState(true);
}
/**
* Handle Task Failed ...
*
* @param name
* @param task
*/
async onTaskFailed(name: string, task: XTask<any>) {
super.onTaskFailed(name, task);
//
// Validate Task Name ...
let isValid = isContainsRegistrationTask(name);
if (!isValid) {
return;
}
//
await this.setLoadingState(false);
this.showError(task.error);
}
/**
* Handle Task Finished ...
*
* @param name
* @param task
*/
async onTaskFinished(name: string, task: XTask<any>) {
super.onTaskFinished(name, task);
//
// Validate Task Name ...
let isValid = isContainsRegistrationTask(name);
if (!isValid) {
return;
}
//
await this.setLoadingState(false);
//
if (name === this.RegistrationTaskNames.GetTermsAndConditions) {
//
// this.showSuccess();
this.handleTermsAndConditionsTaskFinished(task.result);
}
}
//#endregion
//
//#region Providers ...
loadStepInfo() {
//
// Read Registration Step ...
if (isNullOrUndefined(this.step)) {
//
this.step =
this.managerService.secureStorageService.readOfType<VRegistrationSteps>(
RegistrationKeys.Step,
false
);
//
// Set Terms as First Step ...
if (
isNullOrUndefined(this.step) ||
this.step == VRegistrationSteps.UnKnown
) {
this.step = VRegistrationSteps.Terms;
}
}
//
// Read Action Request ...
if (isNullOrUndefined(this.actionRequest)) {
//
this.actionRequest =
this.managerService.secureStorageService.readOfType<XActionRequestDto>(
RegistrationKeys.ActionRequest,
false
);
}
//
// Read Action Response ...
if (isNullOrUndefined(this.actionResponse)) {
//
this.actionResponse =
this.managerService.secureStorageService.readOfType<XActionResponseDto>(
RegistrationKeys.ActionResponse,
false
);
}
//
// Reload Card Sub Title ...
if (!isNullOrUndefined(this.step)) {
//
let stepResourceID = getRegistrationStepResourceID(this.step);
if (!isNullOrUndefined(stepResourceID)) {
this.cardSubTitle = this.resourceProvider(stepResourceID);
}
}
//
// Prepare Current Step ...
this.prepareStep();
//
// Seva Step Info ...
this.saveStepInfo();
}
getCardAvatar() {
//
let result: string = undefined;
//
if (
!isNullOrUndefined(this.actionRequest) &&
!isNullOrUndefined(this.actionRequest.avatar)
) {
//
return this.actionRequest.avatar.name;
}
//
return result;
}
/**
* Preparing Registration Step Info ...
*
* @returns
*/
prepareStep() {
//
if (
isNullOrUndefined(this.step) ||
this.step !== this.RegistrationSteps.Terms ||
!isFunction(this.getTermsAndConditionsTask) ||
isNullOrUndefined(this.getTermsAndConditionsTask)
) {
return;
}
//
let isPassed = false;
//
// Required Preparation Based on Step ...
if (this.step === this.RegistrationSteps.Terms) {
//
// Check Terms and Condiions Must read or not ...
let hasTerms =
!isNullOrUndefined(this.actionRequest) &&
isNullOrEmptyString(this.actionRequest.termsAndConditions);
isPassed = hasTerms && !!this.actionRequest.acceptTerms;
//
if (!isPassed) {
//
// Read Terms and Conditions and Attach it to ActionRequest if not Exists ...
if (!hasTerms) {
this.handleReadTermsAndConditions();
}
} else {
}
//
return;
}
}
//#endregion
//
//#region Handlers ...
handleReadTermsAndConditions() {
//
// Validate ...
let isValid =
isNullOrUndefined(this.actionRequest) ||
isNullOrEmptyString(this.actionRequest.termsAndConditions);
if (!isValid) {
return;
}
//
this.issueGetTermsAndConditionsTask();
}
//#endregion
//
//#region Private ...
private saveStepInfo() {
//
// Step ...
this.managerService.secureStorageService.write(
RegistrationKeys.Step,
this.step,
true
);
//
// Action Request ...
this.managerService.secureStorageService.write(
RegistrationKeys.ActionRequest,
this.actionRequest,
true
);
//
// Action Response ...
this.managerService.secureStorageService.write(
RegistrationKeys.ActionResponse,
this.actionResponse,
true
);
}
private async issueGetTermsAndConditionsTask() {
//
const name = this.RegistrationTaskNames.GetTermsAndConditions;
//
let lang = '';
if (
!isNullOrUndefined(this.actionRequest) &&
!isNullOrEmptyString(this.actionRequest.lang)
) {
lang = this.actionRequest.lang;
} else {
lang = this.managerService.currentLocale;
}
if (isNullOrEmptyString(lang)) {
return;
}
//
const task = this.getTermsAndConditionsTask(lang);
if (isNullOrUndefined(task)) {
return;
}
//
// Add Or Update Task ...
await this.addOrUpdateTask({
name,
task,
affectLoading: true,
priority: XTaskPriority.High,
});
//
// Dispatch Task ...
await this.dispatchTask(name);
}
private handleTermsAndConditionsTaskFinished(result: string) {
console.log('recieved terms: ', result);
}
//#endregion
}
@@ -0,0 +1,42 @@
import { VRegistrationSteps } from './v-register.typings';
import { AccountLocalizationResourceIDs } from '../account.configs';
import { isNullOrUndefined, XResourceIdentifier } from 'x-framework-core';
export function getRegistrationStepResourceID(step: VRegistrationSteps) {
//
let result: XResourceIdentifier = undefined;
//
if (!isNullOrUndefined(step)) {
//
switch (step) {
//
case VRegistrationSteps.Terms:
result = AccountLocalizationResourceIDs.accept_terms;
break;
//
case VRegistrationSteps.EmailConfirmation:
result = AccountLocalizationResourceIDs.email_confirmation;
break;
//
case VRegistrationSteps.UserInfo:
result = AccountLocalizationResourceIDs.input_user_info;
break;
//
case VRegistrationSteps.AttachProfileImage:
result = AccountLocalizationResourceIDs.input_user_avatar;
break;
//
case VRegistrationSteps.FinishRegistration:
result = AccountLocalizationResourceIDs.finish_registration;
break;
}
}
//
return result;
}
@@ -0,0 +1,67 @@
import { isValueInEnum } from '../../tools/v-base.tools';
import { hasChild, isNullOrUndefined } from 'x-framework-core';
/**
* All Steps Which has Passed for Registration ...
*/
export enum VRegistrationSteps {
/**
* Unknown ...
*/
UnKnown = 0,
/**
* User Must Accept Terms and Conditions ...
*/
Terms = 1,
/**
* User Confirm Email Address ...
*/
EmailConfirmation = 2,
/**
* User Input Info ...
*/
UserInfo = 3,
/**
* User add Profile Image ...
*/
AttachProfileImage = 4,
/**
* Finish User Registration ...
*/
FinishRegistration = 5,
}
/**
* Registration Keys ...
*/
export enum RegistrationKeys {
Step = 'RStep',
ActionRequest = 'RAReq',
ActionResponse = 'RARes',
}
//
//#region Tasks ...
export enum RegistrationTaks {
GetTermsAndConditions = 'Get_Terms_And_Conditions',
}
export type RegistrationTaksIdentifier = RegistrationTaks | string;
export function isRegistrationTaks(value: string) {
return isValueInEnum(value, Object.assign({}, RegistrationTaks));
}
export function isContainsRegistrationTask(value: string) {
//
let taskNames = [RegistrationTaks.GetTermsAndConditions];
//
let result =
hasChild(taskNames) &&
!isNullOrUndefined(taskNames.find((tn) => value.includes(tn)));
//
return result;
}
//#endregion
@@ -0,0 +1,112 @@
import { Input } from '@angular/core';
import {
isNullOrEmptyString,
nameofInstance,
XLocale,
XOneOrManyType,
} from 'x-framework-core';
import { VBaseInCardComponent } from '../../classes/v-base.component';
import {
isVTermsPresentType,
VTermsPresentType,
VTermsPresentTypeIdentifier,
} from './v-terms.typings';
export class VTermsComponent extends VBaseInCardComponent {
//
//#region Props ...
readonly PresentTypes = Object.assign({}, VTermsPresentType);
/**
* Css Class List ...
*/
@Input()
cssClass: XOneOrManyType<string>;
/**
* Present Type ...
*/
@Input()
presentType: VTermsPresentTypeIdentifier = this.PresentTypes.AsText;
/**
* Specified Terms and Conditions Language ...
*/
@Input()
language: XLocale | string;
@Input()
terms: string;
//
lang = '';
termsAndConditions = '';
//#endregion
//
//#region Life Cycles ...
async afterViewInit() {
super.afterContentInit();
//
await this.handlePreparePresentType();
}
async onChange(changeKeys: string[]) {
super.onChange(changeKeys);
//
let isChanged = false;
let applyChanges = false;
//
// Present Type ...
isChanged = changeKeys.includes(nameofInstance(this, 'presentType'));
if (isChanged) {
//
if (!isVTermsPresentType(this.presentType)) {
//
applyChanges = true;
this.presentType = this.PresentTypes.AsText;
}
}
//
// Language ...
isChanged = changeKeys.includes(nameofInstance(this, 'language'));
if (isChanged) {
//
if (isNullOrEmptyString(this.language)) {
//
applyChanges = true;
this.language = this.managerService.currentLocale;
}
}
//
// Prepare Present Type ...
isChanged =
changeKeys.includes(nameofInstance(this, 'terms')) ||
changeKeys.includes(nameofInstance(this, 'language')) ||
changeKeys.includes(nameofInstance(this, 'presentType'));
if (isChanged) {
//
await this.handlePreparePresentType();
}
//
if (applyChanges) {
this.detectChanges();
}
}
//#endregion
//
//#region Providers ...
//#endregion
//
//#region Privates ...
private async handlePreparePresentType() {}
//#endregion
}
@@ -0,0 +1,18 @@
import { isValueInEnum } from '../../tools/v-base.tools';
//
//#region PresentType ...
export enum VTermsPresentType {
AsNone = 'as_none',
AsText = 'as_text',
AsForm = 'as_form',
AsMarkdown = 'as_markdown',
AsTermsManagement = 'as_terms_management',
}
export type VTermsPresentTypeIdentifier = VTermsPresentType | string;
export function isVTermsPresentType(value: string) {
return isValueInEnum(value, Object.assign({}, VTermsPresentType));
}
//#endregion
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,78 @@
:host {
--avatar-size: 40px;
}
.x-header {
flex: 1 1 auto;
}
.v-dto-field {
width: 100%;
display: block;
margin: {
top: 8px;
bottom: 8px;
}
}
.v-user {
width: 100%;
display: block;
}
.v-user-wrapper {
padding: 6px;
}
.v-avatar-image {
//
width: var(--avatar-size);
height: var(--avatar-size);
//
clip-path: circle();
}
.v-user-full-name,
.v-user-friendship-state {
//
margin: {
left: 6px;
right: 6px;
}
}
.v-user-role,
.v-user-friendship-state {
font-size: xx-small;
}
.v-user-info-container {
//
width: 100%;
display: block;
padding: {
left: 6px;
right: 6px;
}
// height: var(--avatar-size);
}
::ng-deep x-card.v-user-card {
.x-avatar {
width: var(--avatar-size) !important;
height: var(--avatar-size) !important;
}
}
:host ::ng-deep .v-user-friendship-container {
.x-button {
.x-icon {
color: inherit !important;
}
}
}
.v-dto-field-value-phoneNumber {
direction: ltr;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,254 @@
import {
toNormalString,
isNullOrUndefined,
isNullOrEmptyString,
XResourceIdentifier,
} from 'x-framework-core';
import { defaultAvatar, defaultFullName } from './v-user.typings';
import { XGender, XUserProfileDto } from 'x-framework-identity-sdk';
import { AppResourceIDs } from 'src/app/config/localization.config';
import { getTopRoleByRoles, XAvailableRoles } from 'x-mabsut-api-sdk';
/**
* Generate User Full Name ...
*
* @param user
* @returns
*/
export function getUserFullName(user: XUserProfileDto) {
//
if (isNullOrUndefined(user)) {
return defaultFullName;
}
//
return `${user.firstName} ${user.lastName}`;
}
/**
* Get User Avatar URL ...
*
* @param user
* @returns
*/
export function getUserAvatarURL(user: XUserProfileDto) {
//
if (isNullOrUndefined(user)) {
return defaultAvatar;
}
//
return user.avatar || defaultAvatar;
}
/**
* Retrieve Specified Role Title Resource Id ...
*
* @param role
* @returns
*/
export function getRoleTitleResourceId(role: XAvailableRoles | string) {
//
let result: XResourceIdentifier = null;
if (isNullOrEmptyString(role)) {
return result;
}
//
const mRole = toNormalString(role);
switch (mRole) {
//
case 'admin':
result = AppResourceIDs.admin_role;
break;
//
case 'responsible_manager':
result = AppResourceIDs.responsible_manager_role;
break;
//
case 'journalist':
result = AppResourceIDs.journalist_role;
break;
//
case 'chief_clerk':
result = AppResourceIDs.chief_clerk_role;
break;
//
case 'chief_clerk_assistant':
result = AppResourceIDs.chief_clerk_assistant_role;
break;
//
case 'actuary':
result = AppResourceIDs.actuary_role;
break;
//
case 'actuary_assistant':
result = AppResourceIDs.actuary_assistant_role;
break;
//
case 'reporter':
result = AppResourceIDs.reporter_role;
break;
//
case 'reporter_assistant':
result = AppResourceIDs.reporter_assistant_role;
break;
//
case 'agent':
result = AppResourceIDs.agent_role;
break;
//
case 'user':
result = AppResourceIDs.user_role;
break;
}
//
return result;
}
/**
* Retrieve Specified Role Description Resource Id ...
*
* @param role
* @returns
*/
export function getRoleDescriptionResourceId(role: XAvailableRoles | string) {
//
let result: XResourceIdentifier = null;
if (isNullOrEmptyString(role)) {
return result;
}
//
const mRole = toNormalString(role);
switch (mRole) {
//
case 'admin':
result = AppResourceIDs.admin_role_description;
break;
//
case 'responsible_manager':
result = AppResourceIDs.responsible_manager_role_description;
break;
//
case 'journalist':
result = AppResourceIDs.journalist_role_description;
break;
//
case 'chief_clerk':
result = AppResourceIDs.chief_clerk_role_description;
break;
//
case 'chief_clerk_assistant':
result = AppResourceIDs.chief_clerk_assistant_role_description;
break;
//
case 'actuary':
result = AppResourceIDs.actuary_role_description;
break;
//
case 'actuary_assistant':
result = AppResourceIDs.actuary_assistant_role_description;
break;
//
case 'reporter':
result = AppResourceIDs.reporter_role_description;
break;
//
case 'reporter_assistant':
result = AppResourceIDs.reporter_assistant_role_description;
break;
//
case 'agent':
result = AppResourceIDs.agent_role_description;
break;
//
case 'user':
result = AppResourceIDs.user_role_description;
break;
}
//
return result;
}
/**
* Extract User Top Role ...
*
* @param user
* @returns
*/
export function getUserTopRole(user: XUserProfileDto) {
//
if (isNullOrUndefined(user)) {
return undefined;
}
//
return getTopRole(user.roles);
}
/**
* Extract Top Role based on Roles Array ...
*
* @param roles
* @returns
*/
export function getTopRole(roles: Array<XAvailableRoles | string>) {
return getTopRoleByRoles(roles);
}
/**
* Extract Gender Resource Id ...
*
* @param gender
* @returns
*/
export function getGenderResourceId(gender: XGender) {
//
if (gender === XGender.Male) {
return AppResourceIDs.male;
} else if (gender === XGender.Female) {
return AppResourceIDs.female;
}
//
return undefined;
}
/**
* Extract User Gender Resource Id ...
*
* @param user
* @returns
*/
export function getUserGenderResourceId(user: XUserProfileDto) {
//
if (!user) {
return undefined;
}
//
return getGenderResourceId(user.gender);
}
@@ -0,0 +1,97 @@
import {
XStandardType,
XColorIdentifier,
XColorWithBrightness,
} from 'x-framework-core';
import {
VFriendshipEventModel,
FriendshipActionsPresentType,
FriendshipActionsPresentTypeIdentifier,
} from '../v-friendship/v-friendship.typings';
import { EventEmitter, Injectable } from '@angular/core';
import { XUserProfileDto } from 'x-framework-identity-sdk';
import { XSlotName, XSlotNameIdentifier } from 'x-framework-components';
import { VBaseDtoContainer } from '../../v-dto/v-dto.typings';
//
//#region Resource and Typings ...
export const defaultFullName = '...';
export const defaultAvatar = '/assets/image/default-user-image.png';
/**
* Present Types ...
*/
export enum VUserPresentType {
/**
* Represent Nothing ...
*/
AsNone = 'as_none',
/**
* Represent a User as Form for Add or Update Configured Fields ...
*/
AsForm = 'as_form',
/**
* Represent Only Avatar ...
*/
AsAvatar = 'as_avatar',
/**
* Represent User Avatar and Full Name ...
*/
AsInfo = 'as_info',
/**
* Represent User Info and it's Related Axctions as a Follower ...
*/
AsFollower = 'as_follower',
AsFollowerActions = 'as_follower_actions',
/**
* Represent User Info and it's Related Axctions as a Following ...
*/
AsFollowing = 'as_following',
AsFollowingActions = 'as_following_actions',
/**
* Represent a User as it's Profile Summary which contains all
* available features ...
*/
AsProfile = 'as_profile',
}
export type VUserPresentTypeIdentifier = VUserPresentType | string;
export enum UserProfileTasks {
AddUserProfile = 'add_user_profile',
UpdateUserProfile = 'update_user_profile',
}
//#endregion
//
//#region Container ...
/**
* Contains all available Input/Output(s) default Values ...
*/
@Injectable({
providedIn: 'root',
})
export class VUserDtoContainer extends VBaseDtoContainer {
//
readonly userInfoColor: XColorIdentifier = XColorWithBrightness.PrimaryTint;
readonly putUserInfoOnCardHeader: boolean = false;
//
readonly avatarSize: number = 40;
readonly wrapWithCard: boolean = false;
readonly autoStylingSlots: boolean = true;
readonly avatarSlot: XSlotNameIdentifier = XSlotName.START;
readonly fullNameSlot: XSlotNameIdentifier = XSlotName.CENTER;
readonly friendshipActionsSlot: XSlotNameIdentifier = XSlotName.END;
readonly friendshipActionFired: EventEmitter<VFriendshipEventModel> =
new EventEmitter<VFriendshipEventModel>();
//
readonly showActionsOnProfileView: XStandardType<boolean> = false;
readonly friendshipActionsType: FriendshipActionsPresentTypeIdentifier =
FriendshipActionsPresentType.AsFAB;
//
readonly canSelectUser = false;
}
//#endregion