faalis 0.16.3 → 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/app/views/angularjs_templates/modules.html +1 -1
  3. data/lib/faalis.rb +2 -0
  4. data/lib/faalis/generators.rb +1 -0
  5. data/lib/faalis/generators/concerns.rb +9 -0
  6. data/lib/faalis/generators/concerns/angular.rb +31 -0
  7. data/lib/faalis/generators/concerns/bulk.rb +36 -0
  8. data/lib/faalis/generators/concerns/dependency.rb +14 -0
  9. data/lib/faalis/generators/concerns/menu.rb +29 -0
  10. data/lib/faalis/generators/concerns/parent.rb +35 -0
  11. data/lib/faalis/generators/concerns/required.rb +22 -0
  12. data/lib/faalis/generators/concerns/resource_fields.rb +82 -0
  13. data/lib/faalis/generators/concerns/resource_name.rb +42 -0
  14. data/lib/faalis/generators/concerns/tabs.rb +40 -0
  15. data/lib/faalis/generators/dashboard_scaffold.rb +35 -0
  16. data/lib/faalis/generators/fields/relation.rb +28 -0
  17. data/lib/faalis/version.rb +1 -1
  18. data/lib/generators/faalis/js/list_view_generator.rb +110 -0
  19. data/lib/generators/faalis/js_scaffold_generator.rb +4 -251
  20. data/lib/generators/faalis/templates/angularjs/module.js.erb +1 -1
  21. data/lib/generators/faalis/templates/js/list_view/README +31 -0
  22. data/lib/generators/faalis/templates/js/list_view/details.html.erb +20 -0
  23. data/lib/generators/faalis/templates/js/list_view/index.html.erb +62 -0
  24. data/lib/generators/faalis/templates/js/list_view/module.js.erb +333 -0
  25. data/lib/generators/faalis/templates/js/list_view/new.html.erb +62 -0
  26. metadata +338 -328
  27. data/app/assets/javascripts/faalis/dashboard/gen-doc.sh~ +0 -3
  28. data/spec/dummy/log/development.log +0 -0
  29. data/spec/dummy/log/test.log +0 -15
  30. data/spec/dummy/tmp/ember-rails/ember-data.js +0 -10204
  31. data/spec/dummy/tmp/ember-rails/ember.js +0 -36991
@@ -0,0 +1,20 @@
1
+ <div class="details">
2
+ <% fields.each do |field_name, field_type| %>
3
+ <p>
4
+ <% case field_type
5
+ when "belongs_to" %> <b translate><%= field_name.capitalize %> :</b> {{object.<%= field_name %>.name}}
6
+ <% when "has_many" %><p>
7
+ <b translate><%= field_name.capitalize %> :</b>
8
+ <ul>
9
+ <li ng-repeat="item in object.<%= field_name %>"> {{ item.name }}</li>
10
+ </ul>
11
+ </p>
12
+ <% else %><b translate><%= field_name.capitalize %> :</b> {{object.<%= field_name %>}}
13
+ <% end %></p>
14
+ <% end %>
15
+ <ul class="button-group float-right">
16
+ <a ng-href="#/<%= resource_url %>/{{ object.id }}/edit" class="small">
17
+ <span class="fa fa-edit"></span> <span translated>Edit</span>
18
+ </a>
19
+ </ul>
20
+ </div>
@@ -0,0 +1,62 @@
1
+ <% unless options[:no_filter] %>
2
+ <filter config="filter_config" result="<%= resource.pluralize.underscore %>"></filter>
3
+ <% end %>
4
+ <% unless options[:no_bulk] %>
5
+ <div ng-if="bulk_edit" class="fade_anim">
6
+ <form id="bulk_form">
7
+ <fieldset class="row clearmargin">
8
+ <legend translate>Bulk Edit</legend>
9
+ <div class="row">
10
+ <div class="small-6 columns">
11
+ <label for="field_name" translate>Field Name:</label>
12
+
13
+ <select id="field_name" ng-model="field_name" ng-change="field_name_change()">
14
+ <option value="0" selected translate>-- Select a field --</option>
15
+ <option ng-repeat="field in fields" value="{{ field.name }}" data-type="{{ field.type }}" data-to="{{ field.to }}"><span translate>{{ field.title }}</span></option>
16
+ </select>
17
+ </div>
18
+ <div class="small-6 columns">
19
+ <label for="field_value" translate>Field Value:</label>
20
+ <div id="value_field">
21
+ <input id="field_value" ng-model="field_value" type="text" ng-if="current_field.type == 'string' || current_field.type == 'integer'">
22
+ <textarea id="field_value" ng-model="field_value" ng-if="current_field.type == 'text'"></textarea>
23
+
24
+ <select id="field_value" ng-model="field_value" ng-if="current_field.type == 'belongs_to'">
25
+ <option ng-repeat="item in cache[current_field.name]" value="{{ item.id }}">{{ item.name }}</option>
26
+ </select>
27
+ <select id="field_value" ng-model="field_value" ng-if="current_field.type == 'has_many'" multiple>
28
+ <option ng-repeat="item in cache[current_field.name]" value="{{ item.id }}">{{ item.name }}</option>
29
+ </select>
30
+ </div>
31
+ </div>
32
+ </div>
33
+ <div class="row progressbar-container" ng-if="view_progressbar">
34
+ <div class="small-12 columns">
35
+ <div class="progressbar">
36
+ <div id="request_filler" class="filler yellow" style="width: {{ rfiller}};"></div>
37
+ <div id="success_filler" class="filler green" style="width: {{ sfiller}};"></div>
38
+ </div>
39
+ </div>
40
+ <div class="row">
41
+ <div class="small-3 columns float-right text-right">
42
+ <small>
43
+ {{ success }} <span translate>of</span> {{ total }}<span ng-if="failed > 0"> - <span translate>field:</span><span class="text-error"> {{ failed }}</span></span>
44
+ </small>
45
+ </div>
46
+ </div>
47
+ </fieldset>
48
+ <br />
49
+ <div class="row">
50
+ <div class="small-6 columns">
51
+ <button class="btn tiny green" ng-click="bulk_save()"><i class="fa fa-check"></i> <span translate>Save</span></button>
52
+ <button class="btn tiny red" ng-click="bulk_cancel()"><i class="fa fa-times"></i> <span translate>Cancel</span></button>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </div>
57
+ <% end %>
58
+ <list-view buttons="buttons" model="'<%= resource %>'" objects="<%= resource.pluralize.underscore %>" title-attribute="'<%= options[:title_field] %>'" details-template="details_template" item-per-page="10" on_delete="on_delete" column_defs="columns">
59
+ <div class="small-6 column text-left clearpadding">
60
+ <h3><i class="fa fa-group"></i> <span translate><%= resource.underscore.pluralize.humanize %></span></h3>
61
+ </div>
62
+ </list-view>
@@ -0,0 +1,333 @@
1
+ <% if is_in_engine? %>
2
+ /* -----------------------------------------------------------------------------
3
+ Faalis - Basic website skel engine
4
+ Copyright (C) 2012-2013 Yellowen
5
+
6
+ This program is free software; you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation; either version 2 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License along
17
+ with this program; if not, write to the Free Software Foundation, Inc.,
18
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
+ ----------------------------------------------------------------------------- */
20
+
21
+ <% end %>
22
+ // <%= resource.pluralize %> Module
23
+ var <%= resource.pluralize %> = angular.module("<%= resource %>", ["ListView", "Filter", "Anim", "Fields",<% if options[:deps] %><% options[:deps].gsub(" ", "").split(",").each do |dependency| %> "<%= dependency.camelize %>", <% end %><% end %>]);
24
+
25
+ // <%= resource.pluralize %> configuration section ---------------------------
26
+ <%= resource.pluralize %>.config(["$routeProvider", function($routeProvider){
27
+
28
+ // Add any route you need here
29
+ $routeProvider.
30
+ when("<% if parent? %>/<%= options[:parent] %>/:<%= options[:parent] %>_id<% end %>/<%= resource_url %>", {
31
+ templateUrl: template("<%= resource_path %>/index"),
32
+ controller: "<%= resource %>Controller"
33
+ }).
34
+ when("<% if parent? %>/<%= options[:parent] %>/:<%= options[:parent] %>_id<% end %>/<%= resource_url %>/new",{
35
+ templateUrl: template("<%= resource_path %>/new"),
36
+ controller: "Add<%= resource %>Controller"
37
+ }).
38
+ when("<% if parent? %>/<%= options[:parent] %>/:<%= options[:parent] %>_id<% end %>/<%= resource_url %>/:id/edit",{
39
+ templateUrl: template("<%= resource_path %>/new"),
40
+ controller: "Add<%= resource %>Controller"
41
+ });
42
+
43
+ }]);
44
+
45
+ // <%= resource %> index controller -------------------------------------------------------
46
+ // This controller is responsible for list page (index)
47
+ <%= resource.pluralize %>.controller("<%= resource %>Controller", ["$scope", "gettext", "Restangular", "catch_error", "$location", "$routeParams",
48
+ function($scope, gettext, API, catch_error, $location, $routeParams){
49
+
50
+ <% if parent? %>
51
+ var <%= options[:parent] %>_id = $routeParams.<%= options[:parent] %>_id;
52
+ <% end %>
53
+ <% unless options[:no_filter] %>$scope.filter_config = {
54
+ list: API.all("<%= resource.pluralize.underscore %>")
55
+ };
56
+ $scope.<%= resource.pluralize.underscore %> = [];<% end %>
57
+ <% unless options[:no_bulk] %>// Cache object for each field name possible values
58
+ $scope.cache = {};
59
+
60
+ // Change event handler for field_name combobox in bulk edit
61
+ $scope.field_name_change = function(x){
62
+ var current_value = $("#field_name").val();
63
+ $scope.current_field= _.find($scope.fields, function(x){
64
+ return x.name == current_value;
65
+ });
66
+ if( "to" in $scope.current_field ){
67
+ if (! ($scope.current_field.name in $scope.cache)) {
68
+ $scope.current_field.to().then(function(x){
69
+ $scope.cache[$scope.current_field.name] = x;
70
+ });
71
+ }
72
+ }
73
+ };
74
+
75
+ $scope.columns = [<% grid_fields.each do |name, type| %>
76
+ {field:'<%= name %>', displayName: gettext('<%= name.capitalize.humanize %>')},
77
+ <% end %>];
78
+ $scope.fields = [<% bulk_edit_fields.each do |name| %>
79
+ {
80
+ name: "<%= name %><% if ["belongs_to", "has_many"].include? fields_hash[name] %>_id<% end %>",
81
+ title: gettext("<%= name.capitalize.humanize %>"),
82
+ type: "<%= fields_hash[name] %>"<% if ["belongs_to", "has_many"].include? fields_hash[name] %>,
83
+ to: API.all("<%= fields_hash[name].to %>").getList<% end %>
84
+ },<% end %>
85
+ ];<% end %>
86
+
87
+ // details_template is the address of template which should load for
88
+ // each item details section
89
+ $scope.details_template = template("<%= resource_path %>/details");
90
+
91
+ // Buttons for top of the list-view
92
+ $scope.buttons = [
93
+ {
94
+ title: gettext("New"),
95
+ icon: "fa fa-plus",
96
+ classes: "btn tiny green",
97
+ permission: {
98
+ name: "create",
99
+ model: "<%= resource.classify %>"
100
+ },
101
+ route: "#<% if parent? %>/<%= options[:parent] %>/" + <%= options[:parent] %>_id + "<% end %>/<%= resource_url %>/new"
102
+
103
+ },<% unless options[:no_bulk] %>
104
+ {
105
+ title: gettext("Bulk Edit"),
106
+ icon: "fa fa-edit",
107
+ classes: "btn tiny yellow",
108
+ permission: {
109
+ name: "update",
110
+ model: "<%= resource.classify %>"
111
+ },
112
+ action: function(){
113
+ $scope.$apply("bulk_edit = ! bulk_edit");
114
+ },
115
+
116
+ },<% end %>
117
+ {
118
+ title: gettext("Duplicate"),
119
+ icon: "fa fa-files-o",
120
+ classes: "btn tiny red",
121
+ permission: {
122
+ name: "create",
123
+ model: "<%= resource.classify %>"
124
+ },
125
+ action: function(){
126
+ var selected = _.find($scope.<%= resource.pluralize.underscore %>, function(x){
127
+ return x.is_selected === true;
128
+ });
129
+
130
+ if (selected === undefined ) {
131
+ error_message(gettext("You should only select one item to copy."));
132
+ }
133
+ else {
134
+ $location.path("/<%= resource.pluralize.underscore %>/-" + selected.id + "/edit");
135
+ }
136
+ }
137
+ }
138
+
139
+ ];<% unless options[:no_bulk] %>
140
+
141
+ /*
142
+ * On bulk save event
143
+ */
144
+ $scope.bulk_save = function(){
145
+
146
+ $scope.view_progressbar = true;
147
+ var value = $("#field_value").val();
148
+ var field = $scope.current_field.name;
149
+ var type = $scope.current_field.type;
150
+ var field_name = $scope.current_field.title;
151
+ if ((type == "has_many") || (type == "belongs_to")) {
152
+ value = parseInt(value, 10);
153
+ }
154
+ var requests_count = 0;
155
+
156
+ $scope.rfiller = 0;
157
+ $scope.sfiller = 0;
158
+ $scope.success = 0;
159
+ $scope.failed = 0;
160
+ $scope.total = _.where($scope.<%= resource.pluralize.underscore %>, function(x){return x.is_selected === true;}).length;
161
+
162
+ _.each($scope.<%= resource.pluralize.underscore %>, function(x){
163
+ if( x.is_selected === true ){
164
+ x[field] = value;
165
+ requests_count++;
166
+
167
+ var rwidth = (requests_count * 100) / $scope.total;
168
+ if (requests_count == $scope.total) { rwidth = 100; }
169
+ $scope.rfiller = rwidth + "%";
170
+
171
+ API.one("<%= resource.pluralize.underscore %>", x.id).patch(x).then(function(data){
172
+ $scope.success++;
173
+ var swidth = parseInt(($scope.success * 100) / $scope.total);
174
+ if ($scope.sucess == $scope.total) { swidth = 100; }
175
+ $scope.sfiller = swidth + "%";
176
+ x[field_name.toLowerCase()] = data[field_name.toLowerCase()];
177
+ }, function(data){
178
+ $scope.failed++;
179
+ catch_error(data);
180
+ });
181
+
182
+ }
183
+ });
184
+
185
+ };
186
+
187
+ /*
188
+ * On bulk cancel event
189
+ */
190
+ $scope.bulk_cancel = function(){
191
+ $("#field_name").val(0);
192
+ document.getElementById("bulk_form").reset();
193
+ $scope.view_progressbar = false;
194
+ $scope.bulk_edit = false;
195
+ };
196
+ <% end %>
197
+ /*
198
+ * On delete event handler - `items` is an array of objects to delete
199
+ */
200
+ $scope.on_delete = function(items){
201
+
202
+ var query = [];
203
+ items.forEach(function(item){
204
+ query.push(item.id);
205
+ });
206
+
207
+ API.all("<%= resource.pluralize.underscore %>").customDELETE(query.join(","))
208
+ .then(function(data) {
209
+
210
+ $scope.<%= resource.pluralize.underscore %> = _.filter($scope.<%= resource.pluralize.underscore %>, function(x){
211
+ return !(query.indexOf(x.id) != -1);
212
+ });
213
+ success_message(data.msg);
214
+ }, function(data){
215
+ catch_error(data);
216
+ });
217
+
218
+ };
219
+ <% unless options[:no_filter] %>/*<% end %>
220
+ <% if parent? %>API.one("<%= trim_parent_path %>", <%= options[:parent] %>_id).all("<%= resource.pluralize.underscore %>").getList()<% else %>
221
+ API.all("<%= resource.pluralize.underscore %>").getList()<% end %>
222
+ .then(function(data){
223
+ $scope.<%= resource.pluralize.underscore %> = data;
224
+ }, function(data){
225
+ catch_error(data);
226
+ });
227
+ <% unless options[:no_filter] %>*/<% end %>
228
+ }]);
229
+
230
+ <%= resource.pluralize %>.controller("Add<%= resource %>Controller", ["Restangular", "$scope", "$location", "$routeParams", "gettext", "catch_error", function(API, $scope, $location, $routeParams, gettext, catch_error){
231
+
232
+ <% if parent? %>
233
+ var <%= options[:parent] %>_id = $routeParams.<%= options[:parent] %>_id;
234
+ <% end %>
235
+
236
+ $scope.select2options = {};
237
+ $scope.editing = false;<% if any_tabs? %>
238
+ $scope.current_tab = 1;
239
+ $scope.activate_tab = function(tab, $event){
240
+ $scope.current_tab = tab;
241
+ };<% end %>
242
+ $scope.obj_id = null;
243
+ var is_copy = false;
244
+
245
+ <% fields.each do |name, type| %><% if ["belongs_to", "in", "has_many"].include? type %>
246
+ $scope.<%= name %>_data = {
247
+ type: '<%= type %>',<% if type == "in" %>
248
+ choices: _.sortBy([<% type.to.split(",").each do |choice| %>{name: "<%= choice.underscore %>", title: "<%= choice.humanize %>"},<% end %>]),<% else %>
249
+ to: '<%= type.to %>',<% end %>
250
+ name: '<%= name %>'
251
+ };<% end %><% end %>
252
+ <% fields.each do |name, type| %><% if type == "in" %>$scope.<%= name %>_choices = _.sortBy([<% type.to.split(",").each do |choice| %>
253
+ {name: "<%= choice.underscore %>", title: "<%= choice.humanize %>"},<% end %>
254
+ ], "title");<% end %><% end %>
255
+ if( "id" in $routeParams ){
256
+ $scope.obj_id = $routeParams.id;
257
+ $scope.editing = true;
258
+ if ($scope.obj_id < 0) {
259
+ is_copy = true;
260
+ $scope.obj_id = $scope.obj_id * -1;
261
+ }
262
+
263
+ var obj = API.one("<%= resource.pluralize.underscore %>", $scope.obj_id).get()
264
+ .then(function(data) {
265
+ <% fields.each do |field_name, field_type| %>
266
+ $scope.<%= field_name %> = <% if not ["string", "integer", "belongs_to", "text", "has_many", "in"].include? field_type %><%= "to_#{field_type}(data.#{field_name})" %><% elsif field_type == "belongs_to" %>data.<%= field_name %>.id<% else %>data.<%= field_name %><% end %>;<% end %>
267
+ }, function(data){
268
+ catch_error(data);
269
+ });
270
+
271
+ }
272
+
273
+ $scope.have = function(field, obj_id) {
274
+ var tmp = _.where($scope[field], {id: obj_id});
275
+ if (tmp.length > 0) {
276
+ return true;
277
+ }
278
+ else {
279
+ return false;
280
+ }
281
+ };
282
+
283
+ $scope.cancel = function(){
284
+ $(".form input").val("");
285
+ $location.path("#<% if parent? %>/<%= options[:parent] %>/" + <%= options[:parent] %>_id + "<% end %>/<%= resource_url %>");
286
+ };
287
+
288
+ $scope.save = function(save_another){
289
+ $("small.error").html("");
290
+ $("small.error").removeClass("error");
291
+
292
+ var <%= resource.underscore %> = {<%= resource.underscore %>: {<% fields.each do |field_name, field_type| %>
293
+ <% if ["belongs_to"].include? field_type %><%= field_name %>_id: parseInt($scope.<%= field_name %>),<% else %><%= field_name %>: $scope.<%= field_name %>,<% end %><% end %>
294
+ __res__: 0
295
+ }};
296
+ if (($scope.obj_id) && (is_copy === false)) {
297
+
298
+ API.one("<%= resource.pluralize.underscore %>", $scope.obj_id).patch(<%= resource.underscore %>)
299
+ .then(function(){
300
+ success_message(gettext("<%= resource %> updated successfully."));
301
+ if (save_another) {
302
+ $(".form input").val("");
303
+ }
304
+ else {
305
+ $location.path("<%= resource_url %>");
306
+ }
307
+ }, function(data){
308
+ catch_error(data);
309
+ });
310
+
311
+ }
312
+ else {
313
+ API.all("<%= resource.pluralize.underscore %>").customPOST(<%= resource.underscore %>, "").then(function(){
314
+ success_message(gettext("<%= resource %> created successfully."));
315
+ if (save_another) {
316
+ $(".form input").val("");
317
+ }
318
+ else {
319
+ $location.path("<%= resource_url %>");
320
+ }
321
+ }, function(data){
322
+ catch_error(data);
323
+ });
324
+ }
325
+
326
+ };
327
+ }]);
328
+ <% unless options[:menu].empty? %>
329
+ <%= resource.pluralize %>.controller("<%= resource %>MenuController", ["gettext", function(gettext){
330
+ this.menu_items = [<% options[:menu].split(",").each do |menu| %><% title, url, model = parse_menu(menu) %>
331
+ {title: gettext("<%= title %>"), url: "<%= url %>"<% if model %>, permission: {action: "read", model: "<%= model %>"}<% end %>},<% end %>
332
+ ];
333
+ }]);<% end %>
@@ -0,0 +1,62 @@
1
+ <% if any_tabs? %><section class="tabs"><% tab_count = 1 %>
2
+ <ul><% tabs.each do |name, fields| %>
3
+ <li ng-click="activate_tab(<%= tab_count %>)" ng-class="{active: current_tab == <%= tab_count %>, tab<%= tab_count %>: current_tab == <%= tab_count %>}"><span translate><%= name %></span></li> |<% tab_count += 1 %><% end %>
4
+ </ul>
5
+ </section><% end %>
6
+
7
+ <% unless any_tabs? %>
8
+ <form novalidate name="form">
9
+ <div class="newform">
10
+ <fieldset class="form">
11
+
12
+ <legend ng-if="!editing"><span translate>New <%= resource.underscore.pluralize.humanize %></span></legend>
13
+ <legend ng-if="editing"><span translate>Edit <%= resource.underscore.pluralize.humanize %></span></legend>
14
+
15
+ <% first = true %><% fields.each do |field_name, field_type| %>
16
+ <% if first %><div class="row"><% end %>
17
+ <div class="small-4 columns <% if not first %>float-left small-offset-2<% end %>">
18
+ <label><% if required_fields.include? field_name %><i class="inline fa fa-asterisk"></i> <% end %><span translate><%= field_name.to_s.humanize.capitalize %></span> :</label><% case field_type
19
+ when "belongs_to", "has_many", "in" %>
20
+ <relation-field select2-options="select2options" <% if required_fields.include? field_name %>required="true"<% end %> title-field="'name'" model="<%= field_name %>" field-data="<%= field_name %>_data">
21
+ </relation-field>
22
+ <% when nil %>
23
+ <string-field model="<%= field_name %>" field-name="'<%= field_name %>'" css-class="'rounded <%= field_type %>_field'" <% if required_fields.include? field_name %>required<% end %>></string-field>
24
+ <% else %>
25
+ <<%= field_type%>-field model="<%= field_name %>" field-name="'<%= field_name %>'" css-class="'rounded <%= field_type %>_field'" <% if required_fields.include? field_name %>required="true"<% end %>></<%= field_type%>-field><% end %>
26
+ </div>
27
+ <% if not first %></div><% end %><% first = !first %><% end %>
28
+ </fieldset>
29
+ </form>
30
+
31
+ <% else %><form novalidate name="form"><% tab_count = 1 %><% tabs.each do |name, field_names| %>
32
+ <div class="newform">
33
+ <fieldset class="form" ng-show="current_tab == <%= tab_count %>">
34
+ <legend ng-if="!editing"><span translate>New <%= name %></span></legend>
35
+ <legend ng-if="editing"><span translate>Edit <%= name %></span></legend><% first = true %>
36
+ <% fields.each do |field_name, field_type| %><% if tabs[name].include? field_name or tabs[name].include? "__all__" %>
37
+
38
+ <% if first %><div class="row"><% end %>
39
+ <div class="small-4 columns <% if not first %>float-left small-offset-2<% end %>">
40
+ <label><% if required_fields.include? field_name %><i class="inline fa fa-asterisk"></i> <% end %><span translate><%= field_name.to_s.humanize.capitalize %></span> :</label><% case field_type
41
+ when "belongs_to", "has_many", "in" %>
42
+ <relation-field select2-options="select2options" <% if required_fields.include? field_name %>required="true"<% end %> title-field="'name'" model="<%= field_name %>" field-data="<%= field_name %>_data">
43
+ </relation-field>
44
+ <% when nil %>
45
+ <string-field model="<%= field_name %>" field-name="'<%= field_name %>'" css-class="'rounded <%= field_type %>_field'" <% if required_fields.include? field_name %>required<% end %>></string-field>
46
+ <% else %>
47
+ <<%= field_type%>-field model="<%= field_name %>" field-name="'<%= field_name %>'" css-class="'rounded <%= field_type %>_field'" <% if required_fields.include? field_name %>required="true"<% end %>></<%= field_type%>-field><% end %>
48
+ </div>
49
+ <% if not first %></div><% end %><% first = !first %><% end %><% end %>
50
+ </fieldset>
51
+ </div><% tab_count += 1 %><% end %>
52
+ </form>
53
+ <% end %>
54
+
55
+ <div class="row">
56
+ <div class="small-6 columns">
57
+ <button class="btn small green" ng-click="save(false)" ng-disabled="form.$invalid || !form.$dirty"><i class="fa fa-check"></i> <span translate>Save</span></button>
58
+ <button class="btn small blue" ng-click="save(true)" ng-disabled="form.$invalid || !form.$dirty"><i class="fa fa-check"></i> <span translate>Save & Add Another</span></button>
59
+ <button class="btn small red" ng-click="cancel()"><i class="fa fa-times"></i> <span translate>Cancel</span></button>
60
+ </div>
61
+ </div>
62
+ </div>