Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9e514c9
feat: related objects filter in module index
didoda Apr 3, 2025
3eacb77
feat: apply filter
didoda Apr 3, 2025
f72aa8d
fix: init filter null
didoda Apr 3, 2025
e9555f5
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Apr 8, 2025
df121cb
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Apr 18, 2025
af43650
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda May 6, 2025
7d78678
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda May 16, 2025
1f478b8
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda May 20, 2025
21f8744
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda May 27, 2025
2ffed23
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Jun 3, 2025
bb85cd3
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Jun 13, 2025
a810a67
feat: search in side panel
didoda Jun 16, 2025
69c22b0
fix: open panel if no active filter
didoda Jun 16, 2025
d3eb4ad
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Jun 17, 2025
ecbc81c
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Jul 3, 2025
0c1f1d3
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Jul 3, 2025
d216524
refactor: side panel with pagination
didoda Jul 7, 2025
9f414b0
feat: search in panel
didoda Jul 7, 2025
87d9e6f
fix: better pagination
didoda Jul 10, 2025
f1bcb3b
chore fix: i18n
didoda Jul 10, 2025
838f0c5
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Jul 31, 2025
1128b15
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Aug 7, 2025
e930c17
fix: humanize label
didoda Sep 2, 2025
4dde59c
Merge branch 'master' into feat/related-objects-filter-in-filter-box
didoda Sep 2, 2025
1d6b26e
fix: open panel only if relation filter active
didoda Sep 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions locales/default.pot
Original file line number Diff line number Diff line change
Expand Up @@ -1609,6 +1609,21 @@ msgstr ""
msgid "Error while creating new object."
msgstr ""

msgid "Edit related objects"
msgstr ""

msgid "Choose object type"
msgstr ""

msgid "Choose relation"
msgstr ""

msgid "Filter to apply"
msgstr ""

msgid "Search related objects"
msgstr ""

msgid "Action"
msgstr ""

Expand Down
15 changes: 15 additions & 0 deletions locales/en_US/default.po
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,21 @@ msgstr ""
msgid "Error while creating new object."
msgstr ""

msgid "Edit related objects"
msgstr ""

msgid "Choose object type"
msgstr ""

msgid "Choose relation"
msgstr ""

msgid "Filter to apply"
msgstr ""

msgid "Search related objects"
msgstr ""

msgid "Action"
msgstr ""

Expand Down
15 changes: 15 additions & 0 deletions locales/it_IT/default.po
Original file line number Diff line number Diff line change
Expand Up @@ -1631,6 +1631,21 @@ msgstr "Dato obbligatorio mancante \"${ required }\". Riprovare"
msgid "Error while creating new object."
msgstr "Si è verificato un errore durante la creazione del nuovo oggetto."

msgid "Edit related objects"
msgstr "Modifica oggetti correlati"

msgid "Choose object type"
msgstr "Scegli il tipo di oggetto"

msgid "Choose relation"
msgstr "Scegli la relazione"

msgid "Filter to apply"
msgstr "Filtro da applicare"

msgid "Search related objects"
msgstr "Cerca oggetti correlati"

msgid "Action"
msgstr "Azione"

Expand Down
4 changes: 4 additions & 0 deletions resources/js/app/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
FieldTextarea: () => import(/* webpackChunkName: "field-textarea" */'app/components/form/field-textarea'),
FieldTitle: () => import(/* webpackChunkName: "field-title" */'app/components/form/field-title'),
ObjectInfo: () => import(/* webpackChunkName: "object-info" */'app/components/object-info/object-info'),
RelatedObjectsFilter: () => import(/* webpackChunkName: "related-objects-filter" */'app/components/related-objects-filter/related-objects-filter'),
ModuleProperties: () => import(/* webpackChunkName: "module-properties" */'app/components/module/module-properties'),
ModuleSetup: () => import(/* webpackChunkName: "module-setup" */'app/components/module/module-setup'),
AddRelatedById: () => import(/* webpackChunkName: "add-related-by-id" */'app/components/add-related-by-id/add-related-by-id'),
Expand Down Expand Up @@ -624,6 +625,7 @@

// use component everywhere in Manager
Vue.component('AppIcon', AppIcon);
Vue.component('ClipboardItem', _vueInstance.$options.components.ClipboardItem);
Vue.component('DateRangesView', _vueInstance.$options.components.DateRangesView);
Vue.component('FieldCheckbox', _vueInstance.$options.components.FieldCheckbox);
Vue.component('FieldGeoCoordinates', _vueInstance.$options.components.FieldGeoCoordinates);
Expand All @@ -643,5 +645,7 @@
Vue.component('ObjectCategories', _vueInstance.$options.components.ObjectCategories);
Vue.component('ObjectCaptions', _vueInstance.$options.components.ObjectCaptions);
Vue.component('ObjectInfo', _vueInstance.$options.components.ObjectInfo);
Vue.component('RelatedObjectsFilter', _vueInstance.$options.components.RelatedObjectsFilter);
Vue.component('Thumbnail', _vueInstance.$options.components.Thumbnail);

Check warning on line 649 in resources/js/app/app.js

View workflow job for this annotation

GitHub Actions / Check javascript build (20.x)

Component name "Thumbnail" should always be multi-word

Check warning on line 649 in resources/js/app/app.js

View workflow job for this annotation

GitHub Actions / Check javascript build (22.x)

Component name "Thumbnail" should always be multi-word
Vue.component('RibbonItem', _vueInstance.$options.components.RibbonItem);
Vue.component('UploadedObject', _vueInstance.$options.components.UploadedObject);
24 changes: 24 additions & 0 deletions resources/js/app/components/filter-box.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export default {
default: '[10]'
},
filterActive: Boolean,
filterRelationsActive: {
type: Boolean,
default: false
},
filterList: {
type: Array,
default: () => [],
Expand Down Expand Up @@ -81,7 +85,9 @@ export default {
* When disabled, only direct children are fetched.
* This will switch the API filter between `parent` and `ancestor`.
*/
editFilterRelations: this.filterRelationsActive,
filterByDescendants: false,
filterRelations: {},
folder: null,
moreFilters: this.filterActive,
pageSize: this.pagination.page_size,
Expand Down Expand Up @@ -364,6 +370,10 @@ export default {

const filter = this.prepareFilters();
const filterObject = { ...this.queryFilter, filter };
filterObject.filter = {
...filterObject.filter,
...this.filterRelations,
};
this.availableFilters = this.filtersByType?.[filterObject?.filter?.type] || [];
this.$emit('filter-objects', filterObject);
},
Expand Down Expand Up @@ -461,6 +471,20 @@ export default {
delete this.queryFilter.filter[oldFilter];
this.queryFilter.filter[newFilter] = this.folder?.id || null;
},

toggleFilterRelations() {
this.editFilterRelations = !this.editFilterRelations;
},

updateFilterRelations(filter) {
this.filterRelations = {};
for (const [key, value] of Object.entries(filter)) {
this.filterRelations[key] = [];
for (const v of value) {
this.filterRelations[key].push(v);
}
}
},
}
};
</script>
2 changes: 1 addition & 1 deletion resources/js/app/components/object-info/object-info.vue
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default {
fillData() {
const source = BEDITA?.indexLists?.[this.reloadedData?.type] || {};
this.fields = source || ['title', 'description'];
this.fields = this.fields.filter((value, index, array) => {
this.fields = this.fields?.filter((value, index, array) => {
return array.indexOf(value) === index;
});
for (const field of this.fields) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<template>
<div class="related-objects-filter">
<template v-if="openPanel">
<related-objects-panel
:initial-filter="initialFilter"
:relations-schema="relationsSchema"
:show-panel="openPanel"
@update:filter="updateData('filter', $event)"
@update:objectsMap="updateData('objectsMap', $event)"
@update:showPanel="updateData('openPanel', $event)"
/>
</template>
<template v-if="filter">
<div class="filter-to-apply">
<div
v-for="relationName in Object.keys(filter)"
:key="relationName"
>
<template v-if="filter?.[relationName]?.length">
<span class="tag relation">{{ tr(relationName) }}</span>
<template v-for="relatedId in filter[relationName]">
<div
class="tag"
:class="moduleClass(relatedId)"
:key="relatedId"
>
[{{ relatedId }}] {{ objectsMap?.[relatedId]?.title }}
<a
class="unpick"
@click.prevent="pickout(relationName, relatedId)"
>
<app-icon
icon="carbon:close"
width="18"
height="18"
/>
</a>
</div>
</template>
</template>
</div>

<button
class="mt-1 button button-outlined is-small"
@click.prevent="openPanel = true"
>
<app-icon icon="carbon:edit" />
<span class="ml-05">{{ msgEdit }}</span>
</button>
</div>
</template>
</div>
</template>
<script>
import { t } from 'ttag';

export default {
name: 'RelatedObjectsFilter',
components: {
'related-objects-panel': () => import('./related-objects-panel.vue'),
},
props: {
initialFilter: {
type: Object,
default: () => ({}),
},
relationsSchema: {
type: Object,
required: true,
},
},
data() {
return {
filter: null,
msgEdit: t`Edit related objects`,
objectsMap: null,
openPanel: false,
};
},
mounted() {
this.$nextTick(() => {
if (this.initialFilter) {
const relationNames = Object.keys(this.relationsSchema);
const relationKeys = Object.keys(this.initialFilter).filter((key) => relationNames.includes(key));
this.filter = relationKeys.reduce((acc, key) => {
acc[key] = this.initialFilter[key];
return acc;
}, {});
} else {
this.openPanel = true;
}
});
},
methods: {
moduleClass(item) {
const objectType = this.objectsMap?.[item]?.type || null;
if (!objectType) {
return '';
}

return `has-background-module-${objectType}`;
},
pickout(relationName, relatedId) {
if (this.filter?.[relationName]) {
this.filter[relationName] = this.filter[relationName].filter((id) => id !== relatedId);
this.updateFilter();
}
},
tr(item) {
return BEDITA_I18N?.[item] || this.t(item) || item;
},
updateData(key, value) {
this.$emit('edit-filter-relations', true);
this[key] = value;
if (key === 'filter') {
this.updateFilter();
}
},
updateFilter() {
this.$forceUpdate();
this.$emit('update-filter-related', this.filter);
},
},
}
</script>
<style scoped>
div.related-objects-filter {
display: flex;
flex-direction: column;
grid-gap: 0.5em;
justify-content: space-between;
}
</style>
Loading
Loading