Skip to content

Commit

Permalink
Table Action (#9)
Browse files Browse the repository at this point in the history
* add setMessage method to table store

* Create table action component

* add selection to row component

* refactor table component

* add executeAction method in table store

* increase version

* closeModal using force close

* add confirm and cancel emitter to modal

* Update row.component.vue

* refactor table action

* refactor table

* Update modal.component.vue

* add actionMsg to template props

* Update table.component.vue

* fetch items after row delete

* Update table.component.vue

* set message only if defined

* update modalMessage on props change

* fix method name

* clear selection on search when keepSelectionAcrossPage is false
  • Loading branch information
ibelar authored Sep 6, 2023
1 parent 52af4a7 commit 5e79e5d
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 29 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fohn-ui",
"version": "1.4.0",
"version": "1.5.0",
"description": "Javascript library for Fohn-Ui php framework.",
"main": "dist/fohn-ui.min.js",
"files": [
Expand Down
2 changes: 2 additions & 0 deletions src/components/components-install.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import TableRow from './table/row.component.vue';
import TableCell from './table/cell.component.vue';
import ExceptionModal from './modal/exception-modal.component.vue';
import TablePaginator from './table/paginator.component.vue';
import TableAction from "./table/table.action.component.vue";
import Dummy from './dummy.component.vue';
import Modal from './modal/modal.component.vue';
import Tabs from './tabs/tabs.component.vue';
Expand All @@ -33,6 +34,7 @@ const fohnComponents = [
{name: 'fohn-table-row', def: TableRow},
{name: 'fohn-table-cell', def: TableCell},
{name: 'fohn-table-paginator', def: TablePaginator},
{name: 'fohn-table-action', def: TableAction},
{name: 'fohn-modal', def: Modal},
{name: 'fohn-ui-exception', def: ExceptionModal},
{name: 'fohn-tab', def: Tab},
Expand Down
2 changes: 1 addition & 1 deletion src/components/form/form.store.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const useFormStoreFactory = (id) => {
this.fetchControlValues();
}
},
clearControlValues() {
clearControlsValue() {
for (const value of this.controls.values()) {
value.value = '';
}
Expand Down
37 changes: 29 additions & 8 deletions src/components/modal/modal.component.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
<script>
import {onMounted, ref, computed} from 'vue';
import {onMounted, ref, watch, computed} from 'vue';
import {useModalStoreFactory} from "./modal.store";
import {useElementSize, useWindowSize} from "@vueuse/core";
export default {
name: 'fohn-modal',
props: {
storeId: String,
message: {
type: String,
default: '',
},
title: String,
isClosable: {
type: Boolean,
Expand All @@ -18,7 +22,8 @@ export default {
default: 'close',
}
},
setup: function (props, extra) {
emits: ['onConfirm', 'onCancel'],
setup: function (props, { attrs, slots, emit }) {
const { contentUrl, callbacks, storeId } = props;
const modalTitle = ref(props.title);
const hasRemoteContent = !!contentUrl;
Expand All @@ -30,7 +35,12 @@ export default {
const { height: modalHeight } = useElementSize(modalEl);
const { height: windowHeight } = useWindowSize();
let maxHeight = false;
const message = ref('');
const modalMessage = ref('');
// listen top props change and update store message.
watch(() => props.message, (newMsg) => {
modalStore.setMessage(newMsg);
});
const modalStore = useModalStoreFactory(storeId)();
modalStore.status = status.value;
Expand All @@ -42,16 +52,23 @@ export default {
status.value = state.status;
isLoading.value = state.isLoading;
modalTitle.value = state.title;
message.value = state.message;
modalMessage.value = state.message;
});
const closeModal = () => {
if (isClosable) {
const closeModal = (forceClose = false) => {
if (forceClose || isClosable) {
modalStore.closeModal();
maxHeight = false;
}
}
const emitConfirm = (e) => {
emit('onConfirm', e);
}
const emitCancel = (e) => {
emit('onCancel', e);
}
const openModal = () => {
modalStore.openModal();
}
Expand Down Expand Up @@ -85,9 +102,11 @@ export default {
isLoading,
container,
heightCss,
message,
modalMessage,
onCallback,
hasRemoteContent,
emitConfirm,
emitCancel,
isClosable,
};
},
Expand All @@ -104,9 +123,11 @@ export default {
:closeModal="closeModal"
:openModal="openModal"
:onCallback="onCallback"
:message="message"
:message="modalMessage"
:hasRemoteContent="hasRemoteContent"
:isClosable="isClosable"
:confirm="emitConfirm"
:cancel="emitCancel"
v-bind="$attrs">Modal
</slot>
</div>
Expand Down
7 changes: 6 additions & 1 deletion src/components/modal/modal.store.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,18 @@ export const useModalStoreFactory = (id) => {
*/
openModal(options = {}) {
const {message, args = {}, payload = {}} = options;
this.message = message;
if (message) {
this.setMessage(message);
}
this.callbackPayload = payload;
this.status = 'open';
if (this.contentUrl) {
this.fetchHtml(this.contentUrl, args);
}
},
setMessage(message) {
this.message = message;
},
closeModal() {
this.status = 'close';
if (this.contentUrl && this.contentId) {
Expand Down
37 changes: 27 additions & 10 deletions src/components/table/row.component.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,44 @@
<template>
<slot :row="row" v-bind="$attrs">row</slot>
</template>

<script>
import {computed, inject, toRefs} from "vue";
import {useTableStoreFactory} from "./table.store";
export default {
name: 'fohn-table-row',
props: {
// storeId: String,
hasSelection: {
type: Boolean,
default: false,
},
row: Object,
},
emits: {},
setup: function (props, { attrs, slots, emit }) {
const { row } = props;
const method = {};
const { hasSelection: isActionable } = props;
const { row } = toRefs(props);
const tableStore = useTableStoreFactory(inject('tableStoreId'))();
method.getRowClass = (idx) => ({
'bg-gray-200': idx % 2,
});
const isEvenRow = (idx) => (idx % 2) === 0;
const isSelected = computed(() => tableStore.isRowSelected(row.value.id));
return { row };
const toggleRow = (id) => {
tableStore.toggleRow(id);
}
return { row, isEvenRow, isActionable, isSelected, toggleRow };
},
};
</script>

<template>
<slot
:row="row"
:isEvenRow="isEvenRow"
:isActionable="isActionable"
:isSelected="isSelected"
:toggleRow="toggleRow"
v-bind="$attrs">row</slot>
</template>

<style scoped>
</style>
61 changes: 61 additions & 0 deletions src/components/table/table.action.component.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script>
import {useTableStoreFactory} from "./table.store";
import {computed, inject, toRefs} from "vue";
import {toReactive} from "@vueuse/core";
export default {
name: 'fohn-table-action',
props: {
actionUrl: String,
tableRowsSelected: Number,
isTableFetching: Boolean,
placeHolder: {
type: String,
default: '{#}',
},
messages: {
type: Object,
default: () => ({none: '', single: '', multiple: ''})
}
},
setup(props, { attrs, slots, emit }) {
const {actionUrl, placeHolder} = props;
const {isTableFetching, tableRowsSelected } = toRefs(props);
const {messages} = toReactive(props);
const tableStore = useTableStoreFactory(inject('tableStoreId'))();
const isEnable = computed(() => tableRowsSelected.value > 0);
const actionMsg = computed(() => {
if (tableRowsSelected.value === 0) {
return messages.none || '';
}
if (tableRowsSelected.value === 1 && messages.single) {
return messages.single.replace(placeHolder, tableRowsSelected.value);
}
if (tableRowsSelected.value > 1 && messages.multiple) {
return messages.multiple.replace(placeHolder, tableRowsSelected.value);
}
return '';
});
const execute = (event) => {
if (!isTableFetching.value) {
tableStore.executeAction(actionUrl, event?.currentTarget);
}
}
return {execute, isEnable, isTableFetching, tableRowsSelected, actionMsg}
}
}
</script>
<template>
<slot
:isTableFetching="isTableFetching"
:tableRowsSelected="tableRowsSelected"
:execute="execute"
:isEnable="isEnable"
:actionMsg="actionMsg"
v-bind="$attrs">table action</slot>
</template>
Loading

0 comments on commit 5e79e5d

Please sign in to comment.