vue_crud 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7a3968959d978911425d23ccc57bad7a6e520b1d
4
+ data.tar.gz: e22d398e429375cb72eb45068d691f8e8db1201d
5
+ SHA512:
6
+ metadata.gz: 68fcb6ff3f771628a6d82db744af6e76d87b9e143dea98ab6736a9412d0cd59a82ecc938279c0098fe1e73d6bf43dffea411d7dba191dc6f6e2f0ca1fe478fe2
7
+ data.tar.gz: b57aad62dbf33091b101f4128cabb298a8e73952fa28570a9b7504dbe174c8cd67cd6a19b7020b28d4104ca0cea5a9ce1a5934d6c32f0f6a08e9975a39e3868a
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.0
5
+ before_install: gem install bundler -v 1.13.4
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in vue_crud.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # VueCrud
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/vue_crud`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'vue_crud'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install vue_crud
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/vue_crud.
36
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :test
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "vue_crud"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,11 @@
1
+ #lib/generators/gemname/install_generator.rb
2
+ require 'rails/generators'
3
+ module VueCrud
4
+ class InstallGenerator < Rails::Generators::Base
5
+ source_root File.expand_path("../templates", __FILE__)
6
+
7
+ def copy_template_file
8
+ copy_file "vue_crud.html", "public/vue_crud.html"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,221 @@
1
+ <script type="text/javascript">
2
+ $(document).ready(function() {
3
+ $('.vue_form_for_new').html($('#vue_form').html());
4
+ var model_row = $($('#model-row').html());
5
+ model_row.find('.custom_model_row').html(
6
+ $('#custom_model_row').html()
7
+ );
8
+ model_row.find('.custom_action').html(
9
+ $('#custom_action').html()
10
+ );
11
+ model_row.find('.vue_form_for_edit').html(
12
+ $('#vue_form').html()
13
+ );
14
+ model_row.find('.custom_modal_body').html(
15
+ $('#custom_modal_body').html()
16
+ );
17
+ model_row.find('.custom_modal_action').html(
18
+ $('#custom_modal_action').html()
19
+ );
20
+
21
+ $('#model-row').html(model_row);
22
+ vue_init();
23
+ $('.filter .ui.dropdown').dropdown();
24
+ });
25
+ </script>
26
+
27
+
28
+ <div id="models">
29
+ <input type="text" name="progress" id="form-progress">
30
+ <h1 class="ui header">
31
+ {{ info.titles.title }}
32
+ <div class="sub header"><small>{{ info.titles.subtitle }}</small></div>
33
+ </h1>
34
+ <div class="ui blue button" data-modal="#modelModal">Add</div>
35
+ <div class="ui divider"></div>
36
+ <!-- NOTE: Filter -->
37
+ <div class="ui left action right icon labeled input filter" :class="{loading: is_calculating}">
38
+ <a :href="info.url_prefix" class="ui button red" v-show="selected_attribute">Reset</a>
39
+ <div class="ui basic floating dropdown button">
40
+ <div class="text">{{ selected_attribute || 'Attribute' }}</div>
41
+ <i class="dropdown icon"></i>
42
+ <div class="menu attribute_select">
43
+ <div class="item attribute_option" v-for="attribute in info.model_attributes" :model_prefix="attribute.model_prefix || ''" :target="attribute.name" :class="{selected: selected_attribute == attribute.name,active: selected_attribute == attribute.name}">{{ attribute.display_name }}</div>
44
+ </div>
45
+ </div>
46
+ <input type="text" id="searchQuery" :placeholder="searchStatus" v-model="searchQuery">
47
+ <i class="icon search"></i>
48
+ </div>
49
+ <div class="ui divider"></div>
50
+ <!-- NOTE: Pagination -->
51
+ <div class="ui pagination menu">
52
+ <a class="item" @click.prevent="setPage(currentPage-1)" :class="{'disabled': (currentPage == '1')}">
53
+
54
+ </a>
55
+ <a v-for="n in totalPage" @click.prevent="setPage(n)" :class="{'active': (currentPage == (n))}" class="item">
56
+ {{n}}
57
+ </a>
58
+ <a class="item" @click.prevent="setPage(currentPage+1)" :class="{'disabled': (currentPage == totalPage)}">
59
+
60
+ </a>
61
+ </div>
62
+ <div class="ui divider"></div>
63
+ <!-- NOTE: model-row -->
64
+ <div class="row ui cards">
65
+ <model-row is="model-row" v-for="model in filteredModels" :model="model" :info="info" :selected_attribute="model_prefix + '.' + selected_attribute"></model-row>
66
+ </div>
67
+
68
+ <!-- NOTE: modal for new action -->
69
+ <div class="ui modal new_modal" id="modelModal">
70
+ <div class="header">Create {{ info.titles.title }}</div>
71
+ <!-- NOTE: Vue form -->
72
+ <div class="content vue_form_for_new"></div>
73
+ <div class="actions">
74
+ <div class="ui basic gray cancel button">Cancel</div>
75
+ <div @click="createModel" class="ui primary button">Create</div>
76
+ </div>
77
+ <div class="ui blue bottom attached progress">
78
+ <div class="bar" :style="{width: progress + '%'}"></div>
79
+ </div>
80
+ </div>
81
+ </div>
82
+
83
+ <!-- NOTE: Templates -->
84
+ <script type="text/x-template" id="model-row">
85
+ <div class="col-md-4">
86
+ <div class="card">
87
+ <div class="content">
88
+ <div class="header" v-if="info.titles.title_attribute_model_prefix">{{ model[info.titles.title_attribute_model_prefix][info.titles.title_attribute] }}</div>
89
+ <div class="header" v-else>{{ model[info.titles.title_attribute] }}</div>
90
+ <div class="meta">{{ info.titles.model_name }}</div>
91
+ <div class="ui divider"></div>
92
+ <div class="description">
93
+ <div class="ui small feed" v-for="attribute in info.model_attributes" v-if="attribute.visible">
94
+ <div class="event">
95
+ <div class="content">
96
+ <div class="summary" :class="{highlight: attribute.model_prefix + '.' + attribute.name == selected_attribute}" v-if="attribute.model_prefix">
97
+ {{ attribute.display_name }}: {{ model[attribute.model_prefix][attribute.name] }}
98
+ </div>
99
+ <div class="summary" :class="{highlight: attribute.model_prefix + '.' + attribute.name == selected_attribute}" v-else>
100
+ {{ attribute.display_name }}: {{ model[attribute.name] }}
101
+ </div>
102
+ </div>
103
+ </div>
104
+ </div>
105
+ <!-- NOTE: Custom model row -->
106
+ <div class="custom_model_row"></div>
107
+ </div>
108
+ </div>
109
+ <div class="extra content">
110
+ <div class="ui orange right ribbon label" v-show="modified">您有尚未儲存的變更,<a href="#" @click="updateModel(false)" onclick="return false" class="save_now">立即儲存</a></div>
111
+ <div class="ui teal right ribbon label" v-show="is_success">儲存成功</div>
112
+ <div class="ui divider"></div>
113
+ <!-- NOTE: Custom action -->
114
+ <div class="inline-block custom_action"></div>
115
+ <div class="ui blue button" :data-modal="'#editModal_' + model.id">Edit</div>
116
+ <div @click="deleteModel" class="ui basic red right floated button" v-show="!deleteMode">Delete</div>
117
+ </div>
118
+ <div class="ui modal" :id="'editModal_' + model.id">
119
+ <div class="ui inverted dimmer">
120
+ <div class="ui indeterminate text loader">Progressing</div>
121
+ </div>
122
+ <div class="header">Update {{ info.titles.title }}</div>
123
+ <div class="content">
124
+ <!-- NOTE: Not customMode -->
125
+ <div v-show="!customMode" class="vue_form_for_edit"></div>
126
+ <!-- NOTE: Is customMode -->
127
+ <!-- NOTE: Custom modal body -->
128
+ <div v-show="customMode"><div class="custom_modal_body"></div></div>
129
+ </div>
130
+ <div class="actions">
131
+ <button class="ui basic gray cancel button">Cancel</button>
132
+ <button @click="updateModel" class="ui button blue" v-show="!customMode">Update</button>
133
+ <!-- NOTE: Custom modal action -->
134
+ <div class="inline-block custom_modal_action"></div>
135
+ </div>
136
+ </div>
137
+ <div class="ui blue bottom attached progress">
138
+ <div class="bar" :style="{width: progress + '%'}"></div>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </script>
143
+
144
+ <script type="text/x-template" id="vue_form">
145
+ <form class="ui form">
146
+ <div v-for="attribute in info.model_attributes" v-if="attribute.editable">
147
+ <div class="field" v-if="attribute.type == 'select'">
148
+ <label :for="'model_' + attribute.display_name">{{ attribute.display_name }}</label>
149
+ <select :id="'model_' + attribute.display_name" v-if="attribute.model_prefix" v-model="model[attribute.model_prefix][attribute.name]" class="ui fluid dropdown">
150
+ <option v-for="option in attribute.options" :value="option.value" v-text="option.text"></option>
151
+ </select>
152
+ <select :id="'model_' + attribute.display_name" v-else v-model="model[attribute.name]" class="ui fluid dropdown">
153
+ <option v-for="option in attribute.options" :value="option.value" v-text="option.text"></option>
154
+ </select>
155
+ <div class="ui pointing red basic label" v-show="errors[attribute.name]">
156
+ <span style="color: red" v-for="(error, index) in errors[attribute.name]">
157
+ <span v-if="index > 0">,</span> {{ error }}
158
+ </span>
159
+ </div>
160
+ </div>
161
+ <div class="field" v-if="attribute.type == 'multiSelect'">
162
+ <label :for="'model_' + attribute.display_name">{{ attribute.display_name }}</label>
163
+ <select :id="'model_' + attribute.display_name" multiple v-if="attribute.model_prefix" v-model="model[attribute.model_prefix][attribute.name]" class="ui fluid dropdown">
164
+ <option v-for="option in attribute.options" :value="option.value" v-text="option.text"></option>
165
+ </select>
166
+ <select :id="'model_' + attribute.display_name" multiple v-else v-model="model[attribute.name]" class="ui fluid dropdown">
167
+ <option v-for="option in attribute.options" :value="option.value" v-text="option.text"></option>
168
+ </select>
169
+ <div class="ui pointing red basic label" v-show="errors[attribute.name]">
170
+ <span style="color: red" v-for="(error, index) in errors[attribute.name]">
171
+ <span v-if="index > 0">,</span> {{ error }}
172
+ </span>
173
+ </div>
174
+ </div>
175
+ <div class="field" v-if="attribute.type == 'textarea'">
176
+ <label :for="'model_' + attribute.display_name">{{ attribute.display_name }}</label>
177
+ <textarea :id="'model_' + attribute.display_name" v-if="attribute.model_prefix" v-model="model[attribute.model_prefix][attribute.name]"></textarea>
178
+ <textarea :id="'model_' + attribute.display_name" v-else v-model="model[attribute.name]"></textarea>
179
+ <div class="ui pointing red basic label" v-show="errors[attribute.name]">
180
+ <span style="color: red" v-for="(error, index) in errors[attribute.name]">
181
+ <span v-if="index > 0">,</span> {{ error }}
182
+ </span>
183
+ </div>
184
+ </div>
185
+ <div class="field" v-if="attribute.type == 'checkbox'">
186
+ <div class="ui slider checkbox">
187
+ <input type="checkbox" :id="'model_' + attribute.display_name" v-if="attribute.model_prefix" v-model="model[attribute.model_prefix][attribute.name]">
188
+ <input type="checkbox" :id="'model_' + attribute.display_name" v-else v-model="model[attribute.name]">
189
+ <label :for="'model_' + attribute.display_name">{{ attribute.display_name }}</label>
190
+ </div>
191
+ <div class="ui pointing red basic label" v-show="errors[attribute.name]">
192
+ <span style="color: red" v-for="(error, index) in errors[attribute.name]">
193
+ <span v-if="index > 0">,</span> {{ error }}
194
+ </span>
195
+ </div>
196
+ </div>
197
+ <div class="field" v-if="attribute.type != 'select' && attribute.type != 'multiSelect' && attribute.type != 'textarea' && attribute.type != 'checkbox'">
198
+ <label :for="'model_' + attribute.display_name">{{ attribute.display_name }}</label>
199
+ <input :type="attribute.type" :id="'model_' + attribute.display_name" v-if="attribute.model_prefix" v-model="model[attribute.model_prefix][attribute.name]">
200
+ <input :type="attribute.type" :id="'model_' + attribute.display_name" v-else v-model="model[attribute.name]">
201
+ <div class="ui pointing red basic label" v-show="errors[attribute.name]">
202
+ <span style="color: red" v-for="(error, index) in errors[attribute.name]">
203
+ <span v-if="index > 0">,</span> {{ error }}
204
+ </span>
205
+ </div>
206
+ </div>
207
+ </div>
208
+ </form>
209
+ </script>
210
+ <!-- NOTE: memo-->
211
+ <!-- <div class="row well well-sm">
212
+ <model-row is="model-row" v-for="model in models" :model="model"></model-row>
213
+ </div> -->
214
+ <!-- ┌───────────────────────────────────────┐ -->
215
+ <!-- │ ↓ -->
216
+ <!-- v-for model in models 這個 model 會透過 :model="model" 傳值到 template,無法直接使用 v-for 迴圈出來的 model -->
217
+ <!-- │
218
+ In model-row component props: { ↓
219
+ model: Object
220
+ }
221
+ -->
@@ -0,0 +1,4 @@
1
+ module VueCrud
2
+ class Engine < Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module VueCrud
2
+ VERSION = "0.1.0"
3
+ end
data/lib/vue_crud.rb ADDED
@@ -0,0 +1,6 @@
1
+ require "vue_crud/version"
2
+ require "vue_crud/engine"
3
+ require "generators/vue_crud/install_generator"
4
+ module VueCrud
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,295 @@
1
+ $(document).ajaxStart(function() { Pace.restart(); });
2
+ var suffix = '.json';
3
+ Vue.config.devtools = true;
4
+ Pace.on('done', function() {
5
+ $('#form-progress').val('0');
6
+ });
7
+ var event_hub = new Vue();
8
+ function sleep(time) {
9
+ return new Promise((resolve) => setTimeout(resolve, time));
10
+ }
11
+ function obj_to_json(obj) {
12
+ return JSON.parse(JSON.stringify(obj));
13
+ }
14
+ var model_row_mixin = {}
15
+ var root_mixin = {}
16
+ function updateQueryStringParam(key, value) {
17
+ baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
18
+ urlQueryString = document.location.search;
19
+ var newParam = key + '=' + value,
20
+ params = '?' + newParam;
21
+
22
+ // If the "search" string exists, then build params from it
23
+ if (urlQueryString) {
24
+ keyRegex = new RegExp('([\?&])' + key + '[^&]*');
25
+ // If param exists already, update it
26
+ if (urlQueryString.match(keyRegex) !== null) {
27
+ params = urlQueryString.replace(keyRegex, "$1" + newParam);
28
+ } else { // Otherwise, add it to end of query string
29
+ params = urlQueryString + '&' + newParam;
30
+ }
31
+ }
32
+ window.history.replaceState({}, "", baseUrl + params);
33
+ }
34
+ function getParameterByName(name) {
35
+ var url = window.location.href;
36
+ name = name.replace(/[\[\]]/g, "\\$&");
37
+ var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
38
+ results = regex.exec(url);
39
+ if (!results) return '';
40
+ if (!results[2]) return '';
41
+ return decodeURIComponent(results[2].replace(/\+/g, " "));
42
+ }
43
+ function vue_init() {
44
+ Vue.filter('datetime', function (value) {
45
+ return new Date(value).toLocaleString();
46
+ })
47
+
48
+ var modelRowComponent = Vue.component('model-row', {
49
+ mixins: [model_row_mixin],
50
+ template: '#model-row',
51
+ props: {
52
+ model: Object,
53
+ selected_attribute: String,
54
+ info: Object
55
+ },
56
+ data: function() {
57
+ return {
58
+ progress: '0',
59
+ errors: {},
60
+ modified: false,
61
+ customMode: false,
62
+ deleteMode: false,
63
+ is_success: false
64
+ }
65
+ },
66
+ watch: {
67
+ model: {
68
+ handler: function (value, old_value) {
69
+ // old_value and value(model self) will be changed on Computed method
70
+ // Only watch model's data change so set value === old_value
71
+ // value === old_value means model not change
72
+ if(value === old_value) {
73
+ this.modified = true;
74
+ this.is_success = false;
75
+ }
76
+ },
77
+ deep: true
78
+ }
79
+ },
80
+ mounted: function() {
81
+ event_hub.$on('update_progress', function(progress) {
82
+ this.progress = progress;
83
+ }.bind(this));
84
+
85
+ event_hub.$on('cancel_customMode', function() {
86
+ this.customMode = false;
87
+ }.bind(this));
88
+ },
89
+ methods: {
90
+ deleteModel: function () {
91
+ var that = this;
92
+ that.deleteMode = true;
93
+ if(confirm("Are you sure?") == true) {
94
+ $.ajax({
95
+ method: 'DELETE',
96
+ url: that.info.url_prefix + '/' + that.model.id + suffix,
97
+ success: function(res) {
98
+ $(that.$el).remove();
99
+ },
100
+ error: function(res) {
101
+ that.deleteMode = false;
102
+ }
103
+ })
104
+ }
105
+ else {
106
+ that.deleteMode = false;
107
+ }
108
+ },
109
+ updateModel: function() {
110
+ var that = this;
111
+ var modal = $('#editModal_' + that.model.id);
112
+ $.ajax({
113
+ method: 'PATCH',
114
+ data: {
115
+ model: that.model,
116
+ },
117
+ url: that.info.url_prefix + '/' + that.model.id + suffix,
118
+ beforeSend: function() {
119
+ modal.find('.dimmer').toggleClass('active');
120
+ $('.progress-bar').css('width', '0');
121
+ },
122
+ success: function(res) {
123
+ that.errors = {};
124
+ that.modified = false;
125
+ that.is_success = true;
126
+ sleep(500).then(() => {
127
+ modal.find('.dimmer').toggleClass('active');
128
+ modal.modal('hide');
129
+ });
130
+ sleep(1500).then(() => {
131
+ that.is_success = false;
132
+ });
133
+ },
134
+ error: function(res) {
135
+ that.errors = res.responseJSON.errors;
136
+ modal.find('.dimmer').toggleClass('active');
137
+ }
138
+ });
139
+ }
140
+ }
141
+ })
142
+
143
+ var modelsVue = new Vue({
144
+ mixins: [root_mixin],
145
+ el: '#models',
146
+ data: {
147
+ models: [],
148
+ info: {
149
+ url_prefix: '',
150
+ titles: {},
151
+ structure: {},
152
+ model_attributes: []
153
+ },
154
+ model: {},
155
+ errors: {},
156
+ progress: '0',
157
+ countOfPage: 9,
158
+ currentPage: getParameterByName("p") || 1,
159
+ searchQuery: getParameterByName("q"),
160
+ filteredModelCount: null,
161
+ is_calculating: false,
162
+ model_prefix: getParameterByName("mp"),
163
+ selected_attribute: getParameterByName("sa")
164
+ },
165
+ mounted: function() {
166
+ var that = this;
167
+ $.ajax({
168
+ url: window.location.pathname + '/info' + suffix,
169
+ success: function(res) {
170
+ that.info = res;
171
+ that.model = obj_to_json(that.info.structure);
172
+ $.ajax({
173
+ url: that.info.url_prefix + suffix,
174
+ success: function(res) {
175
+ that.models = res;
176
+ }
177
+ });
178
+ }
179
+ });
180
+ event_hub.$on('update_progress', function(progress) {
181
+ this.progress = progress;
182
+ }.bind(this));
183
+ $('#form-progress').change(function(){
184
+ event_hub.$emit('update_progress', $(this).val());
185
+ });
186
+ $(document).delegate('.attribute_option', 'click', function(event) {
187
+ var model_prefix = $('.attribute_select').find('.item.selected').attr('model_prefix');
188
+ var selected_attribute = $('.attribute_select').find('.item.selected').attr('target') || "id";
189
+ that.model_prefix = model_prefix;
190
+ that.selected_attribute = selected_attribute;
191
+ updateQueryStringParam('mp', that.model_prefix);
192
+ updateQueryStringParam('sa', that.selected_attribute);
193
+ });
194
+ },
195
+ computed: {
196
+ searchStatus: function() {
197
+ if (this.is_calculating) {
198
+ return 'Loading...'
199
+ } else {
200
+ return '✓ Done';
201
+ }
202
+ },
203
+ pageStart: function() {
204
+ var that = this;
205
+ return (that.currentPage - 1) * that.countOfPage;
206
+ },
207
+ totalPage: function() {
208
+ var that = this;
209
+ if(that.searchQuery.trim() === '') {
210
+ return Math.ceil(that.models.length / that.countOfPage);
211
+ }
212
+ else{
213
+ return Math.ceil(that.filteredModelCount / that.countOfPage);
214
+ }
215
+ },
216
+ filteredModels: function() {
217
+ var that = this;
218
+ that.is_calculating = true;
219
+ var result = that.models.filter(function (model) {
220
+ if(that.model_prefix.length > 0) {
221
+ return String(model[that.model_prefix][that.selected_attribute]).indexOf(that.searchQuery) !== -1;
222
+ }
223
+ else {
224
+ return String(model[that.selected_attribute]).indexOf(that.searchQuery) !== -1;
225
+ }
226
+ });
227
+ that.filteredModelCount = result.length
228
+ setTimeout(function () {
229
+ that.is_calculating = false
230
+ }, 500)
231
+ return result.slice(
232
+ that.pageStart,
233
+ that.countOfPage + that.pageStart
234
+ );
235
+ }
236
+ },
237
+ watch: {
238
+ searchQuery: function () {
239
+ this.currentPage = 1;
240
+ updateQueryStringParam('q', this.searchQuery);
241
+ updateQueryStringParam('p', 1);
242
+ }
243
+ },
244
+ methods: {
245
+ setPage: function(idx){
246
+ if( idx <= 0 || idx > this.totalPage ){
247
+ return;
248
+ }
249
+ this.currentPage = idx;
250
+ updateQueryStringParam('p', this.currentPage);
251
+ },
252
+ createModel: function () {
253
+ var that = this;
254
+ $.ajax({
255
+ method: 'POST',
256
+ data: {
257
+ model: that.model,
258
+ },
259
+ url: that.info.url_prefix + suffix,
260
+ before: function() {
261
+ $('.new_modal').find('.dimmer').toggleClass('active');
262
+ $('.progress-bar').css('width', '0');
263
+ },
264
+ success: function(res) {
265
+ var modal = $(that.$el).parents('.modal');
266
+ that.errors = {};
267
+ that.model = obj_to_json(that.info.structure);
268
+ that.models.push(res);
269
+ sleep(500).then(() => {
270
+ $('.new_modal').find('.dimmer').toggleClass('active');
271
+ $('.new_modal').modal('hide');
272
+ });
273
+ },
274
+ error: function(res) {
275
+ that.errors = res.responseJSON.errors;
276
+ $('.new_modal').find('.dimmer').toggleClass('active');
277
+ }
278
+ });
279
+ }
280
+ }
281
+ })
282
+ }
283
+ $(document).ready(function() {
284
+ $(document).delegate('[data-modal]', 'click', function(event) {
285
+ var target = $(this).data('modal');
286
+ $(target).modal({
287
+ onShow: function() {
288
+ $(this).find('select.ui.dropdown').dropdown();
289
+ },
290
+ onHide: function() {
291
+ event_hub.$emit('cancel_customMode');
292
+ }
293
+ }).modal('show');
294
+ });
295
+ });
@@ -0,0 +1,19 @@
1
+ .ui.cards > .card > .extra a.save_now {
2
+ color: rgb(33, 133, 208);
3
+ opacity: 1;
4
+ }
5
+ .progress {
6
+ margin-bottom: 0;
7
+ border-radius: 0;
8
+ height: 10px;
9
+ }
10
+ #form-progress {
11
+ position: fixed;
12
+ top: -9999px;
13
+ }
14
+ .summary.highlight {
15
+ border: 2px solid #a90000;
16
+ }
17
+ .inline-block {
18
+ display: inline-block;
19
+ }
data/vue_crud.gemspec ADDED
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vue_crud/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "vue_crud"
8
+ spec.version = VueCrud::VERSION
9
+ spec.authors = ["Donald Chiang"]
10
+ spec.email = ["dc@mynet.com.tw"]
11
+ spec.license = "MIT"
12
+ spec.summary = %q{Vue js CRUD scaffold}
13
+ spec.description = %q{Vue js CRUD scaffold}
14
+ spec.homepage = "http://www.mynet.com.tw"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ # if spec.respond_to?(:metadata)
19
+ # spec.metadata['allowed_push_host'] = 'http://mygemserver.com'
20
+ # else
21
+ # raise "RubyGems 2.0 or newer is required to protect against " \
22
+ # "public gem pushes."
23
+ # end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(test|spec|features)/})
27
+ end
28
+ spec.bindir = "exe"
29
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
30
+ spec.require_paths = ["lib"]
31
+
32
+ spec.add_development_dependency "bundler", "~> 1.13"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "minitest", "~> 5.0"
35
+ end
metadata ADDED
@@ -0,0 +1,101 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vue_crud
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Donald Chiang
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-11-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: Vue js CRUD scaffold
56
+ email:
57
+ - dc@mynet.com.tw
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - ".travis.yml"
64
+ - Gemfile
65
+ - README.md
66
+ - Rakefile
67
+ - bin/console
68
+ - bin/setup
69
+ - lib/generators/vue_crud/install_generator.rb
70
+ - lib/generators/vue_crud/templates/vue_crud.html
71
+ - lib/vue_crud.rb
72
+ - lib/vue_crud/engine.rb
73
+ - lib/vue_crud/version.rb
74
+ - vendor/assets/javascripts/vue_crud.js
75
+ - vendor/assets/stylesheets/vue_crud.css
76
+ - vue_crud.gemspec
77
+ homepage: http://www.mynet.com.tw
78
+ licenses:
79
+ - MIT
80
+ metadata: {}
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubyforge_project:
97
+ rubygems_version: 2.5.1
98
+ signing_key:
99
+ specification_version: 4
100
+ summary: Vue js CRUD scaffold
101
+ test_files: []