new endpoint

Signed-off-by: FangyuanCheng <fangyuanc@vmware.com>
This commit is contained in:
FangyuanCheng 2019-02-25 16:00:31 +08:00
parent bb76a4d97d
commit 03c9bf8ceb
21 changed files with 293 additions and 112 deletions

View File

@ -11,6 +11,18 @@
</div>
<form #targetForm="ngForm">
<section class="form-block">
<!-- provider -->
<div class="form-group">
<label class="form-group-label-override required">{{'DESTINATION.PROVIDER' | translate}}</label>
<div class="form-select">
<div class="select providerSelect pull-left">
<select name="adapter" id="adapter" [(ngModel)]="target.type" [disabled]="testOngoing || controlEnabled">
<option *ngFor="let adapter of adapterList" [ngValue]="adapter" value="{{adapter.type}}">{{adapter.type}}</option>
</select>
</div>
</div>
</div>
<!-- Endpoint name -->
<div class="form-group">
<label for="destination_name" class="col-md-4 form-group-label-override required">{{ 'DESTINATION.NAME' |
translate }}</label>
@ -23,30 +35,39 @@
</span>
</label>
</div>
<!--Description-->
<div class="form-group">
<label class="form-group-label-override">{{'REPLICATION.DESCRIPTION' | translate}}</label>
<textarea type="text" class="inputWidth" row=3 name="description" [(ngModel)]="target.description"></textarea>
</div>
<!-- Endpoint Url -->
<div class="form-group">
<label for="destination_url" class="col-md-4 form-group-label-override required">{{ 'DESTINATION.URL' |
translate }}</label>
<label class="col-md-8" for="destination_url" aria-haspopup="true" role="tooltip" [class.invalid]="targetEndpoint.errors && (targetEndpoint.dirty || targetEndpoint.touched)"
[class.valid]="targetEndpoint.valid" class="tooltip tooltip-validation tooltip-sm tooltip-bottom-left">
<input type="text" id="destination_url" [disabled]="testOngoing" [readonly]="!editable" [(ngModel)]="target.endpoint"
<input type="text" id="destination_url" [disabled]="testOngoing || controlEnabled" [readonly]="!editable" [(ngModel)]="target.url"
size="20" name="endpointUrl" #targetEndpoint="ngModel" required placeholder="http(s)://192.168.1.1">
<span class="tooltip-content" *ngIf="targetEndpoint.errors && targetEndpoint.errors.required && (targetEndpoint.dirty || targetEndpoint.touched)">
{{ 'DESTINATION.URL_IS_REQUIRED' | translate }}
</span>
</label>
</div>
<!-- access_key -->
<div class="form-group">
<label for="destination_username" class="col-md-4 form-group-label-override">{{ 'DESTINATION.USERNAME' |
<label for="destination_access_key" class="col-md-4 form-group-label-override">{{ 'DESTINATION.ACCESS_ID' |
translate }}</label>
<input type="text" class="col-md-8" id="destination_username" [disabled]="testOngoing" [readonly]="!editable"
[(ngModel)]="target.username" size="20" name="username" #username="ngModel">
<input type="text" placeholder="Access ID" class="col-md-8" id="destination_access_key" [disabled]="testOngoing" [readonly]="!editable"
[(ngModel)]="target.credential.access_key" size="23" name="access_key" #access_key="ngModel">
</div>
<!-- access_secret -->
<div class="form-group">
<label for="destination_password" class="col-md-4 form-group-label-override">{{ 'DESTINATION.PASSWORD' |
<label for="destination_password" class="col-md-4 form-group-label-override">{{ 'DESTINATION.ACCESS_SECRET' |
translate }}</label>
<input type="password" class="col-md-8" id="destination_password" [disabled]="testOngoing" [readonly]="!editable"
[(ngModel)]="target.password" size="20" name="password" #password="ngModel">
<input type="password" placeholder="Access Secret" class="col-md-8" id="destination_password" [disabled]="testOngoing" [readonly]="!editable"
[(ngModel)]="target.credential.access_secret" size="23" name="access_secret" #access_secret="ngModel">
</div>
<!-- Verify Remote Cert -->
<div class="form-group">
<label for="destination_insecure" id="destination_insecure_checkbox">{{'CONFIG.VERIFY_REMOTE_CERT' |
translate }}</label>

View File

@ -10,4 +10,12 @@
.form-height {
height: 30px;
}
}
.providerSelect {
width: 180px;
}
.inputWidth {
width: 182px;
}

View File

@ -12,7 +12,7 @@ import { FilterComponent } from "../filter/filter.component";
import { CreateEditEndpointComponent } from "../create-edit-endpoint/create-edit-endpoint.component";
import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
import { ErrorHandler } from "../error-handler/error-handler";
import { Endpoint } from "../service/interface";
import { Endpoint, Adapter } from "../service/interface";
import {
EndpointService,
EndpointDefaultService
@ -21,14 +21,27 @@ import { IServiceConfig, SERVICE_CONFIG } from "../service.config";
describe("CreateEditEndpointComponent (inline template)", () => {
let mockData: Endpoint = {
id: 1,
url: "https://10.117.4.151",
name: "target_01",
username: "admin",
password: "",
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
type: "harbor"
name: "target_01",
type: "Harbor",
url: "https://10.117.4.151"
};
let mockAdapter: [Adapter] = [{
type: "Harbor",
description: "test",
supported_resource_types: [
"repository"
],
supported_resource_filters: null
}];
let comp: CreateEditEndpointComponent;
let fixture: ComponentFixture<CreateEditEndpointComponent>;
@ -39,6 +52,7 @@ describe("CreateEditEndpointComponent (inline template)", () => {
let endpointService: EndpointService;
let spy: jasmine.Spy;
let spyAdapter: jasmine.Spy;
beforeEach(async(() => {
TestBed.configureTestingModule({
@ -61,6 +75,10 @@ describe("CreateEditEndpointComponent (inline template)", () => {
comp = fixture.componentInstance;
endpointService = fixture.debugElement.injector.get(EndpointService);
spyAdapter = spyOn(endpointService, "getAdapters").and.returnValue(
Promise.resolve(mockAdapter)
);
spy = spyOn(endpointService, "getEndpoint").and.returnValue(
Promise.resolve(mockData)
);

View File

@ -18,7 +18,8 @@ import {
ViewChild,
AfterViewChecked,
ChangeDetectorRef,
OnDestroy
OnDestroy,
OnInit
} from "@angular/core";
import { NgForm } from "@angular/forms";
import { Subscription } from "rxjs";
@ -27,7 +28,7 @@ import { TranslateService } from "@ngx-translate/core";
import { EndpointService } from "../service/endpoint.service";
import { ErrorHandler } from "../error-handler/index";
import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
import { Endpoint } from "../service/interface";
import { Endpoint, Adapter } from "../service/interface";
import { toPromise, clone, compareValue, isEmptyObject } from "../utils";
@ -39,16 +40,17 @@ const FAKE_PASSWORD = "rjGcfuRu";
styleUrls: ["./create-edit-endpoint.component.scss"]
})
export class CreateEditEndpointComponent
implements AfterViewChecked, OnDestroy {
implements AfterViewChecked, OnDestroy, OnInit {
modalTitle: string;
controlEnabled: boolean = false;
createEditDestinationOpened: boolean;
staticBackdrop: boolean = true;
closable: boolean = false;
editable: boolean;
adapterList: Adapter[] = [];
target: Endpoint = this.initEndpoint();
selectedType: string;
initVal: Endpoint;
targetForm: NgForm;
@ViewChild("targetForm") currentForm: NgForm;
@ -71,6 +73,14 @@ export class CreateEditEndpointComponent
private ref: ChangeDetectorRef
) {}
ngOnInit(): void {
toPromise<Adapter[]>(this.endpointService.getAdapters())
.then(adapters => {
this.adapterList = adapters || [];
})
.catch((error: any) => this.errorHandler.error(error));
}
public get isValid(): boolean {
return (
!this.testOngoing &&
@ -98,13 +108,17 @@ export class CreateEditEndpointComponent
initEndpoint(): Endpoint {
return {
url: "",
name: "",
username: "",
password: "",
credential: {
access_key: "",
access_secret: "",
type: "basic"
},
description: "",
insecure: false,
type: ""
};
name: "",
type: "Harbor",
url: "",
};
}
open(): void {
@ -125,7 +139,6 @@ export class CreateEditEndpointComponent
this.initVal = this.initEndpoint();
this.formValues = null;
this.endpointId = "";
this.inlineAlert.close();
}
@ -158,11 +171,12 @@ export class CreateEditEndpointComponent
this.target = target;
// Keep data cache
this.initVal = clone(target);
this.initVal.password = FAKE_PASSWORD;
this.target.password = FAKE_PASSWORD;
this.initVal.credential.access_secret = FAKE_PASSWORD;
this.target.credential.access_secret = FAKE_PASSWORD;
// Open the modal now
this.open();
this.controlEnabled = true;
this.forceRefreshView(2000);
})
.catch(error => this.errorHandler.error(error));
@ -173,15 +187,16 @@ export class CreateEditEndpointComponent
.subscribe(res => (this.modalTitle = res));
// Directly open the modal
this.open();
this.controlEnabled = false;
}
}
testConnection() {
let payload: Endpoint = this.initEndpoint();
if (!this.endpointId) {
payload.endpoint = this.target.endpoint;
payload.username = this.target.username;
payload.password = this.target.password;
payload.url = this.target.url;
payload.credential.access_key = this.target.credential.access_key;
payload.credential.access_secret = this.target.credential.access_secret;
payload.insecure = this.target.insecure;
} else {
let changes: { [key: string]: any } = this.getChanges();
@ -225,7 +240,6 @@ export class CreateEditEndpointComponent
if (this.onGoing) {
return; // Avoid duplicated submitting
}
this.onGoing = true;
toPromise<number>(this.endpointService.createEndpoint(this.target))
.then(response => {

View File

@ -176,7 +176,7 @@ describe("CreateEditRuleComponent (inline template)", () => {
let config: IServiceConfig = {
replicationBaseEndpoint: "/api/replication/executions/testing",
targetBaseEndpoint: "/api/targets/testing"
targetBaseEndpoint: "/api/registries/testing"
};
beforeEach(async(() => {

View File

@ -105,12 +105,16 @@ export class CreateEditRuleComponent implements OnInit, OnDestroy {
};
emptyEndpoint = {
id: -1,
endpoint: "",
credential: {
access_key: "",
access_secret: "",
type: ""
},
description: "",
insecure: false,
name: "",
username: "",
password: "",
insecure: true,
type: 0
type: "",
url: "",
};
constructor(
private fb: FormBuilder,

View File

@ -17,17 +17,27 @@
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!(selectedRow.length ===1)" (click)="editTargets(selectedRow)" ><clr-icon shape="pencil" size="16"></clr-icon>&nbsp;{{'DESTINATION.EDIT' | translate}}</button>
<button type="button" class="btn btn-sm btn-secondary" [disabled]="!selectedRow.length" (click)="deleteTargets(selectedRow)"><clr-icon shape="times" size="16"></clr-icon>&nbsp;{{'DESTINATION.DELETE' | translate}}</button>
</clr-dg-action-bar>
<clr-dg-column [clrDgField]="'name'">{{'DESTINATION.NAME' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'endpoint'">{{'DESTINATION.URL' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'name'" class="flex-min-width">{{'DESTINATION.NAME' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'status'">{{'DESTINATION.STATUS' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'url'" class="flex-min-width">{{'DESTINATION.URL' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'type'" class="flex-min-width">{{'DESTINATION.PROVIDER' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'insecure'">{{'CONFIG.VERIFY_REMOTE_CERT' | translate }}</clr-dg-column>
<clr-dg-column [clrDgField]="'credential.type'">{{'DESTINATION.AUTHENTICATION' | translate }}</clr-dg-column>
<clr-dg-column [clrDgSortBy]="creationTimeComparator">{{'DESTINATION.CREATION_TIME' | translate}}</clr-dg-column>
<clr-dg-placeholder>{{'DESTINATION.PLACEHOLDER' | translate }}</clr-dg-placeholder>
<clr-dg-row *clrDgItems="let t of targets" [clrDgItem]='t'>
<clr-dg-cell>{{t.name}}</clr-dg-cell>
<clr-dg-cell>{{t.endpoint}}</clr-dg-cell>
<clr-dg-cell class="flex-min-width">{{t.name}}</clr-dg-cell>
<clr-dg-cell [ngSwitch]="t.status">
<div *ngSwitchCase="'unhealthy'"><clr-icon shape="exclamation-circle" class="is-error text-alignment" size="22"></clr-icon> Unhealthy</div>
<div *ngSwitchCase="'healthy'"><clr-icon shape="success-standard" class="is-success text-alignment" size="18"></clr-icon> Healthy</div>
<div *ngSwitchCase="'unknown' || ''"><clr-icon shape="exclamation-triangle" class="is-warning text-alignment" size="22"></clr-icon> Unknown</div>
</clr-dg-cell>
<clr-dg-cell class="flex-min-width">{{t.url}}</clr-dg-cell>
<clr-dg-cell class="flex-min-width">{{t.type}}</clr-dg-cell>
<clr-dg-cell>
{{!t.insecure}}
</clr-dg-cell>
<clr-dg-cell>{{t.credential.type}}</clr-dg-cell>
<clr-dg-cell>{{t.creation_time | date: 'short'}}</clr-dg-cell>
</clr-dg-row>
<clr-dg-footer>

View File

@ -25,4 +25,8 @@
.endpoint-view {
position: relative;
}
.flex-min-width {
min-width: 180px;
}

View File

@ -10,7 +10,7 @@ import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation
import { CreateEditEndpointComponent } from "../create-edit-endpoint/create-edit-endpoint.component";
import { InlineAlertComponent } from "../inline-alert/inline-alert.component";
import { ErrorHandler } from "../error-handler/error-handler";
import { Endpoint } from "../service/interface";
import { Endpoint, Adapter } from "../service/interface";
import {
EndpointService,
EndpointDefaultService
@ -24,54 +24,83 @@ describe("EndpointComponent (inline template)", () => {
let mockData: Endpoint[] = [
{
id: 1,
url: "https://10.117.4.151",
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
name: "target_01",
username: "admin",
password: "",
insecure: true,
type: "Harbor"
type: "Harbor",
url: "https://10.117.4.151"
},
{
id: 2,
url: "https://10.117.5.142",
name: "target_02",
username: "AAA",
password: "",
credential: {
access_key: "AAA",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
type: "Harbor"
name: "target_02",
type: "Harbor",
url: "https://10.117.5.142"
},
{
id: 3,
url: "https://101.1.11.111",
name: "target_03",
username: "admin",
password: "",
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
type: "Harbor"
name: "target_03",
type: "Harbor",
url: "https://101.1.11.111"
},
{
id: 4,
url: "http://4.4.4.4",
name: "target_04",
username: "",
password: "",
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
type: "Harbor"
name: "target_04",
type: "Harbor",
url: "https://4.4.4.4"
}
];
let mockOne: Endpoint[] = [
{
id: 1,
url: "https://10.117.4.151",
name: "target_01",
username: "admin",
password: "",
credential: {
access_key: "admin",
access_secret: "",
type: "basic"
},
description: "test",
insecure: false,
type: "Harbor"
name: "target_01",
type: "Harbor",
url: "https://10.117.4.151"
}
];
let mockAdapter: [Adapter] = [{
type: "Harbor",
description: "test",
supported_resource_types: [
"repository"
],
supported_resource_filters: null
}];
let comp: EndpointComponent;
let fixture: ComponentFixture<EndpointComponent>;
let config: IServiceConfig = {
@ -80,6 +109,7 @@ describe("EndpointComponent (inline template)", () => {
let endpointService: EndpointService;
let spy: jasmine.Spy;
let spyAdapter: jasmine.Spy;
let spyOnRules: jasmine.Spy;
let spyOne: jasmine.Spy;
beforeEach(async(() => {
@ -110,6 +140,11 @@ describe("EndpointComponent (inline template)", () => {
spy = spyOn(endpointService, "getEndpoints").and.returnValues(
Promise.resolve(mockData)
);
spyAdapter = spyOn(endpointService, "getAdapters").and.returnValue(
Promise.resolve(mockAdapter)
);
spyOnRules = spyOn(
endpointService,
"getEndpointWithReplicationRules"

View File

@ -77,12 +77,16 @@ export class EndpointComponent implements OnInit, OnDestroy {
get initEndpoint(): Endpoint {
return {
url: "",
name: "",
username: "",
password: "",
credential: {
access_key: "",
access_secret: "",
type: ""
},
description: "",
insecure: false,
type: ""
name: "",
type: "",
url: "",
};
}

View File

@ -86,6 +86,7 @@ export const DefaultServiceConfig: IServiceConfig = {
targetBaseEndpoint: "/api/registries",
replicationBaseEndpoint: "/api/replication/executions",
replicationRuleEndpoint: "/api/replication/policies",
adapterEndpoint: "api/replication/adapters",
vulnerabilityScanningBaseEndpoint: "/api/repositories",
projectPolicyEndpoint: "/api/projects/configs",
projectBaseEndpoint: "/api/projects",

View File

@ -84,21 +84,29 @@ describe('Replication Component (inline template)', () => {
let mockEndpoints: Endpoint[] = [
{
"id": 1,
"url": "https://10.117.4.151",
"name": "target_01",
"username": "admin",
"password": "",
"credential": {
"access_key": "admin",
"access_secret": "",
"type": "basic"
},
"description": "test",
"insecure": false,
"type": "Harbor"
"name": "target_01",
"type": "Harbor",
"url": "https://10.117.4.151"
},
{
"id": 2,
"url": "https://10.117.5.142",
"name": "target_02",
"username": "AAA",
"password": "",
"credential": {
"access_key": "admin",
"access_secret": "",
"type": "basic"
},
"description": "test",
"insecure": false,
"type": "Harbor"
"name": "target_02",
"type": "Harbor",
"url": "https://10.117.5.142"
},
];

View File

@ -54,6 +54,11 @@ export interface IServiceConfig {
*/
replicationBaseEndpoint?: string;
/**
* The base endpoint of the service used to handle the adapters.
*/
adapterEndpoint?: string;
/**
* The base endpoint of the service used to handle the replication rules.
* Replication rule related endpoints will be built based on this endpoint.

View File

@ -9,7 +9,7 @@ import {
HTTP_GET_OPTIONS
} from "../utils";
import { RequestQueryParams } from "./RequestQueryParams";
import { Endpoint, ReplicationRule } from "./interface";
import { Endpoint, ReplicationRule, Adapter } from "./interface";
/**
* Define the service methods to handle the endpoint related things.
@ -57,6 +57,17 @@ export abstract class EndpointService {
*
* @memberOf EndpointService
*/
abstract getAdapters(): Observable<any> | Promise<any> | any;
/**
* Create new endpoint.
*
* @abstract
* ** deprecated param {Adapter} adapter
* returns {(Observable<any> | any)}
*
* @memberOf EndpointService
*/
abstract createEndpoint(
endpoint: Endpoint
): Observable<any> | Promise<any> | any;
@ -167,6 +178,14 @@ export class EndpointDefaultService extends EndpointService {
.catch(error => Promise.reject(error));
}
public getAdapters(): Observable<any> | Promise<any> | any {
return this.http
.get(`/api/replication/adapters`)
.toPromise()
.then(response => response.json() as Adapter)
.catch(error => Promise.reject(error));
}
public createEndpoint(
endpoint: Endpoint
): Observable<any> | Promise<any> | any {

View File

@ -75,13 +75,27 @@ export interface Tag extends Base {
* extends {Base}
*/
export interface Endpoint extends Base {
url: string;
name: string;
username?: string;
password?: string;
credential: {
access_key?: string,
access_secret?: string,
type: string;
};
description: string;
insecure: boolean;
name: string;
type: string;
[key: string]: any;
url: string;
}
export interface Adapter extends Base {
type: string;
description: string;
supported_resource_types: [
string
];
supported_resource_filters: [
string
];
}
/**

View File

@ -65,6 +65,7 @@ const uiLibConfig: IServiceConfig = {
targetBaseEndpoint: "/api/registries",
replicationBaseEndpoint: "/api/replication/executions",
replicationRuleEndpoint: "/api/replication/policies",
adapterEndpoint: "api/replication/adapters",
vulnerabilityScanningBaseEndpoint: "/api/repositories",
projectPolicyEndpoint: "/api/projects/configs",
projectBaseEndpoint: "/api/projects",

View File

@ -456,22 +456,25 @@
},
"DESTINATION": {
"NEW_ENDPOINT": "New Endpoint",
"PROVIDER": "Provider",
"ENDPOINT": "Endpoint",
"NAME": "Endpoint Name",
"NAME": "Name",
"NAME_IS_REQUIRED": "Endpoint name is required.",
"URL": "Endpoint URL",
"URL_IS_REQUIRED": "Endpoint URL is required.",
"USERNAME": "Username",
"PASSWORD": "Password",
"AUTHENTICATION":"Authentication",
"ACCESS_ID": "Access ID",
"ACCESS_SECRET": "Access Secret",
"STATUS": "Status",
"TEST_CONNECTION": "Test Connection",
"TITLE_EDIT": "Edit Endpoint",
"TITLE_ADD": "Create Endpoint",
"TITLE_ADD": "New Registry Endpoint",
"EDIT": "Edit",
"DELETE": "Delete",
"TESTING_CONNECTION": "Testing Connection...",
"TEST_CONNECTION_SUCCESS": "Connection tested successfully.",
"TEST_CONNECTION_FAILURE": "Failed to ping endpoint.",
"CONFLICT_NAME": "Endpoint name or URL already exists.",
"CONFLICT_NAME": "Endpoint name already exists.",
"INVALID_NAME": "Invalid endpoint name.",
"FAILED_TO_GET_TARGET": "Failed to get endpoint.",
"CREATION_TIME": "Creation Time",

View File

@ -457,22 +457,25 @@
},
"DESTINATION": {
"NEW_ENDPOINT": "Nuevo Endpoint",
"PROVIDER": "Provider",
"ENDPOINT": "Endpoint",
"NAME": "Nombre del Endpoint",
"NAME": "Nombre",
"NAME_IS_REQUIRED": "El nombre del endpoint es obligatorio.",
"URL": "URL del Endpoint",
"URL_IS_REQUIRED": "La URL del endpoint es obligatoria.",
"USERNAME": "Nombre de usuario",
"PASSWORD": "Contraseña",
"AUTHENTICATION":"Autenticación",
"ACCESS_ID": "ID de acceso",
"ACCESS_SECRET": "Secreto de acceso",
"STATUS": "Estado",
"TEST_CONNECTION": "Comprobar conexión",
"TITLE_EDIT": "Editar Endpoint",
"TITLE_ADD": "Crear Endpoint",
"TITLE_ADD": "Nuevo punto final de registro",
"EDIT": "Editar",
"DELETE": "Eliminar",
"TESTING_CONNECTION": "Comprobar conexión...",
"TEST_CONNECTION_SUCCESS": "Conexión comprobada satisfactoriamente.",
"TEST_CONNECTION_FAILURE": "Fallo al comprobar el endpoint.",
"CONFLICT_NAME": "El nombre del endpoint ya existe.",
"CONFLICT_NAME": "El nombre ya existe.",
"INVALID_NAME": "El nombre del endpoint no es válido.",
"FAILED_TO_GET_TARGET": "Fallo al obtener el endpoint.",
"CREATION_TIME": "Fecha de creación",

View File

@ -438,21 +438,24 @@
},
"DESTINATION": {
"NEW_ENDPOINT": "Nouveau Point Final",
"PROVIDER": "Provider",
"ENDPOINT": "Point Final",
"NAME": "Nom du Point Final",
"NAME": "Alors",
"NAME_IS_REQUIRED": "Le nom du Point final est obligatoire.",
"URL": "URL du Point Final",
"URL_IS_REQUIRED": "L'URL du Point Final est obligatoire.",
"USERNAME": "Nom d'utilisateur",
"PASSWORD": "Mot de Passe",
"AUTHENTICATION":"Authentification",
"ACCESS_ID": "ID d'accès",
"ACCESS_SECRET": "Secret d'accès",
"STATUS": "Statut",
"TEST_CONNECTION": "Test de Connexion",
"TITLE_EDIT": "Editer le Point Final",
"TITLE_ADD": "Créer le Point Final",
"TITLE_ADD": "Nouveau point de terminaison de registre",
"DELETE": "Supprimer le Point Final",
"TESTING_CONNECTION": "En train de tester la Connexion...",
"TEST_CONNECTION_SUCCESS": "Connexion testée avec succès.",
"TEST_CONNECTION_FAILURE": "Echec du ping du Point Final.",
"CONFLICT_NAME": "Le nom ou l'URL du point final existe déjà.",
"CONFLICT_NAME": "Le nom du noeud final existe déjà.",
"INVALID_NAME": "Nom du point final invalide.",
"FAILED_TO_GET_TARGET": "Echec de l'obtention du point final.",
"CREATION_TIME": "Temps de Création",

View File

@ -456,22 +456,25 @@
},
"DESTINATION": {
"NEW_ENDPOINT": "Novo Endpoint",
"PROVIDER": "Provider",
"ENDPOINT": "Endpoint",
"NAME": "Nome do Endpoint",
"NAME": "Nome",
"NAME_IS_REQUIRED": "Nome do Endpoint é obrigatório.",
"URL": "URL do Endpoint",
"URL_IS_REQUIRED": "URL do Endpoint URL é obrigatória.",
"USERNAME": "Nome de usuário",
"PASSWORD": "Senha",
"AUTHENTICATION":"Autenticação",
"ACCESS_ID": "ID de acesso",
"ACCESS_SECRET": "Secreto de acceso",
"STATUS": "Segredo de acesso",
"TEST_CONNECTION": "Testar Conexão",
"TITLE_EDIT": "Editar Endpoint",
"TITLE_ADD": "Criar Endpoint",
"TITLE_ADD": "Novo ponto final do registro",
"EDIT": "Editar",
"DELETE": "Remover",
"TESTING_CONNECTION": "Testando Conexão...",
"TEST_CONNECTION_SUCCESS": "Conexão testada com sucesso.",
"TEST_CONNECTION_FAILURE": "Falha ao pingar o endpoint.",
"CONFLICT_NAME": "Nome do Endpoint ou URL já existe.",
"CONFLICT_NAME": "O nome do terminal já existe.",
"INVALID_NAME": "Nome do Endpoint inválido.",
"FAILED_TO_GET_TARGET": "Falha ao obter endpoint.",
"CREATION_TIME": "Data de criação",

View File

@ -457,13 +457,16 @@
},
"DESTINATION": {
"NEW_ENDPOINT": "新建目标",
"PROVIDER": "提供者",
"ENDPOINT": "目标",
"NAME": "目标名",
"NAME_IS_REQUIRED": "目标名为必填项。",
"URL": "目标URL",
"URL_IS_REQUIRED": "目标URL为必填项。",
"USERNAME": "用户名",
"PASSWORD": "密码",
"AUTHENTICATION":"认证",
"ACCESS_ID": "访问ID",
"ACCESS_SECRET": "访问密码",
"STATUS": "状态",
"TEST_CONNECTION": "测试连接",
"TITLE_EDIT": "编辑目标",
"TITLE_ADD": "新建目标",
@ -472,7 +475,7 @@
"TESTING_CONNECTION": "正在测试连接...",
"TEST_CONNECTION_SUCCESS": "测试连接成功。",
"TEST_CONNECTION_FAILURE": "测试连接失败。",
"CONFLICT_NAME": "目标名或目标URL已存在。",
"CONFLICT_NAME": "目标名已存在。",
"INVALID_NAME": "无效的目标名称。",
"FAILED_TO_GET_TARGET": "获取目标失败。",
"CREATION_TIME": "创建时间",