faalis 0.16.3 → 0.17.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.
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>