togo 0.4.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +210 -0
- data/lib/togo/admin/admin.rb +6 -25
- data/lib/togo/admin/helpers.rb +57 -0
- data/lib/togo/admin/public/css/screen.css +329 -190
- data/lib/togo/admin/public/img/arrow-down.png +0 -0
- data/lib/togo/admin/public/img/arrows.png +0 -0
- data/lib/togo/admin/public/img/bg-header.png +0 -0
- data/lib/togo/admin/public/img/button-bg-delete.png +0 -0
- data/lib/togo/admin/public/img/button-bg-save.png +0 -0
- data/lib/togo/admin/public/img/footer-bg.png +0 -0
- data/lib/togo/admin/public/img/subhead-bg.png +0 -0
- data/lib/togo/admin/public/js/edit.js +23 -24
- data/lib/togo/admin/public/js/index.js +3 -2
- data/lib/togo/admin/public/js/togo.js +46 -14
- data/lib/togo/admin/views/_paging.erb +14 -0
- data/lib/togo/admin/views/edit.erb +6 -9
- data/lib/togo/admin/views/index.erb +44 -44
- data/lib/togo/admin/views/layout.erb +14 -16
- data/lib/togo/admin/views/new.erb +5 -2
- data/lib/togo/model/model.rb +20 -38
- data/lib/togo/model/relationship_manager/many_to_one.rb +19 -0
- data/lib/togo/model/relationship_manager/one_to_many.rb +19 -0
- data/lib/togo/model/relationship_manager/relationship_manager.rb +40 -0
- data/lib/togo/model/types/belongs_to.erb +42 -40
- data/lib/togo/model/types/has_n.erb +44 -42
- data/lib/togo/model/types/many_to_many.erb +44 -42
- metadata +17 -7
- data/README +0 -29
@@ -6,7 +6,7 @@ var app = (function() {
|
|
6
6
|
|
7
7
|
var searchInputHandler = function(action) {
|
8
8
|
return function(e) {
|
9
|
-
|
9
|
+
e = e || window.event;
|
10
10
|
if (this.value == '') {
|
11
11
|
this.value = searchInputDefaultValue;
|
12
12
|
}
|
@@ -17,6 +17,7 @@ var app = (function() {
|
|
17
17
|
};
|
18
18
|
|
19
19
|
var handleMultiSelect = function(e) {
|
20
|
+
e = e || window.event;
|
20
21
|
var id = e.target.getAttribute('id').split('_')[1];
|
21
22
|
if (e.target.checked) {
|
22
23
|
selectedItems.push(id);
|
@@ -42,7 +43,7 @@ var app = (function() {
|
|
42
43
|
var c = el('list-table').getElementsByTagName('input');
|
43
44
|
for (var i = 0; i < c.length; i++) {
|
44
45
|
if (c[i].getAttribute('type') == 'checkbox') {
|
45
|
-
|
46
|
+
listen('click', c[i], handleMultiSelect);
|
46
47
|
}
|
47
48
|
}
|
48
49
|
|
@@ -1,3 +1,22 @@
|
|
1
|
+
if (!Array.prototype.some)
|
2
|
+
{
|
3
|
+
Array.prototype.some = function(fun /*, thisp*/)
|
4
|
+
{
|
5
|
+
var len = this.length;
|
6
|
+
if (typeof fun != "function")
|
7
|
+
throw new TypeError();
|
8
|
+
|
9
|
+
var thisp = arguments[1];
|
10
|
+
for (var i = 0; i < len; i++)
|
11
|
+
{
|
12
|
+
if (i in this &&
|
13
|
+
fun.call(thisp, this[i], i, this))
|
14
|
+
return true;
|
15
|
+
}
|
16
|
+
|
17
|
+
return false;
|
18
|
+
};
|
19
|
+
}
|
1
20
|
function el(node) {
|
2
21
|
return document.getElementById(node);
|
3
22
|
}
|
@@ -86,6 +105,20 @@ var ajax = function(opts) {
|
|
86
105
|
req.send(null);
|
87
106
|
};
|
88
107
|
|
108
|
+
var ensureEvent = function(func) {
|
109
|
+
return function() {
|
110
|
+
var e = window.event;
|
111
|
+
e.target = e.srcElement;
|
112
|
+
e.preventDefault = function() {
|
113
|
+
e.returnValue = false;
|
114
|
+
};
|
115
|
+
e.stopPropagation = function() {
|
116
|
+
e.cancelBubble = true;
|
117
|
+
};
|
118
|
+
func.call(e.srcElement,e);
|
119
|
+
};
|
120
|
+
};
|
121
|
+
|
89
122
|
var listen = function(evnt, elem, func) {
|
90
123
|
if (elem.addEventListener) {
|
91
124
|
listen = function(evnt, elem, func) {
|
@@ -93,7 +126,7 @@ var listen = function(evnt, elem, func) {
|
|
93
126
|
};
|
94
127
|
} else if (elem.attachEvent) {
|
95
128
|
listen = function(evnt, elem, func) {
|
96
|
-
elem.attachEvent('on' + evnt, func);
|
129
|
+
elem.attachEvent('on' + evnt, ensureEvent(func));
|
97
130
|
};
|
98
131
|
}
|
99
132
|
listen(evnt,elem,func);
|
@@ -106,7 +139,7 @@ var unlisten = function(evnt, elem, func) {
|
|
106
139
|
};
|
107
140
|
} else if (elem.attachEvent) {
|
108
141
|
unlisten = function(evnt, elem, func) {
|
109
|
-
elem.detachEvent('on' + evnt, func);
|
142
|
+
elem.detachEvent('on' + evnt, ensureEvent(func));
|
110
143
|
};
|
111
144
|
}
|
112
145
|
unlisten(evnt,elem,func);
|
@@ -232,23 +265,24 @@ AssociationManager.prototype.addLinkToValue = function(id, value, linkIt) {
|
|
232
265
|
return '<a href="/edit/' + this.model + '/' + id + '">' + value + '</a>';
|
233
266
|
};
|
234
267
|
|
235
|
-
AssociationManager.prototype.
|
236
|
-
var
|
237
|
-
|
268
|
+
AssociationManager.prototype.appendRow = function(data) {
|
269
|
+
var tr = this.tbody.insertRow(-1);
|
270
|
+
var td = tr.insertCell(-1);
|
271
|
+
var cb = '<input type="' + this.selectorType + '" value="' + data.id + '" id="selection_' + this.model + '_' + data.id + '"';
|
238
272
|
if (this.relatedIds[data.id]) {
|
239
|
-
|
273
|
+
cb += ' checked="checked"';
|
240
274
|
}
|
241
275
|
if (this.selectorType == 'radio') {
|
242
|
-
|
276
|
+
cb += ' name="' + this.model + '_' + this.name + '_selection"';
|
243
277
|
}
|
244
|
-
|
278
|
+
cb += ' />';
|
279
|
+
addClass(td, 'checkbox active');
|
280
|
+
td.innerHTML = cb;
|
245
281
|
var linkIt = true;
|
246
282
|
for (var i = 0, len = this.fields.length; i < len; i++) {
|
247
283
|
if (i == 1) { linkIt = false; }
|
248
|
-
|
284
|
+
tr.insertCell(-1).innerHTML = this.addLinkToValue(data.id, (data[this.fields[i]] == null ? '-' : data[this.fields[i]]), linkIt);
|
249
285
|
}
|
250
|
-
out += '</tr>';
|
251
|
-
return out;
|
252
286
|
};
|
253
287
|
|
254
288
|
AssociationManager.prototype.clearTable = function() {
|
@@ -330,11 +364,9 @@ AssociationManager.prototype.searchResultsHandler = function(handler) {
|
|
330
364
|
handler.pageCountField.innerHTML = handler.pageCount;
|
331
365
|
handler.pageNumberField.innerHTML = handler.pageNumber;
|
332
366
|
if (data.results.length > 0) {
|
333
|
-
var out = [];
|
334
367
|
for (var i = 0, len = data.results.length; i < len; i++) {
|
335
|
-
|
368
|
+
handler.appendRow(data.results[i]);
|
336
369
|
}
|
337
|
-
handler.tbody.innerHTML = out.join('');
|
338
370
|
} else {
|
339
371
|
}
|
340
372
|
handler.toggleCheckboxes();
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div id="paging" class="paging">
|
2
|
+
<%= @count %> result<%= @count != 1 ? 's' : '' %>
|
3
|
+
<% if @page_count > 1 %>
|
4
|
+
/ Page <span class="page-number"><%= @p %></span> of <span class="page-count"><%= @page_count %></span> /
|
5
|
+
<% prev_link, next_link = paging_links(@p, @page_count, :q => params[:q], :o => params[:o]) %>
|
6
|
+
<%= prev_link %>
|
7
|
+
<%= next_link %>
|
8
|
+
<% end %>
|
9
|
+
<form method="get" id="search-form">
|
10
|
+
<fieldset>
|
11
|
+
<input type="text" name="q" value="<%= params[:q].blank? ? 'Search...' : params[:q] %>" size="40" />
|
12
|
+
</fieldset>
|
13
|
+
</form>
|
14
|
+
</div>
|
@@ -1,6 +1,9 @@
|
|
1
|
-
<h1><a href="/<%= @model.name %>"><%= @model.display_name %></a> / Edit</h1>
|
2
1
|
<form action="/update/<%= @model.name %>/<%= @content.id %>" method="post" id="edit-form">
|
3
|
-
<
|
2
|
+
<input type="hidden" name="return_url" value="<%= request.referer || '/locations' %>" />
|
3
|
+
<div id="subhead">
|
4
|
+
<h1><a href="/<%= @model.name %>"><%= @model.display_name %></a> / Edit</h1>
|
5
|
+
</div>
|
6
|
+
<div id="main">
|
4
7
|
<% if @errors %><div id="save_errors" class="errors"><%= @errors %></div><% end %>
|
5
8
|
<% @model.get_form_properties.each do |p| %>
|
6
9
|
<fieldset id="property-<%= p.name %>" class="<%= @model.field_class_for(p) %>">
|
@@ -9,13 +12,7 @@
|
|
9
12
|
<% end %>
|
10
13
|
</div>
|
11
14
|
<div class="actions">
|
12
|
-
<button type="submit" class="save">Save
|
15
|
+
<button type="submit" class="save">Save <%= @model.display_name.singularize %></button>
|
13
16
|
</div>
|
14
17
|
</form>
|
15
|
-
<div class="actions external">
|
16
|
-
<form action="/delete/<%= @model.name %>" method="post" id="delete-form">
|
17
|
-
<input type="hidden" id="delete-list" name="id" value="<%= @content.id %>" />
|
18
|
-
<button type="submit" id="delete-button">Delete</button>
|
19
|
-
</form>
|
20
|
-
</div>
|
21
18
|
<script type="text/javascript" src="/js/edit.js"></script>
|
@@ -1,53 +1,53 @@
|
|
1
|
-
<
|
2
|
-
<
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
<%= next_link %>
|
9
|
-
<% end %>
|
10
|
-
</div>
|
11
|
-
<form method="get" id="search-form">
|
12
|
-
<fieldset>
|
13
|
-
<input type="text" name="q" value="<%= params[:q].blank? ? 'Search...' : params[:q] %>" size="40" />
|
14
|
-
</fieldset>
|
15
|
-
</form>
|
16
|
-
<div class="wrapper">
|
17
|
-
<table id="list-table">
|
18
|
-
<thead>
|
19
|
-
<tr>
|
20
|
-
<% if not @content.empty? %>
|
21
|
-
<th></th>
|
22
|
-
<% end %>
|
23
|
-
<% @model.get_list_properties.each do |p| %>
|
24
|
-
<th><%= p.name.to_s.humanize.titleize %></th>
|
1
|
+
<div id="subhead">
|
2
|
+
<h1><%= @model.display_name %>
|
3
|
+
<div id="model-select">
|
4
|
+
<ul>
|
5
|
+
<% Togo.models.each do |m| %>
|
6
|
+
<% next if m == @model %>
|
7
|
+
<li><a href="/<%= m.name %>"><%= m.display_name %></a></li>
|
25
8
|
<% end %>
|
26
|
-
</
|
27
|
-
</
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
9
|
+
</ul>
|
10
|
+
</div>
|
11
|
+
</h1>
|
12
|
+
</div>
|
13
|
+
<div id="main">
|
14
|
+
<%= partial :_paging %>
|
15
|
+
<div class="list-table-wrapper">
|
16
|
+
<table cellspacing="0" id="list-table">
|
17
|
+
<thead>
|
18
|
+
<tr>
|
19
|
+
<% if not @content.empty? %>
|
20
|
+
<th> </th>
|
21
|
+
<% end %>
|
22
|
+
<% @model.get_list_properties.each do |p| %>
|
23
|
+
<th><%= column_head_link(p, @order, :q => params[:q], :p => params[:p]) %></th>
|
24
|
+
<% end %>
|
25
|
+
</tr>
|
26
|
+
</thead>
|
27
|
+
<tbody>
|
28
|
+
<% if @content.empty? %>
|
29
|
+
<tr>
|
30
|
+
<td colspan="<%= @model.get_list_properties.size %>"><% if params[:q] %>No results for '<%= params[:q] %>'<% else %>No content has been created yet.<% end %></td>
|
31
|
+
</tr>
|
32
|
+
<% else %>
|
33
|
+
<% @content.each do |c| %>
|
34
|
+
<tr>
|
35
|
+
<td class="checkbox"><input type="checkbox" name="selection[<%= c.id %>]" value="1" id="selection_<%= c.id %>" /></td>
|
36
|
+
<% @model.get_list_properties.each_with_index do |p,i| %>
|
37
|
+
<td><% if i == 0 %><a href="/edit/<%= @model.name %>/<%= c.id %>"><%= c.send(p.name.to_sym) || '-' %></a><% else %><%= c.send(p.name.to_sym) %><% end %></td>
|
38
|
+
<% end %>
|
39
|
+
</tr>
|
40
|
+
<% end %>
|
41
|
+
<% end %>
|
42
|
+
</tbody>
|
43
|
+
</table>
|
44
|
+
</div>
|
45
45
|
</div>
|
46
46
|
<div class="actions">
|
47
|
-
<a href="/new/<%= @model.name %>" class="action new" id="new-button">New</a>
|
48
47
|
<form action="/delete/<%= @model.name %>" method="post" id="delete-form">
|
49
48
|
<input type="hidden" id="delete-list" name="id" value="" />
|
50
49
|
<button type="submit" id="delete-button" disabled="disabled" onclick="return confirm('Are you sure you want to delete these items?');">Delete</button>
|
51
50
|
</form>
|
51
|
+
<button onclick="window.location='/new/<%= @model.name %>'; return false;">New...</button>
|
52
52
|
</div>
|
53
53
|
<script type="text/javascript" src="/js/index.js"></script>
|
@@ -1,24 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
4
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
5
3
|
<head>
|
6
4
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
|
7
5
|
<title>Togo Admin</title>
|
8
|
-
<link rel="stylesheet" href="/css/screen.css" />
|
6
|
+
<link rel="stylesheet" href="/css/screen.css" type="text/css" media="screen" />
|
9
7
|
<script type="text/javascript" src="/js/togo.js"></script>
|
10
8
|
</head>
|
11
|
-
<body>
|
12
|
-
<div id="
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
</
|
19
|
-
|
20
|
-
|
21
|
-
|
9
|
+
<body id="<%= @body_id %>">
|
10
|
+
<div id="container">
|
11
|
+
<div id="header">
|
12
|
+
<h1>Togo Admin</h1>
|
13
|
+
<div id="system-menu">
|
14
|
+
<span>System Menu</span>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
<div id="content">
|
18
|
+
<%= yield %>
|
19
|
+
</div>
|
22
20
|
</div>
|
23
21
|
</body>
|
24
22
|
</html>
|
@@ -1,6 +1,9 @@
|
|
1
|
-
<h1><a href="/<%= @model.name %>"><%= @model.display_name %></a> / New</h1>
|
2
1
|
<form action="/create/<%= @model.name %>" method="post" id="edit-form">
|
3
|
-
<
|
2
|
+
<input type="hidden" name="return_url" value="<%= request.referer || '/locations' %>" />
|
3
|
+
<div id="subhead">
|
4
|
+
<h1><a href="/<%= @model.name %>"><%= @model.display_name %></a> / New</h1>
|
5
|
+
</div>
|
6
|
+
<div id="main">
|
4
7
|
<% if @errors %><div id="save_errors" class="errors"><%= @errors %></div><% end %>
|
5
8
|
<% @model.get_form_properties.each do |p| %>
|
6
9
|
<fieldset id="property-<%= p.name %>" class="<%= @model.field_class_for(p) %>">
|
data/lib/togo/model/model.rb
CHANGED
@@ -1,4 +1,7 @@
|
|
1
1
|
require 'erubis/tiny'
|
2
|
+
%w( relationship_manager many_to_one one_to_many ).each{|l|
|
3
|
+
require "togo/model/relationship_manager/#{l}"
|
4
|
+
}
|
2
5
|
|
3
6
|
module Togo
|
4
7
|
module DataMapper
|
@@ -13,6 +16,8 @@ module Togo
|
|
13
16
|
base.send(:class_variable_set, :@@user_form_properties, [])
|
14
17
|
base.send(:class_variable_set, :@@custom_form_templates, {})
|
15
18
|
base.send(:class_variable_set, :@@property_options, {})
|
19
|
+
base.send(:class_variable_set, :@@inflector, (Extlib::Inflection rescue ActiveSupport::Inflector))
|
20
|
+
|
16
21
|
if MODELS.include?(base) # support code reloading
|
17
22
|
MODELS[MODELS.index(base)] = base # preserve order of which models were loaded
|
18
23
|
else
|
@@ -44,11 +49,11 @@ module Togo
|
|
44
49
|
end
|
45
50
|
|
46
51
|
def update_content!(id,attrs)
|
47
|
-
stage_content(get(id),attrs).save
|
52
|
+
stage_content(get(id),attrs).save
|
48
53
|
end
|
49
54
|
|
50
55
|
def create_content!(attrs)
|
51
|
-
stage_content(new,attrs).save
|
56
|
+
stage_content(new,attrs).save
|
52
57
|
end
|
53
58
|
|
54
59
|
def stage_content(content,attrs)
|
@@ -56,7 +61,7 @@ module Togo
|
|
56
61
|
relationships.each do |r|
|
57
62
|
val = attrs["related_#{r[0]}".to_sym]
|
58
63
|
next if not val or val == 'unset'
|
59
|
-
content = RelationshipManager.
|
64
|
+
content = RelationshipManager.create(content, r, :ids => val).relate
|
60
65
|
end
|
61
66
|
content
|
62
67
|
end
|
@@ -77,6 +82,7 @@ module Togo
|
|
77
82
|
q = "%#{opts[:q].gsub(/\s+/,'%')}%"
|
78
83
|
limit = opts[:limit]
|
79
84
|
offset = opts[:offset]
|
85
|
+
order = opts[:order]
|
80
86
|
conditions, values = [], []
|
81
87
|
search_properties.each{|l|
|
82
88
|
conditions << "#{l.name} like ?"
|
@@ -84,6 +90,7 @@ module Togo
|
|
84
90
|
}
|
85
91
|
params = {:conditions => [conditions.join(' OR ')] + values}
|
86
92
|
params.merge!(:limit => limit.to_i, :offset => offset.to_i) if limit and offset
|
93
|
+
params.merge!(:order => order) if order
|
87
94
|
all(params)
|
88
95
|
end
|
89
96
|
|
@@ -107,19 +114,27 @@ module Togo
|
|
107
114
|
|
108
115
|
def type_from_property(property)
|
109
116
|
case property
|
110
|
-
when ::DataMapper::Property
|
111
|
-
|
117
|
+
when ::DataMapper::Property::Text
|
118
|
+
'text'
|
119
|
+
when (defined?(::DataMapper::Property::Enum) and ::DataMapper::Property::Enum)
|
120
|
+
'string'
|
112
121
|
when ::DataMapper::Associations::ManyToMany::Relationship
|
113
122
|
'many_to_many'
|
114
123
|
when ::DataMapper::Associations::ManyToOne::Relationship
|
115
124
|
'belongs_to'
|
116
125
|
when ::DataMapper::Associations::OneToMany::Relationship
|
117
126
|
'has_n'
|
127
|
+
when ::DataMapper::Property
|
128
|
+
class_variable_get(:@@inflector).demodulize(property.type || property.primitive || property.class).downcase # type seems to be deprecated in 1.0
|
118
129
|
else
|
119
130
|
'string'
|
120
131
|
end
|
121
132
|
end
|
122
133
|
|
134
|
+
def is_extended_type?(property)
|
135
|
+
|
136
|
+
end
|
137
|
+
|
123
138
|
def pick_properties(selection, args)
|
124
139
|
if class_variable_get(:"@@#{selection}_properties").empty?
|
125
140
|
args = shown_properties.map{|p| p.name} if args.empty?
|
@@ -146,38 +161,5 @@ module Togo
|
|
146
161
|
end
|
147
162
|
|
148
163
|
end # Model
|
149
|
-
|
150
|
-
class RelationshipManager
|
151
|
-
def initialize(content, relationship, opts = {})
|
152
|
-
@content = content
|
153
|
-
@relationship = relationship[1]
|
154
|
-
@relationship_name = relationship[0]
|
155
|
-
@ids = (opts[:ids] || '').split(',').map(&:to_i)
|
156
|
-
define_values
|
157
|
-
end
|
158
|
-
|
159
|
-
def relate
|
160
|
-
@content.send("#{@relationship_name}=", find_for_assignment)
|
161
|
-
@content
|
162
|
-
end
|
163
|
-
|
164
|
-
def define_values
|
165
|
-
case @relationship
|
166
|
-
when ::DataMapper::Associations::ManyToOne::Relationship
|
167
|
-
@unset_value = nil
|
168
|
-
@related_model = @relationship.parent_model
|
169
|
-
@find_op = Proc.new{|p| p.get(@ids.first)}
|
170
|
-
when ::DataMapper::Associations::OneToMany::Relationship
|
171
|
-
@unset_value = []
|
172
|
-
@related_model = @relationship.child_model
|
173
|
-
@find_op = Proc.new{|p| p.all(:id => @ids)}
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def find_for_assignment
|
178
|
-
return @unset_value if @ids.blank?
|
179
|
-
@find_op.call(@related_model)
|
180
|
-
end
|
181
|
-
end # RelationshipManager
|
182
164
|
end # DataMapper
|
183
165
|
end # Togo
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Togo
|
2
|
+
module DataMapper
|
3
|
+
|
4
|
+
class ManyToOne < RelationshipManager
|
5
|
+
def unset_value
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def related_model
|
10
|
+
@relationship.parent_model
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_for_assignment
|
14
|
+
related_model.get(@ids.first)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end # DataMapper
|
19
|
+
end # Model
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Togo
|
2
|
+
module DataMapper
|
3
|
+
|
4
|
+
class OneToMany < RelationshipManager
|
5
|
+
def unset_value
|
6
|
+
[]
|
7
|
+
end
|
8
|
+
|
9
|
+
def related_model
|
10
|
+
@relationship.child_model
|
11
|
+
end
|
12
|
+
|
13
|
+
def find_for_assignment
|
14
|
+
related_model.all(:id => @ids)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end # DataMapper
|
19
|
+
end # Model
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Togo
|
2
|
+
module DataMapper
|
3
|
+
class RelationshipManager
|
4
|
+
|
5
|
+
def self.create(content, relationship, opts = {})
|
6
|
+
case relationship[1]
|
7
|
+
when ::DataMapper::Associations::ManyToOne::Relationship
|
8
|
+
ManyToOne.new(content, relationship, opts)
|
9
|
+
when ::DataMapper::Associations::OneToMany::Relationship
|
10
|
+
OneToMany.new(content, relationship, opts)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(content, relationship, opts = {})
|
15
|
+
@content = content
|
16
|
+
@relationship = relationship[1]
|
17
|
+
@relationship_name = relationship[0]
|
18
|
+
@ids = (opts[:ids] || '').split(',').map(&:to_i)
|
19
|
+
end
|
20
|
+
|
21
|
+
def relate
|
22
|
+
@content.send("#{@relationship_name}=", find_for_assignment)
|
23
|
+
@content
|
24
|
+
end
|
25
|
+
|
26
|
+
def unset_values
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
|
30
|
+
def related_model
|
31
|
+
raise NotImplementedError
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_for_assignment
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end # DataMapper
|
40
|
+
end # Togo
|
@@ -5,49 +5,51 @@
|
|
5
5
|
<input type="hidden" name="related_<%= property.name %>" class="related_ids" value="unset" />
|
6
6
|
<label for="<%= property.name %>"><%= related_model.display_name %></label>
|
7
7
|
<div class="search" id="search-<%= related_model.name %>">
|
8
|
-
<input type="text" name="search-<%= property.name %>" value="Search..." />
|
9
8
|
<div class="paging">
|
10
|
-
|
11
|
-
<
|
9
|
+
<input type="text" name="search-<%= property.name %>" value="Search..." />
|
10
|
+
Page <span class="page-number">1</span> of <span class="page-count"><%= (content_count/10).ceil %></span> /
|
11
|
+
<a href="#" rel="prev">Previous</a> <a href="#" rel="next">Next</a>
|
12
12
|
</div>
|
13
13
|
</div>
|
14
|
-
<table>
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
</
|
14
|
+
<div class="list-table-wrapper">
|
15
|
+
<table cellspacing="0">
|
16
|
+
<thead>
|
17
|
+
<tr>
|
18
|
+
<th class="checkbox"> </th>
|
19
|
+
<% related_model.get_list_properties.each do |p| %>
|
20
|
+
<th><%= p.name.to_s.humanize.titleize %></th>
|
21
|
+
<% end %>
|
22
|
+
</tr>
|
23
|
+
</thead>
|
24
|
+
<tfoot>
|
25
|
+
<tr>
|
26
|
+
<td class="checkbox"></td>
|
27
|
+
<td colspan="<%= related_model.get_list_properties.size %>">
|
28
|
+
<span class="associated-count-display" style="display: none;">
|
29
|
+
...and <span class="associated-count"><%= content_count-related_content.size %></span> more associated items
|
30
|
+
</span>
|
31
|
+
<button class="association-modify">Modify</button>
|
32
|
+
</td>
|
33
|
+
</tr>
|
34
|
+
</tfoot>
|
35
|
+
<tbody>
|
36
|
+
<% if related_content.empty? %>
|
37
|
+
<tr>
|
38
|
+
<td colspan="<%= related_model.get_list_properties.size %>">No Content Associated.</td>
|
39
|
+
</tr>
|
40
|
+
<% else %>
|
41
|
+
<% related_content.each do |c| %>
|
42
|
+
<tr>
|
43
|
+
<td class="checkbox"><input type="radio" name="selection[<%= c.id %>]" value="<%= c.id %>" id="selection_<%= related_model.name %>_<%= c.id %>" checked="checked" /></td>
|
44
|
+
<% related_model.get_list_properties.each_with_index do |p,i| %>
|
45
|
+
<td><% if i == 0 %><a href="/edit/<%= related_model.name %>/<%= c.id %>"><%= c.send(p.name.to_sym) || '-' %></a><% else %><%= c.send(p.name.to_sym) %><% end %></td>
|
46
|
+
<% end %>
|
47
|
+
</tr>
|
48
|
+
<% end %>
|
49
|
+
<% end %>
|
50
|
+
</tbody>
|
51
|
+
</table>
|
52
|
+
</div>
|
51
53
|
<script type="text/javascript">
|
52
54
|
new AssociationManager({
|
53
55
|
relationship: 'belongs_to',
|