diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97bcbf1..10c1765 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,17 +20,24 @@ jobs: with: node-version: 16 # cache: 'npm' + - name: Install dependencies run: | npm install # npm ci + - name: Install Angular dependencies + run: | + cd ngx-flow + npm install - name: Check types run: npm run typecheck - name: Lint run: npm run lint - name: Unit tests run: npm run test:ci - - name: Build frontend + - name: Build Angular frontend + run: npm run build:component + - name: Build and test frontend run: npm run build - name: Check for backend diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ff69d2..6d5d0cc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,13 +21,19 @@ jobs: - name: Setup Go environment uses: actions/setup-go@v3 with: - go-version: '1.19' + go-version: '1.22' - name: Install dependencies run: | npm install # npm ci - + - name: Install Angular dependencies + run: | + cd ngx-flow + npm install + # npm ci + - name: Build Angular frontend + run: npm run build:component - name: Build and test frontend run: npm run build diff --git a/README.md b/README.md index 7e946ec..461431f 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ Grafana 10+ Flow Diagram Visualization plugin ### Installation Allow and Install the unsigned plugin, ie: ``` - - GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=qxip-flow-panel - - GF_INSTALL_PLUGINS=https://github.com/metrico/grafana-flow/releases/download/v10.0.8/qxip-flow-panel-10.0.8.zip;qxip-flow-panel" +- GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=qxip-flow-panel +- GF_INSTALL_PLUGINS=https://github.com/metrico/grafana-flow/releases/download/v10.0.10/qxip-flow-panel-10.0.10.zip;qxip-flow-panel" ``` ### Panel Options diff --git a/ngx-flow/projects/ngx-flow/src/lib/ngx-flow.component.ts b/ngx-flow/projects/ngx-flow/src/lib/ngx-flow.component.ts index f316a0c..c42e7d1 100644 --- a/ngx-flow/projects/ngx-flow/src/lib/ngx-flow.component.ts +++ b/ngx-flow/projects/ngx-flow/src/lib/ngx-flow.component.ts @@ -110,6 +110,7 @@ export class NgxFlowComponent implements OnInit { srcAlias: SRC, typeItem: "SIP", + hash: i.hash } } diff --git a/ngx-flow/projects/ngx-flow/src/tab-flow/tab-flow.component.html b/ngx-flow/projects/ngx-flow/src/tab-flow/tab-flow.component.html index 33ec959..0618532 100644 --- a/ngx-flow/projects/ngx-flow/src/tab-flow/tab-flow.component.html +++ b/ngx-flow/projects/ngx-flow/src/tab-flow/tab-flow.component.html @@ -80,7 +80,7 @@

No Data

[isGroupByAlias]="_isCombineByAlias" [isSimplify]="isSimplify" [isAbsolute]="isAbsolute" - (itemClick)="onClickMessage($event.idx, $event.event, item)" + (itemClick)="onClickMessage(item.hash, $event.event, item)" >
@@ -114,8 +114,8 @@

No Data

[isGroupByAlias]="_isCombineByAlias" [isSimplify]="isSimplify" [isAbsolute]="isAbsolute" - (itemClick)="onClickMessage($event.idx, $event.event, item)" - > + (itemClick)="onClickMessage(item.hash, $event.event, item)" + > diff --git a/package.json b/package.json index 34a6e4e..720d785 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "version": "10.0.13", "description": "Plugin providing Flow diagram for Grafana", "scripts": { - "build": "cd ./ngx-flow && npm run build:component && cd .. && webpack -c ./.config/webpack/webpack.config.ts --env production", + "build:component": "cd ./ngx-flow && npm run build:component", + "build": "webpack -c ./.config/webpack/webpack.config.ts --env production", "dev": "webpack -w -c ./.config/webpack/webpack.config.ts --env development", "test": "jest --watch --onlyChanged", "test:ci": "jest --passWithNoTests --maxWorkers 4", diff --git a/src/components/SimplePanel.tsx b/src/components/SimplePanel.tsx index 8d10efc..9bed411 100644 --- a/src/components/SimplePanel.tsx +++ b/src/components/SimplePanel.tsx @@ -26,6 +26,7 @@ import { Dropdown, Menu } from '@grafana/ui'; +import { hash } from 'helpers/hash'; import { convertDateToFileName } from 'helpers/convertDateToFileName'; @@ -228,7 +229,7 @@ export const SimplePanel: React.FC = ({ options, data, width, height }: a const [flowData, setFlowData] = React.useState({ actors: [], data: [] }); const [modalIsOpen, setModalIsOpen] = React.useState(false); const [modalData, setModalData] = React.useState({}); - const [modalDataFields, setModalDataFields] = React.useState([]); + const [modalDataFields, setModalDataFields] = React.useState>(); const onModalClose = () => { setModalIsOpen(false); @@ -378,9 +379,8 @@ export const SimplePanel: React.FC = ({ options, data, width, height }: a if (fields) { const [firsField]: any = fields; const sortData = formattingDataAndSortIt(fields, options.sortoption); - setModalDataFields(sortData); const outData = firsField?.values; - + const map = new Map(); if (outData) { valueLabelsName = Object.keys(outData?.[0] || {}); setFlowData({ @@ -393,6 +393,8 @@ export const SimplePanel: React.FC = ({ options, data, width, height }: a } return labelItem[optionArr] || ''; }; + const itemHash = hash(JSON.stringify(item)) + map.set(itemHash, item); return { messageID: _(options.colorGenerator) || 'Title', subTitle: options.showbody && message, @@ -402,18 +404,19 @@ export const SimplePanel: React.FC = ({ options, data, width, height }: a aboveArrow: _(options.aboveArrow) || '', belowArrow: _(options.belowArrow) || '', sourceLabel: _(options.sourceLabel) || '', - destinationLabel: _(options.destinationLabel) || '' + destinationLabel: _(options.destinationLabel) || '', + hash: itemHash } }) }) - + setModalDataFields(map); } } /* eslint-disable-next-line */ }, [data, options]); ngxFlowClickHandler = (e: any) => { - const details: any = modalDataFields[e.detail]; + const details: any = modalDataFields?.get(e.detail) if (typeof details.labels === 'object') { details.labels = JSON.stringify(details.labels); } diff --git a/src/helpers/hash.ts b/src/helpers/hash.ts new file mode 100644 index 0000000..647f7df --- /dev/null +++ b/src/helpers/hash.ts @@ -0,0 +1,19 @@ +export function hash(str: string, lenHash = 32) { + lenHash = lenHash || 32; + str = str || ""; + let ar = str.split('').map((a) => a.charCodeAt(0)), + s2alength = ar.length || 1, + i = ar.length ? ar.reduce((p, c) => p + c) : 1, + s = "", + A, + B, + k = 0, + tan = Math.tan; + while (s.length < lenHash) { + A = ar[k++ % s2alength] || 0.5; + B = ar[k++ % s2alength ^ lenHash] || 1.5 ^ lenHash; + i = i + (A ^ B) % lenHash; + s += tan(i * B / A).toString(16).split('.')[1].slice(0, 10); + } + return s.slice(0, lenHash); +}