From 7d6544c3c4846167aee3a1fcef5a75319797f276 Mon Sep 17 00:00:00 2001 From: Stefano Ricci <1219739+SteRiccio@users.noreply.github.com> Date: Fri, 30 Aug 2024 13:52:16 +0200 Subject: [PATCH] Surveys list: added checkbox to show only own surveys (#3549) Co-authored-by: Stefano Ricci Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- core/i18n/resources/en/common.js | 1 + server/modules/survey/api/surveyApi.js | 6 ++++-- server/modules/survey/manager/surveyManager.js | 2 ++ server/modules/survey/repository/surveyRepository.js | 6 ++++-- .../survey/Surveys/HeaderLeft/HeaderLeft.js | 12 +++++++++--- webapp/components/survey/Surveys/Surveys.js | 7 +++++-- 6 files changed, 25 insertions(+), 9 deletions(-) diff --git a/core/i18n/resources/en/common.js b/core/i18n/resources/en/common.js index 52880255b8..7721d4a1df 100644 --- a/core/i18n/resources/en/common.js +++ b/core/i18n/resources/en/common.js @@ -855,6 +855,7 @@ Merge cannot be performed.`, languages: 'Languages', nodes: 'Nodes', noSurveysMatchingFilter: 'No surveys matching the specified filter', + onlyOwn: 'Only own surveys', records: 'Records', recordsCreatedWithMoreApps: 'Records created with more apps:', }, diff --git a/server/modules/survey/api/surveyApi.js b/server/modules/survey/api/surveyApi.js index dcb643721c..f0ef349338 100644 --- a/server/modules/survey/api/surveyApi.js +++ b/server/modules/survey/api/surveyApi.js @@ -76,6 +76,7 @@ export const init = (app) => { sortBy, sortOrder, includeCounts = false, + onlyOwn = false, } = Request.getParams(req) const list = await SurveyService.fetchUserSurveysInfo({ @@ -89,6 +90,7 @@ export const init = (app) => { sortBy, sortOrder, includeCounts, + onlyOwn, }) res.json({ list }) @@ -100,9 +102,9 @@ export const init = (app) => { app.get('/surveys/count', AuthMiddleware.requireLoggedInUser, async (req, res, next) => { try { const user = Request.getUser(req) - const { draft = true, template = false, search = null, lang = null } = Request.getParams(req) + const { draft = true, template = false, search = null, lang = null, onlyOwn = false } = Request.getParams(req) - const count = await SurveyService.countUserSurveys({ user, draft, template, search, lang }) + const count = await SurveyService.countUserSurveys({ user, draft, template, search, lang, onlyOwn }) res.json({ count }) } catch (error) { diff --git a/server/modules/survey/manager/surveyManager.js b/server/modules/survey/manager/surveyManager.js index eeeec2d0da..216b3c2218 100644 --- a/server/modules/survey/manager/surveyManager.js +++ b/server/modules/survey/manager/surveyManager.js @@ -300,6 +300,7 @@ export const fetchUserSurveysInfo = async ( sortOrder, includeCounts = false, includeOwnerEmailAddress = false, + onlyOwn = false, }, client = db ) => { @@ -324,6 +325,7 @@ export const fetchUserSurveysInfo = async ( sortBy, sortOrder, includeOwnerEmailAddress, + onlyOwn, }) ).map(assocSurveyInfo) diff --git a/server/modules/survey/repository/surveyRepository.js b/server/modules/survey/repository/surveyRepository.js index 019be88bd9..e24600a019 100644 --- a/server/modules/survey/repository/surveyRepository.js +++ b/server/modules/survey/repository/surveyRepository.js @@ -82,6 +82,7 @@ const _getSurveysSelectQuery = ({ sortBy = Survey.sortableKeys.dateModified, sortOrder = 'DESC', includeOwnerEmailAddress = false, + onlyOwn = false, }) => { const checkAccess = (!template || draft) && !User.isSystemAdmin(user) const propsCol = draft ? '(s.props || s.props_draft)' : 's.props' @@ -152,6 +153,7 @@ const _getSurveysSelectQuery = ({ -- if draft is false, fetch only published surveys ${draft ? '' : `s.props <> '{}'::jsonb AND `} ${_getSelectWhereCondition({ draft, search })} + ${onlyOwn ? ' AND s.owner_uuid = $/userUuid/' : ''} ORDER BY ${sortByField} ${sortOrder} LIMIT ${limit === null ? 'ALL' : limit} OFFSET ${offset} @@ -194,7 +196,7 @@ export const fetchUserSurveys = async ( } export const countUserSurveys = async ( - { user, draft = false, template = false, search: searchParam = null, lang = null }, + { user, draft = false, template = false, search: searchParam = null, lang = null, onlyOwn = false }, client = db ) => { const search = StringUtils.isNotBlank(searchParam) ? `%${searchParam.toLowerCase()}%` : null @@ -202,7 +204,7 @@ export const countUserSurveys = async ( return client.one( ` SELECT COUNT(*) - FROM (${_getSurveysSelectQuery({ user, draft, template, lang, search })}) AS s`, + FROM (${_getSurveysSelectQuery({ user, draft, template, lang, search, onlyOwn })}) AS s`, { search, template, userUuid: User.getUuid(user) }, (row) => Number(row.count) ) diff --git a/webapp/components/survey/Surveys/HeaderLeft/HeaderLeft.js b/webapp/components/survey/Surveys/HeaderLeft/HeaderLeft.js index cfb11005f5..1a84dfdd79 100644 --- a/webapp/components/survey/Surveys/HeaderLeft/HeaderLeft.js +++ b/webapp/components/survey/Surveys/HeaderLeft/HeaderLeft.js @@ -1,13 +1,14 @@ import React from 'react' import PropTypes from 'prop-types' -import { TextInput } from '@webapp/components/form' +import { Checkbox, TextInput } from '@webapp/components/form' import { ButtonDownload } from '@webapp/components/buttons' -import { useAuthCanExportSurveysList } from '@webapp/store/user/hooks' +import { useAuthCanExportSurveysList, useUserIsSystemAdmin } from '@webapp/store/user/hooks' const HeaderLeft = (props) => { - const { handleSearch, search, totalCount } = props + const { handleSearch, onlyOwn = false, search, setOnlyOwn = null, totalCount } = props + const isSystemAdmin = useUserIsSystemAdmin() const canExportSurveys = useAuthCanExportSurveysList() if (!totalCount) return null @@ -22,6 +23,9 @@ const HeaderLeft = (props) => { }} placeholder="surveysView.filterPlaceholder" /> + {isSystemAdmin && setOnlyOwn && ( + setOnlyOwn(!onlyOwn)} /> + )} {canExportSurveys && } ) @@ -29,7 +33,9 @@ const HeaderLeft = (props) => { HeaderLeft.propTypes = { handleSearch: PropTypes.func.isRequired, + onlyOwn: PropTypes.bool, search: PropTypes.string.isRequired, + setOnlyOwn: PropTypes.func, totalCount: PropTypes.number.isRequired, } diff --git a/webapp/components/survey/Surveys/Surveys.js b/webapp/components/survey/Surveys/Surveys.js index 0dae537f86..37ca500edf 100644 --- a/webapp/components/survey/Surveys/Surveys.js +++ b/webapp/components/survey/Surveys/Surveys.js @@ -12,7 +12,7 @@ import { appModuleUri, homeModules } from '@webapp/app/appModules' import { useBrowserLanguageCode, useOnUpdate } from '@webapp/components/hooks' import { SurveyActions, useSurveyInfo } from '@webapp/store/survey' -import { useUser } from '@webapp/store/user' +import { useUser, useUserIsSystemAdmin } from '@webapp/store/user' import Table from '@webapp/components/Table' import { TableCellFiles } from '@webapp/components/Table/TableCellFiles' @@ -29,12 +29,14 @@ const Surveys = (props) => { const user = useUser() const surveyInfo = useSurveyInfo() const lang = useBrowserLanguageCode() + const isSystemAdmin = useUserIsSystemAdmin() /** * Parameter passed to table rest params * (used to reload table data on survey publish). */ const [requestedAt, setRequestedAt] = useState(Date.now()) + const [onlyOwn, setOnlyOwn] = useState(isSystemAdmin) // Redirect to dashboard on survey change useOnUpdate(() => { @@ -174,13 +176,14 @@ const Surveys = (props) => { className="surveys" columns={columns} headerLeftComponent={HeaderLeft} + headerProps={{ onlyOwn, setOnlyOwn }} isRowActive={isRowActive} keyExtractor={({ item }) => Survey.getId(item)} module={module} moduleApiUri={moduleApiUri} noItemsLabelForSearchKey="surveysView.noSurveysMatchingFilter" onRowClick={onRowClick} - restParams={{ lang, template, requestedAt, includeCounts: true }} + restParams={{ lang, template, requestedAt, includeCounts: true, onlyOwn }} visibleColumnsSelectionEnabled /> )