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

View File

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

View File

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