Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EditDialog: add iD style FieldsEditor #694

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ import { OsmUserLogged } from './OsmUserLogged';
import { ContributionInfoBox } from './ContributionInfoBox';
import { OsmUserLoggedOut } from './OsmUserLoggedOut';
import { PresetSelect } from './PresetSelect';
import { FieldsEditor } from './FieldsEditor';

export const EditContent = () => (
<>
<DialogContent dividers>
<form autoComplete="off" onSubmit={(e) => e.preventDefault()}>
<OsmUserLoggedOut />
<PresetSelect />
<MajorKeysEditor />
<FieldsEditor />
{/*<MajorKeysEditor />*/}
<OptionsEditor />
<ContributionInfoBox />
<CommentField />
Expand Down
179 changes: 179 additions & 0 deletions src/components/FeaturePanel/EditDialog/EditContent/FieldsEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import { useEditContext } from '../EditContext';
import { getFields } from '../../../../services/tagging/fields';
import { getFieldTranslation } from '../../../../services/tagging/translations';
import {
Button,
Checkbox,
FormControl,
InputLabel,
MenuItem,
Select,
Stack,
TextField,
Typography,
} from '@mui/material';
import React, { useState } from 'react';
import { FeatureTags } from '../../../../services/types';
import { Field } from '../../../../services/tagging/types/Fields';
import { t } from '../../../../services/intl';
import { allPresets } from '../../../../services/tagging/data';
import { Preset } from '../../../../services/tagging/types/Presets';
import styled from '@emotion/styled';
import { OpeningHoursEditor } from './OpeningHoursEditor/OpeningHoursEditor';

const StyledFormControl = styled(FormControl)`
margin-top: 16px;
margin-bottom: 8px;
`;

const getInitialActiveFields = (
fields: Field[],
tags: FeatureTags,
): Field[] => {
const activeFields = [];
fields.forEach((field: Field) => {
if (tags[field.key]) {
activeFields.push(field);
}
});

return activeFields;
};

const FieldsEditorInner = ({ preset }: { preset: Preset }) => {
const { tags, setTag } = useEditContext().tags;

const { fields, moreFields, universalFields } = getFields(preset); // TODO
const [activeFields, setActiveFields] = useState(() =>
getInitialActiveFields(fields, tags),
);
const inactiveFields = fields.filter(
({ fieldKey }) => !activeFields.some((f) => f.fieldKey === fieldKey),
);

return (
<>
{activeFields.map((field) => {
const fieldKey = field.fieldKey;
const fieldTranslation = getFieldTranslation(field);
const label = `${fieldTranslation?.label ?? `[${fieldKey}]`} – fieldkey:${fieldKey} – type:${field.type}`;
const k = field.key ?? field.keys?.[0];

console.log({ k, label, field, fieldTranslation });

if (fieldKey === 'opening_hours') {
return <OpeningHoursEditor key={fieldKey} />;
}

if (field.type === 'combo') {
return (
<StyledFormControl key={fieldKey} fullWidth>
<InputLabel shrink>{label}</InputLabel>
<Select
label={label}
value={tags[k]}
onChange={(e) => setTag(k, e.target.value)}
displayEmpty
variant="outlined"
>
{Object.entries(fieldTranslation.options ?? {}).map(
([key, value]) => (
<MenuItem key={key} value={key}>
{value}
</MenuItem>
),
)}
</Select>
</StyledFormControl>
);
}

if (field.type === 'semiCombo') {
const values = tags[k]?.split(';') ?? [];
return (
<StyledFormControl key={fieldKey} fullWidth>
<InputLabel shrink>{label}</InputLabel>
<Select
label={label}
multiple
value={values}
onChange={(e) =>
setTag(k, (e.target.value as string[]).join(';'))
}
renderValue={(selected) => selected.join(', ')}
displayEmpty
fullWidth
variant="outlined"
>
{field.options?.map((option) => (
<MenuItem key={option} value={option}>
<Checkbox checked={values.includes(option)} />
{option}
</MenuItem>
))}
</Select>
</StyledFormControl>
);
}

return (
<div key={fieldKey}>
<TextField
label={label}
value={tags[k]}
InputLabelProps={{ shrink: true }}
variant="outlined"
margin="normal"
name={k}
onChange={(e) => setTag(e.target.name, e.target.value)}
fullWidth
// autoFocus={focusTag === k}
/>
</div>
);
})}

{!!inactiveFields.length && (
<>
<Typography variant="body1" component="span" color="textSecondary">
{t('editdialog.add_major_tag')}:
</Typography>
{inactiveFields.map((field) => {
const fieldTranslation = getFieldTranslation(field);
const label = fieldTranslation?.label ?? `[${field.fieldKey}]`;

return (
<React.Fragment key={field.fieldKey}>
{' '}
<Button
size="small"
onClick={() => setActiveFields((arr) => [...arr, field])}
>
{label}
</Button>
</React.Fragment>
);
})}
</>
)}
<br />
<br />
</>
);
};

export const FieldsEditor = () => {
const { presetKey } = useEditContext();

// TODO remove condition
if (!presetKey) {
return null;
}

const preset = allPresets[presetKey];
if (!preset) {
return null;
}

return <FieldsEditorInner preset={preset} />;
};
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ const LabelWrapper = styled.div`
const useMatchTags = (
feature: Feature,
tags: FeatureTags,
setPreset: Setter<string>,
setPresetKey: Setter<string>,
) => {
useEffect(() => {
(async () => {
Expand All @@ -76,9 +76,9 @@ const useMatchTags = (
const translatedPreset = (await getTranslatedPresets()).find(
(option) => option.presetKey === foundPreset.presetKey,
);
setPreset(translatedPreset?.presetKey ?? '');
setPresetKey(translatedPreset?.presetKey ?? '');
})();
}, [tags, feature, setPreset]);
}, [tags, feature, setPresetKey]);
};

const useOptions = () => {
Expand All @@ -90,11 +90,14 @@ const useOptions = () => {
};

export const PresetSelect = () => {
const { tags } = useEditContext().tags;
const [preset, setPreset] = useState('');
const {
tags: { tags },
presetKey,
setPresetKey,
} = useEditContext();
const { feature } = useFeatureContext();
const options = useOptions();
useMatchTags(feature, tags, setPreset);
useMatchTags(feature, tags, setPresetKey);

if (options.length === 0) {
return null;
Expand All @@ -108,7 +111,11 @@ export const PresetSelect = () => {
</Typography>
</LabelWrapper>

<PresetSearchBox value={preset} setValue={setPreset} options={options} />
<PresetSearchBox
value={presetKey}
setValue={setPresetKey}
options={options}
/>
</Row>
);
};
5 changes: 5 additions & 0 deletions src/components/FeaturePanel/EditDialog/EditContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ type EditContextType = {
setLocation: (s: string) => void;
comment: string;
setComment: (s: string) => void;
presetKey: string;
setPresetKey: Setter<string>;
tags: {
tagsEntries: TagsEntries;
setTagsEntries: Setter<TagsEntries>;
Expand Down Expand Up @@ -65,6 +67,7 @@ export const EditContextProvider = ({ feature, children }: Props) => {
const [location, setLocation] = useState('');
const [comment, setComment] = useState('');
const tags = useTagsState(feature.tags);
const [presetKey, setPresetKey] = useState(''); // only cache, real data in tags

const value: EditContextType = {
successInfo,
Expand All @@ -75,6 +78,8 @@ export const EditContextProvider = ({ feature, children }: Props) => {
setLocation,
comment,
setComment,
presetKey,
setPresetKey,
tags,
};

Expand Down
Loading