Seed patchdb UI data (#1835)

* adjust types
for patchdb ui data and create seed file

* feat: For init and the migration use defaults

* fix update path

* update build for ui seed file

* fix accidential revert

* chore: Convert to do during the init

* chore: Update the commit message

Co-authored-by: BluJ <mogulslayer@gmail.com>
This commit is contained in:
Lucy C
2022-09-26 17:36:37 -06:00
committed by GitHub
parent 31c5aebe90
commit 1702c07481
13 changed files with 113 additions and 67 deletions

View File

@@ -8,7 +8,7 @@ COMPAT_SRC := $(shell find system-images/compat/ -not -path 'system-images/compa
UTILS_SRC := $(shell find system-images/utils/ -not -name utils.tar) UTILS_SRC := $(shell find system-images/utils/ -not -name utils.tar)
BINFMT_SRC := $(shell find system-images/binfmt/ -not -name binfmt.tar) BINFMT_SRC := $(shell find system-images/binfmt/ -not -name binfmt.tar)
BACKEND_SRC := $(shell find backend/src) $(shell find backend/migrations) $(shell find patch-db/*/src) backend/Cargo.toml backend/Cargo.lock BACKEND_SRC := $(shell find backend/src) $(shell find backend/migrations) $(shell find patch-db/*/src) backend/Cargo.toml backend/Cargo.lock
FRONTEND_SHARED_SRC := $(shell find frontend/projects/shared) $(shell find frontend/assets) $(shell ls -p frontend/ | grep -v / | sed 's/^/frontend\//g') frontend/node_modules frontend/config.json patch-db/client/dist FRONTEND_SHARED_SRC := $(shell find frontend/projects/shared) $(shell find frontend/assets) $(shell ls -p frontend/ | grep -v / | sed 's/^/frontend\//g') frontend/node_modules frontend/config.json patch-db/client/dist frontend/patchdb-ui-seed.json
FRONTEND_UI_SRC := $(shell find frontend/projects/ui) FRONTEND_UI_SRC := $(shell find frontend/projects/ui)
FRONTEND_SETUP_WIZARD_SRC := $(shell find frontend/projects/setup-wizard) FRONTEND_SETUP_WIZARD_SRC := $(shell find frontend/projects/setup-wizard)
FRONTEND_DIAGNOSTIC_UI_SRC := $(shell find frontend/projects/diagnostic-ui) FRONTEND_DIAGNOSTIC_UI_SRC := $(shell find frontend/projects/diagnostic-ui)
@@ -74,7 +74,7 @@ snapshots: libs/snapshot-creator/Cargo.toml
cd libs/ && ./build-v8-snapshot.sh cd libs/ && ./build-v8-snapshot.sh
cd libs/ && ./build-arm-v8-snapshot.sh cd libs/ && ./build-arm-v8-snapshot.sh
$(EMBASSY_BINS): $(BACKEND_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) $(EMBASSY_BINS): $(BACKEND_SRC) $(ENVIRONMENT_FILE) $(GIT_HASH_FILE) frontend/patchdb-ui-seed.json
cd backend && ./build-prod.sh cd backend && ./build-prod.sh
touch $(EMBASSY_BINS) touch $(EMBASSY_BINS)
@@ -94,6 +94,10 @@ frontend/config.json: $(GIT_HASH_FILE) frontend/config-sample.json
jq '.useMocks = false' frontend/config-sample.json > frontend/config.json jq '.useMocks = false' frontend/config-sample.json > frontend/config.json
npm --prefix frontend run-script build-config npm --prefix frontend run-script build-config
frontend/patchdb-ui-seed.json: frontend/package.json
jq '."ack-welcome" = "$(shell yq '.version' frontend/package.json)"' frontend/patchdb-ui-seed.json > ui-seed.tmp
mv ui-seed.tmp frontend/patchdb-ui-seed.json
patch-db/client/node_modules: patch-db/client/package.json patch-db/client/node_modules: patch-db/client/package.json
npm --prefix patch-db/client ci npm --prefix patch-db/client ci

View File

@@ -147,6 +147,44 @@ impl serde::ser::Serialize for CharSet {
} }
} }
pub trait MergeWith {
fn merge_with(&mut self, other: &serde_json::Value);
}
impl MergeWith for serde_json::Value {
fn merge_with(&mut self, other: &serde_json::Value) {
use serde_json::Value::Object;
if let (Object(orig), Object(ref other)) = (self, other) {
for (key, val) in other.into_iter() {
match (orig.get_mut(key), val) {
(Some(new_orig @ Object(_)), other @ Object(_)) => {
new_orig.merge_with(other);
}
(None, _) => {
orig.insert(key.clone(), val.clone());
}
_ => (),
}
}
}
}
}
#[test]
fn merge_with_tests() {
use serde_json::json;
let mut a = json!(
{"a": 1, "c": {"d": "123"}, "i": [1,2,3], "j": {}, "k":[1,2,3], "l": "test"}
);
a.merge_with(
&json!({"a":"a", "b": "b", "c":{"d":"d", "e":"e"}, "f":{"g":"g"}, "h": [1,2,3], "i":"i", "j":[1,2,3], "k":{}}),
);
assert_eq!(
a,
json!({"a": 1, "c": {"d": "123", "e":"e"}, "b":"b", "f": {"g":"g"}, "h":[1,2,3], "i":[1,2,3], "j": {}, "k":[1,2,3], "l": "test"})
)
}
pub mod serde_regex { pub mod serde_regex {
use regex::Regex; use regex::Regex;
use serde::*; use serde::*;

View File

@@ -69,7 +69,8 @@ impl Database {
}, },
package_data: AllPackageData::default(), package_data: AllPackageData::default(),
recovered_packages: BTreeMap::new(), recovered_packages: BTreeMap::new(),
ui: Value::Object(Default::default()), ui: serde_json::from_str(include_str!("../../../frontend/patchdb-ui-seed.json"))
.unwrap(),
} }
} }
} }

View File

@@ -8,6 +8,7 @@ use helpers::NonDetachingJoinHandle;
use patch_db::{DbHandle, LockReceipt, LockType}; use patch_db::{DbHandle, LockReceipt, LockType};
use tokio::process::Command; use tokio::process::Command;
use crate::config::util::MergeWith;
use crate::context::rpc::RpcContextConfig; use crate::context::rpc::RpcContextConfig;
use crate::db::model::ServerStatus; use crate::db::model::ServerStatus;
use crate::install::PKG_DOCKER_DIR; use crate::install::PKG_DOCKER_DIR;
@@ -192,6 +193,25 @@ pub async fn init(cfg: &RpcContextConfig) -> Result<InitResult, Error> {
.server_info() .server_info()
.lock(&mut handle, LockType::Write) .lock(&mut handle, LockType::Write)
.await?; .await?;
let defaults: serde_json::Value =
serde_json::from_str(include_str!("../../frontend/patchdb-ui-seed.json")).map_err(|x| {
Error::new(
eyre!("Deserialization error {:?}", x),
crate::ErrorKind::Deserialization,
)
})?;
let mut ui = crate::db::DatabaseModel::new()
.ui()
.get(&mut handle, false)
.await?
.clone();
ui.merge_with(&defaults);
crate::db::DatabaseModel::new()
.ui()
.put(&mut handle, &ui)
.await?;
let receipts = InitReceipts::new(&mut handle).await?; let receipts = InitReceipts::new(&mut handle).await?;
let should_rebuild = tokio::fs::metadata(SYSTEM_REBUILD_PATH).await.is_ok() let should_rebuild = tokio::fs::metadata(SYSTEM_REBUILD_PATH).await.is_ok()

View File

@@ -1,6 +1,8 @@
use emver::VersionRange; use emver::VersionRange;
use crate::config::util::MergeWith;
use crate::hostname::{generate_id, get_hostname, sync_hostname}; use crate::hostname::{generate_id, get_hostname, sync_hostname};
use crate::ErrorKind;
use super::v0_3_0::V0_3_0_COMPAT; use super::v0_3_0::V0_3_0_COMPAT;
use super::*; use super::*;
@@ -35,28 +37,9 @@ impl VersionT for Version {
.await?; .await?;
sync_hostname(db).await?; sync_hostname(db).await?;
let mut ui = crate::db::DatabaseModel::new()
.ui()
.get(db, false)
.await?
.clone();
if let serde_json::Value::Object(ref mut ui) = ui {
ui.insert("ack-instructions".to_string(), serde_json::json!({}));
}
crate::db::DatabaseModel::new().ui().put(db, &ui).await?;
Ok(()) Ok(())
} }
async fn down<Db: DbHandle>(&self, db: &mut Db) -> Result<(), Error> { async fn down<Db: DbHandle>(&self, _db: &mut Db) -> Result<(), Error> {
let mut ui = crate::db::DatabaseModel::new()
.ui()
.get(db, false)
.await?
.clone();
if let serde_json::Value::Object(ref mut ui) = ui {
ui.remove("ack-instructions");
}
crate::db::DatabaseModel::new().ui().put(db, &ui).await?;
Ok(()) Ok(())
} }
} }

View File

@@ -0,0 +1,17 @@
{
"name": null,
"auto-check-updates": true,
"pkg-order": [],
"ack-welcome": "0.3.0",
"marketplace": {
"selected-id": null,
"known-hosts": {}
},
"dev": {},
"gaming": {
"snake": {
"high-score": 0
}
},
"ack-instructions": {}
}

View File

@@ -39,8 +39,8 @@ export class SnekDirective {
try { try {
await this.embassyApi.setDbValue({ await this.embassyApi.setDbValue({
pointer: '/gaming', pointer: '/gaming/snake/high-score',
value: { snake: { 'high-score': data.highScore } }, value: data.highScore,
}) })
} catch (e: any) { } catch (e: any) {
this.errToast.present(e) this.errToast.present(e)

View File

@@ -49,7 +49,7 @@ export class DeveloperListPage {
} }
async openCreateProjectModal() { async openCreateProjectModal() {
const projNumber = Object.keys(this.devData || {}).length + 1 const projNumber = Object.keys(this.devData).length + 1
const options: GenericInputOptions = { const options: GenericInputOptions = {
title: 'Add new project', title: 'Add new project',
message: 'Create a new dev project.', message: 'Create a new dev project.',
@@ -130,7 +130,7 @@ export class DeveloperListPage {
async createProject(name: string) { async createProject(name: string) {
// fail silently if duplicate project name // fail silently if duplicate project name
if ( if (
Object.values(this.devData || {}) Object.values(this.devData)
.map(v => v.name) .map(v => v.name)
.includes(name) .includes(name)
) )
@@ -148,11 +148,7 @@ export class DeveloperListPage {
.replace(/warning:/g, '# Optional\n warning:') .replace(/warning:/g, '# Optional\n warning:')
const def = { name, config, instructions: SAMPLE_INSTUCTIONS } const def = { name, config, instructions: SAMPLE_INSTUCTIONS }
if (this.devData) {
await this.api.setDbValue({ pointer: `/dev/${id}`, value: def }) await this.api.setDbValue({ pointer: `/dev/${id}`, value: def })
} else {
await this.api.setDbValue({ pointer: `/dev`, value: { [id]: def } })
}
} catch (e: any) { } catch (e: any) {
this.errToast.present(e) this.errToast.present(e)
} finally { } finally {

View File

@@ -66,7 +66,7 @@ export class MarketplacesPage {
this.patch this.patch
.watch$('ui', 'marketplace') .watch$('ui', 'marketplace')
.pipe(distinctUntilChanged(), takeUntil(this.destroy$)) .pipe(distinctUntilChanged(), takeUntil(this.destroy$))
.subscribe((mp: UIMarketplaceData | undefined) => { .subscribe((mp: UIMarketplaceData) => {
let marketplaces: Marketplaces = [ let marketplaces: Marketplaces = [
{ {
id: null, id: null,
@@ -74,7 +74,6 @@ export class MarketplacesPage {
url: this.config.marketplace.url, url: this.config.marketplace.url,
}, },
] ]
if (mp) {
this.selectedId = mp['selected-id'] this.selectedId = mp['selected-id']
const alts = Object.entries(mp['known-hosts']).map(([k, v]) => { const alts = Object.entries(mp['known-hosts']).map(([k, v]) => {
return { return {
@@ -84,7 +83,6 @@ export class MarketplacesPage {
} }
}) })
marketplaces = marketplaces.concat(alts) marketplaces = marketplaces.concat(alts)
}
this.marketplaces = marketplaces this.marketplaces = marketplaces
}) })
} }

View File

@@ -23,6 +23,12 @@ export const mockPatchData: DataModel = {
}, },
}, },
}, },
dev: {},
gaming: {
snake: {
'high-score': 0,
},
},
'ack-instructions': {}, 'ack-instructions': {},
}, },
'server-info': { 'server-info': {

View File

@@ -37,13 +37,6 @@ export class MarketplaceService extends AbstractMarketplaceService {
private readonly uiMarketplaceData$ = this.patch private readonly uiMarketplaceData$ = this.patch
.watch$('ui', 'marketplace') .watch$('ui', 'marketplace')
.pipe( .pipe(
map(
m =>
m || {
'selected-id': null,
'known-hosts': {},
},
),
distinctUntilChanged( distinctUntilChanged(
(prev, curr) => prev['selected-id'] === curr['selected-id'], (prev, curr) => prev['selected-id'] === curr['selected-id'],
), ),

View File

@@ -11,13 +11,13 @@ export interface DataModel {
} }
export interface UIData { export interface UIData {
name: string name: string | null
'auto-check-updates': boolean 'auto-check-updates': boolean
'pkg-order': string[] 'pkg-order': string[]
'ack-welcome': string // EOS version 'ack-welcome': string // EOS emver
marketplace?: UIMarketplaceData marketplace: UIMarketplaceData
dev?: DevData dev: DevData
gaming?: { gaming: {
snake: { snake: {
'high-score': number 'high-score': number
} }

View File

@@ -8,15 +8,5 @@ import { firstValueFrom, map } from 'rxjs'
export function getMarketplace( export function getMarketplace(
patch: PatchDB<DataModel>, patch: PatchDB<DataModel>,
): Promise<UIMarketplaceData> { ): Promise<UIMarketplaceData> {
return firstValueFrom( return firstValueFrom(patch.watch$('ui', 'marketplace'))
patch.watch$('ui', 'marketplace').pipe(
map(
m =>
m || {
'selected-id': null,
'known-hosts': {},
},
),
),
)
} }