diff --git a/app/api/server/lib/working-groups-requests.js b/app/api/server/lib/working-groups-requests.js index cf87c70b7a34..0fdec9ac5e00 100644 --- a/app/api/server/lib/working-groups-requests.js +++ b/app/api/server/lib/working-groups-requests.js @@ -1,10 +1,11 @@ import { WorkingGroupsRequests } from '../../../models/server/raw'; -export async function findWorkingGroupsRequests({ query = {}, pagination: { offset, count, sort } }) { +export async function findWorkingGroupsRequests({ query = {}, fields = {}, pagination: { offset, count, sort } }) { const cursor = await WorkingGroupsRequests.find(query, { sort: sort || { time: 1 }, skip: offset, limit: count, + fields, }); const total = await cursor.count(); diff --git a/app/api/server/v1/protocols.js b/app/api/server/v1/protocols.js index ce90b2261c05..048e312f5c56 100644 --- a/app/api/server/v1/protocols.js +++ b/app/api/server/v1/protocols.js @@ -10,10 +10,11 @@ API.v1.addRoute('protocols.list', { authRequired: true }, { // } const { offset, count } = this.getPaginationItems(); - const { sort, query } = this.parseJsonQuery(); + const { sort, query, stockFields } = this.parseJsonQuery(); return API.v1.success(Promise.await(findProtocols({ query, + fields: stockFields, pagination: { offset, count, diff --git a/app/api/server/v1/working-groups-requests.js b/app/api/server/v1/working-groups-requests.js index 5ca6ee77d376..168fe8b7345e 100644 --- a/app/api/server/v1/working-groups-requests.js +++ b/app/api/server/v1/working-groups-requests.js @@ -8,10 +8,11 @@ import { findWorkingGroupRequestAnswerByAnswerId, findWorkingGroupsRequests, fin API.v1.addRoute('working-groups-requests.list', { authRequired: true }, { get() { const { offset, count } = this.getPaginationItems(); - const { sort, query } = this.parseJsonQuery(); + const { sort, query, stockFields } = this.parseJsonQuery(); return API.v1.success(Promise.await(findWorkingGroupsRequests({ query, + fields: stockFields, pagination: { offset, count, diff --git a/app/errand/client/views/errandsPage/index.js b/app/errand/client/views/errandsPage/index.js index 27b9609c4e8f..8971173224d0 100644 --- a/app/errand/client/views/errandsPage/index.js +++ b/app/errand/client/views/errandsPage/index.js @@ -1,5 +1,17 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import { Box, Icon, Table, TextInput, Modal, Button, Label, Field } from '@rocket.chat/fuselage'; +import { + Box, + Icon, + Table, + TextInput, + Modal, + Button, + Label, + Field, + Tabs, + TextAreaInput, + ButtonGroup, +} from '@rocket.chat/fuselage'; import { useMediaQuery, useSafely } from '@rocket.chat/fuselage-hooks'; import Page from '../../../../../client/components/basic/Page'; @@ -8,10 +20,15 @@ import { useRouteParameter } from '../../../../../client/contexts/RouterContext' import { GenericTable, Th } from '../../../../../client/components/GenericTable'; import { useEndpointData } from '../../../../../client/hooks/useEndpointData'; import { useFormatDate } from '../../../../../client/hooks/useFormatDate'; +import { useFormatDateAndTime } from '../../../../../client/hooks/useFormatDateAndTime'; import { useSetModal } from '../../../../../client/contexts/ModalContext'; import { EditErrandContextBar } from './EditErrand'; import { modal } from '../../../../ui-utils/client'; import { GoBackButton } from '../../../../utils/client/views/GoBackButton'; +import { useUserId } from '../../../../../client/contexts/UserContext'; +import { useEndpointDataExperimental, ENDPOINT_STATES } from '../../../../../client/hooks/useEndpointDataExperimental'; +import { settings } from '../../../../settings'; +import VerticalBar from '../../../../../client/components/basic/VerticalBar'; const style = { whiteSpace: 'nowrap', textOverflow: 'ellipsis', overflow: 'hidden' }; @@ -34,6 +51,51 @@ const FilterByText = ({ setFilter, ...props }) => { ; }; +function renderRequestModal({ onCancel, request, formatDateAndTime, ...props }) { + const t = useTranslation(); + // const formatDate = useFormatDate(); + + const goToSendAnswer = () => { + window.open([settings.get('Site_Url'), 'd/', request.inviteLink].join(''), '_blank'); + }; + + return + + {t('Working_group_request')} + + + + + + {t('Number')} + + + + + + {t('Description')} + + + + + + {t('Date')} + + {/**/} + + + + + + + + + + + + ; +} + function renderEditModal({ onCancel, erid, onChange, ...props }) { const t = useTranslation(); return @@ -114,7 +176,6 @@ function Errands({ } function Requests({ - type, data, sort, onClick, @@ -126,61 +187,55 @@ function Requests({ const mediaQuery = useMediaQuery('(min-width: 768px)'); + const formatDate = useFormatDate(); + const header = useMemo(() => [ - type === 'initiated_by_me' || {_t('Errand_Initiated_by')}, - type === 'charged_to_me' || {_t('Errand_Charged_to')}, - mediaQuery && {_t('Description')}, - mediaQuery && {_t('Started_At')}, - {_t('Errand_Expired_date')}, - {_t('Status')}, - ].filter(Boolean), [type, sort, mediaQuery]); + mediaQuery && {_t('Number')}, + mediaQuery && {_t('Description')}, + mediaQuery && {_t('Date')}, + ].filter(Boolean), [sort, mediaQuery]); - const formatDate = useFormatDate(); const renderRow = useCallback((item) => - - { type === 'initiated_by_me' || - {item.initiatedBy.username} - } - {type === 'charged_to_me' || - {item.chargedToUser.username} + + { mediaQuery && + {item.number} } { mediaQuery && {item.desc} } { mediaQuery && - {formatDate(item.ts)} + {formatDate(item.date)} } - - {formatDate(item.expireAt)} - - - {_t(item.t)} - , [mediaQuery]); - return ; + return ; } export function ErrandPage() { const t = useTranslation(); + const formatDateAndTime = useFormatDateAndTime(); + const userId = useUserId(); + const setModal = useSetModal(); const type = useRouteParameter('type'); + + const [sort, setSort] = useState(['ts', 'asc']); + const [params, setParams] = useState({ type, current: 0, itemsPerPage: 100 }); + const [cache, setCache] = useState(); + const [tab, setTab] = useState('errands'); + let title = 'Errands'; switch (type) { case 'initiated_by_me': title = 'Errands_from_me'; + tab !== 'errands' && setTab('errands'); break; case 'charged_to_me': - title = 'Errands_for_me'; + title = 'Tasks_for_me'; break; } - const [sort, setSort] = useState(['ts', 'asc']); - const [params, setParams] = useState({ type, current: 0, itemsPerPage: 100 }); - const [cache, setCache] = useState(); - const setModal = useSetModal(); - const query = useMemo(() => ({ query: JSON.stringify({ type, @@ -190,8 +245,21 @@ export function ErrandPage() { ...params.current && { offset: params.current }, }), [params.itemsPerPage, params.current, sort, type, params.text, cache]); + const currentUserPersonData = useEndpointData('users.getPerson', useMemo(() => ({ query: JSON.stringify({ userId }) }), [userId])); const data = useEndpointData('errands', query) || { result: [], total: 0 }; + const currentUserPersonQuery = useMemo(() => currentUserPersonData || { _id: '' }, [currentUserPersonData]); + const { data: resData, state: resState } = useEndpointDataExperimental('protocolItemsPersonsResponsible.list', useMemo(() => ({ + query: JSON.stringify({ persons: { $elemMatch: { _id: currentUserPersonQuery._id } } }), + fields: JSON.stringify({ persons: 0 }), + }), [currentUserPersonQuery])); + + const requestsQuery = useMemo(() => resData?.protocolItemsPersonsResponsible?.map((protocol) => protocol.itemId) || [], [resData]); + const { data: requests, state } = useEndpointDataExperimental('working-groups-requests.list', useMemo(() => ({ + query: JSON.stringify({ answers: { $elemMatch: { sectionItemId: { $in: requestsQuery } } } }), + fields: JSON.stringify({ answers: 0 }), + }), [requestsQuery])); + const onHeaderClick = useCallback((id) => { const [sortBy, sortDirection] = sort; @@ -211,8 +279,15 @@ export function ErrandPage() { const onClick = useCallback((errand) => () => setModal(() => renderEditModal({ onCancel: cancelModal, erid: errand._id, onChange, key: 'modal-errand' })), []); + const onRequestClick = useCallback((request) => () => setModal(() => renderRequestModal({ onCancel: cancelModal, request, formatDateAndTime, key: 'modal-request' })), []); + const addErrand = useCallback(() => () => setModal(() => renderAddErrandModal({ onChange })), []); + if ([state, resState].includes(ENDPOINT_STATES.LOADING)) { + console.log('loading'); + return {t('Loading')}; + } + return @@ -225,8 +300,12 @@ export function ErrandPage() { } - - {/**/} + {type === 'charged_to_me' && + setTab('errands')}>{t('Errands_for_me')} + setTab('requests')}>{t('Working_group_requests')} + } + {tab === 'errands' && } + {tab === 'requests' && } ; diff --git a/app/models/server/models/Protocols.js b/app/models/server/models/Protocols.js index e2857c9e7125..2b18b0c7baa1 100644 --- a/app/models/server/models/Protocols.js +++ b/app/models/server/models/Protocols.js @@ -1,6 +1,7 @@ -import { Base } from './_Base'; import { ObjectID } from 'bson'; +import { Base } from './_Base'; + class Protocols extends Base { constructor() { super('protocols'); @@ -88,14 +89,13 @@ class Protocols extends Base { data.sections.forEach((section) => { if (section._id === sectionId) { - if (section.items) { let internalNum = 0; section.items.forEach((item) => { if (item.inum > internalNum) { internalNum = item.inum; } - }) + }); internalNum++; item.inum = internalNum; section.items = [...section.items, item]; @@ -103,14 +103,13 @@ class Protocols extends Base { item.inum = 1; section.items = [item]; } - } }); - this.update({ _id: protocolId }, { $set: { ...data } }) + this.update({ _id: protocolId }, { $set: { ...data } }); + return _id; } - - return _id; + return null; } removeItemById(protocolId, sectionId, _id) { diff --git a/app/protocols/server/methods/deleteItem.js b/app/protocols/server/methods/deleteItem.js index 2598c7d250f7..30dcf7823bb8 100644 --- a/app/protocols/server/methods/deleteItem.js +++ b/app/protocols/server/methods/deleteItem.js @@ -1,7 +1,7 @@ import { Meteor } from 'meteor/meteor'; import { hasPermission } from '../../../authorization'; -import { Protocols } from '../../../models'; +import { Protocols, ProtocolItemsPersonsResponsible } from '../../../models'; Meteor.methods({ deleteItem(protocolId, sectionId, _id) { @@ -18,6 +18,7 @@ Meteor.methods({ } Protocols.removeItemById(protocolId, sectionId, _id); + ProtocolItemsPersonsResponsible.removeByItemId(_id); return true; }, diff --git a/app/protocols/server/methods/insertOrUpdateItem.js b/app/protocols/server/methods/insertOrUpdateItem.js index 0c27c0728122..7e9db1a163ca 100644 --- a/app/protocols/server/methods/insertOrUpdateItem.js +++ b/app/protocols/server/methods/insertOrUpdateItem.js @@ -2,11 +2,11 @@ import { Meteor } from 'meteor/meteor'; import s from 'underscore.string'; import { hasPermission } from '../../../authorization'; -import { Protocols } from '../../../models'; +import { Protocols, ProtocolItemsPersonsResponsible } from '../../../models'; Meteor.methods({ insertOrUpdateItem(protocolId, sectionId, item) { - // if (!hasPermission(this.userId, 'manage-protocols')) { + // if (!hasPermission('manage-protocols', Meteor.userId)) { // throw new Meteor.Error('not_authorized'); // } @@ -26,10 +26,18 @@ Meteor.methods({ throw new Meteor.Error('error-the-field-is-required', 'The field Name is required', { method: 'insertOrUpdateItem', field: 'Name' }); } + let _id = null; + const protocolItemsPersonsResponsible = { protocolId, sectionId, itemId: item._id, persons: item.responsible.filter((person) => person.userId).map((person) => ({ _id: person._id })) }; + if (!item._id) { - return Protocols.createItem(protocolId, sectionId, item); + _id = Protocols.createItem(protocolId, sectionId, item); + protocolItemsPersonsResponsible.itemId = _id; + !!_id && ProtocolItemsPersonsResponsible.create(protocolItemsPersonsResponsible); + } else { + _id = Protocols.updateItem(protocolId, sectionId, item); + !!_id && ProtocolItemsPersonsResponsible.updateProtocolItemsPersonsResponsible(protocolItemsPersonsResponsible); } - return Protocols.updateItem(protocolId, sectionId, item); + return _id; }, }); diff --git a/app/working-group-requests/client/views/formForSendingDocuments/steps/WorkingGroupRequestAnswerFileDownloadStep.js b/app/working-group-requests/client/views/formForSendingDocuments/steps/WorkingGroupRequestAnswerFileDownloadStep.js index b5379f412e41..baf3581378e5 100644 --- a/app/working-group-requests/client/views/formForSendingDocuments/steps/WorkingGroupRequestAnswerFileDownloadStep.js +++ b/app/working-group-requests/client/views/formForSendingDocuments/steps/WorkingGroupRequestAnswerFileDownloadStep.js @@ -589,14 +589,30 @@ function WorkingGroupRequestAnswerFileDownloadStep({ step, title, active, workin const packNewData = () => { const dataToSend = {}; - const protocolData = protocolsData[newData.protocol.value]; - const sectionIndex = newData.section.value; - const sectionItemIndex = newData.sectionItem.value; const labelNotChosen = t('Not_chosen'); if (answerTypeContext === 'protocol') { - dataToSend.protocol = protocolData ? [t('Protocol'), '№', protocolData.num, t('Date_From'), formatDate(protocolData.d)].join(' ') : labelNotChosen; - dataToSend.section = sectionIndex === '' ? labelNotChosen : [protocolData.sections[sectionIndex].num ?? '', ': ', protocolData.sections[sectionIndex].name ? preProcessingProtocolItems(protocolData.sections[sectionIndex].name) : ''].join(''); - dataToSend.sectionItem = sectionItemIndex === '' ? labelNotChosen : [protocolData.sections[sectionIndex].items[sectionItemIndex].num ?? '', ': ', protocolData.sections[sectionIndex].items[sectionItemIndex].name ? preProcessingProtocolItems(protocolData.sections[sectionIndex].items[sectionItemIndex].name) : ''].join(''); + const protocolData = protocolsData[newData.protocol.value]; + const sectionData = protocolData.sections[newData.section.value]; + const sectionItemData = sectionData.items[newData.sectionItem.value]; + console.log(protocolData); + console.log(sectionData); + console.log(sectionItemData); + dataToSend.protocol = { + _id: protocolData._id, + title: [t('Protocol'), '№', protocolData.num, t('Date_From'), formatDate(protocolData.d)].join(' '), + section: { + _id: sectionData._id, + title: [sectionData.num ?? '', ': ', sectionData.name ? preProcessingProtocolItems(sectionData.name) : ''].join(''), + }, + sectionItem: { + _id: sectionItemData._id, + title: [sectionItemData.num ?? '', ': ', sectionItemData.name ? preProcessingProtocolItems(sectionItemData.name) : ''].join(''), + }, + }; + dataToSend.protocolId = protocolData._id; + dataToSend.sectionId = sectionData._id; + dataToSend.sectionItemId = sectionItemData._id; + console.log(dataToSend); } else { dataToSend.protocol = labelNotChosen; dataToSend.section = labelNotChosen; @@ -636,8 +652,6 @@ function WorkingGroupRequestAnswerFileDownloadStep({ step, title, active, workin } else { setInfo({ workingGroupRequestId, mailId, workingGroupRequestAnswer, attachedFile }); goToNextStep(); - // const { answerId, mailId: newMailId } = await addWorkingGroupRequestAnswer(workingGroupRequestId, mailId, workingGroupRequestAnswer); - // await fileUploadToWorkingGroupRequestAnswer(attachedFile, { _id: workingGroupRequestId, mailId: newMailId === '' ? mailId : newMailId, answerId }); } } } catch (error) {