ng-kinintel 20.0.2 → 20.0.4
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.
- package/fesm2022/ng-kinintel.mjs +25 -3
- package/fesm2022/ng-kinintel.mjs.map +1 -1
- package/index.d.ts +2 -0
- package/package.json +1 -1
package/fesm2022/ng-kinintel.mjs
CHANGED
|
@@ -2557,6 +2557,7 @@ class DatasetEditorComponent {
|
|
|
2557
2557
|
this.decodeURI = decodeURI;
|
|
2558
2558
|
this.ENTER = ENTER;
|
|
2559
2559
|
this.COMMA = COMMA;
|
|
2560
|
+
this.JSON = JSON;
|
|
2560
2561
|
}
|
|
2561
2562
|
async ngOnInit() {
|
|
2562
2563
|
let limit = null;
|
|
@@ -3163,6 +3164,22 @@ class DatasetEditorComponent {
|
|
|
3163
3164
|
});
|
|
3164
3165
|
}
|
|
3165
3166
|
}
|
|
3167
|
+
toJSON(data) {
|
|
3168
|
+
const jsonStrings = [];
|
|
3169
|
+
Object.keys(data).forEach(key => {
|
|
3170
|
+
if (_$s.isPlainObject(data[key])) {
|
|
3171
|
+
const keyStrings = [];
|
|
3172
|
+
Object.keys(data[key]).forEach(itemKey => {
|
|
3173
|
+
keyStrings.push('<b>' + itemKey + '</b>' + ': ' + data[key][itemKey]);
|
|
3174
|
+
});
|
|
3175
|
+
jsonStrings.push('<b>' + key + '</b>' + ': ' + keyStrings.join(', '));
|
|
3176
|
+
}
|
|
3177
|
+
else {
|
|
3178
|
+
jsonStrings.push('<b>' + key + '</b>' + ': ' + data[key]);
|
|
3179
|
+
}
|
|
3180
|
+
});
|
|
3181
|
+
return jsonStrings.join(', ');
|
|
3182
|
+
}
|
|
3166
3183
|
getOrdinal(n) {
|
|
3167
3184
|
const s = ['th', 'st', 'nd', 'rd'];
|
|
3168
3185
|
const v = n % 100;
|
|
@@ -3554,11 +3571,11 @@ class DatasetEditorComponent {
|
|
|
3554
3571
|
return clonedDatasetInstance;
|
|
3555
3572
|
}
|
|
3556
3573
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatasetEditorComponent, deps: [{ token: i1$1.MatDialogRef }, { token: MAT_DIALOG_DATA }, { token: i1$1.MatDialog }, { token: DatasetService }, { token: i3.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3557
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DatasetEditorComponent, isStandalone: false, selector: "ki-dataset-editor", inputs: { datasetInstanceSummary: "datasetInstanceSummary", environment: "environment", admin: "admin", dashboardParameters: "dashboardParameters", dashboardLayoutSettings: "dashboardLayoutSettings", accountId: "accountId", newTitle: "newTitle", newDescription: "newDescription", datasetEditorReadonly: "datasetEditorReadonly", datasetEditorSimpleMode: "datasetEditorSimpleMode", datasetEditorNoTools: "datasetEditorNoTools" }, outputs: { dataLoaded: "dataLoaded", datasetInstanceSummaryChange: "datasetInstanceSummaryChange" }, ngImport: i0, template: "@if (longRunning) {\n <div class=\"long-running flex-col\">\n <div class=\"loading-box\">\n <mat-spinner [diameter]=\"150\"></mat-spinner>\n <div>Loading</div>\n </div>\n <p class=\"text-center\">Please wait while we process this query.</p>\n <p class=\"text-center\">The results will be shown here once it has finished running.</p>\n <div>\n <a class=\"text-primary hover:underline\" (click)=\"cancelEvaluate()\">Cancel query and return to editor.</a>\n </div>\n </div>\n}\n<div class=\"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 -z-10\" id=\"sidebarWrapper\">\n <div [class]=\"{'translate-x-0': sideOpen, 'translate-x-full': !sideOpen}\"\n (click)=\"$event.stopPropagation()\"\n class=\"pointer-events-auto w-screen max-w-md transform transition ease-in-out duration-500 sm:duration-700\"\n id=\"docSidebar\">\n <div class=\"flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl\">\n <div class=\"px-4 sm:px-6\">\n <div class=\"flex items-start justify-between\">\n <div></div>\n\n <div class=\"ml-3 flex h-7 items-center\">\n <button type=\"button\" (click)=\"openSide.next(false)\"\n class=\"rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none\">\n <span class=\"sr-only\">Close panel</span>\n <!-- Heroicon name: outline/x -->\n <svg class=\"h-6 w-6\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div class=\"relative flex-1 px-4 sm:px-6\">\n <ki-whitelisted-sql-functions [fields]=\"filterFields\"></ki-whitelisted-sql-functions>\n </div>\n </div>\n </div>\n</div>\n\n@if (!datasetEditorNoTools) {\n <div class=\"border-b cell-header end\">\n <div class=\"leading-5 px-4 text-xs uppercase tracking-wider font-medium border-r-2 text-gray-600\">\n Operations\n </div>\n <div class=\"dataset-data-actions\">\n <button (click)=\"addFilter()\"\n title=\"Filter the set using column based restrictions\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">filter_alt</span>\n filter\n </button>\n <button (click)=\"summariseData()\"\n title=\"Summarise this data to produce aggregated totals, sums and other derivations\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">pivot_table_chart</span>\n summarise\n </button>\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"joinData()\"\n title=\"Join another data set to the current dataset\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n join\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"createFormula()\"\n title=\"Create a formula column using an expression based on other columns\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">functions</span>\n formula\n </button>\n <button (click)=\"editColumnSettings()\"\n title=\"Switch on and off columns for display\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">table_chart</span>\n columns\n </button>\n @if (!datasetEditorSimpleMode) {\n <div class=\"divider\"></div>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addParameter()\"\n title=\"Add a parameter to use in filters, expressions etc.\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">text_fields</span>\n parameters\n </button>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addPagingMarker()\"\n title=\"Insert paging marker to limit results at this stage in the query flow\"\n class=\"w-24 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">skip_next</span>\n paging marker\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"evaluateDataset()\"\n title=\"Reload this query based upon changes you may have made\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">sync</span>\n reload\n </button>\n @if (!datasetEditorReadonly) {\n <button [disabled]=\"!datasetInstanceSummary || !datasetInstanceSummary.id\" (click)=\"shareQuery()\"\n title=\"Share this query with other account holders\"\n class=\"disabled:opacity-50 w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">share</span>\n share\n </button>\n <button (click)=\"saveAsQuery()\"\n title=\"Make a copy of this query\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">file_copy</span>\n copy query\n </button>\n @if (!dashboardLayoutSettings && datasetInstanceSummary.id) {\n <button (click)=\"save()\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">save</span>\n save\n </button>\n }\n }\n </div>\n </div>\n}\n\n<div class=\"cell-header\">\n @if (showParameters || parameterValues.length) {\n <div class=\"transformation-listing parameter-listing\">\n <div class=\"list-title\">\n Parameters\n </div>\n <div class=\"flex items-center flex-wrap\">\n @for (parameter of parameterValues; track parameter; let i = $index) {\n <label class=\"pl-4\">\n {{ parameter.title }}\n @if ((parameter.value || '').toString().includes('}}')) {\n <div>\n <mat-chip class=\"bg-gray-50 ml-2\" title=\"Using parameter value from {{parameter.value}}\">\n <div class=\"flex items-center\">\n <span class=\"material-symbols-outlined text-xl mr-1 text-gray-500\">layers</span>\n @if (dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n [innerHTML]=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')].value\"></span>\n }\n @if (!dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n class=\"font-medium text-orange-600\">\n Parameter Not Found !\n </span>\n }\n </div>\n <button matChipRemove (click)=\"parameter.value = ''\" title=\"\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n </div>\n }\n @if (!(parameter.value || '').toString().includes('}}')) {\n <div class=\"parameter-input\">\n @if (!parameter.multiple) {\n @if (parameter.type === 'text') {\n <input class=\"pr-8\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" [(ngModel)]=\"parameter.value\"\n (change)=\"evaluateDataset(true)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n @if (parameter.type === 'date' || parameter.type === 'datetime') {\n @if (!parameter._dateType) {\n <div class=\"flex items-center mr-8\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n }\n @if (parameter._dateType === 'picker') {\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\"\n placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n }\n @if (parameter._dateType === 'period') {\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n <div>Ago</div>\n </div>\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n }\n }\n @if (parameter.type === 'boolean') {\n <mat-slide-toggle class=\"pr-8\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n }\n }\n @if (parameter.multiple) {\n <mat-chip-grid class=\"pl-2\" #chipGrid aria-label=\"Enter values\">\n @for (paramValue of parameter.value; track paramValue) {\n <mat-chip-row\n class=\"bg-white mr-2\"\n (removed)=\"removeParameterValue(parameter, paramValue)\">\n {{paramValue}}\n <button matChipRemove [attr.aria-label]=\"'remove ' + paramValue\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n @if (parameter.type === 'text') {\n <input class=\"pr-8 py-1 self-center\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" matNativeControl\n (change)=\"addParameterValue(parameter, $event)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n </mat-chip-grid>\n }\n @if (!parameter._locked) {\n <button mat-icon-button [matMenuTriggerFor]=\"paramMenu\">\n <mat-icon>settings</mat-icon>\n </button>\n <mat-menu #paramMenu=\"matMenu\">\n <button mat-menu-item (click)=\"addParameter(parameter, i)\">Edit Parameter</button>\n <button mat-menu-item (click)=\"removeParameter(parameter)\">Remove Parameter</button>\n </mat-menu>\n }\n @if (Object.keys(dashboardParameters || {}).length) {\n <button mat-icon-button [matMenuTriggerFor]=\"dashParamMenu\"\n title=\"Bind this parameter value to another\">\n <mat-icon>text_fields</mat-icon>\n </button>\n <mat-menu #dashParamMenu=\"matMenu\">\n @for (dashParamKey of Object.keys(dashboardParameters); track dashParamKey) {\n <button mat-menu-item\n (click)=\"setDashboardParameter(parameter, dashboardParameters[dashParamKey].name)\">{{ dashboardParameters[dashParamKey].title }}\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </label>\n @if (parameterValues.length) {\n <div class=\"divider ml-2\"></div>\n }\n }\n <button mat-icon-button color=\"primary\" class=\"mx-2\" (click)=\"addParameter()\">\n <mat-icon>add_circle</mat-icon>\n </button>\n @if (parameterValues.length) {\n <button type=\"button\" (click)=\"evaluateDataset(true)\"\n class=\"mr-2 flex items-center whitespace-nowrap justify-center px-4 py-1 border border-transparent text-sm rounded-md shadow-sm text-white bg-primary focus:outline-none\">\n Apply Parameters\n </button>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"cell-header\">\n @if (terminatingTransformations.length) {\n <div class=\"transformation-listing py-2\">\n <div class=\"list-title\">\n Transformations\n </div>\n <div class=\"example-list flex flex-wrap\" cdkDropListGroup>\n @for (transformation of terminatingTransformations; track transformation; let i = $index) {\n @if (!transformation.hidden) {\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"{item:transformation,index:i}\">\n <div class=\"flex items-center\">\n <div class=\"new-transformation flex items-center justify-center w-6 h-6\">\n <a [matMenuTriggerFor]=\"addTransformation\"\n class=\"items-center add-transformation text-primary\">\n <mat-icon class=\"flex items-center w-5 h-5 text-xl\">add_circle</mat-icon>\n </a>\n <mat-menu #addTransformation=\"matMenu\">\n <button mat-menu-item (click)=\"insertTransformation(i, 'columns', transformation)\">\n Insert Column Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'formula', transformation)\">\n Insert Formula Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'join', transformation)\">\n Insert Join Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'summarise', transformation)\">\n Insert Summarise Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'filter', transformation)\">\n Insert Filter Transformation\n </button>\n </mat-menu>\n </div>\n <div cdkDrag class=\"pl-0 example-box badge-item w-auto m-0\" cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n [class]=\"{active: transformation._active, 'exclude bg-orange-50 border-orange-200': !!transformation.exclude, 'bg-indigo-50 border-indigo-200': (transformation.type === 'filter' && transformation.hide === false)}\">\n <button class=\"-mt-0.5\" title=\"Show transformation details\" mat-icon-button\n (click)=\"showTransformationDetail(transformation)\">\n @if (transformation.type === 'columns') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >table_chart</span>\n }\n @if (transformation.type === 'formula') {\n <span class=\"material-symbols-outlined text-xl\"\n >functions</span>\n }\n @if (transformation.type === 'join') {\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n }\n @if (transformation.type === 'summarise') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >pivot_table_chart</span>\n }\n @if (transformation.type === 'filter') {\n <span class=\"material-symbols-outlined text-xl\"\n >filter_alt</span>\n }\n </button>\n <span class=\"whitespace-nowrap cursor-pointer\"\n (click)=\"editTerminatingTransformation(transformation)\">{{ transformation._label }}</span>\n @if (transformation.exclude) {\n <button class=\"-ml-1\" [title]=\"'Re-enable this transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon class=\"text-orange-400\">replay</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 === terminatingTransformations.length) {\n <button class=\"-ml-1\" [title]=\"'Disable transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon>block</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 !== terminatingTransformations.length) {\n <button class=\"-ml-1\" [matMenuTriggerFor]=\"disableMenu\"\n [title]=\"'Disable transformation'\"\n mat-icon-button>\n <mat-icon>block</mat-icon>\n </button>\n <mat-menu #disableMenu=\"matMenu\">\n <button mat-menu-item (click)=\"disableTransformation(transformation, i)\">\n Disable this transformation\n </button>\n <button mat-menu-item (click)=\"excludeUpstreamTransformations(transformation)\">\n Disable subsequent transformation(s)\n </button>\n </mat-menu>\n }\n <button class=\"-ml-1\" title=\"Remove this transformation\" mat-icon-button color=\"primary\"\n (click)=\"removeTransformation(transformation, true, null, transformation._active)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"transformation._showDetail\">\n <div class=\"p-4 w-96 bg-white shadow rounded\">\n @if (transformation.type === 'summarise') {\n <p class=\"text-sm text-gray-700 mb-0\">\n <b>SELECT </b>@for (expression of transformation.config.expressions; track expression; let i = $index) {\n <span\n >@if (i > 0) {\n <span\n >, </span>\n }{{ expression.customExpression || expression.expressionType + '(' + (expression.fieldName || '') + ')' }}</span>\n }\n @if (transformation.config.summariseFieldNames.length) {\n <br><b>GROUP\n BY </b> {{ transformation.config.summariseFieldNames.join(', ') }}\n }\n </p>\n }\n @if (transformation.type === 'formula') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>EXPRESSION</b> {{ decodeURIComponent(transformation.config.expressions[0].expression) }}\n </div>\n }\n @if (transformation.type === 'columns') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>COLUMNS</b> {{ _.map(transformation.config.columns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'join') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>JOIN\n COLUMNS</b> {{ _.map(transformation.config.joinColumns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'filter') {\n @for (filter of transformation.config.filters; track filter) {\n <div\n class=\"text-sm text-gray-700 mb-0\">\n <b>FILTER</b> {{ filter.lhsExpression }} <b>{{ filter.filterType }}</b> {{ filter.rhsExpression }}\n </div>\n }\n }\n </div>\n </ng-template>\n </div>\n </div>\n }\n @if (_.some(terminatingTransformations, {exclude: true}) && i === terminatingTransformations.length - 1) {\n <button\n class=\"ml-4 flex items-center border-none bg-primary text-sm rounded-md text-white pr-2 pl-1 py-0.5\"\n (click)=\"enableAllTransformation()\">\n <mat-icon class=\"mr-1 text-base\">replay</mat-icon>\n Enable All\n </button>\n }\n }\n </div>\n</div>\n}\n</div>\n\n<div class=\"cell-header\">\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <div class=\"transformation-listing py-2 filters-list\"\n >\n <a class=\"list-title flex items-center\" (click)=\"showFilters = !showFilters\">\n Filters \n @if (!showFilters) {\n <mat-icon>expand_more</mat-icon>\n }\n @if (showFilters) {\n <mat-icon>expand_less</mat-icon>\n }\n </a>\n @for (filterTransformation of _.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}); track filterTransformation) {\n @if (_.every(filterTransformation.config.filters[0])) {\n <div class=\"badge-item pl-2 mr-1\"\n (click)=\"showFilters = !showFilters\">\n <span class=\"cursor-pointer\" [innerHtml]=\"getFilterString(filterTransformation.config)\"></span>\n </div>\n }\n }\n </div>\n }\n</div>\n\n@if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\n && showFilters) {\n <div class=\"dataset-filters\" id=\"datasetFilters\"\n >\n @for (transformation of datasetInstanceSummary.transformationInstances; track transformation; let i = $index) {\n @if (transformation.type === 'filter' && transformation.hide === false) {\n <div class=\"dataset-filter border-b border-gray-200\">\n <button mat-stroked-button class=\"mr-2 bg-white remove-filter\" color=\"warn\"\n (click)=\"removeTransformation(transformation, true, i)\">\n Remove Filter\n </button>\n @if (filterFields.length) {\n <ki-dataset-filters [filterFields]=\"filterFields\"\n [openSide]=\"openSide\" [parameterValues]=\"filterParameterValues\"\n [filterJunction]=\"transformation.config\"></ki-dataset-filters>\n }\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <button\n mat-flat-button class=\"apply-filter mr-2\" color=\"primary\"\n (click)=\"applyFilters()\" [disabled]=\"!filterJunction.filters.length\">\n Apply Filters\n </button>\n }\n </div>\n }\n }\n </div>\n}\n\n<div class=\"cell-header\">\n @if (_.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'})) {\n <div class=\"transformation-listing sort\"\n >\n <div class=\"list-title\">\n Sort\n </div>\n <div class=\"flex flex-wrap\">\n @for (sort of _.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'}).config.sorts; track sort; let i = $index) {\n <div class=\"badge-item outline\"\n [class]=\"{'exclude bg-orange-50 border-orange-200': _.find(datasetInstanceSummary.transformationInstances, {exclude: true})}\"\n >\n <span>{{ _.startCase(sort.fieldName) }} <span class=\"uppercase\">{{ sort.direction }}</span></span>\n <button mat-icon-button (click)=\"removeFilter(i)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"h-full table-overflow overflow-scroll\">\n @if (displayedColumns.length) {\n <table mat-table [dataSource]=\"tableData\" matSort (matSortChange)=\"sort($event)\"\n class=\"block sticky\">\n @for (column of filterFields; track column) {\n <ng-container [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header\n class=\"text-xs font-semibold text-gray-900 py-3.5 px-4\"> {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"py-3 px-4\">\n @if (!Array.isArray(element[column.name]) && !_.isPlainObject(element[column.name])) {\n @if (element[column.name] && String(element[column.name]).length <= 100) {\n <div [innerHTML]=\"element[column.name]\"></div>\n }\n @if (element[column.name] && String(element[column.name]).length > 100) {\n <div>{{ element[column.name].substring(0, 100) + '...' }}</div>\n <a (click)=\"viewFullItemData(element[column.name], column.name)\"\n class=\"flex items-center text-sm text-cta\">\n view more\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"ml-1 h-4 w-4\" fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"/>\n </svg>\n </a>\n }\n @if (!element[column.name]) {\n @if (element[column.name] === null) {\n <span class=\"font-mono text-gray-400\">null</span>\n }\n @if (element[column.name] !== null) {\n <span>{{ element[column.name] }}</span>\n }\n }\n }\n @if (Array.isArray(element[column.name])) {\n Contains {{ element[column.name].length }} items\n }\n @if (_.isPlainObject(element[column.name])) {\n Object has {{ Object.keys(element[column.name]).length }} keys\n }\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\" class=\"h-auto\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n }\n</div>\n\n\n<div class=\"border-b border-t bg-gray-50 px-4 py-1 flex align-center justify-end\">\n\n <div class=\"flex items-center\">\n <div class=\"text-sm text-gray-500 mr-10\">\n @if (dataset) {\n Showing {{ offset + 1 }} - {{ (page * limit) - (limit - tableData.length) }}\n }\n </div>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"mr-8 p-1.5\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button class=\"mr-4\" (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:column;position:relative;height:100%}:host>div{flex:0 1 auto}.divider{width:1px;height:17px;background-color:#cecece}.new-transformation .add-transformation{display:none}.new-transformation:hover .add-transformation{display:flex}.long-running{position:fixed;inset:0;background-color:#ffffffb3;z-index:99999;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.long-running .loading-box{position:relative;margin-bottom:2rem}.long-running .loading-box div{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.2rem;font-weight:500}.long-running p{font-size:1.1rem}.cell-header{width:100%;display:flex;align-items:center;justify-content:space-between}.cell-header.end{justify-content:flex-end}.cell-header.sorting{min-height:43px}.dataset-data-actions{display:flex;align-items:center;flex-wrap:wrap;width:100%;justify-content:flex-end;background-color:#fff;margin-top:-1px}.dataset-data-actions button{min-width:50px;padding:0 13px;color:#505050}.dataset-data-actions .divider{margin:0 .5rem;width:1px;height:36px;background-color:#ddd}.parameter-listing label{flex-direction:row;align-items:center}.parameter-listing label .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}.parameter-listing label .parameter-input .param-period-picker{padding:5px}.parameter-listing label .parameter-input button{color:#8e8e8e}.parameter-listing label .parameter-input button.edit-parameter{visibility:hidden}.parameter-listing label .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}.parameter-listing label .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.parameter-listing label .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}.parameter-listing label .parameter-input:hover .edit-parameter{visibility:visible}.transformation-listing{display:flex;align-items:center;width:100%;background-color:#00000012;border-bottom:1px solid #ddd;min-height:47px}.transformation-listing .list-title{text-transform:uppercase;font-size:.75rem;padding:0 1rem;border-right:2px solid #ddd;color:#4c4c4c;font-weight:500;letter-spacing:1px}.transformation-listing .badge-item{display:flex;align-items:center;margin-left:1rem;padding-left:1rem;border-radius:20px;background-color:#fff;border:1px solid #ddd;height:30px}.transformation-listing .badge-item.exclude{opacity:.8}.transformation-listing .badge-item:hover{background-color:#fcfcfc}.transformation-listing .badge-item span{margin-right:.5rem;color:#0000008a}.transformation-listing .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.transformation-listing .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}.dataset-filters{position:relative;overflow-y:scroll;flex:none!important;max-height:400px}.dataset-filters .dataset-filter{position:relative}.dataset-filters .dataset-filter .apply-filter{position:absolute;bottom:.5rem;right:0;z-index:10}.dataset-filters .dataset-filter .remove-filter{position:absolute;top:.5rem;right:0;z-index:10}.badge-holder{display:flex;align-items:center;margin:.25rem 0}.badge-holder .badge-item{display:flex;align-items:center;padding-left:1rem;border-radius:20px}.badge-holder .badge-item.outline{background-color:#fff;border:1px solid #efefef}.badge-holder .badge-item span{margin-right:.5rem;color:#0000008a}.badge-holder .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.badge-holder .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}table{position:relative;border-collapse:collapse}table.sticky th{position:sticky;top:0;background-color:#f5f5f5;border-top:none!important;border-bottom:none!important;box-shadow:inset 0 -1px #ddd}table th.settings{padding:0}table td{max-width:400px;word-wrap:break-word;padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;min-width:150px;width:1%}table td.settings{max-width:25px;min-width:25px}table::-webkit-scrollbar{width:.75em;background:transparent}table::-webkit-scrollbar-thumb{background:#d2d2d2}table tbody:nth-of-type(1) tr:nth-of-type(1) td{border-top:none!important}table thead th{border-top:none!important;border-bottom:none!important;box-shadow:inset 0 2px #000,inset 0 -2px #000;padding:2px 0}table thead th{background-clip:padding-box}.table-overflow::-webkit-scrollbar{width:.75em;background:transparent}.table-overflow::-webkit-scrollbar-thumb{background:#d2d2d2}.paging-toolbar{position:sticky;bottom:-20px;left:0;background-color:#fff;right:0;padding:1rem}table{text-align:left;position:relative;border-collapse:collapse}th,td{padding:.25rem}\n"], dependencies: [{ kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i7$4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i7$3.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i7$3.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i7$3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i7$3.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i7$3.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "component", type: i9$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i10.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i6.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i6.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i6.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i7.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i7.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i14.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i12$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i16.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i16.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "component", type: DatasetFiltersComponent, selector: "ki-dataset-filters", inputs: ["filterJunction", "filterFields", "joinFilterFields", "joinFieldsName", "openSide", "parameterValues"] }, { kind: "component", type: WhitelistedSqlFunctionsComponent, selector: "ki-whitelisted-sql-functions", inputs: ["search", "fields"] }] }); }
|
|
3574
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: DatasetEditorComponent, isStandalone: false, selector: "ki-dataset-editor", inputs: { datasetInstanceSummary: "datasetInstanceSummary", environment: "environment", admin: "admin", dashboardParameters: "dashboardParameters", dashboardLayoutSettings: "dashboardLayoutSettings", accountId: "accountId", newTitle: "newTitle", newDescription: "newDescription", datasetEditorReadonly: "datasetEditorReadonly", datasetEditorSimpleMode: "datasetEditorSimpleMode", datasetEditorNoTools: "datasetEditorNoTools" }, outputs: { dataLoaded: "dataLoaded", datasetInstanceSummaryChange: "datasetInstanceSummaryChange" }, ngImport: i0, template: "@if (longRunning) {\n <div class=\"long-running flex-col\">\n <div class=\"loading-box\">\n <mat-spinner [diameter]=\"150\"></mat-spinner>\n <div>Loading</div>\n </div>\n <p class=\"text-center\">Please wait while we process this query.</p>\n <p class=\"text-center\">The results will be shown here once it has finished running.</p>\n <div>\n <a class=\"text-primary hover:underline\" (click)=\"cancelEvaluate()\">Cancel query and return to editor.</a>\n </div>\n </div>\n}\n<div class=\"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 -z-10\" id=\"sidebarWrapper\">\n <div [class]=\"{'translate-x-0': sideOpen, 'translate-x-full': !sideOpen}\"\n (click)=\"$event.stopPropagation()\"\n class=\"pointer-events-auto w-screen max-w-md transform transition ease-in-out duration-500 sm:duration-700\"\n id=\"docSidebar\">\n <div class=\"flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl\">\n <div class=\"px-4 sm:px-6\">\n <div class=\"flex items-start justify-between\">\n <div></div>\n\n <div class=\"ml-3 flex h-7 items-center\">\n <button type=\"button\" (click)=\"openSide.next(false)\"\n class=\"rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none\">\n <span class=\"sr-only\">Close panel</span>\n <!-- Heroicon name: outline/x -->\n <svg class=\"h-6 w-6\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div class=\"relative flex-1 px-4 sm:px-6\">\n <ki-whitelisted-sql-functions [fields]=\"filterFields\"></ki-whitelisted-sql-functions>\n </div>\n </div>\n </div>\n</div>\n\n@if (!datasetEditorNoTools) {\n <div class=\"border-b cell-header end\">\n <div class=\"leading-5 px-4 text-xs uppercase tracking-wider font-medium border-r-2 text-gray-600\">\n Operations\n </div>\n <div class=\"dataset-data-actions\">\n <button (click)=\"addFilter()\"\n title=\"Filter the set using column based restrictions\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">filter_alt</span>\n filter\n </button>\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"summariseData()\"\n title=\"Summarise this data to produce aggregated totals, sums and other derivations\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">pivot_table_chart</span>\n summarise\n </button>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"joinData()\"\n title=\"Join another data set to the current dataset\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n join\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"createFormula()\"\n title=\"Create a formula column using an expression based on other columns\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">functions</span>\n formula\n </button>\n <button (click)=\"editColumnSettings()\"\n title=\"Switch on and off columns for display\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">table_chart</span>\n columns\n </button>\n @if (!datasetEditorSimpleMode) {\n <div class=\"divider\"></div>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addParameter()\"\n title=\"Add a parameter to use in filters, expressions etc.\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">text_fields</span>\n parameters\n </button>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addPagingMarker()\"\n title=\"Insert paging marker to limit results at this stage in the query flow\"\n class=\"w-24 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">skip_next</span>\n paging marker\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"evaluateDataset()\"\n title=\"Reload this query based upon changes you may have made\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">sync</span>\n reload\n </button>\n @if (!datasetEditorReadonly) {\n <button [disabled]=\"!datasetInstanceSummary || !datasetInstanceSummary.id\" (click)=\"shareQuery()\"\n title=\"Share this query with other account holders\"\n class=\"disabled:opacity-50 w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">share</span>\n share\n </button>\n <button (click)=\"saveAsQuery()\"\n title=\"Make a copy of this query\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">file_copy</span>\n copy query\n </button>\n @if (!dashboardLayoutSettings && datasetInstanceSummary.id) {\n <button (click)=\"save()\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">save</span>\n save\n </button>\n }\n }\n </div>\n </div>\n}\n\n<div class=\"cell-header\">\n @if (showParameters || parameterValues.length) {\n <div class=\"transformation-listing parameter-listing\">\n <div class=\"list-title\">\n Parameters\n </div>\n <div class=\"flex items-center flex-wrap\">\n @for (parameter of parameterValues; track parameter; let i = $index) {\n <label class=\"pl-4\">\n {{ parameter.title }}\n @if ((parameter.value || '').toString().includes('}}')) {\n <div>\n <mat-chip class=\"bg-gray-50 ml-2\" title=\"Using parameter value from {{parameter.value}}\">\n <div class=\"flex items-center\">\n <span class=\"material-symbols-outlined text-xl mr-1 text-gray-500\">layers</span>\n @if (dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n [innerHTML]=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')].value\"></span>\n }\n @if (!dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n class=\"font-medium text-orange-600\">\n Parameter Not Found !\n </span>\n }\n </div>\n <button matChipRemove (click)=\"parameter.value = ''\" title=\"\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n </div>\n }\n @if (!(parameter.value || '').toString().includes('}}')) {\n <div class=\"parameter-input\">\n @if (!parameter.multiple) {\n @if (parameter.type === 'text') {\n <input class=\"pr-8\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" [(ngModel)]=\"parameter.value\"\n (change)=\"evaluateDataset(true)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n @if (parameter.type === 'date' || parameter.type === 'datetime') {\n @if (!parameter._dateType) {\n <div class=\"flex items-center mr-8\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n }\n @if (parameter._dateType === 'picker') {\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\"\n placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n }\n @if (parameter._dateType === 'period') {\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n <div>Ago</div>\n </div>\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n }\n }\n @if (parameter.type === 'boolean') {\n <mat-slide-toggle class=\"pr-8\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n }\n }\n @if (parameter.multiple) {\n <mat-chip-grid class=\"pl-2\" #chipGrid aria-label=\"Enter values\">\n @for (paramValue of parameter.value; track paramValue) {\n <mat-chip-row\n class=\"bg-white mr-2\"\n (removed)=\"removeParameterValue(parameter, paramValue)\">\n {{paramValue}}\n <button matChipRemove [attr.aria-label]=\"'remove ' + paramValue\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n @if (parameter.type === 'text') {\n <input class=\"pr-8 py-1 self-center\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" matNativeControl\n (change)=\"addParameterValue(parameter, $event)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n </mat-chip-grid>\n }\n @if (!parameter._locked) {\n <button mat-icon-button [matMenuTriggerFor]=\"paramMenu\">\n <mat-icon>settings</mat-icon>\n </button>\n <mat-menu #paramMenu=\"matMenu\">\n <button mat-menu-item (click)=\"addParameter(parameter, i)\">Edit Parameter</button>\n <button mat-menu-item (click)=\"removeParameter(parameter)\">Remove Parameter</button>\n </mat-menu>\n }\n @if (Object.keys(dashboardParameters || {}).length) {\n <button mat-icon-button [matMenuTriggerFor]=\"dashParamMenu\"\n title=\"Bind this parameter value to another\">\n <mat-icon>text_fields</mat-icon>\n </button>\n <mat-menu #dashParamMenu=\"matMenu\">\n @for (dashParamKey of Object.keys(dashboardParameters); track dashParamKey) {\n <button mat-menu-item\n (click)=\"setDashboardParameter(parameter, dashboardParameters[dashParamKey].name)\">{{ dashboardParameters[dashParamKey].title }}\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </label>\n @if (parameterValues.length) {\n <div class=\"divider ml-2\"></div>\n }\n }\n <button mat-icon-button color=\"primary\" class=\"mx-2\" (click)=\"addParameter()\">\n <mat-icon>add_circle</mat-icon>\n </button>\n @if (parameterValues.length) {\n <button type=\"button\" (click)=\"evaluateDataset(true)\"\n class=\"mr-2 flex items-center whitespace-nowrap justify-center px-4 py-1 border border-transparent text-sm rounded-md shadow-sm text-white bg-primary focus:outline-none\">\n Apply Parameters\n </button>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"cell-header\">\n @if (terminatingTransformations.length) {\n <div class=\"transformation-listing py-2\">\n <div class=\"list-title\">\n Transformations\n </div>\n <div class=\"example-list flex flex-wrap\" cdkDropListGroup>\n @for (transformation of terminatingTransformations; track transformation; let i = $index) {\n @if (!transformation.hidden) {\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"{item:transformation,index:i}\">\n <div class=\"flex items-center\">\n <div class=\"new-transformation flex items-center justify-center w-6 h-6\">\n <a [matMenuTriggerFor]=\"addTransformation\"\n class=\"items-center add-transformation text-primary\">\n <mat-icon class=\"flex items-center w-5 h-5 text-xl\">add_circle</mat-icon>\n </a>\n <mat-menu #addTransformation=\"matMenu\">\n <button mat-menu-item (click)=\"insertTransformation(i, 'columns', transformation)\">\n Insert Column Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'formula', transformation)\">\n Insert Formula Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'join', transformation)\">\n Insert Join Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'summarise', transformation)\">\n Insert Summarise Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'filter', transformation)\">\n Insert Filter Transformation\n </button>\n </mat-menu>\n </div>\n <div cdkDrag class=\"pl-0 example-box badge-item w-auto m-0\" cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n [class]=\"{active: transformation._active, 'exclude bg-orange-50 border-orange-200': !!transformation.exclude, 'bg-indigo-50 border-indigo-200': (transformation.type === 'filter' && transformation.hide === false)}\">\n <button class=\"-mt-0.5\" title=\"Show transformation details\" mat-icon-button\n (click)=\"showTransformationDetail(transformation)\">\n @if (transformation.type === 'columns') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >table_chart</span>\n }\n @if (transformation.type === 'formula') {\n <span class=\"material-symbols-outlined text-xl\"\n >functions</span>\n }\n @if (transformation.type === 'join') {\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n }\n @if (transformation.type === 'summarise') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >pivot_table_chart</span>\n }\n @if (transformation.type === 'filter') {\n <span class=\"material-symbols-outlined text-xl\"\n >filter_alt</span>\n }\n </button>\n <span class=\"whitespace-nowrap cursor-pointer\"\n (click)=\"editTerminatingTransformation(transformation)\">{{ transformation._label }}</span>\n @if (transformation.exclude) {\n <button class=\"-ml-1\" [title]=\"'Re-enable this transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon class=\"text-orange-400\">replay</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 === terminatingTransformations.length) {\n <button class=\"-ml-1\" [title]=\"'Disable transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon>block</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 !== terminatingTransformations.length) {\n <button class=\"-ml-1\" [matMenuTriggerFor]=\"disableMenu\"\n [title]=\"'Disable transformation'\"\n mat-icon-button>\n <mat-icon>block</mat-icon>\n </button>\n <mat-menu #disableMenu=\"matMenu\">\n <button mat-menu-item (click)=\"disableTransformation(transformation, i)\">\n Disable this transformation\n </button>\n <button mat-menu-item (click)=\"excludeUpstreamTransformations(transformation)\">\n Disable subsequent transformation(s)\n </button>\n </mat-menu>\n }\n <button class=\"-ml-1\" title=\"Remove this transformation\" mat-icon-button color=\"primary\"\n (click)=\"removeTransformation(transformation, true, null, transformation._active)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"transformation._showDetail\">\n <div class=\"p-4 w-96 bg-white shadow rounded\">\n @if (transformation.type === 'summarise') {\n <p class=\"text-sm text-gray-700 mb-0\">\n <b>SELECT </b>@for (expression of transformation.config.expressions; track expression; let i = $index) {\n <span\n >@if (i > 0) {\n <span\n >, </span>\n }{{ expression.customExpression || expression.expressionType + '(' + (expression.fieldName || '') + ')' }}</span>\n }\n @if (transformation.config.summariseFieldNames.length) {\n <br><b>GROUP\n BY </b> {{ transformation.config.summariseFieldNames.join(', ') }}\n }\n </p>\n }\n @if (transformation.type === 'formula') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>EXPRESSION</b> {{ decodeURIComponent(transformation.config.expressions[0].expression) }}\n </div>\n }\n @if (transformation.type === 'columns') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>COLUMNS</b> {{ _.map(transformation.config.columns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'join') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>JOIN\n COLUMNS</b> {{ _.map(transformation.config.joinColumns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'filter') {\n @for (filter of transformation.config.filters; track filter) {\n <div\n class=\"text-sm text-gray-700 mb-0\">\n <b>FILTER</b> {{ filter.lhsExpression }} <b>{{ filter.filterType }}</b> {{ filter.rhsExpression }}\n </div>\n }\n }\n </div>\n </ng-template>\n </div>\n </div>\n }\n @if (_.some(terminatingTransformations, {exclude: true}) && i === terminatingTransformations.length - 1) {\n <button\n class=\"ml-4 flex items-center border-none bg-primary text-sm rounded-md text-white pr-2 pl-1 py-0.5\"\n (click)=\"enableAllTransformation()\">\n <mat-icon class=\"mr-1 text-base\">replay</mat-icon>\n Enable All\n </button>\n }\n }\n </div>\n</div>\n}\n</div>\n\n<div class=\"cell-header\">\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <div class=\"transformation-listing py-2 filters-list\"\n >\n <a class=\"list-title flex items-center\" (click)=\"showFilters = !showFilters\">\n Filters \n @if (!showFilters) {\n <mat-icon>expand_more</mat-icon>\n }\n @if (showFilters) {\n <mat-icon>expand_less</mat-icon>\n }\n </a>\n @for (filterTransformation of _.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}); track filterTransformation) {\n @if (_.every(filterTransformation.config.filters[0])) {\n <div class=\"badge-item pl-2 mr-1\"\n (click)=\"showFilters = !showFilters\">\n <span class=\"cursor-pointer\" [innerHtml]=\"getFilterString(filterTransformation.config)\"></span>\n </div>\n }\n }\n </div>\n }\n</div>\n\n@if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\n && showFilters) {\n <div class=\"dataset-filters\" id=\"datasetFilters\"\n >\n @for (transformation of datasetInstanceSummary.transformationInstances; track transformation; let i = $index) {\n @if (transformation.type === 'filter' && transformation.hide === false) {\n <div class=\"dataset-filter border-b border-gray-200\">\n <button mat-stroked-button class=\"mr-2 bg-white remove-filter\" color=\"warn\"\n (click)=\"removeTransformation(transformation, true, i)\">\n Remove Filter\n </button>\n @if (filterFields.length) {\n <ki-dataset-filters [filterFields]=\"filterFields\"\n [openSide]=\"openSide\" [parameterValues]=\"filterParameterValues\"\n [filterJunction]=\"transformation.config\"></ki-dataset-filters>\n }\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <button\n mat-flat-button class=\"apply-filter mr-2\" color=\"primary\"\n (click)=\"applyFilters()\" [disabled]=\"!filterJunction.filters.length\">\n Apply Filters\n </button>\n }\n </div>\n }\n }\n </div>\n}\n\n<div class=\"cell-header\">\n @if (_.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'})) {\n <div class=\"transformation-listing sort\"\n >\n <div class=\"list-title\">\n Sort\n </div>\n <div class=\"flex flex-wrap\">\n @for (sort of _.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'}).config.sorts; track sort; let i = $index) {\n <div class=\"badge-item outline\"\n [class]=\"{'exclude bg-orange-50 border-orange-200': _.find(datasetInstanceSummary.transformationInstances, {exclude: true})}\"\n >\n <span>{{ _.startCase(sort.fieldName) }} <span class=\"uppercase\">{{ sort.direction }}</span></span>\n <button mat-icon-button (click)=\"removeFilter(i)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"h-full table-overflow overflow-scroll\">\n @if (displayedColumns.length) {\n <table mat-table [dataSource]=\"tableData\" matSort (matSortChange)=\"sort($event)\"\n class=\"block sticky\">\n @for (column of filterFields; track column) {\n <ng-container [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header\n class=\"text-xs font-semibold text-gray-900 py-3.5 px-4\"> {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"py-3 px-4\">\n @if (!Array.isArray(element[column.name]) && !_.isPlainObject(element[column.name])) {\n @if (element[column.name] && String(element[column.name]).length <= 100) {\n <div [innerHTML]=\"element[column.name]\"></div>\n }\n @if (element[column.name] && String(element[column.name]).length > 100) {\n <div>{{ element[column.name].substring(0, 100) + '...' }}</div>\n <a (click)=\"viewFullItemData(element[column.name], column.name)\"\n class=\"flex items-center text-sm text-cta\">\n view more\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"ml-1 h-4 w-4\" fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"/>\n </svg>\n </a>\n }\n @if (!element[column.name]) {\n @if (element[column.name] === null) {\n <span class=\"font-mono text-gray-400\">null</span>\n }\n @if (element[column.name] !== null) {\n <span>{{ element[column.name] }}</span>\n }\n }\n }\n @if (Array.isArray(element[column.name])) {\n Contains {{ element[column.name].length }} items\n }\n @if (_.isPlainObject(element[column.name])) {\n <span class=\"text-xs font-mono\" [innerHTML]=\"toJSON(element[column.name])\"></span>\n }\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\" class=\"h-auto\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n }\n</div>\n\n\n<div class=\"border-b border-t bg-gray-50 px-4 py-1 flex align-center justify-end\">\n\n <div class=\"flex items-center\">\n <div class=\"text-sm text-gray-500 mr-10\">\n @if (dataset) {\n Showing {{ offset + 1 }} - {{ (page * limit) - (limit - tableData.length) }}\n }\n </div>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"mr-8 p-1.5\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button class=\"mr-4\" (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:column;position:relative;height:100%}:host>div{flex:0 1 auto}.divider{width:1px;height:17px;background-color:#cecece}.new-transformation .add-transformation{display:none}.new-transformation:hover .add-transformation{display:flex}.long-running{position:fixed;inset:0;background-color:#ffffffb3;z-index:99999;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.long-running .loading-box{position:relative;margin-bottom:2rem}.long-running .loading-box div{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.2rem;font-weight:500}.long-running p{font-size:1.1rem}.cell-header{width:100%;display:flex;align-items:center;justify-content:space-between}.cell-header.end{justify-content:flex-end}.cell-header.sorting{min-height:43px}.dataset-data-actions{display:flex;align-items:center;flex-wrap:wrap;width:100%;justify-content:flex-end;background-color:#fff;margin-top:-1px}.dataset-data-actions button{min-width:50px;padding:0 13px;color:#505050}.dataset-data-actions .divider{margin:0 .5rem;width:1px;height:36px;background-color:#ddd}.parameter-listing label{flex-direction:row;align-items:center}.parameter-listing label .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}.parameter-listing label .parameter-input .param-period-picker{padding:5px}.parameter-listing label .parameter-input button{color:#8e8e8e}.parameter-listing label .parameter-input button.edit-parameter{visibility:hidden}.parameter-listing label .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}.parameter-listing label .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.parameter-listing label .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}.parameter-listing label .parameter-input:hover .edit-parameter{visibility:visible}.transformation-listing{display:flex;align-items:center;width:100%;background-color:#00000012;border-bottom:1px solid #ddd;min-height:47px}.transformation-listing .list-title{text-transform:uppercase;font-size:.75rem;padding:0 1rem;border-right:2px solid #ddd;color:#4c4c4c;font-weight:500;letter-spacing:1px}.transformation-listing .badge-item{display:flex;align-items:center;margin-left:1rem;padding-left:1rem;border-radius:20px;background-color:#fff;border:1px solid #ddd;height:30px}.transformation-listing .badge-item.exclude{opacity:.8}.transformation-listing .badge-item:hover{background-color:#fcfcfc}.transformation-listing .badge-item span{margin-right:.5rem;color:#0000008a}.transformation-listing .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.transformation-listing .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}.dataset-filters{position:relative;overflow-y:scroll;flex:none!important;max-height:400px}.dataset-filters .dataset-filter{position:relative}.dataset-filters .dataset-filter .apply-filter{position:absolute;bottom:.5rem;right:0;z-index:10}.dataset-filters .dataset-filter .remove-filter{position:absolute;top:.5rem;right:0;z-index:10}.badge-holder{display:flex;align-items:center;margin:.25rem 0}.badge-holder .badge-item{display:flex;align-items:center;padding-left:1rem;border-radius:20px}.badge-holder .badge-item.outline{background-color:#fff;border:1px solid #efefef}.badge-holder .badge-item span{margin-right:.5rem;color:#0000008a}.badge-holder .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.badge-holder .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}table{position:relative;border-collapse:collapse}table.sticky th{position:sticky;top:0;background-color:#f5f5f5;border-top:none!important;border-bottom:none!important;box-shadow:inset 0 -1px #ddd}table th.settings{padding:0}table td{max-width:400px;word-wrap:break-word;padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;min-width:150px;width:1%}table td.settings{max-width:25px;min-width:25px}table::-webkit-scrollbar{width:.75em;background:transparent}table::-webkit-scrollbar-thumb{background:#d2d2d2}table tbody:nth-of-type(1) tr:nth-of-type(1) td{border-top:none!important}table thead th{border-top:none!important;border-bottom:none!important;box-shadow:inset 0 2px #000,inset 0 -2px #000;padding:2px 0}table thead th{background-clip:padding-box}.table-overflow::-webkit-scrollbar{width:.75em;background:transparent}.table-overflow::-webkit-scrollbar-thumb{background:#d2d2d2}.paging-toolbar{position:sticky;bottom:-20px;left:0;background-color:#fff;right:0;padding:1rem}table{text-align:left;position:relative;border-collapse:collapse}th,td{padding:.25rem}\n"], dependencies: [{ kind: "component", type: i4.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i4.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i7$4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i7$3.MatChip, selector: "mat-basic-chip, [mat-basic-chip], mat-chip, [mat-chip]", inputs: ["role", "id", "aria-label", "aria-description", "value", "color", "removable", "highlighted", "disableRipple", "disabled"], outputs: ["removed", "destroyed"], exportAs: ["matChip"] }, { kind: "component", type: i7$3.MatChipGrid, selector: "mat-chip-grid", inputs: ["disabled", "placeholder", "required", "value", "errorStateMatcher"], outputs: ["change", "valueChange"] }, { kind: "directive", type: i7$3.MatChipInput, selector: "input[matChipInputFor]", inputs: ["matChipInputFor", "matChipInputAddOnBlur", "matChipInputSeparatorKeyCodes", "placeholder", "id", "disabled", "readonly", "matChipInputDisabledInteractive"], outputs: ["matChipInputTokenEnd"], exportAs: ["matChipInput", "matChipInputFor"] }, { kind: "directive", type: i7$3.MatChipRemove, selector: "[matChipRemove]" }, { kind: "component", type: i7$3.MatChipRow, selector: "mat-chip-row, [mat-chip-row], mat-basic-chip-row, [mat-basic-chip-row]", inputs: ["editable"], outputs: ["edited"] }, { kind: "component", type: i9$1.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9$1.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9$1.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9$1.MatColumnDef, selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i9$1.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9$1.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9$1.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9$1.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9$1.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9$1.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i10.MatSort, selector: "[matSort]", inputs: ["matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear", "matSortDisabled"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i10.MatSortHeader, selector: "[mat-sort-header]", inputs: ["mat-sort-header", "arrowPosition", "start", "disabled", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "directive", type: i6.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i6.CdkDropListGroup, selector: "[cdkDropListGroup]", inputs: ["cdkDropListGroupDisabled"], exportAs: ["cdkDropListGroup"] }, { kind: "directive", type: i6.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: i7.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i7.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i8.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "component", type: i14.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i12$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i16.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "directive", type: i16.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "component", type: DatasetFiltersComponent, selector: "ki-dataset-filters", inputs: ["filterJunction", "filterFields", "joinFilterFields", "joinFieldsName", "openSide", "parameterValues"] }, { kind: "component", type: WhitelistedSqlFunctionsComponent, selector: "ki-whitelisted-sql-functions", inputs: ["search", "fields"] }] }); }
|
|
3558
3575
|
}
|
|
3559
3576
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: DatasetEditorComponent, decorators: [{
|
|
3560
3577
|
type: Component,
|
|
3561
|
-
args: [{ selector: 'ki-dataset-editor', standalone: false, template: "@if (longRunning) {\n <div class=\"long-running flex-col\">\n <div class=\"loading-box\">\n <mat-spinner [diameter]=\"150\"></mat-spinner>\n <div>Loading</div>\n </div>\n <p class=\"text-center\">Please wait while we process this query.</p>\n <p class=\"text-center\">The results will be shown here once it has finished running.</p>\n <div>\n <a class=\"text-primary hover:underline\" (click)=\"cancelEvaluate()\">Cancel query and return to editor.</a>\n </div>\n </div>\n}\n<div class=\"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 -z-10\" id=\"sidebarWrapper\">\n <div [class]=\"{'translate-x-0': sideOpen, 'translate-x-full': !sideOpen}\"\n (click)=\"$event.stopPropagation()\"\n class=\"pointer-events-auto w-screen max-w-md transform transition ease-in-out duration-500 sm:duration-700\"\n id=\"docSidebar\">\n <div class=\"flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl\">\n <div class=\"px-4 sm:px-6\">\n <div class=\"flex items-start justify-between\">\n <div></div>\n\n <div class=\"ml-3 flex h-7 items-center\">\n <button type=\"button\" (click)=\"openSide.next(false)\"\n class=\"rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none\">\n <span class=\"sr-only\">Close panel</span>\n <!-- Heroicon name: outline/x -->\n <svg class=\"h-6 w-6\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div class=\"relative flex-1 px-4 sm:px-6\">\n <ki-whitelisted-sql-functions [fields]=\"filterFields\"></ki-whitelisted-sql-functions>\n </div>\n </div>\n </div>\n</div>\n\n@if (!datasetEditorNoTools) {\n <div class=\"border-b cell-header end\">\n <div class=\"leading-5 px-4 text-xs uppercase tracking-wider font-medium border-r-2 text-gray-600\">\n Operations\n </div>\n <div class=\"dataset-data-actions\">\n <button (click)=\"addFilter()\"\n title=\"Filter the set using column based restrictions\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">filter_alt</span>\n filter\n </button>\n <button (click)=\"summariseData()\"\n title=\"Summarise this data to produce aggregated totals, sums and other derivations\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">pivot_table_chart</span>\n summarise\n </button>\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"joinData()\"\n title=\"Join another data set to the current dataset\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n join\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"createFormula()\"\n title=\"Create a formula column using an expression based on other columns\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">functions</span>\n formula\n </button>\n <button (click)=\"editColumnSettings()\"\n title=\"Switch on and off columns for display\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">table_chart</span>\n columns\n </button>\n @if (!datasetEditorSimpleMode) {\n <div class=\"divider\"></div>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addParameter()\"\n title=\"Add a parameter to use in filters, expressions etc.\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">text_fields</span>\n parameters\n </button>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addPagingMarker()\"\n title=\"Insert paging marker to limit results at this stage in the query flow\"\n class=\"w-24 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">skip_next</span>\n paging marker\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"evaluateDataset()\"\n title=\"Reload this query based upon changes you may have made\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">sync</span>\n reload\n </button>\n @if (!datasetEditorReadonly) {\n <button [disabled]=\"!datasetInstanceSummary || !datasetInstanceSummary.id\" (click)=\"shareQuery()\"\n title=\"Share this query with other account holders\"\n class=\"disabled:opacity-50 w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">share</span>\n share\n </button>\n <button (click)=\"saveAsQuery()\"\n title=\"Make a copy of this query\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">file_copy</span>\n copy query\n </button>\n @if (!dashboardLayoutSettings && datasetInstanceSummary.id) {\n <button (click)=\"save()\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">save</span>\n save\n </button>\n }\n }\n </div>\n </div>\n}\n\n<div class=\"cell-header\">\n @if (showParameters || parameterValues.length) {\n <div class=\"transformation-listing parameter-listing\">\n <div class=\"list-title\">\n Parameters\n </div>\n <div class=\"flex items-center flex-wrap\">\n @for (parameter of parameterValues; track parameter; let i = $index) {\n <label class=\"pl-4\">\n {{ parameter.title }}\n @if ((parameter.value || '').toString().includes('}}')) {\n <div>\n <mat-chip class=\"bg-gray-50 ml-2\" title=\"Using parameter value from {{parameter.value}}\">\n <div class=\"flex items-center\">\n <span class=\"material-symbols-outlined text-xl mr-1 text-gray-500\">layers</span>\n @if (dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n [innerHTML]=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')].value\"></span>\n }\n @if (!dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n class=\"font-medium text-orange-600\">\n Parameter Not Found !\n </span>\n }\n </div>\n <button matChipRemove (click)=\"parameter.value = ''\" title=\"\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n </div>\n }\n @if (!(parameter.value || '').toString().includes('}}')) {\n <div class=\"parameter-input\">\n @if (!parameter.multiple) {\n @if (parameter.type === 'text') {\n <input class=\"pr-8\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" [(ngModel)]=\"parameter.value\"\n (change)=\"evaluateDataset(true)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n @if (parameter.type === 'date' || parameter.type === 'datetime') {\n @if (!parameter._dateType) {\n <div class=\"flex items-center mr-8\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n }\n @if (parameter._dateType === 'picker') {\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\"\n placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n }\n @if (parameter._dateType === 'period') {\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n <div>Ago</div>\n </div>\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n }\n }\n @if (parameter.type === 'boolean') {\n <mat-slide-toggle class=\"pr-8\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n }\n }\n @if (parameter.multiple) {\n <mat-chip-grid class=\"pl-2\" #chipGrid aria-label=\"Enter values\">\n @for (paramValue of parameter.value; track paramValue) {\n <mat-chip-row\n class=\"bg-white mr-2\"\n (removed)=\"removeParameterValue(parameter, paramValue)\">\n {{paramValue}}\n <button matChipRemove [attr.aria-label]=\"'remove ' + paramValue\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n @if (parameter.type === 'text') {\n <input class=\"pr-8 py-1 self-center\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" matNativeControl\n (change)=\"addParameterValue(parameter, $event)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n </mat-chip-grid>\n }\n @if (!parameter._locked) {\n <button mat-icon-button [matMenuTriggerFor]=\"paramMenu\">\n <mat-icon>settings</mat-icon>\n </button>\n <mat-menu #paramMenu=\"matMenu\">\n <button mat-menu-item (click)=\"addParameter(parameter, i)\">Edit Parameter</button>\n <button mat-menu-item (click)=\"removeParameter(parameter)\">Remove Parameter</button>\n </mat-menu>\n }\n @if (Object.keys(dashboardParameters || {}).length) {\n <button mat-icon-button [matMenuTriggerFor]=\"dashParamMenu\"\n title=\"Bind this parameter value to another\">\n <mat-icon>text_fields</mat-icon>\n </button>\n <mat-menu #dashParamMenu=\"matMenu\">\n @for (dashParamKey of Object.keys(dashboardParameters); track dashParamKey) {\n <button mat-menu-item\n (click)=\"setDashboardParameter(parameter, dashboardParameters[dashParamKey].name)\">{{ dashboardParameters[dashParamKey].title }}\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </label>\n @if (parameterValues.length) {\n <div class=\"divider ml-2\"></div>\n }\n }\n <button mat-icon-button color=\"primary\" class=\"mx-2\" (click)=\"addParameter()\">\n <mat-icon>add_circle</mat-icon>\n </button>\n @if (parameterValues.length) {\n <button type=\"button\" (click)=\"evaluateDataset(true)\"\n class=\"mr-2 flex items-center whitespace-nowrap justify-center px-4 py-1 border border-transparent text-sm rounded-md shadow-sm text-white bg-primary focus:outline-none\">\n Apply Parameters\n </button>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"cell-header\">\n @if (terminatingTransformations.length) {\n <div class=\"transformation-listing py-2\">\n <div class=\"list-title\">\n Transformations\n </div>\n <div class=\"example-list flex flex-wrap\" cdkDropListGroup>\n @for (transformation of terminatingTransformations; track transformation; let i = $index) {\n @if (!transformation.hidden) {\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"{item:transformation,index:i}\">\n <div class=\"flex items-center\">\n <div class=\"new-transformation flex items-center justify-center w-6 h-6\">\n <a [matMenuTriggerFor]=\"addTransformation\"\n class=\"items-center add-transformation text-primary\">\n <mat-icon class=\"flex items-center w-5 h-5 text-xl\">add_circle</mat-icon>\n </a>\n <mat-menu #addTransformation=\"matMenu\">\n <button mat-menu-item (click)=\"insertTransformation(i, 'columns', transformation)\">\n Insert Column Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'formula', transformation)\">\n Insert Formula Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'join', transformation)\">\n Insert Join Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'summarise', transformation)\">\n Insert Summarise Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'filter', transformation)\">\n Insert Filter Transformation\n </button>\n </mat-menu>\n </div>\n <div cdkDrag class=\"pl-0 example-box badge-item w-auto m-0\" cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n [class]=\"{active: transformation._active, 'exclude bg-orange-50 border-orange-200': !!transformation.exclude, 'bg-indigo-50 border-indigo-200': (transformation.type === 'filter' && transformation.hide === false)}\">\n <button class=\"-mt-0.5\" title=\"Show transformation details\" mat-icon-button\n (click)=\"showTransformationDetail(transformation)\">\n @if (transformation.type === 'columns') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >table_chart</span>\n }\n @if (transformation.type === 'formula') {\n <span class=\"material-symbols-outlined text-xl\"\n >functions</span>\n }\n @if (transformation.type === 'join') {\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n }\n @if (transformation.type === 'summarise') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >pivot_table_chart</span>\n }\n @if (transformation.type === 'filter') {\n <span class=\"material-symbols-outlined text-xl\"\n >filter_alt</span>\n }\n </button>\n <span class=\"whitespace-nowrap cursor-pointer\"\n (click)=\"editTerminatingTransformation(transformation)\">{{ transformation._label }}</span>\n @if (transformation.exclude) {\n <button class=\"-ml-1\" [title]=\"'Re-enable this transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon class=\"text-orange-400\">replay</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 === terminatingTransformations.length) {\n <button class=\"-ml-1\" [title]=\"'Disable transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon>block</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 !== terminatingTransformations.length) {\n <button class=\"-ml-1\" [matMenuTriggerFor]=\"disableMenu\"\n [title]=\"'Disable transformation'\"\n mat-icon-button>\n <mat-icon>block</mat-icon>\n </button>\n <mat-menu #disableMenu=\"matMenu\">\n <button mat-menu-item (click)=\"disableTransformation(transformation, i)\">\n Disable this transformation\n </button>\n <button mat-menu-item (click)=\"excludeUpstreamTransformations(transformation)\">\n Disable subsequent transformation(s)\n </button>\n </mat-menu>\n }\n <button class=\"-ml-1\" title=\"Remove this transformation\" mat-icon-button color=\"primary\"\n (click)=\"removeTransformation(transformation, true, null, transformation._active)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"transformation._showDetail\">\n <div class=\"p-4 w-96 bg-white shadow rounded\">\n @if (transformation.type === 'summarise') {\n <p class=\"text-sm text-gray-700 mb-0\">\n <b>SELECT </b>@for (expression of transformation.config.expressions; track expression; let i = $index) {\n <span\n >@if (i > 0) {\n <span\n >, </span>\n }{{ expression.customExpression || expression.expressionType + '(' + (expression.fieldName || '') + ')' }}</span>\n }\n @if (transformation.config.summariseFieldNames.length) {\n <br><b>GROUP\n BY </b> {{ transformation.config.summariseFieldNames.join(', ') }}\n }\n </p>\n }\n @if (transformation.type === 'formula') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>EXPRESSION</b> {{ decodeURIComponent(transformation.config.expressions[0].expression) }}\n </div>\n }\n @if (transformation.type === 'columns') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>COLUMNS</b> {{ _.map(transformation.config.columns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'join') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>JOIN\n COLUMNS</b> {{ _.map(transformation.config.joinColumns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'filter') {\n @for (filter of transformation.config.filters; track filter) {\n <div\n class=\"text-sm text-gray-700 mb-0\">\n <b>FILTER</b> {{ filter.lhsExpression }} <b>{{ filter.filterType }}</b> {{ filter.rhsExpression }}\n </div>\n }\n }\n </div>\n </ng-template>\n </div>\n </div>\n }\n @if (_.some(terminatingTransformations, {exclude: true}) && i === terminatingTransformations.length - 1) {\n <button\n class=\"ml-4 flex items-center border-none bg-primary text-sm rounded-md text-white pr-2 pl-1 py-0.5\"\n (click)=\"enableAllTransformation()\">\n <mat-icon class=\"mr-1 text-base\">replay</mat-icon>\n Enable All\n </button>\n }\n }\n </div>\n</div>\n}\n</div>\n\n<div class=\"cell-header\">\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <div class=\"transformation-listing py-2 filters-list\"\n >\n <a class=\"list-title flex items-center\" (click)=\"showFilters = !showFilters\">\n Filters \n @if (!showFilters) {\n <mat-icon>expand_more</mat-icon>\n }\n @if (showFilters) {\n <mat-icon>expand_less</mat-icon>\n }\n </a>\n @for (filterTransformation of _.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}); track filterTransformation) {\n @if (_.every(filterTransformation.config.filters[0])) {\n <div class=\"badge-item pl-2 mr-1\"\n (click)=\"showFilters = !showFilters\">\n <span class=\"cursor-pointer\" [innerHtml]=\"getFilterString(filterTransformation.config)\"></span>\n </div>\n }\n }\n </div>\n }\n</div>\n\n@if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\n && showFilters) {\n <div class=\"dataset-filters\" id=\"datasetFilters\"\n >\n @for (transformation of datasetInstanceSummary.transformationInstances; track transformation; let i = $index) {\n @if (transformation.type === 'filter' && transformation.hide === false) {\n <div class=\"dataset-filter border-b border-gray-200\">\n <button mat-stroked-button class=\"mr-2 bg-white remove-filter\" color=\"warn\"\n (click)=\"removeTransformation(transformation, true, i)\">\n Remove Filter\n </button>\n @if (filterFields.length) {\n <ki-dataset-filters [filterFields]=\"filterFields\"\n [openSide]=\"openSide\" [parameterValues]=\"filterParameterValues\"\n [filterJunction]=\"transformation.config\"></ki-dataset-filters>\n }\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <button\n mat-flat-button class=\"apply-filter mr-2\" color=\"primary\"\n (click)=\"applyFilters()\" [disabled]=\"!filterJunction.filters.length\">\n Apply Filters\n </button>\n }\n </div>\n }\n }\n </div>\n}\n\n<div class=\"cell-header\">\n @if (_.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'})) {\n <div class=\"transformation-listing sort\"\n >\n <div class=\"list-title\">\n Sort\n </div>\n <div class=\"flex flex-wrap\">\n @for (sort of _.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'}).config.sorts; track sort; let i = $index) {\n <div class=\"badge-item outline\"\n [class]=\"{'exclude bg-orange-50 border-orange-200': _.find(datasetInstanceSummary.transformationInstances, {exclude: true})}\"\n >\n <span>{{ _.startCase(sort.fieldName) }} <span class=\"uppercase\">{{ sort.direction }}</span></span>\n <button mat-icon-button (click)=\"removeFilter(i)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"h-full table-overflow overflow-scroll\">\n @if (displayedColumns.length) {\n <table mat-table [dataSource]=\"tableData\" matSort (matSortChange)=\"sort($event)\"\n class=\"block sticky\">\n @for (column of filterFields; track column) {\n <ng-container [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header\n class=\"text-xs font-semibold text-gray-900 py-3.5 px-4\"> {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"py-3 px-4\">\n @if (!Array.isArray(element[column.name]) && !_.isPlainObject(element[column.name])) {\n @if (element[column.name] && String(element[column.name]).length <= 100) {\n <div [innerHTML]=\"element[column.name]\"></div>\n }\n @if (element[column.name] && String(element[column.name]).length > 100) {\n <div>{{ element[column.name].substring(0, 100) + '...' }}</div>\n <a (click)=\"viewFullItemData(element[column.name], column.name)\"\n class=\"flex items-center text-sm text-cta\">\n view more\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"ml-1 h-4 w-4\" fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"/>\n </svg>\n </a>\n }\n @if (!element[column.name]) {\n @if (element[column.name] === null) {\n <span class=\"font-mono text-gray-400\">null</span>\n }\n @if (element[column.name] !== null) {\n <span>{{ element[column.name] }}</span>\n }\n }\n }\n @if (Array.isArray(element[column.name])) {\n Contains {{ element[column.name].length }} items\n }\n @if (_.isPlainObject(element[column.name])) {\n Object has {{ Object.keys(element[column.name]).length }} keys\n }\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\" class=\"h-auto\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n }\n</div>\n\n\n<div class=\"border-b border-t bg-gray-50 px-4 py-1 flex align-center justify-end\">\n\n <div class=\"flex items-center\">\n <div class=\"text-sm text-gray-500 mr-10\">\n @if (dataset) {\n Showing {{ offset + 1 }} - {{ (page * limit) - (limit - tableData.length) }}\n }\n </div>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"mr-8 p-1.5\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button class=\"mr-4\" (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:column;position:relative;height:100%}:host>div{flex:0 1 auto}.divider{width:1px;height:17px;background-color:#cecece}.new-transformation .add-transformation{display:none}.new-transformation:hover .add-transformation{display:flex}.long-running{position:fixed;inset:0;background-color:#ffffffb3;z-index:99999;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.long-running .loading-box{position:relative;margin-bottom:2rem}.long-running .loading-box div{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.2rem;font-weight:500}.long-running p{font-size:1.1rem}.cell-header{width:100%;display:flex;align-items:center;justify-content:space-between}.cell-header.end{justify-content:flex-end}.cell-header.sorting{min-height:43px}.dataset-data-actions{display:flex;align-items:center;flex-wrap:wrap;width:100%;justify-content:flex-end;background-color:#fff;margin-top:-1px}.dataset-data-actions button{min-width:50px;padding:0 13px;color:#505050}.dataset-data-actions .divider{margin:0 .5rem;width:1px;height:36px;background-color:#ddd}.parameter-listing label{flex-direction:row;align-items:center}.parameter-listing label .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}.parameter-listing label .parameter-input .param-period-picker{padding:5px}.parameter-listing label .parameter-input button{color:#8e8e8e}.parameter-listing label .parameter-input button.edit-parameter{visibility:hidden}.parameter-listing label .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}.parameter-listing label .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.parameter-listing label .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}.parameter-listing label .parameter-input:hover .edit-parameter{visibility:visible}.transformation-listing{display:flex;align-items:center;width:100%;background-color:#00000012;border-bottom:1px solid #ddd;min-height:47px}.transformation-listing .list-title{text-transform:uppercase;font-size:.75rem;padding:0 1rem;border-right:2px solid #ddd;color:#4c4c4c;font-weight:500;letter-spacing:1px}.transformation-listing .badge-item{display:flex;align-items:center;margin-left:1rem;padding-left:1rem;border-radius:20px;background-color:#fff;border:1px solid #ddd;height:30px}.transformation-listing .badge-item.exclude{opacity:.8}.transformation-listing .badge-item:hover{background-color:#fcfcfc}.transformation-listing .badge-item span{margin-right:.5rem;color:#0000008a}.transformation-listing .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.transformation-listing .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}.dataset-filters{position:relative;overflow-y:scroll;flex:none!important;max-height:400px}.dataset-filters .dataset-filter{position:relative}.dataset-filters .dataset-filter .apply-filter{position:absolute;bottom:.5rem;right:0;z-index:10}.dataset-filters .dataset-filter .remove-filter{position:absolute;top:.5rem;right:0;z-index:10}.badge-holder{display:flex;align-items:center;margin:.25rem 0}.badge-holder .badge-item{display:flex;align-items:center;padding-left:1rem;border-radius:20px}.badge-holder .badge-item.outline{background-color:#fff;border:1px solid #efefef}.badge-holder .badge-item span{margin-right:.5rem;color:#0000008a}.badge-holder .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.badge-holder .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}table{position:relative;border-collapse:collapse}table.sticky th{position:sticky;top:0;background-color:#f5f5f5;border-top:none!important;border-bottom:none!important;box-shadow:inset 0 -1px #ddd}table th.settings{padding:0}table td{max-width:400px;word-wrap:break-word;padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;min-width:150px;width:1%}table td.settings{max-width:25px;min-width:25px}table::-webkit-scrollbar{width:.75em;background:transparent}table::-webkit-scrollbar-thumb{background:#d2d2d2}table tbody:nth-of-type(1) tr:nth-of-type(1) td{border-top:none!important}table thead th{border-top:none!important;border-bottom:none!important;box-shadow:inset 0 2px #000,inset 0 -2px #000;padding:2px 0}table thead th{background-clip:padding-box}.table-overflow::-webkit-scrollbar{width:.75em;background:transparent}.table-overflow::-webkit-scrollbar-thumb{background:#d2d2d2}.paging-toolbar{position:sticky;bottom:-20px;left:0;background-color:#fff;right:0;padding:1rem}table{text-align:left;position:relative;border-collapse:collapse}th,td{padding:.25rem}\n"] }]
|
|
3578
|
+
args: [{ selector: 'ki-dataset-editor', standalone: false, template: "@if (longRunning) {\n <div class=\"long-running flex-col\">\n <div class=\"loading-box\">\n <mat-spinner [diameter]=\"150\"></mat-spinner>\n <div>Loading</div>\n </div>\n <p class=\"text-center\">Please wait while we process this query.</p>\n <p class=\"text-center\">The results will be shown here once it has finished running.</p>\n <div>\n <a class=\"text-primary hover:underline\" (click)=\"cancelEvaluate()\">Cancel query and return to editor.</a>\n </div>\n </div>\n}\n<div class=\"pointer-events-none fixed inset-y-0 right-0 flex max-w-full pl-10 -z-10\" id=\"sidebarWrapper\">\n <div [class]=\"{'translate-x-0': sideOpen, 'translate-x-full': !sideOpen}\"\n (click)=\"$event.stopPropagation()\"\n class=\"pointer-events-auto w-screen max-w-md transform transition ease-in-out duration-500 sm:duration-700\"\n id=\"docSidebar\">\n <div class=\"flex h-full flex-col overflow-y-scroll bg-white py-6 shadow-xl\">\n <div class=\"px-4 sm:px-6\">\n <div class=\"flex items-start justify-between\">\n <div></div>\n\n <div class=\"ml-3 flex h-7 items-center\">\n <button type=\"button\" (click)=\"openSide.next(false)\"\n class=\"rounded-md bg-white text-gray-400 hover:text-gray-500 focus:outline-none\">\n <span class=\"sr-only\">Close panel</span>\n <!-- Heroicon name: outline/x -->\n <svg class=\"h-6 w-6\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\"\n stroke=\"currentColor\" aria-hidden=\"true\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </button>\n </div>\n </div>\n </div>\n <div class=\"relative flex-1 px-4 sm:px-6\">\n <ki-whitelisted-sql-functions [fields]=\"filterFields\"></ki-whitelisted-sql-functions>\n </div>\n </div>\n </div>\n</div>\n\n@if (!datasetEditorNoTools) {\n <div class=\"border-b cell-header end\">\n <div class=\"leading-5 px-4 text-xs uppercase tracking-wider font-medium border-r-2 text-gray-600\">\n Operations\n </div>\n <div class=\"dataset-data-actions\">\n <button (click)=\"addFilter()\"\n title=\"Filter the set using column based restrictions\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">filter_alt</span>\n filter\n </button>\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"summariseData()\"\n title=\"Summarise this data to produce aggregated totals, sums and other derivations\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">pivot_table_chart</span>\n summarise\n </button>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"joinData()\"\n title=\"Join another data set to the current dataset\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n join\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"createFormula()\"\n title=\"Create a formula column using an expression based on other columns\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">functions</span>\n formula\n </button>\n <button (click)=\"editColumnSettings()\"\n title=\"Switch on and off columns for display\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">table_chart</span>\n columns\n </button>\n @if (!datasetEditorSimpleMode) {\n <div class=\"divider\"></div>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addParameter()\"\n title=\"Add a parameter to use in filters, expressions etc.\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">text_fields</span>\n parameters\n </button>\n }\n @if (!datasetEditorSimpleMode) {\n <button (click)=\"addPagingMarker()\"\n title=\"Insert paging marker to limit results at this stage in the query flow\"\n class=\"w-24 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">skip_next</span>\n paging marker\n </button>\n }\n <div class=\"divider\"></div>\n <button (click)=\"evaluateDataset()\"\n title=\"Reload this query based upon changes you may have made\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">sync</span>\n reload\n </button>\n @if (!datasetEditorReadonly) {\n <button [disabled]=\"!datasetInstanceSummary || !datasetInstanceSummary.id\" (click)=\"shareQuery()\"\n title=\"Share this query with other account holders\"\n class=\"disabled:opacity-50 w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">share</span>\n share\n </button>\n <button (click)=\"saveAsQuery()\"\n title=\"Make a copy of this query\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">file_copy</span>\n copy query\n </button>\n @if (!dashboardLayoutSettings && datasetInstanceSummary.id) {\n <button (click)=\"save()\"\n class=\"w-20 flex flex-col items-center justify-center py-1 px-2 text-xs text-gray-600 cursor-pointer hover:bg-gray-100\">\n <span class=\"material-symbols-outlined text-xl\">save</span>\n save\n </button>\n }\n }\n </div>\n </div>\n}\n\n<div class=\"cell-header\">\n @if (showParameters || parameterValues.length) {\n <div class=\"transformation-listing parameter-listing\">\n <div class=\"list-title\">\n Parameters\n </div>\n <div class=\"flex items-center flex-wrap\">\n @for (parameter of parameterValues; track parameter; let i = $index) {\n <label class=\"pl-4\">\n {{ parameter.title }}\n @if ((parameter.value || '').toString().includes('}}')) {\n <div>\n <mat-chip class=\"bg-gray-50 ml-2\" title=\"Using parameter value from {{parameter.value}}\">\n <div class=\"flex items-center\">\n <span class=\"material-symbols-outlined text-xl mr-1 text-gray-500\">layers</span>\n @if (dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n [innerHTML]=\"dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')].value\"></span>\n }\n @if (!dashboardParameters[parameter.value.replace('{{', '').replace('}}', '')]) {\n <span\n class=\"font-medium text-orange-600\">\n Parameter Not Found !\n </span>\n }\n </div>\n <button matChipRemove (click)=\"parameter.value = ''\" title=\"\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip>\n </div>\n }\n @if (!(parameter.value || '').toString().includes('}}')) {\n <div class=\"parameter-input\">\n @if (!parameter.multiple) {\n @if (parameter.type === 'text') {\n <input class=\"pr-8\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" [(ngModel)]=\"parameter.value\"\n (change)=\"evaluateDataset(true)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n @if (parameter.type === 'date' || parameter.type === 'datetime') {\n @if (!parameter._dateType) {\n <div class=\"flex items-center mr-8\">\n <button (click)=\"changeDateType($event, parameter, 'picker')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n Date Picker\n </button>\n <button (click)=\"changeDateType($event, parameter, 'period')\"\n class=\"hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-2 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n Time Period\n </button>\n </div>\n }\n @if (parameter._dateType === 'picker') {\n <input [type]=\"parameter.type === 'date' ? 'date' : 'datetime-local'\"\n placeholder=\"Enter {{parameter.title}}\" [(ngModel)]=\"parameter.value\"\n (keyup.enter)=\"evaluateDataset(true)\" required autofocus>\n <a (click)=\"changeDateType($event, parameter, 'period')\"\n matTooltip=\"Time Period\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">restore</mat-icon>\n </a>\n }\n @if (parameter._dateType === 'period') {\n <div class=\"flex items-center\">\n <input #periodValue type=\"number\" placeholder=\"No.\" required autofocus\n class=\"w-16 mr-2\" min=\"0\" [value]=\"parameter._periodValue\"\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <select class=\"param-period-picker mr-2\" [value]=\"parameter._period || 'DAYS'\"\n #period\n (change)=\"updatePeriodValue(periodValue.value, period.value, parameter)\">\n <option value=\"DAYS\">Days</option>\n <option value=\"HOURS\">Hours</option>\n </select>\n <div>Ago</div>\n </div>\n <a (click)=\"changeDateType($event, parameter, 'picker')\"\n matTooltip=\"Date Picker\"\n class=\"mr-10 text-center ml-2 hover:bg-gray-50 text-gray-800 border border-gray-300 py-0.5 pr-0.5 rounded mr-2 bg-white flex items-center\">\n <mat-icon class=\"text-base\">calendar_month</mat-icon>\n </a>\n }\n }\n @if (parameter.type === 'boolean') {\n <mat-slide-toggle class=\"pr-8\" color=\"primary\"\n [checked]=\"parameter.value\" (change)=\"booleanUpdate($event, parameter)\"\n required></mat-slide-toggle>\n }\n }\n @if (parameter.multiple) {\n <mat-chip-grid class=\"pl-2\" #chipGrid aria-label=\"Enter values\">\n @for (paramValue of parameter.value; track paramValue) {\n <mat-chip-row\n class=\"bg-white mr-2\"\n (removed)=\"removeParameterValue(parameter, paramValue)\">\n {{paramValue}}\n <button matChipRemove [attr.aria-label]=\"'remove ' + paramValue\">\n <mat-icon>cancel</mat-icon>\n </button>\n </mat-chip-row>\n }\n @if (parameter.type === 'text') {\n <input class=\"pr-8 py-1 self-center\" type=\"text\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'numeric') {\n <input class=\"pr-8\" type=\"number\" placeholder=\"Enter {{parameter.title}}\"\n required autofocus\n [matChipInputFor]=\"chipGrid\"\n [matChipInputSeparatorKeyCodes]=\"[ENTER, COMMA]\"\n [matChipInputAddOnBlur]=\"true\"\n (matChipInputTokenEnd)=\"addParameterValue(parameter, $event)\">\n }\n @if (parameter.type === 'list') {\n <select class=\"pr-8 py-1.5 pl-1 self-center\" matNativeControl\n (change)=\"addParameterValue(parameter, $event)\" required autofocus>\n <option [value]=\"null\">-- Select Value --</option>\n @for (item of parameter.list; track item) {\n <option [value]=\"item.value\">{{ item.label }}\n </option>\n }\n </select>\n }\n </mat-chip-grid>\n }\n @if (!parameter._locked) {\n <button mat-icon-button [matMenuTriggerFor]=\"paramMenu\">\n <mat-icon>settings</mat-icon>\n </button>\n <mat-menu #paramMenu=\"matMenu\">\n <button mat-menu-item (click)=\"addParameter(parameter, i)\">Edit Parameter</button>\n <button mat-menu-item (click)=\"removeParameter(parameter)\">Remove Parameter</button>\n </mat-menu>\n }\n @if (Object.keys(dashboardParameters || {}).length) {\n <button mat-icon-button [matMenuTriggerFor]=\"dashParamMenu\"\n title=\"Bind this parameter value to another\">\n <mat-icon>text_fields</mat-icon>\n </button>\n <mat-menu #dashParamMenu=\"matMenu\">\n @for (dashParamKey of Object.keys(dashboardParameters); track dashParamKey) {\n <button mat-menu-item\n (click)=\"setDashboardParameter(parameter, dashboardParameters[dashParamKey].name)\">{{ dashboardParameters[dashParamKey].title }}\n </button>\n }\n </mat-menu>\n }\n </div>\n }\n </label>\n @if (parameterValues.length) {\n <div class=\"divider ml-2\"></div>\n }\n }\n <button mat-icon-button color=\"primary\" class=\"mx-2\" (click)=\"addParameter()\">\n <mat-icon>add_circle</mat-icon>\n </button>\n @if (parameterValues.length) {\n <button type=\"button\" (click)=\"evaluateDataset(true)\"\n class=\"mr-2 flex items-center whitespace-nowrap justify-center px-4 py-1 border border-transparent text-sm rounded-md shadow-sm text-white bg-primary focus:outline-none\">\n Apply Parameters\n </button>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"cell-header\">\n @if (terminatingTransformations.length) {\n <div class=\"transformation-listing py-2\">\n <div class=\"list-title\">\n Transformations\n </div>\n <div class=\"example-list flex flex-wrap\" cdkDropListGroup>\n @for (transformation of terminatingTransformations; track transformation; let i = $index) {\n @if (!transformation.hidden) {\n <div cdkDropList (cdkDropListDropped)=\"drop($event)\" cdkDropListOrientation=\"horizontal\"\n [cdkDropListData]=\"{item:transformation,index:i}\">\n <div class=\"flex items-center\">\n <div class=\"new-transformation flex items-center justify-center w-6 h-6\">\n <a [matMenuTriggerFor]=\"addTransformation\"\n class=\"items-center add-transformation text-primary\">\n <mat-icon class=\"flex items-center w-5 h-5 text-xl\">add_circle</mat-icon>\n </a>\n <mat-menu #addTransformation=\"matMenu\">\n <button mat-menu-item (click)=\"insertTransformation(i, 'columns', transformation)\">\n Insert Column Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'formula', transformation)\">\n Insert Formula Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'join', transformation)\">\n Insert Join Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'summarise', transformation)\">\n Insert Summarise Transformation\n </button>\n <button mat-menu-item (click)=\"insertTransformation(i, 'filter', transformation)\">\n Insert Filter Transformation\n </button>\n </mat-menu>\n </div>\n <div cdkDrag class=\"pl-0 example-box badge-item w-auto m-0\" cdkOverlayOrigin\n #trigger=\"cdkOverlayOrigin\"\n [class]=\"{active: transformation._active, 'exclude bg-orange-50 border-orange-200': !!transformation.exclude, 'bg-indigo-50 border-indigo-200': (transformation.type === 'filter' && transformation.hide === false)}\">\n <button class=\"-mt-0.5\" title=\"Show transformation details\" mat-icon-button\n (click)=\"showTransformationDetail(transformation)\">\n @if (transformation.type === 'columns') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >table_chart</span>\n }\n @if (transformation.type === 'formula') {\n <span class=\"material-symbols-outlined text-xl\"\n >functions</span>\n }\n @if (transformation.type === 'join') {\n <span class=\"material-symbols-outlined text-xl\">merge_type</span>\n }\n @if (transformation.type === 'summarise') {\n <span class=\"material-symbols-outlined ml-1 text-xl\"\n >pivot_table_chart</span>\n }\n @if (transformation.type === 'filter') {\n <span class=\"material-symbols-outlined text-xl\"\n >filter_alt</span>\n }\n </button>\n <span class=\"whitespace-nowrap cursor-pointer\"\n (click)=\"editTerminatingTransformation(transformation)\">{{ transformation._label }}</span>\n @if (transformation.exclude) {\n <button class=\"-ml-1\" [title]=\"'Re-enable this transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon class=\"text-orange-400\">replay</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 === terminatingTransformations.length) {\n <button class=\"-ml-1\" [title]=\"'Disable transformation'\"\n mat-icon-button (click)=\"disableTransformation(transformation, i)\">\n <mat-icon>block</mat-icon>\n </button>\n }\n @if (!transformation.exclude && i + 1 !== terminatingTransformations.length) {\n <button class=\"-ml-1\" [matMenuTriggerFor]=\"disableMenu\"\n [title]=\"'Disable transformation'\"\n mat-icon-button>\n <mat-icon>block</mat-icon>\n </button>\n <mat-menu #disableMenu=\"matMenu\">\n <button mat-menu-item (click)=\"disableTransformation(transformation, i)\">\n Disable this transformation\n </button>\n <button mat-menu-item (click)=\"excludeUpstreamTransformations(transformation)\">\n Disable subsequent transformation(s)\n </button>\n </mat-menu>\n }\n <button class=\"-ml-1\" title=\"Remove this transformation\" mat-icon-button color=\"primary\"\n (click)=\"removeTransformation(transformation, true, null, transformation._active)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n <ng-template\n cdkConnectedOverlay\n [cdkConnectedOverlayOrigin]=\"trigger\"\n [cdkConnectedOverlayOpen]=\"transformation._showDetail\">\n <div class=\"p-4 w-96 bg-white shadow rounded\">\n @if (transformation.type === 'summarise') {\n <p class=\"text-sm text-gray-700 mb-0\">\n <b>SELECT </b>@for (expression of transformation.config.expressions; track expression; let i = $index) {\n <span\n >@if (i > 0) {\n <span\n >, </span>\n }{{ expression.customExpression || expression.expressionType + '(' + (expression.fieldName || '') + ')' }}</span>\n }\n @if (transformation.config.summariseFieldNames.length) {\n <br><b>GROUP\n BY </b> {{ transformation.config.summariseFieldNames.join(', ') }}\n }\n </p>\n }\n @if (transformation.type === 'formula') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>EXPRESSION</b> {{ decodeURIComponent(transformation.config.expressions[0].expression) }}\n </div>\n }\n @if (transformation.type === 'columns') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>COLUMNS</b> {{ _.map(transformation.config.columns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'join') {\n <div class=\"text-sm text-gray-700 mb-0\">\n <b>JOIN\n COLUMNS</b> {{ _.map(transformation.config.joinColumns, 'title').join(', ') }}\n </div>\n }\n @if (transformation.type === 'filter') {\n @for (filter of transformation.config.filters; track filter) {\n <div\n class=\"text-sm text-gray-700 mb-0\">\n <b>FILTER</b> {{ filter.lhsExpression }} <b>{{ filter.filterType }}</b> {{ filter.rhsExpression }}\n </div>\n }\n }\n </div>\n </ng-template>\n </div>\n </div>\n }\n @if (_.some(terminatingTransformations, {exclude: true}) && i === terminatingTransformations.length - 1) {\n <button\n class=\"ml-4 flex items-center border-none bg-primary text-sm rounded-md text-white pr-2 pl-1 py-0.5\"\n (click)=\"enableAllTransformation()\">\n <mat-icon class=\"mr-1 text-base\">replay</mat-icon>\n Enable All\n </button>\n }\n }\n </div>\n</div>\n}\n</div>\n\n<div class=\"cell-header\">\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <div class=\"transformation-listing py-2 filters-list\"\n >\n <a class=\"list-title flex items-center\" (click)=\"showFilters = !showFilters\">\n Filters \n @if (!showFilters) {\n <mat-icon>expand_more</mat-icon>\n }\n @if (showFilters) {\n <mat-icon>expand_less</mat-icon>\n }\n </a>\n @for (filterTransformation of _.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}); track filterTransformation) {\n @if (_.every(filterTransformation.config.filters[0])) {\n <div class=\"badge-item pl-2 mr-1\"\n (click)=\"showFilters = !showFilters\">\n <span class=\"cursor-pointer\" [innerHtml]=\"getFilterString(filterTransformation.config)\"></span>\n </div>\n }\n }\n </div>\n }\n</div>\n\n@if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length\n && showFilters) {\n <div class=\"dataset-filters\" id=\"datasetFilters\"\n >\n @for (transformation of datasetInstanceSummary.transformationInstances; track transformation; let i = $index) {\n @if (transformation.type === 'filter' && transformation.hide === false) {\n <div class=\"dataset-filter border-b border-gray-200\">\n <button mat-stroked-button class=\"mr-2 bg-white remove-filter\" color=\"warn\"\n (click)=\"removeTransformation(transformation, true, i)\">\n Remove Filter\n </button>\n @if (filterFields.length) {\n <ki-dataset-filters [filterFields]=\"filterFields\"\n [openSide]=\"openSide\" [parameterValues]=\"filterParameterValues\"\n [filterJunction]=\"transformation.config\"></ki-dataset-filters>\n }\n @if (_.filter(datasetInstanceSummary.transformationInstances, {type: 'filter', hide: false}).length) {\n <button\n mat-flat-button class=\"apply-filter mr-2\" color=\"primary\"\n (click)=\"applyFilters()\" [disabled]=\"!filterJunction.filters.length\">\n Apply Filters\n </button>\n }\n </div>\n }\n }\n </div>\n}\n\n<div class=\"cell-header\">\n @if (_.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'})) {\n <div class=\"transformation-listing sort\"\n >\n <div class=\"list-title\">\n Sort\n </div>\n <div class=\"flex flex-wrap\">\n @for (sort of _.find(datasetInstanceSummary.transformationInstances, {type: 'multisort'}).config.sorts; track sort; let i = $index) {\n <div class=\"badge-item outline\"\n [class]=\"{'exclude bg-orange-50 border-orange-200': _.find(datasetInstanceSummary.transformationInstances, {exclude: true})}\"\n >\n <span>{{ _.startCase(sort.fieldName) }} <span class=\"uppercase\">{{ sort.direction }}</span></span>\n <button mat-icon-button (click)=\"removeFilter(i)\">\n <mat-icon>cancel</mat-icon>\n </button>\n </div>\n }\n </div>\n </div>\n }\n</div>\n\n<div class=\"h-full table-overflow overflow-scroll\">\n @if (displayedColumns.length) {\n <table mat-table [dataSource]=\"tableData\" matSort (matSortChange)=\"sort($event)\"\n class=\"block sticky\">\n @for (column of filterFields; track column) {\n <ng-container [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef mat-sort-header\n class=\"text-xs font-semibold text-gray-900 py-3.5 px-4\"> {{ column.title }}\n </th>\n <td mat-cell *matCellDef=\"let element\" class=\"py-3 px-4\">\n @if (!Array.isArray(element[column.name]) && !_.isPlainObject(element[column.name])) {\n @if (element[column.name] && String(element[column.name]).length <= 100) {\n <div [innerHTML]=\"element[column.name]\"></div>\n }\n @if (element[column.name] && String(element[column.name]).length > 100) {\n <div>{{ element[column.name].substring(0, 100) + '...' }}</div>\n <a (click)=\"viewFullItemData(element[column.name], column.name)\"\n class=\"flex items-center text-sm text-cta\">\n view more\n <svg xmlns=\"http://www.w3.org/2000/svg\" class=\"ml-1 h-4 w-4\" fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\"\n d=\"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14\"/>\n </svg>\n </a>\n }\n @if (!element[column.name]) {\n @if (element[column.name] === null) {\n <span class=\"font-mono text-gray-400\">null</span>\n }\n @if (element[column.name] !== null) {\n <span>{{ element[column.name] }}</span>\n }\n }\n }\n @if (Array.isArray(element[column.name])) {\n Contains {{ element[column.name].length }} items\n }\n @if (_.isPlainObject(element[column.name])) {\n <span class=\"text-xs font-mono\" [innerHTML]=\"toJSON(element[column.name])\"></span>\n }\n </td>\n </ng-container>\n }\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\" class=\"h-auto\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n }\n</div>\n\n\n<div class=\"border-b border-t bg-gray-50 px-4 py-1 flex align-center justify-end\">\n\n <div class=\"flex items-center\">\n <div class=\"text-sm text-gray-500 mr-10\">\n @if (dataset) {\n Showing {{ offset + 1 }} - {{ (page * limit) - (limit - tableData.length) }}\n }\n </div>\n <select [value]=\"limit\" (change)=\"pageSizeChange($event.target.value)\"\n class=\"mr-8 p-1.5\">\n <option [value]=\"1\">1</option>\n <option [value]=\"5\">5</option>\n <option [value]=\"10\">10</option>\n <option [value]=\"25\">25</option>\n <option [value]=\"50\">50</option>\n <option [value]=\"100\">100</option>\n <option [value]=\"250\">250</option>\n <option [value]=\"1000\">1000</option>\n </select>\n <button mat-icon-button class=\"mr-4\" (click)=\"decreaseOffset()\" [disabled]=\"page <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <button mat-icon-button (click)=\"increaseOffset()\" [disabled]=\"endOfResults\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n </div>\n</div>\n", styles: [":host{display:flex;flex-direction:column;position:relative;height:100%}:host>div{flex:0 1 auto}.divider{width:1px;height:17px;background-color:#cecece}.new-transformation .add-transformation{display:none}.new-transformation:hover .add-transformation{display:flex}.long-running{position:fixed;inset:0;background-color:#ffffffb3;z-index:99999;display:flex;align-items:center;justify-content:center;-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}.long-running .loading-box{position:relative;margin-bottom:2rem}.long-running .loading-box div{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:1.2rem;font-weight:500}.long-running p{font-size:1.1rem}.cell-header{width:100%;display:flex;align-items:center;justify-content:space-between}.cell-header.end{justify-content:flex-end}.cell-header.sorting{min-height:43px}.dataset-data-actions{display:flex;align-items:center;flex-wrap:wrap;width:100%;justify-content:flex-end;background-color:#fff;margin-top:-1px}.dataset-data-actions button{min-width:50px;padding:0 13px;color:#505050}.dataset-data-actions .divider{margin:0 .5rem;width:1px;height:36px;background-color:#ddd}.parameter-listing label{flex-direction:row;align-items:center}.parameter-listing label .parameter-input{border-radius:4px;padding-left:.5rem;height:36px;display:flex;align-items:center}.parameter-listing label .parameter-input .param-period-picker{padding:5px}.parameter-listing label .parameter-input button{color:#8e8e8e}.parameter-listing label .parameter-input button.edit-parameter{visibility:hidden}.parameter-listing label .parameter-input button.mat-icon-button{width:30px;height:30px;line-height:30px;align-self:center}.parameter-listing label .parameter-input button.mat-icon-button mat-icon{font-size:20px;width:20px;height:20px;line-height:20px}.parameter-listing label .parameter-input input{font-size:.9rem;padding:.25rem .45rem;width:175px}.parameter-listing label .parameter-input:hover .edit-parameter{visibility:visible}.transformation-listing{display:flex;align-items:center;width:100%;background-color:#00000012;border-bottom:1px solid #ddd;min-height:47px}.transformation-listing .list-title{text-transform:uppercase;font-size:.75rem;padding:0 1rem;border-right:2px solid #ddd;color:#4c4c4c;font-weight:500;letter-spacing:1px}.transformation-listing .badge-item{display:flex;align-items:center;margin-left:1rem;padding-left:1rem;border-radius:20px;background-color:#fff;border:1px solid #ddd;height:30px}.transformation-listing .badge-item.exclude{opacity:.8}.transformation-listing .badge-item:hover{background-color:#fcfcfc}.transformation-listing .badge-item span{margin-right:.5rem;color:#0000008a}.transformation-listing .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.transformation-listing .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}.dataset-filters{position:relative;overflow-y:scroll;flex:none!important;max-height:400px}.dataset-filters .dataset-filter{position:relative}.dataset-filters .dataset-filter .apply-filter{position:absolute;bottom:.5rem;right:0;z-index:10}.dataset-filters .dataset-filter .remove-filter{position:absolute;top:.5rem;right:0;z-index:10}.badge-holder{display:flex;align-items:center;margin:.25rem 0}.badge-holder .badge-item{display:flex;align-items:center;padding-left:1rem;border-radius:20px}.badge-holder .badge-item.outline{background-color:#fff;border:1px solid #efefef}.badge-holder .badge-item span{margin-right:.5rem;color:#0000008a}.badge-holder .badge-item button.mat-icon-button{width:33px;height:33px;line-height:33px}.badge-holder .badge-item button.mat-icon-button mat-icon{font-size:20px;height:20px;width:20px;line-height:20px;color:#0000008a}table{position:relative;border-collapse:collapse}table.sticky th{position:sticky;top:0;background-color:#f5f5f5;border-top:none!important;border-bottom:none!important;box-shadow:inset 0 -1px #ddd}table th.settings{padding:0}table td{max-width:400px;word-wrap:break-word;padding-top:.5rem;padding-bottom:.5rem;padding-right:1rem;min-width:150px;width:1%}table td.settings{max-width:25px;min-width:25px}table::-webkit-scrollbar{width:.75em;background:transparent}table::-webkit-scrollbar-thumb{background:#d2d2d2}table tbody:nth-of-type(1) tr:nth-of-type(1) td{border-top:none!important}table thead th{border-top:none!important;border-bottom:none!important;box-shadow:inset 0 2px #000,inset 0 -2px #000;padding:2px 0}table thead th{background-clip:padding-box}.table-overflow::-webkit-scrollbar{width:.75em;background:transparent}.table-overflow::-webkit-scrollbar-thumb{background:#d2d2d2}.paging-toolbar{position:sticky;bottom:-20px;left:0;background-color:#fff;right:0;padding:1rem}table{text-align:left;position:relative;border-collapse:collapse}th,td{padding:.25rem}\n"] }]
|
|
3562
3579
|
}], ctorParameters: () => [{ type: i1$1.MatDialogRef }, { type: undefined, decorators: [{
|
|
3563
3580
|
type: Inject,
|
|
3564
3581
|
args: [MAT_DIALOG_DATA]
|
|
@@ -9014,7 +9031,12 @@ class FeedsComponent {
|
|
|
9014
9031
|
async ngOnInit() {
|
|
9015
9032
|
this.canHaveAPIConnections = this.projectService.doesActiveProjectHavePrivilege('feedaccess');
|
|
9016
9033
|
if (this.canHaveAPIConnections) {
|
|
9017
|
-
|
|
9034
|
+
try {
|
|
9035
|
+
this.apiKeys = await this.http.get('/account/apikey/first/feedaccess').toPromise();
|
|
9036
|
+
}
|
|
9037
|
+
catch (e) {
|
|
9038
|
+
// Ignore
|
|
9039
|
+
}
|
|
9018
9040
|
merge(this.searchText, this.reload)
|
|
9019
9041
|
.pipe(debounceTime(300),
|
|
9020
9042
|
// distinctUntilChanged(),
|