(pages/settings) Added new Settings page

This commit is contained in:
sercan 2021-05-11 12:48:51 +03:00
parent 5c3db88908
commit cc761d58e5
16 changed files with 1285 additions and 0 deletions

View File

@ -130,6 +130,9 @@ export const appRoutes: Route[] = [
// Profile
{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

View File

@ -651,6 +651,13 @@ export const defaultNavigation: FuseNavigationItem[] = [
type : 'basic',
icon : 'heroicons_outline:user-circle',
link : '/pages/profile'
},
{
id : 'pages.settings',
title: 'Settings',
type : 'basic',
icon : 'heroicons_outline:cog',
link : '/pages/settings'
}
]
},

View File

@ -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>

View File

@ -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']
});
}
}

View File

@ -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>

View File

@ -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]
});
}
}

View File

@ -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>

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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]
});
}
}

View 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>

View 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;
}
}

View 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
{
}

View 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
}
];

View File

@ -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>

View 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;
}
}