Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FORMS-844: Add ability to subset submissions for export #1007

Closed
wants to merge 8 commits into from
23 changes: 19 additions & 4 deletions app/frontend/src/components/forms/ExportSubmissions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
</v-radio-group>
</v-col>
</v-row>
<v-row v-if="exportFormat === 'csv'" class="mt-5">
<v-row v-if="exportFormat === 'csv' && !selectedVersion" class="mt-5">
<v-col>
<span class="subTitleObjectStyle" :lang="lang">
{{ $t('trans.exportSubmissions.formVersion') }}
Expand Down Expand Up @@ -408,6 +408,8 @@ export default {
'submissionList',
'isRTL',
'lang',
'selectedSubmissions',
'selectedVersion',
]),

...mapGetters('auth', ['email']),
Expand All @@ -426,7 +428,12 @@ export default {
},
methods: {
...mapActions('notifications', ['addNotification']),
...mapActions('form', ['fetchForm', 'fetchFormCSVExportFields']),
...mapActions('form', [
'fetchForm',
'fetchFormCSVExportFields',
'selectSubmissions',
'selectVersion',
]),
async changeVersions(value) {
this.versionRequired = false;
value !== ''
Expand Down Expand Up @@ -503,7 +510,8 @@ export default {
// drafts: true
},
fieldToExport,
emailExport
emailExport,
this.selectedSubmissions
);

if (response && response.data && !emailExport) {
Expand Down Expand Up @@ -531,6 +539,9 @@ export default {
`${this.form.id}: ${error}`,
});
}
// empty selected submissions for export if there are so
this.selectSubmissions('');
this.selectVersion(null);
},

async updateVersions() {
Expand All @@ -553,7 +564,11 @@ export default {
this.versions.push(
...this.form.versions.map((version) => version.version)
);
this.versionSelected = this.versions[0];
if (this.selectedVersion) {
this.versionSelected = this.selectedVersion;
} else {
this.versionSelected = this.versions[0];
}
await this.refreshFormFields(this.versionSelected);
}
},
Expand Down
42 changes: 41 additions & 1 deletion app/frontend/src/components/forms/SubmissionsTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,17 @@
</template>
</v-checkbox>
</div>
<div>
<span class="subTitleObjectStyle" :lang="lang">
{{ $t('trans.exportSubmissions.formVersion') }}
</span>
<v-select
v-model="versionSelected"
:items="versions"
@change="changeVersions"
class="mt-0"
></v-select>
</div>
<div>
<!-- search input -->
<div class="submissions-search">
Expand Down Expand Up @@ -387,12 +398,24 @@ export default {
deleteItem: {},
switchSubmissionView: false,
firstDataLoad: true,
versionSelected: null,
};
},
computed: {
multiDeleteMessage() {
return this.$t('trans.submissionsTable.multiDelWarning');
},
versions() {
const formVersions = [
{ text: this.$t('trans.exportSubmissions.all'), value: null },
];
if (this.form?.versions) {
this.form.versions.map((v) => {
formVersions.push(v.version);
});
}
return formVersions;
},
singleDeleteMessage() {
return this.$t('trans.submissionsTable.singleDelWarning');
},
Expand All @@ -412,7 +435,6 @@ export default {
'submissionList',
'userFormPreferences',
'roles',
'deletedSubmissions',
'isRTL',
'lang',
'totalSubmissions',
Expand Down Expand Up @@ -622,6 +644,16 @@ export default {
}
},
},
watch: {
selectedSubmissions(newValue) {
if (newValue && newValue.length > 0 && this.versionSelected) {
this.selectSubmissions(
newValue.map((val) => val.submissionId).join(',')
);
this.selectVersion(this.versionSelected);
}
},
},
methods: {
...mapActions('form', [
'fetchForm',
Expand All @@ -635,6 +667,8 @@ export default {
'restoreMultiSubmissions',
'deleteSubmission',
'updateFormPreferencesForCurrentUser',
'selectSubmissions',
'selectVersion',
]),
...mapActions('notifications', ['addNotification']),

Expand Down Expand Up @@ -734,6 +768,7 @@ export default {
: moment().add(50, 'years').utc().format('YYYY-MM-DD hh:mm:ss'), //Get User filter Criteria (Max Date)
}),
deletedOnly: this.deletedOnly,
version: this.versionSelected,
createdBy: this.currentUserOnly
? `${this.user.username}@${this.user.idp}`
: '',
Expand Down Expand Up @@ -805,6 +840,8 @@ export default {
})
.finally(() => {
this.selectedSubmissions = [];
this.selectSubmissions('');
this.selectVersion(null);
});
},

Expand Down Expand Up @@ -854,6 +891,9 @@ export default {
this.debounceInput();
}
},
async changeVersions() {
this.refreshSubmissions();
},
},
async mounted() {
this.debounceInput = _.debounce(async () => {
Expand Down
2 changes: 2 additions & 0 deletions app/frontend/src/services/formService.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,7 @@ export default {
preference,
fields,
emailExport = false,
selectedSubmissions,
options = {}
) {
return appAxios().post(
Expand All @@ -440,6 +441,7 @@ export default {
preference: preference,
fields: fields,
emailExport,
selectedSubmissions,
...options,
},
{
Expand Down
18 changes: 18 additions & 0 deletions app/frontend/src/store/modules/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ export default {
isRTL: false,
subscriptionData: genInitialSubscribeDetails(),
totalSubmissions: 0,
selectedSubmissions: '',
selectedVersion: null,
},
getters: {
getField, // vuex-map-fields
Expand All @@ -127,6 +129,8 @@ export default {
isRTL: (state) => state.isRTL,
subscriptionData: (state) => state.subscriptionData,
totalSubmissions: (state) => state.totalSubmissions,
selectedSubmissions: (state) => state.selectedSubmissions,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to start improving the code coverage of the unit tests. Can you check the coverage reports in the actions (or run the tests locally and check app/frontend/coverage/lcov-report/index.html and app/coverage/lcov-report/index.html) to make sure there are tests for anything that is added?

(Although a lot of the tests are fairly simple and don't add a lot of value, it'll make it easier to identify missing coverage if we follow what the original team did for tests)

selectedVersion: (state) => state.selectedVersion,
},
mutations: {
updateField, // vuex-map-fields
Expand Down Expand Up @@ -203,6 +207,12 @@ export default {
SET_TOTALSUBMISSIONS(state, totalSubmissions) {
state.totalSubmissions = totalSubmissions;
},
SET_SELECTED_SUBMISSIONS(state, selectedSubmissions) {
state.selectedSubmissions = selectedSubmissions;
},
SET_SELECTED_VERSION(state, selectedVersion) {
state.selectedVersion = selectedVersion;
},
},
actions: {
//
Expand Down Expand Up @@ -786,6 +796,7 @@ export default {
sortDesc: sortDesc,
search: search,
searchEnabled: searchEnabled,
version,
}
) {
try {
Expand All @@ -811,6 +822,7 @@ export default {
filterformSubmissionStatusCode: filterformSubmissionStatusCode,
itemsPerPage: itemsPerPage,
totalSubmissions: state.totalSubmissions,
version,
sortBy: sortBy,
sortDesc: sortDesc,
});
Expand Down Expand Up @@ -1080,5 +1092,11 @@ export default {
);
}
},
selectSubmissions({ commit }, selected) {
commit('SET_SELECTED_SUBMISSIONS', selected);
},
selectVersion({ commit }, selected) {
commit('SET_SELECTED_VERSION', selected);
},
},
};
12 changes: 9 additions & 3 deletions app/src/forms/common/models/views/submissionData.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ class SubmissionData extends Model {

static get modifiers() {
return {
filterVersion(query, value) {
if (value) {
query.where('version', value);
filterVersion(query, version, selectedSubmissions) {
// DO NOT need to filter by version if we filter by particular selected ids
if (version && (!selectedSubmissions || selectedSubmissions === '')) {
query.where('version', version);
}
},
filterCreatedAt(query, minDate, maxDate) {
Expand Down Expand Up @@ -45,6 +46,11 @@ class SubmissionData extends Model {
query.where('draft', false);
}
},
filterSubmissionIds(query, value) {
if (value && value !== '') {
query.whereIn('submissionId', value.split(','));
}
},
orderDefault(builder) {
builder.orderBy('createdAt', 'DESC');
},
Expand Down
3 changes: 2 additions & 1 deletion app/src/forms/form/exportService.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,13 @@ const service = {
return SubmissionData.query()
.select(service._submissionsColumns(form, params))
.where('formId', form.id)
.modify('filterVersion', version)
.modify('filterVersion', version, params.selectedSubmissions)
.modify('filterCreatedAt', preference && preference.minDate, preference && preference.maxDate)
.modify('filterUpdatedAt', preference && preference.updatedMinDate, preference && preference.updatedMaxDate)
.modify('filterStatus', params.status)
.modify('filterDeleted', params.deleted)
.modify('filterDrafts', params.drafts)
.modify('filterSubmissionIds', params.selectedSubmissions)
.modify('orderDefault')
.then((submissionData) => {
if (submissionData == undefined || submissionData == null || submissionData.length == 0) return [];
Expand Down
6 changes: 3 additions & 3 deletions app/tests/unit/forms/form/exportService.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ describe('_getSubmissions', () => {
}
exportService._getSubmissions(form, params, params.version);
expect(MockModel.query).toHaveBeenCalledTimes(1);
expect(MockModel.modify).toHaveBeenCalledTimes(7);
expect(MockModel.modify).toHaveBeenCalledTimes(8);
expect(MockModel.modify).toHaveBeenCalledWith('filterUpdatedAt', preference && preference.updatedMinDate, preference && preference.updatedMaxDate);
});

Expand All @@ -591,7 +591,7 @@ describe('_getSubmissions', () => {
exportService._submissionsColumns = jest.fn().mockReturnThis();
exportService._getSubmissions(form, params, params.version);
expect(MockModel.query).toHaveBeenCalledTimes(1);
expect(MockModel.modify).toHaveBeenCalledTimes(7);
expect(MockModel.modify).toHaveBeenCalledTimes(8);
});

it('Should pass this test with preference passed to _getSubmissions', async () => {
Expand All @@ -617,7 +617,7 @@ describe('_getSubmissions', () => {
}
exportService._getSubmissions(form, params, params.version);
expect(MockModel.query).toHaveBeenCalledTimes(1);
expect(MockModel.modify).toHaveBeenCalledTimes(7);
expect(MockModel.modify).toHaveBeenCalledTimes(8);
expect(MockModel.modify).toHaveBeenCalledWith('filterUpdatedAt', preference && preference.updatedMinDate, preference && preference.updatedMaxDate);
});
});
Loading