-
-
<%= jhiPrefix %>Translate="entityAudit.result.showInfo" [translateValues]="{ limit: selectedLimit, entity: selectedEntity }"<% } %>>
- Last {{ selectedLimit }}
- Changes for {{ selectedEntity }}
-
+
+ @if (audits().length > 0 || filterEntityId()) {
+
+
__jhiTranslateTag__('entityAudit.result.showInfo', { "limit": "selectedLimit()", "entity": "selectedEntity()" })
-
+
-
+
-
- <%= jhiPrefix %>Translate="entityAudit.result.tableHeader.entityId"<% } %>>
- Entity Id
- |
- <%= jhiPrefix %>Translate="entityAudit.result.tableHeader.action"<% } %>>
- Action
- |
- <%= jhiPrefix %>Translate="entityAudit.result.tableHeader.version"<% } %>>
- Version
- |
- <%= jhiPrefix %>Translate="entityAudit.result.tableHeader.value"<% } %>>
- Value
- |
- <%= jhiPrefix %>Translate="entityAudit.result.tableHeader.modifiedDate"<% } %>>
- Modified Date
- |
- <%= jhiPrefix %>Translate="entityAudit.result.tableHeader.modifiedBy"<% } %>>
- Modified By
- |
+
+ __jhiTranslateTag__('entityAudit.result.tableHeader.entityId') |
+ __jhiTranslateTag__('entityAudit.result.tableHeader.action') |
+ __jhiTranslateTag__('entityAudit.result.tableHeader.version') |
+ __jhiTranslateTag__('entityAudit.result.tableHeader.value') |
+ __jhiTranslateTag__('entityAudit.result.tableHeader.modifiedDate') |
+ __jhiTranslateTag__('entityAudit.result.tableHeader.modifiedBy') |
|
-
+
-
- {{ audit.entityId }} |
- {{ audit.action }} |
- {{ audit.commitVersion }} |
- {{ audit.entityValue | json }} |
- {{ audit.modifiedDate | date:'medium' }} |
- {{ audit.modifiedBy }} |
-
-
- |
-
+ @for (audit of audits(); track audit.id) {
+
+ {{ audit.entityId }} |
+ {{ audit.action }} |
+ {{ audit.commitVersion }} |
+
+ {{ audit.entityValue | json }}
+ |
+ {{ audit.modifiedDate | date: 'medium' }} |
+ {{ audit.modifiedBy }} |
+
+
+ |
+
+ }
-
+
-
<%= jhiPrefix %>Translate="entityAudit.result.noDataFound"<% } %> class="mt-2">
- No Data found for the filters
-
+ } @else {
+
__jhiTranslateTag__('entityAudit.result.noDataFound')
+ }
diff --git a/generators/angular-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.component.ts.ejs b/generators/angular-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.component.ts.ejs
index 59b4c96..ef0f807 100644
--- a/generators/angular-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.component.ts.ejs
+++ b/generators/angular-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.component.ts.ejs
@@ -1,107 +1,108 @@
-import { Component, OnInit } from '@angular/core';
+import { Component, OnInit, computed, inject, signal } from '@angular/core';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { FormsModule } from '@angular/forms';
import { tap } from 'rxjs';
import SharedModule from 'app/shared/shared.module';
+import { AlertService } from 'app/core/util/alert.service';
import { EntityAuditService } from './entity-audit.service';
import { EntityAuditEvent } from './entity-audit-event.model';
import EntityAuditModalComponent from './entity-audit-modal.component';
-import { AlertService } from 'app/core/util/alert.service';
@Component({
- standalone: true,
- selector: '<%= jhiPrefixDashed %>-entity-audit',
- templateUrl: './entity-audit.component.html',
- imports: [SharedModule, FormsModule, EntityAuditModalComponent],
- styles: [`
+ standalone: true,
+ selector: '<%= jhiPrefixDashed %>-entity-audit',
+ templateUrl: './entity-audit.component.html',
+ imports: [SharedModule, FormsModule, EntityAuditModalComponent],
+ styles: [
+ `
.code {
background: #dcdada;
padding: 10px;
}
- `],
+ `,
+ ],
})
export default class EntityAuditComponent implements OnInit {
- audits: EntityAuditEvent[] = [];
- entities: string[] = [];
- selectedEntity?: string;
- limits = [25, 50, 100, 200];
- selectedLimit = this.limits[0];
- loading = false;
- filterEntityId = '';
- orderProp: keyof EntityAuditEvent = 'entityId';
- ascending = true;
+ entities = signal
([]);
+ selectedEntity = signal(undefined);
+ limits = [25, 50, 100, 200];
+ selectedLimit = signal(this.limits[0]);
+ loading = signal(false);
+ filterEntityId = signal('');
- constructor(
- private modalService: NgbModal,
- private service: EntityAuditService,
- private alertService: AlertService
- ) {}
+ audits = computed(() => {
+ const filterEntityId = this.filterEntityId();
+ const orderProp = this.orderProp();
+ const ascending = this.ascending();
+ return this._audits()
+ .filter(audit => !filterEntityId || audit.entityId.toString() === filterEntityId)
+ .sort((a, b) => {
+ const aOrderProp = a[orderProp];
+ const bOrderProp = b[orderProp];
+ if (aOrderProp === bOrderProp) {
+ return 0;
+ }
+ if (aOrderProp === undefined || aOrderProp < bOrderProp) {
+ return ascending ? -1 : 1;
+ }
+ return ascending ? 1 : -1;
+ });
+ });
- ngOnInit(): void {
- this.service.getAllAudited().subscribe(entities => {
- this.entities = entities;
- });
- }
+ private _audits = signal([]);
+ private orderProp = signal('entityId');
+ private ascending = signal(true);
- loadChanges(): void {
- if (!this.selectedEntity) {
- return;
- }
- this.loading = true;
- this.service.findByEntity(this.selectedEntity, this.selectedLimit)
- .pipe(tap(() => (this.loading = false)))
- .subscribe(res => {
- const data = res.body ?? [];
- this.audits = data.map((it: EntityAuditEvent) => {
- it.entityValue = JSON.parse(it.entityValue ?? '{}');
- return it;
- });
- });
- }
+ private modalService = inject(NgbModal);
+ private service = inject(EntityAuditService);
+ private alertService = inject(AlertService);
- trackId(index: number, item: EntityAuditEvent): number {
- return item.id;
- }
+ ngOnInit(): void {
+ this.service.getAllAudited().subscribe(entities => {
+ this.entities.set(entities);
+ });
+ }
- openChange(audit: EntityAuditEvent): void {
- if (!audit.commitVersion || audit.commitVersion < 2) {
- this.alertService.addAlert({
- type: 'warning',
- <%_ if (enableTranslation) { _%>
- translationKey: 'entityAudit.result.firstAuditEntry',
- <%_ } else { _%>
- message: 'There is no previous version available for this entry.\n' +
- 'This is the first audit entry captured for this object.',
- <%_ } _%>
- });
- } else {
- const modalRef = this.modalService.open(EntityAuditModalComponent);
- modalRef.componentInstance.openChange(audit);
- }
+ loadChanges(): void {
+ const selectedEntity = this.selectedEntity();
+ if (!selectedEntity) {
+ return;
}
+ this.loading.set(true);
+ this.service
+ .findByEntity(selectedEntity, this.selectedLimit())
+ .pipe(tap(() => this.loading.set(false)))
+ .subscribe(res => {
+ const data = res.body ?? [];
+ this._audits.set(
+ data.map((it: EntityAuditEvent) => {
+ it.entityValue = JSON.parse(it.entityValue ?? '{}');
+ return it;
+ }),
+ );
+ });
+ }
- orderBy(orderProp: keyof EntityAuditEvent): void {
- this.ascending = this.orderProp === orderProp ? !this.ascending : true;
- this.orderProp = orderProp;
+ openChange(audit: EntityAuditEvent): void {
+ if (!audit.commitVersion || audit.commitVersion < 2) {
+ this.alertService.addAlert({
+ type: 'warning',
+<%_ if (enableTranslation) { _%>
+ translationKey: 'entityAudit.result.firstAuditEntry',
+<%_ } else { _%>
+ message: 'There is no previous version available for this entry.\n' +
+ 'This is the first audit entry captured for this object.',
+<%_ } _%>
+ });
+ } else {
+ const modalRef = this.modalService.open(EntityAuditModalComponent, { size: 'lg' });
+ modalRef.componentInstance.openChange(audit);
}
+ }
- getAudits(): EntityAuditEvent[] {
- return this.audits
- .filter(audit => !this.filterEntityId || audit.entityId.toString() === this.filterEntityId)
- .sort((a, b) => {
- const aOrderProp = a[this.orderProp];
- const bOrderProp = b[this.orderProp];
- if (
- (aOrderProp === undefined && bOrderProp === undefined) ||
- (aOrderProp !== undefined && bOrderProp !== undefined && aOrderProp === bOrderProp)
- ) {
- return 0;
- }
- if (aOrderProp === undefined || aOrderProp < bOrderProp) {
- return this.ascending ? -1 : 1;
- }
- return this.ascending ? 1 : -1;
- });
- }
+ orderBy(orderProp: keyof EntityAuditEvent): void {
+ this.ascending.update(ascending => (this.orderProp() === orderProp ? !ascending : true));
+ this.orderProp.set(orderProp);
+ }
}
diff --git a/generators/languages/generator.js b/generators/languages/generator.js
index eaf79ba..7621f7b 100644
--- a/generators/languages/generator.js
+++ b/generators/languages/generator.js
@@ -13,10 +13,13 @@ export default class extends BaseApplicationGenerator {
get [BaseApplicationGenerator.WRITING]() {
return this.asWritingTaskGroup({
- async writingTemplateTask({ application: { languages = [], clientSrcDir } }) {
+ async writingTemplateTask({ application: { languages = [], nativeLanguage, clientSrcDir } }) {
if (!clientSrcDir) {
throw new Error('clientSrcDir is missing');
}
+ if (!languages.includes(nativeLanguage)) {
+ languages.unshift(nativeLanguage);
+ }
const templates = languages.map(language => {
const sourceLanguage = existsSync(`${this.templatePath()}/${TEMPLATES_WEBAPP_SOURCES_DIR}i18n/${language}/entity-audit.json`)
? language
diff --git a/generators/spring-boot-javers/generator.js b/generators/spring-boot-javers/generator.js
index df78410..c536901 100644
--- a/generators/spring-boot-javers/generator.js
+++ b/generators/spring-boot-javers/generator.js
@@ -21,7 +21,9 @@ export default class extends BaseApplicationGenerator {
get [BaseApplicationGenerator.DEFAULT]() {
return this.asDefaultTaskGroup({
async defaultTask({ application, entities }) {
- application.auditedEntities = entities.map(e => e.persistClass);
+ application.auditedEntities = entities
+ .filter(e => e.enableAudit)
+ .map(e => `${e.entityPackage ? `${e.entityPackage}.` : ''}domain.${e.persistClass}`);
},
});
}
diff --git a/generators/spring-boot-javers/templates/src/main/java/_package_/web/rest/JaversEntityAuditResource.java.ejs b/generators/spring-boot-javers/templates/src/main/java/_package_/web/rest/JaversEntityAuditResource.java.ejs
index 92495c7..c462370 100644
--- a/generators/spring-boot-javers/templates/src/main/java/_package_/web/rest/JaversEntityAuditResource.java.ejs
+++ b/generators/spring-boot-javers/templates/src/main/java/_package_/web/rest/JaversEntityAuditResource.java.ejs
@@ -5,15 +5,19 @@ import <%=packageName%>.security.AuthoritiesConstants;
import tech.jhipster.web.util.PaginationUtil;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.PersistenceContext;
import org.javers.core.Javers;
import org.javers.core.metamodel.object.CdoSnapshot;
import org.javers.repository.jql.QueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.core.convert.ConversionService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.support.JpaEntityInformationSupport;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
@@ -39,10 +43,16 @@ public class JaversEntityAuditResource {
private final Logger log = LoggerFactory.getLogger(JaversEntityAuditResource.class);
+ @PersistenceContext
+ private EntityManager manager;
+
private final Javers javers;
- public JaversEntityAuditResource(Javers javers) {
+ private final ConversionService conversionService;
+
+ public JaversEntityAuditResource(Javers javers, ConversionService conversionService) {
this.javers = javers;
+ this.conversionService = conversionService;
}
/**
@@ -75,7 +85,7 @@ public class JaversEntityAuditResource {
throws ClassNotFoundException {
log.debug("REST request to get a page of EntityAuditEvents");
- Class entityTypeToFetch = Class.forName("<%=packageName%>.domain." + entityType);
+ var entityTypeToFetch = Class.forName("<%=packageName%>." + entityType);
QueryBuilder jqlQuery = QueryBuilder.byClass(entityTypeToFetch)
.limit(limit);
@@ -111,13 +121,12 @@ public class JaversEntityAuditResource {
@RequestParam(value = "commitVersion") Long commitVersion)
throws ClassNotFoundException {
- Class entityTypeToFetch = Class.forName("<%=packageName%>.domain." + qualifiedName);
-
- QueryBuilder jqlQuery = QueryBuilder.byInstanceId(entityId, entityTypeToFetch)
- .limit(1)
- .withVersion(commitVersion - 1);
+ var entityTypeToFetch = Class.forName("<%- packageName %>." + qualifiedName);
+ var entityInformation = JpaEntityInformationSupport.getEntityInformation(entityTypeToFetch, manager);
+ var id = conversionService.convert(entityId, entityInformation.getIdType());
- EntityAuditEvent prev = EntityAuditEvent.fromJaversSnapshot(javers.findSnapshots(jqlQuery.build()).get(0));
+ var jqlQuery = QueryBuilder.byInstanceId(id, entityTypeToFetch).limit(1).withVersion(commitVersion - 1);
+ var prev = EntityAuditEvent.fromJaversSnapshot(javers.findSnapshots(jqlQuery.build()).get(0));
return new ResponseEntity<>(prev, HttpStatus.OK);
diff --git a/vitest.config.ts b/vitest.config.ts
index d46556a..d1fa83c 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -5,5 +5,6 @@ export default defineConfig({
pool: 'forks',
hookTimeout: 20000,
exclude: [...defaultExclude.filter(val => val !== '**/cypress/**'), '**/templates/**', '**/resources/**'],
+ setupFiles: ['./vitest.test-setup.ts'],
},
});
diff --git a/vitest.test-setup.ts b/vitest.test-setup.ts
new file mode 100644
index 0000000..b94ccb0
--- /dev/null
+++ b/vitest.test-setup.ts
@@ -0,0 +1,6 @@
+import { vi } from 'vitest';
+import { defineDefaults } from 'generator-jhipster/testing';
+
+defineDefaults({
+ mockFactory: () => vi.fn(),
+});