Skip to content

Commit 82ace43

Browse files
authored
Merge pull request #25 from haystack/develop
Develop
2 parents eb344ab + 43cb9bc commit 82ace43

File tree

12 files changed

+494
-291
lines changed

12 files changed

+494
-291
lines changed

src/app.js

Lines changed: 166 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ function embedNbApp() {
137137
:thread-selected="threadSelected"
138138
:user="user"
139139
:activeClass="activeClass"
140+
@log-exp-spotlight="onLogExpSpotlight"
140141
@select-thread="onSelectThread"
141142
@unselect-thread="onUnselectThread"
142143
@hover-innotation="onHoverInnotation"
@@ -168,6 +169,7 @@ function embedNbApp() {
168169
:current-configs="currentConfigs"
169170
:show-sync-features="showSyncFeatures"
170171
:is-innotation-hover="isInnotationHover"
172+
@log-exp-spotlight="onLogExpSpotlight"
171173
@select-thread="onSelectThread"
172174
@unselect-thread="onUnselectThread"
173175
@hover-thread="onHoverThread"
@@ -224,6 +226,7 @@ function embedNbApp() {
224226
threadSelectedPane="allThreads"
225227
:show-sync-features="showSyncFeatures"
226228
:sync-config="syncConfig"
229+
@log-exp-spotlight="onLogExpSpotlight"
227230
@switch-class="onSwitchClass"
228231
@show-sync-features="onShowSyncFeatures"
229232
@toggle-highlights="onToggleHighlights"
@@ -329,7 +332,10 @@ function embedNbApp() {
329332
notificationsMuted: false,
330333
draggableNotificationsOpened: false,
331334
sidebarNotificationsOpened: false,
332-
playSoundNotification: true
335+
playSoundNotification: true,
336+
isExpSpotlight: false,
337+
expSpotlight: {},
338+
expSpotlightOrder: 0,
333339
},
334340
computed: {
335341
style: function () {
@@ -512,10 +518,61 @@ function embedNbApp() {
512518

513519
const config = { headers: { Authorization: 'Bearer ' + token }, params: { url: source, class: newActiveClass.id } }
514520

521+
// TODO: if instructor skip
522+
const expSpotlight = await axios.get('/api/exp/spotlight', config)
523+
if (expSpotlight.data) {
524+
console.log('has exp')
525+
this.expSpotlight.class = expSpotlight.data
526+
const isExpSpotlightStarted = await axios.get('/api/exp/spotlight/source', config)
527+
528+
if (isExpSpotlightStarted.data.length > 0) {
529+
console.log('started')
530+
this.isExpSpotlight = true
531+
532+
if (this.expSpotlight.class.control.includes(this.user.id)) {
533+
console.log('control')
534+
this.expSpotlight.group = 'control'
535+
this.currentConfigs.isShowIndicatorForSpotlitThread = false
536+
this.currentConfigs.isEmphasize = false
537+
this.currentConfigs.isMarginalia = false
538+
this.currentConfigs.isInnotation = false
539+
} else if (this.expSpotlight.class.treatment.includes(this.user.id)) {
540+
console.log('treatment')
541+
this.expSpotlight.group = 'treatment'
542+
const assignment = await axios.get('/api/exp/spotlight/source/assignment', config)
543+
this.expSpotlight.assignment = assignment.data
544+
} else {
545+
console.log('not in the exp')
546+
this.isExpSpotlight = false
547+
}
548+
549+
} else {
550+
console.log('Did not start')
551+
this.isExpSpotlight = false
552+
this.currentConfigs.isShowIndicatorForSpotlitThread = false
553+
this.currentConfigs.isEmphasize = false
554+
this.currentConfigs.isMarginalia = false
555+
this.currentConfigs.isInnotation = false
556+
}
557+
558+
} else {
559+
console.log('no exp')
560+
this.isExpSpotlight = false
561+
}
562+
515563
axios.get('/api/annotations/allUsers', config)
516564
.then(res => {
517565
this.users = res.data
518566
this.$set(this.user, 'role', this.users[this.user.id].role)
567+
this.onLogExpSpotlight('SESSION_START', 'NONE', 'NONE', false)
568+
569+
if (this.expSpotlight.class && this.users[this.user.id].role.toUpperCase() === 'INSTRUCTOR') {
570+
console.log('INSTRUCTOR in expSpotlight')
571+
this.currentConfigs.isShowIndicatorForSpotlitThread = true
572+
this.currentConfigs.isEmphasize = true
573+
this.currentConfigs.isMarginalia = false
574+
this.currentConfigs.isInnotation = false
575+
}
519576

520577
const configSessionStart = { headers: { Authorization: 'Bearer ' + token }, params: { url: this.sourceURL } }
521578
axios.post(`/api/spotlights/log/session/start`, {
@@ -734,14 +791,15 @@ function embedNbApp() {
734791
}
735792
return null
736793
},
737-
getAllAnnotations: function (source, newActiveClass) {
794+
getAllAnnotations: async function (source, newActiveClass) {
738795
this.stillGatheringThreads = true
739796
const token = localStorage.getItem("nb.user");
740797
const config = { headers: { Authorization: 'Bearer ' + token }, params: { url: source, class: newActiveClass.id, sectioned: !this.currentConfigs.isIgnoreSectionsInClass } }
741798

742799
axios.get('/api/annotations/new_annotation', config)
743-
.then(res => {
800+
.then(async res => {
744801
this.threads = []
802+
745803
for (const item of res.data.headAnnotations) {
746804
try {
747805
item.range = deserializeNbRange(item.range)
@@ -758,7 +816,86 @@ function embedNbApp() {
758816
comment.associatedNotification = newNotification
759817
}
760818
}
819+
820+
if (this.isExpSpotlight && this.expSpotlight.group === 'treatment') {
821+
if (!this.expSpotlight.assignment.annotations) {
822+
console.log('need to assign annotations')
823+
const highQualityAnnotations = []
824+
const otherAnnotations = []
825+
const pickedAnnotationsIds = []
826+
const blockPos = ['ABOVE', 'BELLOW', 'LEFT', 'RIGHT']
827+
828+
this.threads.forEach(t => {
829+
if (t.spotlight) {
830+
highQualityAnnotations.push(t.id)
831+
} else {
832+
otherAnnotations.push(t.id)
833+
}
834+
})
835+
836+
const highQualityAnnotations2 = JSON.parse(JSON.stringify(highQualityAnnotations))
837+
838+
while (pickedAnnotationsIds.length < this.expSpotlight.assignment.quantity / 2
839+
&& highQualityAnnotations.length > 0) {
840+
let index = Math.floor(Math.random() * highQualityAnnotations.length)
841+
const picked = highQualityAnnotations[index]
842+
if (!pickedAnnotationsIds.includes(picked)) {
843+
pickedAnnotationsIds.push(picked)
844+
highQualityAnnotations.splice(index, 1)
845+
}
846+
}
847+
848+
while (pickedAnnotationsIds.length < this.expSpotlight.assignment.quantity
849+
&& otherAnnotations.length > 0) {
850+
let index = Math.floor(Math.random() * otherAnnotations.length)
851+
const picked = otherAnnotations[index]
852+
if (!pickedAnnotationsIds.includes(picked)) {
853+
pickedAnnotationsIds.push(picked)
854+
otherAnnotations.splice(index, 1)
855+
}
856+
}
857+
858+
const pickedAnnotations = pickedAnnotationsIds.map(id => {
859+
return {
860+
id: id,
861+
type: this.expSpotlight.assignment.type == 'BLOCK' ? blockPos[Math.floor(Math.random() * blockPos.length)] : this.expSpotlight.assignment.type,
862+
highQuality: highQualityAnnotations2.includes(id)
863+
}
864+
})
865+
866+
const assignmentReqconfig = { headers: { Authorization: 'Bearer ' + token }, params: { assignment: this.expSpotlight.assignment.id } }
867+
await axios.post('/api/exp/spotlight/source/assignment/annotations', pickedAnnotations, assignmentReqconfig)
868+
this.expSpotlight.assignment.annotations = pickedAnnotations
869+
} else {
870+
this.expSpotlight.assignment.annotations = JSON.parse(this.expSpotlight.assignment.annotations)
871+
}
872+
873+
const assignmentAnnotationsIds = this.expSpotlight.assignment.annotations.map(a => a.id)
874+
console.log('Has assign annotations')
875+
876+
this.threads.forEach(t => {
877+
if (assignmentAnnotationsIds.includes(t.id)) {
878+
for (const annotation of this.expSpotlight.assignment.annotations) {
879+
if (annotation.id === t.id) {
880+
t.spotlight = {
881+
type: annotation.type,
882+
highQuality: annotation.highQuality
883+
}
884+
break
885+
}
886+
}
887+
} else {
888+
t.spotlight = null
889+
}
890+
})
891+
} else if (this.isExpSpotlight && this.expSpotlight.group === 'control') {
892+
this.threads.forEach(t => {
893+
t.spotlight = null
894+
})
895+
}
896+
761897
this.stillGatheringThreads = false
898+
762899
let link = window.location.hash.match(/^#nb-comment-(.+$)/)
763900
if (link) {
764901
let id = link[1]
@@ -1066,6 +1203,8 @@ function embedNbApp() {
10661203
},
10671204
onSessionEnd: async function () {
10681205
if (this.activeClass.id) {
1206+
this.onLogExpSpotlight('SESSION_END', 'NONE', 'NONE', false)
1207+
10691208
const token = localStorage.getItem("nb.user");
10701209
const config = { headers: { Authorization: 'Bearer ' + token }, params: { url: this.sourceURL } }
10711210
await axios.post(`/api/spotlights/log/session/end`, {
@@ -1108,6 +1247,30 @@ function embedNbApp() {
11081247
minUpvotes: 0
11091248
}
11101249
this.showHighlights = true
1250+
},
1251+
onLogExpSpotlight: async function (event = 'NONE', initiator = 'NONE', type = 'NONE', highQuality = false, annotationId = null, annotation_replies_count = 0) {
1252+
if (this.isExpSpotlight) {
1253+
console.log(`onLogExpSpotlight \nevent: ${event} \ninitiator: ${initiator} \ntype: ${type} \nhighQuality: ${highQuality} \nannotationId: ${annotationId} \nannotation_replies_count: ${annotation_replies_count}`)
1254+
const token = localStorage.getItem("nb.user");
1255+
const config = { headers: { Authorization: 'Bearer ' + token }, params: { url: this.sourceURL } }
1256+
1257+
axios.post(`/api/exp/spotlight/log`, {
1258+
class_id: this.activeClass.id,
1259+
annotation_id: annotationId,
1260+
event: event,
1261+
type: type,
1262+
order: this.expSpotlightOrder,
1263+
initiator: initiator,
1264+
highQuality: highQuality,
1265+
source_annotations_count: this.threads.length,
1266+
annotation_replies_count: annotation_replies_count,
1267+
exp_group: this.expSpotlight.group.toUpperCase(),
1268+
exp_type: this.expSpotlight.assignment ? this.expSpotlight.assignment.type : 'NONE',
1269+
exp_quantity: this.expSpotlight.assignment ? this.expSpotlight.assignment.quantity : 0,
1270+
}, config)
1271+
1272+
this.expSpotlightOrder = this.expSpotlightOrder + 1
1273+
}
11111274
}
11121275
},
11131276
components: {

src/components/NbSidebar.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
:activeClass="activeClass"
5353
:user="user"
5454
:show-sync-features="showSyncFeatures"
55+
@log-exp-spotlight="onLogExpSpotlight"
5556
@toggle-highlights="onToggleHighlights"
5657
@select-thread="onSelectThread"
5758
@hover-thread="onHoverThread"
@@ -85,6 +86,7 @@
8586
:current-configs="currentConfigs"
8687
:activeClass="activeClass"
8788
:thread-view-initiator="threadViewInitiator"
89+
@log-exp-spotlight="onLogExpSpotlight"
8890
@edit-comment="onEditComment"
8991
@delete-comment="onDeleteComment"
9092
@draft-reply="onDraftReply"
@@ -412,7 +414,7 @@ export default {
412414
seenByMe: true,
413415
})
414416
let source = this.sourceUrl.length > 0 ? this.sourceUrl : window.location.href.split('?')[0]
415-
comment.submitAnnotation(this.activeClass.id, source)
417+
comment.submitAnnotation(this.activeClass.id, source, this.threadViewInitiator, data.replyToComment, this.activeClass, this.user, this.onLogExpSpotlight)
416418
if (data.replyToComment) {
417419
data.replyToComment.children.push(comment)
418420
}
@@ -444,7 +446,7 @@ export default {
444446
seenByMe: true
445447
})
446448
let source = this.sourceUrl.length > 0 ? this.sourceUrl : window.location.href.split('?')[0]
447-
comment.submitAnnotation(this.activeClass.id, source, this.threadViewInitiator, this.replyToComment, this.activeClass, this.user)
449+
comment.submitAnnotation(this.activeClass.id, source, this.threadViewInitiator, this.replyToComment, this.activeClass, this.user, this.onLogExpSpotlight)
448450
if (this.draftRange) {
449451
this.$emit('new-thread', comment)
450452
} else if (this.replyToComment) {
@@ -503,6 +505,9 @@ export default {
503505
},
504506
onOpenSidebarNotifications: function () {
505507
this.$emit('open-sidebar-notifications')
508+
},
509+
onLogExpSpotlight: async function (event = 'NONE', initiator = 'NONE', type = 'NONE', highQuality = false, annotationId = null, annotation_replies_count = 0) {
510+
this.$emit('log-exp-spotlight', event, initiator, type, highQuality, annotationId, annotation_replies_count)
506511
}
507512
},
508513
components: {

src/components/highlights/NbHighlight.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export default {
170170
if (this.threadsHovered.includes(this.thread)) {
171171
return 'fill: rgb(1, 99, 255); fill-opacity: 0.12; cursor: pointer;'
172172
}
173-
if (this.thread.spotlight && this.thread.spotlight.type === 'EM' && this.isEmphasize) {
173+
if (this.thread.spotlight && this.thread.spotlight.type === 'EM' && this.currentConfigs.isEmphasize) {
174174
return 'stroke: lime; fill: lime; fill-opacity: 0.3; stroke-opacity: 0.9; stroke-dasharray: 1,1; stroke-width: 2px; cursor: pointer;'
175175
}
176176
if (this.showTypingActivityAnimation) { // if typing, show a pink outline color
@@ -250,6 +250,9 @@ export default {
250250
type = this.thread.spotlight.type.toUpperCase()
251251
}
252252
253+
const location = this.currentConfigs.isEmphasize && this.thread.spotlight && this.thread.spotlight.type === 'EM' ? 'SPOTLIGHT' : 'HIGHLIGHT'
254+
this.$emit('log-exp-spotlight', 'CLICK', location, this.thread.spotlight ? this.thread.spotlight.type : 'NONE', this.thread.spotlight ? this.thread.spotlight.highQuality : false, this.thread.id, this.thread.countAllReplies())
255+
253256
const source = window.location.pathname === '/nb_viewer.html' ? window.location.href : window.location.origin + window.location.pathname
254257
const token = localStorage.getItem("nb.user");
255258
const config = { headers: { Authorization: 'Bearer ' + token }, params: { url: source } }
@@ -259,7 +262,7 @@ export default {
259262
type: type,
260263
annotation_id: this.thread.id,
261264
class_id: this.activeClass.id,
262-
role: this.user.role.toUpperCase()
265+
role: this.user.role.toUpperCase()
263266
}, config)
264267
265268
this.logSyncClick()

src/components/highlights/NbHighlights.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
:activeClass="activeClass"
1212
:current-configs="currentConfigs"
1313
:show-sync-features="showSyncFeatures"
14+
@log-exp-spotlight="onLogExpSpotlight"
1415
@select-thread="onSelectThread"
1516
@hover-thread="$emit('hover-thread',thread)"
1617
@unhover-thread="$emit('unhover-thread',thread)"
@@ -89,6 +90,9 @@ export default {
8990
}
9091
9192
this.$emit('unselect-thread', null)
93+
},
94+
onLogExpSpotlight: async function (event = 'NONE', initiator = 'NONE', type = 'NONE', highQuality = false, annotationId = null, annotation_replies_count = 0) {
95+
this.$emit('log-exp-spotlight', event, initiator, type, highQuality, annotationId, annotation_replies_count)
9296
}
9397
},
9498
mounted: function () {

src/components/list/ListRow.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ export default {
126126
},
127127
methods: {
128128
onClick: function () {
129+
this.$emit('log-exp-spotlight', 'CLICK', 'LIST', this.thread.spotlight ? this.thread.spotlight.type : 'NONE', this.thread.spotlight ? this.thread.spotlight.highQuality : false, this.thread.id, this.thread.countAllReplies())
130+
129131
const source = window.location.pathname === '/nb_viewer.html' ? window.location.href : window.location.origin + window.location.pathname
130132
const token = localStorage.getItem("nb.user");
131133
const config = { headers: { Authorization: 'Bearer ' + token }, params: { url: source } }

0 commit comments

Comments
 (0)