mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
feat: 1.0.0 appwrite support (#36)
* style: remove padding and x label * feat: add new colors, play with opacity * feat: moved options inside the componenet * chore: bump css to 0.0.0-40 * disabled animations * add bar chart * feat: use charts in dashboard * fix typings * fix typing * fix: some thigs * refactor: chart components * fix: remove function from charts * fix: charts loading condition * feat: 1.0.0 support * fix: charts and project list Co-authored-by: Torsten Dittmann <torsten.dittmann@googlemail.com>
This commit is contained in:
co-authored by
Torsten Dittmann
parent
4b00b0b26a
commit
4cdfd1b575
Generated
+7
-7
@@ -8,7 +8,7 @@
|
||||
"name": "@appwrite/console",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"@aw-labs/appwrite-console": "^5.0.5",
|
||||
"@aw-labs/appwrite-console": "^6.0.0",
|
||||
"@aw-labs/icons": "0.0.0-55",
|
||||
"@aw-labs/ui": "0.0.0-55",
|
||||
"echarts": "^5.3.3",
|
||||
@@ -68,9 +68,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@aw-labs/appwrite-console": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-5.0.5.tgz",
|
||||
"integrity": "sha512-xNyLAr/1KP7JagAwe6zbYRBWp7RgHEwptmCTVeJ/ASxVb0Rz6ItND8nG72dCg9D+lRVI5Qkk6Ks7Xmcj7TZpfg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-6.0.0.tgz",
|
||||
"integrity": "sha512-g4sCMGiIptDUyKhJSfiKsG/gzqMIt3MQCdqod6bNWMunbXUqN7DeA0BT4MuTeVGdQuoOKuSmgHeExatlu0Dh9Q==",
|
||||
"dependencies": {
|
||||
"cross-fetch": "3.1.5",
|
||||
"isomorphic-form-data": "2.0.0"
|
||||
@@ -8192,9 +8192,9 @@
|
||||
}
|
||||
},
|
||||
"@aw-labs/appwrite-console": {
|
||||
"version": "5.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-5.0.5.tgz",
|
||||
"integrity": "sha512-xNyLAr/1KP7JagAwe6zbYRBWp7RgHEwptmCTVeJ/ASxVb0Rz6ItND8nG72dCg9D+lRVI5Qkk6Ks7Xmcj7TZpfg==",
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@aw-labs/appwrite-console/-/appwrite-console-6.0.0.tgz",
|
||||
"integrity": "sha512-g4sCMGiIptDUyKhJSfiKsG/gzqMIt3MQCdqod6bNWMunbXUqN7DeA0BT4MuTeVGdQuoOKuSmgHeExatlu0Dh9Q==",
|
||||
"requires": {
|
||||
"cross-fetch": "3.1.5",
|
||||
"isomorphic-form-data": "2.0.0"
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
"e2e": "playwright test tests/e2e"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aw-labs/appwrite-console": "^5.0.5",
|
||||
"@aw-labs/appwrite-console": "^6.0.0",
|
||||
"@aw-labs/icons": "0.0.0-55",
|
||||
"@aw-labs/ui": "0.0.0-55",
|
||||
"echarts": "^5.3.3",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<script lang="ts">
|
||||
import type { BarSeriesOption } from 'echarts/charts';
|
||||
import Base from './base.svelte';
|
||||
|
||||
export let series: BarSeriesOption[];
|
||||
</script>
|
||||
|
||||
<Base
|
||||
series={series.map((s) => {
|
||||
s.type = 'bar';
|
||||
s.stack = 'total';
|
||||
s.barMaxWidth = 6;
|
||||
s.itemStyle = {
|
||||
borderRadius: [10, 10, 0, 0]
|
||||
};
|
||||
|
||||
return s;
|
||||
})} />
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"color": ["#ff80b7", "#a1c4ff", "#cbb1fc", "#94dbd1", "#fdc584", "#f02e65", "#ffa1a1"],
|
||||
"backgroundColor": "rgba(255,255,255,0)",
|
||||
"textStyle": {},
|
||||
"line": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 1
|
||||
},
|
||||
"lineStyle": {
|
||||
"width": 2
|
||||
},
|
||||
"symbolSize": 4,
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": true
|
||||
},
|
||||
"bar": {
|
||||
"itemStyle": {
|
||||
"barBorderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"categoryAxis": {
|
||||
"axisLine": {
|
||||
"show": true
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true
|
||||
},
|
||||
"splitLine": {
|
||||
"show": false
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false
|
||||
}
|
||||
},
|
||||
"valueAxis": {
|
||||
"axisLine": {
|
||||
"show": false
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false
|
||||
}
|
||||
},
|
||||
"logAxis": {
|
||||
"axisLine": {
|
||||
"show": true
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false
|
||||
}
|
||||
},
|
||||
"timeAxis": {
|
||||
"axisLine": {
|
||||
"show": true
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"axisPointer": {
|
||||
"lineStyle": {
|
||||
"width": 1
|
||||
},
|
||||
"crossStyle": {
|
||||
"width": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"lineStyle": {
|
||||
"width": 1
|
||||
},
|
||||
"itemStyle": {
|
||||
"borderWidth": 1
|
||||
},
|
||||
"controlStyle": {
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"emphasis": {
|
||||
"controlStyle": {
|
||||
"borderWidth": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<script lang="ts">
|
||||
import { registerTheme, use, init } from 'echarts/core';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { defaultConfig } from './config';
|
||||
import base from './base.json';
|
||||
import light from './light.json';
|
||||
import dark from './dark.json';
|
||||
import type { ECharts } from 'echarts/core';
|
||||
import type { BarSeriesOption, LineSeriesOption } from 'echarts/charts';
|
||||
|
||||
registerTheme('light', { ...base, ...light });
|
||||
registerTheme('dark', { ...base, ...dark });
|
||||
|
||||
export let series: (BarSeriesOption | LineSeriesOption)[];
|
||||
|
||||
let chart: ECharts;
|
||||
let container: HTMLDivElement;
|
||||
|
||||
$: option = {
|
||||
...defaultConfig,
|
||||
series
|
||||
};
|
||||
|
||||
$: option && setOption();
|
||||
$: if (chart && $app.themeInUse) {
|
||||
makeChart();
|
||||
setOption();
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
use([
|
||||
(await import('echarts/charts')).BarChart,
|
||||
(await import('echarts/charts')).LineChart,
|
||||
(await import('echarts/components')).TitleComponent,
|
||||
(await import('echarts/components')).TooltipComponent,
|
||||
(await import('echarts/components')).GridComponent,
|
||||
(await import('echarts/components')).DatasetComponent,
|
||||
(await import('echarts/components')).TransformComponent,
|
||||
(await import('echarts/components')).LegendComponent,
|
||||
(await import('echarts/features')).LabelLayout,
|
||||
(await import('echarts/renderers')).CanvasRenderer
|
||||
]);
|
||||
makeChart();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
destroyChart();
|
||||
});
|
||||
|
||||
const setOption = () => {
|
||||
if (chart && !chart.isDisposed()) {
|
||||
chart.setOption(option);
|
||||
}
|
||||
};
|
||||
|
||||
const destroyChart = () => {
|
||||
if (chart && !chart.isDisposed()) {
|
||||
chart.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
const makeChart = () => {
|
||||
destroyChart();
|
||||
chart = init(container, $app.themeInUse);
|
||||
};
|
||||
|
||||
let timeoutId: unknown;
|
||||
const onResize = () => {
|
||||
if (timeoutId == undefined) {
|
||||
timeoutId = setTimeout(() => {
|
||||
if (chart && !chart.isDisposed()) {
|
||||
chart.resize();
|
||||
}
|
||||
timeoutId = undefined;
|
||||
}, 250);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<svelte:window on:resize={onResize} />
|
||||
|
||||
<div class="echart" bind:this={container} />
|
||||
|
||||
<style>
|
||||
.echart {
|
||||
width: 100%;
|
||||
min-height: 12rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { EChartsOption } from 'echarts';
|
||||
|
||||
export const defaultConfig: EChartsOption = {
|
||||
animation: false,
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
grid: {
|
||||
containLabel: true,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 15,
|
||||
top: 15
|
||||
},
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
show: false
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
splitNumber: 3,
|
||||
minInterval: 1
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"color": ["#f02e65", "#a1c4ff", "#cbb1fc", "#94dbd1", "#fdc584", "#f02e65", "#ffa1a1"],
|
||||
"backgroundColor": "rgba(0,0,0,0)",
|
||||
"title": {
|
||||
"textStyle": {
|
||||
"color": "#eeeeee"
|
||||
},
|
||||
"subtextStyle": {
|
||||
"color": "#aaaaaa"
|
||||
}
|
||||
},
|
||||
"bar": {
|
||||
"itemStyle": {
|
||||
"barBorderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"categoryAxis": {
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": "#444444"
|
||||
},
|
||||
"splitLine": {
|
||||
"lineStyle": {
|
||||
"color": ["#444444"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"areaStyle": {
|
||||
"color": ["#eeeeee"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"valueAxis": {
|
||||
"axisTick": {
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": "#666666"
|
||||
},
|
||||
"splitLine": {
|
||||
"lineStyle": {
|
||||
"color": ["#333333"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false
|
||||
}
|
||||
},
|
||||
"logAxis": {
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": "#666666"
|
||||
},
|
||||
"splitLine": {
|
||||
"lineStyle": {
|
||||
"color": ["#333333"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeAxis": {
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": "#666666"
|
||||
},
|
||||
"splitLine": {
|
||||
"lineStyle": {
|
||||
"color": ["#333333"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolbox": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#999999"
|
||||
},
|
||||
"emphasis": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"textStyle": {
|
||||
"color": "#eeeeee"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"axisPointer": {
|
||||
"lineStyle": {
|
||||
"color": "#444444"
|
||||
},
|
||||
"crossStyle": {
|
||||
"color": "#444444"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"lineStyle": {
|
||||
"color": "#444444"
|
||||
},
|
||||
"itemStyle": {
|
||||
"color": "#dd6b66"
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#444444",
|
||||
"borderColor": "#444444"
|
||||
},
|
||||
"checkpointStyle": {
|
||||
"color": "#e43c59",
|
||||
"borderColor": "#c23531"
|
||||
},
|
||||
"label": {
|
||||
"color": "#eeeeee"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"color": "#a9334c"
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#444444",
|
||||
"borderColor": "#444444"
|
||||
},
|
||||
"label": {
|
||||
"color": "#eeeeee"
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualMap": {
|
||||
"color": ["#bf444c", "#d88273", "#f6efa6"]
|
||||
},
|
||||
"markPoint": {
|
||||
"label": {
|
||||
"color": "#444444"
|
||||
},
|
||||
"emphasis": {
|
||||
"label": {
|
||||
"color": "#444444"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
{
|
||||
"color": ["#00a7c3", "#F02E65", "#00BC5D", "#F38500", "#FF453A"],
|
||||
"backgroundColor": "rgba(0,0,0,0)",
|
||||
"textStyle": {},
|
||||
"title": {
|
||||
"textStyle": {
|
||||
"color": "#eeeeee"
|
||||
},
|
||||
"subtextStyle": {
|
||||
"color": "#aaaaaa"
|
||||
}
|
||||
},
|
||||
"line": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 1
|
||||
},
|
||||
"lineStyle": {
|
||||
"width": 2
|
||||
},
|
||||
"symbolSize": 4,
|
||||
"symbol": "circle",
|
||||
"smooth": true
|
||||
},
|
||||
"radar": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 1
|
||||
},
|
||||
"lineStyle": {
|
||||
"width": 2
|
||||
},
|
||||
"symbolSize": 4,
|
||||
"symbol": "circle",
|
||||
"smooth": true
|
||||
},
|
||||
"bar": {
|
||||
"itemStyle": {
|
||||
"barBorderWidth": "0",
|
||||
"barBorderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"pie": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"scatter": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"boxplot": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"parallel": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"sankey": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"funnel": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"gauge": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
},
|
||||
"candlestick": {
|
||||
"itemStyle": {
|
||||
"color": "#fd1050",
|
||||
"color0": "#0cf49b",
|
||||
"borderColor": "#fd1050",
|
||||
"borderColor0": "#0cf49b",
|
||||
"borderWidth": 1
|
||||
}
|
||||
},
|
||||
"graph": {
|
||||
"itemStyle": {
|
||||
"borderWidth": "0",
|
||||
"borderColor": "#444444"
|
||||
},
|
||||
"lineStyle": {
|
||||
"width": 1,
|
||||
"color": "#aaaaaa"
|
||||
},
|
||||
"symbolSize": 4,
|
||||
"symbol": "circle",
|
||||
"smooth": true,
|
||||
"color": ["#dd6b66", "#759aa0", "#e69d87", "#f38500", "#ff453a"],
|
||||
"label": {
|
||||
"color": "#444444"
|
||||
}
|
||||
},
|
||||
"map": {
|
||||
"itemStyle": {
|
||||
"areaColor": "#eee",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"label": {
|
||||
"color": "#000"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"areaColor": "rgba(255,215,0,0.8)",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"label": {
|
||||
"color": "rgb(100,0,0)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"geo": {
|
||||
"itemStyle": {
|
||||
"areaColor": "#eee",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"label": {
|
||||
"color": "#000"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"areaColor": "rgba(255,215,0,0.8)",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"label": {
|
||||
"color": "rgb(100,0,0)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"categoryAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#444444"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": ["#444444"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["#eeeeee"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"valueAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#666666"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": ["#333333"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["#666666"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"logAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#666666"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": ["#333333"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["#666666"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#333333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#666666"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": ["#333333"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["#666666"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolbox": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#999999"
|
||||
},
|
||||
"emphasis": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#444444"
|
||||
}
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"textStyle": {
|
||||
"color": "#eeeeee"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"axisPointer": {
|
||||
"lineStyle": {
|
||||
"color": "#444444",
|
||||
"width": "1"
|
||||
},
|
||||
"crossStyle": {
|
||||
"color": "#444444",
|
||||
"width": "1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"lineStyle": {
|
||||
"color": "#444444",
|
||||
"width": 1
|
||||
},
|
||||
"itemStyle": {
|
||||
"color": "#dd6b66",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#444444",
|
||||
"borderColor": "#444444",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"checkpointStyle": {
|
||||
"color": "#e43c59",
|
||||
"borderColor": "#c23531"
|
||||
},
|
||||
"label": {
|
||||
"color": "#eeeeee"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"color": "#a9334c"
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#444444",
|
||||
"borderColor": "#444444",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"label": {
|
||||
"color": "#eeeeee"
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualMap": {
|
||||
"color": ["#bf444c", "#d88273", "#f6efa6"]
|
||||
},
|
||||
"dataZoom": {
|
||||
"backgroundColor": "rgba(47,69,84,0)",
|
||||
"dataBackgroundColor": "rgba(255,255,255,0.3)",
|
||||
"fillerColor": "rgba(167,183,204,0.4)",
|
||||
"handleColor": "#a7b7cc",
|
||||
"handleSize": "100%",
|
||||
"textStyle": {
|
||||
"color": "#eeeeee"
|
||||
}
|
||||
},
|
||||
"markPoint": {
|
||||
"label": {
|
||||
"color": "#444444"
|
||||
},
|
||||
"emphasis": {
|
||||
"label": {
|
||||
"color": "#444444"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,348 +0,0 @@
|
||||
{
|
||||
"color": ["#00a7c3", "#F02E65", "#00BC5D", "#F38500", "#FF453A"],
|
||||
"backgroundColor": "rgba(255,255,255,0)",
|
||||
"textStyle": {},
|
||||
"title": {
|
||||
"textStyle": {
|
||||
"color": "#373b4d"
|
||||
},
|
||||
"subtextStyle": {
|
||||
"color": "#616b7c"
|
||||
}
|
||||
},
|
||||
"line": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 1
|
||||
},
|
||||
"lineStyle": {
|
||||
"width": 2
|
||||
},
|
||||
"symbolSize": 4,
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": false
|
||||
},
|
||||
"radar": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 1
|
||||
},
|
||||
"lineStyle": {
|
||||
"width": 2
|
||||
},
|
||||
"symbolSize": 4,
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": false
|
||||
},
|
||||
"bar": {
|
||||
"itemStyle": {
|
||||
"barBorderWidth": 0,
|
||||
"barBorderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"pie": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"scatter": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"boxplot": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"parallel": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"sankey": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"funnel": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"gauge": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"candlestick": {
|
||||
"itemStyle": {
|
||||
"color": "#eb5454",
|
||||
"color0": "#47b262",
|
||||
"borderColor": "#eb5454",
|
||||
"borderColor0": "#47b262",
|
||||
"borderWidth": 1
|
||||
}
|
||||
},
|
||||
"graph": {
|
||||
"itemStyle": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"lineStyle": {
|
||||
"width": 1,
|
||||
"color": "#aaa"
|
||||
},
|
||||
"symbolSize": 4,
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": false,
|
||||
"color": ["#007187", "#da1a5b", "#fac858", "#ee6666", "#73c0de"],
|
||||
"label": {
|
||||
"color": "#eee"
|
||||
}
|
||||
},
|
||||
"map": {
|
||||
"itemStyle": {
|
||||
"areaColor": "#eee",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"label": {
|
||||
"color": "#000"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"areaColor": "rgba(255,215,0,0.8)",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"label": {
|
||||
"color": "rgb(100,0,0)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"geo": {
|
||||
"itemStyle": {
|
||||
"areaColor": "#eee",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"label": {
|
||||
"color": "#000"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"areaColor": "rgba(255,215,0,0.8)",
|
||||
"borderColor": "#444",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"label": {
|
||||
"color": "rgb(100,0,0)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"categoryAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#6E7079"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": ["#E0E6F1"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["rgba(250,250,250,0.2)", "rgba(210,219,238,0.2)"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"valueAxis": {
|
||||
"axisLine": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#6E7079"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": ["#E0E6F1"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["rgba(250,250,250,0.2)", "rgba(210,219,238,0.2)"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"logAxis": {
|
||||
"axisLine": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#6E7079"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": ["#E0E6F1"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["rgba(250,250,250,0.2)", "rgba(210,219,238,0.2)"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"color": "#6E7079"
|
||||
},
|
||||
"splitLine": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": ["#E0E6F1"]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": ["rgba(250,250,250,0.2)", "rgba(210,219,238,0.2)"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolbox": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#999"
|
||||
},
|
||||
"emphasis": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#666"
|
||||
}
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"textStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"axisPointer": {
|
||||
"lineStyle": {
|
||||
"color": "#ccc",
|
||||
"width": 1
|
||||
},
|
||||
"crossStyle": {
|
||||
"color": "#ccc",
|
||||
"width": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"lineStyle": {
|
||||
"color": "#DAE1F5",
|
||||
"width": 2
|
||||
},
|
||||
"itemStyle": {
|
||||
"color": "#A4B1D7",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#A4B1D7",
|
||||
"borderColor": "#A4B1D7",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"checkpointStyle": {
|
||||
"color": "#316bf3",
|
||||
"borderColor": "fff"
|
||||
},
|
||||
"label": {
|
||||
"color": "#A4B1D7"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"color": "#FFF"
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#A4B1D7",
|
||||
"borderColor": "#A4B1D7",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"label": {
|
||||
"color": "#A4B1D7"
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualMap": {
|
||||
"color": ["#bf444c", "#d88273", "#f6efa6"]
|
||||
},
|
||||
"dataZoom": {
|
||||
"handleSize": "undefined%",
|
||||
"textStyle": {}
|
||||
},
|
||||
"markPoint": {
|
||||
"label": {
|
||||
"color": "#eee"
|
||||
},
|
||||
"emphasis": {
|
||||
"label": {
|
||||
"color": "#eee"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { registerTheme, use, init, graphic } from 'echarts/core';
|
||||
import type { ECharts } from 'echarts/core';
|
||||
import type { LineSeriesOption } from 'echarts/charts';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import { app } from '$lib/stores/app';
|
||||
import light from './echartLight.json';
|
||||
import dark from './echartDark.json';
|
||||
|
||||
registerTheme('light', light);
|
||||
registerTheme('dark', dark);
|
||||
|
||||
export let series: LineSeriesOption[];
|
||||
export let title: string;
|
||||
|
||||
let chart: ECharts;
|
||||
$: option = {
|
||||
animationDuration: 400,
|
||||
title: {
|
||||
text: ''
|
||||
},
|
||||
legend: {
|
||||
orient: 'vertical',
|
||||
right: 10,
|
||||
top: 'center'
|
||||
},
|
||||
tooltip: { trigger: 'axis' },
|
||||
xAxis: {
|
||||
type: 'time',
|
||||
show: true
|
||||
},
|
||||
yAxis: { type: 'value' },
|
||||
series
|
||||
};
|
||||
let notMerge = false;
|
||||
let lazyUpdate = false;
|
||||
let timeoutId: unknown;
|
||||
|
||||
$: option && setOption();
|
||||
$: if (chart && $app.themeInUse) {
|
||||
makeChart();
|
||||
setOption();
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
use([
|
||||
(await import('echarts/charts')).LineChart,
|
||||
(await import('echarts/components')).TitleComponent,
|
||||
(await import('echarts/components')).TooltipComponent,
|
||||
(await import('echarts/components')).GridComponent,
|
||||
(await import('echarts/components')).DatasetComponent,
|
||||
(await import('echarts/components')).TransformComponent,
|
||||
(await import('echarts/components')).LegendComponent,
|
||||
(await import('echarts/features')).LabelLayout,
|
||||
(await import('echarts/features')).UniversalTransition,
|
||||
(await import('echarts/renderers')).CanvasRenderer
|
||||
]);
|
||||
makeChart();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
destroyChart();
|
||||
});
|
||||
const setOption = () => {
|
||||
if (chart && !chart.isDisposed()) {
|
||||
chart.setOption(option, notMerge, lazyUpdate);
|
||||
}
|
||||
};
|
||||
|
||||
const destroyChart = () => {
|
||||
if (chart && !chart.isDisposed()) {
|
||||
chart.dispose();
|
||||
}
|
||||
};
|
||||
|
||||
const makeChart = () => {
|
||||
destroyChart();
|
||||
chart = init(document.getElementById(`echart-${title}`), $app.themeInUse);
|
||||
series.forEach((s: LineSeriesOption, i: number) => {
|
||||
s.areaStyle = colorToGradient(chart['_theme'].color[i]);
|
||||
});
|
||||
};
|
||||
|
||||
function colorToGradient(color: string) {
|
||||
return {
|
||||
opacity: 0.8,
|
||||
color: new graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{
|
||||
offset: 0,
|
||||
color: `${color}`
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: `${color}30`
|
||||
}
|
||||
])
|
||||
};
|
||||
}
|
||||
window.onresize = () => {
|
||||
if (chart && !chart.isDisposed()) {
|
||||
handleResize();
|
||||
}
|
||||
};
|
||||
const handleResize = () => {
|
||||
if (timeoutId == undefined) {
|
||||
timeoutId = setTimeout(() => {
|
||||
if (chart && !chart.isDisposed()) {
|
||||
chart.resize();
|
||||
}
|
||||
timeoutId = undefined;
|
||||
}, 500);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="echart" id={`echart-${title}`} />
|
||||
|
||||
<style>
|
||||
.echart {
|
||||
width: 100%;
|
||||
min-height: 20rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1 +1,2 @@
|
||||
export { default as Chart } from './echarts.svelte';
|
||||
export { default as BarChart } from './bar.svelte';
|
||||
export { default as LineChart } from './line.svelte';
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
{
|
||||
"color": ["#ff80b7", "#a1c4ff", "#cbb1fc", "#94dbd1", "#fdc584", "#f02e65", "#ffa1a1"],
|
||||
"backgroundColor": "rgba(255,255,255,0)",
|
||||
"title": {
|
||||
"textStyle": {
|
||||
"color": "#373b4d"
|
||||
},
|
||||
"subtextStyle": {
|
||||
"color": "#616b7c"
|
||||
}
|
||||
},
|
||||
"bar": {
|
||||
"itemStyle": {
|
||||
"barBorderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"categoryAxis": {
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"valueAxis": {
|
||||
"axisLabel": {
|
||||
"color": "#6E7079"
|
||||
},
|
||||
"splitLine": {
|
||||
"lineStyle": {
|
||||
"color": ["#E0E6F1"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"logAxis": {
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": "#6E7079"
|
||||
},
|
||||
"splitLine": {
|
||||
"lineStyle": {
|
||||
"color": ["#E0E6F1"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeAxis": {
|
||||
"axisLine": {
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"lineStyle": {
|
||||
"color": "#6E7079"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"color": "#6E7079"
|
||||
},
|
||||
"splitLine": {
|
||||
"lineStyle": {
|
||||
"color": ["#E0E6F1"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolbox": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#999"
|
||||
},
|
||||
"emphasis": {
|
||||
"iconStyle": {
|
||||
"borderColor": "#666"
|
||||
}
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"textStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"axisPointer": {
|
||||
"lineStyle": {
|
||||
"color": "#ccc"
|
||||
},
|
||||
"crossStyle": {
|
||||
"color": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"lineStyle": {
|
||||
"color": "#DAE1F5"
|
||||
},
|
||||
"itemStyle": {
|
||||
"color": "#A4B1D7"
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#A4B1D7",
|
||||
"borderColor": "#A4B1D7"
|
||||
},
|
||||
"checkpointStyle": {
|
||||
"color": "#316bf3",
|
||||
"borderColor": "#fff"
|
||||
},
|
||||
"label": {
|
||||
"color": "#A4B1D7"
|
||||
},
|
||||
"emphasis": {
|
||||
"itemStyle": {
|
||||
"color": "#FFF"
|
||||
},
|
||||
"controlStyle": {
|
||||
"color": "#A4B1D7",
|
||||
"borderColor": "#A4B1D7"
|
||||
},
|
||||
"label": {
|
||||
"color": "#A4B1D7"
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualMap": {
|
||||
"color": ["#bf444c", "#d88273", "#f6efa6"]
|
||||
},
|
||||
"markPoint": {
|
||||
"label": {
|
||||
"color": "#eee"
|
||||
},
|
||||
"emphasis": {
|
||||
"label": {
|
||||
"color": "#eee"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<script lang="ts">
|
||||
import type { LineSeriesOption } from 'echarts/charts';
|
||||
import Base from './base.svelte';
|
||||
|
||||
export let series: LineSeriesOption[];
|
||||
</script>
|
||||
|
||||
<Base
|
||||
series={series.map((s) => {
|
||||
s.type = 'line';
|
||||
s.stack = 'total';
|
||||
s.showSymbol = false;
|
||||
|
||||
return s;
|
||||
})} />
|
||||
@@ -1,5 +1,5 @@
|
||||
export const toLocaleDate = (timestamp: number) => {
|
||||
const date = new Date(timestamp * 1000);
|
||||
export const toLocaleDate = (datetime: string) => {
|
||||
const date = new Date(datetime);
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
@@ -9,8 +9,8 @@ export const toLocaleDate = (timestamp: number) => {
|
||||
return date.toLocaleDateString('en', options);
|
||||
};
|
||||
|
||||
export const toLocaleDateTime = (timestamp: number) => {
|
||||
const date = new Date(timestamp * 1000);
|
||||
export const toLocaleDateTime = (datetime: string) => {
|
||||
const date = new Date(datetime);
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
|
||||
@@ -19,3 +19,55 @@ export function bytesToSize(value: number, unit: string) {
|
||||
const index = sizes.indexOf(unit);
|
||||
return value / Math.pow(1024, index);
|
||||
}
|
||||
|
||||
export function humanFileSize(value: number): {
|
||||
value: string;
|
||||
unit: string;
|
||||
} {
|
||||
const length = value.toString().length;
|
||||
const unit =
|
||||
length < 7
|
||||
? 'kilobyte'
|
||||
: length < 11
|
||||
? 'megabyte'
|
||||
: length < 15
|
||||
? 'gigabyte'
|
||||
: length < 19
|
||||
? 'terabyte'
|
||||
: 'petabyte';
|
||||
|
||||
const formatter = Intl.NumberFormat('en', {
|
||||
style: 'unit',
|
||||
maximumSignificantDigits: 3,
|
||||
maximumFractionDigits: 2,
|
||||
unit
|
||||
});
|
||||
|
||||
while (value > 1000) {
|
||||
value /= 1000;
|
||||
}
|
||||
|
||||
const parts: {
|
||||
integer: string;
|
||||
unit: string;
|
||||
fraction?: string;
|
||||
decimal?: string;
|
||||
} = formatter.formatToParts(value).reduce(
|
||||
(prev, curr) => {
|
||||
prev[curr.type] = curr.value;
|
||||
|
||||
return prev;
|
||||
},
|
||||
{
|
||||
integer: '',
|
||||
unit: '',
|
||||
decimal: '',
|
||||
fraction: ''
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
value: `${parts.integer}${parts.decimal}${parts.fraction}`,
|
||||
unit: parts.unit
|
||||
};
|
||||
}
|
||||
|
||||
@@ -40,19 +40,12 @@ export const organization = cachedStore<
|
||||
export const projectList = cachedStore<
|
||||
Models.ProjectList,
|
||||
{
|
||||
load: (search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (queries: string[], search?: string) => Promise<void>;
|
||||
}
|
||||
>('projectList', function ({ set }) {
|
||||
return {
|
||||
load: async (search, limit, offset) => {
|
||||
const response = await sdkForConsole.projects.list(
|
||||
search,
|
||||
limit,
|
||||
offset,
|
||||
undefined,
|
||||
undefined,
|
||||
'ASC'
|
||||
);
|
||||
load: async (queries, search) => {
|
||||
const response = await sdkForConsole.projects.list(queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
@@ -61,17 +54,12 @@ export const projectList = cachedStore<
|
||||
export const memberList = cachedStore<
|
||||
Models.MembershipList,
|
||||
{
|
||||
load: (teamId: string, search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (teamId: string, queries?: string[], search?: string) => Promise<void>;
|
||||
}
|
||||
>('memberList', function ({ set }) {
|
||||
return {
|
||||
load: async (teamId, search, limit, offset) => {
|
||||
const response = await sdkForConsole.teams.getMemberships(
|
||||
teamId,
|
||||
search,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
load: async (teamId, queries, search) => {
|
||||
const response = await sdkForConsole.teams.listMemberships(teamId, queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import { writable } from 'svelte/store';
|
||||
import { sdkForConsole } from './sdk';
|
||||
|
||||
function createUserStore() {
|
||||
const { subscribe, set } = writable<Models.User<Record<string, unknown>>>();
|
||||
const { subscribe, set } = writable<Models.Account<Record<string, unknown>>>();
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
|
||||
@@ -16,14 +16,15 @@
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
import { onMount } from 'svelte';
|
||||
import { accountActivity } from '../store';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
let offset = 0;
|
||||
|
||||
onMount(async () => {
|
||||
await accountActivity.load($pageLimit, offset);
|
||||
await accountActivity.load([Query.offset(offset), Query.limit($pageLimit)]);
|
||||
});
|
||||
|
||||
$: accountActivity.load($pageLimit, offset);
|
||||
$: accountActivity.load([Query.offset(offset), Query.limit($pageLimit)]);
|
||||
|
||||
const getBrowser = (clientCode: string) => {
|
||||
return sdkForConsole.avatars.getBrowser(clientCode, 40, 40);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
};
|
||||
|
||||
const getMemberships = async (teamId: string) => {
|
||||
const memberships = await sdkForConsole.teams.getMemberships(teamId);
|
||||
const memberships = await sdkForConsole.teams.listMemberships(teamId);
|
||||
return memberships.memberships.map((team) => {
|
||||
return {
|
||||
name: team.userName,
|
||||
|
||||
@@ -10,7 +10,7 @@ export const accountSession = cachedStore<
|
||||
>('accountSession', function ({ set }) {
|
||||
return {
|
||||
load: async () => {
|
||||
const response = await sdkForConsole.account.getSessions();
|
||||
const response = await sdkForConsole.account.listSessions();
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
@@ -18,12 +18,12 @@ export const accountSession = cachedStore<
|
||||
export const accountActivity = cachedStore<
|
||||
Models.LogList,
|
||||
{
|
||||
load: (limit: number, offset: number) => Promise<void>;
|
||||
load: (queries: string[]) => Promise<void>;
|
||||
}
|
||||
>('accountActivity', function ({ set }) {
|
||||
return {
|
||||
load: async (limit, offset) => {
|
||||
const response = await sdkForConsole.account.getLogs(limit, offset);
|
||||
load: async (queries) => {
|
||||
const response = await sdkForConsole.account.listLogs(queries);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
import CreateMember from './_createMember.svelte';
|
||||
import Create from '../_createOrganization.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
$: organizationId = $page.params.organization;
|
||||
$: path = `console/organization-${organizationId}`;
|
||||
@@ -22,7 +23,7 @@
|
||||
async function handle(event = null) {
|
||||
if ($organization?.$id !== organizationId) {
|
||||
await organization.load(organizationId);
|
||||
await memberList.load(organizationId, '', 12, 0);
|
||||
await memberList.load(organizationId, [Query.limit(12)]);
|
||||
}
|
||||
updateLayout({
|
||||
navigate: event,
|
||||
|
||||
@@ -1,25 +1,31 @@
|
||||
<script lang="ts">
|
||||
import { goto } from '$app/navigation';
|
||||
import { afterNavigate, goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { Pill } from '$lib/elements';
|
||||
import { GridItem1, EmptyGridItem, Empty, Pagination } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import CreateOrganization from '../_createOrganization.svelte';
|
||||
import CreateProject from './_createProject.svelte';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import { projectList } from '$lib/stores/organization';
|
||||
import { project } from '../project-[project]/store';
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import CreateOrganization from '../_createOrganization.svelte';
|
||||
import CreateProject from './_createProject.svelte';
|
||||
|
||||
let projects: Models.Project[] = [];
|
||||
$: organizationId = $page.params.organization;
|
||||
|
||||
onMount(async () => {
|
||||
await projectList.load('', undefined, offset);
|
||||
projects = $projectList?.projects?.filter((n) => n.teamId === organizationId);
|
||||
});
|
||||
onMount(handle);
|
||||
afterNavigate(handle);
|
||||
|
||||
async function handle() {
|
||||
await projectList.load([
|
||||
Query.offset(offset),
|
||||
Query.limit(limit),
|
||||
Query.equal('teamId', organizationId)
|
||||
]);
|
||||
}
|
||||
|
||||
let showCreate = false;
|
||||
let addOrganization = false;
|
||||
@@ -56,7 +62,7 @@
|
||||
};
|
||||
|
||||
// $: projectList.load('', limit, offset);
|
||||
$: projects = $projectList?.projects?.filter((a) => a.teamId === organizationId);
|
||||
// $: projects = $projectList?.projects?.filter((a) => a.teamId === organizationId);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
@@ -71,17 +77,18 @@
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{#if projects?.length}
|
||||
{#if $projectList.total}
|
||||
<ul
|
||||
class="grid-box common-section u-margin-block-start-32"
|
||||
style={`--grid-gap:1.5rem; --grid-item-size:${
|
||||
projects.length > 3 ? '22rem' : '25rem'
|
||||
};`}>
|
||||
{#each projects as project, index}
|
||||
{#each $projectList.projects as project, index}
|
||||
{#if index >= offset && index < limit + offset}
|
||||
<GridItem1 href={`${base}/console/project-${project.$id}`}>
|
||||
<svelte:fragment slot="eyebrow"
|
||||
>{project?.platforms?.length ? project?.platforms?.length : 'No'} apps</svelte:fragment>
|
||||
<svelte:fragment slot="eyebrow">
|
||||
{project?.platforms?.length ? project?.platforms?.length : 'No'} apps
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="title">
|
||||
{project.name}
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { organization, memberList } from '$lib/stores/organization';
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
export let showCreate = false;
|
||||
|
||||
@@ -30,7 +31,7 @@
|
||||
type: 'success',
|
||||
message: `Invite has been sent to ${email}`
|
||||
});
|
||||
memberList.load($organization.$id, '', $pageLimit, 0);
|
||||
memberList.load($organization.$id, [Query.limit($pageLimit)], '');
|
||||
dispatch('created', team);
|
||||
} catch ({ message }) {
|
||||
error = message;
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
import Delete from '../_deleteMember.svelte';
|
||||
import { organization, memberList, newMemberModal } from '$lib/stores/organization';
|
||||
import { sdkForConsole } from '$lib/stores/sdk';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
import { page } from '$app/stores';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
|
||||
let search = '';
|
||||
let offset: number = null;
|
||||
let offset = 0;
|
||||
|
||||
let selectedMember: Models.Membership;
|
||||
let showDelete = false;
|
||||
@@ -29,7 +29,8 @@
|
||||
|
||||
const getAvatar = (name: string) =>
|
||||
sdkForConsole.avatars.getInitials(name, 120, 120).toString();
|
||||
const deleted = () => memberList.load($organization.$id, search, $pageLimit, offset ?? 0);
|
||||
const deleted = () =>
|
||||
memberList.load($organization.$id, [Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
const resend = async (member: Models.Membership) => {
|
||||
try {
|
||||
await sdkForConsole.teams.createMembership(
|
||||
@@ -52,7 +53,7 @@
|
||||
};
|
||||
|
||||
$: if (search) offset = 0;
|
||||
$: memberList.load($organization.$id, search, $pageLimit, offset ?? 0);
|
||||
$: memberList.load($organization.$id, [Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { usersList } from './store';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
|
||||
let showCreate = false;
|
||||
@@ -34,7 +34,7 @@
|
||||
};
|
||||
|
||||
$: if (search) offset = 0;
|
||||
$: usersList.load(search, $pageLimit, offset ?? 0);
|
||||
$: usersList.load([Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
|
||||
@@ -5,19 +5,12 @@ import { cachedStore } from '$lib/helpers/cache';
|
||||
export const usersList = cachedStore<
|
||||
Models.UserList<Record<string, unknown>>,
|
||||
{
|
||||
load: (search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (queries: string[], search: string) => Promise<void>;
|
||||
}
|
||||
>('users', function ({ set }) {
|
||||
return {
|
||||
load: async (search, limit, offset) => {
|
||||
const response = await sdkForProject.users.list(
|
||||
search,
|
||||
limit,
|
||||
offset,
|
||||
undefined,
|
||||
undefined,
|
||||
'DESC'
|
||||
);
|
||||
load: async (queries, search) => {
|
||||
const response = await sdkForProject.users.list(queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
@@ -26,19 +19,12 @@ export const usersList = cachedStore<
|
||||
export const teamsList = cachedStore<
|
||||
Models.TeamList,
|
||||
{
|
||||
load: (search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (queries: string[], search: string) => Promise<void>;
|
||||
}
|
||||
>('teams', function ({ set }) {
|
||||
return {
|
||||
load: async (search, limit, offset) => {
|
||||
const response = await sdkForProject.teams.list(
|
||||
search,
|
||||
limit,
|
||||
offset,
|
||||
undefined,
|
||||
undefined,
|
||||
'DESC'
|
||||
);
|
||||
load: async (queries, search) => {
|
||||
const response = await sdkForProject.teams.list(queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { teamsList } from '../store';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
|
||||
let search = '';
|
||||
let showCreate = false;
|
||||
@@ -33,7 +33,7 @@
|
||||
};
|
||||
|
||||
$: if (search) offset = 0;
|
||||
$: teamsList.load(search, limit, offset);
|
||||
$: teamsList.load([Query.limit(limit), Query.offset(offset)], search);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
|
||||
+5
-1
@@ -15,10 +15,14 @@
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
let offset = 0;
|
||||
|
||||
$: request = sdkForProject.teams.listLogs($page.params.team, $pageLimit, offset);
|
||||
$: request = sdkForProject.teams.listLogs($page.params.team, [
|
||||
Query.limit($pageLimit),
|
||||
Query.offset(offset)
|
||||
]);
|
||||
|
||||
const getBrowser = (clientCode: string) => {
|
||||
return sdkForProject.avatars.getBrowser(clientCode, 80, 80);
|
||||
|
||||
+14
-5
@@ -11,7 +11,7 @@
|
||||
} from '$lib/elements/table';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Container } from '$lib/layout';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import { goto } from '$app/navigation';
|
||||
import { base } from '$app/paths';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
@@ -22,21 +22,30 @@
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
|
||||
const getAvatar = (name: string) => sdkForProject.avatars.getInitials(name, 32, 32).toString();
|
||||
const deleted = () => memberships.load($page.params.team, search, $pageLimit, offset ?? 0);
|
||||
const deleted = () =>
|
||||
memberships.load(
|
||||
$page.params.team,
|
||||
[Query.limit($pageLimit), Query.offset(offset)],
|
||||
search
|
||||
);
|
||||
|
||||
const project = $page.params.project;
|
||||
|
||||
let showCreate = false;
|
||||
let showDelete = false;
|
||||
let search = '';
|
||||
let offset: number = null;
|
||||
let offset = 0;
|
||||
let selectedMembership: Models.Membership;
|
||||
|
||||
$: if (search) offset = 0;
|
||||
$: memberships.load($page.params.team, search, $pageLimit, offset ?? 0);
|
||||
$: memberships.load($page.params.team, [Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
|
||||
const memberCreated = async (event: CustomEvent<Models.Membership>) => {
|
||||
memberships.load($page.params.team, search, $pageLimit, offset ?? 0);
|
||||
memberships.load(
|
||||
$page.params.team,
|
||||
[Query.limit($pageLimit), Query.offset(offset)],
|
||||
search
|
||||
);
|
||||
await goto(
|
||||
`${base}/console/project-${project}/authentication/teams/${event.detail.teamId}/members`
|
||||
);
|
||||
|
||||
@@ -18,20 +18,12 @@ export const team = cachedStore<
|
||||
export const memberships = cachedStore<
|
||||
Models.MembershipList,
|
||||
{
|
||||
load: (teamId: string, search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (teamId: string, queries: string[], search: string) => Promise<void>;
|
||||
}
|
||||
>('memberships', function ({ set }) {
|
||||
return {
|
||||
load: async (teamId, search, limit, offset) => {
|
||||
const response = await sdkForProject.teams.getMemberships(
|
||||
teamId,
|
||||
search,
|
||||
limit,
|
||||
offset,
|
||||
undefined,
|
||||
undefined,
|
||||
'DESC'
|
||||
);
|
||||
load: async (teamId, queries, search) => {
|
||||
const response = await sdkForProject.teams.listMemberships(teamId, queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script>
|
||||
import { Container } from '$lib/layout';
|
||||
import { Chart } from '$lib/charts';
|
||||
import { BarChart } from '$lib/charts';
|
||||
import { Card } from '$lib/components';
|
||||
import { usersUsage } from '../store';
|
||||
|
||||
@@ -45,51 +45,55 @@
|
||||
<Card>
|
||||
<h6 class="heading-level-6">Users</h6>
|
||||
<p>Count of users over time</p>
|
||||
<Chart
|
||||
title="Users"
|
||||
<BarChart
|
||||
series={[
|
||||
{
|
||||
name: 'User',
|
||||
data: [...data.usersCount.map((e) => [e.date * 1000, e.value])],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {}
|
||||
data: [...data.usersCount.map((e) => [e.date, e.value])]
|
||||
}
|
||||
]} />
|
||||
</Card>
|
||||
<Card>
|
||||
<h6 class="heading-level-6">Operations</h6>
|
||||
<p>Count of users create, read, update and delete operations over time</p>
|
||||
<Chart
|
||||
title="Operations"
|
||||
<BarChart
|
||||
series={[
|
||||
{
|
||||
name: 'Create',
|
||||
data: [...data.usersCreate.map((e) => [e.date * 1000, e.value])],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {}
|
||||
},
|
||||
data: [...data.usersCreate.map((e) => [e.date, e.value])]
|
||||
}
|
||||
]} />
|
||||
</Card>
|
||||
<Card>
|
||||
<h6 class="heading-level-6">Operations</h6>
|
||||
<p>Count of users create, read, update and delete operations over time</p>
|
||||
<BarChart
|
||||
series={[
|
||||
{
|
||||
name: 'Read',
|
||||
data: [...data.usersRead.map((e) => [e.date * 1000, e.value])],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {}
|
||||
},
|
||||
data: [...data.usersRead.map((e) => [e.date, e.value])]
|
||||
}
|
||||
]} />
|
||||
</Card>
|
||||
<Card>
|
||||
<h6 class="heading-level-6">Operations</h6>
|
||||
<p>Count of users create, read, update and delete operations over time</p>
|
||||
<BarChart
|
||||
series={[
|
||||
{
|
||||
name: 'Update',
|
||||
data: [...data.usersUpdate.map((e) => [e.date * 1000, e.value])],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {}
|
||||
},
|
||||
data: [...data.usersUpdate.map((e) => [e.date, e.value])]
|
||||
}
|
||||
]} />
|
||||
</Card>
|
||||
<Card>
|
||||
<h6 class="heading-level-6">Operations</h6>
|
||||
<p>Count of users create, read, update and delete operations over time</p>
|
||||
<BarChart
|
||||
series={[
|
||||
{
|
||||
name: 'Delete',
|
||||
data: [...data.usersDelete.map((e) => [e.date * 1000, e.value])],
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {}
|
||||
data: [...data.usersDelete.map((e) => [e.date, e.value])]
|
||||
}
|
||||
]} />
|
||||
</Card>
|
||||
|
||||
+5
-1
@@ -15,10 +15,14 @@
|
||||
import { toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { sdkForProject } from '$lib/stores/sdk';
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
let offset = 0;
|
||||
|
||||
$: request = sdkForProject.users.getLogs($page.params.user, $pageLimit, offset);
|
||||
$: request = sdkForProject.users.listLogs($page.params.user, [
|
||||
Query.limit($pageLimit),
|
||||
Query.offset(offset)
|
||||
]);
|
||||
|
||||
const getBrowser = (clientCode: string) => {
|
||||
return sdkForProject.avatars.getBrowser(clientCode, 80, 80);
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
|
||||
const getAvatar = (name: string) => sdkForProject.avatars.getInitials(name, 32, 32).toString();
|
||||
const deleted = () => (request = sdkForProject.users.getMemberships($page.params.user));
|
||||
const deleted = () => (request = sdkForProject.users.listMemberships($page.params.user));
|
||||
const project = $page.params.project;
|
||||
|
||||
let offset = 0;
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
const limit = 25;
|
||||
|
||||
$: request = sdkForProject.users.getMemberships($page.params.user);
|
||||
$: request = sdkForProject.users.listMemberships($page.params.user);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
let selectedSessionId: string = null;
|
||||
let sessionList: Models.SessionList = null;
|
||||
onMount(async () => {
|
||||
sessionList = await sdkForProject.users.getSessions($page.params.user);
|
||||
sessionList = await sdkForProject.users.listSessions($page.params.user);
|
||||
});
|
||||
|
||||
const getBrowser = (clientCode: string) => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, EmptyGridItem, Pagination, Copy, GridItem1 } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import Create from './_create.svelte';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
@@ -21,7 +21,7 @@
|
||||
await goto(`${base}/console/project-${project}/databases/database/${event.detail.$id}`);
|
||||
};
|
||||
|
||||
$: databaseList.load(search, limit, offset ?? 0);
|
||||
$: databaseList.load([Query.limit(limit), Query.offset(offset)], search);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, EmptyGridItem, Pagination, Copy, GridItem1 } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import Create from './_create.svelte';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
@@ -24,7 +24,7 @@
|
||||
);
|
||||
};
|
||||
|
||||
$: collections.load(databaseId, search, limit, offset ?? 0);
|
||||
$: collections.load(databaseId, [Query.limit(limit), Query.offset(offset)], search);
|
||||
$: if (search) offset = 0;
|
||||
</script>
|
||||
|
||||
|
||||
@@ -22,10 +22,7 @@
|
||||
const collection = await sdkForProject.databases.createCollection(
|
||||
databaseId,
|
||||
id ? id : 'unique()',
|
||||
name,
|
||||
'collection',
|
||||
[],
|
||||
[]
|
||||
name
|
||||
);
|
||||
name = id = null;
|
||||
showCreate = false;
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@
|
||||
import { base } from '$app/paths';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import Create from './createDocument.svelte';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
let offset = 0;
|
||||
|
||||
@@ -23,7 +24,7 @@
|
||||
const projectId = $page.params.project;
|
||||
const databaseId = $page.params.database;
|
||||
|
||||
$: documentList.load(databaseId, $collection.$id, [], limit, offset);
|
||||
$: documentList.load(databaseId, $collection.$id, [Query.limit(5), Query.offset(offset)]);
|
||||
$: columns = [
|
||||
...$collection.attributes.map((attribute) => ({
|
||||
key: attribute.key,
|
||||
|
||||
+2
-4
@@ -40,8 +40,7 @@
|
||||
collectionId,
|
||||
$createDocument.id ?? 'unique()',
|
||||
$createDocument.document,
|
||||
$createDocument.read,
|
||||
$createDocument.write
|
||||
$createDocument.permissions
|
||||
);
|
||||
addNotification({
|
||||
message: 'Document has been created',
|
||||
@@ -59,8 +58,7 @@
|
||||
|
||||
onDestroy(() => {
|
||||
initializeDocument();
|
||||
$createDocument.read = [];
|
||||
$createDocument.write = [];
|
||||
$createDocument.permissions = [];
|
||||
});
|
||||
|
||||
beforeNavigate(() => {
|
||||
|
||||
+8
-16
@@ -12,8 +12,7 @@
|
||||
import { page } from '$app/stores';
|
||||
|
||||
let showDelete = false;
|
||||
let read = $doc?.$read;
|
||||
let write = $doc?.$write;
|
||||
let permissions = $doc?.$permissions;
|
||||
let arePermsDisabled = true;
|
||||
const databaseId = $page.params.database;
|
||||
|
||||
@@ -24,11 +23,9 @@
|
||||
$doc.collectionId,
|
||||
$doc.$id,
|
||||
$doc.data,
|
||||
read,
|
||||
write
|
||||
permissions
|
||||
);
|
||||
$doc.$read = read;
|
||||
$doc.$write = write;
|
||||
$doc.$permissions = permissions;
|
||||
arePermsDisabled = true;
|
||||
addNotification({
|
||||
message: 'Permissions have been updated',
|
||||
@@ -42,8 +39,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: if (read || write) {
|
||||
if (difference(read, $doc.$read).length || difference(write, $doc.$write).length) {
|
||||
$: if (permissions) {
|
||||
if (difference(permissions, $doc.$permissions).length) {
|
||||
arePermsDisabled = false;
|
||||
} else arePermsDisabled = true;
|
||||
}
|
||||
@@ -82,15 +79,10 @@
|
||||
</Alert>
|
||||
<ul class="common-section">
|
||||
<InputTags
|
||||
id="read"
|
||||
label="Read Access"
|
||||
id="permissions"
|
||||
label="Permissions"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={read} />
|
||||
<InputTags
|
||||
id="write"
|
||||
label="Write Access"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={write} />
|
||||
bind:tags={permissions} />
|
||||
</ul>
|
||||
</svelte:fragment>
|
||||
|
||||
|
||||
+1
-2
@@ -36,8 +36,7 @@
|
||||
collectionId,
|
||||
documentId,
|
||||
$doc,
|
||||
$doc.$read,
|
||||
$doc.$write
|
||||
$doc.$permissions
|
||||
);
|
||||
|
||||
currentDoc = JSON.stringify($doc);
|
||||
|
||||
+36
-56
@@ -19,28 +19,22 @@
|
||||
errorType: 'error' | 'warning' | 'success' = 'error';
|
||||
let enabled: boolean = null,
|
||||
collectionName: string = null,
|
||||
collectionPermissions: string = null,
|
||||
collectionRead: string[] = null,
|
||||
collectionWrite: string[] = null,
|
||||
collectionDocumentSecurity: boolean = null,
|
||||
collectionPermissions: string[] = [],
|
||||
arePermsDisabled = true;
|
||||
|
||||
onMount(async () => {
|
||||
enabled ??= $collection.enabled;
|
||||
collectionName ??= $collection.name;
|
||||
collectionName ??= $collection.name;
|
||||
collectionPermissions ??= $collection.permission;
|
||||
collectionRead ??= $collection.$read;
|
||||
collectionWrite ??= $collection.$write;
|
||||
collectionPermissions ??= $collection.$permissions;
|
||||
collectionDocumentSecurity ??= $collection.documentSecurity;
|
||||
});
|
||||
|
||||
$: if (collectionPermissions || collectionRead || collectionWrite) {
|
||||
if (collectionPermissions !== $collection.permission) {
|
||||
$: if (collectionDocumentSecurity || collectionPermissions) {
|
||||
if (collectionDocumentSecurity !== $collection.documentSecurity) {
|
||||
arePermsDisabled = false;
|
||||
} else if (collectionRead || collectionWrite) {
|
||||
if (
|
||||
difference(collectionRead, $collection.$read).length ||
|
||||
difference(collectionWrite, $collection.$write).length
|
||||
) {
|
||||
} else if (collectionPermissions) {
|
||||
if (difference(collectionPermissions, $collection.$permissions).length) {
|
||||
arePermsDisabled = false;
|
||||
} else arePermsDisabled = true;
|
||||
}
|
||||
@@ -58,9 +52,8 @@
|
||||
databaseId,
|
||||
$collection.$id,
|
||||
$collection.name,
|
||||
$collection.permission,
|
||||
$collection.$read,
|
||||
$collection.$write,
|
||||
$collection.$permissions,
|
||||
$collection.documentSecurity,
|
||||
enabled
|
||||
);
|
||||
$collection.enabled = enabled;
|
||||
@@ -81,7 +74,7 @@
|
||||
databaseId,
|
||||
$collection.$id,
|
||||
$collection.name,
|
||||
$collection.permission
|
||||
$collection.$permissions
|
||||
);
|
||||
$collection.name = collectionName;
|
||||
showError = false;
|
||||
@@ -99,13 +92,10 @@
|
||||
databaseId,
|
||||
$collection.$id,
|
||||
$collection.name,
|
||||
collectionPermissions,
|
||||
collectionPermissions === 'collection' ? collectionRead : $collection.$read,
|
||||
collectionPermissions === 'collection' ? collectionWrite : $collection.$write
|
||||
collectionDocumentSecurity ? collectionPermissions : $collection.$permissions
|
||||
);
|
||||
$collection.permission = collectionPermissions;
|
||||
$collection.$read = collectionRead;
|
||||
$collection.$write = collectionWrite;
|
||||
$collection.$permissions = collectionPermissions;
|
||||
$collection.documentSecurity = collectionDocumentSecurity;
|
||||
arePermsDisabled = true;
|
||||
addNotification({
|
||||
message: 'Permissions have been updated',
|
||||
@@ -139,11 +129,8 @@
|
||||
</svelte:fragment>
|
||||
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
disabled={enabled === $collection.enabled}
|
||||
on:click={() => {
|
||||
togglecollection();
|
||||
}}>Update</Button>
|
||||
<Button disabled={enabled === $collection.enabled} on:click={togglecollection}
|
||||
>Update</Button>
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
|
||||
@@ -167,9 +154,7 @@
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
disabled={collectionName === $collection.name || !collectionName}
|
||||
on:click={() => {
|
||||
updateName();
|
||||
}}>Update</Button>
|
||||
on:click={updateName}>Update</Button>
|
||||
</svelte:fragment>
|
||||
</CardGrid>
|
||||
<CardGrid>
|
||||
@@ -187,8 +172,8 @@
|
||||
type="radio"
|
||||
class="is-small"
|
||||
name="level"
|
||||
bind:group={collectionPermissions}
|
||||
value="collection" />
|
||||
bind:group={collectionDocumentSecurity}
|
||||
value={true} />
|
||||
<span>Collection Level</span>
|
||||
</label>
|
||||
</li>
|
||||
@@ -198,33 +183,14 @@
|
||||
type="radio"
|
||||
class="is-small"
|
||||
name="level"
|
||||
bind:group={collectionPermissions}
|
||||
value="file" />
|
||||
bind:group={collectionDocumentSecurity}
|
||||
value={false} />
|
||||
<span>Document Level</span>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{#if collectionPermissions === 'collection'}
|
||||
<Alert type="info">
|
||||
<p>
|
||||
Tip: Add <b>role:all</b> for wildcards access. Check out our
|
||||
documentation for more on <a class="link" href="/#">Permissions</a>
|
||||
</p>
|
||||
</Alert>
|
||||
<ul class="form-list">
|
||||
<InputTags
|
||||
id="read"
|
||||
label="Read Access"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={collectionRead} />
|
||||
<InputTags
|
||||
id="write"
|
||||
label="Write Access"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={collectionWrite} />
|
||||
</ul>
|
||||
{:else}
|
||||
{#if collectionDocumentSecurity}
|
||||
<Alert type="info">
|
||||
<p>
|
||||
Manage permissions at the <b>Document Level</b> to control access over
|
||||
@@ -233,6 +199,20 @@
|
||||
<a class="link" href="/#">Permissions</a>
|
||||
</p>
|
||||
</Alert>
|
||||
{:else}
|
||||
<Alert type="info">
|
||||
<p>
|
||||
Tip: Add <b>role:all</b> for wildcards access. Check out our
|
||||
documentation for more on <a class="link" href="/#">Permissions</a>
|
||||
</p>
|
||||
</Alert>
|
||||
<ul class="form-list">
|
||||
<InputTags
|
||||
id="permissions"
|
||||
label="Permissions"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={collectionPermissions} />
|
||||
</ul>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
|
||||
+3
-11
@@ -63,23 +63,15 @@ export const collection = cachedStore<
|
||||
export const documentList = cachedStore<
|
||||
Models.DocumentList<Models.Document>,
|
||||
{
|
||||
load: (
|
||||
databaseId: string,
|
||||
collectionId: string,
|
||||
queries?: [],
|
||||
limit?: number,
|
||||
offset?: number
|
||||
) => Promise<void>;
|
||||
load: (databaseId: string, collectionId: string, queries?: string[]) => Promise<void>;
|
||||
}
|
||||
>('documentList', function ({ set }) {
|
||||
return {
|
||||
load: async (databaseId, collectionId, queries, limit, offset) => {
|
||||
load: async (databaseId, collectionId, queries) => {
|
||||
const response = await sdkForProject.databases.listDocuments(
|
||||
databaseId,
|
||||
collectionId,
|
||||
queries,
|
||||
limit,
|
||||
offset
|
||||
queries
|
||||
);
|
||||
set(response);
|
||||
}
|
||||
|
||||
+3
-8
@@ -24,14 +24,9 @@
|
||||
|
||||
<ul class="common-section">
|
||||
<InputTags
|
||||
id="read"
|
||||
label="Read Access"
|
||||
id="permissions"
|
||||
label="Permissions"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={$createDocument.read} />
|
||||
<InputTags
|
||||
id="write"
|
||||
label="Write Access"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={$createDocument.write} />
|
||||
bind:tags={$createDocument.permissions} />
|
||||
</ul>
|
||||
</WizardStep>
|
||||
|
||||
+2
-4
@@ -4,13 +4,11 @@ import type { Attributes } from '../store';
|
||||
export const createDocument = writable<{
|
||||
id?: string;
|
||||
document: object;
|
||||
read: string[];
|
||||
write: string[];
|
||||
permissions: string[];
|
||||
attributes: Attributes[];
|
||||
}>({
|
||||
id: null,
|
||||
document: {},
|
||||
read: [],
|
||||
write: [],
|
||||
permissions: [],
|
||||
attributes: []
|
||||
});
|
||||
|
||||
@@ -6,17 +6,16 @@ import { cachedStore } from '$lib/helpers/cache';
|
||||
export const collections = cachedStore<
|
||||
Models.CollectionList,
|
||||
{
|
||||
load: (databaseId: string, search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (databaseId: string, queries: string[], search: string) => Promise<void>;
|
||||
total: (databaseId: string, id: string) => Promise<Record<string, unknown>>;
|
||||
}
|
||||
>('collections', function ({ set }) {
|
||||
return {
|
||||
load: async (databaseId, search, limit, offset) => {
|
||||
load: async (databaseId, queries, search) => {
|
||||
const response = await sdkForProject.databases.listCollections(
|
||||
databaseId,
|
||||
search,
|
||||
limit,
|
||||
offset
|
||||
queries,
|
||||
search
|
||||
);
|
||||
set(response);
|
||||
},
|
||||
|
||||
@@ -5,12 +5,12 @@ import { cachedStore } from '$lib/helpers/cache';
|
||||
export const databaseList = cachedStore<
|
||||
Models.DatabaseList,
|
||||
{
|
||||
load: (search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (queries: string[], search: string) => Promise<void>;
|
||||
}
|
||||
>('databaseList', function ({ set }) {
|
||||
return {
|
||||
load: async (search, limit, offset) => {
|
||||
const response = await sdkForProject.databases.list(search, limit, offset);
|
||||
load: async (queries, search) => {
|
||||
const response = await sdkForProject.databases.list(queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import Create from './_create.svelte';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
let search = '';
|
||||
let showCreate = false;
|
||||
@@ -14,7 +15,7 @@
|
||||
const limit = 25;
|
||||
const project = $page.params.project;
|
||||
|
||||
$: request = sdkForProject.functions.list(search, limit, offset);
|
||||
$: request = sdkForProject.functions.list([Query.limit(0), Query.offset(0)], search);
|
||||
$: if (search) offset = 0;
|
||||
</script>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
const create = async () => {
|
||||
try {
|
||||
await sdkForProject.storage.createBucket('unique()', name, 'bucket');
|
||||
await sdkForProject.storage.createBucket('unique()', name);
|
||||
name = null;
|
||||
showCreate = false;
|
||||
dispatch('created');
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import Create from './_create.svelte';
|
||||
import { base } from '$app/paths';
|
||||
import { Query } from '@aw-labs/appwrite-console';
|
||||
|
||||
let search = '';
|
||||
let showCreate = false;
|
||||
@@ -25,7 +26,11 @@
|
||||
const project = $page.params.project;
|
||||
const functionId = $page.params.function;
|
||||
|
||||
$: request = sdkForProject.functions.listDeployments(functionId, search, limit, offset);
|
||||
$: request = sdkForProject.functions.listDeployments(
|
||||
functionId,
|
||||
[Query.offset(offset), Query.limit(limit)],
|
||||
search
|
||||
);
|
||||
$: if (search) offset = 0;
|
||||
</script>
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { afterNavigate } from '$app/navigation';
|
||||
import { DropList, DropListItem } from '$lib/components';
|
||||
import { BarChart, LineChart } from '$lib/charts';
|
||||
import { humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
|
||||
$: projectId = $page.params.project;
|
||||
$: path = `/console/project-${projectId}/overview`;
|
||||
@@ -71,6 +73,16 @@
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//TODO: workaround for broken types
|
||||
$: network = $usage?.network as unknown as Array<{
|
||||
date: number;
|
||||
value: number;
|
||||
}>;
|
||||
$: requests = $usage?.requests as unknown as Array<{
|
||||
date: number;
|
||||
value: number;
|
||||
}>;
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
@@ -80,14 +92,16 @@
|
||||
{#if $project}
|
||||
<Container overlapCover>
|
||||
{#if $usage}
|
||||
{@const bandwith = humanFileSize(total($usage.network))}
|
||||
{@const storage = humanFileSize(last($usage.storage).value)}
|
||||
<section class="common-section">
|
||||
<div class="grid-dashboard-1s-2m-6l">
|
||||
<div class="card is-2-columns-medium-screen is-3-columns-large-screen">
|
||||
<div class="u-flex u-gap-16 u-main-space-between">
|
||||
<div>
|
||||
<div class="heading-level-4">
|
||||
{total($usage.network)}
|
||||
<span class="body-text-2">KB</span>
|
||||
{bandwith.value}
|
||||
<span class="body-text-2">{bandwith.unit}</span>
|
||||
</div>
|
||||
<div>Bandwidth</div>
|
||||
</div>
|
||||
@@ -116,6 +130,15 @@
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
</div>
|
||||
{#if network.length}
|
||||
<BarChart
|
||||
series={[
|
||||
{
|
||||
name: 'Bandwith',
|
||||
data: [...network.map((e) => [e.date, e.value])]
|
||||
}
|
||||
]} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="card is-2-columns-medium-screen is-3-columns-large-screen">
|
||||
<div class="u-flex u-gap-16 u-main-space-between">
|
||||
@@ -150,6 +173,15 @@
|
||||
</svelte:fragment>
|
||||
</DropList>
|
||||
</div>
|
||||
{#if network.length}
|
||||
<LineChart
|
||||
series={[
|
||||
{
|
||||
name: 'Requests',
|
||||
data: [...requests.map((e) => [e.date, e.value])]
|
||||
}
|
||||
]} />
|
||||
{/if}
|
||||
</div>
|
||||
<div class="card is-2-columns-large-screen">
|
||||
<div class="grid-item-1">
|
||||
@@ -185,9 +217,10 @@
|
||||
|
||||
<div class="grid-item-1-end-start">
|
||||
<div class="heading-level-4">
|
||||
8.0 <span class="body-text-2">MB</span>
|
||||
{storage.value}
|
||||
<span class="body-text-2">{storage.unit}</span>
|
||||
</div>
|
||||
<div>Users</div>
|
||||
<div>Storage</div>
|
||||
</div>
|
||||
|
||||
<div class="grid-item-1-end-end">
|
||||
@@ -231,7 +264,7 @@
|
||||
|
||||
<div class="grid-item-1-end-start">
|
||||
<div class="heading-level-4">
|
||||
{format(last($usage.functions).value)}
|
||||
{format(last($usage.executions).value)}
|
||||
</div>
|
||||
<div>Executions</div>
|
||||
</div>
|
||||
|
||||
+2
-3
@@ -9,7 +9,6 @@
|
||||
Form,
|
||||
FormList,
|
||||
InputCheckbox,
|
||||
InputNumber,
|
||||
InputPassword,
|
||||
InputText
|
||||
} from '$lib/elements/forms';
|
||||
@@ -35,7 +34,7 @@
|
||||
let showDelete = false;
|
||||
let name: string = null;
|
||||
let secret: string = null;
|
||||
let expire: number = null;
|
||||
let expire: string = null;
|
||||
|
||||
onMount(handle);
|
||||
afterNavigate(handle);
|
||||
@@ -229,7 +228,7 @@
|
||||
<p class="text">Choose any name that will help you distinguish between API keys.</p>
|
||||
<svelte:fragment slot="aside">
|
||||
<FormList>
|
||||
<InputNumber
|
||||
<InputText
|
||||
id="expire"
|
||||
label="Expiration Date"
|
||||
bind:value={expire}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Empty, Pagination, Copy, GridItem1, EmptyGridItem } from '$lib/components';
|
||||
import { Pill } from '$lib/elements';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import Create from './_create.svelte';
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
@@ -22,7 +22,7 @@
|
||||
await goto(`${base}/console/project-${project}/storage/bucket/${event.detail.$id}`);
|
||||
};
|
||||
|
||||
$: bucketList.load(search, $pageLimit, offset ?? 0);
|
||||
$: bucketList.load([Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
$: if (search) offset = 0;
|
||||
</script>
|
||||
|
||||
|
||||
@@ -16,11 +16,7 @@
|
||||
|
||||
const create = async () => {
|
||||
try {
|
||||
const bucket = await sdkForProject.storage.createBucket(
|
||||
id ? id : 'unique()',
|
||||
name,
|
||||
'bucket'
|
||||
);
|
||||
const bucket = await sdkForProject.storage.createBucket(id ? id : 'unique()', name);
|
||||
name = null;
|
||||
showCreate = false;
|
||||
dispatch('created', bucket);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
import { Container } from '$lib/layout';
|
||||
import { base } from '$app/paths';
|
||||
import { files } from './store';
|
||||
import type { Models } from '@aw-labs/appwrite-console';
|
||||
import { Query, type Models } from '@aw-labs/appwrite-console';
|
||||
import { uploader } from '$lib/stores/uploader';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { pageLimit } from '$lib/stores/layout';
|
||||
@@ -49,20 +49,20 @@
|
||||
|
||||
const fileCreated = () => {
|
||||
showCreate = false;
|
||||
files.load(bucket, search, $pageLimit, offset);
|
||||
files.load(bucket, [Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
};
|
||||
|
||||
const fileDeleted = (event: CustomEvent<Models.File>) => {
|
||||
showDelete = false;
|
||||
uploader.removeFile(event.detail);
|
||||
files.load(bucket, search, $pageLimit, offset);
|
||||
files.load(bucket, [Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
};
|
||||
|
||||
const deleteFile = async (file: Models.File) => {
|
||||
try {
|
||||
await sdkForProject.storage.deleteFile(file.bucketId, file.$id);
|
||||
uploader.removeFile(file);
|
||||
files.load(bucket, search, $pageLimit, offset);
|
||||
files.load(bucket, [Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
} catch (error) {
|
||||
addNotification({
|
||||
type: 'error',
|
||||
@@ -71,7 +71,7 @@
|
||||
}
|
||||
};
|
||||
|
||||
$: files.load(bucket, search, $pageLimit, offset);
|
||||
$: files.load(bucket, [Query.limit($pageLimit), Query.offset(offset)], search);
|
||||
$: if (search) offset = 0;
|
||||
</script>
|
||||
|
||||
|
||||
@@ -16,20 +16,19 @@
|
||||
|
||||
let list = new DataTransfer();
|
||||
let files: FileList;
|
||||
let read: string[] = [];
|
||||
let write: string[] = [];
|
||||
let input: HTMLInputElement;
|
||||
let permissions: string[] = [];
|
||||
let id: string = null;
|
||||
let error: string;
|
||||
let showDropdown = false;
|
||||
|
||||
const create = async () => {
|
||||
async function create() {
|
||||
try {
|
||||
const file = await sdkForProject.storage.createFile(
|
||||
bucketId,
|
||||
id ?? 'unique()',
|
||||
files[0],
|
||||
read,
|
||||
write
|
||||
permissions
|
||||
);
|
||||
files = null;
|
||||
showCreate = false;
|
||||
@@ -39,10 +38,9 @@
|
||||
} catch ({ message }) {
|
||||
error = message;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function dropHandler(ev: DragEvent) {
|
||||
console.log(ev);
|
||||
ev.preventDefault();
|
||||
if (ev.dataTransfer.items) {
|
||||
// Use DataTransferItemList interface to access the file(s)
|
||||
@@ -54,24 +52,17 @@
|
||||
files = list.files;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Use DataTransfer interface to access the file(s)
|
||||
for (let i = 0; i < ev.dataTransfer.files.length; i++) {
|
||||
console.log('... file[' + i + '].name = ' + ev.dataTransfer.files[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function dragOverHandler(ev: DragEvent) {
|
||||
console.log('File(s) in drop zone');
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
$: if (!showCreate) {
|
||||
id = files = error = null;
|
||||
list = new DataTransfer();
|
||||
read = [];
|
||||
write = [];
|
||||
permissions = [];
|
||||
}
|
||||
|
||||
$: if (!showDropdown) {
|
||||
@@ -79,7 +70,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<input bind:files id="file" type="file" style="display: none" />
|
||||
<input bind:files bind:this={input} type="file" style="display: none" />
|
||||
|
||||
<Form on:submit={create}>
|
||||
<Modal {error} bind:show={showCreate}>
|
||||
@@ -88,8 +79,8 @@
|
||||
<div>
|
||||
<div
|
||||
class="card is-border-dashed is-no-shadow"
|
||||
on:drop|preventDefault={(e) => dropHandler(e)}
|
||||
on:dragover|preventDefault={(e) => dragOverHandler(e)}>
|
||||
on:drop|preventDefault={dropHandler}
|
||||
on:dragover|preventDefault={dragOverHandler}>
|
||||
<div class="u-flex u-main-center u-cross-center u-gap-32">
|
||||
<div class="avatar is-size-large">
|
||||
<span class="icon-upload" aria-hidden="true" />
|
||||
@@ -97,11 +88,7 @@
|
||||
<div class="u-grid u-gap-16">
|
||||
<p>Drag and drop files here to upload</p>
|
||||
<div>
|
||||
<Button
|
||||
secondary
|
||||
on:click={() => {
|
||||
document.getElementById('file').click();
|
||||
}}>
|
||||
<Button secondary on:click={input.click}>
|
||||
<span class="icon-upload" aria-hidden="true" />
|
||||
<span class="text">Choose File</span>
|
||||
</Button>
|
||||
@@ -112,9 +99,10 @@
|
||||
type="button"
|
||||
class="x-button"
|
||||
aria-label="remove file"
|
||||
title="Remove file"
|
||||
><span class="icon-x" aria-hidden="true" /></button
|
||||
>{/if}
|
||||
title="Remove file">
|
||||
<span class="icon-x" aria-hidden="true" />
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -125,10 +113,11 @@
|
||||
|
||||
{#if !showDropdown}
|
||||
<div>
|
||||
<Pill button on:click={() => (showDropdown = !showDropdown)}
|
||||
><span class="icon-pencil" aria-hidden="true" /><span class="text">
|
||||
<Pill button on:click={() => (showDropdown = !showDropdown)}>
|
||||
<span class="icon-pencil" aria-hidden="true" /><span class="text">
|
||||
File ID
|
||||
</span></Pill>
|
||||
</span>
|
||||
</Pill>
|
||||
</div>
|
||||
{:else}
|
||||
<InnerModal bind:show={showDropdown}>
|
||||
@@ -168,14 +157,9 @@
|
||||
</p>
|
||||
</Alert>
|
||||
<InputTags
|
||||
id="read"
|
||||
label="Read"
|
||||
bind:tags={read}
|
||||
placeholder="User ID, Team ID or Role" />
|
||||
<InputTags
|
||||
id="write"
|
||||
label="Write"
|
||||
bind:tags={write}
|
||||
id="permissions"
|
||||
label="Permissions"
|
||||
bind:tags={permissions}
|
||||
placeholder="User ID, Team ID or Role" />
|
||||
</FormList>
|
||||
<svelte:fragment slot="footer">
|
||||
|
||||
+12
-25
@@ -11,18 +11,17 @@
|
||||
import Delete from './_deleteFile.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { onMount } from 'svelte';
|
||||
import { difference } from '$lib/helpers/array';
|
||||
|
||||
onMount(async () => {
|
||||
let bucketId = $page.params.bucket;
|
||||
let fileId = $page.params.file;
|
||||
await file.load(bucketId, fileId);
|
||||
fileRead = $file?.$read;
|
||||
fileWrite = $file?.$write;
|
||||
filePermissions = $file?.$permissions;
|
||||
});
|
||||
|
||||
let showDelete = false;
|
||||
let fileRead = $file?.$read;
|
||||
let fileWrite = $file?.$write;
|
||||
let filePermissions = $file?.$permissions;
|
||||
let arePermsDisabled = true;
|
||||
|
||||
const getPreview = (fileId: string) =>
|
||||
@@ -31,16 +30,10 @@
|
||||
const getView = (fileId: string) =>
|
||||
sdkForProject.storage.getFileView($file.bucketId, fileId).toString() + '&mode=admin';
|
||||
|
||||
$: if (fileRead || fileWrite) {
|
||||
if (fileRead) {
|
||||
if (JSON.stringify(fileRead) !== JSON.stringify($file.$read)) {
|
||||
arePermsDisabled = false;
|
||||
} else arePermsDisabled = true;
|
||||
} else if (fileWrite) {
|
||||
if (JSON.stringify(fileWrite) !== JSON.stringify($file.$write)) {
|
||||
arePermsDisabled = false;
|
||||
} else arePermsDisabled = true;
|
||||
}
|
||||
$: if (filePermissions) {
|
||||
if (difference(filePermissions, $file.$permissions).length) {
|
||||
arePermsDisabled = false;
|
||||
} else arePermsDisabled = true;
|
||||
}
|
||||
|
||||
function downloadFile() {
|
||||
@@ -52,9 +45,8 @@
|
||||
|
||||
async function updatePermissions() {
|
||||
try {
|
||||
await sdkForProject.storage.updateFile($file.bucketId, $file.$id, fileRead, fileWrite);
|
||||
$file.$read = fileRead;
|
||||
$file.$write = fileWrite;
|
||||
await sdkForProject.storage.updateFile($file.bucketId, $file.$id, filePermissions);
|
||||
$file.$permissions = filePermissions;
|
||||
arePermsDisabled = true;
|
||||
addNotification({
|
||||
message: 'Permissions have been updated',
|
||||
@@ -133,15 +125,10 @@
|
||||
</Alert>
|
||||
<ul class="common-section">
|
||||
<InputTags
|
||||
id="read"
|
||||
label="Read Access"
|
||||
id="permissions"
|
||||
label="Permissions"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={fileRead} />
|
||||
<InputTags
|
||||
id="write"
|
||||
label="Write Access"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={fileWrite} />
|
||||
bind:tags={filePermissions} />
|
||||
</ul>
|
||||
</svelte:fragment>
|
||||
|
||||
|
||||
+37
-52
@@ -19,14 +19,14 @@
|
||||
import { onMount } from 'svelte';
|
||||
import { page } from '$app/stores';
|
||||
import Pill from '$lib/elements/pill.svelte';
|
||||
import { difference } from '$lib/helpers/array';
|
||||
|
||||
let showDelete = false;
|
||||
|
||||
let enabled: boolean = null,
|
||||
bucketName: string = null,
|
||||
bucketPermissions: string = null,
|
||||
bucketRead: string[] = null,
|
||||
bucketWrite: string[] = null,
|
||||
bucketFileSecurity: boolean = null,
|
||||
bucketPermissions: string[] = null,
|
||||
arePermsDisabled = true,
|
||||
encryption: boolean = null,
|
||||
antivirus: boolean = null,
|
||||
@@ -47,22 +47,17 @@
|
||||
enabled ??= $bucket.enabled;
|
||||
bucketName ??= $bucket.name;
|
||||
bucketName ??= $bucket.name;
|
||||
bucketPermissions ??= $bucket.permission;
|
||||
bucketRead ??= $bucket.$read;
|
||||
bucketWrite ??= $bucket.$write;
|
||||
bucketFileSecurity ??= $bucket.fileSecurity;
|
||||
bucketPermissions ??= $bucket.$permissions;
|
||||
encryption ??= $bucket.encryption;
|
||||
antivirus ??= $bucket.antivirus;
|
||||
});
|
||||
$: maxSizePlaceholder = bytesToSize($bucket.maximumFileSize, byteUnit);
|
||||
$: if (bucketPermissions || bucketRead || bucketWrite) {
|
||||
if (bucketPermissions !== $bucket.permission) {
|
||||
$: if (bucketFileSecurity || bucketPermissions) {
|
||||
if (bucketFileSecurity !== $bucket.fileSecurity) {
|
||||
arePermsDisabled = false;
|
||||
} else if (bucketRead) {
|
||||
if (JSON.stringify(bucketRead) !== JSON.stringify($bucket.$read)) {
|
||||
arePermsDisabled = false;
|
||||
} else arePermsDisabled = true;
|
||||
} else if (bucketWrite) {
|
||||
if (JSON.stringify(bucketWrite) !== JSON.stringify($bucket.$write)) {
|
||||
} else if (bucketPermissions) {
|
||||
if (difference(bucketPermissions, $bucket.$permissions).length) {
|
||||
arePermsDisabled = false;
|
||||
} else arePermsDisabled = true;
|
||||
}
|
||||
@@ -78,9 +73,8 @@
|
||||
await sdkForProject.storage.updateBucket(
|
||||
$bucket.$id,
|
||||
$bucket.name,
|
||||
$bucket.permission,
|
||||
$bucket.$read,
|
||||
$bucket.$write,
|
||||
undefined,
|
||||
undefined,
|
||||
enabled
|
||||
);
|
||||
$bucket.enabled = enabled;
|
||||
@@ -97,7 +91,7 @@
|
||||
}
|
||||
async function updateName() {
|
||||
try {
|
||||
await sdkForProject.storage.updateBucket($bucket.$id, $bucket.name, $bucket.permission);
|
||||
await sdkForProject.storage.updateBucket($bucket.$id, bucketName);
|
||||
$bucket.name = bucketName;
|
||||
addNotification({
|
||||
message: 'Name has been updated',
|
||||
@@ -115,13 +109,11 @@
|
||||
await sdkForProject.storage.updateBucket(
|
||||
$bucket.$id,
|
||||
$bucket.name,
|
||||
bucketPermissions,
|
||||
bucketPermissions === 'bucket' ? bucketRead : $bucket.$read,
|
||||
bucketPermissions === 'bucket' ? bucketWrite : $bucket.$write
|
||||
bucketFileSecurity ? bucketPermissions : undefined,
|
||||
bucketFileSecurity
|
||||
);
|
||||
$bucket.permission = bucketPermissions;
|
||||
$bucket.$read = bucketRead;
|
||||
$bucket.$write = bucketWrite;
|
||||
$bucket.fileSecurity = bucketFileSecurity;
|
||||
$bucket.$permissions = bucketPermissions;
|
||||
arePermsDisabled = true;
|
||||
addNotification({
|
||||
message: 'Permissions have been updated',
|
||||
@@ -140,12 +132,12 @@
|
||||
await sdkForProject.storage.updateBucket(
|
||||
$bucket.$id,
|
||||
$bucket.name,
|
||||
$bucket.permission,
|
||||
$bucket.$read,
|
||||
$bucket.$write,
|
||||
$bucket.enabled,
|
||||
$bucket.maximumFileSize,
|
||||
$bucket.allowedFileExtensions,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
encryption,
|
||||
antivirus
|
||||
);
|
||||
@@ -169,10 +161,9 @@
|
||||
await sdkForProject.storage.updateBucket(
|
||||
$bucket.$id,
|
||||
$bucket.name,
|
||||
$bucket.permission,
|
||||
$bucket.$read,
|
||||
$bucket.$write,
|
||||
$bucket.enabled,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
size
|
||||
);
|
||||
$bucket.maximumFileSize = maxSize;
|
||||
@@ -193,11 +184,10 @@
|
||||
await sdkForProject.storage.updateBucket(
|
||||
$bucket.$id,
|
||||
$bucket.name,
|
||||
$bucket.permission,
|
||||
$bucket.$read,
|
||||
$bucket.$write,
|
||||
$bucket.enabled,
|
||||
$bucket.maximumFileSize,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
extensions
|
||||
);
|
||||
$bucket.allowedFileExtensions = extensions;
|
||||
@@ -274,8 +264,8 @@
|
||||
type="radio"
|
||||
class="is-small"
|
||||
name="level"
|
||||
bind:group={bucketPermissions}
|
||||
value="bucket" />
|
||||
bind:group={bucketFileSecurity}
|
||||
value={true} />
|
||||
<span>Bucket Level</span>
|
||||
</label>
|
||||
</li>
|
||||
@@ -285,8 +275,8 @@
|
||||
type="radio"
|
||||
class="is-small"
|
||||
name="level"
|
||||
bind:group={bucketPermissions}
|
||||
value="file" />
|
||||
bind:group={bucketFileSecurity}
|
||||
value={false} />
|
||||
<span>File Level</span>
|
||||
</label>
|
||||
</li>
|
||||
@@ -297,18 +287,13 @@
|
||||
documentation for more on <a href="/#">Permissions</a>
|
||||
</p>
|
||||
</Alert>
|
||||
{#if bucketPermissions === 'bucket'}
|
||||
{#if bucketFileSecurity}
|
||||
<ul class="common-section">
|
||||
<InputTags
|
||||
id="read"
|
||||
label="Read Access"
|
||||
id="permissions"
|
||||
label="Permissions"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={bucketRead} />
|
||||
<InputTags
|
||||
id="write"
|
||||
label="Write Access"
|
||||
placeholder="User ID, Team ID, or Role"
|
||||
bind:tags={bucketWrite} />
|
||||
bind:tags={bucketPermissions} />
|
||||
</ul>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
|
||||
@@ -26,23 +26,8 @@ function createFilesStore() {
|
||||
return {
|
||||
subscribe,
|
||||
set,
|
||||
load: async (
|
||||
bucketId: string,
|
||||
search?: string,
|
||||
limit?: number,
|
||||
offset?: number,
|
||||
cursor?: string,
|
||||
cursorDirection?: string
|
||||
) => {
|
||||
const response = await sdkForProject.storage.listFiles(
|
||||
bucketId,
|
||||
search,
|
||||
limit,
|
||||
offset,
|
||||
cursor,
|
||||
cursorDirection,
|
||||
'DESC'
|
||||
);
|
||||
load: async (bucketId: string, queries?: string[], search?: string) => {
|
||||
const response = await sdkForProject.storage.listFiles(bucketId, queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,12 +5,12 @@ import { cachedStore } from '$lib/helpers/cache';
|
||||
export const bucketList = cachedStore<
|
||||
Models.BucketList,
|
||||
{
|
||||
load: (search: string, limit: number, offset: number) => Promise<void>;
|
||||
load: (queries: string[], search: string) => Promise<void>;
|
||||
}
|
||||
>('bucketList', function ({ set }) {
|
||||
return {
|
||||
load: async (search, limit, offset) => {
|
||||
const response = await sdkForProject.storage.listBuckets(search, limit, offset);
|
||||
load: async (queries, search) => {
|
||||
const response = await sdkForProject.storage.listBuckets(queries, search);
|
||||
set(response);
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user