-
Notifications
You must be signed in to change notification settings - Fork 47
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pkp/pkp-lib#8248 COUNTER R5 TSV reports
- Loading branch information
Showing
3 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
208
src/components/ListPanel/counter/CounterReportsListPanel.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |