Skip to content

Commit

Permalink
added search and sort
Browse files Browse the repository at this point in the history
  • Loading branch information
Severino committed Dec 9, 2024
1 parent 141f41f commit eab992f
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 78 deletions.
178 changes: 100 additions & 78 deletions resources/js/components/EntityTypeList.vue
Original file line number Diff line number Diff line change
@@ -1,74 +1,80 @@
<template>
<div class="list-group overflow-y-auto">
<a
v-for="(entry, i) in state.entries"
:key="i"
href="#"
class="list-group-item list-group-item-action d-flex flex-row align-items-center p-0"
:class="{ 'active': entry.id == selectedId }"
@click.prevent="selectEntry(entry)"
@mouseenter="onEnter(i)"
@mouseleave="onLeave(i)"
>
<div class="d-flex p-0 flex-fill">
<div
:style="getColorStyle(entry)"
class="me-2"
/>
<span class="flex-fill p-1">
{{ translateConcept(entry.thesaurus_url) }}
</span>
</div>
<div
v-if="state.hasOnHoverListener"
v-show="state.hoverStates[i]"
class="ms-auto btn-fab-list bg-white position-absolute z-1 end-0 me-2"
:class="activeClasses(entry)"
<div class="entity-type-list">
<div class="mb-2">
<ListToolbar v-model="state.order" />
</div>
<div class="list-group overflow-y-auto">
<Alert
v-if="state.entries.length > 0 && state.sortedEntries.length === 0"
type="info"
:message="t('global.search_no_results_for') + ' ' + state.order.text"
/>
<a
v-for="(entry, i) in state.sortedEntries"
:key="i"
href="#"
class="list-group-item list-group-item-action d-flex flex-row align-items-center py-1 px-3"
:class="{ 'active': entry.id == selectedId }"
@click.prevent="selectEntry(entry)"
@mouseenter="onEnter(i)"
@mouseleave="onLeave(i)"
>
<button
v-if="state.hasEditListener"
class="btn btn-outline-info btn-fab-sm rounded-circle"
data-bs-toggle="popover"
:data-content="t('global.edit')"
data-trigger="hover"
data-placement="bottom"
@click="onEdit(entry)"
>
<i
class="fas fa-fw fa-xs fa-edit"
style="vertical-align: 0;"
/>
</button>
<button
v-if="state.hasDuplicateListener"
class="btn btn-outline-primary btn-fab-sm rounded-circle"
data-bs-toggle="popover"
:data-content="t('global.duplicate')"
data-trigger="hover"
data-placement="bottom"
@click="onDuplicate(entry)"
>
<i
class="fas fa-fw fa-xs fa-clone"
style="vertical-align: 0;"
/>
</button>
<button
v-if="state.hasDeleteListener"
class="btn btn-outline-danger btn-fab-sm rounded-circle"
data-bs-toggle="popover"
:data-content="t('global.delete')"
data-trigger="hover"
data-placement="bottom"
@click="onDelete(entry)"
<div class="d-flex flex-fill">
<span class="flex-fill">
{{ translateConcept(entry.thesaurus_url) }}
</span>
</div>
<div
v-if="state.hasOnHoverListener"
v-show="state.hoverStates[i]"
class="ms-auto btn-fab-list bg-white position-absolute z-1 end-0 me-2"
:class="activeClasses(entry)"
>
<i
class="fas fa-fw fa-xs fa-trash"
style="vertical-align: 0;"
/>
</button>
</div>
</a>
<button
v-if="state.hasEditListener"
class="btn btn-outline-info btn-fab-sm rounded-circle"
data-bs-toggle="popover"
:data-content="t('global.edit')"
data-trigger="hover"
data-placement="bottom"
@click="onEdit(entry)"
>
<i
class="fas fa-fw fa-xs fa-edit"
style="vertical-align: 0;"
/>
</button>
<button
v-if="state.hasDuplicateListener"
class="btn btn-outline-primary btn-fab-sm rounded-circle"
data-bs-toggle="popover"
:data-content="t('global.duplicate')"
data-trigger="hover"
data-placement="bottom"
@click="onDuplicate(entry)"
>
<i
class="fas fa-fw fa-xs fa-clone"
style="vertical-align: 0;"
/>
</button>
<button
v-if="state.hasDeleteListener"
class="btn btn-outline-danger btn-fab-sm rounded-circle"
data-bs-toggle="popover"
:data-content="t('global.delete')"
data-trigger="hover"
data-placement="bottom"
@click="onDelete(entry)"
>
<i
class="fas fa-fw fa-xs fa-trash"
style="vertical-align: 0;"
/>
</button>
</div>
</a>
</div>
</div>
</template>

Expand All @@ -85,8 +91,13 @@
import {
translateConcept,
} from '@/helpers/helpers.js';
import { _cloneDeep } from '../helpers/helpers';
import ListToolbar from './forms/ListToolbar.vue';
export default {
components: {
ListToolbar,
},
props: {
data: {
type: Array,
Expand Down Expand Up @@ -155,28 +166,39 @@
const state = reactive({
hoverStates: new Array(data.value.length).fill(false),
entries: computed(_ => data.value.slice()),
sortedEntries: computed(_ => {
let entries = _cloneDeep(state.entries);
entries = entries.map(entry => {
entry.translated = translateConcept(entry.thesaurus_url);
return entry;
});
let filtered = entries.filter((entry) => {
return entry.translated.toLowerCase().includes(state.order.text.toLowerCase());
});
if(state.order.type === 'text') {
return filtered.toSorted((a, b) => a.translated.localeCompare(b.translated) * (state.order.asc ? 1 : -1));
} else {
return state.order.asc ? filtered : filtered.reverse();
}
}),
hasDeleteListener: !!onDeleteElement.value,
hasDuplicateListener: !!onDuplicateElement.value,
hasEditListener: !!onEditElement.value,
hasOnHoverListener: computed(_ => state.hasDeleteListener || state.hasDuplicateListener || state.hasEditListener),
order: {
text: '',
asc: true,
type: 'number',
}
});
const getColorStyle = entry => {
const size = '3px';
return {
backgroundColor: entry.color ?? '#000000',
width: size,
'flex-shrink': 0,
};
};
// RETURN
return {
t,
// HELPERS
translateConcept,
// LOCAL
getColorStyle,
onEnter,
onLeave,
activeClasses,
Expand Down
74 changes: 74 additions & 0 deletions resources/js/components/forms/ListToolbar.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<template>
<div class="toolbar list-toolbar input-group">
<span
class="input-group-text"
:class="{
'active':
modelValue.text.length
> 0
}"
>
<i class="fas fa-search" />
</span>
<input
class="form-control"
type="search"
:value="modelValue.text"
@input="updateText"
>
<button
class="btn input-group-text d-flex align-items-center"
type="button"
:class="{
'btn-outline-primary': modelValue.type === 'text',
'btn-outline-secondary': modelValue.type !== 'text',
'active': modelValue.type === 'text'
}"
@click="sortClicked('text')"
>
<span v-show="modelValue.type === 'text'">
<i class="fas fa-fw fa-arrow-down-a-z" />
</span>
<span v-show="modelValue.type === 'number'">
<i class="fas fa-fw fa-arrow-down-1-9" />
</span>
</button>
</div>
</template>

<script>
import { _cloneDeep } from '../../helpers/helpers';
export default {
props: {
modelValue: {
type: Object,
required: true,
validation: (obj) => {
return obj.hasOwnProperty('text') && obj.hasOwnProperty('type') && obj.hasOwnProperty('asc');
}
},
},
emits: ['update:modelValue'],
setup(props, context) {
const sortClicked = _ => {
const clone = _cloneDeep(props.modelValue);
clone.type = clone.type === 'text' ? 'number' : 'text';
context.emit('update:modelValue', clone);
};
const updateText = event => {
const clone = _cloneDeep(props.modelValue);
clone.text = event.target.value;
context.emit('update:modelValue', clone);
};
return {
updateText,
sortClicked,
};
},
};
</script>
6 changes: 6 additions & 0 deletions resources/js/helpers/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -970,4 +970,10 @@ export function copyToClipboard(elemId) {

export function sortConcepts(ca, cb) {
return translateConcept(ca.concept_url).localeCompare(translateConcept(cb.concept_url));
}

export function sortTranslated(asc = true, prop = 'thesaurus_url') {
return function (a, b) {
return translateConcept(a[prop]).localeCompare(translateConcept(b[prop])) * (asc ? 1 : -1);
};
}

0 comments on commit eab992f

Please sign in to comment.