feat: implement simulation dashboard element data management with new input components and styles
This commit is contained in:
@@ -107,23 +107,17 @@ const AnalyzerManager: React.FC = () => {
|
||||
|
||||
const assetAnalysis = getAssetAnalysis(assetId);
|
||||
if (assetAnalysis) {
|
||||
const timeLabel = new Date().toLocaleTimeString();
|
||||
const newPoint: GraphDataPoint = { name: timeLabel, value: 0 };
|
||||
|
||||
let hasValidData = false;
|
||||
dataKeys.forEach((key) => {
|
||||
const newGraphData = dataKeys.map((key) => {
|
||||
const val = resolvePath(assetAnalysis, key);
|
||||
if (typeof val === "number") {
|
||||
newPoint["value"] = val;
|
||||
hasValidData = true;
|
||||
}
|
||||
return {
|
||||
// Make the key readable or just use it as name
|
||||
name: key.split(".").pop() || key,
|
||||
value: typeof val === "number" ? val : 0,
|
||||
};
|
||||
});
|
||||
|
||||
if (hasValidData) {
|
||||
const currentGraphData = element.graphData || [];
|
||||
const newGraphData = [...currentGraphData, newPoint].slice(-10);
|
||||
|
||||
// Always update for single-machine as we are appending time-series data
|
||||
// Deep check to avoid unnecessary updates
|
||||
if (JSON.stringify(newGraphData) !== JSON.stringify(element.graphData)) {
|
||||
updateGraphData(block.blockUuid, element.elementUuid, newGraphData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ const ElementData: React.FC<ElementDataProps> = ({
|
||||
const totalAssetOptions = assetDropdownItems.length;
|
||||
|
||||
return (
|
||||
<div className="data-details">
|
||||
<div className="fields-wrapper data-details">
|
||||
{element?.type === "label-value" && (
|
||||
<>
|
||||
<div className="design-section">
|
||||
@@ -99,7 +99,7 @@ const ElementData: React.FC<ElementDataProps> = ({
|
||||
updateElementData(selectedBlock, selectedElement, { label: value });
|
||||
}}
|
||||
/>
|
||||
<div className="data">
|
||||
<div className="datas">
|
||||
<DataDetailedDropdown
|
||||
title="Data Source"
|
||||
placeholder="Select assets"
|
||||
@@ -134,9 +134,10 @@ const ElementData: React.FC<ElementDataProps> = ({
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="data">
|
||||
<div className="datas">
|
||||
<DataDetailedDropdown
|
||||
title="Data Value"
|
||||
className="fill-width"
|
||||
placeholder="Select Value"
|
||||
sections={getLableValueDropdownItems(element.dataBinding?.dataSource as string | undefined)}
|
||||
value={
|
||||
@@ -163,8 +164,8 @@ const ElementData: React.FC<ElementDataProps> = ({
|
||||
|
||||
{/* Data Mapping */}
|
||||
{element?.type === "graph" && (
|
||||
<div className="data-mapping">
|
||||
<div className="heading">Data Mapping</div>
|
||||
<div className="data-mapping design-section">
|
||||
<div className="sub-header">Data Mapping</div>
|
||||
|
||||
<div className="type-switch">
|
||||
<div className={`type ${selectDataMapping === "singleMachine" ? "active" : ""}`} onClick={() => handleDataTypeSwitch("singleMachine")}>
|
||||
@@ -243,6 +244,7 @@ const ElementData: React.FC<ElementDataProps> = ({
|
||||
{multipleValueFields.map((field) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
className="fill-width"
|
||||
label={field.label}
|
||||
options={field.options}
|
||||
selected={field.options.find((o) => o.id === element.dataBinding?.commonValue)?.label ?? ""}
|
||||
@@ -258,6 +260,7 @@ const ElementData: React.FC<ElementDataProps> = ({
|
||||
{multipleSourceFields.map((field, index) => (
|
||||
<DataSourceSelector
|
||||
key={field.id}
|
||||
className="dual-buttons"
|
||||
label={field.label}
|
||||
options={getFilteredOptions(field.options, element.dataBinding?.dataSource, index)}
|
||||
selected={getEventByModelUuid(selectedProduct.productUuid, (element.dataBinding?.dataSource as string[])?.[index] || "")?.modelName ?? ""}
|
||||
|
||||
@@ -450,7 +450,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
|
||||
return dataValues.map((value, index) => ({
|
||||
id: `data-value-${index}`,
|
||||
label: `Data Value ${index + 1}`,
|
||||
label: `Value ${index + 1}`,
|
||||
showEyeDropper: false,
|
||||
options: valueOptions,
|
||||
}));
|
||||
@@ -459,7 +459,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
return [
|
||||
{
|
||||
id: "data-value",
|
||||
label: "Data Value",
|
||||
label: "Value",
|
||||
showEyeDropper: false,
|
||||
options: [],
|
||||
},
|
||||
@@ -472,7 +472,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
|
||||
return dataSources.map((_, index) => ({
|
||||
id: `data-source-${index}`,
|
||||
label: `Data Source ${index + 1}`,
|
||||
label: `Source ${index + 1}`,
|
||||
showEyeDropper: true,
|
||||
options: getAssetDropdownItems().map((item) => ({
|
||||
id: item.id,
|
||||
@@ -485,7 +485,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
}, [element, getAssetDropdownItems]);
|
||||
|
||||
const multipleValueFields = useMemo(
|
||||
() => [{ id: "data-value", label: "Data Value", showEyeDropper: false, options: getCommonValueDropdownItems().map((item) => ({ id: item.id, label: item.label })) }],
|
||||
() => [{ id: "data-value", label: "Value", showEyeDropper: false, options: getCommonValueDropdownItems().map((item) => ({ id: item.id, label: item.label })) }],
|
||||
[getCommonValueDropdownItems]
|
||||
);
|
||||
|
||||
@@ -524,7 +524,7 @@ const ElementEditor: React.FC<ElementEditorProps> = ({
|
||||
}
|
||||
}}
|
||||
className="panel element-editor-panel"
|
||||
style={{ position: "fixed", left: position.x, top: position.y, zIndex: 1000, width: panelWidth }}
|
||||
style={{ position: "fixed", left: position.x, top: position.y, zIndex: 1000, width: panelWidth }}
|
||||
>
|
||||
<div className="free-move-button" onPointerDown={startDrag} onDoubleClick={resetPosition}>
|
||||
<ResizeHeightIcon />
|
||||
|
||||
@@ -9,6 +9,7 @@ export type DropdownItem = {
|
||||
|
||||
type DataDetailedDropdownProps = {
|
||||
title: string;
|
||||
className?: string;
|
||||
placeholder?: string;
|
||||
sections: {
|
||||
title?: string;
|
||||
@@ -22,7 +23,18 @@ type DataDetailedDropdownProps = {
|
||||
onEyeDrop?: () => void;
|
||||
};
|
||||
|
||||
const DataDetailedDropdown: React.FC<DataDetailedDropdownProps> = ({ title, placeholder = "Select value", sections, value, onChange, dropDownHeader, eyedroper, eyeDropperActive, onEyeDrop }) => {
|
||||
const DataDetailedDropdown: React.FC<DataDetailedDropdownProps> = ({
|
||||
title,
|
||||
className,
|
||||
placeholder = "Select value",
|
||||
sections,
|
||||
value,
|
||||
onChange,
|
||||
dropDownHeader,
|
||||
eyedroper,
|
||||
eyeDropperActive,
|
||||
onEyeDrop,
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [search, setSearch] = useState("");
|
||||
const [isEyeDroperActiveLocal, setIsEyeDroperActiveLocal] = useState(false);
|
||||
@@ -62,7 +74,7 @@ const DataDetailedDropdown: React.FC<DataDetailedDropdownProps> = ({ title, plac
|
||||
}, [search, sections]);
|
||||
|
||||
return (
|
||||
<div className="data-detailed-dropdown" ref={containerRef}>
|
||||
<div className={`data-detailed-dropdown ${className ?? ""}`} ref={containerRef}>
|
||||
<div className="title">{title}</div>
|
||||
<div className="input-container">
|
||||
<div className="input-wrapper">
|
||||
|
||||
@@ -5,6 +5,7 @@ import { DeleteIcon } from "../../icons/ContextMenuIcons";
|
||||
|
||||
type DataSourceSelectorProps = {
|
||||
label?: string;
|
||||
className?: string;
|
||||
options: {
|
||||
id: string;
|
||||
label: string;
|
||||
@@ -18,7 +19,18 @@ type DataSourceSelectorProps = {
|
||||
onEyeDrop?: () => void;
|
||||
};
|
||||
|
||||
const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({ label = "Data Source", options, selected, onSelect, showEyeDropper = true, showDeleteBtn, onDelete, eyeDropperActive, onEyeDrop }) => {
|
||||
const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({
|
||||
label = "Data Source",
|
||||
className,
|
||||
options,
|
||||
selected,
|
||||
onSelect,
|
||||
showEyeDropper = true,
|
||||
showDeleteBtn,
|
||||
onDelete,
|
||||
eyeDropperActive,
|
||||
onEyeDrop,
|
||||
}) => {
|
||||
// Local state fallback if no external control provided
|
||||
const [isEyeActiveLocal, setIsEyeActiveLocal] = useState(false);
|
||||
|
||||
@@ -33,7 +45,7 @@ const DataSourceSelector: React.FC<DataSourceSelectorProps> = ({ label = "Data S
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="datas">
|
||||
<div className={`datas ${className ?? ""}`}>
|
||||
<div className="datas__label">{label}</div>
|
||||
|
||||
<div className="datas__class">
|
||||
|
||||
@@ -2,145 +2,123 @@ import React, { useState, useEffect, useRef } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
interface DropdownProps {
|
||||
header: string;
|
||||
options: string[];
|
||||
onSelect: (option: string) => void;
|
||||
search?: boolean;
|
||||
onClick?: () => void;
|
||||
onChange?: () => void;
|
||||
header: string;
|
||||
options: string[];
|
||||
onSelect: (option: string) => void;
|
||||
search?: boolean;
|
||||
onClick?: () => void;
|
||||
onChange?: () => void;
|
||||
}
|
||||
|
||||
const RegularDropDown: React.FC<DropdownProps> = ({
|
||||
header,
|
||||
options,
|
||||
onSelect,
|
||||
search = true,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedOption, setSelectedOption] = useState<string | null>(null);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [filteredOptions, setFilteredOptions] = useState<string[]>(options);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const [position, setPosition] = useState<{
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
}>({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
});
|
||||
const RegularDropDown: React.FC<DropdownProps> = ({ header, options, onSelect, search = true }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedOption, setSelectedOption] = useState<string | null>(null);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [filteredOptions, setFilteredOptions] = useState<string[]>(options);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null);
|
||||
const [position, setPosition] = useState<{
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
}>({
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
});
|
||||
|
||||
// Reset when closed
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setSelectedOption(null);
|
||||
setSearchTerm("");
|
||||
setFilteredOptions(options);
|
||||
}
|
||||
}, [isOpen, options]);
|
||||
// Reset when closed
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setSelectedOption(null);
|
||||
setSearchTerm("");
|
||||
setFilteredOptions(options);
|
||||
}
|
||||
}, [isOpen, options]);
|
||||
|
||||
// Reset when header changes
|
||||
useEffect(() => {
|
||||
setSelectedOption(null);
|
||||
setSearchTerm("");
|
||||
setFilteredOptions(options);
|
||||
}, [header, options]);
|
||||
// Reset when header changes
|
||||
useEffect(() => {
|
||||
setSelectedOption(null);
|
||||
setSearchTerm("");
|
||||
setFilteredOptions(options);
|
||||
}, [header, options]);
|
||||
|
||||
// Close if clicked outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (
|
||||
dropdownRef.current &&
|
||||
!dropdownRef.current.contains(event.target as Node)
|
||||
) {
|
||||
// Close if clicked outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
document.addEventListener("click", handleClickOutside);
|
||||
return () => document.removeEventListener("click", handleClickOutside);
|
||||
}, []);
|
||||
|
||||
// Recalculate position when opening
|
||||
useEffect(() => {
|
||||
if (isOpen && dropdownRef.current) {
|
||||
const rect = dropdownRef.current.getBoundingClientRect();
|
||||
setPosition({
|
||||
top: rect.bottom + window.scrollY,
|
||||
left: rect.left + window.scrollX,
|
||||
width: rect.width,
|
||||
});
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const toggleDropdown = () => setIsOpen((prev) => !prev);
|
||||
|
||||
const handleOptionClick = (option: string) => {
|
||||
setSelectedOption(option);
|
||||
onSelect(option);
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
document.addEventListener("click", handleClickOutside);
|
||||
return () => document.removeEventListener("click", handleClickOutside);
|
||||
}, []);
|
||||
|
||||
// Recalculate position when opening
|
||||
useEffect(() => {
|
||||
if (isOpen && dropdownRef.current) {
|
||||
const rect = dropdownRef.current.getBoundingClientRect();
|
||||
setPosition({
|
||||
top: rect.bottom + window.scrollY,
|
||||
left: rect.left + window.scrollX,
|
||||
width: rect.width,
|
||||
});
|
||||
}
|
||||
}, [isOpen]);
|
||||
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const term = event.target.value;
|
||||
setSearchTerm(term);
|
||||
setFilteredOptions(options.filter((option) => option.toLowerCase().includes(term.toLowerCase())));
|
||||
};
|
||||
|
||||
const toggleDropdown = () => setIsOpen((prev) => !prev);
|
||||
return (
|
||||
<div className="regularDropdown-container" ref={dropdownRef}>
|
||||
{/* Header */}
|
||||
<div className="dropdown-header flex-sb" onClick={toggleDropdown}>
|
||||
<div className="key">{selectedOption || header}</div>
|
||||
<div className="icon">▾</div>
|
||||
</div>
|
||||
|
||||
const handleOptionClick = (option: string) => {
|
||||
setSelectedOption(option);
|
||||
onSelect(option);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const term = event.target.value;
|
||||
setSearchTerm(term);
|
||||
setFilteredOptions(
|
||||
options.filter((option) =>
|
||||
option.toLowerCase().includes(term.toLowerCase())
|
||||
)
|
||||
{/* Options rendered in portal */}
|
||||
{isOpen &&
|
||||
createPortal(
|
||||
<div
|
||||
className="dropdown-options"
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: position.top,
|
||||
left: position.left,
|
||||
width: position.width,
|
||||
zIndex: 9999,
|
||||
}}
|
||||
>
|
||||
{search && (
|
||||
<div className="dropdown-search">
|
||||
<input type="text" placeholder="Search..." value={searchTerm} onChange={handleSearchChange} />
|
||||
</div>
|
||||
)}
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option, index) => (
|
||||
<div className="option" key={index} onClick={() => handleOptionClick(option)} title={option}>
|
||||
{option}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="no-options">No options found</div>
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="regularDropdown-container" ref={dropdownRef}>
|
||||
{/* Header */}
|
||||
<div className="dropdown-header flex-sb" onClick={toggleDropdown}>
|
||||
<div className="key">{selectedOption || header}</div>
|
||||
<div className="icon">▾</div>
|
||||
</div>
|
||||
|
||||
{/* Options rendered in portal */}
|
||||
{isOpen &&
|
||||
createPortal(
|
||||
<div
|
||||
className="dropdown-options"
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: position.top,
|
||||
left: position.left,
|
||||
width: position.width,
|
||||
zIndex: 9999,
|
||||
}}
|
||||
>
|
||||
{search && (
|
||||
<div className="dropdown-search">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
value={searchTerm}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option, index) => (
|
||||
<div
|
||||
className="option"
|
||||
key={index}
|
||||
onClick={() => handleOptionClick(option)}
|
||||
title={option}
|
||||
>
|
||||
{option}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="no-options">No options found</div>
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RegularDropDown;
|
||||
|
||||
@@ -15,12 +15,7 @@ interface DropdownProps {
|
||||
onChange?: () => void;
|
||||
}
|
||||
|
||||
const RegularDropDownID: React.FC<DropdownProps> = ({
|
||||
header,
|
||||
options,
|
||||
onSelect,
|
||||
search = true,
|
||||
}) => {
|
||||
const RegularDropDownID: React.FC<DropdownProps> = ({ header, options, onSelect, search = true }) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedOption, setSelectedOption] = useState<string | null>(null);
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
@@ -70,7 +65,7 @@ const RegularDropDownID: React.FC<DropdownProps> = ({
|
||||
const handleSearchChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const term = e.target.value;
|
||||
setSearchTerm(term);
|
||||
setFilteredOptions(options.filter(o => o.label.toLowerCase().includes(term.toLowerCase())));
|
||||
setFilteredOptions(options.filter((o) => o.label.toLowerCase().includes(term.toLowerCase())));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -80,27 +75,28 @@ const RegularDropDownID: React.FC<DropdownProps> = ({
|
||||
<div className="icon">▾</div>
|
||||
</div>
|
||||
|
||||
{isOpen && createPortal(
|
||||
<div className="dropdown-options" style={{ position: "absolute", top: position.top, left: position.left, width: position.width, zIndex: 9999 }}>
|
||||
{search && (
|
||||
<div className="dropdown-search">
|
||||
<input type="text" placeholder="Search..." value={searchTerm} onChange={handleSearchChange} />
|
||||
</div>
|
||||
)}
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((opt) => (
|
||||
<div className="option" key={opt.id} onClick={() => handleOptionClick(opt)} title={opt.label}>
|
||||
{opt.label}
|
||||
{isOpen &&
|
||||
createPortal(
|
||||
<div className="dropdown-options" style={{ position: "absolute", top: position.top, left: position.left, width: position.width, zIndex: 9999 }}>
|
||||
{search && (
|
||||
<div className="dropdown-search">
|
||||
<input type="text" placeholder="Search..." value={searchTerm} onChange={handleSearchChange} />
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="no-options">No options found</div>
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
)}
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((opt) => (
|
||||
<div className="option" key={opt.id} onClick={() => handleOptionClick(opt)} title={opt.label}>
|
||||
{opt.label}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="no-options">No options found</div>
|
||||
)}
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default RegularDropDownID
|
||||
export default RegularDropDownID;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -337,6 +337,11 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.sub-header {
|
||||
padding: 4px 6px 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.design-section {
|
||||
padding: 4px;
|
||||
outline: 1px solid var(--border-color);
|
||||
@@ -353,6 +358,10 @@
|
||||
.value-field-container {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
.label {
|
||||
width: 90px;
|
||||
max-width: 90px;
|
||||
}
|
||||
}
|
||||
|
||||
.select-type {
|
||||
@@ -534,18 +543,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.datas {
|
||||
// width: 100% ;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.datas__label,
|
||||
.datas__class {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.type-switch {
|
||||
display: flex;
|
||||
|
||||
@@ -594,6 +591,101 @@
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
|
||||
.datas {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// padding: 6px 12px;
|
||||
|
||||
&__label,
|
||||
&__class,
|
||||
.input-container,
|
||||
.title {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__label,
|
||||
.title {
|
||||
flex: 0.8;
|
||||
max-width: 90px;
|
||||
min-width: 90px;
|
||||
width: 90px;
|
||||
line-height: 23px;
|
||||
}
|
||||
|
||||
&__class,
|
||||
.input-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.input-wrapper {
|
||||
max-width: 126px;
|
||||
width: 126px;
|
||||
.icon {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.add-icon,
|
||||
.delete {
|
||||
display: flex;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--background-color-input);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--background-color-button);
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: var(--log-error-background-color);
|
||||
path {
|
||||
stroke: var(--log-error-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.regularDropdown-container {
|
||||
max-width: 112px;
|
||||
width: 112px;
|
||||
.icon {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fields-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
|
||||
.add-field {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
svg path {
|
||||
stroke: #ccacff !important;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #ccacff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.data-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -633,97 +725,6 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 9px;
|
||||
background: var(--background-color);
|
||||
border: 1px solid var(--border-color);
|
||||
box-shadow: var(--box-shadow-medium);
|
||||
padding: 15px 12px;
|
||||
border-radius: 25px;
|
||||
|
||||
.heading {
|
||||
padding: 4px 6px 8px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.fields-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
|
||||
.datas {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// padding: 6px 12px;
|
||||
|
||||
.datas__label,
|
||||
.datas__class {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.datas__label {
|
||||
flex: 0.8;
|
||||
min-width: 96px;
|
||||
}
|
||||
|
||||
.datas__class {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
|
||||
.add-icon,
|
||||
.delete {
|
||||
display: flex;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: var(--background-color-input);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--background-color-button);
|
||||
}
|
||||
}
|
||||
|
||||
.delete {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: var(--log-error-background-color);
|
||||
path {
|
||||
stroke: var(--log-error-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.regularDropdown-container {
|
||||
max-width: 106px;
|
||||
width: 106px;
|
||||
.icon {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-field {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
svg path {
|
||||
stroke: #ccacff !important;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: #ccacff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1106,3 +1107,18 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fill-width {
|
||||
.input-wrapper,
|
||||
.regularDropdown-container {
|
||||
max-width: none !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.dual-buttons {
|
||||
.regularDropdown-container {
|
||||
max-width: 70px !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user