delete multiple view in one request

This commit is contained in:
appflowy 2021-10-15 13:42:52 +08:00
parent bcaa942dfc
commit dfd6046214
17 changed files with 138 additions and 143 deletions

View File

@ -11,17 +11,17 @@ import 'package:protobuf/protobuf.dart' as $pb;
class DeleteViewRequest extends $pb.GeneratedMessage { class DeleteViewRequest extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteViewRequest', createEmptyInstance: create) static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteViewRequest', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') ..pPS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewIds')
..hasRequiredFields = false ..hasRequiredFields = false
; ;
DeleteViewRequest._() : super(); DeleteViewRequest._() : super();
factory DeleteViewRequest({ factory DeleteViewRequest({
$core.String? viewId, $core.Iterable<$core.String>? viewIds,
}) { }) {
final _result = create(); final _result = create();
if (viewId != null) { if (viewIds != null) {
_result.viewId = viewId; _result.viewIds.addAll(viewIds);
} }
return _result; return _result;
} }
@ -47,28 +47,22 @@ class DeleteViewRequest extends $pb.GeneratedMessage {
static DeleteViewRequest? _defaultInstance; static DeleteViewRequest? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.String get viewId => $_getSZ(0); $core.List<$core.String> get viewIds => $_getList(0);
@$pb.TagNumber(1)
set viewId($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasViewId() => $_has(0);
@$pb.TagNumber(1)
void clearViewId() => clearField(1);
} }
class DeleteViewParams extends $pb.GeneratedMessage { class DeleteViewParams extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteViewParams', createEmptyInstance: create) static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'DeleteViewParams', createEmptyInstance: create)
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') ..pPS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewIds')
..hasRequiredFields = false ..hasRequiredFields = false
; ;
DeleteViewParams._() : super(); DeleteViewParams._() : super();
factory DeleteViewParams({ factory DeleteViewParams({
$core.String? viewId, $core.Iterable<$core.String>? viewIds,
}) { }) {
final _result = create(); final _result = create();
if (viewId != null) { if (viewIds != null) {
_result.viewId = viewId; _result.viewIds.addAll(viewIds);
} }
return _result; return _result;
} }
@ -94,12 +88,6 @@ class DeleteViewParams extends $pb.GeneratedMessage {
static DeleteViewParams? _defaultInstance; static DeleteViewParams? _defaultInstance;
@$pb.TagNumber(1) @$pb.TagNumber(1)
$core.String get viewId => $_getSZ(0); $core.List<$core.String> get viewIds => $_getList(0);
@$pb.TagNumber(1)
set viewId($core.String v) { $_setString(0, v); }
@$pb.TagNumber(1)
$core.bool hasViewId() => $_has(0);
@$pb.TagNumber(1)
void clearViewId() => clearField(1);
} }

View File

@ -12,19 +12,19 @@ import 'dart:typed_data' as $typed_data;
const DeleteViewRequest$json = const { const DeleteViewRequest$json = const {
'1': 'DeleteViewRequest', '1': 'DeleteViewRequest',
'2': const [ '2': const [
const {'1': 'view_id', '3': 1, '4': 1, '5': 9, '10': 'viewId'}, const {'1': 'view_ids', '3': 1, '4': 3, '5': 9, '10': 'viewIds'},
], ],
}; };
/// Descriptor for `DeleteViewRequest`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `DeleteViewRequest`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List deleteViewRequestDescriptor = $convert.base64Decode('ChFEZWxldGVWaWV3UmVxdWVzdBIXCgd2aWV3X2lkGAEgASgJUgZ2aWV3SWQ='); final $typed_data.Uint8List deleteViewRequestDescriptor = $convert.base64Decode('ChFEZWxldGVWaWV3UmVxdWVzdBIZCgh2aWV3X2lkcxgBIAMoCVIHdmlld0lkcw==');
@$core.Deprecated('Use deleteViewParamsDescriptor instead') @$core.Deprecated('Use deleteViewParamsDescriptor instead')
const DeleteViewParams$json = const { const DeleteViewParams$json = const {
'1': 'DeleteViewParams', '1': 'DeleteViewParams',
'2': const [ '2': const [
const {'1': 'view_id', '3': 1, '4': 1, '5': 9, '10': 'viewId'}, const {'1': 'view_ids', '3': 1, '4': 3, '5': 9, '10': 'viewIds'},
], ],
}; };
/// Descriptor for `DeleteViewParams`. Decode as a `google.protobuf.DescriptorProto`. /// Descriptor for `DeleteViewParams`. Decode as a `google.protobuf.DescriptorProto`.
final $typed_data.Uint8List deleteViewParamsDescriptor = $convert.base64Decode('ChBEZWxldGVWaWV3UGFyYW1zEhcKB3ZpZXdfaWQYASABKAlSBnZpZXdJZA=='); final $typed_data.Uint8List deleteViewParamsDescriptor = $convert.base64Decode('ChBEZWxldGVWaWV3UGFyYW1zEhkKCHZpZXdfaWRzGAEgAygJUgd2aWV3SWRz');

View File

@ -10,7 +10,7 @@ use flowy_workspace::protobuf::{CreateViewParams, DeleteViewParams, QueryViewPar
use crate::service::{ use crate::service::{
doc::doc::DocBiz, doc::doc::DocBiz,
util::parse_from_payload, util::parse_from_payload,
view::{create_view, delete_view, read_view, update_view}, view::{create_view, delete_views, read_view, update_view},
}; };
use std::sync::Arc; use std::sync::Arc;
@ -42,6 +42,6 @@ pub async fn update_handler(payload: Payload, pool: Data<PgPool>) -> Result<Http
pub async fn delete_handler(payload: Payload, pool: Data<PgPool>) -> Result<HttpResponse, ServerError> { pub async fn delete_handler(payload: Payload, pool: Data<PgPool>) -> Result<HttpResponse, ServerError> {
let params: DeleteViewParams = parse_from_payload(payload).await?; let params: DeleteViewParams = parse_from_payload(payload).await?;
let resp = delete_view(pool.get_ref(), &params.view_id).await?; let resp = delete_views(pool.get_ref(), params.view_ids.into_vec()).await?;
Ok(resp.into()) Ok(resp.into())
} }

View File

@ -74,8 +74,12 @@ impl NewViewSqlBuilder {
} }
} }
pub(crate) fn check_view_id(id: String) -> Result<Uuid, ServerError> { pub(crate) fn check_view_ids(ids: Vec<String>) -> Result<Vec<Uuid>, ServerError> {
let view_id = ViewId::parse(id).map_err(invalid_params)?; let mut view_ids = vec![];
let view_id = Uuid::parse_str(view_id.as_ref())?; for id in ids {
Ok(view_id) let view_id = ViewId::parse(id).map_err(invalid_params)?;
let view_id = Uuid::parse_str(view_id.as_ref())?;
view_ids.push(view_id);
}
Ok(view_ids)
} }

View File

@ -74,7 +74,7 @@ pub(crate) async fn read_view(
params: QueryViewParams, params: QueryViewParams,
_doc_biz: Data<Arc<DocBiz>>, _doc_biz: Data<Arc<DocBiz>>,
) -> Result<FlowyResponse, ServerError> { ) -> Result<FlowyResponse, ServerError> {
let view_id = check_view_id(params.view_id)?; let view_id = check_view_ids(vec![params.view_id])?.pop().unwrap();
let mut transaction = pool let mut transaction = pool
.begin() .begin()
.await .await
@ -111,7 +111,7 @@ pub(crate) async fn read_view(
} }
pub(crate) async fn update_view(pool: &PgPool, params: UpdateViewParams) -> Result<FlowyResponse, ServerError> { pub(crate) async fn update_view(pool: &PgPool, params: UpdateViewParams) -> Result<FlowyResponse, ServerError> {
let view_id = check_view_id(params.view_id.clone())?; let view_id = check_view_ids(vec![params.view_id.clone()])?.pop().unwrap();
let name = match params.has_name() { let name = match params.has_name() {
false => None, false => None,
@ -159,21 +159,22 @@ pub(crate) async fn update_view(pool: &PgPool, params: UpdateViewParams) -> Resu
Ok(FlowyResponse::success()) Ok(FlowyResponse::success())
} }
pub(crate) async fn delete_view(pool: &PgPool, view_id: &str) -> Result<FlowyResponse, ServerError> { pub(crate) async fn delete_views(pool: &PgPool, view_ids: Vec<String>) -> Result<FlowyResponse, ServerError> {
let view_id = check_view_id(view_id.to_owned())?; let view_ids = check_view_ids(view_ids)?;
let mut transaction = pool let mut transaction = pool
.begin() .begin()
.await .await
.context("Failed to acquire a Postgres connection to delete view")?; .context("Failed to acquire a Postgres connection to delete view")?;
let (sql, args) = SqlBuilder::delete(VIEW_TABLE).and_where_eq("id", &view_id).build()?; for view_id in view_ids {
let (sql, args) = SqlBuilder::delete(VIEW_TABLE).and_where_eq("id", &view_id).build()?;
let _ = sqlx::query_with(&sql, args)
.execute(&mut transaction)
.await
.map_err(map_sqlx_error)?;
let _ = sqlx::query_with(&sql, args) let _ = delete_doc(&mut transaction, view_id).await?;
.execute(&mut transaction) }
.await
.map_err(map_sqlx_error)?;
let _ = delete_doc(&mut transaction, view_id).await?;
transaction transaction
.commit() .commit()

View File

@ -18,7 +18,7 @@ async fn doc_read() {
async fn doc_delete() { async fn doc_delete() {
let test = ViewTest::new().await; let test = ViewTest::new().await;
let delete_params = DeleteViewParams { let delete_params = DeleteViewParams {
view_id: test.view.id.clone(), view_ids: vec![test.view.id.clone()],
}; };
test.server.delete_view(delete_params).await; test.server.delete_view(delete_params).await;

View File

@ -157,7 +157,7 @@ async fn view_delete() {
let test = ViewTest::new().await; let test = ViewTest::new().await;
// delete // delete
let delete_params = DeleteViewParams { let delete_params = DeleteViewParams {
view_id: test.view.id.clone(), view_ids: vec![test.view.id.clone()],
}; };
test.server.delete_view(delete_params).await; test.server.delete_view(delete_params).await;

View File

@ -80,3 +80,7 @@ pub struct QueryDocParams {
#[pb(index = 1)] #[pb(index = 1)]
pub doc_id: String, pub doc_id: String,
} }
impl std::convert::From<String> for QueryDocParams {
fn from(doc_id: String) -> Self { QueryDocParams { doc_id } }
}

View File

@ -1,4 +1,4 @@
use crate::{errors::WorkspaceError, impl_def_and_def_mut}; use crate::{impl_def_and_def_mut};
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use std::convert::TryInto; use std::convert::TryInto;

View File

@ -1,32 +1,33 @@
use crate::{entities::view::parser::ViewId, errors::WorkspaceError}; use crate::{entities::view::parser::ViewId, errors::WorkspaceError};
use flowy_derive::ProtoBuf; use flowy_derive::ProtoBuf;
use flowy_document::entities::doc::QueryDocParams;
use std::convert::TryInto; use std::convert::TryInto;
#[derive(Default, ProtoBuf)] #[derive(Default, ProtoBuf)]
pub struct DeleteViewRequest { pub struct DeleteViewRequest {
#[pb(index = 1)] #[pb(index = 1)]
view_id: String, view_ids: Vec<String>,
} }
#[derive(Default, ProtoBuf)] #[derive(Default, ProtoBuf)]
pub struct DeleteViewParams { pub struct DeleteViewParams {
#[pb(index = 1)] #[pb(index = 1)]
pub view_id: String, pub view_ids: Vec<String>,
} }
impl TryInto<DeleteViewParams> for DeleteViewRequest { impl TryInto<DeleteViewParams> for DeleteViewRequest {
type Error = WorkspaceError; type Error = WorkspaceError;
fn try_into(self) -> Result<DeleteViewParams, Self::Error> { fn try_into(self) -> Result<DeleteViewParams, Self::Error> {
let view_id = ViewId::parse(self.view_id) let mut view_ids = vec![];
.map_err(|e| WorkspaceError::view_id().context(e))? for view_id in self.view_ids {
.0; let view_id = ViewId::parse(view_id)
.map_err(|e| WorkspaceError::view_id().context(e))?
.0;
Ok(DeleteViewParams { view_id }) view_ids.push(view_id);
}
Ok(DeleteViewParams { view_ids })
} }
} }
impl std::convert::Into<QueryDocParams> for DeleteViewParams {
fn into(self) -> QueryDocParams { QueryDocParams { doc_id: self.view_id } }
}

View File

@ -1,13 +1,12 @@
use crate::{ use crate::{
entities::{ entities::{
trash::{RepeatedTrash, TrashIdentifier}, trash::{RepeatedTrash, TrashIdentifier},
view::RepeatedView,
}, },
errors::WorkspaceError, errors::WorkspaceError,
services::TrashCan, services::TrashCan,
}; };
use flowy_dispatch::prelude::{data_result, Data, DataResult, Unit}; use flowy_dispatch::prelude::{data_result, Data, DataResult, Unit};
use std::{convert::TryInto, sync::Arc}; use std::{sync::Arc};
#[tracing::instrument(skip(controller), err)] #[tracing::instrument(skip(controller), err)]
pub(crate) async fn read_trash_handler(controller: Unit<Arc<TrashCan>>) -> DataResult<RepeatedTrash, WorkspaceError> { pub(crate) async fn read_trash_handler(controller: Unit<Arc<TrashCan>>) -> DataResult<RepeatedTrash, WorkspaceError> {

View File

@ -26,7 +26,7 @@
#[derive(PartialEq,Clone,Default)] #[derive(PartialEq,Clone,Default)]
pub struct DeleteViewRequest { pub struct DeleteViewRequest {
// message fields // message fields
pub view_id: ::std::string::String, pub view_ids: ::protobuf::RepeatedField<::std::string::String>,
// special fields // special fields
pub unknown_fields: ::protobuf::UnknownFields, pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize, pub cached_size: ::protobuf::CachedSize,
@ -43,30 +43,29 @@ impl DeleteViewRequest {
::std::default::Default::default() ::std::default::Default::default()
} }
// string view_id = 1; // repeated string view_ids = 1;
pub fn get_view_id(&self) -> &str { pub fn get_view_ids(&self) -> &[::std::string::String] {
&self.view_id &self.view_ids
} }
pub fn clear_view_id(&mut self) { pub fn clear_view_ids(&mut self) {
self.view_id.clear(); self.view_ids.clear();
} }
// Param is passed by value, moved // Param is passed by value, moved
pub fn set_view_id(&mut self, v: ::std::string::String) { pub fn set_view_ids(&mut self, v: ::protobuf::RepeatedField<::std::string::String>) {
self.view_id = v; self.view_ids = v;
} }
// Mutable pointer to the field. // Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first. pub fn mut_view_ids(&mut self) -> &mut ::protobuf::RepeatedField<::std::string::String> {
pub fn mut_view_id(&mut self) -> &mut ::std::string::String { &mut self.view_ids
&mut self.view_id
} }
// Take field // Take field
pub fn take_view_id(&mut self) -> ::std::string::String { pub fn take_view_ids(&mut self) -> ::protobuf::RepeatedField<::std::string::String> {
::std::mem::replace(&mut self.view_id, ::std::string::String::new()) ::std::mem::replace(&mut self.view_ids, ::protobuf::RepeatedField::new())
} }
} }
@ -80,7 +79,7 @@ impl ::protobuf::Message for DeleteViewRequest {
let (field_number, wire_type) = is.read_tag_unpack()?; let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number { match field_number {
1 => { 1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?; ::protobuf::rt::read_repeated_string_into(wire_type, is, &mut self.view_ids)?;
}, },
_ => { _ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@ -94,18 +93,18 @@ impl ::protobuf::Message for DeleteViewRequest {
#[allow(unused_variables)] #[allow(unused_variables)]
fn compute_size(&self) -> u32 { fn compute_size(&self) -> u32 {
let mut my_size = 0; let mut my_size = 0;
if !self.view_id.is_empty() { for value in &self.view_ids {
my_size += ::protobuf::rt::string_size(1, &self.view_id); my_size += ::protobuf::rt::string_size(1, &value);
} };
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size); self.cached_size.set(my_size);
my_size my_size
} }
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.view_id.is_empty() { for v in &self.view_ids {
os.write_string(1, &self.view_id)?; os.write_string(1, &v)?;
} };
os.write_unknown_fields(self.get_unknown_fields())?; os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(()) ::std::result::Result::Ok(())
} }
@ -144,10 +143,10 @@ impl ::protobuf::Message for DeleteViewRequest {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| { descriptor.get(|| {
let mut fields = ::std::vec::Vec::new(); let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"view_id", "view_ids",
|m: &DeleteViewRequest| { &m.view_id }, |m: &DeleteViewRequest| { &m.view_ids },
|m: &mut DeleteViewRequest| { &mut m.view_id }, |m: &mut DeleteViewRequest| { &mut m.view_ids },
)); ));
::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteViewRequest>( ::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteViewRequest>(
"DeleteViewRequest", "DeleteViewRequest",
@ -165,7 +164,7 @@ impl ::protobuf::Message for DeleteViewRequest {
impl ::protobuf::Clear for DeleteViewRequest { impl ::protobuf::Clear for DeleteViewRequest {
fn clear(&mut self) { fn clear(&mut self) {
self.view_id.clear(); self.view_ids.clear();
self.unknown_fields.clear(); self.unknown_fields.clear();
} }
} }
@ -185,7 +184,7 @@ impl ::protobuf::reflect::ProtobufValue for DeleteViewRequest {
#[derive(PartialEq,Clone,Default)] #[derive(PartialEq,Clone,Default)]
pub struct DeleteViewParams { pub struct DeleteViewParams {
// message fields // message fields
pub view_id: ::std::string::String, pub view_ids: ::protobuf::RepeatedField<::std::string::String>,
// special fields // special fields
pub unknown_fields: ::protobuf::UnknownFields, pub unknown_fields: ::protobuf::UnknownFields,
pub cached_size: ::protobuf::CachedSize, pub cached_size: ::protobuf::CachedSize,
@ -202,30 +201,29 @@ impl DeleteViewParams {
::std::default::Default::default() ::std::default::Default::default()
} }
// string view_id = 1; // repeated string view_ids = 1;
pub fn get_view_id(&self) -> &str { pub fn get_view_ids(&self) -> &[::std::string::String] {
&self.view_id &self.view_ids
} }
pub fn clear_view_id(&mut self) { pub fn clear_view_ids(&mut self) {
self.view_id.clear(); self.view_ids.clear();
} }
// Param is passed by value, moved // Param is passed by value, moved
pub fn set_view_id(&mut self, v: ::std::string::String) { pub fn set_view_ids(&mut self, v: ::protobuf::RepeatedField<::std::string::String>) {
self.view_id = v; self.view_ids = v;
} }
// Mutable pointer to the field. // Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first. pub fn mut_view_ids(&mut self) -> &mut ::protobuf::RepeatedField<::std::string::String> {
pub fn mut_view_id(&mut self) -> &mut ::std::string::String { &mut self.view_ids
&mut self.view_id
} }
// Take field // Take field
pub fn take_view_id(&mut self) -> ::std::string::String { pub fn take_view_ids(&mut self) -> ::protobuf::RepeatedField<::std::string::String> {
::std::mem::replace(&mut self.view_id, ::std::string::String::new()) ::std::mem::replace(&mut self.view_ids, ::protobuf::RepeatedField::new())
} }
} }
@ -239,7 +237,7 @@ impl ::protobuf::Message for DeleteViewParams {
let (field_number, wire_type) = is.read_tag_unpack()?; let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number { match field_number {
1 => { 1 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?; ::protobuf::rt::read_repeated_string_into(wire_type, is, &mut self.view_ids)?;
}, },
_ => { _ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
@ -253,18 +251,18 @@ impl ::protobuf::Message for DeleteViewParams {
#[allow(unused_variables)] #[allow(unused_variables)]
fn compute_size(&self) -> u32 { fn compute_size(&self) -> u32 {
let mut my_size = 0; let mut my_size = 0;
if !self.view_id.is_empty() { for value in &self.view_ids {
my_size += ::protobuf::rt::string_size(1, &self.view_id); my_size += ::protobuf::rt::string_size(1, &value);
} };
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size); self.cached_size.set(my_size);
my_size my_size
} }
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
if !self.view_id.is_empty() { for v in &self.view_ids {
os.write_string(1, &self.view_id)?; os.write_string(1, &v)?;
} };
os.write_unknown_fields(self.get_unknown_fields())?; os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(()) ::std::result::Result::Ok(())
} }
@ -303,10 +301,10 @@ impl ::protobuf::Message for DeleteViewParams {
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
descriptor.get(|| { descriptor.get(|| {
let mut fields = ::std::vec::Vec::new(); let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"view_id", "view_ids",
|m: &DeleteViewParams| { &m.view_id }, |m: &DeleteViewParams| { &m.view_ids },
|m: &mut DeleteViewParams| { &mut m.view_id }, |m: &mut DeleteViewParams| { &mut m.view_ids },
)); ));
::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteViewParams>( ::protobuf::reflect::MessageDescriptor::new_pb_name::<DeleteViewParams>(
"DeleteViewParams", "DeleteViewParams",
@ -324,7 +322,7 @@ impl ::protobuf::Message for DeleteViewParams {
impl ::protobuf::Clear for DeleteViewParams { impl ::protobuf::Clear for DeleteViewParams {
fn clear(&mut self) { fn clear(&mut self) {
self.view_id.clear(); self.view_ids.clear();
self.unknown_fields.clear(); self.unknown_fields.clear();
} }
} }
@ -342,18 +340,19 @@ impl ::protobuf::reflect::ProtobufValue for DeleteViewParams {
} }
static file_descriptor_proto_data: &'static [u8] = b"\ static file_descriptor_proto_data: &'static [u8] = b"\
\n\x11view_delete.proto\",\n\x11DeleteViewRequest\x12\x17\n\x07view_id\ \n\x11view_delete.proto\".\n\x11DeleteViewRequest\x12\x19\n\x08view_ids\
\x18\x01\x20\x01(\tR\x06viewId\"+\n\x10DeleteViewParams\x12\x17\n\x07vie\ \x18\x01\x20\x03(\tR\x07viewIds\"-\n\x10DeleteViewParams\x12\x19\n\x08vi\
w_id\x18\x01\x20\x01(\tR\x06viewIdJ\xb0\x01\n\x06\x12\x04\0\0\x07\x01\n\ ew_ids\x18\x01\x20\x03(\tR\x07viewIdsJ\xcc\x01\n\x06\x12\x04\0\0\x07\x01\
\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\n\ \n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x04\x01\n\
\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\ \n\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\x04\x04\0\x02\0\x12\x03\
\x04\x17\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\ \x03\x04!\n\x0c\n\x05\x04\0\x02\0\x04\x12\x03\x03\x04\x0c\n\x0c\n\x05\
\x02\0\x01\x12\x03\x03\x0b\x12\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\ \x04\0\x02\0\x05\x12\x03\x03\r\x13\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\
\x15\x16\n\n\n\x02\x04\x01\x12\x04\x05\0\x07\x01\n\n\n\x03\x04\x01\x01\ \x03\x14\x1c\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x1f\x20\n\n\n\x02\
\x12\x03\x05\x08\x18\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\x04\x17\n\x0c\ \x04\x01\x12\x04\x05\0\x07\x01\n\n\n\x03\x04\x01\x01\x12\x03\x05\x08\x18\
\n\x05\x04\x01\x02\0\x05\x12\x03\x06\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\ \n\x0b\n\x04\x04\x01\x02\0\x12\x03\x06\x04!\n\x0c\n\x05\x04\x01\x02\0\
\x12\x03\x06\x0b\x12\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\x06\x15\x16b\ \x04\x12\x03\x06\x04\x0c\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\x06\r\x13\
\x06proto3\ \n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x06\x14\x1c\n\x0c\n\x05\x04\x01\
\x02\0\x03\x12\x03\x06\x1f\x20b\x06proto3\
"; ";
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

View File

@ -1,8 +1,8 @@
syntax = "proto3"; syntax = "proto3";
message DeleteViewRequest { message DeleteViewRequest {
string view_id = 1; repeated string view_ids = 1;
} }
message DeleteViewParams { message DeleteViewParams {
string view_id = 1; repeated string view_ids = 1;
} }

View File

@ -6,8 +6,8 @@ use crate::{
sql_tables::trash::{TrashSource, TrashTable, TrashTableSql}, sql_tables::trash::{TrashSource, TrashTable, TrashTableSql},
}; };
use flowy_database::SqliteConnection; use flowy_database::SqliteConnection;
use parking_lot::RwLock;
use std::{collections::HashSet, sync::Arc}; use std::{sync::Arc};
use tokio::sync::{broadcast, mpsc}; use tokio::sync::{broadcast, mpsc};
#[derive(Clone)] #[derive(Clone)]

View File

@ -9,7 +9,6 @@ use crate::{
use crate::{ use crate::{
entities::{ entities::{
trash::Trash,
view::{DeleteViewParams, QueryViewParams, RepeatedView}, view::{DeleteViewParams, QueryViewParams, RepeatedView},
}, },
errors::internal_error, errors::internal_error,
@ -25,9 +24,9 @@ use flowy_document::{
}; };
use crate::errors::WorkspaceResult; use crate::errors::WorkspaceResult;
use futures::{future, FutureExt, StreamExt, TryStreamExt}; use futures::{FutureExt, StreamExt, TryStreamExt};
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::broadcast::error::RecvError;
pub(crate) struct ViewController { pub(crate) struct ViewController {
user: Arc<dyn WorkspaceUser>, user: Arc<dyn WorkspaceUser>,
@ -102,17 +101,19 @@ impl ViewController {
#[tracing::instrument(level = "debug", skip(self, params), err)] #[tracing::instrument(level = "debug", skip(self, params), err)]
pub(crate) async fn delete_view(&self, params: DeleteViewParams) -> Result<(), WorkspaceError> { pub(crate) async fn delete_view(&self, params: DeleteViewParams) -> Result<(), WorkspaceError> {
let conn = &*self.database.db_connection()?; let conn = &*self.database.db_connection()?;
let _ = self.delete_view_on_server(&params.view_id); let _ = self.delete_view_on_server(params.view_ids.clone());
conn.immediate_transaction::<_, WorkspaceError, _>(|| { conn.immediate_transaction::<_, WorkspaceError, _>(|| {
let view_table = ViewTableSql::delete_view(&params.view_id, conn)?; for view_id in params.view_ids {
let _ = self.document.delete(params.into())?; let view_table = ViewTableSql::delete_view(&view_id, conn)?;
let _ = self.document.delete(view_id.into())?;
let repeated_view = ViewTableSql::read_views(&view_table.belong_to_id, conn)?; let repeated_view = ViewTableSql::read_views(&view_table.belong_to_id, conn)?;
send_dart_notification(&view_table.belong_to_id, WorkspaceNotification::AppViewsChanged) send_dart_notification(&view_table.belong_to_id, WorkspaceNotification::AppViewsChanged)
.payload(repeated_view) .payload(repeated_view)
.send(); .send();
}
Ok(()) Ok(())
})?; })?;
@ -189,12 +190,10 @@ impl ViewController {
} }
#[tracing::instrument(skip(self), err)] #[tracing::instrument(skip(self), err)]
fn delete_view_on_server(&self, view_id: &str) -> Result<(), WorkspaceError> { fn delete_view_on_server(&self, view_ids: Vec<String>) -> Result<(), WorkspaceError> {
let token = self.user.token()?; let token = self.user.token()?;
let server = self.server.clone(); let server = self.server.clone();
let params = DeleteViewParams { let params = DeleteViewParams { view_ids };
view_id: view_id.to_string(),
};
spawn(async move { spawn(async move {
match server.delete_view(&token, params).await { match server.delete_view(&token, params).await {
Ok(_) => {}, Ok(_) => {},

View File

@ -1,5 +1,5 @@
use crate::entities::trash::Trash; use crate::entities::trash::Trash;
use diesel::sql_types::{Binary, Integer}; use diesel::sql_types::{Integer};
use flowy_database::schema::trash_table; use flowy_database::schema::trash_table;
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)] #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]

View File

@ -5,7 +5,7 @@ use crate::{
}; };
use flowy_database::{ use flowy_database::{
prelude::*, prelude::*,
schema::{trash_table, trash_table::dsl::id as trash_id, view_table, view_table::dsl}, schema::{trash_table, view_table, view_table::dsl},
SqliteConnection, SqliteConnection,
}; };
@ -36,7 +36,7 @@ impl ViewTableSql {
.first::<ViewTable>(conn)?; .first::<ViewTable>(conn)?;
let repeated_trash: Vec<String> = trash_table::dsl::trash_table let repeated_trash: Vec<String> = trash_table::dsl::trash_table
.select((trash_table::dsl::id)) .select(trash_table::dsl::id)
.load(conn)?; .load(conn)?;
if repeated_trash.contains(&view_table.id) { if repeated_trash.contains(&view_table.id) {
@ -54,7 +54,7 @@ impl ViewTableSql {
.load::<ViewTable>(conn)?; .load::<ViewTable>(conn)?;
let repeated_trash: Vec<String> = trash_table::dsl::trash_table let repeated_trash: Vec<String> = trash_table::dsl::trash_table
.select((trash_table::dsl::id)) .select(trash_table::dsl::id)
.load(conn)?; .load(conn)?;
view_tables = view_tables view_tables = view_tables