mango-cms 0.1.22 → 0.1.24

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/cli.js CHANGED
@@ -168,9 +168,17 @@ program
168
168
  console.log('Error reading settings file:', error.message);
169
169
  }
170
170
 
171
+ // Convert project name to lowercase and remove spaces for domain/DB names
172
+ const projectSlug = answers.projectName.toLowerCase().replace(/[^a-z0-9]/g, '');
173
+
171
174
  settings = {
172
175
  ...settings,
173
- license: answers.license
176
+ license: answers.license,
177
+ siteName: answers.projectName,
178
+ siteDomain: `${projectSlug}.com`,
179
+ domain: `api.${projectSlug}.com`,
180
+ database: `${projectSlug}`,
181
+ s3Bucket: `${projectSlug}`
174
182
  };
175
183
  fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
176
184
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
@@ -7,12 +7,29 @@
7
7
  <div>{{ online ? 'Online' : 'Offline' }}</div>
8
8
  </div>
9
9
 
10
+ <!-- Dark Mode Toggle -->
11
+ <div class="absolute top-4 right-4 z-20">
12
+ <button @click="darkMode.enabled = !darkMode.enabled"
13
+ class="p-2 rounded-full bg-white dark:bg-indigo-950/80 shadow-md hover:shadow-lg transition-all">
14
+ <svg v-if="darkMode.enabled" xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-yellow-400"
15
+ fill="none" viewBox="0 0 24 24" stroke="currentColor">
16
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
17
+ d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
18
+ </svg>
19
+ <svg v-else xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-slate-700" fill="none"
20
+ viewBox="0 0 24 24" stroke="currentColor">
21
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
22
+ d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" />
23
+ </svg>
24
+ </button>
25
+ </div>
26
+
10
27
  <div class="pt-16 lg:pt-32 flex items-center justify-center w-full">
11
28
 
12
29
  <div class="w-full max-2xl py-16 md:py-32 text-center flex flex-col items-center px-8 md:px-16">
13
30
  <div class="text-9xl pb-8">🥭</div>
14
31
  <h1 class="font-bold text-5xl pb-4 bg-clip-text bg-gradient-to-r from-orange-500 to-green-500 text-transparent">Welcome to Mango</h1>
15
- <h1 class="font-bold text-lg bg-clip-text bg-gradient-to-r from-orange-500 to-green-500 text-transparent italic opacity-50">Here to make your life stinking easy.</h1>
32
+ <h1 class="font-bold text-lg bg-clip-text bg-gradient-to-r from-orange-500 to-green-500 text-transparent italic opacity-50">Here to make your life easier.</h1>
16
33
  </div>
17
34
 
18
35
  </div>
@@ -22,7 +39,20 @@
22
39
  <div v-else class="space-y-8">
23
40
  <div class="text-lg">Looks like the local Mango server isn't up and running yet. Please start it by running:</div>
24
41
  <div class="w-full">
25
- <code class="bg-gray-200 dark:bg-black p-3 border border-gray-700 rounded-lg w-full">cd mango; yarn; yarn watch;</code>
42
+ <div class="flex items-center space-x-2 relative">
43
+ <code class="bg-gray-200 dark:bg-black p-3 border border-gray-700 rounded-lg flex-grow dark:selection:bg-sky-700">cd mango; yarn; yarn watch;</code>
44
+ <button @click="copyToClipboard('cd mango; yarn; yarn watch;')" class="p-2 rounded-lg bg-gray-200 dark:bg-black border border-gray-700 hover:bg-gray-300 dark:hover:bg-gray-800 transition-colors relative group">
45
+ <svg v-if="!copied" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
46
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 5H6a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2v-1M8 5a2 2 0 002 2h2a2 2 0 002-2M8 5a2 2 0 012-2h2a2 2 0 012 2m0 0h2a2 2 0 012 2v3m2 4H10m0 0l3-3m-3 3l3 3" />
47
+ </svg>
48
+ <svg v-else xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
49
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
50
+ </svg>
51
+ <div class="absolute -top-8 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-2 py-1 rounded text-sm whitespace-nowrap opacity-0 transition-opacity duration-300" :class="{ 'opacity-100': copied }">
52
+ Copied!
53
+ </div>
54
+ </button>
55
+ </div>
26
56
  </div>
27
57
  </div>
28
58
  </div>
@@ -33,7 +63,7 @@
33
63
  <div class="text mb-4">Great! Now you're logged in as:</div>
34
64
  <div class="text-2xl mb-8">{{ store.user.title }}</div>
35
65
  <div class="rounded-lg bg-gray-100 dark:bg-gray-800 p-4 ">
36
- <div class="tracking-widest opacity-75 font-mono mt-2 truncate" v-html="JSON.stringify(store.user, undefined, 4).replaceAll('\n', '<br>').replaceAll(' ', '&nbsp;')" />
66
+ <pre class="tracking-widest opacity-75 font-mono mt-2 truncate text-xs" v-html="JSON.stringify(store.user, undefined, 4).replaceAll('\n', '<br>').replaceAll(' ', '&nbsp;')" />
37
67
  </div>
38
68
  </div>
39
69
 
@@ -54,11 +84,25 @@ import Login from '../layout/login.vue'
54
84
 
55
85
  export default {
56
86
  components: { Login },
57
- inject: ['store'],
87
+ inject: ['store','darkMode'],
88
+ methods: {
89
+ async copyToClipboard(text) {
90
+ try {
91
+ await navigator.clipboard.writeText(text);
92
+ this.copied = true;
93
+ setTimeout(() => {
94
+ this.copied = false;
95
+ }, 2000);
96
+ } catch (err) {
97
+ console.error('Failed to copy text:', err);
98
+ }
99
+ },
100
+ },
58
101
  data() {
59
102
  return {
60
103
  online: false,
61
104
  checker: null,
105
+ copied: false,
62
106
  }
63
107
  },
64
108
  async created() {
@@ -7,7 +7,6 @@
7
7
  <script setup>
8
8
  import Mango from './mango'
9
9
  import { siteName } from '@config/config/settings.json'
10
- import rws from './reconnecting-websocket'
11
10
  import { ref, watch, computed, nextTick, onUnmounted } from 'vue'
12
11
  import { useRoute } from 'vue-router'
13
12
 
@@ -245,105 +244,6 @@ async function init() {
245
244
 
246
245
  }
247
246
 
248
- const GQL = {
249
- CONNECTION_INIT: 'connection_init',
250
- CONNECTION_ACK: 'connection_ack',
251
- CONNECTION_ERROR: 'connection_error',
252
- CONNECTION_KEEP_ALIVE: 'ka',
253
- START: 'start',
254
- STOP: 'stop',
255
- CONNECTION_TERMINATE: 'connection_terminate',
256
- DATA: 'data',
257
- ERROR: 'error',
258
- COMPLETE: 'complete'
259
- }
260
- function subscribe(collection, id) {
261
-
262
- webSocket = new rws(Mango.ws, 'graphql-ws')
263
-
264
- webSocket.onopen = event => {
265
-
266
- webSocket.send(JSON.stringify({
267
- type: GQL.CONNECTION_INIT,
268
- payload: {}
269
- }))
270
-
271
- webSocket.send(JSON.stringify({
272
- type: GQL.START,
273
- id: Date.now(),
274
- payload: {
275
- query: `
276
- subscription {
277
- ${collection}(id: "${id}") {
278
- id
279
- settings {
280
- clueTimeLimit
281
- guessTimeLimit
282
- }
283
- guesses {
284
- word
285
- playerId
286
- time
287
- }
288
- clue {
289
- text
290
- number
291
- time
292
- team
293
- words
294
- guesses
295
- }
296
- words {
297
- value
298
- color
299
- guessed
300
- }
301
- }
302
- }`,
303
- variables: {},
304
- operationName: null
305
- }
306
- }))
307
- }
308
-
309
- webSocket.onmessage = event => {
310
- const response = JSON.parse(event.data)
311
- switch (response.type) {
312
- case GQL.CONNECTION_ACK: {
313
- console.log('success')
314
- break
315
- }
316
- case GQL.CONNECTION_ERROR: {
317
- console.error(response.payload)
318
- break
319
- }
320
- case GQL.CONNECTION_KEEP_ALIVE: {
321
- break
322
- }
323
- case GQL.DATA: {
324
- console.log(response.id, response.payload.errors, response.payload.data)
325
- if (response.payload.data) {
326
- data.value = response.payload.data[collection]
327
- emit('update:data', data.value)
328
- }
329
- break
330
- }
331
- case GQL.COMPLETE: {
332
- console.log('completed', response.id)
333
- break
334
- }
335
- }
336
- }
337
- }
338
-
339
- onUnmounted(() => {
340
- if (webSocket?.send) {
341
- webSocket.send(JSON.stringify({
342
- type: GQL.CONNECTION_TERMINATE
343
- }))
344
- }
345
- })
346
-
347
247
  // init()
348
248
  // await init()
349
249
 
@@ -0,0 +1,36 @@
1
+ import Swal from "sweetalert2"
2
+ import axios from "axios"
3
+
4
+ function validateEmail(email) {
5
+ var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
6
+ return re.test(String(email.trim()).toLowerCase());
7
+ }
8
+
9
+ async function subscribeToMailChimp({ email, list, source, alert }) {
10
+
11
+ let lists = {
12
+ master: '816047355d',
13
+ devotional: '5fbac827f8'
14
+ }
15
+
16
+ let listId = lists[list]
17
+
18
+ if (!listId) return console.error(`"${list}" is not a valid email list`)
19
+ if (!source) return console.error(`You must provide a subscription source`)
20
+
21
+ if (!validateEmail(email)) {
22
+ new Swal('Invalid Email', `"${email}" is not a valid email address`, 'warning')
23
+ return console.error(`"${email}" is not a valid email address`)
24
+ }
25
+
26
+ try {
27
+ await axios.post(`https://churchandfamilylife.us2.list-manage.com/subscribe/post?u=12eae89c5f8969e490844c75a&id=${listId}`, { EMAIL: email, MMERGE3: source })
28
+ .then(response => { if (alert) new Swal('Subscribed!', 'Thank you for subscribing.', 'success') })
29
+ // MC apparently doesn't give a proper error message we can read at the time of writing this...
30
+ .catch(response => { if (alert) new Swal('Subscribed!', 'Thank you for subscribing.', 'success') })
31
+ } catch (e) {
32
+ console.log(e)
33
+ }
34
+ }
35
+
36
+ export { subscribeToMailChimp, validateEmail }
@@ -1,7 +1,7 @@
1
1
  // import collections from '../../../mango/config/.collections.json'
2
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'
3
+ import collections from '@collections'
4
+ import { algoliaAppId, algoliaSearchKey, algoliaIndex, port, domain } from '@settings'
5
5
  import axios from "axios";
6
6
  import { ref } from 'vue'
7
7
  import algoliasearch from 'algoliasearch/lite'
@@ -2,8 +2,7 @@ import axios from 'axios'
2
2
  import { computed, createApp, defineAsyncComponent, reactive, ref } from 'vue'
3
3
  import { createRouter, createWebHistory } from 'vue-router'
4
4
  import { MotionPlugin } from '@vueuse/motion'
5
- // import { port, domain } from '../../mango/config/settings'
6
- import { port, domain } from '../../config/config/settings'
5
+ import { port, domain } from '@settings'
7
6
  import VueClipboard from 'vue3-clipboard'
8
7
  import Vue3TouchEvents from "vue3-touch-events";
9
8
  import App from './App.vue'
@@ -62,12 +61,9 @@ Global Properties
62
61
 
63
62
  */
64
63
 
65
- import breakpoints from './helpers/breakpoints'
66
64
  import darkMode from './helpers/darkMode'
67
- import formatPhone from './helpers/formatPhone'
68
65
  import { initUser } from './helpers/user';
69
66
 
70
- app.provide('breakpoints', breakpoints().breakpoints)
71
67
  app.provide('darkMode', darkMode().darkMode)
72
68
 
73
69
  const user = initUser()
@@ -90,7 +86,6 @@ app.provide('store', store)
90
86
  app.provide('axios', axios)
91
87
 
92
88
  app.provide('mode', import.meta.env.MODE)
93
- app.provide('formatPhone', formatPhone)
94
89
 
95
90
 
96
91
  /*
@@ -102,12 +97,10 @@ Global Components
102
97
  import Mango from './helpers/Mango.vue'
103
98
  import Spinner from './components/layout/spinner.vue'
104
99
  import Modal from './components/layout/modal.vue'
105
- import Button from './components/partials/button.vue'
106
100
 
107
101
  app.component('Mango', Mango)
108
102
  app.component('Spinner', Spinner)
109
103
  app.component('Modal', Modal)
110
- app.component('btn', Button)
111
104
  // app.component('resource', defineAsyncComponent(Layouter.vue')))
112
105
 
113
106
  /*
@@ -27,6 +27,8 @@ export default defineConfig({
27
27
  resolve: {
28
28
  alias: {
29
29
  '@config': configPath,
30
+ '@settings': path.resolve(configPath, 'config/settings.json'),
31
+ '@collections': path.resolve(configPath, 'config/.collections.json'),
30
32
  '@plugins': path.resolve(configPath, 'plugins'),
31
33
  'vue': path.resolve(__dirname, 'node_modules/vue'),
32
34
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mango-cms",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "main": "./index.js",
5
5
  "exports": {
6
6
  ".": "./index.js"