Skip to content

Commit

Permalink
Merge pull request #16 from bruceyyu/main
Browse files Browse the repository at this point in the history
updates for v0.1.4
  • Loading branch information
bruceyyu authored Apr 12, 2024
2 parents 1dd0880 + 41046be commit 62efa39
Show file tree
Hide file tree
Showing 12 changed files with 3,257 additions and 941 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: GWalkR
Title: Interactive Exploratory Data Analysis Tool
Version: 0.1.3
Version: 0.1.4
Authors@R: c(
person("Yue", "Yu", , "[email protected]", role = c("aut", "cre"),
comment = c(ORCID = "0000-0002-9302-0793")),
Expand Down
5 changes: 5 additions & 0 deletions GWalkR.Rproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ SaveWorkspace: No
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: Sweave
LaTeX: pdfLaTeX

AutoAppendNewline: Yes
StripTrailingWhitespace: Yes
LineEndingConversion: Posix
Expand Down
35 changes: 13 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,39 +25,30 @@ It can simplify your R data analysis and data visualization workflow, by turning

### Setup GWalkR

#### Through CRAN (Recommended)

```R
install.packages("GWalkR")
library(GWalkR)
```

#### Through Running R Script

If you have `devtools` installed in R, you can run the following R code to install.

```R
devtools::install_url("https://kanaries-app.s3.ap-northeast-1.amazonaws.com/oss/gwalkr/GWalkR_latest.tar.gz")
```

#### Through Package Archive File (.tar.gz)

Alternatively, download the package archive file `GWalkR_latest.tar.gz` from [this link](https://kanaries-app.s3.ap-northeast-1.amazonaws.com/oss/gwalkr/GWalkR_latest.tar.gz).
Open R Studio, click "Install" in the "Packages" window, and select "Package Archive File (.tgz; .tar.gz)" in the "Install from". Then, select the archive in your file system and click "Install".

### Start Your Data Exploration in a Single Line of Code

```R
library(GWalkR)
data(iris)
gwalkr(iris)
```

<img width="1437" alt="image" src="https://github.com/Bruceshark/GWalkR/assets/33870780/718d8ff6-4ad5-492d-9afb-c4ed67573f51">

## Main Features
1. 🧑‍🎨 Turn a data frame into charts through simple drag-and-drop operations.
2. ✨ Empower your RMarkdown: Showcase your data insights with editable and explorable charts on a webpage ([example](https://bruceyyu.github.io/show/tidytuesday_etymology.nb.html))!
3. 🤖️ [coming soon] Work with AI copilot in R: Let AI generate explorable charts for you!
### Get an overview of your data frame under 'Data' tab.
<img width="700" alt="image" src="https://github.com/bruceyyu/GWalkR/assets/33870780/67131cfa-a25b-44ae-90a0-95902ea5edb1">

### Creat data viz with simple drag-and-drop operations.
<img width="700" alt="image" src="https://github.com/Bruceshark/GWalkR/assets/33870780/718d8ff6-4ad5-492d-9afb-c4ed67573f51">

### Find interesting data points? Brush them and zoom in!
<img width="700" alt="image" src="https://github.com/bruceyyu/GWalkR/assets/33870780/8033885d-3699-4f50-84e1-2201b3846b5a">

### Empower your R notebook (R Markdown).

Showcase your data insights with editable and explorable charts on a webpage ([example](https://bruceyyu.github.io/show/tidytuesday_etymology.nb.html))!

https://github.com/Kanaries/GWalkR/assets/33870780/4a3a9f9c-ff17-484b-9503-af82bd609b99
<img width="700" alt="image" src="https://github.com/bruceyyu/GWalkR/assets/33870780/4798367c-0dd4-4ad3-b25b-7ea48b79205a">
2 changes: 1 addition & 1 deletion web_app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
"@kanaries/graphic-walker": "^0.4.13",
"@kanaries/graphic-walker": "^0.4.61",
"@rollup/plugin-commonjs": "^25.0.2",
"@rollup/plugin-replace": "^5.0.2",
"@rollup/plugin-terser": "^0.4.3",
Expand Down
17 changes: 9 additions & 8 deletions web_app/src/components/codeExportModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import { observer } from "mobx-react-lite";
import DefaultButton from "../button/default";
import PrimaryButton from "../button/primary";

import type { IGlobalStore } from "@kanaries/graphic-walker/dist/store";
import type { VizSpecStore } from '@kanaries/graphic-walker/store/visualSpecStore'

interface ICodeExport {
globalStore: React.MutableRefObject<IGlobalStore | null>;
globalStore: React.MutableRefObject<VizSpecStore | null>;
open: boolean;
setOpen: (open: boolean) => void;
}
Expand All @@ -27,20 +27,21 @@ const downloadFile = (data: string) => {
};

const CodeExport: React.FC<ICodeExport> = observer((props) => {
const { globalStore, open, setOpen } = props;
const [code, setCode] = useState<string>("");

useEffect(() => {
if (props.open) {
const res = props.globalStore.current?.vizStore.exportViewSpec();
if (open && globalStore.current) {
const res = globalStore.current.exportCode();
if (res) setCode(JSON.stringify(res));
}
}, [props.open]);
}, [open]);

return (
<Modal
show={props.open}
show={open}
onClose={() => {
props.setOpen(false);
setOpen(false);
}}
>
<div className="dark:text-white">
Expand All @@ -66,7 +67,7 @@ const CodeExport: React.FC<ICodeExport> = observer((props) => {
</div>
<div className="text-sm max-h-56 mt-4 text-left">
<div>Option 1: paste the config in your R code as a string and pass it to `visConfig` parameter.</div>
<div>Option 2: download the config file and pass the file path to `visConfigFile` parameter.</div>
<div>Option 2 (recommended): download the config file and pass the file path to `visConfigFile` parameter.</div>
</div>
</div>
</Modal>
Expand Down
55 changes: 8 additions & 47 deletions web_app/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,21 @@
import React, { useMemo, useState } from "react";
import React, { useState } from "react";
import { createRoot } from "react-dom/client";
import { observer } from "mobx-react-lite";
import { IAppProps } from "./interfaces";
import { GraphicWalker } from "@kanaries/graphic-walker";
import type { IGlobalStore } from "@kanaries/graphic-walker/dist/store";
import type { IDataSetInfo, IMutField, IRow, IVisSpec } from "@kanaries/graphic-walker/dist/interfaces";
import type { IStoInfo } from "@kanaries/graphic-walker/dist/utils/save";
import type { VizSpecStore } from '@kanaries/graphic-walker/store/visualSpecStore';
import { getExportTool } from "./tools/exportTool";
import CodeExportModal from "./components/codeExportModal";
import { StyleSheetManager } from "styled-components";
import tailwindStyle from "tailwindcss/tailwind.css?inline";
import formatSpec from "./utils/formatSpec";

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const App: React.FC<IAppProps> = observer((propsIn) => {
const { dataSource, ...props } = propsIn;
const storeRef = React.useRef<IGlobalStore>(null);
const specList: IVisSpec[] = useMemo(() => {
return props.visSpec ? (JSON.parse(props.visSpec) as IVisSpec[]) : [];
}, []);
const [exportOpen, setExportOpen] = useState(false);

const setData = (data?: IRow[], rawFields?: IMutField[]) => {
if (specList.length !== 0) {
setTimeout(() => {
storeRef?.current?.vizStore?.importStoInfo({
dataSources: [
{
id: "dataSource-0",
data: data,
},
],
datasets: [
{
id: "dataset-0",
name: "DataSet",
rawFields: rawFields,
dsId: "dataSource-0",
},
],
specList,
} as IStoInfo);
}, 1);
} else {
storeRef?.current?.commonStore?.updateTempSTDDS({
name: "Dataset",
rawFields: rawFields,
dataSource: data,
} as IDataSetInfo);
storeRef?.current?.commonStore?.commitTempDS();
}
};
const { dataSource, visSpec, rawFields, ...props } = propsIn;
const storeRef = React.useRef<VizSpecStore|null>(null);

React.useEffect(() => {
setData(dataSource, props.rawFields);
}, []);
const specList = visSpec ? formatSpec(JSON.parse(visSpec) as any[], rawFields) : undefined
const [exportOpen, setExportOpen] = useState(false);

const exportTool = getExportTool(setExportOpen);

Expand All @@ -66,9 +28,8 @@ const App: React.FC<IAppProps> = observer((propsIn) => {
return (
<React.StrictMode>
<div className="h-full w-full overflow-y-scroll font-sans">
{/* <div style={{ height: "100%", width: "100%", overflowY: "scroll" }}> */}
<CodeExportModal open={exportOpen} setOpen={setExportOpen} globalStore={storeRef} />
<GraphicWalker {...props} storeRef={storeRef} toolbar={toolbarConfig} />
<GraphicWalker {...props} storeRef={storeRef} data={dataSource} toolbar={toolbarConfig} fields={rawFields} chart={specList} />
</div>
</React.StrictMode>
);
Expand Down
6 changes: 4 additions & 2 deletions web_app/src/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { IGWProps } from "@kanaries/graphic-walker/dist/App";
import type { IRow, IMutField } from '@kanaries/graphic-walker/interfaces'

export interface IAppProps extends IGWProps {
export interface IAppProps {
id: string;
version?: string;
hashcode?: string;
visSpec?: string;
env?: string;
needLoadDatas?: boolean;
specType?: string;
dataSource: IRow[];
rawFields: IMutField[];
}
2 changes: 1 addition & 1 deletion web_app/src/tools/exportTool.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";

import { CodeBracketSquareIcon } from "@heroicons/react/24/outline";

import type { ToolbarButtonItem } from "@kanaries/graphic-walker/dist/components/toolbar/toolbar-button";
import type { ToolbarButtonItem } from "@kanaries/graphic-walker/components/toolbar/toolbar-button";

export function getExportTool(setExportOpen: React.Dispatch<React.SetStateAction<boolean>>): ToolbarButtonItem {
return {
Expand Down
17 changes: 17 additions & 0 deletions web_app/src/utils/formatSpec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable no-prototype-builtins */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import { VegaliteMapper } from "@kanaries/graphic-walker/lib/vl2gw";

export default function formatSpec(spec: any[], fields: any[]) {
return spec.map((item, index) => {
if (["config", "encodings", "visId"].every((key) => item.hasOwnProperty(key))) {
return item;
} else {
const result = VegaliteMapper(item, fields, Math.random().toString(16).split(".").at(1)!, `Chart ${index + 1}`);
return result;
}
});
}
10 changes: 8 additions & 2 deletions web_app/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"allowJs": true,
"module": "ESNext",
"skipLibCheck": true,

/* Bundler mode */
"moduleResolution": "Node",
"moduleResolution": "Bundler",
"allowImportingTsExtensions": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
Expand All @@ -19,7 +20,12 @@
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
"noFallthroughCasesInSwitch": true,

"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
Expand Down
3 changes: 3 additions & 0 deletions web_app/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export default defineConfig((config: ConfigEnv) => {
... (config.mode === 'production') ? [CommonJs(), Terser()]: []
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
//dedupe: modulesNotToBundle,
},
build: {
Expand Down
Loading

0 comments on commit 62efa39

Please sign in to comment.