Skip to content

Commit

Permalink
fix: layers override behavior on rearth/core (#479)
Browse files Browse the repository at this point in the history
fix: override behavior on rearth/core
  • Loading branch information
keiya01 committed Feb 21, 2023
1 parent edf546e commit faff37f
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 9 deletions.
30 changes: 24 additions & 6 deletions src/core/Map/Layers/hooks.test.ts
Expand Up @@ -446,18 +446,36 @@ test("override", () => {
const l2 = result.current.flattenedLayers[1];
if (l2.type !== "simple") throw new Error("invalid layer type");
expect(l2.title).toBe("Y!!");
expect(l2.data?.value).toBe(dataValue);
expect(l2.marker).toEqual({ pointSize: 10, pointColor: "blue" });
expect(l2.data?.value).toBe(dataValue2);
expect(l2.marker).toEqual({ pointSize: 100, pointColor: "blue" });
expect(l2.tags).toEqual([{ id: "t2", label: "t2" }]);

result.current.ref.current?.override("y");
rerender();
const l3 = result.current.flattenedLayers[1];
if (l3.type !== "simple") throw new Error("invalid layer type");
expect(l3.title).toBe("Y");
expect(l3.data?.value).toBe(dataValue);
expect(l3.marker).toEqual({ pointSize: 10, pointColor: "red" });
expect(l3.tags).toBeUndefined();
expect(l3.title).toBe("Y!!");
expect(l3.data?.value).toBe(dataValue2);
expect(l3.marker).toEqual({ pointSize: 100, pointColor: "blue" });
expect(l2.tags).toEqual([{ id: "t2", label: "t2" }]);

result.current.ref.current?.override("y", { marker: {} });
rerender();
const l4 = result.current.flattenedLayers[1];
if (l4.type !== "simple") throw new Error("invalid layer type");
expect(l4.title).toBe("Y!!");
expect(l4.data?.value).toBe(dataValue2);
expect(l4.marker).toEqual({ pointSize: 10, pointColor: "red" });
expect(l2.tags).toEqual([{ id: "t2", label: "t2" }]);

result.current.ref.current?.override("y", { marker: undefined });
rerender();
const l5 = result.current.flattenedLayers[1];
if (l5.type !== "simple") throw new Error("invalid layer type");
expect(l5.title).toBe("Y!!");
expect(l5.data?.value).toBe(dataValue2);
expect(l5.marker).toEqual({ pointSize: 10, pointColor: "red" });
expect(l2.tags).toEqual([{ id: "t2", label: "t2" }]);
});

test("override property for compat", () => {
Expand Down
25 changes: 22 additions & 3 deletions src/core/Map/Layers/hooks.ts
Expand Up @@ -21,6 +21,7 @@ import type { Atom, ComputedLayer, Layer, NaiveLayer } from "../../mantle";
import { useGet } from "../utils";

import { computedLayerKeys, layerKeys } from "./keys";
import { deepAssign } from "./utils";

export type { Layer, NaiveLayer } from "../../mantle";

Expand Down Expand Up @@ -296,6 +297,24 @@ export default function useHooks({
const originalLayer = layerMap.get(id);
if (!originalLayer) return;

const overriddenLayer: any = overriddenLayers.find(l => l.id === id);
// prevents unnecessary copying of data value
const dataValue = (layer as any)?.data?.value ?? overriddenLayer?.data?.value;
const res = deepAssign(
{
...(overriddenLayer || {}),
...(overriddenLayer?.data ? { data: omit(overriddenLayer.data, "value") } : {}),
},
{
...(layer || {}),
...((layer as any)?.data ? { data: omit((layer as any).data, "value") } : {}),
},
);

if (dataValue && res.data) {
res.data.value = dataValue;
}

const property = layer?.property;
const rawLayer = compat({
...originalLayer,
Expand All @@ -312,7 +331,7 @@ export default function useHooks({
}
: {}),
...(!originalLayer.compat && property ? { property } : {}),
...layer,
...res,
});
if (!rawLayer) return;

Expand All @@ -327,14 +346,14 @@ export default function useHooks({
rawLayer.data.value.id = id;
}

const layer2 = { id, ...omit(rawLayer, "id", "type", "children") };
const layer2 = { id, ...omit(rawLayer, "id", "type", "children") } as Layer;
setOverridenLayers(layers => {
const i = layers.findIndex(l => l.id === id);
if (i < 0) return [...layers, layer2];
return [...layers.slice(0, i), layer2, ...layers.slice(i + 1)];
});
},
[layerMap],
[layerMap, overriddenLayers],
);

const deleteLayer = useCallback(
Expand Down
56 changes: 56 additions & 0 deletions src/core/Map/Layers/utils.test.ts
@@ -0,0 +1,56 @@
import { expect, test } from "vitest";

import { deepAssign } from "./utils";

test("deepAssign", () => {
expect(
deepAssign(
{ marker: { color: "red", size: 100 } },
{ marker: { color: "blue", image: "example.com" } },
),
).toEqual({ marker: { color: "blue", size: 100, image: "example.com" } });

expect(
deepAssign({ marker: { color: "red", size: 100 } }, { marker: { color: undefined } }),
).toEqual({ marker: { color: "red", size: 100 } });

expect(deepAssign({ marker: { color: "red", size: 100 } }, { marker: undefined })).toEqual({
marker: { color: "red", size: 100 },
});

expect(
deepAssign(
{ marker: { color: "red", size: 100 }, test: { value: ["abc"] } },
{ marker: undefined },
),
).toEqual({
marker: { color: "red", size: 100 },
test: { value: ["abc"] },
});

expect(
deepAssign(
{
marker: { color: "red", size: 100, deep: { value: { a: "abc" } } },
test: { value: ["abc"] },
},
{ marker: { deep: { value: { b: "def" } } } },
),
).toEqual({
marker: { color: "red", size: 100, deep: { value: { a: "abc", b: "def" } } },
test: { value: ["abc"] },
});

expect(
deepAssign(
{
marker: { color: "red", size: 100, deep: { value: { a: "abc" } } },
test: { value: ["abc"] },
},
{ marker: {} },
),
).toEqual({
marker: {},
test: { value: ["abc"] },
});
});
33 changes: 33 additions & 0 deletions src/core/Map/Layers/utils.ts
@@ -0,0 +1,33 @@
import { isArray, isObject } from "lodash-es";

export const deepAssign = <O extends Record<string, any>>(obj: O, src: O) => {
return Object.fromEntries(
Object.entries({ ...src, ...obj })
.map(([k, v]): [string, any] | undefined => {
const srcV: unknown = src[k];
if (srcV === undefined) {
return [k, v];
}

if (isArray(srcV)) {
return [k, srcV];
}

if (
isObject(v) &&
Object.keys(v).length !== 0 &&
isObject(srcV) &&
Object.keys(srcV).length !== 0
) {
return [k, deepAssign(v, srcV)];
}

if (v !== srcV) {
return [k, srcV];
}

return [k, v];
})
.filter((v): v is [string, any] => !!v),
) as O;
};

0 comments on commit faff37f

Please sign in to comment.