Merge pull request #7365 from kalutkaz/fixMarkdownWidget
[3.4.2] UI: Fix markdown widget
This commit is contained in:
		
						commit
						bbc74d98dd
					
				@ -22,7 +22,6 @@ import { EntityId } from '@shared/models/id/entity-id';
 | 
			
		||||
import { NULL_UUID } from '@shared/models/id/has-uuid';
 | 
			
		||||
import { EntityType, baseDetailsPageByEntityType } from '@shared/models/entity-type.models';
 | 
			
		||||
import { HttpErrorResponse } from '@angular/common/http';
 | 
			
		||||
import { letterSpacing } from 'html2canvas/dist/types/css/property-descriptors/letter-spacing';
 | 
			
		||||
import { TranslateService } from '@ngx-translate/core';
 | 
			
		||||
import { serverErrorCodesTranslations } from '@shared/models/constants';
 | 
			
		||||
 | 
			
		||||
@ -479,6 +478,18 @@ export function flatFormattedData(input: FormattedData[]): FormattedData {
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function flatDataWithoutOverride(data: FormattedData[]): FormattedData {
 | 
			
		||||
  const processingKeyValue = data[0];
 | 
			
		||||
  for (let i = 1; i < data.length; i++) {
 | 
			
		||||
    Object.keys(data[i]).forEach((key) => {
 | 
			
		||||
      if (!isDefinedAndNotNull(processingKeyValue[key]) || isEmptyStr(processingKeyValue[key])) {
 | 
			
		||||
        processingKeyValue[key] = data[i][key];
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
  return processingKeyValue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function mergeFormattedData(first: FormattedData[], second: FormattedData[]): FormattedData[] {
 | 
			
		||||
  const merged = first.concat(second);
 | 
			
		||||
  return _(merged).groupBy(el => el.$datasource)
 | 
			
		||||
 | 
			
		||||
@ -23,12 +23,11 @@ import { DatasourceData, FormattedData } from '@shared/models/widget.models';
 | 
			
		||||
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
 | 
			
		||||
import {
 | 
			
		||||
  createLabelFromPattern,
 | 
			
		||||
  fillDataPattern,
 | 
			
		||||
  flatFormattedData,
 | 
			
		||||
  flatDataWithoutOverride,
 | 
			
		||||
  formattedDataFormDatasourceData,
 | 
			
		||||
  hashCode, isDefinedAndNotNull,
 | 
			
		||||
  isNotEmptyStr,
 | 
			
		||||
  parseFunction, processDataPattern,
 | 
			
		||||
  parseFunction,
 | 
			
		||||
  safeExecute
 | 
			
		||||
} from '@core/utils';
 | 
			
		||||
import cssjs from '@core/css/css';
 | 
			
		||||
@ -119,7 +118,7 @@ export class MarkdownWidgetComponent extends PageComponent implements OnInit {
 | 
			
		||||
    const data = formattedDataFormDatasourceData(initialData);
 | 
			
		||||
    let markdownText = this.settings.useMarkdownTextFunction ?
 | 
			
		||||
      safeExecute(this.markdownTextFunction, [data]) : this.settings.markdownTextPattern;
 | 
			
		||||
    const allData = flatFormattedData(data);
 | 
			
		||||
    const allData: FormattedData = flatDataWithoutOverride(data);
 | 
			
		||||
    markdownText = createLabelFromPattern(markdownText, allData);
 | 
			
		||||
    if (this.markdownText !== markdownText) {
 | 
			
		||||
      this.markdownText = this.utils.customTranslation(markdownText, markdownText);
 | 
			
		||||
 | 
			
		||||
@ -23,7 +23,7 @@ import { DatasourceData, FormattedData } from '@shared/models/widget.models';
 | 
			
		||||
import { DataKeyType } from '@shared/models/telemetry/telemetry.models';
 | 
			
		||||
import {
 | 
			
		||||
  createLabelFromPattern,
 | 
			
		||||
  flatFormattedData,
 | 
			
		||||
  flatDataWithoutOverride,
 | 
			
		||||
  formattedDataFormDatasourceData,
 | 
			
		||||
  isNumber,
 | 
			
		||||
  isObject,
 | 
			
		||||
@ -101,7 +101,7 @@ export class QrCodeWidgetComponent extends PageComponent implements OnInit, Afte
 | 
			
		||||
    const data = formattedDataFormDatasourceData(initialData);
 | 
			
		||||
    const pattern = this.settings.useQrCodeTextFunction ?
 | 
			
		||||
      safeExecute(this.qrCodeTextFunction, [data]) : this.settings.qrCodeTextPattern;
 | 
			
		||||
    const allData = flatFormattedData(data);
 | 
			
		||||
    const allData: FormattedData = flatDataWithoutOverride(data);
 | 
			
		||||
    qrCodeText = createLabelFromPattern(pattern, allData);
 | 
			
		||||
    this.updateQrCodeText(qrCodeText);
 | 
			
		||||
  }
 | 
			
		||||
@ -132,5 +132,4 @@ export class QrCodeWidgetComponent extends PageComponent implements OnInit, Afte
 | 
			
		||||
      this.scheduleUpdateCanvas = true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,8 @@
 | 
			
		||||
  </tb-js-func>
 | 
			
		||||
  <tb-markdown-editor [fxShow]="!markdownWidgetSettingsForm.get('useMarkdownTextFunction').value"
 | 
			
		||||
                      formControlName="markdownTextPattern"
 | 
			
		||||
                      label="{{ 'widgets.markdown.markdown-text-pattern' | translate }}">
 | 
			
		||||
                      label="{{ 'widgets.markdown.markdown-text-pattern' | translate }}"
 | 
			
		||||
                      helpId="widget/editor/widget_js_markdown_pattern">
 | 
			
		||||
  </tb-markdown-editor>
 | 
			
		||||
  <tb-css formControlName="markdownCss"
 | 
			
		||||
          label="{{ 'widgets.markdown.markdown-css' | translate }}">
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@
 | 
			
		||||
  <mat-form-field [fxShow]="!qrCodeWidgetSettingsForm.get('useQrCodeTextFunction').value">
 | 
			
		||||
    <mat-label translate>widgets.qr-code.qr-code-text-pattern</mat-label>
 | 
			
		||||
    <input required matInput formControlName="qrCodeTextPattern">
 | 
			
		||||
    <mat-hint>{{ 'widgets.qr-code.qr-code-text-pattern-hint' | translate }}</mat-hint>
 | 
			
		||||
    <mat-error *ngIf="qrCodeWidgetSettingsForm.get('qrCodeTextPattern').hasError('required')">
 | 
			
		||||
      {{ 'widgets.qr-code.qr-code-text-pattern-required' | translate }}
 | 
			
		||||
    </mat-error>
 | 
			
		||||
 | 
			
		||||
@ -17,25 +17,30 @@
 | 
			
		||||
-->
 | 
			
		||||
<div class="markdown-content" [ngClass]="{'tb-edit-mode': !readonly}"
 | 
			
		||||
     tb-fullscreen [fullscreen]="fullscreen" (fullscreenChanged)="onFullscreen()">
 | 
			
		||||
  <div *ngIf="label" fxLayout="row" fxLayoutAlign="start center" style="height: 40px;">
 | 
			
		||||
  <div fxLayout="row" fxLayoutAlign="start center" style="height: 40px;">
 | 
			
		||||
    <label class="tb-title no-padding" [ngClass]="{'tb-error': !disabled && required && !markdownValue, 'tb-required': !disabled && required}">{{ label }}</label>
 | 
			
		||||
    <span fxFlex></span>
 | 
			
		||||
    <button [fxShow]="!editorMode"
 | 
			
		||||
            class="panel-button"
 | 
			
		||||
            type="button"
 | 
			
		||||
            mat-button (click)="toggleEditMode()">{{ 'markdown.edit' | translate }}</button>
 | 
			
		||||
    <button [fxShow]="editorMode"
 | 
			
		||||
            class="panel-button"
 | 
			
		||||
            type="button"
 | 
			
		||||
            mat-button (click)="toggleEditMode()">{{ 'markdown.preview' | translate }}</button>
 | 
			
		||||
    <div *ngIf = "helpId" [tb-help-popup]="helpId"></div>
 | 
			
		||||
    <fieldset style="width: initial">
 | 
			
		||||
      <div matTooltip="{{(fullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
 | 
			
		||||
           matTooltipPosition="above"
 | 
			
		||||
           style="border-radius: 50%"
 | 
			
		||||
           (click)="fullscreen = !fullscreen">
 | 
			
		||||
        <button type='button' mat-button mat-icon-button class="tb-mat-32 panel-button">
 | 
			
		||||
          <mat-icon class="material-icons">{{ fullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
 | 
			
		||||
        </button>
 | 
			
		||||
      </div>
 | 
			
		||||
    </fieldset>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div [fxShow]="!readonly && !disabled" class="markdown-content-editor">
 | 
			
		||||
    <div class="buttons-panel">
 | 
			
		||||
      <button [fxShow]="!editorMode"
 | 
			
		||||
              class="edit-toggle"
 | 
			
		||||
              type="button"
 | 
			
		||||
              mat-button (click)="toggleEditMode()">{{ 'markdown.edit' | translate }}</button>
 | 
			
		||||
      <button [fxShow]="editorMode"
 | 
			
		||||
              class="edit-toggle"
 | 
			
		||||
              type="button"
 | 
			
		||||
              mat-button (click)="toggleEditMode()">{{ 'markdown.preview' | translate }}</button>
 | 
			
		||||
      <button mat-button mat-icon-button (click)="fullscreen = !fullscreen"
 | 
			
		||||
              matTooltip="{{(fullscreen ? 'fullscreen.exit' : 'fullscreen.expand') | translate}}"
 | 
			
		||||
              matTooltipPosition="above">
 | 
			
		||||
        <mat-icon class="material-icons">{{ fullscreen ? 'fullscreen_exit' : 'fullscreen' }}</mat-icon>
 | 
			
		||||
      </button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div [fxShow]="editorMode" #markdownEditor class="tb-markdown-editor"></div>
 | 
			
		||||
    <div [fxShow]="!editorMode" class="tb-markdown-view-container">
 | 
			
		||||
      <tb-markdown [data]="renderValue" lineNumbers fallbackToPlainMarkdown></tb-markdown>
 | 
			
		||||
 | 
			
		||||
@ -58,20 +58,15 @@
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
  }
 | 
			
		||||
  .buttons-panel {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 5px;
 | 
			
		||||
    right: 24px;
 | 
			
		||||
    z-index: 1;
 | 
			
		||||
    button.edit-toggle {
 | 
			
		||||
      min-width: 32px;
 | 
			
		||||
      min-height: 15px;
 | 
			
		||||
      padding: 4px;
 | 
			
		||||
      margin: 0;
 | 
			
		||||
      font-size: .8rem;
 | 
			
		||||
      line-height: 15px;
 | 
			
		||||
      color: #7b7b7b;
 | 
			
		||||
      background: rgba(220, 220, 220, .35);
 | 
			
		||||
    }
 | 
			
		||||
  button.panel-button {
 | 
			
		||||
    background: rgba(220, 220, 220, .35);
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
    min-width: 32px;
 | 
			
		||||
    min-height: 15px;
 | 
			
		||||
    padding: 4px;
 | 
			
		||||
    font-size: .8rem;
 | 
			
		||||
    line-height: 15px;
 | 
			
		||||
    color: #7b7b7b;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -40,6 +40,8 @@ export class MarkdownEditorComponent implements OnInit, ControlValueAccessor, On
 | 
			
		||||
 | 
			
		||||
  @Input() readonly: boolean;
 | 
			
		||||
 | 
			
		||||
  @Input() helpId: string;
 | 
			
		||||
 | 
			
		||||
  @ViewChild('markdownEditor', {static: true})
 | 
			
		||||
  markdownEditorElmRef: ElementRef;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,68 @@
 | 
			
		||||
#### Markdown pattern
 | 
			
		||||
 | 
			
		||||
<div class="divider"></div>
 | 
			
		||||
<br/>
 | 
			
		||||
 | 
			
		||||
The Markdown template displays the value of the first found key in the entities in the entity alias.
 | 
			
		||||
 | 
			
		||||
<div class="divider"></div>
 | 
			
		||||
<br/>
 | 
			
		||||
 | 
			
		||||
#### Examples
 | 
			
		||||
 | 
			
		||||
Use # to create a Markdown header. The number of characters # specifies the type of header: # - h1, ## - h2, ### - h3, etc.
 | 
			
		||||
 | 
			
		||||
```markdown
 | 
			
		||||
    ###### Markdown/HTML card
 | 
			
		||||
{:copy-code}
 | 
			
		||||
```
 | 
			
		||||
 ###### Markdown/HTML card
 | 
			
		||||
 
 | 
			
		||||
<div class="divider"></div>
 | 
			
		||||
<br/>
 | 
			
		||||
 | 
			
		||||
Use - character to create list item. You can create nested lists separating them with tabs in the pattern:
 | 
			
		||||
 | 
			
		||||
 ```markdown
 | 
			
		||||
    - Element 1
 | 
			
		||||
    - Element 2
 | 
			
		||||
        - Element 2.1
 | 
			
		||||
        - Element 2.2
 | 
			
		||||
    -Element 3 
 | 
			
		||||
{:copy-code}
 | 
			
		||||
 ```
 | 
			
		||||
- Element 1
 | 
			
		||||
- Element 2
 | 
			
		||||
    - Element 2.1
 | 
			
		||||
    - Element 2.2
 | 
			
		||||
- Element 3
 | 
			
		||||
 | 
			
		||||
<div class="divider"></div>
 | 
			
		||||
<br/>
 | 
			
		||||
 | 
			
		||||
Use * character to choose style:
 | 
			
		||||
 
 | 
			
		||||
 ```markdown
 | 
			
		||||
   - *Element 1*
 | 
			
		||||
   - **Element 2**
 | 
			
		||||
   - ***Element 3***
 | 
			
		||||
{:copy-code}
 | 
			
		||||
 ```
 | 
			
		||||
- *Element 1*
 | 
			
		||||
- **Element 2**
 | 
			
		||||
- ***Element 3***
 | 
			
		||||
 | 
			
		||||
<div class="divider"></div>
 | 
			
		||||
<br/>
 | 
			
		||||
 | 
			
		||||
Use ${} to add some value from your key:
 | 
			
		||||
 ```markdown
 | 
			
		||||
    - **Element 1**: ${key1Name}
 | 
			
		||||
    - **Element 1**: ${key2Name}
 | 
			
		||||
    - **Element 1**: ${key3Name}
 | 
			
		||||
{:copy-code}
 | 
			
		||||
 ```
 | 
			
		||||
 - **Element 1**: key1Value
 | 
			
		||||
 - **Element 2**: key2Value
 | 
			
		||||
 - **Element 3**: key3Value
 | 
			
		||||
 
 | 
			
		||||
@ -4276,6 +4276,7 @@
 | 
			
		||||
        "qr-code": {
 | 
			
		||||
            "use-qr-code-text-function": "Use QR code text function",
 | 
			
		||||
            "qr-code-text-pattern": "QR code text pattern (for ex. '${entityName} | ${keyName} - some text.')",
 | 
			
		||||
            "qr-code-text-pattern-hint": "QR code text pattern use the value of the first found key in the entities in the entity alias.",
 | 
			
		||||
            "qr-code-text-pattern-required": "QR code text pattern is required.",
 | 
			
		||||
            "qr-code-text-function": "QR code text function"
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user