Skip to content

Alex/cmdb view 100 #822

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions bricks/basic/docs/eo-snapshot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
构件 `eo-snapshot`

## Examples

### Basic

```yaml preview
- brick: eo-snapshot
properties:
id: snapshot
events:
save:
action: console.log
upload:
action: console.log
- brick: eo-button
properties:
textContent: Save As Image
style:
margin-right: 10px
events:
click:
- action: console.log
- target: "#snapshot"
method: saveAsImage
args:
- name: image
- brick: eo-button
properties:
textContent: Save As PDF
style:
margin-right: 10px
events:
click:
- action: console.log
- target: "#snapshot"
method: saveAsPDF
args:
- name: pdf
- brick: eo-button
properties:
textContent: Capture And Upload
events:
click:
- action: console.log
- target: "#snapshot"
method: captureImageAndUpload
args:
- name: upload
bucketName: examples
```
2 changes: 2 additions & 0 deletions bricks/basic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
"@next-core/types": "^1.7.1",
"@next-shared/general": "^0.7.2",
"classnames": "^2.3.2",
"html2canvas": "^1.4.1",
"jspdf": "^2.5.1",
"lodash": "^4.17.21",
"react": "0.0.0-experimental-ee8509801-20230117"
},
Expand Down
1 change: 1 addition & 0 deletions bricks/basic/src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ import "./v3-widget-mate/index.js";
import "./easyops-avatar/index.js";
import "./data-providers/lock-body-scroll/lock-body-scroll.js";
import "./data-providers/set-theme-by-apps.js";
import "./snapshot/index.js";
18 changes: 18 additions & 0 deletions bricks/basic/src/snapshot/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export enum K {}
// HELLO = "HELLO",

const en: Locale = {
// HELLO: "Hello",
};

const zh: Locale = {
// HELLO: "你好",
};

export const NS = "bricks/basic/eo-snapshot";

export const locales = { en, zh };

type Locale = { [k in K]: string } & {
[k in K as `${k}_plural`]?: string;
};
24 changes: 24 additions & 0 deletions bricks/basic/src/snapshot/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, test, expect, jest } from "@jest/globals";
import { act } from "react-dom/test-utils";
import "./";
import { EoSnapshot } from "./index.js";

jest.mock("@next-core/theme", () => ({}));

describe("eo-snapshot", () => {
test("basic usage", async () => {
const element = document.createElement("eo-snapshot") as EoSnapshot;

expect(element.shadowRoot).toBeFalsy();

act(() => {
document.body.appendChild(element);
});
expect(element.shadowRoot?.childNodes.length).toBeGreaterThan(0);

act(() => {
document.body.removeChild(element);
});
expect(element.shadowRoot?.childNodes.length).toBe(0);
});
});
103 changes: 103 additions & 0 deletions bricks/basic/src/snapshot/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// istanbul ignore file: nothing logical except calling html2canvas and jspdf.
import React from "react";
import { EventEmitter, createDecorators } from "@next-core/element";
import { ReactNextElement } from "@next-core/react-element";
import "@next-core/theme";
import styleText from "./styles.shadow.css";
import {
buildImageUrl,
capture,
downloadImage,
getCanvasBlob,
uploadFile,
} from "./snapshot.js";

const { defineElement, event, method } = createDecorators();

export type SnapshotConf = {
id?: "string";
name: string;
};

/**
* 截图或者截图上传构件
*/
export
@defineElement("eo-snapshot", {
styleTexts: [styleText],
})
class EoSnapshot extends ReactNextElement {
/*
* 保存图片或者PDF时触发
*/
@event({ type: "save" })
accessor #onSave!: EventEmitter<{
fileType: "image" | "pdf";
status: "saving" | "succeed" | "failed";
}>;

/*
* 上传图片时触发
*/
@event({ type: "upload" })
accessor #onUpload!: EventEmitter<{
url?: string;
status: "uploading" | "succeed" | "failed";
}>;

/*
* 截图并保存为图片
*/
@method()
async saveAsImage(conf: SnapshotConf) {
try {
this.#onSave.emit({ fileType: "image", status: "saving" });
const canvas = await capture();
await downloadImage(canvas, conf.name);
this.#onSave.emit({ fileType: "image", status: "succeed" });
} catch (e) {
this.#onSave.emit({ fileType: "image", status: "failed" });
}
}

/*
* 截图并保存为PDF
*/
@method()
async saveAsPDF(conf: SnapshotConf) {
try {
const { jsPDF } = await import("jspdf");
this.#onSave.emit({ fileType: "pdf", status: "saving" });
const canvas = await capture(conf.id);
const imageData = canvas.toDataURL("image/jpeg", 1.0);
const pdf = new jsPDF("l", "pt", [canvas.width, canvas.height]);
pdf.addImage(imageData, "JPEG", 0, 0, canvas.width, canvas.height);
await pdf.save(`${conf.name}.pdf`, { returnPromise: true });
this.#onSave.emit({ fileType: "pdf", status: "succeed" });
} catch (e) {
this.#onSave.emit({ fileType: "pdf", status: "failed" });
}
}

/*
* 截图并上传
*/
@method()
async captureImageAndUpload(conf: SnapshotConf & { bucketName: string }) {
try {
this.#onUpload.emit({ status: "uploading" });
const canvas = await capture(conf.id);
const blob = await getCanvasBlob(canvas);
const files = new File([blob], `${conf.name}.png`, { type: blob.type });
const result = await uploadFile(files, conf.bucketName);
const url = buildImageUrl(conf.bucketName, result.data.objectName);
this.#onUpload.emit({ url, status: "succeed" });
} catch (e) {
this.#onUpload.emit({ status: "failed" });
}
}

render() {
return null;
}
}
91 changes: 91 additions & 0 deletions bricks/basic/src/snapshot/snapshot.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// istanbul ignore file: nothing logical except calling html2canvas.
import { http } from "@next-core/http";
import { getBasePath } from "@next-core/runtime";
import _html2canvas from "html2canvas";

// There is a type issue like i18next
const html2canvas = _html2canvas as unknown as typeof _html2canvas.default;
export type UploadStatus = "uploading" | "done" | "error";

export function capture(id?: string): Promise<HTMLCanvasElement> {
const target = document.querySelector(`#${id}`) || document.body;

return new Promise(function (resolve, reject) {
html2canvas(document.body, {
logging: false,
scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
width: target.clientWidth || window.innerWidth,
height: target.clientHeight || window.innerHeight,
foreignObjectRendering: true,
allowTaint: true,
useCORS: true,
removeContainer: false,
})
.then(function (canvas) {
resolve(canvas);
})
.catch(reject);
});
}

export function downloadImage(
canvas: HTMLCanvasElement,
name = "image"
): Promise<string> {
return new Promise((resolve, reject) => {
try {
const url = canvas.toDataURL("image/png");

const image = new Image();
image.onload = function () {
const canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
const ctx = canvas.getContext("2d");
ctx?.drawImage(image, 0, 0, image.width, image.height);

const url = canvas.toDataURL("image/png");
const a = document.createElement("a");
a.href = url;
a.download = name;
const event = new MouseEvent("click");
a.dispatchEvent(event);
};
image.src = url;
resolve("succeed");
} catch (e) {
reject("failed");
}
});
}

export function getCanvasBlob(canvas: HTMLCanvasElement): Promise<Blob> {
return new Promise(function (resolve, reject) {
canvas.toBlob(function (blob: Blob | null) {
if (blob) {
resolve(blob);
} else {
reject();
}
});
});
}

export function uploadFile(
file: File,
bucketName: string
): Promise<{ data: { objectName: string } }> {
const formData = new FormData();
formData.append("file", file, file.name);

const url = `/next/api/gateway/object_store.object_store.PutObject/api/v1/objectStore/bucket/${bucketName}/object`;

return http.request(url, {
method: "PUT",
body: formData,
});
}

export function buildImageUrl(bucketName: string, objectName: string) {
return `${getBasePath()}api/gateway/logic.object_store_service/api/v1/objectStore/bucket/${bucketName}/object/${objectName}`;
}
7 changes: 7 additions & 0 deletions bricks/basic/src/snapshot/styles.shadow.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
:host {
display: inline-block;
}

:host([hidden]) {
display: none;
}
75 changes: 75 additions & 0 deletions bricks/data-view/docs/indicator-card.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
构件 `data-view.indicator-card`

## Examples

### Column

```yaml preview
- brick: data-view.indicator-card
properties:
layout: "column"
datasource:
- value: 300
desc: 月碳排放量
unit: (吨)
- value: 1000.33
desc: 季度碳排放总量
unit: (吨)
- value: 2507.55
desc: 年度碳排放总量
unit: (吨)
```

### Column Townhouse

```yaml preview
- brick: data-view.indicator-card
properties:
layout: "column-townhouse"
datasource:
- value: 300
desc: 月碳排放量
unit: (吨)
- value: 1000.33
desc: 季度碳排放总量
unit: (吨)
- value: 2507.55
desc: 年度碳排放总量
unit: (吨)
```

### Row

```yaml preview
- brick: data-view.indicator-card
properties:
layout: "row"
datasource:
- value: 300
desc: 月碳排放量
unit: (吨)
- value: 1000.33
desc: 季度碳排放总量
unit: (吨)
- value: 2507.55
desc: 年度碳排放总量
unit: (吨)
```

### Row Townhouse

```yaml preview
- brick: data-view.indicator-card
properties:
layout: "row-townhouse"
datasource:
- value: 300
desc: 月碳排放量
unit: (吨)
- value: 1000.33
desc: 季度碳排放总量
unit: (吨)
- value: 2507.55
desc: 年度碳排放总量
unit: (吨)
```
Binary file added bricks/data-view/src/asset/images/block.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added bricks/data-view/src/asset/images/colBg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added bricks/data-view/src/asset/images/divider.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added bricks/data-view/src/asset/images/rowBg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions bricks/data-view/src/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ import "./basic-index-group/index.js";
import "./data-display-flipper/index.js";
import "./data-display-flipper-fifth/index.js";
import "./data-display-flipper-sixth/index.js";
import "./indicator-card/index.js";
Loading