@memberjunction/ng-record-changes 0.9.34 → 0.9.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { EventEmitter, OnInit, Renderer2, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
|
|
2
2
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
3
3
|
import { SortDescriptor } from '@progress/kendo-data-query';
|
|
4
|
+
import { BaseEntity } from '@memberjunction/core';
|
|
4
5
|
import * as i0 from "@angular/core";
|
|
5
6
|
export declare class RecordChangesComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
6
7
|
private sanitizer;
|
|
7
8
|
private renderer;
|
|
8
9
|
showloader: boolean;
|
|
9
10
|
dialogClosed: EventEmitter<any>;
|
|
10
|
-
record:
|
|
11
|
+
record: BaseEntity;
|
|
11
12
|
wrapper: ElementRef;
|
|
12
13
|
viewData: any;
|
|
13
14
|
visibleColumns: any;
|
|
@@ -19,7 +20,13 @@ export declare class RecordChangesComponent implements OnInit, AfterViewInit, On
|
|
|
19
20
|
LoadRecordChanges(recordId: number, appName: string, entityName: string): Promise<void>;
|
|
20
21
|
prepareColumns(): void;
|
|
21
22
|
closePropertiesDialog(): void;
|
|
22
|
-
FormatColumnValue(col: any, value: any, maxLength?: number, trailingChars?: string): any;
|
|
23
|
+
FormatColumnValue(col: any, value: any, dataItem: any, maxLength?: number, trailingChars?: string): any;
|
|
24
|
+
protected fieldMarkup(fieldName: string): string;
|
|
25
|
+
protected valueMarkup(changeInfo: {
|
|
26
|
+
field: string;
|
|
27
|
+
oldValue: any;
|
|
28
|
+
newValue: any;
|
|
29
|
+
}, isOldValue: boolean): string;
|
|
23
30
|
static ɵfac: i0.ɵɵFactoryDeclaration<RecordChangesComponent, never>;
|
|
24
31
|
static ɵcmp: i0.ɵɵComponentDeclaration<RecordChangesComponent, "mj-record-changes", never, { "record": "record"; }, { "dialogClosed": "dialogClosed"; }, never, never, false, never>;
|
|
25
32
|
}
|
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
|
11
|
-
import { LogError, RunView } from '@memberjunction/core';
|
|
11
|
+
import { EntityFieldTSType, LogError, RunView } from '@memberjunction/core';
|
|
12
12
|
import * as i0 from "@angular/core";
|
|
13
13
|
import * as i1 from "@angular/platform-browser";
|
|
14
14
|
import * as i2 from "@angular/common";
|
|
@@ -25,7 +25,7 @@ function RecordChangesComponent_div_5_kendo_grid_column_4_ng_template_1_Template
|
|
|
25
25
|
const dataItem_r8 = ctx.$implicit;
|
|
26
26
|
const item_r5 = i0.ɵɵnextContext().$implicit;
|
|
27
27
|
const ctx_r7 = i0.ɵɵnextContext(2);
|
|
28
|
-
i0.ɵɵproperty("innerHTML", ctx_r7.FormatColumnValue(item_r5, dataItem_r8[item_r5.field]), i0.ɵɵsanitizeHtml);
|
|
28
|
+
i0.ɵɵproperty("innerHTML", ctx_r7.FormatColumnValue(item_r5, dataItem_r8[item_r5.field], dataItem_r8), i0.ɵɵsanitizeHtml);
|
|
29
29
|
} }
|
|
30
30
|
const _c1 = function () { return { "font-weight": "bold", "background-color": "#a9c2af" }; };
|
|
31
31
|
function RecordChangesComponent_div_5_kendo_grid_column_4_Template(rf, ctx) { if (rf & 1) {
|
|
@@ -55,7 +55,6 @@ export class RecordChangesComponent {
|
|
|
55
55
|
this.renderer = renderer;
|
|
56
56
|
this.showloader = false;
|
|
57
57
|
this.dialogClosed = new EventEmitter();
|
|
58
|
-
this.record = {};
|
|
59
58
|
this.viewData = [];
|
|
60
59
|
this.visibleColumns = [];
|
|
61
60
|
this.sortSettings = [
|
|
@@ -102,9 +101,9 @@ export class RecordChangesComponent {
|
|
|
102
101
|
prepareColumns() {
|
|
103
102
|
this.visibleColumns = [{
|
|
104
103
|
field: 'ChangedAt',
|
|
105
|
-
title: '
|
|
104
|
+
title: 'Date',
|
|
106
105
|
type: 'datetime',
|
|
107
|
-
width:
|
|
106
|
+
width: 175,
|
|
108
107
|
},
|
|
109
108
|
{
|
|
110
109
|
field: 'ChangesDescription',
|
|
@@ -115,37 +114,56 @@ export class RecordChangesComponent {
|
|
|
115
114
|
closePropertiesDialog() {
|
|
116
115
|
this.dialogClosed.emit();
|
|
117
116
|
}
|
|
118
|
-
FormatColumnValue(col, value, maxLength = 0, trailingChars = "...") {
|
|
117
|
+
FormatColumnValue(col, value, dataItem, maxLength = 0, trailingChars = "...") {
|
|
119
118
|
if (value === null)
|
|
120
119
|
return null;
|
|
121
120
|
try {
|
|
122
121
|
switch (col.type.toLowerCase()) {
|
|
123
122
|
case 'datetime':
|
|
124
|
-
let
|
|
123
|
+
let utcDate = new Date(value); // UTC date
|
|
124
|
+
// Calculate the local timezone offset and adjust the date
|
|
125
|
+
const localDate = new Date(utcDate.getTime() - utcDate.getTimezoneOffset() * 60000);
|
|
125
126
|
return new Intl.DateTimeFormat('en-US', {
|
|
126
127
|
year: 'numeric',
|
|
127
128
|
month: 'short',
|
|
128
129
|
day: 'numeric',
|
|
129
130
|
hour: 'numeric',
|
|
130
131
|
minute: 'numeric',
|
|
131
|
-
second: 'numeric',
|
|
132
132
|
hour12: true,
|
|
133
|
-
}).format(
|
|
133
|
+
}).format(localDate);
|
|
134
134
|
case 'int':
|
|
135
135
|
return new Intl.NumberFormat(undefined, { minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(value);
|
|
136
136
|
case 'description':
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
// while the database stores a description, it is easier to use the ChangesJSON field to get the structured data and then generate our HTML
|
|
138
|
+
const json = JSON.parse(dataItem.ChangesJSON);
|
|
139
|
+
if (!json)
|
|
140
|
+
return value;
|
|
141
|
+
else {
|
|
142
|
+
const fields = Object.keys(json); // each field that was changed is a key in the JSON object
|
|
143
|
+
let formattedDescription = '<div>';
|
|
144
|
+
for (let i = 0; i < fields.length; i++) {
|
|
145
|
+
const changeInfo = json[fields[i]];
|
|
146
|
+
const field = this.record.EntityInfo.Fields.find((f) => { var _a; return f.Name.trim().toLowerCase() === ((_a = changeInfo.field) === null || _a === void 0 ? void 0 : _a.trim().toLowerCase()); });
|
|
147
|
+
let innerDescription = "";
|
|
148
|
+
if (field) {
|
|
149
|
+
// we have field metadata, so we can use that
|
|
150
|
+
if (field.TSType === EntityFieldTSType.Boolean) {
|
|
151
|
+
// for boolean fields, it is cleaner to just show new value, no need to show old value as it is always the opposite
|
|
152
|
+
innerDescription = `${this.fieldMarkup(field.DisplayNameOrName)} set to ${this.valueMarkup(changeInfo, false)}`;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
innerDescription = `${this.fieldMarkup(field.DisplayNameOrName)} changed from ${this.valueMarkup(changeInfo, true)} to ${this.valueMarkup(changeInfo, false)}`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// we don't have field metadata - this could happen if a field was removed or renamed after a record change was recorded in the database, so just use what we have
|
|
160
|
+
innerDescription = `${this.fieldMarkup(changeInfo.field)} changed from ${this.valueMarkup(changeInfo, true)}} to ${this.valueMarkup(changeInfo, false)}`;
|
|
161
|
+
}
|
|
162
|
+
formattedDescription += `<div>${innerDescription}</div>`;
|
|
163
|
+
}
|
|
164
|
+
formattedDescription += '</div>';
|
|
165
|
+
return this.sanitizer.bypassSecurityTrustHtml(formattedDescription);
|
|
146
166
|
}
|
|
147
|
-
formattedDescription += '</ul>';
|
|
148
|
-
return this.sanitizer.bypassSecurityTrustHtml(formattedDescription);
|
|
149
167
|
default:
|
|
150
168
|
return value;
|
|
151
169
|
}
|
|
@@ -155,6 +173,12 @@ export class RecordChangesComponent {
|
|
|
155
173
|
return value;
|
|
156
174
|
}
|
|
157
175
|
}
|
|
176
|
+
fieldMarkup(fieldName) {
|
|
177
|
+
return `<b>${fieldName}</b>`;
|
|
178
|
+
}
|
|
179
|
+
valueMarkup(changeInfo, isOldValue) {
|
|
180
|
+
return `<span style="color: ${isOldValue ? 'darkgray' : 'blue'};">${isOldValue ? changeInfo.oldValue : changeInfo.newValue}</span>`;
|
|
181
|
+
}
|
|
158
182
|
}
|
|
159
183
|
RecordChangesComponent.ɵfac = function RecordChangesComponent_Factory(t) { return new (t || RecordChangesComponent)(i0.ɵɵdirectiveInject(i1.DomSanitizer), i0.ɵɵdirectiveInject(i0.Renderer2)); };
|
|
160
184
|
RecordChangesComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: RecordChangesComponent, selectors: [["mj-record-changes"]], viewQuery: function RecordChangesComponent_Query(rf, ctx) { if (rf & 1) {
|
|
@@ -180,7 +204,7 @@ RecordChangesComponent.ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: Reco
|
|
|
180
204
|
} }, dependencies: [i2.NgForOf, i2.NgIf, i3.GridComponent, i3.DataBindingDirective, i3.ColumnComponent, i3.CellTemplateDirective, i4.WindowComponent, i5.LoaderComponent] });
|
|
181
205
|
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(RecordChangesComponent, [{
|
|
182
206
|
type: Component,
|
|
183
|
-
args: [{ selector: 'mj-record-changes', template: "<div #recordChangesWrapper>\r\n <div class=\"k-overlay\"></div>\r\n <kendo-window \r\n class=\"kendo-window-custom\"\r\n [width]=\"700\"\r\n [height]=\"525\"\r\n [minHeight]=\"300\"\r\n [minWidth]=\"400\"\r\n [resizable]=\"true\"\r\n title=\"Record Changes\"\r\n (close)=\"closePropertiesDialog()\"\r\n >\r\n <kendo-loader *ngIf=\"showloader\" type=\"converging-spinner\" ></kendo-loader>\r\n <div class=\"k-d-flex k-flex-col k-justify-content-between k-h-full\" #dialogContainer *ngIf=\"!showloader\">\r\n <div class=\"kendo-grid-container\">\r\n <kendo-grid \r\n [kendoGridBinding]=\"viewData\" \r\n scrollable=\"virtual\" \r\n [pageSize]=\"100\" \r\n [sortable]=\"true\"\r\n [sort]=\"sortSettings\" \r\n [loading]=\"showloader\" \r\n [resizable]=\"true\" \r\n [navigable]=\"true\"\r\n >\r\n <kendo-grid-column \r\n *ngFor=\"let item of visibleColumns; let i = index\" \r\n field=\"{{item.field}}\"\r\n title=\"{{item.title}}\" \r\n [width]=\"item.width\"\r\n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': '#a9c2af' }\"\r\n >\r\n <ng-template kendoGridCellTemplate let-dataItem>\r\n <span [innerHTML]=\"FormatColumnValue(item, dataItem[item.field])\"></span>\r\n </ng-template>\r\n </kendo-grid-column>\r\n </kendo-grid>\r\n </div>\r\n </div>\r\n </kendo-window>\r\n</div>" }]
|
|
207
|
+
args: [{ selector: 'mj-record-changes', template: "<div #recordChangesWrapper>\r\n <div class=\"k-overlay\"></div>\r\n <kendo-window \r\n class=\"kendo-window-custom\"\r\n [width]=\"700\"\r\n [height]=\"525\"\r\n [minHeight]=\"300\"\r\n [minWidth]=\"400\"\r\n [resizable]=\"true\"\r\n title=\"Record Changes\"\r\n (close)=\"closePropertiesDialog()\"\r\n >\r\n <kendo-loader *ngIf=\"showloader\" type=\"converging-spinner\" ></kendo-loader>\r\n <div class=\"k-d-flex k-flex-col k-justify-content-between k-h-full\" #dialogContainer *ngIf=\"!showloader\">\r\n <div class=\"kendo-grid-container\">\r\n <kendo-grid \r\n [kendoGridBinding]=\"viewData\" \r\n scrollable=\"virtual\" \r\n [pageSize]=\"100\" \r\n [sortable]=\"true\"\r\n [sort]=\"sortSettings\" \r\n [loading]=\"showloader\" \r\n [resizable]=\"true\" \r\n [navigable]=\"true\"\r\n >\r\n <kendo-grid-column \r\n *ngFor=\"let item of visibleColumns; let i = index\" \r\n field=\"{{item.field}}\"\r\n title=\"{{item.title}}\" \r\n [width]=\"item.width\"\r\n [headerStyle]=\"{ 'font-weight' : 'bold', 'background-color': '#a9c2af' }\"\r\n >\r\n <ng-template kendoGridCellTemplate let-dataItem>\r\n <span [innerHTML]=\"FormatColumnValue(item, dataItem[item.field], dataItem)\"></span>\r\n </ng-template>\r\n </kendo-grid-column>\r\n </kendo-grid>\r\n </div>\r\n </div>\r\n </kendo-window>\r\n</div>" }]
|
|
184
208
|
}], function () { return [{ type: i1.DomSanitizer }, { type: i0.Renderer2 }]; }, { dialogClosed: [{
|
|
185
209
|
type: Output
|
|
186
210
|
}], record: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-record-changes",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.36",
|
|
4
4
|
"description": "MemberJunction: Angular pop-up window and grid to show changes made to a specific individual record",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"@progress/kendo-angular-grid": "^12.1.0"
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
|
-
"@memberjunction/core": "^0.9.
|
|
30
|
-
"@memberjunction/global": "^0.9.
|
|
29
|
+
"@memberjunction/core": "^0.9.99",
|
|
30
|
+
"@memberjunction/global": "^0.9.101",
|
|
31
31
|
"@memberjunction/ng-compare-records": "^0.9.69",
|
|
32
32
|
"@memberjunction/ng-container-directives": "^0.9.45",
|
|
33
33
|
"tslib": "^2.3.0"
|