Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organisation settings ui #719

Merged
merged 15 commits into from
Jun 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<div class="modal--head">
<h1>Add an Organization</h1>
<button class="modal--close button__clear" (click)="close()">
<img src="/assets/img/modal-close-icon.svg" alt="close icon" />
</button>
</div>

<div class="modal--body">
<form [formGroup]="addOrganisationForm" (ngSubmit)="addNewOrganisation()">
<div class="input">
<label for="organisation">Organisation Name</label>
<input type="text" id="organisation" formControlName="name" required />
<div class="input__error input__error__danger" *ngIf="addOrganisationForm.controls.name.touched && addOrganisationForm.controls.name.invalid">
<img src="assets/img/input-error-icon.svg" alt="input error icon" />
<span>Organisation name is required</span>
</div>
</div>

<div class="flex flex__justify-end margin-top__40px">
<button class="button button__white margin-right__24px" type="button" (click)="close()">Discard</button>
<button class="button button__primary" [disabled]="loading">{{ loading ? 'Adding Organisation' : 'Create Organisation' }}</button>
</div>
</form>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { CreateOrganisationComponent } from './create-organisation.component';

describe('CreateOrganisationComponent', () => {
let component: CreateOrganisationComponent;
let fixture: ComponentFixture<CreateOrganisationComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ CreateOrganisationComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(CreateOrganisationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { GeneralService } from 'src/app/services/general/general.service';
import { CreateOrganisationService } from './create-organisation.service';

@Component({
selector: 'app-create-organisation',
templateUrl: './create-organisation.component.html',
styleUrls: ['./create-organisation.component.scss']
})
export class CreateOrganisationComponent implements OnInit {
@Output() closeModal = new EventEmitter<any>();
loading: boolean = false;
addOrganisationForm: FormGroup = this.formBuilder.group({
name: ['', Validators.required]
});
constructor(private createOrganisationService: CreateOrganisationService, private formBuilder: FormBuilder, private generalService: GeneralService) {}

ngOnInit(): void {}

close() {
this.closeModal.emit();
}

async addNewOrganisation() {
if (this.addOrganisationForm.invalid) {
(<any>this.addOrganisationForm).values(this.addOrganisationForm.controls).forEach((control: FormControl) => {
control?.markAsTouched();
});
return;
}
this.loading = true;
try {
const response = await this.createOrganisationService.addOrganisation(this.addOrganisationForm.value);
if (response.status == true) {
this.generalService.showNotification({ style: 'success', message: response.message });
this.closeModal.emit();
}
this.loading = false;
} catch {
this.loading = false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CreateOrganisationComponent } from './create-organisation.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@NgModule({
declarations: [CreateOrganisationComponent],
imports: [CommonModule, ReactiveFormsModule, FormsModule],
exports: [CreateOrganisationComponent]
})
export class CreateOrganisationModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { CreateOrganisationService } from './create-organisation.service';

describe('CreateOrganisationService', () => {
let service: CreateOrganisationService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(CreateOrganisationService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Injectable } from '@angular/core';
import { HTTP_RESPONSE } from 'src/app/models/http.model';
import { HttpService } from 'src/app/services/http/http.service';

@Injectable({
providedIn: 'root'
})
export class CreateOrganisationService {

constructor(private http:HttpService) { }

async addOrganisation(requestDetails: { name: string }): Promise<HTTP_RESPONSE> {
try {
const response = await this.http.request({
url: `/organisations`,
method: 'post',
body: requestDetails
});
return response;
} catch (error: any) {
return error;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<div class="page">
<div class="card flex padding-all__0px">
<div class="sidemenu">
<div class="border__bottom padding-x__24px padding-top__16px padding-bottom__10px">
<h3>Organisation Settings</h3>
</div>
<ul class="sidemenu--items">
<li class="sidemenu--item font__14px" [ngClass]="{ active: activePage === 'general settings' }">
<button (click)="activePage = 'general settings'" class="button__clear">General Settings</button>
</li>

<li class="sidemenu--item font__14px" [ngClass]="{ active: activePage === 'danger zone' }">
<button (click)="activePage = 'danger zone'" class="button__clear">Danger Zone</button>
</li>
<hr class="border__top" />
<li class="sidemenu--item font__14px color__danger font-weight__600" (click)="logout()">
<a href="">Logout</a>
</li>
</ul>
</div>

<div class="page__small--view">
<ng-container *ngIf="activePage === 'general settings'">
<div class="flex flex__justify-between flex__align-items-center margin-bottom__28px">
<h3>Organisation Info</h3>

<button class="button button__primary button__small" [disabled]="isEditingOrganisation" (click)="updateOrganisation()">Save Changes</button>
</div>

<form [formGroup]="editOrganisationForm">
<div class="input">
<label class="margin-bottom__4px" for="organisation-name">Organisation name</label>
<input type="text" aria-label="Organization name" formControlName="name" id="organisation-name" />
<div class="input__error input__error__danger" *ngIf="editOrganisationForm.controls.name.touched && editOrganisationForm.controls.name.invalid">
<img src="assets/img/input-error-icon.svg" alt="input error icon" />
<span>Please enter a name for your organisation</span>
</div>
</div>
</form>
</ng-container>

<ng-container *ngIf="activePage === 'danger zone'">
<h3 class="color__danger margin-bottom__8px">Danger zone</h3>
<p class="color__grey font__14px">Deleting your organisation means you will lose all workspaces created by you and all your every other organisation information.</p>
<button class="button button__danger button__small margin-top__20px" (click)="showDeleteModal = !showDeleteModal">Delete Organisation</button>
</ng-container>
</div>
</div>
</div>
<div class="_overlay" *ngIf="showDeleteModal" (click)="showDeleteModal = false"></div>

<div class="modal modal__center" *ngIf="showDeleteModal">
<div class="modal--body flex flex__column flex__justify-center flex__align-items-center deactivate">
<img src="/assets/img/warning.gif" class="img" alt="warning" />
<p class="font__20px color__black font__weight-600 margin-bottom__8px margin-top__16px text--center no-width">
Are you sure you want to deactivate
<span class="text__capitalize font__weight-600">“{{ organisationName }}”</span>
?
</p>
<p class="color__grey font__14px font__weight-500 margin-bottom__12px">This action is irrevesible</p>
<button class="button button__deactivate" [disabled]="isDeletingOrganisation" (click)="deleteOrganisation()">{{ isDeletingOrganisation ? 'Deleting...' : 'Yes, Delete' }}</button>
<button class="button__primary button__clear margin-top__28px" (click)="showDeleteModal = false">No, Cancel</button>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
.page {
margin-top: 80px;
max-width: calc(834px + 48px);
width: 100%;
}
.sidemenu {
border-right: 1px solid var(--line-border);
max-width: 260px;
width: 100%;

&--item {
margin: 30px 0;
padding-left: 22px;

button {
color: var(--grey-color);
}

&.active {
color: var(--primary-color);
position: relative;

&::before {
position: absolute;
content: '';
width: 3px;
height: 16px;
background-color: var(--primary-color);
left: 0;
top: 50%;
transform: translate(0, -50%);
border-radius: 100px;
}

button {
font-weight: 600;
color: var(--primary-color);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { OrganisationComponent } from './organisation.component';

describe('OrganisationComponent', () => {
let component: OrganisationComponent;
let fixture: ComponentFixture<OrganisationComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ OrganisationComponent ]
})
.compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(OrganisationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { GeneralService } from 'src/app/services/general/general.service';
import { OrganisationService } from './organisation.service';

@Component({
selector: 'app-organisation',
templateUrl: './organisation.component.html',
styleUrls: ['./organisation.component.scss']
})
export class OrganisationComponent implements OnInit {
activePage: 'general settings' | 'danger zone' = 'general settings';
showDeactivateAccountModal = false;
isEditingOrganisation = false;
isDeletingOrganisation = false;
showDeleteModal = false;
organisationId!: string;
organisationName!: string;
editOrganisationForm: FormGroup = this.formBuilder.group({
name: ['', Validators.required]
});

constructor(private formBuilder: FormBuilder, private router: Router, private organisationService: OrganisationService, private generalService: GeneralService) {}

ngOnInit() {
this.getOrganisationDetails();
}
async logout() {
try {
const response: any = await this.organisationService.logout();
if (response) {
this.router.navigateByUrl('/login');
localStorage.clear();
}
} catch (error) {}
}

async updateOrganisation() {
if (this.editOrganisationForm.invalid) {
(<any>this.editOrganisationForm).values(this.editOrganisationForm.controls).forEach((control: FormControl) => {
control?.markAsTouched();
});
return;
}
this.isEditingOrganisation = true;
try {
const response = await this.organisationService.updateOrganisation({ org_id: this.organisationId, body: this.editOrganisationForm.value });
if (response.status == true) {
this.generalService.showNotification({ style: 'success', message: response.message });
localStorage.setItem('ORG_DETAILS', JSON.stringify(response.data));
window.location.reload();
}
this.isEditingOrganisation = false;
} catch {
this.isEditingOrganisation = false;
}
}

getOrganisationDetails() {
const org = localStorage.getItem('ORG_DETAILS');
if (org) {
const organisationDetails = JSON.parse(org);
this.organisationId = organisationDetails.uid;
this.organisationName = organisationDetails.name;
this.editOrganisationForm.patchValue({
name: organisationDetails.name
});
}
}

async deleteOrganisation() {
this.isDeletingOrganisation = true;
try {
const response = await this.organisationService.deleteOrganisation({ org_id: this.organisationId });
if (response.status == true) {
this.generalService.showNotification({ style: 'success', message: response.message });
localStorage.removeItem('ORG_DETAILS');
this.router.navigateByUrl('/').then(() => {
window.location.reload();
});
}
this.isDeletingOrganisation = false;
} catch {
this.isDeletingOrganisation = false;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OrganisationComponent } from './organisation.component';
import { RouterModule, Routes } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';

const routes: Routes = [{ path: '', component: OrganisationComponent }];

@NgModule({
declarations: [OrganisationComponent],
imports: [CommonModule, ReactiveFormsModule, RouterModule.forChild(routes)]
})
export class OrganisationModule {}
Loading