Version Control for OTA updates
This commit is contained in:
commit
db2ca43b02
@ -38,6 +38,7 @@ import { JsLibraryTableHeaderComponent } from '@home/pages/admin/resource/js-lib
|
|||||||
import { JsResourceComponent } from '@home/pages/admin/resource/js-resource.component';
|
import { JsResourceComponent } from '@home/pages/admin/resource/js-resource.component';
|
||||||
import { NgxFlowModule } from '@flowjs/ngx-flow';
|
import { NgxFlowModule } from '@flowjs/ngx-flow';
|
||||||
import { TrendzSettingsComponent } from '@home/pages/admin/trendz-settings.component';
|
import { TrendzSettingsComponent } from '@home/pages/admin/trendz-settings.component';
|
||||||
|
import { ResourceLibraryTabsComponent } from '@home/pages/admin/resource/resource-library-tabs.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations:
|
declarations:
|
||||||
@ -50,6 +51,7 @@ import { TrendzSettingsComponent } from '@home/pages/admin/trendz-settings.compo
|
|||||||
HomeSettingsComponent,
|
HomeSettingsComponent,
|
||||||
ResourcesLibraryComponent,
|
ResourcesLibraryComponent,
|
||||||
ResourceTabsComponent,
|
ResourceTabsComponent,
|
||||||
|
ResourceLibraryTabsComponent,
|
||||||
ResourcesTableHeaderComponent,
|
ResourcesTableHeaderComponent,
|
||||||
JsResourceComponent,
|
JsResourceComponent,
|
||||||
JsLibraryTableHeaderComponent,
|
JsLibraryTableHeaderComponent,
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2025 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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<mat-tab *ngIf="entity && entity.tenantId.id !== NULL_UUID && authUser.authority === authorities.TENANT_ADMIN && !isEdit"
|
||||||
|
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
|
||||||
|
<tb-version-control detailsMode="true" singleEntityMode="true"
|
||||||
|
(versionRestored)="entitiesTableConfig.updateData()"
|
||||||
|
[active]="versionControlTab.isActive" [entityId]="entity.id" [entityName]="entity.name" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
|
||||||
|
</mat-tab>
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2025 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 } from '@angular/core';
|
||||||
|
import { EntityTabsComponent } from '@home/components/entity/entity-tabs.component';
|
||||||
|
import { Resource } from '@shared/models/resource.models';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-resource-library-tabs',
|
||||||
|
templateUrl: './resource-library-tabs.component.html',
|
||||||
|
styleUrls: []
|
||||||
|
})
|
||||||
|
export class ResourceLibraryTabsComponent extends EntityTabsComponent<Resource> {
|
||||||
|
|
||||||
|
readonly NULL_UUID = NULL_UUID;
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -37,6 +37,7 @@ import { PageLink } from '@shared/models/page/page-link';
|
|||||||
import { EntityAction } from '@home/models/entity/entity-component.models';
|
import { EntityAction } from '@home/models/entity/entity-component.models';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { ResourcesTableHeaderComponent } from '@home/pages/admin/resource/resources-table-header.component';
|
import { ResourcesTableHeaderComponent } from '@home/pages/admin/resource/resources-table-header.component';
|
||||||
|
import { ResourceLibraryTabsComponent } from '@home/pages/admin/resource/resource-library-tabs.component';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ResourcesLibraryTableConfigResolver {
|
export class ResourcesLibraryTableConfigResolver {
|
||||||
@ -55,6 +56,7 @@ export class ResourcesLibraryTableConfigResolver {
|
|||||||
this.config.entityTranslations = entityTypeTranslations.get(EntityType.TB_RESOURCE);
|
this.config.entityTranslations = entityTypeTranslations.get(EntityType.TB_RESOURCE);
|
||||||
this.config.entityResources = entityTypeResources.get(EntityType.TB_RESOURCE);
|
this.config.entityResources = entityTypeResources.get(EntityType.TB_RESOURCE);
|
||||||
this.config.headerComponent = ResourcesTableHeaderComponent;
|
this.config.headerComponent = ResourcesTableHeaderComponent;
|
||||||
|
this.config.entityTabsComponent = ResourceLibraryTabsComponent;
|
||||||
|
|
||||||
this.config.entityTitle = (resource) => resource ?
|
this.config.entityTitle = (resource) => resource ?
|
||||||
resource.title : '';
|
resource.title : '';
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import { PageLink } from '@shared/models/page/page-link';
|
|||||||
import { OtaUpdateComponent } from '@home/pages/ota-update/ota-update.component';
|
import { OtaUpdateComponent } from '@home/pages/ota-update/ota-update.component';
|
||||||
import { EntityAction } from '@home/models/entity/entity-component.models';
|
import { EntityAction } from '@home/models/entity/entity-component.models';
|
||||||
import { FileSizePipe } from '@shared/pipe/file-size.pipe';
|
import { FileSizePipe } from '@shared/pipe/file-size.pipe';
|
||||||
|
import { OtaUpdateTabsComponent } from '@home/pages/ota-update/ota-update-tabs.component';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OtaUpdateTableConfigResolve {
|
export class OtaUpdateTableConfigResolve {
|
||||||
@ -50,6 +51,7 @@ export class OtaUpdateTableConfigResolve {
|
|||||||
private fileSize: FileSizePipe) {
|
private fileSize: FileSizePipe) {
|
||||||
this.config.entityType = EntityType.OTA_PACKAGE;
|
this.config.entityType = EntityType.OTA_PACKAGE;
|
||||||
this.config.entityComponent = OtaUpdateComponent;
|
this.config.entityComponent = OtaUpdateComponent;
|
||||||
|
this.config.entityTabsComponent = OtaUpdateTabsComponent;
|
||||||
this.config.entityTranslations = entityTypeTranslations.get(EntityType.OTA_PACKAGE);
|
this.config.entityTranslations = entityTypeTranslations.get(EntityType.OTA_PACKAGE);
|
||||||
this.config.entityResources = entityTypeResources.get(EntityType.OTA_PACKAGE);
|
this.config.entityResources = entityTypeResources.get(EntityType.OTA_PACKAGE);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,23 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
Copyright © 2016-2025 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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<mat-tab *ngIf="isTenantOtaUpdate() && authUser.authority === authorities.TENANT_ADMIN"
|
||||||
|
label="{{ 'version-control.version-control' | translate }}" #versionControlTab="matTab">
|
||||||
|
<tb-version-control detailsMode="true" singleEntityMode="true"
|
||||||
|
(versionRestored)="entitiesTableConfig.updateData()"
|
||||||
|
[active]="versionControlTab.isActive" [entityId]="entity.id" [entityName]="entity.title" [externalEntityId]="entity.externalId || entity.id"></tb-version-control>
|
||||||
|
</mat-tab>
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
///
|
||||||
|
/// Copyright © 2016-2025 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 } from '@angular/core';
|
||||||
|
import { Store } from '@ngrx/store';
|
||||||
|
import { AppState } from '@core/core.state';
|
||||||
|
import { EntityTabsComponent } from '../../components/entity/entity-tabs.component';
|
||||||
|
import { WidgetsBundle } from '@shared/models/widgets-bundle.model';
|
||||||
|
import { NULL_UUID } from '@shared/models/id/has-uuid';
|
||||||
|
import { OtaPackage } from '@shared/models/ota-package.models';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'tb-ota-update-tabs',
|
||||||
|
templateUrl: './ota-update-tabs.component.html',
|
||||||
|
styleUrls: []
|
||||||
|
})
|
||||||
|
export class OtaUpdateTabsComponent extends EntityTabsComponent<OtaPackage> {
|
||||||
|
|
||||||
|
constructor(protected store: Store<AppState>) {
|
||||||
|
super(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
isTenantOtaUpdate() {
|
||||||
|
return this.entity && this.entity.tenantId.id !== NULL_UUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -20,10 +20,12 @@ import { SharedModule } from '@shared/shared.module';
|
|||||||
import { HomeComponentsModule } from '@home/components/home-components.module';
|
import { HomeComponentsModule } from '@home/components/home-components.module';
|
||||||
import { OtaUpdateRoutingModule } from '@home/pages/ota-update/ota-update-routing.module';
|
import { OtaUpdateRoutingModule } from '@home/pages/ota-update/ota-update-routing.module';
|
||||||
import { OtaUpdateComponent } from '@home/pages/ota-update/ota-update.component';
|
import { OtaUpdateComponent } from '@home/pages/ota-update/ota-update.component';
|
||||||
|
import { OtaUpdateTabsComponent } from '@home/pages/ota-update/ota-update-tabs.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
OtaUpdateComponent
|
OtaUpdateComponent,
|
||||||
|
OtaUpdateTabsComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
@ -346,6 +346,8 @@ export const entityTypeTranslations = new Map<EntityType | AliasEntityType, Enti
|
|||||||
EntityType.OTA_PACKAGE,
|
EntityType.OTA_PACKAGE,
|
||||||
{
|
{
|
||||||
type: 'entity.type-ota-package',
|
type: 'entity.type-ota-package',
|
||||||
|
typePlural: 'entity.type-ota-packages',
|
||||||
|
list: 'entity.list-of-ota-packages',
|
||||||
details: 'ota-update.ota-update-details',
|
details: 'ota-update.ota-update-details',
|
||||||
add: 'ota-update.add',
|
add: 'ota-update.add',
|
||||||
noEntities: 'ota-update.no-packages-text',
|
noEntities: 'ota-update.no-packages-text',
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
/// limitations under the License.
|
/// limitations under the License.
|
||||||
///
|
///
|
||||||
|
|
||||||
import { BaseData } from '@shared/models/base-data';
|
import { BaseData, ExportableEntity } from '@shared/models/base-data';
|
||||||
import { TenantId } from '@shared/models/id/tenant-id';
|
import { TenantId } from '@shared/models/id/tenant-id';
|
||||||
import { OtaPackageId } from '@shared/models/id/ota-package-id';
|
import { OtaPackageId } from '@shared/models/id/ota-package-id';
|
||||||
import { DeviceProfileId } from '@shared/models/id/device-profile-id';
|
import { DeviceProfileId } from '@shared/models/id/device-profile-id';
|
||||||
@ -86,7 +86,7 @@ export interface OtaPagesIds {
|
|||||||
softwareId?: OtaPackageId;
|
softwareId?: OtaPackageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OtaPackageInfo extends BaseData<OtaPackageId>, HasTenantId {
|
export interface OtaPackageInfo extends Omit<BaseData<OtaPackageId>, 'label'>, HasTenantId, ExportableEntity<OtaPackageId> {
|
||||||
tenantId?: TenantId;
|
tenantId?: TenantId;
|
||||||
type: OtaUpdateType;
|
type: OtaUpdateType;
|
||||||
deviceProfileId?: DeviceProfileId;
|
deviceProfileId?: DeviceProfileId;
|
||||||
|
|||||||
@ -33,16 +33,18 @@ export const exportableEntityTypes: Array<EntityType> = [
|
|||||||
EntityType.WIDGET_TYPE,
|
EntityType.WIDGET_TYPE,
|
||||||
EntityType.WIDGETS_BUNDLE,
|
EntityType.WIDGETS_BUNDLE,
|
||||||
EntityType.TB_RESOURCE,
|
EntityType.TB_RESOURCE,
|
||||||
|
EntityType.OTA_PACKAGE,
|
||||||
EntityType.NOTIFICATION_TEMPLATE,
|
EntityType.NOTIFICATION_TEMPLATE,
|
||||||
EntityType.NOTIFICATION_TARGET,
|
EntityType.NOTIFICATION_TARGET,
|
||||||
EntityType.NOTIFICATION_RULE
|
EntityType.NOTIFICATION_RULE
|
||||||
];
|
];
|
||||||
|
|
||||||
export const entityTypesWithoutRelatedData: Set<EntityType | AliasEntityType> = new Set([
|
export const entityTypesWithoutRelatedData = new Set<EntityType | AliasEntityType>([
|
||||||
EntityType.NOTIFICATION_TEMPLATE,
|
EntityType.NOTIFICATION_TEMPLATE,
|
||||||
EntityType.NOTIFICATION_TARGET,
|
EntityType.NOTIFICATION_TARGET,
|
||||||
EntityType.NOTIFICATION_RULE,
|
EntityType.NOTIFICATION_RULE,
|
||||||
EntityType.TB_RESOURCE
|
EntityType.TB_RESOURCE,
|
||||||
|
EntityType.OTA_PACKAGE,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export interface VersionCreateConfig {
|
export interface VersionCreateConfig {
|
||||||
|
|||||||
@ -2584,6 +2584,8 @@
|
|||||||
"type-tb-resources": "Resources",
|
"type-tb-resources": "Resources",
|
||||||
"list-of-tb-resources": "{ count, plural, =1 {One resource} other {List of # resources} }",
|
"list-of-tb-resources": "{ count, plural, =1 {One resource} other {List of # resources} }",
|
||||||
"type-ota-package": "OTA package",
|
"type-ota-package": "OTA package",
|
||||||
|
"type-ota-packages": "OTA packages",
|
||||||
|
"list-of-ota-packages": "{ count, plural, =1 {One OTA package} other {List of # OTA packages} }",
|
||||||
"type-rpc": "RPC",
|
"type-rpc": "RPC",
|
||||||
"type-queue": "Queue",
|
"type-queue": "Queue",
|
||||||
"type-queue-stats": "Queue statistics",
|
"type-queue-stats": "Queue statistics",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user