Version 3 #67

Merged
danieljsummers merged 53 commits from version-3 into master 2021-10-26 23:39:59 +00:00
8 changed files with 252 additions and 157 deletions
Showing only changes of commit 33effdd17e - Show all commits

View File

@ -14,15 +14,14 @@
"core-js": "^3.6.5",
"date-fns": "^2.24.0",
"vue": "^3.0.0",
"vue-class-component": "^8.0.0-0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@types/auth0-js": "^9.14.5",
"@types/events": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.29.3",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
@ -31,11 +30,11 @@
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"typescript": "~4.1.5",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^7.17.0",
"sass": "^1.37.0",
"sass-loader": "^10.0.0",
"typescript": "~4.3.5",
"vue-cli-plugin-pug": "~2.0.0"
}
},
@ -5009,20 +5008,6 @@
"node": ">=0.8"
}
},
"node_modules/clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
"integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
"dev": true,
"dependencies": {
"is-plain-object": "^2.0.4",
"kind-of": "^6.0.2",
"shallow-clone": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/coa": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
@ -9912,6 +9897,15 @@
"node": ">=0.10.0"
}
},
"node_modules/klona": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/launch-editor": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz",
@ -13429,19 +13423,19 @@
}
},
"node_modules/sass-loader": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz",
"integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==",
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.2.0.tgz",
"integrity": "sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw==",
"dev": true,
"dependencies": {
"clone-deep": "^4.0.1",
"loader-utils": "^1.2.3",
"neo-async": "^2.6.1",
"schema-utils": "^2.6.1",
"semver": "^6.3.0"
"klona": "^2.0.4",
"loader-utils": "^2.0.0",
"neo-async": "^2.6.2",
"schema-utils": "^3.0.0",
"semver": "^7.3.2"
},
"engines": {
"node": ">= 8.9.0"
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
@ -13449,7 +13443,7 @@
},
"peerDependencies": {
"fibers": ">= 3.1.0",
"node-sass": "^4.0.0",
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0",
"sass": "^1.3.0",
"webpack": "^4.36.0 || ^5.0.0"
},
@ -13465,6 +13459,71 @@
}
}
},
"node_modules/sass-loader/node_modules/loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
},
"engines": {
"node": ">=8.9.0"
}
},
"node_modules/sass-loader/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sass-loader/node_modules/schema-utils": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
},
"engines": {
"node": ">= 10.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
}
},
"node_modules/sass-loader/node_modules/semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sass-loader/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
@ -13721,18 +13780,6 @@
"sha.js": "bin.js"
}
},
"node_modules/shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
"integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
"dev": true,
"dependencies": {
"kind-of": "^6.0.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@ -15378,9 +15425,9 @@
"dev": true
},
"node_modules/typescript": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.6.tgz",
"integrity": "sha512-pxnwLxeb/Z5SP80JDRzVjh58KsM6jZHRAOtTpS7sXLS4ogXNKC9ANxHHZqLLeVHZN35jCtI4JdmLLbLiC1kBow==",
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@ -15837,14 +15884,6 @@
"@vue/shared": "3.2.12"
}
},
"node_modules/vue-class-component": {
"version": "8.0.0-rc.1",
"resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-8.0.0-rc.1.tgz",
"integrity": "sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==",
"peerDependencies": {
"vue": "^3.0.0"
}
},
"node_modules/vue-cli-plugin-pug": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/vue-cli-plugin-pug/-/vue-cli-plugin-pug-2.0.0.tgz",
@ -21288,17 +21327,6 @@
"integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=",
"dev": true
},
"clone-deep": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
"integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
"dev": true,
"requires": {
"is-plain-object": "^2.0.4",
"kind-of": "^6.0.2",
"shallow-clone": "^3.0.0"
}
},
"coa": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
@ -25137,6 +25165,12 @@
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"dev": true
},
"klona": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/klona/-/klona-2.0.4.tgz",
"integrity": "sha512-ZRbnvdg/NxqzC7L9Uyqzf4psi1OM4Cuc+sJAkQPjO6XkQIJTNbfK2Rsmbw8fx1p2mkZdp2FZYo2+LwXYY/uwIA==",
"dev": true
},
"launch-editor": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz",
@ -28030,16 +28064,64 @@
}
},
"sass-loader": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-8.0.2.tgz",
"integrity": "sha512-7o4dbSK8/Ol2KflEmSco4jTjQoV988bM82P9CZdmo9hR3RLnvNc0ufMNdMrB0caq38JQ/FgF4/7RcbcfKzxoFQ==",
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-10.2.0.tgz",
"integrity": "sha512-kUceLzC1gIHz0zNJPpqRsJyisWatGYNFRmv2CKZK2/ngMJgLqxTbXwe/hJ85luyvZkgqU3VlJ33UVF2T/0g6mw==",
"dev": true,
"requires": {
"clone-deep": "^4.0.1",
"loader-utils": "^1.2.3",
"neo-async": "^2.6.1",
"schema-utils": "^2.6.1",
"semver": "^6.3.0"
"klona": "^2.0.4",
"loader-utils": "^2.0.0",
"neo-async": "^2.6.2",
"schema-utils": "^3.0.0",
"semver": "^7.3.2"
},
"dependencies": {
"loader-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
"dev": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
"yallist": "^4.0.0"
}
},
"schema-utils": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
}
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
}
}
},
"sax": {
@ -28266,15 +28348,6 @@
"safe-buffer": "^5.0.1"
}
},
"shallow-clone": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
"integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
"dev": true,
"requires": {
"kind-of": "^6.0.2"
}
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@ -29627,9 +29700,9 @@
"dev": true
},
"typescript": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.6.tgz",
"integrity": "sha512-pxnwLxeb/Z5SP80JDRzVjh58KsM6jZHRAOtTpS7sXLS4ogXNKC9ANxHHZqLLeVHZN35jCtI4JdmLLbLiC1kBow==",
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz",
"integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==",
"dev": true
},
"uglify-js": {
@ -30005,12 +30078,6 @@
"@vue/shared": "3.2.12"
}
},
"vue-class-component": {
"version": "8.0.0-rc.1",
"resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-8.0.0-rc.1.tgz",
"integrity": "sha512-w1nMzsT/UdbDAXKqhwTmSoyuJzUXKrxLE77PCFVuC6syr8acdFDAq116xgvZh9UCuV0h+rlCtxXolr3Hi3HyPQ==",
"requires": {}
},
"vue-cli-plugin-pug": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/vue-cli-plugin-pug/-/vue-cli-plugin-pug-2.0.0.tgz",

View File

@ -19,15 +19,14 @@
"core-js": "^3.6.5",
"date-fns": "^2.24.0",
"vue": "^3.0.0",
"vue-class-component": "^8.0.0-0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
},
"devDependencies": {
"@types/auth0-js": "^9.14.5",
"@types/events": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^4.18.0",
"@typescript-eslint/parser": "^4.18.0",
"@typescript-eslint/eslint-plugin": "^4.29.3",
"@typescript-eslint/parser": "^4.29.3",
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
@ -36,11 +35,11 @@
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0",
"@vue/eslint-config-typescript": "^7.0.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"typescript": "~4.1.5",
"eslint": "^6.8.0",
"eslint-plugin-vue": "^7.17.0",
"sass": "^1.37.0",
"sass-loader": "^10.0.0",
"typescript": "~4.3.5",
"vue-cli-plugin-pug": "~2.0.0"
}
}

View File

@ -8,17 +8,7 @@
</template>
<script setup lang="ts">
import { provide } from "vue"
import "bootstrap/dist/css/bootstrap.min.css"
import { AuthService } from "./auth"
/** The auth service injection symbol */
export const AuthSymbol = Symbol("AuthService")
provide(AuthSymbol, AuthService)
</script>
<style lang="sass">

View File

@ -1,6 +1,7 @@
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import { createApp } from "vue"
import App from "./App.vue"
import auth from "./plugins/auth"
import router from "./router"
import store from "./store"
createApp(App).use(store).use(router).mount('#app')
createApp(App).use(store).use(router).use(auth).mount('#app')

View File

@ -0,0 +1,31 @@
import { App, inject, InjectionKey } from "vue"
import authService, { AuthService } from "@/auth"
/** The symbol to use for dependency injection */
const AuthSymbol : InjectionKey<AuthService> = Symbol("Auth service")
export default {
install (app : App) {
Object.defineProperty(app, "authService", { get: () => authService })
app.provide(AuthSymbol, authService)
app.mixin({
created () {
if (this.handleLoginEvent) {
authService.addListener("loginEvent", this.handleLoginEvent)
}
},
destroyed () {
if (this.handleLoginEvent) {
authService.removeListener("loginEvent", this.handleLoginEvent)
}
}
})
}
}
/** Use the auth service */
export function useAuth () : AuthService {
return inject(AuthSymbol)!
}

View File

@ -17,12 +17,12 @@ const routes: Array<RouteRecordRaw> = [
component: Home,
meta: { title: "Welcome!" }
},
{
path: "/journal",
name: "Journal",
component: () => import(/* webpackChunkName: "journal" */ "@/views/Journal.vue"),
meta: { auth: true, title: "Loading Prayer Journal..." }
},
// {
// path: "/journal",
// name: "Journal",
// component: () => import(/* webpackChunkName: "journal" */ "@/views/Journal.vue"),
// meta: { auth: true, title: "Loading Prayer Journal..." }
// },
{
path: "/legal/privacy-policy",
name: "PrivacyPolicy",
@ -35,36 +35,36 @@ const routes: Array<RouteRecordRaw> = [
component: () => import(/* webpackChunkName: "legal" */ "@/views/legal/TermsOfService.vue"),
meta: { title: "Terms of Service" }
},
{
path: "/request/:id/edit",
name: "EditRequest",
component: () => import(/* webpackChunkName: "edit" */ "@/views/request/EditRequest.vue"),
meta: { auth: true, title: "Edit Prayer Request" }
},
{
path: "/request/:id/full",
name: "FullRequest",
component: () => import(/* webpackChunkName: "full" */ "@/views/request/FullRequest.vue"),
meta: { auth: true, title: "View Full Prayer Request" }
},
{
path: "/requests/active",
name: "ActiveRequests",
component: () => import(/* webpackChunkName: "list" */ "@/views/request/ActiveRequests.vue"),
meta: { auth: true, title: "All Active Requests" }
},
{
path: "/requests/answered",
name: "AnsweredRequests",
component: () => import(/* webpackChunkName: "list" */ "@/views/request/AnsweredRequests.vue"),
meta: { auth: true, title: "Answered Requests" }
},
{
path: "/requests/snoozed",
name: "SnoozedRequests",
component: () => import(/* webpackChunkName: "list" */ "@/views/request/SnoozedRequests.vue"),
meta: { auth: true, title: "Snoozed Requests" }
},
// {
// path: "/request/:id/edit",
// name: "EditRequest",
// component: () => import(/* webpackChunkName: "edit" */ "@/views/request/EditRequest.vue"),
// meta: { auth: true, title: "Edit Prayer Request" }
// },
// {
// path: "/request/:id/full",
// name: "FullRequest",
// component: () => import(/* webpackChunkName: "full" */ "@/views/request/FullRequest.vue"),
// meta: { auth: true, title: "View Full Prayer Request" }
// },
// {
// path: "/requests/active",
// name: "ActiveRequests",
// component: () => import(/* webpackChunkName: "list" */ "@/views/request/ActiveRequests.vue"),
// meta: { auth: true, title: "All Active Requests" }
// },
// {
// path: "/requests/answered",
// name: "AnsweredRequests",
// component: () => import(/* webpackChunkName: "list" */ "@/views/request/AnsweredRequests.vue"),
// meta: { auth: true, title: "Answered Requests" }
// },
// {
// path: "/requests/snoozed",
// name: "SnoozedRequests",
// component: () => import(/* webpackChunkName: "list" */ "@/views/request/SnoozedRequests.vue"),
// meta: { auth: true, title: "Snoozed Requests" }
// },
{
path: "/user/log-on",
name: "LogOn",

View File

@ -4,18 +4,16 @@ main.container
</template>
<script setup lang="ts">
import { inject, onBeforeMount } from "vue"
import { onBeforeMount } from "vue"
import { useRouter } from "vue-router"
import { AuthService } from "@/auth"
import { useAuth } from "@/plugins/auth"
import { useStore } from "@/store"
import { AuthSymbol } from "@/App.vue"
const store = useStore()
const router = useRouter()
/** Auth service instance */
const auth = inject(AuthSymbol) as AuthService
const auth = useAuth()
/** Navigate on auth completion */
auth.on("loginEvent", (data: any) => {

View File

@ -1,3 +1,12 @@
module.exports = {
lintOnSave: false
lintOnSave: false,
configureWebpack: {
module: {
rules: [{
test: /\.mjs$/,
include: /node_modules/,
type: "javascript/auto"
}]
}
}
}