passing labels in echart line graph - flask

I have a line chart that gets data from the back end. I am able to plot the data but not the labels from the back end. This is my code:
import {Line} from 'vue-chartjs'
import axios from 'axios';
export default {
extends: Line,
props: ["data"],
methods: {
getScore() {
axios({
method: 'get',
url: 'http://localhost:5000/time',
}).then((response) => {
this.renderChart(
{
labels: [],
datasets: [
{
labels: response.data.score,
label: 'Stream',
backgroundColor: "#42c9d5",
data: response.data.score
}
]
},
{responsive: true, maintainApsectRatio: false}
)
})
.catch((error) => {
// eslint-disable-next-line
console.error(error);
});
}
},
mounted() {
this.getScore();
}
}
because I am getting the data from the getScore method. how Can I get the labels from another method? Or do I need to send two json responses? Also how do I loop through the json responses inside the this.renderchart?

I figured out how to do it. For those interested I passed a list of of dictionaries from the back end:
#app.route('/time')
def timeData():
response_object = {'status': 'success'}
SCORES = []
score = {}
score["value"] = [23,38,12]
score["date"] = ["Jan", "Feb", "Mar"]
SCORES.append(score)
response_object['score'] = SCORES
return jsonify(response_object)
I then added ... before the date key value pair:
import {Line} from 'vue-chartjs'
import axios from 'axios';
export default {
extends: Line,
props: ["data"],
methods: {
getScore() {
axios({
method: 'get',
url: 'http://localhost:5000/time',
}).then((response) => {
this.renderChart(
{
labels: [...response.data.score[0].date],
datasets: [
{
label: 'Stream',
backgroundColor: "#42c9d5",
data: response.data.score[0].value
}
]
},
{responsive: true, maintainApsectRatio: false}
)
})
.catch((error) => {
// eslint-disable-next-line
console.error(error);
});
}
},
mounted() {
this.getScore();
}

Related

Mirage server GETs data but POST fails

I have the mirage models:
// mirage/models/country.js
import { Model, belongsTo, hasMany } from 'miragejs';
export default Model.extend({
name: '',
iso3166_1_alpha3: '',
capitol_city: belongsTo('city', {inverse: null}),
cities: hasMany('city', {inverse: 'country'})
});
and:
// mirage/models/city.js
import { Model, belongsTo } from 'miragejs';
export default Model.extend({
name: '',
country: belongsTo('country', {inverse: 'cities'})
});
and the serializer:
// mirage/serializers/application.js
import { camelize, capitalize, underscore } from '#ember/string';
import { JSONAPISerializer } from 'miragejs';
export default class ApplicationSerializer extends JSONAPISerializer
{
alwaysIncludeLinkageData = true;
keyForAttribute(attr) {
return underscore(attr);
};
keyForRelationship(modelName) {
return underscore(modelName);
};
typeKeyForModel(model) {
return capitalize(camelize(model.modelName));
};
};
When I run the tests:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
module('Unit | Mirage | mirage models', function (hooks) {
setupTest(hooks);
setupMirage(hooks);
test('it retrieves the country', async function (assert) {
const server = this.server;
let city = server.create('city', { id: '1', name: 'Paris' });
server.create(
'country',
{
id: 'FR',
name: 'France',
iso3166_1_alpha3: 'FRA',
capitol_city: city
}
);
let response = await fetch('/api/countries')
assert.strictEqual(response.status, 200, "Should have created the model");
let json = await response.json();
assert.deepEqual(
json,
{
data: [
{
type: 'Country',
id: 'FR',
attributes: {
name: 'France',
iso3166_1_alpha3: 'FRA',
},
relationships: {
capitol_city: {data: {type: 'City', id: '1'}},
cities: {data: []},
}
}
]
}
)
});
test('it creates the country', async function (assert) {
const server = this.server;
server.create('city', { id: '1', name: 'Paris' });
let response = await fetch(
'/api/countries',
{
method: 'POST',
headers: {'Countent-Type': 'application/json'},
body: JSON.stringify(
{
data: {
id: 'FR',
type: 'Country',
attributes: {
iso3166_1_alpha3: 'FRA',
name: 'France',
},
relationships: {
capitol_city: { data: { type: 'City', id: '1'} },
cities: { data: [{ type: 'City', id: '1'}] }
}
}
}
)
}
);
console.log((await response.json()).message);
assert.strictEqual(response.status, 201, "Should have created the model");
});
});
The first one passes and the second one fails with the message:
Mirage: You're passing the relationship 'capitol_city' to the 'country' model via a POST to '/api/countries', but you did not define the 'capitol_city' association on the 'country' model.
How can I get Mirage to recognise the capitol_city attribute on the model?
Mirage is opinionated with regards to the format of attributes and expects the attributes to be in camelCase (and not snake_case).
Unfortunately the Ember CLI Mirage model relationships documentation does not mention this expectation and all the examples use single-word attributes. Even more unfortunately, Mirage will work with snake_case attributes for simple GET requests and when directly creating models through the API; it is only when you make a request to POST/PUT/PATCH a model into the server that it fails and the message will (confusingly) refer to the snake case attribute which has been defined. (See the Mirage source code for where it fails.)
To solve it, convert the attributes to camel case:
// mirage/models/country.js
import { Model, belongsTo, hasMany } from 'miragejs';
export default Model.extend({
name: '',
iso31661Alpha3: 0,
capitolCity: belongsTo('city', {inverse: null}),
cities: hasMany('city', {inverse: 'country'})
});
and change it in the tests as well:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { setupMirage } from 'ember-cli-mirage/test-support';
module('Unit | Mirage | mirage models', function (hooks) {
setupTest(hooks);
setupMirage(hooks);
test('it retrieves the country', async function (assert) {
const server = (this as any).server;
let city = server.create('city', { id: '1', name: 'Paris' });
server.create(
'country',
{
id: 'FR',
name: 'France',
iso31661Alpha3: 'FRA',
capitolCity: city
}
);
let response = await fetch('/api/countries')
assert.strictEqual(response.status, 200, "Should have created the model");
let json = await response.json();
console.log(JSON.stringify(json));
assert.deepEqual(
json,
{
data: [
{
type: 'Country',
id: 'FR',
attributes: {
name: 'France',
iso3166_1_alpha3: 'FRA',
},
relationships: {
capitol_city: {data: {type: 'City', id: '1'}},
cities: {data: []},
}
}
]
}
)
});
test('it creates the country', async function (assert) {
const server = (this as any).server;
let city = server.create('city', { id: '1', name: 'Paris' });
let response = await fetch(
'/api/countries',
{
method: 'POST',
headers: {'Countent-Type': 'application/json'},
body: JSON.stringify(
{
data: {
id: 'FR',
type: 'Country',
attributes: {
iso3166_1_alpha3: 'FRA',
name: 'France',
},
relationships: {
capitol_city: { data: { type: 'City', id: '1'} },
cities: { data: [{ type: 'City', id: '1'}] }
}
}
}
)
}
);
console.log((await response.json()).message);
assert.strictEqual(response.status, 201, "Should have created the model");
});
});
However, once you convert it to camel case then the attribute iso31661Alpha3 does not get formatted correctly in the output so you have to manually change the serializer for the country model:
// mirage/serializers/country.js
import ApplicationSerializer from './application';
export default class CountrySerializer extends ApplicationSerializer
{
keyForAttribute(attr: string) {
switch(attr)
{
case 'iso31661Alpha3': return 'iso3166_1_alpha3';
default: return super.keyForAttribute(attr);
}
};
};
Once the attributes are in the correct case then it will work.

Chartjs not reading data from vuex mapped state

I am using chartjs in a nuxt component.
The problem is, I am getting referrence error, chartLabels and chartDataPoints are not defined.
If I replace chartLabels and chartDataPoints with this.$store.state.chartLabels and this.$store.state.chartDataPoints, my chart gets rendered, but then, it is no longer reactive since I need to use computed for that.
The store has been set up properly, and I am getting the correct data in vue devtools so the store doesn't seem to be the issue.
What am I doing wrong?
<canvas id="daily-chart"></canvas>
The chart is getting called in mounted() as so:
mounted() {
const ctx = document.getElementById("daily-chart")
new Chart(ctx, this.chartData)
},
Here is the chartData:
chartData: {
type: "line",
data: {
labels: chartLabels,
datasets: [
{
data: chartDataPoints,
},
],
},
options: {
responsive: true,
lineTension: 1,
},
}
chartDataPoints and chartLabels are being fetched from the store's state:
computed: {
...mapState(['chartDataPoints', 'chartLabels'])
},
If you are using vue-chart-js you may want to declare your chartData inside a specific js file that you would put in your template file.
Here is an example :
import {Line} from "vue-chartjs"
export default {
extends: Line,
data: function(){
return {
datacollection: {
labels: chartLabels,
datasets: [{
data: chartDataPoints,
}],
},
options: {
responsive: true,
lineTension: 1,
},
},
props:{
chartDataPoints : Array,
},
}
Then put the line chart in your template as :
<template>
<line-chart
:chartDataPoints="charData"
>
</line-chart>
</template>
I would also recommand using MapGetters from vuex instead of mapState and putting this in to a computed properties.
computed: {
...mapGetters({
chartDataPoints : 'chartData/getChartDataPoints'
})
},
And in your chartData.js (store) :
export const state = () => ({
charData: [],
})
export const getters = {
getChartDataPoints: (state) => () => {
return this.charData
}
}
Then, you would change your template to :
<template>
<line-chart
:chartDataPoints="chartDataPoints()"
>
</line-chart>
</template>

chart js not dispalying data array that comes from an axios request

I have an API end point that returns an array of 24 values that I want to use in my chartjs within a vue component.
when the page loads I get no errors but the bars on the charts just don't show and I don't know why.
EDIT: I noticed that the async function returns a promise instead of the actual data:
async filterData() {
await this.$axios.get('/api/data_app/job_count_by_hour/')
.then(response => {
return this.chart_data = response.data;
})
}
here is the data return code, I have a function that populates the chart_data array :
data(){
return {
form:{
day: 'select day',
workspace:'',
machine_family: [],
duration: []
},
res: [],
total:[],
chart_data: [],
url: '/api/jobs/job_count_by_hour/',
days: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "sunday"],
barChart2: {
labels: ["6h", "7h", "8h", "9h","10h","11h", "12h", "13h", "14h", "15h", "16h", "17h", "18h", "19h", "20h", "21h","22h", "23h", "00h"],
datasets: [{
label: ["popularity"],
backgroundColor:"#f93232" ,
data: this.chart_data
},],
},
}
},
methods: {
async filterData() {
let _url = `${this.url}`
await this.$axios.get(_url)
.then(response => {
this.chart_data = response.data;
})
return this.chart_data
},
},
mounted() {
this.filterData()
}
}
this is the chart component:
<script>
import { Line } from 'vue-chartjs'
export default {
extends: Line,
props: {
chartdata: {
type: Object,
default: null
},
options: {
type: Object,
default: null
}
},
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
in the parent component It looks like this:
en <BarChart :labels="barChart2.labels"
:datasets="barChart2.datasets"
:height="100"
>
</BarChart>ter code here
Turns out that when you try to update nested data, the component doesn't re-render.
This is how I solved it, I put the entire object in an update function and call that function when i get my data from the back end, I hope this helps!:
methods: {
onInput(value) {
this.filterData()
},
updateChart(data) {
this.datasets = [{
label: ["popularity"],
backgroundColor:"#f93232",
data: data
}]
},
async loadData() {
await this.$axios.get(this.url)
.then(response => {
this.updateChart(response.data)
})
},
},
mounted() {
this.loadData()
},

apexchart - Get label from database

I'm not sure as to why the labels doesn't work but series works when fetching data from the database. I'm using vue and laravel.
Here is my code
<div id="chart">
<apexchart type="pie" width="380" :options="chartOptions" :series="series"></apexchart>
</div>
export default {
data: () => ({
employees: [],
series: [],
chartOptions: {
chart: {
width: 380,
type: 'pie',
},
labels: [],
responsive: [{
breakpoint: 80,
options: {
chart: {
width: 200
},
legend: {
position: 'bottom'
}
}
}]
}
}),
methods: {
kpiProgress () {
axios.get('/api/employee-kpi-progress', {
params: { employee_id: this.$store.state.authUser.employee_id }
})
.then(response => {
this.series = response.data
})
.catch(error => console.log(error))
},
kpaInfo () {
axios.get('/api/employee-kpa-info', {
params: { employee_id: this.$store.state.authUser.employee_id }
})
.then(response => {
this.chartOptions.labels = response.data
console.log(this.chartOptions.labels)
})
.catch(error => console.log(error))
},
}
}
Made it work. This is a really weird solution since this is my first time directly calling data from a response.
kpaInfo () {
axios.get('/api/employee-kpa-info', {
params: { employee_id: this.$store.state.authUser.employee_id }
})
.then(response => {
this.chartOptions = {
labels: response.data,
}
})
.catch(error => console.log(error))
},

Why is my Apollo Client optimistic reply failing?

I'm recording this to document the answer to a problem that took me several hours to solve. Scenario:
I'm using two mutation queries on a single component in React Apollo-Client. This is a component wrapped into a larger component to form a page. Something like this (this is not the actual code, but it should give the idea):
import { compose } from 'react-apollo';
// submitNewUser contains
// postedBy
// createdAt
// content
// submitRepository contains
// otherProp
const thisProps1 = {
name: 'mutation1',
props: ({ ownProps, mutation1 }) => ({
submit: ({ repoFullName, commentContent }) => mutation1({
variables: { repoFullName, commentContent },
optimisticResponse: {
__typename: 'Mutation',
submitNewUser: {
__typename: 'Comment',
postedBy: ownProps.currentUser,
content: commentContent,
},
},
}),
}),
};
const thisProps2 = {
name: 'mutation2',
props: ({ ownProps, mutation2 }) => ({
submit: ({ repoFullName, commentContent }) => mutation2({
variables: { repoFullName, commentContent },
optimisticResponse: {
__typename: 'Mutation',
submitRepository: {
__typename: 'Comment',
otherProp: 'foobar',
},
},
}),
}),
};
const ComponentWithMutations = compose(
graphql(submitNewUser, thisProps1),
graphql(submitRepository, thisProps2)
)(Component);
Whenever the optimistic response fires, only the second result is fed back to into the query-response in the outer component. In other words, the first query gives an 'undefined' response (but no error), while the second returns an object as expect.
Why??
The property "createdAt" is not included in the optimistic reply.
__typename: 'Comment',
postedBy: ownProps.currentUser,
content: commentContent,
Should be:
__typename: 'Comment',
postedBy: ownProps.currentUser,
createdAt: Date(),
content: commentContent,
A missing field in an optimistic reply will silently fail to return anything to any queries that call that data.