Skip to content

Commit

Permalink
support export configuration data (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
domechn authored Oct 28, 2023
1 parent 75d778a commit b27d814
Show file tree
Hide file tree
Showing 8 changed files with 176 additions and 78 deletions.
7 changes: 7 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ tauri = {version = "1.2", features = ["app-all", "dialog-open", "dialog-save", "
tokio = {version = "1", features = ["sync"] }
uuid = "1.3.3"
tauri-plugin-aptabase = "0.3"
md5 = "0.7.0"

[features]
# by default Tauri runs in production mode
Expand Down
11 changes: 11 additions & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,16 @@ fn decrypt(data: String) -> Result<String, String> {
}
}

#[cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
#[tauri::command]
fn md5(data: String) -> Result<String, String> {
let digest = md5::compute(data.as_bytes());
Ok(format!("{:x}", digest))
}

#[cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
Expand Down Expand Up @@ -160,6 +170,7 @@ fn main() {
query_okex_balance,
encrypt,
decrypt,
md5,
get_polybase_namespace,
])
.run(tauri::generate_context!())
Expand Down
6 changes: 5 additions & 1 deletion src/components/data-management/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
background-color: #a1a1a1;
}

.dataManagement input {
.dataManagement input:not([type="checkbox"]) {
width: 300px;
height: 30px;
margin-top: 20px;
Expand All @@ -27,3 +27,7 @@
border: none;
font-size: large;
}

.exportDataCheckbox {
width: 25px;
}
34 changes: 29 additions & 5 deletions src/components/data-management/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ import {
} from "../../middlelayers/cloudsync";
import { LoadingContext } from "../../App";
import { timestampToDate } from "../../utils/date";
import { trackEventWithClientID } from '../../utils/app'
import { trackEventWithClientID } from "../../utils/app";
import Modal from "../common/modal";

const App = ({
onDataImported,
Expand All @@ -41,6 +42,8 @@ const App = ({
const [lastSyncAt, setLastSyncAt] = useState<number>(0);
const [enableAutoSync, setEnableAutoSync] = useState<boolean>(false);

const [exportConfiguration, setExportConfiguration] = useState(false);

useEffect(() => {
onAuthStateUpdate((authState) => {
setIsLogin(!!authState);
Expand Down Expand Up @@ -103,7 +106,7 @@ const App = ({
}

async function onExportDataClick() {
const exported = await exportHistoricalData();
const exported = await exportHistoricalData(exportConfiguration);
if (exported) {
toast.success("export data successfully");
}
Expand Down Expand Up @@ -141,7 +144,7 @@ const App = ({
try {
await signIn(email, verificationCode);

trackEventWithClientID("sign_in")
trackEventWithClientID("sign_in");
} finally {
if (signInRef.current) {
signInRef.current!.disabled = false;
Expand Down Expand Up @@ -319,7 +322,7 @@ const App = ({
style={{
marginTop: 10,
}}
onClick={()=>syncDataBetweenCloudAndLocal()}
onClick={() => syncDataBetweenCloudAndLocal()}
>
Sync Data ( Beta )
</button>
Expand All @@ -330,7 +333,7 @@ const App = ({
backgroundColor: "#FF4500",
color: "white",
}}
onClick={()=>syncDataBetweenCloudAndLocal(true)}
onClick={() => syncDataBetweenCloudAndLocal(true)}
>
Hard Sync Data ( Beta )
</button>
Expand All @@ -351,6 +354,27 @@ const App = ({
</div>

<div>
<h4 style={{
marginBottom: 10,
}}>Select Exported Data</h4>
<div>
<input
className="exportDataCheckbox"
type="checkbox"
checked={exportConfiguration}
onChange={(e) => setExportConfiguration(e.target.checked)}
/>
<span>Export Configuration</span>
</div>
<div>
<input
className="exportDataCheckbox"
type="checkbox"
checked={true}
disabled
/>
<span>Export Historical Data</span>
</div>
<button onClick={onExportDataClick}>Export Data</button>
</div>
</div>
Expand Down
107 changes: 50 additions & 57 deletions src/components/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ const App = ({
}) => {
const [version, setVersion] = useState<string>("0.1.0");
const [isModalOpen, setIsModalOpen] = useState(false);
const [activeId, setActiveId] = useState<string>("configuration");
const size = useWindowSize();
const [isSmallScreenAndSidecarActive, setIsSmallScreenAndSidecarActive] =
useState(true);

useEffect(() => {
if (isModalOpen) {
loadVersion();
setIsSmallScreenAndSidecarActive(true)

setIsSmallScreenAndSidecarActive(true);
}
}, [isModalOpen]);

Expand All @@ -46,40 +48,6 @@ const App = ({
setIsModalOpen(false);
}

function setActiveOnSidebarItem(activeId?: string) {
const allowedIds = ["configuration", "data"];
const allowedContentIds = _(allowedIds)
.map((id) => `${id}Content`)
.value();
const sidebarItems = document.getElementsByClassName("sidebar-item");
const contentItems = document.getElementsByClassName("content-item");
_.forEach(sidebarItems, (item) => {
if (allowedIds.includes(item.id)) {
item.classList.remove("active");
}
});

_.forEach(contentItems, (item) => {
if (allowedContentIds.includes(item.id)) {
(item as any).style.display = "none";
}
});
if (!activeId) {
return
}

const activeSidebarItem = document.getElementById(activeId);
if (activeSidebarItem) {
activeSidebarItem.classList.add("active");
}

const activeContentItem = document.getElementById(`${activeId}Content`);

if (activeContentItem) {
activeContentItem.style.display = "block";
}
}

function getSettingWidth() {
const width = Math.floor(size.width ? size.width * 0.8 : 800);
// keep it even
Expand All @@ -91,13 +59,13 @@ const App = ({

function onConfigurationSidebarClick() {
// add active class to the clicked item
setActiveOnSidebarItem("configuration");
setIsSmallScreenAndSidecarActive(false)
setActiveId("configuration");
setIsSmallScreenAndSidecarActive(false);
}
function onDataSidebarClick() {
// add active class to the clicked item
setActiveOnSidebarItem("data");
setIsSmallScreenAndSidecarActive(false)
setActiveId("data");
setIsSmallScreenAndSidecarActive(false);
}

function _onConfigurationSave() {
Expand All @@ -124,26 +92,40 @@ const App = ({
<div className="settings-sidebar">
<div
id="configuration"
className="sidebar-item active"
className={`sidebar-item ${
!smallScreen() && activeId === "configuration" ? "active" : ""
}`}
onClick={onConfigurationSidebarClick}
>
Configuration
</div>
<div id="data" className="sidebar-item" onClick={onDataSidebarClick}>
<div
id="data"
className={`sidebar-item ${
!smallScreen() && activeId === "data" ? "active" : ""
}`}
onClick={onDataSidebarClick}
>
Data
</div>
<div className="version">version: {version}</div>
</div>

<div className="settings-content">
<div id="configurationContent" className="content-item">
<div
id="configurationContent"
className="content-item"
style={{
display: activeId === "configuration" ? "block" : "none",
}}
>
<Configuration onConfigurationSave={_onConfigurationSave} />
</div>
<div
id="dataContent"
className="content-item"
style={{
display: "none",
display: activeId === "data" ? "block" : "none",
}}
>
<DataManagement
Expand Down Expand Up @@ -188,26 +170,37 @@ const App = ({
width: "90%",
}}
>
<div style={{
textAlign: "left",
marginBottom: "10px",
cursor: "pointer",
fontFamily: "monospace",
fontSize: "14px",
color: "#0078d4"
}} onClick={()=>{
setIsSmallScreenAndSidecarActive(true)
// clear active class
setActiveOnSidebarItem()
}}>{'< back'}</div>
<div id="configurationContent" className="content-item">
<div
style={{
textAlign: "left",
marginBottom: "10px",
cursor: "pointer",
fontFamily: "monospace",
fontSize: "14px",
color: "#0078d4",
}}
onClick={() => {
setIsSmallScreenAndSidecarActive(true);
// clear active class
setActiveId("");
}}
>
{"< back"}
</div>
<div
id="configurationContent"
className="content-item"
style={{
display: activeId === "configuration" ? "block" : "none",
}}
>
<Configuration onConfigurationSave={_onConfigurationSave} />
</div>
<div
id="dataContent"
className="content-item"
style={{
display: "none",
display: activeId === "data" ? "block" : "none",
}}
>
<DataManagement
Expand Down
35 changes: 27 additions & 8 deletions src/middlelayers/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ export async function saveConfiguration(cfg: GlobalConfig) {
await saveConfigurationById(fixId, data)
}

// used for import data
export async function saveRawConfiguration(data: string) {
await saveConfigurationById(fixId, data)
}

export async function getCloudSyncConfiguration(): Promise<ConfigurationModel | undefined> {
return getConfigurationById(cloudSyncFixId)
}
Expand All @@ -45,30 +50,34 @@ async function saveConfigurationById(id: string, cfg: string) {
await db.execute(`INSERT OR REPLACE INTO configuration (id, data) VALUES (${id}, ?)`, [encrypted])
}

export async function exportConfigurationString(): Promise<string | undefined> {
const model = await getConfigurationModelById(fixId)
return model?.data
}

async function getConfigurationById(id: string): Promise<ConfigurationModel | undefined> {
const db = await getDatabase()
const configurations = await db.select<ConfigurationModel[]>(`SELECT * FROM configuration where id = ${id}`)
if (configurations.length === 0) {
return undefined
const model = await getConfigurationModelById(id)
if (!model) {
return
}

const cfg = configurations[0].data
const cfg = model.data

// legacy logic
if (!cfg.startsWith(prefix)) {
return configurations[0]
return model
}

// decrypt data
return invoke<string>("decrypt", { data: cfg }).then((res) => {
return {
...configurations[0],
...model,
data: res,
}

}).catch((err) => {
if (err.includes("not ent")) {
return configurations[0]
return model
}
throw err
})
Expand Down Expand Up @@ -101,3 +110,13 @@ export async function getClientIDConfiguration(): Promise<string | undefined> {
const model = await getConfigurationById(clientInfoFixId)
return model?.data
}

async function getConfigurationModelById(id: string): Promise<ConfigurationModel | undefined> {
const db = await getDatabase()
const configurations = await db.select<ConfigurationModel[]>(`SELECT * FROM configuration where id = ${id}`)
if (configurations.length === 0) {
return undefined
}

return configurations[0]
}
Loading

0 comments on commit b27d814

Please sign in to comment.