Add project files.

This commit is contained in:
2023-04-29 09:17:17 +03:00
commit 62178f1f32
493 changed files with 45863 additions and 0 deletions
@@ -0,0 +1,22 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { UserProfileComponent } from './user-profile/user-profile.component';
const routes: Routes = [
{
path: '',
redirectTo: 'signin',
pathMatch: 'full',
},
{
path: 'user/profile',
component: UserProfileComponent,
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class PagesRoutingModule {
}
@@ -0,0 +1,30 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { PagesRoutingModule } from './pages-routing.module';
import { UserProfileComponent } from './user-profile/user-profile.component';
import { ReactiveFormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { ComponentsModule } from '../shared/components/components.module';
@NgModule({
declarations: [
UserProfileComponent,
],
imports: [
CommonModule,
ComponentsModule,
FormsModule,
ReactiveFormsModule,
PagesRoutingModule,
MatFormFieldModule,
MatInputModule,
MatIconModule,
MatButtonModule,
],
})
export class PagesModule {
}
@@ -0,0 +1,116 @@
<section class="content">
<div class="content-block">
<div class="block-header">
<!-- breadcrumb -->
<app-breadcrumb [title]="'Profile'" [items]="['User']" [active_item]="'Profile'">
</app-breadcrumb>
</div>
<div class="row clearfix">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div class="card">
<div class="header">
<h2><strong>User</strong> Profile</h2>
</div>
<div class="body">
<form class="m-4" [formGroup]="form!" (ngSubmit)="onSubmit()">
<div class="row">
<div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 mb-2">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Email</mat-label>
<input matInput formControlName="email" autocomplete="off">
<mat-icon class="material-icons-two-tone color-icon p-3" matSuffix>email</mat-icon>
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-xl-6 col-lg-6 col-md-12 col-sm-12 mb-2">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>First name</mat-label>
<input matInput formControlName="firstName" autocomplete="off">
<mat-icon class="material-icons-two-tone color-icon p-3" matSuffix>face</mat-icon>
<mat-error *ngIf="form.get('firstName')?.hasError('pattern')">
Only characters or numbers allowed
</mat-error>
</mat-form-field>
</div>
<div class="col-xl-6 col-lg-6 col-md-12 col-sm-12 mb-2">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Last name</mat-label>
<input matInput formControlName="lastName" autocomplete="off">
<mat-icon class="material-icons-two-tone color-icon p-3" matSuffix>face</mat-icon>
<mat-error *ngIf="form.get('lastName')?.hasError('pattern')">
Only characters or numbers allowed
</mat-error>
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 mb-2">
<mat-form-field class="example-full-width" appearance="fill">
<mat-label>Full name</mat-label>
<input matInput formControlName="fullName" autocomplete="off">
<mat-icon class="material-icons-two-tone color-icon p-3" matSuffix>face</mat-icon>
<mat-error *ngIf="form.get('fullName')?.hasError('whitespace')">
Full name is empty
</mat-error>
</mat-form-field>
</div>
</div>
<div class="row">
<div class="col-xl-12 col-lg-12 col-md-12 col-sm-12 mb-2">
<button class="btn-space" [disabled]="!form.valid" mat-raised-button color="primary">
Submit
</button>
<button type="button" mat-button>Cancel</button>
</div>
</div>
</form>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<div class="card">
<div class="header">
<h2>
<strong>Providers</strong>
</h2>
</div>
<div class="body">
<div class="row" *ngFor="let provider of providers">
<div class="col-md-1">
<mat-icon class="material-icons-two-tone color-icon" color="secondary" *ngIf="!provider.isConnected" matSuffix>link</mat-icon>
<mat-icon class="material-icons-two-tone color-icon" color="accent" *ngIf="provider.isConnected && !provider.isEmailConfirmed" title="Email not confirmed" matSuffix>email</mat-icon>
<mat-icon class="material-icons-two-tone color-icon" color="primary" *ngIf="provider.isConnected && provider.isEmailConfirmed" title="Email confirmed" matSuffix>mark_email_read</mat-icon>
</div>
<div class="col-md-4">
{{provider.name}}
</div>
<div class="col-md-2">
<span class="fl-r" *ngIf="!provider.isConnected">
<button color="accent" class="btn-block mw-100-imp"
mat-raised-button
(click)="connect(provider)"
[disabled]="provider.isLoading"
[class.spinner]="provider.isLoading"
type="button">
Connect
</button>
</span>
<span class="fl-r" *ngIf="provider.isConnected">
<button color="warn" class="btn-block mw-100-imp"
mat-raised-button
(click)="disconnect(provider.provider)"
[disabled]="provider.isLoading"
[class.spinner]="provider.isLoading"
type="button">
Disconect
</button>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
@@ -0,0 +1,24 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { UserProfileComponent } from './user-profile.component';
describe('UserProfileComponent',
() => {
let component: UserProfileComponent;
let fixture: ComponentFixture<UserProfileComponent>;
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [UserProfileComponent],
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(UserProfileComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create',
() => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,139 @@
// angular
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { UntypedFormBuilder } from '@angular/forms';
import { UntypedFormGroup } from '@angular/forms';
import { Validators } from '@angular/forms';
import { FormControl } from '@angular/forms';
// libs
import Swal from 'sweetalert2';
// app
import { ApiRoutes } from '../../api-routes';
import { ExternalLoginConfig } from '../../config.external-login';
import { AuthService } from '../../core/service/auth.service';
@Component({
selector: 'app-blank',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss'],
})
export class UserProfileComponent {
form: UntypedFormGroup;
providers?: ProviderModel[];
constructor(
private fb: UntypedFormBuilder,
private httpClient: HttpClient,
private authService: AuthService,
) {
this.form = this.fb.group({
firstName: ['', [Validators.pattern('[a-zA-Z0-9]+')]],
lastName: ['', [Validators.pattern('[a-zA-Z0-9]+')]],
fullName: ['', [Validators.pattern('[a-zA-Z0-9 ]+')]],
email: [{ value: '', disabled: true }, []],
});
this.providers = ExternalLoginConfig
.getConfiguredProviders()
.map(x => <ProviderModel>{
provider: x.provider,
name: x.name,
isConnected: false,
isEmailConfirmed: false
});
}
ngOnInit(): void {
this.load();
}
private updateForm(data: ProfileModel) {
this.form.patchValue(data);
}
private load() {
this.httpClient.get<ProfileModel>(ApiRoutes.UserProfile).subscribe(data => {
this.updateForm(data);
this.providers?.map((provider) => {
var attached = data.providers?.find(x => x.provider === provider.provider);
provider.isConnected = false;
provider.isEmailConfirmed = false;
if (attached) {
provider.isConnected = true;
provider.isEmailConfirmed = attached.isEmailConfirmed;
}
});
});
}
onSubmit() {
if (this.form.invalid) {
return;
}
this.httpClient.post<ProfileModel>(ApiRoutes.UserProfile, this.form.value).subscribe(data => {
this.updateForm(data);
console.log(this.form);
});
}
connect(provider: ProviderModel) {
provider.error = undefined;
provider.isLoading = true;
if (provider.provider === ExternalLoginConfig.GOOGLE) {
this.authService.attachGoogle().subscribe(r => {
this.load();
provider.isLoading = false;
});
}
if (provider.provider === ExternalLoginConfig.AUTH0) {
this.authService.attachAuth0().subscribe(resp => {
provider.error = '';
if (!resp.success) {
provider.error = resp.data || 'Connect failed';
}
this.load();
provider.isLoading = false;
});
}
}
disconnect(provider: string) {
Swal.fire({
title: 'Are you sure to disconnect ' + provider + ' ?',
text: 'Some providers can be connected only with login!',
icon: 'warning',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Yes, disconnect it!',
}).then((result) => {
if (result.value) {
this.authService.deattach(provider).subscribe(x => {
this.load();
});
}
});
}
}
interface ProviderModel {
provider: string;
name: string;
isConnected: boolean;
isEmailConfirmed: boolean;
error?: string;
isLoading: boolean;
}
interface ProfileModel {
firstName?: string,
lastName?: string,
fullName?: string,
isEmailConfirmed?: boolean,
providers?: ProviderModel[],
}