同步器增加属性配置管理

This commit is contained in:
llh
2024-09-24 17:00:56 +08:00
parent 0199445c51
commit e3b9fdb201
39 changed files with 6003 additions and 71 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -66,6 +66,7 @@
"ngx-cookie-service": "^13.2.0",
"ngx-tinymce": "^13.0.0",
"ngx-ueditor": "^13.0.0",
"npm": "^8.5.5",
"rxjs": "~7.5.0",
"screenfull": "^6.0.1",
"tslib": "^2.3.0",

View File

@@ -0,0 +1,46 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BaseEntity } from './BaseEntity';
export class JobConfigFeild extends BaseEntity {
jobId!: String;
name!: String;
objectType!: String;
targetField!: String;
sourceField!: String;
constructor() {
super();
}
override init(data: any): void {
Object.assign(this, data);
if (this.status == 1) {
this.switch_status = true;
}
}
override trans(): void {
if (this.switch_status) {
this.status = 1;
} else {
this.status = 0;
}
}
}

View File

@@ -45,6 +45,10 @@ import { SocialsProviderEditerComponent } from './socials-provider/socials-provi
import { SocialsProviderComponent } from './socials-provider/socials-provider.component';
import { SynchronizerEditerComponent } from './synchronizers/synchronizer-editer/synchronizer-editer.component';
import { SynchronizersComponent } from './synchronizers/synchronizers.component';
import { SynchronizerConfigFieldComponent } from './synchronizers/synchronizer-config-field/synchronizer-config-field.component';
import {
SynchronizerConfigFieldEditComponent
} from "./synchronizers/synchronizer-config-field/editer/synchronizer-config-field-edit.component";
const routes: Routes = [
{
@@ -115,7 +119,9 @@ const COMPONENTS = [PasswordPolicyComponent, EmailSendersComponent, LdapContextC
SelectAccountsStrategyComponent,
SelectAdaptersComponent,
ConnectorsComponent,
ConnectorEditerComponent
ConnectorEditerComponent,
SynchronizerConfigFieldComponent,
SynchronizerConfigFieldEditComponent
],
imports: [SharedModule, CommonModule, RouterModule.forChild(routes)],
exports: [RouterModule]

View File

@@ -0,0 +1,41 @@
<div *nzModalTitle> {{ isEdit ? ('mxk.text.edit' | i18n) : ('mxk.text.add' | i18n) }} </div>
<div>
<form nz-form [formGroup]="formGroup" (ngSubmit)="onSubmit($event)" se-container="1">
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="sourceField">{{ 'mxk.job.mapping.sourceField' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.sourceField" [ngModelOptions]="{ standalone: true }" nz-input
name="sourceField" id="sourceField" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="targetField">{{ 'mxk.job.mapping.targetField' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.targetField" [ngModelOptions]="{ standalone: true }" nz-input
name="targetField" id="targetField" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="description">{{ 'mxk.job.mapping.description' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<input [(ngModel)]="form.model.description" [ngModelOptions]="{ standalone: true }" nz-input
name="description" id="description" />
</nz-form-control>
</nz-form-item>
<nz-form-item>
<nz-form-label [nzMd]="6" nzFor="objectType">{{ 'mxk.job.mapping.objectType' | i18n }}</nz-form-label>
<nz-form-control [nzMd]="18" nzErrorTip="The input is not valid id!">
<nz-select [(ngModel)]="form.model.objectType" [ngModelOptions]="{ standalone: true }" name="objectType" id="objectType">
<nz-option nzValue="1" nzLabel="{{ 'mxk.menu.identities.users' | i18n }}"></nz-option>
<nz-option nzValue="2" nzLabel="{{ 'mxk.menu.identities.organizations' | i18n }}"></nz-option>
</nz-select>
</nz-form-control>
</nz-form-item>
</form>
</div>
<div *nzModalFooter>
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div>

View File

@@ -0,0 +1,92 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component, ChangeDetectorRef, Input, OnInit, Inject } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { I18NService } from '@core';
import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { JobConfigFeild } from '../../../../../entity/JobConfigFeild';
import { SynchronizersService } from '../../../../../service/synchronizers.service';
@Component({
selector: 'app-synchronizer-config-field-edit',
templateUrl: './synchronizer-config-field-edit.component.html',
styles: [
`
nz-form-item {
width: 100%;
}
`
],
})
export class SynchronizerConfigFieldEditComponent implements OnInit {
@Input() id?: String;
@Input() jobId?: String;
@Input() isEdit?: boolean;
form: {
submitting: boolean;
model: JobConfigFeild
} = {
submitting: false,
model: new JobConfigFeild(),
};
formGroup: FormGroup = new FormGroup({});
constructor(
private modalRef: NzModalRef,
private synchronizersService: SynchronizersService,
private fb: FormBuilder,
private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void {
this.get()
}
get(){
if (this.isEdit) {
this.synchronizersService.getField(`${this.id}`).subscribe(res => {
this.form.model.init(res.data);
this.cdr.detectChanges();
});
}
}
onClose(e: MouseEvent): void {
e.preventDefault();
this.modalRef.destroy({ refresh: false });
}
onSubmit(e: MouseEvent): void {
e.preventDefault();
this.form.submitting = true;
this.form.model.jobId = this.jobId +"";
(this.isEdit ? this.synchronizersService.mappingUpdate(this.form.model) : this.synchronizersService.mappingAdd(this.form.model)).subscribe(res => {
if (res.code == 0) {
this.msg.success(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.success' : 'mxk.alert.add.success'));
} else {
this.msg.error(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.error' : 'mxk.alert.add.error'));
}
this.form.submitting = false;
this.modalRef.destroy({ refresh: true });
this.cdr.detectChanges();
});
}
}

View File

@@ -0,0 +1,41 @@
<div *nzModalTitle> {{ ('mxk.text.mapping' | i18n) }} </div>
<div>
<div nz-row [nzGutter]="{ xs: 8, sm: 8, md: 8, lg: 24, xl: 48, xxl: 48 }">
<div nz-col [nzSpan]="24" class="table-list-toolbar">
<button nz-button type="button" [nzType]="'primary'" (click)="onAdd($event)">{{ 'mxk.text.add' | i18n }}</button>
</div>
<div nz-col nzMd="24" nzSm="24">
<nz-table [nzShowPagination]="false" [nzData]="form.rows">
<thead>
<tr>
<th nzAlign="center">{{ 'mxk.job.mapping.sourceField' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.job.mapping.targetField' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.job.mapping.description' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.job.mapping.objectType' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.action' | i18n }}</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let data of form.rows">
<td nzAlign="left">{{ data.sourceField }} </td>
<td nzAlign="left">{{ data.targetField }} </td>
<td nzAlign="left">{{ data.description }} </td>
<td nzAlign="center">
{{ data.objectType == '1' ? ('mxk.menu.identities.users' | i18n) : ('mxk.menu.identities.organizations' | i18n) }}
</td>
<td nzAlign="center">
<button nz-button type="button" (click)="onEdit($event, data.id)">{{ 'mxk.text.edit' | i18n }}</button>
<button nz-button type="button" nzDanger (click)="onDelete($event, data.id)">{{ 'mxk.text.delete' | i18n }}</button>
</td>
</tr>
</tbody>
</nz-table>
</div>
</div>
</div>
<div *nzModalFooter>
<button nz-button nzType="default" (click)="onClose($event)">{{ 'mxk.text.close' | i18n }}</button>
<button nz-button nzType="primary" (click)="onSubmit($event)">{{ 'mxk.text.submit' | i18n }}</button>
</div>

View File

@@ -0,0 +1,42 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SynchronizerConfigFieldComponent } from './synchronizer-config-field.component';
describe('SynchronizerConfigFieldComponent', () => {
let component: SynchronizerConfigFieldComponent;
let fixture: ComponentFixture<SynchronizerConfigFieldComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ SynchronizerConfigFieldComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(SynchronizerConfigFieldComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,148 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Component, ChangeDetectorRef, Input, OnInit, Inject, ViewContainerRef} from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { I18NService } from '@core';
import { _HttpClient, ALAIN_I18N_TOKEN, SettingsService } from '@delon/theme';
import format from 'date-fns/format';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalRef, NzModalService } from 'ng-zorro-antd/modal';
import { JobConfigFeild } from '../../../../entity/JobConfigFeild';
import { SynchronizersService } from '../../../../service/synchronizers.service';
import {NzSafeAny} from "ng-zorro-antd/core/types";
import { SynchronizerConfigFieldEditComponent } from './editer/synchronizer-config-field-edit.component';
@Component({
selector: 'app-synchronizer-config-field',
templateUrl: './synchronizer-config-field.component.html',
styles: [
`
nz-form-item {
width: 100%;
}
`
],
styleUrls: ['./synchronizer-config-field.component.less']
})
export class SynchronizerConfigFieldComponent implements OnInit {
@Input() jobId?: String;
@Input() isEdit?: boolean;
form: {
submitting: boolean;
rows: NzSafeAny[]
} = {
submitting: false,
rows: []
};
formGroup: FormGroup = new FormGroup({});
constructor(
private modalRef: NzModalRef,
private modalService: NzModalService,
private synchronizersService: SynchronizersService,
private viewContainerRef: ViewContainerRef,
private fb: FormBuilder,
private msg: NzMessageService,
@Inject(ALAIN_I18N_TOKEN) private i18n: I18NService,
private cdr: ChangeDetectorRef
) {}
ngOnInit(): void {
this.fetch()
}
fetch(){
this.synchronizersService.getMapping(`${this.jobId}`).subscribe(res => {
this.form.rows = res.data
this.cdr.detectChanges();
});
}
onClose(e: MouseEvent): void {
e.preventDefault();
this.modalRef.destroy({ refresh: false });
}
onDelete(e: MouseEvent, deleteId: String): void {
e.preventDefault();
this.synchronizersService.deleteMapping(deleteId).subscribe(res => {
if (res.code == 0) {
this.msg.success(this.i18n.fanyi('mxk.alert.delete.success'));
this.fetch();
} else {
this.msg.error(this.i18n.fanyi('mxk.alert.delete.error'));
}
this.cdr.detectChanges();
});
}
onEdit(e: MouseEvent, id: String): void {
e.preventDefault();
const modal = this.modalService.create({
nzContent: SynchronizerConfigFieldEditComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: true,
id: id,
jobId: this.jobId,
},
nzWidth: 1200,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
onAdd(e: MouseEvent): void {
e.preventDefault();
const modal = this.modalService.create({
nzContent: SynchronizerConfigFieldEditComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: false,
jobId: this.jobId,
},
nzWidth: 1200,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
onSubmit(e: MouseEvent): void {
e.preventDefault();
this.form.submitting = true;
/* (this.isEdit ? this.synchronizersService.update(this.form.model) : this.synchronizersService.add(this.form.model)).subscribe(res => {
if (res.code == 0) {
this.msg.success(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.success' : 'mxk.alert.add.success'));
} else {
this.msg.error(this.i18n.fanyi(this.isEdit ? 'mxk.alert.update.error' : 'mxk.alert.add.error'));
}
this.form.submitting = false;
this.modalRef.destroy({ refresh: true });
this.cdr.detectChanges();
});*/
}
}

View File

@@ -43,7 +43,7 @@
<th nzAlign="center">{{ 'mxk.synchronizers.name' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.synchronizers.scheduler' | i18n }}</th>
<th nzAlign="center">{{ 'mxk.text.status' | i18n }}</th>
<th nzAlign="center" class="table_cell_action_3">{{ 'mxk.text.action' | i18n }}</th>
<th nzAlign="center" class="table_cell_action_5">{{ 'mxk.text.action' | i18n }}</th>
</tr>
</thead>
<tbody>
@@ -62,10 +62,14 @@
<div nz-col>
<button nz-button type="button" (click)="onSynchr($event, data.id)">{{ 'mxk.text.synchr'
| i18n }}</button>
<button nz-button type="button" (click)="onConfigFeild($event, data.id)">{{ 'mxk.text.mapping'
| i18n }}</button>
<button nz-button type="button" (click)="onEdit($event, data.id)">{{ 'mxk.text.edit' |
i18n }}</button>
<button nz-button type="button" (click)="onDelete($event, data.id)" nzDanger>{{ 'mxk.text.delete' | i18n
}}</button>
</div>
</td>
</tr>

View File

@@ -27,6 +27,7 @@ import { NzTableQueryParams } from 'ng-zorro-antd/table';
import { SynchronizersService } from '../../../service/synchronizers.service';
import { set2String } from '../../../shared/index';
import { SynchronizerEditerComponent } from './synchronizer-editer/synchronizer-editer.component';
import { SynchronizerConfigFieldComponent } from './synchronizer-config-field/synchronizer-config-field.component';
@Component({
selector: 'app-synchronizers',
templateUrl: './synchronizers.component.html',
@@ -150,6 +151,7 @@ export class SynchronizersComponent implements OnInit {
});
}
onEdit(e: MouseEvent, editId: String): void {
e.preventDefault();
const modal = this.modalService.create({
@@ -159,6 +161,7 @@ export class SynchronizersComponent implements OnInit {
isEdit: true,
id: editId
},
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
@@ -168,6 +171,26 @@ export class SynchronizersComponent implements OnInit {
}
});
}
onConfigFeild(e: MouseEvent, jobId: String): void {
e.preventDefault();
const modal = this.modalService.create({
nzContent: SynchronizerConfigFieldComponent,
nzViewContainerRef: this.viewContainerRef,
nzComponentParams: {
isEdit: true,
jobId: jobId
},
nzWidth: 1200,
nzOnOk: () => new Promise(resolve => setTimeout(resolve, 1000))
});
// Return a result when closed
modal.afterClose.subscribe(result => {
if (result.refresh) {
this.fetch();
}
});
}
onDelete(e: MouseEvent, deleteId: String): void {
e.preventDefault();

View File

@@ -22,6 +22,7 @@ import { Observable } from 'rxjs';
import { Message } from '../entity/Message';
import { Synchronizers } from '../entity/Synchronizers';
import { BaseService } from './base.service';
import {JobConfigFeild} from "../entity/JobConfigFeild";
@Injectable({
providedIn: 'root'
@@ -34,4 +35,24 @@ export class SynchronizersService extends BaseService<Synchronizers> {
synchr(synchrId: String): Observable<Message<Synchronizers>> {
return this.http.get<Message<Synchronizers>>(`${`${this.server.urls.base}/synchr`}?id=${synchrId}`);
}
getMapping(synchrId: String): Observable<Message<Synchronizers>> {
return this.http.get<Message<JobConfigFeild>>(`${`${this.server.urls.base}/mapping-list`}/${synchrId}`);
}
getField(id: String): Observable<Message<Synchronizers>> {
return this.http.get<Message<JobConfigFeild>>(`${`${this.server.urls.base}/mapping-get`}/${id}`);
}
mappingAdd(body: any): Observable<Message<JobConfigFeild>> {
return this.http.post<Message<JobConfigFeild>>(`${this.server.urls.base}/mapping-add`, body);
}
mappingUpdate(body: any): Observable<Message<JobConfigFeild>> {
return this.http.put<Message<JobConfigFeild>>(`${this.server.urls.base}/mapping-update`, body);
}
deleteMapping(id: String): Observable<Message<JobConfigFeild>> {
return this.http.get<Message<JobConfigFeild>>(`${`${this.server.urls.base}/mapping-delete`}/${id}`);
}
}

View File

@@ -119,6 +119,10 @@ body {
margin-bottom: 2px !important;
}
.table_cell_action_5 {
width: 360px;
}
.table_cell_action_3 {
width: 240px;
}

View File

@@ -720,7 +720,7 @@
"success":"Operate Success!",
"error":"Operate Error!"
}
},
"text": {
"action": "Action",
@@ -935,5 +935,10 @@
"validation.title.required": "Please enter a title",
"validation.date.required": "Please select the start and end date",
"validation.goal.required": "Please enter a description of the goal",
"validation.standard.required": "Please enter a metric"
}
"validation.standard.required": "Please enter a metric",
"mxk.text.mapping": "Feild Mapping",
"mxk.job.mapping.targetField": "TargetField",
"mxk.job.mapping.sourceField": "SourceField",
"mxk.job.mapping.objectType": "ObjectType",
"mxk.job.mapping.description": "Description"
}

View File

@@ -927,5 +927,12 @@
"validation.title.required": "请输入标题",
"validation.date.required": "请选择起止日期",
"validation.goal.required": "请输入目标描述",
"validation.standard.required": "请输入衡量标准"
}
"validation.standard.required": "请输入衡量标准",
"mxk.text.mapping": "属性映射",
"mxk.job.mapping.targetField": "目标字段",
"mxk.job.mapping.sourceField": "来源字段",
"mxk.job.mapping.objectType": "映射类型",
"mxk.job.mapping.description": "规则说明"
}

View File

@@ -928,5 +928,10 @@
"validation.title.required": "請輸入標題",
"validation.date.required": "請選擇起止日期",
"validation.goal.required": "請輸入目標描述",
"validation.standard.required": "請輸入衡量標準"
}
"validation.standard.required": "請輸入衡量標準",
"mxk.text.mapping": "属性映射",
"mxk.job.mapping.targetField": "目标字段",
"mxk.job.mapping.sourceField": "来源字段",
"mxk.job.mapping.objectType": "映射类型",
"mxk.job.mapping.description": "规则说明"
}