Закончена первая версия Дела скважины

This commit is contained in:
goodmice 2022-09-13 16:21:57 +05:00
parent 6c52a091c9
commit 664e3aa57a
3 changed files with 206 additions and 66 deletions

View File

@ -3,25 +3,14 @@ import { Empty, Timeline } from 'antd'
import moment from 'moment' import moment from 'moment'
import { useWell } from '@asb/context' import { useWell } from '@asb/context'
import { UserView } from '@components/views'
import DownloadLink from '@components/DownloadLink' import DownloadLink from '@components/DownloadLink'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
// import { makeColumn, makeDateColumn, Table } from '@components/Table' import { WellFinalDocumentsService } from '@api'
import { formatDate } from '@utils' import { formatDate } from '@utils'
import { UserView } from '@asb/components/views'
// const columns = [ export const HistoryTable = memo(({ category }) => {
// makeColumn('Файл', 'file', {
// render: (file) => (
// <DownloadLink file={file} />
// ),
// }),
// makeDateColumn('Дата загрузки', 'date', undefined, undefined, {
// defaultSortOrder: 'descend',
// }),
// ]
export const HistoryTable = memo(({ users, category }) => {
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [files, setFiles] = useState([]) const [files, setFiles] = useState([])
@ -30,26 +19,29 @@ export const HistoryTable = memo(({ users, category }) => {
useEffect(() => { useEffect(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
const files = [{ uploadDate: moment().format(), id: 0, idWell: 0 }] const result = await WellFinalDocumentsService.getFilesHistoryByIdCategory(well.id, category.idCategory)
if (!result) return
const files = result.file
files.sort((a, b) => moment(a.uploadDate) - moment(b.uploadDate)) files.sort((a, b) => moment(a.uploadDate) - moment(b.uploadDate))
const fileSource = files.map((file) => ({ const fileSource = files.map((file) => ({
file, file,
date: file.uploadDate, date: file.uploadDate,
user: users.find(({ id }) => id === file.idAuthor) ?? null, user: file.author,
})) }))
setFiles(fileSource) // Получаем список файлов и записываем в state setFiles(fileSource)
}, },
setIsLoading, setIsLoading,
`Не удалось загрузить историю файлов категории "${category.caption}"`, `Не удалось загрузить историю файлов категории "${category.nameCategory}"`,
{ actionName: `Загрузка истории файлов категории "${category.nameCategory}"`, well }
) )
}, [well, category]) }, [well, category])
return ( return (
<LoaderPortal show={isLoading}> <LoaderPortal show={isLoading}>
{files.length > 0 ? ( {files.length > 0 ? (
<Timeline reverse style={{ marginLeft: 20 }}> <Timeline reverse style={{ marginLeft: 50, marginTop: 20 }}>
{files.map(({ date, user, file }) => ( {files.map(({ date, user, file }) => (
<Timeline.Item> <Timeline.Item key={date}>
{formatDate(date)} {formatDate(date)}
<UserView user={user} style={{ marginLeft: 10 }} /> <UserView user={user} style={{ marginLeft: 10 }} />
<DownloadLink file={file} /> <DownloadLink file={file} />
@ -57,17 +49,10 @@ export const HistoryTable = memo(({ users, category }) => {
))} ))}
</Timeline> </Timeline>
) : ( ) : (
<Empty /> <Empty description={'Нет данных о версиях файлов'} />
)} )}
{/* <Table
bordered
size={'small'}
dataSource={files}
columns={columns}
/> */}
</LoaderPortal> </LoaderPortal>
) )
}) })
export default HistoryTable export default HistoryTable

View File

@ -1,20 +1,161 @@
import { memo, useCallback, useState } from 'react' import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { Modal, Transfer } from 'antd' import { AutoComplete, List, Modal, Tooltip, Transfer } from 'antd'
import { useWell } from '@asb/context' import { useWell } from '@asb/context'
import { UserView } from '@components/views'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { WellFinalDocumentsService } from '@api'
import { arrayOrDefault } from '@utils'
export const WellCaseEditor = memo(({ show, onClose }) => { import '@styles/well_case.less'
const [users, setUsers] = useState([])
const filterCategoriesByText = (text) => (cat) =>
!text || !!cat?.nameCategory?.toLowerCase().includes(text.toLowerCase())
const filterUserByText = (text, user) =>
!text || (user && `${user.login} ${user.email} ${user.surname} ${user.name} ${user.patronymic}`.toLowerCase().includes(text.toLowerCase()))
export const WellCaseEditor = memo(({ categories: currentCategories, show, onClose }) => {
const [users, setUsersDataSource] = useState([])
const [isLoading, setIsLoading] = useState(false)
const [categories, setCategories] = useState([])
const [availableCategories, setAvailableCategories] = useState([])
const [catSearchText, setCatSearchText] = useState(null)
const [selectedCatId, setSelectedCatId] = useState(null)
const [well] = useWell() const [well] = useWell()
const unusedCategories = useMemo(() => availableCategories.filter(({ id }) => !categories.find((cat) => cat.idCategory === id)), [categories, availableCategories])
const catOptions = useMemo(() => {
return unusedCategories
.filter(filterCategoriesByText(catSearchText))
.map((cat) => ({ label: cat.name, value: cat.name, id: cat.id }))
}, [catSearchText, unusedCategories])
const onModalOk = useCallback(() => { const onModalOk = useCallback(() => {
onClose(true) invokeWebApiWrapperAsync(
async () => {
await WellFinalDocumentsService.updateRange(well.id, categories)
onClose?.(true)
},
setIsLoading,
'Не удалось изменить ответственных',
{ actionName: 'Изменение ответственных', well }
)
}, [onClose, well, categories])
const onModalCancel = useCallback(() => onClose?.(false), [onClose])
const onAddCategory = useCallback((name, cat) => {
setCategories((prev) => [...prev, { idCategory: cat.id, nameCategory: name, publishers: [] }])
}, [])
const categoryRender = useCallback((item) => {
const hasPublishers = item.idsPublishers?.length > 0
const selected = selectedCatId === item.idCategory
return (
<List.Item
className={`category-list-item ${!hasPublishers ? 'empty' : ''} ${selected ? 'active' : ''}`}
onClick={() => setSelectedCatId(item.idCategory)}
>
{hasPublishers ? (item.nameCategory) : (
<Tooltip title={'Категория будет скрыта, так как не назначены ответственные'}>
{item.nameCategory}
</Tooltip>
)}
</List.Item>
)
}, [selectedCatId])
const onPublishersChange = useCallback((selectedPublishers) => {
setCategories((prev) => {
const cats = [...prev]
const idx = cats.findIndex((cat) => cat.idCategory === selectedCatId)
cats[idx].idsPublishers = selectedPublishers
return cats
})
}, [selectedCatId])
useEffect(() => {
const cats = currentCategories?.map((cat) => ({
idCategory: cat.idCategory,
nameCategory: cat.nameCategory,
idsPublishers: cat.publishers.map((user) => user.id),
}))
setCategories(cats ?? [])
}, [currentCategories])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const users = arrayOrDefault(await WellFinalDocumentsService.getAvailableUsers(well.id))
const usersDataSource = users.map((user) => ({ key: user.id, ...user }))
setUsersDataSource(usersDataSource)
},
setIsLoading,
'Не удалось загрузить список доступных публикаторов',
{ actionName: 'Загрузка списка доступных публикаторов', well }
)
}, [well])
useEffect(() => {
invokeWebApiWrapperAsync(
async () => {
const categories = arrayOrDefault(await WellFinalDocumentsService.getWellCaseCategories())
setAvailableCategories(categories)
},
setIsLoading,
'Не удалось загрузить список доступных категорий',
{ actionName: 'Загрузка списка доступных категорий' }
)
}, []) }, [])
return ( return (
<Modal visible={show} onCancel={() => onClose(false)} onOk={onModalOk}> <Modal
<Transfer /> centered
width={1000}
visible={show}
onOk={onModalOk}
onCancel={onModalCancel}
okText={'Сохранить'}
title={'Редактирование ответственных за категории'}
>
<LoaderPortal show={isLoading} style={{ width: '100%', height: '100%' }}>
<div className={'well-case-editor'}>
<div className={'category-list'}>
<AutoComplete
options={catOptions}
onSearch={(searchText) => setCatSearchText(searchText)}
onSelect={onAddCategory}
placeholder={'Впишите категорию для добавления'}
/>
<List
bordered
size={'small'}
style={{ flexGrow: 1 }}
itemLayout={'horizontal'}
dataSource={categories}
renderItem={categoryRender}
/>
</div>
<Transfer
showSearch
dataSource={users}
disabled={!selectedCatId}
listStyle={{ width: 300, height: '100%' }}
titles={['Пользователи', 'Публикаторы']}
onChange={onPublishersChange}
filterOption={filterUserByText}
targetKeys={categories.find((cat) => cat.idCategory === selectedCatId)?.idsPublishers ?? []}
render={(item) => (
<UserView user={item} />
)}
/>
</div>
</LoaderPortal>
</Modal> </Modal>
) )
}) })

View File

@ -7,64 +7,77 @@ import DownloadLink from '@components/DownloadLink'
import LoaderPortal from '@components/LoaderPortal' import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory' import { invokeWebApiWrapperAsync } from '@components/factory'
import { makeColumn, makeDateColumn, makeTextColumn, Table } from '@components/Table' import { makeColumn, makeDateColumn, makeTextColumn, Table } from '@components/Table'
import { delay, wrapPrivateComponent } from '@utils' import { WellFinalDocumentsService } from '@api'
import { MimeTypes, wrapPrivateComponent } from '@utils'
import WellCaseEditor from './WellCaseEditor' import WellCaseEditor from './WellCaseEditor'
import { HistoryTable } from './HistoryTable' import { HistoryTable } from './HistoryTable'
import UploadForm from '@asb/components/UploadForm'
const columns = [ const expandable = {
makeTextColumn('Категория', 'caption'), expandedRowRender: (category) => (
makeColumn('Файл', 'file', { <HistoryTable category={category} />
render: (file) => file ? ( )
<DownloadLink file={file} /> }
) : (
<span>Файл не загружен</span>
),
}),
makeDateColumn('Дата загрузки', 'uploadDate'),
makeColumn('Ответственные', 'responsible', {
render: (responsible) => responsible.map((user) => (
<UserView user={user} />
)),
}),
]
const WellCase = memo(() => { const WellCase = memo(() => {
const [isLoading, setIsLoading] = useState(false) const [isLoading, setIsLoading] = useState(false)
const [categories, setCategories] = useState([]) const [categories, setCategories] = useState([])
const [canEdit, setCanEdit] = useState(false) const [canEdit, setCanEdit] = useState(false)
const [showEdit, setShowEdit] = useState(false) const [showEdit, setShowEdit] = useState(false)
const [users, setUsers] = useState([])
const [well] = useWell() const [well] = useWell()
const updateTable = useCallback(() => { const updateTable = useCallback(() => {
invokeWebApiWrapperAsync( invokeWebApiWrapperAsync(
async () => { async () => {
await delay(1000) const { permissionToSetPubliher, wellFinalDocuments } = await WellFinalDocumentsService.get(well.id)
const categories = [{ responsible: [{}] }]
setCanEdit(true) setCategories(wellFinalDocuments.map((cat) => ({ ...cat, uploadDate: cat.file?.uploadDate })))
const showingCategories = categories.filter((cat) => cat.responsible && cat.responsible?.length > 0) setCanEdit(permissionToSetPubliher)
setCategories(showingCategories)
}, },
setIsLoading, setIsLoading,
'Не удалось загрузить список категорий', 'Не удалось загрузить список категорий',
{ actionName: 'Загрузка списка категорий', well }
) )
}, [well]) }, [well])
const columns = useMemo(() => [
makeTextColumn('Категория', 'nameCategory'),
makeColumn('Файл', 'file', {
render: (file, category) => (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
{file ? (
<DownloadLink file={file} />
) : (
<span style={{ marginLeft: 15 }}>Файл не загружен</span>
)}
{category.permissionToUpload && (
<UploadForm
url={`/api/WellFinalDocuments/${well.id}?idCategory=${category.idCategory}`}
onUploadStart={() => setIsLoading(true)}
onUploadComplete={updateTable}
onUploadError={() => setIsLoading(false)}
/>
)}
</div>
),
}),
makeDateColumn('Дата загрузки', 'uploadDate'),
makeColumn('Ответственные', 'publishers', {
render: (publishers) => publishers?.map((user) => (
<UserView user={user} />
)),
}),
], [well, updateTable])
const onEditClose = useCallback((changed = false) => { const onEditClose = useCallback((changed = false) => {
setShowEdit(false) setShowEdit(false)
if (changed) updateTable() if (changed) updateTable()
}, [updateTable]) }, [updateTable])
const expandable = useMemo(() => ({ useEffect(updateTable, [updateTable])
expandedRowRender: (category) => (
<HistoryTable users={users} category={category} />
)
}), [users])
useEffect(() => updateTable(), [updateTable])
return ( return (
<> <>
@ -80,7 +93,7 @@ const WellCase = memo(() => {
expandable={expandable} expandable={expandable}
/> />
</LoaderPortal> </LoaderPortal>
<WellCaseEditor users={users} show={showEdit} onClose={onEditClose} /> <WellCaseEditor categories={categories} show={showEdit} onClose={onEditClose} />
</> </>
) )
}) })
@ -89,4 +102,5 @@ export default wrapPrivateComponent(WellCase, {
title: 'Дело скважины', title: 'Дело скважины',
route: 'well_case', route: 'well_case',
requirements: [], requirements: [],
// requirements: ['WellFinalDocuments.get'],
}) })