|
- import { Component, h, Fragment, createRef } from 'preact';
- import cls from 'classnames';
- import { AnnotationSource } from '../storage/AnnotationSource';
- import classes from './AnnotationStoreSelector.module.scss';
-
- interface AnnotationStoreSelectorProps {}
-
- interface AnnotationStoreSelectorState {
- possiblyWritableSources?: AnnotationSource[];
- selectedSource?: AnnotationSource | null;
- testSuccess?: boolean;
- }
-
- export class AnnotationStoreSelector extends Component<
- AnnotationStoreSelectorProps,
- AnnotationStoreSelectorState
- > {
- state: AnnotationStoreSelectorState = {};
-
- selectElement = createRef<HTMLSelectElement>();
- testButton = createRef<HTMLButtonElement>();
-
- override async componentDidMount() {
- await this.loadData();
- }
-
- async loadData() {
- const possiblyWritableSources =
- await AnnotationSource.getPossiblyWritableSources();
- const selectedSource = possiblyWritableSources.find(
- (source) => source.data.useForNewAnnotations,
- );
- this.setState({
- possiblyWritableSources: possiblyWritableSources,
- selectedSource,
- });
- }
-
- async onChange() {
- const optionValue = this.selectElement.current?.value;
- const selectedSourceId = optionValue ? +optionValue : null;
- const selectedSource = selectedSourceId
- ? await AnnotationSource.get(selectedSourceId)
- : null;
- this.setState({ selectedSource, testSuccess: false });
- }
-
- async testCreateAnnotation() {
- this.testButton.current?.classList.add(classes.loading);
- const { selectedSource } = this.state;
- try {
- if (!selectedSource) throw new Error('No source selected to test.');
- await selectedSource.testWritable();
- this.setState({ testSuccess: true });
-
- // Flag the selected source, unflag the others.
- const allSources = await AnnotationSource.getAll();
- await Promise.all(
- allSources.map((source) =>
- source.useForNewAnnotations(
- source.data._id === selectedSource.data._id,
- ),
- ),
- );
- await this.loadData();
- } catch (error) {
- this.setState({ testSuccess: false });
- alert(error);
- } finally {
- this.testButton.current?.classList.remove(classes.loading);
- }
- }
-
- render(
- {}: AnnotationStoreSelectorProps,
- {
- possiblyWritableSources,
- selectedSource,
- testSuccess,
- }: AnnotationStoreSelectorState,
- ) {
- // List sources, sorting previously connected ones first.
- const optionsList = possiblyWritableSources
- ?.sort((a, b) =>
- a.data.writable === b.data.writable ? 0 : b.data.writable ? 1 : -1,
- )
- .map((source) => (
- <option
- value={source.data._id}
- selected={source.data._id === selectedSource?.data._id}
- >
- {source.data.writable ? '✓' : '?'} {source.data.title} <
- {source.data.url}>
- </option>
- ));
-
- if (optionsList?.length === 0) {
- return (
- <p>
- To create annotations, first subscribe to a collection (that you have
- write access to).
- </p>
- );
- }
-
- return (
- <>
- <p>Choose the collection to store/publish annotations you create:</p>
- <select
- ref={this.selectElement}
- value={`${selectedSource?.data._id ?? ''}`}
- onChange={(e) => this.onChange()}
- class={classes.select}
- >
- <option value="">None</option>
- {optionsList}
- </select>
- {selectedSource && (
- <>
- <button
- onClick={() => this.testCreateAnnotation()}
- title="Click to test if you can create an annotation in the chosen collection. Your browser may prompt you to provide login credentials."
- ref={this.testButton}
- class={cls(classes.button, { [classes.success]: testSuccess })}
- >
- {testSuccess
- ? 'Connected'
- : selectedSource.data.writable
- ? selectedSource.data.needsAuth
- ? 'Reconnect'
- : 'Check'
- : 'Connect'}
- </button>
- {selectedSource.data.writable && selectedSource.data.needsAuth && (
- <p>
- Your browser appears to have lost write access to the
- collection. Please click reconnect to try log in again.
- </p>
- )}
- </>
- )}
- </>
- );
- }
- }
|