Skip to content

Commit

Permalink
Rewrite Layout Page using Vue3 syntax
Browse files Browse the repository at this point in the history
Bug: T353886
  • Loading branch information
guergana committed Dec 27, 2023
1 parent 3358e75 commit eb0647c
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 101 deletions.
3 changes: 2 additions & 1 deletion resources/js/Pages/Home.vue
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,8 @@
const textareaInputValue: Ref<string> = ref(store.lastSearchedIds);
const faqDialog = ref(false);
const serversideValidationError = computed<boolean>(() => {
const serversideValidationError = computed<boolean>(() => {
const errors = page.props.value.errors as ErrorMessages;
return errors && Object.keys(errors).length > 0;
});
Expand Down
184 changes: 84 additions & 100 deletions resources/js/Pages/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -64,122 +64,106 @@
</div>
</template>

<script lang="ts">
import { PropType } from 'vue';
<script setup lang="ts">
import { Link as InertiaLink } from '@inertiajs/inertia-vue3';
import { CdxButton as LanguageSelectorButton, CdxIcon } from "@wikimedia/codex";
import { cdxIconLanguage } from '@wikimedia/codex-icons';
import AuthWidget from '../Components/AuthWidget.vue';
import LanguageSelector from '../Components/LanguageSelector.vue';
import WikidataToolFooter from '../Components/WikidataToolFooter.vue';
import { DirectiveBinding, ComponentPublicInstance } from 'vue';
import { defineComponent } from 'vue';
import { ref, computed, nextTick, onMounted, onBeforeUnmount } from 'vue';
import type { Ref } from 'vue';
import User from '../types/User';
import languagedata from '@wikimedia/language-data';
let handleOutsideClick: (event: MouseEvent | TouchEvent) => void;
export default defineComponent({
components: {
AuthWidget,
LanguageSelectorButton,
CdxIcon,
InertiaLink,
LanguageSelector,
WikidataToolFooter
},
setup() {
return {
cdxIconLanguage
};
},
data() {
return {
showLanguageSelector: false,
resizeObserver: null as unknown as ResizeObserver,
};
},
directives: {
detectClickOutside: {
mounted(element: HTMLElement, binding: DirectiveBinding): void {
handleOutsideClick = (event: MouseEvent | TouchEvent): void => {
const callback = binding.value;
if (!element.contains(event.target as Node)) {
callback();
}
};
const showLanguageSelector = ref(false);
const resizeObserver: Ref<ResizeObserver> = ref(null);
const languageSelector: Ref<ComponentPublicInstance> = ref(null);
const header: Ref<HTMLElement> = ref(null);
const userSection: Ref<HTMLElement> = ref(null);
const contentWrap: Ref<Element> = ref(null);
document.addEventListener('click', handleOutsideClick);
document.addEventListener('touchstart', handleOutsideClick);
},
unmounted(): void {
document.removeEventListener('click', handleOutsideClick);
document.removeEventListener('touchstart', handleOutsideClick);
},
},
},
mounted() {
this.resizeObserver = new ResizeObserver(this.onWindowResize);
this.resizeObserver.observe(this.$refs.contentWrap as Element);
},
computed: {
currentLanguageAutonym(): string {
return languagedata.getAutonym(document.documentElement.lang);
},
},
props: {
user: Object as PropType<User>,
},
methods: {
onChangeLanguage(newLanguage: string): void {
/**
* Manipulate the url to maintain it as the single source of truth
* and avoid having either to load all language files upfront or
* request language file reactively.
*/
const url = new URL(document.URL);
url.searchParams.set('uselang', newLanguage);
document.location.assign(url.toString());
},
onCloseLanguageSelector(): void {
this.showLanguageSelector = false;
},
onToggleLanguageSelector(): void {
this.showLanguageSelector = !this.showLanguageSelector;
if (this.showLanguageSelector === true) {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const languageSelectorRefs = this.$refs.languageSelector as any;
this.$nextTick(() => {
languageSelectorRefs.focus();
this.changeLanguageSelectorMenuDirection();
});
}
},
onClickOutsideLanguageSelector(): void {
this.showLanguageSelector = false;
},
changeLanguageSelectorMenuDirection(): void {
const headerTop = (this.$refs.header as HTMLElement).getBoundingClientRect().top;
const userSectionTop = (this.$refs.userSection as HTMLElement).getBoundingClientRect().top;
if( userSectionTop > headerTop ){
((this.$refs.languageSelector as ComponentPublicInstance)
.$el as HTMLElement).style.insetInlineEnd = 'unset';
((this.$refs.languageSelector as ComponentPublicInstance)
.$el as HTMLElement).style.insetInlineStart = '0';
} else {
((this.$refs.languageSelector as ComponentPublicInstance)
.$el as HTMLElement).style.insetInlineEnd = '0';
((this.$refs.languageSelector as ComponentPublicInstance)
.$el as HTMLElement).style.insetInlineStart = 'unset';
defineProps<{user: User}>();
const currentLanguageAutonym = computed<string>(() => {
return languagedata.getAutonym(document.documentElement.lang);
});
const vDetectClickOutside = {
mounted: (element: HTMLElement, binding: DirectiveBinding): void => {
handleOutsideClick = (event: MouseEvent | TouchEvent): void => {
const callback = binding.value;
if (!element.contains(event.target as Node)) {
callback();
}
},
onWindowResize(): void {
this.changeLanguageSelectorMenuDirection();
},
};
document.addEventListener('click', handleOutsideClick);
document.addEventListener('touchstart', handleOutsideClick);
},
beforeUnmount () {
this.resizeObserver.unobserve(this.$refs.contentWrap as Element)
unmounted(): void {
document.removeEventListener('click', handleOutsideClick);
document.removeEventListener('touchstart', handleOutsideClick);
}
};
function onChangeLanguage(newLanguage: string): void {
/**
* Manipulate the url to maintain it as the single source of truth
* and avoid having either to load all language files upfront or
* request language file reactively.
*/
const url = new URL(document.URL);
url.searchParams.set('uselang', newLanguage);
document.location.assign(url.toString());
}
function onCloseLanguageSelector(): void {
showLanguageSelector.value = false;
}
async function onToggleLanguageSelector(): Promise<void> {
showLanguageSelector.value = !showLanguageSelector.value;
if (showLanguageSelector.value === true) {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
const languageSelectorRefs = languageSelector.value as any;
await nextTick(() => {
languageSelectorRefs.focus();
changeLanguageSelectorMenuDirection();
});
}
}
function onClickOutsideLanguageSelector(): void {
showLanguageSelector.value = false;
}
function changeLanguageSelectorMenuDirection(): void {
const headerTop = header.value.getBoundingClientRect().top;
const userSectionTop = (userSection).value.getBoundingClientRect().top;
if( userSectionTop > headerTop ){
(languageSelector.value.$el as HTMLElement).style.insetInlineEnd = 'unset';
languageSelector.value.$el.style.insetInlineStart = '0';
} else {
languageSelector.value.$el.style.insetInlineEnd = '0';
languageSelector.value.$el.style.insetInlineStart = 'unset';
}
}
function onWindowResize(): void {
changeLanguageSelectorMenuDirection();
}
onMounted(() => {
resizeObserver.value = new ResizeObserver(onWindowResize);
resizeObserver.value.observe(contentWrap.value);
});
onBeforeUnmount(() => {
resizeObserver.value.unobserve(contentWrap.value)
});
</script>

Expand Down

0 comments on commit eb0647c

Please sign in to comment.