Merge pull request #9470 from AllForNothing/scanner-improve

Improve scanner UI
This commit is contained in:
Will Sun 2019-10-21 18:12:05 +08:00 committed by GitHub
commit d137471906
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 115 additions and 68 deletions

View File

@ -10,7 +10,7 @@
<clr-tab>
<button id="config-vulnerability" clrTabLink>{{'CONFIG.VULNERABILITY' | translate}}</button>
<clr-tab-content id="vulnerability" *clrIfActive>
<vulnerability-config *ngIf="withClair" #vulnerabilityConfig [showSubTitle]="true"></vulnerability-config>
<vulnerability-config #vulnerabilityConfig [showSubTitle]="true"></vulnerability-config>
</clr-tab-content>
</clr-tab>
<clr-tab>

View File

@ -19,3 +19,6 @@
.replication-tooltip {
top: -8px;
}
.margin-top-3px {
margin-top: 3px;
}

View File

@ -73,7 +73,7 @@
</clr-checkbox-container>
<div class="clr-form-control d-f" *ngIf="withClair">
<div class="clr-form-control d-f">
<label for="systemWhitelist"
class="clr-control-label">{{'CVE_WHITELIST.DEPLOYMENT_SECURITY'|translate}}</label>
<div class="form-content">

View File

@ -10,7 +10,7 @@
<clr-control-helper class="config-subtext"> {{ 'PROJECT_CONFIG.PUBLIC_POLICY' | translate }}
</clr-control-helper>
</clr-checkbox-container>
<clr-checkbox-container *ngIf="withNotary || withClair">
<clr-checkbox-container *ngIf="withNotary">
<label><span *ngIf="withNotary">{{ 'PROJECT_CONFIG.SECURITY' | translate }}</span></label>
<clr-checkbox-wrapper *ngIf="withNotary">
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.ContentTrust" name="content-trust"
@ -20,9 +20,9 @@
<clr-control-helper class="config-subtext"> {{ 'PROJECT_CONFIG.CONTENT_TRUST_POLCIY' | translate }}
</clr-control-helper>
</clr-checkbox-container>
<clr-checkbox-container id="prevent-vulenrability-image" *ngIf="withNotary || withClair">
<clr-checkbox-container id="prevent-vulenrability-image" *ngIf="withNotary">
<label><span *ngIf="!withNotary">{{ 'PROJECT_CONFIG.SECURITY' | translate }}</span></label>
<clr-checkbox-wrapper *ngIf="withClair">
<clr-checkbox-wrapper>
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.PreventVulImg"
name="prevent-vulenrability-image-input" [disabled]="!hasChangeConfigRole" />
<label>{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_TOGGLE' | translate }}</label>
@ -46,7 +46,7 @@
</div>
</clr-control-helper>
</clr-checkbox-container>
<clr-checkbox-container *ngIf="withClair">
<clr-checkbox-container>
<label>{{ 'PROJECT_CONFIG.SCAN' | translate }}</label>
<clr-checkbox-wrapper id="scan-image-on-push-wrapper">
<input type="checkbox" clrCheckbox [(ngModel)]="projectPolicy.ScanImgOnPush"
@ -56,7 +56,7 @@
<clr-control-helper class="config-subtext"> {{ 'PROJECT_CONFIG.AUTOSCAN_POLICY' | translate }}
</clr-control-helper>
</clr-checkbox-container>
<div class="clr-form-control" [class.clr-form-control-disabled]="!hasChangeConfigRole" *ngIf="withClair">
<div class="clr-form-control" [class.clr-form-control-disabled]="!hasChangeConfigRole">
<label for="systemWhitelist" class="clr-control-label">{{'CVE_WHITELIST.CVE_WHITELIST'|translate}}</label>
<div class="w-100 clr-control-container">
<div class="config-subtext">

View File

@ -55,8 +55,7 @@
<section id="image" role="tabpanel" aria-labelledby="repo-image" [hidden]='!isCurrentTabContent("image")'>
<div id=images-container>
<hbr-tag ngProjectAs="clr-dg-row-detail" (tagClickEvent)="watchTagClickEvt($event)" (signatureOutput)="saveSignatures($event)"
class="sub-grid-custom" [repoName]="repoName" [registryUrl]="registryUrl" [withNotary]="withNotary"
[withClair]="withClair" [withAdmiral]="withAdmiral" [hasSignedIn]="hasSignedIn"
class="sub-grid-custom" [repoName]="repoName" [registryUrl]="registryUrl" [withNotary]="withNotary" [withAdmiral]="withAdmiral" [hasSignedIn]="hasSignedIn"
[isGuest]="isGuest" [projectId]="projectId" [memberRoleID]="memberRoleID"></hbr-tag>
</div>
</section>

View File

@ -85,7 +85,7 @@
<clr-dg-column *ngIf="withNotary">{{'REPOSITORY.SIGNED' | translate}}</clr-dg-column>
<clr-dg-column>{{'REPOSITORY.AUTHOR' | translate}}</clr-dg-column>
<clr-dg-column [clrDgSortBy]="createdComparator">{{'REPOSITORY.CREATED' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'docker_version'" *ngIf="!withClair">{{'REPOSITORY.DOCKER_VERSION' | translate}}</clr-dg-column>
<clr-dg-column [clrDgField]="'docker_version'">{{'REPOSITORY.DOCKER_VERSION' | translate}}</clr-dg-column>
<clr-dg-column *ngIf="!withAdmiral">{{'REPOSITORY.LABELS' | translate}}</clr-dg-column>
<clr-dg-column [clrDgSortBy]="pushComparator">{{'REPOSITORY.PUSH_TIME' | translate}}</clr-dg-column>
<clr-dg-column [clrDgSortBy]="pullComparator">{{'REPOSITORY.PULL_TIME' | translate}}</clr-dg-column>
@ -111,7 +111,7 @@
</clr-dg-cell>
<clr-dg-cell class="truncated" title="{{t.author}}">{{t.author}}</clr-dg-cell>
<clr-dg-cell>{{t.created | date: 'short'}}</clr-dg-cell>
<clr-dg-cell *ngIf="!withClair">{{t.docker_version}}</clr-dg-cell>
<clr-dg-cell>{{t.docker_version}}</clr-dg-cell>
<clr-dg-cell *ngIf="!withAdmiral">
<hbr-label-piece *ngIf="t.labels?.length" [label]="t.labels[0]" [labelWidth]="90"> </hbr-label-piece>
<div class="signpost-item" [hidden]="t.labels?.length<=1">

View File

@ -723,9 +723,7 @@ export class TagComponent implements OnInit, AfterViewInit {
canScanNow(t: Tag[]): boolean {
if (!this.hasScanImagePermission) { return false; }
let st: string = this.scanStatus(t[0]);
return st !== VULNERABILITY_SCAN_STATUS.PENDING &&
st !== VULNERABILITY_SCAN_STATUS.RUNNING;
return st !== VULNERABILITY_SCAN_STATUS.RUNNING;
}
getImagePermissionRule(projectId: number): void {
let hasAddLabelImagePermission = this.userPermissionService.getPermission(projectId, USERSTATICPERMISSION.REPOSITORY_TAG_LABEL.KEY,

View File

@ -43,12 +43,12 @@
</a>
</clr-vertical-nav-group-children>
</clr-vertical-nav-group>
<clr-vertical-nav-group *ngIf="isSystemAdmin && (withClair || hasAdminRole)" routerLinkActive="active">
<clr-vertical-nav-group *ngIf="isSystemAdmin && hasAdminRole" routerLinkActive="active">
<clr-icon shape="event" clrVerticalNavIcon></clr-icon>
{{'SIDE_NAV.TASKS' | translate}}
<a routerLink="#" hidden aria-hidden="true"></a>
<clr-vertical-nav-group-children *clrIfExpanded="true">
<a clrVerticalNavLink *ngIf="withClair" routerLink="/harbor/vulnerability"
<a clrVerticalNavLink routerLink="/harbor/vulnerability"
routerLinkActive="active">
{{'SIDE_NAV.SYSTEM_MGMT.VULNERABILITY' | translate}}
</a>

View File

@ -17,18 +17,26 @@
<button clrDropdownItem
(click)="changeStat()"
[disabled]="!(selectedRow && !selectedRow.is_default)">
<span *ngIf="selectedRow && selectedRow.disabled">{{'BUTTON.ENABLE' | translate}}</span>
<span *ngIf="!(selectedRow && selectedRow.disabled)">{{'BUTTON.DISABLE' | translate}}</span>
<span *ngIf="selectedRow && selectedRow.disabled">
<clr-icon class="margin-top-2" size="16" shape="success-standard"></clr-icon>
<span class="margin-left-10">{{'SCANNER.ENABLE' | translate}}</span>
</span>
<span *ngIf="!(selectedRow && selectedRow.disabled)">
<clr-icon class="margin-top-2" size="16" shape="ban"></clr-icon>
<span class="margin-left-10">{{'SCANNER.DISABLE' | translate}}</span>
</span>
</button>
<button clrDropdownItem
(click)="editScanner()"
class="btn btn-sm btn-secondary" [disabled]="!selectedRow">
{{'BUTTON.EDIT' | translate}}
<clr-icon class="margin-top-0" size="16" shape="pencil"></clr-icon>
<span class="margin-left-10">{{'BUTTON.EDIT' | translate}}</span>
</button>
<button clrDropdownItem
(click)="deleteScanners()"
class="btn btn-sm btn-secondary" [disabled]="!selectedRow">
{{'BUTTON.DELETE' | translate}}
<clr-icon class="margin-top-0" size="16" shape="times"></clr-icon>
<span class="margin-left-10">{{'BUTTON.DELETE' | translate}}</span>
</button>
</clr-dropdown-menu>
</clr-dropdown>
@ -45,7 +53,7 @@
<clr-dg-column class="width-240" [clrDgField]="'name'">{{'SCANNER.NAME' | translate}}</clr-dg-column>
<clr-dg-column class="width-240" [clrDgField]="'url'">{{'SCANNER.ENDPOINT' | translate}}</clr-dg-column>
<clr-dg-column>{{'SCANNER.HEALTH' | translate}}</clr-dg-column>
<clr-dg-column>{{'SCANNER.DISABLED' | translate}}</clr-dg-column>
<clr-dg-column>{{'SCANNER.ENABLED' | translate}}</clr-dg-column>
<clr-dg-column>{{'SCANNER.AUTH' | translate}}</clr-dg-column>
<clr-dg-placeholder>
{{'SCANNER.NO_SCANNER' | translate}}
@ -62,7 +70,7 @@
<span class="label label-danger">{{'SCANNER.UNHEALTHY' | translate}}</span>
</ng-template>
</clr-dg-cell>
<clr-dg-cell>{{scanner.disabled}}</clr-dg-cell>
<clr-dg-cell>{{!scanner.disabled}}</clr-dg-cell>
<clr-dg-cell>{{scanner.auth?scanner.auth:'None'}}</clr-dg-cell>
<scanner-metadata *clrIfExpanded [uid]="scanner.uuid" ngProjectAs="clr-dg-row-detail"></scanner-metadata>
</clr-dg-row>

View File

@ -22,3 +22,12 @@
.width-240 {
min-width: 240px !important;
}
.margin-top-0 {
margin-top: 0;
}
.margin-top-2 {
margin-top: 2px;
}
.margin-left-10 {
margin-left: 10px;
}

View File

@ -35,7 +35,7 @@ export class ConfigurationScannerComponent implements OnInit, OnDestroy {
confirmed.state === ConfirmationState.CONFIRMED) {
this.configScannerService.deleteScanners(confirmed.data)
.subscribe(response => {
this.msgHandler.showSuccess("Delete Success");
this.msgHandler.showSuccess("SCANNER.DELETE_SUCCESS");
this.getScanners();
}, error => {
this.errorHandler.error(error);
@ -76,7 +76,7 @@ export class ConfigurationScannerComponent implements OnInit, OnDestroy {
scanner.disabled = !scanner.disabled;
this.configScannerService.updateScanner(scanner)
.subscribe(response => {
this.msgHandler.showSuccess("Update Success");
this.msgHandler.showSuccess("SCANNER.UPDATE_SUCCESS");
this.getScanners();
}, error => {
this.errorHandler.error(error);
@ -87,7 +87,7 @@ export class ConfigurationScannerComponent implements OnInit, OnDestroy {
if (this.selectedRow) {
this.configScannerService.setAsDefault(this.selectedRow.uuid)
.subscribe(response => {
this.msgHandler.showSuccess("Update Success");
this.msgHandler.showSuccess("SCANNER.UPDATE_SUCCESS");
this.getScanners();
}, error => {
this.errorHandler.error(error);

View File

@ -4,7 +4,7 @@
<label class="required clr-control-label">{{"SCANNER.NAME" | translate}}</label>
<div class="clr-control-container" [class.clr-error]="!isNameValid">
<div class="clr-input-wrapper">
<input autocomplete="off" #name formControlName="name" class="clr-input width-312"
<input autocomplete="off" #name formControlName="name" class="clr-input width-280"
type="text"
id="scanner-name">
<clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon>
@ -18,7 +18,7 @@
<div class="clr-form-control">
<label class="clr-control-label">{{"SCANNER.DESCRIPTION" | translate}}</label>
<div class="clr-control-container">
<textarea autocomplete="off" formControlName="description" class="clr-textarea width-312" type="text"
<textarea autocomplete="off" formControlName="description" class="clr-textarea width-280" type="text"
id="description">
</textarea>
</div>
@ -28,7 +28,7 @@
<div class="clr-control-container" [class.clr-error]="!isEndpointValid || showEndpointError">
<div class="clr-input-wrapper">
<input (focus)="showEndpointError=false" (blur)="checkEndpointUrl()" #endpointUrl placeholder="http(s)://192.168.1.1" autocomplete="off" formControlName="url"
class="clr-input width-312" type="text" id="scanner-endpoint">
class="clr-input width-280" type="text" id="scanner-endpoint">
<clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon>
<span class="spinner spinner-inline" [hidden]="!checkEndpointOnGoing"></span>
</div>
@ -41,7 +41,7 @@
<label class="clr-control-label">{{"SCANNER.AUTH" | translate}}</label>
<div class="clr-control-container">
<div class="clr-select-wrapper">
<select formControlName="auth" class="clr-select width-312" id="scanner-authorization">
<select formControlName="auth" class="clr-select width-280" id="scanner-authorization">
<option value="None">{{"SCANNER.NONE" | translate}}</option>
<option value="Basic">{{"SCANNER.BASIC" | translate}}</option>
<option value="Bearer">{{"SCANNER.BEARER" | translate}}</option>
@ -56,7 +56,7 @@
<div class="clr-control-container" [class.clr-error]="!isUserNameValid">
<div class="clr-input-wrapper">
<input formControlName="username" autocomplete="off"
class="clr-input width-312" type="text" id="scanner-username">
class="clr-input width-280" type="text" id="scanner-username">
<clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon>
</div>
<clr-control-error *ngIf="!isUserNameValid">
@ -69,7 +69,7 @@
<div class="clr-control-container" [class.clr-error]="!isPasswordValid">
<div class="clr-input-wrapper">
<input formControlName="password" autocomplete="off"
class="clr-input width-312" type="password" id="scanner-password">
class="clr-input width-280" type="password" id="scanner-password">
<clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon>
</div>
<clr-control-error *ngIf="!isPasswordValid">
@ -82,7 +82,7 @@
<div class="clr-control-container" [class.clr-error]="!isTokenValid">
<div class="clr-input-wrapper">
<input formControlName="token" autocomplete="off"
class="clr-input width-312" type="text" id="scanner-token">
class="clr-input width-280" type="text" id="scanner-token">
<clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon>
</div>
<clr-control-error *ngIf="!isTokenValid">
@ -95,7 +95,7 @@
<div class="clr-control-container" [class.clr-error]="!isApiKeyValid">
<div class="clr-input-wrapper">
<input formControlName="apiKey" autocomplete="off"
class="clr-input width-312" type="text" id="scanner-apiKey">
class="clr-input width-280" type="text" id="scanner-apiKey">
<clr-icon class="clr-validate-icon" shape="exclamation-circle"></clr-icon>
</div>
<clr-control-error *ngIf="!isApiKeyValid">

View File

@ -1,6 +1,9 @@
.width-312 {
width: 312px;
.width-280 {
width: 280px;
}
.padding-top-3 {
padding-top: 3px;
}
.clr-control-label {
width: 9rem !important;
}

View File

@ -21,7 +21,7 @@ export class NewScannerFormComponent implements OnInit, AfterViewInit, OnDestro
checkOnGoing: boolean = false;
newScannerForm: FormGroup = this.fb.group({
name: this.fb.control("",
[Validators.required, Validators.pattern(/^[a-z0-9]+(?:[._-][a-z0-9]+)*$/)]),
[Validators.required]),
description: this.fb.control(""),
url: this.fb.control("",
[Validators.required,
@ -57,7 +57,7 @@ export class NewScannerFormComponent implements OnInit, AfterViewInit, OnDestro
if (this.isEdit && this.originValue && this.originValue.name === name) {
return false;
}
return this.newScannerForm.get('name').valid && name.length > 1;
return this.newScannerForm.get('name').valid && name.length > 0;
}),
debounceTime(500),
distinctUntilChanged(),
@ -130,15 +130,15 @@ export class NewScannerFormComponent implements OnInit, AfterViewInit, OnDestro
return true;
}
if (this.isNameExisting) {
this.nameTooltip = 'NAME_EXISTS';
this.nameTooltip = 'SCANNER.NAME_EXISTS';
return false;
}
if (this.newScannerForm.get('name').errors && this.newScannerForm.get('name').errors.required) {
this.nameTooltip = 'NAME_REQUIRED';
this.nameTooltip = 'SCANNER.NAME_REQUIRED';
return false;
}
if (this.newScannerForm.get('name').errors && this.newScannerForm.get('name').errors.pattern) {
this.nameTooltip = 'NAME_REX';
this.nameTooltip = 'SCANNER.NAME_REX';
return false;
}
return true;
@ -151,11 +151,11 @@ export class NewScannerFormComponent implements OnInit, AfterViewInit, OnDestro
return true;
}
if (this.isEndpointUrlExisting) {
this.endpointTooltip = 'ENDPOINT_EXISTS';
this.endpointTooltip = 'SCANNER.ENDPOINT_EXISTS';
return false;
}
if (this.newScannerForm.get('url').errors && this.newScannerForm.get('url').errors.required) {
this.endpointTooltip = 'ENDPOINT_REQUIRED';
this.endpointTooltip = 'SCANNER.ENDPOINT_REQUIRED';
return false;
}
// skip here, validate when onblur
@ -167,7 +167,7 @@ export class NewScannerFormComponent implements OnInit, AfterViewInit, OnDestro
// validate endpointUrl when onblur
checkEndpointUrl() {
if (this.newScannerForm.get('url').errors && this.newScannerForm.get('url').errors.pattern) {
this.endpointTooltip = "ILLEGAL_ENDPOINT";
this.endpointTooltip = "SCANNER.ILLEGAL_ENDPOINT";
this.showEndpointError = true;
}
}

View File

@ -5,7 +5,7 @@
<div class="clr-form-control">
<label class="clr-control-label name">{{'SCANNER.SCANNER' | translate}}</label>
<div class="clr-control-container">
<button *ngIf="scanners && scanners.length > 0" id="edit-scanner" class="btn btn-link edit" (click)="open()">{{'SCANNER.EDIT' | translate}}</button>
<label *ngIf="!(scanners && scanners.length > 0)" class="name">{{'SCANNER.NOT_AVAILABLE' | translate}}</label>
</div>
</div>
@ -16,9 +16,10 @@
<div class="clr-input-wrapper">
<div class="clr-input-wrapper">
<span id="scanner-name" class="scanner-name">{{scanner?.name}}</span>
<button *ngIf="scanners && scanners.length > 0" id="edit-scanner" class="btn btn-primary btn-sm" (click)="open()">{{'SCANNER.EDIT' | translate}}</button>
<span *ngIf="scanner?.disabled" class="label label-warning ml-1">{{'SCANNER.DISABLED' | translate}}</span>
<span *ngIf="scanner?.health" class="label label-success ml-1">{{'SCANNER.HEALTHY' | translate}}</span>
<span *ngIf="!scanner?.health" class="label label-danger ml-1">{{'SCANNER.Unhealthy' | translate}}</span>
<span *ngIf="!scanner?.health" class="label label-danger ml-1">{{'SCANNER.UNHEALTHY' | translate}}</span>
</div>
</div>
</div>

View File

@ -18,3 +18,6 @@
justify-content: center;
align-items: center;
}
.clr-form-control {
margin-top: 0.75rem !important;
}

View File

@ -6,7 +6,6 @@
</div>
<hbr-tag-detail (backEvt)="goBack($event)"
[tagId]="tagId"
[withClair]="withClair"
[withAdmiral]="withAdmiral"
[projectId]="projectId"
[repositoryId]="repositoryId"></hbr-tag-detail>

View File

@ -1260,10 +1260,10 @@
"ADD_SCANNER": "Add Scanner",
"EDIT_SCANNER": "Edit Scanner",
"TEST_CONNECTION": "TEST CONNECTION",
"ADD_SUCCESS": "Added successfully",
"ADD_SUCCESS": "Successfully added ",
"TEST_PASS": "Test passed",
"TEST_FAILED": "Test failed",
"UPDATE_SUCCESS": "Updated successfully",
"UPDATE_SUCCESS": "Successfully updated",
"SCANNER_COLON": "Scanner:",
"NAME_COLON": "Name:",
"VENDOR_COLON": "Vendor:",
@ -1287,6 +1287,10 @@
"ADAPTER": "Adapter",
"VENDOR": "Vendor",
"VERSION": "Version",
"SELECT_SCANNER": "Select Scanner"
"SELECT_SCANNER": "Select Scanner",
"ENABLED": "Enabled",
"ENABLE": "Enable",
"DISABLE": "Disable",
"DELETE_SUCCESS": "Successfully deleted"
}
}

View File

@ -1257,10 +1257,10 @@
"ADD_SCANNER": "Add Scanner",
"EDIT_SCANNER": "Edit Scanner",
"TEST_CONNECTION": "TEST CONNECTION",
"ADD_SUCCESS": "Added successfully",
"ADD_SUCCESS": "Successfully added ",
"TEST_PASS": "Test passed",
"TEST_FAILED": "Test failed",
"UPDATE_SUCCESS": "Updated successfully",
"UPDATE_SUCCESS": "Successfully updated",
"SCANNER_COLON": "Scanner:",
"NAME_COLON": "Name:",
"VENDOR_COLON": "Vendor:",
@ -1284,6 +1284,10 @@
"ADAPTER": "Adapter",
"VENDOR": "Vendor",
"VERSION": "Version",
"SELECT_SCANNER": "Select Scanner"
"SELECT_SCANNER": "Select Scanner",
"ENABLED": "Enabled",
"ENABLE": "Enable",
"DISABLE": "Disable",
"DELETE_SUCCESS": "Successfully deleted"
}
}

View File

@ -1229,10 +1229,10 @@
"ADD_SCANNER": "Add Scanner",
"EDIT_SCANNER": "Edit Scanner",
"TEST_CONNECTION": "TEST CONNECTION",
"ADD_SUCCESS": "Added successfully",
"ADD_SUCCESS": "Successfully added ",
"TEST_PASS": "Test passed",
"TEST_FAILED": "Test failed",
"UPDATE_SUCCESS": "Updated successfully",
"UPDATE_SUCCESS": "Successfully updated",
"SCANNER_COLON": "Scanner:",
"NAME_COLON": "Name:",
"VENDOR_COLON": "Vendor:",
@ -1256,6 +1256,10 @@
"ADAPTER": "Adapter",
"VENDOR": "Vendor",
"VERSION": "Version",
"SELECT_SCANNER": "Select Scanner"
"SELECT_SCANNER": "Select Scanner",
"ENABLED": "Enabled",
"ENABLE": "Enable",
"DISABLE": "Disable",
"DELETE_SUCCESS": "Successfully deleted"
}
}

View File

@ -1254,10 +1254,10 @@
"ADD_SCANNER": "Add Scanner",
"EDIT_SCANNER": "Edit Scanner",
"TEST_CONNECTION": "TEST CONNECTION",
"ADD_SUCCESS": "Added successfully",
"ADD_SUCCESS": "Successfully added ",
"TEST_PASS": "Test passed",
"TEST_FAILED": "Test failed",
"UPDATE_SUCCESS": "Updated successfully",
"UPDATE_SUCCESS": "Successfully updated",
"SCANNER_COLON": "Scanner:",
"NAME_COLON": "Name:",
"VENDOR_COLON": "Vendor:",
@ -1281,7 +1281,11 @@
"ADAPTER": "Adapter",
"VENDOR": "Vendor",
"VERSION": "Version",
"SELECT_SCANNER": "Select Scanner"
"SELECT_SCANNER": "Select Scanner",
"ENABLED": "Enabled",
"ENABLE": "Enable",
"DISABLE": "Disable",
"DELETE_SUCCESS": "Successfully deleted"
}
}

View File

@ -1259,10 +1259,10 @@
"ADD_SCANNER": "Add Scanner",
"EDIT_SCANNER": "Edit Scanner",
"TEST_CONNECTION": "TEST CONNECTION",
"ADD_SUCCESS": "Added successfully",
"ADD_SUCCESS": "Successfully added ",
"TEST_PASS": "Test passed",
"TEST_FAILED": "Test failed",
"UPDATE_SUCCESS": "Updated successfully",
"UPDATE_SUCCESS": "Successfully updated",
"SCANNER_COLON": "Scanner:",
"NAME_COLON": "Name:",
"VENDOR_COLON": "Vendor:",
@ -1286,6 +1286,10 @@
"ADAPTER": "Adapter",
"VENDOR": "Vendor",
"VERSION": "Version",
"SELECT_SCANNER": "Select Scanner"
"SELECT_SCANNER": "Select Scanner",
"ENABLED": "Enabled",
"ENABLE": "Enable",
"DISABLE": "Disable",
"DELETE_SUCCESS": "Successfully deleted"
}
}

View File

@ -1283,6 +1283,10 @@
"ADAPTER": "适配器",
"VENDOR": "供应商",
"VERSION": "版本",
"SELECT_SCANNER": "选择扫描器"
"SELECT_SCANNER": "选择扫描器",
"ENABLED": "启用",
"ENABLE": "启用",
"DISABLE": "禁用",
"DELETE_SUCCESS": "删除成功"
}
}