Skip to content

Commit e8480e3

Browse files
authored
refactor(web): builtin widget Data Attribution (#1641)
1 parent 723bc06 commit e8480e3

File tree

10 files changed

+161
-139
lines changed

10 files changed

+161
-139
lines changed

web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@
129129
"@monaco-editor/react": "4.6.0",
130130
"@popperjs/core": "2.11.8",
131131
"@radix-ui/react-slot": "1.1.0",
132-
"@reearth/core": "0.0.7-alpha.37",
132+
"@reearth/core": "0.0.7-alpha.38",
133133
"@rot1024/use-transition": "1.0.0",
134134
"@sentry/browser": "7.77.0",
135135
"@seznam/compose-react-refs": "1.0.6",

web/src/beta/features/Visualizer/Crust/Widgets/Widget/builtin/DataAttribution/UI/hooks.ts

Lines changed: 0 additions & 79 deletions
This file was deleted.

web/src/beta/features/Visualizer/Crust/Widgets/Widget/builtin/DataAttribution/UI/index.stories.tsx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,11 @@ export const Normal: StoryFn<DataAttributionProps> = (args) => (
1313
<div style={{ width: "100%", maxWidth: "416px" }}>
1414
<DataAttributionUI
1515
{...args}
16-
widget={{
17-
id: "",
18-
extended: {
19-
horizontally: false,
20-
vertically: false
21-
},
22-
property: {
23-
default: [
24-
{
25-
description: "Testing",
26-
creditUrl: "https://www.sample.com/",
27-
id: "01"
28-
}
29-
]
30-
}
31-
}}
3216
credits={[
3317
{
34-
html: `<a href="https://example.com" target="_blank">Example Credit</a>`
18+
description: "Test description",
19+
logo: "",
20+
creditUrl: "https://www.sample.com/"
3521
}
3622
]}
3723
/>

web/src/beta/features/Visualizer/Crust/Widgets/Widget/builtin/DataAttribution/UI/index.tsx

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,23 @@
11
import { IconButton } from "@reearth/beta/lib/reearth-ui";
2-
import { Credit } from "@reearth/core";
2+
import { Credit } from "@reearth/beta/utils/value";
33
import { useT } from "@reearth/services/i18n";
44
import { fonts, styled } from "@reearth/services/theme";
55
import { FC } from "react";
66

7-
import { Theme, Widget } from "../../../types";
8-
9-
import { useDataAttribution } from "./hooks";
7+
import { Theme } from "../../../types";
108

119
export type DataAttributionProps = {
1210
theme?: Theme;
13-
widget: Widget;
1411
credits?: Credit[];
1512
onClose: () => void;
1613
};
1714

1815
export const DataAttributionUI: FC<DataAttributionProps> = ({
1916
theme,
20-
widget,
2117
credits,
2218
onClose
2319
}) => {
2420
const t = useT();
25-
const { processedCredits } = useDataAttribution({
26-
credits,
27-
widget
28-
});
2921

3022
return (
3123
<Wrapper>
@@ -41,19 +33,19 @@ export const DataAttributionUI: FC<DataAttributionProps> = ({
4133
<Title>{t("Data Provided by:")}</Title>
4234
<ContentWrapper>
4335
<Content>
44-
{processedCredits &&
45-
processedCredits.map((credit, i) => (
36+
{credits &&
37+
credits.map((credit, i) => (
4638
<ListItem key={i}>
4739
<ListMarker></ListMarker>
48-
{credit.link ? (
40+
{credit.creditUrl ? (
4941
<CreditItemLink
5042
target="_blank"
51-
href={credit.link}
43+
href={credit.creditUrl}
5244
rel="noopener noreferrer"
5345
>
54-
{credit.img && (
46+
{credit.logo && (
5547
<LogoWrapper>
56-
<StyledImage src={credit.img} />
48+
<StyledImage src={credit.logo} />
5749
</LogoWrapper>
5850
)}
5951
{credit.description && (
@@ -62,9 +54,9 @@ export const DataAttributionUI: FC<DataAttributionProps> = ({
6254
</CreditItemLink>
6355
) : (
6456
<CreditItem>
65-
{credit.img && (
57+
{credit.logo && (
6658
<LogoWrapper>
67-
<StyledImage src={credit.img} />
59+
<StyledImage src={credit.logo} />
6860
</LogoWrapper>
6961
)}
7062
{credit.description && (
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { Credit as ProcessesCredit } from "@reearth/beta/utils/value";
2+
import { CreditItem, Credits } from "@reearth/core";
3+
import { useEffect, useMemo, useState } from "react";
4+
5+
import { Widget } from "../../types";
6+
7+
type WidgetCredit = {
8+
description?: string;
9+
logo?: string;
10+
creditUrl: string;
11+
};
12+
13+
export const useDataAttribution = ({
14+
credits,
15+
widget
16+
}: {
17+
credits?: Credits;
18+
widget: Widget;
19+
}) => {
20+
const [cesiumCredit, setCesiumCredit] = useState<ProcessesCredit | undefined>(
21+
undefined
22+
);
23+
const [otherCredits, setOtherCredits] = useState<
24+
ProcessesCredit[] | undefined
25+
>(undefined);
26+
27+
const widgetCredits = useMemo(
28+
() => widget?.property.default || [],
29+
[widget?.property.default]
30+
);
31+
32+
useEffect(() => {
33+
if (credits) {
34+
const cesium = parseCreditHtml(credits?.engine?.cesium);
35+
setCesiumCredit(cesium);
36+
37+
const lightboxCredits = credits.lightbox
38+
.map(parseCreditHtml)
39+
.filter(Boolean) as ProcessesCredit[];
40+
const screenCredits = credits.screen
41+
.map(parseCreditHtml)
42+
.filter(Boolean) as ProcessesCredit[];
43+
44+
const widgetProcessesCredits: ProcessesCredit[] = widgetCredits
45+
.filter(
46+
(widgetCredit: WidgetCredit) =>
47+
widgetCredit.description ||
48+
widgetCredit.logo ||
49+
widgetCredit.creditUrl
50+
)
51+
.map(
52+
(widgetCredit: WidgetCredit): ProcessesCredit => ({
53+
description: widgetCredit.description || "",
54+
logo: widgetCredit.logo,
55+
creditUrl: widgetCredit.creditUrl
56+
})
57+
);
58+
59+
setOtherCredits([
60+
...lightboxCredits,
61+
...screenCredits,
62+
...widgetProcessesCredits
63+
]);
64+
}
65+
}, [credits, widget.property.default, widgetCredits]);
66+
67+
return {
68+
cesiumCredit,
69+
otherCredits
70+
};
71+
};
72+
73+
function parseCreditHtml(
74+
credit: CreditItem | undefined
75+
): ProcessesCredit | undefined {
76+
if (!credit) return undefined;
77+
78+
if (credit?.html) {
79+
try {
80+
const parser = new DOMParser();
81+
const doc = parser.parseFromString(credit.html, "text/html");
82+
const logo = doc.querySelector("img")?.getAttribute("src") || "";
83+
const description =
84+
doc.querySelector("img")?.getAttribute("title") ||
85+
doc.body.textContent ||
86+
"";
87+
const creditUrl = doc.querySelector("a")?.getAttribute("href") || "";
88+
89+
return { logo, description, creditUrl };
90+
} catch (error) {
91+
console.error("Error processing credit HTML:", error);
92+
return undefined;
93+
}
94+
}
95+
96+
return undefined;
97+
}

web/src/beta/features/Visualizer/Crust/Widgets/Widget/builtin/DataAttribution/index.stories.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ Default.args = {
2222
horizontally: false,
2323
vertically: false
2424
},
25-
2625
property: {
2726
default: [
2827
{
@@ -35,9 +34,18 @@ Default.args = {
3534
}
3635
},
3736
context: {
38-
getCredits: () => [
39-
{ html: '<a href="#">Credit 1</a>' },
40-
{ html: '<a href="#">Credit 2</a>' }
41-
]
37+
getCredits: () => ({
38+
engine: {
39+
cesium: {
40+
html: `<a href="#">Credit 1</a>`
41+
}
42+
},
43+
lightbox: [
44+
{
45+
html: `<a href="#">Credit 2</a>`
46+
}
47+
],
48+
screen: []
49+
})
4250
}
4351
};

0 commit comments

Comments
 (0)