forked from tsai/budibase
32 changed files with 188 additions and 533 deletions
@ -0,0 +1,12 @@ |
|||
import api from "./api" |
|||
|
|||
/** |
|||
* Uploads an attachment to the server. |
|||
*/ |
|||
export const uploadAttachment = async data => { |
|||
return await api.post({ |
|||
url: "/api/attachments/upload", |
|||
body: data, |
|||
json: false, |
|||
}) |
|||
} |
|||
@ -1,2 +1,7 @@ |
|||
export * from "./rows" |
|||
export * from "./auth" |
|||
export * from "./datasources" |
|||
export * from "./tables" |
|||
export * from "./attachments" |
|||
export * from "./views" |
|||
export * from "./relationships" |
|||
|
|||
@ -1,82 +0,0 @@ |
|||
<script> |
|||
import { onMount } from "svelte" |
|||
|
|||
export let _bb |
|||
export let table |
|||
export let layout = "list" |
|||
|
|||
let headers = [] |
|||
let store = _bb.store |
|||
|
|||
async function fetchData() { |
|||
if (!table || !table.length) return |
|||
|
|||
const FETCH_ROWS_URL = `/api/views/all_${table}` |
|||
const response = await _bb.api.get(FETCH_ROWS_URL) |
|||
if (response.status === 200) { |
|||
const json = await response.json() |
|||
|
|||
store.update(state => { |
|||
state[table] = json |
|||
return state |
|||
}) |
|||
} else { |
|||
throw new Error("Failed to fetch rows.", response) |
|||
} |
|||
} |
|||
|
|||
$: data = $store[table] || [] |
|||
$: if (table) fetchData() |
|||
|
|||
onMount(async () => { |
|||
await fetchData() |
|||
}) |
|||
</script> |
|||
|
|||
<section class:grid={layout === 'grid'} class:list={layout === 'list'}> |
|||
{#each data as data} |
|||
<div class="data-card"> |
|||
<ul> |
|||
{#each Object.keys(data) as key} |
|||
<li> |
|||
<span class="data-key">{key}:</span> |
|||
<span class="data-value">{data[key]}</span> |
|||
</li> |
|||
{/each} |
|||
</ul> |
|||
</div> |
|||
{/each} |
|||
</section> |
|||
|
|||
<style> |
|||
.list { |
|||
display: flex; |
|||
flex-direction: column; |
|||
font-family: Inter; |
|||
} |
|||
|
|||
.grid { |
|||
display: grid; |
|||
grid-template-columns: 1fr 1fr 1fr; |
|||
} |
|||
|
|||
ul { |
|||
list-style-type: none; |
|||
} |
|||
|
|||
li { |
|||
margin: 5px 0 5px 0; |
|||
} |
|||
|
|||
.data-card { |
|||
border: 1px solid #ccc; |
|||
border-radius: 5px; |
|||
padding: 10px; |
|||
} |
|||
|
|||
.data-key { |
|||
font-weight: bold; |
|||
font-size: 20px; |
|||
text-transform: capitalize; |
|||
} |
|||
</style> |
|||
@ -1,15 +0,0 @@ |
|||
<script> |
|||
export let _bb |
|||
export let table |
|||
|
|||
let searchValue = "" |
|||
|
|||
function search() { |
|||
const SEARCH_URL = _bb.api.get(``) |
|||
} |
|||
</script> |
|||
|
|||
<div> |
|||
<input type="text" bind:value={searchValue} /> |
|||
<button on:click={search}>Search</button> |
|||
</div> |
|||
@ -1,9 +0,0 @@ |
|||
<script> |
|||
export let icon = "" |
|||
export let fontSize = "1em" |
|||
export let _bb |
|||
|
|||
$: style = { fontSize } |
|||
</script> |
|||
|
|||
<i class={icon} {style} /> |
|||
@ -1,116 +0,0 @@ |
|||
<script> |
|||
import { cssVars } from "./helpers" |
|||
|
|||
export let navBarBackground = "" |
|||
export let navBarBorder = "" |
|||
export let navBarColor = "" |
|||
export let selectedItemBackground = "" |
|||
export let selectedItemColor = "" |
|||
export let selectedItemBorder = "" |
|||
export let itemHoverBackground = "" |
|||
export let itemHoverColor = "" |
|||
export let hideNavBar = false |
|||
export let selectedItem = "" |
|||
|
|||
export let _children |
|||
export let _bb |
|||
|
|||
let selectedIndex = -1 |
|||
let styleVars = {} |
|||
let components = {} |
|||
let componentElements = {} |
|||
|
|||
const hasComponentElements = () => |
|||
Object.getOwnPropertyNames(componentElements).length > 0 |
|||
|
|||
$: { |
|||
styleVars = { |
|||
navBarBackground, |
|||
navBarBorder, |
|||
navBarColor, |
|||
selectedItemBackground, |
|||
selectedItemColor, |
|||
selectedItemBorder, |
|||
itemHoverBackground, |
|||
itemHoverColor, |
|||
} |
|||
|
|||
if (_children && _children.length > 0 && hasComponentElements()) { |
|||
const currentSelectedItem = |
|||
selectedIndex > 0 ? _children[selectedIndex].title : "" |
|||
if (selectedItem && currentSelectedItem !== selectedItem) { |
|||
let i = 0 |
|||
for (let child of _children) { |
|||
if (child.title === selectedItem) { |
|||
onSelectItem(i)() |
|||
} |
|||
i++ |
|||
} |
|||
} else if (!currentSelectedItem) { |
|||
onSelectItem(0) |
|||
} |
|||
} |
|||
} |
|||
|
|||
const onSelectItem = index => () => { |
|||
selectedIndex = index |
|||
if (!components[index]) { |
|||
const comp = _bb.attachChildren(componentElements[index]) |
|||
components[index] = comp |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<div class="root" use:cssVars={styleVars}> |
|||
{#if !hideNavBar} |
|||
<div class="navbar"> |
|||
{#each _children as navItem, index} |
|||
<div |
|||
class="navitem" |
|||
on:click={onSelectItem(index)} |
|||
class:selected={selectedIndex === index}> |
|||
{navItem.title} |
|||
</div> |
|||
{/each} |
|||
</div> |
|||
{/if} |
|||
{#each _children as navItem, index} |
|||
<div class="content" bind:this={componentElements[index]} /> |
|||
{/each} |
|||
</div> |
|||
|
|||
<style> |
|||
.root { |
|||
height: 100%; |
|||
width: 100%; |
|||
grid-template-columns: [navbar] auto [content] 1fr; |
|||
display: grid; |
|||
} |
|||
|
|||
.navbar { |
|||
grid-column: navbar; |
|||
background: var(--navBarBackground); |
|||
border: var(--navBarBorder); |
|||
color: var(--navBarColor); |
|||
} |
|||
|
|||
.navitem { |
|||
padding: 10px 17px; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.navitem:hover { |
|||
background: var(--itemHoverBackground); |
|||
color: var(--itemHoverColor); |
|||
} |
|||
|
|||
.navitem.selected { |
|||
background: var(--selectedItemBackground); |
|||
border: var(--selectedItemBorder); |
|||
color: var(--selectedItemColor); |
|||
} |
|||
|
|||
.content { |
|||
grid-column: content; |
|||
} |
|||
</style> |
|||
@ -1,77 +0,0 @@ |
|||
<script> |
|||
export let columns = [] |
|||
export let data = "" |
|||
export let tableClass = "" |
|||
export let theadClass = "" |
|||
export let tbodyClass = "" |
|||
export let trClass = "" |
|||
export let thClass = "" |
|||
export let onRowClick |
|||
|
|||
export let _bb |
|||
|
|||
const rowClickHandler = row => () => { |
|||
// call currently only accepts one argument, so passing row does nothing |
|||
// however, we do not expose this event anyway. I am leaving this |
|||
// in for the future, as can and probably should hande this |
|||
_bb.call("onRowClick", row) |
|||
} |
|||
|
|||
const cellValue = (colIndex, row) => { |
|||
const val = _bb.getStateOrValue(_bb.props.columns[colIndex].value, row) |
|||
return val |
|||
} |
|||
</script> |
|||
|
|||
<table class={tableClass}> |
|||
<thead class={theadClass}> |
|||
<tr class={trClass}> |
|||
{#each columns as col} |
|||
<th class={thClass}>{col.title}</th> |
|||
{/each} |
|||
</tr> |
|||
</thead> |
|||
<tbody class={tbodyClass}> |
|||
{#if data} |
|||
{#each data as row} |
|||
<tr class={trClass} on:click={rowClickHandler(row)}> |
|||
{#each columns as col, index} |
|||
<th class={thClass}>{cellValue(index, row)}</th> |
|||
{/each} |
|||
</tr> |
|||
{/each} |
|||
{/if} |
|||
</tbody> |
|||
</table> |
|||
|
|||
<style> |
|||
.table-default { |
|||
width: 100%; |
|||
margin-bottom: 1rem; |
|||
color: #212529; |
|||
border-collapse: collapse; |
|||
} |
|||
|
|||
.table-default .thead-default .th-default { |
|||
vertical-align: bottom; |
|||
border-bottom: 2px solid #dee2e6; |
|||
font-weight: bold; |
|||
} |
|||
|
|||
.table-default .th-default { |
|||
padding: 0.75rem; |
|||
vertical-align: top; |
|||
border-top: 1px solid #dee2e6; |
|||
font-weight: normal; |
|||
} |
|||
|
|||
.th-default { |
|||
text-align: inherit; |
|||
} |
|||
|
|||
.table-default .tbody-default .tr-default:hover { |
|||
color: #212529; |
|||
background-color: rgba(0, 0, 0, 0.075); |
|||
cursor: pointer; |
|||
} |
|||
</style> |
|||
@ -1,10 +0,0 @@ |
|||
<script> |
|||
export let className = "" |
|||
export let _bb |
|||
|
|||
let thead |
|||
|
|||
$: _bb.attachChildren(thead) |
|||
</script> |
|||
|
|||
<tbody bind:this={thead} class="className" /> |
|||
@ -1,10 +0,0 @@ |
|||
<script> |
|||
export let className = "" |
|||
export let _bb |
|||
|
|||
let thead |
|||
|
|||
$: _bb.attachChildren(thead) |
|||
</script> |
|||
|
|||
<thead bind:this={thead} class="className" /> |
|||
@ -1,20 +0,0 @@ |
|||
import api from "../../api" |
|||
|
|||
let cache = {} |
|||
|
|||
async function fetchTable(id) { |
|||
const FETCH_TABLE_URL = `/api/tables/${id}` |
|||
const response = await api.get(FETCH_TABLE_URL) |
|||
return await response.json() |
|||
} |
|||
|
|||
export async function getTable(tableId) { |
|||
if (!tableId) { |
|||
return null |
|||
} |
|||
if (!cache[tableId]) { |
|||
cache[tableId] = fetchTable(tableId) |
|||
cache[tableId] = await cache[tableId] |
|||
} |
|||
return await cache[tableId] |
|||
} |
|||
Loading…
Reference in new issue