Skip to content

Commit 3238549

Browse files
authored
fix(web): Layer style expression startsWith doesn’t work[VIZ-2094] (#1759)
1 parent 7040def commit 3238549

File tree

2 files changed

+126
-5
lines changed

2 files changed

+126
-5
lines changed

web/src/app/features/Editor/Map/LayerStylePanel/Editor/StyleInterface/convert.test.tsx

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,51 @@ describe("parseConditions", () => {
218218
}
219219
]);
220220
});
221+
222+
it("should parse startsWith function call format correctly", () => {
223+
const conditions = parseConditions("color", [
224+
["startsWith(${gml_id}, 'bldg')", "color('red')"]
225+
]);
226+
227+
expect(conditions).toEqual([
228+
{
229+
variable: "${gml_id}",
230+
operator: "startsWith",
231+
value: "'bldg'",
232+
applyValue: "red"
233+
}
234+
]);
235+
});
236+
237+
it("should parse startsWith operator format correctly", () => {
238+
const conditions = parseConditions("color", [
239+
["${gml_id} startsWith 'bldg'", "color('red')"]
240+
]);
241+
242+
expect(conditions).toEqual([
243+
{
244+
variable: "${gml_id}",
245+
operator: "startsWith",
246+
value: "'bldg'",
247+
applyValue: "red"
248+
}
249+
]);
250+
});
251+
252+
it("should handle startsWith with different field types", () => {
253+
const conditions = parseConditions("text", [
254+
["startsWith(${name}, 'test')", "'example'"]
255+
]);
256+
257+
expect(conditions).toEqual([
258+
{
259+
variable: "${name}",
260+
operator: "startsWith",
261+
value: "'test'",
262+
applyValue: "example"
263+
}
264+
]);
265+
});
221266
});
222267

223268
it("should parse conditions with URL values correctly", () => {
@@ -255,6 +300,58 @@ describe("generateConditions", () => {
255300
["${marker-size} === 'medium'", "12"]
256301
]);
257302
});
303+
304+
it("should generate startsWith in function call format", () => {
305+
const startsWithConditions = generateConditions("color", [
306+
{
307+
variable: "${gml_id}",
308+
operator: "startsWith",
309+
value: "'bldg'",
310+
applyValue: "#FF0000"
311+
}
312+
]);
313+
314+
expect(startsWithConditions).toEqual([
315+
["startsWith(${gml_id}, 'bldg')", "color('#FF0000')"]
316+
]);
317+
});
318+
319+
it("should generate other operators in standard format", () => {
320+
const mixedConditions = generateConditions("color", [
321+
{
322+
variable: "${gml_id}",
323+
operator: "startsWith",
324+
value: "'bldg'",
325+
applyValue: "#FF0000"
326+
},
327+
{
328+
variable: "${type}",
329+
operator: "===",
330+
value: "'building'",
331+
applyValue: "#00FF00"
332+
}
333+
]);
334+
335+
expect(mixedConditions).toEqual([
336+
["startsWith(${gml_id}, 'bldg')", "color('#FF0000')"],
337+
["${type} === 'building'", "color('#00FF00')"]
338+
]);
339+
});
340+
341+
it("should handle startsWith with different field types", () => {
342+
const textConditions = generateConditions("text", [
343+
{
344+
variable: "${name}",
345+
operator: "startsWith",
346+
value: "'test'",
347+
applyValue: "example"
348+
}
349+
]);
350+
351+
expect(textConditions).toEqual([
352+
["startsWith(${name}, 'test')", "'example'"]
353+
]);
354+
});
258355
});
259356

260357
describe("wrapColor", () => {

web/src/app/features/Editor/Map/LayerStylePanel/Editor/StyleInterface/convert.ts

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ export const convertToStyleNodes = (
4747
}, {} as StyleNodes);
4848
};
4949

50-
export const checkExpressionAndConditions = (
51-
v: unknown
52-
): StyleValueType => {
50+
export const checkExpressionAndConditions = (v: unknown): StyleValueType => {
5351
if (
5452
typeof v === "string" ||
5553
typeof v === "number" ||
@@ -169,11 +167,30 @@ export const parseConditions = (
169167
conditions: [string, string][]
170168
): StyleCondition[] => {
171169
const operatorRegex = new RegExp(
172-
`(${styleConditionOperators.map((op) => op.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("|")})`
170+
`(${styleConditionOperators
171+
.map((op) => {
172+
if (op === "startsWith") {
173+
return "startsWith";
174+
}
175+
return op.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
176+
})
177+
.join("|")})`
173178
);
174179

175180
return conditions
176181
.map(([condition, applyValue]) => {
182+
if (condition.startsWith("startsWith(")) {
183+
const match = condition.match(/^startsWith\((.+),\s*(.+)\)$/);
184+
if (match) {
185+
return {
186+
variable: match[1].trim(),
187+
operator: "startsWith" as StyleConditionOperator,
188+
value: match[2].trim(),
189+
applyValue: unwrapConditionAppliedValue(field, applyValue)
190+
};
191+
}
192+
}
193+
177194
const match = condition.match(operatorRegex);
178195

179196
if (match) {
@@ -200,8 +217,15 @@ export const generateConditions = (
200217
): [string, string][] => {
201218
if (!conditions) return [];
202219
return conditions.map((c) => {
220+
let conditionExpression: string;
221+
if (c.operator === "startsWith") {
222+
conditionExpression = `startsWith(${c.variable}, ${c.value})`;
223+
} else {
224+
conditionExpression = `${c.variable} ${c.operator} ${c.value}`;
225+
}
226+
203227
return [
204-
`${c.variable} ${c.operator} ${c.value}`,
228+
conditionExpression,
205229
wrapConditionApplyValue((c.applyValue ?? "").toString(), field)
206230
];
207231
});

0 commit comments

Comments
 (0)