Skip to content

Commit

Permalink
♻️ [arrSearch] refactor to composition API
Browse files Browse the repository at this point in the history
  • Loading branch information
jxn-30 committed Aug 27, 2023
1 parent 770bf56 commit b9afbfa
Show file tree
Hide file tree
Showing 3 changed files with 193 additions and 196 deletions.
8 changes: 4 additions & 4 deletions src/modules/extendedCallWindow/assets/arrSearch.ts
Expand Up @@ -171,14 +171,14 @@ export default (
aaoGroupElement.prepend(wrapper);
import(
/* webpackChunkName: "modules/extendedCallWindow/components/arrSearchDropdown" */
'../components/arrSearch/arrSearchDropdown.vue'
).then(({ default: arrSearchDropdown }) =>
'../components/arrSearch/ARRSearchDropdown.vue'
).then(({ default: ARRSearchDropdown }) =>
new LSSM.$vue({
pinia: LSSM.$pinia,
i18n: LSSM.$i18n,
render: h =>
h(arrSearchDropdown, {
props: { closeDropdownOnSelect, $sm },
h(ARRSearchDropdown, {
props: { closeDropdownOnSelect },
}),
}).$mount(wrapper)
);
Expand Down
@@ -0,0 +1,189 @@
<template>
<v-select
:id="id"
class="arr-search"
:options="options"
:clearable="false"
multiple
:placeholder="$m('settings.arrSearch.title')"
:selectable="option => !option.category"
:close-on-select="closeDropdownOnSelect"
:clear-search-on-select="false"
:components="{ Deselect: emptyComponent }"
:filter-by="filterBy"
@option:selecting="selectARR"
v-model="clickedARRs"
>
<div slot="no-options">
{{ $t('noOptions') }}
</div>
<template #option="option">
<a v-if="!option.category" v-html="option.html"></a>
<b v-else>{{ option.label }}</b>
</template>
<template #selected-option="option">
<a v-html="option.html"></a>
</template>
</v-select>
</template>

<script setup lang="ts">
import { onBeforeMount, ref } from 'vue';
import { useRootStore } from '@stores/index';
import VSelect, { type VueSelectProps } from 'vue-select';
import { useI18nModule } from '../../../../i18n';
interface BaseOption {
label: string;
id: string;
origEl: HTMLElement;
}
interface ARROption extends BaseOption {
html: string;
}
interface CategoryOption extends BaseOption {
category: true;
labels: string[];
}
type Option = ARROption | CategoryOption;
type Options = Option[];
const { $m } = useI18nModule('extendedCallWindow');
const rootStore = useRootStore();
const id = rootStore.nodeAttribute('ecw-arr_search-dropdown', true);
const options = ref<Options>([]);
const clickedARRs = ref<Options>([]);
const emptyComponent: VueSelectProps['components']['Deselect'] = {
render: createElement => createElement(),
};
defineProps<{ closeDropdownOnSelect: boolean }>();
const selectARR = (option: Option) => option.origEl?.click();
const filterBy = (option: Option, label: string, search: string) => {
const searchString = search.toLowerCase();
if ('category' in option) {
return option.labels.some(label =>
label.toLowerCase().includes(searchString)
);
}
return (label || '').toLocaleLowerCase().includes(searchString);
};
const _getOptionFromARRElement = (arr: HTMLAnchorElement): ARROption => ({
label: (arr.title || arr.textContent?.trim()) ?? '',
id: `${PREFIX}_${arr.id}`,
html: arr.outerHTML.replace(
new RegExp(`(?<=id=")(?=${arr.id}")`),
`${PREFIX}_`
),
origEl: arr,
});
const _updateARR = (arr: HTMLAnchorElement) => {
if (arr.getAttribute('reset') === 'true') clickedARRs.value.splice(0);
const arrOption = options.value.find(({ origEl }) =>
arr.isEqualNode(origEl)
);
if (arrOption && 'html' in arrOption) {
arrOption.html = arr.outerHTML.replace(
new RegExp(`(?<=id=")(?=${arr.id}")`),
`${PREFIX}_`
);
}
};
rootStore.hook({
event: 'aaoClickHandler',
post: true,
callback: _updateARR,
});
rootStore.hook({
event: 'vehicleGroupClickHandler',
post: true,
callback: _updateARR,
});
rootStore.hook({
event: 'aao_available',
post: true,
callback(id: number) {
const arr = document.querySelector<HTMLAnchorElement>(
`#mission-aao-group #aao_${id}`
);
if (arr) _updateARR(arr);
},
});
rootStore.hook({
event: 'vehicle_group_available',
post: true,
callback(id: number) {
const arr = document.querySelector<HTMLAnchorElement>(
`#mission-aao-group #vehicle_group_${id}`
);
if (arr) _updateARR(arr);
},
});
rootStore.hook({
event: 'vehicleSelectionReset',
callback: () => this.$set(this, 'clickedARRs', []),
});
onBeforeMount(() => {
// add ARR entries without category
options.value.push(
...Array.from(
document.querySelectorAll<HTMLAnchorElement>(
'#mission_aao_no_category .aao_searchable, #aao_without_category .aao_searchable'
)
).map(_getOptionFromARRElement)
);
// add ARR entries in Categories
document
.querySelectorAll<HTMLAnchorElement>(
'#aao-tabs > li > a[href^="#aao_category_"]'
)
.forEach(category => {
const title = category.textContent?.trim() ?? '';
const tab = category.getAttribute('href') ?? '';
const categoryOption = {
label: title,
id: tab,
category: true,
origEl: category,
labels: [],
} satisfies CategoryOption;
options.value.push(
categoryOption,
...Array.from(
document.querySelectorAll<HTMLAnchorElement>(
`${tab} .aao_searchable`
)
).map(el => {
const option = _getOptionFromARRElement(el);
if (!categoryOption.labels.includes(option.label))
categoryOption.labels.push(option.label);
return option;
})
);
});
});
</script>

<style scoped module lang="sass">
:global(#mission-aao-group > *:not(.arr-search))
display: none
</style>

0 comments on commit b9afbfa

Please sign in to comment.