From 21d5424825adf90f89ee190cf02d468b3571e172 Mon Sep 17 00:00:00 2001 From: imadjamil Date: Tue, 29 Jun 2021 17:36:09 +0200 Subject: [PATCH 1/9] Update server.py Allow access from other ip terminals --- src_backend_python/tabloo/server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_backend_python/tabloo/server.py b/src_backend_python/tabloo/server.py index 48d41fe..6b2032a 100644 --- a/src_backend_python/tabloo/server.py +++ b/src_backend_python/tabloo/server.py @@ -106,7 +106,7 @@ def index(): def serve(df, open_browser, server_port=5000, server_logging=True, debug=False): # TODO: We may add some auto port handling like this: https://stackoverflow.com/a/5089963/1804173 - url = "http://127.0.0.1:{0}".format(server_port) + url = "http://0.0.0.0:{0}".format(server_port) global backend backend = Backend(df) From 08386492f70c73866b3b4bcf6dd2464a17af1223 Mon Sep 17 00:00:00 2001 From: imadjamil Date: Tue, 29 Jun 2021 18:03:22 +0200 Subject: [PATCH 2/9] Update server.py Configure Flask dev server to be visible across the network --- src_backend_python/tabloo/server.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src_backend_python/tabloo/server.py b/src_backend_python/tabloo/server.py index 6b2032a..3c3d08f 100644 --- a/src_backend_python/tabloo/server.py +++ b/src_backend_python/tabloo/server.py @@ -105,8 +105,10 @@ def index(): def serve(df, open_browser, server_port=5000, server_logging=True, debug=False): # TODO: We may add some auto port handling like this: https://stackoverflow.com/a/5089963/1804173 + + server_host="0.0.0.0" - url = "http://0.0.0.0:{0}".format(server_port) + url = "http://{0}:{1}".format(server_host, server_port) global backend backend = Backend(df) @@ -127,6 +129,7 @@ def serve(df, open_browser, server_port=5000, server_logging=True, debug=False): app.run( port=server_port, + host=server_host, debug=debug, use_reloader=debug, processes=1, From 1ad37ada9e8a75c649d8f5ed580715123f44961c Mon Sep 17 00:00:00 2001 From: Imad Date: Wed, 30 Jun 2021 09:57:43 +0200 Subject: [PATCH 3/9] Redirecting to the server host address instead of localhost --- src_frontend/store_backend.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_frontend/store_backend.ts b/src_frontend/store_backend.ts index ebef540..ab47fc7 100644 --- a/src_frontend/store_backend.ts +++ b/src_frontend/store_backend.ts @@ -16,7 +16,7 @@ function transformValue(x: any): any { export class StoreBackend implements StoreInterface { - url = "http://localhost:5000" + url = "http://10.70.16.18:5000" async fetchColumns(): Promise { let response = await axios.get(`${this.url}/api/get_columns`) From 481f84f0c9c3edc1990e1f27a221b93e2f89bf9c Mon Sep 17 00:00:00 2001 From: Imad Date: Wed, 6 Jul 2022 17:55:20 +0200 Subject: [PATCH 4/9] Merging 2021 upstream updates --- .envrc | 4 + .github/workflows/ci.yaml | 4 + css/styles.scss | 52 ++--- src_frontend/App.tsx | 148 ++++++------- src_frontend/Dropdown.tsx | 54 +++-- src_frontend/ForIndex.tsx | 44 ---- src_frontend/Icons.tsx | 50 +++-- src_frontend/MapHandler.tsx | 202 ----------------- src_frontend/PlotHandler.tsx | 196 +++++++++-------- src_frontend/TableHandler.tsx | 352 +++++++++++++++--------------- src_frontend/Tabs.tsx | 24 +- src_frontend/dom_lifecycle.ts | 31 +-- src_frontend/fn.ts | 27 +-- src_frontend/index.tsx | 11 +- src_frontend/index_standalone.tsx | 11 +- src_frontend/store.ts | 28 ++- 16 files changed, 506 insertions(+), 732 deletions(-) create mode 100644 .envrc delete mode 100644 src_frontend/ForIndex.tsx delete mode 100644 src_frontend/MapHandler.tsx diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..401fe7a --- /dev/null +++ b/.envrc @@ -0,0 +1,4 @@ +source "/home/imad/.local/bin/virtualenvwrapper.sh" +workon tabloo + +unset PS1 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index b5a0ad6..9b9f25e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -95,3 +95,7 @@ jobs: - run: npm install - run: npm run check-types + + - run: npm run lint + + - run: npm run fmt-check diff --git a/css/styles.scss b/css/styles.scss index f096689..d0d98c3 100644 --- a/css/styles.scss +++ b/css/styles.scss @@ -7,14 +7,14 @@ // https://fonts.google.com/?sort=popularity // TODO: use https://google-webfonts-helper.herokuapp.com //@import url('https://fonts.googleapis.com/css?family=Open+Sans'); -@import url('https://fonts.googleapis.com/css?family=Roboto'); +@import url("https://fonts.googleapis.com/css?family=Roboto"); $family-sans-serif: "Roboto", sans-serif; // https://fonts.google.com/specimen/Open+Sans+Condensed?selection.family=Open+Sans+Condensed:300 -@import url('https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300&display=swap'); +@import url("https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300&display=swap"); // https://fonts.google.com/specimen/Open+Sans?selection.family=Open+Sans -@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap'); +@import url("https://fonts.googleapis.com/css?family=Open+Sans&display=swap"); $default-font-size: 0.75rem; @@ -27,9 +27,7 @@ $default-font-size: 0.75rem; // Dropdown customization // https://bulma.io/documentation/components/dropdown/#variables $dropdown-item-active-background-color: hsl(217, 61%, 19%); -$dropdown-content-shadow: - 2px 2px 25px 0px rgba($black, 0.3), - 0px 0px 0px 1px rgba($black, 0.1); // the spread is used to generate a border +$dropdown-content-shadow: 2px 2px 25px 0px rgba($black, 0.3), 0px 0px 0px 1px rgba($black, 0.1); // the spread is used to generate a border // TODO: Maybe adjust radius, but has to be synced with other components // $dropdown-content-radius: 8px; @@ -89,10 +87,8 @@ $ui-navbar-height: 3rem; min-height: $ui-navbar-height; - box-shadow: - 0 3px 3px rgba(12,13,14,0.1), - 0 1px 6px rgba(59,64,69,0.1); - background: #1B1D1F; + box-shadow: 0 3px 3px rgba(12, 13, 14, 0.1), 0 1px 6px rgba(59, 64, 69, 0.1); + background: #1b1d1f; display: flex; align-items: center; @@ -100,10 +96,10 @@ $ui-navbar-height: 3rem; .ui-navbar-button { border-radius: 0.25rem; - background: #25282C; - padding: 0.3rem 1.0rem; + background: #25282c; + padding: 0.3rem 1rem; font-size: 0.9rem; - font-family: 'Open Sans Condensed', sans-serif; + font-family: "Open Sans Condensed", sans-serif; font-weight: 900; transition: 0.1s; @@ -113,16 +109,13 @@ $ui-navbar-height: 3rem; margin-left: 0.75rem; } - .ui-navbar-button:hover { background: rgb(59, 63, 70); color: #337aec; } .ui-navbar-button.is-active { - box-shadow: - 0px 0px 3px 0px #080808, - 0px 0px 0px 1px #888888; // the spread is used to generate a border + box-shadow: 0px 0px 3px 0px #080808, 0px 0px 0px 1px #888888; // the spread is used to generate a border } $sidebar-placeholder-width: 8rem; @@ -139,21 +132,21 @@ $sidebar-placeholder-width: 8rem; } .ui-navbar-logo { - font-family: 'Open Sans Condensed', sans-serif; + font-family: "Open Sans Condensed", sans-serif; font-weight: bold; font-size: 23px; // giving height of 32px border-radius: 0.25rem; - background: #25282C; - padding: 2px 1.0rem; // giving height of 36px + background: #25282c; + padding: 2px 1rem; // giving height of 36px margin-left: 6px; // navbar 48px, this is 36px, leaving 12px for vertical, 6px to make it symmetrical - color: #F0F1F1; + color: #f0f1f1; transition: 0.1s; } .ui-navbar-logo:hover { - color: #F0F1F1; + color: #f0f1f1; background: rgb(59, 63, 70); } @@ -164,8 +157,8 @@ $sidebar-placeholder-width: 8rem; $margin-bottom-widget: 0.2rem; .ui-widget-header { - background: #F5F5F9; - border: 1px solid #DDD; + background: #f5f5f9; + border: 1px solid #ddd; margin-top: 1.5rem; margin-bottom: 0.5rem; padding: 6px 10px; @@ -307,14 +300,15 @@ see https://stackoverflow.com/questions/9789723/css-text-overflow-in-a-table-cel /* https://stackoverflow.com/questions/6795981/textarea-to-fill-a-parent-container-exactly-with-padding/6796064 */ .is-maximized { - width:100%; - height:100%; - box-sizing: border-box; /* For IE and modern versions of Chrome */ - -moz-box-sizing: border-box; /* For Firefox */ + width: 100%; + height: 100%; + box-sizing: border-box; /* For IE and modern versions of Chrome */ + -moz-box-sizing: border-box; /* For Firefox */ -webkit-box-sizing: border-box; /* For Safari */ } -.ui-text-area:not([rows]) { // need to overrule Bulma's text-area:not([rows]) +.ui-text-area:not([rows]) { + // need to overrule Bulma's text-area:not([rows]) height: 100%; min-height: 600px; } diff --git a/src_frontend/App.tsx b/src_frontend/App.tsx index 1941519..4d84e25 100644 --- a/src_frontend/App.tsx +++ b/src_frontend/App.tsx @@ -1,45 +1,40 @@ - -import { createState, createEffect, createMemo } from 'solid-js'; -import { For, Switch, Match } from 'solid-js/dom'; +import { JSX } from "solid-js"; +import { createStore } from "solid-js/store"; +import { For, Switch, Match } from "solid-js/web"; import { StoreInterface } from "./store"; import { Tabs } from "./Tabs"; -import { TableHandler } from "./TableHandler" -import { PlotHandler } from "./PlotHandler" -// import { MapHandler } from "./MapHandler" - -import { IconDatabase, IconChartBar } from "./Icons" +import { TableHandler } from "./TableHandler"; +import { PlotHandler } from "./PlotHandler"; +import { IconDatabase, IconChartBar } from "./Icons"; interface TabConfig { name: { - icon: string, - text: string, - } - widgets: WidgetConfig[] + icon: string; + text: string; + }; + widgets: WidgetConfig[]; } interface WidgetConfig { - type: string - filterId: string + type: string; + filterId: string; } - function buildIcon(icon: string) { if (icon === "database") { - return ; + return ; } else if (icon === "plot") { - return ; + return ; } else { - return ? + return ?; } } - -export function App({store} : {store: StoreInterface}) { - - const [state, setState] = createState({ +export function App({ store }: { store: StoreInterface }) { + const [state, setState] = createStore({ appstate: { tabs: [ { @@ -52,7 +47,7 @@ export function App({store} : {store: StoreInterface}) { type: "table", filterId: "default", }, - ] + ], }, { name: { @@ -64,74 +59,69 @@ export function App({store} : {store: StoreInterface}) { type: "scatter-plot", filterId: "default", }, - ] - } + ], + }, ] as TabConfig[], filters: { default: "", - } as {[index: string]: string}, + } as { [index: string]: string }, }, activeTabIndex: 0, - }) - - let tabHeaders = ( - {tab => - {buildIcon(tab.name.icon)} {tab.name.text} - } - ) as () => JSX.Element[] - - let tabContents = ( - { tab => - { widget => - - - { - setState("appstate", "filters", widget.filterId, s) - }} - /> - - - { - setState("appstate", "filters", widget.filterId, s) - }} - /> - - {/* - - { - setState("appstate", "filters", widget.filterId, s) - }} - /> - - */} - -
{("Illegal widget.type: " + widget.type)}
-
-
- }
- }
- ) as () => JSX.Element[] + }); + + const tabHeaders = ( + + {(tab) => ( + + {buildIcon(tab.name.icon)} {tab.name.text} + + )} + + ) as () => JSX.Element[]; + + const tabContents = ( + + {(tab) => ( + + {(widget) => ( + + + { + setState("appstate", "filters", widget.filterId, s); + }} + /> + + + { + setState("appstate", "filters", widget.filterId, s); + }} + /> + + +
{"Illegal widget.type: " + widget.type}
+
+
+ )} +
+ )} +
+ ) as () => JSX.Element[]; function onActivate(i: number) { - setState({activeTabIndex: i}) + setState({ activeTabIndex: i }); } return ( <> - +
-
- {( tabContents()[state.activeTabIndex] )} -
+
{tabContents()[state.activeTabIndex]}
); diff --git a/src_frontend/Dropdown.tsx b/src_frontend/Dropdown.tsx index effcd35..d089bed 100644 --- a/src_frontend/Dropdown.tsx +++ b/src_frontend/Dropdown.tsx @@ -1,25 +1,24 @@ -import { createState, createEffect, onCleanup } from 'solid-js' -import { Show } from "solid-js/dom" +import { createStore } from "solid-js/store"; +import { Show } from "solid-js/web"; -import { IconAngleDown } from "./Icons" +import { IconAngleDown } from "./Icons"; interface DropdownProps { - items: string[], - selectedIndex?: number, - cbSelect: (index: number) => void, + items: string[]; + selectedIndex?: number; + cbSelect: (index: number) => void; } export function Dropdown(props: DropdownProps) { - - const [state, setState] = createState({ + const [state, setState] = createStore({ active: false, - }) + }); - function onClick(event: Event) { - setState({active: !state.active}) + function onClick(_event: Event) { + setState({ active: !state.active }); } - function onBlur(event: Event) { - setState({active: false}) + function onBlur(_event: Event) { + setState({ active: false }); } // Note the click handler of the dropdown items uses an onMouseDown @@ -27,28 +26,35 @@ export function Dropdown(props: DropdownProps) { // onClick of the item, see: // https://stackoverflow.com/questions/17769005/onclick-and-onblur-ordering-issue return ( -
+
- +
- ) + ); } diff --git a/src_frontend/ForIndex.tsx b/src_frontend/ForIndex.tsx deleted file mode 100644 index 9c82e50..0000000 --- a/src_frontend/ForIndex.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { map, createMemo, createSignal, createEffect, sample } from 'solid-js'; - -export function ForIndexed( - props: { - each: T[], - fallback?: any, - transform?: (mapped: () => U[], - source: () => T[]) => () => U[], - children: (item: T, n: number) => U, - }) { - const mapped = map(props.children, 'fallback' in props ? () => props.fallback : undefined)(() => props.each); - return props.transform ? props.transform(mapped, () => props.each) : mapped; -} - -interface MergedGetterSetter { - (): T; - set(x: T): void -} - -export function ForIndex(props: { - each: T[], - children: (item: T, n: () => number) => U, - }) { - const fn = props.children; - const list = () => props.each; - // We createMemo to prevent work being done each row in the final map we return - const indices = createMemo( - map((x: T, i: number) => { - const [s, set] = createSignal(i, (a, b) => a === b) as [MergedGetterSetter, (i: number) => void]; - s.set = set; - return s; - })(list), - [] // workaround as per https://github.com/ryansolid/solid/issues/51 - ); - //console.log("list 1", list) - //console.log("list 2", list()) - //console.log("indices 1:", indices) - //console.log("indices 2:", indices()) - createEffect(() => { - //console.log("indices effect", indices()) - return indices().forEach((index, i) => index.set(i)) - }); - return map((v: T, i: number) => fn(v, sample(indices)[i]))(list); -} diff --git a/src_frontend/Icons.tsx b/src_frontend/Icons.tsx index 93b9218..24b4d1f 100644 --- a/src_frontend/Icons.tsx +++ b/src_frontend/Icons.tsx @@ -1,32 +1,38 @@ -import { library, icon, Icon } from '@fortawesome/fontawesome-svg-core' +import { library, icon, Icon } from "@fortawesome/fontawesome-svg-core"; import { - faDatabase, faChartBar, - faLongArrowAltUp, faLongArrowAltDown, - faSortAmountUp, faSortAmountDown, + faDatabase, + faChartBar, + faLongArrowAltUp, + faLongArrowAltDown, + faSortAmountUp, + faSortAmountDown, faAngleDown, -} from '@fortawesome/free-solid-svg-icons' +} from "@fortawesome/free-solid-svg-icons"; // https://fontawesome.com/how-to-use/with-the-api/setup/library -library.add(faDatabase) -library.add(faChartBar) -library.add(faLongArrowAltUp) -library.add(faLongArrowAltDown) -library.add(faSortAmountUp) -library.add(faSortAmountDown) -library.add(faAngleDown) +library.add(faDatabase); +library.add(faChartBar); +library.add(faLongArrowAltUp); +library.add(faLongArrowAltDown); +library.add(faSortAmountUp); +library.add(faSortAmountDown); +library.add(faAngleDown); -const iDatabase = icon({ prefix: 'fas', iconName: 'database' }) -const iChartBar = icon({ prefix: 'fas', iconName: 'chart-bar' }) -const iLongArrowAltUp = icon({ prefix: 'fas', iconName: 'long-arrow-alt-up' }) -const iLongArrowAltDown = icon({ prefix: 'fas', iconName: 'long-arrow-alt-down' }) -const iSortAmountUp = icon({ prefix: 'fas', iconName: 'sort-amount-up' }) -const iSortAmountDown = icon({ prefix: 'fas', iconName: 'sort-amount-down' }) -const iAngleDown = icon({ prefix: 'fas', iconName: 'angle-down' }) +const iDatabase = icon({ prefix: "fas", iconName: "database" }); +const iChartBar = icon({ prefix: "fas", iconName: "chart-bar" }); +const iLongArrowAltUp = icon({ prefix: "fas", iconName: "long-arrow-alt-up" }); +const iLongArrowAltDown = icon({ + prefix: "fas", + iconName: "long-arrow-alt-down", +}); +const iSortAmountUp = icon({ prefix: "fas", iconName: "sort-amount-up" }); +const iSortAmountDown = icon({ prefix: "fas", iconName: "sort-amount-down" }); +const iAngleDown = icon({ prefix: "fas", iconName: "angle-down" }); function convert(icon: Icon) { // Note: icon.node is an HTMLCollection https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection - let fragment = []; // <> - for (let node of Array.from(icon.node)) { + const fragment = []; // <> + for (const node of Array.from(icon.node)) { fragment.push(node); } return fragment; @@ -52,4 +58,4 @@ export function IconSortAmountDown() { } export function IconAngleDown() { return convert(iAngleDown); -} \ No newline at end of file +} diff --git a/src_frontend/MapHandler.tsx b/src_frontend/MapHandler.tsx deleted file mode 100644 index d576aee..0000000 --- a/src_frontend/MapHandler.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import { createRoot, createState, createEffect, onCleanup, sample } from 'solid-js'; - -import { StoreInterface, DataFetchOptions, TableData, ColumnData } from "./store"; -import { Dropdown } from "./Dropdown"; - -import * as leaflet from "leaflet"; - -//import { addLayerGL } from "./webgl"; - - -function MapWrapper(props: { - mapData?: any, - }) { - - let el: HTMLDivElement = null!; - let map: leaflet.Map | undefined = undefined; - let layerGroup: leaflet.LayerGroup | undefined = undefined; - - const [state, setState] = createState({ - mounted: false, - cachedMapData: null, - }) - - let updateMap = (mapData: any) => { - if (map == null) { - console.log("Init map", el); - map = leaflet.map(el, {preferCanvas: true}).fitWorld(); - leaflet.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", { - attribution: '© OpenStreetMap contributors' - }).addTo(map) - } - - - let t1 = performance.now() - if (false) { - /* - try { - let data = [] as number[][]; - for (let trajectory of mapData) { - data = data.concat(trajectory); - } - addLayerGL(map, data); - } catch { - console.log("Invalid plot data"); - } - */ - } - if (true) { // pure leaflet implementation => not very scalable... - if (layerGroup != undefined) { - map!.removeLayer(layerGroup!); - } - try { - let lines = [] as leaflet.Polyline[]; - for (let trajectory of mapData) { - lines.push(leaflet.polyline(trajectory, {color: "red"})) - } - layerGroup = new leaflet.LayerGroup(lines); - layerGroup!.addTo(map!); - } catch { - console.log("Invalid plot data"); - } - } - let t2 = performance.now() - console.log("Updated map took", (t2 - t1) / 1000); - } - - createEffect(() => { - // effect to monitor changes to props.mapData - let newMapData = props.mapData; - if (sample(() => state.mounted)) { - // already mounted => we can call into the external lib directly - updateMap(newMapData) - } else { - // not mounted => need to cache - setState({cachedMapData: newMapData}); - } - }) - - let onMounted = () => { - if (state.cachedMapData != null) { - updateMap(state.cachedMapData!) - setState({cachedMapData: null}); - } - setState({mounted: true}) - } - - let onUnmounted = () => { - setState({mounted: false}) - } - - return ( -
- ) -} - - -export function MapHandler(props: { - store: StoreInterface, - filter: string, - onSetFilter: (s: string) => void, - }) { - - const { store } = props - - const [state, setState] = createState({ - columns: [] as string[], - mapData: {} as any, - selectedCol: undefined! as number, - }) - - createEffect(() => { - // handels updates of selected column indices - let col = state.selectedCol; - let filter = props.filter; - if (col != undefined) { - fetchData(col, filter); - } - }) - - async function fetchColumns() { - let columns = await store.fetchColumns() - console.log(columns) - setState({columns: columns}) - - if (columns.length >= 1) { - setState({ - selectedCol: 0, - }) - } - } - - async function fetchData(col: number, filter: string) { - console.log(`Fetching data for column ${col}`) - let data = await store.fetchData({ - sortKind: 0, - filter: filter, - }) - - const numCols = data.length; - if (numCols === 0) { - console.log("WARNING: received data with 0 columns, ignoring..."); - return; - } - const numRows = data[0].values.length; - - // console.log(data); - let coordinates = Array(numRows); - for (let i=0; i { - let newFilter = props.filter; - console.log("MapHandler: filter updated to", newFilter); - if (inputFilter != undefined) { - inputFilter.value = newFilter; - } - }) - - return ( -
-
-
- Filter - -
-
- Column - setState({selectedCol: index})} - /> -
-
- -
- ) -} \ No newline at end of file diff --git a/src_frontend/PlotHandler.tsx b/src_frontend/PlotHandler.tsx index fd7e9e1..d290584 100644 --- a/src_frontend/PlotHandler.tsx +++ b/src_frontend/PlotHandler.tsx @@ -1,14 +1,14 @@ -import { createRoot, createState, createEffect, onCleanup, sample } from 'solid-js'; +import { createEffect, untrack, onMount } from "solid-js"; +import { createStore } from "solid-js/store"; -import { StoreInterface, DataFetchOptions, TableData, ColumnData } from "./store"; +import { StoreInterface } from "./store"; import { Dropdown } from "./Dropdown"; import * as echarts from "echarts"; import { ECharts } from "echarts"; - export interface PlotWrapperProps { - plotData?: any + plotData?: any; } /* @@ -50,66 +50,74 @@ function PlotWrapper(props: PlotWrapperProps) { } */ - function PlotWrapper(props: PlotWrapperProps) { - let el: HTMLDivElement = null!; - let chart: ECharts = null!; + let el: HTMLDivElement | null = null; + let chart: ECharts | null = null; - const [state, setState] = createState({ + const [state, setState] = createStore({ mounted: false, cachedPlotData: null, - }) + }); - let updatePlot = (plotData: any) => { - if (chart == null) { - chart = echarts.init(el as HTMLDivElement); + const updatePlot = (plotData: any) => { + if (el != null) { + if (chart == null) { + chart = echarts.init(el as HTMLDivElement, { locale: "EN" }); + } + console.log("updating plot with:", plotData); + chart.setOption(plotData); } - console.log("updating plot with:", plotData) - chart.setOption(plotData) - } + }; + + onMount(() => { + if (el != null) { + (el as any).onconnected = onMounted; + (el as any).ondisconnected = onUnmounted; + } + }); createEffect(() => { // effect to monitor changes to props.plotData - let newPlotData = props.plotData; - if (sample(() => state.mounted)) { + const newPlotData = props.plotData; + if (untrack(() => state.mounted)) { // already mounted => we can call into the external lib directly - updatePlot(newPlotData) + updatePlot(newPlotData); } else { // not mounted => need to cache - setState({cachedPlotData: newPlotData}); + setState({ cachedPlotData: newPlotData }); } - }) + }); - let onMounted = () => { + const onMounted = () => { if (state.cachedPlotData != null) { - updatePlot(state.cachedPlotData!) - setState({cachedPlotData: null}); + updatePlot(state.cachedPlotData); + setState({ cachedPlotData: null }); } - setState({mounted: true}) - } + setState({ mounted: true }); + }; - let onUnmounted = () => { - setState({mounted: false}) - } + const onUnmounted = () => { + setState({ mounted: false }); + }; return (
(el = ref)} style="width: 800px;height:600px;" - onconnected={onMounted} - ondisconnected={onUnmounted} + // onconnected={onMounted} + // ondisconnected={onUnmounted} >
- ) + ); } - export function PlotHandler(props: { - store: StoreInterface, - filter: string, - onSetFilter: (s: string) => void, - }) { - - const { store } = props + store: StoreInterface; + filter: string; + onSetFilter: (s: string) => void; +}) { + const { store } = props; /* const dataFetchOptions = { @@ -117,42 +125,42 @@ export function PlotHandler(props: { } as DataFetchOptions */ - const [state, setState] = createState({ + const [state, setState] = createStore({ columns: [] as string[], plotData: {} as any, selectedColX: undefined! as number, selectedColY: undefined! as number, - }) + }); createEffect(() => { - // handels updates of selected column indices - let xCol = state.selectedColX; - let yCol = state.selectedColY; - let filter = props.filter; + // handles updates of selected column indices + const xCol = state.selectedColX; + const yCol = state.selectedColY; + const filter = props.filter; if (xCol != undefined && yCol != undefined) { fetchData(xCol, yCol, filter); } - }) + }); async function fetchColumns() { - let columns = await store.fetchColumns() - console.log(columns) - setState({columns: columns}) + const columns = await store.fetchColumns(); + console.log(columns); + setState({ columns: columns }); if (columns.length >= 2) { setState({ selectedColX: 0, selectedColY: 1, - }) + }); } } async function fetchData(xCol: number, yCol: number, filter: string) { - console.log(`Fetching data for columns ${xCol} vs ${yCol}`) - let data = await store.fetchData({ + console.log(`Fetching data for columns ${xCol} vs ${yCol}`); + const data = await store.fetchData({ sortKind: 0, filter: filter, - }) + }); const numCols = data.length; if (numCols === 0) { @@ -161,17 +169,17 @@ export function PlotHandler(props: { } const numRows = data[0].values.length; - const valueConverter = (x: any) => { - if (x == undefined || x === "inf" || x === "-inf" || !isFinite(x)) { + const valueConverter = (x: string | number) => { + if (x == undefined || x === "inf" || x === "-inf" || (typeof x == "number" && !isFinite(x))) { return NaN; } else { - return x; // TODO: do we need to convert to string for categorial data? + return x; // TODO: do we need to convert to string for categorical data? } - } + }; - let rowsData = Array(numRows); - for (let i=0; i doesn't seem to match specific types? + setState({ plotData: plotData as any }); // FIXME: Partial doesn't seem to match specific types? } - fetchColumns() + fetchColumns(); - let inputFilter: HTMLInputElement | undefined + let inputFilter: HTMLInputElement | undefined; function onFilterKeydown(event: KeyboardEvent) { if (event.keyCode === 13 && inputFilter != undefined) { - props.onSetFilter(inputFilter.value.trim()) + props.onSetFilter(inputFilter.value.trim()); } } createEffect(() => { - let newFilter = props.filter; + const newFilter = props.filter; console.log("PlotHandler: filter updated to", newFilter); if (inputFilter != undefined) { inputFilter.value = newFilter; } - }) + }); return (
-
- Filter +
+ Filter Dimension x setState({selectedColX: index})} + items={state.columns} + selectedIndex={state.selectedColX} + cbSelect={(index: number) => setState({ selectedColX: index })} />
Dimension y setState({selectedColY: index})} + items={state.columns} + selectedIndex={state.selectedColY} + cbSelect={(index: number) => setState({ selectedColY: index })} />
- +
- ) -} \ No newline at end of file + ); +} diff --git a/src_frontend/TableHandler.tsx b/src_frontend/TableHandler.tsx index 27b5f49..a664d01 100644 --- a/src_frontend/TableHandler.tsx +++ b/src_frontend/TableHandler.tsx @@ -1,22 +1,23 @@ -import { createRoot, createState, createEffect, onCleanup, sample } from 'solid-js'; -import { For } from 'solid-js/dom'; -import { ForIndex } from './ForIndex'; +import { createEffect, untrack } from "solid-js"; +import { createStore } from "solid-js/store"; +import { For } from "solid-js/web"; -import { StoreInterface, DataFetchOptions, TableData, ColumnData } from "./store"; +import { StoreInterface, TableData, ColumnData } from "./store"; import { - IconLongArrowAltUp, IconLongArrowAltDown, - IconSortAmountUp, IconSortAmountDown, + IconLongArrowAltUp, + IconLongArrowAltDown, + IconSortAmountUp, + IconSortAmountDown, } from "./Icons"; - type Value = string | number; function transformToString(x: Value) { if (x != undefined) { return x.toString(); } else { - return "-" + return "-"; } } @@ -25,20 +26,20 @@ function transformFloatToString(digits: number, x: number) { // TODO: handle limitations of toFixed return x.toFixed(digits); } else { - return "-" + return "-"; } } interface ColumnFormatter { - format: (x: Value) => string - align: number + format: (x: Value) => string; + align: number; } function analyzeColumn(data: Value[]): ColumnFormatter { - let allNull = true; + let _allNull = true; let allNumbers = true; let allInteger = true; - let hasExponetials = false; + let hasExponentials = false; let absMax = -Infinity; let absMin = +Infinity; @@ -46,11 +47,11 @@ function analyzeColumn(data: Value[]): ColumnFormatter { let maxDecimalPlacesR = 0; let maxDecimalPlacesL = 0; - for (let i=0; i absMax) { absMax = absValue; } @@ -70,14 +71,14 @@ function analyzeColumn(data: Value[]): ColumnFormatter { absMin = absValue; } - let valueString = (value > 0 ? value.toString() : (-value).toString()); + const valueString = value > 0 ? value.toString() : (-value).toString(); if (valueString.includes("e")) { - hasExponetials = true; + hasExponentials = true; // TODO } else if (valueString.includes(".")) { - let split = valueString.split("."); - let decL = split[0].length; - let decR = split[1].length; + const split = valueString.split("."); + const decL = split[0].length; + const decR = split[1].length; if (decL > maxDecimalPlacesL) { maxDecimalPlacesL = decL; } @@ -89,8 +90,8 @@ function analyzeColumn(data: Value[]): ColumnFormatter { } // console.log(maxDecimalPlacesL, maxDecimalPlacesR) - if (allNumbers && !allInteger && !hasExponetials) { - let maxDigits = 6; + if (allNumbers && !allInteger && !hasExponentials) { + const maxDigits = 6; let digits = maxDigits - maxDecimalPlacesL + 1; if (digits < 1) { digits = 1; @@ -98,19 +99,18 @@ function analyzeColumn(data: Value[]): ColumnFormatter { return { format: transformFloatToString.bind(null, digits) as (x: Value) => string, align: +1, - } + }; } else if (allInteger) { return { format: transformToString, align: +1, - } + }; } else { return { format: transformToString, align: -1, - } + }; } - } /** @@ -125,11 +125,11 @@ function transformData(data: TableData): Value[][] { console.log("Transforming data of shape:", numRows, numCols); // we need to convert from columnar to row-wise data - let rowsData = Array(numRows) as Value[][]; - for (let i=0; i void, - }) { - - const [state, setState] = createState({ + data: TableData; + cbSort: (sortKind: number, columnIndex?: number) => void; +}) { + const [state, setState] = createStore({ rowsData: [] as Value[][], headerData: [] as ColHeader[], - sortColIndex: undefined as (number | undefined), + sortColIndex: undefined as number | undefined, sortColKind: 0, - }) + }); - let columnFormatters = [] as ColumnFormatter[]; + const columnFormatters = [] as ColumnFormatter[]; createEffect(() => { - console.log("Data updated", props.data.length) - const data = props.data + console.log("Data updated", props.data.length); + const data = props.data; if (data.length == 0) { return; } // update column formatters - let numCols = data.length; + const numCols = data.length; columnFormatters.length = numCols; - for (let j=0; j ({ + const headerData = data.map((x: ColumnData) => ({ name: x.columnName, sortKind: x.sortKind, //onsort: () => { this.props.onsort(x.columnName) } - })) - setState({headerData: headerData}) - - }) + })); + setState({ headerData: headerData }); + }); createEffect(() => { - console.log("Rowsdata updated", state.rowsData.length) - }) + console.log("Rowsdata updated", state.rowsData.length); + }); createEffect(() => { - console.log("headerData updated", state.headerData.length) - }) + console.log("headerData updated", state.headerData.length); + }); createEffect(() => { - console.log("Updated sortColIndex", state.sortColIndex) - }) + console.log("Updated sortColIndex", state.sortColIndex); + }); createEffect(() => { - console.log("Updated sortColKind", state.sortColKind) - }) + console.log("Updated sortColKind", state.sortColKind); + }); function sortByCol(name: string, index: number) { - console.log("Sorting by column:", name, index, state.sortColIndex, state.sortColKind) + console.log("Sorting by column:", name, index, state.sortColIndex, state.sortColKind); if (state.sortColIndex !== index || state.sortColKind == 0) { - props.cbSort(1, index) + props.cbSort(1, index); setState({ sortColIndex: index, sortColKind: 1, - }) + }); } else { if (state.sortColKind == 1) { - props.cbSort(-1, index) + props.cbSort(-1, index); setState({ sortColKind: -1, - }) + }); } else { - props.cbSort(0, undefined) + props.cbSort(0, undefined); setState({ sortColKind: 0, - }) + }); } } } function renderSymbol(name: string, sortKind: number) { if (sortKind == 0) { - return <> - - - + return ( + <> + + + + ); } else if (sortKind < 0) { - return + return ; } else { - return + return ; } } function onCopy(event: ClipboardEvent) { // https://jsbin.com/runomuheye/1/edit?html,css,js,output // http://jsfiddle.net/vello/qvw0pgcu/ - console.log("Handling copy event") - var clipboardData = event.clipboardData; + console.log("Handling copy event"); + const _clipboardData = event.clipboardData; // TODO... /* if (clipboardData != null) { @@ -256,62 +254,72 @@ function Table(props: { > - - {(colHeader: ColHeader, index: () => number) => + + {(colHeader: ColHeader, index: () => number) => ( - } - + )} + - No data
}> - { (row: string[]) => + No data
} + > + {(row: string[]) => ( - - { (x: Value, j: () => number) => - 0 ? "has-text-right" : undefined))}>{columnFormatters[j()].format(x)} - } - + + {(x: Value, j: () => number) => ( + 0 ? "has-text-right" : undefined) + } + > + {columnFormatters[j()].format(x)} + + )} + - } + )} - ) + ); } - interface PaginationData { - numPages: number - currentPage: number - onPaginate: (i: number) => void + numPages: number; + currentPage: number; + onPaginate: (i: number) => void; } function Pagination(props: PaginationData) { - function constructPageArray(n: number, current: number): Array { if (n <= 10) { return Array.from(Array(props.numPages).keys()); } else { if (current <= 2) { - return [0, 1, 2, 3, undefined, n-1]; - } else if (current >= n-3) { - return [0, undefined, n-4, n-3, n-2, n-1]; + return [0, 1, 2, 3, undefined, n - 1]; + } else if (current >= n - 3) { + return [0, undefined, n - 4, n - 3, n - 2, n - 1]; } else { - return [0, undefined, current-1, current, current+1, undefined, n-1]; + return [0, undefined, current - 1, current, current + 1, undefined, n - 1]; } } } @@ -319,16 +327,16 @@ function Pagination(props: PaginationData) { return ( ); } - export function TableHandler(props: { - store: StoreInterface, - filter: string, - onSetFilter: (s: string) => void, - }) { - - const { store } = props + store: StoreInterface; + filter: string; + onSetFilter: (s: string) => void; +}) { + const { store } = props; - const [state, setState] = createState({ + const [state, setState] = createStore({ tableData: [] as TableData, sortKind: 0, - sortColumn: undefined as (string|undefined), + sortColumn: undefined as string | undefined, pagination: { numPages: 0, - currentPage: 0 - } as PaginationData - }) + currentPage: 0, + }, + }); - initialize() + initialize(); async function initialize() { - await fetchNumPages() - await fetchData() + await fetchNumPages(); + await fetchData(); } async function fetchNumPages() { - let numPages = await store.fetchNumPages(20, props.filter) - console.log("num pages:", numPages) + const numPages = await store.fetchNumPages(20, props.filter); + console.log("num pages:", numPages); setState({ pagination: { numPages: numPages, currentPage: 0, - } - }) + }, + }); } async function fetchData() { @@ -390,20 +396,20 @@ export function TableHandler(props: { paginationSize: 20, page: state.pagination.currentPage, filter: props.filter, - } - let data = await store.fetchData(dataFetchOptions) - setState({tableData: data}) + }; + const data = await store.fetchData(dataFetchOptions); + setState({ tableData: data }); } function cbSort(sortKind: number, columnIndex?: number) { - setState({sortKind: sortKind}) + setState({ sortKind: sortKind }); if (columnIndex != null) { - setState({sortColumn: state.tableData[columnIndex].columnName}) + setState({ sortColumn: state.tableData[columnIndex].columnName }); } - fetchData() + fetchData(); } - let inputFilter: HTMLInputElement | undefined + let inputFilter: HTMLInputElement | undefined; function onFilterKeydown(event: KeyboardEvent) { if (event.keyCode === 13 && inputFilter != undefined) { @@ -413,60 +419,62 @@ export function TableHandler(props: { // page number with the new filter => returning no data). // We'll have to see if resetting the page number is what we // want on changing selections... - props.onSetFilter(inputFilter.value.trim()) + props.onSetFilter(inputFilter.value.trim()); setState({ pagination: { currentPage: 0, numPages: state.pagination.numPages, - } - }) + }, + }); } } createEffect(() => { - let newFilter = props.filter; + const newFilter = props.filter; console.log("TableHandler: filter updated to", newFilter); if (inputFilter != undefined) { inputFilter.value = newFilter; } - // TODO: clarify why not sampling here causes an infinte loop. + // TODO: clarify why not sampling here causes an infinite loop. // Interestingly running either fetchNumPages or fetchDat alone is fine. // Only the combination causes an infinite loop. - sample(() => { - fetchNumPages() - fetchData() - }) - }) + untrack(() => { + fetchNumPages(); + fetchData(); + }); + }); function onPaginate(i: number) { setState({ pagination: { currentPage: i, numPages: state.pagination.numPages, - } - }) - fetchData() + }, + }); + fetchData(); } - return (<> -
-
- Filter - + return ( + <> +
+
+ Filter + +
-
-
- - - - ) -} \ No newline at end of file +
+
+ + + + ); +} diff --git a/src_frontend/Tabs.tsx b/src_frontend/Tabs.tsx index 9685ad9..86f485d 100644 --- a/src_frontend/Tabs.tsx +++ b/src_frontend/Tabs.tsx @@ -1,13 +1,12 @@ +import { JSX } from "solid-js"; export function Tabs(props: { - activeIndex: number, - tabHeaders: JSX.Element[], - onActivate: (i: number) => void - }) { - + activeIndex: number; + tabHeaders: JSX.Element[]; + onActivate: (i: number) => void; +}) { return ( - ) + ); } diff --git a/src_frontend/dom_lifecycle.ts b/src_frontend/dom_lifecycle.ts index 6a0f9f5..07655da 100644 --- a/src_frontend/dom_lifecycle.ts +++ b/src_frontend/dom_lifecycle.ts @@ -1,25 +1,24 @@ -new MutationObserver(changes).observe(document, { +new MutationObserver(mutationCallback).observe(document, { subtree: true, childList: true, }); -export function changes(records: any) { - for (var record, length = records.length, i = 0; i < length; i++) { - record = records[i]; +export function mutationCallback(records: MutationRecord[]) { + for (let i = 0; i < records.length; i++) { + const record = records[i]; dispatchAll(record.removedNodes, "disconnected"); dispatchAll(record.addedNodes, "connected"); } } -export function dispatchAll(nodes: any, type: any) { - for ( - var node, length = nodes.length, i = 0; - i < length; - (node = nodes[i++]).nodeType === 1 && dispatchTarget(node, type) - ); +export function dispatchAll(nodes: NodeList, type: "disconnected" | "connected") { + for (let i = 0; i < nodes.length; ++i) { + const node = nodes[i]; + node.nodeType === 1 && dispatchTarget(node, type); + } } -export function dispatchTarget(node: any, type: any) { +export function dispatchTarget(node: any, type: "disconnected" | "connected") { node["on" + type] && node["on" + type](); node = node.firstChild; while (node) { @@ -28,11 +27,15 @@ export function dispatchTarget(node: any, type: any) { } } -declare global { +/* +// Solid doesn't seem to auto-attach these callbacks to the node anymore, +// therefore this currently doesn't work, and manual attach is required. +declare module "solid-js" { namespace JSX { interface HTMLAttributes { - onconnected?: () => void - ondisconnected?: () => void + onconnected?: () => void; + ondisconnected?: () => void; } } } +*/ diff --git a/src_frontend/fn.ts b/src_frontend/fn.ts index f6444f0..7c6f695 100644 --- a/src_frontend/fn.ts +++ b/src_frontend/fn.ts @@ -1,19 +1,17 @@ - // https://webbjocke.com/javascript-check-data-types/ -export function isObject(value: any) { - return value && typeof value === 'object' && value.constructor === Object; +export function isObject(value: any): value is object { + return value && typeof value === "object" && value.constructor === Object; } -export function isArray(value: any) { - return value && typeof value === 'object' && value.constructor === Array; +export function isArray(value: any): value is Array { + return value && typeof value === "object" && value.constructor === Array; // ES5 actually has a method for this (ie9+) // Array.isArray(value); } - -export function forEach(obj: {[key: string]: V}, f: (k: string, v: V) => void) { - for (let key in obj) { - let value = obj[key]; +export function forEach(obj: { [key: string]: V }, f: (k: string, v: V) => void) { + for (const key in obj) { + const value = obj[key]; f(key, value); } } @@ -30,16 +28,15 @@ export function mapEntries(obj: {[key: string]: A}, f: (k: string, v: A) = } */ -export function mapEntries(obj: {[key: string]: A}, f: (k: string, v: A) => B): Array { - let result = Array(); - for (let key in obj) { - let value = obj[key]; - result.push(f(key, value)) +export function mapEntries(obj: { [key: string]: A }, f: (k: string, v: A) => B): Array { + const result = Array(); + for (const key in obj) { + const value = obj[key]; + result.push(f(key, value)); } return result; } - /* export function forEach(arr: Array, f: (v: V) => void) { for (let value of arr) { diff --git a/src_frontend/index.tsx b/src_frontend/index.tsx index cc118d3..fb0f7d0 100755 --- a/src_frontend/index.tsx +++ b/src_frontend/index.tsx @@ -1,11 +1,12 @@ // Needs to be imported once to enable lifecycle hooks -import './dom_lifecycle'; +import "./dom_lifecycle"; -import { render } from 'solid-js/dom'; +import { render } from "solid-js/web"; import { App } from "./App"; import { StoreBackend } from "./store_backend"; -let store = new StoreBackend() +const store = new StoreBackend(); -let el = document.getElementById('ROOT')!; -render(() => , el); +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +const el = document.getElementById("ROOT")!; +render(() => , el); diff --git a/src_frontend/index_standalone.tsx b/src_frontend/index_standalone.tsx index 3b0927a..eb766b2 100755 --- a/src_frontend/index_standalone.tsx +++ b/src_frontend/index_standalone.tsx @@ -1,11 +1,12 @@ // Needs to be imported once to enable lifecycle hooks -import './dom_lifecycle'; +import "./dom_lifecycle"; -import { render } from 'solid-js/dom'; +import { render } from "solid-js/web"; import { App } from "./App"; import { StoreStandalone } from "./store_standalone"; -let store = new StoreStandalone() +const store = new StoreStandalone(); -let el = document.getElementById('ROOT')!; -render(() => , el); +// eslint-disable-next-line @typescript-eslint/no-non-null-assertion +const el = document.getElementById("ROOT")!; +render(() => , el); diff --git a/src_frontend/store.ts b/src_frontend/store.ts index 688c68f..4f084ce 100644 --- a/src_frontend/store.ts +++ b/src_frontend/store.ts @@ -1,31 +1,29 @@ - export interface ColumnData { columnName: string; sortKind: number; - values: Array; + values: Array; } -export type TableData = ColumnData[] +export type TableData = ColumnData[]; export interface DataFetchOptions { - sortColumn?: string - sortKind: number - paginationSize?: number - page?: number - filter?: string + sortColumn?: string; + sortKind: number; + paginationSize?: number; + page?: number; + filter?: string; } export interface StoreInterface { - //async fetchData(): void - fetchColumns(): Promise - fetchNumPages(paginationSize: number, filter?: string): Promise - fetchData(opts: DataFetchOptions): Promise + fetchColumns(): Promise; + fetchNumPages(paginationSize: number, filter?: string): Promise; + fetchData(opts: DataFetchOptions): Promise; } export function clone(data: TableData): TableData { - let newData = [...Array(data.length)].map((x, i) => ({ + const newData = [...Array(data.length)].map((x, i) => ({ columnName: data[i].columnName, sortKind: data[i].sortKind, values: data[i].values.slice(), - })) + })); return newData; -} \ No newline at end of file +} From 8ce5da6be6094e963a664ef0f4c2074abdbe96b3 Mon Sep 17 00:00:00 2001 From: Imad Date: Wed, 6 Jul 2022 18:11:49 +0200 Subject: [PATCH 5/9] adding server_host as a parameter --- src_backend_python/tabloo/server.py | 4 +--- src_backend_python/tabloo/tabloo.py | 5 +++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src_backend_python/tabloo/server.py b/src_backend_python/tabloo/server.py index 3c3d08f..cd4a15d 100644 --- a/src_backend_python/tabloo/server.py +++ b/src_backend_python/tabloo/server.py @@ -103,11 +103,9 @@ def index(): return redirect("index.html") -def serve(df, open_browser, server_port=5000, server_logging=True, debug=False): +def serve(df, open_browser, server_host="0.0.0.0", server_port=5000, server_logging=True, debug=False): # TODO: We may add some auto port handling like this: https://stackoverflow.com/a/5089963/1804173 - server_host="0.0.0.0" - url = "http://{0}:{1}".format(server_host, server_port) global backend diff --git a/src_backend_python/tabloo/tabloo.py b/src_backend_python/tabloo/tabloo.py index a2c1709..6b99bcb 100644 --- a/src_backend_python/tabloo/tabloo.py +++ b/src_backend_python/tabloo/tabloo.py @@ -10,10 +10,10 @@ def show( df, open_browser=True, + server_host="0.0.0.0", server_port=5000, server_logging=False, - debug=False, - ): + debug=False): """ Runs a Tabloo app on a given dataframe. @@ -33,6 +33,7 @@ def show( server.serve( df=df, open_browser=open_browser, + server_host=server_host, server_port=server_port, server_logging=server_logging, debug=debug, From ffbb465a91eb7ea2cd0b5944927e104ed56a68da Mon Sep 17 00:00:00 2001 From: Imad Date: Wed, 6 Jul 2022 18:17:32 +0200 Subject: [PATCH 6/9] add todo comment --- src_frontend/store_backend.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src_frontend/store_backend.ts b/src_frontend/store_backend.ts index 181b04b..a854177 100644 --- a/src_frontend/store_backend.ts +++ b/src_frontend/store_backend.ts @@ -13,6 +13,7 @@ function transformValue(x: any): any { } export class StoreBackend implements StoreInterface { + // TODO: this needs to be dynamic url = "http://10.70.16.18:5000" async fetchColumns(): Promise { From 3fa9ac5a4765ec5d2fc023bbdfdb6d197a3a5710 Mon Sep 17 00:00:00 2001 From: Imad Date: Wed, 6 Jul 2022 18:30:03 +0200 Subject: [PATCH 7/9] add dynamic host todo comment --- src_backend_python/tabloo/server.py | 2 +- src_backend_python/tabloo/tabloo.py | 2 +- src_frontend/store_backend.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src_backend_python/tabloo/server.py b/src_backend_python/tabloo/server.py index cd4a15d..7fddbff 100644 --- a/src_backend_python/tabloo/server.py +++ b/src_backend_python/tabloo/server.py @@ -103,7 +103,7 @@ def index(): return redirect("index.html") -def serve(df, open_browser, server_host="0.0.0.0", server_port=5000, server_logging=True, debug=False): +def serve(df, open_browser, server_host="127.0.0.1", server_port=5000, server_logging=True, debug=False): # TODO: We may add some auto port handling like this: https://stackoverflow.com/a/5089963/1804173 url = "http://{0}:{1}".format(server_host, server_port) diff --git a/src_backend_python/tabloo/tabloo.py b/src_backend_python/tabloo/tabloo.py index 6b99bcb..74457e6 100644 --- a/src_backend_python/tabloo/tabloo.py +++ b/src_backend_python/tabloo/tabloo.py @@ -10,7 +10,7 @@ def show( df, open_browser=True, - server_host="0.0.0.0", + server_host="127.0.0.1", server_port=5000, server_logging=False, debug=False): diff --git a/src_frontend/store_backend.ts b/src_frontend/store_backend.ts index a854177..ce42e93 100644 --- a/src_frontend/store_backend.ts +++ b/src_frontend/store_backend.ts @@ -14,7 +14,7 @@ function transformValue(x: any): any { export class StoreBackend implements StoreInterface { // TODO: this needs to be dynamic - url = "http://10.70.16.18:5000" + url = "http://127.0.0.1:5000" async fetchColumns(): Promise { const response = await axios.get(`${this.url}/api/get_columns`); From 4e48eaf201b11a8664680d2c1044544850547ec6 Mon Sep 17 00:00:00 2001 From: Imad Date: Wed, 6 Jul 2022 18:32:37 +0200 Subject: [PATCH 8/9] remove perso file --- .envrc | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 .envrc diff --git a/.envrc b/.envrc deleted file mode 100644 index 401fe7a..0000000 --- a/.envrc +++ /dev/null @@ -1,4 +0,0 @@ -source "/home/imad/.local/bin/virtualenvwrapper.sh" -workon tabloo - -unset PS1 From f096e2bfa2f07dbf4205c4b8496d3688086aceea Mon Sep 17 00:00:00 2001 From: Imad Date: Thu, 7 Jul 2022 10:46:47 +0200 Subject: [PATCH 9/9] fmt fix --- src_frontend/store_backend.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src_frontend/store_backend.ts b/src_frontend/store_backend.ts index ce42e93..747a832 100644 --- a/src_frontend/store_backend.ts +++ b/src_frontend/store_backend.ts @@ -14,7 +14,7 @@ function transformValue(x: any): any { export class StoreBackend implements StoreInterface { // TODO: this needs to be dynamic - url = "http://127.0.0.1:5000" + url = "http://127.0.0.1:5000"; async fetchColumns(): Promise { const response = await axios.get(`${this.url}/api/get_columns`);