Browse Source

dockerize

master
drfelfel 1 year ago
parent
commit
c1f1d8b522
41 changed files with 1148 additions and 143 deletions
  1. +26
    -0
      Dockerfile
  2. +7
    -3
      angular.json
  3. +18
    -0
      docker-compose.yml
  4. +25
    -0
      nginx.conf
  5. +6
    -6
      package-lock.json
  6. +3
    -1
      package.json
  7. +12
    -2
      src/app/app.component.ts
  8. +4
    -4
      src/database/drawer.list.ts
  9. +8
    -2
      src/database/user.permission.ts
  10. +1
    -1
      src/routes/auth/app/app.component.ts
  11. +2
    -0
      src/routes/panel/panel.module.ts
  12. +50
    -0
      src/routes/panel/permissions/form/form.component.html
  13. +35
    -0
      src/routes/panel/permissions/form/form.component.scss
  14. +25
    -0
      src/routes/panel/permissions/form/form.component.spec.ts
  15. +25
    -0
      src/routes/panel/permissions/form/form.component.ts
  16. +33
    -0
      src/routes/panel/permissions/material.ts
  17. +25
    -0
      src/routes/panel/permissions/permissions.module.ts
  18. +57
    -0
      src/routes/panel/permissions/table/table.component.html
  19. +21
    -0
      src/routes/panel/permissions/table/table.component.scss
  20. +25
    -0
      src/routes/panel/permissions/table/table.component.spec.ts
  21. +35
    -0
      src/routes/panel/permissions/table/table.component.ts
  22. +55
    -0
      src/routes/panel/reports/app/app.component.html
  23. +28
    -0
      src/routes/panel/reports/app/app.component.scss
  24. +25
    -0
      src/routes/panel/reports/app/app.component.spec.ts
  25. +63
    -0
      src/routes/panel/reports/app/app.component.ts
  26. +14
    -0
      src/routes/panel/reports/dialog/dialog.component.html
  27. +29
    -0
      src/routes/panel/reports/dialog/dialog.component.scss
  28. +25
    -0
      src/routes/panel/reports/dialog/dialog.component.spec.ts
  29. +53
    -0
      src/routes/panel/reports/dialog/dialog.component.ts
  30. +34
    -0
      src/routes/panel/reports/material.ts
  31. +23
    -0
      src/routes/panel/reports/reports.module.ts
  32. +79
    -53
      src/routes/panel/users/table/table.component.html
  33. +74
    -11
      src/routes/panel/users/table/table.component.ts
  34. +39
    -0
      src/routes/panel/volunteer/form/form.component.html
  35. +39
    -0
      src/routes/panel/volunteer/form/form.component.scss
  36. +25
    -0
      src/routes/panel/volunteer/form/form.component.spec.ts
  37. +17
    -0
      src/routes/panel/volunteer/form/form.component.ts
  38. +3
    -1
      src/routes/panel/volunteer/material.ts
  39. +68
    -55
      src/routes/panel/volunteer/table/table.component.html
  40. +8
    -3
      src/routes/panel/volunteer/table/table.component.ts
  41. +4
    -1
      src/routes/panel/volunteer/volunteer.module.ts

+ 26
- 0
Dockerfile View File

@ -0,0 +1,26 @@
# The builder from node image
FROM node:alpine as builder
# build-time variables
# prod|sandbox its value will be come from outside
ARG env=prod
RUN apk update && apk add --no-cache make git
# Move our files into directory name "app"
WORKDIR /app
COPY package.json package-lock.json /app/
RUN npm install @angular/cli@6.0.8 -g
RUN cd /app && npm install
COPY . /app
# Build with $env variable from outside
RUN cd /app && npm run build:$env
# Build a small nginx image with static website
FROM nginx:alpine
RUN rm -rf /usr/share/nginx/html/*
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

+ 7
- 3
angular.json View File

@ -123,6 +123,10 @@
}
}
}
}},
"defaultProject": "kateb-panel"
}
}
},
"defaultProject": "kateb-panel",
"cli": {
"analytics": false
}
}

+ 18
- 0
docker-compose.yml View File

@ -0,0 +1,18 @@
version: '2'
services:
sandbox.web:
build:
context: .
args:
env: sandbox
ports:
- "8080:80"
app.web:
build:
context: .
args:
env: prod
ports:
- "8081:80"

+ 25
- 0
nginx.conf View File

@ -0,0 +1,25 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html index.htm;
include /etc/nginx/mime.types;
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
location / {
try_files $uri $uri/ /index.html;
}
}
}

+ 6
- 6
package-lock.json View File

@ -10057,9 +10057,9 @@
}
},
"rayconnect-client": {
"version": "0.10.25",
"resolved": "https://registry.npmjs.org/rayconnect-client/-/rayconnect-client-0.10.25.tgz",
"integrity": "sha512-wyA7mp3w1trbOFrwiS4xnv610LyHaogQ0frIgl7Q2nMolcd6AFMdrPvNGQ8CLGB6qVY1/KxkaY0GtDew3+uovQ==",
"version": "0.10.26",
"resolved": "https://registry.npmjs.org/rayconnect-client/-/rayconnect-client-0.10.26.tgz",
"integrity": "sha512-GBhwcagoEt9Hseds2a2i/Efi5uQr/eJ4jxSOwdyTw7XB6RxVuX6LloXLnfyCdHHTsJU5KxB+BhFAQa4lMrWXiw==",
"requires": {
"@types/events": "^3.0.0",
"@types/node": "^13.13.15",
@ -10071,9 +10071,9 @@
},
"dependencies": {
"@types/node": {
"version": "13.13.17",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.17.tgz",
"integrity": "sha512-rGZftvdDpsYtG/rOlDOwny1f6Aq4FHJdGSVfPg5vC2DaR9Rt4W2OpsOF5GTU2bSqZmwTkfnsvJhhzpMWYxxlEA=="
"version": "13.13.21",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.21.tgz",
"integrity": "sha512-tlFWakSzBITITJSxHV4hg4KvrhR/7h3xbJdSFbYJBVzKubrASbnnIFuSgolUh7qKGo/ZeJPKUfbZ0WS6Jp14DQ=="
}
}
},

+ 3
- 1
package.json View File

@ -3,6 +3,8 @@
"version": "0.0.0",
"scripts": {
"ng": "ng",
"build:prod": "ng build --env=prod --prod --build-optimizer",
"build:sandbox": "ng build --env=sandbox ---prod --build-optimizer",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
@ -22,7 +24,7 @@
"@angular/platform-browser-dynamic": "~10.0.6",
"@angular/router": "~10.0.6",
"jalali-moment": "^3.3.8",
"rayconnect-client": "^0.10.25",
"rayconnect-client": "^0.10.26",
"rxjs": "~6.5.5",
"tslib": "^2.0.0",
"xlsx": "^0.16.6",

+ 12
- 2
src/app/app.component.ts View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Rayconnect } from '../services/rayconnect/rayconnect.service';
@Component({
@ -8,11 +9,20 @@ import { Rayconnect } from '../services/rayconnect/rayconnect.service';
})
export class AppComponent implements OnInit {
public splash: boolean = true;
constructor(private rayconnect: Rayconnect) { }
constructor(private rayconnect: Rayconnect, private router: Router) { }
async ngOnInit(): Promise<void> {
await this.rayconnect.init()
await this.rayconnect.setProfile();
if (this.rayconnect.user.uid != "guest") {
await this.rayconnect.setProfile();
if (this.router.url === "/") {
this.router.navigate(["/panel"])
}
} else {
this.router.navigate(["/auth"])
}
this.splash = false;
}
}

+ 4
- 4
src/database/drawer.list.ts View File

@ -21,7 +21,7 @@ export const items: Item[] = [
path: '/panel/reports'
},
{
title: 'کارمندان رایدا',
title: 'کاربران رایدا',
icon: 'person',
path: '/panel/users'
},
@ -35,9 +35,9 @@ export const items: Item[] = [
icon: 'group',
path: '/panel/volunteers'
},
{
/* {
title: 'گفتگو با داوطلبین',
icon: 'forum',
path: '/panel/chat'
}
]
}*/
]

+ 8
- 2
src/database/user.permission.ts View File

@ -11,5 +11,11 @@ export const items: Item[] = [
value: 'superadmin',
access: [],
denice: []
}
];
},
{
title: 'عادی',
value: 'none',
access: [],
denice: []
}
];

+ 1
- 1
src/routes/auth/app/app.component.ts View File

@ -28,7 +28,7 @@ export class AppComponent implements OnInit {
this.snackbar.open(res['message'], 'باشه', { duration: 3000, direction: 'rtl' });
if (res['status'] == true) {
await this.rayconnect.setToken(res['data']['token']);
this.router.navigate(['/panel/dahboard']);
this.router.navigate(['/panel']);
} else
this.form.enable();
} catch (error) {

+ 2
- 0
src/routes/panel/panel.module.ts View File

@ -17,6 +17,8 @@ import AppComponent from '../../components/view/view.module';
children: [
{ path: 'calendar', loadChildren: () => import('./calendar/calendar.module').then(m => m.CalendarModule) },
{ path: 'users', loadChildren: () => import('./users/users.module').then(m => m.UsersModule) },
{ path: 'permissions', loadChildren: () => import('./permissions/permissions.module').then(m => m.PermissionsModule) },
{ path: 'reports', loadChildren: () => import('./reports/reports.module').then(m => m.ReportsModule) },
{ path: 'majors', loadChildren: () => import('./majors/majors.module').then(m => m.MajorsModule) },
{ path: 'volunteers', loadChildren: () => import('./volunteer/volunteer.module').then(m => m.VolunteerModule) },
{ path: 'chat', loadChildren: () => import('./chat/chat.module').then(m => m.ChatModule) },

+ 50
- 0
src/routes/panel/permissions/form/form.component.html View File

@ -0,0 +1,50 @@
<mat-toolbar color="primary" class="card-over">
<mat-toolbar-row>
<button mat-icon-button routerLink="/panel/users">
<mat-icon>arrow_forward</mat-icon>
</button>
<span class="title">بازگشت</span>
</mat-toolbar-row>
<mat-toolbar-row></mat-toolbar-row>
</mat-toolbar>
<mat-card>
<header>
<h3>افزودن کاربر جدید</h3>
</header>
<form [formGroup]="form">
<div class="row">
<mat-form-field appearance="outline" class="col s12 m12 l6">
<mat-label>نام</mat-label>
<input matInput formControlName="firstname" type="text" name="firstname" autocomplete="off" required>
</mat-form-field>
<mat-form-field appearance="outline" class="col s12 m12 l6">
<mat-label>نام خانوادگی</mat-label>
<input matInput formControlName="lastname" type="text" name="lastname" autocomplete="off" required>
</mat-form-field>
<mat-form-field appearance="outline" class="col s12 m12 l6">
<mat-label>نام کاربری</mat-label>
<input matInput formControlName="username" type="text" name="username" autocomplete="off" required>
</mat-form-field>
<mat-form-field appearance="outline" class="col s12 m12 l6">
<mat-label>کلمه عبور</mat-label>
<input matInput formControlName="password" type="password" name="password" autocomplete="off" required>
</mat-form-field>
<mat-form-field appearance="outline" class="col s12 m12 l12">
<mat-label>دسترسی</mat-label>
<mat-select formControlName="permission" required>
<mat-option *ngFor="let item of permissions" [value]="item.value">{{item.title}}</mat-option>
</mat-select>
</mat-form-field>
</div>
</form>
<footer>
<button mat-button color="warn">
<mat-icon>delete</mat-icon>
<span>حذف کاربر</span>
</button>
<button mat-raised-button color="accent">
<mat-icon>add</mat-icon>
<span>افزودن کاربر</span>
</button>
</footer>
</mat-card>

+ 35
- 0
src/routes/panel/permissions/form/form.component.scss View File

@ -0,0 +1,35 @@
mat-card {
width: 70%;
header {
display: flex;
flex-wrap: nowrap;
align-items: center;
h3 {
margin-left: auto;
margin-top: 0;
margin-right: 20px;
}
}
}
form {
display: flex;
flex-direction: column;
div.row,
mat-form-field {
width: 100%;
}
}
footer {
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: flex-end;
button {
margin-right: 10px;
}
}

+ 25
- 0
src/routes/panel/permissions/form/form.component.spec.ts View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormComponent } from './form.component';
describe('FormComponent', () => {
let component: FormComponent;
let fixture: ComponentFixture<FormComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FormComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 25
- 0
src/routes/panel/permissions/form/form.component.ts View File

@ -0,0 +1,25 @@
import { Component, OnInit } from '@angular/core';
import { FormGroup, Validators, FormControl } from '@angular/forms';
import { Item, items } from '../../../../database/user.permission';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
public form: FormGroup = new FormGroup({
firstname: new FormControl('', [Validators.required]),
lastname: new FormControl('', [Validators.required]),
username: new FormControl('', [Validators.required]),
password: new FormControl('', [Validators.required, Validators.minLength(6)]),
permission: new FormControl('', [Validators.required])
})
public permissions: Item[] = items;
constructor() { }
ngOnInit(): void {
}
}

+ 33
- 0
src/routes/panel/permissions/material.ts View File

@ -0,0 +1,33 @@
import { NgModule } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSelectModule } from '@angular/material/select';
import { MatButtonModule } from '@angular/material/button';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatDividerModule } from '@angular/material/divider';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatTableModule } from '@angular/material/table';
const modules = [
MatCardModule,
MatInputModule,
MatFormFieldModule,
MatButtonModule,
MatSelectModule,
MatProgressSpinnerModule,
MatProgressBarModule,
MatDividerModule,
MatToolbarModule,
MatIconModule,
MatTableModule
]
@NgModule({
imports: modules,
exports: modules
})
export class MaterialModule { }

+ 25
- 0
src/routes/panel/permissions/permissions.module.ts View File

@ -0,0 +1,25 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { MaterialModule } from './material';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { TableComponent } from './table/table.component';
import { FormComponent } from './form/form.component';
@NgModule({
declarations: [TableComponent, FormComponent],
imports: [
CommonModule,
MaterialModule,
FormsModule,
ReactiveFormsModule,
RouterModule.forChild([
{ path: '', component: TableComponent },
{ path: 'form', component: FormComponent },
{ path: 'form/:id', component: FormComponent }
])
]
})
export class PermissionsModule { }

+ 57
- 0
src/routes/panel/permissions/table/table.component.html View File

@ -0,0 +1,57 @@
<mat-toolbar color="primary" class="card-over">
<mat-toolbar-row>
<span class="title">دسترسی های رایدا</span>
<button mat-raised-button color="accent" routerLink="/panel/permissions/form">
<mat-icon>add</mat-icon>
افزودن دسترسی جدید
</button>
</mat-toolbar-row>
<mat-toolbar-row></mat-toolbar-row>
</mat-toolbar>
<mat-card>
<mat-toolbar>
<mat-form-field appearance="outline">
<mat-label>جستجو کاربر</mat-label>
<input matInput [(ngModel)]="search" type="text" name="search" autocomplete="off">
<button mat-icon-button matSuffix>
<mat-icon>search</mat-icon>
</button>
</mat-form-field>
<div class="flex-space"></div>
<mat-form-field appearance="outline">
<mat-label>دسترسی</mat-label>
<mat-select multiple required>
<mat-option *ngFor="let item of permissions" [value]="item.value">{{item.title}}</mat-option>
</mat-select>
</mat-form-field>
</mat-toolbar>
<mat-progress-bar *ngIf="loading == true" mode="indeterminate"></mat-progress-bar>
<ng-container *ngIf="data != null">
<mat-divider></mat-divider>
<table mat-table [dataSource]="data">
<ng-container matColumnDef="fullname">
<th mat-header-cell *matHeaderCellDef> نام و نام خانوادگی </th>
<td mat-cell *matCellDef="let element"> {{element.firstname}} {{element.lastname}}</td>
</ng-container>
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef> نام کاربری </th>
<td mat-cell *matCellDef="let element"> {{element.username}} </td>
</ng-container>
<ng-container matColumnDef="permission">
<th mat-header-cell *matHeaderCellDef> دسترسی </th>
<td mat-cell *matCellDef="let element"> {{getPermission(element.permission)}} </td>
</ng-container>
<ng-container matColumnDef="options">
<th mat-header-cell *matHeaderCellDef style="width: 25px;"></th>
<td mat-cell *matCellDef="let element" style="width: 25px;">
<button mat-icon-button [routerLink]="'/panel/users/form/' + element.id">
<mat-icon>arrow_back</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columns"></tr>
<tr mat-row *matRowDef="let row; columns: columns;"></tr>
</table>
</ng-container>
</mat-card>

+ 21
- 0
src/routes/panel/permissions/table/table.component.scss View File

@ -0,0 +1,21 @@
table {
width: 100%;
}
mat-card {
mat-toolbar {
margin-top: -16px;
margin-right: -16px;
width: calc(100% + 32px);
border-radius: 4px 4px 0 0;
padding-top: 16px;
div.flex-space {
flex: 1;
}
mat-form-field {
font-size: 0.8rem;
}
}
}

+ 25
- 0
src/routes/panel/permissions/table/table.component.spec.ts View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TableComponent } from './table.component';
describe('TableComponent', () => {
let component: TableComponent;
let fixture: ComponentFixture<TableComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TableComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 35
- 0
src/routes/panel/permissions/table/table.component.ts View File

@ -0,0 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { Rayconnect } from '../../../../services/rayconnect/rayconnect.service';
import { Item, items } from '../../../../database/user.permission';
@Component({
selector: 'app-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.scss']
})
export class TableComponent implements OnInit {
public columns: string[] = ['fullname', 'username', 'permission', 'options'];
public data: object[] = null;
public search: string = ''; // search filter
public permissions: Item[] = items;
public loading: boolean = false; // is loading and fetching data or doing process
constructor(private rayconnect: Rayconnect) { }
ngOnInit(): void {
this.data = [
{
id: '1',
firstname: 'محمد حسین',
lastname: 'میرزایی',
username: 'mhmirzaei',
permission: 'superadmin',
}
]
}
getPermission(value: string) {
return this.permissions.find(item => item.value == value).title;
}
}

+ 55
- 0
src/routes/panel/reports/app/app.component.html View File

@ -0,0 +1,55 @@
<mat-toolbar color="primary">
<mat-toolbar-row>
<span class="title">گزارش گیری</span>
</mat-toolbar-row>
</mat-toolbar>
<br>
<section>
<ng-container>
<mat-card>
<mat-horizontal-stepper labelPosition="bottom" #stepper>
<mat-step >
<form >
<ng-template matStepLabel>نوع گزارش را انتخاب کنید</ng-template>
<mat-form-field appearance="outline">
<mat-label>نوع گزارش</mat-label>
<mat-select disableRipple>
<mat-option *ngFor="let item of list" [value]="item._id">{{
item.name
}}</mat-option>
</mat-select>
</mat-form-field>
<div>
<button mat-button matStepperNext>بعدی</button>
</div>
</form>
</mat-step>
<mat-step >
<form >
<ng-template matStepLabel>ویژگی ها</ng-template>
<mat-form-field>
<mat-label>تاریخ</mat-label>
<input matInput placeholder=""
required>
</mat-form-field>
<div>
<button mat-button matStepperNext>بعدی</button>
</div>
</form>
</mat-step>
<mat-step>
<ng-template matStepLabel>دریافت گزارش</ng-template>
<p>گزارش اماده شد</p>
<div>
<button mat-button (click)="stepper.reset()">باز نشانی</button>
</div>
</mat-step>
</mat-horizontal-stepper>
</mat-card>
</ng-container>
</section>

+ 28
- 0
src/routes/panel/reports/app/app.component.scss View File

@ -0,0 +1,28 @@
section {
position: relative;
top: -50px;
display: flex;
flex-wrap: wrap;
align-items: center;
mat-form-field{
padding: 5px;
}
mat-horizontal-stepper {
width: 100%;
}
mat-card {
display: flex;
flex-wrap: nowrap;
align-items: center;
margin: 0 auto;
min-width: 850px;
span {
margin-left: auto;
}
}
}

+ 25
- 0
src/routes/panel/reports/app/app.component.spec.ts View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AppComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 63
- 0
src/routes/panel/reports/app/app.component.ts View File

@ -0,0 +1,63 @@
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { DialogComponent } from '../dialog/dialog.component';
import { Rayconnect } from '../../../../services/rayconnect/rayconnect.service';
@Component({
selector: 'app-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
public list: { _id: string, name: string }[] = [];
constructor(private dialog: MatDialog, private rayconnect: Rayconnect, private snackbar: MatSnackBar) { }
ngOnInit(): void {
this.fetch();
}
fetch() {
this.rayconnect.RequestBack({
scope: 'kateb',
uniqueID: 'profile',
TokenID: '*',
address: 'major/list',
info: {
method: 'LIST',
data: {}
}
}).then(res => {
if (res['data']['status'] == true) this.list = res['data']['result'];
})
}
delete(id: string) {
this.rayconnect.RequestBack({
scope: 'kateb',
uniqueID: 'profile',
TokenID: '*',
address: 'major/delete',
info: {
method: 'DELETE',
data: { id }
}
}).then(res => {
this.snackbar.open(res['data']['message'], 'باشه', { duration: 3000, direction: 'rtl' });
if (res['data']['status'] == true) {
let index = this.list.findIndex(item => item._id == id);
this.list.splice(index, 1);
}
})
}
openDialog(data) {
this.dialog.open(DialogComponent, { data, autoFocus: false, disableClose: true }).afterClosed().subscribe((result: { name: string, _id: string }) => {
if (!result) return;
let index = this.list.findIndex(item => item._id == result._id);
if (index < 0) this.list.push(result);
else this.list[index] = result;
})
}
}

+ 14
- 0
src/routes/panel/reports/dialog/dialog.component.html View File

@ -0,0 +1,14 @@
<h1 mat-dialog-title>افزودن رشته ی تحصیلی جدید</h1>
<form [formGroup]="form" mat-dialog-content>
<mat-form-field appearance="outline">
<mat-label>عنوان رشته</mat-label>
<input matInput formControlName="major" type="text" autocomplete="off" (keyup.enter)="submit()">
</mat-form-field>
</form>
<div mat-dialog-actions>
<button mat-button color="warn" [disabled]="form.disabled" mat-dialog-close>لغو</button>
<button mat-raised-button color="primary" [disabled]="form.invalid || form.disabled" (click)="submit()">
<span *ngIf="form.disabled == false">ثبت و ارسال</span>
<mat-spinner *ngIf="form.disabled == true" color="primary" diameter="20"></mat-spinner>
</button>
</div>

+ 29
- 0
src/routes/panel/reports/dialog/dialog.component.scss View File

@ -0,0 +1,29 @@
$width: 350px;
form {
display: flex;
flex-direction: column;
mat-form-field {
width: 100%;
}
}
div[mat-dialog-content],
div[mat-dialog-actions] {
min-width: $width;
max-width: $width;
}
div[mat-dialog-actions] {
justify-content: flex-end;
button[mat-raised-button] {
width: 101px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
}
}

+ 25
- 0
src/routes/panel/reports/dialog/dialog.component.spec.ts View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DialogComponent } from './dialog.component';
describe('DialogComponent', () => {
let component: DialogComponent;
let fixture: ComponentFixture<DialogComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DialogComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DialogComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 53
- 0
src/routes/panel/reports/dialog/dialog.component.ts View File

@ -0,0 +1,53 @@
import { Component, OnInit, Inject } from '@angular/core';
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { FormGroup, Validators, FormControl } from '@angular/forms';
import { Rayconnect } from '../../../../services/rayconnect/rayconnect.service';
@Component({
selector: 'app-dialog',
templateUrl: './dialog.component.html',
styleUrls: ['./dialog.component.scss']
})
export class DialogComponent implements OnInit {
public form: FormGroup = new FormGroup({
major: new FormControl('', [Validators.required])
});
public id: string = null;
constructor(private rayconnect: Rayconnect, private snackbar: MatSnackBar, private ref: MatDialogRef<DialogComponent>, @Inject(MAT_DIALOG_DATA) public data: { name: string, _id: string }) { }
ngOnInit(): void {
if (this.data && this.data.name) this.form.get('major').setValue(this.data.name);
if (this.data && this.data._id) this.id = this.data._id;
}
submit() {
if (this.form.valid) {
this.form.disable();
let data: any = { name: this.form.get('major').value }
if (this.id) {
data = { major: data, id: this.id }
}
this.rayconnect.RequestBack({
scope: 'kateb',
uniqueID: 'profile',
TokenID: '*',
address: this.id ? "major/update" : "major/new",
info: {
method: this.id ? "UPDATE" : 'NEW',
data
}
}).then(res => {
this.snackbar.open(res['data']['message'], 'باشه', { duration: 3000, direction: 'rtl' });
if (res['data']['status'] == true) {
if (this.id)
this.ref.close({ _id: this.id, name: data['major']['name'] })
else
this.ref.close(res['data']['result']);
} else
this.form.enable();
})
}
}
}

+ 34
- 0
src/routes/panel/reports/material.ts View File

@ -0,0 +1,34 @@
import { NgModule } from '@angular/core';
import { MatCardModule } from '@angular/material/card';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButtonModule } from '@angular/material/button';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSnackBarModule } from '@angular/material/snack-bar';
import { MatSelectModule } from '@angular/material/select';
import { MatStepperModule } from '@angular/material/stepper';
const modules = [
MatCardModule,
MatInputModule,
MatFormFieldModule,
MatButtonModule,
MatProgressSpinnerModule,
MatToolbarModule,
MatIconModule,
MatDialogModule,
MatSnackBarModule,
MatSelectModule,
MatStepperModule
]
@NgModule({
imports: modules,
exports: modules,
})
export class MaterialModule { }

+ 23
- 0
src/routes/panel/reports/reports.module.ts View File

@ -0,0 +1,23 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { MaterialModule } from './material';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { AppComponent } from './app/app.component';
import { DialogComponent } from './dialog/dialog.component';
@NgModule({
declarations: [DialogComponent, AppComponent],
imports: [
CommonModule,
MaterialModule,
FormsModule,
ReactiveFormsModule,
RouterModule.forChild([
{ path: '', component: AppComponent }
])
]
})
export class ReportsModule { }

+ 79
- 53
src/routes/panel/users/table/table.component.html View File

@ -1,57 +1,83 @@
<mat-toolbar color="primary" class="card-over">
<mat-toolbar-row>
<span class="title">کامندان پنل مدیریت</span>
<button mat-raised-button color="accent" routerLink="/panel/users/form">
<mat-icon>add</mat-icon>
افزودن کاربر جدید
</button>
</mat-toolbar-row>
<mat-toolbar-row></mat-toolbar-row>
<mat-toolbar-row>
<span class="title">کاربران رایدا</span>
<button mat-raised-button color="accent" routerLink="/panel/users/form">
<mat-icon>add</mat-icon>
افزودن کاربر جدید
</button>
</mat-toolbar-row>
<mat-toolbar-row></mat-toolbar-row>
</mat-toolbar>
<mat-card>
<mat-toolbar>
<mat-form-field appearance="outline">
<mat-label>جستجو کاربر</mat-label>
<input matInput [(ngModel)]="search" type="text" name="search" autocomplete="off">
<button mat-icon-button matSuffix>
<mat-icon>search</mat-icon>
</button>
</mat-form-field>
<div class="flex-space"></div>
<mat-form-field appearance="outline">
<mat-label>دسترسی</mat-label>
<mat-select multiple required>
<mat-option *ngFor="let item of permissions" [value]="item.value">{{item.title}}</mat-option>
</mat-select>
</mat-form-field>
</mat-toolbar>
<mat-progress-bar *ngIf="loading == true" mode="indeterminate"></mat-progress-bar>
<ng-container *ngIf="data != null">
<mat-divider></mat-divider>
<table mat-table [dataSource]="data">
<ng-container matColumnDef="fullname">
<th mat-header-cell *matHeaderCellDef> نام و نام خانوادگی </th>
<td mat-cell *matCellDef="let element"> {{element.firstname}} {{element.lastname}}</td>
</ng-container>
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef> نام کاربری </th>
<td mat-cell *matCellDef="let element"> {{element.username}} </td>
</ng-container>
<ng-container matColumnDef="permission">
<th mat-header-cell *matHeaderCellDef> دسترسی </th>
<td mat-cell *matCellDef="let element"> {{getPermission(element.permission)}} </td>
</ng-container>
<ng-container matColumnDef="options">
<th mat-header-cell *matHeaderCellDef style="width: 25px;"></th>
<td mat-cell *matCellDef="let element" style="width: 25px;">
<button mat-icon-button [routerLink]="'/panel/users/form/' + element.id">
<mat-icon>arrow_back</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columns"></tr>
<tr mat-row *matRowDef="let row; columns: columns;"></tr>
</table>
</ng-container>
</mat-card>
<mat-toolbar>
<mat-form-field appearance="outline">
<mat-label>جستجو کاربر</mat-label>
<input
matInput
[(ngModel)]="search"
type="text"
name="search"
autocomplete="off"
(keyup)="searching()"
/>
<button mat-icon-button matSuffix>
<mat-icon>search</mat-icon>
</button>
</mat-form-field>
<div class="flex-space"></div>
<mat-form-field appearance="outline">
<mat-label>دسترسی</mat-label>
<mat-select multiple required>
<mat-option *ngFor="let item of permissions" [value]="item.value">{{
item.title
}}</mat-option>
</mat-select>
</mat-form-field>
</mat-toolbar>
<mat-progress-bar
*ngIf="loading == true"
mode="indeterminate"
></mat-progress-bar>
<ng-container *ngIf="data != null">
<mat-divider></mat-divider>
<table mat-table [dataSource]="data">
<ng-container matColumnDef="fullname">
<th mat-header-cell *matHeaderCellDef>نام و نام خانوادگی</th>
<td mat-cell *matCellDef="let element">
{{ element.firstname }} {{ element.lastname }}
</td>
</ng-container>
<ng-container matColumnDef="username">
<th mat-header-cell *matHeaderCellDef>نام کاربری</th>
<td mat-cell *matCellDef="let element">{{ element.username }}</td>
</ng-container>
<ng-container matColumnDef="permission">
<th mat-header-cell *matHeaderCellDef>دسترسی</th>
<td mat-cell *matCellDef="let element">
{{ getPermission(element.permission) }}
</td>
</ng-container>
<ng-container matColumnDef="cards">
<th mat-header-cell *matHeaderCellDef>کارت</th>
<td mat-cell *matCellDef="let element">
{{ element.cards.length > 0 ? "دارای کارت" : "فاقد کارت" }}
</td>
</ng-container>
<ng-container matColumnDef="options">
<th mat-header-cell *matHeaderCellDef style="width: 25px"></th>
<td mat-cell *matCellDef="let element" style="width: 25px">
<button
mat-icon-button
[routerLink]="'/panel/users/form/' + element.id"
>
<mat-icon>arrow_back</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columns"></tr>
<tr mat-row *matRowDef="let row; columns: columns"></tr>
</table>
</ng-container>
</mat-card>

+ 74
- 11
src/routes/panel/users/table/table.component.ts View File

@ -1,5 +1,7 @@
import { Component, OnInit } from '@angular/core';
import { Rayconnect } from '../../../../services/rayconnect/rayconnect.service';
import { Item, items } from '../../../../database/user.permission';
import { MatTableDataSource } from '@angular/material/table';
@Component({
selector: 'app-table',
@ -8,25 +10,86 @@ import { Item, items } from '../../../../database/user.permission';
})
export class TableComponent implements OnInit {
public columns: string[] = ['fullname', 'username', 'permission', 'options'];
public data: object[] = null;
public columns: string[] = ['fullname', 'username', 'permission', 'cards', 'options'];
public data: MatTableDataSource<object> = new MatTableDataSource<object>();
public search: string = ''; // search filter
public permissions: Item[] = items;
public loading: boolean = false; // is loading and fetching data or doing process
constructor() { }
constructor(private rayconnect: Rayconnect) { }
ngOnInit(): void {
this.data = [
this.data.data = []
this.getUsers()
}
searching() {
if(this.search.length % 2 == 0){
this.getUsers(this.search)
}
}
getUsers(content = null) {
let query
if (content) {
query = {
sync: true,
index: 0,
limit: 15,
search: content
}
} else {
query = {
sync: true,
index: 0,
limit: 5,
search: content
}
}
this.rayconnect.RequestBack(
{
id: '1',
firstname: 'محمد حسین',
lastname: 'میرزایی',
username: 'mhmirzaei',
permission: 'superadmin',
uniqueID: "profile",
TokenID: "*",
scope: 'profile',
address: 'profile/user/manage/list/get',
info: {
method: 'get',
data: query
}
}
]
}
).then((data: any) => {
this.data.data = [];
const users = data.data
users.list.forEach(element => {
this.data.data.push({
id: element._id,
firstname: element.name,
lastname: element.family,
username: element.uid,
permission: 'none',
cards: element.cards
})
});
this.data.data = this.data.data
})
}
getPermission(value: string) {
return this.permissions.find(item => item.value == value).title;
}

+ 39
- 0
src/routes/panel/volunteer/form/form.component.html View File

@ -0,0 +1,39 @@
<mat-toolbar color="primary" class="card-over">
<mat-toolbar-row>
<button mat-icon-button routerLink="/panel/volunteers">
<mat-icon>arrow_forward</mat-icon>
</button>
<span class="title">بازگشت</span>
</mat-toolbar-row>
<mat-toolbar-row></mat-toolbar-row>
</mat-toolbar>
<mat-card>
<header>
<h3>مشاهده اطلاعات داوطلب</h3>
</header>
<section>
<p>
شما در حال مشاهده اطلاعات داوطلب .... .... زاده به کد ملی .... هستید برای
مشاهده اطلاعات کامل نیازمند ورود به پروفایل کاربر هستید که از طریق دکمه
زیر امکان پذیر است
</p>
<button mat-raised-button color="primary" style="float: left;">
<mat-icon>visibility</mat-icon>
<span>مشاهده پروفایل کاربر</span>
</button>
</section>
<br><br><br>
<footer>
<button mat-raised-button color="green">
<mat-icon>check</mat-icon>
<span>تایید مشخصات کاربر</span>
</button>
<button mat-raised-button color="warn">
<mat-icon>error</mat-icon>
<span>رد مشخصات کاربر</span>
</button>
</footer>
</mat-card>

+ 39
- 0
src/routes/panel/volunteer/form/form.component.scss View File

@ -0,0 +1,39 @@
mat-card {
width: 70%;
button[color="green"] {
background-color: #00c853;
color: white;
}
header {
display: flex;
flex-wrap: nowrap;
align-items: center;
h3 {
margin-left: auto;
margin-top: 0;
margin-right: 20px;
}
}
}
form {
display: flex;
flex-direction: column;
div.row,
mat-form-field {
width: 100%;
}
}
footer {
display: flex;
flex-wrap: nowrap;
align-items: center;
justify-content: flex-end;
button {
margin-right: 10px;
}
}

+ 25
- 0
src/routes/panel/volunteer/form/form.component.spec.ts View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { FormComponent } from './form.component';
describe('FormComponent', () => {
let component: FormComponent;
let fixture: ComponentFixture<FormComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ FormComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

+ 17
- 0
src/routes/panel/volunteer/form/form.component.ts View File

@ -0,0 +1,17 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

+ 3
- 1
src/routes/panel/volunteer/material.ts View File

@ -10,6 +10,7 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatTableModule } from '@angular/material/table';
import { MatSelectModule } from '@angular/material/select';
const modules = [
MatCardModule,
@ -21,7 +22,8 @@ const modules = [
MatDividerModule,
MatToolbarModule,
MatIconModule,
MatTableModule
MatTableModule,
MatSelectModule
]
@NgModule({

+ 68
- 55
src/routes/panel/volunteer/table/table.component.html View File

@ -1,59 +1,72 @@
<mat-toolbar color="primary" class="card-over">
<mat-toolbar-row>
<span class="title">داوطلبین</span>
</mat-toolbar-row>
<mat-toolbar-row></mat-toolbar-row>
<mat-toolbar-row>
<span class="title">داوطلبین</span>
</mat-toolbar-row>
<mat-toolbar-row></mat-toolbar-row>
</mat-toolbar>
<mat-card>
<mat-toolbar>
<mat-form-field appearance="outline">
<mat-label>جستجو داوطلب</mat-label>
<input matInput [(ngModel)]="search" type="text" name="search" autocomplete="off">
<button mat-icon-button matSuffix>
<mat-icon>search</mat-icon>
</button>
</mat-form-field>
<div class="flex-space"></div>
<button mat-raised-button color="green" (click)="exportExcel()">
<mat-icon>cloud_download</mat-icon>
<span>دریافت خروجی اکسل</span>
</button>
</mat-toolbar>
<mat-progress-bar *ngIf="loading == true" mode="indeterminate"></mat-progress-bar>
<ng-container *ngIf="data != null">
<mat-divider></mat-divider>
<table mat-table [dataSource]="data">
<ng-container matColumnDef="firstname">
<th mat-header-cell *matHeaderCellDef> نام</th>
<td mat-cell *matCellDef="let element"> {{element.firstname}} </td>
</ng-container>
<ng-container matColumnDef="lastname">
<th mat-header-cell *matHeaderCellDef> نام خانوادگی </th>
<td mat-cell *matCellDef="let element"> {{element.lastname}} </td>
</ng-container>
<ng-container matColumnDef="fathername">
<th mat-header-cell *matHeaderCellDef> نام پدر </th>
<td mat-cell *matCellDef="let element"> {{element.fathername}} </td>
</ng-container>
<ng-container matColumnDef="nationalcode">
<th mat-header-cell *matHeaderCellDef> کد ملی </th>
<td mat-cell *matCellDef="let element"> {{element.nationalcode}} </td>
</ng-container>
<ng-container matColumnDef="step">
<th mat-header-cell *matHeaderCellDef> مرحله </th>
<td mat-cell *matCellDef="let element"> {{element.step}} </td>
</ng-container>
<ng-container matColumnDef="options">
<th mat-header-cell *matHeaderCellDef style="width: 25px;"></th>
<td mat-cell *matCellDef="let element" style="width: 25px;">
<button mat-icon-button [routerLink]="'/panel/users/form/' + element.id">
<mat-icon>arrow_back</mat-icon>
</button>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columns"></tr>
<tr mat-row *matRowDef="let row; columns: columns;"></tr>
</table>
</ng-container>
</mat-card>
<mat-toolbar>
<mat-form-field appearance="outline">
<mat-label>جستجو داوطلب</mat-label>
<input
matInput
[(ngModel)]="search"
type="text"
name="search"
autocomplete="off"
/>
<button mat-icon-button matSuffix>
<mat-icon>search</mat-icon>
</button>
</mat-form-field>
<div class="flex-space"></div>
<button mat-raised-button color="green" (click)="exportExcel()">
<mat-icon>cloud_download</mat-icon>
<span>دریافت خروجی اکسل</span>
</button>
</mat-toolbar>
<mat-progress-bar
*ngIf="loading == true"
mode="indeterminate"
></mat-progress-bar>
<ng-container *ngIf="data != null">
<mat-divider></mat-divider>
<table mat-table [dataSource]="data">
<ng-container matColumnDef="firstname">
<th mat-header-cell *matHeaderCellDef>نام</th>
<td mat-cell *matCellDef="let element">{{ element.firstname }}</td>
</ng-container>
<ng-container matColumnDef="lastname">
<th mat-header-cell *matHeaderCellDef>نام خانوادگی</th>
<td mat-cell *matCellDef="let element">{{ element.lastname }}</td>
</ng-container>
<ng-container matColumnDef="fathername">
<th mat-header-cell *matHeaderCellDef>نام پدر</th>
<td mat-cell *matCellDef="let element">{{ element.fathername }}</td>
</ng-container>
<ng-container matColumnDef="nationalcode">
<th mat-header-cell *matHeaderCellDef>کد ملی</th>
<td mat-cell *matCellDef="let element">{{ element.nationalcode }}</td>
</ng-container>
<ng-container matColumnDef="step">
<th mat-header-cell *matHeaderCellDef>مرحله</th>
<td mat-cell *matCellDef="let element">{{ element.step }}</td>
</ng-container>
<ng-container matColumnDef="options">
<th mat-header-cell *matHeaderCellDef style="width: 25px"></th>
<td mat-cell *matCellDef="let element" style="width: 25px">
<a
mat-icon-button
href="http://37.152.181.239:2188/register/step/personal?admin=true&uid={{element.uid}}&token=test"
target="”_blank”"
>
<mat-icon>arrow_back</mat-icon>
</a>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columns"></tr>
<tr mat-row *matRowDef="let row; columns: columns"></tr>
</table>
</ng-container>
</mat-card>

+ 8
- 3
src/routes/panel/volunteer/table/table.component.ts View File

@ -10,7 +10,7 @@ import { Rayconnect } from '../../../../services/rayconnect/rayconnect.service';
})
export class TableComponent implements OnInit {
public columns: string[] = ['firstname', 'lastname', 'fathername', 'nationalcode', 'step'];
public columns: string[] = ['firstname', 'lastname', 'fathername', 'nationalcode', 'step', 'options'];
public data: MatTableDataSource<object> = new MatTableDataSource<object>();
public loading: boolean = false;
public search: string = '';
@ -39,9 +39,14 @@ export class TableComponent implements OnInit {
}, (res => {
let list: object[] = res.data['list'];
for (let i in list) {
let index: number = this.data.data.findIndex(item => item['_id'] == list[i]['_id']);
let index: number = this.data.data.findIndex(item => item['_id'] == list[i]['information']['_id']);
if (index >= 0) this.data.data.splice(index, 1);
this.addNewUser(list[i]);
const user = list[i]['information']
user.step = list[i]['step']
user.options = true
user.uid = list[i]['uid']
this.addNewUser(list[i]['information']);
}
this.data.data = this.data.data;
this.cdr.markForCheck();

+ 4
- 1
src/routes/panel/volunteer/volunteer.module.ts View File

@ -4,11 +4,12 @@ import { RouterModule } from '@angular/router';
import { MaterialModule } from './material';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { TableComponent } from './table/table.component';
import { FormComponent } from './form/form.component';
@NgModule({
declarations: [TableComponent],
declarations: [TableComponent, FormComponent],
imports: [
CommonModule,
MaterialModule,
@ -16,6 +17,8 @@ import { TableComponent } from './table/table.component';
ReactiveFormsModule,
RouterModule.forChild([
{ path: '', component: TableComponent },
{ path: 'form/:id', component: FormComponent },
])
]
})

Loading…
Cancel
Save