From 1702c074819267819c47e0225a7ee9afdc4b1d74 Mon Sep 17 00:00:00 2001 From: Lucy C <12953208+elvece@users.noreply.github.com> Date: Mon, 26 Sep 2022 17:36:37 -0600 Subject: [PATCH] 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 --- Makefile | 8 +++- backend/src/config/util.rs | 38 +++++++++++++++++++ backend/src/db/model.rs | 3 +- backend/src/init.rs | 20 ++++++++++ backend/src/version/v0_3_2.rs | 23 ++--------- frontend/patchdb-ui-seed.json | 17 +++++++++ .../ui/src/app/app/snek/snek.directive.ts | 4 +- .../developer-list/developer-list.page.ts | 10 ++--- .../marketplaces/marketplaces.page.ts | 22 +++++------ .../ui/src/app/services/api/mock-patch.ts | 6 +++ .../src/app/services/marketplace.service.ts | 7 ---- .../src/app/services/patch-db/data-model.ts | 10 ++--- .../ui/src/app/util/get-marketplace.ts | 12 +----- 13 files changed, 113 insertions(+), 67 deletions(-) create mode 100644 frontend/patchdb-ui-seed.json diff --git a/Makefile b/Makefile index 47231dc2d..15d8987cb 100644 --- a/Makefile +++ b/Makefile @@ -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) 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 -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_SETUP_WIZARD_SRC := $(shell find frontend/projects/setup-wizard) 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-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 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 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 npm --prefix patch-db/client ci diff --git a/backend/src/config/util.rs b/backend/src/config/util.rs index 8e29d6509..f6acd092e 100644 --- a/backend/src/config/util.rs +++ b/backend/src/config/util.rs @@ -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 { use regex::Regex; use serde::*; diff --git a/backend/src/db/model.rs b/backend/src/db/model.rs index 82c9a6424..d51b1f59f 100644 --- a/backend/src/db/model.rs +++ b/backend/src/db/model.rs @@ -69,7 +69,8 @@ impl Database { }, package_data: AllPackageData::default(), recovered_packages: BTreeMap::new(), - ui: Value::Object(Default::default()), + ui: serde_json::from_str(include_str!("../../../frontend/patchdb-ui-seed.json")) + .unwrap(), } } } diff --git a/backend/src/init.rs b/backend/src/init.rs index 78088899e..8c2d5efc7 100644 --- a/backend/src/init.rs +++ b/backend/src/init.rs @@ -8,6 +8,7 @@ use helpers::NonDetachingJoinHandle; use patch_db::{DbHandle, LockReceipt, LockType}; use tokio::process::Command; +use crate::config::util::MergeWith; use crate::context::rpc::RpcContextConfig; use crate::db::model::ServerStatus; use crate::install::PKG_DOCKER_DIR; @@ -192,6 +193,25 @@ pub async fn init(cfg: &RpcContextConfig) -> Result { .server_info() .lock(&mut handle, LockType::Write) .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 should_rebuild = tokio::fs::metadata(SYSTEM_REBUILD_PATH).await.is_ok() diff --git a/backend/src/version/v0_3_2.rs b/backend/src/version/v0_3_2.rs index 4f47135a3..8487691f9 100644 --- a/backend/src/version/v0_3_2.rs +++ b/backend/src/version/v0_3_2.rs @@ -1,6 +1,8 @@ use emver::VersionRange; +use crate::config::util::MergeWith; use crate::hostname::{generate_id, get_hostname, sync_hostname}; +use crate::ErrorKind; use super::v0_3_0::V0_3_0_COMPAT; use super::*; @@ -35,28 +37,9 @@ impl VersionT for Version { .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(()) } - async fn down(&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?; + async fn down(&self, _db: &mut Db) -> Result<(), Error> { Ok(()) } } diff --git a/frontend/patchdb-ui-seed.json b/frontend/patchdb-ui-seed.json new file mode 100644 index 000000000..e31279b82 --- /dev/null +++ b/frontend/patchdb-ui-seed.json @@ -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": {} +} diff --git a/frontend/projects/ui/src/app/app/snek/snek.directive.ts b/frontend/projects/ui/src/app/app/snek/snek.directive.ts index d87a0898e..7d167d236 100644 --- a/frontend/projects/ui/src/app/app/snek/snek.directive.ts +++ b/frontend/projects/ui/src/app/app/snek/snek.directive.ts @@ -39,8 +39,8 @@ export class SnekDirective { try { await this.embassyApi.setDbValue({ - pointer: '/gaming', - value: { snake: { 'high-score': data.highScore } }, + pointer: '/gaming/snake/high-score', + value: data.highScore, }) } catch (e: any) { this.errToast.present(e) diff --git a/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts b/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts index 896e0dc4e..1c9bd14d0 100644 --- a/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts +++ b/frontend/projects/ui/src/app/pages/developer-routes/developer-list/developer-list.page.ts @@ -49,7 +49,7 @@ export class DeveloperListPage { } async openCreateProjectModal() { - const projNumber = Object.keys(this.devData || {}).length + 1 + const projNumber = Object.keys(this.devData).length + 1 const options: GenericInputOptions = { title: 'Add new project', message: 'Create a new dev project.', @@ -130,7 +130,7 @@ export class DeveloperListPage { async createProject(name: string) { // fail silently if duplicate project name if ( - Object.values(this.devData || {}) + Object.values(this.devData) .map(v => v.name) .includes(name) ) @@ -148,11 +148,7 @@ export class DeveloperListPage { .replace(/warning:/g, '# Optional\n warning:') const def = { name, config, instructions: SAMPLE_INSTUCTIONS } - if (this.devData) { - await this.api.setDbValue({ pointer: `/dev/${id}`, value: def }) - } else { - await this.api.setDbValue({ pointer: `/dev`, value: { [id]: def } }) - } + await this.api.setDbValue({ pointer: `/dev/${id}`, value: def }) } catch (e: any) { this.errToast.present(e) } finally { diff --git a/frontend/projects/ui/src/app/pages/server-routes/marketplaces/marketplaces.page.ts b/frontend/projects/ui/src/app/pages/server-routes/marketplaces/marketplaces.page.ts index e8fb02caf..2cf5e8315 100644 --- a/frontend/projects/ui/src/app/pages/server-routes/marketplaces/marketplaces.page.ts +++ b/frontend/projects/ui/src/app/pages/server-routes/marketplaces/marketplaces.page.ts @@ -66,7 +66,7 @@ export class MarketplacesPage { this.patch .watch$('ui', 'marketplace') .pipe(distinctUntilChanged(), takeUntil(this.destroy$)) - .subscribe((mp: UIMarketplaceData | undefined) => { + .subscribe((mp: UIMarketplaceData) => { let marketplaces: Marketplaces = [ { id: null, @@ -74,17 +74,15 @@ export class MarketplacesPage { url: this.config.marketplace.url, }, ] - if (mp) { - this.selectedId = mp['selected-id'] - const alts = Object.entries(mp['known-hosts']).map(([k, v]) => { - return { - id: k, - name: v.name, - url: v.url, - } - }) - marketplaces = marketplaces.concat(alts) - } + this.selectedId = mp['selected-id'] + const alts = Object.entries(mp['known-hosts']).map(([k, v]) => { + return { + id: k, + name: v.name, + url: v.url, + } + }) + marketplaces = marketplaces.concat(alts) this.marketplaces = marketplaces }) } diff --git a/frontend/projects/ui/src/app/services/api/mock-patch.ts b/frontend/projects/ui/src/app/services/api/mock-patch.ts index 3af7daf0b..fac6ef275 100644 --- a/frontend/projects/ui/src/app/services/api/mock-patch.ts +++ b/frontend/projects/ui/src/app/services/api/mock-patch.ts @@ -23,6 +23,12 @@ export const mockPatchData: DataModel = { }, }, }, + dev: {}, + gaming: { + snake: { + 'high-score': 0, + }, + }, 'ack-instructions': {}, }, 'server-info': { diff --git a/frontend/projects/ui/src/app/services/marketplace.service.ts b/frontend/projects/ui/src/app/services/marketplace.service.ts index 2127d8702..c85f38413 100644 --- a/frontend/projects/ui/src/app/services/marketplace.service.ts +++ b/frontend/projects/ui/src/app/services/marketplace.service.ts @@ -37,13 +37,6 @@ export class MarketplaceService extends AbstractMarketplaceService { private readonly uiMarketplaceData$ = this.patch .watch$('ui', 'marketplace') .pipe( - map( - m => - m || { - 'selected-id': null, - 'known-hosts': {}, - }, - ), distinctUntilChanged( (prev, curr) => prev['selected-id'] === curr['selected-id'], ), diff --git a/frontend/projects/ui/src/app/services/patch-db/data-model.ts b/frontend/projects/ui/src/app/services/patch-db/data-model.ts index f1a8e797e..cbb21b7f6 100644 --- a/frontend/projects/ui/src/app/services/patch-db/data-model.ts +++ b/frontend/projects/ui/src/app/services/patch-db/data-model.ts @@ -11,13 +11,13 @@ export interface DataModel { } export interface UIData { - name: string + name: string | null 'auto-check-updates': boolean 'pkg-order': string[] - 'ack-welcome': string // EOS version - marketplace?: UIMarketplaceData - dev?: DevData - gaming?: { + 'ack-welcome': string // EOS emver + marketplace: UIMarketplaceData + dev: DevData + gaming: { snake: { 'high-score': number } diff --git a/frontend/projects/ui/src/app/util/get-marketplace.ts b/frontend/projects/ui/src/app/util/get-marketplace.ts index 05e6a05db..dd65c8839 100644 --- a/frontend/projects/ui/src/app/util/get-marketplace.ts +++ b/frontend/projects/ui/src/app/util/get-marketplace.ts @@ -8,15 +8,5 @@ import { firstValueFrom, map } from 'rxjs' export function getMarketplace( patch: PatchDB, ): Promise { - return firstValueFrom( - patch.watch$('ui', 'marketplace').pipe( - map( - m => - m || { - 'selected-id': null, - 'known-hosts': {}, - }, - ), - ), - ) + return firstValueFrom(patch.watch$('ui', 'marketplace')) }