diff --git a/Cargo.lock b/Cargo.lock
index aa08b5c..302cb77 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3414,6 +3414,7 @@ dependencies = [
"saleor-app-sdk",
"semver",
"serde",
+ "strum 0.26.2",
"surrealdb",
"thiserror",
"tokio",
@@ -3923,6 +3924,9 @@ name = "strum"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
+dependencies = [
+ "strum_macros 0.26.2",
+]
[[package]]
name = "strum_macros"
diff --git a/Cargo.toml b/Cargo.toml
index 3ed93ed..bf6b035 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,7 @@ serde = { version = "1.0.202", features = ["derive"] }
semver = { version = "1.0.23", features = ["serde"] }
saleor-app-sdk = { version = "0.2.3", default-features = false }
chrono = { version = "0.4.38", features = ["serde"] }
+strum = { version = "0.26.2", features = ["derive"] }
[features]
hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"]
diff --git a/db/000073.log b/db/000073.log
new file mode 100644
index 0000000..5743ec3
Binary files /dev/null and b/db/000073.log differ
diff --git a/db/000077.sst b/db/000077.sst
new file mode 100644
index 0000000..86dc836
Binary files /dev/null and b/db/000077.sst differ
diff --git a/db/CURRENT b/db/CURRENT
new file mode 100644
index 0000000..f8d57cc
--- /dev/null
+++ b/db/CURRENT
@@ -0,0 +1 @@
+MANIFEST-000074
diff --git a/db/IDENTITY b/db/IDENTITY
new file mode 100644
index 0000000..35f14cb
--- /dev/null
+++ b/db/IDENTITY
@@ -0,0 +1 @@
+b5f7ce4a-316f-4c07-b7bc-cd8d68a9439c
\ No newline at end of file
diff --git a/db/LOCK b/db/LOCK
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG b/db/LOG
new file mode 100644
index 0000000..ccc994d
--- /dev/null
+++ b/db/LOG
@@ -0,0 +1 @@
+2024/06/03-19:37:28.956980 624181 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717436248 acquiring thread 624180: db/LOCK: No locks available
diff --git a/db/LOG.old.1717435701378412 b/db/LOG.old.1717435701378412
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435706407552 b/db/LOG.old.1717435706407552
new file mode 100644
index 0000000..8f96461
--- /dev/null
+++ b/db/LOG.old.1717435706407552
@@ -0,0 +1 @@
+2024/06/03-19:28:21.378715 614548 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717435701 acquiring thread 614547: db/LOCK: No locks available
diff --git a/db/LOG.old.1717435706433232 b/db/LOG.old.1717435706433232
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435724748969 b/db/LOG.old.1717435724748969
new file mode 100644
index 0000000..ddd0fc6
--- /dev/null
+++ b/db/LOG.old.1717435724748969
@@ -0,0 +1 @@
+2024/06/03-19:28:26.433575 614548 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717435706 acquiring thread 614547: db/LOCK: No locks available
diff --git a/db/LOG.old.1717435729131921 b/db/LOG.old.1717435729131921
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435729162210 b/db/LOG.old.1717435729162210
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435750726033 b/db/LOG.old.1717435750726033
new file mode 100644
index 0000000..247f669
--- /dev/null
+++ b/db/LOG.old.1717435750726033
@@ -0,0 +1 @@
+2024/06/03-19:28:49.162709 615596 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717435729 acquiring thread 615595: db/LOCK: No locks available
diff --git a/db/LOG.old.1717435750753549 b/db/LOG.old.1717435750753549
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435798384726 b/db/LOG.old.1717435798384726
new file mode 100644
index 0000000..6c4fbd6
--- /dev/null
+++ b/db/LOG.old.1717435798384726
@@ -0,0 +1 @@
+2024/06/03-19:29:10.753898 616639 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717435750 acquiring thread 616638: db/LOCK: No locks available
diff --git a/db/LOG.old.1717435798416760 b/db/LOG.old.1717435798416760
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435802312556 b/db/LOG.old.1717435802312556
new file mode 100644
index 0000000..66f5ef1
--- /dev/null
+++ b/db/LOG.old.1717435802312556
@@ -0,0 +1 @@
+2024/06/03-19:29:58.417187 617450 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717435798 acquiring thread 617449: db/LOCK: No locks available
diff --git a/db/LOG.old.1717435946446866 b/db/LOG.old.1717435946446866
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435946481362 b/db/LOG.old.1717435946481362
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717435984147165 b/db/LOG.old.1717435984147165
new file mode 100644
index 0000000..5d61e58
--- /dev/null
+++ b/db/LOG.old.1717435984147165
@@ -0,0 +1 @@
+2024/06/03-19:32:26.481702 619379 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717435946 acquiring thread 619378: db/LOCK: No locks available
diff --git a/db/LOG.old.1717435984174324 b/db/LOG.old.1717435984174324
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717436222135051 b/db/LOG.old.1717436222135051
new file mode 100644
index 0000000..8cd5df4
--- /dev/null
+++ b/db/LOG.old.1717436222135051
@@ -0,0 +1 @@
+2024/06/03-19:33:04.174695 620857 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717435984 acquiring thread 620856: db/LOCK: No locks available
diff --git a/db/LOG.old.1717436222174269 b/db/LOG.old.1717436222174269
new file mode 100644
index 0000000..e69de29
diff --git a/db/LOG.old.1717436248932389 b/db/LOG.old.1717436248932389
new file mode 100644
index 0000000..8898568
--- /dev/null
+++ b/db/LOG.old.1717436248932389
@@ -0,0 +1 @@
+2024/06/03-19:37:02.174732 623193 [WARN] [db/db_impl/db_impl_open.cc:2074] DB::Open() failed: IO error: lock hold by current process, acquire time 1717436222 acquiring thread 623192: db/LOCK: No locks available
diff --git a/db/LOG.old.1717436248956615 b/db/LOG.old.1717436248956615
new file mode 100644
index 0000000..e69de29
diff --git a/db/MANIFEST-000074 b/db/MANIFEST-000074
new file mode 100644
index 0000000..11ca6f4
Binary files /dev/null and b/db/MANIFEST-000074 differ
diff --git a/db/OPTIONS-000071 b/db/OPTIONS-000071
new file mode 100644
index 0000000..8f0fb8c
--- /dev/null
+++ b/db/OPTIONS-000071
@@ -0,0 +1,199 @@
+# This is a RocksDB option file.
+#
+# For detailed file format spec, please refer to the example file
+# in examples/rocksdb_option_file_example.ini
+#
+
+[Version]
+ rocksdb_version=8.1.1
+ options_file_version=1.1
+
+[DBOptions]
+ compaction_readahead_size=0
+ strict_bytes_per_sync=false
+ bytes_per_sync=0
+ max_background_jobs=16
+ avoid_flush_during_shutdown=false
+ max_background_flushes=-1
+ delayed_write_rate=16777216
+ max_open_files=-1
+ max_subcompactions=1
+ writable_file_max_buffer_size=1048576
+ wal_bytes_per_sync=0
+ max_background_compactions=-1
+ max_total_wal_size=0
+ delete_obsolete_files_period_micros=21600000000
+ stats_dump_period_sec=600
+ stats_history_buffer_size=1048576
+ stats_persist_period_sec=600
+ enforce_single_del_contracts=true
+ lowest_used_cache_tier=kNonVolatileBlockTier
+ bgerror_resume_retry_interval=1000000
+ best_efforts_recovery=false
+ log_readahead_size=0
+ write_dbid_to_manifest=false
+ wal_compression=kNoCompression
+ manual_wal_flush=false
+ db_host_id=__hostname__
+ two_write_queues=false
+ random_access_max_buffer_size=1048576
+ avoid_unnecessary_blocking_io=false
+ skip_checking_sst_file_sizes_on_db_open=false
+ flush_verify_memtable_count=true
+ fail_if_options_file_error=false
+ atomic_flush=false
+ verify_sst_unique_id_in_manifest=true
+ skip_stats_update_on_db_open=false
+ track_and_verify_wals_in_manifest=false
+ paranoid_checks=true
+ create_if_missing=true
+ max_write_batch_group_size_bytes=1048576
+ avoid_flush_during_recovery=false
+ file_checksum_gen_factory=nullptr
+ enable_thread_tracking=false
+ allow_fallocate=true
+ allow_data_in_errors=false
+ error_if_exists=false
+ use_direct_io_for_flush_and_compaction=false
+ create_missing_column_families=true
+ WAL_size_limit_MB=0
+ use_direct_reads=false
+ persist_stats_to_disk=false
+ allow_mmap_reads=false
+ allow_mmap_writes=false
+ use_adaptive_mutex=false
+ allow_2pc=false
+ is_fd_close_on_exec=true
+ max_log_file_size=0
+ access_hint_on_compaction_start=NORMAL
+ max_file_opening_threads=16
+ wal_filter=nullptr
+ use_fsync=false
+ table_cache_numshardbits=6
+ dump_malloc_stats=false
+ db_write_buffer_size=0
+ allow_ingest_behind=false
+ keep_log_file_num=20
+ max_bgerror_resume_count=2147483647
+ allow_concurrent_memtable_write=true
+ recycle_log_file_num=0
+ log_file_time_to_roll=0
+ manifest_preallocation_size=4194304
+ enable_write_thread_adaptive_yield=true
+ WAL_ttl_seconds=0
+ max_manifest_file_size=1073741824
+ wal_recovery_mode=kPointInTimeRecovery
+ enable_pipelined_write=true
+ write_thread_slow_yield_usec=3
+ unordered_write=false
+ write_thread_max_yield_usec=100
+ advise_random_on_open=true
+ info_log_level=WARN_LEVEL
+
+
+[CFOptions "default"]
+ compression_opts={max_dict_buffer_bytes=0;enabled=false;max_dict_bytes=0;parallel_threads=1;zstd_max_train_bytes=0;level=32767;use_zstd_dict_trainer=true;strategy=0;window_bits=-14;}
+ memtable_protection_bytes_per_key=0
+ target_file_size_multiplier=1
+ report_bg_io_stats=false
+ write_buffer_size=268435456
+ memtable_huge_page_size=0
+ max_successive_merges=0
+ max_write_buffer_number=32
+ prefix_extractor=nullptr
+ bottommost_compression_opts={max_dict_buffer_bytes=0;enabled=false;max_dict_bytes=0;parallel_threads=1;zstd_max_train_bytes=0;level=32767;use_zstd_dict_trainer=true;strategy=0;window_bits=-14;}
+ paranoid_file_checks=false
+ blob_garbage_collection_force_threshold=1.000000
+ enable_blob_files=true
+ blob_file_starting_level=0
+ memtable_prefix_bloom_size_ratio=0.000000
+ inplace_update_num_locks=10000
+ blob_compaction_readahead_size=0
+ ignore_max_compaction_bytes_for_input=true
+ arena_block_size=1048576
+ level0_stop_writes_trigger=36
+ blob_compression_type=kNoCompression
+ level0_slowdown_writes_trigger=20
+ hard_pending_compaction_bytes_limit=274877906944
+ soft_pending_compaction_bytes_limit=68719476736
+ target_file_size_base=536870912
+ level0_file_num_compaction_trigger=4
+ max_compaction_bytes=13421772800
+ disable_auto_compactions=false
+ check_flush_compaction_key_order=true
+ min_blob_size=4096
+ memtable_whole_key_filtering=false
+ max_bytes_for_level_base=268435456
+ last_level_temperature=kUnknown
+ compaction_options_fifo={allow_compaction=false;age_for_warm=0;max_table_files_size=1073741824;}
+ max_bytes_for_level_multiplier=10.000000
+ compression_per_level=kNoCompression:kNoCompression:kLZ4HCCompression:kLZ4HCCompression:kLZ4HCCompression
+ max_bytes_for_level_multiplier_additional=1:1:1:1:1:1:1
+ max_sequential_skip_in_iterations=8
+ prepopulate_blob_cache=kDisable
+ compression=kSnappyCompression
+ compaction_options_universal={incremental=false;compression_size_percent=-1;allow_trivial_move=false;max_size_amplification_percent=200;max_merge_width=4294967295;stop_style=kCompactionStopStyleTotalSize;min_merge_width=2;size_ratio=1;}
+ blob_garbage_collection_age_cutoff=0.250000
+ ttl=2592000
+ periodic_compaction_seconds=0
+ sample_for_compression=0
+ blob_file_size=268435456
+ enable_blob_garbage_collection=false
+ experimental_mempurge_threshold=0.000000
+ bottommost_compression=kDisableCompressionOption
+ min_write_buffer_number_to_merge=4
+ preserve_internal_time_seconds=0
+ preclude_last_level_data_seconds=0
+ sst_partitioner_factory=nullptr
+ num_levels=7
+ force_consistency_checks=true
+ memtable_insert_with_hint_prefix_extractor=nullptr
+ memtable_factory=SkipListFactory
+ level_compaction_dynamic_file_size=true
+ max_write_buffer_number_to_maintain=0
+ optimize_filters_for_hits=false
+ level_compaction_dynamic_level_bytes=false
+ compaction_style=kCompactionStyleLevel
+ compaction_filter=nullptr
+ inplace_update_support=false
+ merge_operator=nullptr
+ table_factory=BlockBasedTable
+ bloom_locality=0
+ comparator=leveldb.BytewiseComparator
+ compaction_filter_factory=nullptr
+ max_write_buffer_size_to_maintain=8589934592
+ compaction_pri=kMinOverlappingRatio
+
+[TableOptions/BlockBasedTable "default"]
+ initial_auto_readahead_size=8192
+ pin_top_level_index_and_filter=true
+ block_align=false
+ block_size_deviation=10
+ checksum=kXXH3
+ index_shortening=kShortenSeparators
+ num_file_reads_for_auto_readahead=2
+ whole_key_filtering=true
+ data_block_index_type=kDataBlockBinarySearch
+ index_type=kBinarySearch
+ no_block_cache=false
+ index_block_restart_interval=1
+ data_block_hash_table_util_ratio=0.750000
+ prepopulate_block_cache=kDisable
+ pin_l0_filter_and_index_blocks_in_cache=false
+ filter_policy=nullptr
+ cache_index_and_filter_blocks_with_high_priority=true
+ verify_compression=false
+ block_restart_interval=16
+ max_auto_readahead_size=262144
+ flush_block_policy_factory=FlushBlockBySizePolicyFactory
+ partition_filters=false
+ cache_index_and_filter_blocks=false
+ block_size=4096
+ metadata_block_size=4096
+ optimize_filters_for_memory=false
+ detect_filter_construct_corruption=false
+ format_version=5
+ metadata_cache_options={unpartitioned_pinning=kFallback;partition_pinning=kFallback;top_level_index_pinning=kFallback;}
+ read_amp_bytes_per_bit=0
+ enable_index_compression=true
+
diff --git a/db/OPTIONS-000076 b/db/OPTIONS-000076
new file mode 100644
index 0000000..8f0fb8c
--- /dev/null
+++ b/db/OPTIONS-000076
@@ -0,0 +1,199 @@
+# This is a RocksDB option file.
+#
+# For detailed file format spec, please refer to the example file
+# in examples/rocksdb_option_file_example.ini
+#
+
+[Version]
+ rocksdb_version=8.1.1
+ options_file_version=1.1
+
+[DBOptions]
+ compaction_readahead_size=0
+ strict_bytes_per_sync=false
+ bytes_per_sync=0
+ max_background_jobs=16
+ avoid_flush_during_shutdown=false
+ max_background_flushes=-1
+ delayed_write_rate=16777216
+ max_open_files=-1
+ max_subcompactions=1
+ writable_file_max_buffer_size=1048576
+ wal_bytes_per_sync=0
+ max_background_compactions=-1
+ max_total_wal_size=0
+ delete_obsolete_files_period_micros=21600000000
+ stats_dump_period_sec=600
+ stats_history_buffer_size=1048576
+ stats_persist_period_sec=600
+ enforce_single_del_contracts=true
+ lowest_used_cache_tier=kNonVolatileBlockTier
+ bgerror_resume_retry_interval=1000000
+ best_efforts_recovery=false
+ log_readahead_size=0
+ write_dbid_to_manifest=false
+ wal_compression=kNoCompression
+ manual_wal_flush=false
+ db_host_id=__hostname__
+ two_write_queues=false
+ random_access_max_buffer_size=1048576
+ avoid_unnecessary_blocking_io=false
+ skip_checking_sst_file_sizes_on_db_open=false
+ flush_verify_memtable_count=true
+ fail_if_options_file_error=false
+ atomic_flush=false
+ verify_sst_unique_id_in_manifest=true
+ skip_stats_update_on_db_open=false
+ track_and_verify_wals_in_manifest=false
+ paranoid_checks=true
+ create_if_missing=true
+ max_write_batch_group_size_bytes=1048576
+ avoid_flush_during_recovery=false
+ file_checksum_gen_factory=nullptr
+ enable_thread_tracking=false
+ allow_fallocate=true
+ allow_data_in_errors=false
+ error_if_exists=false
+ use_direct_io_for_flush_and_compaction=false
+ create_missing_column_families=true
+ WAL_size_limit_MB=0
+ use_direct_reads=false
+ persist_stats_to_disk=false
+ allow_mmap_reads=false
+ allow_mmap_writes=false
+ use_adaptive_mutex=false
+ allow_2pc=false
+ is_fd_close_on_exec=true
+ max_log_file_size=0
+ access_hint_on_compaction_start=NORMAL
+ max_file_opening_threads=16
+ wal_filter=nullptr
+ use_fsync=false
+ table_cache_numshardbits=6
+ dump_malloc_stats=false
+ db_write_buffer_size=0
+ allow_ingest_behind=false
+ keep_log_file_num=20
+ max_bgerror_resume_count=2147483647
+ allow_concurrent_memtable_write=true
+ recycle_log_file_num=0
+ log_file_time_to_roll=0
+ manifest_preallocation_size=4194304
+ enable_write_thread_adaptive_yield=true
+ WAL_ttl_seconds=0
+ max_manifest_file_size=1073741824
+ wal_recovery_mode=kPointInTimeRecovery
+ enable_pipelined_write=true
+ write_thread_slow_yield_usec=3
+ unordered_write=false
+ write_thread_max_yield_usec=100
+ advise_random_on_open=true
+ info_log_level=WARN_LEVEL
+
+
+[CFOptions "default"]
+ compression_opts={max_dict_buffer_bytes=0;enabled=false;max_dict_bytes=0;parallel_threads=1;zstd_max_train_bytes=0;level=32767;use_zstd_dict_trainer=true;strategy=0;window_bits=-14;}
+ memtable_protection_bytes_per_key=0
+ target_file_size_multiplier=1
+ report_bg_io_stats=false
+ write_buffer_size=268435456
+ memtable_huge_page_size=0
+ max_successive_merges=0
+ max_write_buffer_number=32
+ prefix_extractor=nullptr
+ bottommost_compression_opts={max_dict_buffer_bytes=0;enabled=false;max_dict_bytes=0;parallel_threads=1;zstd_max_train_bytes=0;level=32767;use_zstd_dict_trainer=true;strategy=0;window_bits=-14;}
+ paranoid_file_checks=false
+ blob_garbage_collection_force_threshold=1.000000
+ enable_blob_files=true
+ blob_file_starting_level=0
+ memtable_prefix_bloom_size_ratio=0.000000
+ inplace_update_num_locks=10000
+ blob_compaction_readahead_size=0
+ ignore_max_compaction_bytes_for_input=true
+ arena_block_size=1048576
+ level0_stop_writes_trigger=36
+ blob_compression_type=kNoCompression
+ level0_slowdown_writes_trigger=20
+ hard_pending_compaction_bytes_limit=274877906944
+ soft_pending_compaction_bytes_limit=68719476736
+ target_file_size_base=536870912
+ level0_file_num_compaction_trigger=4
+ max_compaction_bytes=13421772800
+ disable_auto_compactions=false
+ check_flush_compaction_key_order=true
+ min_blob_size=4096
+ memtable_whole_key_filtering=false
+ max_bytes_for_level_base=268435456
+ last_level_temperature=kUnknown
+ compaction_options_fifo={allow_compaction=false;age_for_warm=0;max_table_files_size=1073741824;}
+ max_bytes_for_level_multiplier=10.000000
+ compression_per_level=kNoCompression:kNoCompression:kLZ4HCCompression:kLZ4HCCompression:kLZ4HCCompression
+ max_bytes_for_level_multiplier_additional=1:1:1:1:1:1:1
+ max_sequential_skip_in_iterations=8
+ prepopulate_blob_cache=kDisable
+ compression=kSnappyCompression
+ compaction_options_universal={incremental=false;compression_size_percent=-1;allow_trivial_move=false;max_size_amplification_percent=200;max_merge_width=4294967295;stop_style=kCompactionStopStyleTotalSize;min_merge_width=2;size_ratio=1;}
+ blob_garbage_collection_age_cutoff=0.250000
+ ttl=2592000
+ periodic_compaction_seconds=0
+ sample_for_compression=0
+ blob_file_size=268435456
+ enable_blob_garbage_collection=false
+ experimental_mempurge_threshold=0.000000
+ bottommost_compression=kDisableCompressionOption
+ min_write_buffer_number_to_merge=4
+ preserve_internal_time_seconds=0
+ preclude_last_level_data_seconds=0
+ sst_partitioner_factory=nullptr
+ num_levels=7
+ force_consistency_checks=true
+ memtable_insert_with_hint_prefix_extractor=nullptr
+ memtable_factory=SkipListFactory
+ level_compaction_dynamic_file_size=true
+ max_write_buffer_number_to_maintain=0
+ optimize_filters_for_hits=false
+ level_compaction_dynamic_level_bytes=false
+ compaction_style=kCompactionStyleLevel
+ compaction_filter=nullptr
+ inplace_update_support=false
+ merge_operator=nullptr
+ table_factory=BlockBasedTable
+ bloom_locality=0
+ comparator=leveldb.BytewiseComparator
+ compaction_filter_factory=nullptr
+ max_write_buffer_size_to_maintain=8589934592
+ compaction_pri=kMinOverlappingRatio
+
+[TableOptions/BlockBasedTable "default"]
+ initial_auto_readahead_size=8192
+ pin_top_level_index_and_filter=true
+ block_align=false
+ block_size_deviation=10
+ checksum=kXXH3
+ index_shortening=kShortenSeparators
+ num_file_reads_for_auto_readahead=2
+ whole_key_filtering=true
+ data_block_index_type=kDataBlockBinarySearch
+ index_type=kBinarySearch
+ no_block_cache=false
+ index_block_restart_interval=1
+ data_block_hash_table_util_ratio=0.750000
+ prepopulate_block_cache=kDisable
+ pin_l0_filter_and_index_blocks_in_cache=false
+ filter_policy=nullptr
+ cache_index_and_filter_blocks_with_high_priority=true
+ verify_compression=false
+ block_restart_interval=16
+ max_auto_readahead_size=262144
+ flush_block_policy_factory=FlushBlockBySizePolicyFactory
+ partition_filters=false
+ cache_index_and_filter_blocks=false
+ block_size=4096
+ metadata_block_size=4096
+ optimize_filters_for_memory=false
+ detect_filter_construct_corruption=false
+ format_version=5
+ metadata_cache_options={unpartitioned_pinning=kFallback;partition_pinning=kFallback;top_level_index_pinning=kFallback;}
+ read_amp_bytes_per_bit=0
+ enable_index_compression=true
+
diff --git a/src/app.rs b/src/app.rs
index 9724dd0..1fd67b2 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -1,10 +1,17 @@
+use crate::components::header::Header;
use crate::error_template::{AppError, ErrorTemplate};
-use crate::server::types::SaleorApp;
-
+use crate::routes::apps::Apps;
+use crate::routes::guides::Guides;
+use crate::routes::home::Home;
use leptos::*;
use leptos_meta::*;
use leptos_router::*;
+#[derive(Params, PartialEq)]
+pub struct UrlAppParams {
+ slug: String,
+}
+
#[component]
pub fn App() -> impl IntoView {
// Provides context that manages stylesheets, titles, meta tags, etc.
@@ -14,43 +21,25 @@ pub fn App() -> impl IntoView {
// sets the document title
-
+
+
// content for this welcome page
}.into_view()
}>
-
+
-
+
+
+
+
+
+
}
}
-
-#[server]
-pub async fn get_all_apps() -> Result, ServerFnError>{
- let conn = crate::server::db::connect()?;
- let res = conn.query("SELECT * FROM saleor_app WHERE saleor_app.name ='Sitemap generator' ");
- dbg!(&res);
- _ = res.await;
- Err(ServerFnError::new("rip"))
-}
-
-/// Renders the home page of your application.
-#[component]
-fn HomePage() -> impl IntoView {
- let apps = create_resource(|| (), |_| async move {get_all_apps().await});
- view! {
- "Welcome to Leptos!"
- {move || match apps.get() {
- Some(_d) => view! { "loaded smt"
}.into_view(),
- None => view! { "loading..."
}.into_view(),
- }}
-
-
- }
-}
diff --git a/src/components/app_list.rs b/src/components/app_list.rs
new file mode 100644
index 0000000..c4b97ca
--- /dev/null
+++ b/src/components/app_list.rs
@@ -0,0 +1,40 @@
+use leptos::*;
+
+use crate::server::functions::get_all_apps;
+
+
+#[component]
+pub fn app_list() -> impl IntoView {
+ let apps = create_resource(|| (), |_| async move {get_all_apps().await});
+ view! {
+ "Welcome to Leptos!"
+ "Loading..." }
+ }>
+ {move || {
+ apps.get()
+ .map(|apps| {
+ match apps {
+ Ok(apps) => {
+ view! {
+
+
+ {apps
+ .into_iter()
+ .map(|app| view! { - {app.name}
})
+ .collect_view()}
+
+ }
+ .into_view()
+ }
+ Err(e) => {
+ view! { "Failed fetching apps, " {e.to_string()}
}
+ .into_view()
+ }
+ }
+ })
+ }}
+
+
+ }
+}
diff --git a/src/components/header.rs b/src/components/header.rs
new file mode 100644
index 0000000..923b83b
--- /dev/null
+++ b/src/components/header.rs
@@ -0,0 +1,42 @@
+use crate::components::search::Search;
+use leptos::*;
+
+#[component]
+pub fn Header() -> impl IntoView {
+ view! {
+
+ }
+}
diff --git a/src/components/mod.rs b/src/components/mod.rs
new file mode 100644
index 0000000..1ad4a86
--- /dev/null
+++ b/src/components/mod.rs
@@ -0,0 +1,4 @@
+pub mod app_list;
+pub mod header;
+pub mod search;
+pub mod universal;
diff --git a/src/components/search.rs b/src/components/search.rs
new file mode 100644
index 0000000..fb375b1
--- /dev/null
+++ b/src/components/search.rs
@@ -0,0 +1,33 @@
+use crate::components::universal::text_line::TextLine;
+use leptos::*;
+
+#[component]
+pub fn Search() -> impl IntoView {
+ let (search_text, search_text_setter) = create_signal("".to_string());
+ view! {
+
+
+ //
+
+
+ // {#if products}
+ //
+ // {/if}
+
+ }
+}
diff --git a/src/components/universal/app_editor.rs b/src/components/universal/app_editor.rs
new file mode 100644
index 0000000..b4bf0a7
--- /dev/null
+++ b/src/components/universal/app_editor.rs
@@ -0,0 +1,91 @@
+use leptos::*;
+use strum::IntoEnumIterator;
+
+use crate::server::types::{AppCategory, DeploymentType};
+
+#[component]
+pub fn app_editor() -> impl IntoView {
+ let name = create_node_ref();
+ let slug = create_node_ref();
+ let authors = create_node_ref();
+ let built_for_url = create_node_ref();
+ let description = create_node_ref();
+ let version = create_node_ref();
+ let images = create_node_ref();
+ let logo = create_node_ref();
+ let manifest = create_node_ref();
+ let supported_deployments = create_node_ref();
+ let category = create_node_ref();
+ let docker_compose = create_node_ref();
+
+ view! {
+
+ }
+}
diff --git a/src/components/universal/mod.rs b/src/components/universal/mod.rs
new file mode 100644
index 0000000..59a55b6
--- /dev/null
+++ b/src/components/universal/mod.rs
@@ -0,0 +1,2 @@
+pub mod app_editor;
+pub mod text_line;
diff --git a/src/components/universal/text_line.rs b/src/components/universal/text_line.rs
new file mode 100644
index 0000000..a52abf6
--- /dev/null
+++ b/src/components/universal/text_line.rs
@@ -0,0 +1,32 @@
+use leptos::*;
+
+#[component]
+pub fn TextLine(
+ title: &'static str,
+ required: bool,
+ value_setter: WriteSignal,
+) -> impl IntoView {
+ view! {
+
+
+
+
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index dbcbb70..32befb0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,6 +3,8 @@ pub mod error_template;
#[cfg(feature = "ssr")]
pub mod fileserv;
+pub mod components;
+pub mod routes;
pub mod server;
#[cfg(feature = "hydrate")]
diff --git a/src/main.rs b/src/main.rs
index 43ea6e6..7d84e3b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,6 @@
pub mod server;
+pub mod components;
+pub mod routes;
#[cfg(feature = "ssr")]
#[tokio::main]
diff --git a/src/routes/apps/create.rs b/src/routes/apps/create.rs
new file mode 100644
index 0000000..a777b7f
--- /dev/null
+++ b/src/routes/apps/create.rs
@@ -0,0 +1,6 @@
+use leptos::*;
+
+#[component]
+pub fn Create() -> impl IntoView {
+ view! {}
+}
diff --git a/src/routes/apps/mod.rs b/src/routes/apps/mod.rs
new file mode 100644
index 0000000..30eb5c3
--- /dev/null
+++ b/src/routes/apps/mod.rs
@@ -0,0 +1,7 @@
+pub mod create;
+pub mod update;
+
+use leptos::*;
+
+#[component]
+pub fn Apps() -> impl IntoView {}
diff --git a/src/routes/apps/update.rs b/src/routes/apps/update.rs
new file mode 100644
index 0000000..e69de29
diff --git a/src/routes/guides.rs b/src/routes/guides.rs
new file mode 100644
index 0000000..4bd5392
--- /dev/null
+++ b/src/routes/guides.rs
@@ -0,0 +1,4 @@
+use leptos::*;
+
+#[component]
+pub fn Guides() -> impl IntoView {}
diff --git a/src/routes/home.rs b/src/routes/home.rs
new file mode 100644
index 0000000..b8f23f4
--- /dev/null
+++ b/src/routes/home.rs
@@ -0,0 +1,11 @@
+use leptos::*;
+
+#[component]
+pub fn Home() -> impl IntoView {
+ view! {
+ Saleor community Harbour
+
+ Crafted fer ye to muster yer wits an all the booty an wisdom ye may be needin fer yer next voyage.
+
+ }
+}
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
new file mode 100644
index 0000000..016b0dc
--- /dev/null
+++ b/src/routes/mod.rs
@@ -0,0 +1,3 @@
+pub mod apps;
+pub mod guides;
+pub mod home;
diff --git a/src/server/db.rs b/src/server/db.rs
index 7f1bd0a..cf4d975 100644
--- a/src/server/db.rs
+++ b/src/server/db.rs
@@ -1,56 +1,51 @@
-use std::path::PathBuf;
-
-use saleor_app_sdk::manifest::AppManifest;
use serde::Deserialize;
use surrealdb::engine::local::Db;
use surrealdb::engine::local::RocksDb;
use surrealdb::sql::Thing;
use surrealdb::Surreal;
-use super::types::SaleorApp;
-
#[derive(Debug, Deserialize)]
struct Record {
#[allow(dead_code)]
id: Thing,
}
-#[tokio::main]
pub async fn connect() -> surrealdb::Result> {
// Create database connection
- let db = Surreal::new::("/db").await?;
+ let db = Surreal::new::("./db").await?;
// Select a specific namespace / database
db.use_ns("marketplace").use_db("apps").await?;
- let demo_data: Vec = db.create("saleor_app").content(SaleorApp{
- name: "Sitemap generator".to_owned(),
- logo: PathBuf::new(),
- images: vec![PathBuf::new()],
- authors: vec![],
- versions: vec![semver::Version::parse( "2.1.1").unwrap()],
- description: "Sitemap stuff".to_owned(),
- is_verified: true,
- last_updated: chrono::Local::now().into(),
- built_for_url: None,
- supported_apls: vec![],
- supported_deployments: vec![],
- minimal_docker_compose: "".to_owned(),
- manifest: AppManifest{
- name: "Sitemap generator".to_owned(),
- id: "hihihaha".to_owned(),
- about: None,
- brand: None,
- author: None,
- version: "2.1.1".to_owned(),
- app_url: "localhost:3000".to_owned(),
- token_target_url: "localhost:3000".to_owned(),
- ..Default::default()
- }
- }).await?;
+ // let demo_data: Vec = db.create("saleor_app").content(SaleorApp{
+ // name: "Sitemap generator".to_owned(),
+ // logo: PathBuf::new(),
+ // images: vec![PathBuf::new()],
+ // authors: vec![],
+ // versions: vec![semver::Version::parse( "2.1.1").unwrap()],
+ // description: "Sitemap stuff".to_owned(),
+ // is_verified: true,
+ // last_updated: chrono::Local::now().into(),
+ // built_for_url: None,
+ // supported_apls: vec![],
+ // supported_deployments: vec![],
+ // minimal_docker_compose: "".to_owned(),
+ // manifest: AppManifest{
+ // name: "Sitemap generator".to_owned(),
+ // id: "hihihaha".to_owned(),
+ // about: None,
+ // brand: None,
+ // author: None,
+ // version: "2.1.1".to_owned(),
+ // app_url: "localhost:3000".to_owned(),
+ // token_target_url: "localhost:3000".to_owned(),
+ // ..Default::default()
+ // }
+ // }).await?;
+
+ // dbg!(demo_data);
- dbg!(demo_data);
// // Create a new person with a random id
// let created: Vec = db
// .create("person")
diff --git a/src/server/functions.rs b/src/server/functions.rs
new file mode 100644
index 0000000..b345320
--- /dev/null
+++ b/src/server/functions.rs
@@ -0,0 +1,16 @@
+use leptos::*;
+
+use super::types::SaleorApp;
+
+#[server]
+pub async fn get_all_apps() -> Result, ServerFnError>{
+ let conn = crate::server::db::connect().await?;
+ let mut res = conn.query("SELECT * FROM saleor_app").await?;
+
+ let apps :Vec = res.take(0)?;
+ // dbg!(&apps);
+ Ok(apps)
+}
+
+
+
diff --git a/src/server/mod.rs b/src/server/mod.rs
index 02e9f16..4425323 100644
--- a/src/server/mod.rs
+++ b/src/server/mod.rs
@@ -1,4 +1,5 @@
#[cfg(feature = "ssr")]
pub mod db;
+pub mod functions;
pub mod types;
diff --git a/src/server/types.rs b/src/server/types.rs
index 07a24e4..f52e7fb 100644
--- a/src/server/types.rs
+++ b/src/server/types.rs
@@ -8,9 +8,11 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct SaleorApp {
pub name: String,
+ pub slug: String,
pub authors: Vec,
pub description: String,
pub versions: Vec,
+ pub curr_version: Version,
/**
All files will target ./public/app_data//
*/
@@ -33,9 +35,12 @@ pub struct SaleorApp {
pub minimal_docker_compose: String,
pub supported_apls: Vec,
pub last_updated: chrono::DateTime,
+ pub categories: Vec,
}
-#[derive(Debug, Serialize, PartialEq, Deserialize, Clone)]
+#[derive(
+ Debug, Serialize, PartialEq, Deserialize, Clone, strum::EnumIter, strum::IntoStaticStr,
+)]
pub enum DeploymentType {
Docker,
Podman,
@@ -54,3 +59,20 @@ pub struct AppAuthor {
#[derive(Debug, Serialize, PartialEq, Deserialize, Clone)]
pub struct CustomAplType(String);
+
+#[derive(
+ Debug, Serialize, PartialEq, Deserialize, Clone, strum::EnumIter, strum::IntoStaticStr,
+)]
+pub enum AppCategory {
+ CMS,
+ Messaging,
+ Taxes,
+ Payments,
+ CRM,
+ Monitoring,
+ Marketplaces,
+ Search,
+ SEO,
+ DashboardUtilities,
+ Other,
+}
diff --git a/style/base.css b/style/base.css
index a0b3509..175f94e 100644
--- a/style/base.css
+++ b/style/base.css
@@ -1,5 +1,78 @@
-@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700;1,900&display=swap');
-@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital@0;1&display=swap');
+@import url("https://fonts.googleapis.com/css2?family=PT+Serif:ital,wght@0,400;0,700;1,400;1,700&family=Space+Grotesk:wght@300..700&display=swap");
+
@tailwind base;
@tailwind components;
@tailwind utilities;
+
+@layer base {
+ body {
+ @apply bg-brand-white;
+ }
+
+ html {
+ @apply text-brand-black;
+ }
+
+ ::selection {
+ @apply bg-brand-sunset-400;
+ }
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ @apply font-sans my-4 text-brand-sea-300 text-2xl;
+ }
+
+ h2 {
+ @apply text-brand-sea-300 text-xl;
+ }
+
+ h3,
+ h4,
+ h5,
+ h6 {
+ @apply text-brand-sea-500 text-base;
+ }
+
+ p {
+ @apply font-serif my-2 text-base;
+ }
+
+ input:disabled,
+ button:disabled {
+ @apply brightness-50 cursor-not-allowed;
+ }
+
+ details,
+ summary {
+ @apply list-none;
+ }
+
+ input:focus,
+ input:active,
+ option:focus,
+ option:active {
+ @apply !outline-none !appearance-none !select-none shadow-none !border-none;
+ -webkit-tap-highlight-color: transparent;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -khtml-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ }
+}
+
+@layer components {
+ .header-gradient {
+ background: theme("colors.brand-sea.400");
+ background: linear-gradient(25deg,
+ theme("colors.brand-sunset.500") 0%,
+ theme("colors.brand-sea.300") 45%,
+ theme("colors.brand-sea.300") 55%,
+ theme("colors.brand-sunset.500") 100%);
+ }
+}
diff --git a/tailwind.config.js b/tailwind.config.js
index 9d923f1..bad3a9a 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -3,6 +3,55 @@ module.exports = {
content: {
files: ["*.html", "./src/**/*.rs"],
},
- theme: {},
+ theme: {
+ fontFamily: {
+ sans: ["Space Grotesk", "sans-serif"],
+ serif: ["PT Serif", "serif"],
+ },
+ fontSize: {
+ xs: "0.75rem",
+ sm: "0.875rem",
+ base: "0.875rem",
+ "base-sans": "1rem",
+ lg: "1.125rem",
+ xl: "1.5rem",
+ "2xl": "2rem",
+ },
+ borderRadius: {
+ base: "0.5rem",
+ sm: "0.25rem",
+ xs: "0.156rem",
+ lg: "1rem",
+ xl: "2rem",
+ max: "999999px",
+ },
+ extend: {
+ colors: {
+ "brand-sea": {
+ 100: "#C5ECE0",
+ 200: "#17C3B2",
+ 300: "#1DA0A8",
+ 400: "#227C9D",
+ 500: "#094074",
+ },
+ "brand-sunset": {
+ 100: "#FEF9EF",
+ 200: "#FFEED1",
+ 300: "#FFE2B3",
+ 400: "#FFD795",
+ 500: "#FFCB77",
+ },
+ "brand-red": {
+ 100: "#FED6D0",
+ 200: "#FEB3B1",
+ 300: "#FE9092",
+ 400: "#FE7F83",
+ 500: "#FE6D73",
+ },
+ "brand-black": "#161a1e",
+ "brand-white": "#fbfbfb",
+ },
+ },
+ },
plugins: [],
-}
+};