Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gsoc table #3

Merged
merged 43 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
2f527c3
Initialisating KTable Component
BabyElias May 30, 2024
523168e
Initialised KTable (fixed linting)
BabyElias May 30, 2024
9109552
Fixed linting errors
BabyElias May 30, 2024
5b13c64
fixed failing tests
BabyElias May 30, 2024
ba89898
Merge pull request #647 from BabyElias/gsoc-table
MisRob May 31, 2024
60caa84
Added sorting functionality
BabyElias Jun 3, 2024
b85a6d3
organised file structure
BabyElias Jun 3, 2024
2784a07
added ktable to playground
BabyElias Jun 3, 2024
058e4c8
fixed linting errors
BabyElias Jun 3, 2024
b8db731
fixed linting errors
BabyElias Jun 3, 2024
bce8877
fixing linting errors, again
BabyElias Jun 3, 2024
491fe19
Merge pull request #649 from BabyElias/gsoc-table
MisRob Jun 5, 2024
f464d27
added scoped slots and sorting composable
BabyElias Jun 9, 2024
de583df
removed unnecessary validator
BabyElias Jun 9, 2024
2209b03
Merge branch 'learningequality:gsoc-table' into gsoc-table
BabyElias Jun 9, 2024
6f78cd7
Merge pull request #654 from BabyElias/gsoc-table
MisRob Jun 11, 2024
583999a
added changesort event handler and tests
BabyElias Jun 13, 2024
f843b55
Merge pull request #655 from BabyElias/gsoc-table
MisRob Jun 14, 2024
31f0f61
Added date sorting
BabyElias Jun 17, 2024
23a4c65
Merge branch 'learningequality:gsoc-table' into gsoc-table
BabyElias Jun 17, 2024
37beb3f
Fixed screen reader loading states
BabyElias Jun 18, 2024
218205b
Merge pull request #657 from BabyElias/gsoc-table
MisRob Jun 18, 2024
b8b752e
enhanced keyboard nav
BabyElias Jun 21, 2024
e897a71
Merge branch 'learningequality:gsoc-table' into gsoc-table
BabyElias Jul 9, 2024
091e7f2
fixed firefox accessibility issues
BabyElias Jul 11, 2024
11f0604
Merge pull request #669 from BabyElias/gsoc-table
MisRob Jul 12, 2024
e871bf2
Added scroll and custom widths
BabyElias Jul 16, 2024
a1393d1
Merge branch 'learningequality:gsoc-table' into gsoc-table
BabyElias Jul 16, 2024
48e969c
fixed conflicts
BabyElias Jul 16, 2024
96ede77
Added sticky panes
BabyElias Jul 18, 2024
d5b2b5c
added hover effect
BabyElias Jul 22, 2024
83b29fb
Added sortColumn icon
BabyElias Jul 26, 2024
f118cd9
added header highlight feature
BabyElias Jul 27, 2024
fb8bf2b
fixed focus state
BabyElias Aug 1, 2024
05576d1
partial theming
BabyElias Aug 2, 2024
2b0ca06
highlight-header theming and updated examples for clarity
BabyElias Aug 2, 2024
778c512
fixed outline and enhanced tab key navigation
BabyElias Aug 3, 2024
b7f5847
completed theming
BabyElias Aug 5, 2024
0613a21
fixed theming, removed unnecessary code
BabyElias Aug 5, 2024
9c4d02b
Merge pull request #682 from BabyElias/gsoc-table
MisRob Aug 6, 2024
b150305
added more tests
BabyElias Aug 8, 2024
67e1928
Merge branch 'learningequality:gsoc-table' into gsoc-table
BabyElias Aug 11, 2024
90d8c24
Merge branch 'gsoc-table-develop' into gsoc-table
BabyElias Aug 11, 2024
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
4 changes: 4 additions & 0 deletions custom-icons/sortColumn.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions docs/pages/ktable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>

<DocsPageTemplate apiDocs />

</template>
213 changes: 184 additions & 29 deletions docs/pages/playground.vue
Original file line number Diff line number Diff line change
@@ -1,29 +1,51 @@
<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: '#' } },
]"
/> -->

<!-- Play around with your component here: -->
<div id="app">
<h1>KTable Component Example</h1>

<!-- Local Sorting Table Example -->
<h2>Local Sorting Table</h2>
<KTable
:headers="headers"
:rows="rows"
caption="Local Sorting Table"
:useLocalSorting="true"
sortable
>
<template #header="{ header, index }">

Check failure on line 15 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'index' is defined but never used

Check failure on line 15 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'index' is defined but never used
<span>{{ header.label }} (Local)</span>
</template>
<template #cell="{ content, rowIndex, colIndex }">

Check failure on line 18 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'rowIndex' is defined but never used

Check failure on line 18 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'rowIndex' is defined but never used
<span v-if="colIndex === 1">{{ content }} years old</span>
<span v-else>{{ content }}</span>
</template>
</KTable>

<!-- Backend Sorting Table Example -->
<h2>Backend Sorting Table(with Custom Widths)</h2>
<div ref="loadingArea" role="status" aria-live="polite" class="sr-only">
{{ loadingMessage }}
</div>
<KTable
:headers="headersWithCustomWidths"
:rows="backendRows"
caption="Backend Sorting Table"
:useLocalSorting="false"
sortable
@changeSort="changeSortHandler"
>
<template #header="{ header, index }">

Check failure on line 37 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'index' is defined but never used

Check failure on line 37 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'index' is defined but never used
<span>{{ header.label }} (Backend)</span>
</template>
<template #cell="{ content, rowIndex, colIndex }">

Check failure on line 40 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'rowIndex' is defined but never used

Check failure on line 40 in docs/pages/playground.vue

View workflow job for this annotation

GitHub Actions / lint

'rowIndex' is defined but never used
<span v-if="colIndex === 2">{{ content }} (City)</span>
<span v-else>{{ content }}</span>
</template>
</KTable>

<div v-if="isLoading" class="loading-overlay">
Data is loading. Please wait...
</div>
</div>

</template>
Expand All @@ -32,16 +54,149 @@
<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 { ref } from '@vue/composition-api';
import KTable from '../../lib/KTable';

export default {
name: 'Playground',
components: {
KTable,
},
setup() {
const loadingArea = ref(null);
const isLoading = ref(false);
const loadingMessage = ref('');

const updateLoadingMessage = message => {
loadingMessage.value = message;
if (loadingArea.value) {
loadingArea.value.setAttribute('aria-live', 'off'); // Temporarily disable live region
void loadingArea.value.offsetWidth; // Force reflow
loadingArea.value.setAttribute('aria-live', 'polite'); // Re-enable live region
}
};

return {
loadingArea,
isLoading,
loadingMessage,
updateLoadingMessage,
};
},
data() {
return {};
return {
headers: [
{ label: 'Name', dataType: 'string' },
{ label: 'Age', dataType: 'numeric' },
{ label: 'City', dataType: 'string' },
{ label: 'Joined', dataType: 'date' },
{ label: 'Misc', dataType: 'others' },
],
headersWithCustomWidths: [
{ label: 'Name', dataType: 'string', minWidth: '20px', width: '2%' },
{ label: 'Age', dataType: 'numeric', minWidth: '100px', width: '33%' },
{ label: 'City', dataType: 'string', minWidth: '200px', width: '25%' },
{ label: 'Joined', dataType: 'date', minWidth: '150px', width: '20%' },
{ label: 'Misc', dataType: 'others', minWidth: '100px', width: '20%' },
],
rows: [
['John Doe', 28, 'New York', '2022-01-15T00:00:00Z', 'N/A'],
['Jane Smith', 34, 'Los Angeles', '2021-12-22T00:00:00Z', 'N/A'],
['Samuel Green', 22, 'Chicago', '2023-03-10T00:00:00Z', 'N/A'],
['Alice Johnson', 30, 'Houston', '2020-07-18T00:00:00Z', 'N/A'],
['Michael Brown', 45, 'Phoenix', '2019-11-05T00:00:00Z', 'N/A'],
['Emily Davis', 27, 'Philadelphia', '2021-08-14T00:00:00Z', 'N/A'],
['Christopher Wilson', 33, 'San Antonio', '2022-04-22T00:00:00Z', 'N/A'],
['Jessica Martinez', 29, 'San Diego', '2020-09-30T00:00:00Z', 'N/A'],
['Daniel Anderson', 40, 'Dallas', '2018-06-25T00:00:00Z', 'N/A'],
['Laura Thomas', 31, 'San Jose', '2021-03-18T00:00:00Z', 'N/A'],
['Matthew Jackson', 26, 'Austin', '2022-07-12T00:00:00Z', 'N/A'],
['Sarah White', 35, 'Fort Worth', '2020-02-27T00:00:00Z', 'N/A'],
['David Harris', 38, 'Columbus', '2019-10-19T00:00:00Z', 'N/A'],
['Sophia Clark', 24, 'Charlotte', '2023-01-05T00:00:00Z', 'N/A'],
['James Lewis', 32, 'San Francisco', '2021-05-23T00:00:00Z', 'N/A'],
['Olivia Robinson', 28, 'Indianapolis', '2022-11-11T00:00:00Z', 'N/A'],
['Benjamin Walker', 37, 'Seattle', '2020-12-03T00:00:00Z', 'N/A'],
],
backendRows: [
['John Doe', 28, 'New York', '2022-01-15T00:00:00Z', 'N/A'],
['Jane Smith', 34, 'Los Angeles', '2021-12-22T00:00:00Z', 'N/A'],
['Samuel Green', 22, 'Chicago', '2023-03-10T00:00:00Z', 'N/A'],
['Alice Johnson', 30, 'Houston', '2020-07-18T00:00:00Z', 'N/A'],
],
};
},
methods: {
async changeSortHandler(index, sortOrder) {
this.isLoading = true;
this.updateLoadingMessage('Data is loading. Please wait...');

this.$nextTick(() => {
if (this.$refs.loadingArea) {
this.$refs.loadingArea.focus();
}
});

// Simulate fetching sorted data from backend
console.log('Fetching sorted data from backend for column:', index, 'order:', sortOrder);

setTimeout(() => {
// For demo purposes, we just reverse the rows
this.backendRows = [...this.backendRows].reverse();
this.isLoading = false;
this.updateLoadingMessage('Data loaded successfully.');

setTimeout(() => {
this.updateLoadingMessage('');
}, 5000);
}, 10000); // Simulate a 10 second delay for fetching data
},
},
methods: {},
};

</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;
}

.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(255, 255, 255, 0.8);
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5em;
z-index: 5;
}

.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border-width: 0;
}
</style>
1 change: 1 addition & 0 deletions docs/rstIconReplacements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@
.. |skillsResource| replace:: :raw-html:`<span class="design-system-icon"><svg role="presentation" focusable="false" width="24" height="24" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M5 28.75V35h6.25l18.433-18.45-6.25-6.25L5 28.75zm32.683 1.85L30.6 37.684l-8.667-8.667 2.95-2.95 1.667 1.667 4.117-4.134 2.366 2.367-2.433 2.367L32.367 30l2.366-2.333 2.95 2.933zM11.017 18.05l-8.7-8.65L9.4 2.317l2.933 2.95L8.217 9.4 10 11.167l4.1-4.133L16.467 9.4 14.1 11.75l1.667 1.667-4.75 4.633zm23.5-6.383c.65-.65.65-1.667 0-2.35l-3.9-3.833c-.617-.65-1.7-.65-2.35 0L25.2 8.534l6.25 6.25 3.067-3.117z"/></svg></span>`
.. |slideshow| replace:: :raw-html:`<span class="design-system-icon"><svg viewBox="0 0 24 24" role="presentation" focusable="false" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M22 16V4c0-1.1-.9-2-2-2H8c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2zm-11-4l2.03 2.71L16 11l4 5H8l3-4zM2 6v14c0 1.1.9 2 2 2h14v-2H4V6H2z"/></svg></span>`
.. |socialSciencesResource| replace:: :raw-html:`<span class="design-system-icon"><svg viewBox="0 0 24 24" role="presentation" focusable="false" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M12 12.75c1.63 0 3.07.39 4.24.9 1.08.48 1.76 1.56 1.76 2.73V18H6v-1.61c0-1.18.68-2.26 1.76-2.73 1.17-.52 2.61-.91 4.24-.91zM4 13c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm1.13 1.1c-.37-.06-.74-.1-1.13-.1-.99 0-1.93.21-2.78.58A2.01 2.01 0 000 16.43V18h4.5v-1.61c0-.83.23-1.61.63-2.29zM20 13c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm4 3.43c0-.81-.48-1.53-1.22-1.85A6.95 6.95 0 0020 14c-.39 0-.76.04-1.13.1.4.68.63 1.46.63 2.29V18H24v-1.57zM12 6c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3z"/></svg></span>`
.. |sortColumn| replace:: :raw-html:`<span class="design-system-icon"><svg viewBox="0 0 24 24" role="presentation" focusable="false" width="24" height="25" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.178 4.154l5.177 5.523H7l5.177-5.523zM12.177 20.654L7 15.13h10.354l-5.177 5.524z" fill="#000"/></svg></span>`
.. |sort| replace:: :raw-html:`<span class="design-system-icon"><svg viewBox="0 0 24 24" role="presentation" focusable="false" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M18 21l-4-4h3V7h-3l4-4 4 4h-3v10h3M2 19v-2h10v2M2 13v-2h7v2M2 7V5h4v2H2z"/></svg></span>`
.. |starBorder| replace:: :raw-html:`<span class="design-system-icon"><svg viewBox="0 0 24 24" role="presentation" focusable="false" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M22 9.24l-7.19-.62L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21 12 17.27 18.18 21l-1.63-7.03L22 9.24zM12 15.4l-3.76 2.27 1-4.28-3.32-2.88 4.38-.38L12 6.1l1.71 4.04 4.38.38-3.32 2.88 1 4.28L12 15.4z"/></svg></span>`
.. |star| replace:: :raw-html:`<span class="design-system-icon"><svg viewBox="0 0 24 24" role="presentation" focusable="false" xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg></span>`
Expand Down
5 changes: 5 additions & 0 deletions docs/tableOfContents.js
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,11 @@ export default [
isCode: true,
keywords: ['button'],
}),
new Page({
path: '/ktable',
title: 'KTable',
isCode: true,
}),
new Page({
path: '/kgrid',
title: 'KGrid',
Expand Down
3 changes: 3 additions & 0 deletions lib/KIcon/iconDefinitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ const KolibriIcons = {
icon: require('./precompiled-icons/le/preview-unavailable.vue').default,
},
sort: { icon: require('./precompiled-icons/le/sort.vue').default },
sortColumn: {
icon: require('./precompiled-icons/le/sortColumn.vue').default,
},

// Features and links
learn: { icon: require('./precompiled-icons/material-icons/school/baseline.vue').default },
Expand Down
12 changes: 12 additions & 0 deletions lib/KIcon/precompiled-icons/le/sortColumn.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<template>

<svg viewBox="0 0 24 24" role="presentation" focusable="false" width="24" height="25" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.178 4.154l5.177 5.523H7l5.177-5.523zM12.177 20.654L7 15.13h10.354l-5.177 5.524z" fill="#000"/></svg>

</template>


<script>

export default {"name":"icon-804c4e229f501f72a23ba2f5a5cc42d5"}

</script>
91 changes: 91 additions & 0 deletions lib/KTable/KTableGridItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<template>

<td
:class="$computedClass(coreOutlineFocus)"
:style="{ textAlign: textAlign, minWidth: minWidth, width: width }"
tabindex="0"
role="gridcell"
@keydown="onKeydown"
>
<slot :content="content">
{{ content }}
</slot>
</td>

</template>


<script>

import { DATA_TYPE_NUMERIC } from '../composables/useSorting';

export default {
name: 'KTableGridItem',
props: {
content: {
type: [String, Number],
required: true,
},
dataType: {
type: String,
default: 'string',
},
rowIndex: {
type: Number,
required: true,
},
colIndex: {
type: Number,
required: true,
},
minWidth: {
type: String,
default: 'auto',
},
width: {
type: String,
default: 'auto',
},
},
computed: {
coreOutlineFocus() {
return {
':focus': {
...this.$coreOutline,
outlineOffset: '-2px',
},
};
},
textAlign() {
return this.dataType === DATA_TYPE_NUMERIC ? 'right' : 'left';
},
},
methods: {
onKeydown(event) {
// Check if the focused element is a button or actionable item
const focusedElement = event.target;
if (
event.key === 'Enter' &&
(focusedElement.tagName === 'BUTTON' ||
focusedElement.tagName === 'A' ||
focusedElement.hasAttribute('role'))
) {
focusedElement.click();
} else {
this.$emit('keydown', event, this.rowIndex, this.colIndex);
}
},
},
};

</script>


<style scoped>
td {
word-wrap: break-word;
white-space: normal;
}


</style>
Loading
Loading