export_manager 0.1.1 → 1.0.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 +4 -4
- data/README.md +21 -14
- data/app/assets/stylesheets/export_manager/export.css +197 -79
- data/app/controllers/export_manager/export_custom_queries_controller.rb +78 -0
- data/app/models/export_manager/export_custom_query.rb +5 -0
- data/app/views/export_manager/export_custom_queries/_form.html.erb +34 -0
- data/app/views/export_manager/export_custom_queries/edit.html.erb +6 -0
- data/app/views/export_manager/export_custom_queries/index.html.erb +29 -0
- data/app/views/export_manager/export_custom_queries/new.html.erb +5 -0
- data/app/views/export_manager/export_custom_queries/show.html.erb +19 -0
- data/app/views/export_manager/export_manager/export.html.erb +50 -35
- data/app/views/layouts/export_manager/application.html.erb +13 -1
- data/lib/export_manager/version.rb +1 -1
- data/lib/generators/export_manager/install_generator.rb +26 -0
- data/lib/generators/export_manager/templates/create_custom_query_table.rb +11 -0
- metadata +17 -9
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fb0b529ac6300efbebe327ad14fe4ac2885ddc66d5b52d7f12d1c22daac62047
|
|
4
|
+
data.tar.gz: 8830a7c7e838aa2483d0df97d3a70917ff11a26e425cdabc1cf935bc4e5ff916
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 006d45edc2fbc3884b09c67d05d1c5500834e31c97d6d39df94bcf5a6c00eda52e140972956dc8b073948a606ba0110f08270bca0bc5e5953e5416be46976175
|
|
7
|
+
data.tar.gz: 915224332f2003c57cb61854677cb882856c3f46993089cb11e9ea00b692d983b2933a52420499d1774de6b8f99f27ef195601732bda105a70b95366343cb1e0
|
data/README.md
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
# ExportManager
|
|
2
|
-
ExportManager handles the dynamic export of table data to CSV, JSON,
|
|
2
|
+
The ExportManager handles the dynamic export of table data to CSV, JSON, Excel, and XML formats.
|
|
3
3
|
|
|
4
4
|
## Usage
|
|
5
|
-
The ExportManager allows users to export data from dynamic tables with dynamic columns. The system provides flexibility in
|
|
5
|
+
The ExportManager allows users to export data from dynamic tables with dynamic columns. The system provides flexibility in selecting the data to be exported and generates a **CSV, JSON, Excel, or XML** file accordingly.
|
|
6
|
+
|
|
7
|
+
## Demo
|
|
8
|
+
[Screencast from 27-12-24 04:09:24 PM IST.webm](https://github.com/user-attachments/assets/17d245c3-5234-4171-b349-6cc1a74ea847)
|
|
6
9
|
|
|
7
10
|
## Quick Start
|
|
8
11
|
```ruby
|
|
9
|
-
1)
|
|
12
|
+
1) Add the following gems to your Gemfile
|
|
13
|
+
gem "export_manager"
|
|
10
14
|
gem "caxlsx"
|
|
11
15
|
gem "caxlsx_rails"
|
|
12
|
-
2)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
2) In config/routes.rb, add
|
|
17
|
+
mount ExportManager::Engine, at: '/'
|
|
18
|
+
|
|
19
|
+
3) Add the following lines to manifest.js
|
|
20
|
+
//= link export_manager/application.css
|
|
21
|
+
//= link export_manager/application.js
|
|
22
|
+
|
|
23
|
+
4) Run rails assets:precompile in the console
|
|
17
24
|
```
|
|
18
25
|
|
|
19
|
-
##
|
|
26
|
+
## Database Support
|
|
20
27
|
```ruby
|
|
21
|
-
1)
|
|
22
|
-
2)
|
|
28
|
+
1) PostgreSQL
|
|
29
|
+
2) MySQL
|
|
23
30
|
```
|
|
24
31
|
|
|
25
32
|
|
|
@@ -43,14 +50,14 @@ $ gem install export_manager
|
|
|
43
50
|
```
|
|
44
51
|
|
|
45
52
|
|
|
46
|
-
Remove
|
|
53
|
+
Remove a specific table name from the select box by creating a **global.rb** file in the **config/initializers** directory and adding the following code
|
|
47
54
|
```ruby
|
|
48
55
|
config/initializers/global.rb
|
|
49
56
|
|
|
50
57
|
REMOVE_TABLE_NAME = ['ActiveStorageBlobs'] # remove table
|
|
51
58
|
```
|
|
52
59
|
|
|
53
|
-
Add the custom file name in global.rb
|
|
60
|
+
Add the custom file name in **global.rb**
|
|
54
61
|
```ruby
|
|
55
62
|
config/initializers/global.rb
|
|
56
63
|
|
|
@@ -60,7 +67,7 @@ JSON_FILE_NAME = "JSON_EXPORT_#{Date.today}.json"
|
|
|
60
67
|
XML_FILE_NAME = "XML_EXPORT_#{Date.today}.xml"
|
|
61
68
|
```
|
|
62
69
|
|
|
63
|
-
If an authenticated user has the admin
|
|
70
|
+
If an authenticated user has the **admin?** method returning **true**, they can access the ExportManager engine at /.
|
|
64
71
|
```ruby
|
|
65
72
|
authenticated :user, ->(user) { user.admin? } do
|
|
66
73
|
mount ExportManager::Engine, at: '/'
|
|
@@ -1,122 +1,240 @@
|
|
|
1
1
|
body {
|
|
2
|
-
font-family: Arial, sans-serif;
|
|
3
2
|
margin: 0;
|
|
4
|
-
|
|
5
|
-
background
|
|
3
|
+
font-family: sans-serif;
|
|
4
|
+
background: #f6f6f6;
|
|
5
|
+
color: #333;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
display:
|
|
12
|
-
|
|
8
|
+
.navbar {
|
|
9
|
+
background: #fff;
|
|
10
|
+
padding: 10px 20px;
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
justify-content: space-between;
|
|
14
|
+
border-bottom: 1px solid #ddd;
|
|
13
15
|
}
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
font-size: 1.
|
|
17
|
-
|
|
18
|
-
margin-bottom: 20px;
|
|
17
|
+
.navbar .logo {
|
|
18
|
+
font-size: 1.4em;
|
|
19
|
+
font-weight: bold;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
.
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
.navbar .red { color: crimson; }
|
|
23
|
+
.navbar .green { color: #397e3b; }
|
|
24
|
+
|
|
25
|
+
.navbar ul {
|
|
26
|
+
list-style: none;
|
|
27
|
+
display: flex;
|
|
28
|
+
gap: 15px;
|
|
29
|
+
margin: 0;
|
|
30
|
+
padding: 0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.navbar ul li {
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
padding: 6px 10px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.navbar ul li a {
|
|
39
|
+
text-decoration: none;
|
|
40
|
+
color: #333;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.navbar ul .active {
|
|
44
|
+
background: #ddd;
|
|
45
|
+
border-radius: 4px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.live-poll {
|
|
49
|
+
background: crimson;
|
|
50
|
+
color: white;
|
|
51
|
+
border: none;
|
|
52
|
+
padding: 6px 12px;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.stats {
|
|
58
|
+
background: white;
|
|
59
|
+
margin: 20px;
|
|
24
60
|
padding: 20px;
|
|
25
|
-
|
|
26
|
-
|
|
61
|
+
border-radius: 6px;
|
|
62
|
+
display: flex;
|
|
63
|
+
justify-content: space-around;
|
|
64
|
+
text-align: center;
|
|
65
|
+
font-size: 0.9em;
|
|
66
|
+
border: 1px solid #ddd;
|
|
27
67
|
}
|
|
28
68
|
|
|
29
|
-
.
|
|
69
|
+
.stats .number {
|
|
70
|
+
font-size: 1.2em;
|
|
30
71
|
font-weight: bold;
|
|
31
|
-
font-size: 1rem;
|
|
32
72
|
}
|
|
33
73
|
|
|
34
|
-
.
|
|
35
|
-
|
|
36
|
-
border-radius: 5px;
|
|
37
|
-
border: 1px solid #ccc;
|
|
38
|
-
display: flex;
|
|
39
|
-
align-items: center;
|
|
74
|
+
.content {
|
|
75
|
+
margin: 20px;
|
|
40
76
|
}
|
|
41
77
|
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
color: #333;
|
|
78
|
+
.content h2 {
|
|
79
|
+
margin-bottom: 10px;
|
|
45
80
|
}
|
|
46
81
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
border:
|
|
50
|
-
|
|
82
|
+
table {
|
|
83
|
+
width: 100%;
|
|
84
|
+
border-collapse: collapse;
|
|
85
|
+
margin-bottom: 20px;
|
|
86
|
+
background: white;
|
|
87
|
+
border: 1px solid #ddd;
|
|
51
88
|
}
|
|
52
89
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
90
|
+
th, td {
|
|
91
|
+
padding: 12px;
|
|
92
|
+
border-bottom: 1px solid #ddd;
|
|
93
|
+
vertical-align: top;
|
|
56
94
|
}
|
|
57
95
|
|
|
58
|
-
|
|
59
|
-
background
|
|
60
|
-
|
|
61
|
-
padding:
|
|
62
|
-
|
|
96
|
+
.label {
|
|
97
|
+
background: #397e3b;
|
|
98
|
+
color: white;
|
|
99
|
+
padding: 2px 6px;
|
|
100
|
+
font-size: 0.8em;
|
|
101
|
+
border-radius: 3px;
|
|
102
|
+
margin-left: 5px;
|
|
63
103
|
}
|
|
64
104
|
|
|
65
|
-
|
|
66
|
-
|
|
105
|
+
.btn {
|
|
106
|
+
padding: 6px 10px;
|
|
107
|
+
margin: 2px;
|
|
108
|
+
border-radius: 4px;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
font-size: 0.9em;
|
|
67
111
|
}
|
|
68
112
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
transform: scale(1.2); /* Larger checkbox size */
|
|
73
|
-
transition: transform 0.3s ease; /* Smooth scaling effect */
|
|
113
|
+
.btn.quiet {
|
|
114
|
+
background: #e0e0e0;
|
|
115
|
+
border: 1px solid #ccc;
|
|
74
116
|
}
|
|
75
117
|
|
|
76
|
-
|
|
77
|
-
|
|
118
|
+
.btn.stop {
|
|
119
|
+
background: crimson;
|
|
120
|
+
color: white;
|
|
121
|
+
border: none;
|
|
78
122
|
}
|
|
79
123
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
font-size: 1rem;
|
|
83
|
-
color: #333;
|
|
84
|
-
margin-bottom: 8px;
|
|
124
|
+
.controls {
|
|
125
|
+
margin-bottom: 30px;
|
|
85
126
|
}
|
|
86
127
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
margin-bottom: 15px; /* Increase margin for better spacing */
|
|
90
|
-
display: block;
|
|
91
|
-
padding: 12px 20px; /* More padding for the button */
|
|
92
|
-
background-color: #007bff;
|
|
128
|
+
footer {
|
|
129
|
+
background: #222;
|
|
93
130
|
color: white;
|
|
94
|
-
border-radius: 25px;
|
|
95
|
-
cursor: pointer;
|
|
96
|
-
font-size: 1.1rem;
|
|
97
131
|
text-align: center;
|
|
98
|
-
|
|
99
|
-
|
|
132
|
+
padding: 10px;
|
|
133
|
+
font-size: 0.85em;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.export-container {
|
|
137
|
+
max-width: 1200px;
|
|
138
|
+
margin: 20px auto;
|
|
139
|
+
padding: 20px;
|
|
140
|
+
background: #fff;
|
|
141
|
+
border-radius: 4px;
|
|
142
|
+
border: 1px solid rgb(221, 221, 221);
|
|
100
143
|
}
|
|
101
144
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
transform: scale(1.05); /* Slight grow effect on hover */
|
|
145
|
+
.select-table {
|
|
146
|
+
margin-bottom: 20px;
|
|
105
147
|
}
|
|
106
148
|
|
|
107
|
-
|
|
149
|
+
.select-table label {
|
|
150
|
+
display: block;
|
|
151
|
+
margin-bottom: 8px;
|
|
152
|
+
font-weight: 600;
|
|
153
|
+
color: #333;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.select2-container {
|
|
157
|
+
width: 100% !important;
|
|
158
|
+
max-width: 400px;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* Export Form Styles */
|
|
162
|
+
.export-form {
|
|
163
|
+
padding: 20px;
|
|
164
|
+
background: #f9f9f9;
|
|
165
|
+
border-radius: 6px;
|
|
108
166
|
margin-top: 20px;
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.select-all-container {
|
|
170
|
+
padding: 10px 0;
|
|
171
|
+
margin-bottom: 15px;
|
|
172
|
+
border-bottom: 1px solid #e0e0e0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.checkbox-grid {
|
|
176
|
+
display: grid;
|
|
177
|
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
|
178
|
+
gap: 12px;
|
|
179
|
+
margin-bottom: 20px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.checkbox-item {
|
|
183
|
+
display: flex;
|
|
184
|
+
align-items: center;
|
|
185
|
+
padding: 6px 0;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.export-select {
|
|
189
|
+
margin-right: 10px;
|
|
190
|
+
width: 16px;
|
|
191
|
+
height: 16px;
|
|
192
|
+
accent-color: #397e3b;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.export-label {
|
|
196
|
+
font-size: 14px;
|
|
197
|
+
color: #444;
|
|
114
198
|
cursor: pointer;
|
|
115
|
-
|
|
116
|
-
transition: background-color 0.3s ease, transform 0.3s ease;
|
|
199
|
+
user-select: none;
|
|
117
200
|
}
|
|
118
201
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
202
|
+
/* Buttons Styles */
|
|
203
|
+
.buttons-container {
|
|
204
|
+
display: flex;
|
|
205
|
+
flex-wrap: wrap;
|
|
206
|
+
gap: 10px;
|
|
207
|
+
padding-top: 15px;
|
|
208
|
+
border-top: 1px solid #e0e0e0;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.export-button {
|
|
212
|
+
padding: 8px 16px;
|
|
213
|
+
border-radius: 4px;
|
|
214
|
+
font-size: 14px;
|
|
215
|
+
font-weight: 500;
|
|
216
|
+
cursor: pointer;
|
|
217
|
+
transition: all 0.2s ease;
|
|
218
|
+
border: none;
|
|
219
|
+
color: white;
|
|
220
|
+
background-color: #397e3b;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.export-button:hover {
|
|
224
|
+
opacity: 0.9;
|
|
225
|
+
transform: translateY(-1px);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@media (max-width: 768px) {
|
|
229
|
+
.checkbox-grid {
|
|
230
|
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
.buttons-container {
|
|
234
|
+
flex-direction: column;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.export-button {
|
|
238
|
+
width: 100%;
|
|
239
|
+
}
|
|
122
240
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
module ExportManager
|
|
2
|
+
class ExportCustomQueriesController < ApplicationController
|
|
3
|
+
before_action :set_export_custom_query, only: [ :show, :edit, :update, :destroy ]
|
|
4
|
+
before_action :set_model, only: [ :show, :edit, :new ]
|
|
5
|
+
|
|
6
|
+
# GET /export_manager/export_custom_queries
|
|
7
|
+
def index
|
|
8
|
+
@export_custom_queries = ExportCustomQuery.all
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# GET /export_manager/export_custom_queries/1
|
|
12
|
+
def show
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# GET /export_manager/export_custom_queries/new
|
|
16
|
+
def new
|
|
17
|
+
@export_custom_query = ExportCustomQuery.new
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# GET /export_manager/export_custom_queries/1/edit
|
|
21
|
+
def edit
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# POST /export_manager/export_custom_queries
|
|
25
|
+
def create
|
|
26
|
+
@export_custom_query = ExportCustomQuery.new(export_custom_query_params)
|
|
27
|
+
|
|
28
|
+
if @export_custom_query.save
|
|
29
|
+
redirect_to @export_custom_query, notice: "Export custom query was successfully created."
|
|
30
|
+
else
|
|
31
|
+
render :new
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# PATCH/PUT /export_manager/export_custom_queries/1
|
|
36
|
+
def update
|
|
37
|
+
if @export_custom_query.update(export_custom_query_params)
|
|
38
|
+
redirect_to @export_custom_query, notice: "Export custom query was successfully updated."
|
|
39
|
+
else
|
|
40
|
+
render :edit
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# DELETE /export_manager/export_custom_queries/1
|
|
45
|
+
def destroy
|
|
46
|
+
@export_custom_query.destroy
|
|
47
|
+
redirect_to export_manager_export_custom_queries_url, notice: "Export custom query was successfully destroyed."
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
# Use callbacks to share common setup or constraints between actions.
|
|
52
|
+
def set_export_custom_query
|
|
53
|
+
@export_custom_query = ExportCustomQuery.find(params[:id])
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Only allow a list of trusted parameters through.
|
|
57
|
+
def export_custom_query_params
|
|
58
|
+
params.require(:export_custom_query).permit(:name, :model, :query)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def set_model
|
|
62
|
+
remove_table = defined?(REMOVE_TABLE_NAME) ? REMOVE_TABLE_NAME : []
|
|
63
|
+
|
|
64
|
+
@model_name = ActiveRecord::Base.connection.tables.map do |t|
|
|
65
|
+
next if remove_table.include?(t.downcase)
|
|
66
|
+
|
|
67
|
+
formatted_name = t.gsub("_", " ").titleize.gsub(" ", "")
|
|
68
|
+
[ formatted_name, t ]
|
|
69
|
+
end.compact
|
|
70
|
+
|
|
71
|
+
if remove_table.present?
|
|
72
|
+
@model_name.delete_if { |item| remove_table.any? { |target| item.include?(target) } }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
@model_name
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<%= form_with(model: export_custom_query, url: export_custom_queries_path, local: true) do |form| %>
|
|
2
|
+
<% if export_custom_query.errors.any? %>
|
|
3
|
+
<div id="error_explanation">
|
|
4
|
+
<h2><%= pluralize(export_custom_query.errors.count, "error") %> prohibited this export_custom_query from being saved:</h2>
|
|
5
|
+
|
|
6
|
+
<ul>
|
|
7
|
+
<% export_custom_query.errors.full_messages.each do |message| %>
|
|
8
|
+
<li><%= message %></li>
|
|
9
|
+
<% end %>
|
|
10
|
+
</ul>
|
|
11
|
+
</div>
|
|
12
|
+
<% end %>
|
|
13
|
+
|
|
14
|
+
<div class="field">
|
|
15
|
+
<%= form.label :name %>
|
|
16
|
+
<%= form.text_field :name %>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
<div class="field">
|
|
21
|
+
<%= form.label :model %>
|
|
22
|
+
<%= select_tag 'model', options_for_select(@model_name), include_blank: 'Select Table', id: 'table-select', class: 'basic-single' %>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
<div class="field">
|
|
27
|
+
<%= form.label :query %>
|
|
28
|
+
<%= form.text_area :query %>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<div class="actions">
|
|
32
|
+
<%= form.submit %>
|
|
33
|
+
</div>
|
|
34
|
+
<% end %>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<h1>Export Custom Queries</h1>
|
|
2
|
+
|
|
3
|
+
<table>
|
|
4
|
+
<thead>
|
|
5
|
+
<tr>
|
|
6
|
+
<th>Name</th>
|
|
7
|
+
<th>Model</th>
|
|
8
|
+
<th>Query</th>
|
|
9
|
+
<th colspan="3"></th>
|
|
10
|
+
</tr>
|
|
11
|
+
</thead>
|
|
12
|
+
|
|
13
|
+
<tbody>
|
|
14
|
+
<% @export_custom_queries.each do |export_custom_query| %>
|
|
15
|
+
<tr>
|
|
16
|
+
<td><%= export_custom_query.name %></td>
|
|
17
|
+
<td><%= export_custom_query.model %></td>
|
|
18
|
+
<td><%= export_custom_query.query %></td>
|
|
19
|
+
<td><%= link_to 'Show', export_custom_query %></td>
|
|
20
|
+
<td><%= link_to 'Edit', edit_export_custom_query_path(export_custom_query) %></td>
|
|
21
|
+
<td><%= link_to 'Destroy', export_custom_query, method: :delete, data: { confirm: 'Are you sure?' } %></td>
|
|
22
|
+
</tr>
|
|
23
|
+
<% end %>
|
|
24
|
+
</tbody>
|
|
25
|
+
</table>
|
|
26
|
+
|
|
27
|
+
<br>
|
|
28
|
+
|
|
29
|
+
<%= link_to 'New Export Custom Query', new_export_custom_query_path %>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<p id="notice"><%= notice %></p>
|
|
2
|
+
|
|
3
|
+
<p>
|
|
4
|
+
<strong>Name:</strong>
|
|
5
|
+
<%= @export_custom_query.name %>
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p>
|
|
9
|
+
<strong>Model:</strong>
|
|
10
|
+
<%= @export_custom_query.model %>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p>
|
|
14
|
+
<strong>Query:</strong>
|
|
15
|
+
<%= @export_custom_query.query %>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<%= link_to 'Edit', edit_export_custom_query_path(@export_custom_query) %> |
|
|
19
|
+
<%= link_to 'Back', export_custom_queries_path %>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
// Handle change event
|
|
14
14
|
$('#table-select').change(function() {
|
|
15
15
|
var selectTable = $(this).val();
|
|
16
|
+
if (!selectTable) return;
|
|
16
17
|
console.log('Calling API to get column names');
|
|
17
18
|
|
|
18
19
|
$.ajax({
|
|
@@ -27,16 +28,18 @@
|
|
|
27
28
|
id: 'checkbox-form',
|
|
28
29
|
action: '/download',
|
|
29
30
|
method: 'GET'
|
|
30
|
-
});
|
|
31
|
+
}).addClass('export-form');
|
|
31
32
|
|
|
32
33
|
var hiddenField1 = $('<input>').attr({
|
|
33
34
|
type: 'hidden',
|
|
34
35
|
name: 'table',
|
|
35
|
-
value:
|
|
36
|
+
value: selectTable
|
|
36
37
|
});
|
|
37
38
|
|
|
38
39
|
form.append(hiddenField1);
|
|
39
40
|
|
|
41
|
+
// Create select all section
|
|
42
|
+
var selectAllContainer = $('<div>').addClass('select-all-container');
|
|
40
43
|
var selectAllCheckbox = $('<input>').attr({
|
|
41
44
|
type: 'checkbox',
|
|
42
45
|
id: 'select-all',
|
|
@@ -44,76 +47,88 @@
|
|
|
44
47
|
checked: true,
|
|
45
48
|
class: 'export-select'
|
|
46
49
|
}).on('change', function() {
|
|
47
|
-
$('
|
|
50
|
+
$('.export-select:not(#select-all)').prop('checked', $(this).prop('checked'));
|
|
48
51
|
});
|
|
49
52
|
|
|
50
|
-
var selectAllLabel = $('<label>').attr('for', 'select-all')
|
|
53
|
+
var selectAllLabel = $('<label>').attr('for', 'select-all')
|
|
54
|
+
.text('Select All')
|
|
55
|
+
.addClass('export-label');
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
marginBottom: '15px'
|
|
56
|
-
});
|
|
57
|
+
selectAllContainer.append(selectAllCheckbox)
|
|
58
|
+
.append(selectAllLabel);
|
|
59
|
+
form.append(selectAllContainer);
|
|
57
60
|
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
// Create checkbox grid
|
|
62
|
+
var checkboxGrid = $('<div>').addClass('checkbox-grid');
|
|
60
63
|
|
|
61
64
|
for (var i = 0; i < response.length; i++) {
|
|
62
65
|
var key = response[i];
|
|
66
|
+
var checkboxItem = $('<div>').addClass('checkbox-item');
|
|
67
|
+
|
|
63
68
|
var checkbox = $('<input>').attr({
|
|
64
69
|
type: 'checkbox',
|
|
65
70
|
id: key,
|
|
66
71
|
name: key,
|
|
67
72
|
value: key,
|
|
68
|
-
checked:
|
|
73
|
+
checked: true,
|
|
69
74
|
class: 'export-select'
|
|
70
75
|
});
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
|
|
77
|
+
var label = $('<label>').attr('for', key)
|
|
78
|
+
.text(key)
|
|
79
|
+
.addClass('export-label');
|
|
80
|
+
|
|
81
|
+
checkboxItem.append(checkbox).append(label);
|
|
82
|
+
checkboxGrid.append(checkboxItem);
|
|
73
83
|
}
|
|
74
84
|
|
|
75
|
-
|
|
85
|
+
form.append(checkboxGrid);
|
|
86
|
+
|
|
87
|
+
// Create buttons container
|
|
88
|
+
var buttonsContainer = $('<div>').addClass('buttons-container');
|
|
89
|
+
|
|
90
|
+
var exportTypeField = $('<input>').attr({
|
|
91
|
+
type: 'hidden',
|
|
92
|
+
name: 'type',
|
|
93
|
+
id: 'export-type',
|
|
94
|
+
value: 'CSV'
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
var csvButton = $('<button>').attr({
|
|
76
98
|
type: 'submit',
|
|
77
|
-
value: 'Export CSV',
|
|
78
99
|
class: 'export-button'
|
|
79
|
-
}).on('click', function() {
|
|
100
|
+
}).text('Export CSV').on('click', function() {
|
|
80
101
|
$('#export-type').val('csv');
|
|
81
102
|
});
|
|
82
103
|
|
|
83
|
-
var excelButton = $('<
|
|
104
|
+
var excelButton = $('<button>').attr({
|
|
84
105
|
type: 'submit',
|
|
85
|
-
value: 'Export EXCEL',
|
|
86
106
|
class: 'export-button'
|
|
87
|
-
}).on('click', function() {
|
|
107
|
+
}).text('Export Excel').on('click', function() {
|
|
88
108
|
$('#export-type').val('excel');
|
|
89
109
|
});
|
|
90
110
|
|
|
91
|
-
var jsonButton = $('<
|
|
111
|
+
var jsonButton = $('<button>').attr({
|
|
92
112
|
type: 'submit',
|
|
93
|
-
value: 'Export JSON',
|
|
94
113
|
class: 'export-button'
|
|
95
|
-
}).on('click', function() {
|
|
114
|
+
}).text('Export JSON').on('click', function() {
|
|
96
115
|
$('#export-type').val('json');
|
|
97
116
|
});
|
|
98
117
|
|
|
99
|
-
var xmlButton = $('<
|
|
118
|
+
var xmlButton = $('<button>').attr({
|
|
100
119
|
type: 'submit',
|
|
101
|
-
value: 'Export XML',
|
|
102
120
|
class: 'export-button'
|
|
103
|
-
}).on('click', function() {
|
|
121
|
+
}).text('Export XML').on('click', function() {
|
|
104
122
|
$('#export-type').val('xml');
|
|
105
123
|
});
|
|
106
124
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
form.append(exportTypeField);
|
|
115
|
-
form.append(csvButton).append(excelButton).append(jsonButton).append(xmlButton);
|
|
125
|
+
buttonsContainer.append(exportTypeField)
|
|
126
|
+
.append(csvButton)
|
|
127
|
+
.append(excelButton)
|
|
128
|
+
.append(jsonButton)
|
|
129
|
+
.append(xmlButton);
|
|
116
130
|
|
|
131
|
+
form.append(buttonsContainer);
|
|
117
132
|
checkboxesContainer.append(form);
|
|
118
133
|
},
|
|
119
134
|
error: function() {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
4
6
|
<title>Export manager</title>
|
|
5
7
|
<%= csrf_meta_tags %>
|
|
6
8
|
<%= csp_meta_tag %>
|
|
@@ -12,8 +14,18 @@
|
|
|
12
14
|
<%= javascript_include_tag 'export_manager/application', 'data-turbolinks-track': 'reload' %>
|
|
13
15
|
</head>
|
|
14
16
|
<body>
|
|
17
|
+
<nav class="navbar">
|
|
18
|
+
<div class="logo"><span class="green">Export Manager</span></div>
|
|
19
|
+
<ul>
|
|
20
|
+
<li class="<%= 'active' if request.path == '/export' %>">
|
|
21
|
+
<a href="/export">Dashboard</a>
|
|
22
|
+
</li>
|
|
23
|
+
</ul>
|
|
24
|
+
</nav>
|
|
15
25
|
|
|
16
|
-
|
|
26
|
+
<section class="export-container">
|
|
27
|
+
<%= yield %>
|
|
28
|
+
</section>
|
|
17
29
|
|
|
18
30
|
</body>
|
|
19
31
|
</html>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# lib/generators/my_gem/install_generator.rb
|
|
2
|
+
#
|
|
3
|
+
require "rails/generators"
|
|
4
|
+
require "rails/generators/migration"
|
|
5
|
+
|
|
6
|
+
module ExportManager
|
|
7
|
+
module Generators
|
|
8
|
+
class InstallGenerator < Rails::Generators::Base
|
|
9
|
+
include Rails::Generators::Migration
|
|
10
|
+
|
|
11
|
+
source_root File.expand_path("templates", __dir__)
|
|
12
|
+
|
|
13
|
+
def copy_migration
|
|
14
|
+
migration_template "create_custom_query_table.rb", "db/migrate/create_custom_query_table.rb"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.next_migration_number(dirname)
|
|
18
|
+
if ActiveRecord::Base.timestamped_migrations
|
|
19
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
|
20
|
+
else
|
|
21
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: export_manager
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Vishal Mahto
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2025-09-23 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rails
|
|
@@ -25,8 +24,8 @@ dependencies:
|
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
25
|
version: '7.0'
|
|
27
26
|
description: The ExportManager allows users to export data from dynamic tables with
|
|
28
|
-
dynamic columns. The system provides flexibility in
|
|
29
|
-
and generates a CSV file accordingly.
|
|
27
|
+
dynamic columns. The system provides flexibility in selecting the data to be exported
|
|
28
|
+
and generates a CSV, JSON, Excel, or XML file accordingly.
|
|
30
29
|
email:
|
|
31
30
|
- vishalgmahto@proton.me
|
|
32
31
|
executables: []
|
|
@@ -42,26 +41,35 @@ files:
|
|
|
42
41
|
- app/assets/stylesheets/export_manager/export.css
|
|
43
42
|
- app/assets/stylesheets/export_manager/select.css
|
|
44
43
|
- app/controllers/export_manager/application_controller.rb
|
|
44
|
+
- app/controllers/export_manager/export_custom_queries_controller.rb
|
|
45
45
|
- app/controllers/export_manager/export_manager_controller.rb
|
|
46
46
|
- app/helpers/export_manager/application_helper.rb
|
|
47
47
|
- app/jobs/export_manager/application_job.rb
|
|
48
48
|
- app/mailers/export_manager/application_mailer.rb
|
|
49
49
|
- app/models/export_manager/application_record.rb
|
|
50
|
+
- app/models/export_manager/export_custom_query.rb
|
|
51
|
+
- app/views/export_manager/export_custom_queries/_form.html.erb
|
|
52
|
+
- app/views/export_manager/export_custom_queries/edit.html.erb
|
|
53
|
+
- app/views/export_manager/export_custom_queries/index.html.erb
|
|
54
|
+
- app/views/export_manager/export_custom_queries/new.html.erb
|
|
55
|
+
- app/views/export_manager/export_custom_queries/show.html.erb
|
|
50
56
|
- app/views/export_manager/export_manager/export.html.erb
|
|
51
57
|
- app/views/layouts/export_manager/application.html.erb
|
|
52
58
|
- config/routes.rb
|
|
53
59
|
- lib/export_manager.rb
|
|
54
60
|
- lib/export_manager/engine.rb
|
|
55
61
|
- lib/export_manager/version.rb
|
|
62
|
+
- lib/generators/export_manager/install_generator.rb
|
|
63
|
+
- lib/generators/export_manager/templates/create_custom_query_table.rb
|
|
56
64
|
- lib/tasks/export_manager_tasks.rake
|
|
57
65
|
homepage: https://github.com/VishalMahtog/export_manager
|
|
58
66
|
licenses:
|
|
59
67
|
- MIT
|
|
60
68
|
metadata:
|
|
69
|
+
keywords: export, csv, excel, JSON, json, xml, XML, export data, Export, gem, ruby
|
|
61
70
|
homepage_uri: https://github.com/VishalMahtog/export_manager
|
|
62
71
|
source_code_uri: https://github.com/VishalMahtog/export_manager
|
|
63
72
|
changelog_uri: http://mygemserver.com
|
|
64
|
-
post_install_message:
|
|
65
73
|
rdoc_options: []
|
|
66
74
|
require_paths:
|
|
67
75
|
- lib
|
|
@@ -76,8 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
76
84
|
- !ruby/object:Gem::Version
|
|
77
85
|
version: '0'
|
|
78
86
|
requirements: []
|
|
79
|
-
rubygems_version: 3.
|
|
80
|
-
signing_key:
|
|
87
|
+
rubygems_version: 3.6.2
|
|
81
88
|
specification_version: 4
|
|
82
|
-
summary: ExportManager handles the dynamic export of table data to CSV
|
|
89
|
+
summary: ExportManager handles the dynamic export of table data to CSV, JSON, Excel,
|
|
90
|
+
or XML format.
|
|
83
91
|
test_files: []
|