mysqlsyncr 1.0.15 → 1.0.16

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.
@@ -1,3 +1,3 @@
1
- <!DOCTYPE html><html><head><title>MySQLsyncr</title><meta charset=utf-8><meta name=description content="A simple ui for the sync features in mysqlsyncr"><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=/icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=/icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=/icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/icons/favicon-16x16.png><link rel=icon type=image/ico href=/favicon.ico> <script type="module" crossorigin src="/assets/index-Bgaq8Ay7.js"></script>
2
- <link rel="stylesheet" crossorigin href="/assets/index-DbZFTc3Z.css">
1
+ <!DOCTYPE html><html><head><title>MySQLsyncr</title><meta charset=utf-8><meta name=description content="A simple ui for the sync features in mysqlsyncr"><meta name=format-detection content="telephone=no"><meta name=msapplication-tap-highlight content=no><meta name=viewport content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width"><link rel=icon type=image/png sizes=128x128 href=/icons/favicon-128x128.png><link rel=icon type=image/png sizes=96x96 href=/icons/favicon-96x96.png><link rel=icon type=image/png sizes=32x32 href=/icons/favicon-32x32.png><link rel=icon type=image/png sizes=16x16 href=/icons/favicon-16x16.png><link rel=icon type=image/ico href=/favicon.ico> <script type="module" crossorigin src="/assets/index-8ohClfZU.js"></script>
2
+ <link rel="stylesheet" crossorigin href="/assets/index-767_aev0.css">
3
3
  </head><body><div id=q-app></div></body></html>
@@ -0,0 +1,194 @@
1
+ <template>
2
+ <q-dialog v-model="isOpen" persistent>
3
+ <q-card class="folder-browser-card">
4
+ <q-card-section class="header-section row items-center justify-between">
5
+ <div class="text-h6">Select Folder</div>
6
+ <q-btn icon="close" flat round dense v-close-popup />
7
+ </q-card-section>
8
+
9
+ <q-card-section>
10
+ <div class="path-section">
11
+ <div class="text-subtitle2 q-mb-sm">Current Path:</div>
12
+ <q-input
13
+ v-model="currentPath"
14
+ dense
15
+ readonly
16
+ filled
17
+ class="current-path-input"
18
+ bg-color="grey-2"
19
+ >
20
+ <template v-slot:prepend>
21
+ <q-icon name="folder" color="primary" />
22
+ </template>
23
+ </q-input>
24
+ </div>
25
+
26
+ <q-list bordered separator class="directory-list">
27
+ <q-item
28
+ v-for="item in sortedItems"
29
+ :key="item.path"
30
+ clickable
31
+ v-ripple
32
+ @click="item.isDirectory ? navigateToFolder(item.path) : null"
33
+ class="directory-item"
34
+ >
35
+ <q-item-section avatar>
36
+ <q-icon
37
+ :name="getItemIcon(item)"
38
+ :color="getItemColor(item)"
39
+ size="sm"
40
+ />
41
+ </q-item-section>
42
+ <q-item-section>
43
+ {{ item.name }}
44
+ </q-item-section>
45
+ <q-item-section side v-if="item.isDirectory">
46
+ <q-icon name="chevron_right" color="grey-6" size="xs" />
47
+ </q-item-section>
48
+ </q-item>
49
+ </q-list>
50
+ </q-card-section>
51
+
52
+ <q-card-actions align="right" class="action-buttons">
53
+ <q-btn
54
+ flat
55
+ label="Cancel"
56
+ color="grey-7"
57
+ v-close-popup
58
+ class="q-px-md"
59
+ />
60
+ <q-btn
61
+ unelevated
62
+ label="Select"
63
+ color="primary"
64
+ @click="selectCurrentFolder"
65
+ class="q-px-md q-ml-sm"
66
+ />
67
+ </q-card-actions>
68
+ </q-card>
69
+ </q-dialog>
70
+ </template>
71
+
72
+ <script>
73
+ import axios from 'axios';
74
+
75
+ export default {
76
+ name: 'FolderBrowser',
77
+ props: {
78
+ modelValue: {
79
+ type: Boolean,
80
+ required: true
81
+ },
82
+ initialPath: {
83
+ type: String,
84
+ default: ''
85
+ }
86
+ },
87
+ data() {
88
+ return {
89
+ currentPath: '',
90
+ items: []
91
+ }
92
+ },
93
+ computed: {
94
+ isOpen: {
95
+ get() {
96
+ return this.modelValue
97
+ },
98
+ set(value) {
99
+ this.$emit('update:modelValue', value)
100
+ }
101
+ },
102
+ sortedItems() {
103
+ return this.items;
104
+ }
105
+ },
106
+ methods: {
107
+ async navigateToFolder(folderPath) {
108
+ await this.loadFolderContents(folderPath);
109
+ },
110
+
111
+ async loadFolderContents(path) {
112
+ try {
113
+ const response = await axios.post('http://localhost:3000/api/browse-folders', {
114
+ currentPath: path
115
+ });
116
+
117
+ if (response.data) {
118
+ this.currentPath = response.data.currentPath;
119
+ this.items = response.data.items || [];
120
+ }
121
+ } catch (error) {
122
+ console.error('Error loading folder contents:', error);
123
+ this.$q.notify({
124
+ type: 'negative',
125
+ message: 'Error loading folder contents'
126
+ });
127
+ }
128
+ },
129
+
130
+ selectCurrentFolder() {
131
+ this.$emit('folder-selected', this.currentPath);
132
+ this.isOpen = false;
133
+ },
134
+
135
+ getItemIcon(item) {
136
+ if (item.isParent) return 'reply';
137
+ if (item.isDirectory) return 'folder';
138
+ return 'insert_drive_file';
139
+ },
140
+
141
+ getItemColor(item) {
142
+ if (item.isParent) return 'grey-7';
143
+ if (item.isDirectory) return 'primary';
144
+ return 'grey-6';
145
+ }
146
+ },
147
+ async mounted() {
148
+ await this.loadFolderContents(this.initialPath || process.cwd());
149
+ }
150
+ }
151
+ </script>
152
+
153
+ <style scoped>
154
+ .folder-browser-card {
155
+ min-width: 450px;
156
+ max-width: 700px;
157
+ border-radius: 8px;
158
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
159
+ }
160
+
161
+ .header-section {
162
+ background-color: #f5f5f5;
163
+ border-bottom: 1px solid #e0e0e0;
164
+ padding: 12px 20px;
165
+ }
166
+
167
+ .path-section {
168
+ margin-bottom: 20px;
169
+ }
170
+
171
+ .current-path-input {
172
+ font-family: monospace;
173
+ }
174
+
175
+ .directory-list {
176
+ max-height: 400px;
177
+ overflow-y: auto;
178
+ border-radius: 4px;
179
+ border: 1px solid #e0e0e0;
180
+ }
181
+
182
+ .directory-item {
183
+ transition: background-color 0.2s;
184
+ }
185
+
186
+ .directory-item:hover {
187
+ background-color: #f0f4f8;
188
+ }
189
+
190
+ .action-buttons {
191
+ padding: 16px;
192
+ border-top: 1px solid #e0e0e0;
193
+ }
194
+ </style>
@@ -200,7 +200,6 @@
200
200
  <q-input
201
201
  v-model="dbFolder"
202
202
  label="Database Folder"
203
-
204
203
  default="db-dump"
205
204
  filled
206
205
  class="q-mb-md"
@@ -209,6 +208,16 @@
209
208
  <template v-slot:prepend>
210
209
  <q-icon name="folder" />
211
210
  </template>
211
+ <template v-slot:append>
212
+ <q-btn
213
+ flat
214
+ dense
215
+ icon="folder_open"
216
+ @click="showFolderBrowser = true"
217
+ >
218
+ <q-tooltip>Browse</q-tooltip>
219
+ </q-btn>
220
+ </template>
212
221
  </q-input>
213
222
  </div>
214
223
  </div>
@@ -374,13 +383,24 @@
374
383
  </q-card-actions>
375
384
  </q-card>
376
385
  </q-dialog>
386
+
387
+ <FolderBrowser v-if="showFolderBrowser"
388
+ v-model="showFolderBrowser"
389
+ :initial-path="dbFolder"
390
+ @folder-selected="onFolderSelected"
391
+ />
377
392
  </q-page>
378
393
  </template>
379
394
 
380
395
  <script>
381
396
  import axios from 'axios'
397
+ import FolderBrowser from '../components/FolderBrowser.vue'
398
+
382
399
 
383
400
  export default {
401
+ components: {
402
+ FolderBrowser
403
+ },
384
404
  data() {
385
405
  return {
386
406
  isDbSetup: false,
@@ -407,6 +427,7 @@ export default {
407
427
  selectedIssues: [],
408
428
  selectedNode: null,
409
429
  isNodeFixing: {}, // Tracks loading state for each node
430
+ showFolderBrowser: false,
410
431
  }
411
432
  },
412
433
  methods: {
@@ -989,6 +1010,19 @@ export default {
989
1010
  this.isApplying = false
990
1011
  }
991
1012
  },
1013
+ onFolderSelected(path) {
1014
+ this.dbFolder = path;
1015
+ // If you want to save the setting immediately
1016
+ const dbConfig = {
1017
+ host: this.host,
1018
+ port: this.port,
1019
+ user: this.user,
1020
+ password: this.password,
1021
+ database: this.database,
1022
+ output: this.dbFolder,
1023
+ }
1024
+ localStorage.setItem('dbConfig', JSON.stringify(dbConfig));
1025
+ },
992
1026
  },
993
1027
  mounted() {
994
1028
  const dbConfig = localStorage.getItem('dbConfig')