diff --git a/ui/src/components/template/UserDropdown.tsx b/ui/src/components/template/UserDropdown.tsx
index 06541ff..18c6aa4 100644
--- a/ui/src/components/template/UserDropdown.tsx
+++ b/ui/src/components/template/UserDropdown.tsx
@@ -6,22 +6,31 @@ import withHeaderItem from '@/utils/hoc/withHeaderItem'
import useAuth from '@/utils/hooks/useAuth'
import { useLocalization } from '@/utils/hooks/useLocalization'
import classNames from 'classnames'
+import type { ReactElement } from 'react'
import { Link } from 'react-router-dom'
import { Avatar } from '../ui'
-import { FcEngineering, FcNext, FcNfcSign, FcVoicePresentation } from 'react-icons/fc'
+import {
+ FcEngineering,
+ FcNext,
+ FcNfcSign,
+ FcSynchronize,
+ FcVoicePresentation,
+} from 'react-icons/fc'
+import { useManualUpdateCheck } from '@/views/version/ChangeLog'
type DropdownList = {
label: string
path: string
- icon: JSX.Element
+ icon: ReactElement
}
-const _UserDropdown = ({ className }: CommonProps) => {
+const UserDropdownBase = ({ className }: CommonProps) => {
const { setPanelExpand } = useStoreActions((actions) => actions.theme)
const { userName, name, email, avatar } = useStoreState((state) => state.auth.user)
const tenant = useStoreState((state) => state.abpConfig.config?.currentTenant)
const { translate } = useLocalization()
const { signOut } = useAuth()
+ const { isCheckingUpdate, checkForUpdate } = useManualUpdateCheck()
const displayName = name || userName
const tenantName = tenant?.name
@@ -113,6 +122,23 @@ const _UserDropdown = ({ className }: CommonProps) => {
)
})}
+
+
+
+
+
+
+ {isCheckingUpdate
+ ? translate('::App.CheckUpdate')
+ : translate('::App.CheckForUpdates')}
+
+
+
+
{/* */}
@@ -124,6 +150,6 @@ const _UserDropdown = ({ className }: CommonProps) => {
)
}
-const UserDropdown = withHeaderItem(_UserDropdown)
+const UserDropdown = withHeaderItem(UserDropdownBase)
export default UserDropdown
diff --git a/ui/src/components/ui/StatusIcon/StatusIcon.tsx b/ui/src/components/ui/StatusIcon/StatusIcon.tsx
index e843dc5..d3265a4 100644
--- a/ui/src/components/ui/StatusIcon/StatusIcon.tsx
+++ b/ui/src/components/ui/StatusIcon/StatusIcon.tsx
@@ -1,10 +1,10 @@
import { FaCheckCircle, FaInfoCircle, FaExclamation, FaTimesCircle } from 'react-icons/fa';
import type { TypeAttributes, CommonProps } from '../@types/common'
-import type { ReactNode } from 'react'
+import type { ReactElement, ReactNode } from 'react'
export interface StatusIconProps extends CommonProps {
type: TypeAttributes.Status
- custom?: ReactNode | JSX.Element
+ custom?: ReactNode | ReactElement
iconColor?: string
}
@@ -12,7 +12,7 @@ const ICONS: Record<
TypeAttributes.Status,
{
color: string
- icon: JSX.Element
+ icon: ReactElement
}
> = {
success: {
diff --git a/ui/src/proxy/routes/routes.tsx b/ui/src/proxy/routes/routes.tsx
index b42cacb..4ba094f 100644
--- a/ui/src/proxy/routes/routes.tsx
+++ b/ui/src/proxy/routes/routes.tsx
@@ -1,11 +1,11 @@
import { LayoutType } from '../theme/models'
-import type { LazyExoticComponent, ReactNode } from 'react'
+import type { LazyExoticComponent, ReactElement, ReactNode } from 'react'
export interface Meta {
pageContainerType?: 'default' | 'gutterless' | 'contained'
header?: string | ReactNode
headerContainer?: boolean
- extraHeader?: LazyExoticComponent<() => JSX.Element>
+ extraHeader?: LazyExoticComponent<() => ReactElement>
footer?: boolean
layout?: LayoutType
}
@@ -13,7 +13,7 @@ export interface Meta {
export type Route = {
key: string
path: string
- component: LazyExoticComponent<(props: T) => JSX.Element>
+ component: LazyExoticComponent<(props: T) => ReactElement>
authority: string[]
meta?: Meta
}
diff --git a/ui/src/store/store.ts b/ui/src/store/store.ts
index c464ac3..aa33c72 100644
--- a/ui/src/store/store.ts
+++ b/ui/src/store/store.ts
@@ -45,6 +45,7 @@ export const store = createStore(
},
{
allow: ['auth', 'theme', 'locale', 'client', 'admin'],
+ storage: 'localStorage',
},
),
{
diff --git a/ui/src/utils/hooks/useCurrentMenuIcon.tsx b/ui/src/utils/hooks/useCurrentMenuIcon.tsx
index f629226..a91cf58 100644
--- a/ui/src/utils/hooks/useCurrentMenuIcon.tsx
+++ b/ui/src/utils/hooks/useCurrentMenuIcon.tsx
@@ -3,6 +3,7 @@ import { useLocation } from 'react-router-dom'
import { FaUser } from 'react-icons/fa'
import navigationIcon from '@/proxy/menus/navigation-icon.config'
import { navigationTreeToFlat } from '@/utils/navigation'
+import { ReactElement } from 'react'
const extractListFormCode = (path: string): string | null => {
const p = (path ?? '').toLowerCase()
@@ -14,7 +15,7 @@ const extractListFormCode = (path: string): string | null => {
return null
}
-export function useCurrentMenuIcon(className = 'w-6 h-6'): JSX.Element {
+export function useCurrentMenuIcon(className = 'w-6 h-6'): ReactElement {
const mainMenu = useStoreState((state) => state.abpConfig.menu.mainMenu)
const location = useLocation()
const menus = navigationTreeToFlat(mainMenu)
diff --git a/ui/src/views/list/useListFormColumns.ts b/ui/src/views/list/useListFormColumns.ts
index da30ad2..784b4e2 100644
--- a/ui/src/views/list/useListFormColumns.ts
+++ b/ui/src/views/list/useListFormColumns.ts
@@ -1073,6 +1073,7 @@ const useListFormColumns = ({
dataField: item.dataField,
visible: false,
showInColumnChooser: false,
+ allowSearch: false
})
insertedColumns.push(item.dataField)
}
diff --git a/ui/src/views/shared/DialogContext/DialogShowComponent.tsx b/ui/src/views/shared/DialogContext/DialogShowComponent.tsx
index f3574a6..aef6f25 100644
--- a/ui/src/views/shared/DialogContext/DialogShowComponent.tsx
+++ b/ui/src/views/shared/DialogContext/DialogShowComponent.tsx
@@ -6,8 +6,9 @@ import AuditLogDetail from '@/views/admin/auditLog/AuditLogDetail'
import RolesPermission from '@/views/admin/role-management/RolesPermission'
import UsersPermission from '@/views/admin/user-management/UsersPermission'
import BranchSeed from '@/views/branch/BranchSeed'
+import { ReactElement } from 'react'
-const DialogShowComponent = (): JSX.Element => {
+const DialogShowComponent = (): ReactElement => {
const dialogContext: any = useDialogContext()
const handleDialogClose = () => {
diff --git a/ui/src/views/shared/TableNoRecords.tsx b/ui/src/views/shared/TableNoRecords.tsx
index ea64438..969d0df 100644
--- a/ui/src/views/shared/TableNoRecords.tsx
+++ b/ui/src/views/shared/TableNoRecords.tsx
@@ -4,12 +4,13 @@ import Tr from '@/components/ui/Table/Tr'
import { useLocalization } from '@/utils/hooks/useLocalization'
import useThemeClass from '@/utils/hooks/useThemeClass'
import classNames from 'classnames'
+import { ReactElement } from 'react'
interface TableNoRecordsProps extends CommonProps {
show: boolean
}
-const TableNoRecords = (props: TableNoRecordsProps): JSX.Element => {
+const TableNoRecords = (props: TableNoRecordsProps): ReactElement => {
const { show, children, className, ...rest } = props
const { textTheme } = useThemeClass()
diff --git a/ui/src/views/version/ChangeLog.tsx b/ui/src/views/version/ChangeLog.tsx
index 3b052e7..fc8805f 100644
--- a/ui/src/views/version/ChangeLog.tsx
+++ b/ui/src/views/version/ChangeLog.tsx
@@ -14,47 +14,13 @@ type Release = {
changeLog: string[]
}
-const Log = ({
- version,
- date,
- children,
-}: {
- version: string
- date: string
- children?: React.ReactNode
-}) => {
- return (
-
-
-
-
- v{version}
-
-
-
{children}
-
- )
-}
-
-const Changelog = () => {
+// User dropdown reuses the exact update-check flow owned by this component.
+// eslint-disable-next-line react-refresh/only-export-components
+export const useManualUpdateCheck = () => {
const { translate } = useLocalization()
- const [releases, setReleases] = useState([])
const [isCheckingUpdate, setIsCheckingUpdate] = useState(false)
- useEffect(() => {
- fetch('/version.json?ts=' + Date.now())
- .then((res) => res.json())
- .then((data) => {
- if (data?.releases) {
- setReleases(data.releases)
- }
- })
- .catch(() => setReleases([]))
- }, [])
-
- const handleManualUpdate = async () => {
+ const checkForUpdate = async () => {
if (isCheckingUpdate) return
setIsCheckingUpdate(true)
@@ -96,6 +62,49 @@ const Changelog = () => {
}
}
+ return { isCheckingUpdate, checkForUpdate }
+}
+
+const Log = ({
+ version,
+ date,
+ children,
+}: {
+ version: string
+ date: string
+ children?: React.ReactNode
+}) => {
+ return (
+
+
+
+
+ v{version}
+
+
+
{children}
+
+ )
+}
+
+const Changelog = () => {
+ const { translate } = useLocalization()
+ const [releases, setReleases] = useState([])
+ const { isCheckingUpdate, checkForUpdate } = useManualUpdateCheck()
+
+ useEffect(() => {
+ fetch('/version.json?ts=' + Date.now())
+ .then((res) => res.json())
+ .then((data) => {
+ if (data?.releases) {
+ setReleases(data.releases)
+ }
+ })
+ .catch(() => setReleases([]))
+ }, [])
+
return (
{
icon={}
loading={isCheckingUpdate}
variant="solid"
- onClick={handleManualUpdate}
+ onClick={checkForUpdate}
>
{isCheckingUpdate
? translate('::App.CheckUpdate')