新增图片画布项目页
新增 /project 项目页和我的页项目入口 补齐图片画布工程列表、重命名和删除 API 支持 /editor/canvas 按 projectid 加载指定工程 更新图片画布文档、TRACKING 和对应测试
This commit is contained in:
@@ -9,7 +9,8 @@ use serde_json::{Value, json};
|
||||
use shared_kernel::build_prefixed_uuid_id;
|
||||
use spacetime_client::{
|
||||
EditorCanvasRecord, EditorCanvasViewportRecord, EditorProjectCreateRecordInput,
|
||||
EditorProjectGetRecordInput, EditorProjectLayoutSaveRecordInput, EditorProjectRecord,
|
||||
EditorProjectDeleteRecordInput, EditorProjectGetRecordInput,
|
||||
EditorProjectLayoutSaveRecordInput, EditorProjectRecord, EditorProjectRenameRecordInput,
|
||||
EditorProjectResourceCreateRecordInput, EditorProjectResourceRecord, SpacetimeClientError,
|
||||
};
|
||||
|
||||
@@ -53,6 +54,12 @@ pub struct EditorProjectLayoutSaveRequest {
|
||||
layers: Value,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditorProjectRenameRequest {
|
||||
title: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditorProjectResourceCreateRequest {
|
||||
@@ -95,6 +102,18 @@ pub struct EditorProjectRecentResponse {
|
||||
project: Option<EditorProjectPayload>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditorProjectListResponse {
|
||||
projects: Vec<EditorProjectPayload>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditorProjectDeleteResponse {
|
||||
deleted_project_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct EditorProjectResourceResponse {
|
||||
@@ -179,6 +198,27 @@ pub async fn load_recent_editor_project(
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn list_editor_projects(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
) -> Result<Json<Value>, AppError> {
|
||||
let owner_user_id = authenticated.claims().user_id().to_string();
|
||||
let projects = state
|
||||
.spacetime_client()
|
||||
.list_editor_projects(owner_user_id)
|
||||
.await
|
||||
.map_err(map_editor_project_error)?
|
||||
.into_iter()
|
||||
.map(editor_project_payload_from_record)
|
||||
.collect();
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
EditorProjectListResponse { projects },
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn create_editor_project(
|
||||
State(state): State<AppState>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
@@ -261,6 +301,53 @@ pub async fn save_editor_project_layout(
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn rename_editor_project(
|
||||
State(state): State<AppState>,
|
||||
Path(project_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
Json(payload): Json<EditorProjectRenameRequest>,
|
||||
) -> Result<Json<Value>, AppError> {
|
||||
let project = state
|
||||
.spacetime_client()
|
||||
.rename_editor_project(EditorProjectRenameRecordInput {
|
||||
project_id,
|
||||
owner_user_id: authenticated.claims().user_id().to_string(),
|
||||
title: payload.title,
|
||||
updated_at_micros: current_utc_micros(),
|
||||
})
|
||||
.await
|
||||
.map_err(map_editor_project_error)?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
EditorProjectResponse {
|
||||
project: editor_project_payload_from_record(project),
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn delete_editor_project(
|
||||
State(state): State<AppState>,
|
||||
Path(project_id): Path<String>,
|
||||
Extension(request_context): Extension<RequestContext>,
|
||||
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
||||
) -> Result<Json<Value>, AppError> {
|
||||
let deleted_project_id = state
|
||||
.spacetime_client()
|
||||
.delete_editor_project(EditorProjectDeleteRecordInput {
|
||||
project_id,
|
||||
owner_user_id: authenticated.claims().user_id().to_string(),
|
||||
})
|
||||
.await
|
||||
.map_err(map_editor_project_error)?;
|
||||
|
||||
Ok(json_success_body(
|
||||
Some(&request_context),
|
||||
EditorProjectDeleteResponse { deleted_project_id },
|
||||
))
|
||||
}
|
||||
|
||||
pub async fn create_editor_project_resource(
|
||||
State(state): State<AppState>,
|
||||
Path(project_id): Path<String>,
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use axum::{
|
||||
Router, middleware,
|
||||
routing::{get, post},
|
||||
routing::{get, patch, post},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
auth::require_bearer_auth,
|
||||
editor_project::{
|
||||
create_editor_project, create_editor_project_resource, edit_editor_image,
|
||||
generate_editor_image, get_editor_project, load_recent_editor_project,
|
||||
save_editor_project_layout,
|
||||
create_editor_project, create_editor_project_resource, delete_editor_project,
|
||||
edit_editor_image, generate_editor_image, get_editor_project, list_editor_projects,
|
||||
load_recent_editor_project, rename_editor_project, save_editor_project_layout,
|
||||
},
|
||||
state::AppState,
|
||||
};
|
||||
@@ -24,20 +24,30 @@ pub fn router(state: AppState) -> Router<AppState> {
|
||||
)
|
||||
.route(
|
||||
"/api/editor/projects",
|
||||
post(create_editor_project).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
get(list_editor_projects)
|
||||
.post(create_editor_project)
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/editor/projects/{project_id}",
|
||||
get(get_editor_project)
|
||||
.patch(save_editor_project_layout)
|
||||
.delete(delete_editor_project)
|
||||
.route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/editor/projects/{project_id}/metadata",
|
||||
patch(rename_editor_project).route_layer(middleware::from_fn_with_state(
|
||||
state.clone(),
|
||||
require_bearer_auth,
|
||||
)),
|
||||
)
|
||||
.route(
|
||||
"/api/editor/projects/{project_id}/resources",
|
||||
post(create_editor_project_resource).route_layer(middleware::from_fn_with_state(
|
||||
|
||||
@@ -70,6 +70,75 @@ impl SpacetimeClient {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn list_editor_projects(
|
||||
&self,
|
||||
owner_user_id: String,
|
||||
) -> Result<Vec<EditorProjectRecord>, SpacetimeClientError> {
|
||||
let procedure_input = EditorProjectListInput { owner_user_id };
|
||||
|
||||
self.call_after_connect(
|
||||
"list_editor_projects_and_return",
|
||||
move |connection, sender| {
|
||||
connection.procedures().list_editor_projects_and_return_then(
|
||||
procedure_input,
|
||||
move |_, result| {
|
||||
let mapped = result
|
||||
.map_err(SpacetimeClientError::from_sdk_error)
|
||||
.and_then(map_editor_project_list_procedure_result);
|
||||
send_once(&sender, mapped);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn rename_editor_project(
|
||||
&self,
|
||||
input: EditorProjectRenameRecordInput,
|
||||
) -> Result<EditorProjectRecord, SpacetimeClientError> {
|
||||
let procedure_input = input.into();
|
||||
|
||||
self.call_after_connect(
|
||||
"rename_editor_project_and_return",
|
||||
move |connection, sender| {
|
||||
connection.procedures().rename_editor_project_and_return_then(
|
||||
procedure_input,
|
||||
move |_, result| {
|
||||
let mapped = result
|
||||
.map_err(SpacetimeClientError::from_sdk_error)
|
||||
.and_then(map_editor_project_required_procedure_result);
|
||||
send_once(&sender, mapped);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_editor_project(
|
||||
&self,
|
||||
input: EditorProjectDeleteRecordInput,
|
||||
) -> Result<String, SpacetimeClientError> {
|
||||
let procedure_input = input.into();
|
||||
|
||||
self.call_after_connect(
|
||||
"delete_editor_project_and_return",
|
||||
move |connection, sender| {
|
||||
connection.procedures().delete_editor_project_and_return_then(
|
||||
procedure_input,
|
||||
move |_, result| {
|
||||
let mapped = result
|
||||
.map_err(SpacetimeClientError::from_sdk_error)
|
||||
.and_then(map_editor_project_delete_procedure_result);
|
||||
send_once(&sender, mapped);
|
||||
},
|
||||
);
|
||||
},
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn save_editor_project_layout(
|
||||
&self,
|
||||
input: EditorProjectLayoutSaveRecordInput,
|
||||
|
||||
@@ -31,8 +31,9 @@ pub use mapper::{
|
||||
CustomWorldPublishWorldRecordInput, CustomWorldPublishedProfileCompileRecord,
|
||||
CustomWorldResultPreviewBlockerRecord, CustomWorldSupportedActionRecord,
|
||||
CustomWorldWorkSummaryRecord, EditorCanvasRecord, EditorCanvasViewportRecord,
|
||||
EditorProjectCreateRecordInput, EditorProjectGetRecordInput, EditorProjectLayoutSaveRecordInput,
|
||||
EditorProjectRecord, EditorProjectResourceCreateRecordInput, EditorProjectResourceRecord,
|
||||
EditorProjectCreateRecordInput, EditorProjectDeleteRecordInput, EditorProjectGetRecordInput,
|
||||
EditorProjectLayoutSaveRecordInput, EditorProjectRecord, EditorProjectRenameRecordInput,
|
||||
EditorProjectResourceCreateRecordInput, EditorProjectResourceRecord,
|
||||
ExternalGenerationJobClaimRecordInput,
|
||||
ExternalGenerationJobCompleteRecordInput, ExternalGenerationJobEnqueueRecordInput,
|
||||
ExternalGenerationJobFailRecordInput, ExternalGenerationJobGetRecordInput,
|
||||
|
||||
@@ -44,7 +44,8 @@ pub use self::combat::{
|
||||
};
|
||||
pub use self::editor_project::{
|
||||
EditorCanvasRecord, EditorCanvasViewportRecord, EditorProjectCreateRecordInput,
|
||||
EditorProjectGetRecordInput, EditorProjectLayoutSaveRecordInput, EditorProjectRecord,
|
||||
EditorProjectDeleteRecordInput, EditorProjectGetRecordInput,
|
||||
EditorProjectLayoutSaveRecordInput, EditorProjectRecord, EditorProjectRenameRecordInput,
|
||||
EditorProjectResourceCreateRecordInput, EditorProjectResourceRecord,
|
||||
};
|
||||
pub use self::common::{
|
||||
@@ -193,6 +194,7 @@ pub(crate) use self::custom_world::{
|
||||
parse_rpg_agent_stage_record,
|
||||
};
|
||||
pub(crate) use self::editor_project::{
|
||||
map_editor_project_delete_procedure_result, map_editor_project_list_procedure_result,
|
||||
map_editor_project_optional_procedure_result, map_editor_project_required_procedure_result,
|
||||
map_editor_project_resource_procedure_result,
|
||||
};
|
||||
|
||||
@@ -65,6 +65,20 @@ pub struct EditorProjectGetRecordInput {
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct EditorProjectRenameRecordInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub title: String,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct EditorProjectDeleteRecordInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct EditorProjectLayoutSaveRecordInput {
|
||||
pub project_id: String,
|
||||
@@ -114,6 +128,26 @@ impl From<EditorProjectGetRecordInput> for crate::module_bindings::EditorProject
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EditorProjectRenameRecordInput> for crate::module_bindings::EditorProjectRenameInput {
|
||||
fn from(input: EditorProjectRenameRecordInput) -> Self {
|
||||
Self {
|
||||
project_id: input.project_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
title: input.title,
|
||||
updated_at_micros: input.updated_at_micros,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EditorProjectDeleteRecordInput> for crate::module_bindings::EditorProjectDeleteInput {
|
||||
fn from(input: EditorProjectDeleteRecordInput) -> Self {
|
||||
Self {
|
||||
project_id: input.project_id,
|
||||
owner_user_id: input.owner_user_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<EditorProjectLayoutSaveRecordInput>
|
||||
for crate::module_bindings::EditorProjectLayoutSaveInput
|
||||
{
|
||||
@@ -174,6 +208,33 @@ pub(crate) fn map_editor_project_required_procedure_result(
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("图片画布工程快照"))
|
||||
}
|
||||
|
||||
pub(crate) fn map_editor_project_list_procedure_result(
|
||||
result: EditorProjectListProcedureResult,
|
||||
) -> Result<Vec<EditorProjectRecord>, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
result
|
||||
.projects
|
||||
.into_iter()
|
||||
.map(map_editor_project_snapshot)
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub(crate) fn map_editor_project_delete_procedure_result(
|
||||
result: EditorProjectDeleteProcedureResult,
|
||||
) -> Result<String, SpacetimeClientError> {
|
||||
if !result.ok {
|
||||
return Err(SpacetimeClientError::procedure_failed(result.error_message));
|
||||
}
|
||||
|
||||
result
|
||||
.deleted_project_id
|
||||
.filter(|project_id| !project_id.trim().is_empty())
|
||||
.ok_or_else(|| SpacetimeClientError::missing_snapshot("图片画布工程删除结果"))
|
||||
}
|
||||
|
||||
pub(crate) fn map_editor_project_resource_procedure_result(
|
||||
result: EditorProjectResourceProcedureResult,
|
||||
) -> Result<EditorProjectResourceRecord, SpacetimeClientError> {
|
||||
|
||||
@@ -338,6 +338,7 @@ pub mod delete_bark_battle_work_procedure;
|
||||
pub mod delete_big_fish_work_procedure;
|
||||
pub mod delete_custom_world_agent_session_procedure;
|
||||
pub mod delete_custom_world_profile_and_return_procedure;
|
||||
pub mod delete_editor_project_and_return_procedure;
|
||||
pub mod delete_jump_hop_work_procedure;
|
||||
pub mod delete_match_3_d_work_procedure;
|
||||
pub mod delete_puzzle_work_procedure;
|
||||
@@ -351,10 +352,15 @@ pub mod editor_canvas_snapshot_type;
|
||||
pub mod editor_canvas_table;
|
||||
pub mod editor_canvas_type;
|
||||
pub mod editor_project_create_input_type;
|
||||
pub mod editor_project_delete_input_type;
|
||||
pub mod editor_project_delete_procedure_result_type;
|
||||
pub mod editor_project_get_input_type;
|
||||
pub mod editor_project_get_recent_input_type;
|
||||
pub mod editor_project_layout_save_input_type;
|
||||
pub mod editor_project_list_input_type;
|
||||
pub mod editor_project_list_procedure_result_type;
|
||||
pub mod editor_project_procedure_result_type;
|
||||
pub mod editor_project_rename_input_type;
|
||||
pub mod editor_project_resource_create_input_type;
|
||||
pub mod editor_project_resource_procedure_result_type;
|
||||
pub mod editor_project_resource_snapshot_type;
|
||||
@@ -521,6 +527,7 @@ pub mod list_big_fish_works_procedure;
|
||||
pub mod list_custom_world_gallery_entries_procedure;
|
||||
pub mod list_custom_world_profiles_procedure;
|
||||
pub mod list_custom_world_works_procedure;
|
||||
pub mod list_editor_projects_and_return_procedure;
|
||||
pub mod list_jump_hop_works_procedure;
|
||||
pub mod list_match_3_d_works_procedure;
|
||||
pub mod list_platform_browse_history_procedure;
|
||||
@@ -817,6 +824,7 @@ pub mod release_puzzle_background_compile_task_procedure;
|
||||
pub mod remix_big_fish_work_procedure;
|
||||
pub mod remix_custom_world_profile_procedure;
|
||||
pub mod remix_puzzle_work_procedure;
|
||||
pub mod rename_editor_project_and_return_procedure;
|
||||
pub mod renew_external_generation_job_lease_and_return_procedure;
|
||||
pub mod resolve_combat_action_and_return_procedure;
|
||||
pub mod resolve_combat_action_input_type;
|
||||
@@ -1496,6 +1504,7 @@ pub use delete_bark_battle_work_procedure::delete_bark_battle_work;
|
||||
pub use delete_big_fish_work_procedure::delete_big_fish_work;
|
||||
pub use delete_custom_world_agent_session_procedure::delete_custom_world_agent_session;
|
||||
pub use delete_custom_world_profile_and_return_procedure::delete_custom_world_profile_and_return;
|
||||
pub use delete_editor_project_and_return_procedure::delete_editor_project_and_return;
|
||||
pub use delete_jump_hop_work_procedure::delete_jump_hop_work;
|
||||
pub use delete_match_3_d_work_procedure::delete_match_3_d_work;
|
||||
pub use delete_puzzle_work_procedure::delete_puzzle_work;
|
||||
@@ -1509,10 +1518,15 @@ pub use editor_canvas_snapshot_type::EditorCanvasSnapshot;
|
||||
pub use editor_canvas_table::*;
|
||||
pub use editor_canvas_type::EditorCanvas;
|
||||
pub use editor_project_create_input_type::EditorProjectCreateInput;
|
||||
pub use editor_project_delete_input_type::EditorProjectDeleteInput;
|
||||
pub use editor_project_delete_procedure_result_type::EditorProjectDeleteProcedureResult;
|
||||
pub use editor_project_get_input_type::EditorProjectGetInput;
|
||||
pub use editor_project_get_recent_input_type::EditorProjectGetRecentInput;
|
||||
pub use editor_project_layout_save_input_type::EditorProjectLayoutSaveInput;
|
||||
pub use editor_project_list_input_type::EditorProjectListInput;
|
||||
pub use editor_project_list_procedure_result_type::EditorProjectListProcedureResult;
|
||||
pub use editor_project_procedure_result_type::EditorProjectProcedureResult;
|
||||
pub use editor_project_rename_input_type::EditorProjectRenameInput;
|
||||
pub use editor_project_resource_create_input_type::EditorProjectResourceCreateInput;
|
||||
pub use editor_project_resource_procedure_result_type::EditorProjectResourceProcedureResult;
|
||||
pub use editor_project_resource_snapshot_type::EditorProjectResourceSnapshot;
|
||||
@@ -1679,6 +1693,7 @@ pub use list_big_fish_works_procedure::list_big_fish_works;
|
||||
pub use list_custom_world_gallery_entries_procedure::list_custom_world_gallery_entries;
|
||||
pub use list_custom_world_profiles_procedure::list_custom_world_profiles;
|
||||
pub use list_custom_world_works_procedure::list_custom_world_works;
|
||||
pub use list_editor_projects_and_return_procedure::list_editor_projects_and_return;
|
||||
pub use list_jump_hop_works_procedure::list_jump_hop_works;
|
||||
pub use list_match_3_d_works_procedure::list_match_3_d_works;
|
||||
pub use list_platform_browse_history_procedure::list_platform_browse_history;
|
||||
@@ -1975,6 +1990,7 @@ pub use release_puzzle_background_compile_task_procedure::release_puzzle_backgro
|
||||
pub use remix_big_fish_work_procedure::remix_big_fish_work;
|
||||
pub use remix_custom_world_profile_procedure::remix_custom_world_profile;
|
||||
pub use remix_puzzle_work_procedure::remix_puzzle_work;
|
||||
pub use rename_editor_project_and_return_procedure::rename_editor_project_and_return;
|
||||
pub use renew_external_generation_job_lease_and_return_procedure::renew_external_generation_job_lease_and_return;
|
||||
pub use resolve_combat_action_and_return_procedure::resolve_combat_action_and_return;
|
||||
pub use resolve_combat_action_input_type::ResolveCombatActionInput;
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
use super::editor_project_delete_input_type::EditorProjectDeleteInput;
|
||||
use super::editor_project_delete_procedure_result_type::EditorProjectDeleteProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct DeleteEditorProjectAndReturnArgs {
|
||||
pub input: EditorProjectDeleteInput,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for DeleteEditorProjectAndReturnArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `delete_editor_project_and_return`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait delete_editor_project_and_return {
|
||||
fn delete_editor_project_and_return(&self, input: EditorProjectDeleteInput) {
|
||||
self.delete_editor_project_and_return_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn delete_editor_project_and_return_then(
|
||||
&self,
|
||||
input: EditorProjectDeleteInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<EditorProjectDeleteProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl delete_editor_project_and_return for super::RemoteProcedures {
|
||||
fn delete_editor_project_and_return_then(
|
||||
&self,
|
||||
input: EditorProjectDeleteInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<EditorProjectDeleteProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
) {
|
||||
self.imp
|
||||
.invoke_procedure_with_callback::<_, EditorProjectDeleteProcedureResult>(
|
||||
"delete_editor_project_and_return",
|
||||
DeleteEditorProjectAndReturnArgs { input },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct EditorProjectDeleteInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for EditorProjectDeleteInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct EditorProjectDeleteProcedureResult {
|
||||
pub ok: bool,
|
||||
pub deleted_project_id: Option<String>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for EditorProjectDeleteProcedureResult {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct EditorProjectListInput {
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for EditorProjectListInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
use super::editor_project_snapshot_type::EditorProjectSnapshot;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct EditorProjectListProcedureResult {
|
||||
pub ok: bool,
|
||||
pub projects: Vec<EditorProjectSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for EditorProjectListProcedureResult {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
pub struct EditorProjectRenameInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub title: String,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for EditorProjectRenameInput {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
use super::editor_project_list_input_type::EditorProjectListInput;
|
||||
use super::editor_project_list_procedure_result_type::EditorProjectListProcedureResult;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct ListEditorProjectsAndReturnArgs {
|
||||
pub input: EditorProjectListInput,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for ListEditorProjectsAndReturnArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `list_editor_projects_and_return`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait list_editor_projects_and_return {
|
||||
fn list_editor_projects_and_return(&self, input: EditorProjectListInput) {
|
||||
self.list_editor_projects_and_return_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn list_editor_projects_and_return_then(
|
||||
&self,
|
||||
input: EditorProjectListInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<EditorProjectListProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl list_editor_projects_and_return for super::RemoteProcedures {
|
||||
fn list_editor_projects_and_return_then(
|
||||
&self,
|
||||
input: EditorProjectListInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<EditorProjectListProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
) {
|
||||
self.imp
|
||||
.invoke_procedure_with_callback::<_, EditorProjectListProcedureResult>(
|
||||
"list_editor_projects_and_return",
|
||||
ListEditorProjectsAndReturnArgs { input },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
// THIS FILE IS AUTOMATICALLY GENERATED BY SPACETIMEDB. EDITS TO THIS FILE
|
||||
// WILL NOT BE SAVED. MODIFY TABLES IN YOUR MODULE SOURCE CODE INSTEAD.
|
||||
|
||||
#![allow(unused, clippy::all)]
|
||||
use spacetimedb_sdk::__codegen::{self as __sdk, __lib, __sats, __ws};
|
||||
|
||||
use super::editor_project_procedure_result_type::EditorProjectProcedureResult;
|
||||
use super::editor_project_rename_input_type::EditorProjectRenameInput;
|
||||
|
||||
#[derive(__lib::ser::Serialize, __lib::de::Deserialize, Clone, PartialEq, Debug)]
|
||||
#[sats(crate = __lib)]
|
||||
struct RenameEditorProjectAndReturnArgs {
|
||||
pub input: EditorProjectRenameInput,
|
||||
}
|
||||
|
||||
impl __sdk::InModule for RenameEditorProjectAndReturnArgs {
|
||||
type Module = super::RemoteModule;
|
||||
}
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Extension trait for access to the procedure `rename_editor_project_and_return`.
|
||||
///
|
||||
/// Implemented for [`super::RemoteProcedures`].
|
||||
pub trait rename_editor_project_and_return {
|
||||
fn rename_editor_project_and_return(&self, input: EditorProjectRenameInput) {
|
||||
self.rename_editor_project_and_return_then(input, |_, _| {});
|
||||
}
|
||||
|
||||
fn rename_editor_project_and_return_then(
|
||||
&self,
|
||||
input: EditorProjectRenameInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<EditorProjectProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
);
|
||||
}
|
||||
|
||||
impl rename_editor_project_and_return for super::RemoteProcedures {
|
||||
fn rename_editor_project_and_return_then(
|
||||
&self,
|
||||
input: EditorProjectRenameInput,
|
||||
|
||||
__callback: impl FnOnce(
|
||||
&super::ProcedureEventContext,
|
||||
Result<EditorProjectProcedureResult, __sdk::InternalError>,
|
||||
) + Send
|
||||
+ 'static,
|
||||
) {
|
||||
self.imp
|
||||
.invoke_procedure_with_callback::<_, EditorProjectProcedureResult>(
|
||||
"rename_editor_project_and_return",
|
||||
RenameEditorProjectAndReturnArgs { input },
|
||||
__callback,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -94,6 +94,25 @@ pub struct EditorProjectGetRecentInput {
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct EditorProjectListInput {
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct EditorProjectRenameInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
pub title: String,
|
||||
pub updated_at_micros: i64,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct EditorProjectDeleteInput {
|
||||
pub project_id: String,
|
||||
pub owner_user_id: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct EditorProjectLayoutSaveInput {
|
||||
pub project_id: String,
|
||||
@@ -172,6 +191,20 @@ pub struct EditorProjectProcedureResult {
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct EditorProjectListProcedureResult {
|
||||
pub ok: bool,
|
||||
pub projects: Vec<EditorProjectSnapshot>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, SpacetimeType)]
|
||||
pub struct EditorProjectDeleteProcedureResult {
|
||||
pub ok: bool,
|
||||
pub deleted_project_id: Option<String>,
|
||||
pub error_message: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, SpacetimeType)]
|
||||
pub struct EditorProjectResourceProcedureResult {
|
||||
pub ok: bool,
|
||||
@@ -201,6 +234,25 @@ pub fn get_recent_editor_project_and_return(
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn list_editor_projects_and_return(
|
||||
ctx: &mut ProcedureContext,
|
||||
input: EditorProjectListInput,
|
||||
) -> EditorProjectListProcedureResult {
|
||||
match ctx.try_with_tx(|tx| list_editor_projects(tx, input.clone())) {
|
||||
Ok(projects) => EditorProjectListProcedureResult {
|
||||
ok: true,
|
||||
projects,
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => EditorProjectListProcedureResult {
|
||||
ok: false,
|
||||
projects: Vec::new(),
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn get_editor_project_and_return(
|
||||
ctx: &mut ProcedureContext,
|
||||
@@ -223,6 +275,36 @@ pub fn save_editor_project_layout_and_return(
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn rename_editor_project_and_return(
|
||||
ctx: &mut ProcedureContext,
|
||||
input: EditorProjectRenameInput,
|
||||
) -> EditorProjectProcedureResult {
|
||||
match ctx.try_with_tx(|tx| rename_editor_project(tx, input.clone())) {
|
||||
Ok(project) => editor_project_ok(Some(project)),
|
||||
Err(message) => editor_project_error(message),
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn delete_editor_project_and_return(
|
||||
ctx: &mut ProcedureContext,
|
||||
input: EditorProjectDeleteInput,
|
||||
) -> EditorProjectDeleteProcedureResult {
|
||||
match ctx.try_with_tx(|tx| delete_editor_project(tx, input.clone())) {
|
||||
Ok(project_id) => EditorProjectDeleteProcedureResult {
|
||||
ok: true,
|
||||
deleted_project_id: Some(project_id),
|
||||
error_message: None,
|
||||
},
|
||||
Err(message) => EditorProjectDeleteProcedureResult {
|
||||
ok: false,
|
||||
deleted_project_id: None,
|
||||
error_message: Some(message),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[spacetimedb::procedure]
|
||||
pub fn create_editor_project_resource_and_return(
|
||||
ctx: &mut ProcedureContext,
|
||||
@@ -309,6 +391,32 @@ fn get_recent_editor_project(
|
||||
.transpose()
|
||||
}
|
||||
|
||||
fn list_editor_projects(
|
||||
ctx: &ReducerContext,
|
||||
input: EditorProjectListInput,
|
||||
) -> Result<Vec<EditorProjectSnapshot>, String> {
|
||||
let owner_user_id = normalize_required(&input.owner_user_id, "editor_project.owner_user_id")?;
|
||||
let mut projects = ctx
|
||||
.db
|
||||
.editor_project()
|
||||
.by_editor_project_owner_user_id()
|
||||
.filter(&owner_user_id)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
projects.sort_by(|left, right| {
|
||||
right
|
||||
.updated_at
|
||||
.to_micros_since_unix_epoch()
|
||||
.cmp(&left.updated_at.to_micros_since_unix_epoch())
|
||||
.then_with(|| right.project_id.cmp(&left.project_id))
|
||||
});
|
||||
|
||||
projects
|
||||
.into_iter()
|
||||
.map(|project| build_project_snapshot(ctx, project.project_id.as_str()))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn get_editor_project(
|
||||
ctx: &ReducerContext,
|
||||
input: EditorProjectGetInput,
|
||||
@@ -319,6 +427,68 @@ fn get_editor_project(
|
||||
build_project_snapshot(ctx, project.project_id.as_str())
|
||||
}
|
||||
|
||||
fn rename_editor_project(
|
||||
ctx: &ReducerContext,
|
||||
input: EditorProjectRenameInput,
|
||||
) -> Result<EditorProjectSnapshot, String> {
|
||||
let project_id = normalize_required(&input.project_id, "editor_project.project_id")?;
|
||||
let owner_user_id = normalize_required(&input.owner_user_id, "editor_project.owner_user_id")?;
|
||||
let project = require_owned_project(ctx, project_id.as_str(), owner_user_id.as_str())?;
|
||||
let now = Timestamp::from_micros_since_unix_epoch(input.updated_at_micros);
|
||||
|
||||
ctx.db.editor_project().project_id().delete(&project_id);
|
||||
ctx.db.editor_project().insert(EditorProject {
|
||||
project_id: project.project_id.clone(),
|
||||
owner_user_id: project.owner_user_id,
|
||||
title: normalize_title(&input.title),
|
||||
viewport_x: project.viewport_x,
|
||||
viewport_y: project.viewport_y,
|
||||
viewport_scale: project.viewport_scale,
|
||||
layers_json: project.layers_json,
|
||||
created_at: project.created_at,
|
||||
updated_at: now,
|
||||
});
|
||||
|
||||
build_project_snapshot(ctx, project_id.as_str())
|
||||
}
|
||||
|
||||
fn delete_editor_project(
|
||||
ctx: &ReducerContext,
|
||||
input: EditorProjectDeleteInput,
|
||||
) -> Result<String, String> {
|
||||
let project_id = normalize_required(&input.project_id, "editor_project.project_id")?;
|
||||
let owner_user_id = normalize_required(&input.owner_user_id, "editor_project.owner_user_id")?;
|
||||
require_owned_project(ctx, project_id.as_str(), owner_user_id.as_str())?;
|
||||
let project_key = project_id.clone();
|
||||
let canvas_ids = ctx
|
||||
.db
|
||||
.editor_canvas()
|
||||
.by_editor_canvas_project_id()
|
||||
.filter(&project_key)
|
||||
.map(|canvas| canvas.canvas_id)
|
||||
.collect::<Vec<_>>();
|
||||
let resource_ids = ctx
|
||||
.db
|
||||
.editor_project_resource()
|
||||
.by_editor_project_resource_project_id()
|
||||
.filter(&project_key)
|
||||
.map(|resource| resource.resource_id)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for canvas_id in canvas_ids {
|
||||
ctx.db.editor_canvas().canvas_id().delete(&canvas_id);
|
||||
}
|
||||
for resource_id in resource_ids {
|
||||
ctx.db
|
||||
.editor_project_resource()
|
||||
.resource_id()
|
||||
.delete(&resource_id);
|
||||
}
|
||||
ctx.db.editor_project().project_id().delete(&project_id);
|
||||
|
||||
Ok(project_id)
|
||||
}
|
||||
|
||||
fn save_editor_project_layout(
|
||||
ctx: &ReducerContext,
|
||||
input: EditorProjectLayoutSaveInput,
|
||||
|
||||
Reference in New Issue
Block a user