ModelViewSelect updates, Fetchdata, Chart Hooks

This commit is contained in:
cmack 2020-08-24 16:26:00 +01:00
parent 2fe7e42fb5
commit fc0d5d65bb
10 changed files with 124 additions and 105 deletions

View File

@ -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>

View File

@ -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",

View File

@ -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

View File

@ -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")

View File

@ -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"

View File

@ -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")

View File

@ -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) => {

View File

@ -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"),
}

View File

@ -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()
}
}