forked from pkp/ui-library
-
Notifications
You must be signed in to change notification settings - Fork 0
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
379 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'; | ||
import Page from '@/components/Container/Page'; | ||
export default { | ||
name: 'CounterReportsPage', | ||
extends: Page, | ||
components: { | ||
CounterReportsListPanel, | ||
}, | ||
}; | ||
</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,157 @@ | ||
<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': | ||
params.customer_id = value; | ||
break; | ||
case 'begin_date': | ||
params.begin_date = value; | ||
break; | ||
case 'end_date': | ||
params.end_date = value; | ||
break; | ||
case 'metric_type': | ||
if (value != null && value.length > 0) { | ||
params.metric_type = value.join('|'); | ||
} | ||
break; | ||
case 'attributes_to_show': | ||
if (value != null && value.length > 0) { | ||
params.attributes_to_show = value.join('|'); | ||
} | ||
break; | ||
case 'yop': | ||
if (value != null && value.length > 0) { | ||
params.yop = value; | ||
} | ||
break; | ||
case 'item_id': | ||
if (value != null && value.length > 0) { | ||
params.item_id = value; | ||
} | ||
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; | ||
} | ||
if (this.action === 'emit') { | ||
this.$emit('success', this.submitValues); | ||
} else { | ||
this.isDownloadingReport = true; | ||
let downloadFileName = 'counterReport.tsv'; | ||
$.ajax({ | ||
context: this, | ||
method: this.method, | ||
url: this.action, | ||
type: 'GET', | ||
headers: { | ||
Accept: 'text/tab-separated-values; charset=utf-8', | ||
'Content-Type': 'text/tab-separated-values;·charset_utf-8', | ||
}, | ||
data: this.getReportParams(this.submitValues), | ||
error(r) { | ||
this.isDownloadingReport = 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) { | ||
var blob = new Blob([r]); | ||
var link = document.createElement('a'); | ||
link.href = window.URL.createObjectURL(blob); | ||
link.download = downloadFileName; | ||
link.click(); | ||
this.isDownloadingReport = false; | ||
this.$modal.hide('form'); | ||
}, | ||
}); | ||
} | ||
}, | ||
}, | ||
}; | ||
</script> |
210 changes: 210 additions & 0 deletions
210
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,210 @@ | ||
<template> | ||
<div class="counterReportsListPanel"> | ||
<slot> | ||
<list-panel :items="items"> | ||
<pkp-header slot="header"> | ||
<h2>{{ title }}</h2> | ||
<spinner v-if="isLoading" /> | ||
</pkp-header> | ||
<template v-slot:item-title="{item}"> | ||
<span :id="item.Report_ID"> | ||
{{ item.Report_Name }} ({{ item.Report_ID }}) | ||
</span> | ||
</template> | ||
<template v-slot:item-actions="{item}"> | ||
<pkp-button | ||
:aria-describedby="item.Report_ID" | ||
@click="openEditModal(item.Report_ID)" | ||
> | ||
{{ __('common.edit') }} | ||
</pkp-button> | ||
</template> | ||
</list-panel> | ||
<modal | ||
:closeLabel="__('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, | ||
}; | ||
}, | ||
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. | ||
* | ||
* @param {Object} item | ||
*/ | ||
formSuccess(item) { | ||
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; | ||
}, | ||
}, | ||
mounted() { | ||
/** | ||
* Load the items | ||
*/ | ||
this.getItems(); | ||
}, | ||
}; | ||
</script> | ||
|
||
<style lang="less"> | ||
@import '../../../styles/_import'; | ||
.counterReportsListPanel { | ||
.listPanel__itemTitle { | ||
font-weight: @normal; | ||
} | ||
} | ||
</style> |