Skip to content

Commit

Permalink
Merge branch 'master' into feat/survey-user-extra-props
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Oct 11, 2024
2 parents 5539934 + 7e0a41f commit d5dbc3b
Show file tree
Hide file tree
Showing 22 changed files with 181 additions and 187 deletions.
4 changes: 2 additions & 2 deletions common/model/csvExport/CsvDataExportModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class CsvDataExportModel {

_extractAttributeDefsColumns(nodeDefContext) {
const { cycle, options } = this
const { includeAnalysis, includeFiles, includeReadOnlyAttributes } = options
const { includeAnalysis, includeFileAttributeDefs, includeFiles, includeReadOnlyAttributes } = options

let descendantDefs = NodeDef.isEntity(nodeDefContext)
? Survey.getNodeDefDescendantAttributesInSingleEntities({
Expand All @@ -199,7 +199,7 @@ export class CsvDataExportModel {

descendantDefs = descendantDefs.filter(
(nodeDef) =>
(includeFiles || !NodeDef.isFile(nodeDef)) &&
(includeFileAttributeDefs || includeFiles || !NodeDef.isFile(nodeDef)) &&
(includeReadOnlyAttributes || !NodeDef.isReadOnly(nodeDef) || NodeDef.isKey(nodeDef))
)

Expand Down
8 changes: 8 additions & 0 deletions common/model/db/views/dataNodeDef/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export default class ViewDataNodeDef extends TableDataNodeDef {
return this.columnNodeDefUuid.nameFull
}

get columnUuidName() {
return this.columnNodeDefUuid.name
}

get columnIdName() {
const { nodeDef } = this.tableData
return `_${NodeDef.getName(nodeDef)}_${TableDataNodeDef.columnSet.id}`
Expand Down Expand Up @@ -118,6 +122,10 @@ export default class ViewDataNodeDef extends TableDataNodeDef {
return this.columnNodeDefs.flatMap((columnNodeDef) => new ColumnNodeDef(this, columnNodeDef.nodeDef).namesFull)
}

get columnParentUuidName() {
return this.viewDataParent?.columnUuidName
}

get tableData() {
return this._tableData
}
Expand Down
8 changes: 5 additions & 3 deletions core/i18n/resources/en/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,8 @@ Thank you and enjoy **$t(common.appNameFull)**!`,
activityLog: {
title: 'Activity log',
},
exportWithData: 'Export with data',
exportWithDataNoActivityLog: 'Export with data (NO Activity Log)',
exportWithData: 'Export + data (Backup)',
exportWithDataNoActivityLog: 'Export + data (NO Activity Log)',
surveyPropUpdate: {
main: `<title>Welcome to Arena</title>
Expand Down Expand Up @@ -560,6 +560,8 @@ $t(common.cantUndoWarning)`,
includeAnalysis: 'Include result variables',
includeDataFromAllCycles: 'Include data from all cycles',
includeFiles: 'Include files',
includeFileAttributeDefs: 'Include file attribute columns',
includeInternalUuids: 'Include internal UUIDs',
recordsModifiedAfter: 'Records modified after',
},
optionsInfo: {
Expand Down Expand Up @@ -1725,7 +1727,7 @@ Levels will be renamed into level_1, level_2... level_N and an extra 'area' prop
keyDuplicate: 'Duplicate record key',
entityKeyDuplicate: 'Duplicate key',
entityKeyValueNotSpecified: 'Key value for "{{keyDefName}}" not specified',
missingAncestorForEntity: 'Cannot find ancestor "{{ancestorName}}" for entity "{{entityName}}"',
missingAncestorForEntity: 'Cannot find "{{ancestorName}}" with these keys: {{keyValues}}',
oneOrMoreInvalidValues: 'One or more values are invalid',
uniqueAttributeDuplicate: 'Duplicate value',
valueInvalid: 'Invalid value',
Expand Down
26 changes: 16 additions & 10 deletions core/record/_record/recordNodesUpdater.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ const { updateNodesDependents } = CoreRecordNodesUpdater

import { afterNodesUpdate } from './recordNodesUpdaterCommon'

const getKeyValuePairs = ({ survey, entityDef, valuesByDefUuid }) => {
const keyDefs = Survey.getNodeDefKeys(entityDef)(survey)
return keyDefs
.map((keyDef) => {
const keyDefUuid = NodeDef.getUuid(keyDef)
const keyDefName = NodeDef.getName(keyDef)
const value = valuesByDefUuid[keyDefUuid]
const keyValue = NodeValueFormatter.format({ survey, nodeDef: keyDef, value })
return `${keyDefName}=${keyValue}`
})
.join(',')
}

const _valueAdapterByType = {
[NodeDef.nodeDefType.code]: ({ survey, record, parentNode, attributeDef, value }) => {
if (value[Node.valuePropsCode.itemUuid]) {
Expand Down Expand Up @@ -126,16 +139,7 @@ const _getOrCreateEntityByKeys =
const entityDef = Survey.getNodeDefByUuid(entityDefUuid)(survey)

if (!insertMissingNodes) {
const keyDefs = Survey.getNodeDefKeys(entityDef)(survey)
const keyValuePairs = keyDefs
.map((keyDef) => {
const keyDefUuid = NodeDef.getUuid(keyDef)
const keyDefName = NodeDef.getName(keyDef)
const value = valuesByDefUuid[keyDefUuid]
const keyValue = NodeValueFormatter.format({ survey, nodeDef: keyDef, value })
return `${keyDefName}=${keyValue}`
})
.join(',')
const keyValuePairs = getKeyValuePairs({ survey, entityDef, valuesByDefUuid })
throw new SystemError('appErrors:record.entityNotFound', {
entityName: NodeDef.getName(entityDef),
keyValues: keyValuePairs,
Expand All @@ -153,9 +157,11 @@ const _getOrCreateEntityByKeys =
})(record)

if (!entityParent) {
const keyValuePairs = getKeyValuePairs({ survey, entityDef: entityParentDef, valuesByDefUuid })
throw new SystemError('validationErrors.record.missingAncestorForEntity', {
entityName: NodeDef.getName(entityDef),
ancestorName: NodeDef.getName(entityParentDef),
keyValues: keyValuePairs,
})
}
const { entity: entityInserted, updateResult } = _addEntityAndKeyValues({
Expand Down
24 changes: 2 additions & 22 deletions server/modules/dataExport/api/dataExportApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,7 @@ export const init = (app) => {
AuthMiddleware.requireRecordsExportPermission,
async (req, res, next) => {
try {
const {
surveyId,
cycle,
recordUuids,
search,
includeCategories,
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeDataFromAllCycles,
includeFiles,
recordsModifiedAfter,
} = Request.getParams(req)
const { surveyId, cycle, recordUuids, search, options } = Request.getParams(req)

const user = Request.getUser(req)

Expand All @@ -39,14 +26,7 @@ export const init = (app) => {
cycle,
recordUuids,
search,
includeCategories,
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeDataFromAllCycles,
includeFiles,
recordsModifiedAfter,
options,
})
res.json({ job: JobUtils.jobToJSON(job) })
} catch (error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export default class DataExportJob extends Job {
}

async _fetchSurvey() {
const { surveyId, cycle, includeAnalysis, includeDataFromAllCycles, expandCategoryItems } = this.context
const { surveyId, cycle, options } = this.context
const { includeAnalysis, includeDataFromAllCycles, expandCategoryItems } = options
const cycleToFetch = includeDataFromAllCycles ? undefined : cycle

return expandCategoryItems
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,7 @@ export default class CSVDataExtractionJob extends Job {
}

async execute() {
const {
survey,
cycle,
recordUuids,
search,
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeDataFromAllCycles,
includeFiles,
recordsModifiedAfter,
outputDir,
} = this.context
const { survey, cycle, recordUuids, search, options, outputDir } = this.context

await SurveyRdbService.fetchEntitiesDataToCsvFiles(
{
Expand All @@ -30,13 +17,7 @@ export default class CSVDataExtractionJob extends Job {
cycle,
recordUuids,
search,
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeDataFromAllCycles,
includeFiles,
recordsModifiedAfter,
options,
outputDir,
callback: ({ total }) => {
this.total = total
Expand Down
25 changes: 2 additions & 23 deletions server/modules/dataExport/service/dataExportService.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,14 @@
import * as JobManager from '@server/job/jobManager'
import DataExportJob from '@server/modules/dataExport/service/DataExportJob'

export const startCsvDataExportJob = ({
user,
surveyId,
cycle,
recordUuids,
search,
includeCategories,
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeDataFromAllCycles,
includeFiles,
recordsModifiedAfter,
}) => {
export const startCsvDataExportJob = ({ user, surveyId, cycle, recordUuids, search, options }) => {
const job = new DataExportJob({
user,
surveyId,
cycle,
recordUuids,
search,
includeCategories,
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeDataFromAllCycles,
includeFiles,
recordsModifiedAfter,
options,
})

JobManager.executeJobThread(job)
Expand Down
44 changes: 28 additions & 16 deletions server/modules/surveyRdb/manager/surveyRdbCsvExport.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as Survey from '@core/survey/survey'
import * as NodeDef from '@core/survey/nodeDef'
import * as CategoryItem from '@core/survey/categoryItem'

import { ArrayUtils } from '@core/arrayUtils'
import { Query } from '@common/model/query'
import { CsvDataExportModel } from '@common/model/csvExport'
import { ColumnNodeDef, ViewDataNodeDef } from '@common/model/db'
Expand Down Expand Up @@ -66,29 +67,40 @@ const getCsvExportFields = ({
addCycle = false,
includeCategoryItemsLabels = true,
expandCategoryItems = false,
includeInternalUuids = false,
}) => {
const entityDef = Survey.getNodeDefByUuid(Query.getEntityDefUuid(query))(survey)
const viewDataNodeDef = new ViewDataNodeDef(survey, entityDef)

// Consider only user selected fields (from column node defs)
const nodeDefUuidCols = Query.getAttributeDefUuids(query)
const nodeDefCols = Survey.getNodeDefsByUuids(nodeDefUuidCols)(survey)
const fields = nodeDefCols.flatMap((nodeDefCol) => {
const columnNodeDef = new ColumnNodeDef(viewDataNodeDef, nodeDefCol)
const fieldsExtractor = fieldsExtractorByNodeDefType[NodeDef.getType(nodeDefCol)]
if (fieldsExtractor) {
return fieldsExtractor({
survey,
columnNodeDef,
includeCategoryItemsLabels,
expandCategoryItems,
})
} else {
return columnNodeDef.names
}
})
// Cycle is 0-based
return [...(addCycle ? [DataTable.columnNameRecordCycle] : []), ...fields]
const fields = []
if (includeInternalUuids) {
ArrayUtils.addIfNotEmpty(viewDataNodeDef.columnParentUuidName)(fields)
fields.push(viewDataNodeDef.columnUuidName)
}
if (addCycle) {
// Cycle is 0-based
fields.push(DataTable.columnNameRecordCycle)
}
fields.push(
...nodeDefCols.flatMap((nodeDefCol) => {
const columnNodeDef = new ColumnNodeDef(viewDataNodeDef, nodeDefCol)
const fieldsExtractor = fieldsExtractorByNodeDefType[NodeDef.getType(nodeDefCol)]
if (fieldsExtractor) {
return fieldsExtractor({
survey,
columnNodeDef,
includeCategoryItemsLabels,
expandCategoryItems,
})
} else {
return columnNodeDef.names
}
})
)
return fields
}

const getCsvExportFieldsAgg = ({ survey, query }) => {
Expand Down
31 changes: 20 additions & 11 deletions server/modules/surveyRdb/manager/surveyRdbManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const fetchViewData = async (params, client = db) => {
addCycle = false,
includeCategoryItemsLabels = true,
expandCategoryItems = false,
includeInternalUuids = false,
nullsToEmpty = false,
} = params

Expand Down Expand Up @@ -107,6 +108,7 @@ export const fetchViewData = async (params, client = db) => {
addCycle,
includeCategoryItemsLabels,
expandCategoryItems,
includeInternalUuids,
})
await db.stream(result, (dbStream) => {
const csvTransform = CSVWriter.transformJsonToCsv({
Expand Down Expand Up @@ -167,8 +169,8 @@ export const fetchViewDataAgg = async (params) => {
return result
}

const _determineRecordUuidsFilter = async ({ survey, cycle, recordsModifiedAfter, recordUuidsParam, search }) => {
if (recordUuidsParam) return recordUuidsParam
const _determineRecordUuidsFilter = async ({ survey, cycle, recordsModifiedAfter, recordUuids, search }) => {
if (recordUuids) return recordUuids

if (Objects.isEmpty(search) && !recordsModifiedAfter) return null

Expand All @@ -194,20 +196,26 @@ export const fetchEntitiesDataToCsvFiles = async (
{
survey,
cycle,
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeFiles,
search = null,
recordOwnerUuid = null,
recordUuids: recordUuidsParam = null,
recordsModifiedAfter,
search = null,
options,
outputDir,
callback,
},
client = db
) => {
const {
includeCategoryItemsLabels,
expandCategoryItems,
includeAncestorAttributes,
includeAnalysis,
includeFileAttributeDefs,
includeFiles,
includeInternalUuids,
recordsModifiedAfter,
} = options

const addCycle = Survey.getCycleKeys(survey).length > 1

const nodeDefs = Survey.findDescendants({
Expand All @@ -218,7 +226,7 @@ export const fetchEntitiesDataToCsvFiles = async (
survey,
cycle,
recordsModifiedAfter,
recordUuidsParam,
recordUuids: recordUuidsParam,
search,
})

Expand Down Expand Up @@ -249,7 +257,7 @@ export const fetchEntitiesDataToCsvFiles = async (
? getChildAttributes(nodeDefContext)
: // Multiple attribute
[nodeDefContext]
).filter((childDef) => includeFiles || !NodeDef.isFile(childDef))
).filter((childDef) => includeFileAttributeDefs || includeFiles || !NodeDef.isFile(childDef))

const ancestorDefs = []
if (includeAncestorAttributes) {
Expand Down Expand Up @@ -281,6 +289,7 @@ export const fetchEntitiesDataToCsvFiles = async (
addCycle,
includeCategoryItemsLabels,
expandCategoryItems,
includeInternalUuids,
},
client
)
Expand Down
Loading

0 comments on commit d5dbc3b

Please sign in to comment.