Skip to content

Instantly share code, notes, and snippets.

@anandadake
Created January 15, 2024 04:53
Show Gist options
  • Select an option

  • Save anandadake/e65e38258705d5b72986446120f1d700 to your computer and use it in GitHub Desktop.

Select an option

Save anandadake/e65e38258705d5b72986446120f1d700 to your computer and use it in GitHub Desktop.
Component Code structure style
<div class="container mt-5">
<div class="row">
<div class="col-md-12">
<div class="row mb-2">
<div class="col-md-8">
<h1>{{project_info.project_name}}</h1>
</div>
<div class="col-md-2"><div class="d-grid"><button class="btn btn-warning" data-bs-toggle="modal" data-bs-target="#makeACopyModal" (click)="onPreCopy($event)">Make a Copy</button></div></div>
<div class="col-md-2"><div class="d-grid"><button class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">Delete project</button></div></div>
</div>
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Project Details</h5>
</div>
<div class="modal-body">
<form [formGroup]="projectInfo">
<div class="mb-3">
<label for="projectTitle" class="form-label">Project Title</label>
<input type="text" class="form-control" maxlength="50" formControlName="project_name" (input)="removeSpecialCharAndFirstCharIfNumber($event)" #wordForName>
<div class="form-text">Title for your Project (Min 5 Character to Max 50 Characters)</div>
<div class="form-text alert-info">{{maxWordsForName - wordForName.value.length}} Characters Remaining..</div>
<div class="alert alert-danger" *ngIf="projectInfo.controls['project_name'].touched && projectInfo.controls['project_name'].invalid">
<strong>Project Title Can't be Empty!</strong> Please fill Project Title.
</div>
</div>
<div class="mb-3">
<label for="projectDescription" class="form-label">Project Description</label>
<textarea type="text" class="form-control" rows="5" maxlength="500" formControlName="description" #wordForDescription></textarea>
<div class="form-text">Description for your Project (Min 1 Character to Max 500 Characters)</div>
<div class="form-text alert-info">{{maxWordsForDescription - wordForDescription.value.length}} Characters Remaining..</div>
</div>
<div class="mb-3">
<label class="form-label">Unit System</label>
<select class="form-select" formControlName="unit_system">
<option disabled [value]="null">Select Unit System</option>
<option *ngFor="let unit of unit_systems" [value]="unit">{{ unit }}</option>
</select>
</div>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" (click)="onSave($event)" [disabled]="!projectInfo.valid">Update project</button>
<button class="btn " data-bs-toggle="modal" data-bs-target="#shareProject" (click)="fetchPermissions($event)" > Permissions </button>
<button class="btn btn-outline-primary" (click)="onMakeTemplateProject($event)">Make Template Project</button>
<button class="btn btn-secondary" routerLink="/dashboard">Cancel</button>
</div>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="makeACopyModal" tabindex="-1" aria-labelledby="makeACopyModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="makeACopyModalLabel">Copy Project</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form [formGroup]="projectInfo">
<div class="mb-3">
<label for="projectTitle" class="form-label">New Project Title</label>
<input type="text" class="form-control" maxlength="50" formControlName="project_name" (input)="removeSpecialCharAndFirstCharIfNumber($event)">
<div class="form-text">Title for your Project (Min 5 Character to Max 50 Characters)</div>
</div>
<div class="mb-3">
<label for="projectDescription" class="form-label">New Project Description</label>
<textarea type="text" class="form-control" rows="5" maxlength="500" formControlName="description"></textarea>
<div class="form-text">Description for your Project (Min 1 Character to Max 500 Characters)</div>
</div>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-secondary" data-bs-dismiss="modal" (click)="onPreCopClose($event)">Cancel</button>
<button class="btn btn-primary" (click)="onCopy($event)">Copy</button>
</div>
</div>
</div>
</div>
<!-- Modal -->
<div class="modal fade" id="shareProject" tabindex="-1" aria-labelledby="shareProject" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="shareProject">Share - Project</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form class="form" [formGroup]="sharedWithOther" >
<label for="inputShareWith" class="visually-hidden"><b>Share with</b></label>
<div class="d-flex flex-row justify-space-between mb-3 g-3">
<div class="p-2"><input type="text" class="form-control" id="inputShareWith" placeholder="Username" formControlName="username" #username></div>
<div class="p-2"><button class="btn btn-info" (click)="addSharedWith(username.value)"><i class='bx bx-user-plus' ></i></button></div>
</div>
<ng-container formArrayName="shared_with">
<ng-container *ngFor="let skill of sharedWith.controls; let i=index">
<ng-container [formGroupName]="i" class="mb-5">
<div class="row g-3 mb-3">
<div class="col-5">
<label for="username" class="visually-hidden">Username</label>
<input type="text" class="form-control form-control-sm" id="username" formControlName="username" readonly>
</div>
<div class="col-5">
<label for="permission" class="visually-hidden">permission</label>
<select class="form-select form-select-sm" id="permission" formControlName="permission">
<option disabled [value]="null" [selected]="null==sharedWithOther.value.permission">Select permission</option>
<!-- <option [value]="'OWNER'">OWNER</option> -->
<option [value]="'EDIT'">EDIT</option>
<option [value]="'COPY'">COPY</option>
</select>
</div>
<div class="col-2">
<button class="btn btn-danger" (click)="removeSharedWith(i)"><i class="bx bx-trash"></i></button>
</div>
</div>
</ng-container>
</ng-container>
</ng-container>
</form>
</div>
<div class="modal-footer">
<!-- <button class="btn btn-secondary" data-bs-dismiss="modal" (click)="onPreCopClose($event)">Cancel</button> -->
<button class="btn btn-primary" (click)="permissionSave($event)">Apply</button>
</div>
</div>
</div>
</div>
<!-- Modal HTML -->
<div id="deleteModal" class="modal fade">
<div class="modal-dialog modal-confirm">
<div class="modal-content">
<div class="modal-header flex-column">
<div class="icon-box">
<i class='bx bx-x bx-size'></i>
</div>
<h4 class="modal-title">Are you sure?</h4>
</div>
<div class="modal-body">
<p>Do you really want to delete this Project? <br> This process cannot be undone.</p>
</div>
<div class="modal-footer justify-content-center">
<button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button class="btn btn-danger" (click)="onDelete($event)">Delete</button>
</div>
</div>
</div>
</div>
import { ToastrService } from 'ngx-toastr';
import { catchError, finalize, of } from 'rxjs';
import { HttpParams } from '@angular/common/http';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { removeSpecialCharAndFirstCharIfNumber } from '../shared/util/util';
import { WorkspaceApiService } from '../workspace/service/workspace-api.service';
import { WorkspaceStateService } from '../workspace/state/workspace-state.service';
declare var $: any;
@Component({
selector: 'app-project-view',
templateUrl: './project-view.component.html',
styleUrls: ['./project-view.component.css']
})
export class ProjectViewComponent implements OnInit {
private subscriptions$:any = [];
public unit_systems:any[] = ["SI"];
public maxWordsForName:number = 50;
public maxWordsForDescription:number = 500;
public project_info:any = {};
public project_data:any = {};
public projectInfo: FormGroup = this.fb.group({
pid:[undefined],
project_name: [null, [Validators.required, Validators.min(5), Validators.maxLength(50),]],
description: [undefined, [Validators.maxLength(500)]],
unit_system: [{value: undefined}, Validators.required,],
});
public sharedWithOther: FormGroup = this.fb.group({
pid:[undefined],
username:[undefined],
shared_with: this.fb.array([]),
});
get sharedWith() : FormArray { return this.sharedWithOther.get("shared_with") as FormArray }
addSharedWith(username:any=undefined, permission:any='COPY') {
this.sharedWith.push(this.fb.group({username,permission,}));
}
removeSharedWith(i:number) { this.sharedWith.removeAt(i); }
clearPermissions = () => { while (this.sharedWith.length !== 0) { this.sharedWith.removeAt(0); } }
permissionSave(event:any){
this.sharedWithOther.patchValue({pid: this.project_info.pid});
this.subscriptions$.push(this.apiService.save_project_permissions_api(this.sharedWithOther.value).pipe(
finalize(()=>{$('#shareProject')?.modal('hide');}),
catchError((err)=>{this.toastr.error(err?.error?.msg, "API Error!");return (err)}),
).subscribe(
(resp:any) => {
this.clearPermissions();
resp?.data?.forEach((item: any) => this.addSharedWith(item.username, item.permission,));
this.toastr.success(resp.msg, "Successful");
}
));
}
fetchPermissions(event:any){
this.subscriptions$.push(this.apiService.get_project_permissions_api(this.project_info.pid).subscribe(
(resp:any) => {
this.clearPermissions();
resp.data.forEach((item: any) => this.addSharedWith(item.username, item.permission,));
}
));
}
constructor(
private router: Router,
private fb: FormBuilder,
private toastr: ToastrService,
private activatedRoute: ActivatedRoute,
public apiService:WorkspaceApiService,
public stateService:WorkspaceStateService,
) { }
ngOnInit(): void {
// ----------------------------------------------------------------------------
// fetch Project data via api
// ----------------------------------------------------------------------------
this.activatedRoute.queryParamMap.subscribe((queryParamMap:any)=>{
if(queryParamMap.params.pid!=undefined && queryParamMap.params.pid != 0){
let params = new HttpParams().set('only_info', true);
this.subscriptions$.push(this.apiService.get_project_api(queryParamMap.params.pid,params).subscribe(
(resp:any) => {
this.project_info = resp.data.project_info;
this.project_data = resp.data.project_data;
this.patchValue(resp.data.project_info);
}
));
}
});
}
ngOnDestroy(): void {
this.subscriptions$.forEach((subscription:any)=>subscription.unsubscribe());
}
patchValue(values:any) {
this.projectInfo.patchValue(values);
}
onSave(event:any) {
// this.project_info.project_name = this.projectInfo.value.project_name;
// alert('SUCCESS!! :-)\n\n' + JSON.stringify(this.projectInfo.value, null, 4));
this.subscriptions$.push(this.apiService.update_project_api(this.projectInfo.value).subscribe(
(resp:any) => {
this.toastr.success("Your changes have been saved successfully!", "Successful");
this.project_info = resp.data.project_info;
this.patchValue(resp.data.project_info);
this.router.navigate(['/dashboard']);
},
(error: any) => {
this.toastr.error(error.error.msg, "API Error!");
}
));
}
onMakeTemplateProject(event?:any) {
// this.project_info.project_name = this.projectInfo.value.project_name;
// alert('SUCCESS!! :-)\n\n' + JSON.stringify(this.projectInfo.value, null, 4));
// return;
this.subscriptions$.push(this.apiService.make_project_template_api(this.projectInfo.value).subscribe(
(resp:any) => {
this.toastr.success(resp.msg, "Successful");
},
(error: any) => {
this.toastr.error(error.error.msg, "API Error!");
}
));
}
onPreCopy(event?:any) {
const project_name = this.projectInfo.getRawValue()?.project_name + "_copy";
this.projectInfo.patchValue({project_name});
}
onPreCopClose(event?:any) {
const project_name = this.projectInfo.getRawValue()?.project_name.replace("_copy", "");
this.projectInfo.patchValue({project_name});
}
onCopy(event?:any) {
this.stateService.clear();
this.subscriptions$.push(this.apiService.copy_project_api(this.projectInfo.value).subscribe(
(resp:any) => {
$('#makeACopyModal').modal('hide');
this.router.navigate(['/dashboard'], { queryParams: { pid: resp.data.pid } });
},
(e:any) => {console.error(e)}
));
}
onDelete(event:any) {
this.subscriptions$.push(this.apiService.delete_project_api(this.projectInfo.value).pipe(
finalize(()=>{$('#deleteModal').modal('hide');}),
catchError((err)=>{
this.toastr.error(err.error.msg, "API Error!");
return err;
})
).subscribe(
(resp:any) => {
this.toastr.success("Deleted Successfully", "Successful");
this.router.navigate(['/dashboard']);
}));
}
removeSpecialCharAndFirstCharIfNumber(event:any){
// const str = removeSpecialCharAndFirstCharIfNumber(event.target.value);
let str = event.target.value.replace(/[^A-Z0-9_ ]/ig, "");
str = str.replace(/^[0-9_]+/, "");
this.projectInfo.patchValue({project_name:str});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment