1/*
2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import {Component, ElementRef, Inject, Input} from '@angular/core';
17import {assertDefined} from 'common/assert_utils';
18import {Timestamp} from 'common/time';
19import {DiffType} from 'viewers/common/diff_type';
20import {UiPropertyTreeNode} from 'viewers/common/ui_property_tree_node';
21import {TimestampClickDetail, ViewerEvents} from 'viewers/common/viewer_events';
22import {propertyTreeNodeDataViewStyles} from 'viewers/components/styles/tree_node_data_view.styles';
23import {timeButtonStyle} from './styles/clickable_property.styles';
24
25@Component({
26  selector: 'property-tree-node-data-view',
27  template: `
28    <div class="mat-body-1 node-property" *ngIf="node">
29      <span class="property-key"> {{ getKey(node) }} </span>
30      <div *ngIf="node?.formattedValue()" class="property-value" [class]="[timeClass()]">
31        <button
32          *ngIf="isTimestamp()"
33          mat-button
34          color="primary"
35          (click)="onTimestampClicked(node)">
36          {{ node.formattedValue() }}
37        </button>
38        <a *ngIf="!isTimestamp()" [class]="[valueClass()]" class="value new">{{ node.formattedValue() }}</a>
39        <s *ngIf="isModified()" class="old-value">{{ node.getOldValue() }}</s>
40      </div>
41    </div>
42  `,
43  styles: [
44    `
45      .property-value button {
46        white-space: normal;
47      }
48    `,
49    propertyTreeNodeDataViewStyles,
50    timeButtonStyle,
51  ],
52})
53export class PropertyTreeNodeDataViewComponent {
54  @Input() node?: UiPropertyTreeNode;
55
56  constructor(@Inject(ElementRef) private elementRef: ElementRef) {}
57
58  getKey(node: UiPropertyTreeNode) {
59    if (!this.node?.formattedValue()) {
60      return node.getDisplayName();
61    }
62    return node.getDisplayName() + ': ';
63  }
64
65  isTimestamp() {
66    return this.node?.getValue() instanceof Timestamp;
67  }
68
69  onTimestampClicked(timestamp: UiPropertyTreeNode) {
70    const customEvent = new CustomEvent(ViewerEvents.TimestampClick, {
71      bubbles: true,
72      detail: new TimestampClickDetail(timestamp.getValue(), undefined),
73    });
74    this.elementRef.nativeElement.dispatchEvent(customEvent);
75  }
76
77  valueClass() {
78    const property = assertDefined(this.node).formattedValue();
79    if (!property) {
80      return null;
81    }
82
83    if (property === 'null') {
84      return 'null';
85    }
86
87    if (property === 'true') {
88      return 'true';
89    }
90
91    if (property === 'false') {
92      return 'false';
93    }
94
95    if (!isNaN(Number(property))) {
96      return 'number';
97    }
98
99    return null;
100  }
101
102  timeClass() {
103    if (this.isTimestamp()) {
104      return 'time';
105    }
106
107    return null;
108  }
109
110  isModified() {
111    return assertDefined(this.node).getDiff() === DiffType.MODIFIED;
112  }
113}
114