netzke-basepack 0.12.9 → 1.0.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +75 -44
- data/Gemfile +4 -2
- data/LICENSE +2 -6
- data/README.md +22 -24
- data/javascripts/basepack.js +0 -8
- data/javascripts/{columns.js → grid/columns.js} +59 -71
- data/javascripts/grid/event_handlers.js +218 -0
- data/javascripts/netzkeremotecombo.js +5 -13
- data/javascripts/tristate.js +62 -0
- data/javascripts/xdatetime.js +8 -37
- data/lib/netzke-basepack.rb +3 -2
- data/lib/netzke/basepack.rb +1 -1
- data/lib/netzke/basepack/action_column.rb +6 -23
- data/lib/netzke/basepack/active_record.rb +0 -6
- data/lib/netzke/basepack/attr_config.rb +20 -11
- data/lib/netzke/basepack/attribute_config.rb +10 -0
- data/lib/netzke/basepack/attributes.rb +196 -0
- data/lib/netzke/basepack/column_config.rb +47 -39
- data/lib/netzke/basepack/columns.rb +127 -97
- data/lib/netzke/basepack/data_accessor.rb +7 -48
- data/lib/netzke/basepack/data_adapters/abstract_adapter.rb +15 -17
- data/lib/netzke/basepack/data_adapters/active_record_adapter.rb +111 -90
- data/lib/netzke/basepack/dynamic_tab_panel.rb +3 -5
- data/lib/netzke/basepack/dynamic_tab_panel/{javascripts → client}/dynamic_tab_panel.js +6 -5
- data/lib/netzke/basepack/field_config.rb +30 -19
- data/lib/netzke/basepack/fields.rb +22 -12
- data/lib/netzke/basepack/grid_live_search.rb +1 -4
- data/lib/netzke/basepack/grid_live_search/{javascripts → client}/grid_live_search.js +9 -7
- data/lib/netzke/basepack/item_persistence.rb +3 -3
- data/lib/netzke/basepack/item_persistence/events_plugin.rb +8 -10
- data/lib/netzke/basepack/paging_form.rb +7 -11
- data/lib/netzke/basepack/paging_form/{javascripts → client}/paging_form.js +4 -4
- data/lib/netzke/basepack/query_builder.rb +12 -10
- data/lib/netzke/basepack/query_builder/{javascripts → client}/query_builder.js +14 -12
- data/lib/netzke/basepack/record_form_window.rb +8 -8
- data/lib/netzke/basepack/search_panel.rb +4 -6
- data/lib/netzke/basepack/search_panel/{javascripts → client}/condition_field.js +13 -16
- data/lib/netzke/basepack/search_panel/{javascripts → client}/search_panel.js +7 -7
- data/lib/netzke/basepack/search_window.rb +6 -6
- data/lib/netzke/basepack/simple_app/{javascripts → client}/statusbar_ext.js +0 -0
- data/lib/netzke/basepack/version.rb +1 -1
- data/lib/netzke/form/base.rb +166 -0
- data/lib/netzke/{basepack/form/javascripts/form.js → form/base/client/base.js} +77 -38
- data/lib/netzke/form/base/client/readonly_mode.css +4 -0
- data/lib/netzke/{basepack/form/javascripts → form/base/client}/readonly_mode.js +5 -5
- data/lib/netzke/form/endpoints.rb +33 -0
- data/lib/netzke/form/services.rb +74 -0
- data/lib/netzke/grid/actions.rb +52 -0
- data/lib/netzke/grid/base.rb +289 -0
- data/lib/netzke/{basepack/grid/javascripts → grid/base/client}/advanced_search.js +5 -1
- data/lib/netzke/{basepack/grid/javascripts/grid.js → grid/base/client/base.js} +61 -53
- data/lib/netzke/{basepack/grid/javascripts → grid/base/client}/extensions.js +19 -13
- data/lib/netzke/{basepack/grid/javascripts → grid/base/client}/remember_selection.js +0 -1
- data/lib/netzke/grid/client.rb +8 -0
- data/lib/netzke/grid/components.rb +55 -0
- data/lib/netzke/grid/configuration.rb +72 -0
- data/lib/netzke/grid/endpoints.rb +99 -0
- data/lib/netzke/grid/permissions.rb +18 -0
- data/lib/netzke/grid/services.rb +141 -0
- data/lib/netzke/tree/base.rb +173 -0
- data/lib/netzke/{basepack/tree/javascripts/tree.js → tree/base/client/base.js} +55 -26
- data/lib/netzke/{basepack/tree/javascripts → tree/base/client}/extensions.js +7 -7
- data/lib/netzke/tree/endpoints.rb +34 -0
- data/lib/netzke/{basepack/viewport.rb → viewport/base.rb} +3 -3
- data/lib/netzke/{basepack/window.rb → window/base.rb} +7 -8
- data/lib/netzke/window/base/client/base.js +26 -0
- data/locales/de.yml +49 -33
- data/locales/en.yml +32 -39
- data/locales/es.yml +39 -25
- data/locales/nl.yml +39 -25
- data/locales/ru.yml +38 -25
- data/locales/uk.yml +40 -26
- data/stylesheets/basepack.css +10 -0
- metadata +48 -45
- data/javascripts/mixins/grid_event_handlers.js +0 -139
- data/lib/netzke/basepack/accordion.rb +0 -45
- data/lib/netzke/basepack/active_record/relation_extensions.rb +0 -27
- data/lib/netzke/basepack/form.rb +0 -131
- data/lib/netzke/basepack/form/endpoints.rb +0 -35
- data/lib/netzke/basepack/form/services.rb +0 -74
- data/lib/netzke/basepack/form/stylesheets/readonly_mode.css +0 -14
- data/lib/netzke/basepack/grid.rb +0 -570
- data/lib/netzke/basepack/grid/endpoints.rb +0 -111
- data/lib/netzke/basepack/grid/javascripts/edit_in_form.js +0 -51
- data/lib/netzke/basepack/grid/services.rb +0 -148
- data/lib/netzke/basepack/tab_panel.rb +0 -22
- data/lib/netzke/basepack/tab_panel/javascripts/tab_panel.js +0 -11
- data/lib/netzke/basepack/tree.rb +0 -269
- data/lib/netzke/basepack/window/javascripts/window.js +0 -26
- data/lib/netzke/basepack/wrap_lazy_loaded.rb +0 -29
@@ -0,0 +1,99 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Grid
|
3
|
+
module Endpoints
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
endpoint :read do |data|
|
8
|
+
attempt_operation(:read, data, client)
|
9
|
+
end
|
10
|
+
|
11
|
+
endpoint :create do |data|
|
12
|
+
attempt_operation(:create, data, client)
|
13
|
+
end
|
14
|
+
|
15
|
+
endpoint :update do |data|
|
16
|
+
attempt_operation(:update, data, client)
|
17
|
+
end
|
18
|
+
|
19
|
+
endpoint :destroy do |data|
|
20
|
+
attempt_operation(:destroy, data, client)
|
21
|
+
end
|
22
|
+
|
23
|
+
endpoint :save_columns do |cols|
|
24
|
+
state[:columns_order] = cols
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns options for a combobox
|
28
|
+
# params receive:
|
29
|
+
# +attr+ - column's name
|
30
|
+
# +query+ - what's typed-in in the combobox
|
31
|
+
# +id+ - selected record id
|
32
|
+
endpoint :get_combobox_options do |params|
|
33
|
+
column = non_meta_columns.detect{ |c| c[:name] == params[:attr] }
|
34
|
+
client.data = model_adapter.combo_data(column, params[:query])
|
35
|
+
end
|
36
|
+
|
37
|
+
endpoint :move_rows do |params|
|
38
|
+
model_adapter.move_records(params)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Process the submit of multi-editing form ourselves
|
42
|
+
# TODO: refactor to let the form handle the validations
|
43
|
+
endpoint :multiedit_window__multiedit_form__submit do |params|
|
44
|
+
ids = ActiveSupport::JSON.decode(params.delete(:ids))
|
45
|
+
data = ids.collect{ |id| ActiveSupport::JSON.decode(params[:data]).merge("id" => id) }
|
46
|
+
|
47
|
+
data.map!{|el| el.select {|k,v| v.present? }} # only interested in set values
|
48
|
+
|
49
|
+
res = attempt_operation(:update, data, client)
|
50
|
+
|
51
|
+
errors = []
|
52
|
+
res.each do |id, out|
|
53
|
+
errors << out[:error] if out[:error]
|
54
|
+
end
|
55
|
+
|
56
|
+
if errors.empty?
|
57
|
+
on_data_changed
|
58
|
+
client.netzke_on_submit_success
|
59
|
+
"ok"
|
60
|
+
else
|
61
|
+
client.netzke_notify(errors)
|
62
|
+
"failure"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# The following two look a bit hackish, but serve to invoke on_data_changed when a form gets successfully
|
67
|
+
# submitted
|
68
|
+
endpoint :add_window__add_form__submit do |params|
|
69
|
+
client.merge!(component_instance(:add_window).
|
70
|
+
component_instance(:add_form).
|
71
|
+
invoke_endpoint(:submit, [params]))
|
72
|
+
on_data_changed if client.netzke_set_form_values.present?
|
73
|
+
client.delete(:netzke_set_form_values)
|
74
|
+
end
|
75
|
+
|
76
|
+
endpoint :edit_window__edit_form__submit do |params|
|
77
|
+
client.merge!(component_instance(:edit_window).
|
78
|
+
component_instance(:edit_form).
|
79
|
+
invoke_endpoint(:submit, [params]))
|
80
|
+
on_data_changed if client.netzke_set_form_values.present?
|
81
|
+
client.delete(:netzke_set_form_values)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Attempts a given operation on the data. Checks permissions first.
|
86
|
+
# @param [Symbol] Operation: :create, :read, :update, or :delete
|
87
|
+
# @param [Array] Workload of operation data
|
88
|
+
# @param [Netzke::Core::EndpointResponse] Object collecting response to the client
|
89
|
+
def attempt_operation(op, data, client)
|
90
|
+
if allowed_to?(op)
|
91
|
+
send(op, data)
|
92
|
+
else
|
93
|
+
client.netzke_notify I18n.t("netzke.basepack.cannot_#{op}")
|
94
|
+
{}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Grid
|
3
|
+
module Permissions
|
4
|
+
def allowed_to?(action)
|
5
|
+
return allowed_to_read? if action == :read
|
6
|
+
permissions[action].nil? ? !config.read_only : permissions[action]
|
7
|
+
end
|
8
|
+
|
9
|
+
def allowed_to_read?
|
10
|
+
permissions[:read] != false
|
11
|
+
end
|
12
|
+
|
13
|
+
def permissions
|
14
|
+
config.permissions || {}
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Grid
|
3
|
+
# Implements Grid server-side operations. Used by the Endpoints module.
|
4
|
+
module Services
|
5
|
+
# Implementation for the "server_read" endpoint
|
6
|
+
def read(params = {})
|
7
|
+
{}.tap do |res|
|
8
|
+
records = get_records(params)
|
9
|
+
res[:data] = records.map{|r| model_adapter.record_to_array(r, final_columns)}
|
10
|
+
res[:total] = count_records(params)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns hash with results per client (temporary) id, e.g.:
|
15
|
+
#
|
16
|
+
# {
|
17
|
+
# 1: {errors: [], record: {title: 'New title'}},
|
18
|
+
# 2: {errors: ["Title must be present"], record: nil}
|
19
|
+
# }
|
20
|
+
def create(data)
|
21
|
+
data.inject({}) do |out, attrs|
|
22
|
+
id = attrs.delete('internal_id')
|
23
|
+
record = model_adapter.new_record
|
24
|
+
out.merge(id => update_record(record, attrs))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Receives an array of attribute hashes, e.g.:
|
29
|
+
#
|
30
|
+
# [{"id": 1, title: "New title"}, {"id": 2, title: ""}]
|
31
|
+
#
|
32
|
+
# Returns hash with results per id, e.g.:
|
33
|
+
#
|
34
|
+
# {
|
35
|
+
# 1: {errors: [], record: {title: 'New title'}},
|
36
|
+
# 2: {errors: ["Title must be present"], record: nil}
|
37
|
+
# }
|
38
|
+
def update(data)
|
39
|
+
data.inject({}) do |out, attrs|
|
40
|
+
id = attrs.delete(model_adapter.primary_key)
|
41
|
+
record = model_adapter.find_record(id, scope: config.scope)
|
42
|
+
record.nil? ? out.merge(id => {error: "Not allowed to edit record #{id}"}) : out.merge(id => update_record(record, attrs))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Destroys records by ids
|
47
|
+
# Returns hash with results per id, e.g.:
|
48
|
+
#
|
49
|
+
# {
|
50
|
+
# 1: "ok",
|
51
|
+
# 2: "error: "This record could not be destroyed"
|
52
|
+
# }
|
53
|
+
def destroy(ids)
|
54
|
+
out = {}
|
55
|
+
|
56
|
+
ids.each {|id|
|
57
|
+
record = model_adapter.find_record(id, scope: config[:scope])
|
58
|
+
next if record.nil?
|
59
|
+
|
60
|
+
if record.destroy
|
61
|
+
out[id] = "ok"
|
62
|
+
else
|
63
|
+
out[id] = {error: record.errors.to_a.first}
|
64
|
+
end
|
65
|
+
}
|
66
|
+
|
67
|
+
out
|
68
|
+
end
|
69
|
+
|
70
|
+
# Returns an array of records.
|
71
|
+
def get_records(params)
|
72
|
+
params[:filters] = normalize_filters(params[:filters]) if params[:filters]
|
73
|
+
params[:query] = normalize_query(params[:query]) if params[:query].present?
|
74
|
+
params[:scope] = config[:scope] # note, params[:scope] becomes ActiveSupport::HashWithIndifferentAccess
|
75
|
+
|
76
|
+
model_adapter.get_records(params, final_columns)
|
77
|
+
end
|
78
|
+
|
79
|
+
def count_records(params)
|
80
|
+
params[:scope] = config[:scope] # note, params[:scope] becomes ActiveSupport::HashWithIndifferentAccess
|
81
|
+
|
82
|
+
model_adapter.count_records(params, final_columns)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Override this method to react on each operation that caused changing of data
|
86
|
+
def on_data_changed
|
87
|
+
end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
def normalize_filters(filters)
|
92
|
+
filters.map do |f|
|
93
|
+
{ attr: f["property"], value: f["value"], operator: f["operator"] }.tap do |norm|
|
94
|
+
|
95
|
+
# Ext JS filters send us date in the American format
|
96
|
+
if f["value"].is_a?(String) && f["value"].match(/^(\d\d)\/(\d\d)\/(\d\d\d\d)$/)
|
97
|
+
norm[:value] = "#{$3}-#{$1}-#{$2}"
|
98
|
+
end
|
99
|
+
|
100
|
+
if filter_with = final_columns_hash[norm[:attr].to_sym][:filter_with]
|
101
|
+
norm[:proc] = filter_with
|
102
|
+
end
|
103
|
+
|
104
|
+
norm[:operator] = "contains" if f["type"] == "string"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def normalize_query(or_query)
|
110
|
+
or_query.each do |and_query|
|
111
|
+
and_query.each do |q|
|
112
|
+
column_config = final_columns_hash[q[:attr].to_sym] || {}
|
113
|
+
if filter_with = column_config[:filter_with]
|
114
|
+
q[:proc] = filter_with
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def update_record(record, attrs)
|
121
|
+
attrs.each_pair do |k,v|
|
122
|
+
attr = final_columns_hash[k.to_sym]
|
123
|
+
next if attr.nil?
|
124
|
+
model_adapter.set_record_value_for_attribute(record, attr, v)
|
125
|
+
end
|
126
|
+
|
127
|
+
strong_attrs = config[:strong_values] || {}
|
128
|
+
|
129
|
+
strong_attrs.each_pair do |k,v|
|
130
|
+
model_adapter.set_record_value_for_attribute(record, {name: k.to_s}, v)
|
131
|
+
end
|
132
|
+
|
133
|
+
if record.save
|
134
|
+
{record: model_adapter.record_to_array(record, final_columns)}
|
135
|
+
else
|
136
|
+
{error: record.errors.to_a}
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
module Netzke
|
2
|
+
module Tree
|
3
|
+
# Ext.tree.Panel-based component with the following features:
|
4
|
+
#
|
5
|
+
# * CRUD operations
|
6
|
+
# * Persistence of node expand/collapse state
|
7
|
+
# * Node reordering by DnD
|
8
|
+
#
|
9
|
+
# Client-side methods are documented here: http://api.netzke.org/client/classes/Netzke.Tree.Base.html.
|
10
|
+
#
|
11
|
+
# == Simple example
|
12
|
+
#
|
13
|
+
# class Files < Netzke::Tree::Base
|
14
|
+
# def configure(c)
|
15
|
+
# super
|
16
|
+
# c.model = "FileRecord"
|
17
|
+
# c.columns = [
|
18
|
+
# {name: :name, xtype: :treecolumn}, # this column will show tree nodes
|
19
|
+
# :size
|
20
|
+
# ]
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# == Instance configuration
|
25
|
+
#
|
26
|
+
# The following config options are supported:
|
27
|
+
#
|
28
|
+
# [model]
|
29
|
+
#
|
30
|
+
# Name of the ActiveRecord model that provides data to this Tree, e.g. "FileRecord"
|
31
|
+
# The model must respond to the following methods:
|
32
|
+
#
|
33
|
+
# * TreeModel.root - the root record
|
34
|
+
# * TreeModel#children - child records
|
35
|
+
#
|
36
|
+
# Note that the awesome_nested_set gem implements the above, so, feel free to use it.
|
37
|
+
#
|
38
|
+
# [columns]
|
39
|
+
#
|
40
|
+
# An array of columns to be displayed in the tree. See the "Columns" section in the `Netzke::Grid::Base`.
|
41
|
+
# Additionally, you probably will want to specify which column will have the tree nodes UI by providing the
|
42
|
+
# `xtype` config option set to `:treecolumn`.
|
43
|
+
#
|
44
|
+
# [root]
|
45
|
+
#
|
46
|
+
# By default, the component will pick whatever record is returned by `TreeModel.root`, and use it as the root
|
47
|
+
# record. However, sometimes the model table has multiple root records (whith `parent_id` set to `nil`), and all
|
48
|
+
# of them should be shown in the panel. To achive this, you can define the `root` config option,
|
49
|
+
# which will serve as a virtual root record for those records. You may set it to `true`, or a hash of
|
50
|
+
# attributes, e.g.:
|
51
|
+
#
|
52
|
+
# c.root = {name: 'Root', size: 1000}
|
53
|
+
#
|
54
|
+
# Note, that the root record can be hidden from the tree by specifying the `Ext.tree.Panel`'s `root_visible`
|
55
|
+
# config option set to `false`, which is probably what you want when you have multiple root records.
|
56
|
+
#
|
57
|
+
# [drag_drop]
|
58
|
+
#
|
59
|
+
# Enables drag and drop in the tree.
|
60
|
+
#
|
61
|
+
# == Persisting nodes' expand/collapse state
|
62
|
+
#
|
63
|
+
# If the model includes the `expanded` DB field, the expand/collapse state will get stored in the DB.
|
64
|
+
class Base < Netzke::Base
|
65
|
+
NODE_ATTRS = {
|
66
|
+
boolean: %w[leaf checked expanded expandable qtip qtitle],
|
67
|
+
string: %w[icon icon_cls href href_target qtip qtitle]
|
68
|
+
}
|
69
|
+
|
70
|
+
include Netzke::Grid::Configuration
|
71
|
+
include Netzke::Grid::Endpoints
|
72
|
+
include Netzke::Grid::Services
|
73
|
+
include Netzke::Grid::Actions
|
74
|
+
include Netzke::Grid::Components
|
75
|
+
include Netzke::Grid::Permissions
|
76
|
+
include Netzke::Basepack::Columns
|
77
|
+
include Netzke::Basepack::Attributes
|
78
|
+
include Netzke::Basepack::DataAccessor
|
79
|
+
include Netzke::Tree::Endpoints
|
80
|
+
|
81
|
+
client_class do |c|
|
82
|
+
c.extend = "Ext.tree.Panel"
|
83
|
+
c.require :extensions
|
84
|
+
c.mixins << "Netzke.Grid.Columns"
|
85
|
+
c.mixins << "Netzke.Grid.EventHandlers"
|
86
|
+
c.translate *%w[are_you_sure confirmation]
|
87
|
+
end
|
88
|
+
|
89
|
+
action :search do |c|
|
90
|
+
c.excluded = true
|
91
|
+
end
|
92
|
+
|
93
|
+
class << self
|
94
|
+
def server_side_config_options
|
95
|
+
super + [:model]
|
96
|
+
end
|
97
|
+
|
98
|
+
# Borrow translations from the grid for now
|
99
|
+
def i18n_id
|
100
|
+
"netzke.grid.base"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def columns
|
105
|
+
add_node_interface_methods(super)
|
106
|
+
end
|
107
|
+
|
108
|
+
# Overrides Grid::Services#get_records
|
109
|
+
def get_records(params)
|
110
|
+
if params[:id] == 'root'
|
111
|
+
model_adapter.find_root_records
|
112
|
+
else
|
113
|
+
model_adapter.find_record_children(model_adapter.find_record(params[:id]))
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Overrides Grid::Services#read so we send records as key-value JSON (instead of array)
|
118
|
+
def read(params = {})
|
119
|
+
{}.tap do |res|
|
120
|
+
records = get_records(params)
|
121
|
+
res["children"] = records.map{|r| node_to_hash(r, final_columns).netzke_literalize_keys}
|
122
|
+
res["total"] = count_records(params) if config[:enable_pagination]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def node_to_hash(record, columns)
|
127
|
+
model_adapter.record_to_hash(record, columns).tap do |hash|
|
128
|
+
if is_node_expanded?(record)
|
129
|
+
hash["children"] = record.children.map {|child| node_to_hash(child, columns).netzke_literalize_keys}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def is_node_expanded?(record)
|
135
|
+
record.respond_to?(:expanded) && record.expanded?
|
136
|
+
end
|
137
|
+
|
138
|
+
# Overrides `Grid::Configuration#configure_client`
|
139
|
+
def configure_client(c)
|
140
|
+
super
|
141
|
+
|
142
|
+
c.root ||= model_adapter.record_to_hash(model_adapter.root, final_columns).netzke_literalize_keys
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
|
147
|
+
def update_record(record, attrs)
|
148
|
+
if config.drag_drop && attrs['parentId']
|
149
|
+
parent_id = attrs['parentId'] == 'root' ? nil : attrs['parentId']
|
150
|
+
model_adapter.set_record_value_for_attribute(record, { name: 'parent_id' }, parent_id)
|
151
|
+
end
|
152
|
+
|
153
|
+
super
|
154
|
+
end
|
155
|
+
|
156
|
+
# Adds attributes known to Ext.data.NodeInterface as meta columns (only those our model responds to)
|
157
|
+
def add_node_interface_methods(columns)
|
158
|
+
columns.clone.tap do |columns|
|
159
|
+
NODE_ATTRS.each do |type, attrs|
|
160
|
+
add_node_interface_methods_by_type!(columns, attrs, type)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_node_interface_methods_by_type!(columns, attrs, type)
|
166
|
+
attrs.each do |a|
|
167
|
+
next unless model_adapter.model_respond_to?(a.to_sym)
|
168
|
+
columns << {type: type, name: a, meta: true}
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -1,39 +1,45 @@
|
|
1
|
+
/**
|
2
|
+
* Client-side code for [Netzke::Tree::Base](http://www.rubydoc.info/github/netzke/netzke-basepack/Netzke/Tree/Base)
|
3
|
+
* @class Netzke.Tree.Base
|
4
|
+
*/
|
1
5
|
{
|
2
6
|
multiSelect: true,
|
3
7
|
|
4
8
|
initComponent: function(){
|
5
9
|
this.netzkeProcessColumns();
|
6
|
-
this.netzkeBuildModel('Ext.data.TreeModel');
|
7
10
|
this.netzkeBuildStore();
|
8
11
|
|
9
12
|
delete this.root;
|
10
13
|
|
14
|
+
if (this.config.dragDrop) {
|
15
|
+
this.netzkeSetDragDrop();
|
16
|
+
}
|
17
|
+
|
11
18
|
this.plugins = this.plugins || [];
|
12
19
|
this.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {pluginId: 'celleditor'}));
|
13
20
|
|
14
21
|
this.callParent();
|
15
22
|
|
16
|
-
this.
|
17
|
-
|
18
|
-
this.getView().on('
|
23
|
+
this.netzkeSetActionEvents();
|
24
|
+
|
25
|
+
this.getView().on('afteritemcollapse', this.netzkeOnNodeStateChange, this);
|
26
|
+
this.getView().on('afteritemexpand', this.netzkeOnNodeStateChange, this);
|
19
27
|
|
20
28
|
this.store.on('load', function(){
|
21
29
|
var root = this.getRootNode();
|
22
30
|
root.collapse();
|
23
31
|
root.expand(false);
|
24
32
|
}, this);
|
25
|
-
},
|
26
33
|
|
27
|
-
|
28
|
-
this.serverUpdateNodeState({id: node.get('id'), expanded: node.isExpanded()});
|
34
|
+
this.on('itemdblclick', this.netzkeHandleItemdblclick, this);
|
29
35
|
},
|
30
36
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
+
/**
|
38
|
+
* Called when a node gets expanded or collapsed.
|
39
|
+
* @method netzkeOnNodeStateChange
|
40
|
+
*/
|
41
|
+
netzkeOnNodeStateChange: function(node){
|
42
|
+
this.server.updateNodeState({id: node.get('id'), expanded: node.isExpanded()});
|
37
43
|
},
|
38
44
|
|
39
45
|
netzkeBuildStore: function() {
|
@@ -57,23 +63,47 @@
|
|
57
63
|
},
|
58
64
|
|
59
65
|
netzkeBuildProxy: function() {
|
60
|
-
return Ext.create('Netzke.
|
61
|
-
reader:
|
66
|
+
return Ext.create('Netzke.Tree.Proxy', {
|
67
|
+
reader: 'json',
|
62
68
|
grid: this
|
63
69
|
});
|
64
70
|
},
|
65
71
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
72
|
+
netzkeSetDragDrop: function() {
|
73
|
+
this.nezkeInitViewConfig();
|
74
|
+
|
75
|
+
this.viewConfig.plugins.push(
|
76
|
+
Ext.create('Ext.tree.plugin.TreeViewDragDrop', {
|
77
|
+
enableDrag: true
|
78
|
+
})
|
79
|
+
);
|
80
|
+
|
81
|
+
this.viewConfig.listeners['drop'] = function( node, data, overModel, dropPosition, eOpts ) {
|
82
|
+
var parentId = (dropPosition == 'append') ? overModel.id : overModel.data.parentId;
|
83
|
+
var dataRecords = data.records;
|
84
|
+
var records = dataRecords.map(function(element){ return { id: element.id, parentId: parentId } });
|
85
|
+
this.panel.server.updateParentId(records, function(response){
|
86
|
+
dataRecords.forEach(function(record){
|
87
|
+
if (record.modified !== undefined &&
|
88
|
+
Object.keys(record.modified).length == 1
|
89
|
+
&& record.modified["parentId"] !== undefined){
|
90
|
+
record.dirty = false;
|
91
|
+
delete record.modified["parentId"];
|
92
|
+
}
|
93
|
+
});
|
94
|
+
});
|
95
|
+
}
|
96
|
+
},
|
97
|
+
|
98
|
+
nezkeInitViewConfig: function() {
|
99
|
+
this.viewConfig = this.viewConfig || {};
|
100
|
+
this.viewConfig.plugins = this.viewConfig.plugins || [];
|
101
|
+
this.viewConfig.listeners = this.viewConfig.listeners || {};
|
71
102
|
},
|
72
103
|
|
73
104
|
// overriding
|
74
|
-
|
105
|
+
netzkeOnAdd: function(){
|
75
106
|
var selected = this.getSelection()[0]
|
76
|
-
|
77
107
|
this.netzkeLoadComponent("add_window", {
|
78
108
|
callback: function(w){
|
79
109
|
w.show();
|
@@ -101,14 +131,14 @@
|
|
101
131
|
},
|
102
132
|
|
103
133
|
// overriding
|
104
|
-
|
134
|
+
netzkeOnApply: function(){
|
105
135
|
var topModified = this.store.getModifiedRecords()[0]; // the most top-level modified record
|
106
136
|
this.store.sync();
|
107
137
|
this.store.load({node: topModified.parentNode});
|
108
138
|
},
|
109
139
|
|
110
140
|
// overriding
|
111
|
-
|
141
|
+
netzkeOnDelete: function() {
|
112
142
|
Ext.Msg.confirm(this.i18n.confirmation, this.i18n.areYouSure, function(btn){
|
113
143
|
if (btn == 'yes') {
|
114
144
|
var toDelete = this.getSelectionModel().getSelection();
|
@@ -118,6 +148,5 @@
|
|
118
148
|
store.sync();
|
119
149
|
}
|
120
150
|
}, this);
|
121
|
-
}
|
122
|
-
|
151
|
+
}
|
123
152
|
}
|