diff --git a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/FeatureEditSection.tsx b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/FeatureEditSection.tsx
index 00bf0eb9..4632d1de 100644
--- a/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/FeatureEditSection.tsx
+++ b/src/components/FeaturePanel/EditDialog/EditContent/FeatureEditSection/FeatureEditSection.tsx
@@ -2,16 +2,46 @@ import { PresetSelect } from './PresetSelect';
import { MajorKeysEditor } from './MajorKeysEditor';
import { TagsEditor } from './TagsEditor/TagsEditor';
import React from 'react';
-import { SingleFeatureEditContextProvider } from './SingleFeatureEditContext';
+import {
+ SingleFeatureEditContextProvider,
+ useFeatureEditData,
+} from './SingleFeatureEditContext';
import { MembersEditor } from '../MembersEditor';
import { ParentsEditor } from '../ParentsEditor';
+import { Stack, Typography } from '@mui/material';
+import { useEditContext } from '../../EditContext';
type Props = {
shortId: string;
};
+const EditFeatureHeading = (props: { shortId: string }) => {
+ const { items } = useEditContext();
+ const { tags } = useFeatureEditData();
+
+ if (items.length <= 1) {
+ return null;
+ }
+
+ return (
+
+ {tags.name || ' '}
+
+ {props.shortId}
+
+
+ );
+};
+
export const FeatureEditSection = ({ shortId }: Props) => (
+
diff --git a/src/components/FeaturePanel/EditDialog/EditContent/MembersEditor.tsx b/src/components/FeaturePanel/EditDialog/EditContent/MembersEditor.tsx
index ae44b251..210848fc 100644
--- a/src/components/FeaturePanel/EditDialog/EditContent/MembersEditor.tsx
+++ b/src/components/FeaturePanel/EditDialog/EditContent/MembersEditor.tsx
@@ -11,31 +11,16 @@ import {
} from '@mui/material';
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
import { FeatureRow } from './FeatureRow';
-import { OsmId } from '../../../../services/types';
-import { getApiId, getShortId } from '../../../../services/helpers';
-import { fetchSchemaTranslations } from '../../../../services/tagging/translations';
-import { fetchFeature } from '../../../../services/osmApi';
-import { useEditContext } from '../EditContext';
import { t } from '../../../../services/intl';
+import { useGetHandleClick } from './helpers';
export const MembersEditor = () => {
const { members } = useFeatureEditData();
const theme = useTheme();
- const { addFeature, items, setCurrent } = useEditContext();
+ const handleClick = useGetHandleClick();
if (!members || members.length === 0) return null;
- const handleClick = async (shortId) => {
- const apiId: OsmId = getApiId(shortId);
- await fetchSchemaTranslations();
- const isNotInItems = !items.find((item) => item.shortId === shortId);
- const feature = await fetchFeature(apiId);
- if (isNotInItems) {
- addFeature(feature);
- }
- setCurrent(getShortId(feature.osmMeta));
- };
-
return (
{
const { shortId } = useFeatureEditData();
const [parents, setParents] = useState([]);
const theme = useTheme();
- const { addFeature, setCurrent, items } = useEditContext();
+ const handleClick = useGetHandleClick();
useEffect(() => {
(async () => {
@@ -65,16 +64,7 @@ export const ParentsEditor = () => {
key={shortId}
shortId={shortId}
label={parent.tags.name}
- onClick={() => {
- const isNotInItems = !items.find(
- (item) => item.shortId === shortId,
- );
- fetchSchemaTranslations();
- if (isNotInItems) {
- addFeature(parent);
- }
- setCurrent(shortId);
- }}
+ onClick={() => handleClick(shortId)}
/>
);
})}
diff --git a/src/components/FeaturePanel/EditDialog/EditContent/helpers.tsx b/src/components/FeaturePanel/EditDialog/EditContent/helpers.tsx
index 507b0dbd..2d94150b 100644
--- a/src/components/FeaturePanel/EditDialog/EditContent/helpers.tsx
+++ b/src/components/FeaturePanel/EditDialog/EditContent/helpers.tsx
@@ -1,6 +1,10 @@
import styled from '@emotion/styled';
import { Box, Stack } from '@mui/material';
import React from 'react';
+import { EditDataItem } from '../useEditItems';
+import { useEditContext } from '../EditContext';
+import { getApiId, getShortId } from '../../../../services/helpers';
+import { getFullFeatureWithMemberFeatures } from '../../../../services/osmApi';
const CharacterCountContainer = styled.div`
position: absolute;
@@ -49,3 +53,27 @@ export const getInputTypeForKey = (key: string) => {
}
return 'text';
};
+
+const isInItems = (items: Array, shortId: string) =>
+ items.find((item) => item.shortId === shortId);
+
+export const useGetHandleClick = () => {
+ const { addFeature, items, setCurrent } = useEditContext();
+
+ return async (shortId: string) => {
+ const apiId = getApiId(shortId);
+ if (apiId.id < 0) {
+ setCurrent(shortId);
+ return;
+ }
+
+ if (isInItems(items, shortId)) {
+ setCurrent(shortId);
+ return;
+ }
+
+ const feature = await getFullFeatureWithMemberFeatures(apiId);
+ addFeature(feature);
+ setCurrent(getShortId(feature.osmMeta));
+ };
+};
diff --git a/src/services/osmApi.ts b/src/services/osmApi.ts
index 9d285537..accd8a61 100644
--- a/src/services/osmApi.ts
+++ b/src/services/osmApi.ts
@@ -1,7 +1,14 @@
import { resolveCountryCode } from 'next-codegrid';
import { FetchError, getShortId, getUrlOsmId, prod } from './helpers';
import { fetchJson } from './fetch';
-import { Feature, LonLat, OsmId, Position, SuccessInfo } from './types';
+import {
+ Feature,
+ LonLat,
+ OsmId,
+ Position,
+ RelationMember,
+ SuccessInfo,
+} from './types';
import { removeFetchCache } from './fetchCache';
import { overpassAroundToSkeletons } from './overpassAroundToSkeletons';
import { isBrowser } from '../components/helpers';
@@ -20,30 +27,31 @@ import {
} from '../utils';
import { getOverpassUrl } from './overpassSearch';
-type GetOsmUrl = (object: OsmId) => string;
-
-const getOsmUrl: GetOsmUrl = ({ type, id }) =>
+const getOsmUrl = ({ type, id }: OsmId) =>
`https://api.openstreetmap.org/api/0.6/${type}/${id}.json`;
-const getOsmFullUrl: GetOsmUrl = ({ type, id }) =>
+const getOsmFullUrl = ({ type, id }: OsmId) =>
`https://api.openstreetmap.org/api/0.6/${type}/${id}/full.json`;
-const getOsmParentUrl: GetOsmUrl = ({ type, id }) =>
+const getOsmParentUrl = ({ type, id }: OsmId) =>
`https://api.openstreetmap.org/api/0.6/${type}/${id}/relations.json`;
-const getOsmHistoryUrl: GetOsmUrl = ({ type, id }) =>
+const getOsmHistoryUrl = ({ type, id }: OsmId) =>
`https://api.openstreetmap.org/api/0.6/${type}/${id}/history.json`;
+type OsmTypes = 'node' | 'way' | 'relation';
+type OsmElement = {
+ type: T;
+ id: number;
+ lat: number;
+ lon: number;
+ timestamp: string;
+ version: number;
+ changeset: number;
+ user: string;
+ uid: number;
+ tags: Record;
+ members?: RelationMember[];
+};
type OsmResponse = {
- elements?: {
- type: 'node' | 'way' | 'relation';
- id: number;
- lat: number;
- lon: number;
- timestamp: string;
- version: number;
- changeset: number;
- user: string;
- uid: number;
- tags: Record;
- }[];
+ elements: OsmElement[];
};
const getOsmElement = async (apiId: OsmId) => {
@@ -196,8 +204,12 @@ export const fetchParentFeatures = async (apiId: OsmId) => {
return elements.map((element) => addSchemaToFeature(osmToFeature(element)));
};
-const getItemsMap = (elements) => {
- const map = { node: {}, way: {}, relation: {} };
+const getItemsMap = (elements: OsmElement[]) => {
+ const map = {
+ node: {} as Record>,
+ way: {} as Record>,
+ relation: {} as Record>,
+ };
elements.forEach((element) => {
map[element.type][element.id] = element;
});
@@ -270,6 +282,17 @@ const addMemberFeaturesToArea = async (relation: Feature) => {
return { ...relation, memberFeatures };
};
+export const getFullFeatureWithMemberFeatures = async (apiId: OsmId) => {
+ await fetchSchemaTranslations();
+ const full = await fetchJson(getOsmFullUrl(apiId));
+ const map = getItemsMap(full.elements);
+ const feature = addSchemaToFeature(osmToFeature(map[apiId.type][apiId.id]));
+ return {
+ ...feature,
+ memberFeatures: getMemberFeatures(feature.members, map),
+ };
+};
+
const addMemberFeaturesToRelation = async (relation: Feature) => {
const { tags, osmMeta: apiId } = relation;
if (apiId.type !== 'relation') {
@@ -280,12 +303,10 @@ const addMemberFeaturesToRelation = async (relation: Feature) => {
return await addMemberFeaturesToArea(relation);
}
- const full = await fetchJson(getOsmFullUrl(apiId));
- const map = getItemsMap(full.elements);
-
+ const full = await getFullFeatureWithMemberFeatures(apiId);
const out: Feature = {
...relation,
- memberFeatures: getMemberFeatures(relation.members, map),
+ memberFeatures: full.memberFeatures,
};
mergeMemberImageDefs(out);
return out;
diff --git a/src/services/types.ts b/src/services/types.ts
index 6695fcb3..a5d1f852 100644
--- a/src/services/types.ts
+++ b/src/services/types.ts
@@ -72,7 +72,7 @@ export type FeatureTags = {
[key: string]: string;
};
-type RelationMember = {
+export type RelationMember = {
type: OsmType;
ref: number;
role: string;