Open fushang318 opened 9 years ago
弹出组件的UI交互中没有删除bucket么? 的确没有。dribbble.com是在用户buckets管理页面里面操作的
引用方式参考 enumerize
class Folder
extend Bucketerize
bucketerize resources: ["Book"]
end
class Folder
extend Bucketerize
bucketerize bucket: "Folder"
end
class Folder
extend Bucketerize
bucketerize resources: ["Book", "Photo"]
end
class Book
extend Bucketerize
bucketerize bucket: "Folder"
end
class Photo
extend Bucketerize
bucketerize bucket: "Folder"
end
个人的一些设计思路供参考:
class Shelf
act_as_bucket :collect => [:book]
# 赋予 Shelf 收藏夹特性,并且指定被收藏的对象为 Book
# 一种收藏夹能收藏多种资源,所以这里传数组
end
class Book
act_as_bucket_resource :into => :shelf
# 赋予 Book 被收藏资源特性,并且指定它可以被 Shelf 收藏
# 一种资源只能被一种收藏夹收藏,所以这里传单值
end
class Album
act_as_bucket :collect => [:photo]
# 赋予 Album 收藏夹特性,并且指定被收藏的对象为 Photo
end
class Photo
act_as_bucket_resource :into => :album
# 赋予 Photo 被收藏资源特性,并且指定它可以被 Album 收藏
end
class Folder
act_as_bucket :collect => [:book, :photo]
# 赋予 Shelf 收藏夹特性,并且指定被收藏的对象为 Book 和 Photo
end
class Book
act_as_bucket_resource :into => :folder
# 赋予 Book 被收藏资源特性,并且指定它可以被 Folder 收藏
# 一种资源只能被一种收藏夹收藏,所以这里传单值
end
class Photo
act_as_bucket_resource :into => :folder
# 赋予 Photo 被收藏资源特性,并且指定它可以被 Folder 收藏
end
# 假设 Folder 是带有 Bucket 特征的类
# 假设 Book 和 Photo 是带有 BucketResource 特征的类
# Folder 允许收集 Book 和 Photo
# 则有:
folder.add_resource book
folder.add_resource photo
# 添加一个资源,通过 Bucket 特征类调用
folder.add_resources [book1, photo1, book2, photo2]
# 添加多个资源,通过 Bucket 特征类调用
book.add_to_bucket folder
photo.add_to_bucket folder
# 添加到一个收藏夹,通过 BucketResource 特征类调用
book.add_to_buckets [folder1, folder2]
photo.add_to_buckets [folder1, folder2]
# 添加到多个收藏夹,通过 BucketResource 特征类调用
folder.remove_resource book
folder.remove_resource photo
folder.remove_resources [book1, book2, photo1, photo2]
# 从收藏夹中移除指定的资源,如果资源本来就不在收藏夹里,则忽略
book.remove_from_bucket folder
photo.remove_from_bucket folder
book.remove_from_buckets [folder1, folder2]
# 将资源从指定收藏夹移除,如果资源本来就不在收藏夹里,则忽略
folder.resources
#=> 返回包含所有 book photo 的资源集合。通过参数支持分页或通过 scope 支持分页。(查询并列在一起很容易,实现分页支持可能相对比较麻烦)
folder.resources :of => [:book, :photo]
folder.resources :of => [:photo]
folder.resources :of => [:book]
#=> 返回包含指定类型资源的集合。通过参数支持分页或通过 scope 支持分页。(查询并列在一起很容易,实现分页支持可能相对比较麻烦)
# 如果多种资源混合查找确实比较难做到,那就优先支持单一资源查找。
# 重点是需要支持分页。
经过讨论,觉得共享收藏夹,以及混合类型查询这些事情都可以通过多态解决 例如,img4ye 0.3 里面封装的对象就是多态 同时代表 图片,视频,音频
个人的一些设计思路供参考:
class Album
act_as_bucket :collect => :photo
# 赋予 Album 收藏夹特性,并且指定被收藏的对象为 Photo
end
class Photo
act_as_bucket_resource :into => :album
# 赋予 Photo 被收藏资源特性,并且指定它可以被 Album 收藏
end
可以指定多组成对出现的收藏夹和被收藏资源。
class Album
act_as_bucket :collect => :photo
# 赋予 Album 收藏夹特性,并且指定被收藏的对象为 Photo
end
class Photo
act_as_bucket_resource :into => :album
# 赋予 Photo 被收藏资源特性,并且指定它可以被 Album 收藏
end
class Shelf
act_as_bucket :collect => :book
# 赋予 Shelf 收藏夹特性,并且指定被收藏的对象为 Book
end
class Book
act_as_bucket_resource :into => :resource
# 赋予 Book 被收藏资源特性,并且指定它可以被 Shelf 收藏
end
class Folder
act_as_bucket :collect => [:book, :photo]
# 赋予 Shelf 收藏夹特性,并且指定被收藏的对象为 Book 和 Photo
end
class Book
act_as_bucket_resource :into => :folder
# 赋予 Book 被收藏资源特性,并且指定它可以被 Folder 收藏
# 一种资源只能被一种收藏夹收藏,所以这里传单值
end
class Photo
act_as_bucket_resource :into => :folder
# 赋予 Photo 被收藏资源特性,并且指定它可以被 Folder 收藏
end
可以把资源类写成一个多态的类,同时代表多个类型来实现这种逻辑。 本插件不对此提供特别支持。
# 假设 Folder 是带有 Bucket 特征的类
# 假设 Book 特征的类
# Folder 允许收集 Book
# 则有:
folder.add_resource book
# 添加一个资源,通过 Bucket 特征类调用
folder.add_resources [book1, book2]
# 添加多个资源,通过 Bucket 特征类调用
book.add_to_bucket folder
# 添加到一个收藏夹,通过 BucketResource 特征类调用
book.add_to_buckets [folder1, folder2]
# 添加到多个收藏夹,通过 BucketResource 特征类调用
folder.remove_resource book
folder.remove_resources [book1, book2]
# 从收藏夹中移除指定的资源,如果资源本来就不在收藏夹里,则忽略
book.remove_from_bucket folder
book.remove_from_buckets [folder1, folder2]
# 将资源从指定收藏夹移除,如果资源本来就不在收藏夹里,则忽略
folder.resources
#=> 返回资源集合(这里返回的应该是 book 查询结果)。通过 scope 支持分页。
获取buckets列表
path
/buckets
method
"GET"
params
*type String (例如bucket)
respond
{ type: "bucket", result:[{id: 1, name: 'name1', desc: 'desc1'}, {id: 2, name: 'name2', desc: 'desc2'}] }
获取buckets列表(2015-06-16修改)
path
/buckets
method
"GET"
params
*bucket_type String (例如bucket)
resource_type String (例如resource, 必须与resource_id同时提交, 用于获取是否已经加入收藏夹)
resource_id String (例如1, 必须与resource_type同时提交, 用于获取是否已经加入收藏夹)
respond
{ type: "bucket", result:[{id: 1, name: 'name1', desc: 'desc1', added: false}, {id: 2, name: 'name2', desc: 'desc2', added: true }] }
创建bucket
path
/buckets
method
"POST"
params
*type String (例如bucket)
*name String (例如bucket)
desc String (非必填)
respond
{ type: "bucket", result: {id: 1, name: 'name1', desc: 'desc1'}}
添加resource到bucket
path
/bucketing
method
"POST"
params
*bucket_type String (例如bucket)
*bucket_id String (例如"123")
*resource_type String (例如photo)
*resource_id String (例如”234“)
respond
{result: "ok"}
从bucket移除resource
path
/bucketing
method
"DELETE"
params
*bucket_type String (例如bucket)
*bucket_id String (例如"123")
*resource_type String (例如photo)
*resource_id String (例如”234“)
respond
{result: "ok"}
参考RailsAdmin,设计可以自定义路径、前缀
mount RailsAdmin::Engine => '/admin', :as => 'rails_admin'
新追加一个逻辑,就是限制为当前用户的buckets
需在models与controllers里面,加上相应逻辑
我们需要在一个dom里面申明一些data内容 ,然后通过JS传入HOOK,处理相应的UI操作,在此,我只简单说明,具体请参考demo https://github.com/destinyd/mindpin_buckets_demo (暂时一页只支持一个Resource)
<a class="add_to_folder btn btn-default" data-rel="mindpin_buckets" data-resource-id="557f9857636865734e000002" data-resource-type="photo" href="javascript:;">添加到Folder</a>
data-rel="mindpin_buckets"为默认激活选择器名称 data-resource-type="photo"为资源类型 data-resource-id="557f9857636865734e000002"为资源类型
class FolderHook extends MindpinHook
constructor: (@$fm) ->
@modal_folders = jQuery('#modal-folders')
@_init()
_init: () ->
# 创建按钮点击
@modal_folders.find('.new').click () =>
console.log 'click new'
@modal_new_folder.modal('show')
@modal_new_folder = jQuery('#modal-new-folder')
@modal_new_folder.find('.create').click () =>
console.log 'create'
name = @modal_new_folder.find('.name').val()
desc = @modal_new_folder.find('.desc').val()
console.log name
console.log desc
@$fm.create_bucket(name, desc)
el_click: (el) ->
console.log 'hook el click'
# todo
@modal_folders.modal('show')
buckets_success: (buckets) =>
console.log 'hook buckets success'
console.log buckets
str = ''
that = this
jQuery.each buckets, ->
bucket = this
str += that._str_bucket(bucket.id, bucket.name, bucket.added)
@modal_folders.find('.buckets').html(str)
# li点击事件绑定:添加、移除到folder
@modal_folders.on 'click', '.buckets li.group', ->
console.log 'click li'
if $(this).hasClass('unbucketed')
bucket_id = $(this).data('id')
that.$fm.add_to_bucket(bucket_id) # that.$fm.resource_type, that.$fm.resource_id, bucket_type, bucket_id)
else
bucket_id = $(this).data('id')
bucket_type = that.$fm.bucket_type
that.$fm.remove_from_bucket(bucket_id)
create_bucket_success: (bucket) =>
console.log 'hook create bucket success'
that = this
str = @_str_bucket(bucket.id, bucket.name, false)
@modal_folders.find('.buckets').append str
@modal_new_folder.find('.name').val('')
@modal_new_folder.find('.desc').val('')
@modal_new_folder.modal('hide')
add_to_bucket_success: (bucket) =>
@modal_folders.find("[data-id=#{bucket.id}]").removeClass('unbucketed').addClass('bucketed')
remove_from_bucket_success: (bucket) ->
console.log 'remove_from_bucket_success'
console.log bucket
@modal_folders.find("[data-id=#{bucket.id}]").removeClass('bucketed').addClass('unbucketed')
_str_bucket: (id, name, added) ->
"<li class=\"group #{if !added then "un" else ""}bucketed\" data-id=\"#{id}\" id=\"bucket_#{id}\"><a href=\"javascript:;\"><strong>#{name}</strong><!--<span class=\"bucket-meta\">1 photos</span>--><span class=\"bucket-meta\">更新时间</span></a></li>"
jQuery(document).on 'ready page:load', ->
configs =
bucket_type: "Folder"
hook_class: FolderHook
window.mindpin_buckets = new MindpinBuckets(configs)
此coffee文件主要作用为自定义Hook,改写原有方法,在对应时刻做相应的UI操作(通过configs传入)。
示例为使用Bootstrap的modal来实现demo,你会发现里面使用了一些未写出的dom,都可以在https://github.com/destinyd/mindpin_buckets_demo代码中找到
对目前前端用法的总结: 针对:https://github.com/destinyd/mindpin_buckets_demo/commit/65e3f5d0f32a4a9bf18f31c8989e2be788e747fe
HOOK dom 定义 定义一个 dom 为 HOOK,代码如下:
<a class="add_to_folder btn btn-default" data-rel="mindpin_buckets" data-resource-id="557f9857636865734e000002" data-resource-type="photo" href="javascript:;">添加到Folder</a>
data-rel="mindpin_buckets"
固定不变,为默认激活选择器名称
data-resource-type="photo"
为资源类型
data-resource-id="557f9857636865734e000002"
为资源ID
这样,页面加载的时候,组件会自动找到上面这个 dom,并把 resource_id 和 resource_type 读入组件来构造实例。
HOOK 类定义
定义一个类,继承 MindpinHook
. 在该类的构造函数中,可以自行实现一些事件。
例如,初始化对话框,并且为对话框的按钮注册点击事件。
class FolderHook extends MindpinHook
constructor: (@api)->
# do sth..
框架会将一个 MindpinBuckets
的实例传给该 HOOK 类。该实例可以用于调用 API 方法:
@api.create_bucket(name, desc)
# 根据传入的 name, desc 创建一个 bucket
@api.add_to_bucket(bucket_id)
# 将当前资源(根据 dom 读入的资源)添加到指定 ID 的 bucket 中
@api.remove_from_bucket(bucket_id)
# 将当前资源(根据 dom 读入的资源)从指定 ID 的 bucket 中移除
页面初始化
页面初始化时,需要构造一个 MindpinBuckets 实例,并且把 HOOK 类传进去。
jQuery(document).on 'ready page:load', ->
configs =
bucket_type: "Folder"
hook_class: FolderHook
window.mindpin_buckets = new MindpinBuckets(configs)
MindpinBuckets 的实例被构造时,会发起读取 buckets 列表的请求。并且把读取到的信息传给 HOOK 类的 buckets_success 方法。 开发者需要实现此方法,增加自己的处理逻辑,例如生成收藏夹列表。
使用过程
页面加载完毕后,点击 HOOK dom 时,会触发 HOOK 类的 el.click()
方法。
开发者需要实现此方法,增加自己的处理逻辑。例如弹出收藏夹对话框。
el_click: (el) ->
@modal_folders.modal('show')
在 HOOK 类的构造函数里,开发者需要自行绑定事件,实现对 @api.create_bucket(name, desc)
的调用。
该调用请求完毕后,会触发HOOK 类的 create_bucket_success(bucket)
方法。并把 bukcet 信息传给该方法。
开发者可以自行实现该方法,做一些创建收藏夹的后续处理。例如更新列表。
在 HOOK 类的构造函数里,开发者需要自行绑定事件,实现对 @api.add_to_bucket(name, desc)
的调用。
该调用请求完毕后,会触发HOOK 类的 add_to_bucket_success(bucket)
方法。并把 bukcet 信息传给该方法。
开发者可以自行实现该方法,做一些添加资源到收藏夹的后续处理。例如更新页面信息。
在 HOOK 类的构造函数里,开发者需要自行绑定事件,实现对 @api.remove_from_bucket(name, desc)
的调用。
该调用请求完毕后,会触发HOOK 类的 remove_from_bucket_success(bucket)
方法。并把 bukcet 信息传给该方法。
开发者可以自行实现该方法,做一些添加资源到收藏夹的后续处理。例如更新列表。
使用以上的方法,开发者就可以实现自己的复合收藏夹前端。
以前的内容
https://github.com/mindpin/web-url-collector/issues/13 https://github.com/destinyd/buckets_demo https://buckets-demo-fushang318.herokuapp.com/
http://oss.aliyuncs.com/pie-documents/20150303/dribbble-buckets-usage.mp4 这个视频演示了一个把资源收藏到收藏夹(bucket)的整个逻辑和UI交互
现在希望把这个逻辑和UI交互整个封装到gem 方便使用 封装的内容包括 1 后台的逻辑 2 前端的交互
设想的使用方法
增加配置信息
config/initialize/simple_bucket.rb
增加模型
config/models/folder.rb
config/models/book.rb
给页面元素增加点击弹出 bucket 编辑框
当工程引入bucket组件后,在页面声明带有如下属性的元素 就可以给元素注册点击事件,点击弹出 bucket 编辑框
如何实现的一些思路记录
组件应该需要封装的 controller
组件应该封装的给页面元素增加点击弹出 bucket 编辑框
组件中有一段js 遍历页面中的 jQuery("*[data-rel='simple-bucket']") 并增加相关逻辑
疑惑
弹出组件的UI交互中没有删除bucket么