Commit 539f7e82 by Ooh-Ao

widjet

parent e454f58f
......@@ -22,6 +22,7 @@
"bootstrap": "^5.3.3",
"echarts": "^5.5.1",
"express": "^4.18.2",
"jwt-decode": "^4.0.0",
"ngx-echarts": "^18.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
......@@ -7889,6 +7890,14 @@
"node >= 0.2.0"
]
},
"node_modules/jwt-decode": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
"engines": {
"node": ">=18"
}
},
"node_modules/karma": {
"version": "6.4.3",
"resolved": "https://registry.npmjs.org/karma/-/karma-6.4.3.tgz",
......
......@@ -25,6 +25,7 @@
"bootstrap": "^5.3.3",
"echarts": "^5.5.1",
"express": "^4.18.2",
"jwt-decode": "^4.0.0",
"ngx-echarts": "^18.0.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
......
......@@ -3,6 +3,7 @@ import { RouterOutlet } from '@angular/router';
import { NgxEchartsDirective, provideEcharts } from 'ngx-echarts';
import { ConsultancyComponent } from './components';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { TimestampWidgetComponent } from './widjets/zeeme/timestamp-widget/timestamp-widget.component';
@Component({
selector: 'app-root',
......
......@@ -28,6 +28,10 @@ export const routes: Routes = [
component: LayoutWidjetComponent
},
{
path: 'layout/:appName/:companyId/:token',
component: LayoutWidjetComponent
},
{
path: 'layout-setting',
component: LayoutWidjetSettingComponent
}
......
body,
html {
overflow-x: hidden !important;
margin: 0 !important;
padding: 0 !important;
/* height: 200%; */
}
::-webkit-scrollbar {
......@@ -18,3 +16,8 @@ html {
::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.4);
}
app-services{
/* padding: 5px !important; */
margin-top: 5px !important;
}
<div #rowWidjet class="row" style="background-color:transparent;">
<app-services [id]="item.id" *ngFor="let item of widgetList" class="col-{{item.width}}"
style="margin-top: 5px;"></app-services>
<app-services [id]="item.id" *ngFor="let item of widgetList" class="col-{{item.width}}" [token]="token"
[companyId]="companyId"></app-services>
</div>
......@@ -15,11 +15,16 @@ import { ActivatedRoute } from '@angular/router';
export class LayoutWidjetComponent implements OnInit {
@ViewChild('rowWidjet', { static: false }) rowWidjet?: ElementRef;
appName = ""
token = ""
companyId = ""
widjetId = 0
widgetList: Service[] = []
constructor(private widjetService: WidjetService, private readonly activatedRoute: ActivatedRoute) {
this.activatedRoute.paramMap.subscribe(result => {
this.appName = result.get('appName')!
this.companyId = result.get('companyId')!
this.token = result.get('token')!
sessionStorage.setItem("token", this.token)
this.widgetList = this.widjetService.widjetConfig.filter(e => e.appName == this.appName)[0].widjet
})
......
......@@ -6,10 +6,11 @@ import {
} from './components';
import { Type } from '@angular/core';
import { ServiceTypes } from './services/widjet.service';
import { TimestampWidgetComponent } from './widjets/zeeme/timestamp-widget/timestamp-widget.component';
export type ServiceComponentType = ConsultancyComponent
| TrainingsComponent
| SoftwareEngineeringComponent | StatisticComponent;
| SoftwareEngineeringComponent | StatisticComponent | TimestampWidgetComponent;
export const servicesComponentFactory:
Record<ServiceTypes, Type<ServiceComponentType>>
......@@ -18,5 +19,6 @@ export const servicesComponentFactory:
[ServiceTypes.trainings]: TrainingsComponent,
[ServiceTypes.engineering]: SoftwareEngineeringComponent,
[ServiceTypes.statistic]: StatisticComponent,
[ServiceTypes.timestamp]: TimestampWidgetComponent,
};
......@@ -5,7 +5,7 @@ import { ComponentHostDirective } from '../directives/component-host.directive';
import { ServiceComponentType, servicesComponentFactory } from '../services-factory';
import { HttpClient, HttpClientModule, HttpHeaders } from '@angular/common/http';
import { Service, ServiceTypes, WidjetService } from './widjet.service';
import { jwtDecode } from "jwt-decode";
@Component({
selector: 'app-services',
standalone: true,
......@@ -14,14 +14,16 @@ import { Service, ServiceTypes, WidjetService } from './widjet.service';
styleUrls: ['./services.component.scss'],
})
export class ServicesComponent implements OnInit {
@Input() token?: string;
@Input() companyId?: string;
@Input() id?: number;
@Output() valueChange: EventEmitter<Service> = new EventEmitter<Service>();
widjetSelect?: Service
@ViewChild(ComponentHostDirective, { static: true }) componentHost!: ComponentHostDirective;
constructor(private readonly route: ActivatedRoute, private widjetService: WidjetService) { }
constructor(private readonly route: ActivatedRoute, private widjetService: WidjetService, private http: HttpClient) { }
destroy: Subject<void> = new Subject<void>();
......@@ -35,7 +37,8 @@ export class ServicesComponent implements OnInit {
tap((service: Service) => this.loadComponent(service)),
takeUntil(this.destroy.asObservable()),
)
.subscribe();
.subscribe(result => {
});
......@@ -50,7 +53,14 @@ export class ServicesComponent implements OnInit {
this.destroy.asObservable()
this.id = changes['id'].currentValue
this.getOne(this.id!).subscribe(result => {
this.loadComponent(result)
this.widjetSelect = result
if (this.token) {
console.log(this.token)
this.loadData(this.widjetSelect)
} else {
this.loadComponent(this.widjetSelect)
}
})
}
......@@ -66,9 +76,25 @@ export class ServicesComponent implements OnInit {
const { instance } = viewContainerRef.createComponent<ServiceComponentType>(
servicesComponentFactory[service.id as ServiceTypes]
);
service.dataModel = instance.model;
if (service.dataSoure) {
instance.model = service.dataSoure;
}else{
service.dataModel = instance.model;
}
}
// setComponent(service: Service): void {
// const { viewContainerRef }: ComponentHostDirective = this.componentHost;
// viewContainerRef.clear();
// const { instance } = viewContainerRef.createComponent<ServiceComponentType>(
// servicesComponentFactory[service.id as ServiceTypes]
// );
// instance.model = service.dataSoure
// }
ngOnDestroy(): void {
this.destroy.next();
}
......@@ -79,4 +105,19 @@ export class ServicesComponent implements OnInit {
e.id == num)[0];
return of(componentFilter)
}
loadData(widget: Service) {
const user: any = jwtDecode(this.token!)
widget.api = widget.api.replace('${companyId}', this.companyId!).replace('${memberId}', user.uid)
const options = {
headers: new HttpHeaders({
"Authorization": "Bearer " + this.token,
}),
};
this.http.get(widget.api, options).subscribe(result => {
console.log("token", result)
widget.dataSoure = result
this.loadComponent(widget)
})
}
}
......@@ -23,7 +23,8 @@ export enum ServiceTypes {
consultancy, // 0
trainings, // 1
engineering, // 2
statistic, //3
statistic, //3,
timestamp,
}
@Injectable({
providedIn: 'root'
......@@ -38,7 +39,7 @@ export class WidjetService {
title: "11111",
description: "111",
dataModel: "ss",
dataSoure: "sss",
dataSoure: "",
api: "",
width: 12,
heigth: "",
......@@ -49,7 +50,7 @@ export class WidjetService {
title: "222",
description: "222",
dataModel: "ss",
dataSoure: "sss",
dataSoure: "",
api: "",
width: 12,
heigth: "",
......@@ -60,7 +61,7 @@ export class WidjetService {
title: "3333",
description: "33333",
dataModel: "ss",
dataSoure: "sss",
dataSoure: "",
api: "select data",
width: 12,
heigth: "",
......@@ -71,7 +72,7 @@ export class WidjetService {
title: "4444",
description: "4444",
dataModel: "4444",
dataSoure: "2312",
dataSoure: "",
api: "https://hrplus.myhr.co.th/hr/taapi/leave/statistic?yearId=2024",
width: 12,
heigth: "",
......@@ -82,7 +83,7 @@ export class WidjetService {
title: "4444",
description: "4444",
dataModel: "4444",
dataSoure: "2312",
dataSoure: "",
api: "https://hrplus.myhr.co.th/hr/taapi/leave/statistic?yearId=2024",
width: 12,
heigth: "",
......@@ -93,11 +94,22 @@ export class WidjetService {
title: "4444",
description: "4444",
dataModel: "4444",
dataSoure: "2312",
dataSoure: "",
api: "https://hrplus.myhr.co.th/hr/taapi/leave/statistic?yearId=2024",
width: 12,
heigth: "",
tag: ""
},
{
id: 4,
title: "Timestamp log",
description: "4444",
dataModel: "4444",
dataSoure: "",
api: "https://zeeme.myhr.co.th/ZeemeApi/rest/timestamp/empfull-between-date/${companyId}/${memberId}/2024-07-23/2024-07-23",
width: 12,
heigth: "",
tag: ""
}
]
}, {
......@@ -668,7 +680,7 @@ export class WidjetService {
"width": 6,
"heigth": "",
"tag": ""
},{
}, {
"id": 0,
"title": "11111",
"description": "111",
......@@ -758,7 +770,7 @@ export class WidjetService {
title: "11111",
description: "111",
dataModel: "ss",
dataSoure: "sss",
dataSoure: "",
api: "",
width: 6,
heigth: "",
......@@ -769,7 +781,7 @@ export class WidjetService {
title: "222",
description: "222",
dataModel: "ss",
dataSoure: "sss",
dataSoure: "",
api: "",
width: 6,
heigth: "",
......@@ -780,7 +792,7 @@ export class WidjetService {
title: "3333",
description: "33333",
dataModel: "ss",
dataSoure: "sss",
dataSoure: "",
api: "select data",
width: 3,
heigth: "",
......@@ -791,34 +803,23 @@ export class WidjetService {
title: "4444",
description: "4444",
dataModel: "4444",
dataSoure: "2312",
dataSoure: "",
api: "https://hrplus.myhr.co.th/hr/taapi/leave/statistic?yearId=2024",
width: 3,
heigth: "",
tag: ""
},
{
id: 3,
title: "4444",
id: 4,
title: "Timestamp log",
description: "4444",
dataModel: "4444",
dataSoure: "2312",
api: "https://hrplus.myhr.co.th/hr/taapi/leave/statistic?yearId=2024",
width: 3,
heigth: "",
tag: ""
},
{
id: 3,
title: "4444",
description: "4444",
dataModel: "4444",
dataSoure: "2312",
api: "https://hrplus.myhr.co.th/hr/taapi/leave/statistic?yearId=2024",
width: 3,
dataSoure: "",
api: "https://zeeme.myhr.co.th/ZeemeApi/rest/timestamp/empfull-between-date/${companyId}/${memberId}/2024-07-01/2024-07-23",
width: 12,
heigth: "",
tag: ""
},]
}]
constructor() { }
}
......@@ -46,13 +46,13 @@ export class SettingWidgetComponent implements OnInit {
console.log("changeComponent", this.widgetModel)
this.widjetId = this.widgetModel?.id!
this.api = this.widgetModel?.api!
this.loadData()
// this.loadData()
}
loadData() {
const options = {
headers: new HttpHeaders({
"Authorization": "Bearer eyJhbGciOiJIUzI1NiJ9.eyJzY2hlbWEiOiJkYm8iLCJlbmNvZGUiOiIyIiwic3ViIjoiQXV0aCIsImNvbXBhbnlOYW1lIjoi4Lia4Lij4Li04Lip4Lix4LiXIOC4oeC4suC4ouC5gOC4reC4iuC4reC4suC4o-C5jCDguIjguLPguIHguLHguJQiLCJkYk5hbWUiOiJIUlBsdXMiLCJyb2xlcyI6WyJVU0VSIl0sIndvcmthcmVhIjoiTk9ORSIsImlzcyI6IkNvbXB1dGVyIFNjaWVuY2UgQ29ycG9yYXRpb24gTGltaXRlZCIsInptbG9naW4iOiJmYWxzZSIsInJvbGVfbGV2ZWwiOiIiLCJlbXBsb3llZWlkIjoiMjAxODAyMTAiLCJicmFuY2giOiIxMDAiLCJlbXBfcG9zaXRpb24iOiJQLVJELTIyMDEiLCJ1c2VyX3JvbGUiOiIiLCJ1aWQiOiIyMDE4MDIxMCIsImNvbXBhbnlpZCI6IjEwMCIsImFjdG9yaWQiOiIyMDE4MDIxMCIsImxhbmciOiJ0aCIsImFkIjoiZmFsc2UiLCJmaXJzdGxvZ2luIjoiZmFsc2UiLCJ1cmxfbXlociI6Imh0dHA6Ly9ocnBsdXMubXloci5jby50aC9ociIsImFwcF9uYW1lIjoibXlociIsInJlZ2lvbmFsbHR5IjoiRU5HIiwidG9rZW5femVlbWUiOiIiLCJ1c2VyX2xldmVsIjoiRW1wLVVzZXIiLCJmdWxsbmFtZSI6IuC4meC4suC4ouC4iuC4meC4sOC4iuC4seC4oiAg4LmC4Lit4LiU4Lie4Li04Lih4Lie4LmMIiwiY29taWQiOiIiLCJqb2IiOiJKLVJELTIyMDEiLCJ1c2VyIjoiQ2hhbmFjaGFpLm8iLCJ6bV91c2VyIjoiIiwidXNlcm5hbWUiOiJjaGFuYWNoYWkubyIsIm1lbWJlcmlkIjoiIn0.5BgyoT-lLs9qFDj3iIizzYNeA0vWd9nTU8QHpzxMF7A",
"Authorization": "Bearer " + sessionStorage.getItem("token"),
}),
};
this.http.get(this.widgetModel.api, options).subscribe(result => {
......
<div class="card mb-4">
<div class="col-12">
<ul class="list-group list-group-flush bg-none">
<li class="list-group-item" *ngFor="let item of model.timestamps">
<div class="row">
<div class="col-auto">
<div class="avatar avatar-50 shadow rounded-10">
<img appShowLoading *ngIf="item?.pictureUrl != '' ;else personblank" src="{{item?.pictureUrl}}">
<ng-template #personblank>
<img src="assets/img/icon/person.png">
</ng-template>
</div>
</div>
<div class="col align-self-center ps-0">
<p class="text-color-theme mb-0">{{item.locationName}}</p>
<span
class="tag text-white py-1 px-2 {{item.timeStampStatus==1?'bg-warning border-warning':'bg-success border-success'}}">{{item.timeStampStatus==1?"Warning":"Complete"}}</span>
</div>
<div class="col-auto align-self-center text-end">
<p class="mb-0">{{item.swipeDatetime | date : 'HH:mm'}}</p>
<p class="text-muted size-12">{{item.swipeType =='In'?'บันทึกเข้า':'บันทึกออก'}}</p>
</div>
</div>
</li>
</ul>
</div>
</div>
/* tslint:disable:no-unused-variable */
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { TimestampWidgetComponent } from './timestamp-widget.component';
describe('TimestampWidgetComponent', () => {
let component: TimestampWidgetComponent;
let fixture: ComponentFixture<TimestampWidgetComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ TimestampWidgetComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(TimestampWidgetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { CommonModule, DatePipe } from '@angular/common';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-timestamp-widget',
templateUrl: './timestamp-widget.component.html',
styleUrls: ['./timestamp-widget.component.scss'],
standalone: true,
imports: [CommonModule, DatePipe]
})
export class TimestampWidgetComponent implements OnInit {
model: any = {
"employee": {
"memberId": "13c8f7a0-cc39-11e8-97e8-e1409beaaed1",
"companyId": "1f2d7f90-24dc-11e7-a032-7b0164ffa2bb",
"employeeCode": "13c8f7a0-cc39-11e8-97e8-e1409beaaed11f2d7f90-24dc-11e7-a032-7b0164ffa2bb",
"fullName": "ชนะชัย โอดพิมพ์",
"position": "Front-End Developer Manager",
"department": "แผนกการค้นคว้าวิจัยระบบ",
"pictureUrl": "https://zeeme.myhr.co.th/ZeemeApi/rest/image/employee/picture/1f2d7f90-24dc-11e7-a032-7b0164ffa2bb/13c8f7a0-cc39-11e8-97e8-e1409beaaed1/3b48fa06-37e4-4b08-a7e0-6a646a33616a",
"faceUrl": "https://zeeme.myhr.co.th/ZeemeApi/rest/image/employee/face/1f2d7f90-24dc-11e7-a032-7b0164ffa2bb/13c8f7a0-cc39-11e8-97e8-e1409beaaed1/d0508e10-605c-11eb-96ed-1f2a4d52256e",
"tel": "#0983162284",
"bossModel": null,
"lagacyCode": "20180210",
"picture": null,
"noCriteria": 0
},
"timestamps": [
{
"companyId": "1f2d7f90-24dc-11e7-a032-7b0164ffa2bb",
"memberId": "13c8f7a0-cc39-11e8-97e8-e1409beaaed1",
"fullName": "ชนะชัย โอดพิมพ์",
"employeeCode": null,
"swipeDatetime": "2024-07-23 08:52+0700",
"swipeTypeId": 1,
"swipeType": "In",
"authenBy": "Face Recognition",
"latitude": "13.9807609",
"longitude": "100.4784027",
"locationName": "NH",
"pictureUrl": "https://zeeme.myhr.co.th/ZeemeApi/rest/image/company/timestamp/1f2d7f90-24dc-11e7-a032-7b0164ffa2bb/13c8f7a0-cc39-11e8-97e8-e1409beaaed1/202407230852/996e28ec-4198-4aa4-b590-764d33847eff",
"timeStampStatus": 2,
"contractNo": null,
"siteNo": null,
"customerId": null,
"siteName": null,
"approveId": null,
"approveName": null,
"createDatetime": "2024-07-23 08:52+0700",
"editDatetime": null,
"deviceNo": "50eac3ede2e4adea",
"deviceName": null
}
]
}
constructor() { }
ngOnInit() {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment