vue_crud-generator 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
|
+
SHA256:
|
3
|
+
metadata.gz: 91c1e659bf0a9f074d213b3d1b43d71a36aca203cd7197919b52b92c1517525d
|
4
|
+
data.tar.gz: f2de1c452a0039ac649d04594ce76660d64076c99a4e85837d5c657061a0360d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5c2df4665592e2264239b7803a561151b45cf846eb0ae31c6f717665d47826b98acebc1b3eb5b0d667efdb31014aebe0eb5d893170bf19be402782cbe207401f
|
7
|
+
data.tar.gz: 1dc92cb5b11d04fec6dbc4ff2d87548a3a03be893950ee180c29a837dbd1de2bd41998d6850c5a522105fa5d312bd744cdff992deaf2d1d6df76f57d3d96b829
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Description:
|
2
|
+
Generates a front end CRUD vuetify component compatible with Rails controller_scaffold.
|
3
|
+
|
4
|
+
At least one field with "primary_key" type is required.
|
5
|
+
|
6
|
+
Example:
|
7
|
+
rails generate vuetify_crud User id:primary_key email:string role:integer
|
8
|
+
|
9
|
+
This will create:
|
10
|
+
app/javascript/components/users_crud.vue
|
@@ -0,0 +1,188 @@
|
|
1
|
+
<!--
|
2
|
+
Vuetify component structure inspired by CRUD example from official docs:
|
3
|
+
https://vuetifyjs.com/components/data-tables
|
4
|
+
-->
|
5
|
+
|
6
|
+
<template>
|
7
|
+
<div>
|
8
|
+
<v-toolbar flat color="white">
|
9
|
+
<v-toolbar-title><%= plural_name.capitalize %></v-toolbar-title>
|
10
|
+
<v-spacer />
|
11
|
+
<v-dialog v-model="dialog" max-width="500px">
|
12
|
+
<v-btn slot="activator" color="primary" dark class="mb-2">New Item</v-btn>
|
13
|
+
<v-card>
|
14
|
+
<v-card-title>
|
15
|
+
<span class="headline">{{ formTitle }}</span>
|
16
|
+
</v-card-title>
|
17
|
+
|
18
|
+
<v-card-text>
|
19
|
+
<v-container grid-list-md>
|
20
|
+
<v-layout wrap>
|
21
|
+
<div v-if="editedId !== -1">
|
22
|
+
<%= primary_key_name.capitalize %> {{editedItem.<%= primary_key_name %>}}
|
23
|
+
</div>
|
24
|
+
<%= attributes_names_without_id.map { |name| (<<-JS).strip }.join("\n#{' ' * 26}")
|
25
|
+
<v-flex xs12 sm12 md12>
|
26
|
+
<v-text-field v-model="editedItem.#{name}" label="#{name.capitalize}" />
|
27
|
+
</v-flex>
|
28
|
+
JS
|
29
|
+
%>
|
30
|
+
</v-layout>
|
31
|
+
</v-container>
|
32
|
+
</v-card-text>
|
33
|
+
|
34
|
+
<v-card-actions>
|
35
|
+
<v-spacer></v-spacer>
|
36
|
+
<v-btn color="blue darken-1" flat @click.native="close">Cancel</v-btn>
|
37
|
+
<v-btn color="blue darken-1" flat @click.native="save">Save</v-btn>
|
38
|
+
</v-card-actions>
|
39
|
+
</v-card>
|
40
|
+
</v-dialog>
|
41
|
+
</v-toolbar>
|
42
|
+
|
43
|
+
<v-data-table
|
44
|
+
:headers="headers"
|
45
|
+
:items="items"
|
46
|
+
hide-actions
|
47
|
+
class="elevation-1"
|
48
|
+
>
|
49
|
+
<template slot="items" slot-scope="props">
|
50
|
+
<%= attributes_names.map { |name| "<td>{{ props.item.#{name} }}</td>" }.join("\n#{' ' * 10}") %>
|
51
|
+
<td>
|
52
|
+
<v-icon
|
53
|
+
small
|
54
|
+
class="mr-2"
|
55
|
+
@click="editItem(props.item)"
|
56
|
+
>
|
57
|
+
edit
|
58
|
+
</v-icon>
|
59
|
+
<v-icon
|
60
|
+
small
|
61
|
+
@click="deleteItem(props.item)"
|
62
|
+
>
|
63
|
+
delete
|
64
|
+
</v-icon>
|
65
|
+
</td>
|
66
|
+
</template>
|
67
|
+
</v-data-table>
|
68
|
+
|
69
|
+
<v-snackbar v-model="errorSnackbar" top color="error" :timeout="6000">
|
70
|
+
Error occured{{renderErrorText}}
|
71
|
+
</v-snackbar>
|
72
|
+
</div>
|
73
|
+
</template>
|
74
|
+
|
75
|
+
<script>
|
76
|
+
import axios from 'axios'
|
77
|
+
|
78
|
+
const routeURL = '<%= route_url %>';
|
79
|
+
|
80
|
+
export default {
|
81
|
+
methods: {
|
82
|
+
resetToDefault() {
|
83
|
+
this.editedId = -1;
|
84
|
+
Object.assign(this.editedItem, this.defaultItem);
|
85
|
+
},
|
86
|
+
|
87
|
+
close() {
|
88
|
+
this.resetToDefault();
|
89
|
+
this.dialog = false;
|
90
|
+
},
|
91
|
+
|
92
|
+
errorHandler(error) {
|
93
|
+
if (error.response) {
|
94
|
+
const data = error.response.data;
|
95
|
+
this.errorText = data.errors || data;
|
96
|
+
}
|
97
|
+
this.errorSnackbar = true;
|
98
|
+
},
|
99
|
+
|
100
|
+
save() {
|
101
|
+
if (this.editedId === -1) {
|
102
|
+
axios.post(routeURL, this.editedItem).then(res => {
|
103
|
+
this.items.push(res.data);
|
104
|
+
this.close();
|
105
|
+
}).catch(this.errorHandler.bind(this));
|
106
|
+
} else {
|
107
|
+
axios.patch(routeURL + '/' + this.editedId, this.editedItem).then(res => {;
|
108
|
+
var elementIndex = this.findItemById(res.data.<%= primary_key_name %>);
|
109
|
+
if (elementIndex !== -1) {
|
110
|
+
Object.assign(this.items[elementIndex], res.data);
|
111
|
+
}
|
112
|
+
this.close();
|
113
|
+
}).catch(this.errorHandler.bind(this));
|
114
|
+
}
|
115
|
+
},
|
116
|
+
|
117
|
+
findItemById(id) {
|
118
|
+
return this.items.findIndex(element => {
|
119
|
+
return element.<%= primary_key_name %> == id;
|
120
|
+
});
|
121
|
+
},
|
122
|
+
|
123
|
+
editItem(item) {
|
124
|
+
this.editedId = item.<%= primary_key_name %>;
|
125
|
+
Object.assign(this.editedItem, item);
|
126
|
+
this.dialog = true;
|
127
|
+
},
|
128
|
+
|
129
|
+
deleteItem(item) {
|
130
|
+
const id = item.<%= primary_key_name %>;
|
131
|
+
const run = confirm(
|
132
|
+
'Are you sure you want to delete <%= singular_name %> with <%= primary_key_name %> ' + id + '?'
|
133
|
+
);
|
134
|
+
|
135
|
+
if (run) {
|
136
|
+
axios.delete(routeURL + '/' + id).then(res => {
|
137
|
+
const index = this.findItemById(id);
|
138
|
+
if (index !== -1) {
|
139
|
+
this.items.splice(index, 1);
|
140
|
+
}
|
141
|
+
}).catch(this.errorHandler.bind(this));
|
142
|
+
}
|
143
|
+
}
|
144
|
+
},
|
145
|
+
|
146
|
+
computed: {
|
147
|
+
renderErrorText() {
|
148
|
+
return this.errorText ? ': ' + this.errorText : '';
|
149
|
+
},
|
150
|
+
|
151
|
+
formTitle () {
|
152
|
+
return this.editedId === -1 ? 'New Item' : 'Edit Item';
|
153
|
+
}
|
154
|
+
},
|
155
|
+
|
156
|
+
created() {
|
157
|
+
this.resetToDefault();
|
158
|
+
axios.get(routeURL).then(res => {
|
159
|
+
this.items = res.data;
|
160
|
+
}).catch(this.errorHandler.bind(this));
|
161
|
+
},
|
162
|
+
|
163
|
+
data() {
|
164
|
+
return {
|
165
|
+
defaultItem: {
|
166
|
+
// you can add default values for your attributes here
|
167
|
+
<%= attributes_names_without_id.map {|name| "#{name}: null" }.join(",\n#{' ' * 10}") %>
|
168
|
+
},
|
169
|
+
editedItem: {
|
170
|
+
},
|
171
|
+
editedId: -1,
|
172
|
+
errorSnackbar: false,
|
173
|
+
errorText: null,
|
174
|
+
dialog: false,
|
175
|
+
items: [],
|
176
|
+
headers: [
|
177
|
+
<%= attributes_names.map {|name| (<<-JS).strip }.join(",\n#{' ' * 10}")
|
178
|
+
{
|
179
|
+
text: '#{name.capitalize}',
|
180
|
+
value: '#{name}'
|
181
|
+
}
|
182
|
+
JS
|
183
|
+
%>
|
184
|
+
]
|
185
|
+
};
|
186
|
+
}
|
187
|
+
};
|
188
|
+
</script>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module VueJs
|
4
|
+
class VuetifyCrudGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
6
|
+
|
7
|
+
argument :attributes, type: :array, default: [], banner: "field:type field:type"
|
8
|
+
|
9
|
+
def create_component_file
|
10
|
+
template "crud_component.vue.tt", "app/javascript/components/#{plural_name}_crud.vue"
|
11
|
+
end
|
12
|
+
|
13
|
+
def attributes_names_without_id
|
14
|
+
attributes_without_id.map(&:name)
|
15
|
+
end
|
16
|
+
|
17
|
+
def attributes_without_id
|
18
|
+
@attributes_without_id ||= attributes.reject {|attr| attr.type == :primary_key}
|
19
|
+
end
|
20
|
+
|
21
|
+
def primary_key_name
|
22
|
+
@primary_key_name ||= find_primary_key.name
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def find_primary_key
|
28
|
+
attributes.find {|attribute|
|
29
|
+
attribute.type == :primary_key
|
30
|
+
}.tap {|attribute|
|
31
|
+
raise Thor::RequiredArgumentMissingError, "Error: primary key field is required" if attribute.nil?
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vue_crud-generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Senya
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-07-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Rails generator which makes a front end CRUD Vuetify component compatible
|
28
|
+
with Rails `controller_scaffold`.
|
29
|
+
email:
|
30
|
+
- senya@riseup.net
|
31
|
+
executables: []
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- lib/generators/vue_js/vuetify_crud/USAGE
|
36
|
+
- lib/generators/vue_js/vuetify_crud/templates/crud_component.vue.tt
|
37
|
+
- lib/generators/vue_js/vuetify_crud/vuetify_crud_generator.rb
|
38
|
+
homepage: https://gitlab.com/cmrd-senya/vue_crud-generator
|
39
|
+
licenses:
|
40
|
+
- MPL-2.0
|
41
|
+
metadata: {}
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
requirements: []
|
57
|
+
rubyforge_project:
|
58
|
+
rubygems_version: 2.7.6
|
59
|
+
signing_key:
|
60
|
+
specification_version: 4
|
61
|
+
summary: A rails generator for front end CRUD component built with VueJS.
|
62
|
+
test_files: []
|