Improvements to heatmap construction. #483.

This commit is contained in:
mateuswetah 2021-03-11 14:29:24 -03:00
parent 3b63528305
commit 1b83b54743
8 changed files with 172 additions and 7 deletions

View File

@ -1,4 +1,6 @@
#tainacan-reports-app .tainacan-icon::before {
#tainacan-reports-app {
margin: 10px 2px 10px 2px; }
#tainacan-reports-app .tainacan-icon::before {
opacity: 0.0; }
/*# sourceMappingURL=tainacan-reports.css.map */

View File

@ -1,6 +1,6 @@
{
"version": 3,
"mappings": "AAEI,4CAAuB;EACnB,OAAO,EAAE,GAAG",
"mappings": "AAAA,qBAAsB;EAClB,MAAM,EAAE,iBAAiB;EAGzB,4CAAuB;IACnB,OAAO,EAAE,GAAG",
"sources": ["../../views/reports/tainacan-reports.scss"],
"names": [],
"file": "tainacan-reports.css"

View File

@ -485,7 +485,7 @@ class REST_Reports_Controller extends REST_Controller {
$response['totals'] = array(
'last_year' => array(
'genreal' => $this->get_activities_general($collection_id),
'general' => $this->get_activities_general($collection_id),
'by_user' => $this->get_activities_general_by_user($collection_id)
),
'by_user' => $this->get_activities_users($collection_id)

View File

@ -110,3 +110,24 @@ export const fetchTaxonomyTerms = ({ commit }, taxonomyId) => {
.catch(error => reject(error));
});
};
export const fetchActivities = ({ commit }, { collectionId } ) => {
let endpoint = '/reports';
if (collectionId && collectionId != 'default')
endpoint += '/collection/' + collectionId + '/activities';
else
endpoint += '/activities';
return new Promise((resolve, reject) => {
axios.tainacan.get(endpoint)
.then(res => {
let activities = res.data;
commit('setActivities', activities);
resolve(activities);
})
.catch(error => reject(error));
});
};

View File

@ -22,6 +22,10 @@ export const getTaxonomyTerms = state => {
return state.taxonomyTerms;
};
export const getActivities = state => {
return state.activities;
};
export const getStackedBarChartOptions = state => {
return state.stackedBarChartOptions;
};
@ -33,3 +37,7 @@ export const getHorizontalBarChartOptions = state => {
export const getDonutChartOptions = state => {
return state.donutChartOptions;
};
export const getHeatMapChartOptions = state => {
return state.heatMapChartOptions;
};

View File

@ -9,6 +9,7 @@ const state = {
taxonomyTerms: {},
metadata: {},
metadataList: {},
activities: {},
stackedBarChartOptions: {
chart: {
type: 'bar',
@ -132,6 +133,18 @@ const state = {
horizontalAlign: 'left',
offsetX: 40,
}
},
heatMapChartOptions: {
chart: {
height: 350,
type: 'heatmap',
},
dataLabels: {
enabled: false
},
title: {
text: ''
},
}
};

View File

@ -22,6 +22,10 @@ export const setTaxonomyTerms = (state, taxonomyTerms) => {
state.taxonomyTerms = taxonomyTerms;
};
export const setActivities = (state, activities) => {
state.activities = activities;
};
export const setStackedBarChartOptions = (state, stackedBarChartOptions) => {
state.stackedBarChartOptions = stackedBarChartOptions;
};
@ -33,3 +37,7 @@ export const setHorizontalBarChartOptions = (state, horizontalBarChartOptions) =
export const setDonutChartOptions = (state, donutChartOptions) => {
state.donutChartOptions = donutChartOptions;
};
export const setHeatMapChartOptions = (state, heatMapChartOptions) => {
state.heatMapChartOptions = heatMapChartOptions;
};

View File

@ -170,6 +170,21 @@
style="min-height=380px"
class="skeleton postbox" />
</div>
<div
v-if="activities != undefined"
class="column is-full">
<apexchart
v-if="!isFetchingActivities"
height="380px"
class="postbox"
type="heatmap"
:series="activitiesChartSeries"
:options="activitiesChartOptions" />
<div
v-else
style="min-height=380px"
class="skeleton postbox" />
</div>
</div>
</div>
</template>
@ -191,6 +206,7 @@ export default {
isFetchingTaxonomyTerms: false,
isFetchingMetadata: false,
isFetchingMetadataList: false,
isFetchingActivities: false,
collectionsListChartSeries: [],
collectionsListChartOptions: {},
taxonomiesListChartSeries: [],
@ -203,7 +219,9 @@ export default {
metadataTypeChartOptions: {},
metadataDistributionChartSeries: [],
metadataDistributionChartOptions: {},
metadataDistributionChartHeight: 730
metadataDistributionChartHeight: 730,
activitiesChartSeries: [],
activitiesChartOptions: {}
}
},
computed: {
@ -217,9 +235,11 @@ export default {
taxonomyTerms: 'getTaxonomyTerms',
taxonomiesList: 'getTaxonomiesList',
collectionsList: 'getCollectionsList',
activities: 'getActivities',
stackedBarChartOptions: 'getStackedBarChartOptions',
donutChartOptions: 'getDonutChartOptions',
horizontalBarChartOptions: 'getHorizontalBarChartOptions'
horizontalBarChartOptions: 'getHorizontalBarChartOptions',
heatMapChartOptions: 'getHeatMapChartOptions'
}),
taxonomiesListArray() {
return this.taxonomiesList && this.taxonomiesList != undefined ? Object.values(this.taxonomiesList) : [];
@ -234,6 +254,7 @@ export default {
this.selectedCollection = to['collection'] ? to['collection'] : 'default';
this.loadSummary();
this.loadMetadata();
this.loadActivities();
if (!this.selectedCollection || this.selectedCollection == 'default') {
this.loadCollectionsList();
@ -269,7 +290,8 @@ export default {
'fetchTaxonomiesList',
'fetchTaxonomyTerms',
'fetchMetadata',
'fetchMetadataList'
'fetchMetadataList',
'fetchActivities'
]),
loadCollections() {
this.isFetchingCollections = true;
@ -578,6 +600,97 @@ export default {
this.isFetchingMetadataList = false;
})
.catch(() => this.isFetchingMetadataList = false);
},
loadActivities() {
this.isFetchingActivities = true;
this.fetchActivities({ collectionId: this.selectedCollection })
.then(() => {
const daysWithActivities = this.activities && this.activities.totals && this.activities.totals.last_year && this.activities.totals.last_year.general ? this.activities.totals.last_year.general : [];
if (daysWithActivities && daysWithActivities.length) {
let everyDayOfTheYear = Array.from(new Array(7),
(val,index) => {
return {
name: (index + 1),
data: new Array(53).fill({x: '', y: 0})
}
}
);
const firstDayOfTheWeekWithActivity = parseInt(daysWithActivities[0].day_of_week);
let dayWithActivityIndex = 0;
let daysToSkip = 0;
// Loop for each column (number of the week in the year)
for (let column = 0; column < 53; column++) {
// Loop for each line (number of the day in the week)
for (let line = 0; line < 7; line++) {
// If there are no more days with activities, get outta here
if (dayWithActivityIndex >= daysWithActivities.length)
break;
// We should only begin inserting days from firstDayOfTheWeekWithActivity
if (column == 0 && line < firstDayOfTheWeekWithActivity - 1) {
continue;
// On the first day, we don't need to calculate distances, just set the value and save the date
} else if (column == 0 && line == firstDayOfTheWeekWithActivity - 1) {
everyDayOfTheYear[line].data[column] = {
x: '',
y: parseInt(daysWithActivities[dayWithActivityIndex].total)
};
const lastDayWithActivity = new Date(daysWithActivities[dayWithActivityIndex].year, daysWithActivities[dayWithActivityIndex].month - 1, daysWithActivities[dayWithActivityIndex].day);
dayWithActivityIndex++;
const nextDayWithActivity = new Date(daysWithActivities[dayWithActivityIndex].year, daysWithActivities[dayWithActivityIndex].month - 1, daysWithActivities[dayWithActivityIndex].day);
daysToSkip = Math.floor( (nextDayWithActivity - lastDayWithActivity) / (1000 * 60 * 60 * 24) );
} else {
daysToSkip--;
// If we don't have more days to skip, time to update values
if ( daysToSkip <= 0) {
everyDayOfTheYear[line].data[column] = {
x: '',
y: parseInt(daysWithActivities[dayWithActivityIndex].total)
};
const lastDayWithActivity = new Date(daysWithActivities[dayWithActivityIndex].year, daysWithActivities[dayWithActivityIndex].month - 1, daysWithActivities[dayWithActivityIndex].day);
dayWithActivityIndex++;
const nextDayWithActivity = new Date(daysWithActivities[dayWithActivityIndex].year, daysWithActivities[dayWithActivityIndex].month - 1, daysWithActivities[dayWithActivityIndex].day);
daysToSkip = Math.floor( (nextDayWithActivity - lastDayWithActivity) / (1000 * 60 * 60 * 24) );
console.log(daysToSkip, nextDayWithActivity, lastDayWithActivity);
}
}
}
}
this.activitiesChartSeries = everyDayOfTheYear();
this.activitiesChartOptions = {
...this.heatMapChartOptions,
title: {
text: this.$i18n.get('label_activities_last_year')
},
}
} else {
this.activitiesChartSeries = [];
this.activitiesChartOptions = {
...this.heatMapChartOptions,
title: {
text: this.$i18n.get('label_activities_last_year')
},
}
}
this.isFetchingActivities = false;
})
.catch(() => this.isFetchingActivities = false);
}
}
}