Skip to content

Commit

Permalink
Merge pull request #40 from Infineon/39-option-to-display-some-action…
Browse files Browse the repository at this point in the history
…s-in-a-popup-menu-instead-of-the-actions-column

Enhancement: Option to display some actions in a popup menu instead of the actions column
  • Loading branch information
PTUifx authored Jun 18, 2024
2 parents 52c1163 + 8f93359 commit 0126d75
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 14 deletions.
73 changes: 73 additions & 0 deletions examples/src/components/examples/ExamplePopupMenuActions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<template>
<div>
<InfineonDatatable
:data="rows"
:columns="columns"
:default-sort="{ key: 'name', type: 'D' }"
:can-edit="true"
:additional-actions="[ {
title: 'Print to Console.log',
label: 'Console.log',
action: logToConsole,
icon: ['fas', 'exclamation-triangle']},
]"
:popup-menu-actions="[ {
title: 'Open an alert box',
label: 'Alert',
action: showAlert,
icon: ['fas', 'terminal']
},
{
title: 'Open an alert box',
label: 'Alert',
action: showAlert,
icon: ['fas', 'terminal'],
canCloseMenu: true
} ]"
@on-menu-button-click="onMenuOpened"
/>
<!-- don't forget to load any fontawesome icons in /plugins/fontawesome.js!! -->
</div>
</template>

<script setup>
import { InfineonDatatable } from '../../../../lib';
const logToConsole = (row) => {
// eslint-disable-next-line no-console
console.log('we print to current row to console');
// eslint-disable-next-line no-console
console.log(row);
};
const showAlert = (row) => {
// eslint-disable-next-line no-alert
alert(JSON.stringify(row));
};
const onMenuOpened = (row) => {
console.log(`Menu triggered for row ${row.id}`)
}
const rows = [
{ id: 1, name: 'item1' },
{ id: 2, name: 'item2' },
{ id: 3, name: 'item3' },
{ id: 4, name: 'item4' },
];
const columns = [
{
key: 'id',
title: 'ID column title',
sortable: true,
sortType: 'NUMBER',
},
{
key: 'name',
title: 'Name',
sortable: true,
sortType: 'STRING',
},
];
</script>
4 changes: 4 additions & 0 deletions examples/src/components/global/TheHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ const links = ref([
label: 'Additional Actions',
routeName: 'exampleAdditionalActions',
},
{
label: 'Popup Menu Actions',
routeName: 'examplePopupMenuActions',
},
{
label: 'CSV Export',
routeName: 'exampleCsvExport',
Expand Down
6 changes: 6 additions & 0 deletions examples/src/router/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import ExampleEdit from '../components/examples/ExampleEdit.vue';
import ExampleHideColumns from '../components/examples/ExampleHideColumns.vue';
import ExampleStoreHiddenColumnsPerView from '../components/examples/ExampleStoreHiddenColumnsPerView.vue';
import ExampleAdditionalActions from '../components/examples/ExampleAdditionalActions.vue';
import ExamplePopupMenuActions from '../components/examples/ExamplePopupMenuActions.vue';
import ExampleDynamicColumnTitle from '../components/examples/ExampleDynamicColumnTitle.vue';
import ExampleConditionallyHideColumns from '../components/examples/ExampleConditionallyHideColumns.vue';
import ExampleCsvExport from '../components/examples/ExampleCsvExport.vue';
Expand Down Expand Up @@ -57,6 +58,11 @@ const router = createRouter({
name: 'exampleConditionallyHideAdditionalActions',
component: ExampleConditionallyHideAdditionalActions,
},
{
path: '/example-popup-menu-actions',
name: 'examplePopupMenuActions',
component: ExamplePopupMenuActions,
},
{
path: '/example-conditionally-hide-columns',
name: 'exampleConditionallyHideColumns',
Expand Down
15 changes: 13 additions & 2 deletions lib/datatable/InfineonDatatable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,13 @@
:row-is-in-edit-mode="(row.id) === (rowInEditMode?.id)"
:can-edit="canEdit"
:additional-actions="additionalActions"
:popup-menu-actions="popupMenuActions"
:is-menu-open="(row.id) === (rowMenuIsOpen?.id)"
@start-edit-row="startEditRow"
@save-row="saveRow"
@cancel-row="cancelRow"
@edit-mode-value="editModeValue"
@on-menu-button-click="closeOtherActionsPopupMenus"
>
<template
v-for="(_, name) in $slots"
Expand Down Expand Up @@ -158,9 +161,9 @@ const props = defineProps({
// [ { label: '', action: (row) => {}, icon: ['fas', 'list-ol'] } ]
additionalExportColumns: { type: Array, default: () => [] },
// customColHidden: { type: String, default: 'Custom column' },
popupMenuActions: { type: Array, default: () => [] },
});
const emit = defineEmits(['saveRow', 'editModeValue', 'cancelRow']);
const emit = defineEmits(['saveRow', 'editModeValue', 'cancelRow', 'onMenuButtonClick']);
const {
data, columns, localStorageKey,
Expand All @@ -169,6 +172,7 @@ const sortColumn = ref(props.defaultSort);
const currentPage = ref(0);
const pageSize = ref(10);
const rowInEditMode = ref(undefined);
const rowMenuIsOpen = ref(undefined);
const count = ref(0);
const hiddenColumnKeys = ref([]);
Expand Down Expand Up @@ -240,6 +244,8 @@ const processedData = computed(() => {
return sliced;
});
const closeRowMenusMap = ref(new Map(processedData.value.map((_, index) => [index, false])));
// store hidden columns for a predefined property localStorageKey - if not defined, use default
const hiddenColumnsLocalStorageKey = computed(() => localStorageKey.value || realColumns
.value.map((c) => c.key).sort().join());
Expand Down Expand Up @@ -279,6 +285,11 @@ function editModeValue(row) {
emit('editModeValue', row);
}
function closeOtherActionsPopupMenus(row) {
rowMenuIsOpen.value = row ? row : undefined;
emit('onMenuButtonClick', row);
}
function cancelRow(row) {
emit('cancelRow', row);
rowInEditMode.value = undefined;
Expand Down
122 changes: 110 additions & 12 deletions lib/datatable/InfineonDatatableRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,67 @@
class="btn btn-outline-primary btn-sm"
:class="{'ms-1': idx > 0}"
:title="additionalAction.title"
:style="additionalAction.style ? additionalAction.style : ''"
@click="additionalAction.action(row)"
>
<font-awesome-icon
v-if="additionalAction.icon"
:icon="additionalAction.icon"
/>
<span v-if="additionalAction.label">
{{ additionalAction.label }}
</span>
<div style="display: flex;">
<div
:style="additionalAction.label ? 'margin-right: 4px;' : ''"
>
<font-awesome-icon
v-if="additionalAction.icon"
:icon="additionalAction.icon"
/>
</div>
<span v-if="additionalAction.label">
{{ additionalAction.label }}
</span>
</div>
</button>
</template>
<button
v-if="canEdit && (popupMenuActions.length > 0)"
ref="menuButtonRef"
class="btn btn-outline-primary btn-sm me-1"
:style="additionalActions.length > 0 ? 'margin-left: 4px;' : ''"
style="position: relative"
@click="showPopupMenu"
>
<font-awesome-icon :icon="['fas', 'ellipsis-h']" />
<div
v-show="showMenu && isMenuOpen"
ref="menuRef"
class="menu"
>
<template
v-for="(popupMenuAction, idx) in popupMenuActions"
:key="idx"
>
<button
v-show="!popupMenuAction.visible || popupMenuAction.visible(row)"
class="btn btn-outline-primary btn-sm"
:class="{'ms-1': idx > 0}"
:title="popupMenuAction.title"
:style="popupMenuAction.style ? popupMenuAction.style : ''"
@click="(event) => popupMenuActionOnClick(event, popupMenuAction.action, popupMenuAction.canCloseMenu)"
>
<div style="display: flex;">
<div
:style="popupMenuAction.label ? 'margin-right: 4px;' : ''"
>
<font-awesome-icon
v-if="popupMenuAction.icon"
:icon="popupMenuAction.icon"
/>
</div>
<span v-if="popupMenuAction.label">
{{ popupMenuAction.label }}
</span>
</div>
</button>
</template>
</div>
</button>
</td>
<DatatableRowColumn
v-for="(column, index) in shownColumns"
Expand Down Expand Up @@ -152,7 +202,7 @@
<script setup>
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import {
toRefs, computed, ref,
toRefs, computed, ref, onMounted, watch
} from 'vue';
import DatatableRowColumn from './InfineonDatatableRowColumn.vue';
Expand All @@ -161,21 +211,23 @@ const props = defineProps({
rowIndex: { type: Number, default: undefined },
columns: { type: Array, default: () => [] },
canEdit: Boolean,
isMenuOpen: Boolean,
rowIsInEditMode: Boolean,
hiddenColumnKeys: { type: Array, default: () => [] },
additionalActions: { type: Object, default: () => {} }, // { label: '', action: (row) => {} }
popupMenuActions: { type: Array, default: () => [] },
});
const {
row, columns, rowIndex, hiddenColumnKeys, canEdit, additionalActions,
row, columns, rowIndex, hiddenColumnKeys, canEdit, additionalActions, popupMenuActions, popupMenuOpen, isMenuOpen
} = toRefs(props);
const emit = defineEmits(['startEditRow', 'saveRow', 'cancelRow', 'onRowButtonClick', 'editRow', 'editModeValue']);
const emit = defineEmits(['startEditRow', 'saveRow', 'cancelRow', 'onRowButtonClick', 'editRow', 'editModeValue', 'onMenuButtonClick']);
const shownColumns = computed(() => columns.value
.filter((c) => !c.hidable || !hiddenColumnKeys.value.includes(c.key)));
.filter((c) => !c.hidable || !hiddenColumnKeys.value.includes(c.key)));
const hiddenColumns = computed(() => columns.value
.filter((c) => c.hidable && hiddenColumnKeys.value.includes(c.key)));
.filter((c) => c.hidable && hiddenColumnKeys.value.includes(c.key)));
const calculateColspan = computed(() => {
let colspan = shownColumns.value.length;
Expand All @@ -191,6 +243,41 @@ const calculateColspan = computed(() => {
const editRow = ref(row.value);
const expanded = ref(false);
const menuRef = ref(null);
const menuButtonRef = ref(null);
const menuActionButtonRefs = ref([]);
const forcedMenuClose = ref(false);
const showMenu = ref(false);
function showPopupMenu(event) {
emit('onMenuButtonClick', row.value);
showMenu.value =!showMenu.value || !menuButtonRef.value.contains(event.target);
}
function popupMenuActionOnClick(_, action, canCloseMenu) {
if (canCloseMenu) {
forcedMenuClose.value = true;
}
action(row.value)
}
function closeMenuOnClickOutside(event) {
if (menuRef.value?.contains(event.target)) {
showMenu.value = !forcedMenuClose.value;
forcedMenuClose.value = false;
}
}
onMounted(() => {
document.addEventListener('click', closeMenuOnClickOutside);
});
watch(isMenuOpen, () => {
if (!isMenuOpen.value) {
showMenu.value = false;
}
})
function startEditRow() {
// aktuelle row in editier row kopieren
editRow.value = { ...row.value };
Expand All @@ -209,6 +296,17 @@ function cancelRow() {
</script>
<style scoped>
.menu {
position: absolute;
background-color: white;
border: 2px solid var(--bs-table-border-color);
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
padding: 8px;
margin-left: -3px;
margin-top: -2px;
z-index: 4656546797;
}
.row-odd {
--bs-table-accent-bg: var(--bs-table-striped-bg);
color: var(--bs-table-striped-color);
Expand Down
2 changes: 2 additions & 0 deletions lib/plugins/fontawesome.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
faAngleLeft,
faAngleRight,
faAngleDoubleRight,
faEllipsisH,
} from '@fortawesome/free-solid-svg-icons';

library.add(
Expand All @@ -28,4 +29,5 @@ library.add(
faAngleLeft,
faAngleRight,
faAngleDoubleRight,
faEllipsisH,
);

0 comments on commit 0126d75

Please sign in to comment.