Quellcode durchsuchen

:gear: more tweaking mock data for onboarding | filtering out profile 45 for testing onboarding | adjusting services to error handle better

tags/0.0.3^2
j vor 3 Jahren
Ursprung
Commit
0fc109fd0b

+ 1
- 0
backend/db/data-generator/config.json Datei anzeigen

2
     "mockOutputPath": "./db/generated",
2
     "mockOutputPath": "./db/generated",
3
     "magic": 1000,
3
     "magic": 1000,
4
     "total": 100,
4
     "total": 100,
5
+    "ignore": [45],
5
     "batchSize": 10,
6
     "batchSize": 10,
6
     "percentageOfSeekers": 90,
7
     "percentageOfSeekers": 90,
7
     "scoreVals": [1, 2, 3, 4, 5, 6, 7],
8
     "scoreVals": [1, 2, 3, 4, 5, 6, 7],

+ 4
- 4
backend/db/data-generator/mock.js Datei anzeigen

226
     ],
226
     ],
227
     messages: [],
227
     messages: [],
228
     match_queues: [
228
     match_queues: [
229
-        { match_queue_id: 1, profile_id: 45, target_id: 62, is_deleted: false },
230
-        { match_queue_id: 2, profile_id: 62, target_id: 45, is_deleted: false },
229
+        { match_queue_id: 1, profile_id: 47, target_id: 62, is_deleted: false },
230
+        { match_queue_id: 2, profile_id: 62, target_id: 47, is_deleted: false },
231
         { match_queue_id: 3, profile_id: 62, target_id: 46, is_deleted: false },
231
         { match_queue_id: 3, profile_id: 62, target_id: 46, is_deleted: false },
232
         { match_queue_id: 4, profile_id: 46, target_id: 62, is_deleted: false },
232
         { match_queue_id: 4, profile_id: 46, target_id: 62, is_deleted: false },
233
-        { match_queue_id: 5, profile_id: 45, target_id: 46, is_deleted: false },
234
-        { match_queue_id: 6, profile_id: 46, target_id: 45, is_deleted: false },
233
+        { match_queue_id: 5, profile_id: 47, target_id: 46, is_deleted: false },
234
+        { match_queue_id: 6, profile_id: 46, target_id: 48, is_deleted: false },
235
         { match_queue_id: 7, profile_id: 46, target_id: 44, is_deleted: false },
235
         { match_queue_id: 7, profile_id: 46, target_id: 44, is_deleted: false },
236
         { match_queue_id: 8, profile_id: 46, target_id: 43, is_deleted: false },
236
         { match_queue_id: 8, profile_id: 46, target_id: 43, is_deleted: false },
237
         { match_queue_id: 9, profile_id: 46, target_id: 42, is_deleted: false },
237
         { match_queue_id: 9, profile_id: 46, target_id: 42, is_deleted: false },

+ 2
- 2
backend/db/dataSort.js Datei anzeigen

1
-const dataSort = (table, id) => { return table.sort((a,b) => {return a[`${id}`] < b[`${id}`]})}
1
+const dataSort = (table, id) => table.sort((a, b) => a[`${id}`] < b[`${id}`])
2
 
2
 
3
-module.exports = dataSort
3
+module.exports = dataSort

+ 6
- 6
backend/db/seeds/02-profiles.js Datei anzeigen

1
 const mock = require('../data-generator/mock')
1
 const mock = require('../data-generator/mock')
2
 const fs = require('fs')
2
 const fs = require('fs')
3
-const dataSort = require ('../dataSort')
4
-const { batchSize } = require('../data-generator/config.json')
5
-
3
+const dataSort = require('../dataSort')
4
+const { batchSize, ignore } = require('../data-generator/config.json')
6
 
5
 
7
 let profiles = []
6
 let profiles = []
8
 const generatedDataPath = './db/generated'
7
 const generatedDataPath = './db/generated'
9
 let fileNames = fs.readdirSync(generatedDataPath)
8
 let fileNames = fs.readdirSync(generatedDataPath)
10
 for (let name of fileNames) {
9
 for (let name of fileNames) {
11
     const data = require(`../generated/${name}`)
10
     const data = require(`../generated/${name}`)
12
-    if(name[0] == '_') {
11
+    if (name[0] == '_') {
13
         profiles = [...profiles, ...data.profiles]
12
         profiles = [...profiles, ...data.profiles]
14
     }
13
     }
15
 }
14
 }
16
-// sort data
17
-profiles = dataSort(profiles, 'profile_id')
18
 
15
 
16
+profiles = dataSort(profiles, 'profile_id').filter(
17
+    profile => !ignore.includes(profile.profile_id),
18
+)
19
 
19
 
20
 exports.seed = async knex => {
20
 exports.seed = async knex => {
21
     await knex('profiles').del()
21
     await knex('profiles').del()

+ 11
- 6
backend/db/seeds/04-responses.js Datei anzeigen

1
 const mock = require('../data-generator/mock')
1
 const mock = require('../data-generator/mock')
2
 const fs = require('fs')
2
 const fs = require('fs')
3
-const dataSort = require ('../dataSort')
4
-const { batchSize } = require('../data-generator/config.json')
3
+const dataSort = require('../dataSort')
4
+const { batchSize, ignore } = require('../data-generator/config.json')
5
 
5
 
6
 let responses = []
6
 let responses = []
7
 const generatedDataPath = './db/generated'
7
 const generatedDataPath = './db/generated'
8
 let fileNames = fs.readdirSync(generatedDataPath)
8
 let fileNames = fs.readdirSync(generatedDataPath)
9
 for (let name of fileNames) {
9
 for (let name of fileNames) {
10
     const data = require(`../generated/${name}`)
10
     const data = require(`../generated/${name}`)
11
-    if(name[0] == '_') {
11
+    if (name[0] == '_') {
12
         responses = [...responses, ...data.responses]
12
         responses = [...responses, ...data.responses]
13
     }
13
     }
14
 }
14
 }
15
 
15
 
16
-// sort data
17
-responses = dataSort(responses, 'response_id')
16
+/**
17
+ * Prevent seeding responses for
18
+ * profile ids so we can test oboarding
19
+ */
20
+responses = dataSort(responses, 'response_id').filter(
21
+    response => !ignore.includes(response.profile_id),
22
+)
18
 
23
 
19
 exports.seed = async knex => {
24
 exports.seed = async knex => {
20
     await knex('responses').del()
25
     await knex('responses').del()
23
     for (let i = 1; i <= len; i += 1) {
28
     for (let i = 1; i <= len; i += 1) {
24
         responsesToPush.push(responses.shift())
29
         responsesToPush.push(responses.shift())
25
         if (i % batchSize === 0 || i > responses.length) {
30
         if (i % batchSize === 0 || i > responses.length) {
26
-            // await knex('responses').insert(responsesToPush)
31
+            await knex('responses').insert(responsesToPush)
27
             responsesToPush = []
32
             responsesToPush = []
28
         }
33
         }
29
     }
34
     }

+ 1
- 1
frontend/src/App.vue Datei anzeigen

17
 import { surveyFactory } from './utils'
17
 import { surveyFactory } from './utils'
18
 
18
 
19
 const DEV_MODE = import.meta.env.VITE_DEV == 'true'
19
 const DEV_MODE = import.meta.env.VITE_DEV == 'true'
20
-const DEV_PID = 45
20
+const DEV_PID = 46
21
 
21
 
22
 export default {
22
 export default {
23
     components: { TopNav, SideBar },
23
     components: { TopNav, SideBar },

+ 14
- 8
frontend/src/components/NamePlate.vue Datei anzeigen

1
 <template lang="pug">
1
 <template lang="pug">
2
 .name-plate.xs12.w-flex.justify-center
2
 .name-plate.xs12.w-flex.justify-center
3
-    section(v-if="pid" :class="{ box: !isList }")
4
-        router-link(:to="`/profile/${pid}`" disabled)
3
+    section(:class='{ box: !isList }' v-if='pid')
4
+        router-link(:to='`/profile/${pid}`' disabled)
5
             h1.text-capitalize {{ name }}
5
             h1.text-capitalize {{ name }}
6
                 span O
6
                 span O
7
-            p.text-capitalize {{role}}&nbsp;
8
-                span.text-capitalize(v-if="isList")
9
-                    span.text-capitalize Registered Nurse | Los Angeles, CA.
10
-            p.text-capitalize(v-if="!isList") {{ pronouns }}&nbsp;
11
-                span.text-capitalize | ethnicity
7
+            p.text-capitalize {{ role }}&nbsp;
8
+                span.text-capitalize(v-if='isList')
9
+                    span.text-capitalize | {{ locale }}
10
+            p.text-capitalize(v-if='!isList') {{ pronouns }}
12
 </template>
11
 </template>
13
 
12
 
14
 <script>
13
 <script>
22
             type: String,
21
             type: String,
23
             required: true,
22
             required: true,
24
         },
23
         },
24
+        role: {
25
+            type: String,
26
+            required: true,
27
+        },
28
+        locale: {
29
+            type: String,
30
+            required: true,
31
+        },
25
         pronouns: {
32
         pronouns: {
26
             type: String,
33
             type: String,
27
             required: true,
34
             required: true,
32
             default: true,
39
             default: true,
33
         },
40
         },
34
     },
41
     },
35
-    data: () => ({}),
36
 }
42
 }
37
 </script>
43
 </script>
38
 <style lang="sass">
44
 <style lang="sass">

+ 2
- 0
frontend/src/components/ProfileCard.vue Datei anzeigen

2
 w-card.profile-card-list--card.xs12
2
 w-card.profile-card-list--card.xs12
3
     header.xs12.w-flex.column.center
3
     header.xs12.w-flex.column.center
4
         NamePlate(
4
         NamePlate(
5
+            :ethnicity='card.ethnicity'
5
             :is-list='isList'
6
             :is-list='isList'
6
             :is-paired='isPaired'
7
             :is-paired='isPaired'
8
+            :locale='card.locale'
7
             :name='card.name'
9
             :name='card.name'
8
             :pid='card.pid'
10
             :pid='card.pid'
9
             :pronouns='card.pronouns'
11
             :pronouns='card.pronouns'

+ 5
- 27
frontend/src/components/ProfileCardList.vue Datei anzeigen

12
 
12
 
13
 <script setup>
13
 <script setup>
14
 import { ref } from 'vue'
14
 import { ref } from 'vue'
15
-import { useRouter } from 'vue-router'
16
-import {
17
-    updateQueueByProfileId,
18
-    postMembershipByProfileId,
19
-    currentProfile,
20
-} from '../services'
15
+import { currentProfile } from '../services'
16
+import { cardAspects } from '../entities'
21
 import ProfileCard from './ProfileCard.vue'
17
 import ProfileCard from './ProfileCard.vue'
22
 
18
 
23
-class Aspect {
24
-    constructor({ name, labels, percentage = 50 }) {
25
-        this.name = name
26
-        this.labels = labels
27
-        this.percentage = percentage
28
-    }
29
-}
30
-const aspects = ref([
31
-    new Aspect({ name: 'creativity', labels: ['creative', 'methodical'] }),
32
-    new Aspect({ name: 'dynamism', labels: ['dynamic', 'ordered'] }),
33
-    new Aspect({ name: 'precision', labels: ['precise', 'resourceful'] }),
34
-    new Aspect({ name: 'vision', labels: ['visionary', 'implementer'] }),
35
-    new Aspect({ name: 'focus', labels: ['big picture', 'focused'] }),
36
-    new Aspect({ name: 'attention', labels: ['guided', 'self-managed'] }),
37
-])
38
-
39
-const router = useRouter()
40
-const emit = defineEmits(['reload'])
19
+const aspects = ref(cardAspects)
41
 
20
 
42
 const props = defineProps({
21
 const props = defineProps({
43
     cards: {
22
     cards: {
48
                 name: 'Full Name',
27
                 name: 'Full Name',
49
                 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:*',
28
                 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:*',
50
                 metadata: { age: '21', rawMetadata: 'Some Text Here!' },
29
                 metadata: { age: '21', rawMetadata: 'Some Text Here!' },
30
+                role: 'more filler',
31
+                ethnicity: 'some background',
51
             },
32
             },
52
         ],
33
         ],
53
     },
34
     },
54
-    isGrid: {
55
-        type: Boolean,
56
-    },
57
 })
35
 })
58
 
36
 
59
 /**
37
 /**

+ 36
- 34
frontend/src/entities/card/card.js Datei anzeigen

4
     'Hello! My name is L.L. and I am a nurse from New York. I have been in the healthcare industry for over 6 years.'
4
     'Hello! My name is L.L. and I am a nurse from New York. I have been in the healthcare industry for over 6 years.'
5
 
5
 
6
 class SummaryGroup {
6
 class SummaryGroup {
7
-    constructor () {
7
+    constructor() {
8
         this.about = {
8
         this.about = {
9
             tab: null,
9
             tab: null,
10
             matchPerc: null,
10
             matchPerc: null,
40
 }
40
 }
41
 
41
 
42
 class Aspect {
42
 class Aspect {
43
-    constructor ({ name, labels, percentage = 50 }) {
43
+    constructor({ name, labels, percentage = 50 }) {
44
         this.name = name
44
         this.name = name
45
         this.labels = labels
45
         this.labels = labels
46
         this.percentage = percentage
46
         this.percentage = percentage
47
     }
47
     }
48
 }
48
 }
49
+const cardAspects = [
50
+    new Aspect({
51
+        name: 'creativity',
52
+        labels: ['creative', 'methodical'],
53
+    }),
54
+    new Aspect({
55
+        name: 'dynamism',
56
+        labels: ['dynamic', 'ordered'],
57
+    }),
58
+    new Aspect({
59
+        name: 'precision',
60
+        labels: ['precise', 'resourceful'],
61
+    }),
62
+    new Aspect({
63
+        name: 'vision',
64
+        labels: ['visionary', 'implementer'],
65
+    }),
66
+    new Aspect({
67
+        name: 'focus',
68
+        labels: ['big picture', 'focused'],
69
+    }),
70
+    new Aspect({
71
+        name: 'attention',
72
+        labels: ['guided', 'self-managed'],
73
+    }),
74
+]
49
 
75
 
50
 /**
76
 /**
51
  * Class representing a profile card
77
  * Class representing a profile card
54
  * card facade
80
  * card facade
55
  */
81
  */
56
 class Card {
82
 class Card {
57
-    constructor ({ pid, name, role }) {
83
+    constructor({ pid, name, email, role }) {
58
         this.pid = pid
84
         this.pid = pid
59
 
85
 
60
         /**  Fields */
86
         /**  Fields */
61
         this.name = name
87
         this.name = name
62
 
88
 
63
-        this.role = role ? role : null
89
+        this.role = role ? role : 'registered nurse'
64
 
90
 
65
         this.presence = null
91
         this.presence = null
66
         this.urgency = null
92
         this.urgency = null
67
         this.pronouns = 'she/her/hers'
93
         this.pronouns = 'she/her/hers'
68
-        this.ethinicity = null
69
-        this.locale = null
70
-        this.email = null
94
+        this.ethinicity = 'something'
95
+        this.locale = 'los angeles ca'
96
+        this.email = email
71
 
97
 
72
         this.images = []
98
         this.images = []
73
         this.tags = []
99
         this.tags = []
74
 
100
 
75
         this.summary = new SummaryGroup()
101
         this.summary = new SummaryGroup()
76
 
102
 
77
-        this.aspects = [
78
-            new Aspect({
79
-                name: 'creativity',
80
-                labels: ['creative', 'methodical'],
81
-            }),
82
-            new Aspect({
83
-                name: 'dynamism',
84
-                labels: ['dynamic', 'ordered'],
85
-            }),
86
-            new Aspect({
87
-                name: 'precision',
88
-                labels: ['precise', 'resourceful'],
89
-            }),
90
-            new Aspect({
91
-                name: 'vision',
92
-                labels: ['visionary', 'implementer'],
93
-            }),
94
-            new Aspect({
95
-                name: 'focus',
96
-                labels: ['big picture', 'focused'],
97
-            }),
98
-            new Aspect({
99
-                name: 'attention',
100
-                labels: ['guided', 'self-managed'],
101
-            }),
102
-        ]
103
+        this.aspects = cardAspects
103
 
104
 
104
         return this
105
         return this
105
     }
106
     }
109
     const c = new Card({
110
     const c = new Card({
110
         pid: profile.profile_id,
111
         pid: profile.profile_id,
111
         name: profile.user_name,
112
         name: profile.user_name,
113
+        email: profile.user_email,
112
         role: profile?.profile_prefs?.role?.val,
114
         role: profile?.profile_prefs?.role?.val,
113
     })
115
     })
114
 
116
 
128
     }
130
     }
129
     return c
131
     return c
130
 }
132
 }
131
-export { Card, makeCardFromProfile }
133
+export { Card, makeCardFromProfile, cardAspects }

+ 1
- 1
frontend/src/entities/profile/profile.js Datei anzeigen

36
          * TODO: Send validate.error to logging error handler
36
          * TODO: Send validate.error to logging error handler
37
          */
37
          */
38
         if (validate.error) {
38
         if (validate.error) {
39
-            console.error(`error: ${validate.error} - ${this.type} validation`)
39
+            console.error(`[Profile Entitiy error]: ${validate.error}`)
40
         }
40
         }
41
 
41
 
42
         /** validate(this) always returns something so force it to a bool */
42
         /** validate(this) always returns something so force it to a bool */

+ 2
- 2
frontend/src/router/index.js Datei anzeigen

73
         path: `/settings`,
73
         path: `/settings`,
74
         component: HomeView,
74
         component: HomeView,
75
         name: `SettingsView`,
75
         name: `SettingsView`,
76
-        meta: { requiresAuth: false, requiresCompleteProfile: false },
76
+        meta: { requiresAuth: true, requiresCompleteProfile: true },
77
     },
77
     },
78
     {
78
     {
79
         path: `/search`,
79
         path: `/search`,
80
         component: HomeView,
80
         component: HomeView,
81
         name: `SearchView`,
81
         name: `SearchView`,
82
-        meta: { requiresAuth: false, requiresCompleteProfile: false },
82
+        meta: { requiresAuth: true, requiresCompleteProfile: true },
83
     },
83
     },
84
 ]
84
 ]
85
 
85
 

+ 27
- 9
frontend/src/services/login.service.js Datei anzeigen

4
     updateQueueByProfileId,
4
     updateQueueByProfileId,
5
     fetchMembershipsByProfileId,
5
     fetchMembershipsByProfileId,
6
     fetchResponsesByProfileId,
6
     fetchResponsesByProfileId,
7
+    fetchProfileByProfileId,
7
     Chatter,
8
     Chatter,
8
     StonkAlert,
9
     StonkAlert,
9
 } from '../services/index.js'
10
 } from '../services/index.js'
17
     constructor() {
18
     constructor() {
18
         this._loading = ref(true)
19
         this._loading = ref(true)
19
 
20
 
21
+        // Profile entity instance for self
22
+        this._profile = null
20
         // Make reactive with vue observer
23
         // Make reactive with vue observer
21
         this.id = ref(null)
24
         this.id = ref(null)
22
 
25
 
77
      */
80
      */
78
     async login(profileId, cb) {
81
     async login(profileId, cb) {
79
         this._loading.value = true
82
         this._loading.value = true
80
-
83
+        // First check if profile exists
81
         console.warn('[Login Service warn]: Logging in:', profileId)
84
         console.warn('[Login Service warn]: Logging in:', profileId)
82
-        this.id.value = parseInt(profileId)
83
 
85
 
86
+        // TODO: You can probably use this call to get responses, groupings and tags
87
+        this._profile = await fetchProfileByProfileId(profileId)
88
+        this.id.value = this._profile.profile_id
89
+
90
+        if (!this.id.value) {
91
+            console.error(
92
+                `[Login Service error]: No profile found for profile_id: ${profileId}`,
93
+            )
94
+        }
95
+
96
+        // Then grab groupings and queue for display
84
         await this.getGroupings()
97
         await this.getGroupings()
85
         await this.getQueue()
98
         await this.getQueue()
86
 
99
 
87
-        await this.setupChatter()
100
+        // Then hook into chat services
101
+        try {
102
+            await this.setupChatter()
103
+            console.warn(
104
+                `[Login Service warn]: ${profileId} subscribed to:`,
105
+                this.chatter.subscriptions,
106
+            )
107
+        } catch (err) {
108
+            console.error(err)
109
+        }
110
+        // Finally setup notifications and sse handling
88
         this.setupToaster(cb)
111
         this.setupToaster(cb)
89
-
90
-        this._loading.value = false
91
         console.warn('[Login Service warn]: Login SUCCESSFUL')
112
         console.warn('[Login Service warn]: Login SUCCESSFUL')
92
-        console.warn(
93
-            `[Login Service warn]: ${profileId} subscribed to:`,
94
-            this.chatter.subscriptions,
95
-        )
113
+        this._loading.value = false
96
         return this.id.value
114
         return this.id.value
97
     }
115
     }
98
     logout() {
116
     logout() {

+ 10
- 1
frontend/src/services/profile.service.js Datei anzeigen

26
 }
26
 }
27
 
27
 
28
 const fetchProfileByProfileId = async profileId => {
28
 const fetchProfileByProfileId = async profileId => {
29
-    const profile = await db.get(`/profile/${profileId}`)
29
+    let profile
30
+    try {
31
+        const profileData = await db.get(`/profile/${profileId}`)
32
+        profile = new Profile(profileData)
33
+        if (!profile.isValid()) {
34
+            throw '[Profile Service error]: Invalid or incomplete profile returned.'
35
+        }
36
+    } catch (err) {
37
+        console.error(err)
38
+    }
30
     return profile
39
     return profile
31
 }
40
 }
32
 
41
 

Laden…
Abbrechen
Speichern