mango-cms 0.0.13
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.
- package/README.md +17 -0
- package/bin/mango +4 -0
- package/frontend-starter/README.md +8 -0
- package/frontend-starter/dist/_redirects +1 -0
- package/frontend-starter/dist/assets/index.00922bd5.js +99 -0
- package/frontend-starter/dist/assets/index.1781f175.css +1 -0
- package/frontend-starter/dist/favicon.png +0 -0
- package/frontend-starter/dist/index.html +53 -0
- package/frontend-starter/dist/index.js +66 -0
- package/frontend-starter/index.html +25 -0
- package/frontend-starter/index.js +197 -0
- package/frontend-starter/package-lock.json +5454 -0
- package/frontend-starter/package.json +40 -0
- package/frontend-starter/postcss.config.js +6 -0
- package/frontend-starter/public/_redirects +1 -0
- package/frontend-starter/public/favicon.png +0 -0
- package/frontend-starter/public/index.js +66 -0
- package/frontend-starter/src/App.vue +27 -0
- package/frontend-starter/src/components/layout/login.vue +212 -0
- package/frontend-starter/src/components/layout/modal.vue +113 -0
- package/frontend-starter/src/components/layout/spinner.vue +17 -0
- package/frontend-starter/src/components/pages/404.vue +28 -0
- package/frontend-starter/src/components/pages/home.vue +74 -0
- package/frontend-starter/src/components/partials/button.vue +31 -0
- package/frontend-starter/src/helpers/Mango.vue +455 -0
- package/frontend-starter/src/helpers/breakpoints.js +34 -0
- package/frontend-starter/src/helpers/darkMode.js +38 -0
- package/frontend-starter/src/helpers/email.js +32 -0
- package/frontend-starter/src/helpers/formatPhone.js +18 -0
- package/frontend-starter/src/helpers/localDB.js +315 -0
- package/frontend-starter/src/helpers/mango.js +338 -0
- package/frontend-starter/src/helpers/model.js +9 -0
- package/frontend-starter/src/helpers/multiSelect.vue +252 -0
- package/frontend-starter/src/helpers/pills.vue +75 -0
- package/frontend-starter/src/helpers/reconnecting-websocket.js +357 -0
- package/frontend-starter/src/helpers/uploadFile.vue +157 -0
- package/frontend-starter/src/helpers/uploadFiles.vue +100 -0
- package/frontend-starter/src/helpers/uploadImages.vue +89 -0
- package/frontend-starter/src/helpers/user.js +40 -0
- package/frontend-starter/src/index.css +281 -0
- package/frontend-starter/src/main.js +145 -0
- package/frontend-starter/tailwind.config.js +46 -0
- package/frontend-starter/vite.config.js +10 -0
- package/frontend-starter/yarn.lock +3380 -0
- package/mango-cms-0.0.13.tgz +0 -0
- package/package.json +24 -0
- package/src/cli.js +93 -0
- package/src/default-config/automation/index.js +37 -0
- package/src/default-config/collections/examples.js +60 -0
- package/src/default-config/config/.collections.json +1 -0
- package/src/default-config/config/globalFields.js +15 -0
- package/src/default-config/config/settings.json +23 -0
- package/src/default-config/config/statuses.js +0 -0
- package/src/default-config/config/users.js +35 -0
- package/src/default-config/endpoints/index.js +19 -0
- package/src/default-config/fields/vimeo.js +36 -0
- package/src/default-config/hooks/test.js +5 -0
- package/src/default-config/plugins/mango-stand/index.js +206 -0
- package/src/main.js +278 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
import axios from "axios"
|
|
2
|
+
import Mango from "./mango"
|
|
3
|
+
import Swal from "sweetalert2"
|
|
4
|
+
|
|
5
|
+
// Function for setting cookies
|
|
6
|
+
let setCookie = function (cname, cvalue) {
|
|
7
|
+
var d = new Date();
|
|
8
|
+
d.setTime(d.getTime() + (365 * 24 * 60 * 60 * 1000));
|
|
9
|
+
var expires = "expires=" + d.toUTCString();
|
|
10
|
+
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function timeout(ms) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
reject(new Error(`Timeout after ${ms} ms`));
|
|
17
|
+
}, ms);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function runWithTimeout(callback, ms) {
|
|
22
|
+
try {
|
|
23
|
+
let response = await Promise.race([
|
|
24
|
+
callback(),
|
|
25
|
+
timeout(ms)
|
|
26
|
+
]);
|
|
27
|
+
console.log('timeout', response)
|
|
28
|
+
return response;
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error(error.message);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default class LocalDB {
|
|
35
|
+
|
|
36
|
+
constructor(collection, api) {
|
|
37
|
+
|
|
38
|
+
this.collection = collection
|
|
39
|
+
|
|
40
|
+
this.getDb()
|
|
41
|
+
|
|
42
|
+
this.ready = false
|
|
43
|
+
this.db = null
|
|
44
|
+
this.loading = false
|
|
45
|
+
this.saving = false
|
|
46
|
+
this.deleting = false
|
|
47
|
+
this.entry = null
|
|
48
|
+
this.entries = null
|
|
49
|
+
|
|
50
|
+
this.api = api
|
|
51
|
+
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async getDb() {
|
|
55
|
+
|
|
56
|
+
let request = window.indexedDB.open(this.collection, 1);
|
|
57
|
+
|
|
58
|
+
request.onerror = e => {
|
|
59
|
+
this.ready = false
|
|
60
|
+
console.error('Error opening db', e);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
request.onsuccess = e => {
|
|
64
|
+
this.db = e.target.result
|
|
65
|
+
this.ready = true
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
request.onupgradeneeded = e => {
|
|
69
|
+
console.log('onupgradeneeded');
|
|
70
|
+
this.db = e.target.result;
|
|
71
|
+
let objectStore = this.db.createObjectStore(this.collection, { autoIncrement: true, keyPath: 'id' });
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async save(entry, syncing) {
|
|
77
|
+
|
|
78
|
+
if (!this.ready) return
|
|
79
|
+
|
|
80
|
+
this.saving = true;
|
|
81
|
+
|
|
82
|
+
let entryExists = !!entry.id
|
|
83
|
+
let onlyLocal = !isNaN(entry?.id) || !entryExists
|
|
84
|
+
|
|
85
|
+
let existingEntry
|
|
86
|
+
|
|
87
|
+
if (onlyLocal && entryExists) {
|
|
88
|
+
entry.id = Number(entry.id)
|
|
89
|
+
existingEntry = await this.get(entry.id)
|
|
90
|
+
} else if (entryExists) {
|
|
91
|
+
try {
|
|
92
|
+
existingEntry = await this.get(entry.id)
|
|
93
|
+
} catch {
|
|
94
|
+
// console.log('must just be in cloud')
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return await new Promise(async (resolve, reject) => {
|
|
99
|
+
|
|
100
|
+
let trans = this.db.transaction([this.collection], 'readwrite');
|
|
101
|
+
let store = trans.objectStore(this.collection);
|
|
102
|
+
|
|
103
|
+
if (existingEntry) entry = { ...existingEntry, ...entry }
|
|
104
|
+
|
|
105
|
+
// Remove Vue Proxy stuff so indexedDB is happy
|
|
106
|
+
let savedImage = entry.image
|
|
107
|
+
delete entry.image
|
|
108
|
+
entry = JSON.parse(JSON.stringify(entry))
|
|
109
|
+
if (!syncing) entry.updatedLocally = new Date()
|
|
110
|
+
|
|
111
|
+
// Format Address for offline
|
|
112
|
+
// if (!entry.address?.id && entry.address?.formatted) entry.address = entry.address.formatted
|
|
113
|
+
|
|
114
|
+
// Handle images
|
|
115
|
+
if (savedImage?.type?.includes?.('image')) entry.image = savedImage
|
|
116
|
+
if (savedImage?.includes?.('http')) entry.image = savedImage
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
let method = entryExists ? 'put' : 'add'
|
|
120
|
+
let request = store[method](entry)
|
|
121
|
+
|
|
122
|
+
request.onsuccess = async () => {
|
|
123
|
+
this.saving = false
|
|
124
|
+
let localId = request.result
|
|
125
|
+
|
|
126
|
+
if (window?.offlineMode) return resolve({ ...entry, id: localId })
|
|
127
|
+
|
|
128
|
+
// If it only exists in the localDB, remove the ID for Mango
|
|
129
|
+
if (onlyLocal) delete entry.id
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
|
|
133
|
+
// Try to upload the image
|
|
134
|
+
if (entry?.image?.type?.includes?.('image')) {
|
|
135
|
+
await runWithTimeout(async () => {
|
|
136
|
+
console.log('upload')
|
|
137
|
+
const formData = new FormData()
|
|
138
|
+
formData.append('file', entry.image)
|
|
139
|
+
const response = await axios.post(`${this.api}/upload`, formData)
|
|
140
|
+
console.log('upload response:', response)
|
|
141
|
+
const path = response?.data?.paths?.[0]
|
|
142
|
+
const url = `${this.api}${path}`
|
|
143
|
+
entry.image = url
|
|
144
|
+
}, 10 * 1000)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Save to the cloud - this will throw if offline)
|
|
148
|
+
|
|
149
|
+
// If the entry is over a day old...
|
|
150
|
+
let olderThanOneDay = new Date(entry?.updatedLocally || '1/1/2024') < new Date(new Date().getTime() - 24 * 60 * 60 * 1000)
|
|
151
|
+
if (onlyLocal && olderThanOneDay) await this.delete(localId)
|
|
152
|
+
|
|
153
|
+
delete entry.updatedLocally
|
|
154
|
+
|
|
155
|
+
// Save to Mango (timeout if already created, else no timeout)
|
|
156
|
+
let response
|
|
157
|
+
if (onlyLocal) {
|
|
158
|
+
// Check the internet speed, if too slow, throw and queue for later
|
|
159
|
+
let speedTest = await axios.get(`/images/logo.jpg?v=${Date.now()}`, { timeout: 1000 })
|
|
160
|
+
let { response: mangoResponse, warnings } = await Mango[this.collection].save(entry, null, true)
|
|
161
|
+
if (warnings?.length) Swal.fire('WARNING:', warnings?.join(', '), 'warning')
|
|
162
|
+
console.log('mangoResponse', mangoResponse)
|
|
163
|
+
response = mangoResponse
|
|
164
|
+
}
|
|
165
|
+
else response = await runWithTimeout(async () => await Mango[this.collection].save(entry), 5000)
|
|
166
|
+
|
|
167
|
+
// If successfull, delete from local queue
|
|
168
|
+
if (response?.id) {
|
|
169
|
+
await this.delete(localId)
|
|
170
|
+
resolve(response);
|
|
171
|
+
} else {
|
|
172
|
+
console.log('response', response)
|
|
173
|
+
// Mango will throw if offline so delete this entry and save it to the failed queue
|
|
174
|
+
// await Mango.failedleads.save({ data: { raw: entry }, error: response, user: window.localStorage.getItem('user') })
|
|
175
|
+
// await this.delete(localId)
|
|
176
|
+
|
|
177
|
+
// Unauthorized
|
|
178
|
+
if (typeof response == 'string' && response?.includes?.('not have permission')) {
|
|
179
|
+
// Logout if credentials are bad
|
|
180
|
+
window.localStorage.removeItem('user')
|
|
181
|
+
window.localStorage.removeItem('token')
|
|
182
|
+
window.localStorage.removeItem('email')
|
|
183
|
+
window.localStorage.removeItem('auth')
|
|
184
|
+
setCookie(`Authorization`, ``)
|
|
185
|
+
window.location.reload()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Existing Address
|
|
189
|
+
if (typeof response == 'string' && response?.includes?.('already visited this address')) {
|
|
190
|
+
await this.delete(localId)
|
|
191
|
+
Swal.fire('Existing Address', response, 'warning')
|
|
192
|
+
if (window.location.href.includes(`leads/${localId}`)) window.location.href = '/'
|
|
193
|
+
resolve({ stop: true });
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Address Lockout
|
|
197
|
+
if (typeof response == 'string' && response?.includes?.('asked not to be disturbed')) {
|
|
198
|
+
await this.delete(localId)
|
|
199
|
+
Swal.fire('Address Lockout', response, 'warning')
|
|
200
|
+
if (window.location.href.includes(`leads/${localId}`)) window.location.href = '/'
|
|
201
|
+
resolve({ stop: true });
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
console.log(response, onlyLocal);
|
|
205
|
+
resolve({ ...entry, id: localId });
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
} catch (e) {
|
|
209
|
+
console.log(e.message)
|
|
210
|
+
resolve({ ...entry, id: localId });
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
request.onerror = (e) => {
|
|
215
|
+
this.saving = false
|
|
216
|
+
reject(e);
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async get(id) {
|
|
224
|
+
|
|
225
|
+
if (!this.ready) return
|
|
226
|
+
|
|
227
|
+
this.loading = true;
|
|
228
|
+
|
|
229
|
+
return await new Promise((resolve, reject) => {
|
|
230
|
+
let trans = this.db.transaction([this.collection], 'readonly');
|
|
231
|
+
let store = trans.objectStore(this.collection);
|
|
232
|
+
let request = store.get(id);
|
|
233
|
+
|
|
234
|
+
request.onsuccess = () => {
|
|
235
|
+
this.loading = false;
|
|
236
|
+
resolve(request.result);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
request.onerror = (e) => {
|
|
240
|
+
this.loading = false;
|
|
241
|
+
reject(e);
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async getEntries({ pageIndex = 0, pageSize = 1000 } = {}) {
|
|
248
|
+
|
|
249
|
+
if (!this.ready) return []
|
|
250
|
+
|
|
251
|
+
this.loading = true;
|
|
252
|
+
|
|
253
|
+
let response = await new Promise((resolve, reject) => {
|
|
254
|
+
let trans = this.db.transaction([this.collection], 'readonly');
|
|
255
|
+
let store = trans.objectStore(this.collection);
|
|
256
|
+
let cursorRequest = store.openCursor();
|
|
257
|
+
|
|
258
|
+
let entries = [];
|
|
259
|
+
let skippedEntries = pageIndex * pageSize;
|
|
260
|
+
|
|
261
|
+
cursorRequest.onsuccess = (e) => {
|
|
262
|
+
let cursor = e.target.result;
|
|
263
|
+
if (cursor) {
|
|
264
|
+
if (skippedEntries > 0) {
|
|
265
|
+
// Skip the entries before the current page
|
|
266
|
+
cursor.advance(skippedEntries);
|
|
267
|
+
skippedEntries = 0;
|
|
268
|
+
} else {
|
|
269
|
+
entries.push(cursor.value);
|
|
270
|
+
if (entries.length < pageSize) {
|
|
271
|
+
cursor.continue();
|
|
272
|
+
} else {
|
|
273
|
+
resolve(entries);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
} else {
|
|
277
|
+
// No more entries to read; resolve with what we have
|
|
278
|
+
resolve(entries);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
cursorRequest.onerror = (e) => {
|
|
283
|
+
reject(e);
|
|
284
|
+
};
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// console.log('response', response);
|
|
288
|
+
this.loading = false;
|
|
289
|
+
return response;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async delete(id) {
|
|
293
|
+
|
|
294
|
+
this.deleting = true;
|
|
295
|
+
|
|
296
|
+
return new Promise((resolve, reject) => {
|
|
297
|
+
|
|
298
|
+
let trans = this.db.transaction([this.collection], 'readwrite');
|
|
299
|
+
let store = trans.objectStore(this.collection);
|
|
300
|
+
let request = store.delete(id);
|
|
301
|
+
|
|
302
|
+
request.onsuccess = () => {
|
|
303
|
+
this.deleting = false
|
|
304
|
+
resolve(request.result);
|
|
305
|
+
};
|
|
306
|
+
|
|
307
|
+
request.onerror = (e) => {
|
|
308
|
+
this.deleting = false
|
|
309
|
+
reject(e);
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
}
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
// import collections from '../../../mango/config/.collections.json'
|
|
2
|
+
// import { algoliaAppId, algoliaSearchKey, algoliaIndex, port, domain } from '../../../mango/config/settings'
|
|
3
|
+
import collections from '../../../config/config/.collections.json'
|
|
4
|
+
import { algoliaAppId, algoliaSearchKey, algoliaIndex, port, domain } from '../../../config/config/settings'
|
|
5
|
+
import axios from "axios";
|
|
6
|
+
import { ref } from 'vue'
|
|
7
|
+
import algoliasearch from 'algoliasearch/lite'
|
|
8
|
+
|
|
9
|
+
let endpoints = {
|
|
10
|
+
authors: ['get'],
|
|
11
|
+
// scripture: { validate: ['post'] }
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// console.log('collections', collections)
|
|
15
|
+
|
|
16
|
+
const client = algoliasearch(algoliaAppId, algoliaSearchKey);
|
|
17
|
+
const algolia = client.initIndex(algoliaIndex);
|
|
18
|
+
|
|
19
|
+
let api = `https://${domain}`
|
|
20
|
+
let ws = `wss://${domain}/graphql`
|
|
21
|
+
|
|
22
|
+
if (process.env.NODE_ENV != 'production') {
|
|
23
|
+
api = `http://localhost:${port}`
|
|
24
|
+
ws = `ws://localhost:${port}/graphql`
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const Mango = collections.reduce((a, c) => {
|
|
28
|
+
|
|
29
|
+
let runQuery = ({ limit, page, search, fields, id, sort, depthLimit } = {}) => {
|
|
30
|
+
|
|
31
|
+
let fullQuery
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
const params = { limit, page, search, fields, sort, depthLimit }
|
|
35
|
+
|
|
36
|
+
if (params.search != undefined) params.search = JSON.stringify(params.search)
|
|
37
|
+
if (params.fields != undefined) params.fields = JSON.stringify(params.fields)
|
|
38
|
+
if (params.sort != undefined) params.sort = JSON.stringify(params.sort)
|
|
39
|
+
|
|
40
|
+
const query = Object.keys(params)
|
|
41
|
+
.filter(key => params[key] != undefined)
|
|
42
|
+
?.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|
43
|
+
?.join('&') || ''
|
|
44
|
+
// console.log(query)
|
|
45
|
+
|
|
46
|
+
fullQuery = `${api}/${c.name}/${id || ''}?${query}`
|
|
47
|
+
|
|
48
|
+
let Authorization = window.localStorage.getItem('token')
|
|
49
|
+
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
axios.get(fullQuery, { headers: { Authorization } })
|
|
52
|
+
.then(response => resolve(response?.data?.response))
|
|
53
|
+
.catch(e => reject(e))
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let runGraphql = (query) => {
|
|
59
|
+
|
|
60
|
+
let Authorization = window.localStorage.getItem('token')
|
|
61
|
+
query = { query }
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
axios.post(`${api}/graphql`, query, { headers: { Authorization } })
|
|
64
|
+
.then(response => resolve(response?.data?.data))
|
|
65
|
+
.catch(e => reject(e))
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let runAlgolia = (search, query, algoliaFilters) => {
|
|
71
|
+
|
|
72
|
+
search = search || ''
|
|
73
|
+
|
|
74
|
+
let filters = `collection:${c.name}`
|
|
75
|
+
if (algoliaFilters) filters += ` AND ${algoliaFilters}`
|
|
76
|
+
|
|
77
|
+
let algoliaQuery = {
|
|
78
|
+
page: query?.page || 0,
|
|
79
|
+
filters,
|
|
80
|
+
hitsPerPage: query?.limit || 10
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (query?.fields) algoliaQuery.attributesToRetrieve = query.fields
|
|
84
|
+
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
algolia.search(search, algoliaQuery)
|
|
87
|
+
.then(({ hits, nbHits }) => {
|
|
88
|
+
hits.forEach(h => h.id = h.objectID)
|
|
89
|
+
resolve({ hits, nbHits })
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
let save = (data) => {
|
|
96
|
+
let { id } = data
|
|
97
|
+
let method = id ? 'put' : 'post'
|
|
98
|
+
|
|
99
|
+
// // Remove _id and computed fields
|
|
100
|
+
delete data.collection
|
|
101
|
+
delete data._id
|
|
102
|
+
delete data.id
|
|
103
|
+
|
|
104
|
+
for (let field of c.fields) {
|
|
105
|
+
if (field.computed) delete data[field.name]
|
|
106
|
+
if (field.relationship) data[field.name] = Array.isArray(data[field.name]) ? data[field.name].map(r => r.id) : data[field.name]?.id ? data[field.name].id : data[field.name]
|
|
107
|
+
}
|
|
108
|
+
for (let name in data) {
|
|
109
|
+
if (name.includes('__')) delete data[name]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
let payload = { ...data }
|
|
113
|
+
|
|
114
|
+
let Authorization = window.localStorage.getItem('token')
|
|
115
|
+
|
|
116
|
+
return new Promise((resolve, reject) => {
|
|
117
|
+
axios[method](`${api}/${c.name}/${id || ''}`, payload, { headers: { Authorization } })
|
|
118
|
+
.then(response => resolve(response?.data?.response))
|
|
119
|
+
.catch(e => reject(e))
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
let deleteEntry = (data) => {
|
|
124
|
+
let id = data.id || data
|
|
125
|
+
|
|
126
|
+
let Authorization = window.localStorage.getItem('token')
|
|
127
|
+
|
|
128
|
+
return new Promise((resolve, reject) => {
|
|
129
|
+
axios.delete(`${api}/${c.name}/${id || ''}`, { headers: { Authorization } })
|
|
130
|
+
.then(response => resolve(response?.data))
|
|
131
|
+
.catch(e => reject(e))
|
|
132
|
+
})
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
a[c.name] = runQuery
|
|
136
|
+
a[c.name]['save'] = save
|
|
137
|
+
a[c.name]['delete'] = deleteEntry
|
|
138
|
+
a[c.singular] = (id, query) => runQuery({ id, ...query })
|
|
139
|
+
|
|
140
|
+
a[c.name]['search'] = runAlgolia
|
|
141
|
+
a[c.name]['search']['init'] = (search, query, algoliaFilters) => {
|
|
142
|
+
let loading = ref(true)
|
|
143
|
+
let data = ref(null)
|
|
144
|
+
let error = ref(null)
|
|
145
|
+
let totalResults = ref(null)
|
|
146
|
+
|
|
147
|
+
let response = runAlgolia(search, query, algoliaFilters)
|
|
148
|
+
.then(response => {
|
|
149
|
+
data.value = response.hits
|
|
150
|
+
totalResults.value = response.nbHits
|
|
151
|
+
loading.value = false
|
|
152
|
+
})
|
|
153
|
+
.catch(e => {
|
|
154
|
+
loading.value = false
|
|
155
|
+
error.value = e
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
return { data, loading, error }
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
a[c.name]['init'] = ({ limit, page, search, fields, id, sort } = {}) => {
|
|
162
|
+
|
|
163
|
+
let loading = ref(true)
|
|
164
|
+
let data = ref(null)
|
|
165
|
+
let error = ref(null)
|
|
166
|
+
|
|
167
|
+
let response = runQuery({ limit, page, search, fields, id, sort })
|
|
168
|
+
.then(response => {
|
|
169
|
+
data.value = response
|
|
170
|
+
loading.value = false
|
|
171
|
+
})
|
|
172
|
+
.catch(e => {
|
|
173
|
+
loading.value = false
|
|
174
|
+
error.value = e
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
return { data, loading, error }
|
|
178
|
+
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
a[c.singular]['init'] = (id) => a[c.name]['init']({ id })
|
|
182
|
+
|
|
183
|
+
a.relationRequest = ({ limit, page, search, fields, id, sort, depthLimit, path } = {}) => {
|
|
184
|
+
|
|
185
|
+
let fullQuery
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
const params = { limit, page, search, fields, sort, depthLimit }
|
|
189
|
+
|
|
190
|
+
if (params.search != undefined) params.search = JSON.stringify(params.search)
|
|
191
|
+
if (params.fields != undefined) params.fields = JSON.stringify(params.fields)
|
|
192
|
+
if (params.sort != undefined) params.sort = JSON.stringify(params.sort)
|
|
193
|
+
|
|
194
|
+
const query = Object.keys(params)
|
|
195
|
+
.filter(key => params[key] != undefined)
|
|
196
|
+
?.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|
197
|
+
?.join('&') || ''
|
|
198
|
+
// console.log(query)
|
|
199
|
+
|
|
200
|
+
fullQuery = `${api}/${path}?${query}`
|
|
201
|
+
|
|
202
|
+
let Authorization = window.localStorage.getItem('token')
|
|
203
|
+
|
|
204
|
+
return new Promise((resolve, reject) => {
|
|
205
|
+
axios.get(fullQuery, { headers: { Authorization } })
|
|
206
|
+
.then(response => resolve(response?.data?.response))
|
|
207
|
+
.catch(e => reject(e))
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
}
|
|
211
|
+
a.relationRequest.init = (query) => {
|
|
212
|
+
|
|
213
|
+
let loading = ref(true)
|
|
214
|
+
let data = ref(null)
|
|
215
|
+
let error = ref(null)
|
|
216
|
+
|
|
217
|
+
let response = a.relationRequest(query)
|
|
218
|
+
.then(response => {
|
|
219
|
+
data.value = response
|
|
220
|
+
loading.value = false
|
|
221
|
+
})
|
|
222
|
+
.catch(e => {
|
|
223
|
+
loading.value = false
|
|
224
|
+
error.value = e
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
return { data, loading, error }
|
|
228
|
+
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
a.graphql = runGraphql
|
|
233
|
+
a.graphql.init = (query) => {
|
|
234
|
+
|
|
235
|
+
let loading = ref(true)
|
|
236
|
+
let data = ref(null)
|
|
237
|
+
let error = ref(null)
|
|
238
|
+
|
|
239
|
+
let response = runGraphql(query)
|
|
240
|
+
.then(response => {
|
|
241
|
+
data.value = response
|
|
242
|
+
loading.value = false
|
|
243
|
+
})
|
|
244
|
+
.catch(e => {
|
|
245
|
+
loading.value = false
|
|
246
|
+
error.value = e
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
return { data, loading, error }
|
|
250
|
+
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return a
|
|
254
|
+
|
|
255
|
+
}, {})
|
|
256
|
+
|
|
257
|
+
Mango.search = (search, query, algoliaFilters) => {
|
|
258
|
+
|
|
259
|
+
search = search || ''
|
|
260
|
+
|
|
261
|
+
let filters = ``
|
|
262
|
+
if (algoliaFilters) filters += `${algoliaFilters}`
|
|
263
|
+
|
|
264
|
+
let algoliaQuery = {
|
|
265
|
+
page: query?.page || 0,
|
|
266
|
+
filters,
|
|
267
|
+
hitsPerPage: query?.limit || 10
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
if (query?.fields) algoliaQuery.attributesToRetrieve = query.fields
|
|
271
|
+
|
|
272
|
+
return new Promise((resolve, reject) => {
|
|
273
|
+
algolia.search(search, algoliaQuery)
|
|
274
|
+
.then(({ hits }) => {
|
|
275
|
+
hits.forEach(h => h.id = h.objectID)
|
|
276
|
+
resolve(hits)
|
|
277
|
+
})
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
Mango.login = ({ email, password }) => {
|
|
283
|
+
return new Promise((resolve, reject) => {
|
|
284
|
+
axios.post(`${api}/endpoints/account/login`, { email, password })
|
|
285
|
+
.then(response => {
|
|
286
|
+
window.localStorage.setItem('token', response.data.token)
|
|
287
|
+
window.localStorage.setItem('user', response.data.memberId)
|
|
288
|
+
window.localStorage.setItem('email', email)
|
|
289
|
+
resolve(response.data)
|
|
290
|
+
})
|
|
291
|
+
.catch(e => reject(e))
|
|
292
|
+
})
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
Mango.endpoints = Object.keys(endpoints).reduce((a, c) => {
|
|
296
|
+
|
|
297
|
+
a[c] = {}
|
|
298
|
+
|
|
299
|
+
for (let method of endpoints[c]) {
|
|
300
|
+
a[c][method] = () => {
|
|
301
|
+
|
|
302
|
+
return new Promise((resolve, reject) => {
|
|
303
|
+
console.log('method', method)
|
|
304
|
+
console.log('`${api}/endpoints/${c}`', `${api}/endpoints/${c}`)
|
|
305
|
+
axios[method](`${api}/endpoints/${c}`)
|
|
306
|
+
.then(response => resolve(response?.data))
|
|
307
|
+
.catch(e => reject(e))
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
for (let method of endpoints[c]) {
|
|
314
|
+
a[c][method]['init'] = () => {
|
|
315
|
+
|
|
316
|
+
let loading = ref(true)
|
|
317
|
+
let data = ref(null)
|
|
318
|
+
let error = ref(null)
|
|
319
|
+
|
|
320
|
+
let response = a[c][method]().then(r => {
|
|
321
|
+
data.value = r
|
|
322
|
+
loading.value = false
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
return { data, loading, error }
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return a
|
|
330
|
+
|
|
331
|
+
}, {})
|
|
332
|
+
|
|
333
|
+
Mango.collections = collections
|
|
334
|
+
Mango.ws = ws
|
|
335
|
+
|
|
336
|
+
Mango.online = async () => { try { return (await axios.get(`${api}/endpoints/test`))?.data?.includes('ðŸ¥') } catch (e) { return false } }
|
|
337
|
+
|
|
338
|
+
export default Mango
|