@bettertogether/community-engine-vue 0.1.7 → 0.2.2

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.
Files changed (230) hide show
  1. package/README.md +140 -1
  2. package/dist/assets/BBadge.vue_vue_type_script_setup_true_lang-IIZ8QpjG-Z9WDKHqT.js +1 -0
  3. package/dist/assets/BCardText.vue_vue_type_script_setup_true_lang-Be6CD36N-B5JCTdmm.js +3 -0
  4. package/dist/assets/BFormSelect.vue_vue_type_script_setup_true_lang-BigptVap-B_HbOOZR.js +1 -0
  5. package/dist/assets/BRow.vue_vue_type_script_setup_true_lang-69TY75-8-DJdEdyx7.js +1 -0
  6. package/dist/assets/Communities-Cx4tT-bx.js +1 -0
  7. package/dist/assets/Communities-n33ssuUH.css +1 -0
  8. package/dist/assets/CommunityConversation-bBkYBs2k.css +1 -0
  9. package/dist/assets/CommunityConversation-jHAnv_Ps.js +1 -0
  10. package/dist/assets/CommunityConversations-rEDGS7To.js +1 -0
  11. package/dist/assets/CommunityEvent-CUdT0aT4.js +1 -0
  12. package/dist/assets/CommunityEvents-rsOgcxQr.js +1 -0
  13. package/dist/assets/CommunityHome-ChuTE2Nz.js +1 -0
  14. package/dist/assets/CommunityJoaTu-CpLIY_83.js +1 -0
  15. package/dist/assets/CommunityMembers-C3UtzQGp.css +1 -0
  16. package/dist/assets/CommunityMembers-DKf74ltl.js +1 -0
  17. package/dist/assets/CommunityPage-C5x23iQl.css +1 -0
  18. package/dist/assets/CommunityPage-CRYg9-rW.js +1 -0
  19. package/dist/assets/CommunityPages-IsLTNFC3.js +1 -0
  20. package/dist/assets/CommunityPost-BOnqqxVs.js +1 -0
  21. package/dist/assets/CommunityPost-BRYtkDSY.css +1 -0
  22. package/dist/assets/CommunityPosts-DY1olmcU.js +1 -0
  23. package/dist/assets/Error404-D10VQARe.js +1 -0
  24. package/dist/assets/EventCard-vfutXTdg.js +1 -0
  25. package/dist/assets/EventList-ChtehYcJ.js +1 -0
  26. package/dist/assets/ExtensionSlot-DJKbrq4c.js +1 -0
  27. package/dist/assets/PostList-BuHrBBqX.css +1 -0
  28. package/dist/assets/PostList-DYFgxlE8.js +1 -0
  29. package/dist/assets/SyncBadge-B1JBsdUk.js +1 -0
  30. package/dist/assets/SyncBadge-FNO-QLuu.css +1 -0
  31. package/dist/assets/UserPasswordNew-D_Djldm9.css +1 -0
  32. package/dist/assets/UserPasswordNew-al9bNBTZ.js +1 -0
  33. package/dist/assets/UserPasswordReset-42zs98RW.js +1 -0
  34. package/dist/assets/UserPasswordReset-D_6OQDZY.css +1 -0
  35. package/dist/assets/UserResendConfirmation-CGavYB81.js +1 -0
  36. package/dist/assets/UserResendConfirmation-DNTHcaar.css +1 -0
  37. package/dist/assets/UserSignIn-BIRb0HkV.js +1 -0
  38. package/dist/assets/UserSignIn-C-Pol8OD.css +1 -0
  39. package/dist/assets/UserSignUp-ChkKQAd2.css +1 -0
  40. package/dist/assets/UserSignUp-Df6o3vlO.js +1 -0
  41. package/dist/assets/better-together-logo-61cxo5d5.png +0 -0
  42. package/dist/assets/index-BFt-JKVh.css +5 -0
  43. package/dist/assets/index-COo3Jb7v.js +1088 -0
  44. package/dist/assets/nodefs-Bfyh92qg.js +1 -0
  45. package/dist/assets/opfs-ahp-BLzlXf6u.js +3 -0
  46. package/dist/assets/pglite-BdRI_ZYT.wasm +0 -0
  47. package/dist/assets/pglite-COscPi1Y.data +0 -0
  48. package/dist/assets/usePages-DDjDQRCy.js +1 -0
  49. package/dist/assets/usePosts-Bf2Ccwr4.js +1 -0
  50. package/{public → dist}/index.html +9 -19
  51. package/package.json +57 -45
  52. package/src/BtApp.vue +34 -43
  53. package/src/components/BtBrandingLogo.vue +10 -18
  54. package/src/components/BtHeader.vue +31 -89
  55. package/src/components/BtMainContent.vue +12 -43
  56. package/src/components/BtNavBar.vue +25 -38
  57. package/src/components/BtNavItem.vue +25 -58
  58. package/src/components/BtNavUser.vue +65 -86
  59. package/src/components/BtProfileForm.vue +48 -39
  60. package/src/components/BtUserNewPasswordForm.vue +52 -74
  61. package/src/components/BtUserResendConfirmationForm.vue +45 -83
  62. package/src/components/BtUserResetPasswordForm.vue +45 -77
  63. package/src/components/BtUserSignInForm.vue +59 -75
  64. package/src/components/BtUserSignUpForm.vue +90 -103
  65. package/src/components/CommunityForm.vue +47 -39
  66. package/src/components/community/CommunityCard.vue +113 -0
  67. package/src/components/community/CommunityHeader.vue +91 -0
  68. package/src/components/community/CommunityList.vue +59 -0
  69. package/src/components/community/MemberRoleRow.vue +107 -0
  70. package/src/components/conversation/ConversationCard.vue +49 -0
  71. package/src/components/conversation/ConversationDetail.vue +53 -0
  72. package/src/components/conversation/ConversationList.vue +51 -0
  73. package/src/components/conversation/MessageForm.vue +45 -0
  74. package/src/components/conversation/MessageItem.vue +43 -0
  75. package/src/components/conversation/MessageList.vue +39 -0
  76. package/src/components/event/EventCard.vue +82 -0
  77. package/src/components/event/EventForm.vue +99 -0
  78. package/src/components/event/EventList.vue +47 -0
  79. package/src/components/invitation/InvitationCard.vue +56 -0
  80. package/src/components/invitation/InvitationForm.vue +70 -0
  81. package/src/components/invitation/InvitationList.vue +51 -0
  82. package/src/components/joatu/AgreementCard.vue +57 -0
  83. package/src/components/joatu/AgreementList.vue +51 -0
  84. package/src/components/joatu/OfferCard.vue +65 -0
  85. package/src/components/joatu/OfferForm.vue +82 -0
  86. package/src/components/joatu/OfferList.vue +51 -0
  87. package/src/components/joatu/RequestCard.vue +65 -0
  88. package/src/components/joatu/RequestForm.vue +82 -0
  89. package/src/components/joatu/RequestList.vue +51 -0
  90. package/src/components/page/PageCard.vue +55 -0
  91. package/src/components/page/PageDetail.vue +35 -0
  92. package/src/components/page/PageList.vue +51 -0
  93. package/src/components/person/MemberList.vue +61 -0
  94. package/src/components/person/PersonAvatar.vue +54 -0
  95. package/src/components/person/PersonCard.vue +47 -0
  96. package/src/components/post/PostCard.vue +105 -0
  97. package/src/components/post/PostDetail.vue +98 -0
  98. package/src/components/post/PostForm.vue +84 -0
  99. package/src/components/post/PostList.vue +53 -0
  100. package/src/components/role/BlockButton.vue +44 -0
  101. package/src/components/role/RoleBadge.vue +19 -0
  102. package/src/components/role/RoleGate.vue +62 -0
  103. package/src/components/role/RoleSelector.vue +29 -0
  104. package/src/components/shared/ExtensionSlot.vue +27 -0
  105. package/src/components/sync/OfflineBanner.vue +49 -0
  106. package/src/components/sync/SyncBadge.vue +108 -0
  107. package/src/components/sync/SyncStatusBar.vue +121 -0
  108. package/src/composables/useCommunities.js +19 -0
  109. package/src/composables/useConversations.js +5 -0
  110. package/src/composables/useEvents.js +28 -0
  111. package/src/composables/useInvitations.js +10 -0
  112. package/src/composables/useJoaTuAgreements.js +11 -0
  113. package/src/composables/useJoaTuOffers.js +10 -0
  114. package/src/composables/useJoaTuRequests.js +10 -0
  115. package/src/composables/useMembers.js +30 -0
  116. package/src/composables/useMessages.js +5 -0
  117. package/src/composables/useNotifications.js +5 -0
  118. package/src/composables/usePages.js +6 -0
  119. package/src/composables/usePersonBlocks.js +65 -0
  120. package/src/composables/usePosts.js +27 -0
  121. package/src/composables/useResource.js +137 -0
  122. package/src/composables/useRoles.js +94 -0
  123. package/src/composables/useSyncStatus.js +22 -0
  124. package/src/composables/useToaster.js +20 -0
  125. package/src/context.js +18 -0
  126. package/src/db/client.js +343 -0
  127. package/src/db/migrations/001_initial.sql +131 -0
  128. package/src/db/migrations/003_conversations_invitations_pages_joatu.sql +76 -0
  129. package/src/db/sync.js +276 -0
  130. package/src/endpoints/BtApiAuth.js +1 -1
  131. package/src/endpoints/BtApiV1.js +1 -1
  132. package/src/extension.js +45 -0
  133. package/src/i18n/index.js +103 -0
  134. package/src/i18n/locales/en.json +275 -0
  135. package/src/i18n/locales/es.json +275 -0
  136. package/src/i18n/locales/fr.json +223 -0
  137. package/src/i18n/locales/uk.json +275 -0
  138. package/src/index.js +168 -22
  139. package/src/layouts/CommunityLayout.vue +89 -0
  140. package/src/main.js +16 -12
  141. package/src/mixins/error-handling.js +6 -15
  142. package/src/mixins/toaster.js +15 -10
  143. package/src/pages/Communities.vue +59 -0
  144. package/src/pages/Error404.vue +10 -14
  145. package/src/pages/Home.vue +11 -18
  146. package/src/pages/Me.vue +39 -59
  147. package/src/pages/UserPasswordNew.vue +12 -68
  148. package/src/pages/UserPasswordReset.vue +15 -64
  149. package/src/pages/UserResendConfirmation.vue +39 -113
  150. package/src/pages/UserSignIn.vue +18 -67
  151. package/src/pages/UserSignUp.vue +15 -64
  152. package/src/pages/community/CommunityConversation.vue +31 -0
  153. package/src/pages/community/CommunityConversations.vue +18 -0
  154. package/src/pages/community/CommunityEvent.vue +39 -0
  155. package/src/pages/community/CommunityEvents.vue +58 -0
  156. package/src/pages/community/CommunityHome.vue +49 -0
  157. package/src/pages/community/CommunityJoaTu.vue +115 -0
  158. package/src/pages/community/CommunityMembers.vue +23 -0
  159. package/src/pages/community/CommunityPage.vue +31 -0
  160. package/src/pages/community/CommunityPages.vue +25 -0
  161. package/src/pages/community/CommunityPost.vue +28 -0
  162. package/src/pages/community/CommunityPosts.vue +58 -0
  163. package/src/pages/community/CommunitySettingsPage.vue +117 -0
  164. package/src/pages/community/RoleManagerPage.vue +93 -0
  165. package/src/plugins/bootstrap-vue.js +5 -5
  166. package/src/plugins/font-awesome.js +3 -2
  167. package/src/plugins/index.js +9 -4
  168. package/src/plugins/progress.js +16 -0
  169. package/src/pwa/index.js +156 -0
  170. package/src/pwa/sw-helpers.js +130 -0
  171. package/src/router/communityRoutes.js +78 -0
  172. package/src/router/index.js +30 -144
  173. package/src/slot-registry.js +15 -0
  174. package/src/stores/auth.js +134 -0
  175. package/src/stores/communities.js +59 -0
  176. package/src/stores/index.js +5 -0
  177. package/src/stores/menus.js +14 -0
  178. package/src/stores/people.js +48 -0
  179. package/src/stores/sync.js +93 -0
  180. package/src/stylesheets/sync-indicators.scss +34 -0
  181. package/.env.sample +0 -1
  182. package/.eslintrc.js +0 -51
  183. package/.gitlab-ci.yml +0 -14
  184. package/.travis/.rbenv-gemsets +0 -1
  185. package/.travis/.ruby-version +0 -1
  186. package/.travis.yml +0 -31
  187. package/babel.config.js +0 -5
  188. package/cypress.json +0 -3
  189. package/deploy/build.sh +0 -8
  190. package/eslint.config.js +0 -16
  191. package/postcss.config.js +0 -5
  192. package/src/eslint.config.js +0 -16
  193. package/src/forms/BtProfileFormSchema.js +0 -19
  194. package/src/forms/BtUserConfirmationFormSchema.js +0 -20
  195. package/src/forms/BtUserNewPasswordFormSchema.js +0 -29
  196. package/src/forms/BtUserResetPasswordFormSchema.js +0 -20
  197. package/src/forms/BtUserSignInFormSchema.js +0 -29
  198. package/src/forms/BtUserSignUpFormSchema.js +0 -63
  199. package/src/forms/CommunityFormSchema.js +0 -19
  200. package/src/plugins/vue-form-generator.js +0 -4
  201. package/src/plugins/vue-loading.js +0 -10
  202. package/src/registerServiceWorker.js +0 -32
  203. package/src/store/index.js +0 -32
  204. package/src/store/modules/authentication.js +0 -170
  205. package/src/store/modules/communities.js +0 -98
  206. package/src/store/modules/community-engine.js +0 -14
  207. package/src/store/modules/menus.js +0 -52
  208. package/src/store/modules/people.js +0 -88
  209. package/src/vue.config.js +0 -0
  210. package/tests/e2e/.eslintrc.js +0 -12
  211. package/tests/e2e/plugins/index.js +0 -26
  212. package/tests/e2e/specs/home.js +0 -8
  213. package/tests/e2e/support/commands.js +0 -25
  214. package/tests/e2e/support/index.js +0 -20
  215. package/tests/unit/.eslintrc.js +0 -5
  216. package/tests/unit/example.spec.js +0 -13
  217. package/vue.config.js +0 -11
  218. package/webpack.config.js +0 -28
  219. /package/{public → dist}/_redirects +0 -0
  220. /package/{public → dist}/favicon.ico +0 -0
  221. /package/{public → dist}/img/favicon.ico +0 -0
  222. /package/{public → dist}/img/icons/android-chrome-192x192.png +0 -0
  223. /package/{public → dist}/img/icons/android-chrome-384x384.png +0 -0
  224. /package/{public → dist}/img/icons/apple-touch-icon.png +0 -0
  225. /package/{public → dist}/img/icons/favicon-16x16.png +0 -0
  226. /package/{public → dist}/img/icons/favicon-32x32.png +0 -0
  227. /package/{public → dist}/img/icons/favicon.ico +0 -0
  228. /package/{public → dist}/img/icons/mstile-150x150.png +0 -0
  229. /package/{public → dist}/img/icons/safari-pinned-tab.svg +0 -0
  230. /package/{public → dist}/robots.txt +0 -0
@@ -0,0 +1 @@
1
+ import{ap as o,aq as r,ar as n}from"./index-COo3Jb7v.js";n();var d=class extends o{constructor(s){super(s),this.rootDir=(void 0)(s),(void 0)((void 0)(this.rootDir))||(void 0)(this.rootDir)}async init(s,e){return this.pg=s,{emscriptenOpts:{...e,preRun:[...e.preRun||[],t=>{let i=t.FS.filesystems.NODEFS;t.FS.mkdir(r),t.FS.mount(i,{root:this.rootDir},r)}]}}}async closeFs(){this.pg.Module.FS.quit()}};export{d as NodeFS};
@@ -0,0 +1,3 @@
1
+ import{as as H,at as m,au as o,av as a,aw as A,ar as C,ax as P,ay as v}from"./index-COo3Jb7v.js";C();var B="state.txt",L="data",W={DIR:16384,FILE:32768},T,I,N,_,f,k,y,j,F,O,S,l,R,E,M,g,w,D,$,x,U=class extends H{constructor(t,{initialPoolSize:e=1e3,maintainedPoolSize:s=100,debug:i=!1}={}){super(t,{debug:i}),m(this,l),m(this,T),m(this,I),m(this,N),m(this,_),m(this,f),m(this,k,new Map),m(this,y,new Map),m(this,j,0),m(this,F,new Map),m(this,O,new Map),this.lastCheckpoint=0,this.checkpointInterval=1e3*60,this.poolCounter=0,m(this,S,new Set),this.initialPoolSize=e,this.maintainedPoolSize=s}async init(t,e){return await o(this,l,R).call(this),super.init(t,e)}async syncToFs(t=!1){await this.maybeCheckpointState(),await this.maintainPool(),t||this.flush()}async closeFs(){for(let t of a(this,y).values())t.close();a(this,f).flush(),a(this,f).close(),this.pg.Module.FS.quit()}async maintainPool(t){t=t||this.maintainedPoolSize;let e=t-this.state.pool.length,s=[];for(let i=0;i<e;i++)s.push(new Promise(async h=>{++this.poolCounter;let r=`${(Date.now()-1704063600).toString(16).padStart(8,"0")}-${this.poolCounter.toString(16).padStart(8,"0")}`,c=await a(this,N).getFileHandle(r,{create:!0}),d=await c.createSyncAccessHandle();a(this,k).set(r,c),a(this,y).set(r,d),o(this,l,M).call(this,{opp:"createPoolFile",args:[r]}),this.state.pool.push(r),h()}));for(let i=0;i>e;i--)s.push(new Promise(async h=>{var d;let r=this.state.pool.pop();o(this,l,M).call(this,{opp:"deletePoolFile",args:[r]});let c=a(this,k).get(r);(d=a(this,y).get(r))==null||d.close(),await a(this,N).removeEntry(c.name),a(this,k).delete(r),a(this,y).delete(r),h()}));await Promise.all(s)}_createPoolFileState(t){this.state.pool.push(t)}_deletePoolFileState(t){let e=this.state.pool.indexOf(t);e>-1&&this.state.pool.splice(e,1)}async maybeCheckpointState(){Date.now()-this.lastCheckpoint>this.checkpointInterval&&await this.checkpointState()}async checkpointState(){let t=new TextEncoder().encode(JSON.stringify(this.state));a(this,f).truncate(0),a(this,f).write(t,{at:0}),a(this,f).flush(),this.lastCheckpoint=Date.now()}flush(){for(let t of a(this,S))try{t.flush()}catch{}a(this,S).clear()}chmod(t,e){o(this,l,E).call(this,{opp:"chmod",args:[t,e]},()=>{this._chmodState(t,e)})}_chmodState(t,e){let s=o(this,l,w).call(this,t);s.mode=e}close(t){let e=o(this,l,D).call(this,t);a(this,F).delete(t),a(this,O).delete(e)}fstat(t){let e=o(this,l,D).call(this,t);return this.lstat(e)}lstat(t){let e=o(this,l,w).call(this,t),s=e.type==="file"?a(this,y).get(e.backingFilename).getSize():0,i=4096;return{dev:0,ino:0,mode:e.mode,nlink:1,uid:0,gid:0,rdev:0,size:s,blksize:i,blocks:Math.ceil(s/i),atime:e.lastModified,mtime:e.lastModified,ctime:e.lastModified}}mkdir(t,e){o(this,l,E).call(this,{opp:"mkdir",args:[t,e]},()=>{this._mkdirState(t,e)})}_mkdirState(t,e){let s=o(this,l,g).call(this,t),i=s.pop(),h=[],r=this.state.root;for(let d of s){if(h.push(t),!Object.prototype.hasOwnProperty.call(r.children,d))if(e!=null&&e.recursive)this.mkdir(h.join("/"));else throw new p("ENOENT","No such file or directory");if(r.children[d].type!=="directory")throw new p("ENOTDIR","Not a directory");r=r.children[d]}if(Object.prototype.hasOwnProperty.call(r.children,i))throw new p("EEXIST","File exists");let c={type:"directory",lastModified:Date.now(),mode:(e==null?void 0:e.mode)||W.DIR,children:{}};r.children[i]=c}open(t,e,s){if(o(this,l,w).call(this,t).type!=="file")throw new p("EISDIR","Is a directory");let i=o(this,l,$).call(this);return a(this,F).set(i,t),a(this,O).set(t,i),i}readdir(t){let e=o(this,l,w).call(this,t);if(e.type!=="directory")throw new p("ENOTDIR","Not a directory");return Object.keys(e.children)}read(t,e,s,i,h){let r=o(this,l,D).call(this,t),c=o(this,l,w).call(this,r);if(c.type!=="file")throw new p("EISDIR","Is a directory");return a(this,y).get(c.backingFilename).read(new Uint8Array(e.buffer,s,i),{at:h})}rename(t,e){o(this,l,E).call(this,{opp:"rename",args:[t,e]},()=>{this._renameState(t,e,!0)})}_renameState(t,e,s=!1){let i=o(this,l,g).call(this,t),h=i.pop(),r=o(this,l,w).call(this,i.join("/"));if(!Object.prototype.hasOwnProperty.call(r.children,h))throw new p("ENOENT","No such file or directory");let c=o(this,l,g).call(this,e),d=c.pop(),n=o(this,l,w).call(this,c.join("/"));if(s&&Object.prototype.hasOwnProperty.call(n.children,d)){let u=n.children[d];a(this,y).get(u.backingFilename).truncate(0),this.state.pool.push(u.backingFilename)}n.children[d]=r.children[h],delete r.children[h]}rmdir(t){o(this,l,E).call(this,{opp:"rmdir",args:[t]},()=>{this._rmdirState(t)})}_rmdirState(t){let e=o(this,l,g).call(this,t),s=e.pop(),i=o(this,l,w).call(this,e.join("/"));if(!Object.prototype.hasOwnProperty.call(i.children,s))throw new p("ENOENT","No such file or directory");let h=i.children[s];if(h.type!=="directory")throw new p("ENOTDIR","Not a directory");if(Object.keys(h.children).length>0)throw new p("ENOTEMPTY","Directory not empty");delete i.children[s]}truncate(t,e=0){let s=o(this,l,w).call(this,t);if(s.type!=="file")throw new p("EISDIR","Is a directory");let i=a(this,y).get(s.backingFilename);if(!i)throw new p("ENOENT","No such file or directory");i.truncate(e),a(this,S).add(i)}unlink(t){o(this,l,E).call(this,{opp:"unlink",args:[t]},()=>{this._unlinkState(t,!0)})}_unlinkState(t,e=!1){let s=o(this,l,g).call(this,t),i=s.pop(),h=o(this,l,w).call(this,s.join("/"));if(!Object.prototype.hasOwnProperty.call(h.children,i))throw new p("ENOENT","No such file or directory");let r=h.children[i];if(r.type!=="file")throw new p("EISDIR","Is a directory");if(delete h.children[i],e){let c=a(this,y).get(r.backingFilename);c==null||c.truncate(0),a(this,S).add(c),a(this,O).has(t)&&(a(this,F).delete(a(this,O).get(t)),a(this,O).delete(t))}this.state.pool.push(r.backingFilename)}utimes(t,e,s){o(this,l,E).call(this,{opp:"utimes",args:[t,e,s]},()=>{this._utimesState(t,e,s)})}_utimesState(t,e,s){let i=o(this,l,w).call(this,t);i.lastModified=s}writeFile(t,e,s){let i=o(this,l,g).call(this,t),h=i.pop(),r=o(this,l,w).call(this,i.join("/"));if(Object.prototype.hasOwnProperty.call(r.children,h)){let n=r.children[h];n.lastModified=Date.now(),o(this,l,M).call(this,{opp:"setLastModified",args:[t,n.lastModified]})}else{if(this.state.pool.length===0)throw new Error("No more file handles available in the pool");let n={type:"file",lastModified:Date.now(),mode:(s==null?void 0:s.mode)||W.FILE,backingFilename:this.state.pool.pop()};r.children[h]=n,o(this,l,M).call(this,{opp:"createFileNode",args:[t,n]})}let c=r.children[h],d=a(this,y).get(c.backingFilename);e.length>0&&(d.write(typeof e=="string"?new TextEncoder().encode(e):new Uint8Array(e),{at:0}),t.startsWith("/pg_wal")&&a(this,S).add(d))}_createFileNodeState(t,e){let s=o(this,l,g).call(this,t),i=s.pop(),h=o(this,l,w).call(this,s.join("/"));h.children[i]=e;let r=this.state.pool.indexOf(e.backingFilename);return r>-1&&this.state.pool.splice(r,1),e}_setLastModifiedState(t,e){let s=o(this,l,w).call(this,t);s.lastModified=e}write(t,e,s,i,h){let r=o(this,l,D).call(this,t),c=o(this,l,w).call(this,r);if(c.type!=="file")throw new p("EISDIR","Is a directory");let d=a(this,y).get(c.backingFilename);if(!d)throw new p("EBADF","Bad file descriptor");let n=d.write(new Uint8Array(e,s,i),{at:h});return r.startsWith("/pg_wal")&&a(this,S).add(d),n}};T=new WeakMap,I=new WeakMap,N=new WeakMap,_=new WeakMap,f=new WeakMap,k=new WeakMap,y=new WeakMap,j=new WeakMap,F=new WeakMap,O=new WeakMap,S=new WeakMap,l=new WeakSet,R=async function(){P(this,T,await navigator.storage.getDirectory()),P(this,I,await o(this,l,x).call(this,this.dataDir,{create:!0})),P(this,N,await o(this,l,x).call(this,L,{from:a(this,I),create:!0})),P(this,_,await a(this,I).getFileHandle(B,{create:!0})),P(this,f,await a(this,_).createSyncAccessHandle());let t=new ArrayBuffer(a(this,f).getSize());a(this,f).read(t,{at:0});let e,s=new TextDecoder().decode(t).split(`
2
+ `),i=!1;try{e=JSON.parse(s[0])}catch{e={root:{type:"directory",lastModified:Date.now(),mode:W.DIR,children:{}},pool:[]},a(this,f).truncate(0),a(this,f).write(new TextEncoder().encode(JSON.stringify(e)),{at:0}),i=!0}this.state=e;let h=s.slice(1).filter(Boolean).map(n=>JSON.parse(n));for(let n of h){let u=`_${n.opp}State`;if(typeof this[u]=="function")try{this[u].bind(this)(...n.args)}catch(b){console.warn("Error applying OPFS AHP WAL entry",n,b)}}let r=[],c=async n=>{if(n.type==="file")try{let u=await a(this,N).getFileHandle(n.backingFilename),b=await u.createSyncAccessHandle();a(this,k).set(n.backingFilename,u),a(this,y).set(n.backingFilename,b)}catch(u){console.error("Error opening file handle for node",n,u)}else for(let u of Object.values(n.children))r.push(c(u))};await c(this.state.root);let d=[];for(let n of this.state.pool)d.push(new Promise(async u=>{a(this,k).has(n)&&console.warn("File handle already exists for pool file",n);let b=await a(this,N).getFileHandle(n),z=await b.createSyncAccessHandle();a(this,k).set(n,b),a(this,y).set(n,z),u()}));await Promise.all([...r,...d]),await this.maintainPool(i?this.initialPoolSize:this.maintainedPoolSize)},E=function(t,e){let s=o(this,l,M).call(this,t);try{e()}catch(i){throw a(this,f).truncate(s),i}},M=function(t){let e=JSON.stringify(t),s=new TextEncoder().encode(`
3
+ ${e}`),i=a(this,f).getSize();return a(this,f).write(s,{at:i}),a(this,S).add(a(this,f)),i},g=function(t){return t.split("/").filter(Boolean)},w=function(t,e){let s=o(this,l,g).call(this,t),i=e||this.state.root;for(let h of s){if(i.type!=="directory")throw new p("ENOTDIR","Not a directory");if(!Object.prototype.hasOwnProperty.call(i.children,h))throw new p("ENOENT","No such file or directory");i=i.children[h]}return i},D=function(t){let e=a(this,F).get(t);if(!e)throw new p("EBADF","Bad file descriptor");return e},$=function(){let t=++v(this,j)._;for(;a(this,F).has(t);)v(this,j)._++;return t},x=async function(t,e){let s=o(this,l,g).call(this,t),i=(e==null?void 0:e.from)||a(this,T);for(let h of s)i=await i.getDirectoryHandle(h,{create:e==null?void 0:e.create});return i};var p=class extends Error{constructor(t,e){super(e),typeof t=="number"?this.code=t:typeof t=="string"&&(this.code=A[t])}};export{U as OpfsAhpFS};
Binary file
Binary file
@@ -0,0 +1 @@
1
+ import{M as s}from"./index-COo3Jb7v.js";function u(e=null){return s("pages",e?{community_id:e}:{})}export{u};
@@ -0,0 +1 @@
1
+ import{L as a,M as i}from"./index-COo3Jb7v.js";function n(t=null){const e=i("posts",t?{community_id:t}:{});async function r(o={}){const u=await a();if(t){const{rows:s}=await u.query("SELECT * FROM posts WHERE published_at IS NOT NULL AND community_id = $1 ORDER BY published_at DESC",[t]);return e.items.value=s,s}else{const{rows:s}=await u.query("SELECT * FROM posts WHERE published_at IS NOT NULL ORDER BY published_at DESC",[]);return e.items.value=s,s}}return{...e,listPublished:r}}export{n as u};
@@ -4,26 +4,12 @@
4
4
  <meta charset="utf-8">
5
5
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
6
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
7
- <link rel="apple-touch-icon" sizes="180x180" href="<%= BASE_URL %>/icons/apple-touch-icon.png?v=5A6MOkp5OM">
8
- <link rel="icon" type="image/png" sizes="32x32" href="<%= BASE_URL %>/icons/favicon-32x32.png?v=5A6MOkp5OM">
9
- <link rel="icon" type="image/png" sizes="16x16" href="<%= BASE_URL %>/icons/favicon-16x16.png?v=5A6MOkp5OM">
10
- <link rel="manifest" href="<%= BASE_URL %>/icons/site.webmanifest?v=5A6MOkp5OM">
11
- <link rel="mask-icon" href="<%= BASE_URL %>/icons/safari-pinned-tab.svg?v=5A6MOkp5OM" color="#42b983">
12
- <link rel="shortcut icon" href="<%= BASE_URL %>/icons/favicon.ico?v=5A6MOkp5OM">
13
- <meta name="msapplication-TileColor" content="#42b983">
7
+ <link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png">
8
+ <link rel="icon" type="image/png" sizes="32x32" href="/icons/favicon-32x32.png">
9
+ <link rel="icon" type="image/png" sizes="16x16" href="/icons/favicon-16x16.png">
10
+ <link rel="manifest" href="/icons/site.webmanifest">
14
11
  <meta name="theme-color" content="#42b983">
15
-
16
12
  <title>Be Better Together</title>
17
- </head>
18
- <body class="bg-dark">
19
- <noscript>
20
- <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
21
- </noscript>
22
-
23
- <!-- built files will be auto injected -->
24
- <div id="app"></div>
25
-
26
- <!-- Global site tag (gtag.js) - Google Analytics -->
27
13
  <!-- Google Tag Manager -->
28
14
  <script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
29
15
  new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
@@ -31,10 +17,14 @@
31
17
  'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
32
18
  })(window,document,'script','dataLayer','GTM-WCDBXXT');</script>
33
19
  <!-- End Google Tag Manager -->
34
-
20
+ <script type="module" crossorigin src="/assets/index-COo3Jb7v.js"></script>
21
+ <link rel="stylesheet" crossorigin href="/assets/index-BFt-JKVh.css">
22
+ </head>
23
+ <body class="bg-dark">
35
24
  <!-- Google Tag Manager (noscript) -->
36
25
  <noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-WCDBXXT"
37
26
  height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
38
27
  <!-- End Google Tag Manager (noscript) -->
28
+ <div id="app"></div>
39
29
  </body>
40
30
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "private": false,
3
- "version": "0.1.7",
3
+ "version": "0.2.2",
4
4
  "name": "@bettertogether/community-engine-vue",
5
5
  "description": "The Better Together Community Engine is a universal community platform",
6
6
  "author": "Better Together Community Co-op",
@@ -14,56 +14,68 @@
14
14
  "homepage": "https://bebettertogether.ca",
15
15
  "license": "LGPL-3.0-or-later",
16
16
  "main": "./src/index.js",
17
+ "module": "./src/index.js",
18
+ "files": [
19
+ "src",
20
+ "dist"
21
+ ],
22
+ "publishConfig": {
23
+ "registry": "https://git.btsdev.ca/api/packages/better-together-org/npm/"
24
+ },
17
25
  "scripts": {
18
- "serve": "vue-cli-service serve",
19
- "build": "vue-cli-service build",
20
- "test:unit": "vue-cli-service test:unit",
21
- "test:e2e": "vue-cli-service test:e2e",
22
- "lint": "vue-cli-service lint"
26
+ "dev": "vite",
27
+ "build": "vite build",
28
+ "preview": "vite preview",
29
+ "test:unit": "vitest run",
30
+ "test:unit:watch": "vitest",
31
+ "test:e2e": "cypress run",
32
+ "lint": "eslint --ext .js,.vue src",
33
+ "i18n:check": "node scripts/i18n-check.mjs",
34
+ "i18n:check:strict": "node scripts/i18n-check.mjs --strict",
35
+ "i18n:check:fr": "node scripts/i18n-check-fr.mjs",
36
+ "i18n:check:es": "node scripts/i18n-check-es.mjs",
37
+ "i18n:check:uk": "node scripts/i18n-check-uk.mjs"
23
38
  },
24
39
  "dependencies": {
25
- "@babel/polyfill": "^7.7.0",
40
+ "@electric-sql/pglite": "^0.3.16",
26
41
  "@fortawesome/fontawesome-svg-core": "^1.2.34",
27
42
  "@fortawesome/free-solid-svg-icons": "^5.15.2",
28
- "@fortawesome/vue-fontawesome": "^2.0.2",
29
- "axios": "^0.21.1",
30
- "bootstrap": "^4.3.1",
31
- "bootstrap-vue": "^2.21.2",
32
- "core-js": "^3.8.1",
33
- "crip-vue-loading": "^1.2.5",
34
- "devour-client": "^2.1.1",
35
- "mutationobserver-shim": "^0.3.3",
36
- "popper.js": "^1.16.0",
37
- "register-service-worker": "^1.7.2",
38
- "secure-ls": "^1.2.6",
39
- "vue": "^2.6.11",
40
- "vue-form-generator": "^2.3.4",
41
- "vue-router": "^3.4.9",
42
- "vuex": "^3.6.0",
43
- "vuex-persistedstate": "^4.0.0-beta.3"
43
+ "@fortawesome/vue-fontawesome": "^3.0.6",
44
+ "axios": "^1.8.4",
45
+ "bootstrap": "^5.3.3",
46
+ "bootstrap-vue-next": "^0.43.9",
47
+ "core-js": "^3.31.1",
48
+ "devour-client": "^3.1.5",
49
+ "nprogress": "^0.2.0",
50
+ "pinia": "^2.3.0",
51
+ "pinia-plugin-persistedstate": "^4.2.0",
52
+ "vue": "^3.5.0",
53
+ "vue-i18n": "^9.14.0",
54
+ "vue-router": "^4.4.0"
44
55
  },
45
56
  "devDependencies": {
46
- "@vue/cli-plugin-babel": "~4.5.9",
47
- "@vue/cli-plugin-e2e-cypress": "~4.5.9",
48
- "@vue/cli-plugin-eslint": "~4.5.9",
49
- "@vue/cli-plugin-pwa": "~4.5.9",
50
- "@vue/cli-plugin-router": "~4.5.9",
51
- "@vue/cli-plugin-unit-mocha": "~4.5.9",
52
- "@vue/cli-plugin-vuex": "~4.5.9",
53
- "@vue/cli-service": "~4.5.9",
54
- "@vue/eslint-config-airbnb": "^5.3.0",
55
- "@vue/test-utils": "1.1.2",
56
- "babel-eslint": "^10.0.3",
57
- "chai": "^4.1.2",
58
- "eslint": "^7.17.0",
59
- "eslint-plugin-import": "^2.20.1",
60
- "eslint-plugin-vue": "^7.4.0",
61
- "html-webpack-plugin": "^4.5.0",
62
- "mini-css-extract-plugin": "^1.3.3",
63
- "portal-vue": "^2.1.6",
64
- "sass": "^1.32.0",
65
- "sass-loader": "^10.1.0",
66
- "vue-cli-plugin-bootstrap-vue": "~0.7.0",
67
- "vue-template-compiler": "^2.6.11"
57
+ "@babel/eslint-parser": "^7.12.1",
58
+ "@intlify/eslint-plugin-vue-i18n": "^3.0.0",
59
+ "@vitejs/plugin-vue": "^5.2.0",
60
+ "@vue/test-utils": "^2.4.6",
61
+ "cypress": "^15.12.0",
62
+ "eslint": "^8.57.0",
63
+ "eslint-plugin-import": "^2.29.0",
64
+ "eslint-plugin-vue": "^9.32.0",
65
+ "jsdom": "^26.0.0",
66
+ "sass": "^1.98.0",
67
+ "vite": "^6.2.0",
68
+ "vitest": "^3.0.0"
69
+ },
70
+ "peerDependencies": {
71
+ "pinia": "^2.0.0",
72
+ "vue": "^3.0.0",
73
+ "vue-router": "^4.0.0"
74
+ },
75
+ "resolutions": {
76
+ "lodash": "^4.17.23",
77
+ "cross-spawn": "^7.0.6",
78
+ "flatted": "^3.2.8",
79
+ "yauzl": "^3.2.1"
68
80
  }
69
81
  }
package/src/BtApp.vue CHANGED
@@ -1,27 +1,38 @@
1
1
  <template>
2
2
  <div id="app">
3
- <BtNav />
3
+ <BToastOrchestrator />
4
+ <SyncStatusBar />
5
+ <BtHeader />
6
+ <OfflineBanner />
4
7
  <BtMainContent />
5
8
  </div>
6
9
  </template>
7
10
 
8
- <script>
9
- import BtNav from './components/BtNav.vue'
10
- import BtMainContent from './components/MainContent.vue'
11
+ <script setup>
12
+ import { onMounted } from 'vue'
13
+ import { BToastOrchestrator } from 'bootstrap-vue-next'
14
+ import { useMenuStore } from './stores/menus'
15
+ import { useSyncStore } from './stores/sync'
16
+ import BtHeader from './components/BtHeader.vue'
17
+ import BtMainContent from './components/BtMainContent.vue'
18
+ import SyncStatusBar from './components/sync/SyncStatusBar.vue'
19
+ import OfflineBanner from './components/sync/OfflineBanner.vue'
11
20
 
12
- export default {
13
- name: 'BtApp',
14
- components: {
15
- BtNav,
16
- BtMainContent,
17
- },
18
- }
21
+ const menuStore = useMenuStore()
22
+ const syncStore = useSyncStore()
23
+
24
+ onMounted(() => {
25
+ menuStore.setHeaderMenuItems([
26
+ { id: 0, external: false, label: 'About', path: '/about', title: 'About the Better Together Community', sortOrder: 0 },
27
+ ])
28
+ syncStore.initNetworkListeners()
29
+ })
19
30
  </script>
20
31
 
21
32
  <style lang="scss">
22
- @import 'bootstrap/scss/_functions.scss';
23
- @import 'bootstrap/scss/_variables.scss';
24
- @import 'bootstrap/scss/_mixins.scss';
33
+ @import 'bootstrap/scss/functions';
34
+ @import 'bootstrap/scss/variables';
35
+ @import 'bootstrap/scss/mixins';
25
36
  @import 'stylesheets/theme.scss';
26
37
 
27
38
  #app {
@@ -32,17 +43,13 @@ export default {
32
43
 
33
44
  a {
34
45
  color: $accent-color;
35
-
36
- &:hover {
37
- color: $accent-color;
38
- }
46
+ &:hover { color: $accent-color; }
39
47
  }
40
48
 
41
49
  .btn-primary {
42
50
  color: $default-text-color-bg-dark;
43
51
  background-color: $accent-color;
44
52
  border-color: $accent-color;
45
-
46
53
  &:hover, &:focus, &:active {
47
54
  color: $default-text-color-bg-dark;
48
55
  background-color: #399f71;
@@ -50,45 +57,29 @@ export default {
50
57
  }
51
58
  }
52
59
 
53
- header,
54
- footer {
55
- // width: 100vw;
56
- // height: 15vh;
60
+ header, footer {
57
61
  padding: 0;
58
-
59
62
  .navbar-nav {
60
63
  a {
61
64
  font-weight: bold;
62
65
  color: $default-text-color-bg-dark;
63
-
64
- &.router-link-exact-active,
65
- &:hover {
66
- color: $accent-color;
67
- }
66
+ &.router-link-exact-active, &:hover { color: $accent-color; }
67
+ }
68
+ ul.dropdown-menu a {
69
+ color: $default-text-color;
70
+ &:hover { color: $accent-color; }
68
71
  }
69
-
70
72
  @include media-breakpoint-up(md) {
71
73
  li.nav-item {
72
74
  margin-right: 1vw;
73
-
74
- &:last-child {
75
- margin-right: 0;
76
- }
75
+ &:last-child { margin-right: 0; }
77
76
  }
78
77
  }
79
78
  }
80
79
  }
81
80
 
82
81
  @include media-breakpoint-down(lg) {
83
- header,
84
- footer {
85
- height: 10vh;
86
- }
82
+ header, footer { height: 10vh; }
87
83
  }
88
84
  }
89
-
90
- .b-toaster.b-toaster-top-center .b-toaster-slot,
91
- .b-toaster.b-toaster-top-right .b-toaster-slot, {
92
- top: 10vh;
93
- }
94
85
  </style>
@@ -1,34 +1,26 @@
1
1
  <template>
2
- <b-navbar-brand href="/">
2
+ <BNavbarBrand href="/">
3
3
  <img
4
4
  class="logo"
5
5
  src="../assets/better-together-logo.png"
6
6
  alt="Better Together"
7
7
  >
8
- </b-navbar-brand>
8
+ </BNavbarBrand>
9
9
  </template>
10
10
 
11
- <script>
12
- export default {
13
- name: 'BtBrandingLogo',
14
- }
11
+ <script setup>
12
+ import { BNavbarBrand } from 'bootstrap-vue-next'
15
13
  </script>
16
14
 
17
15
  <style scoped lang="scss">
18
- @import 'bootstrap/scss/_functions.scss';
19
- @import 'bootstrap/scss/_variables.scss';
20
- @import 'bootstrap/scss/_mixins.scss';
16
+ @import 'bootstrap/scss/functions';
17
+ @import 'bootstrap/scss/variables';
18
+ @import 'bootstrap/scss/mixins';
21
19
 
22
- .logo {
23
- height: 10vh;
24
- }
25
- .navbar-brand {
26
- margin-right: 5vw;
27
- }
20
+ .logo { height: 10vh; }
21
+ .navbar-brand { margin-right: 5vw; }
28
22
 
29
23
  @include media-breakpoint-down(lg) {
30
- .logo {
31
- height: 7vh;
32
- }
24
+ .logo { height: 7vh; }
33
25
  }
34
26
  </style>
@@ -3,10 +3,10 @@
3
3
  id="bt-header"
4
4
  class="container-fluid"
5
5
  >
6
- <b-navbar
6
+ <BNavbar
7
7
  toggleable="lg"
8
- :type="backgroundStyle"
9
- :style="headerStyle()"
8
+ :variant="backgroundStyle"
9
+ :style="headerStyle"
10
10
  >
11
11
  <div
12
12
  id="nav-inner"
@@ -15,115 +15,57 @@
15
15
  <slot name="branding-logo">
16
16
  <BtBrandingLogo />
17
17
  </slot>
18
- <b-navbar-toggle target="mobile-collapse" />
19
- <b-collapse
20
- id="right-collapse"
18
+ <BNavbarToggle target="nav-collapse" />
19
+ <BCollapse
20
+ id="nav-collapse"
21
21
  is-nav
22
- invisible
23
22
  >
24
- <BtNavBar navbar-class="ml-auto justify-content-center" />
25
- </b-collapse>
26
-
27
- <b-collapse
28
- id="mobile-collapse"
29
- is-nav
30
- >
31
- <BtNavBar
32
- navbar-class="m-auto d-block d-lg-none center"
33
- />
34
- </b-collapse>
23
+ <BtNavBar navbar-class="ms-auto justify-content-center" />
24
+ </BCollapse>
35
25
  </div>
36
- </b-navbar>
26
+ </BNavbar>
37
27
  </header>
38
28
  </template>
39
29
 
40
- <script>
41
- import { mapGetters } from 'vuex'
30
+ <script setup>
31
+ import { computed } from 'vue'
32
+ import { BNavbar, BNavbarToggle, BCollapse } from 'bootstrap-vue-next'
33
+ import { useCommunityStore } from '../stores/communities'
42
34
  import BtBrandingLogo from './BtBrandingLogo.vue'
43
35
  import BtNavBar from './BtNavBar.vue'
44
36
 
45
- export default {
46
- name: 'BtHeader',
47
- components: {
48
- BtBrandingLogo,
49
- BtNavBar,
50
- },
51
- props: {
52
- backgroundStyle: {
53
- type: String,
54
- default: () => 'dark',
55
- },
56
- },
57
- computed: {
58
- ...mapGetters('CommunityEngine/Communities', ['customization']),
59
- },
60
- methods: {
61
- headerStyle() {
62
- const styles = {
63
- backgroundColor: this.customization.backgroundColor,
64
- }
37
+ defineProps({
38
+ backgroundStyle: { type: String, default: 'dark' },
39
+ })
65
40
 
66
- if (this.customization.coverImageUrl !== '' && this.customization.coverImageUrl !== undefined) {
67
- styles.backgroundImage = `url(${this.customization.coverImageUrl})`
68
- styles.backgroundPositionY = this.customization.coverImagePositionY
69
- }
41
+ const communityStore = useCommunityStore()
70
42
 
71
- return styles
72
- },
73
- },
74
- }
43
+ const headerStyle = computed(() => {
44
+ const { customization } = communityStore
45
+ const styles = { backgroundColor: customization.backgroundColor }
46
+ if (customization.coverImageUrl) {
47
+ styles.backgroundImage = `url(${customization.coverImageUrl})`
48
+ styles.backgroundPositionY = customization.coverImagePositionY
49
+ }
50
+ return styles
51
+ })
75
52
  </script>
76
53
 
77
- <!-- Add "scoped" attribute to limit CSS to this component only -->
78
54
  <style scoped lang="scss">
79
- @import 'bootstrap/scss/_functions.scss';
80
- @import 'bootstrap/scss/_variables.scss';
81
- @import 'bootstrap/scss/_mixins.scss';
55
+ @import 'bootstrap/scss/functions';
56
+ @import 'bootstrap/scss/variables';
57
+ @import 'bootstrap/scss/mixins';
82
58
  @import '../stylesheets/theme.scss';
83
59
 
84
60
  #bt-header {
85
61
  min-height: 15vh;
86
-
87
62
  nav {
88
63
  z-index: 1000;
89
64
  background-repeat: no-repeat;
90
65
  background-size: cover;
91
-
92
- ::v-deep #nav-inner {
93
- position: relative;
94
- }
66
+ :deep(#nav-inner) { position: relative; }
95
67
  }
96
-
97
- #right-collapse {
98
- bottom: 0;
99
- position: absolute;
100
- right: 0;
101
- }
102
-
103
- #mobile-collapse.show {
104
- ::v-deep .user-dropdown {
105
- a.dropdown-toggle {
106
- > span {
107
- max-width: initial;
108
- }
109
- }
110
- a.dropdown-item {
111
- text-align: center;
112
- color: $default-text-color-bg-dark;
113
-
114
- &.router-link-exact-active,
115
- &:hover {
116
- background-color: initial;
117
- color: $accent-color;
118
- }
119
- }
120
- ul.dropdown-menu {
121
- background-color: initial;
122
- }
123
- }
124
- }
125
-
126
- .navbar-toggler >>> .navbar-toggler-icon {
68
+ :deep(.navbar-toggler .navbar-toggler-icon) {
127
69
  width: 1em;
128
70
  height: 1em;
129
71
  }
@@ -3,67 +3,36 @@
3
3
  id="main-content"
4
4
  class="container"
5
5
  >
6
- <router-view />
6
+ <RouterView />
7
7
  </main>
8
8
  </template>
9
9
 
10
- <script>
11
- export default {
12
- name: 'BtMainContent',
13
- }
10
+ <script setup>
11
+ import { RouterView } from 'vue-router'
14
12
  </script>
15
13
 
16
14
  <style lang="scss">
17
- @import 'bootstrap/scss/_functions.scss';
18
- @import 'bootstrap/scss/_variables.scss';
19
- @import 'bootstrap/scss/_mixins.scss';
15
+ @import 'bootstrap/scss/functions';
16
+ @import 'bootstrap/scss/variables';
17
+ @import 'bootstrap/scss/mixins';
20
18
  @import '../stylesheets/theme.scss';
21
19
 
22
20
  #main-content {
23
21
  margin-bottom: 5vh;
24
-
25
- h1, h2, h3, h4, h5, h6 {
26
- text-align: center;
27
- margin-bottom: 20px;
28
- }
29
-
22
+ h1, h2, h3, h4, h5, h6 { text-align: center; margin-bottom: 20px; }
30
23
  section {
31
24
  border-radius: 10px;
32
25
  margin-bottom: 20px;
33
26
  padding: 15px;
34
27
  background-color: #fff;
35
-
36
- a {
37
- color: $accent-color;
38
-
39
- &:hover {
40
- color: $accent-color;
41
- }
42
- }
43
-
44
- .heading {
45
- margin-top: 20px;
46
- }
47
-
28
+ a { color: $accent-color; &:hover { color: $accent-color; } }
29
+ .heading { margin-top: 20px; }
48
30
  .card {
49
31
  border: none;
50
- .card-header, .card-footer {
51
- background: none;
52
- border: none;
53
- }
54
-
55
- .card-header {
56
- h5 {
57
- margin-bottom: 0;
58
- }
59
- }
32
+ .card-header, .card-footer { background: none; border: none; }
33
+ .card-header h5 { margin-bottom: 0; }
60
34
  }
61
35
  }
62
- }
63
-
64
- @include media-breakpoint-down(lg) {
65
- #main-content {
66
- height: auto;
67
- }
36
+ @include media-breakpoint-down(lg) { height: auto; }
68
37
  }
69
38
  </style>