ModelViewSelect updates, Fetchdata, Chart Hooks
This commit is contained in:
parent
2fe7e42fb5
commit
fc0d5d65bb
|
@ -1,18 +1,28 @@
|
|||
<script>
|
||||
import { Button, Icon, DropdownMenu } from "@budibase/bbui"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
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 => ({
|
||||
name: m.name,
|
||||
label: m.name,
|
||||
name: `all_${m._id}`,
|
||||
modelId: m._id,
|
||||
isModel: true,
|
||||
}))
|
||||
|
||||
const views = $backendUiStore.models.reduce((acc, cur) => {
|
||||
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
||||
label: key,
|
||||
name: key,
|
||||
modelId: value.modelId,
|
||||
}))
|
||||
|
@ -20,26 +30,26 @@
|
|||
}, [])
|
||||
</script>
|
||||
|
||||
<div bind:this={anchorLeft}>
|
||||
<Button secondary small on:click={dropdownLeft.show}>
|
||||
<span>{selected.name ? selected.name : 'Model / View'}</span>
|
||||
<div bind:this={anchor}>
|
||||
<Button secondary small on:click={dropdown.show}>
|
||||
<span>{value.label ? value.label : 'Model / View'}</span>
|
||||
<Icon name="arrowdown" />
|
||||
</Button>
|
||||
</div>
|
||||
<DropdownMenu
|
||||
bind:this={dropdownLeft}
|
||||
bind:this={dropdown}
|
||||
width="175px"
|
||||
borderColor="#d1d1d1ff"
|
||||
anchor={anchorLeft}
|
||||
{anchor}
|
||||
align="right">
|
||||
<div class="model-view-container">
|
||||
<p>Tables</p>
|
||||
<ul>
|
||||
{#each models as model}
|
||||
<li
|
||||
class:selected={selected === model}
|
||||
on:click={() => (selected = model)}>
|
||||
{model.name}
|
||||
class:selected={value === model}
|
||||
on:click={() => handleSelected(model)}>
|
||||
{model.label}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
@ -48,9 +58,9 @@
|
|||
<ul>
|
||||
{#each views as view}
|
||||
<li
|
||||
class:selected={selected === view}
|
||||
on:click={() => (selected = view)}>
|
||||
{view.name}
|
||||
class:selected={value === view}
|
||||
on:click={() => handleSelected(view)}>
|
||||
{view.label}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
|
|
@ -2,6 +2,7 @@ import Input from "./PropertyPanelControls/Input.svelte"
|
|||
import OptionSelect from "./OptionSelect.svelte"
|
||||
import Checkbox from "../common/Checkbox.svelte"
|
||||
import ModelSelect from "components/userInterface/ModelSelect.svelte"
|
||||
import ModelViewSelect from "components/userInterface/ModelViewSelect.svelte"
|
||||
|
||||
import { all } from "./propertyCategories.js"
|
||||
/*
|
||||
|
@ -258,7 +259,13 @@ export default {
|
|||
icon: "ri-file-list-line",
|
||||
properties: {
|
||||
design: { ...all },
|
||||
settings: [{ label: "Table", key: "model", control: ModelSelect }],
|
||||
settings: [
|
||||
{
|
||||
label: "Table",
|
||||
key: "datasource",
|
||||
control: ModelViewSelect,
|
||||
},
|
||||
],
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
|
@ -486,7 +493,11 @@ export default {
|
|||
properties: {
|
||||
design: { ...all },
|
||||
settings: [
|
||||
{ label: "Model", key: "model", control: ModelSelect },
|
||||
{
|
||||
label: "Table",
|
||||
key: "datasource",
|
||||
control: ModelViewSelect,
|
||||
},
|
||||
{ label: "Stripe Color", key: "stripeColor", control: Input },
|
||||
{ label: "Border Color", key: "borderColor", control: Input },
|
||||
{ label: "TH Color", key: "backgroundColor", control: Input },
|
||||
|
@ -568,8 +579,8 @@ export default {
|
|||
settings: [
|
||||
{
|
||||
label: "Table",
|
||||
key: "model",
|
||||
control: ModelSelect,
|
||||
key: "datasource",
|
||||
control: ModelViewSelect,
|
||||
},
|
||||
{
|
||||
label: "Animate Chart",
|
||||
|
@ -660,8 +671,8 @@ export default {
|
|||
settings: [
|
||||
{
|
||||
label: "Table",
|
||||
key: "model",
|
||||
control: ModelSelect,
|
||||
key: "datasource",
|
||||
control: ModelViewSelect,
|
||||
},
|
||||
{
|
||||
label: "Name Label",
|
||||
|
@ -772,8 +783,8 @@ export default {
|
|||
settings: [
|
||||
{
|
||||
label: "Table",
|
||||
key: "model",
|
||||
control: ModelSelect,
|
||||
key: "datasource",
|
||||
control: ModelViewSelect,
|
||||
},
|
||||
{
|
||||
label: "Color",
|
||||
|
@ -867,8 +878,8 @@ export default {
|
|||
settings: [
|
||||
{
|
||||
label: "Table",
|
||||
key: "model",
|
||||
control: ModelSelect,
|
||||
key: "datasource",
|
||||
control: ModelViewSelect,
|
||||
},
|
||||
{
|
||||
label: "Colors",
|
||||
|
|
|
@ -203,7 +203,7 @@
|
|||
"description": "an HTML table that fetches data from a table or view and displays it.",
|
||||
"data": true,
|
||||
"props": {
|
||||
"model": "models",
|
||||
"datasource": "models",
|
||||
"stripeColor": "string",
|
||||
"borderColor": "string",
|
||||
"backgroundColor": "string",
|
||||
|
@ -248,7 +248,7 @@
|
|||
"children": true,
|
||||
"data": true,
|
||||
"props": {
|
||||
"model": "models"
|
||||
"datasource": "models"
|
||||
}
|
||||
},
|
||||
"stackedlist": {
|
||||
|
@ -357,7 +357,7 @@
|
|||
"description": "Donut Chart",
|
||||
"data": true,
|
||||
"props": {
|
||||
"model": "string",
|
||||
"datasource": "string",
|
||||
"color": "string",
|
||||
"height": "number",
|
||||
"width": "number",
|
||||
|
@ -397,7 +397,7 @@
|
|||
"description": "Stacked Bar Chart",
|
||||
"data": true,
|
||||
"props": {
|
||||
"model": "string",
|
||||
"datasource": "models",
|
||||
"color": "string",
|
||||
"height": "number",
|
||||
"width": "number",
|
||||
|
@ -498,7 +498,7 @@
|
|||
"description": "Bar Chart",
|
||||
"data": true,
|
||||
"props": {
|
||||
"model": "string",
|
||||
"datasource": "models",
|
||||
"betweenBarsPadding": "number",
|
||||
"gradient": "string",
|
||||
"color": "string",
|
||||
|
@ -523,7 +523,7 @@
|
|||
"description": "Line Chart",
|
||||
"data": true,
|
||||
"props": {
|
||||
"model": "string",
|
||||
"datasource": "models",
|
||||
"width": "number",
|
||||
"height": "number",
|
||||
"axisTimeCombinations": "string",
|
||||
|
@ -581,7 +581,7 @@
|
|||
"description": "Groupedbar chart",
|
||||
"data": true,
|
||||
"props": {
|
||||
"model": "string",
|
||||
"datasource": "models",
|
||||
"color": "string",
|
||||
"height": "string",
|
||||
"width": "string",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -6,6 +6,7 @@
|
|||
hasProp,
|
||||
} from "./utils.js"
|
||||
import britecharts from "britecharts"
|
||||
import fetchData from "../fetchData.js"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
import { select } from "d3-selection"
|
||||
|
@ -53,17 +54,11 @@
|
|||
export let yTicks = null
|
||||
export let percentageAxisToMaxRatio = null
|
||||
|
||||
export let useLegend = true
|
||||
|
||||
export let _bb
|
||||
export let model
|
||||
|
||||
let store = _bb.store
|
||||
|
||||
onMount(async () => {
|
||||
if (model) {
|
||||
await fetchData()
|
||||
data = $store[model]
|
||||
if (datasource) {
|
||||
data = await fetchData(datasource)
|
||||
if (schemaIsValid()) {
|
||||
chartContainer = select(`.${chartClass}`)
|
||||
bindChartUIProps()
|
||||
|
@ -80,20 +75,6 @@
|
|||
(hasProp(data, "name") || hasProp(data, nameLabel)) &&
|
||||
(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() {
|
||||
chart.numberFormat(".0f")
|
||||
chart.labelsNumberFormat(".1f")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { getColorSchema, notNull } from "./utils.js"
|
||||
import fetchData from "../fetchData.js"
|
||||
import Legend from "./Legend.svelte"
|
||||
import britecharts from "britecharts"
|
||||
import { onMount } from "svelte"
|
||||
|
@ -31,6 +32,8 @@
|
|||
export let orderingFunction = null
|
||||
|
||||
let data = []
|
||||
export let datasource = {}
|
||||
|
||||
export let color = "britecharts"
|
||||
export let height = 200
|
||||
export let width = 200
|
||||
|
@ -54,25 +57,11 @@
|
|||
export let legendWidth = 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 () => {
|
||||
if (chart) {
|
||||
if (model) {
|
||||
await fetchData()
|
||||
data = checkAndReformatData($store[model])
|
||||
let _data = await fetchData(datasource)
|
||||
data = checkAndReformatData(_data)
|
||||
if (data.length === 0) {
|
||||
console.error(
|
||||
"Donut - please provide a valid name and value field for the chart"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils"
|
||||
import Tooltip from "./Tooltip.svelte"
|
||||
import fetchData from "../fetchData.js"
|
||||
import britecharts from "britecharts"
|
||||
import { onMount } from "svelte"
|
||||
import { select } from "d3-selection"
|
||||
|
@ -9,7 +10,7 @@
|
|||
const _id = shortid.generate()
|
||||
|
||||
export let _bb
|
||||
export let model
|
||||
export let datasource = {}
|
||||
|
||||
let store = _bb.store
|
||||
|
||||
|
@ -51,8 +52,7 @@
|
|||
|
||||
onMount(async () => {
|
||||
if (model) {
|
||||
await fetchData()
|
||||
data = $store[model]
|
||||
data = await fetchData(datasource)
|
||||
if (schemaIsValid()) {
|
||||
chartContainer = select(`.${chartClass}`)
|
||||
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() {
|
||||
tooltipContainer = select(`.${chartClass} .metadata-group`)
|
||||
tooltip.topicLabel("values")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { getColorSchema, getChartGradient, notNull, hasProp } from "./utils"
|
||||
import fetchData from "../fetchData.js"
|
||||
import britecharts from "britecharts"
|
||||
import { onMount } from "svelte"
|
||||
|
||||
|
@ -9,7 +10,7 @@
|
|||
const _id = shortid.generate()
|
||||
|
||||
export let _bb
|
||||
export let model
|
||||
export let datasource = {}
|
||||
|
||||
let store = _bb.store
|
||||
|
||||
|
@ -65,7 +66,7 @@
|
|||
export let tooltipTitle = ""
|
||||
|
||||
onMount(async () => {
|
||||
if (model) {
|
||||
if (datasource) {
|
||||
data = await getAndPrepareData()
|
||||
if (data.dataByTopic.length > 0) {
|
||||
chartContainer = select(`.${chartClass}`)
|
||||
|
@ -89,20 +90,6 @@
|
|||
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 =>
|
||||
hasProp(data, valueLabel) &&
|
||||
hasProp(data, dateLabel) &&
|
||||
|
@ -124,8 +111,7 @@
|
|||
dateLabel = "date"
|
||||
}
|
||||
|
||||
await fetchData()
|
||||
_data = $store[model]
|
||||
_data = await fetchData(datasource)
|
||||
|
||||
if (schemaIsValid(_data)) {
|
||||
_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