Skip to content

Commit fc38e69

Browse files
richipargopaveltiunov
authored andcommitted
feat: Vue package improvements and docs
Fix slot composing issue and add examples using vue library (#68)
1 parent a00aef0 commit fc38e69

28 files changed

+10208
-19
lines changed
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
---
2+
title: '@cubejs-client/vue'
3+
permalink: /@cubejs-client-vue
4+
category: Cube.js Frontend
5+
---
6+
7+
`@cubejs-client/vue` provides Vue Components for easy integration Cube.js
8+
into Vue.js app.
9+
10+
## QueryRenderer
11+
12+
`<QueryRenderer />` Vue component takes a query, fetches the given query, and uses the slot scoped props to render the resulting data.
13+
14+
### Props
15+
16+
- `query`: analytic query. [Learn more about it's format](query-format).
17+
- `cubejsApi`: `CubejsApi` instance to use.
18+
19+
### Scoped Slot Props
20+
21+
- `resultSet`: A `resultSet` is an object containing data obtained from the query. If this object is not defined, it means that the data is still being fetched. [ResultSet](@cubejs-client-core#result-set) object provides a convient interface for data munipulation.
22+
- `error`: Error will be defined if an error has occurred while fetching the query.
23+
- `loadingState`: Provides information about the state of the query loading.
24+
25+
## QueryBuilder
26+
`<QueryBuilder />` is used to build interactive analytics query builders. It abstracts state management and API calls to Cube.js Backend. It uses scoped slot props technique.
27+
28+
### Props
29+
30+
- `query`: default query.
31+
- `cubejsApi`: `CubejsApi` instance to use. Required.
32+
- `defaultChartType`: default value of chart type. Default: 'line'.
33+
34+
### Scoped Slot Props
35+
36+
- `measurers`, `dimensions`, `segments`, `timeDimensions`, `filters` - arrays of
37+
selected query builder members.
38+
- `availableMeasures`, `availableDimensions`, `availableTimeDimensions`,
39+
`availableSegments` - arrays of available to select members. They are loaded via
40+
API from Cube.js Backend.
41+
- `updateMeasures`, `updateDimensions`, `updateSegments`, `updateTimeDimensions` - objects with three functions: `add`, `remove`, and `update`. They are used to control the state of the query builder. Ex: `updateMeasures.add(newMeasure)`
42+
- `chartType` - string, containing currently selected chart type.
43+
- `updateChartType` - function-setter for chart type.
44+
- `isQueryPresent` - Bool indicating whether is query ready to be displayed or
45+
not.
46+
- `query` - current query, based on selected members.
47+
- `resultSet`, `error`, `loadingState` - same as `<QueryRenderer />` [Scoped slot params.](#query-scoped-slot-props)
48+
49+
### Example
50+
[Open in CodeSandbox](https://codesandbox.io/s/3rlxjkv2p)
51+
```vue
52+
<template>
53+
<div class="hello">
54+
<query-builder :cubejs-api="cubejsApi" :query="query">
55+
<template v-slot="{ resultSet }">
56+
</template>
57+
</query-builder>
58+
</div>
59+
</template>
60+
61+
<script>
62+
import cubejs from '@cubejs-client/core';
63+
import { QueryBuilder } from '@cubejs-client/vue';
64+
import ChartRenderer from "./ChartRenderer.vue";
65+
66+
const cubejsApi = cubejs(
67+
'YOUR-CUBEJS-API-TOKEN',
68+
{ apiUrl: 'http://localhost:4000/cubejs-api/v1' },
69+
);
70+
71+
export default {
72+
name: "HelloWorld",
73+
components: {
74+
QueryBuilder,
75+
ChartRenderer
76+
},
77+
data() {
78+
const query = {
79+
measures: ["LineItems.count", "LineItems.quantity", "Orders.count"],
80+
timeDimensions: [
81+
{
82+
dimension: "LineItems.createdAt",
83+
granularity: "month"
84+
}
85+
]
86+
};
87+
88+
return {
89+
cubejsApi,
90+
query
91+
};
92+
}
93+
};
94+
</script>
95+
```

docs/Getting-started.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ $ npm i --save @cubejs-client/core
112112
$ npm i --save @cubejs-client/react
113113
```
114114

115+
Vue:
116+
117+
```bash
118+
$ npm i --save @cubejs-client/core
119+
$ npm i --save @cubejs-client/vue
120+
```
121+
115122
### Example Usage
116123

117124
#### Vanilla Javascript
@@ -175,3 +182,72 @@ export default () => {
175182
)
176183
}
177184
```
185+
186+
#### Vue
187+
Import `cubejs` and `QueryRenderer` components, and use them to fetch the data.
188+
In the example below we use Vue-Chartkick to visualize data.
189+
190+
```jsx
191+
<template>
192+
<div class="hello">
193+
<query-renderer :cubejs-api="cubejsApi" :query="query">
194+
<template v-slot="{ measures, resultSet, loading }">
195+
<line-chart :data="transformData(resultSet)"></line-chart>
196+
</template>
197+
</query-renderer>
198+
</div>
199+
</template>
200+
201+
<script>
202+
import cubejs from '@cubejs-client/core';
203+
import { QueryBuilder } from '@cubejs-client/vue';
204+
import Vue from 'vue';
205+
import VueChartkick from 'vue-chartkick';
206+
import Chart from 'chart.js';
207+
208+
Vue.use(VueChartkick, { adapter: Chart });
209+
210+
const cubejsApi = cubejs(
211+
'YOUR-CUBEJS-API-TOKEN',
212+
{ apiUrl: 'http://localhost:4000/cubejs-api/v1' },
213+
);
214+
215+
export default {
216+
name: 'HelloWorld',
217+
components: {
218+
QueryBuilder,
219+
},
220+
props: {
221+
msg: String,
222+
},
223+
data() {
224+
const query = {
225+
measures: ['LineItems.count', 'LineItems.quantity', 'Orders.count'],
226+
timeDimensions: [
227+
{
228+
dimension: 'LineItems.createdAt',
229+
granularity: 'month',
230+
},
231+
],
232+
};
233+
234+
return {
235+
cubejsApi,
236+
query,
237+
};
238+
},
239+
methods: {
240+
transformData(resultSet) {
241+
const seriesNames = resultSet.seriesNames();
242+
const pivot = resultSet.chartPivot();
243+
const series = [];
244+
seriesNames.forEach((e) => {
245+
const data = pivot.map(p => [p.x, p[e.key]]);
246+
series.push({ name: e.key, data });
247+
});
248+
return series;
249+
},
250+
},
251+
};
252+
</script>
253+
```

examples/vue-dashboard/backend/.env

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CUBEJS_API_SECRET=SECRET
2+
CUBEJS_DB_TYPE=postgres
3+
CUBEJS_DB_NAME=ecom
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const CubejsServer = require('@cubejs-backend/server');
2+
3+
const server = new CubejsServer();
4+
5+
server.listen().then(({ port }) => {
6+
console.log(`🚀 Cube.js server is listening on ${port}`);
7+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "backend",
3+
"version": "0.0.1",
4+
"private": true,
5+
"scripts": {
6+
"dev": "./node_modules/.bin/cubejs-dev-server"
7+
},
8+
"dependencies": {
9+
"@cubejs-backend/postgres-driver": "^0.4.4",
10+
"@cubejs-backend/server": "^0.4.6"
11+
}
12+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
cube(`LineItems`, {
2+
sql: `SELECT * FROM public.line_items`,
3+
4+
joins: {
5+
Orders: {
6+
sql: `${CUBE}.order_id = ${Orders}.id`,
7+
relationship: `belongsTo`
8+
}
9+
},
10+
11+
measures: {
12+
count: {
13+
type: `count`,
14+
drillMembers: [id, createdAt]
15+
},
16+
17+
quantity: {
18+
sql: `quantity`,
19+
type: `sum`
20+
},
21+
22+
price: {
23+
sql: `price`,
24+
type: `sum`
25+
}
26+
},
27+
28+
dimensions: {
29+
id: {
30+
sql: `id`,
31+
type: `number`,
32+
primaryKey: true
33+
},
34+
35+
createdAt: {
36+
sql: `created_at`,
37+
type: `time`
38+
}
39+
}
40+
});
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
cube(`Orders`, {
2+
sql: `SELECT * FROM public.orders`,
3+
4+
joins: {
5+
Users: {
6+
sql: `${CUBE}.user_id = ${Users}.id`,
7+
relationship: `belongsTo`
8+
}
9+
},
10+
11+
measures: {
12+
count: {
13+
type: `count`,
14+
drillMembers: [id, createdAt]
15+
},
16+
17+
number: {
18+
sql: `number`,
19+
type: `sum`
20+
}
21+
},
22+
23+
dimensions: {
24+
id: {
25+
sql: `id`,
26+
type: `number`,
27+
primaryKey: true
28+
},
29+
30+
status: {
31+
sql: `status`,
32+
type: `string`
33+
},
34+
35+
createdAt: {
36+
sql: `created_at`,
37+
type: `time`
38+
},
39+
40+
completedAt: {
41+
sql: `completed_at`,
42+
type: `time`
43+
}
44+
}
45+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
cube(`Users`, {
2+
sql: `SELECT * FROM public.users`,
3+
4+
joins: {
5+
6+
},
7+
8+
measures: {
9+
count: {
10+
type: `count`,
11+
drillMembers: [city, id, createdAt]
12+
}
13+
},
14+
15+
dimensions: {
16+
city: {
17+
sql: `city`,
18+
type: `string`
19+
},
20+
21+
gender: {
22+
sql: `gender`,
23+
type: `string`
24+
},
25+
26+
id: {
27+
sql: `id`,
28+
type: `number`,
29+
primaryKey: true
30+
},
31+
32+
company: {
33+
sql: `company`,
34+
type: `string`
35+
},
36+
37+
createdAt: {
38+
sql: `created_at`,
39+
type: `time`
40+
}
41+
}
42+
});
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
REACT_APP_CUBEJS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE1NTM3NjIwNzIsImV4cCI6MTU1Mzg0ODQ3Mn0.zwBj40GgBSwGc72RYo2_6PeOnHMNo7AYummdYGJkiDo
2+
REACT_APP_API_URL=http://localhost:4000/cubejs-api/v1
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
REACT_APP_CUBEJS_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.e30.K9PiJkjegbhnw4Ca5pPlkTmZihoOm42w8bja9Qs2qJg
2+
REACT_APP_API_URL=https://react-query-builder.herokuapp.com/cubejs-api/v1

0 commit comments

Comments
 (0)