Skip to content

Commit

Permalink
Merge pull request learningequality#655 from BabyElias/gsoc-table
Browse files Browse the repository at this point in the history
KTable - [Trial] Added changeSort event handler
  • Loading branch information
MisRob authored Jun 14, 2024
2 parents 6f78cd7 + 583999a commit f843b55
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 53 deletions.
83 changes: 45 additions & 38 deletions docs/pages/playground.vue
Original file line number Diff line number Diff line change
@@ -1,63 +1,41 @@
<template>

<!--
Playground: A private page for components development
*****************************************************
Place a component you're working on here and see it
live on http://localhost:4000/playground
Please do not commit your local updates of this file.
-->
<div style="padding: 24px">
<!--
Example: Uncomment lines bellow, change something
in lib/KBreadcrumbs.vue and see the updates reflected
on this page
-->
<!-- <KBreadcrumbs
:items="[
{ text: 'Global Digital Library', link: { path: '#' } },
{ text: 'English', link: { path: '#' } },
{ text: 'Level 2 ', link: { path: '#' } },
]"
/> -->
<div id="app">
<h1>KTable Component Example</h1>
<h2>Sortable Table</h2>
<h2>Sortable Table with Local Sorting</h2>
<KTable
:headers="headers"
:rows="rows"
:rows="localRows"
caption="Sortable Table"
:useLocalSorting="true"
sortable
>
<template #header="{ header, index }">
<span>{{ header.label }} (Custom)</span>
<span>{{ header.label }} (Local Sort)</span>
</template>
<template #cell="{ content, rowIndex, colIndex }">
<span v-if="colIndex === 1">{{ content }} years old</span>
<span v-else>{{ content }}</span>
</template>
</KTable>

<h2>Non-Sortable Table</h2>
<h2>Sortable Table with Backend Sorting</h2>
<KTable
:headers="headers"
:rows="rows"
caption="Non-Sortable Table"
:sortable="false"
:rows="backendRows"
caption="Sortable Table"
:useLocalSorting="false"
sortable
@changeSort="changeSortHandler"
>
<template #header="{ header, index }">
<span>{{ header.label }} (Non-Sortable)</span>
<span>{{ header.label }} (Backend Sort)</span>
</template>
<template #cell="{ content, rowIndex, colIndex }">
<span v-if="colIndex === 2">{{ content }} (City)</span>
<span v-else>{{ content }}</span>
</template>
</KTable>


<!-- Play around with your component here: -->

</div>

</template>
Expand All @@ -66,10 +44,10 @@
<script>
/*
Playground is a Vue component too,
so you can also use `data`, `methods`, etc.
as usual if helpful
*/
Playground is a Vue component too,
so you can also use `data`, `methods`, etc.
as usual if helpful
*/
import KTable from '../../lib/KTable';
export default {
Expand All @@ -86,14 +64,43 @@
{ label: 'Joined', dataType: 'date' },
{ label: 'Misc', dataType: 'others' },
],
rows: [
localRows: [
['John Doe', 28, 'New York', '2022-01-15', 'N/A'],
['Jane Smith', 34, 'Los Angeles', '2021-12-22', 'N/A'],
['Samuel Green', 22, 'Chicago', '2023-03-10', 'N/A'],
['Alice Johnson', 30, 'Houston', '2020-07-18', 'N/A'],
],
backendRows: [
['John Doe', 28, 'New York', '2022-01-15', 'N/A'],
['Jane Smith', 34, 'Los Angeles', '2021-12-22', 'N/A'],
['Samuel Green', 22, 'Chicago', '2023-03-10', 'N/A'],
['Alice Johnson', 30, 'Houston', '2020-07-18', 'N/A'],
],
};
},
methods: {
changeSortHandler(index, sortOrder) {
// Simulate fetching sorted data from backend
console.log('Fetching sorted data from backend for column:', index, 'order:', sortOrder);
// You can replace this with an actual API call
// For demo purposes, we just reverse the rows
this.backendRows = [...this.backendRows].reverse();
},
},
};
</script>

<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
margin-top: 60px;
}
h1, h2 {
margin: 20px 0;
}
</style>
4 changes: 3 additions & 1 deletion lib/KTable/KTableGridItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

<script>
import { DATA_TYPE_NUMERIC } from '../composables/useSorting';
export default {
name: 'KTableGridItem',
props: {
Expand All @@ -33,7 +35,7 @@
},
computed: {
textAlign() {
return this.dataType === 'numeric' ? 'right' : 'left';
return this.dataType === DATA_TYPE_NUMERIC ? 'right' : 'left';
},
},
methods: {
Expand Down
46 changes: 35 additions & 11 deletions lib/KTable/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
v-for="(header, index) in headers"
:key="index"
tabindex="0"
:aria-sort="sortable ? getAriaSort(index) : null"
:aria-sort="sortable && header.dataType !== DATA_TYPE_OTHERS ? getAriaSort(index) : null"
:class="{ sortable: sortable && header.dataType !== DATA_TYPE_OTHERS }"
@click="sortable ? handleSort(index) : null"
@click="sortable && header.dataType !== DATA_TYPE_OTHERS ? handleSort(index) : null"
@keydown="handleKeydown($event, -1, index)"
>
<slot name="header" :header="header" :index="index">
Expand Down Expand Up @@ -54,25 +54,31 @@

<script>
import { ref, computed } from '@vue/composition-api';
import useSorting, { SORT_ORDER_ASC, SORT_ORDER_DESC, DATA_TYPE_OTHERS } from './useSorting';
import { ref, computed, watch } from '@vue/composition-api';
import useSorting, {
SORT_ORDER_ASC,
SORT_ORDER_DESC,
DATA_TYPE_OTHERS,
} from '../composables/useSorting';
import KTableGridItem from './KTableGridItem.vue';
export default {
name: 'KTable',
components: {
KTableGridItem,
},
setup(props) {
setup(props, { emit }) {
const headers = ref(props.headers);
const rows = ref(props.rows);
const useLocalSorting = ref(props.useLocalSorting);
const { sortKey, sortOrder, sortedRows, handleSort, getAriaSort } = useSorting(
headers,
rows,
useLocalSorting
);
const {
sortKey,
sortOrder,
sortedRows,
handleSort: localHandleSort,
getAriaSort,
} = useSorting(headers, rows, useLocalSorting);
const finalRows = computed(() => {
if (props.sortable) {
Expand All @@ -82,6 +88,25 @@
}
});
watch(
() => props.rows,
newRows => {
rows.value = newRows;
}
);
const handleSort = index => {
if (useLocalSorting.value) {
localHandleSort(index);
} else {
emit(
'changeSort',
index,
sortOrder.value === SORT_ORDER_ASC ? SORT_ORDER_DESC : SORT_ORDER_ASC
);
}
};
return {
sortKey,
sortOrder,
Expand All @@ -105,7 +130,6 @@
caption: {
type: String,
required: true,
default: 'Information',
},
useLocalSorting: {
type: Boolean,
Expand Down
41 changes: 38 additions & 3 deletions lib/__tests__/KTable.spec.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { shallowMount } from '@vue/test-utils';
import KTable from '../../lib/KTable';
import KTable from '../KTable';

describe('KTable.vue', () => {
it('should mount the component', () => {
const headers = ['Name', 'Age', 'City'];
const headers = [
{ label: 'Name', dataType: 'string' },
{ label: 'Age', dataType: 'numeric' },
{ label: 'City', dataType: 'string' },
];
const rows = [
['Alice', 25, 'New York'],
['Bob', 30, 'Los Angeles'],
Expand All @@ -13,13 +17,19 @@ describe('KTable.vue', () => {
propsData: {
headers,
rows,
useLocalSorting: true,
},
});
const thElements = wrapper.findAll('th');
expect(thElements.length).toBe(headers.length);
});

it('should render correct number of rows', () => {
const headers = ['Name', 'Age', 'City'];
const headers = [
{ label: 'Name', dataType: 'string' },
{ label: 'Age', dataType: 'numeric' },
{ label: 'City', dataType: 'string' },
];
const rows = [
['Alice', 25, 'New York'],
['Bob', 30, 'Los Angeles'],
Expand All @@ -29,9 +39,34 @@ describe('KTable.vue', () => {
propsData: {
headers,
rows,
useLocalSorting: true,
},
});
const trElements = wrapper.findAll('tbody tr');
expect(trElements.length).toBe(rows.length);
});

it('should emit changeSort event on header click when useLocalSorting is false', async () => {
const headers = [
{ label: 'Name', dataType: 'string', sortable: true },
{ label: 'Age', dataType: 'numeric', sortable: true },
{ label: 'City', dataType: 'string', sortable: true },
];
const items = [
['Alice', 25, 'New York'],
['Bob', 30, 'Los Angeles'],
['Charlie', 35, 'San Francisco'],
];
const wrapper = shallowMount(KTable, {
propsData: {
headers,
items,
useLocalSorting: false,
},
});

const thElements = wrapper.findAll('th');
await thElements.at(0).trigger('click');
expect(wrapper.emitted().changeSort).toBeTruthy();
});
});
File renamed without changes.

0 comments on commit f843b55

Please sign in to comment.