dolfo-angular 1.212.0 → 1.214.0

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.
@@ -2,7 +2,7 @@ import * as i0 from '@angular/core';
2
2
  import { Directive, Input, ChangeDetectionStrategy, Component, InjectionToken, Injectable, inject, Inject, signal, Pipe, EventEmitter, Output, ViewChild, forwardRef, booleanAttribute, Injector, ChangeDetectorRef, ViewChildren, TemplateRef, ContentChild, EnvironmentInjector, createComponent, NgModule } from '@angular/core';
3
3
  import * as i1$1 from '@angular/forms';
4
4
  import { ControlContainer, FormControl, Validators, NG_VALUE_ACCESSOR, NG_VALIDATORS, FormGroupDirective, FormGroup, ReactiveFormsModule } from '@angular/forms';
5
- import { BehaviorSubject, map, tap, distinctUntilChanged, filter, mergeMap, of, delay, catchError, throwError, zip, fromEvent, from, concatAll, race } from 'rxjs';
5
+ import { BehaviorSubject, map, tap, distinctUntilChanged, filter, delay, mergeMap, of, catchError, throwError, zip, fromEvent, from, concatAll, race } from 'rxjs';
6
6
  import * as i1 from '@angular/common';
7
7
  import { formatDate, DecimalPipe, APP_BASE_HREF, CommonModule } from '@angular/common';
8
8
  import { HttpClient, HttpErrorResponse } from '@angular/common/http';
@@ -42,6 +42,7 @@ var ColumnDataType;
42
42
  ColumnDataType[ColumnDataType["TEXT"] = 0] = "TEXT";
43
43
  ColumnDataType[ColumnDataType["DATE"] = 1] = "DATE";
44
44
  ColumnDataType[ColumnDataType["DATETIME"] = 2] = "DATETIME";
45
+ ColumnDataType[ColumnDataType["LINK"] = 3] = "LINK";
45
46
  })(ColumnDataType || (ColumnDataType = {}));
46
47
  class GridConfig {
47
48
  config;
@@ -135,10 +136,6 @@ const ROUTE_CHECK_SERVICE = new InjectionToken("ROUTE_CHECK_SERVICE", {
135
136
  }
136
137
  });
137
138
 
138
- var StoreLists;
139
- (function (StoreLists) {
140
- StoreLists[StoreLists["EMPTY"] = 0] = "EMPTY";
141
- })(StoreLists || (StoreLists = {}));
142
139
  var StorageValues;
143
140
  (function (StorageValues) {
144
141
  StorageValues["TOKEN"] = "token";
@@ -267,7 +264,7 @@ class DialogService {
267
264
  ...input,
268
265
  _dialogId: new Date().getTime()
269
266
  }));
270
- return this.getLastWaiter().pipe(filter(d => d != null));
267
+ return this.getLastWaiter().pipe(filter(d => d != null), delay(0));
271
268
  };
272
269
  openDialogComponent = (component) => this.openDialog({
273
270
  message: null,
@@ -1621,7 +1618,7 @@ class DialogComponent extends Formable {
1621
1618
  this.form.forEach(f => this.formGroup.addControl(f.name, f.control));
1622
1619
  }
1623
1620
  }
1624
- submit = () => of(null);
1621
+ submit = (_formValue) => of(null);
1625
1622
  getIcon = () => {
1626
1623
  if (this.type === "info")
1627
1624
  return { icon: "info", color: "info" };
@@ -2269,7 +2266,7 @@ class NavigateDirective extends Subscriptable {
2269
2266
  constructor(storeService, router, elementRef) {
2270
2267
  super();
2271
2268
  this.elementRef = elementRef;
2272
- this.isLink = elementRef.nativeElement.tagName.toLocaleLowerCase() === "a";
2269
+ this.isLink = elementRef.nativeElement.tagName.toLowerCase() === "a";
2273
2270
  this.addSubscription(fromEvent(elementRef.nativeElement, "click").subscribe(e => {
2274
2271
  if (this.isLink)
2275
2272
  e.preventDefault();
@@ -2514,7 +2511,7 @@ class GridComponent {
2514
2511
  this.translateService = translateService;
2515
2512
  this.sanitizer = sanitizer;
2516
2513
  }
2517
- resolveField = (item, { field, formatter, dataType }) => {
2514
+ resolveField = (item, { field, formatter, dataType, onLink }) => {
2518
2515
  let value = field
2519
2516
  .toString()
2520
2517
  .split(".")
@@ -2523,15 +2520,32 @@ class GridComponent {
2523
2520
  value = this.translateService.formatDate(value);
2524
2521
  else if (dataType === ColumnDataType.DATETIME)
2525
2522
  value = this.translateService.formatDateTime(value);
2526
- const retValue = formatter ? formatter(value) : value;
2523
+ let retValue = formatter ? formatter(value) : value;
2524
+ if (dataType === ColumnDataType.LINK)
2525
+ retValue = `<a href="javascript:void(0)">${retValue}</a>`;
2527
2526
  return this.sanitizer.bypassSecurityTrustHtml(retValue);
2528
2527
  };
2528
+ checkLink = (e, col, item, cell) => {
2529
+ if (col.dataType !== ColumnDataType.LINK || !col.onLink)
2530
+ return;
2531
+ const colValue = col.field
2532
+ .toString()
2533
+ .split(".")
2534
+ .reduce((prev, curr) => prev?.[curr], item), htmlTarget = e.target;
2535
+ if (htmlTarget.tagName.toLowerCase() === "a")
2536
+ col.onLink(colValue);
2537
+ else {
2538
+ const a = cell.querySelector("a[href]");
2539
+ if (a.contains(htmlTarget))
2540
+ col.onLink(colValue);
2541
+ }
2542
+ };
2529
2543
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: GridComponent, deps: [{ token: TranslateService }, { token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component });
2530
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: GridComponent, isStandalone: false, selector: "dolfo-grid", inputs: { config: "config" }, ngImport: i0, template: "@let loading = config.isLoading$() | async;\r\n\r\n<div class=\"grid-container\" [class.loading]=\"loading\">\r\n @if(loading){\r\n <div class=\"grid-loading\">\r\n <dolfo-icon name=\"spinner2\"></dolfo-icon>\r\n </div>\r\n }\r\n\r\n <table>\r\n @let columns = config.getColumns();\r\n @let showActions = config.hasActions;\r\n @let selection = config.getSelectionConfig();\r\n @let colSpan = columns.length + (showActions ? 1 : 0) + (selection ? 1 : 0);\r\n \r\n <thead>\r\n <tr>\r\n @if(selection){\r\n <th [style]=\"{ width: 0 }\">\r\n @if(selection.showSelectAll && selection.type === \"multiple\"){\r\n <input type=\"checkbox\" [checked]=\"config.isAllSelected()\" (change)=\"config.toggleSelectAll()\" />\r\n }\r\n </th>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <th [ngStyle]=\"{ width: col.width + 'px', maxWidth: col.width + 'px' }\">{{ col.label | translate }}</th>\r\n }\r\n \r\n @if(showActions){\r\n <th>{{ \"grid.actions\" | translate }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n \r\n <tbody>\r\n @let list = config.getList$() | async;\r\n \r\n @if(list.length > 0){\r\n @for(item of list; track config.getUniqueId(item)){\r\n @let itemActions = config.getActions$(item) | async;\r\n @let rowClass = config.getRowClass(item);\r\n \r\n <tr (click)=\"config.getEvents()?.onRowClick?.(item)\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\">\r\n @if(selection){\r\n <td [ngClass]=\"rowClass\" class=\"align-center\">\r\n <input type=\"checkbox\" [checked]=\"config.isItemSelected(item)\" (change)=\"config.toggleSelection(item)\" />\r\n </td>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <td [ngStyle]=\"{ width: col.width + 'px' }\" [ngClass]=\"rowClass\" [class.align-right]=\"col.align === 'right'\" [class.align-center]=\"col.align === 'center'\" [innerHTML]=\"resolveField(item, col)\"></td>\r\n }\r\n \r\n @if(showActions){\r\n <td class=\"align-center actions\" [ngClass]=\"rowClass\">\r\n @if(itemActions.length > 0){\r\n <dolfo-button color=\"secondary\" [dolfoTooltip]=\"'grid.showActions' | translate\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\" openOnClick>\r\n <dolfo-icon name=\"flickr\"></dolfo-icon>\r\n </dolfo-button>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }@else {\r\n <tr>\r\n <td [colSpan]=\"colSpan\" class=\"align-center\">{{ \"grid.noResults\" | translate }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: ContextMenuDirective, selector: "[dolfoContextMenu]", inputs: ["dolfoContextMenu", "openOnClick", "useElRef", "position"] }, { kind: "directive", type: TooltipDirective, selector: "[dolfoTooltip]", inputs: ["dolfoTooltip", "direction"] }, { kind: "component", type: ButtonComponent, selector: "dolfo-button", inputs: ["type", "disabled", "color", "loading", "size"], outputs: ["onClick", "onBlur", "onFocus"] }, { kind: "component", type: IconWrapperComponent, selector: "dolfo-icon", inputs: ["name"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
2544
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: GridComponent, isStandalone: false, selector: "dolfo-grid", inputs: { config: "config" }, ngImport: i0, template: "@let loading = config.isLoading$() | async;\r\n\r\n<div class=\"grid-container\" [class.loading]=\"loading\">\r\n @if(loading){\r\n <div class=\"grid-loading\">\r\n <dolfo-icon name=\"spinner2\"></dolfo-icon>\r\n </div>\r\n }\r\n\r\n <table>\r\n @let columns = config.getColumns();\r\n @let showActions = config.hasActions;\r\n @let selection = config.getSelectionConfig();\r\n @let colSpan = columns.length + (showActions ? 1 : 0) + (selection ? 1 : 0);\r\n \r\n <thead>\r\n <tr>\r\n @if(selection){\r\n <th [style]=\"{ width: 0 }\">\r\n @if(selection.showSelectAll && selection.type === \"multiple\"){\r\n <input type=\"checkbox\" [checked]=\"config.isAllSelected()\" (change)=\"config.toggleSelectAll()\" />\r\n }\r\n </th>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <th [ngStyle]=\"{ width: col.width + 'px', maxWidth: col.width + 'px' }\">{{ col.label | translate }}</th>\r\n }\r\n \r\n @if(showActions){\r\n <th>{{ \"grid.actions\" | translate }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n \r\n <tbody>\r\n @let list = config.getList$() | async;\r\n \r\n @if(list.length > 0){\r\n @for(item of list; track config.getUniqueId(item)){\r\n @let itemActions = config.getActions$(item) | async;\r\n @let rowClass = config.getRowClass(item);\r\n \r\n <tr (click)=\"config.getEvents()?.onRowClick?.(item)\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\">\r\n @if(selection){\r\n <td [ngClass]=\"rowClass\" class=\"align-center\">\r\n <input type=\"checkbox\" [checked]=\"config.isItemSelected(item)\" (change)=\"config.toggleSelection(item)\" />\r\n </td>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <td #cell [ngStyle]=\"{ width: col.width + 'px' }\" [ngClass]=\"rowClass\" [class.align-right]=\"col.align === 'right'\" [class.align-center]=\"col.align === 'center'\" (click)=\"checkLink($event, col, item, cell)\" [innerHTML]=\"resolveField(item, col)\"></td>\r\n }\r\n \r\n @if(showActions){\r\n <td class=\"align-center actions\" [ngClass]=\"rowClass\">\r\n @if(itemActions.length > 0){\r\n <dolfo-button color=\"secondary\" [dolfoTooltip]=\"'grid.showActions' | translate\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\" openOnClick>\r\n <dolfo-icon name=\"flickr\"></dolfo-icon>\r\n </dolfo-button>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }@else {\r\n <tr>\r\n <td [colSpan]=\"colSpan\" class=\"align-center\">{{ \"grid.noResults\" | translate }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: ContextMenuDirective, selector: "[dolfoContextMenu]", inputs: ["dolfoContextMenu", "openOnClick", "useElRef", "position"] }, { kind: "directive", type: TooltipDirective, selector: "[dolfoTooltip]", inputs: ["dolfoTooltip", "direction"] }, { kind: "component", type: ButtonComponent, selector: "dolfo-button", inputs: ["type", "disabled", "color", "loading", "size"], outputs: ["onClick", "onBlur", "onFocus"] }, { kind: "component", type: IconWrapperComponent, selector: "dolfo-icon", inputs: ["name"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] });
2531
2545
  }
2532
2546
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: GridComponent, decorators: [{
2533
2547
  type: Component,
2534
- args: [{ selector: "dolfo-grid", standalone: false, template: "@let loading = config.isLoading$() | async;\r\n\r\n<div class=\"grid-container\" [class.loading]=\"loading\">\r\n @if(loading){\r\n <div class=\"grid-loading\">\r\n <dolfo-icon name=\"spinner2\"></dolfo-icon>\r\n </div>\r\n }\r\n\r\n <table>\r\n @let columns = config.getColumns();\r\n @let showActions = config.hasActions;\r\n @let selection = config.getSelectionConfig();\r\n @let colSpan = columns.length + (showActions ? 1 : 0) + (selection ? 1 : 0);\r\n \r\n <thead>\r\n <tr>\r\n @if(selection){\r\n <th [style]=\"{ width: 0 }\">\r\n @if(selection.showSelectAll && selection.type === \"multiple\"){\r\n <input type=\"checkbox\" [checked]=\"config.isAllSelected()\" (change)=\"config.toggleSelectAll()\" />\r\n }\r\n </th>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <th [ngStyle]=\"{ width: col.width + 'px', maxWidth: col.width + 'px' }\">{{ col.label | translate }}</th>\r\n }\r\n \r\n @if(showActions){\r\n <th>{{ \"grid.actions\" | translate }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n \r\n <tbody>\r\n @let list = config.getList$() | async;\r\n \r\n @if(list.length > 0){\r\n @for(item of list; track config.getUniqueId(item)){\r\n @let itemActions = config.getActions$(item) | async;\r\n @let rowClass = config.getRowClass(item);\r\n \r\n <tr (click)=\"config.getEvents()?.onRowClick?.(item)\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\">\r\n @if(selection){\r\n <td [ngClass]=\"rowClass\" class=\"align-center\">\r\n <input type=\"checkbox\" [checked]=\"config.isItemSelected(item)\" (change)=\"config.toggleSelection(item)\" />\r\n </td>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <td [ngStyle]=\"{ width: col.width + 'px' }\" [ngClass]=\"rowClass\" [class.align-right]=\"col.align === 'right'\" [class.align-center]=\"col.align === 'center'\" [innerHTML]=\"resolveField(item, col)\"></td>\r\n }\r\n \r\n @if(showActions){\r\n <td class=\"align-center actions\" [ngClass]=\"rowClass\">\r\n @if(itemActions.length > 0){\r\n <dolfo-button color=\"secondary\" [dolfoTooltip]=\"'grid.showActions' | translate\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\" openOnClick>\r\n <dolfo-icon name=\"flickr\"></dolfo-icon>\r\n </dolfo-button>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }@else {\r\n <tr>\r\n <td [colSpan]=\"colSpan\" class=\"align-center\">{{ \"grid.noResults\" | translate }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>" }]
2548
+ args: [{ selector: "dolfo-grid", standalone: false, template: "@let loading = config.isLoading$() | async;\r\n\r\n<div class=\"grid-container\" [class.loading]=\"loading\">\r\n @if(loading){\r\n <div class=\"grid-loading\">\r\n <dolfo-icon name=\"spinner2\"></dolfo-icon>\r\n </div>\r\n }\r\n\r\n <table>\r\n @let columns = config.getColumns();\r\n @let showActions = config.hasActions;\r\n @let selection = config.getSelectionConfig();\r\n @let colSpan = columns.length + (showActions ? 1 : 0) + (selection ? 1 : 0);\r\n \r\n <thead>\r\n <tr>\r\n @if(selection){\r\n <th [style]=\"{ width: 0 }\">\r\n @if(selection.showSelectAll && selection.type === \"multiple\"){\r\n <input type=\"checkbox\" [checked]=\"config.isAllSelected()\" (change)=\"config.toggleSelectAll()\" />\r\n }\r\n </th>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <th [ngStyle]=\"{ width: col.width + 'px', maxWidth: col.width + 'px' }\">{{ col.label | translate }}</th>\r\n }\r\n \r\n @if(showActions){\r\n <th>{{ \"grid.actions\" | translate }}</th>\r\n }\r\n </tr>\r\n </thead>\r\n \r\n <tbody>\r\n @let list = config.getList$() | async;\r\n \r\n @if(list.length > 0){\r\n @for(item of list; track config.getUniqueId(item)){\r\n @let itemActions = config.getActions$(item) | async;\r\n @let rowClass = config.getRowClass(item);\r\n \r\n <tr (click)=\"config.getEvents()?.onRowClick?.(item)\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\">\r\n @if(selection){\r\n <td [ngClass]=\"rowClass\" class=\"align-center\">\r\n <input type=\"checkbox\" [checked]=\"config.isItemSelected(item)\" (change)=\"config.toggleSelection(item)\" />\r\n </td>\r\n }\r\n\r\n @for(col of columns; track col.label){\r\n <td #cell [ngStyle]=\"{ width: col.width + 'px' }\" [ngClass]=\"rowClass\" [class.align-right]=\"col.align === 'right'\" [class.align-center]=\"col.align === 'center'\" (click)=\"checkLink($event, col, item, cell)\" [innerHTML]=\"resolveField(item, col)\"></td>\r\n }\r\n \r\n @if(showActions){\r\n <td class=\"align-center actions\" [ngClass]=\"rowClass\">\r\n @if(itemActions.length > 0){\r\n <dolfo-button color=\"secondary\" [dolfoTooltip]=\"'grid.showActions' | translate\" [dolfoContextMenu]=\"itemActions\" position=\"bottom-right\" openOnClick>\r\n <dolfo-icon name=\"flickr\"></dolfo-icon>\r\n </dolfo-button>\r\n }\r\n </td>\r\n }\r\n </tr>\r\n }\r\n }@else {\r\n <tr>\r\n <td [colSpan]=\"colSpan\" class=\"align-center\">{{ \"grid.noResults\" | translate }}</td>\r\n </tr>\r\n }\r\n </tbody>\r\n </table>\r\n</div>" }]
2535
2549
  }], ctorParameters: () => [{ type: TranslateService }, { type: i1$2.DomSanitizer }], propDecorators: { config: [{
2536
2550
  type: Input,
2537
2551
  args: [{ required: true }]
@@ -2588,5 +2602,5 @@ const errorInterceptor = (req, next) => {
2588
2602
  * Generated bundle index. Do not edit.
2589
2603
  */
2590
2604
 
2591
- export { AutocompleteComponent, BaseAppComponent, BaseFormInput, ButtonComponent, CONTEXT_MENU_DESTROY_TOKEN, ColumnAlign, ColumnDataType, ComboboxComponent, ContextMenuComponent, ContextMenuDirective, ContextMenuService, DatepickerComponent, DialogActionType, DialogComponent, DialogContentComponent, DialogFooterComponent, DialogHeaderComponent, DialogLayoutComponent, DialogLayoutModule, DialogService, DialogUtilsService, DirectivesModule, FormComponent, FormModule, Formable, GridComponent, GridConfig, GridModule, ICON_COMPONENT, IconComponent, IconWrapperComponent, InputCheckboxComponent, InputContainerComponent, InputRadioComponent, InputTextComponent, LANGUAGE_TOKEN, LayoutModule, LoaderComponent, MAX_DEVICE_SIZE, MAX_SMALL_DEVICE, NavigateDirective, NotificationComponent, NotificationService, OverlayManager, POPOVER_DESTROY_TOKEN, PopoverComponent, PopoverDirective, PopoverService, ROUTE_CHECK_SERVICE, RouteCheckService, RouteConfig, ScrollDragDirective, StorageValues, StoreLists, StoreService, Subscriptable, TOOLTIP_DESTROY_TOKEN, TRANSLATE_STORAGE_KEY, TooltipComponent, TooltipDirective, TooltipService, TranslatePipe, TranslateService, authInterceptor, errorInterceptor, isDeepEqual, passwordValidator, provideDolfoLanguages };
2605
+ export { AutocompleteComponent, BaseAppComponent, BaseFormInput, ButtonComponent, CONTEXT_MENU_DESTROY_TOKEN, ColumnAlign, ColumnDataType, ComboboxComponent, ContextMenuComponent, ContextMenuDirective, ContextMenuService, DatepickerComponent, DialogActionType, DialogComponent, DialogContentComponent, DialogFooterComponent, DialogHeaderComponent, DialogLayoutComponent, DialogLayoutModule, DialogService, DialogUtilsService, DirectivesModule, FormComponent, FormModule, Formable, GridComponent, GridConfig, GridModule, ICON_COMPONENT, IconComponent, IconWrapperComponent, InputCheckboxComponent, InputContainerComponent, InputRadioComponent, InputTextComponent, LANGUAGE_TOKEN, LayoutModule, LoaderComponent, MAX_DEVICE_SIZE, MAX_SMALL_DEVICE, NavigateDirective, NotificationComponent, NotificationService, OverlayManager, POPOVER_DESTROY_TOKEN, PopoverComponent, PopoverDirective, PopoverService, ROUTE_CHECK_SERVICE, RouteCheckService, RouteConfig, ScrollDragDirective, StorageValues, StoreService, Subscriptable, TOOLTIP_DESTROY_TOKEN, TRANSLATE_STORAGE_KEY, TooltipComponent, TooltipDirective, TooltipService, TranslatePipe, TranslateService, authInterceptor, errorInterceptor, isDeepEqual, passwordValidator, provideDolfoLanguages };
2592
2606
  //# sourceMappingURL=dolfo-angular.mjs.map