Browse Source

UI: Refactor vc settings to repository settings. Add remove other entities confirm.

pull/6641/head
Igor Kulikov 4 years ago
parent
commit
09402f40ac
  1. 77
      application/src/main/java/org/thingsboard/server/controller/AdminController.java
  2. 8
      application/src/main/java/org/thingsboard/server/service/sync/vc/repository/DefaultTbRepositorySettingsService.java
  3. 2
      common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/RepositoryAuthMethod.java
  4. 6
      common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/RepositorySettings.java
  5. 14
      common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java
  6. 10
      ui-ngx/src/app/core/auth/auth.actions.ts
  7. 2
      ui-ngx/src/app/core/auth/auth.models.ts
  8. 4
      ui-ngx/src/app/core/auth/auth.reducer.ts
  9. 4
      ui-ngx/src/app/core/auth/auth.selectors.ts
  10. 10
      ui-ngx/src/app/core/auth/auth.service.ts
  11. 47
      ui-ngx/src/app/core/http/admin.service.ts
  12. 8
      ui-ngx/src/app/core/http/entities-version-control.service.ts
  13. 8
      ui-ngx/src/app/core/services/menu.service.ts
  14. 13
      ui-ngx/src/app/modules/home/components/home-components.module.ts
  15. 13
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.html
  16. 2
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts
  17. 28
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.html
  18. 42
      ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts
  19. 3
      ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.html
  20. 6
      ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.ts
  21. 3
      ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.html
  22. 6
      ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts
  23. 41
      ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.html
  24. 66
      ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.ts
  25. 26
      ui-ngx/src/app/modules/home/components/vc/repository-settings.component.html
  26. 2
      ui-ngx/src/app/modules/home/components/vc/repository-settings.component.scss
  27. 216
      ui-ngx/src/app/modules/home/components/vc/repository-settings.component.ts
  28. 218
      ui-ngx/src/app/modules/home/components/vc/version-control-settings.component.ts
  29. 6
      ui-ngx/src/app/modules/home/components/vc/version-control.component.html
  30. 10
      ui-ngx/src/app/modules/home/components/vc/version-control.component.ts
  31. 10
      ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts
  32. 4
      ui-ngx/src/app/modules/home/pages/admin/admin.module.ts
  33. 2
      ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.html
  34. 12
      ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.ts
  35. 2
      ui-ngx/src/app/shared/models/constants.ts
  36. 19
      ui-ngx/src/app/shared/models/settings.models.ts
  37. 23
      ui-ngx/src/app/shared/models/vc.models.ts
  38. 19
      ui-ngx/src/assets/locale/locale.constant-en_US.json

77
application/src/main/java/org/thingsboard/server/controller/AdminController.java

@ -191,12 +191,12 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Get version control settings (getVersionControlSettings)",
notes = "Get the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Get repository settings (getRepositorySettings)",
notes = "Get the repository settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/vcSettings")
@GetMapping("/repositorySettings")
@ResponseBody
public RepositorySettings getVersionControlSettings() throws ThingsboardException {
public RepositorySettings getRepositorySettings() throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
RepositorySettings versionControlSettings = checkNotNull(versionControlService.getVersionControlSettings(getTenantId()));
@ -209,12 +209,12 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Check version control settings exists (versionControlSettingsExists)",
notes = "Check whether the version control settings exists. " + TENANT_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Check repository settings exists (repositorySettingsExists)",
notes = "Check whether the repository settings exists. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/vcSettings/exists")
@GetMapping("/repositorySettings/exists")
@ResponseBody
public Boolean versionControlSettingsExists() throws ThingsboardException {
public Boolean repositorySettingsExists() throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
return versionControlService.getVersionControlSettings(getTenantId()) != null;
@ -223,11 +223,11 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Creates or Updates the version control settings (saveVersionControlSettings)",
notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Creates or Updates the repository settings (saveRepositorySettings)",
notes = "Creates or Updates the repository settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@PostMapping("/vcSettings")
public DeferredResult<RepositorySettings> saveVersionControlSettings(@RequestBody RepositorySettings settings) throws ThingsboardException {
@PostMapping("/repositorySettings")
public DeferredResult<RepositorySettings> saveRepositorySettings(@RequestBody RepositorySettings settings) throws ThingsboardException {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.WRITE);
ListenableFuture<RepositorySettings> future = versionControlService.saveVersionControlSettings(getTenantId(), settings);
return wrapFuture(Futures.transform(future, savedSettings -> {
@ -238,13 +238,13 @@ public class AdminController extends BaseController {
}, MoreExecutors.directExecutor()));
}
@ApiOperation(value = "Delete version control settings (deleteVersionControlSettings)",
notes = "Deletes the version control settings."
@ApiOperation(value = "Delete repository settings (deleteRepositorySettings)",
notes = "Deletes the repository settings."
+ TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/vcSettings", method = RequestMethod.DELETE)
@RequestMapping(value = "/repositorySettings", method = RequestMethod.DELETE)
@ResponseStatus(value = HttpStatus.OK)
public DeferredResult<Void> deleteVersionControlSettings() throws ThingsboardException {
public DeferredResult<Void> deleteRepositorySettings() throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.DELETE);
return wrapFuture(versionControlService.deleteVersionControlSettings(getTenantId()));
@ -253,6 +253,23 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Check repository access (checkRepositoryAccess)",
notes = "Attempts to check repository access. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/repositorySettings/checkAccess", method = RequestMethod.POST)
public DeferredResult<Void> checkRepositoryAccess(
@ApiParam(value = "A JSON value representing the Repository Settings.")
@RequestBody RepositorySettings settings) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
settings = checkNotNull(settings);
return wrapFuture(versionControlService.checkVersionControlAccess(getTenantId(), settings));
} catch (Exception e) {
throw handleException(e);
}
}
@ApiOperation(value = "Get auto commit settings (getAutoCommitSettings)",
notes = "Get the auto commit settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@ -267,8 +284,8 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Check version control settings exists (versionControlSettingsExists)",
notes = "Check whether the version control settings exists. " + TENANT_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Check auto commit settings exists (autoCommitSettingsExists)",
notes = "Check whether the auto commit settings exists. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@GetMapping("/vc/autoCommitSettings/exists")
@ResponseBody
@ -281,8 +298,8 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Creates or Updates the version control settings (saveVersionControlSettings)",
notes = "Creates or Updates the version control settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@ApiOperation(value = "Creates or Updates the auto commit settings (saveAutoCommitSettings)",
notes = "Creates or Updates the auto commit settings object. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@PostMapping("/vc/autoCommitSettings")
public AutoCommitSettings saveAutoCommitSettings(@RequestBody AutoCommitSettings settings) throws ThingsboardException {
@ -290,8 +307,8 @@ public class AdminController extends BaseController {
return autoCommitSettingsService.save(getTenantId(), settings);
}
@ApiOperation(value = "Delete version control settings (deleteVersionControlSettings)",
notes = "Deletes the version control settings."
@ApiOperation(value = "Delete auto commit settings (deleteAutoCommitSettings)",
notes = "Deletes the auto commit settings."
+ TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/vc/autoCommitSettings", method = RequestMethod.DELETE)
@ -305,22 +322,6 @@ public class AdminController extends BaseController {
}
}
@ApiOperation(value = "Check version control access (checkVersionControlAccess)",
notes = "Attempts to check version control access. " + TENANT_AUTHORITY_PARAGRAPH)
@PreAuthorize("hasAuthority('TENANT_ADMIN')")
@RequestMapping(value = "/vcSettings/checkAccess", method = RequestMethod.POST)
public DeferredResult<Void> checkVersionControlAccess(
@ApiParam(value = "A JSON value representing the Entities Version Control Settings.")
@RequestBody RepositorySettings settings) throws ThingsboardException {
try {
accessControlService.checkPermission(getCurrentUser(), Resource.ADMIN_SETTINGS, Operation.READ);
settings = checkNotNull(settings);
return wrapFuture(versionControlService.checkVersionControlAccess(getTenantId(), settings));
} catch (Exception e) {
throw handleException(e);
}
}
@ApiOperation(value = "Check for new Platform Releases (checkUpdates)",
notes = "Check notifications about new platform releases. "
+ SYSTEM_AUTHORITY_PARAGRAPH)

8
application/src/main/java/org/thingsboard/server/service/sync/vc/repository/DefaultTbRepositorySettingsService.java

@ -19,7 +19,7 @@ import org.springframework.stereotype.Service;
import org.thingsboard.server.cache.TbTransactionalCache;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.VersionControlAuthMethod;
import org.thingsboard.server.common.data.sync.vc.RepositoryAuthMethod;
import org.thingsboard.server.dao.settings.AdminSettingsService;
import org.thingsboard.server.queue.util.TbCoreComponent;
import org.thingsboard.server.service.sync.vc.TbAbstractVersionControlSettingsService;
@ -38,10 +38,10 @@ public class DefaultTbRepositorySettingsService extends TbAbstractVersionControl
public RepositorySettings restore(TenantId tenantId, RepositorySettings settings) {
RepositorySettings storedSettings = get(tenantId);
if (storedSettings != null) {
VersionControlAuthMethod authMethod = settings.getAuthMethod();
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(authMethod) && settings.getPassword() == null) {
RepositoryAuthMethod authMethod = settings.getAuthMethod();
if (RepositoryAuthMethod.USERNAME_PASSWORD.equals(authMethod) && settings.getPassword() == null) {
settings.setPassword(storedSettings.getPassword());
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(authMethod) && settings.getPrivateKey() == null) {
} else if (RepositoryAuthMethod.PRIVATE_KEY.equals(authMethod) && settings.getPrivateKey() == null) {
settings.setPrivateKey(storedSettings.getPrivateKey());
if (settings.getPrivateKeyPassword() == null) {
settings.setPrivateKeyPassword(storedSettings.getPrivateKeyPassword());

2
common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/VersionControlAuthMethod.java → common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/RepositoryAuthMethod.java

@ -15,7 +15,7 @@
*/
package org.thingsboard.server.common.data.sync.vc;
public enum VersionControlAuthMethod {
public enum RepositoryAuthMethod {
USERNAME_PASSWORD,
PRIVATE_KEY
}

6
common/data/src/main/java/org/thingsboard/server/common/data/sync/vc/RepositorySettings.java

@ -17,12 +17,8 @@ package org.thingsboard.server.common.data.sync.vc;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.sync.vc.request.create.AutoVersionCreateConfig;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
@Data
@JsonIgnoreProperties(ignoreUnknown = true) // temporary to make sure no need to wipe db during development.
@ -30,7 +26,7 @@ public class RepositorySettings implements Serializable {
private static final long serialVersionUID = -3211552851889198721L;
private String repositoryUri;
private VersionControlAuthMethod authMethod;
private RepositoryAuthMethod authMethod;
private String username;
private String password;
private String privateKeyFileName;

14
common/version-control/src/main/java/org/thingsboard/server/service/sync/vc/GitRepository.java

@ -59,7 +59,7 @@ import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.page.SortOrder;
import org.thingsboard.server.common.data.sync.vc.RepositorySettings;
import org.thingsboard.server.common.data.sync.vc.VersionControlAuthMethod;
import org.thingsboard.server.common.data.sync.vc.RepositoryAuthMethod;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -95,9 +95,9 @@ public class GitRepository {
public static GitRepository clone(RepositorySettings settings, File directory) throws GitAPIException {
CredentialsProvider credentialsProvider = null;
SshdSessionFactory sshSessionFactory = null;
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
if (RepositoryAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
credentialsProvider = newCredentialsProvider(settings.getUsername(), settings.getPassword());
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
} else if (RepositoryAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
sshSessionFactory = newSshdSessionFactory(settings.getPrivateKey(), settings.getPrivateKeyPassword(), directory);
}
CloneCommand cloneCommand = Git.cloneRepository()
@ -113,9 +113,9 @@ public class GitRepository {
Git git = Git.open(directory);
CredentialsProvider credentialsProvider = null;
SshdSessionFactory sshSessionFactory = null;
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
if (RepositoryAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
credentialsProvider = newCredentialsProvider(settings.getUsername(), settings.getPassword());
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
} else if (RepositoryAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
sshSessionFactory = newSshdSessionFactory(settings.getPrivateKey(), settings.getPrivateKeyPassword(), directory);
}
return new GitRepository(git, settings, credentialsProvider, sshSessionFactory, directory.getAbsolutePath());
@ -124,9 +124,9 @@ public class GitRepository {
public static void test(RepositorySettings settings, File directory) throws GitAPIException {
CredentialsProvider credentialsProvider = null;
SshdSessionFactory sshSessionFactory = null;
if (VersionControlAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
if (RepositoryAuthMethod.USERNAME_PASSWORD.equals(settings.getAuthMethod())) {
credentialsProvider = newCredentialsProvider(settings.getUsername(), settings.getPassword());
} else if (VersionControlAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
} else if (RepositoryAuthMethod.PRIVATE_KEY.equals(settings.getAuthMethod())) {
sshSessionFactory = newSshdSessionFactory(settings.getPrivateKey(), settings.getPrivateKeyPassword(), directory);
}
LsRemoteCommand lsRemoteCommand = Git.lsRemoteRepository().setRemote(settings.getRepositoryUri());

10
ui-ngx/src/app/core/auth/auth.actions.ts

@ -24,7 +24,7 @@ export enum AuthActionTypes {
LOAD_USER = '[Auth] Load User',
UPDATE_USER_DETAILS = '[Auth] Update User Details',
UPDATE_LAST_PUBLIC_DASHBOARD_ID = '[Auth] Update Last Public Dashboard Id',
UPDATE_HAS_VERSION_CONTROL = '[Auth] Change Has Version Control'
UPDATE_HAS_REPOSITORY = '[Auth] Change Has Repository'
}
export class ActionAuthAuthenticated implements Action {
@ -55,11 +55,11 @@ export class ActionAuthUpdateLastPublicDashboardId implements Action {
constructor(readonly payload: { lastPublicDashboardId: string }) {}
}
export class ActionAuthUpdateHasVersionControl implements Action {
readonly type = AuthActionTypes.UPDATE_HAS_VERSION_CONTROL;
export class ActionAuthUpdateHasRepository implements Action {
readonly type = AuthActionTypes.UPDATE_HAS_REPOSITORY;
constructor(readonly payload: { hasVersionControl: boolean }) {}
constructor(readonly payload: { hasRepository: boolean }) {}
}
export type AuthActions = ActionAuthAuthenticated | ActionAuthUnauthenticated |
ActionAuthLoadUser | ActionAuthUpdateUserDetails | ActionAuthUpdateLastPublicDashboardId | ActionAuthUpdateHasVersionControl;
ActionAuthLoadUser | ActionAuthUpdateUserDetails | ActionAuthUpdateLastPublicDashboardId | ActionAuthUpdateHasRepository;

2
ui-ngx/src/app/core/auth/auth.models.ts

@ -20,7 +20,7 @@ export interface SysParamsState {
userTokenAccessEnabled: boolean;
allowedDashboardIds: string[];
edgesSupportEnabled: boolean;
hasVersionControl: boolean;
hasRepository: boolean;
}
export interface AuthPayload extends SysParamsState {

4
ui-ngx/src/app/core/auth/auth.reducer.ts

@ -24,7 +24,7 @@ const emptyUserAuthState: AuthPayload = {
forceFullscreen: false,
allowedDashboardIds: [],
edgesSupportEnabled: false,
hasVersionControl: false
hasRepository: false
};
export const initialState: AuthState = {
@ -55,7 +55,7 @@ export function authReducer(
case AuthActionTypes.UPDATE_LAST_PUBLIC_DASHBOARD_ID:
return { ...state, ...action.payload};
case AuthActionTypes.UPDATE_HAS_VERSION_CONTROL:
case AuthActionTypes.UPDATE_HAS_REPOSITORY:
return { ...state, ...action.payload};
default:

4
ui-ngx/src/app/core/auth/auth.selectors.ts

@ -55,9 +55,9 @@ export const selectUserTokenAccessEnabled = createSelector(
(state: AuthState) => state.userTokenAccessEnabled
);
export const selectHasVersionControl = createSelector(
export const selectHasRepository = createSelector(
selectAuthState,
(state: AuthState) => state.hasVersionControl
(state: AuthState) => state.hasRepository
);
export function getCurrentAuthState(store: Store<AppState>): AuthState {

10
ui-ngx/src/app/core/auth/auth.service.ts

@ -437,9 +437,9 @@ export class AuthService {
return this.http.get<boolean>('/api/edges/enabled', defaultHttpOptions());
}
private loadHasVersionControl(authUser: AuthUser): Observable<boolean> {
private loadHasRepository(authUser: AuthUser): Observable<boolean> {
if (authUser.authority === Authority.TENANT_ADMIN) {
return this.http.get<boolean>('/api/admin/vcSettings/exists', defaultHttpOptions());
return this.http.get<boolean>('/api/admin/repositorySettings/exists', defaultHttpOptions());
} else {
return of(false);
}
@ -449,15 +449,15 @@ export class AuthService {
const sources = [this.loadIsUserTokenAccessEnabled(authPayload.authUser),
this.fetchAllowedDashboardIds(authPayload),
this.loadIsEdgesSupportEnabled(),
this.loadHasVersionControl(authPayload.authUser),
this.loadHasRepository(authPayload.authUser),
this.timeService.loadMaxDatapointsLimit()];
return forkJoin(sources)
.pipe(map((data) => {
const userTokenAccessEnabled: boolean = data[0] as boolean;
const allowedDashboardIds: string[] = data[1] as string[];
const edgesSupportEnabled: boolean = data[2] as boolean;
const hasVersionControl: boolean = data[3] as boolean;
return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasVersionControl};
const hasRepository: boolean = data[3] as boolean;
return {userTokenAccessEnabled, allowedDashboardIds, edgesSupportEnabled, hasRepository};
}, catchError((err) => {
return of({});
})));

47
ui-ngx/src/app/core/http/admin.service.ts

@ -15,19 +15,21 @@
///
import { Injectable } from '@angular/core';
import { defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
import { Observable } from 'rxjs';
import { defaultHttpOptions, defaultHttpOptionsFromConfig, RequestConfig } from './http-utils';
import { Observable, of } from 'rxjs';
import { HttpClient } from '@angular/common/http';
import {
AdminSettings,
EntitiesVersionControlSettings,
RepositorySettings,
MailServerSettings,
SecuritySettings,
TestSmsRequest,
UpdateMessage
UpdateMessage, AutoCommitSettings
} from '@shared/models/settings.models';
import { EntitiesVersionControlService } from '@core/http/entities-version-control.service';
import { tap } from 'rxjs/operators';
import { AuthUser } from '@shared/models/user.model';
import { Authority } from '@shared/models/authority.enum';
@Injectable({
providedIn: 'root'
@ -68,13 +70,13 @@ export class AdminService {
defaultHttpOptionsFromConfig(config));
}
public getEntitiesVersionControlSettings(config?: RequestConfig): Observable<EntitiesVersionControlSettings> {
return this.http.get<EntitiesVersionControlSettings>(`/api/admin/vcSettings`, defaultHttpOptionsFromConfig(config));
public getRepositorySettings(config?: RequestConfig): Observable<RepositorySettings> {
return this.http.get<RepositorySettings>(`/api/admin/repositorySettings`, defaultHttpOptionsFromConfig(config));
}
public saveEntitiesVersionControlSettings(versionControlSettings: EntitiesVersionControlSettings,
config?: RequestConfig): Observable<EntitiesVersionControlSettings> {
return this.http.post<EntitiesVersionControlSettings>('/api/admin/vcSettings', versionControlSettings,
public saveRepositorySettings(repositorySettings: RepositorySettings,
config?: RequestConfig): Observable<RepositorySettings> {
return this.http.post<RepositorySettings>('/api/admin/repositorySettings', repositorySettings,
defaultHttpOptionsFromConfig(config)).pipe(
tap(() => {
this.entitiesVersionControlService.clearBranchList();
@ -82,17 +84,34 @@ export class AdminService {
);
}
public deleteEntitiesVersionControlSettings(config?: RequestConfig) {
return this.http.delete('/api/admin/vcSettings', defaultHttpOptionsFromConfig(config)).pipe(
public deleteRepositorySettings(config?: RequestConfig) {
return this.http.delete('/api/admin/repositorySettings', defaultHttpOptionsFromConfig(config)).pipe(
tap(() => {
this.entitiesVersionControlService.clearBranchList();
})
);
}
public checkVersionControlAccess(versionControlSettings: EntitiesVersionControlSettings,
config?: RequestConfig): Observable<void> {
return this.http.post<void>('/api/admin/vcSettings/checkAccess', versionControlSettings, defaultHttpOptionsFromConfig(config));
public checkRepositoryAccess(repositorySettings: RepositorySettings,
config?: RequestConfig): Observable<void> {
return this.http.post<void>('/api/admin/repositorySettings/checkAccess', repositorySettings, defaultHttpOptionsFromConfig(config));
}
public getAutoCommitSettings(config?: RequestConfig): Observable<AutoCommitSettings> {
return this.http.get<AutoCommitSettings>(`/api/admin/autoCommitSettings`, defaultHttpOptionsFromConfig(config));
}
private autoCommitSettingsExists(config?: RequestConfig): Observable<boolean> {
return this.http.get<boolean>('/api/admin/autoCommitSettings/exists', defaultHttpOptionsFromConfig(config));
}
public saveAutoCommitSettings(autoCommitSettings: AutoCommitSettings,
config?: RequestConfig): Observable<AutoCommitSettings> {
return this.http.post<AutoCommitSettings>('/api/admin/autoCommitSettings', autoCommitSettings, defaultHttpOptionsFromConfig(config));
}
public deleteAutoCommitSettings(config?: RequestConfig) {
return this.http.delete('/api/admin/autoCommitSettings', defaultHttpOptionsFromConfig(config));
}
public checkUpdates(config?: RequestConfig): Observable<UpdateMessage> {

8
ui-ngx/src/app/core/http/entities-version-control.service.ts

@ -17,7 +17,7 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { defaultHttpOptionsFromConfig, RequestConfig } from '@core/http/http-utils';
import { combineLatest, Observable, of } from 'rxjs';
import { Observable, of } from 'rxjs';
import {
BranchInfo, EntityDataDiff,
EntityVersion,
@ -29,10 +29,10 @@ import { PageLink } from '@shared/models/page/page-link';
import { PageData } from '@shared/models/page/page-data';
import { EntityId } from '@shared/models/id/entity-id';
import { EntityType } from '@shared/models/entity-type.models';
import { createSelector, select, Store } from '@ngrx/store';
import { select, Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { selectHasVersionControl, selectIsAuthenticated, selectIsUserLoaded } from '@core/auth/auth.selectors';
import { catchError, combineAll, tap } from 'rxjs/operators';
import { selectIsUserLoaded } from '@core/auth/auth.selectors';
import { catchError, tap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'

8
ui-ngx/src/app/core/services/menu.service.ts

@ -388,9 +388,9 @@ export class MenuService {
},
{
id: guid(),
name: 'admin.git-settings',
name: 'admin.repository-settings',
type: 'link',
path: '/settings/vc',
path: '/settings/repository',
icon: 'manage_history'
}
]
@ -538,9 +538,9 @@ export class MenuService {
path: '/settings/resources-library'
},
{
name: 'admin.git-settings',
name: 'admin.repository-settings',
icon: 'manage_history',
path: '/settings/vc',
path: '/settings/repository',
}
]
}

13
ui-ngx/src/app/modules/home/components/home-components.module.ts

@ -153,7 +153,7 @@ import { TenantProfileQueuesComponent } from '@home/components/profile/queue/ten
import { QueueFormComponent } from '@home/components/queue/queue-form.component';
import { WidgetSettingsModule } from '@home/components/widget/lib/settings/widget-settings.module';
import { WidgetSettingsComponent } from '@home/components/widget/widget-settings.component';
import { VersionControlSettingsComponent } from '@home/components/vc/version-control-settings.component';
import { RepositorySettingsComponent } from '@home/components/vc/repository-settings.component';
import { VersionControlComponent } from '@home/components/vc/version-control.component';
import { EntityVersionsTableComponent } from '@home/components/vc/entity-versions-table.component';
import { EntityVersionCreateComponent } from '@home/components/vc/entity-version-create.component';
@ -163,6 +163,7 @@ import { ComplexVersionCreateComponent } from '@home/components/vc/complex-versi
import { EntityTypesVersionCreateComponent } from '@home/components/vc/entity-types-version-create.component';
import { EntityTypesVersionLoadComponent } from '@home/components/vc/entity-types-version-load.component';
import { ComplexVersionLoadComponent } from '@home/components/vc/complex-version-load.component';
import { RemoveOtherEntitiesConfirmComponent } from '@home/components/vc/remove-other-entities-confirm.component';
@NgModule({
declarations:
@ -287,7 +288,7 @@ import { ComplexVersionLoadComponent } from '@home/components/vc/complex-version
DisplayWidgetTypesPanelComponent,
TenantProfileQueuesComponent,
QueueFormComponent,
VersionControlSettingsComponent,
RepositorySettingsComponent,
VersionControlComponent,
EntityVersionsTableComponent,
EntityVersionCreateComponent,
@ -296,7 +297,8 @@ import { ComplexVersionLoadComponent } from '@home/components/vc/complex-version
ComplexVersionCreateComponent,
EntityTypesVersionCreateComponent,
EntityTypesVersionLoadComponent,
ComplexVersionLoadComponent
ComplexVersionLoadComponent,
RemoveOtherEntitiesConfirmComponent
],
imports: [
CommonModule,
@ -415,7 +417,7 @@ import { ComplexVersionLoadComponent } from '@home/components/vc/complex-version
DisplayWidgetTypesPanelComponent,
TenantProfileQueuesComponent,
QueueFormComponent,
VersionControlSettingsComponent,
RepositorySettingsComponent,
VersionControlComponent,
EntityVersionsTableComponent,
EntityVersionCreateComponent,
@ -424,7 +426,8 @@ import { ComplexVersionLoadComponent } from '@home/components/vc/complex-version
ComplexVersionCreateComponent,
EntityTypesVersionCreateComponent,
EntityTypesVersionLoadComponent,
ComplexVersionLoadComponent
ComplexVersionLoadComponent,
RemoveOtherEntitiesConfirmComponent
],
providers: [
WidgetComponentService,

13
ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.html

@ -53,7 +53,7 @@
[allowedEntityTypes]="allowedEntityTypes(entityTypeFormGroup)">
</tb-entity-type-select>
<div fxFlex fxLayout="row" fxLayoutGap="16px" fxLayoutAlign="start center" formGroupName="config">
<mat-form-field class="mat-block">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>version-control.sync-strategy</mat-label>
<mat-select formControlName="syncStrategy">
<mat-option [value]="'default'">
@ -64,9 +64,14 @@
</mat-option>
</mat-select>
</mat-form-field>
<mat-checkbox formControlName="saveRelations">
{{ 'version-control.export-entity-relations' | translate }}
</mat-checkbox>
<div fxFlex fxLayout="column" fxLayoutGap="8px">
<mat-checkbox formControlName="saveRelations">
{{ 'version-control.export-entity-relations' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="saveAttributes">
{{ 'version-control.export-entity-attributes' | translate }}
</mat-checkbox>
</div>
</div>
</div>
<div fxLayout="row" fxLayoutGap="16px" fxLayoutAlign="start center"

2
ui-ngx/src/app/modules/home/components/vc/entity-types-version-create.component.ts

@ -135,6 +135,7 @@ export class EntityTypesVersionCreateComponent extends PageComponent implements
config: this.fb.group({
syncStrategy: [config.syncStrategy === null ? 'default' : config.syncStrategy, []],
saveRelations: [config.saveRelations, []],
saveAttributes: [config.saveAttributes, []],
allEntities: [config.allEntities, []],
entityIds: [config.entityIds, [Validators.required]]
})
@ -183,6 +184,7 @@ export class EntityTypesVersionCreateComponent extends PageComponent implements
const config: EntityTypeVersionCreateConfig = {
syncStrategy: null,
saveRelations: false,
saveAttributes: false,
allEntities: true,
entityIds: []
};

28
ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.html

@ -44,7 +44,7 @@
<ng-template matExpansionPanelContent>
<div class="entity-type-config-content" fxLayout="column" fxLayoutGap="0.5em">
<mat-divider></mat-divider>
<div fxLayout="row" fxLayoutGap="16px">
<div fxLayout="row" fxLayoutGap="32px">
<tb-entity-type-select
showLabel
formControlName="entityType"
@ -52,13 +52,25 @@
[filterAllowedEntityTypes]="false"
[allowedEntityTypes]="allowedEntityTypes(entityTypeFormGroup)">
</tb-entity-type-select>
<div fxFlex fxLayout="row" fxLayoutGap="16px" fxLayoutAlign="start center" formGroupName="config">
<mat-checkbox formControlName="removeOtherEntities">
{{ 'version-control.remove-other-entities' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="loadRelations">
{{ 'version-control.load-entities-relations' | translate }}
</mat-checkbox>
<div fxFlex fxLayout="row" fxLayoutAlign="start center" fxLayoutGap="16px" formGroupName="config">
<div fxFlex fxLayout="column" fxLayoutGap="8px">
<mat-checkbox #removeOtherEntitiesCheckbox
formControlName="removeOtherEntities"
(click)="onRemoveOtherEntities(removeOtherEntitiesCheckbox, entityTypeFormGroup, $event)">
{{ 'version-control.remove-other-entities' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="findExistingEntityByName">
{{ 'version-control.find-existing-entity-by-name' | translate }}
</mat-checkbox>
</div>
<div fxFlex fxLayout="column" fxLayoutGap="8px">
<mat-checkbox formControlName="loadRelations">
{{ 'version-control.load-entities-relations' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="loadAttributes">
{{ 'version-control.load-entities-attributes' | translate }}
</mat-checkbox>
</div>
</div>
</div>
</div>

42
ui-ngx/src/app/modules/home/components/vc/entity-types-version-load.component.ts

@ -14,7 +14,7 @@
/// limitations under the License.
///
import { Component, forwardRef, Input, OnInit } from '@angular/core';
import { Component, forwardRef, Input, OnInit, Renderer2, ViewContainerRef } from '@angular/core';
import {
AbstractControl,
ControlValueAccessor,
@ -28,11 +28,15 @@ import {
Validators
} from '@angular/forms';
import { PageComponent } from '@shared/components/page.component';
import { EntityTypeVersionLoadConfig, exportableEntityTypes } from '@shared/models/vc.models';
import { EntityTypeVersionLoadConfig, exportableEntityTypes, VersionCreationResult } from '@shared/models/vc.models';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { EntityType, entityTypeTranslations } from '@shared/models/entity-type.models';
import { MatCheckbox } from '@angular/material/checkbox/checkbox';
import { TbPopoverService } from '@shared/components/popover.service';
import { EntityVersionCreateComponent } from '@home/components/vc/entity-version-create.component';
import { RemoveOtherEntitiesConfirmComponent } from '@home/components/vc/remove-other-entities-confirm.component';
@Component({
selector: 'tb-entity-types-version-load',
@ -64,6 +68,9 @@ export class EntityTypesVersionLoadComponent extends PageComponent implements On
constructor(protected store: Store<AppState>,
private translate: TranslateService,
private popoverService: TbPopoverService,
private renderer: Renderer2,
private viewContainerRef: ViewContainerRef,
private fb: FormBuilder) {
super(store);
}
@ -124,7 +131,9 @@ export class EntityTypesVersionLoadComponent extends PageComponent implements On
entityType: [entityType, [Validators.required]],
config: this.fb.group({
loadRelations: [config.loadRelations, []],
removeOtherEntities: [config.removeOtherEntities, []]
loadAttributes: [config.loadAttributes, []],
removeOtherEntities: [config.removeOtherEntities, []],
findExistingEntityByName: [config.findExistingEntityByName, []]
})
}
);
@ -156,7 +165,9 @@ export class EntityTypesVersionLoadComponent extends PageComponent implements On
const entityTypesArray = this.entityTypesVersionLoadFormGroup.get('entityTypes') as FormArray;
const config: EntityTypeVersionLoadConfig = {
loadRelations: false,
removeOtherEntities: false
loadAttributes: false,
removeOtherEntities: false,
findExistingEntityByName: false
};
const allowed = this.allowedEntityTypes();
let entityType: EntityType = null;
@ -194,6 +205,29 @@ export class EntityTypesVersionLoadComponent extends PageComponent implements On
return res;
}
onRemoveOtherEntities(removeOtherEntitiesCheckbox: MatCheckbox, entityTypeControl: AbstractControl, $event: Event) {
const removeOtherEntities: boolean = entityTypeControl.get('config.removeOtherEntities').value;
if (!removeOtherEntities) {
$event.preventDefault();
$event.stopPropagation();
const trigger = $('.mat-checkbox-frame', removeOtherEntitiesCheckbox._elementRef.nativeElement)[0];
if (this.popoverService.hasPopover(trigger)) {
this.popoverService.hidePopover(trigger);
} else {
const removeOtherEntitiesConfirmPopover = this.popoverService.displayPopover(trigger, this.renderer,
this.viewContainerRef, RemoveOtherEntitiesConfirmComponent, 'bottom', true, null,
{
onClose: (result: boolean | null) => {
removeOtherEntitiesConfirmPopover.hide();
if (result) {
entityTypeControl.get('config').get('removeOtherEntities').patchValue(true, {emitEvent: true});
}
}
}, {}, {}, {}, false);
}
}
}
private updateModel() {
const value: [{entityType: string, config: EntityTypeVersionLoadConfig}] =
this.entityTypesVersionLoadFormGroup.get('entityTypes').value || [];

3
ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.html

@ -41,6 +41,9 @@
<mat-checkbox formControlName="saveRelations" style="margin-bottom: 16px;">
{{ 'version-control.export-entity-relations' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="saveAttributes" style="margin-bottom: 16px;">
{{ 'version-control.export-entity-attributes' | translate }}
</mat-checkbox>
</div>
</fieldset>
</form>

6
ui-ngx/src/app/modules/home/components/vc/entity-version-create.component.ts

@ -62,7 +62,8 @@ export class EntityVersionCreateComponent extends PageComponent implements OnIni
this.createVersionFormGroup = this.fb.group({
branch: [this.branch, [Validators.required]],
versionName: [null, [Validators.required]],
saveRelations: [false, []]
saveRelations: [false, []],
saveAttributes: [false, []]
});
}
@ -78,7 +79,8 @@ export class EntityVersionCreateComponent extends PageComponent implements OnIni
branch: this.createVersionFormGroup.get('branch').value,
versionName: this.createVersionFormGroup.get('versionName').value,
config: {
saveRelations: this.createVersionFormGroup.get('saveRelations').value
saveRelations: this.createVersionFormGroup.get('saveRelations').value,
saveAttributes: this.createVersionFormGroup.get('saveAttributes').value,
},
type: VersionCreateRequestType.SINGLE_ENTITY
};

3
ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.html

@ -29,6 +29,9 @@
<mat-checkbox formControlName="loadRelations" style="margin-bottom: 16px;">
{{ 'version-control.load-entity-relations' | translate }}
</mat-checkbox>
<mat-checkbox formControlName="loadAttributes" style="margin-bottom: 16px;">
{{ 'version-control.load-entity-attributes' | translate }}
</mat-checkbox>
</div>
</fieldset>
</form>

6
ui-ngx/src/app/modules/home/components/vc/entity-version-restore.component.ts

@ -57,7 +57,8 @@ export class EntityVersionRestoreComponent extends PageComponent implements OnIn
ngOnInit(): void {
this.restoreFormGroup = this.fb.group({
loadRelations: [false, []]
loadRelations: [false, []],
loadAttributes: [false, []]
});
}
@ -73,7 +74,8 @@ export class EntityVersionRestoreComponent extends PageComponent implements OnIn
versionId: this.versionId,
externalEntityId: this.externalEntityId,
config: {
loadRelations: this.restoreFormGroup.get('loadRelations').value
loadRelations: this.restoreFormGroup.get('loadRelations').value,
loadAttributes: this.restoreFormGroup.get('loadAttributes').value
},
type: VersionLoadRequestType.SINGLE_ENTITY
};

41
ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.html

@ -0,0 +1,41 @@
<!--
Copyright © 2016-2022 The Thingsboard Authors
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.
-->
<section style="min-width: 300px;">
<form [formGroup]="confirmFormGroup" style="padding-top: 16px;">
<fieldset [disabled]="(isLoading$ | async)">
<div style="user-select: none;" [innerHTML]="removeOtherEntitiesConfirmText"></div>
<mat-form-field class="mat-block">
<input matInput formControlName="verification"/>
</mat-form-field>
</fieldset>
</form>
<div fxLayoutAlign="end center" fxLayoutGap="8px">
<button mat-button color="primary"
type="button"
[disabled]="(isLoading$ | async)"
(click)="cancel()" cdkFocusInitial>
{{ 'action.cancel' | translate }}
</button>
<button mat-raised-button color="primary"
type="button"
(click)="confirm()"
[disabled]="(isLoading$ | async) || confirmFormGroup.invalid || confirmFormGroup.get('verification').value !== removeOtherEntitiesVerificationText">
{{ 'action.confirm' | translate }}
</button>
</div>
</section>

66
ui-ngx/src/app/modules/home/components/vc/remove-other-entities-confirm.component.ts

@ -0,0 +1,66 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// 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, Input, OnInit } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { TranslateService } from '@ngx-translate/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
@Component({
selector: 'tb-remove-other-entities-confirm',
templateUrl: './remove-other-entities-confirm.component.html',
styleUrls: []
})
export class RemoveOtherEntitiesConfirmComponent extends PageComponent implements OnInit {
@Input()
onClose: (result: boolean | null) => void;
confirmFormGroup: FormGroup;
removeOtherEntitiesConfirmText: SafeHtml;
removeOtherEntitiesVerificationText = 'remove other entities';
constructor(protected store: Store<AppState>,
private translate: TranslateService,
private sanitizer: DomSanitizer,
private fb: FormBuilder) {
super(store);
this.removeOtherEntitiesConfirmText = this.sanitizer.bypassSecurityTrustHtml(this.translate.instant('version-control.remove-other-entities-confirm-text'));
}
ngOnInit(): void {
this.confirmFormGroup = this.fb.group({
verification: [null, []]
});
}
cancel(): void {
if (this.onClose) {
this.onClose(null);
}
}
confirm(): void {
if (this.onClose) {
this.onClose(true);
}
}
}

26
ui-ngx/src/app/modules/home/components/vc/version-control-settings.component.html → ui-ngx/src/app/modules/home/components/vc/repository-settings.component.html

@ -16,24 +16,24 @@
-->
<div>
<mat-card class="vc-settings" [ngClass]="{'settings-card': !detailsMode}">
<mat-card class="repository-settings" [ngClass]="{'settings-card': !detailsMode}">
<mat-card-title>
<div fxLayout="row">
<span class="mat-headline" translate>admin.git-repository-settings</span>
<span class="mat-headline" translate>admin.repository-settings</span>
<span fxFlex></span>
<div tb-help="versionControlSettings"></div>
<div tb-help="repositorySettings"></div>
</div>
</mat-card-title>
<mat-progress-bar color="warn" mode="indeterminate" *ngIf="isLoading$ | async">
</mat-progress-bar>
<div style="height: 4px;" *ngIf="!(isLoading$ | async)"></div>
<mat-card-content style="padding-top: 16px;">
<form [formGroup]="versionControlSettingsForm" #formDirective="ngForm" (ngSubmit)="save()">
<form [formGroup]="repositorySettingsForm" #formDirective="ngForm" (ngSubmit)="save()">
<fieldset [disabled]="isLoading$ | async">
<mat-form-field class="mat-block">
<mat-label translate>admin.repository-url</mat-label>
<input matInput required formControlName="repositoryUri">
<mat-error translate *ngIf="versionControlSettingsForm.get('repositoryUri').hasError('required')">
<mat-error translate *ngIf="repositorySettingsForm.get('repositoryUri').hasError('required')">
admin.repository-url-required
</mat-error>
</mat-form-field>
@ -46,12 +46,12 @@
<mat-form-field fxFlex class="mat-block">
<mat-label translate>admin.auth-method</mat-label>
<mat-select required formControlName="authMethod">
<mat-option *ngFor="let method of versionControlAuthMethods" [value]="method">
{{versionControlAuthMethodTranslations.get(method) | translate}}
<mat-option *ngFor="let method of repositoryAuthMethods" [value]="method">
{{repositoryAuthMethodTranslations.get(method) | translate}}
</mat-option>
</mat-select>
</mat-form-field>
<section [fxShow]="versionControlSettingsForm.get('authMethod').value === versionControlAuthMethod.USERNAME_PASSWORD" fxLayout="column">
<section [fxShow]="repositorySettingsForm.get('authMethod').value === repositoryAuthMethod.USERNAME_PASSWORD" fxLayout="column">
<mat-form-field fxFlex class="mat-block">
<mat-label translate>common.username</mat-label>
<input matInput formControlName="username" placeholder="{{ 'common.enter-username' | translate }}"
@ -68,14 +68,14 @@
<tb-toggle-password matSuffix></tb-toggle-password>
</mat-form-field>
</section>
<section [fxShow]="versionControlSettingsForm.get('authMethod').value === versionControlAuthMethod.PRIVATE_KEY" fxLayout="column">
<section [fxShow]="repositorySettingsForm.get('authMethod').value === repositoryAuthMethod.PRIVATE_KEY" fxLayout="column">
<tb-file-input style="margin-bottom: 16px;"
[existingFileName]="versionControlSettingsForm.get('privateKeyFileName').value"
[existingFileName]="repositorySettingsForm.get('privateKeyFileName').value"
required
formControlName="privateKey"
dropLabel="{{ 'admin.drop-private-key-file-or' | translate }}"
[label]="'admin.private-key' | translate"
(fileNameChanged)="versionControlSettingsForm.get('privateKeyFileName').patchValue($event)">
(fileNameChanged)="repositorySettingsForm.get('privateKeyFileName').patchValue($event)">
</tb-file-input>
<mat-checkbox *ngIf="showChangePrivateKeyPassword" (change)="changePrivateKeyPasswordChanged()"
[(ngModel)]="changePrivateKeyPassword" [ngModelOptions]="{ standalone: true }" style="padding-bottom: 16px;">
@ -96,10 +96,10 @@
</button>
<span fxFlex></span>
<button mat-raised-button type="button"
[disabled]="(isLoading$ | async) || versionControlSettingsForm.invalid" (click)="checkAccess()">
[disabled]="(isLoading$ | async) || repositorySettingsForm.invalid" (click)="checkAccess()">
{{'admin.check-access' | translate}}
</button>
<button mat-raised-button color="primary" [disabled]="(isLoading$ | async) || versionControlSettingsForm.invalid || !versionControlSettingsForm.dirty"
<button mat-raised-button color="primary" [disabled]="(isLoading$ | async) || repositorySettingsForm.invalid || !repositorySettingsForm.dirty"
type="submit">{{'action.save' | translate}}
</button>
</div>

2
ui-ngx/src/app/modules/home/components/vc/version-control-settings.component.scss → ui-ngx/src/app/modules/home/components/vc/repository-settings.component.scss

@ -14,7 +14,7 @@
* limitations under the License.
*/
:host {
mat-card.vc-settings {
mat-card.repository-settings {
margin: 8px;
}
.fields-group {

216
ui-ngx/src/app/modules/home/components/vc/repository-settings.component.ts

@ -0,0 +1,216 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// 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, Input, OnInit } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { FormBuilder, FormGroup, FormGroupDirective, Validators } from '@angular/forms';
import { select, Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { AdminService } from '@core/http/admin.service';
import {
RepositorySettings,
RepositoryAuthMethod,
repositoryAuthMethodTranslationMap
} from '@shared/models/settings.models';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { TranslateService } from '@ngx-translate/core';
import { isNotEmptyStr } from '@core/utils';
import { DialogService } from '@core/services/dialog.service';
import { ActionAuthUpdateHasRepository } from '@core/auth/auth.actions';
import { selectHasRepository } from '@core/auth/auth.selectors';
import { catchError, mergeMap, take } from 'rxjs/operators';
import { of } from 'rxjs';
@Component({
selector: 'tb-repository-settings',
templateUrl: './repository-settings.component.html',
styleUrls: ['./repository-settings.component.scss', './../../pages/admin/settings-card.scss']
})
export class RepositorySettingsComponent extends PageComponent implements OnInit {
@Input()
detailsMode = false;
repositorySettingsForm: FormGroup;
settings: RepositorySettings = null;
repositoryAuthMethod = RepositoryAuthMethod;
repositoryAuthMethods = Object.values(RepositoryAuthMethod);
repositoryAuthMethodTranslations = repositoryAuthMethodTranslationMap;
showChangePassword = false;
changePassword = false;
showChangePrivateKeyPassword = false;
changePrivateKeyPassword = false;
constructor(protected store: Store<AppState>,
private adminService: AdminService,
private dialogService: DialogService,
private translate: TranslateService,
public fb: FormBuilder) {
super(store);
}
ngOnInit() {
this.repositorySettingsForm = this.fb.group({
repositoryUri: [null, [Validators.required]],
defaultBranch: ['main', []],
authMethod: [RepositoryAuthMethod.USERNAME_PASSWORD, [Validators.required]],
username: [null, []],
password: [null, []],
privateKeyFileName: [null, [Validators.required]],
privateKey: [null, []],
privateKeyPassword: [null, []]
});
this.updateValidators(false);
this.repositorySettingsForm.get('authMethod').valueChanges.subscribe(() => {
this.updateValidators(true);
});
this.repositorySettingsForm.get('privateKeyFileName').valueChanges.subscribe(() => {
this.updateValidators(false);
});
this.store.pipe(
select(selectHasRepository),
take(1),
mergeMap((hasRepository) => {
if (hasRepository) {
return this.adminService.getRepositorySettings({ignoreErrors: true}).pipe(
catchError(() => of(null))
);
} else {
return of(null);
}
})
).subscribe(
(settings) => {
this.settings = settings;
if (this.settings != null) {
if (this.settings.authMethod === RepositoryAuthMethod.USERNAME_PASSWORD) {
this.showChangePassword = true;
} else {
this.showChangePrivateKeyPassword = true;
}
this.repositorySettingsForm.reset(this.settings);
this.updateValidators(false);
}
});
}
checkAccess(): void {
const settings: RepositorySettings = this.repositorySettingsForm.value;
this.adminService.checkRepositoryAccess(settings).subscribe(() => {
this.store.dispatch(new ActionNotificationShow({ message: this.translate.instant('admin.check-repository-access-success'),
type: 'success' }));
});
}
save(): void {
const settings: RepositorySettings = this.repositorySettingsForm.value;
this.adminService.saveRepositorySettings(settings).subscribe(
(savedSettings) => {
this.settings = savedSettings;
if (this.settings.authMethod === RepositoryAuthMethod.USERNAME_PASSWORD) {
this.showChangePassword = true;
this.changePassword = false;
} else {
this.showChangePrivateKeyPassword = true;
this.changePrivateKeyPassword = false;
}
this.repositorySettingsForm.reset(this.settings);
this.updateValidators(false);
this.store.dispatch(new ActionAuthUpdateHasRepository({ hasRepository: true }));
}
);
}
delete(formDirective: FormGroupDirective): void {
this.dialogService.confirm(
this.translate.instant('admin.delete-repository-settings-title', ),
this.translate.instant('admin.delete-repository-settings-text'), null,
this.translate.instant('action.delete')
).subscribe((data) => {
if (data) {
this.adminService.deleteRepositorySettings().subscribe(
() => {
this.settings = null;
this.showChangePassword = false;
this.changePassword = false;
this.showChangePrivateKeyPassword = false;
this.changePrivateKeyPassword = false;
formDirective.resetForm();
this.repositorySettingsForm.reset({ defaultBranch: 'main', authMethod: RepositoryAuthMethod.USERNAME_PASSWORD });
this.updateValidators(false);
this.store.dispatch(new ActionAuthUpdateHasRepository({ hasRepository: false }));
}
);
}
});
}
changePasswordChanged() {
if (this.changePassword) {
this.repositorySettingsForm.get('password').patchValue('');
this.repositorySettingsForm.get('password').markAsDirty();
}
this.updateValidators(false);
}
changePrivateKeyPasswordChanged() {
if (this.changePrivateKeyPassword) {
this.repositorySettingsForm.get('privateKeyPassword').patchValue('');
this.repositorySettingsForm.get('privateKeyPassword').markAsDirty();
}
this.updateValidators(false);
}
updateValidators(emitEvent?: boolean): void {
const authMethod: RepositoryAuthMethod = this.repositorySettingsForm.get('authMethod').value;
const privateKeyFileName: string = this.repositorySettingsForm.get('privateKeyFileName').value;
if (authMethod === RepositoryAuthMethod.USERNAME_PASSWORD) {
this.repositorySettingsForm.get('username').enable({emitEvent});
if (this.changePassword || !this.showChangePassword) {
this.repositorySettingsForm.get('password').enable({emitEvent});
} else {
this.repositorySettingsForm.get('password').disable({emitEvent});
}
this.repositorySettingsForm.get('privateKeyFileName').disable({emitEvent});
this.repositorySettingsForm.get('privateKey').disable({emitEvent});
this.repositorySettingsForm.get('privateKeyPassword').disable({emitEvent});
} else {
this.repositorySettingsForm.get('username').disable({emitEvent});
this.repositorySettingsForm.get('password').disable({emitEvent});
this.repositorySettingsForm.get('privateKeyFileName').enable({emitEvent});
this.repositorySettingsForm.get('privateKey').enable({emitEvent});
if (this.changePrivateKeyPassword || !this.showChangePrivateKeyPassword) {
this.repositorySettingsForm.get('privateKeyPassword').enable({emitEvent});
} else {
this.repositorySettingsForm.get('privateKeyPassword').disable({emitEvent});
}
if (isNotEmptyStr(privateKeyFileName)) {
this.repositorySettingsForm.get('privateKey').clearValidators();
} else {
this.repositorySettingsForm.get('privateKey').setValidators([Validators.required]);
}
}
this.repositorySettingsForm.get('username').updateValueAndValidity({emitEvent: false});
this.repositorySettingsForm.get('password').updateValueAndValidity({emitEvent: false});
this.repositorySettingsForm.get('privateKeyFileName').updateValueAndValidity({emitEvent: false});
this.repositorySettingsForm.get('privateKey').updateValueAndValidity({emitEvent: false});
this.repositorySettingsForm.get('privateKeyPassword').updateValueAndValidity({emitEvent: false});
}
}

218
ui-ngx/src/app/modules/home/components/vc/version-control-settings.component.ts

@ -1,218 +0,0 @@
///
/// Copyright © 2016-2022 The Thingsboard Authors
///
/// 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, Input, OnInit } from '@angular/core';
import { PageComponent } from '@shared/components/page.component';
import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard';
import { FormBuilder, FormGroup, FormGroupDirective, Validators } from '@angular/forms';
import { select, Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { AdminService } from '@core/http/admin.service';
import {
EntitiesVersionControlSettings,
VersionControlAuthMethod,
versionControlAuthMethodTranslationMap
} from '@shared/models/settings.models';
import { ActionNotificationShow } from '@core/notification/notification.actions';
import { TranslateService } from '@ngx-translate/core';
import { isNotEmptyStr } from '@core/utils';
import { DialogService } from '@core/services/dialog.service';
import { ActionSettingsChangeLanguage } from '@core/settings/settings.actions';
import { ActionAuthUpdateHasVersionControl } from '@core/auth/auth.actions';
import { selectHasVersionControl } from '@core/auth/auth.selectors';
import { catchError, mergeMap, take } from 'rxjs/operators';
import { of } from 'rxjs';
@Component({
selector: 'tb-version-control-settings',
templateUrl: './version-control-settings.component.html',
styleUrls: ['./version-control-settings.component.scss', './../../pages/admin/settings-card.scss']
})
export class VersionControlSettingsComponent extends PageComponent implements OnInit {
@Input()
detailsMode = false;
versionControlSettingsForm: FormGroup;
settings: EntitiesVersionControlSettings = null;
versionControlAuthMethod = VersionControlAuthMethod;
versionControlAuthMethods = Object.values(VersionControlAuthMethod);
versionControlAuthMethodTranslations = versionControlAuthMethodTranslationMap;
showChangePassword = false;
changePassword = false;
showChangePrivateKeyPassword = false;
changePrivateKeyPassword = false;
constructor(protected store: Store<AppState>,
private adminService: AdminService,
private dialogService: DialogService,
private translate: TranslateService,
public fb: FormBuilder) {
super(store);
}
ngOnInit() {
this.versionControlSettingsForm = this.fb.group({
repositoryUri: [null, [Validators.required]],
defaultBranch: ['main', []],
authMethod: [VersionControlAuthMethod.USERNAME_PASSWORD, [Validators.required]],
username: [null, []],
password: [null, []],
privateKeyFileName: [null, [Validators.required]],
privateKey: [null, []],
privateKeyPassword: [null, []]
});
this.updateValidators(false);
this.versionControlSettingsForm.get('authMethod').valueChanges.subscribe(() => {
this.updateValidators(true);
});
this.versionControlSettingsForm.get('privateKeyFileName').valueChanges.subscribe(() => {
this.updateValidators(false);
});
this.store.pipe(
select(selectHasVersionControl),
take(1),
mergeMap((hasVersionControl) => {
if (hasVersionControl) {
return this.adminService.getEntitiesVersionControlSettings({ignoreErrors: true}).pipe(
catchError(() => of(null))
);
} else {
return of(null);
}
})
).subscribe(
(settings) => {
this.settings = settings;
if (this.settings != null) {
if (this.settings.authMethod === VersionControlAuthMethod.USERNAME_PASSWORD) {
this.showChangePassword = true;
} else {
this.showChangePrivateKeyPassword = true;
}
this.versionControlSettingsForm.reset(this.settings);
this.updateValidators(false);
}
});
}
checkAccess(): void {
const settings: EntitiesVersionControlSettings = this.versionControlSettingsForm.value;
this.adminService.checkVersionControlAccess(settings).subscribe(() => {
this.store.dispatch(new ActionNotificationShow({ message: this.translate.instant('admin.check-vc-access-success'),
type: 'success' }));
});
}
save(): void {
const settings: EntitiesVersionControlSettings = this.versionControlSettingsForm.value;
this.adminService.saveEntitiesVersionControlSettings(settings).subscribe(
(savedSettings) => {
this.settings = savedSettings;
if (this.settings.authMethod === VersionControlAuthMethod.USERNAME_PASSWORD) {
this.showChangePassword = true;
this.changePassword = false;
} else {
this.showChangePrivateKeyPassword = true;
this.changePrivateKeyPassword = false;
}
this.versionControlSettingsForm.reset(this.settings);
this.updateValidators(false);
this.store.dispatch(new ActionAuthUpdateHasVersionControl({ hasVersionControl: true }));
}
);
}
delete(formDirective: FormGroupDirective): void {
this.dialogService.confirm(
this.translate.instant('admin.delete-git-settings-title', ),
this.translate.instant('admin.delete-git-settings-text'), null,
this.translate.instant('action.delete')
).subscribe((data) => {
if (data) {
this.adminService.deleteEntitiesVersionControlSettings().subscribe(
() => {
this.settings = null;
this.showChangePassword = false;
this.changePassword = false;
this.showChangePrivateKeyPassword = false;
this.changePrivateKeyPassword = false;
formDirective.resetForm();
this.versionControlSettingsForm.reset({ defaultBranch: 'main', authMethod: VersionControlAuthMethod.USERNAME_PASSWORD });
this.updateValidators(false);
this.store.dispatch(new ActionAuthUpdateHasVersionControl({ hasVersionControl: false }));
}
);
}
});
}
changePasswordChanged() {
if (this.changePassword) {
this.versionControlSettingsForm.get('password').patchValue('');
this.versionControlSettingsForm.get('password').markAsDirty();
}
this.updateValidators(false);
}
changePrivateKeyPasswordChanged() {
if (this.changePrivateKeyPassword) {
this.versionControlSettingsForm.get('privateKeyPassword').patchValue('');
this.versionControlSettingsForm.get('privateKeyPassword').markAsDirty();
}
this.updateValidators(false);
}
updateValidators(emitEvent?: boolean): void {
const authMethod: VersionControlAuthMethod = this.versionControlSettingsForm.get('authMethod').value;
const privateKeyFileName: string = this.versionControlSettingsForm.get('privateKeyFileName').value;
if (authMethod === VersionControlAuthMethod.USERNAME_PASSWORD) {
this.versionControlSettingsForm.get('username').enable({emitEvent});
if (this.changePassword || !this.showChangePassword) {
this.versionControlSettingsForm.get('password').enable({emitEvent});
} else {
this.versionControlSettingsForm.get('password').disable({emitEvent});
}
this.versionControlSettingsForm.get('privateKeyFileName').disable({emitEvent});
this.versionControlSettingsForm.get('privateKey').disable({emitEvent});
this.versionControlSettingsForm.get('privateKeyPassword').disable({emitEvent});
} else {
this.versionControlSettingsForm.get('username').disable({emitEvent});
this.versionControlSettingsForm.get('password').disable({emitEvent});
this.versionControlSettingsForm.get('privateKeyFileName').enable({emitEvent});
this.versionControlSettingsForm.get('privateKey').enable({emitEvent});
if (this.changePrivateKeyPassword || !this.showChangePrivateKeyPassword) {
this.versionControlSettingsForm.get('privateKeyPassword').enable({emitEvent});
} else {
this.versionControlSettingsForm.get('privateKeyPassword').disable({emitEvent});
}
if (isNotEmptyStr(privateKeyFileName)) {
this.versionControlSettingsForm.get('privateKey').clearValidators();
} else {
this.versionControlSettingsForm.get('privateKey').setValidators([Validators.required]);
}
}
this.versionControlSettingsForm.get('username').updateValueAndValidity({emitEvent: false});
this.versionControlSettingsForm.get('password').updateValueAndValidity({emitEvent: false});
this.versionControlSettingsForm.get('privateKeyFileName').updateValueAndValidity({emitEvent: false});
this.versionControlSettingsForm.get('privateKey').updateValueAndValidity({emitEvent: false});
this.versionControlSettingsForm.get('privateKeyPassword').updateValueAndValidity({emitEvent: false});
}
}

6
ui-ngx/src/app/modules/home/components/vc/version-control.component.html

@ -15,9 +15,9 @@
limitations under the License.
-->
<tb-version-control-settings #versionControlSettingsComponent [detailsMode]="detailsMode"
*ngIf="!(hasVersionControl$ | async); else versionsTable">
</tb-version-control-settings>
<tb-repository-settings #repositorySettingsComponent [detailsMode]="detailsMode"
*ngIf="!(hasRepository$ | async); else versionsTable">
</tb-repository-settings>
<ng-template #versionsTable>
<tb-entity-versions-table [singleEntityMode]="singleEntityMode"
[active]="active"

10
ui-ngx/src/app/modules/home/components/vc/version-control.component.ts

@ -17,9 +17,9 @@
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
import { select, Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { selectHasVersionControl } from '@core/auth/auth.selectors';
import { selectHasRepository } from '@core/auth/auth.selectors';
import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard';
import { VersionControlSettingsComponent } from '@home/components/vc/version-control-settings.component';
import { RepositorySettingsComponent } from '@home/components/vc/repository-settings.component';
import { FormGroup } from '@angular/forms';
import { EntityId } from '@shared/models/id/entity-id';
@ -30,7 +30,7 @@ import { EntityId } from '@shared/models/id/entity-id';
})
export class VersionControlComponent implements OnInit, HasConfirmForm {
@ViewChild('versionControlSettingsComponent', {static: false}) versionControlSettingsComponent: VersionControlSettingsComponent;
@ViewChild('repositorySettingsComponent', {static: false}) repositorySettingsComponent: RepositorySettingsComponent;
@Input()
detailsMode = false;
@ -50,7 +50,7 @@ export class VersionControlComponent implements OnInit, HasConfirmForm {
@Output()
versionRestored = new EventEmitter<void>();
hasVersionControl$ = this.store.pipe(select(selectHasVersionControl));
hasRepository$ = this.store.pipe(select(selectHasRepository));
constructor(private store: Store<AppState>) {
@ -61,7 +61,7 @@ export class VersionControlComponent implements OnInit, HasConfirmForm {
}
confirmForm(): FormGroup {
return this.versionControlSettingsComponent?.versionControlSettingsForm;
return this.repositorySettingsComponent?.repositorySettingsForm;
}
}

10
ui-ngx/src/app/modules/home/pages/admin/admin-routing.module.ts

@ -33,7 +33,7 @@ import { EntityDetailsPageComponent } from '@home/components/entity/entity-detai
import { entityDetailsPageBreadcrumbLabelFunction } from '@home/pages/home-pages.models';
import { BreadCrumbConfig } from '@shared/components/breadcrumb';
import { QueuesTableConfigResolver } from '@home/pages/admin/queue/queues-table-config.resolver';
import { VersionControlAdminSettingsComponent } from '@home/pages/admin/version-control-admin-settings.component';
import { RepositoryAdminSettingsComponent } from '@home/pages/admin/repository-admin-settings.component';
@Injectable()
export class OAuth2LoginProcessingUrlResolver implements Resolve<string> {
@ -225,14 +225,14 @@ const routes: Routes = [
]
},
{
path: 'vc',
component: VersionControlAdminSettingsComponent,
path: 'repository',
component: RepositoryAdminSettingsComponent,
canDeactivate: [ConfirmOnExitGuard],
data: {
auth: [Authority.TENANT_ADMIN],
title: 'admin.git-settings',
title: 'admin.repository-settings',
breadcrumb: {
label: 'admin.git-settings',
label: 'admin.repository-settings',
icon: 'manage_history'
}
}

4
ui-ngx/src/app/modules/home/pages/admin/admin.module.ts

@ -29,7 +29,7 @@ import { SendTestSmsDialogComponent } from '@home/pages/admin/send-test-sms-dial
import { HomeSettingsComponent } from '@home/pages/admin/home-settings.component';
import { ResourcesLibraryComponent } from '@home/pages/admin/resource/resources-library.component';
import { QueueComponent} from '@home/pages/admin/queue/queue.component';
import { VersionControlAdminSettingsComponent } from '@home/pages/admin/version-control-admin-settings.component';
import { RepositoryAdminSettingsComponent } from '@home/pages/admin/repository-admin-settings.component';
@NgModule({
declarations:
@ -43,7 +43,7 @@ import { VersionControlAdminSettingsComponent } from '@home/pages/admin/version-
HomeSettingsComponent,
ResourcesLibraryComponent,
QueueComponent,
VersionControlAdminSettingsComponent
RepositoryAdminSettingsComponent
],
imports: [
CommonModule,

2
ui-ngx/src/app/modules/home/pages/admin/version-control-admin-settings.component.html → ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.html

@ -15,4 +15,4 @@
limitations under the License.
-->
<tb-version-control-settings #versionControlSettingsComponent></tb-version-control-settings>
<tb-repository-settings #repositorySettingsComponent></tb-repository-settings>

12
ui-ngx/src/app/modules/home/pages/admin/version-control-admin-settings.component.ts → ui-ngx/src/app/modules/home/pages/admin/repository-admin-settings.component.ts

@ -20,16 +20,16 @@ import { HasConfirmForm } from '@core/guards/confirm-on-exit.guard';
import { Store } from '@ngrx/store';
import { AppState } from '@core/core.state';
import { FormGroup } from '@angular/forms';
import { VersionControlSettingsComponent } from '@home/components/vc/version-control-settings.component';
import { RepositorySettingsComponent } from '@home/components/vc/repository-settings.component';
@Component({
selector: 'tb-version-control-admin-settings',
templateUrl: './version-control-admin-settings.component.html',
selector: 'tb-repository-admin-settings',
templateUrl: './repository-admin-settings.component.html',
styleUrls: []
})
export class VersionControlAdminSettingsComponent extends PageComponent implements OnInit, HasConfirmForm {
export class RepositoryAdminSettingsComponent extends PageComponent implements OnInit, HasConfirmForm {
@ViewChild('versionControlSettingsComponent') versionControlSettingsComponent: VersionControlSettingsComponent;
@ViewChild('repositorySettingsComponent') repositorySettingsComponent: RepositorySettingsComponent;
constructor(protected store: Store<AppState>) {
super(store);
@ -39,6 +39,6 @@ export class VersionControlAdminSettingsComponent extends PageComponent implemen
}
confirmForm(): FormGroup {
return this.versionControlSettingsComponent?.versionControlSettingsForm;
return this.repositorySettingsComponent?.repositorySettingsForm;
}
}

2
ui-ngx/src/app/shared/models/constants.ts

@ -135,7 +135,7 @@ export const HelpLinks = {
ruleNodePushToCloud: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-cloud',
ruleNodePushToEdge: helpBaseUrl + '/docs/user-guide/rule-engine-2-0/action-nodes/#push-to-edge',
queue: helpBaseUrl + '/docs/user-guide/queue',
versionControlSettings: helpBaseUrl + '/docs/user-guide/ui/version-control-settings'
repositorySettings: helpBaseUrl + '/docs/user-guide/ui/repository-settings'
}
};

19
ui-ngx/src/app/shared/models/settings.models.ts

@ -16,6 +16,7 @@
import { ValidatorFn } from '@angular/forms';
import { isNotEmptyStr, isNumber } from '@core/utils';
import { VersionCreateConfig } from '@shared/models/vc.models';
export const smtpPortPattern: RegExp = /^([0-9]{1,4}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5])$/;
@ -397,23 +398,29 @@ export function createSmsProviderConfiguration(type: SmsProviderType): SmsProvid
return smsProviderConfiguration;
}
export enum VersionControlAuthMethod {
export enum RepositoryAuthMethod {
USERNAME_PASSWORD = 'USERNAME_PASSWORD',
PRIVATE_KEY = 'PRIVATE_KEY'
}
export const versionControlAuthMethodTranslationMap = new Map<VersionControlAuthMethod, string>([
[VersionControlAuthMethod.USERNAME_PASSWORD, 'admin.auth-method-username-password'],
[VersionControlAuthMethod.PRIVATE_KEY, 'admin.auth-method-private-key']
export const repositoryAuthMethodTranslationMap = new Map<RepositoryAuthMethod, string>([
[RepositoryAuthMethod.USERNAME_PASSWORD, 'admin.auth-method-username-password'],
[RepositoryAuthMethod.PRIVATE_KEY, 'admin.auth-method-private-key']
]);
export interface EntitiesVersionControlSettings {
export interface RepositorySettings {
repositoryUri: string;
defaultBranch: string;
authMethod: VersionControlAuthMethod;
authMethod: RepositoryAuthMethod;
username: string;
password: string;
privateKeyFileName: string;
privateKey: string;
privateKeyPassword: string;
}
export interface AutoVersionCreateConfig extends VersionCreateConfig {
branch: string;
}
export type AutoCommitSettings = {[entityType: string]: AutoVersionCreateConfig};

23
ui-ngx/src/app/shared/models/vc.models.ts

@ -32,6 +32,7 @@ export const exportableEntityTypes: Array<EntityType> = [
export interface VersionCreateConfig {
saveRelations: boolean;
saveAttributes: boolean;
}
export enum VersionCreateRequestType {
@ -81,6 +82,7 @@ export function createDefaultEntityTypesVersionCreate(): {[entityType: string]:
res[entityType] = {
syncStrategy: null,
saveRelations: false,
saveAttributes: false,
allEntities: true,
entityIds: []
};
@ -90,6 +92,7 @@ export function createDefaultEntityTypesVersionCreate(): {[entityType: string]:
export interface VersionLoadConfig {
loadRelations: boolean;
loadAttributes: boolean;
}
export enum VersionLoadRequestType {
@ -111,6 +114,7 @@ export interface SingleEntityVersionLoadRequest extends VersionLoadRequest {
export interface EntityTypeVersionLoadConfig extends VersionLoadConfig {
removeOtherEntities: boolean;
findExistingEntityByName: boolean;
}
export interface EntityTypeVersionLoadRequest extends VersionLoadRequest {
@ -123,7 +127,9 @@ export function createDefaultEntityTypesVersionLoad(): {[entityType: string]: En
for (const entityType of exportableEntityTypes) {
res[entityType] = {
loadRelations: false,
removeOtherEntities: false
loadAttributes: false,
removeOtherEntities: false,
findExistingEntityByName: false
};
}
return res;
@ -176,18 +182,5 @@ export interface EntityDataDiff {
}
export function entityExportDataToJsonString(data: EntityExportData<any>): string {
if (!data.relations) {
data.relations = [];
}
const allKeys = new Set<string>();
JSON.stringify(data, (key, value) => (allKeys.add(key), value));
return JSON.stringify(data, Array.from(allKeys).sort((key1, key2) => {
if (key1 === 'relations') {
return 1;
} else if (key2 === 'relations') {
return -1;
} else {
return 0;
}
}), 4);
return JSON.stringify(data, null, 4);
}

19
ui-ngx/src/assets/locale/locale.constant-en_US.json

@ -58,7 +58,8 @@
"next-with-label": "Next: {{label}}",
"read-more": "Read more",
"hide": "Hide",
"restore": "Restore"
"restore": "Restore",
"confirm": "Confirm"
},
"aggregation": {
"aggregation": "Aggregation",
@ -321,8 +322,7 @@
"queue-submit-strategy": "Submit strategy",
"queue-processing-strategy": "Processing strategy",
"queue-configuration": "Queue configuration",
"git-settings": "Git settings",
"git-repository-settings": "Git repository settings",
"repository-settings": "Repository settings",
"repository-url": "Repository URL",
"repository-url-required": "Repository URL is required.",
"default-branch": "Default branch name",
@ -338,9 +338,9 @@
"enter-passphrase": "Enter passphrase",
"change-passphrase": "Change passphrase",
"check-access": "Check access",
"check-vc-access-success": "Git repository access successfully verified!",
"delete-git-settings-title": "Are you sure you want to delete git settings?",
"delete-git-settings-text": "Be careful, after the confirmation the git settings will be removed and git synchronization feature will be unavailable."
"check-repository-access-success": "Repository access successfully verified!",
"delete-repository-settings-title": "Are you sure you want to delete repository settings?",
"delete-repository-settings-text": "Be careful, after the confirmation the repository settings will be removed and version control feature will be unavailable."
},
"alarm": {
"alarm": "Alarm",
@ -3121,6 +3121,7 @@
"version-name-required": "Version name is required",
"author": "Author",
"export-entity-relations": "Export entity relations",
"export-entity-attributes": "Export entity attributes",
"entity-versions": "Entity versions",
"versions": "Versions",
"created-time": "Created time",
@ -3133,6 +3134,7 @@
"restore-version": "Restore version",
"restore-entity-from-version": "Restore entity from version '{{versionName}}'",
"load-entity-relations": "Load entity relations",
"load-entity-attributes": "Load entity attributes",
"show-version-diff": "Show version diff",
"diff-entity-with-version": "Diff with entity version '{{versionName}}'",
"previous-difference": "Previous Difference",
@ -3151,12 +3153,15 @@
"remove-all": "Remove all",
"version-create-result": "{ added, plural, 0 {No entities} 1 {1 entity} other {# entities} } added.\n{ modified, plural, 0 {No entities} 1 {1 entity} other {# entities} } modified.\n{ removed, plural, 0 {No entities} 1 {1 entity} other {# entities} } removed.",
"load-entities-relations": "Load entities relations",
"load-entities-attributes": "Load entities attributes",
"remove-other-entities": "Remove other entities",
"find-existing-entity-by-name": "Find existing entity by name",
"restore-entities-from-version": "Restore entities from version '{{versionName}}'",
"no-entities-restored": "No entities restored",
"created": "{{created}} created",
"updated": "{{updated}} updated",
"deleted": "{{deleted}} deleted"
"deleted": "{{deleted}} deleted",
"remove-other-entities-confirm-text": "Be careful! This will permanently <b>delete</b> <b>all</b> current entities<br/>not present in the version you want to restore.<br/><br/>Please type <b>remove other entities</b> to confirm."
},
"widget": {
"widget-library": "Widgets Library",

Loading…
Cancel
Save