rails_admin_tree_browser 0.1.1
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 +7 -0
- data/README.md +69 -0
- data/app/views/rails_admin/main/_tree_browser.html.erb +17 -0
- data/config/locales/en.yml +6 -0
- data/config/locales/fr.yml +6 -0
- data/lib/rails_admin_tree_browser/engine.rb +10 -0
- data/lib/rails_admin_tree_browser/tree_browser_field.rb +43 -0
- data/lib/rails_admin_tree_browser.rb +7 -0
- data/vendor/assets/javascripts/rails_admin/app.js +12 -0
- data/vendor/assets/javascripts/rails_admin/components/tree-browser.vue +193 -0
- data/vendor/assets/javascripts/rails_admin/rails_admin_tree_browser.js.erb +12284 -0
- data/vendor/assets/stylesheets/rails_admin/rails_admin_tree_browser.sass +0 -0
- data/vendor/assets/stylesheets/rails_admin_tree_browser/rails_admin_tree_browser.css.erb +0 -0
- metadata +86 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6541aa2a148b8e60bcac20dec52271d9f89ea0bc
|
4
|
+
data.tar.gz: 6f0c79b9044f8b61719232b3897369a976ed2954
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 310439b1aed54dac6d96851587ece69cbd6a800702e1c989e46670d38b30c5d27d7fe8f202f477f3440ae1a3a3a8b1ab480c8552532e3d77b981db0c46bcbadc
|
7
|
+
data.tar.gz: 72a65838a73b1848d48223310fea18adb655256d9750e2fa43fe9768e90d1d82f11f70a7fd874f0ac0b05fe5480ba9bb1bc4ea2a447c7d11e3f2cccfc70c6134
|
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
# Rails Admin tree browser field
|
3
|
+
|
4
|
+
A simple gem to work with [rails_admin](https://github.com/sferik/rails_admin) that allow you to choose element in a tree.
|
5
|
+
|
6
|
+
## Usage
|
7
|
+
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem "rails_admin_browser_tree"
|
11
|
+
```
|
12
|
+
|
13
|
+
Then, add in your rails admin model initializer<br/>
|
14
|
+
``` config/initializers/rails_admin/modelName.rb ```
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
RailsAdmin.config do |config|
|
18
|
+
config.model MyAwesomeModel do
|
19
|
+
edit do
|
20
|
+
field :db_path_field, :tree_browser do
|
21
|
+
tree_root_url 'https://url_to_api_return_json.com'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
## Config
|
29
|
+
|
30
|
+
- `tree_root_url` - The root url from where we show the files tree
|
31
|
+
- `button_label` - Overwrite the label name (Optional)
|
32
|
+
- `download_link` - true/false Show icon with link to download (Optional)
|
33
|
+
- `node_type_name` - overwrite de node type name, default: node (Optional)
|
34
|
+
- `element_type_name` - overwrite de element type name, default: element (Optional)
|
35
|
+
|
36
|
+
example:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
RailsAdmin.config do |config|
|
40
|
+
config.model MyAwesomeModel do
|
41
|
+
edit do
|
42
|
+
field :path, :tree_browser do
|
43
|
+
tree_root_url 'https://url_to_api_return_json.com'
|
44
|
+
button_label 'Choose a file please'
|
45
|
+
download_link true
|
46
|
+
node_type_name 'dir'
|
47
|
+
element_type_name 'file'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
```
|
53
|
+
## JSON need for API return
|
54
|
+
|
55
|
+
example for https://url_to_api_return_json.com/node
|
56
|
+
|
57
|
+
```json
|
58
|
+
[{
|
59
|
+
name: "element",
|
60
|
+
path: "node/element",
|
61
|
+
type: "element"
|
62
|
+
},
|
63
|
+
{
|
64
|
+
name: "sub_node",
|
65
|
+
path: "node/sub_node",
|
66
|
+
type: "node"
|
67
|
+
}]
|
68
|
+
```
|
69
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<%= javascript_include_tag 'rails_admin/rails_admin_tree_browser' %>
|
2
|
+
<%= stylesheet_link_tag 'rails_admin/rails_admin_tree_browser' %>
|
3
|
+
|
4
|
+
<div id="tree-browser-input">
|
5
|
+
<tree-browser
|
6
|
+
v-bind:download-link="<%= field.download_link %>"
|
7
|
+
back-button-label="<%= I18n.t('rails_admin_tree_browser.back_button') %>"
|
8
|
+
remove-button-label="<%= I18n.t('rails_admin_tree_browser.remove_button') %>"
|
9
|
+
list-title-label="<%= I18n.t('rails_admin_tree_browser.list_title') %>"
|
10
|
+
root-node="<%= field.tree_root_url %>"
|
11
|
+
button-label="<%= field.button_label %>"
|
12
|
+
field-value="<%= @object[field.name] %>"
|
13
|
+
field-name="<%= field.input_name %>"
|
14
|
+
node-type-name="<%= field.node_type_name %>"
|
15
|
+
element-type-name="<%= field.element_type_name %>">
|
16
|
+
</tree-browser>
|
17
|
+
</div>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
module RailsAdminFilesTree
|
3
|
+
class Engine < ::Rails::Engine
|
4
|
+
isolate_namespace RailsAdmin
|
5
|
+
|
6
|
+
initializer "RailsAdminTreeBrowser precompile hook" do |app|
|
7
|
+
app.config.assets.precompile += ['rails_admin/rails_admin_tree_browser.css', 'rails_admin/rails_admin_tree_browser.js']
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module RailsAdmin::Config::Fields::Types
|
2
|
+
class TreeBrowserField < RailsAdmin::Config::Fields::Base
|
3
|
+
|
4
|
+
RailsAdmin::Config::Fields::Types::register(:tree_browser, self)
|
5
|
+
|
6
|
+
def allowed_methods
|
7
|
+
[@name, button_label, download_link, tree_root_url]
|
8
|
+
end
|
9
|
+
|
10
|
+
register_instance_option(:partial) do
|
11
|
+
:tree_browser
|
12
|
+
end
|
13
|
+
|
14
|
+
register_instance_option(:tree_root_url) do
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
register_instance_option(:button_label) do
|
19
|
+
I18n.t('rails_admin_tree_browser.choose_button') || :button_label
|
20
|
+
end
|
21
|
+
|
22
|
+
register_instance_option(:download_link) do
|
23
|
+
false || :download_link
|
24
|
+
end
|
25
|
+
|
26
|
+
register_instance_option(:node_type_name) do
|
27
|
+
'node' || :node_type_name
|
28
|
+
end
|
29
|
+
|
30
|
+
register_instance_option(:element_type_name) do
|
31
|
+
'element' || :element_type_name
|
32
|
+
end
|
33
|
+
|
34
|
+
def input_name
|
35
|
+
"#{bindings[:form].object_name}[#{@name}]"
|
36
|
+
end
|
37
|
+
|
38
|
+
def dom_name
|
39
|
+
@dom_name ||= "#{bindings[:form].object_name}_#{@name}"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import Vue from 'vue'
|
2
|
+
import TreeBrowser from './components/tree-browser.vue'
|
3
|
+
|
4
|
+
|
5
|
+
document.addEventListener("DOMContentLoaded", function() {
|
6
|
+
if(document.getElementById('tree-browser-input')) {
|
7
|
+
new Vue({
|
8
|
+
el: '#tree-browser-input',
|
9
|
+
components: { TreeBrowser }
|
10
|
+
})
|
11
|
+
}
|
12
|
+
})
|
@@ -0,0 +1,193 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
<span class="tree-browser__preview" v-if="selectedNode"><i class="fa fa-file-o"></i>{{selectedNode}}</span>
|
4
|
+
<input type="hidden" :name="fieldName" v-model="selectedNode">
|
5
|
+
<button class="btn btn-info" type="button" @click="showInsertOverlay = !showInsertOverlay" name="button">{{buttonLabel}}</button>
|
6
|
+
<button v-if="selectedNode" class="btn btn-default" type="button" @click="selectedNode = ''" name="button"><i class="icon-remove"></i> {{ removeButtonLabel }}</button>
|
7
|
+
<transition name="fade">
|
8
|
+
<div class="tree-browser__overlay" v-if="showInsertOverlay">
|
9
|
+
<div class="header">
|
10
|
+
<button type="button" @click="showInsertOverlay = false" class="btn tree-browser__overlay-close" name="button">×</button>
|
11
|
+
</div>
|
12
|
+
<table class="table">
|
13
|
+
<caption>{{ node }}</caption>
|
14
|
+
<thead>
|
15
|
+
<tr>
|
16
|
+
<th>{{ listTitleLabel }}</th>
|
17
|
+
<th class="text-right"><button type="button" class="btn btn-info btn-xs" @click="goBack()" v-if="node !== '/'">{{ backButtonLabel }}</button></th>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
<tr v-for="element in elements">
|
22
|
+
<td>
|
23
|
+
<div @click="nodeClick(element)" class="element" v-if="element.type === elementTypeName">
|
24
|
+
<i class="fa fa-file-o"></i>
|
25
|
+
{{ element.name }}
|
26
|
+
</div>
|
27
|
+
<div class="node" v-if="element.type === nodeTypeName">
|
28
|
+
<i class="fa fa-folder-o"></i>
|
29
|
+
<a @click="changeNode(element.path)">{{ element.name }}</a>
|
30
|
+
</div>
|
31
|
+
</td>
|
32
|
+
<td class="text-right" v-show="downloadLink">
|
33
|
+
<a :href="downloadLinkPath(element)" download v-if="element.type === elementTypeName">
|
34
|
+
<i class="fa fa-cloud-download"></i>
|
35
|
+
</a>
|
36
|
+
</td>
|
37
|
+
</tr>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
40
|
+
</div>
|
41
|
+
</transition>
|
42
|
+
</div>
|
43
|
+
</template>
|
44
|
+
|
45
|
+
<script>
|
46
|
+
import axios from 'axios'
|
47
|
+
|
48
|
+
export default {
|
49
|
+
watch: {
|
50
|
+
repo: function(newVal, oldVal) {
|
51
|
+
this.node = '/';
|
52
|
+
this.getElements();
|
53
|
+
}
|
54
|
+
},
|
55
|
+
props: {
|
56
|
+
fieldName: {
|
57
|
+
type: String,
|
58
|
+
required: true
|
59
|
+
},
|
60
|
+
fieldValue: {
|
61
|
+
type: String,
|
62
|
+
required: true
|
63
|
+
},
|
64
|
+
rootNode: {
|
65
|
+
type: String,
|
66
|
+
required: true
|
67
|
+
},
|
68
|
+
downloadLink: {
|
69
|
+
type: Boolean,
|
70
|
+
required: false
|
71
|
+
},
|
72
|
+
nodeTypeName: {
|
73
|
+
type: String,
|
74
|
+
defaut: 'node',
|
75
|
+
required: false
|
76
|
+
},
|
77
|
+
elementTypeName: {
|
78
|
+
type: String,
|
79
|
+
defaut: 'element',
|
80
|
+
required: false
|
81
|
+
},
|
82
|
+
buttonLabel: {
|
83
|
+
type: String,
|
84
|
+
required: true
|
85
|
+
},
|
86
|
+
backButtonLabel: {
|
87
|
+
type: String,
|
88
|
+
required: true
|
89
|
+
},
|
90
|
+
removeButtonLabel: {
|
91
|
+
type: String,
|
92
|
+
required: true
|
93
|
+
},
|
94
|
+
listTitleLabel: {
|
95
|
+
type: String,
|
96
|
+
required: true
|
97
|
+
}
|
98
|
+
},
|
99
|
+
data: function(){
|
100
|
+
return {
|
101
|
+
showInsertOverlay: false,
|
102
|
+
node: '/',
|
103
|
+
selectedNode: '',
|
104
|
+
elements: []
|
105
|
+
}
|
106
|
+
},
|
107
|
+
created: function() {
|
108
|
+
this.getElements();
|
109
|
+
},
|
110
|
+
mounted() {
|
111
|
+
//do something after mounting vue instance
|
112
|
+
if (this.fieldValue) {
|
113
|
+
this.selectedNode = this.fieldValue;
|
114
|
+
}
|
115
|
+
},
|
116
|
+
methods: {
|
117
|
+
downloadLinkPath: function(element) {
|
118
|
+
return this.rootNode + '/' + element.path
|
119
|
+
},
|
120
|
+
nodeClick: function(node) {
|
121
|
+
this.selectedNode = node.path;
|
122
|
+
this.showInsertOverlay = false;
|
123
|
+
},
|
124
|
+
getElements: function() {
|
125
|
+
axios.get(this.rootNode + this.node).then(function(response){
|
126
|
+
this.elements = response.data;
|
127
|
+
}.bind(this));
|
128
|
+
},
|
129
|
+
changeNode: function(node) {
|
130
|
+
this.node = '/' + node;
|
131
|
+
this.getElements();
|
132
|
+
},
|
133
|
+
goBack: function() {
|
134
|
+
this.node = this.node.split('/').slice(0, -1).join('/');
|
135
|
+
if (this.node === ''){
|
136
|
+
this.node = '/';
|
137
|
+
}
|
138
|
+
this.getElements();
|
139
|
+
}
|
140
|
+
}
|
141
|
+
}
|
142
|
+
</script>
|
143
|
+
|
144
|
+
<style media="screen">
|
145
|
+
.tree-browser__overlay {
|
146
|
+
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
|
147
|
+
position: fixed;
|
148
|
+
top: 100px;
|
149
|
+
left: 50%;
|
150
|
+
transform: translate(-50%,0);
|
151
|
+
width: 100%;
|
152
|
+
max-width: 475px;
|
153
|
+
z-index: 20;
|
154
|
+
max-height: 100vh;
|
155
|
+
overflow-y: auto;
|
156
|
+
background-color: white;
|
157
|
+
padding: 20px;
|
158
|
+
border-radius: 4px;
|
159
|
+
max-height: 80vh;
|
160
|
+
overflow-y: auto; }
|
161
|
+
|
162
|
+
.tree-browser__overlay .node,
|
163
|
+
.tree-browser__overlay .element{
|
164
|
+
cursor: pointer;
|
165
|
+
}
|
166
|
+
|
167
|
+
.tree-browser__overlay-close {
|
168
|
+
float: right;
|
169
|
+
font-size: 21px;
|
170
|
+
font-weight: bold;
|
171
|
+
line-height: 1;
|
172
|
+
color: #000;
|
173
|
+
text-shadow: 0 1px 0 #fff;
|
174
|
+
opacity: 0.2;
|
175
|
+
}
|
176
|
+
|
177
|
+
.tree-browser__preview {
|
178
|
+
display: block;
|
179
|
+
color: #b5b5b5;
|
180
|
+
font-size: 14px;
|
181
|
+
margin-bottom: 5px;
|
182
|
+
}
|
183
|
+
.tree-browser__preview i{
|
184
|
+
margin-right: 5px;
|
185
|
+
}
|
186
|
+
|
187
|
+
.fade-enter-active, .fade-leave-active {
|
188
|
+
transition: opacity .5s
|
189
|
+
}
|
190
|
+
.fade-enter, .fade-leave-to /* .fade-leave-active in <2.1.8 */ {
|
191
|
+
opacity: 0
|
192
|
+
}
|
193
|
+
</style>
|