From 7e9a652249d2dd98d2dada7d060dffe1f0a4680f Mon Sep 17 00:00:00 2001 From: MrKBear Date: Fri, 11 Mar 2022 17:00:05 +0800 Subject: [PATCH 1/4] Add label list edit panel --- source/Component/AttrInput/AttrInput.tsx | 6 +++ source/Component/LabelList/LabelList.scss | 16 ++++++-- source/Component/LabelList/LabelList.tsx | 3 -- .../Component/TogglesInput/TogglesInput.tsx | 18 +++++++-- source/Context/Status.tsx | 19 ++++++++++ source/Localization/EN-US.ts | 2 + source/Localization/ZH-CN.ts | 2 + source/Panel/LabelDetails/LabelDetails.tsx | 37 ++++++++----------- source/Panel/LabelList/LabelList.tsx | 2 +- 9 files changed, 72 insertions(+), 33 deletions(-) diff --git a/source/Component/AttrInput/AttrInput.tsx b/source/Component/AttrInput/AttrInput.tsx index 03bbc77..148d3fe 100644 --- a/source/Component/AttrInput/AttrInput.tsx +++ b/source/Component/AttrInput/AttrInput.tsx @@ -12,6 +12,7 @@ interface IAttrInputProps { value?: number | string; isNumber?: boolean; maxLength?: number; + minLength?: number; max?: number; min?: number; step?: number; @@ -40,6 +41,11 @@ class AttrInput extends Component { return } + const minLength = this.props.minLength ?? 1; + if (value.length < minLength) { + return + } + if (this.props.isNumber) { const praseNumber = (value as any) / 1; diff --git a/source/Component/LabelList/LabelList.scss b/source/Component/LabelList/LabelList.scss index fb58a26..a7adf0c 100644 --- a/source/Component/LabelList/LabelList.scss +++ b/source/Component/LabelList/LabelList.scss @@ -63,14 +63,22 @@ div.light.label { } } -div.dark.label:hover, -div.dark.label.focus { +div.dark.label:hover { color: $lt-font-color-lvl2-dark; background-color: $lt-bg-color-lvl2-dark; } -div.light.label:hover, -div.light.label.focus { +div.dark.label.focus { + color: $lt-font-color-lvl1-dark; + background-color: $lt-bg-color-lvl1-dark; +} + +div.light.label:hover { color: $lt-font-color-lvl2-light; background-color: $lt-bg-color-lvl2-light; +} + +div.light.label.focus { + color: $lt-font-color-lvl1-light; + background-color: $lt-bg-color-lvl1-light; } \ No newline at end of file diff --git a/source/Component/LabelList/LabelList.tsx b/source/Component/LabelList/LabelList.tsx index 59eba50..a37f410 100644 --- a/source/Component/LabelList/LabelList.tsx +++ b/source/Component/LabelList/LabelList.tsx @@ -38,9 +38,6 @@ class LabelList extends Component { } this.isDeleteClick = false; }} - style={{ - borderColor: isFocus ? colorCss : undefined - }} >
any; + onIconName?: string; + offIconName?: string; + valueChange?: (value: boolean) => any; } class TogglesInput extends Component { @@ -33,9 +35,17 @@ class TogglesInput extends Component { } })} > - +
diff --git a/source/Context/Status.tsx b/source/Context/Status.tsx index 957e196..27bea80 100644 --- a/source/Context/Status.tsx +++ b/source/Context/Status.tsx @@ -32,6 +32,7 @@ interface IStatusEvent { objectChange: void; labelChange: void; rangeAttrChange: void; + labelAttrChange: void; } class Status extends Emitter { @@ -120,6 +121,24 @@ class Status extends Emitter { } } + /** + * 修改范围属性 + */ + public changeLabelAttrib + (label: Label, key: K, val: Label[K]) { + let findLabel: Label | undefined; + for (let i = 0; i < this.model.labelPool.length; i++) { + if (this.model.labelPool[i].equal(label)) { + findLabel = this.model.labelPool[i]; + break; + } + } + if (findLabel) { + findLabel[key] = val; + this.emit("labelAttrChange"); + } + } + /** * 鼠标工具状态 */ diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index 9253e47..6f7d75f 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -23,6 +23,7 @@ const EN_US = { "Input.Error.Max": "Enter value must be less than {num}", "Input.Error.Min": "Enter value must be greater than {num}", "Input.Error.Length": "The length of the input content must be less than {num}", + "Input.Error.Length.Less": "The length of the input content must be greater than {num}", "Object.List.New.Group": "Group object {id}", "Object.List.New.Range": "Range object {id}", "Object.List.New.Label": "Label {id}", @@ -49,6 +50,7 @@ const EN_US = { "Common.Attr.Key.Color": "Color", "Common.Attr.Key.Display": "Display", "Common.Attr.Key.Update": "Update", + "Common.Attr.Key.Delete": "Delete", "Common.Attr.Key.Error.Multiple": "Multiple values", "Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range", "Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index 7986b9e..b6731a9 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -23,6 +23,7 @@ const ZH_CN = { "Input.Error.Max": "输入数值须小于 {number}", "Input.Error.Min": "输入数值须大于 {number}", "Input.Error.Length": "输入内容长度须小于 {number}", + "Input.Error.Length.Less": "输入内容长度须大于 {number}", "Object.List.New.Group": "组对象 {id}", "Object.List.New.Range": "范围对象 {id}", "Object.List.New.Label": "标签 {id}", @@ -49,6 +50,7 @@ const ZH_CN = { "Common.Attr.Key.Color": "颜色", "Common.Attr.Key.Display": "显示", "Common.Attr.Key.Update": "更新", + "Common.Attr.Key.Delete": "删除", "Common.Attr.Key.Error.Multiple": "多重数值", "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", diff --git a/source/Panel/LabelDetails/LabelDetails.tsx b/source/Panel/LabelDetails/LabelDetails.tsx index 118a2df..fbda488 100644 --- a/source/Panel/LabelDetails/LabelDetails.tsx +++ b/source/Panel/LabelDetails/LabelDetails.tsx @@ -4,37 +4,32 @@ import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; import { AllI18nKeys } from "@Component/Localization/Localization"; import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; import { ColorInput } from "@Component/ColorInput/ColorInput"; -import "./LabelDetails.scss"; -import { LabelList } from "@Component/LabelList/LabelList"; import { Label } from "@Model/Label"; +import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; +import "./LabelDetails.scss"; -@useStatusWithEvent("focusLabelChange") +@useStatusWithEvent("focusLabelChange", "labelAttrChange", "labelChange") class LabelDetails extends Component { - - public readonly AttrI18nKey: AllI18nKeys[] = [ - "Common.Attr.Key.Display.Name", - "Common.Attr.Key.Color", - ] private renderFrom(label: Label) { return <> - - { - if (this.props.status) { - this.props.status.model.deleteLabel(label); - this.props.status.setLabelObject(); - } - }} - /> - + { + if (this.props.status) { + this.props.status.changeLabelAttrib(label, "name", value); + } + }}/> { if (this.props.status) { - + this.props.status.changeLabelAttrib(label, "color", color); + } + }}/> + + { + if (this.props.status) { + this.props.status.model.deleteLabel(label); + this.props.status.setLabelObject(); } }}/> diff --git a/source/Panel/LabelList/LabelList.tsx b/source/Panel/LabelList/LabelList.tsx index bb41ae5..b6dd9a1 100644 --- a/source/Panel/LabelList/LabelList.tsx +++ b/source/Panel/LabelList/LabelList.tsx @@ -10,7 +10,7 @@ interface ILabelListProps { } @useSetting -@useStatusWithEvent("labelChange", "focusLabelChange") +@useStatusWithEvent("labelChange", "focusLabelChange", "labelAttrChange") class LabelList extends Component { private labelInnerClick: boolean = false; -- 2.45.2 From c84c0b903bfbc373da8c79a72d58768cfa82fb47 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Fri, 11 Mar 2022 22:10:19 +0800 Subject: [PATCH 2/4] Add add button on label list --- source/Component/LabelList/LabelList.scss | 27 ++++++++++++ source/Component/LabelList/LabelList.tsx | 50 +++++++++++++++++++---- source/Panel/LabelList/LabelList.scss | 2 +- source/Panel/LabelList/LabelList.tsx | 5 ++- 4 files changed, 75 insertions(+), 9 deletions(-) diff --git a/source/Component/LabelList/LabelList.scss b/source/Component/LabelList/LabelList.scss index a7adf0c..3a046a7 100644 --- a/source/Component/LabelList/LabelList.scss +++ b/source/Component/LabelList/LabelList.scss @@ -3,6 +3,8 @@ div.label { width: auto; height: auto; + min-height: 24px; + box-sizing: border-box; display: inline-flex; margin: 5px 5px; justify-content: center; @@ -23,11 +25,14 @@ div.label { div.label-name { padding: 2px 3px; + display: flex; + align-items: center; text-overflow: ellipsis; overflow: hidden; } div.delete-button { + flex-shrink: 0; padding: 2px 3px; border-radius: 3px; display: flex; @@ -37,6 +42,28 @@ div.label { } } +div.label.one-line div.label-name { + max-width: 100%; + word-break: keep-all; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +div.label.add-button { + width: 24px; + align-items: center; + justify-content: center; +} + +div.dark.label.add-button { + border: .5px dashed $lt-bg-color-lvl3-dark; +} + +div.light.label.add-button { + border: .5px dashed $lt-bg-color-lvl3-light; +} + div.dark.label { transition: none; background-color: $lt-bg-color-lvl3-dark; diff --git a/source/Component/LabelList/LabelList.tsx b/source/Component/LabelList/LabelList.tsx index a37f410..db90129 100644 --- a/source/Component/LabelList/LabelList.tsx +++ b/source/Component/LabelList/LabelList.tsx @@ -6,11 +6,14 @@ import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; import "./LabelList.scss"; interface ILabelListProps { + minHeight?: number; + maxWidth?: number; + width?: number; labels: Label[]; - canDelete?: boolean; focusLabel?: Label; clickLabel?: (label: Label) => any; deleteLabel?: (label: Label) => any; + addLabel?: () => any; } @useSetting @@ -21,15 +24,22 @@ class LabelList extends Component { private renderLabel(label: Label) { const theme = this.props.setting?.themes ?? Themes.dark; - const classList:string[] = ["label"]; + const classList: string[] = ["label"]; classList.push( theme === Themes.dark ? "dark" : "light" ); const isFocus = this.props.focusLabel && this.props.focusLabel.equal(label); if (isFocus) { classList.push("focus"); } + if (this.props.maxWidth) { + classList.push("one-line"); + } const colorCss = `rgb(${label.color.join(",")})`; return
{ @@ -44,10 +54,10 @@ class LabelList extends Component { borderRadius: isFocus ? 0 : 3 }}/>
- {label.name} +
{label.name}
{ - this.props.canDelete ? + this.props.deleteLabel ?
{ @@ -63,17 +73,43 @@ class LabelList extends Component {
} - private renderAllLabels(labels: Label[]) { + private renderAllLabels() { return this.props.labels.map((label) => { return this.renderLabel(label); }); } + + private renderAddButton(isNoMargin: boolean = false) { + const theme = this.props.setting?.themes ?? Themes.dark; + const classList: string[] = ["label", "add-button"]; + classList.push( theme === Themes.dark ? "dark" : "light" ); + + return
{ + this.props.addLabel ? this.props.addLabel() : null + }} + > + +
; + } public render() { if (this.props.labels.length > 0) { - return this.renderAllLabels(this.props.labels); + return <> + {this.renderAllLabels()} + {this.props.addLabel ? this.renderAddButton() : null} + ; } else { - return + return <> + + {this.props.addLabel ? this.renderAddButton(true) : null} + ; } } } diff --git a/source/Panel/LabelList/LabelList.scss b/source/Panel/LabelList/LabelList.scss index b9eec31..b2233e1 100644 --- a/source/Panel/LabelList/LabelList.scss +++ b/source/Panel/LabelList/LabelList.scss @@ -2,7 +2,7 @@ div.label-list-panel-root { width: 100%; - height: 100%; + min-height: 100%; padding: 10px; box-sizing: border-box; } \ No newline at end of file diff --git a/source/Panel/LabelList/LabelList.tsx b/source/Panel/LabelList/LabelList.tsx index b6dd9a1..13c15b8 100644 --- a/source/Panel/LabelList/LabelList.tsx +++ b/source/Panel/LabelList/LabelList.tsx @@ -30,7 +30,6 @@ class LabelList extends Component { @@ -49,6 +48,10 @@ class LabelList extends Component { + this.props.status ? this.props.status.newLabel() : undefined; + }} />
; } -- 2.45.2 From f832a5af00ec8b72952d39d70725173f46bd94bb Mon Sep 17 00:00:00 2001 From: MrKBear Date: Sat, 12 Mar 2022 16:33:46 +0800 Subject: [PATCH 3/4] Add label picker --- .../Component/ErrorMessage/ErrorMessage.tsx | 3 +- source/Component/LabelList/LabelList.scss | 4 ++ source/Component/LabelList/LabelList.tsx | 24 +++++------- source/Component/LabelPicker/LabelPicker.scss | 31 +++++++++++++++ source/Component/LabelPicker/LabelPicker.tsx | 38 +++++++++++++++++++ .../Component/ObjectPicker/ObjectPicker.tsx | 12 ++++++ source/Component/PickerList/PickerList.tsx | 12 ++++++ source/Localization/EN-US.ts | 1 + source/Localization/ZH-CN.ts | 1 + source/Panel/LabelList/LabelList.scss | 4 ++ source/Panel/LabelList/LabelList.tsx | 7 ++++ source/Panel/RangeDetails/RangeDetails.tsx | 7 ++++ 12 files changed, 128 insertions(+), 16 deletions(-) create mode 100644 source/Component/LabelPicker/LabelPicker.scss create mode 100644 source/Component/LabelPicker/LabelPicker.tsx create mode 100644 source/Component/ObjectPicker/ObjectPicker.tsx create mode 100644 source/Component/PickerList/PickerList.tsx diff --git a/source/Component/ErrorMessage/ErrorMessage.tsx b/source/Component/ErrorMessage/ErrorMessage.tsx index d82ef9c..375dc24 100644 --- a/source/Component/ErrorMessage/ErrorMessage.tsx +++ b/source/Component/ErrorMessage/ErrorMessage.tsx @@ -5,10 +5,11 @@ import "./ErrorMessage.scss"; interface IErrorMessageProps { i18nKey: AllI18nKeys; options?: Record; + className?: string; } const ErrorMessage: FunctionComponent = (props) => { - return
+ return
!!c).join(" ")}>
} diff --git a/source/Component/LabelList/LabelList.scss b/source/Component/LabelList/LabelList.scss index 3a046a7..b0af602 100644 --- a/source/Component/LabelList/LabelList.scss +++ b/source/Component/LabelList/LabelList.scss @@ -1,5 +1,9 @@ @import "../Theme/Theme.scss"; +div.label-list-root { + margin: -5px; +} + div.label { width: auto; height: auto; diff --git a/source/Component/LabelList/LabelList.tsx b/source/Component/LabelList/LabelList.tsx index db90129..7250fa8 100644 --- a/source/Component/LabelList/LabelList.tsx +++ b/source/Component/LabelList/LabelList.tsx @@ -1,4 +1,4 @@ -import { Component } from "react"; +import { Component, RefObject } from "react"; import { Label } from "@Model/Label"; import { Icon } from "@fluentui/react"; import { useSetting, IMixinSettingProps, Themes } from "@Context/Setting"; @@ -10,6 +10,7 @@ interface ILabelListProps { maxWidth?: number; width?: number; labels: Label[]; + addRef?: RefObject; focusLabel?: Label; clickLabel?: (label: Label) => any; deleteLabel?: (label: Label) => any; @@ -79,17 +80,17 @@ class LabelList extends Component { }); } - private renderAddButton(isNoMargin: boolean = false) { + private renderAddButton() { const theme = this.props.setting?.themes ?? Themes.dark; const classList: string[] = ["label", "add-button"]; classList.push( theme === Themes.dark ? "dark" : "light" ); return
{ this.props.addLabel ? this.props.addLabel() : null @@ -100,17 +101,10 @@ class LabelList extends Component { } public render() { - if (this.props.labels.length > 0) { - return <> - {this.renderAllLabels()} - {this.props.addLabel ? this.renderAddButton() : null} - ; - } else { - return <> - - {this.props.addLabel ? this.renderAddButton(true) : null} - ; - } + return
+ {this.renderAllLabels()} + {this.props.addLabel ? this.renderAddButton() : null} +
; } } diff --git a/source/Component/LabelPicker/LabelPicker.scss b/source/Component/LabelPicker/LabelPicker.scss new file mode 100644 index 0000000..b3a74f3 --- /dev/null +++ b/source/Component/LabelPicker/LabelPicker.scss @@ -0,0 +1,31 @@ +@import "../Theme/Theme.scss"; + +$line-min-height: 26px; + +div.label-picker-root { + width: 100%; + display: flex; + flex-wrap: wrap; + min-height: $line-min-height; + padding: 5px 0; + + div.input-intro { + width: 50%; + height: 100%; + max-width: 220px; + display: flex; + align-items: center; + padding-right: 5px; + box-sizing: border-box; + } + + div.root-content { + width: 50%; + height: 100%; + max-width: 180px; + min-height: $line-min-height; + border-radius: 3px; + overflow: hidden; + display: flex; + } +} \ No newline at end of file diff --git a/source/Component/LabelPicker/LabelPicker.tsx b/source/Component/LabelPicker/LabelPicker.tsx new file mode 100644 index 0000000..6abe2ac --- /dev/null +++ b/source/Component/LabelPicker/LabelPicker.tsx @@ -0,0 +1,38 @@ +import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; +import { Label } from "@Model/Label"; +import { Component, ReactNode } from "react"; +import { LabelList } from "../LabelList/LabelList"; +import "./LabelPicker.scss" + +interface ILabelPickerProps { + keyI18n: AllI18nKeys; + infoI18n?: AllI18nKeys; + labels: Label[]; +} + +class LabelPicker extends Component { + + public render(): ReactNode { + return
+
+ +
+
+ { + + }} + addLabel={() => { + + }} + /> +
+
+ } +} + +export { LabelPicker } \ No newline at end of file diff --git a/source/Component/ObjectPicker/ObjectPicker.tsx b/source/Component/ObjectPicker/ObjectPicker.tsx new file mode 100644 index 0000000..63f649f --- /dev/null +++ b/source/Component/ObjectPicker/ObjectPicker.tsx @@ -0,0 +1,12 @@ +import { Component, ReactNode } from "react"; + +interface IObjectPickerProps {} + +class ObjectPicker extends Component { + + public render(): ReactNode { + return
+ } +} + +export { ObjectPicker } \ No newline at end of file diff --git a/source/Component/PickerList/PickerList.tsx b/source/Component/PickerList/PickerList.tsx new file mode 100644 index 0000000..108a62d --- /dev/null +++ b/source/Component/PickerList/PickerList.tsx @@ -0,0 +1,12 @@ +import { Component, ReactNode } from "react"; + +interface IPickerListProps {} + +class PickerList extends Component { + + public render(): ReactNode { + return
+ } +} + +export { PickerList } \ No newline at end of file diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index 6f7d75f..6712c93 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -51,6 +51,7 @@ const EN_US = { "Common.Attr.Key.Display": "Display", "Common.Attr.Key.Update": "Update", "Common.Attr.Key.Delete": "Delete", + "Common.Attr.Key.Label": "Label", "Common.Attr.Key.Error.Multiple": "Multiple values", "Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range", "Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index b6731a9..8e4bce6 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -51,6 +51,7 @@ const ZH_CN = { "Common.Attr.Key.Display": "显示", "Common.Attr.Key.Update": "更新", "Common.Attr.Key.Delete": "删除", + "Common.Attr.Key.Label": "标签", "Common.Attr.Key.Error.Multiple": "多重数值", "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", diff --git a/source/Panel/LabelList/LabelList.scss b/source/Panel/LabelList/LabelList.scss index b2233e1..7643f5c 100644 --- a/source/Panel/LabelList/LabelList.scss +++ b/source/Panel/LabelList/LabelList.scss @@ -5,4 +5,8 @@ div.label-list-panel-root { min-height: 100%; padding: 10px; box-sizing: border-box; +} + +div.label-list-pabel-err-msg { + padding-bottom: 5px; } \ No newline at end of file diff --git a/source/Panel/LabelList/LabelList.tsx b/source/Panel/LabelList/LabelList.tsx index 13c15b8..fce98be 100644 --- a/source/Panel/LabelList/LabelList.tsx +++ b/source/Panel/LabelList/LabelList.tsx @@ -3,6 +3,7 @@ import { Component } from "react"; import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; import { useSetting, IMixinSettingProps } from "@Context/Setting"; import { Label } from "@Model/Label"; +import { ErrorMessage } from "@Component/ErrorMessage/ErrorMessage"; import "./LabelList.scss"; interface ILabelListProps { @@ -29,6 +30,12 @@ class LabelList extends Component + {labels.length <=0 ? + : null + } { public readonly AttrI18nKey: AllI18nKeys[] = [ "Common.Attr.Key.Display.Name", + "Common.Attr.Key.Label", "Common.Attr.Key.Display", "Common.Attr.Key.Update", "Common.Attr.Key.Color", @@ -58,6 +60,11 @@ class RangeDetails extends Component { {this.renderAttrInput(range.id, keyIndex ++, range.displayName, (val, status) => { status.changeRangeAttrib(range.id, "displayName", val); })} + + { if (this.props.status) { -- 2.45.2 From b2eff20b6eb3285479524e02707dcd3eb46e2712 Mon Sep 17 00:00:00 2001 From: MrKBear Date: Sat, 12 Mar 2022 21:11:09 +0800 Subject: [PATCH 4/4] Add label picker --- source/Component/LabelList/LabelList.tsx | 9 ++- source/Component/LabelPicker/LabelPicker.tsx | 65 ++++++++++++++-- source/Component/PickerList/PickerList.scss | 72 +++++++++++++++++ source/Component/PickerList/PickerList.tsx | 81 +++++++++++++++++++- source/Context/Status.tsx | 19 ++++- source/Localization/EN-US.ts | 1 + source/Localization/ZH-CN.ts | 1 + source/Panel/RangeDetails/RangeDetails.tsx | 15 +++- 8 files changed, 250 insertions(+), 13 deletions(-) create mode 100644 source/Component/PickerList/PickerList.scss diff --git a/source/Component/LabelList/LabelList.tsx b/source/Component/LabelList/LabelList.tsx index 7250fa8..eae20cd 100644 --- a/source/Component/LabelList/LabelList.tsx +++ b/source/Component/LabelList/LabelList.tsx @@ -35,6 +35,7 @@ class LabelList extends Component { classList.push("one-line"); } const colorCss = `rgb(${label.color.join(",")})`; + const isDelete = label.isDeleted(); return
{ backgroundColor: colorCss, borderRadius: isFocus ? 0 : 3 }}/> -
+
{label.name}
{ diff --git a/source/Component/LabelPicker/LabelPicker.tsx b/source/Component/LabelPicker/LabelPicker.tsx index 6abe2ac..0989151 100644 --- a/source/Component/LabelPicker/LabelPicker.tsx +++ b/source/Component/LabelPicker/LabelPicker.tsx @@ -1,6 +1,8 @@ import { AllI18nKeys, Localization } from "@Component/Localization/Localization"; +import { PickerList } from "../PickerList/PickerList"; import { Label } from "@Model/Label"; -import { Component, ReactNode } from "react"; +import { useStatusWithEvent, IMixinStatusProps } from "@Context/Status"; +import { Component, ReactNode, createRef } from "react"; import { LabelList } from "../LabelList/LabelList"; import "./LabelPicker.scss" @@ -8,9 +10,42 @@ interface ILabelPickerProps { keyI18n: AllI18nKeys; infoI18n?: AllI18nKeys; labels: Label[]; + labelAdd?: (label: Label) => any; + labelDelete?: (label: Label) => any; } -class LabelPicker extends Component { +interface ILabelPickerState { + isPickerVisible: boolean; +} + +@useStatusWithEvent("labelAttrChange", "labelChange") +class LabelPicker extends Component { + + public constructor(props: ILabelPickerProps) { + super(props); + this.state = { + isPickerVisible: false + } + } + + private addButtonRef = createRef(); + + private getOtherLabel() { + let res: Label[] = []; + let nowLabel: Label[] = this.props.labels ?? []; + if (this.props.status) { + this.props.status.model.labelPool.forEach((aLabel) => { + let isHas = false; + nowLabel.forEach((nLabel) => { + if (aLabel.equal(nLabel)) isHas = true; + }) + if (!isHas) { + res.push(aLabel); + } + }) + } + return res; + } public render(): ReactNode { return
{
{ - + deleteLabel={(label) => { + this.props.labelDelete ? this.props.labelDelete(label) : 0; }} addLabel={() => { - + this.setState({ + isPickerVisible: true + }); }} /> + {this.state.isPickerVisible ? { + this.setState({ + isPickerVisible: false + }); + }} + click={(label) => { + if (label instanceof Label && this.props.labelAdd) { + this.props.labelAdd(label) + } + this.setState({ + isPickerVisible: false + }); + }} + target={this.addButtonRef} + /> : null}
} diff --git a/source/Component/PickerList/PickerList.scss b/source/Component/PickerList/PickerList.scss new file mode 100644 index 0000000..f080962 --- /dev/null +++ b/source/Component/PickerList/PickerList.scss @@ -0,0 +1,72 @@ +div.picker-list-root { + max-width: 200px; + padding: 0px; + margin: 0px; + overflow-y: auto; + + div.picker-list-item { + width: 200px; + height: 36px; + display: flex; + justify-content: center; + align-items: center; + vertical-align: middle; + cursor: pointer; + user-select: none; + border-radius: 3px; + overflow: hidden; + + div.list-item-color { + width: 3px; + height: calc( 100% - 6px ); + margin: 3px 0 3px 3px; + flex-shrink: 0; + border-radius: 1000px; + overflow: hidden; + background-color: black; + } + + div.list-item-icon { + width: 30px; + flex-shrink: 0; + display: flex; + justify-content: center; + align-items: center; + } + + div.list-item-name { + width: 100%; + } + } + + div.picker-list-item:hover { + background-color: rgba($color: #000000, $alpha: .1); + } + + span.picker-list-nodata { + display: inline-block; + padding: 5px; + } +} + +div.picker-list-root::-webkit-scrollbar { + width : 0; /*高宽分别对应横竖滚动条的尺寸*/ + height: 0; +} + +div.picker-list-root::-webkit-scrollbar { + width : 8px; /*高宽分别对应横竖滚动条的尺寸*/ + height: 0; +} + +div.picker-list-root::-webkit-scrollbar-thumb { + /*滚动条里面小方块*/ + border-radius: 8px; + background-color: rgba($color: #000000, $alpha: .1); +} + +div.picker-list-root::-webkit-scrollbar-track { + /*滚动条里面轨道*/ + border-radius: 8px; + background-color: rgba($color: #000000, $alpha: 0); +} \ No newline at end of file diff --git a/source/Component/PickerList/PickerList.tsx b/source/Component/PickerList/PickerList.tsx index 108a62d..47daa87 100644 --- a/source/Component/PickerList/PickerList.tsx +++ b/source/Component/PickerList/PickerList.tsx @@ -1,11 +1,86 @@ -import { Component, ReactNode } from "react"; +import { Localization } from "@Component/Localization/Localization"; +import { Callout, DirectionalHint, Icon } from "@fluentui/react"; +import { CtrlObject } from "@Model/CtrlObject"; +import { Group } from "@Model/Group"; +import { Label } from "@Model/Label"; +import { Range } from "@Model/Range"; +import { Component, ReactNode, RefObject } from "react"; +import "./PickerList.scss"; -interface IPickerListProps {} +type IPickerListItem = CtrlObject | Label; + +interface IPickerListProps { + objectList?: IPickerListItem[]; + target?: RefObject; + dismiss?: () => any; + click?: (item: IPickerListItem) => any; +} class PickerList extends Component { + private renderItem(item: IPickerListItem) { + + let color: number[] = []; + let icon: string = "tag"; + let name: string = ""; + + if (item instanceof Range) { + icon = "CubeShape" + } + if (item instanceof Group) { + icon = "WebAppBuilderFragment" + } + if (item instanceof CtrlObject) { + color[0] = Math.round(item.color[0] * 255); + color[1] = Math.round(item.color[1] * 255); + color[2] = Math.round(item.color[2] * 255); + name = item.displayName; + } + if (item instanceof Label) { + icon = "tag"; + color = item.color.concat([]); + name = item.name; + } + + return
{ + if (this.props.click) { + this.props.click(item) + } + }} + > +
+
+ +
+
+ {name} +
+
; + } + public render(): ReactNode { - return
+ return +
+ {this.props.objectList ? this.props.objectList.map((item) => { + return this.renderItem(item); + }) : null} + {!this.props.objectList || (this.props.objectList && this.props.objectList.length <= 0) ? + + : null + } +
+
} } diff --git a/source/Context/Status.tsx b/source/Context/Status.tsx index 27bea80..8853e52 100644 --- a/source/Context/Status.tsx +++ b/source/Context/Status.tsx @@ -30,6 +30,7 @@ interface IStatusEvent { focusObjectChange: void; focusLabelChange: void; objectChange: void; + rangeLabelChange: void; labelChange: void; rangeAttrChange: void; labelAttrChange: void; @@ -121,6 +122,22 @@ class Status extends Emitter { } } + public addRangeLabel(id: ObjectID, val: Label) { + const range = this.model.getObjectById(id); + if (range && range instanceof Range) { + range.addLabel(val); + this.emit("rangeLabelChange"); + } + } + + public deleteRangeLabel(id: ObjectID, val: Label) { + const range = this.model.getObjectById(id); + if (range && range instanceof Range) { + range.removeLabel(val); + this.emit("rangeLabelChange"); + } + } + /** * 修改范围属性 */ @@ -137,7 +154,7 @@ class Status extends Emitter { findLabel[key] = val; this.emit("labelAttrChange"); } - } + } /** * 鼠标工具状态 diff --git a/source/Localization/EN-US.ts b/source/Localization/EN-US.ts index 6712c93..3554142 100644 --- a/source/Localization/EN-US.ts +++ b/source/Localization/EN-US.ts @@ -53,6 +53,7 @@ const EN_US = { "Common.Attr.Key.Delete": "Delete", "Common.Attr.Key.Label": "Label", "Common.Attr.Key.Error.Multiple": "Multiple values", + "Common.Attr.Key.Label.Picker.Nodata": "No tags can be added", "Panel.Info.Range.Details.Attr.Error.Not.Range": "Object is not a Range", "Panel.Info.Range.Details.Attr.Error.Unspecified": "Unspecified range object", "Panel.Info.Label.Details.Error.Unspecified": "Label object not specified", diff --git a/source/Localization/ZH-CN.ts b/source/Localization/ZH-CN.ts index 8e4bce6..8e63ed4 100644 --- a/source/Localization/ZH-CN.ts +++ b/source/Localization/ZH-CN.ts @@ -53,6 +53,7 @@ const ZH_CN = { "Common.Attr.Key.Delete": "删除", "Common.Attr.Key.Label": "标签", "Common.Attr.Key.Error.Multiple": "多重数值", + "Common.Attr.Key.Label.Picker.Nodata": "没有可以被添加的标签", "Panel.Info.Range.Details.Attr.Error.Not.Range": "对象不是一个范围", "Panel.Info.Range.Details.Attr.Error.Unspecified": "未指定范围对象", "Panel.Info.Label.Details.Error.Unspecified": "未指定标签对象", diff --git a/source/Panel/RangeDetails/RangeDetails.tsx b/source/Panel/RangeDetails/RangeDetails.tsx index 6326b64..5a74f57 100644 --- a/source/Panel/RangeDetails/RangeDetails.tsx +++ b/source/Panel/RangeDetails/RangeDetails.tsx @@ -10,7 +10,7 @@ import { TogglesInput } from "@Component/TogglesInput/TogglesInput"; import { LabelPicker } from "@Component/LabelPicker/LabelPicker"; import "./RangeDetails.scss"; -@useStatusWithEvent("rangeAttrChange", "focusObjectChange") +@useStatusWithEvent("rangeAttrChange", "focusObjectChange", "rangeLabelChange") class RangeDetails extends Component { public readonly AttrI18nKey: AllI18nKeys[] = [ @@ -62,8 +62,17 @@ class RangeDetails extends Component { })} { + if (this.props.status) { + this.props.status.addRangeLabel(range.id, label); + } + }} + labelDelete={(label) => { + if (this.props.status) { + this.props.status.deleteRangeLabel(range.id, label); + } + }} /> { -- 2.45.2