Skip to content

Commit

Permalink
pkp/pkp-lib#9666 COUNTER R5 TSV reports
Browse files Browse the repository at this point in the history
  • Loading branch information
bozana committed Oct 8, 2024
1 parent 9706e18 commit 15f5ba0
Show file tree
Hide file tree
Showing 3 changed files with 357 additions and 0 deletions.
12 changes: 12 additions & 0 deletions src/components/Container/CounterReportsPage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<script>
import CounterReportsListPanel from '@/components/ListPanel/counter/CounterReportsListPanel.vue';
import Page from '@/components/Container/Page.vue';
export default {
name: 'CounterReportsPage',
components: {
CounterReportsListPanel,
},
extends: Page,
};
</script>
137 changes: 137 additions & 0 deletions src/components/Form/counter/CounterReportForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
<script>
import PkpForm from '@/components/Form/Form.vue';
export default {
name: 'CounterReportForm',
extends: PkpForm,
components: {
PkpForm,
},
props: {
reportId: {
type: String,
required: false,
},
reportFields: {
type: Array,
required: true,
},
earliestDate: {
type: String,
required: true,
},
lastDate: {
type: String,
required: true,
},
},
methods: {
/**
* Get the report parameters
*
* @param Object
* @return Object
*/
getReportParams(formSubmitValues) {
let params = {};
for (const [key, value] of Object.entries(formSubmitValues)) {
switch (key) {
case 'customer_id':
case 'begin_date':
case 'end_date':
case 'yop':
case 'item_id':
if (value != null && value.length > 0) {
params[key] = value;
}
break;
case 'metric_type':
case 'attributes_to_show':
if (value != null && value.length > 0) {
params[key] = value.join('|');
}
break;
case 'include_parent_details':
if (value == true) {
params.include_parent_details = 'True';
}
break;
case 'granularity':
if (value == true) {
params.granularity = 'Totals';
}
break;
}
}
return params;
},
/**
* Submit the form
*/
submit() {
if (!this.canSubmit) {
return false;
}
let errors = this.validate();
if (Object.keys(errors).length) {
this.$emit('set', this.id, {
errors: {
...this.errors,
...errors,
},
});
return;
}
this.isSaving = true;
$.ajax({
context: this,
method: this.method,
url: this.action,
headers: {
Accept: 'text/tab-separated-values; charset=utf-8',
},
data: this.getReportParams(this.submitValues),
error(r) {
this.isSaving = false;
if (r.status && r.status === 400) {
if (r.responseJSON.hasOwnProperty('Code')) {
// COUNTER speific errors should actually not occur
// because of the form/user input validation
// but consider them for any case as well.
pkp.eventBus.$emit(
'notify',
r.responseJSON.Code +
':' +
r.responseJSON.Message +
'(' +
r.responseJSON.Data +
')',
'warning'
);
} else {
// Field validation errors
this.$emit('set', this.id, {errors: r.responseJSON});
}
} else {
this.error(r);
}
},
success(r) {
this.$emit('success', r);
var blob = new Blob([r]);
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'counterReport.tsv';
link.click();
this.isSaving = false;
pkp.eventBus.$emit('form-success', this.id, r);
},
});
},
},
};
</script>
208 changes: 208 additions & 0 deletions src/components/ListPanel/counter/CounterReportsListPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
<template>
<div class="counterReportsListPanel">
<slot>
<list-panel :items="items">
<pkp-header>
<h2>{{ title }}</h2>
<spinner v-if="isLoading" />
</pkp-header>
<template #item-title="{item}">
<span :id="item.Report_ID">
{{ item.Report_Name }} ({{ item.Report_ID }})
</span>
</template>
<template #item-actions="{item}">
<pkp-button
:aria-describedby="item.Report_ID"
@click="openEditModal(item.Report_ID)"
>
{{ __('common.edit') }}
</pkp-button>
</template>
</list-panel>
<modal
:close-label="__('common.close')"
name="form"
:title="activeFormTitle"
@closed="formModalClosed"
>
<counter-report-form
v-bind="activeForm"
@set="updateForm"
@success="formSuccess"
/>
</modal>
</slot>
</div>
</template>

<script>
import ListPanel from '@/components/ListPanel/ListPanel.vue';
import CounterReportForm from '@/components/Form/counter/CounterReportForm.vue';
import PkpHeader from '@/components/Header/Header.vue';
import Modal from '@/components/Modal/Modal.vue';
import ajaxError from '@/mixins/ajaxError';
import fetch from '@/mixins/fetch';
import cloneDeep from 'clone-deep';
export default {
components: {
ListPanel,
CounterReportForm,
PkpHeader,
Modal,
},
mixins: [fetch, ajaxError],
props: {
editCounterReportLabel: {
type: String,
required: true,
},
form: {
type: Object,
required: true,
},
id: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
},
data() {
return {
items: [],
isLoadingItems: false,
latestItemsGetRequest: '',
isDownloadingReport: false,
activeForm: null,
activeFormTitle: '',
resetFocusTo: null,
};
},
mounted() {
/**
* Load the items
*/
this.getItems();
},
methods: {
/**
* Get the list of items from the server
*/
getItems() {
let self = this;
this.isLoadingItems = true;
this.latestItemsGetRequest = $.pkp.classes.Helper.uuid();
$.ajax({
url: this.apiUrl + '/reports',
type: 'GET',
data: [],
_uuid: this.latestItemsGetRequest,
error(r) {
if (self.latestItemsGetRequest !== this._uuid) {
return;
}
self.ajaxErrorCallback(r);
},
success(r) {
if (self.latestItemsGetRequest !== this._uuid) {
return;
}
self.setItems(r);
},
complete(r) {
if (self.latestItemsGetRequest !== this._uuid) {
return;
}
self.isLoadingItems = false;
},
});
},
/**
* Clear the active form when the modal is closed
*
* @param {Object} event
*/
formModalClosed(event) {
this.activeForm = null;
this.activeFormTitle = '';
if (this.resetFocusTo) {
this.resetFocusTo.focus();
}
},
/**
* The edit form has been successfully
* submitted.
*/
formSuccess() {
this.$modal.hide('form');
},
/**
* Open the modal to edit an item
*
* @param {Number} id
*/
openEditModal(id) {
this.resetFocusTo = document.activeElement;
const report = this.items.find((report) => report.Report_ID === id);
if (!report) {
this.ajaxErrorCallback({});
return;
}
let activeForm = cloneDeep(this.form);
activeForm.reportId = id;
activeForm.action = this.apiUrl + '/' + report.Path;
activeForm.method = 'GET';
activeForm.fields = activeForm.reportFields[id];
this.activeForm = activeForm;
this.activeFormTitle = this.editCounterReportLabel;
this.$modal.show('form');
},
/**
* Set the list of items
*
* @see @/mixins/fetch.js
* @param {Array} result
*/
setItems(result) {
let self = this;
self.items = result;
},
/**
* Update form values when they change
*
* @param {String} formId
* @param {Object} data
*/
updateForm(formId, data) {
let activeForm = {...this.activeForm};
Object.keys(data).forEach(function (key) {
activeForm[key] = data[key];
});
this.activeForm = activeForm;
},
},
};
</script>

<style lang="less">
@import '../../../styles/_import';
.counterReportsListPanel {
.listPanel__itemTitle {
font-weight: @normal;
}
}
</style>

0 comments on commit 15f5ba0

Please sign in to comment.