Skip to content

Commit ad6d03a

Browse files
Theme: allow overwrite theme styles
1 parent 9cb0240 commit ad6d03a

File tree

12 files changed

+127
-56
lines changed

12 files changed

+127
-56
lines changed

client/packages/lowcoder/src/api/commonSettingApi.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export interface ThemeType {
3535
id: string;
3636
updateTime: number;
3737
theme: ThemeDetail;
38+
overwriteStyles?: boolean;
3839
}
3940

4041
export interface ThemeDetail {

client/packages/lowcoder/src/comps/comps/containerComp/containerView.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,9 +293,10 @@ const getExtraLayout = (
293293
const autoHeight = item.autoHeight;
294294
const name = item.name;
295295
const compType = item.compType;
296+
const comp = item.comp;
296297
const isSelected = selectedCompNames.has(name) || dragSelectedNames?.has?.(name);
297298
const hidden = item.hidden;
298-
return { autoHeight, isSelected, name, hidden, compType };
299+
return { autoHeight, isSelected, name, hidden, compType, comp };
299300
});
300301
};
301302

client/packages/lowcoder/src/comps/comps/rootComp.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ function RootView(props: RootViewProps) {
7070
previewTheme?.previewTheme ||
7171
getCurrentTheme(themeList, appThemeId)?.theme ||
7272
localDefaultTheme;
73-
73+
74+
const overwriteStyles = Boolean(getCurrentTheme(themeList, appThemeId)?.overwriteStyles);
75+
7476
useEffect(() => {
7577
const newEditorState = new EditorState(comp, (changeEditorStateFn) => {
7678
setEditorState((oldState) => (oldState ? changeEditorStateFn(oldState) : undefined));
@@ -90,6 +92,7 @@ function RootView(props: RootViewProps) {
9092
const themeContextValue = useMemo(
9193
() => ({
9294
theme,
95+
overwriteStyles,
9396
}),
9497
[theme]
9598
);

client/packages/lowcoder/src/comps/comps/textComp.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { ThemeContext } from "../utils/themeContext";
2727
import { CompTypeContext } from "../utils/compTypeContext";
2828
import { changeChildAction } from "lowcoder-core";
2929
import { setInitialCompStyles } from "../utils/themeUtil";
30+
import { BoolControl } from "../controls/boolControl";
3031

3132
const getStyle = (style: TextStyleType) => {
3233
return css`
@@ -141,6 +142,7 @@ let TextTmpComp = (function () {
141142
animationStyle: styleControl(AnimationStyle, 'animationStyle'),
142143
margin: MarginControl,
143144
padding: PaddingControl,
145+
themeApplied: BoolControl,
144146
};
145147
return new UICompBuilder(childrenMap, (props, dispatch) => {
146148
const value = props.text.value;
@@ -154,6 +156,7 @@ let TextTmpComp = (function () {
154156
});
155157

156158
useEffect(() => {
159+
if (props.themeApplied) return;
157160
setInitialCompStyles({
158161
dispatch,
159162
compTheme,

client/packages/lowcoder/src/comps/controls/styleControl.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ import appSelectControl from "./appSelectControl";
8282
import { JSONObject, JSONValue } from "@lowcoder-ee/util/jsonTypes";
8383
import { CompTypeContext } from "../utils/compTypeContext";
8484
import { defaultTheme } from "@lowcoder-ee/constants/themeConstants";
85+
import { CompContext } from "../utils/compContext";
8586

8687
function isSimpleColorConfig(config: SingleColorConfig): config is SimpleColorConfig {
8788
return config.hasOwnProperty("color");
@@ -856,9 +857,11 @@ export function styleControl<T extends readonly SingleColorConfig[]>(
856857
return new ControlItemCompBuilder(
857858
childrenMap as ToConstructor<{ [K in Names<T>]: ColorControl }>,
858859
(props) => {
859-
const compType = useContext(CompTypeContext);
860+
// const compType = useContext(CompTypeContext);
861+
const {comp, compType} = useContext(CompContext);
860862
const theme = useContext(ThemeContext);
861863
const bgColor = useContext(BackgroundColorContext);
864+
const { overwriteStyles } = theme || {};
862865
const compTheme = compType
863866
? {
864867
...(defaultTheme.components?.[compType]?.[styleKey] || {}) as unknown as Record<string, string>,
@@ -867,7 +870,7 @@ export function styleControl<T extends readonly SingleColorConfig[]>(
867870
: undefined;
868871

869872
return calcColors(
870-
props as ColorMap,
873+
overwriteStyles && !Boolean(comp?.comp?.themeApplied) ? {} as ColorMap : props as ColorMap,
871874
colorConfigs,
872875
theme?.theme,
873876
bgColor,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import React from "react";
2+
3+
export const CompContext = React.createContext<{
4+
comp?: any;
5+
compType: string;
6+
}>({ comp: undefined, compType: '' });

client/packages/lowcoder/src/comps/utils/themeContext.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ import React from "react";
44
export class Theme {
55
readonly theme?: ThemeDetail;
66
readonly previewTheme?: ThemeDetail;
7+
readonly overwriteStyles?: boolean;
78
}
89
export const ThemeContext = React.createContext<Theme | undefined>(undefined);

client/packages/lowcoder/src/comps/utils/themeUtil.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export function setInitialCompStyles({
4040
...styleProps[styleKey],
4141
}, false);
4242
})
43+
actions['themeApplied'] = changeValueAction(true, false);
4344

4445
dispatch(
4546
multiChangeAction(actions),

client/packages/lowcoder/src/layout/gridLayout.tsx

Lines changed: 55 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import {
5252
updateInCanvasCount,
5353
} from "./utils";
5454
import { CompTypeContext } from "@lowcoder-ee/comps/utils/compTypeContext";
55+
import { CompContext } from "@lowcoder-ee/comps/utils/compContext";
5556

5657
type GridLayoutState = {
5758
layout: Layout;
@@ -443,55 +444,60 @@ class GridLayout extends React.Component<GridLayoutProps, GridLayoutState> {
443444
const selectable = isSelectable;
444445
const positionParams = genPositionParams(this.props);
445446
return (
446-
<CompTypeContext.Provider value={extraItem?.compType}>
447-
<GridItem
448-
compType={extraItem?.compType}
449-
key={item.i}
450-
containerWidth={width}
451-
cols={cols}
452-
margin={margin}
453-
containerPadding={positionParams.containerPadding}
454-
maxRows={maxRows}
455-
rowHeight={rowHeight}
456-
onDragStart={this.onDragStart}
457-
onDrag={this.onDrag}
458-
onDragEnd={this.onDragEnd}
459-
onResizeStart={this.onResizeStart}
460-
onResize={this.onResize}
461-
onResizeStop={this.onResizeStop}
462-
onHeightChange={this.onHeightChange}
463-
isDraggable={isDraggable && isItemDraggable(item)}
464-
isResizable={isResizable && isItemResizable(item)}
465-
isSelectable={selectable}
466-
transformScale={transformScale}
467-
w={item.w}
468-
h={extraItem?.hidden && !extraItem?.isSelected ? 0 : item.h}
469-
x={item.x}
470-
y={item.y}
471-
i={item.i}
472-
minH={item.minH}
473-
minW={item.minW}
474-
maxH={item.maxH}
475-
maxW={item.maxW}
476-
placeholder={item.placeholder}
477-
layoutHide={item.hide}
478-
static={item.static}
479-
resizeHandles={getItemResizeHandles(item, extraItem)}
480-
name={extraItem?.name}
481-
autoHeight={extraItem?.autoHeight}
482-
isSelected={extraItem?.isSelected}
483-
hidden={extraItem?.hidden}
484-
selectedSize={selectedSize}
485-
clickItem={clickItem}
486-
showName={{
487-
top: showName?.top ?? 0,
488-
bottom: (showName?.bottom ?? 0) + (this.ref.current?.scrollHeight ?? 0),
489-
}}
490-
zIndex={zIndex}
491-
>
492-
{child}
493-
</GridItem>
494-
</CompTypeContext.Provider>
447+
<CompContext.Provider value={{
448+
compType: extraItem?.compType,
449+
comp: extraItem?.comp?.toJsonValue(),
450+
}}>
451+
<CompTypeContext.Provider value={extraItem?.compType}>
452+
<GridItem
453+
compType={extraItem?.compType}
454+
key={item.i}
455+
containerWidth={width}
456+
cols={cols}
457+
margin={margin}
458+
containerPadding={positionParams.containerPadding}
459+
maxRows={maxRows}
460+
rowHeight={rowHeight}
461+
onDragStart={this.onDragStart}
462+
onDrag={this.onDrag}
463+
onDragEnd={this.onDragEnd}
464+
onResizeStart={this.onResizeStart}
465+
onResize={this.onResize}
466+
onResizeStop={this.onResizeStop}
467+
onHeightChange={this.onHeightChange}
468+
isDraggable={isDraggable && isItemDraggable(item)}
469+
isResizable={isResizable && isItemResizable(item)}
470+
isSelectable={selectable}
471+
transformScale={transformScale}
472+
w={item.w}
473+
h={extraItem?.hidden && !extraItem?.isSelected ? 0 : item.h}
474+
x={item.x}
475+
y={item.y}
476+
i={item.i}
477+
minH={item.minH}
478+
minW={item.minW}
479+
maxH={item.maxH}
480+
maxW={item.maxW}
481+
placeholder={item.placeholder}
482+
layoutHide={item.hide}
483+
static={item.static}
484+
resizeHandles={getItemResizeHandles(item, extraItem)}
485+
name={extraItem?.name}
486+
autoHeight={extraItem?.autoHeight}
487+
isSelected={extraItem?.isSelected}
488+
hidden={extraItem?.hidden}
489+
selectedSize={selectedSize}
490+
clickItem={clickItem}
491+
showName={{
492+
top: showName?.top ?? 0,
493+
bottom: (showName?.bottom ?? 0) + (this.ref.current?.scrollHeight ?? 0),
494+
}}
495+
zIndex={zIndex}
496+
>
497+
{child}
498+
</GridItem>
499+
</CompTypeContext.Provider>
500+
</CompContext.Provider>
495501
);
496502
}
497503

client/packages/lowcoder/src/layout/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export type LayoutItem = {
3333
};
3434
export type ExtraItem = {
3535
name: string;
36+
comp: any;
3637
compType: UICompType;
3738
autoHeight?: boolean;
3839
isSelected?: boolean;

client/packages/lowcoder/src/pages/setting/theme/detail/index.tsx

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { Card, Collapse, CollapseProps, Divider, Flex, List, Tooltip } from 'ant
4545

4646
import { ThemeCompPanel } from "pages/setting/theme/ThemeCompPanel";
4747
import { JSONObject } from "@lowcoder-ee/util/jsonTypes";
48+
import Switch from "antd/es/switch";
4849

4950
const ThemeSettingsView = styled.div`
5051
font-size: 14px;
@@ -75,6 +76,7 @@ type LocationProp = {
7576
name: string;
7677
id: string;
7778
type: DETAIL_TYPE;
79+
overwriteStyles?: boolean;
7880
};
7981

8082
type ThemeDetailPageProps = {
@@ -97,15 +99,15 @@ type ThemeDetailPageState = {
9799

98100
class ThemeDetailPage extends React.Component<ThemeDetailPageProps, ThemeDetailPageState> {
99101
themeDefault: ThemeDetail;
102+
overwriteStyles: boolean;
100103
readonly id: string;
101104
readonly type: string;
102105
readonly inputRef: React.RefObject<InputRef>;
103106
footerRef = React.createRef<HTMLDivElement>();
104107

105108
constructor(props: ThemeDetailPageProps) {
106109
super(props);
107-
const { name, id, theme, type } = props.location.state || {};
108-
console.log("defaultTheme", theme);
110+
const { name, id, theme, type, overwriteStyles } = props.location.state || {};
109111
if (!name || !id || !theme || !type) {
110112
history.replace(BASE_URL);
111113
window.location.reload();
@@ -122,6 +124,7 @@ class ThemeDetailPage extends React.Component<ThemeDetailPageProps, ThemeDetailP
122124

123125
this.id = id;
124126
this.type = type;
127+
this.overwriteStyles = Boolean(overwriteStyles);
125128
this.state = {
126129
theme,
127130
name,
@@ -135,6 +138,36 @@ class ThemeDetailPage extends React.Component<ThemeDetailPageProps, ThemeDetailP
135138
this.setState({ theme: this.themeDefault });
136139
}
137140

141+
handleOverwriteStyles(overwriteStyles: boolean) {
142+
this.props.fetchCommonSettings(this.props.orgId, ({ themeList }) => {
143+
let list = [];
144+
const currentTheme = {
145+
name: this.state.name,
146+
id: this.id,
147+
updateTime: new Date().getTime(),
148+
theme: this.themeDefault,
149+
overwriteStyles: overwriteStyles,
150+
};
151+
list = themeList!.map((theme) => {
152+
if (theme.id === this.id) {
153+
return currentTheme;
154+
} else {
155+
return theme;
156+
}
157+
});
158+
159+
this.props.setCommonSettings({
160+
orgId: this.props.orgId,
161+
data: { key: "themeList", value: list },
162+
onSuccess: () => {
163+
messageInstance.success(trans("theme.saveSuccessMsg"));
164+
this.themeDefault = this.state.theme;
165+
this.overwriteStyles = overwriteStyles;
166+
},
167+
});
168+
});
169+
}
170+
138171
handleSave() {
139172
this.props.fetchCommonSettings(this.props.orgId, ({ themeList }) => {
140173
let list = [];
@@ -343,6 +376,15 @@ class ThemeDetailPage extends React.Component<ThemeDetailPageProps, ThemeDetailP
343376
<ArrowIcon />
344377
<span>{this.state.name}</span>
345378
</HeaderBack>
379+
<Flex gap={8}>
380+
<b style={{margin: 0}}>
381+
Overwrite styles
382+
</b>
383+
<Switch defaultValue={this.overwriteStyles} onChange={() => {
384+
console.log('change');
385+
this.handleOverwriteStyles(!this.overwriteStyles)
386+
}}/>
387+
</Flex>
346388
</Header>
347389

348390
<DetailContent>

client/packages/lowcoder/src/pages/setting/theme/styledComponents.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,10 @@ export const Footer = styled.div`
134134
`;
135135

136136
export const Header = styled.div`
137-
margin: 0 0 37px 24px;
137+
display: flex;
138+
justify-content: space-between;
139+
align-items: center;
140+
margin: 0 24px 37px 24px;
138141
`;
139142

140143
export const DetailTitle = styled.div`

0 commit comments

Comments
 (0)