Check New Version eklendi
This commit is contained in:
parent
28ec641275
commit
4805e8c4d9
9 changed files with 92 additions and 52 deletions
|
|
@ -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) => {
|
|||
)
|
||||
})}
|
||||
|
||||
<Dropdown.Item
|
||||
eventKey="Check New Version"
|
||||
className="mb-1 px-0"
|
||||
onClick={checkForUpdate}
|
||||
>
|
||||
<span className="flex h-full w-full items-center gap-2 px-2">
|
||||
<span className={classNames('text-xl opacity-50', isCheckingUpdate && 'animate-spin')}>
|
||||
<FcSynchronize />
|
||||
</span>
|
||||
<span>
|
||||
{isCheckingUpdate
|
||||
? translate('::App.CheckUpdate')
|
||||
: translate('::App.CheckForUpdates')}
|
||||
</span>
|
||||
</span>
|
||||
</Dropdown.Item>
|
||||
|
||||
{/* <Dropdown.Item variant="divider" /> */}
|
||||
<Dropdown.Item eventKey="Sign Out" className="mb-1 px-2" onClick={signOut}>
|
||||
<span className="text-xl opacity-50">
|
||||
|
|
@ -124,6 +150,6 @@ const _UserDropdown = ({ className }: CommonProps) => {
|
|||
)
|
||||
}
|
||||
|
||||
const UserDropdown = withHeaderItem(_UserDropdown)
|
||||
const UserDropdown = withHeaderItem(UserDropdownBase)
|
||||
|
||||
export default UserDropdown
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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<<T extends Meta>(props: T) => JSX.Element>
|
||||
component: LazyExoticComponent<<T extends Meta>(props: T) => ReactElement>
|
||||
authority: string[]
|
||||
meta?: Meta
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ export const store = createStore<StoreModel>(
|
|||
},
|
||||
{
|
||||
allow: ['auth', 'theme', 'locale', 'client', 'admin'],
|
||||
storage: 'localStorage',
|
||||
},
|
||||
),
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -1073,6 +1073,7 @@ const useListFormColumns = ({
|
|||
dataField: item.dataField,
|
||||
visible: false,
|
||||
showInColumnChooser: false,
|
||||
allowSearch: false
|
||||
})
|
||||
insertedColumns.push(item.dataField)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = () => {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -14,47 +14,13 @@ type Release = {
|
|||
changeLog: string[]
|
||||
}
|
||||
|
||||
const Log = ({
|
||||
version,
|
||||
date,
|
||||
children,
|
||||
}: {
|
||||
version: string
|
||||
date: string
|
||||
children?: React.ReactNode
|
||||
}) => {
|
||||
return (
|
||||
<div className="relative pl-4 sm:pl-32 py-4 group">
|
||||
<div className="flex flex-col sm:flex-row items-start mb-1 group-last:before:hidden before:absolute before:left-2 sm:before:left-0 before:h-full before:px-px before:bg-slate-200 sm:before:ml-[6.5rem] before:self-start before:-translate-x-1/2 before:translate-y-3 after:absolute after:left-2 sm:after:left-0 after:w-2 after:h-2 after:bg-indigo-600 after:border-4 after:box-content after:border-slate-50 after:rounded-full sm:after:ml-[6.5rem] after:-translate-x-1/2 after:translate-y-1.5">
|
||||
<time className="sm:absolute left-0 translate-y-0.5 inline-flex items-center justify-center text-xs font-semibold uppercase w-20 h-6 mb-3 sm:mb-0 text-emerald-600 bg-emerald-100 rounded-full">
|
||||
{date}
|
||||
</time>
|
||||
<div className="flex items-center text-xl font-bold text-gray-900 dark:text-white">
|
||||
<FaTag className="mr-2 text-indigo-500" />v{version}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-slate-500">{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
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<Release[]>([])
|
||||
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 (
|
||||
<div className="relative pl-4 sm:pl-32 py-4 group">
|
||||
<div className="flex flex-col sm:flex-row items-start mb-1 group-last:before:hidden before:absolute before:left-2 sm:before:left-0 before:h-full before:px-px before:bg-slate-200 sm:before:ml-[6.5rem] before:self-start before:-translate-x-1/2 before:translate-y-3 after:absolute after:left-2 sm:after:left-0 after:w-2 after:h-2 after:bg-indigo-600 after:border-4 after:box-content after:border-slate-50 after:rounded-full sm:after:ml-[6.5rem] after:-translate-x-1/2 after:translate-y-1.5">
|
||||
<time className="sm:absolute left-0 translate-y-0.5 inline-flex items-center justify-center text-xs font-semibold uppercase w-20 h-6 mb-3 sm:mb-0 text-emerald-600 bg-emerald-100 rounded-full">
|
||||
{date}
|
||||
</time>
|
||||
<div className="flex items-center text-xl font-bold text-gray-900 dark:text-white">
|
||||
<FaTag className="mr-2 text-indigo-500" />v{version}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-slate-500">{children}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Changelog = () => {
|
||||
const { translate } = useLocalization()
|
||||
const [releases, setReleases] = useState<Release[]>([])
|
||||
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 (
|
||||
<Container>
|
||||
<Helmet
|
||||
|
|
@ -114,7 +123,7 @@ const Changelog = () => {
|
|||
icon={<FaSyncAlt />}
|
||||
loading={isCheckingUpdate}
|
||||
variant="solid"
|
||||
onClick={handleManualUpdate}
|
||||
onClick={checkForUpdate}
|
||||
>
|
||||
{isCheckingUpdate
|
||||
? translate('::App.CheckUpdate')
|
||||
|
|
|
|||
Loading…
Reference in a new issue