ModelViewSelect updates, Fetchdata, Chart Hooks
This commit is contained in:
parent
ead8f51303
commit
cc8df3fad6
|
@ -1,18 +1,28 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, Icon, DropdownMenu } from "@budibase/bbui"
|
import { Button, Icon, DropdownMenu } from "@budibase/bbui"
|
||||||
|
import { createEventDispatcher } from "svelte"
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
|
||||||
let anchorLeft, dropdownLeft
|
const dispatch = createEventDispatcher()
|
||||||
|
let anchor, dropdown
|
||||||
|
|
||||||
export let selected = {}
|
export let value = {}
|
||||||
|
|
||||||
|
function handleSelected(selected) {
|
||||||
|
dispatch("change", selected)
|
||||||
|
dropdown.hide()
|
||||||
|
}
|
||||||
|
|
||||||
const models = $backendUiStore.models.map(m => ({
|
const models = $backendUiStore.models.map(m => ({
|
||||||
name: m.name,
|
label: m.name,
|
||||||
|
name: `all_${m._id}`,
|
||||||
modelId: m._id,
|
modelId: m._id,
|
||||||
|
isModel: true,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const views = $backendUiStore.models.reduce((acc, cur) => {
|
const views = $backendUiStore.models.reduce((acc, cur) => {
|
||||||
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
||||||
|
label: key,
|
||||||
name: key,
|
name: key,
|
||||||
modelId: value.modelId,
|
modelId: value.modelId,
|
||||||
}))
|
}))
|
||||||
|
@ -20,26 +30,26 @@
|
||||||
}, [])
|
}, [])
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={anchorLeft}>
|
<div bind:this={anchor}>
|
||||||
<Button secondary small on:click={dropdownLeft.show}>
|
<Button secondary small on:click={dropdown.show}>
|
||||||
<span>{selected.name ? selected.name : 'Model / View'}</span>
|
<span>{value.label ? value.label : 'Model / View'}</span>
|
||||||
<Icon name="arrowdown" />
|
<Icon name="arrowdown" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
bind:this={dropdownLeft}
|
bind:this={dropdown}
|
||||||
width="175px"
|
width="175px"
|
||||||
borderColor="#d1d1d1ff"
|
borderColor="#d1d1d1ff"
|
||||||
anchor={anchorLeft}
|
{anchor}
|
||||||
align="right">
|
align="right">
|
||||||
<div class="model-view-container">
|
<div class="model-view-container">
|
||||||
<p>Tables</p>
|
<p>Tables</p>
|
||||||
<ul>
|
<ul>
|
||||||
{#each models as model}
|
{#each models as model}
|
||||||
<li
|
<li
|
||||||
class:selected={selected === model}
|
class:selected={value === model}
|
||||||
on:click={() => (selected = model)}>
|
on:click={() => handleSelected(model)}>
|
||||||
{model.name}
|
{model.label}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -48,9 +58,9 @@
|
||||||
<ul>
|
<ul>
|
||||||
{#each views as view}
|
{#each views as view}
|
||||||
<li
|
<li
|
||||||
class:selected={selected === view}
|
class:selected={value === view}
|
||||||
on:click={() => (selected = view)}>
|
on:click={() => handleSelected(view)}>
|
||||||
{view.name}
|
{view.label}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Input from "./PropertyPanelControls/Input.svelte"
|
||||||
import OptionSelect from "./OptionSelect.svelte"
|
import OptionSelect from "./OptionSelect.svelte"
|
||||||
import Checkbox from "../common/Checkbox.svelte"
|
import Checkbox from "../common/Checkbox.svelte"
|
||||||
import ModelSelect from "components/userInterface/ModelSelect.svelte"
|
import ModelSelect from "components/userInterface/ModelSelect.svelte"
|
||||||
|
import ModelViewSelect from "components/userInterface/ModelViewSelect.svelte"
|
||||||
|
|
||||||
import { all } from "./propertyCategories.js"
|
import { all } from "./propertyCategories.js"
|
||||||
/*
|
/*
|
||||||
|
@ -258,7 +259,13 @@ export default {
|
||||||
icon: "ri-file-list-line",
|
icon: "ri-file-list-line",
|
||||||
properties: {
|
properties: {
|
||||||
design: { ...all },
|
design: { ...all },
|
||||||
settings: [{ label: "Table", key: "model", control: ModelSelect }],
|
settings: [
|
||||||
|
{
|
||||||
|
label: "Table",
|
||||||
|
key: "datasource",
|
||||||
|
control: ModelViewSelect,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
@ -486,7 +493,11 @@ export default {
|
||||||
properties: {
|
properties: {
|
||||||
design: { ...all },
|
design: { ...all },
|
||||||
settings: [
|
settings: [
|
||||||
{ label: "Model", key: "model", control: ModelSelect },
|
{
|
||||||
|
label: "Table",
|
||||||
|
key: "datasource",
|
||||||
|
control: ModelViewSelect,
|
||||||
|
},
|
||||||
{ label: "Stripe Color", key: "stripeColor", control: Input },
|
{ label: "Stripe Color", key: "stripeColor", control: Input },
|
||||||
{ label: "Border Color", key: "borderColor", control: Input },
|
{ label: "Border Color", key: "borderColor", control: Input },
|
||||||
{ label: "TH Color", key: "backgroundColor", control: Input },
|
{ label: "TH Color", key: "backgroundColor", control: Input },
|
||||||
|
@ -568,8 +579,8 @@ export default {
|
||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
label: "Table",
|
label: "Table",
|
||||||
key: "model",
|
key: "datasource",
|
||||||
control: ModelSelect,
|
control: ModelViewSelect,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Animate Chart",
|
label: "Animate Chart",
|
||||||
|
@ -660,8 +671,8 @@ export default {
|
||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
label: "Table",
|
label: "Table",
|
||||||
key: "model",
|
key: "datasource",
|
||||||
control: ModelSelect,
|
control: ModelViewSelect,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Name Label",
|
label: "Name Label",
|
||||||
|
@ -772,8 +783,8 @@ export default {
|
||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
label: "Table",
|
label: "Table",
|
||||||
key: "model",
|
key: "datasource",
|
||||||
control: ModelSelect,
|
control: ModelViewSelect,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Color",
|
label: "Color",
|
||||||
|
@ -867,8 +878,8 @@ export default {
|
||||||
settings: [
|
settings: [
|
||||||
{
|
{
|
||||||
label: "Table",
|
label: "Table",
|
||||||
key: "model",
|
key: "datasource",
|
||||||
control: ModelSelect,
|
control: ModelViewSelect,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Colors",
|
label: "Colors",
|
||||||
|
|
|
@ -203,7 +203,7 @@
|
||||||
"description": "an HTML table that fetches data from a table or view and displays it.",
|
"description": "an HTML table that fetches data from a table or view and displays it.",
|
||||||
"data": true,
|
"data": true,
|
||||||
"props": {
|
"props": {
|
||||||
"model": "models",
|
"datasource": "models",
|
||||||
"stripeColor": "string",
|
"stripeColor": "string",
|
||||||
"borderColor": "string",
|
"borderColor": "string",
|
||||||
"backgroundColor": "string",
|
"backgroundColor": "string",
|
||||||
|
@ -248,7 +248,7 @@
|
||||||
"children": true,
|
"children": true,
|
||||||
"data": true,
|
"data": true,
|
||||||
"props": {
|
"props": {
|
||||||
"model": "models"
|
"datasource": "models"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"stackedlist": {
|
"stackedlist": {
|
||||||
|
@ -357,7 +357,7 @@
|
||||||
"description": "Donut Chart",
|
"description": "Donut Chart",
|
||||||
"data": true,
|
"data": true,
|
||||||
"props": {
|
"props": {
|
||||||
"model": "string",
|
"datasource": "string",
|
||||||
"color": "string",
|
"color": "string",
|
||||||
"height": "number",
|
"height": "number",
|
||||||
"width": "number",
|
"width": "number",
|
||||||
|
@ -397,7 +397,7 @@
|
||||||
"description": "Stacked Bar Chart",
|
"description": "Stacked Bar Chart",
|
||||||
"data": true,
|
"data": true,
|
||||||
"props": {
|
"props": {
|
||||||
"model": "string",
|
"datasource": "models",
|
||||||
"color": "string",
|
"color": "string",
|
||||||
"height": "number",
|
"height": "number",
|
||||||
"width": "number",
|
"width": "number",
|
||||||
|
@ -498,7 +498,7 @@
|
||||||
"description": "Bar Chart",
|
"description": "Bar Chart",
|
||||||
"data": true,
|
"data": true,
|
||||||
"props": {
|
"props": {
|
||||||
"model": "string",
|
"datasource": "models",
|
||||||
"betweenBarsPadding": "number",
|
"betweenBarsPadding": "number",
|
||||||
"gradient": "string",
|
"gradient": "string",
|
||||||
"color": "string",
|
"color": "string",
|
||||||
|
@ -523,7 +523,7 @@
|
||||||
"description": "Line Chart",
|
"description": "Line Chart",
|
||||||
"data": true,
|
"data": true,
|
||||||
"props": {
|
"props": {
|
||||||
"model": "string",
|
"datasource": "models",
|
||||||
"width": "number",
|
"width": "number",
|
||||||
"height": "number",
|
"height": "number",
|
||||||
"axisTimeCombinations": "string",
|
"axisTimeCombinations": "string",
|
||||||
|
@ -581,7 +581,7 @@
|
||||||
"description": "Groupedbar chart",
|
"description": "Groupedbar chart",
|
||||||
"data": true,
|
"data": true,
|
||||||
"props": {
|
"props": {
|
||||||
"model": "string",
|
"datasource": "models",
|
||||||
"color": "string",
|
"color": "string",
|
||||||
"height": "string",
|
"height": "string",
|
||||||
"width": "string",
|
"width": "string",
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -6,6 +6,7 @@
|
||||||
hasProp,
|
hasProp,
|
||||||
} from "./utils.js"
|
} from "./utils.js"
|
||||||
import britecharts from "britecharts"
|
import britecharts from "britecharts"
|
||||||
|
import fetchData from "../fetchData.js"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
import { select } from "d3-selection"
|
import { select } from "d3-selection"
|
||||||
|
@ -53,17 +54,11 @@
|
||||||
export let yTicks = null
|
export let yTicks = null
|
||||||
export let percentageAxisToMaxRatio = null
|
export let percentageAxisToMaxRatio = null
|
||||||
|
|
||||||
export let useLegend = true
|
|
||||||
|
|
||||||
export let _bb
|
export let _bb
|
||||||
export let model
|
|
||||||
|
|
||||||
let store = _bb.store
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (model) {
|
if (datasource) {
|
||||||
await fetchData()
|
data = await fetchData(datasource)
|
||||||
data = $store[model]
|
|
||||||
if (schemaIsValid()) {
|
if (schemaIsValid()) {
|
||||||
chartContainer = select(`.${chartClass}`)
|
chartContainer = select(`.${chartClass}`)
|
||||||
bindChartUIProps()
|
bindChartUIProps()
|
||||||
|
@ -80,20 +75,6 @@
|
||||||
(hasProp(data, "name") || hasProp(data, nameLabel)) &&
|
(hasProp(data, "name") || hasProp(data, nameLabel)) &&
|
||||||
(hasProp(data, "value") || hasProp(data, valueLabel))
|
(hasProp(data, "value") || hasProp(data, valueLabel))
|
||||||
|
|
||||||
async function fetchData() {
|
|
||||||
const FETCH_RECORDS_URL = `/api/views/all_${model}`
|
|
||||||
const response = await _bb.api.get(FETCH_RECORDS_URL)
|
|
||||||
if (response.status === 200) {
|
|
||||||
const json = await response.json()
|
|
||||||
store.update(state => {
|
|
||||||
state[model] = json
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw new Error("Failed to fetch records.", response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindChartUIProps() {
|
function bindChartUIProps() {
|
||||||
chart.numberFormat(".0f")
|
chart.numberFormat(".0f")
|
||||||
chart.labelsNumberFormat(".1f")
|
chart.labelsNumberFormat(".1f")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { getColorSchema, notNull } from "./utils.js"
|
import { getColorSchema, notNull } from "./utils.js"
|
||||||
|
import fetchData from "../fetchData.js"
|
||||||
import Legend from "./Legend.svelte"
|
import Legend from "./Legend.svelte"
|
||||||
import britecharts from "britecharts"
|
import britecharts from "britecharts"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
@ -31,6 +32,8 @@
|
||||||
export let orderingFunction = null
|
export let orderingFunction = null
|
||||||
|
|
||||||
let data = []
|
let data = []
|
||||||
|
export let datasource = {}
|
||||||
|
|
||||||
export let color = "britecharts"
|
export let color = "britecharts"
|
||||||
export let height = 200
|
export let height = 200
|
||||||
export let width = 200
|
export let width = 200
|
||||||
|
@ -54,25 +57,11 @@
|
||||||
export let legendWidth = null
|
export let legendWidth = null
|
||||||
export let legendHeight = null
|
export let legendHeight = null
|
||||||
|
|
||||||
async function fetchData() {
|
|
||||||
const FETCH_RECORDS_URL = `/api/views/all_${model}`
|
|
||||||
const response = await _bb.api.get(FETCH_RECORDS_URL)
|
|
||||||
if (response.status === 200) {
|
|
||||||
const json = await response.json()
|
|
||||||
store.update(state => {
|
|
||||||
state[model] = json
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw new Error("Failed to fetch records.", response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (chart) {
|
if (chart) {
|
||||||
if (model) {
|
if (model) {
|
||||||
await fetchData()
|
let _data = await fetchData(datasource)
|
||||||
data = checkAndReformatData($store[model])
|
data = checkAndReformatData(_data)
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
console.error(
|
console.error(
|
||||||
"Donut - please provide a valid name and value field for the chart"
|
"Donut - please provide a valid name and value field for the chart"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils"
|
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils"
|
||||||
import Tooltip from "./Tooltip.svelte"
|
import Tooltip from "./Tooltip.svelte"
|
||||||
|
import fetchData from "../fetchData.js"
|
||||||
import britecharts from "britecharts"
|
import britecharts from "britecharts"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { select } from "d3-selection"
|
import { select } from "d3-selection"
|
||||||
|
@ -9,7 +10,7 @@
|
||||||
const _id = shortid.generate()
|
const _id = shortid.generate()
|
||||||
|
|
||||||
export let _bb
|
export let _bb
|
||||||
export let model
|
export let datasource = {}
|
||||||
|
|
||||||
let store = _bb.store
|
let store = _bb.store
|
||||||
|
|
||||||
|
@ -51,8 +52,7 @@
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (model) {
|
if (model) {
|
||||||
await fetchData()
|
data = await fetchData(datasource)
|
||||||
data = $store[model]
|
|
||||||
if (schemaIsValid()) {
|
if (schemaIsValid()) {
|
||||||
chartContainer = select(`.${chartClass}`)
|
chartContainer = select(`.${chartClass}`)
|
||||||
bindChartUIProps()
|
bindChartUIProps()
|
||||||
|
@ -67,20 +67,6 @@
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
async function fetchData() {
|
|
||||||
const FETCH_RECORDS_URL = `/api/views/all_${model}`
|
|
||||||
const response = await _bb.api.get(FETCH_RECORDS_URL)
|
|
||||||
if (response.status === 200) {
|
|
||||||
const json = await response.json()
|
|
||||||
store.update(state => {
|
|
||||||
state[model] = json
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw new Error("Failed to fetch records.", response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function bindTooltip() {
|
function bindTooltip() {
|
||||||
tooltipContainer = select(`.${chartClass} .metadata-group`)
|
tooltipContainer = select(`.${chartClass} .metadata-group`)
|
||||||
tooltip.topicLabel("values")
|
tooltip.topicLabel("values")
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils"
|
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils"
|
||||||
|
import fetchData from "../fetchData.js"
|
||||||
import britecharts from "britecharts"
|
import britecharts from "britecharts"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
|
||||||
|
@ -9,7 +10,7 @@
|
||||||
const _id = shortid.generate()
|
const _id = shortid.generate()
|
||||||
|
|
||||||
export let _bb
|
export let _bb
|
||||||
export let model
|
export let datasource = {}
|
||||||
|
|
||||||
let store = _bb.store
|
let store = _bb.store
|
||||||
|
|
||||||
|
@ -65,7 +66,7 @@
|
||||||
export let tooltipTitle = ""
|
export let tooltipTitle = ""
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
if (model) {
|
if (datasource) {
|
||||||
data = await getAndPrepareData()
|
data = await getAndPrepareData()
|
||||||
if (data.dataByTopic.length > 0) {
|
if (data.dataByTopic.length > 0) {
|
||||||
chartContainer = select(`.${chartClass}`)
|
chartContainer = select(`.${chartClass}`)
|
||||||
|
@ -89,20 +90,6 @@
|
||||||
tooltipContainer.datum([]).call(tooltip)
|
tooltipContainer.datum([]).call(tooltip)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchData() {
|
|
||||||
const FETCH_RECORDS_URL = `/api/views/all_${model}`
|
|
||||||
const response = await _bb.api.get(FETCH_RECORDS_URL)
|
|
||||||
if (response.status === 200) {
|
|
||||||
const json = await response.json()
|
|
||||||
store.update(state => {
|
|
||||||
state[model] = json
|
|
||||||
return state
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
throw new Error("Failed to fetch records.", response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const schemaIsValid = data =>
|
const schemaIsValid = data =>
|
||||||
hasProp(data, valueLabel) &&
|
hasProp(data, valueLabel) &&
|
||||||
hasProp(data, dateLabel) &&
|
hasProp(data, dateLabel) &&
|
||||||
|
@ -124,8 +111,7 @@
|
||||||
dateLabel = "date"
|
dateLabel = "date"
|
||||||
}
|
}
|
||||||
|
|
||||||
await fetchData()
|
_data = await fetchData(datasource)
|
||||||
_data = $store[model]
|
|
||||||
|
|
||||||
if (schemaIsValid(_data)) {
|
if (schemaIsValid(_data)) {
|
||||||
_data.forEach((data, idx, arr) => {
|
_data.forEach((data, idx, arr) => {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
const apiCall = method => async (url, body) => {
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
}
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: method,
|
||||||
|
body: body && JSON.stringify(body),
|
||||||
|
headers,
|
||||||
|
})
|
||||||
|
|
||||||
|
return response
|
||||||
|
}
|
||||||
|
|
||||||
|
export const post = apiCall("POST")
|
||||||
|
export const get = apiCall("GET")
|
||||||
|
export const patch = apiCall("PATCH")
|
||||||
|
export const del = apiCall("DELETE")
|
||||||
|
export const put = apiCall("PUT")
|
||||||
|
|
||||||
|
export default {
|
||||||
|
post: apiCall("POST"),
|
||||||
|
get: apiCall("GET"),
|
||||||
|
patch: apiCall("PATCH"),
|
||||||
|
delete: apiCall("DELETE"),
|
||||||
|
put: apiCall("PUT"),
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
import api from "./api"
|
||||||
|
|
||||||
|
export default async function fetchData(datasource) {
|
||||||
|
const { isModel, name } = datasource
|
||||||
|
|
||||||
|
if (name) {
|
||||||
|
return isModel ? await fetchModelData() : await fetchViewData()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchModelData() {
|
||||||
|
if (!name.startsWith("all_")) {
|
||||||
|
throw new Error("Incorrect model convention - must begin with all_")
|
||||||
|
}
|
||||||
|
const modelsResponse = await api.get(`/api/views/${name}`)
|
||||||
|
return await modelsResponse.json()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchViewData() {
|
||||||
|
const { field, groupBy } = datasource
|
||||||
|
const params = new URLSearchParams()
|
||||||
|
|
||||||
|
if (field) params.set("stats", true)
|
||||||
|
if (groupBy) params.set("group", groupBy)
|
||||||
|
let QUERY_VIEW_URL =
|
||||||
|
field && groupBy ? `/api/views/${name}?${params}` : `/api/views/${name}`
|
||||||
|
|
||||||
|
const response = await api.get(QUERY_VIEW_URL)
|
||||||
|
return await response.json()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue