Migrate LoginControl to vue

This commit is contained in:
James Lyne 2022-06-23 21:27:50 +01:00
parent c6502e5023
commit 627e3219d1
3 changed files with 47 additions and 130 deletions

View File

@ -26,7 +26,7 @@
<div id="ui__bottom-left" class="ui__section"> <div id="ui__bottom-left" class="ui__section">
<div class="ui__toolbar toolbar--vertical"> <div class="ui__toolbar toolbar--vertical">
<LoginControl v-if="loginEnabled" :leaflet="leaflet"></LoginControl> <LoginControl v-if="loginEnabled"></LoginControl>
<ChatControl v-if="chatBoxEnabled"></ChatControl> <ChatControl v-if="chatBoxEnabled"></ChatControl>
</div> </div>
<div class="ui__toolbar"> <div class="ui__toolbar">

View File

@ -14,30 +14,56 @@
- limitations under the License. - limitations under the License.
--> -->
<template>
<button class="ui__element ui__button" type="button" :title="buttonTitle" :aria-expanded="modalVisible"
@click.prevent.stop="handleClick"
@keydown.right.prevent.stop="handleClick">
<SvgIcon :name="loggedIn ? 'logout' : 'login'"></SvgIcon>
</button>
</template>
<script lang="ts"> <script lang="ts">
import {defineComponent, onMounted, onUnmounted} from "@vue/runtime-core"; import {computed, defineComponent} from "@vue/runtime-core";
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap"; import SvgIcon from "@/components/SvgIcon.vue";
import {LoginControl} from "@/leaflet/control/LoginControl"; import {useStore} from "@/store";
import {ActionTypes} from "@/store/action-types";
import {notify} from "@kyvg/vue3-notification";
import "@/assets/icons/login.svg";
import "@/assets/icons/logout.svg";
export default defineComponent({ export default defineComponent({
props: { components: {SvgIcon},
leaflet: {
type: Object as () => LiveAtlasLeafletMap, setup() {
required: true, const store = useStore(),
loggedIn = computed(() => store.state.loggedIn),
buttonTitle = computed(() => loggedIn.value ? store.state.messages.logoutTitle : store.state.messages.loginTitle),
modalVisible = computed(() => store.state.ui.visibleModal === 'login');
const handleClick = async () => {
const logoutSuccess = computed(() => store.state.messages.logoutSuccess),
logoutError = computed(() => store.state.messages.logoutErrorUnknown);
if (loggedIn.value) {
try {
await store.dispatch(ActionTypes.LOGOUT, undefined);
notify(logoutSuccess.value);
} catch(e) {
notify(logoutError.value);
}
} else {
await store.dispatch(ActionTypes.LOGIN, null)
}
};
return {
modalVisible,
loggedIn,
buttonTitle,
handleClick
} }
}, },
setup(props) {
const control = new LoginControl({
position: 'topleft',
});
onMounted(() => props.leaflet.addControl(control));
onUnmounted(() => props.leaflet.removeControl(control));
},
render() {
return null;
}
}) })
</script> </script>

View File

@ -1,109 +0,0 @@
/*
* Copyright 2022 James Lyne
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {Control, ControlOptions, DomEvent, DomUtil} from 'leaflet';
import {useStore} from "@/store";
import {watch} from "@vue/runtime-core";
import "@/assets/icons/login.svg";
import "@/assets/icons/logout.svg";
import {computed} from "vue";
import {ActionTypes} from "@/store/action-types";
import {notify} from "@kyvg/vue3-notification";
import LiveAtlasLeafletMap from "@/leaflet/LiveAtlasLeafletMap";
/**
* Leaflet map control providing a login/logout button which opens the login modal/logs out on click
*/
export class LoginControl extends Control {
declare _map: LiveAtlasLeafletMap;
declare options: ControlOptions;
private readonly store = useStore();
private readonly loggedIn = computed(() => this.store.state.loggedIn);
private readonly _button: HTMLButtonElement;
constructor(options: ControlOptions) {
super(options);
this._button = DomUtil.create('button',
'leaflet-control-bottom leaflet-control-button leaflet-control-login') as HTMLButtonElement;
this._button.type = 'button';
this._button.addEventListener('click', async e => {
e.stopPropagation();
e.preventDefault();
await this.handleClick();
});
//Open login on ArrowRight from button
DomEvent.on(this._button,'keydown', async (e: Event) => {
if ((e as KeyboardEvent).key === 'ArrowRight') {
e.stopPropagation();
e.preventDefault();
await this.handleClick();
}
});
watch(this.loggedIn, () => {
this.update();
});
const visibleModal = computed(() => this.store.state.ui.visibleModal);
watch(visibleModal, (newValue, oldValue) => {
this._button.setAttribute('aria-expanded', (newValue === 'login').toString());
if(this._map && !newValue && oldValue === 'login') {
this._button.focus();
}
});
this.update();
}
onAdd() {
return this._button;
}
private update() {
this._button.title = this.loggedIn.value
? this.store.state.messages.logoutTitle : this.store.state.messages.loginTitle;
this._button.innerHTML = `
<svg class="svg-icon">
<use xlink:href="#icon--${this.loggedIn.value ? 'logout' : 'login'}" />
</svg>`;
}
private async handleClick() {
const logoutSuccess = computed(() => this.store.state.messages.logoutSuccess),
logoutError = computed(() => this.store.state.messages.logoutErrorUnknown);
if (this.loggedIn.value) {
try {
await this.store.dispatch(ActionTypes.LOGOUT, undefined);
notify(logoutSuccess.value);
} catch(e) {
notify(logoutError.value);
}
} else {
await this.store.dispatch(ActionTypes.LOGIN, null)
}
}
}