diff --git a/ui/src/CurrentUser.ts b/ui/src/CurrentUser.ts index 6de4edb..0d657f6 100644 --- a/ui/src/CurrentUser.ts +++ b/ui/src/CurrentUser.ts @@ -15,7 +15,7 @@ export class CurrentUser { @observable public loggedIn = false; @observable - public authenticating = false; + public authenticating = true; @observable public user: IUser = {name: 'unknown', admin: false, id: -1}; @observable @@ -80,17 +80,11 @@ export class CurrentUser { .then((resp: AxiosResponse) => { this.snack(`A client named '${name}' was created for your session.`); this.setToken(resp.data.token); - this.tryAuthenticate() - .then(() => { - this.authenticating = false; - this.loggedIn = true; - }) - .catch(() => { - this.authenticating = false; - console.log( - 'create client succeeded, but authenticated with given token failed' - ); - }); + this.tryAuthenticate().catch(() => { + console.log( + 'create client succeeded, but authenticated with given token failed' + ); + }); }) .catch(() => { this.authenticating = false; @@ -100,6 +94,7 @@ export class CurrentUser { public tryAuthenticate = async (): Promise> => { if (this.token() === '') { + this.authenticating = false; return Promise.reject(); } @@ -111,11 +106,13 @@ export class CurrentUser { .then((passThrough) => { this.user = passThrough.data; this.loggedIn = true; + this.authenticating = false; this.connectionErrorMessage = null; this.reconnectTime = 7500; return passThrough; }) .catch((error: AxiosError) => { + this.authenticating = false; if (!error || !error.response) { this.connectionError('No network connection or server unavailable.'); return Promise.reject(error); diff --git a/ui/src/common/BaseStore.ts b/ui/src/common/BaseStore.ts index 6b9a73d..4b2b4ee 100644 --- a/ui/src/common/BaseStore.ts +++ b/ui/src/common/BaseStore.ts @@ -30,6 +30,13 @@ export abstract class BaseStore implements IClearable { this.items = await this.requestItems().then((items) => items || []); }; + @action + public refreshIfMissing = async (id: number): Promise => { + if (this.getByIDOrUndefined(id) === undefined) { + await this.refresh(); + } + }; + public getByID = (id: number): T => { const item = this.getByIDOrUndefined(id); if (item === undefined) { diff --git a/ui/src/plugin/PluginDetailView.tsx b/ui/src/plugin/PluginDetailView.tsx index 0a27fad..7c83877 100644 --- a/ui/src/plugin/PluginDetailView.tsx +++ b/ui/src/plugin/PluginDetailView.tsx @@ -16,6 +16,7 @@ import * as config from '../config'; import Container from '../common/Container'; import {inject, Stores} from '../inject'; import {IPlugin} from '../types'; +import LoadingSpinner from '../common/LoadingSpinner'; type IProps = RouteComponentProps<{id: string}>; @@ -42,8 +43,9 @@ class PluginDetailView extends Component, IState> this.refreshFeatures(); } - private refreshFeatures() { - return Promise.all([this.refreshConfigurer(), this.refreshDisplayer()]); + private async refreshFeatures() { + await this.props.pluginStore.refreshIfMissing(this.pluginID); + return await Promise.all([this.refreshConfigurer(), this.refreshDisplayer()]); } private async refreshConfigurer() { @@ -67,14 +69,16 @@ class PluginDetailView extends Component, IState> } public render() { - const pluginInfo = this.pluginInfo(); - const {name, capabilities} = pluginInfo; + const pluginInfo = this.props.pluginStore.getByIDOrUndefined(this.pluginID); + if (pluginInfo === undefined) { + return ; + } return ( - + - {capabilities.indexOf('configurer') !== -1 ? ( + {pluginInfo.capabilities.indexOf('configurer') !== -1 ? ( , IState> /> ) : null}{' '} - {capabilities.indexOf('displayer') !== -1 ? ( + {pluginInfo.capabilities.indexOf('displayer') !== -1 ? ( { it('does login', async () => await auth.login(page)); - it('navigates to users', async () => { - await page.click('#navigate-users'); + it('navigates to users through window location', async () => { + await page.goto(gotify.url + '/#/users'); await waitForExists(page, selector.heading(), 'Users'); }); it('has changed url', async () => {