mirror of
https://github.com/richard-loafle/fuse-angular.git
synced 2025-01-08 19:45:08 +00:00
(pages/settings) Added new Settings page
This commit is contained in:
parent
5c3db88908
commit
cc761d58e5
|
@ -130,6 +130,9 @@ export const appRoutes: Route[] = [
|
||||||
|
|
||||||
// Profile
|
// Profile
|
||||||
{path: 'profile', loadChildren: () => import('app/modules/admin/pages/profile/profile.module').then(m => m.ProfileModule)},
|
{path: 'profile', loadChildren: () => import('app/modules/admin/pages/profile/profile.module').then(m => m.ProfileModule)},
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
{path: 'settings', loadChildren: () => import('app/modules/admin/pages/settings/settings.module').then(m => m.SettingsModule)},
|
||||||
]},
|
]},
|
||||||
|
|
||||||
// User interface
|
// User interface
|
||||||
|
|
|
@ -651,6 +651,13 @@ export const defaultNavigation: FuseNavigationItem[] = [
|
||||||
type : 'basic',
|
type : 'basic',
|
||||||
icon : 'heroicons_outline:user-circle',
|
icon : 'heroicons_outline:user-circle',
|
||||||
link : '/pages/profile'
|
link : '/pages/profile'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id : 'pages.settings',
|
||||||
|
title: 'Settings',
|
||||||
|
type : 'basic',
|
||||||
|
icon : 'heroicons_outline:cog',
|
||||||
|
link : '/pages/settings'
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
<div class="w-full max-w-3xl">
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="text-3xl font-bold tracking-tight leading-none">Account</div>
|
||||||
|
|
||||||
|
<!-- Form -->
|
||||||
|
<form
|
||||||
|
class="mt-8"
|
||||||
|
[formGroup]="accountForm">
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full">
|
||||||
|
<div class="text-xl">Profile</div>
|
||||||
|
<div class="text-secondary">Following information is publicly displayed, be careful!</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid sm:grid-cols-4 gap-6 w-full mt-8">
|
||||||
|
<!-- Name -->
|
||||||
|
<div class="sm:col-span-4">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Name</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:user'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'name'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Username -->
|
||||||
|
<div class="sm:col-span-4">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript fuse-mat-emphasized-affix w-full">
|
||||||
|
<mat-label>Username</mat-label>
|
||||||
|
<div
|
||||||
|
class="text-secondary"
|
||||||
|
matPrefix>
|
||||||
|
fusetheme.com/
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
[formControlName]="'username'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Title</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:briefcase'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'title'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Company -->
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Company</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:office-building'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'company'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- About -->
|
||||||
|
<div class="sm:col-span-4">
|
||||||
|
<mat-form-field class="fuse-mat-textarea fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>About</mat-label>
|
||||||
|
<textarea
|
||||||
|
[formControlName]="'about'"
|
||||||
|
[cdkTextareaAutosize]
|
||||||
|
cdkAutosizeMinRows="5"
|
||||||
|
matInput></textarea>
|
||||||
|
</mat-form-field>
|
||||||
|
<div class="mt-1 text-md text-hint">Brief description for your profile. Basic HTML and Emoji are allowed.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full">
|
||||||
|
<div class="text-xl">Personal Information</div>
|
||||||
|
<div class="text-secondary">Communication details in case we want to connect with you. These will be kept private.</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid sm:grid-cols-4 gap-6 w-full mt-8">
|
||||||
|
<!-- Email -->
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Email</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:mail'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'email'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Phone -->
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Phone</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:phone'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'phone'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Country -->
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Country</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:location-marker'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<mat-select [formControlName]="'country'">
|
||||||
|
<mat-option [value]="'usa'">United States</mat-option>
|
||||||
|
<mat-option [value]="'canada'">Canada</mat-option>
|
||||||
|
<mat-option [value]="'mexico'">Mexico</mat-option>
|
||||||
|
<mat-option [value]="'france'">France</mat-option>
|
||||||
|
<mat-option [value]="'germany'">Germany</mat-option>
|
||||||
|
<mat-option [value]="'italy'">Italy</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Language -->
|
||||||
|
<div class="sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Language</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:globe-alt'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<mat-select [formControlName]="'language'">
|
||||||
|
<mat-option [value]="'english'">English</mat-option>
|
||||||
|
<mat-option [value]="'french'">French</mat-option>
|
||||||
|
<mat-option [value]="'spanish'">Spanish</mat-option>
|
||||||
|
<mat-option [value]="'german'">German</mat-option>
|
||||||
|
<mat-option [value]="'italian'">Italian</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="flex items-center justify-end">
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
type="button">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="ml-4"
|
||||||
|
mat-flat-button
|
||||||
|
type="button"
|
||||||
|
[color]="'primary'">Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'settings-account',
|
||||||
|
templateUrl : './account.component.html',
|
||||||
|
encapsulation : ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class SettingsAccountComponent implements OnInit
|
||||||
|
{
|
||||||
|
accountForm: FormGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _formBuilder: FormBuilder
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Create the form
|
||||||
|
this.accountForm = this._formBuilder.group({
|
||||||
|
name : ['Brian Hughes'],
|
||||||
|
username: ['brianh'],
|
||||||
|
title : ['Senior Frontend Developer'],
|
||||||
|
company : ['YXZ Software'],
|
||||||
|
about : ['Hey! This is Brian; husband, father and gamer. I\'m mostly passionate about bleeding edge tech and chocolate! 🍫'],
|
||||||
|
email : ['hughes.brian@mail.com', Validators.email],
|
||||||
|
phone : ['121-490-33-12'],
|
||||||
|
country : ['usa'],
|
||||||
|
language: ['english']
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
<div class="w-full max-w-3xl">
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="text-3xl font-bold tracking-tight leading-none">Notifications</div>
|
||||||
|
|
||||||
|
<!-- Form -->
|
||||||
|
<form
|
||||||
|
class="mt-8"
|
||||||
|
[formGroup]="notificationsForm">
|
||||||
|
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full text-xl">Alerts</div>
|
||||||
|
<div class="grid grid-cols-1 gap-6 w-full mt-8">
|
||||||
|
<!-- Communication -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto cursor-pointer"
|
||||||
|
(click)="communication.toggle()">
|
||||||
|
<div class="leading-6 font-medium">Communication</div>
|
||||||
|
<div class="text-md text-secondary">Get news, announcements, and product updates.</div>
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-2"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'communication'"
|
||||||
|
#communication>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<!-- Security -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto cursor-pointer"
|
||||||
|
(click)="securityToggle.toggle()">
|
||||||
|
<div class="leading-6 font-medium">Security</div>
|
||||||
|
<div class="text-md text-secondary">
|
||||||
|
Get important notifications about your account security.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-2"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'security'"
|
||||||
|
#securityToggle>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<!-- Meetups -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto cursor-pointer"
|
||||||
|
(click)="meetupsToggle.toggle()">
|
||||||
|
<div class="leading-6 font-medium">Meetups</div>
|
||||||
|
<div class="text-md text-secondary">
|
||||||
|
Get an email when a Meetup is posted close to my location.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-2"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'meetups'"
|
||||||
|
#meetupsToggle>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full text-xl">Account Activity</div>
|
||||||
|
<div class="w-full mt-8 font-medium">Email me when:</div>
|
||||||
|
<div class="grid grid-cols-1 gap-4 w-full mt-4">
|
||||||
|
<!-- Comments -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto leading-6 cursor-pointer"
|
||||||
|
(click)="comments.toggle()">
|
||||||
|
someone comments on one of my items
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-2"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'comments'"
|
||||||
|
#comments>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<!-- Mention -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto leading-6 cursor-pointer"
|
||||||
|
(click)="mention.toggle()">
|
||||||
|
someone mentions me
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-2"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'mention'"
|
||||||
|
#mention>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<!-- Follow -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto leading-6 cursor-pointer"
|
||||||
|
(click)="follow.toggle()">
|
||||||
|
someone follows me
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-2"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'follow'"
|
||||||
|
#follow>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<!-- Inquiry -->
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto leading-6 cursor-pointer"
|
||||||
|
(click)="inquiry.toggle()">
|
||||||
|
someone replies to my job posting
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-2"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'inquiry'"
|
||||||
|
#inquiry>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="flex items-center justify-end">
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
type="button">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="ml-4"
|
||||||
|
mat-flat-button
|
||||||
|
type="button"
|
||||||
|
[color]="'primary'">Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'settings-notifications',
|
||||||
|
templateUrl : './notifications.component.html',
|
||||||
|
encapsulation : ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class SettingsNotificationsComponent implements OnInit
|
||||||
|
{
|
||||||
|
notificationsForm: FormGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _formBuilder: FormBuilder
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Create the form
|
||||||
|
this.notificationsForm = this._formBuilder.group({
|
||||||
|
communication: [true],
|
||||||
|
security : [true],
|
||||||
|
meetups : [false],
|
||||||
|
comments : [false],
|
||||||
|
mention : [true],
|
||||||
|
follow : [true],
|
||||||
|
inquiry : [true]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
<div class="w-full max-w-3xl">
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="text-3xl font-bold tracking-tight leading-none">Plan & Billing</div>
|
||||||
|
|
||||||
|
<!-- Form -->
|
||||||
|
<form
|
||||||
|
class="mt-8"
|
||||||
|
[formGroup]="planBillingForm">
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full">
|
||||||
|
<div class="text-xl">Change your plan</div>
|
||||||
|
<div class="text-secondary">Upgrade or downgrade your current plan.</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid sm:grid-cols-3 gap-6 w-full mt-8">
|
||||||
|
<!-- Plan -->
|
||||||
|
<div class="sm:col-span-3">
|
||||||
|
<fuse-alert
|
||||||
|
[appearance]="'outline'"
|
||||||
|
[type]="'info'">
|
||||||
|
Changing the plan will take effect immediately. You will be charged for the rest of the current month.
|
||||||
|
</fuse-alert>
|
||||||
|
</div>
|
||||||
|
<mat-radio-group
|
||||||
|
class="invisible absolute w-0 h-0 pointer-events-none"
|
||||||
|
[formControlName]="'plan'"
|
||||||
|
#planRadioGroup="matRadioGroup">
|
||||||
|
<ng-container *ngFor="let plan of plans; trackBy: trackByFn">
|
||||||
|
<mat-radio-button [value]="plan.value"></mat-radio-button>
|
||||||
|
</ng-container>
|
||||||
|
</mat-radio-group>
|
||||||
|
<ng-container *ngFor="let plan of plans; trackBy: trackByFn">
|
||||||
|
<div
|
||||||
|
class="relative flex flex-col items-start justify-start p-6 rounded-md shadow cursor-pointer bg-card"
|
||||||
|
[ngClass]="{'ring ring-inset ring-primary': planRadioGroup.value === plan.value}"
|
||||||
|
(click)="planRadioGroup.value = plan.value">
|
||||||
|
<ng-container *ngIf="planRadioGroup.value === plan.value">
|
||||||
|
<mat-icon
|
||||||
|
class="absolute top-0 right-0 mt-3 mr-3 icon-size-7 text-primary"
|
||||||
|
[svgIcon]="'heroicons_solid:check-circle'"></mat-icon>
|
||||||
|
</ng-container>
|
||||||
|
<div class="font-medium">{{plan.label}}</div>
|
||||||
|
<div class="mt-1 whitespace-normal text-secondary">{{plan.details}}</div>
|
||||||
|
<div class="flex-auto"></div>
|
||||||
|
<div class="mt-8 text-lg">
|
||||||
|
<span>{{plan.price | currency:'USD':'symbol':'1.0'}}</span>
|
||||||
|
<span class="text-secondary"> / month</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full">
|
||||||
|
<div class="text-xl">Payment Details</div>
|
||||||
|
<div class="text-secondary">Update your billing information. Make sure to set your location correctly as it could affect your tax rates.</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-4 gap-6 w-full mt-8">
|
||||||
|
<!-- Card holder -->
|
||||||
|
<div class="col-span-4">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Card holder</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:user'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'cardHolder'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Card number -->
|
||||||
|
<div class="col-span-4 sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Card number</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:credit-card'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'cardNumber'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Card expiration -->
|
||||||
|
<div class="col-span-2 sm:col-span-1">
|
||||||
|
<mat-form-field
|
||||||
|
class="fuse-mat-no-subscript w-full"
|
||||||
|
[floatLabel]="'always'">
|
||||||
|
<mat-label>Expiration date</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:calendar'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'cardExpiration'"
|
||||||
|
[placeholder]="'MM / YY'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Card CVC -->
|
||||||
|
<div class="col-span-2 sm:col-span-1">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>CVC / CVC2</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:lock-closed'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'cardCVC'"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- Country -->
|
||||||
|
<div class="col-span-4 sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Country</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:location-marker'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<mat-select [formControlName]="'country'">
|
||||||
|
<mat-option [value]="'usa'">United States</mat-option>
|
||||||
|
<mat-option [value]="'canada'">Canada</mat-option>
|
||||||
|
<mat-option [value]="'mexico'">Mexico</mat-option>
|
||||||
|
<mat-option [value]="'france'">France</mat-option>
|
||||||
|
<mat-option [value]="'germany'">Germany</mat-option>
|
||||||
|
<mat-option [value]="'italy'">Italy</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- ZIP -->
|
||||||
|
<div class="col-span-4 sm:col-span-2">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>ZIP / Postal code</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:hashtag'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="flex items-center justify-end">
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
type="button">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="ml-4"
|
||||||
|
mat-flat-button
|
||||||
|
type="button"
|
||||||
|
[color]="'primary'">Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,81 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'settings-plan-billing',
|
||||||
|
templateUrl : './plan-billing.component.html',
|
||||||
|
encapsulation : ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class SettingsPlanBillingComponent implements OnInit
|
||||||
|
{
|
||||||
|
planBillingForm: FormGroup;
|
||||||
|
plans: any[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _formBuilder: FormBuilder
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Create the form
|
||||||
|
this.planBillingForm = this._formBuilder.group({
|
||||||
|
plan : ['team'],
|
||||||
|
cardHolder : ['Brian Hughes'],
|
||||||
|
cardNumber : [''],
|
||||||
|
cardExpiration: [''],
|
||||||
|
cardCVC : [''],
|
||||||
|
country : ['usa'],
|
||||||
|
zip : ['']
|
||||||
|
});
|
||||||
|
|
||||||
|
// Setup the plans
|
||||||
|
this.plans = [
|
||||||
|
{
|
||||||
|
value : 'basic',
|
||||||
|
label : 'BASIC',
|
||||||
|
details: 'Starter plan for individuals.',
|
||||||
|
price : '10'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value : 'team',
|
||||||
|
label : 'TEAM',
|
||||||
|
details: 'Collaborate up to 10 people.',
|
||||||
|
price : '20'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value : 'enterprise',
|
||||||
|
label : 'ENTERPRISE',
|
||||||
|
details: 'For bigger businesses.',
|
||||||
|
price : '40'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track by function for ngFor loops
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
trackByFn(index: number, item: any): any
|
||||||
|
{
|
||||||
|
return item.id || index;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
<div class="w-full max-w-3xl">
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="text-3xl font-bold tracking-tight leading-none">Security</div>
|
||||||
|
|
||||||
|
<!-- Form -->
|
||||||
|
<form
|
||||||
|
class="mt-8"
|
||||||
|
[formGroup]="securityForm">
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full">
|
||||||
|
<div class="text-xl">Change your password</div>
|
||||||
|
<div class="text-secondary">You can only change your password twice within 24 hours!</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid sm:grid-cols-4 gap-6 w-full mt-8">
|
||||||
|
<!-- Current password -->
|
||||||
|
<div class="sm:col-span-4">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>Current password</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:key'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'currentPassword'"
|
||||||
|
type="password"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<!-- New password -->
|
||||||
|
<div class="sm:col-span-4">
|
||||||
|
<mat-form-field class="fuse-mat-no-subscript w-full">
|
||||||
|
<mat-label>New password</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:key'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
[formControlName]="'newPassword'"
|
||||||
|
type="password"
|
||||||
|
matInput>
|
||||||
|
</mat-form-field>
|
||||||
|
<div class="mt-1 text-md text-hint">Minimum 8 characters. Must include numbers, letters and special characters.</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Section -->
|
||||||
|
<div class="w-full">
|
||||||
|
<div class="text-xl">Security preferences</div>
|
||||||
|
<div class="text-secondary">Keep your account more secure with following preferences.</div>
|
||||||
|
</div>
|
||||||
|
<div class="grid sm:grid-cols-4 gap-6 w-full mt-8">
|
||||||
|
<!-- 2-step auth -->
|
||||||
|
<div class="sm:col-span-4 flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto cursor-pointer"
|
||||||
|
(click)="twoStepToggle.toggle()">
|
||||||
|
<div class="leading-6 font-medium">Enable 2-step authentication</div>
|
||||||
|
<div class="text-md text-secondary">
|
||||||
|
Protects you against password theft by requesting an authentication code via SMS on every login.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-4"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'twoStep'"
|
||||||
|
#twoStepToggle>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
<!-- Ask to change password -->
|
||||||
|
<div class="sm:col-span-4 flex items-center justify-between">
|
||||||
|
<div
|
||||||
|
class="flex-auto cursor-pointer"
|
||||||
|
(click)="askPasswordChangeToggle.toggle()">
|
||||||
|
<div class="leading-6 font-medium">Ask to change password on every 6 months</div>
|
||||||
|
<div class="text-md text-secondary">
|
||||||
|
A simple but an effective way to be protected against data leaks and password theft.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<mat-slide-toggle
|
||||||
|
class="ml-4"
|
||||||
|
[color]="'primary'"
|
||||||
|
[formControlName]="'askPasswordChange'"
|
||||||
|
#askPasswordChangeToggle>
|
||||||
|
</mat-slide-toggle>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Divider -->
|
||||||
|
<div class="mt-12 mb-10 border-t"></div>
|
||||||
|
|
||||||
|
<!-- Actions -->
|
||||||
|
<div class="flex items-center justify-end">
|
||||||
|
<button
|
||||||
|
mat-stroked-button
|
||||||
|
type="button">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="ml-4"
|
||||||
|
mat-flat-button
|
||||||
|
type="button"
|
||||||
|
[color]="'primary'">Save
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'settings-security',
|
||||||
|
templateUrl : './security.component.html',
|
||||||
|
encapsulation : ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class SettingsSecurityComponent implements OnInit
|
||||||
|
{
|
||||||
|
securityForm: FormGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _formBuilder: FormBuilder
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Create the form
|
||||||
|
this.securityForm = this._formBuilder.group({
|
||||||
|
currentPassword : [''],
|
||||||
|
newPassword : [''],
|
||||||
|
twoStep : [true],
|
||||||
|
askPasswordChange: [false]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
92
src/app/modules/admin/pages/settings/settings.component.html
Normal file
92
src/app/modules/admin/pages/settings/settings.component.html
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<div class="absolute inset-0 flex flex-col min-w-0 overflow-hidden">
|
||||||
|
|
||||||
|
<mat-drawer-container class="flex-auto h-full">
|
||||||
|
|
||||||
|
<!-- Drawer -->
|
||||||
|
<mat-drawer
|
||||||
|
class="sm:w-96 dark:bg-gray-900"
|
||||||
|
[autoFocus]="false"
|
||||||
|
[mode]="drawerMode"
|
||||||
|
[opened]="drawerOpened"
|
||||||
|
#drawer>
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="m-8 sm:my-10 text-4xl font-extrabold tracking-tight leading-none">Settings</div>
|
||||||
|
<!-- Panel links -->
|
||||||
|
<div class="flex flex-col divide-y border-t border-b">
|
||||||
|
<ng-container *ngFor="let panel of panels; trackBy: trackByFn">
|
||||||
|
<div
|
||||||
|
class="flex px-8 py-5 cursor-pointer"
|
||||||
|
[ngClass]="{'hover:bg-gray-100 dark:hover:bg-hover': !selectedPanel || selectedPanel !== panel.id,
|
||||||
|
'bg-primary-50 dark:bg-hover': selectedPanel && selectedPanel === panel.id}"
|
||||||
|
(click)="selectedPanel = panel.id; drawer.close()">
|
||||||
|
<mat-icon
|
||||||
|
[ngClass]="{'text-hint': !selectedPanel || selectedPanel !== panel.id,
|
||||||
|
'text-primary dark:text-primary-500': selectedPanel && selectedPanel === panel.id}"
|
||||||
|
[svgIcon]="panel.icon"></mat-icon>
|
||||||
|
<div class="ml-3">
|
||||||
|
<div
|
||||||
|
class="font-medium leading-6"
|
||||||
|
[ngClass]="{'text-primary dark:text-primary-500': selectedPanel && selectedPanel === panel.id}">
|
||||||
|
{{panel.title}}
|
||||||
|
</div>
|
||||||
|
<div class="mt-0.5 text-secondary">
|
||||||
|
{{panel.description}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
</mat-drawer>
|
||||||
|
|
||||||
|
<!-- Drawer content -->
|
||||||
|
<mat-drawer-content class="flex flex-col">
|
||||||
|
|
||||||
|
<!-- Main -->
|
||||||
|
<div class="flex-auto p-6 md:p-8 lg:p-12">
|
||||||
|
|
||||||
|
<!-- Drawer toggle -->
|
||||||
|
<button
|
||||||
|
class="lg:hidden mb-4 -ml-2"
|
||||||
|
mat-icon-button
|
||||||
|
(click)="drawer.toggle()">
|
||||||
|
<mat-icon [svgIcon]="'heroicons_outline:menu'"></mat-icon>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Load settings panel -->
|
||||||
|
<ng-container [ngSwitch]="selectedPanel">
|
||||||
|
|
||||||
|
<!-- Account -->
|
||||||
|
<ng-container *ngSwitchCase="'account'">
|
||||||
|
<settings-account></settings-account>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Security -->
|
||||||
|
<ng-container *ngSwitchCase="'security'">
|
||||||
|
<settings-security></settings-security>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Plan & Billing -->
|
||||||
|
<ng-container *ngSwitchCase="'plan-billing'">
|
||||||
|
<settings-plan-billing></settings-plan-billing>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Notifications -->
|
||||||
|
<ng-container *ngSwitchCase="'notifications'">
|
||||||
|
<settings-notifications></settings-notifications>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<!-- Team -->
|
||||||
|
<ng-container *ngSwitchCase="'team'">
|
||||||
|
<settings-team></settings-team>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</mat-drawer-content>
|
||||||
|
|
||||||
|
</mat-drawer-container>
|
||||||
|
|
||||||
|
</div>
|
119
src/app/modules/admin/pages/settings/settings.component.ts
Normal file
119
src/app/modules/admin/pages/settings/settings.component.ts
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
import { Subject } from 'rxjs';
|
||||||
|
import { takeUntil } from 'rxjs/operators';
|
||||||
|
import { FuseMediaWatcherService } from '@fuse/services/media-watcher';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'settings',
|
||||||
|
templateUrl : './settings.component.html',
|
||||||
|
encapsulation : ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class SettingsComponent implements OnInit, OnDestroy
|
||||||
|
{
|
||||||
|
drawerMode: 'over' | 'side' = 'side';
|
||||||
|
drawerOpened: boolean = true;
|
||||||
|
panels: any[] = [];
|
||||||
|
selectedPanel: string = 'account';
|
||||||
|
private _unsubscribeAll: Subject<any> = new Subject<any>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private _changeDetectorRef: ChangeDetectorRef,
|
||||||
|
private _fuseMediaWatcherService: FuseMediaWatcherService
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Setup available panels
|
||||||
|
this.panels = [
|
||||||
|
{
|
||||||
|
id : 'account',
|
||||||
|
icon : 'heroicons_outline:user-circle',
|
||||||
|
title : 'Account',
|
||||||
|
description: 'Manage your public profile and private information'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id : 'security',
|
||||||
|
icon : 'heroicons_outline:lock-closed',
|
||||||
|
title : 'Security',
|
||||||
|
description: 'Manage your password and 2-step verification preferences'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id : 'plan-billing',
|
||||||
|
icon : 'heroicons_outline:credit-card',
|
||||||
|
title : 'Plan & Billing',
|
||||||
|
description: 'Manage your subscription plan, payment method and billing information'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id : 'notifications',
|
||||||
|
icon : 'heroicons_outline:bell',
|
||||||
|
title : 'Notifications',
|
||||||
|
description: 'Manage when you\'ll be notified on which channels'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id : 'team',
|
||||||
|
icon : 'heroicons_outline:user-group',
|
||||||
|
title : 'Team',
|
||||||
|
description: 'Manage your existing team and change roles/permissions'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Subscribe to media changes
|
||||||
|
this._fuseMediaWatcherService.onMediaChange$
|
||||||
|
.pipe(takeUntil(this._unsubscribeAll))
|
||||||
|
.subscribe(({matchingAliases}) => {
|
||||||
|
|
||||||
|
// Set the drawerMode and drawerOpened
|
||||||
|
if ( matchingAliases.includes('lg') )
|
||||||
|
{
|
||||||
|
this.drawerMode = 'side';
|
||||||
|
this.drawerOpened = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.drawerMode = 'over';
|
||||||
|
this.drawerOpened = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark for check
|
||||||
|
this._changeDetectorRef.markForCheck();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On destroy
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void
|
||||||
|
{
|
||||||
|
// Unsubscribe from all subscriptions
|
||||||
|
this._unsubscribeAll.next();
|
||||||
|
this._unsubscribeAll.complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track by function for ngFor loops
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
trackByFn(index: number, item: any): any
|
||||||
|
{
|
||||||
|
return item.id || index;
|
||||||
|
}
|
||||||
|
}
|
48
src/app/modules/admin/pages/settings/settings.module.ts
Normal file
48
src/app/modules/admin/pages/settings/settings.module.ts
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||||
|
import { FuseAlertModule } from '@fuse/components/alert';
|
||||||
|
import { FuseAutogrowModule } from '@fuse/directives/autogrow';
|
||||||
|
import { SharedModule } from 'app/shared/shared.module';
|
||||||
|
import { SettingsComponent } from 'app/modules/admin/pages/settings/settings.component';
|
||||||
|
import { SettingsAccountComponent } from 'app/modules/admin/pages/settings/account/account.component';
|
||||||
|
import { SettingsSecurityComponent } from 'app/modules/admin/pages/settings/security/security.component';
|
||||||
|
import { SettingsPlanBillingComponent } from 'app/modules/admin/pages/settings/plan-billing/plan-billing.component';
|
||||||
|
import { SettingsNotificationsComponent } from 'app/modules/admin/pages/settings/notifications/notifications.component';
|
||||||
|
import { SettingsTeamComponent } from 'app/modules/admin/pages/settings/team/team.component';
|
||||||
|
import { settingsRoutes } from 'app/modules/admin/pages/settings/settings.routing';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
SettingsComponent,
|
||||||
|
SettingsAccountComponent,
|
||||||
|
SettingsSecurityComponent,
|
||||||
|
SettingsPlanBillingComponent,
|
||||||
|
SettingsNotificationsComponent,
|
||||||
|
SettingsTeamComponent
|
||||||
|
],
|
||||||
|
imports : [
|
||||||
|
RouterModule.forChild(settingsRoutes),
|
||||||
|
MatButtonModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatIconModule,
|
||||||
|
MatInputModule,
|
||||||
|
MatRadioModule,
|
||||||
|
MatSelectModule,
|
||||||
|
MatSidenavModule,
|
||||||
|
MatSlideToggleModule,
|
||||||
|
FuseAlertModule,
|
||||||
|
FuseAutogrowModule,
|
||||||
|
SharedModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class SettingsModule
|
||||||
|
{
|
||||||
|
}
|
9
src/app/modules/admin/pages/settings/settings.routing.ts
Normal file
9
src/app/modules/admin/pages/settings/settings.routing.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import { Route } from '@angular/router';
|
||||||
|
import { SettingsComponent } from 'app/modules/admin/pages/settings/settings.component';
|
||||||
|
|
||||||
|
export const settingsRoutes: Route[] = [
|
||||||
|
{
|
||||||
|
path : '',
|
||||||
|
component: SettingsComponent
|
||||||
|
}
|
||||||
|
];
|
|
@ -0,0 +1,87 @@
|
||||||
|
<div class="w-full max-w-3xl">
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<div class="text-3xl font-bold tracking-tight leading-none">Team</div>
|
||||||
|
|
||||||
|
<!-- Add team member -->
|
||||||
|
<div class="w-full mt-8">
|
||||||
|
<mat-form-field
|
||||||
|
class="fuse-mat-no-subscript w-full"
|
||||||
|
[floatLabel]="'always'">
|
||||||
|
<mat-label>Add team members</mat-label>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:user'"
|
||||||
|
matPrefix></mat-icon>
|
||||||
|
<input
|
||||||
|
matInput
|
||||||
|
[placeholder]="'Email address'">
|
||||||
|
<button
|
||||||
|
mat-icon-button
|
||||||
|
matSuffix>
|
||||||
|
<mat-icon
|
||||||
|
class="icon-size-5"
|
||||||
|
[svgIcon]="'heroicons_solid:plus-circle'"></mat-icon>
|
||||||
|
</button>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Team members -->
|
||||||
|
<div class="flex flex-col mt-8 divide-y border-t border-b">
|
||||||
|
<ng-container *ngFor="let member of members; trackBy: trackByFn;">
|
||||||
|
<div class="flex flex-col sm:flex-row sm:items-center py-6">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="flex flex-0 items-center justify-center w-10 h-10 rounded-full overflow-hidden">
|
||||||
|
<ng-container *ngIf="member.avatar">
|
||||||
|
<img
|
||||||
|
class="object-cover w-full h-full"
|
||||||
|
[src]="member.avatar"
|
||||||
|
alt="Contact avatar"/>
|
||||||
|
</ng-container>
|
||||||
|
<ng-container *ngIf="!member.avatar">
|
||||||
|
<div class="flex items-center justify-center w-full h-full rounded-full text-lg uppercase bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-200">
|
||||||
|
{{member.name.charAt(0)}}
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
<div class="ml-4">
|
||||||
|
<div class="font-medium">{{member.name}}</div>
|
||||||
|
<div class="text-secondary">{{member.email}}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mt-4 sm:mt-0 sm:ml-auto">
|
||||||
|
<div class="order-2 sm:order-1 ml-4 sm:ml-0">
|
||||||
|
<mat-form-field class="fuse-mat-dense fuse-mat-no-subscript w-32">
|
||||||
|
<mat-select
|
||||||
|
[panelClass]="'w-72 min-w-72 max-w-72 h-auto max-h-none'"
|
||||||
|
[value]="member.role"
|
||||||
|
disableOptionCentering
|
||||||
|
#roleSelect="matSelect">
|
||||||
|
<mat-select-trigger class="text-md">
|
||||||
|
<span>Role:</span>
|
||||||
|
<span class="ml-1 font-medium">{{roleSelect.value | titlecase}}</span>
|
||||||
|
</mat-select-trigger>
|
||||||
|
<ng-container *ngFor="let role of roles">
|
||||||
|
<mat-option
|
||||||
|
class="h-auto py-4 leading-none"
|
||||||
|
[value]="role.value">
|
||||||
|
<div class="font-medium">{{role.label}}</div>
|
||||||
|
<div class="mt-1.5 text-sm whitespace-normal leading-normal text-secondary">{{role.description}}</div>
|
||||||
|
</mat-option>
|
||||||
|
</ng-container>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="order-1 sm:order-2 sm:ml-3">
|
||||||
|
<button mat-icon-button>
|
||||||
|
<mat-icon
|
||||||
|
class="text-hint"
|
||||||
|
[svgIcon]="'heroicons_outline:trash'"></mat-icon>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
110
src/app/modules/admin/pages/settings/team/team.component.ts
Normal file
110
src/app/modules/admin/pages/settings/team/team.component.ts
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector : 'settings-team',
|
||||||
|
templateUrl : './team.component.html',
|
||||||
|
encapsulation : ViewEncapsulation.None,
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
|
})
|
||||||
|
export class SettingsTeamComponent implements OnInit
|
||||||
|
{
|
||||||
|
members: any[];
|
||||||
|
roles: any[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
constructor()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Lifecycle hooks
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On init
|
||||||
|
*/
|
||||||
|
ngOnInit(): void
|
||||||
|
{
|
||||||
|
// Setup the team members
|
||||||
|
this.members = [
|
||||||
|
{
|
||||||
|
avatar: 'assets/images/avatars/male-01.jpg',
|
||||||
|
name : 'Dejesus Michael',
|
||||||
|
email : 'dejesusmichael@mail.org',
|
||||||
|
role : 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/images/avatars/male-03.jpg',
|
||||||
|
name : 'Mclaughlin Steele',
|
||||||
|
email : 'mclaughlinsteele@mail.me',
|
||||||
|
role : 'admin'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/images/avatars/female-02.jpg',
|
||||||
|
name : 'Laverne Dodson',
|
||||||
|
email : 'lavernedodson@mail.ca',
|
||||||
|
role : 'write'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/images/avatars/female-03.jpg',
|
||||||
|
name : 'Trudy Berg',
|
||||||
|
email : 'trudyberg@mail.us',
|
||||||
|
role : 'read'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/images/avatars/male-07.jpg',
|
||||||
|
name : 'Lamb Underwood',
|
||||||
|
email : 'lambunderwood@mail.me',
|
||||||
|
role : 'read'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/images/avatars/male-08.jpg',
|
||||||
|
name : 'Mcleod Wagner',
|
||||||
|
email : 'mcleodwagner@mail.biz',
|
||||||
|
role : 'read'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
avatar: 'assets/images/avatars/female-07.jpg',
|
||||||
|
name : 'Shannon Kennedy',
|
||||||
|
email : 'shannonkennedy@mail.ca',
|
||||||
|
role : 'read'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Setup the roles
|
||||||
|
this.roles = [
|
||||||
|
{
|
||||||
|
label : 'Read',
|
||||||
|
value : 'read',
|
||||||
|
description: 'Can read and clone this repository. Can also open and comment on issues and pull requests.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label : 'Write',
|
||||||
|
value : 'write',
|
||||||
|
description: 'Can read, clone, and push to this repository. Can also manage issues and pull requests.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label : 'Admin',
|
||||||
|
value : 'admin',
|
||||||
|
description: 'Can read, clone, and push to this repository. Can also manage issues, pull requests, and repository settings, including adding collaborators.'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
// @ Public methods
|
||||||
|
// -----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track by function for ngFor loops
|
||||||
|
*
|
||||||
|
* @param index
|
||||||
|
* @param item
|
||||||
|
*/
|
||||||
|
trackByFn(index: number, item: any): any
|
||||||
|
{
|
||||||
|
return item.id || index;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user