Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
f08d96a
WIP big changes
nucleogenesis Oct 1, 2025
669b812
Add flex for users layout
AlexVelezLl Oct 3, 2025
7939234
Refactor users table components to eliminate code duplication
nucleogenesis Oct 3, 2025
c3965c3
updating styles/layout userstable & toolbar, refactoring PaginatedLis…
nucleogenesis Oct 6, 2025
22dd44c
use PaginationActions in DownloadsList
nucleogenesis Oct 6, 2025
4503c23
ClassEnrollForm uses pagination actions now; top and bottom
nucleogenesis Oct 6, 2025
fc60c1b
remove dupe method; dupe actions in DownloadsList
nucleogenesis Oct 9, 2025
ef610b9
bottom margin fixed in MyDownloads
nucleogenesis Oct 9, 2025
227ff59
convert roleType to roleType/user_types query param in UsersTable
nucleogenesis Oct 9, 2025
be7d103
fix missing clear button when users selected
nucleogenesis Oct 9, 2025
8beb52a
refactor empty message handling in UsersTable
nucleogenesis Oct 9, 2025
6fbe85d
user table background opacity fix, better css for paddings
nucleogenesis Oct 9, 2025
6767f8e
update NewUsersPage to utilize updated layout/styles from UsersRootPage
nucleogenesis Oct 9, 2025
c557796
dedupe css
nucleogenesis Oct 9, 2025
3cfe9d4
lint
nucleogenesis Oct 9, 2025
d7ec47c
usersrootpage cleanup style & busted code
nucleogenesis Oct 9, 2025
7c4a3fa
refactor UsersTrashPage to use same styles/ux as UsersRootPage
nucleogenesis Oct 9, 2025
a1e31e0
clean up dead styles; use appBarHeight for calculating heights
nucleogenesis Oct 9, 2025
e4d1441
pass appbarheight through appbar to facilityappbar so we can use it i…
nucleogenesis Oct 9, 2025
66018bb
$themeTokens.surface > "white"
nucleogenesis Oct 10, 2025
ef96beb
fix android height issue w/ proper maxHeight
nucleogenesis Oct 10, 2025
93d77bc
improved padding on left/right table actions
nucleogenesis Oct 10, 2025
c613052
fix height, use kpagecontainer in userrootpage
nucleogenesis Oct 10, 2025
329f4d9
rekpagecontainerization
nucleogenesis Oct 10, 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
112 changes: 112 additions & 0 deletions kolibri/plugins/facility/assets/src/composables/usePagination.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { computed } from 'vue';
import { useRoute, useRouter } from 'vue-router/composables';
import pickBy from 'lodash/pickBy';
import clamp from 'lodash/clamp';

/**
* Composable for managing pagination state and navigation
* Handles page changes, items per page, and URL query synchronization
*/
export default function usePagination({ usersCount, totalPages } = {}) {
const route = useRoute();
const router = useRouter();

// Current page from URL query params
const currentPage = computed({
get() {
return Number(route.query.page) || 1;
},
set(value) {
router.push({
...route,
query: pickBy({
...route.query,
page: value > 1 ? value : null, // Don't include page=1 in URL
}),
});
},
});

// Items per page from URL query params
const itemsPerPage = computed({
get() {
return Number(route.query.page_size) || 30;
},
set(value) {
router.push({
...route,
query: pickBy({
...route.query,
page_size: value !== 30 ? value : null, // Don't include default size in URL
page: null, // Reset to first page when changing page size
}),
});
},
});

// Calculate visible range for pagination display
const startRange = computed(() => {
return (currentPage.value - 1) * itemsPerPage.value;
});

const visibleStartRange = computed(() => {
const count = usersCount?.value || 0;
return Math.min(startRange.value + 1, count);
});

const endRange = computed(() => {
return currentPage.value * itemsPerPage.value;
});

const visibleEndRange = computed(() => {
const count = usersCount?.value || 0;
return Math.min(endRange.value, count);
});

// Button states
const previousButtonDisabled = computed(() => {
const count = usersCount?.value || 0;
return currentPage.value === 1 || count === 0;
});

const nextButtonDisabled = computed(() => {
const count = usersCount?.value || 0;
const total = totalPages?.value || 1;
return total === 1 || currentPage.value === total || count === 0;
});

// Method to change page with bounds checking
const changePage = change => {
const total = totalPages?.value || 1;
const newPage = clamp(currentPage.value + change, 1, total);
currentPage.value = newPage;
};

// Method to go to specific page
const goToPage = pageNumber => {
const total = totalPages?.value || 1;
currentPage.value = clamp(pageNumber, 1, total);
};

// Method to reset to first page
const resetToFirstPage = () => {
currentPage.value = 1;
};

return {
// State
currentPage,
itemsPerPage,

// Computed properties for display
visibleStartRange,
visibleEndRange,
previousButtonDisabled,
nextButtonDisabled,

// Methods
changePage,
goToPage,
resetToFirstPage,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ref, computed } from 'vue';
import { useRoute, useRouter } from 'vue-router/composables';
import pickBy from 'lodash/pickBy';
import debounce from 'lodash/debounce';

/**
* Composable for managing search functionality in the Users table
* Handles search term state and URL query parameter synchronization
*/
export default function useUsersTableSearch() {
const route = useRoute();
const router = useRouter();
const filterTextboxRef = ref(null);

// Create debounced function for updating search in URL
const updateSearchInUrl = value => {
if (value === '') {
value = null;
}
router.push({
...route,
query: pickBy({
...route.query,
search: value,
page: null, // Reset to first page when searching
}),
});
};

const debouncedSearchTerm = debounce(updateSearchInUrl, 300);

// Computed property for search term with getter/setter
const searchTerm = computed({
get() {
return route.query.search || '';
},
set(value) {
debouncedSearchTerm(value);
},
});

// Method to focus the search textbox
const focusSearchBox = () => {
if (filterTextboxRef.value?.focus) {
filterTextboxRef.value.focus();
}
};

// Method to clear search
const clearSearch = () => {
searchTerm.value = '';
};

return {
searchTerm,
filterTextboxRef,
focusSearchBox,
clearSearch,
};
}
43 changes: 31 additions & 12 deletions kolibri/plugins/facility/assets/src/views/ClassEnrollForm.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
<template>

<form>
<PaginatedListContainerWithBackend
v-model="currentPage"
:items="facilityUsers"
:itemsPerPage="itemsPerPage"
:totalPageNumber="totalPages"
:numFilteredItems="totalLearners"
>
<template #filter>
<FilterTextbox
v-model="search"
:placeholder="coreString('searchForUser')"
/>
<PaginatedListContainerWithBackend>
<template #topActions>
<div class="flex-row">
<FilterTextbox
v-model="search"
:placeholder="coreString('searchForUser')"
/>
<PaginationActions
v-model="currentPage"
:itemsPerPage="itemsPerPage"
:totalPageNumber="totalPages"
:numFilteredItems="totalLearners"
/>
</div>
</template>
<template>
<UserTable
Expand All @@ -24,6 +26,14 @@
/>
</template>
</PaginatedListContainerWithBackend>
<PaginationActions
v-if="totalPages > 1"
v-model="currentPage"
style="text-align: right"
:itemsPerPage="itemsPerPage"
:totalPageNumber="totalPages"
:numFilteredItems="totalLearners"
/>
<SelectionBottomBar
:count="selectedUsers.length"
:disabled="disabled || selectedUsers.length === 0"
Expand All @@ -44,13 +54,15 @@
import FilterTextbox from 'kolibri/components/FilterTextbox';
import UserTable from 'kolibri-common/components/UserTable';
import PaginatedListContainerWithBackend from 'kolibri-common/components/PaginatedListContainerWithBackend';
import PaginationActions from 'kolibri-common/components/PaginationActions';
import SelectionBottomBar from './SelectionBottomBar';

export default {
name: 'ClassEnrollForm',
components: {
SelectionBottomBar,
PaginatedListContainerWithBackend,
PaginationActions,
UserTable,
FilterTextbox,
},
Expand Down Expand Up @@ -168,4 +180,11 @@
justify-content: flex-end;
}

.flex-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1em 0;
}

</style>
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
:title="title"
:appearanceOverrides="appearanceOverrides"
>
<template #default="{ pageContentHeight }">
<slot :pageContentHeight="pageContentHeight"></slot>
<template #default="{ pageContentHeight, appBarHeight }">
<slot
:pageContentHeight="pageContentHeight"
:appBarHeight="appBarHeight"
></slot>
</template>
</AppBarPage>

Expand Down
Loading