Преглед на файлове

Merge branch 'chat-gui' of fyindr/siimee into dev

tags/0.0.1^2
maeda преди 3 години
родител
ревизия
bbcec16c67

+ 2
- 1
backend/lib/routes/membership/active.js Целия файл

53
                 profileId,
53
                 profileId,
54
                 membershipType,
54
                 membershipType,
55
             )
55
             )
56
-            console.log('groupings :>> ', groupings)
56
+            // console.log('groupings :>> ', groupings)
57
+
57
             /**
58
             /**
58
              * Heavily process the result by storing just a profile_id
59
              * Heavily process the result by storing just a profile_id
59
              * and attach complete profiles
60
              * and attach complete profiles

+ 3
- 2
backend/lib/schemas/profiles.js Целия файл

3
 const Joi = require('joi')
3
 const Joi = require('joi')
4
 const surveyResponseSchema = require('./responses')
4
 const surveyResponseSchema = require('./responses')
5
 const userSchema = require('./user')
5
 const userSchema = require('./user')
6
+const tagSchema = require('./tags')
6
 
7
 
7
 const singleProfile = Joi.object({
8
 const singleProfile = Joi.object({
8
     profile_id: Joi.number(),
9
     profile_id: Joi.number(),
11
     user_email: Joi.string(),
12
     user_email: Joi.string(),
12
     responses: surveyResponseSchema.list,
13
     responses: surveyResponseSchema.list,
13
     reveal: Joi.array().items(),
14
     reveal: Joi.array().items(),
14
-    tags: Joi.array().items(),
15
+    tags: tagSchema.list,
15
     user_type: Joi.any(),
16
     user_type: Joi.any(),
16
     user: userSchema.single,
17
     user: userSchema.single,
17
     profile_description: Joi.string().allow(null, ''),
18
     profile_description: Joi.string().allow(null, ''),
22
 
23
 
23
 module.exports = {
24
 module.exports = {
24
     single: singleProfile,
25
     single: singleProfile,
25
-    list: Joi.array().items(singleProfile).label('profile_list')
26
+    list: Joi.array().items(singleProfile).label('profile_list'),
26
 }
27
 }

+ 24
- 0
backend/lib/schemas/tags.js Целия файл

1
+'use strict'
2
+
3
+const Joi = require('joi')
4
+
5
+const singleTag = Joi.object({
6
+    tag_id: Joi.number(),
7
+    tag_category: Joi.string(),
8
+    tag_description: Joi.string(),
9
+    is_active: Joi.number().required(),
10
+}).label('tag_single')
11
+
12
+const singleTagAssociation = Joi.object({
13
+    tag_association_id: Joi.number(),
14
+    profile_id: Joi.number().required(),
15
+    membership_id: Joi.number(),
16
+    tag_id: Joi.number().required(),
17
+    is_deleted: Joi.boolean().required(),
18
+}).label('tag_association_single')
19
+
20
+module.exports = {
21
+    association: singleTagAssociation,
22
+    single: singleTag,
23
+    list: Joi.array().items(singleTag).label('tag_list'),
24
+}

+ 1
- 1
backend/lib/services/membership.js Целия файл

70
             profileId,
70
             profileId,
71
             type,
71
             type,
72
         )
72
         )
73
-        console.log('dedupedGroupings :>> ', dedupedGroupings)
73
+
74
         /** Grab just the Groupings this id has a Membership for */
74
         /** Grab just the Groupings this id has a Membership for */
75
         return await Grouping.query()
75
         return await Grouping.query()
76
             .whereIn('grouping_id', dedupedGroupings)
76
             .whereIn('grouping_id', dedupedGroupings)

+ 6
- 20
backend/lib/services/user.js Целия файл

148
     async login({ email, password }, txn) {
148
     async login({ email, password }, txn) {
149
         const { User, Auth } = this.server.models()
149
         const { User, Auth } = this.server.models()
150
 
150
 
151
-        
152
-        
153
         const user = await Auth.query(txn)
151
         const user = await Auth.query(txn)
154
             .throwIfNotFound()
152
             .throwIfNotFound()
155
             .first()
153
             .first()
159
 
157
 
160
         /** Uncomment to run password check using SecurePassword */
158
         /** Uncomment to run password check using SecurePassword */
161
         const passwordCheck = await this.pwd.verify(bufferPepper, user.token)
159
         const passwordCheck = await this.pwd.verify(bufferPepper, user.token)
162
-        console.log("passwordCheck", passwordCheck)
163
         if (passwordCheck === SecurePassword.VALID_NEEDS_REHASH) {
160
         if (passwordCheck === SecurePassword.VALID_NEEDS_REHASH) {
164
             await this.changePassword(user.user_email, password, txn)
161
             await this.changePassword(user.user_email, password, txn)
165
-        }
166
-        else if (passwordCheck !== SecurePassword.VALID) {
162
+        } else if (passwordCheck !== SecurePassword.VALID) {
167
             throw User.createNotFoundError()
163
             throw User.createNotFoundError()
168
         }
164
         }
169
 
165
 
202
      * @returns {number}
198
      * @returns {number}
203
      */
199
      */
204
     async changePassword(email, password, txn) {
200
     async changePassword(email, password, txn) {
205
-        const { User, Auth } = this.server.models()
206
-
207
-        console.log('email passed to changePassword', email)
201
+        const { Auth } = this.server.models()
208
 
202
 
209
-        const hashed = await this.pwd.hash(Buffer.from(process.env.PEPPER + password))
210
-        console.log('hashed', hashed)
203
+        const hashed = await this.pwd.hash(
204
+            Buffer.from(process.env.PEPPER + password),
205
+        )
211
 
206
 
212
         await Auth.query(txn)
207
         await Auth.query(txn)
213
             .throwIfNotFound()
208
             .throwIfNotFound()
214
             .where({ user_email: email })
209
             .where({ user_email: email })
215
             .patch({
210
             .patch({
216
                 // user_email: email,
211
                 // user_email: email,
217
-                token: hashed
212
+                token: hashed,
218
             })
213
             })
219
-        console.log('changePassword query completed')
220
         return email
214
         return email
221
-
222
-        // await User.query(txn)
223
-        //     .throwIfNotFound()
224
-        //     .where({ id })
225
-        //     .patch({
226
-        //         password: await this.pwd.hash(Buffer.from(password)),
227
-        //     })
228
-        // return id
229
     }
215
     }
230
 
216
 
231
     async getPassword(email, txn) {
217
     async getPassword(email, txn) {

+ 9
- 19
frontend/src/App.vue Целия файл

1
 <template lang="pug">
1
 <template lang="pug">
2
 w-app
2
 w-app
3
-    div.nav(v-if="isLoggedIn" style="display: flex; justify-content: space-between;")
3
+    .nav(v-if="profile.isLoggedIn" style="display: flex; justify-content: space-between;")
4
         header
4
         header
5
-            h2 home - profile: {{ getPid }}
5
+            h2 current - profile: {{ profile.id }}
6
         w-drawer(v-model="openDrawer")
6
         w-drawer(v-model="openDrawer")
7
-            SideBar(
8
-                :pid="getPid"
9
-                @updatePid="setPid"
10
-                @hide="showSidebar = false"
11
-            )
7
+            SideBar(@updatePid="setPid" :pid="profile.id.value")
12
         w-button(@click="openDrawer = true" outline="")
8
         w-button(@click="openDrawer = true" outline="")
13
             | Active Chats
9
             | Active Chats
10
+
14
     RouterView(
11
     RouterView(
15
-        v-if="isLoggedIn"
16
-        :pid="getPid"
12
+        v-if="profile.isLoggedIn"
13
+        :pid="profile.id.value"
17
         @updatePid="setPid"
14
         @updatePid="setPid"
18
         @show-sidebar="showSidebar = !showSidebar"
15
         @show-sidebar="showSidebar = !showSidebar"
19
     )
16
     )
32
 export default {
29
 export default {
33
     components: { SideBar },
30
     components: { SideBar },
34
     data: () => ({
31
     data: () => ({
35
-        showSidebar: false,
36
         sliderVal: 1,
32
         sliderVal: 1,
37
         openDrawer: false,
33
         openDrawer: false,
38
     }),
34
     }),
39
     computed: {
35
     computed: {
40
-        getPid: () => {
41
-            return currentProfile.id.value ? currentProfile.id.value : null
42
-        },
43
-        isLoggedIn: () => {
44
-            return currentProfile.isLoggedIn
36
+        profile: () => {
37
+            return currentProfile
45
         },
38
         },
46
     },
39
     },
47
     async created() {
40
     async created() {
54
          * using the login form
47
          * using the login form
55
          */
48
          */
56
         if (DEV_MODE) {
49
         if (DEV_MODE) {
57
-            this.setPid(DEV_PID)
50
+            await this.setPid(DEV_PID)
58
         }
51
         }
59
     },
52
     },
60
     methods: {
53
     methods: {
68
             }
61
             }
69
             await currentProfile.login(profileId, this.$waveui.notify)
62
             await currentProfile.login(profileId, this.$waveui.notify)
70
             console.log('---')
63
             console.log('---')
71
-            //  step 3: subscribe to the this.subscriptions array
72
-            // view current subscriptions on the currentProfile.chatter.subscriptions
73
-            console.log('subscriptions', currentProfile.chatter.subscriptions)
74
         },
64
         },
75
     },
65
     },
76
 }
66
 }

+ 0
- 1
frontend/src/components/MainNav.vue Целия файл

1
 <template lang="pug">
1
 <template lang="pug">
2
 nav#main-header
2
 nav#main-header
3
-    button(@click="$emit('show-sidebar')") toggle sidebar
4
     router-link(:to="`/matches`") matches
3
     router-link(:to="`/matches`") matches
5
     router-link(to='/') home
4
     router-link(to='/') home
6
     router-link(:to="`/survey`") survey
5
     router-link(:to="`/survey`") survey

+ 8
- 8
frontend/src/components/Messages.vue Целия файл

1
 <template lang="pug">
1
 <template lang="pug">
2
 .sidebar--messages
2
 .sidebar--messages
3
-  h5.message__title messages from matches
3
+  h5.message__title matches
4
   router-link(
4
   router-link(
5
-        :to="`/chats/${profile.profile_id}`" 
6
-        v-for='profile in matches' 
7
-        :key='profile.profile_id' 
8
-        :class="[pid == profile.profile_id ? 'active' : '', 'sidebar__message', 'f-col', 'start']"
5
+        :to="`/chats/${match.profile.profile_id}`" 
6
+        v-for='match in matches' 
7
+        :key='match.profile.profile_id' 
8
+        :class="[pid == match.profile.profile_id ? 'active' : '', 'sidebar__message', 'f-col', 'start']"
9
     )
9
     )
10
-    img(:src='profile.avatar' style="max-height:100px")
10
+    img(:src='match.profile.avatar' style="max-height:100px")
11
     .message__right
11
     .message__right
12
-        h4.message__name {{ profile.name }}
13
-        p.message__content {{ profile.metadata.rawMetadata || &quot;Hello I&apos;m using tinder!&quot; }}
12
+        h4.message__name {{ match.profile.name }}
13
+        p.message__content {{ match.profile }}
14
 </template>
14
 </template>
15
 
15
 
16
 <script>
16
 <script>

+ 0
- 6
frontend/src/components/ProfileCardList.vue Целия файл

85
 }
85
 }
86
 
86
 
87
 // AHP Button behavior
87
 // AHP Button behavior
88
-
89
 const accept = async targetId => {
88
 const accept = async targetId => {
90
     if (targetId == props.pid) return
89
     if (targetId == props.pid) return
91
     // need to pass these arguments (profileId, targetId, status)
90
     // need to pass these arguments (profileId, targetId, status)
101
 
100
 
102
     // Reuse old grouping name if theres a match
101
     // Reuse old grouping name if theres a match
103
     let channel = groupingName
102
     let channel = groupingName
104
-    console.log('membershipMatch :>> ', membershipMatch)
105
     if (membershipMatch?.hasMatch) {
103
     if (membershipMatch?.hasMatch) {
106
-        const [time, intiator, target] = groupingName.split('_')
107
         channel = membershipMatch.groupings[0].grouping_name
104
         channel = membershipMatch.groupings[0].grouping_name
108
-        console.log('channel :>> ', channel)
109
     }
105
     }
110
     await subscribeToChannel(channel)
106
     await subscribeToChannel(channel)
111
     emit('reload')
107
     emit('reload')
118
 const subscribeToChannel = async channelName => {
114
 const subscribeToChannel = async channelName => {
119
     // create a chatter reference from the current profile
115
     // create a chatter reference from the current profile
120
     const chatter = currentProfile.chatter
116
     const chatter = currentProfile.chatter
121
-    // console.log('mock sender:', pid)
122
 
117
 
123
     /**
118
     /**
124
      * publish a new message to the chatter with the channel and the message & title is optional
119
      * publish a new message to the chatter with the channel and the message & title is optional
130
         description: `This is the checking to see if we are subscribed to the ${channelName} channel!`,
125
         description: `This is the checking to see if we are subscribed to the ${channelName} channel!`,
131
     })
126
     })
132
     // PubNub response will be a timecode of when the message was published
127
     // PubNub response will be a timecode of when the message was published
133
-    console.log('res:', res)
134
     //router.push({ path: `/chat/${pid}` })
128
     //router.push({ path: `/chat/${pid}` })
135
 }
129
 }
136
 
130
 

+ 10
- 17
frontend/src/components/SideBar.vue Целия файл

1
 <template lang="pug">
1
 <template lang="pug">
2
-aside.sidebar
3
-    .temp-control-box
2
+aside.sidebar.w-flex.column.pa8
3
+    Messages(:matches="matches" :pid="pid")
4
+    .spacer
5
+    nav.temp-control-box
4
         input(v-model="switchToPID" @keyup.enter="$emit('updatePid', switchToPID)")
6
         input(v-model="switchToPID" @keyup.enter="$emit('updatePid', switchToPID)")
5
         button(@click="$emit('updatePid', switchToPID)") switch profile
7
         button(@click="$emit('updatePid', switchToPID)") switch profile
6
     
8
     
7
-    Messages(:matches="matches" :pid="pid")
8
 </template>
9
 </template>
9
 
10
 
10
 <script>
11
 <script>
12
+import { currentProfile } from '../services'
11
 import Messages from './Messages.vue'
13
 import Messages from './Messages.vue'
12
 import { mixins } from '../utils'
14
 import { mixins } from '../utils'
13
 
15
 
16
     mixins: [mixins.pidMixin],
18
     mixins: [mixins.pidMixin],
17
     data: () => ({
19
     data: () => ({
18
         switchToPID: null,
20
         switchToPID: null,
19
-        matches: [
20
-            {
21
-                name: 'Bob McRob',
22
-                profile_id: 111,
23
-                avatar: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/newborn-baby-boy-sleeping-peacefully-wearing-knit-royalty-free-image-1589459736.jpg?crop=0.669xw:1.00xh;0.228xw,0&resize=640:*',
24
-                metadata: { rawMetadata: 'howdy howdy howdy' },
25
-            },
26
-            {
27
-                name: 'Rob Bebob',
28
-                profile_id: 112,
29
-                avatar: 'https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/newborn-baby-boy-sleeping-peacefully-wearing-knit-royalty-free-image-1589459736.jpg?crop=0.669xw:1.00xh;0.228xw,0&resize=640:*',
30
-                metadata: { rawMetadata: 'this is the last message' },
31
-            },
32
-        ],
33
     }),
21
     }),
22
+    computed: {
23
+        profile: () => currentProfile,
24
+        matches: () =>
25
+            currentProfile.groupings.filter(g => g.grouping_type == 'match'),
26
+    },
34
     mounted() {
27
     mounted() {
35
         // Set the form to display the default pid set in Home.vue
28
         // Set the form to display the default pid set in Home.vue
36
         this.switchToPID = this.pid
29
         this.switchToPID = this.pid

+ 10
- 0
frontend/src/router/index.js Целия файл

2
 
2
 
3
 import HomeView from '../views/HomeView.vue'
3
 import HomeView from '../views/HomeView.vue'
4
 import ProfileView from '../views/ProfileView.vue'
4
 import ProfileView from '../views/ProfileView.vue'
5
+import ChatView from '../views/ChatView.vue'
5
 import MatchesView from '../views/MatchesView.vue'
6
 import MatchesView from '../views/MatchesView.vue'
6
 import LoginView from '../views/LoginView.vue'
7
 import LoginView from '../views/LoginView.vue'
7
 import SurveyView from '../views/SurveyView.vue'
8
 import SurveyView from '../views/SurveyView.vue'
30
         component: ProfileView,
31
         component: ProfileView,
31
         meta: { requiresAuth: true, requiresCompleteProfile: true },
32
         meta: { requiresAuth: true, requiresCompleteProfile: true },
32
     },
33
     },
34
+    {
35
+        path: '/chat/:tid',
36
+        component: ChatView,
37
+        meta: {
38
+            requiresAuth: true,
39
+            requiresCompleteProfile: true,
40
+            props: true,
41
+        },
42
+    },
33
     {
43
     {
34
         path: `/survey`,
44
         path: `/survey`,
35
         component: SurveyView,
45
         component: SurveyView,

+ 12
- 23
frontend/src/services/chat.service.js Целия файл

1
 import PubNub from 'pubnub'
1
 import PubNub from 'pubnub'
2
 
2
 
3
-// custom services
4
-import { fetchMembershipsByProfileId } from '../services/grouping.service'
5
-
6
 /**
3
 /**
7
  * Provider method holder
4
  * Provider method holder
8
  * We always reference this object so
5
  * We always reference this object so
67
         // Setup the main channel
64
         // Setup the main channel
68
         //  subscriptions array will be built dynamically from the "this.groupings" object
65
         //  subscriptions array will be built dynamically from the "this.groupings" object
69
         this.subscriptions = [MAIN_CHANNEL]
66
         this.subscriptions = [MAIN_CHANNEL]
67
+
70
         this.listeners = {
68
         this.listeners = {
71
             status: async e => {
69
             status: async e => {
72
-                // await this.publish(this.subscriptions[0], testMessage)
73
                 if (e.category !== 'PNConnectedCategory') return
70
                 if (e.category !== 'PNConnectedCategory') return
74
             },
71
             },
75
-            message: this._onMessage,
72
+            message: null, // Set manually in chat view
76
             presence: this._onPresence,
73
             presence: this._onPresence,
77
         }
74
         }
78
     }
75
     }
79
-    /**
80
-     * Callback that fires on every message
81
-     * @param {event} e
82
-     */
83
-    async _onMessage(e) {
84
-        if (e.message) {
85
-            console.log(
86
-                `received message: ${e.message.title} - ${e.message.description}`,
87
-                e,
88
-            )
89
-        }
90
-    }
91
     async _onPresence(e) {
76
     async _onPresence(e) {
92
         return
77
         return
93
     }
78
     }
94
-    async setup(uuid) {
79
+    setOnMessage(cb) {
80
+        this.listeners.message = cb
81
+    }
82
+
83
+    async setup(uuid, groupings) {
95
         this.uuid = `${uuid}`
84
         this.uuid = `${uuid}`
96
         this.provider = await setupPubnub(this.uuid)
85
         this.provider = await setupPubnub(this.uuid)
97
 
86
 
98
         //  step 1: build the this.groupings object from the backend
87
         //  step 1: build the this.groupings object from the backend
99
         // ? .await for the groupings to be fetched before subscribing to channels
88
         // ? .await for the groupings to be fetched before subscribing to channels
100
-        await this._setupAllChannels(this.uuid)
89
+        await this._setupAllChannels(groupings)
101
         this._listenFor({ listeners: this.listeners })
90
         this._listenFor({ listeners: this.listeners })
102
         this.subscribe({ channels: this.subscriptions })
91
         this.subscribe({ channels: this.subscriptions })
92
+        return this.subscriptions
103
     }
93
     }
104
     /**
94
     /**
105
      * Send a message to a channel
95
      * Send a message to a channel
110
      * @return {object} timestamp
100
      * @return {object} timestamp
111
      */
101
      */
112
     async publish(channel, message) {
102
     async publish(channel, message) {
113
-        console.log('publishing message to channel:', channel)
103
+        // console.log('publishing message to channel:', channel)
114
         return providerMethods.publish({ channel, message })
104
         return providerMethods.publish({ channel, message })
115
     }
105
     }
116
     /**
106
     /**
130
     }
120
     }
131
     //  step 2: build the this.subscriptions array from the this.groupings object
121
     //  step 2: build the this.subscriptions array from the this.groupings object
132
     // fetch all groupings for this profile and then store them in the chatter groupings object for reference
122
     // fetch all groupings for this profile and then store them in the chatter groupings object for reference
133
-    async _setupAllChannels(profileId) {
134
-        const groupings = await fetchMembershipsByProfileId(profileId)
135
-        console.log(`fetched groupings for profileId: ${profileId}`, groupings)
123
+    async _setupAllChannels(groupings) {
136
         groupings.forEach(grouping => {
124
         groupings.forEach(grouping => {
137
             this.subscriptions.push(grouping.grouping_name)
125
             this.subscriptions.push(grouping.grouping_name)
138
         })
126
         })
139
     }
127
     }
140
     stop() {
128
     stop() {
129
+        this.subscriptions = [MAIN_CHANNEL]
141
         console.warn('chatter stop no implemented')
130
         console.warn('chatter stop no implemented')
142
     }
131
     }
143
 }
132
 }

+ 28
- 11
frontend/src/services/login.service.js Целия файл

1
 import { ref } from 'vue'
1
 import { ref } from 'vue'
2
-import { fetchResponsesByProfileId, Chatter, StonkAlert } from '../services'
2
+import {
3
+    fetchMembershipsByProfileId,
4
+    fetchResponsesByProfileId,
5
+    Chatter,
6
+    StonkAlert,
7
+} from '../services'
3
 import { surveyFactory } from '../utils'
8
 import { surveyFactory } from '../utils'
4
 
9
 
5
-
6
 /**
10
 /**
7
  * Logged in profile state manager
11
  * Logged in profile state manager
8
  * Sort of a util and service hybrid
12
  * Sort of a util and service hybrid
9
  */
13
  */
10
 class Login {
14
 class Login {
11
     constructor() {
15
     constructor() {
12
-        this._loading = false
16
+        this._loading = ref(true)
13
 
17
 
14
         // Make reactive with vue observer
18
         // Make reactive with vue observer
15
         this.id = ref(null)
19
         this.id = ref(null)
16
 
20
 
21
+        this.groupings = []
17
         this.responses = []
22
         this.responses = []
18
         this.tags = []
23
         this.tags = []
19
 
24
 
21
         this.chatter = null
26
         this.chatter = null
22
     }
27
     }
23
     get isLoading() {
28
     get isLoading() {
24
-        return this._loading
29
+        return this._loading.value
25
     }
30
     }
26
     /**
31
     /**
27
      * Track login separate from complete-ess
32
      * Track login separate from complete-ess
30
      * @returns {boolean}
35
      * @returns {boolean}
31
      */
36
      */
32
     get isLoggedIn() {
37
     get isLoggedIn() {
33
-        return this.id.value != null
38
+        return this.id.value != null && this.isLoading == false
34
     }
39
     }
35
     /**
40
     /**
36
      * Combine questions retrieved from the database and
41
      * Combine questions retrieved from the database and
58
      * @returns {number} stored reactive id
63
      * @returns {number} stored reactive id
59
      */
64
      */
60
     async login(profileId, cb) {
65
     async login(profileId, cb) {
66
+        this._loading.value = true
67
+
61
         console.warn('logging in:', profileId)
68
         console.warn('logging in:', profileId)
62
         this.id.value = parseInt(profileId)
69
         this.id.value = parseInt(profileId)
63
 
70
 
64
-        this.setupChatter()
71
+        await this.getGroupings()
72
+
73
+        await this.setupChatter()
65
         this.setupToaster(cb)
74
         this.setupToaster(cb)
66
 
75
 
76
+        this._loading.value = false
77
+        console.warn('logged in:', this.isLoggedIn)
67
         return this.id.value
78
         return this.id.value
68
     }
79
     }
69
     logout() {
80
     logout() {
91
 
102
 
92
     async getResponses() {
103
     async getResponses() {
93
         try {
104
         try {
94
-            const responseList = await fetchResponsesByProfileId(this.id)
105
+            const responseList = await fetchResponsesByProfileId(this.id.value)
95
             this.setResponses(responseList)
106
             this.setResponses(responseList)
96
         } catch (err) {
107
         } catch (err) {
97
             console.error(err)
108
             console.error(err)
100
     setResponses(responses) {
111
     setResponses(responses) {
101
         this.responses = responses
112
         this.responses = responses
102
     }
113
     }
114
+
115
+    async getGroupings() {
116
+        try {
117
+            this.groupings = await fetchMembershipsByProfileId(this.id.value)
118
+        } catch (err) {
119
+            console.error(err)
120
+        }
121
+    }
103
     /**
122
     /**
104
      * For push notifications and chat
123
      * For push notifications and chat
105
      */
124
      */
106
     setupToaster(waveCb) {
125
     setupToaster(waveCb) {
107
         this.toaster = new StonkAlert(this.id.value, waveCb)
126
         this.toaster = new StonkAlert(this.id.value, waveCb)
108
     }
127
     }
109
-    setupChatter() {
128
+    async setupChatter() {
110
         this.chatter = new Chatter()
129
         this.chatter = new Chatter()
111
         // Use the reactive id object
130
         // Use the reactive id object
112
         const testAccountUUID = this.id.value
131
         const testAccountUUID = this.id.value
113
-        this.chatter.setup(testAccountUUID)
132
+        await this.chatter.setup(testAccountUUID, this.groupings)
114
     }
133
     }
115
-
116
-    
117
 }
134
 }
118
 
135
 
119
 const currentProfile = new Login()
136
 const currentProfile = new Login()

+ 1
- 18
frontend/src/services/survey.service.js Целия файл

16
     })
16
     })
17
 }
17
 }
18
 
18
 
19
-// TODO: Remove
20
-const saveSurveyByProfileId = async (surveyResponses, profileId) => {
21
-    surveyResponses.forEach(responseKeyIdwithVal => {
22
-        const keyId = responseKeyIdwithVal.response_key_id
23
-        const val = responseKeyIdwithVal.val
24
-        console.log(keyId, val)
25
-        // POST
26
-        // const myresponses = db.post(
27
-        //     `/profile/${profileId}/respond?response_key_id=${keyId}&val=${val}`,
28
-        // )
29
-        // return myresponses
30
-    })
31
-}
32
-
33
 const updateSurveyByProfileId = async (surveyResponses, profileId) => {
19
 const updateSurveyByProfileId = async (surveyResponses, profileId) => {
34
     surveyResponses.forEach(responseKeyIdwithVal => {
20
     surveyResponses.forEach(responseKeyIdwithVal => {
35
         const keyId = responseKeyIdwithVal.response_key_id
21
         const keyId = responseKeyIdwithVal.response_key_id
54
 }
40
 }
55
 
41
 
56
 const fetchResponsesByProfileId = async profileId => {
42
 const fetchResponsesByProfileId = async profileId => {
57
-    return await db.get(
58
-        `/profile/${profileId}/responses`,
59
-    )
43
+    return await db.get(`/profile/${profileId}/responses`)
60
 }
44
 }
61
 
45
 
62
 export {
46
 export {
63
     fetchQuestions,
47
     fetchQuestions,
64
-    saveSurveyByProfileId,
65
     updateSurveyByProfileId,
48
     updateSurveyByProfileId,
66
     scoreSurveyByProfileId,
49
     scoreSurveyByProfileId,
67
     fetchResponsesByProfileId,
50
     fetchResponsesByProfileId,

+ 8
- 6
frontend/src/utils/mixins.js Целия файл

3
         pid: {
3
         pid: {
4
             type: Number,
4
             type: Number,
5
             required: true,
5
             required: true,
6
-            validator: prop => typeof prop === 'number' || prop === null
6
+            validator: prop => typeof prop === 'number' || prop === null,
7
         },
7
         },
8
-    }
8
+    },
9
 }
9
 }
10
 
10
 
11
 const cardMixin = {
11
 const cardMixin = {
16
     }),
16
     }),
17
     watch: {
17
     watch: {
18
         /** Fetch the queue if pid changes */
18
         /** Fetch the queue if pid changes */
19
-        pid() { this.getCards() },
19
+        pid() {
20
+            this.getCards()
21
+        },
20
     },
22
     },
21
     async created() {
23
     async created() {
22
         await this.getCards()
24
         await this.getCards()
24
     methods: {
26
     methods: {
25
         _reformat(data, mapCb) {
27
         _reformat(data, mapCb) {
26
             return data.map(mapCb)
28
             return data.map(mapCb)
27
-        }
28
-    }
29
+        },
30
+    },
29
 }
31
 }
30
 
32
 
31
-export { pidMixin, cardMixin }
33
+export { pidMixin, cardMixin }

+ 89
- 0
frontend/src/views/ChatView.vue Целия файл

1
+<template lang="pug">
2
+main.view--chat
3
+    header 
4
+        h2 Chat Page
5
+ 
6
+    article(v-if="profile.isLoggedIn && target")
7
+        h3 {{ profile.id }} 
8
+            span chatting with: {{ target.profile_id }}
9
+        p subscriptions: {{ profile.chatter.subscriptions }}
10
+
11
+        ul(id="messages").w-flex.column
12
+            li(v-for="message, i in messages" class="pa1")
13
+                w-card.w-flex.row
14
+                    article
15
+                        p {{ message.message }}
16
+                    footer
17
+                        p {{ message.publisher }} | {{ message.timetoken }}
18
+                        w-button(class="my12" @click="openDrawer = i" text) setting
19
+                    w-drawer(v-model="openDrawer" absolute width="160px")
20
+                        p some settings things
21
+
22
+        input(v-model="toSend" @keyup.enter="sendMessage")
23
+        button(@click="sendMessage") send
24
+
25
+    p(v-else-if="profile.isLoggedIn && !target") No match found between profile {{ $route.params.tid }} and {{profile.id}}... 
26
+    p(v-else) Loading...
27
+
28
+    MainNav(@show-sidebar="$emit('show-sidebar')")
29
+</template>
30
+
31
+<script>
32
+import { currentProfile } from '../services'
33
+
34
+export default {
35
+    name: 'ProfileView',
36
+    data: () => ({
37
+        target: null,
38
+        toSend: '',
39
+        messages: [],
40
+        openDrawer: null,
41
+    }),
42
+    computed: {
43
+        profile: () => currentProfile,
44
+    },
45
+    watch: {
46
+        profile() {
47
+            this.loadTargetProfile()
48
+            currentProfile.chatter.setOnMessage(this._onMessage)
49
+        },
50
+    },
51
+    created() {
52
+        this.loadTargetProfile()
53
+        currentProfile.chatter.setOnMessage(this._onMessage)
54
+    },
55
+    methods: {
56
+        /**
57
+         * Pubnub message callback fires when message event
58
+         * is detected. We define is HERE because we need the
59
+         * component state and `this` context
60
+         */
61
+        _onMessage(e) {
62
+            if (!e.message) return
63
+            this.messages.push(e)
64
+        },
65
+        getGrouping() {
66
+            return currentProfile.groupings.find(
67
+                g => g.profile.profile_id == this.$route.params.tid,
68
+            )
69
+        },
70
+        sendMessage() {
71
+            const grouping = this.getGrouping()
72
+            currentProfile.chatter.publish(grouping.grouping_name, this.toSend)
73
+            this.toSend = ''
74
+        },
75
+        loadTargetProfile() {
76
+            try {
77
+                const grouping = this.getGrouping()
78
+                if (!grouping) {
79
+                    throw `no match found for ${currentProfile.id.value}`
80
+                }
81
+
82
+                this.target = grouping.profile
83
+            } catch (err) {
84
+                console.error(err)
85
+            }
86
+        },
87
+    },
88
+}
89
+</script>

Loading…
Отказ
Запис