Admin Tools: fix for 6.3.0

This commit is contained in:
yu-i-i
2026-09-27 18:11:27 +02:00
parent 4552eef3f6
commit 404623dc25
16 changed files with 329 additions and 325 deletions
@@ -1,10 +1,10 @@
import { useTranslation } from 'react-i18next'
import {
Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownItem,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import DownloadProjectButton from '../table/cells/action-buttons/download-project-button'
import TrashProjectButton from '../table/cells/action-buttons/trash-project-button'
import UntrashProjectButton from '../table/cells/action-buttons/untrash-project-button'
@@ -16,128 +16,122 @@ import { Project } from '../../../../../types/project/api'
import MaterialIcon from '@/shared/components/material-icon'
import OLSpinner from '@/shared/components/ol/ol-spinner'
type ActionDropdownProps = {
type ActionsDropdownProps = {
project: Project
}
function ActionsDropdown({ project }: ActionDropdownProps) {
function ActionsDropdown({ project }: ActionsDropdownProps) {
const { t } = useTranslation()
return (
<Dropdown align="end">
<DropdownToggle
<OLDropdown align="end">
<OLDropdownToggle
id={`project-actions-dropdown-toggle-btn-${project.id}`}
bsPrefix="dropdown-table-button-toggle"
>
<MaterialIcon type="more_vert" accessibilityLabel={t('actions')} />
</DropdownToggle>
<DropdownMenu flip={false}>
</OLDropdownToggle>
<OLDropdownMenu flip={false}>
<DownloadProjectButton project={project}>
{(text, downloadProject) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={downloadProject}
leadingIcon="download"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</DownloadProjectButton>
<TransferProjectButton project={project}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="swap_horiz"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</TransferProjectButton>
<TrashProjectButton project={project}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="delete"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</TrashProjectButton>
<UntrashProjectButton project={project}>
{(text, untrashProject) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={untrashProject}
leadingIcon="restore_page"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</UntrashProjectButton>
<DeleteProjectButton project={project}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="block"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</DeleteProjectButton>
<RestoreProjectButton project={project}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="restore"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</RestoreProjectButton>
<PurgeProjectButton project={project}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="delete_forever"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</PurgeProjectButton>
</DropdownMenu>
</Dropdown>
</OLDropdownMenu>
</OLDropdown>
)
}
@@ -5,12 +5,12 @@ import {
useProjectListContext,
} from '../../context/project-list-context'
import {
Dropdown,
DropdownHeader,
DropdownItem,
DropdownMenu,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownHeader,
OLDropdownItem,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import BackToUserList from '../back-to-user-list'
import ProjectsFilterMenu from '../projects-filter-menu'
@@ -30,7 +30,7 @@ export function Item({ filter, text, onClick }: ItemProps) {
return (
<ProjectsFilterMenu filter={filter}>
{isActive => (
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleClick}
@@ -38,7 +38,7 @@ export function Item({ filter, text, onClick }: ItemProps) {
active={isActive}
>
{text}
</DropdownItem>
</OLDropdownItem>
)}
</ProjectsFilterMenu>
)
@@ -60,8 +60,8 @@ function ProjectsDropdown() {
}, [filter, t])
return (
<Dropdown>
<DropdownToggle
<OLDropdown>
<OLDropdownToggle
id="projects-types-dropdown-toggle-btn"
className="ps-0 mb-0 btn-transparent h4"
size="lg"
@@ -70,8 +70,8 @@ function ProjectsDropdown() {
<span className="text-truncate" aria-hidden>
{title}
</span>
</DropdownToggle>
<DropdownMenu flip={false}>
</OLDropdownToggle>
<OLDropdownMenu flip={false}>
<li role="none">
<Item filter="owned" text={t('all_projects')} />
</li>
@@ -84,8 +84,8 @@ function ProjectsDropdown() {
<li role="none">
<Item filter="deleted" text={t('deleted_projects')} />
</li>
</DropdownMenu>
</Dropdown>
</OLDropdownMenu>
</OLDropdown>
)
}
@@ -5,23 +5,23 @@ import withContent, { SortBtnProps } from '../sort/with-content'
import { useProjectListContext } from '../../context/project-list-context'
import { Sort } from '../../../../../types/project/api'
import {
Dropdown,
DropdownHeader,
DropdownItem,
DropdownMenu,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownHeader,
OLDropdownItem,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
function Item({ onClick, text, iconType }: SortBtnProps) {
return (
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={onClick}
trailingIcon={iconType}
>
{text}
</DropdownItem>
</OLDropdownItem>
)
}
@@ -48,8 +48,8 @@ function SortByDropdown() {
}, [sort.by])
return (
<Dropdown className="projects-sort-dropdown" align="end">
<DropdownToggle
<OLDropdown className="projects-sort-dropdown" align="end">
<OLDropdownToggle
id="projects-sort-dropdown"
className="pe-0 mb-0 btn-transparent"
size="sm"
@@ -58,11 +58,11 @@ function SortByDropdown() {
<span className="text-truncate" aria-hidden>
{title}
</span>
</DropdownToggle>
<DropdownMenu flip={false}>
<DropdownHeader className="text-uppercase">
</OLDropdownToggle>
<OLDropdownMenu flip={false}>
<OLDropdownHeader className="text-uppercase">
{t('sort_by')}:
</DropdownHeader>
</OLDropdownHeader>
<ItemWithContent
column="title"
text={t('title')}
@@ -90,8 +90,8 @@ function SortByDropdown() {
onClick={() => handleClick('deletedAt')}
/>
)}
</DropdownMenu>
</Dropdown>
</OLDropdownMenu>
</OLDropdown>
)
}
@@ -8,7 +8,7 @@ import ProjectListTitle from './title/project-list-title'
import LoadMore from './load-more'
import OLCol from '@/shared/components/ol/ol-col'
import OLRow from '@/shared/components/ol/ol-row'
import { TableContainer } from '@/shared/components/table'
import { TableContainer } from '@/shared/components/ol/ol-table'
import DashApiError from '@/features/project-list/components/dash-api-error'
import getMeta from '@/utils/meta'
import DefaultNavbar from '@/shared/components/navbar/default-navbar'
@@ -1,10 +1,10 @@
import { useTranslation } from 'react-i18next'
import {
Dropdown,
DropdownMenu,
DropdownItem,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownMenu,
OLDropdownItem,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import { useProjectListContext } from '../context/project-list-context'
const OPTIONS = [20, 40, 80]
@@ -31,28 +31,28 @@ export default function ProjectListSummary() {
<span className="mx-2">·</span>
<span className="d-inline-flex gap-1">
<Dropdown>
<OLDropdown>
<DropdownToggle
<OLDropdownToggle
as="span"
className="entries-per-page-toggle"
>
{projectsPerPage}
</DropdownToggle>
</OLDropdownToggle>
<DropdownMenu>
<OLDropdownMenu>
{OPTIONS.map((value) => (
<DropdownItem
<OLDropdownItem
key={value}
active={value === projectsPerPage}
onClick={() => setProjectsPerPage(value)}
>
{value}
</DropdownItem>
</OLDropdownItem>
))}
</DropdownMenu>
</OLDropdownMenu>
</Dropdown>
</OLDropdown>
<span>{t('per_page')}</span>
</span>
</div>
@@ -3,7 +3,7 @@ import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { useCombobox } from 'downshift'
import MaterialIcon from '@/shared/components/material-icon'
import { DropdownItem } from '@/shared/components/dropdown/dropdown-menu'
import { OLDropdownItem } from '@/shared/components/ol/ol-dropdown-menu'
import OLFormLabel from '@/shared/components/ol/ol-form-label'
import OLSpinner from '@/shared/components/ol/ol-spinner'
import { UserRef } from '../../../../types/project/api'
@@ -173,7 +173,7 @@ const SelectOwnerForm = React.forwardRef<
key={item.id}
{...getItemProps({ item, index })}
>
<DropdownItem
<OLDropdownItem
as="span"
role={undefined}
leadingIcon="person"
@@ -182,7 +182,7 @@ const SelectOwnerForm = React.forwardRef<
})}
>
{getDisplayName(item)}
</DropdownItem>
</OLDropdownItem>
</li>
))}
</ul>
@@ -1,7 +1,11 @@
import classnames from 'classnames'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Dropdown } from 'react-bootstrap'
import {
OLDropdown,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import { User as UserIcon } from '@phosphor-icons/react'
import { usePersistedResize } from '@/shared/hooks/use-resize'
import getMeta from '@/utils/meta'
@@ -13,6 +17,7 @@ import { useUserIdentityContext } from '../../../user-list/context/user-identity
import { useProjectListContext } from '../../context/project-list-context'
import { useScrolled } from '@/features/project-list/components/sidebar/use-scroll'
import { useSendProjectListMB } from '@/features/project-list/components/project-list-events'
import { SidebarLowerSection } from '@/shared/components/sidebar/sidebar-lower-section'
function SidebarDsNav() {
const { t } = useTranslation()
@@ -79,62 +84,7 @@ function SidebarDsNav() {
scrolledUp && 'show-shadow'
)}
>
<nav
className="d-flex flex-row gap-3 mb-2"
aria-label={t('account_help')}
>
{sessionUser && (
<>
<Dropdown
className="ds-nav-icon-dropdown"
onToggle={show => {
setShowAccountDropdown(show)
if (show) {
sendMB('menu-expand', {
item: 'account',
location: 'sidebar',
})
}
}}
role="menu"
>
<Dropdown.Toggle role="menuitem" aria-label={t('Account')}>
<OLTooltip
description={t('Account')}
id="open-account"
overlayProps={{
placement: 'top',
}}
hidden={showAccountDropdown}
>
<div>
<UserIcon size={24} />
</div>
</OLTooltip>
</Dropdown.Toggle>
<Dropdown.Menu
as="ul"
role="menu"
align="end"
popperConfig={{
modifiers: [
{ name: 'offset', options: { offset: [-50, 5] } },
],
}}
>
<AccountMenuItems
sessionUser={sessionUser}
showSubscriptionLink={false}
showThemeToggle={true}
/>
</Dropdown.Menu>
</Dropdown>
</>
)}
</nav>
<div className="ds-nav-ds-name" translate="no">
<span>Extended CE</span>
</div>
<SidebarLowerSection showThemeToggle />
</div>
<div
{...getHandleProps({
@@ -1,11 +1,11 @@
import { useTranslation } from 'react-i18next'
import getMeta from '@/utils/meta'
import {
Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownItem,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import MaterialIcon from '@/shared/components/material-icon'
import OLSpinner from '@/shared/components/ol/ol-spinner'
import FlagUserButton from '../table/cells/action-buttons/flag-user-button'
@@ -22,27 +22,27 @@ const flagActions = [
{ action: 'resume', icon: 'resume', unfilled: false },
]
type ActionDropdownProps = {
type ActionsDropdownProps = {
user: User
}
function ActionsDropdown({ user }: ActionDropdownProps) {
function ActionsDropdown({ user }: ActionsDropdownProps) {
const { t } = useTranslation()
const isSelf = getMeta('ol-user_id') === user.id
return (
<Dropdown align="end">
<DropdownToggle
<OLDropdown align="end">
<OLDropdownToggle
id={`user-actions-dropdown-toggle-btn-${user.id}`}
bsPrefix="dropdown-table-button-toggle"
>
<MaterialIcon type="more_vert" accessibilityLabel={t('actions')} />
</DropdownToggle>
<DropdownMenu flip={false}>
</OLDropdownToggle>
<OLDropdownMenu flip={false}>
<ShowUserInfoButton user={user}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
@@ -50,14 +50,14 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
unfilled={true}
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</ShowUserInfoButton>
<UpdateUserButton user={user}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
@@ -65,7 +65,7 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
unfilled={true}
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</UpdateUserButton>
@@ -75,7 +75,7 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
<FlagUserButton key={action} user={user} action={action}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
@@ -83,7 +83,7 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
unfilled={unfilled}
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</FlagUserButton>
@@ -92,7 +92,7 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
<DeleteUserButton user={user}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
@@ -100,7 +100,7 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
unfilled
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</DeleteUserButton>
@@ -108,14 +108,14 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
<RestoreUserButton user={user}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="restore"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</RestoreUserButton>
@@ -123,14 +123,14 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
<PurgeUserButton user={user}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
leadingIcon="delete_forever"
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</PurgeUserButton>
@@ -138,7 +138,7 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
<SendRegEmailButton user={user}>
{(text, handleOpenModal) => (
<li role="none">
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleOpenModal}
@@ -146,15 +146,15 @@ function ActionsDropdown({ user }: ActionDropdownProps) {
unfilled
>
{text}
</DropdownItem>
</OLDropdownItem>
</li>
)}
</SendRegEmailButton>
)}
</>
)}
</DropdownMenu>
</Dropdown>
</OLDropdownMenu>
</OLDropdown>
)
}
@@ -1,12 +1,12 @@
import { useState, useEffect, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import {
Dropdown,
DropdownHeader,
DropdownItem,
DropdownMenu,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownHeader,
OLDropdownItem,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import { useUserListContext } from '../../context/user-list-context'
import useSort from '../../hooks/use-sort'
import withContent, { SortBtnProps } from '../sort/with-content'
@@ -14,14 +14,14 @@ import { Sort } from '../../../../../types/user/api'
function Item({ onClick, text, iconType }: SortBtnProps) {
return (
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={onClick}
trailingIcon={iconType}
>
{text}
</DropdownItem>
</OLDropdownItem>
)
}
@@ -50,8 +50,8 @@ function SortByDropdown() {
}, [sort.by])
return (
<Dropdown className="projects-sort-dropdown" align="end">
<DropdownToggle
<OLDropdown className="projects-sort-dropdown" align="end">
<OLDropdownToggle
id="projects-sort-dropdown"
className="pe-0 mb-0 btn-transparent"
size="sm"
@@ -60,11 +60,11 @@ function SortByDropdown() {
<span className="text-truncate" aria-hidden>
{title}
</span>
</DropdownToggle>
<DropdownMenu flip={false}>
<DropdownHeader className="text-uppercase">
</OLDropdownToggle>
<OLDropdownMenu flip={false}>
<OLDropdownHeader className="text-uppercase">
{t('sort_by')}:
</DropdownHeader>
</OLDropdownHeader>
<ItemWithContent
column="name"
text={t('name')}
@@ -99,8 +99,8 @@ function SortByDropdown() {
sort={sort}
onClick={() => handleClick('lastActive')}
/>
</DropdownMenu>
</Dropdown>
</OLDropdownMenu>
</OLDropdown>
)
}
@@ -5,11 +5,11 @@ import {
useUserListContext,
} from '../../context/user-list-context'
import {
Dropdown,
DropdownItem,
DropdownMenu,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownItem,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import UsersFilterMenu from '../users-filter-menu'
type ItemProps = {
@@ -28,7 +28,7 @@ export function Item({ filter, text, onClick }: ItemProps) {
return (
<UsersFilterMenu filter={filter}>
{isActive => (
<DropdownItem
<OLDropdownItem
as="button"
tabIndex={-1}
onClick={handleClick}
@@ -36,7 +36,7 @@ export function Item({ filter, text, onClick }: ItemProps) {
active={isActive}
>
{text}
</DropdownItem>
</OLDropdownItem>
)}
</UsersFilterMenu>
)
@@ -49,8 +49,8 @@ function UsersDropdown() {
const title = filterTranslations.get(filter) ?? t('user_category_all')
return (
<Dropdown>
<DropdownToggle
<OLDropdown>
<OLDropdownToggle
id="users-types-dropdown-toggle-btn"
className="ps-0 mb-0 btn-transparent h3"
size="lg"
@@ -59,15 +59,15 @@ function UsersDropdown() {
<span className="text-truncate" aria-hidden>
{title}
</span>
</DropdownToggle>
<DropdownMenu flip={false}>
</OLDropdownToggle>
<OLDropdownMenu flip={false}>
{[...filterTranslations.entries()].map(([key, text]) => (
<li role="none" key={key}>
<Item filter={key} text={text} />
</li>
))}
</DropdownMenu>
</Dropdown>
</OLDropdownMenu>
</OLDropdown>
)
}
@@ -1,7 +1,11 @@
import classnames from 'classnames'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Dropdown } from 'react-bootstrap'
import {
OLDropdown,
OLDropdownMenu,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import { User as UserIcon } from '@phosphor-icons/react'
import { usePersistedResize } from '@/shared/hooks/use-resize'
import getMeta from '@/utils/meta'
@@ -11,6 +15,7 @@ import SidebarFilters from './sidebar-filters'
import CreateAccountButton from '../create-account-button'
import { useSendUserListMB } from '../user-list-events'
import { useScrolled } from '@/features/project-list/components/sidebar/use-scroll'
import { SidebarLowerSection } from '@/shared/components/sidebar/sidebar-lower-section'
function SidebarDsNav() {
const { t } = useTranslation()
@@ -52,62 +57,7 @@ function SidebarDsNav() {
scrolledUp && 'show-shadow'
)}
>
<nav
className="d-flex flex-row gap-3 mb-2"
aria-label={t('account_help')}
>
{sessionUser && (
<>
<Dropdown
className="ds-nav-icon-dropdown"
onToggle={show => {
setShowAccountDropdown(show)
if (show) {
sendMB('menu-expand', {
item: 'account',
location: 'sidebar',
})
}
}}
role="menu"
>
<Dropdown.Toggle role="menuitem" aria-label={t('Account')}>
<OLTooltip
description={t('Account')}
id="open-account"
overlayProps={{
placement: 'top',
}}
hidden={showAccountDropdown}
>
<div>
<UserIcon size={24} />
</div>
</OLTooltip>
</Dropdown.Toggle>
<Dropdown.Menu
as="ul"
role="menu"
align="end"
popperConfig={{
modifiers: [
{ name: 'offset', options: { offset: [-50, 5] } },
],
}}
>
<AccountMenuItems
sessionUser={sessionUser}
showSubscriptionLink={false}
showThemeToggle={true}
/>
</Dropdown.Menu>
</Dropdown>
</>
)}
</nav>
<div className="ds-nav-ds-name" translate="no">
<span>Extended CE</span>
</div>
<SidebarLowerSection showThemeToggle />
</div>
<div
{...getHandleProps({
@@ -19,8 +19,10 @@ export default function ActionsCell({ user }: ActionsCellProps) {
<span style={isSelf ? { visibility: 'hidden' } : undefined} >
<SendRegEmailButtonTooltip user={user} />
</span>
<span>
<ShowUserInfoButtonTooltip user={user} />
<UpdateUserButtonTooltip user={user} />
</span>
<span style={isSelf ? { visibility: 'hidden' } : undefined} >
<FlagUserButtonTooltip user={user} flag="suspended" />
</span>
@@ -10,7 +10,7 @@ import UserListTitle from './title/user-list-title'
import CountUsers from './count-users'
import OLCol from '@/shared/components/ol/ol-col'
import OLRow from '@/shared/components/ol/ol-row'
import { TableContainer } from '@/shared/components/table'
import { TableContainer } from '@/shared/components/ol/ol-table'
import DashApiError from '@/features/project-list/components/dash-api-error'
import getMeta from '@/utils/meta'
import DefaultNavbar from '@/shared/components/navbar/default-navbar'
@@ -1,10 +1,10 @@
import { useTranslation } from 'react-i18next'
import {
Dropdown,
DropdownMenu,
DropdownItem,
DropdownToggle,
} from '@/shared/components/dropdown/dropdown-menu'
OLDropdown,
OLDropdownMenu,
OLDropdownItem,
OLDropdownToggle,
} from '@/shared/components/ol/ol-dropdown-menu'
import { useUserListContext } from '../context/user-list-context'
const OPTIONS = [20, 40, 80]
@@ -30,28 +30,28 @@ export default function UserListSummary() {
<span className="mx-2">·</span>
<span className="d-inline-flex gap-1">
<Dropdown>
<OLDropdown>
<DropdownToggle
<OLDropdownToggle
as="span"
className="entries-per-page-toggle"
>
{usersPerPage}
</DropdownToggle>
</OLDropdownToggle>
<DropdownMenu>
<OLDropdownMenu>
{OPTIONS.map((value) => (
<DropdownItem
<OLDropdownItem
key={value}
active={value === usersPerPage}
onClick={() => setUsersPerPage(value)}
>
{value}
</DropdownItem>
</OLDropdownItem>
))}
</DropdownMenu>
</OLDropdownMenu>
</Dropdown>
</OLDropdown>
<span>{t('per_page')}</span>
</span>
@@ -2,6 +2,7 @@
--ds-nav-active-bg: var(--bg-accent-03);
--ds-nav-active-color: var(--green-60);
--theme-toggle-selected-background: var(--green-20);
--ds-nav-content-bg-primary: var(--bg-light-primary);
--ds-nav-content-bg-secondary: var(--bg-light-secondary);
--table-icon-bg-hover: 27 34 44;
--themed-dashboard-popover-bg: var(--bg-dark-primary);
@@ -15,6 +16,7 @@
--ds-nav-active-bg: var(--green-70);
--ds-nav-active-color: var(--green-10);
--theme-toggle-selected-background: var(--green-70);
--ds-nav-content-bg-primary: var(--bg-dark-primary);
--ds-nav-content-bg-secondary: var(--bg-dark-secondary);
--table-icon-bg-hover: 255 255 255;
--themed-dashboard-popover-bg: var(--bg-light-primary);
@@ -51,7 +53,8 @@ body {
.navbar-header .navbar-logo {
@include media-breakpoint-up(md) {
position: relative;
top: var(--spacing-05);
top: calc(var(--spacing-05) * 2);
left: var(--spacing-05);
}
}
@@ -103,6 +106,38 @@ body {
}
}
&.ds-nav-hides-top-navbar {
// The sidebar shows the logo and account/help menus from md upwards, so
// the top navbar is only needed on mobile.
.navbar-default {
@include media-breakpoint-up(md) {
display: none;
}
}
.project-list-wrapper
.project-ds-nav-content-and-messages
.project-ds-nav-content {
@include media-breakpoint-up(md) {
border-top-left-radius: 0;
border-top: none;
}
}
.project-list-header-row {
@include media-breakpoint-up(md) {
margin-top: var(--spacing-08);
}
// On mobile the trash page has no heading or plan widget in this row
// (both are desktop-only), so collapse it to avoid an empty gap above
// the navigation dropdown.
@include media-breakpoint-down(md) {
display: none;
}
}
}
.navbar-nav > li > .dropdown-toggle::after {
display: none;
}
@@ -121,7 +156,7 @@ body {
max-width: 320px;
min-width: 200px;
margin-top: var(--spacing-03);
padding: var(--spacing-08) 0 0 0;
padding: calc(var(--spacing-08) - 1px) 0 0;
.create-account-button-wrapper {
padding: 0 var(--spacing-08) var(--spacing-05) var(--spacing-05);
@@ -143,12 +178,103 @@ body {
flex: 1 1 auto;
overflow: auto;
margin: 0 var(--spacing-02) 0 0;
padding: var(--spacing-05) var(--spacing-07) var(--spacing-05)
var(--spacing-05);
padding: 0 var(--spacing-05) var(--spacing-05);
}
ul.user-list-filters {
margin-top: var(--spacing-05);
.sidebar-filter-button {
display: flex;
align-items: center;
padding-left: calc(var(--spacing-05) + 20px + var(--spacing-05));
}
.sidebar-filter-button-with-icon {
// Only the items with an icon are 44px tall: 20px of content between
// 12px paddings. The rest of the filters stay at 40px.
line-height: var(--line-height-02);
padding: var(--spacing-05);
// Without this the icon is an inline box sitting on the text
// baseline, which leaves descender space below it and stops
// align-items from centring it against the label.
.icon {
display: flex;
align-items: center;
}
svg {
margin-right: var(--spacing-05);
}
}
.dropdown-header {
padding-left: calc(var(--spacing-06) + 20px + var(--spacing-05));
}
> li.tag button.tag-name {
padding-left: calc(var(--spacing-06) + 20px + var(--spacing-05));
}
}
.ds-nav-page-switcher-logo {
padding: 0 var(--spacing-08) var(--spacing-04);
img {
width: 130px;
height: auto;
}
}
.ds-nav-page-switcher-item {
display: flex;
align-items: center;
width: 100%;
gap: var(--spacing-05);
// 20px of text between 12px paddings makes the item 44px tall.
line-height: var(--line-height-02);
padding: var(--spacing-05);
border: none;
border-radius: var(--border-radius-medium);
background: none;
color: var(--ds-nav-color);
font-size: var(--font-size-03);
text-align: left;
text-decoration: none;
.ds-nav-page-switcher-item-label {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&:hover {
background-color: var(--ds-nav-hover-bg);
color: var(--ds-nav-color);
text-decoration: none;
}
&.active {
background-color: var(--ds-nav-active-bg);
color: var(--ds-nav-active-color);
font-weight: bold;
}
}
.ds-nav-dropdown-list {
display: flex;
flex-direction: column;
gap: var(--spacing-02);
padding: 0;
margin: 0;
}
.ds-nav-sidebar-lower {
padding: var(--spacing-05) var(--spacing-08) 0 var(--spacing-05);
padding: var(--spacing-05) var(--spacing-05) 0 var(--spacing-05);
border-top: solid 1px transparent;
&.show-shadow {
@@ -189,47 +315,23 @@ body {
font-weight: bold;
}
}
.dropdown-header {
font-weight: bold;
color: var(--ds-nav-color);
}
> li.tag {
button.tag-name {
padding-right: var(--spacing-08) !important;
}
}
.tag-menu {
button.dropdown-toggle {
border-radius: var(--border-radius-full);
border: none;
color: var(--ds-nav-color);
height: 20px;
width: 20px;
padding: 0;
&::after {
display: none;
}
&:hover,
&:active,
&[aria-expanded='true'] {
background-color: var(--neutral-20);
}
}
}
}
.user-ds-nav-main {
display: flex;
flex-direction: column;
min-height: 100%;
padding: var(--spacing-08) var(--spacing-06);
@include media-breakpoint-up(md) {
padding: var(--spacing-08);
}
main {
display: flex;
flex-direction: column;
flex: 1;
}
}
.user-dash-table {
@@ -292,14 +394,13 @@ body {
}
}
.ds-nav-icon-dropdown {
.ds-nav-dropdown {
.dropdown-toggle {
color: var(--ds-nav-color);
width: 100%;
border: none;
background: none;
height: 44px;
width: 44px;
padding: 0;
overflow: hidden;
font-weight: normal;
text-align: left;
&:hover {
background-color: var(--ds-nav-hover-bg);
@@ -313,17 +414,6 @@ body {
&::after {
display: none;
}
> div {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.material-symbols {
vertical-align: middle;
}
}
}
@@ -1,3 +1,21 @@
:root {
--user-list-upload-modal-hint-color: var(--neutral-60);
}
@include theme('default') {
.modal-themed {
--user-list-upload-modal-hint-color: var(--content-secondary-dark);
}
}
.user-list-modal .form-label {
color: var(--content-secondary-themed);
}
.user-list-action-modal {
@include themed-links;
}
.user-list-empty-col {
display: flex;
height: 100%;
@@ -48,7 +66,7 @@
min-height: 36px;
.user-list-title {
@include heading-sm;
@include heading-md;
color: var(--content-secondary-themed);
font-weight: bold;
@@ -463,15 +481,15 @@ ul.user-list-filters {
}
.dash-cell-date-signup {
width: 17%;
width: 16%;
}
.dash-cell-date-active {
width: 17%;
width: 16%;
}
.dash-cell-actions {
width: 12%;
width: 14%;
}
}
@@ -514,7 +532,7 @@ ul.user-list-filters {
.uppy-Dashboard-AddFiles-title {
display: flex;
flex-direction: column;
color: var(--neutral-60);
color: var(--user-list-upload-modal-hint-color);
white-space: pre-line;
@include body-base;