Add an unsaved indicator to editors.

This commit is contained in:
Bauke 2022-10-27 21:33:46 +02:00
parent 9ee0d2db90
commit 459380cb69
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558
3 changed files with 37 additions and 8 deletions

View File

@ -20,13 +20,16 @@ type Props = {
saveRedirect: (redirect: Redirect) => void;
};
type State = RedirectParameters;
type State = {
hasBeenEdited: boolean;
} & RedirectParameters;
export default class Editor extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
hasBeenEdited: false,
...props.redirect.parameters,
};
}
@ -34,27 +37,37 @@ export default class Editor extends Component<Props, State> {
onInput = (event: Event, input: 'matcher' | 'redirect') => {
const target = event.target as HTMLInputElement;
const value = target.value;
const newState: Partial<State> = {
hasBeenEdited: true,
};
if (input === 'matcher') {
this.setState({matcherValue: value});
newState.matcherValue = value;
} else if (input === 'redirect') {
this.setState({redirectValue: value});
newState.redirectValue = value;
} else {
throw new Error(`Unexpected input changed: ${input as string}`);
}
this.setState(newState);
};
onSelectChange = (event: Event, select: 'matcher' | 'redirect') => {
const target = event.target as HTMLSelectElement;
const value = target.value;
const newState: Partial<State> = {
hasBeenEdited: true,
};
if (select === 'matcher' && narrowMatcherType(value)) {
this.setState({matcherType: value});
newState.matcherType = value;
} else if (select === 'redirect' && narrowRedirectType(value)) {
this.setState({redirectType: value});
newState.redirectType = value;
} else {
throw new Error(`${value} is not a valid MatcherType or RedirectType`);
}
this.setState(newState);
};
onMatcherInput = (event: Event) => {
@ -99,6 +112,7 @@ export default class Editor extends Component<Props, State> {
const redirect = this.parseRedirect();
await storage.save(redirect);
this.props.saveRedirect(redirect);
this.setState({hasBeenEdited: false});
};
toggleEnabled = async () => {
@ -111,8 +125,14 @@ export default class Editor extends Component<Props, State> {
};
render() {
const {enabled, matcherType, matcherValue, redirectType, redirectValue} =
this.state;
const {
enabled,
hasBeenEdited,
matcherType,
matcherValue,
redirectType,
redirectValue,
} = this.state;
const matcherTypeOptions = matcherTypes.map(
(value) => html`<option value=${value}>${value}</option>`,
@ -122,7 +142,7 @@ export default class Editor extends Component<Props, State> {
);
return html`
<div class="editor">
<div class="editor ${hasBeenEdited ? 'has-been-edited' : ''}">
<select
class="select"
id="matcher-type"

View File

@ -30,6 +30,10 @@ export default class Usage extends Component {
<p>Editing redirects:</p>
<ul>
<li>
If a redirect has been edited, a yellow border will be shown around
it.
</li>
<li>
Changes to redirects are only saved when you click the save button.
</li>

View File

@ -1,9 +1,14 @@
.editor {
align-items: center;
background-color: var(--db-2);
border: 1px solid transparent;
display: flex;
padding: 8px;
&.has-been-edited {
border: 1px solid var(--da-3);
}
.arrow-span {
aspect-ratio: 1;
align-items: center;