togo 0.4.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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',
|