diff --git a/src/components/AdminTeamFolders.vue b/src/components/AdminTeamFolders.vue index f0590302e..2e842cff9 100644 --- a/src/components/AdminTeamFolders.vue +++ b/src/components/AdminTeamFolders.vue @@ -96,6 +96,7 @@ const updatingQuotaTeamIds = ref>(new Set()) const loadingTeamFolders = ref(true) const sortKey = ref('teamName') const sortAscending = ref(true) +const teamSearch = ref('') const selectedTeam = ref(null) const folderName = ref('') const assigningFolder = ref(false) @@ -120,17 +121,20 @@ const quotaRows = computed(() => [...rows.value, ...groupRows.value] const sortedTeamFolders = computed(() => { const direction = sortAscending.value ? 1 : -1 - return [...teamFolders.value].sort((a, b) => { - const left = getSortValue(a, sortKey.value) - const right = getSortValue(b, sortKey.value) - if (left < right) { - return -1 * direction - } - if (left > right) { - return direction - } - return 0 - }) + const query = teamSearch.value.trim().toLocaleLowerCase() + return teamFolders.value + .filter((teamFolder) => teamFolder.teamName.toLocaleLowerCase().includes(query)) + .sort((a, b) => { + const left = getSortValue(a, sortKey.value) + const right = getSortValue(b, sortKey.value) + if (left < right) { + return -1 * direction + } + if (left > right) { + return direction + } + return 0 + }) }) /** @@ -528,33 +532,41 @@ onMounted(() => Promise.all([loadTeamFolders(), loadGroupQuotas()]))

{{ t('circles', 'Configure default storage quotas and manage team folders.') }}

-
- - +
+
+ + +
+
Promise.all([loadTeamFolders(), loadGroupQuotas()])) - {{ t('circles', 'No team folders found.') }} + {{ teamSearch.trim() ? t('circles', 'No teams match your search.') : t('circles', 'No teams found.') }} @@ -806,13 +818,21 @@ onMounted(() => Promise.all([loadTeamFolders(), loadGroupQuotas()])) color: var(--color-text-maxcontrast); } -.team-folders__tabs { +.team-folders__tabbar { display: flex; - gap: 24px; + flex-wrap: wrap; + align-items: flex-end; + justify-content: space-between; + gap: 8px 16px; margin-bottom: 24px; border-bottom: 1px solid var(--color-border); } +.team-folders__tabs { + display: flex; + gap: 24px; +} + .team-folders__tab { position: relative; padding: 10px 4px 9px; @@ -977,6 +997,11 @@ onMounted(() => Promise.all([loadTeamFolders(), loadGroupQuotas()])) font-weight: 600; } +.team-folders__search { + flex: 0 1 320px; + margin-bottom: 4px; +} + .team-folders__scroll { overflow-x: auto; } @@ -1079,4 +1104,10 @@ onMounted(() => Promise.all([loadTeamFolders(), loadGroupQuotas()])) min-width: 640px; } } + +@media (max-width: 600px) { + .team-folders__search { + flex-basis: 100%; + } +} diff --git a/tests/playwright/e2e/admin-settings.spec.ts b/tests/playwright/e2e/admin-settings.spec.ts index e9e18e589..65ed15dfe 100644 --- a/tests/playwright/e2e/admin-settings.spec.ts +++ b/tests/playwright/e2e/admin-settings.spec.ts @@ -16,4 +16,32 @@ test.describe('Admin settings', () => { await expect(page.getByRole('heading', { name: 'Federated Teams' })).toBeVisible() }) + + test('filters teams by name', async ({ page }) => { + const matchingTeam = 'Search match' + const otherTeam = 'Search other' + await page.route('**/ocs/v2.php/apps/circles/admin/teamfolders', (route) => route.fulfill({ + contentType: 'application/json', + body: JSON.stringify({ + ocs: { + data: [ + { teamId: 'matching-team', teamName: matchingTeam, defaultQuota: null, folder: null }, + { teamId: 'other-team', teamName: otherTeam, defaultQuota: null, folder: null }, + ], + }, + }), + })) + + await page.goto('settings/admin/teams', { waitUntil: 'networkidle' }) + const search = page.getByRole('searchbox', { name: 'Search team by name' }) + await expect(page.getByRole('cell', { name: matchingTeam })).toBeVisible() + await expect(page.getByRole('cell', { name: otherTeam })).toBeVisible() + + await search.fill('match') + await expect(page.getByRole('cell', { name: matchingTeam })).toBeVisible() + await expect(page.getByRole('cell', { name: otherTeam })).not.toBeVisible() + + await search.fill('no matching team') + await expect(page.getByText('No teams match your search.')).toBeVisible() + }) })