diff --git a/.yo-rc.json b/.yo-rc.json index 00e18a7..cd6cf0d 100644 --- a/.yo-rc.json +++ b/.yo-rc.json @@ -1,6 +1,6 @@ { "generator-jhipster": { - "additionalSubGenerators": "angular-audit,java-audit,spring-boot-custom-audit,spring-boot-javers", + "additionalSubGenerators": "angular-audit,java-audit,spring-boot-custom-audit,spring-boot-javers,vue-audit", "baseName": "entity-audit", "caret": true, "cli": true, diff --git a/generators/client/generator.js b/generators/client/generator.js index 58c7962..88e041e 100644 --- a/generators/client/generator.js +++ b/generators/client/generator.js @@ -14,6 +14,8 @@ export default class extends BaseApplicationGenerator { async composeTask() { if (this.blueprintConfig.auditPage && ['angularX', 'angular'].includes(this.jhipsterConfigWithDefaults.clientFramework)) { await this.composeWithJHipster('jhipster-entity-audit:angular-audit'); + } else if (this.blueprintConfig.auditPage && ['vue'].includes(this.jhipsterConfigWithDefaults.clientFramework)) { + await this.composeWithJHipster('jhipster-entity-audit:vue-audit'); } }, }); diff --git a/generators/languages/templates/src/main/webapp/i18n/th/entity-audit.json b/generators/languages/templates/src/main/webapp/i18n/th/entity-audit.json new file mode 100644 index 0000000..605bc78 --- /dev/null +++ b/generators/languages/templates/src/main/webapp/i18n/th/entity-audit.json @@ -0,0 +1,49 @@ +{ + "global": { + "menu": { + "admin": { + "entityAudit": "การตรวจสอบข้อมูล" + } + } + }, + "entityAudit": { + "home": { + "title": "รายการการตรวจสอบข้อมูล", + "filter": "ตัวกรอง", + "entityOrTable": "เอนทิตี/ตาราง", + "limitTo": "จำกัดจำนวน", + "loadChangeList": "โหลดรายการเปลี่ยนแปลง" + }, + "result": { + "showInfo": "แสดง {{ limit }} การเปลี่ยนแปลงล่าสุดของ {{ entity }}", + "searchFieldLabel": "ตัวกรอง:", + "globalFilter": "ตัวกรองทั่วไป", + "entityIdFilter": "ตัวกรอง ID ของเอนทิตี", + "tableHeader": { + "entityId": "ID ของเอนทิตี", + "action": "การกระทำ", + "version": "เวอร์ชัน", + "value": "ค่า", + "modifiedDate": "วันที่แก้ไข", + "modifiedBy": "ผู้แก้ไข" + }, + "tableBody": { + "field": "ฟิลด์", + "value": "ค่า", + "viewDetails": "ดูรายละเอียดการเปลี่ยนแปลง" + }, + "noDataFound": "ไม่พบข้อมูลตามเงื่อนไขที่กรอง", + "firstAuditEntry": "ไม่มีเวอร์ชันก่อนหน้าสำหรับรายการนี้\nเป็นรายการบันทึกการตรวจสอบครั้งแรกของวัตถุนี้" + }, + "detail": { + "close": "ปิด", + "title": "รายละเอียดการตรวจสอบ", + "action": "มีการดำเนินการ {{action}} กับข้อมูลด้านล่าง", + "old": "ค่าเก่า/ค่าที่ถูกลบ", + "new": "ค่าใหม่/ค่าที่เพิ่ม", + "changedFields": "ฟิลด์ที่เปลี่ยนแปลง", + "allFields": "ฟิลด์ทั้งหมด", + "done": "เสร็จสิ้น" + } + } +} diff --git a/generators/languages/templates/src/main/webapp/i18n/zh-cn/entity-audit.json b/generators/languages/templates/src/main/webapp/i18n/zh-cn/entity-audit.json new file mode 100644 index 0000000..220012a --- /dev/null +++ b/generators/languages/templates/src/main/webapp/i18n/zh-cn/entity-audit.json @@ -0,0 +1,49 @@ +{ + "global": { + "menu": { + "admin": { + "entityAudit": "实体审计" + } + } + }, + "entityAudit": { + "home": { + "title": "实体审计", + "filter": "筛选", + "entityOrTable": "实体/表", + "limitTo": "限制到", + "loadChangeList": "加载变更列表" + }, + "result": { + "showInfo": "{{ entity }} 的最近 {{ limit }} 个变更", + "searchFieldLabel": "筛选:", + "globalFilter": "全局筛选", + "entityIdFilter": "实体ID筛选", + "tableHeader": { + "entityId": "实体ID", + "action": "操作", + "version": "版本", + "value": "值", + "modifiedDate": "修改日期", + "modifiedBy": "修改人" + }, + "tableBody": { + "field": "字段", + "value": "值", + "viewDetails": "查看审计变更详情" + }, + "noDataFound": "未找到符合条件的数据", + "firstAuditEntry": "此条目没有之前的版本。\n这是为此对象捕获的第一个审计条目。" + }, + "detail": { + "close": "关闭", + "title": "审计详情", + "action": "以下数据执行了{{action}}操作", + "old": "旧值/移除的值", + "new": "新值/添加的值", + "changedFields": "更改字段", + "allFields": "所有字段", + "done": "完成" + } + } +} diff --git a/generators/vue-audit/__snapshots__/generator.spec.js.snap b/generators/vue-audit/__snapshots__/generator.spec.js.snap new file mode 100644 index 0000000..258b5d4 --- /dev/null +++ b/generators/vue-audit/__snapshots__/generator.spec.js.snap @@ -0,0 +1,30 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`SubGenerator angular-audit of entity-audit JHipster blueprint > run > should succeed 1`] = ` +{ + ".yo-rc.json": { + "stateCleared": "modified", + }, + "package.json": { + "stateCleared": "modified", + }, + "src/main/webapp/app/admin/entity-audit/entity-audit-event.model.ts": { + "stateCleared": "modified", + }, + "src/main/webapp/app/admin/entity-audit/entity-audit-modal.component.html": { + "stateCleared": "modified", + }, + "src/main/webapp/app/admin/entity-audit/entity-audit-modal.component.ts": { + "stateCleared": "modified", + }, + "src/main/webapp/app/admin/entity-audit/entity-audit.component.html": { + "stateCleared": "modified", + }, + "src/main/webapp/app/admin/entity-audit/entity-audit.component.ts": { + "stateCleared": "modified", + }, + "src/main/webapp/app/admin/entity-audit/entity-audit.service.ts": { + "stateCleared": "modified", + }, +} +`; diff --git a/generators/vue-audit/command.js b/generators/vue-audit/command.js new file mode 100644 index 0000000..ea17f84 --- /dev/null +++ b/generators/vue-audit/command.js @@ -0,0 +1,5 @@ +import { asCommand } from 'generator-jhipster'; + +export default asCommand({ + configs: {}, +}); diff --git a/generators/vue-audit/generator.js b/generators/vue-audit/generator.js new file mode 100644 index 0000000..09e0eec --- /dev/null +++ b/generators/vue-audit/generator.js @@ -0,0 +1,80 @@ +import BaseApplicationGenerator from 'generator-jhipster/generators/base-application'; +import { clientApplicationTemplatesBlock } from 'generator-jhipster/generators/client/support'; + +export default class extends BaseApplicationGenerator { + vueVersion; + + constructor(args, opts, features) { + super(args, opts, { ...features, queueCommandTasks: true }); + } + + async beforeQueue() { + await this.dependsOnJHipster('bootstrap-application'); + } + + get [BaseApplicationGenerator.PREPARING]() { + return this.asPreparingTaskGroup({ + loadDependabot() { + const { + dependencies: { vue: vueVersion }, + } = this.fs.readJSON(this.templatePath('../resources/package.json')); + this.vueVersion = vueVersion; + }, + }); + } + + get [BaseApplicationGenerator.WRITING]() { + return this.asWritingTaskGroup({ + cleanup() { + // 可选清理逻辑 + }, + + writingTemplateTask({ application }) { + return this.writeFiles({ + sections: { + files: [ + { + ...clientApplicationTemplatesBlock('admin/entity-audit/'), + templates: [ + 'entity-audit-event.model.ts', + 'entity-audit-modal.component.vue', + 'entity-audit.component.vue', + 'entity-audit.service.ts', + ], + }, + ], + }, + context: application, + }); + }, + }); + } + + get [BaseApplicationGenerator.POST_WRITING]() { + return this.asPostWritingTaskGroup({ + postWritingTemplateTask({ source }) { + this.packageJson.merge({ + dependencies: { + vue: this.vueVersion, + }, + }); + + if (this.options.skipMenu) return; + + source.addAdminRoute?.({ + route: 'entity-audit', + modulePath: './entity-audit/entity-audit.component.vue', + title: 'entityAudit.home.title', + component: true, + }); + + source.addItemToAdminMenu?.({ + icon: 'list', + route: 'admin/entity-audit', + translationKey: 'global.menu.admin.entityAudit', + name: 'Entity Audit', + }); + }, + }); + } +} diff --git a/generators/vue-audit/index.js b/generators/vue-audit/index.js new file mode 100644 index 0000000..3eccd6e --- /dev/null +++ b/generators/vue-audit/index.js @@ -0,0 +1,2 @@ +export { default } from './generator.js'; +export { default as command } from './command.js'; diff --git a/generators/vue-audit/resources/package.json b/generators/vue-audit/resources/package.json new file mode 100644 index 0000000..46f6165 --- /dev/null +++ b/generators/vue-audit/resources/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "deep-diff": "1.0.2", + "deepmerge": "4.3.1", + "dompurify": "3.2.6", + "vue-diff": "1.2.4" + } +} diff --git a/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit-event.model.ts.ejs b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit-event.model.ts.ejs new file mode 100644 index 0000000..cf17fc1 --- /dev/null +++ b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit-event.model.ts.ejs @@ -0,0 +1,15 @@ +export type EntityAuditEntityChoice = { + name: string; + value: string; +}; + +export type EntityAuditEvent = { + id: number; + entityId: any; + entityType: string; + action: string; + entityValue?: string; + commitVersion?: number; + modifiedBy?: string; + modifiedDate: Date; +}; \ No newline at end of file diff --git a/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit-modal.component.vue.ejs b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit-modal.component.vue.ejs new file mode 100644 index 0000000..31f99e8 --- /dev/null +++ b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit-modal.component.vue.ejs @@ -0,0 +1,202 @@ + + + + + diff --git a/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.component.vue.ejs b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.component.vue.ejs new file mode 100644 index 0000000..bf04a9e --- /dev/null +++ b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.component.vue.ejs @@ -0,0 +1,184 @@ + + + + + diff --git a/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.service.ts.ejs b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.service.ts.ejs new file mode 100644 index 0000000..6d21016 --- /dev/null +++ b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/entity-audit.service.ts.ejs @@ -0,0 +1,19 @@ +import axios from 'axios'; + +class EntityAuditService { + getAllAudited() { + return axios.get('api/audits/entity/all').then(res => res.data); + } + + findByEntity(entity, limit) { + return axios.get(`api/audits/entity/changes?entityType=${entity}&limit=${limit}`).then(res => res.data); + } + + getPrevVersion(qualifiedName, entityId, commitVersion) { + return axios.get( + `api/audits/entity/changes/version/previous?qualifiedName=${qualifiedName}&entityId=${entityId}&commitVersion=${commitVersion}` + ).then(res => res.data); + } +} + +export default EntityAuditService; diff --git a/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/translate-html.vue.ejs b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/translate-html.vue.ejs new file mode 100644 index 0000000..bd79db8 --- /dev/null +++ b/generators/vue-audit/templates/src/main/webapp/app/admin/entity-audit/translate-html.vue.ejs @@ -0,0 +1,90 @@ + + + +