• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zooniverse / front-end-monorepo / 12353075782

16 Dec 2024 12:53PM UTC coverage: 77.332% (-0.06%) from 77.39%
12353075782

Pull #6568

github

web-flow
Merge f434245be into 23916ae72
Pull Request #6568: VV - Implement Classifier Annotation Model

10732 of 16063 branches covered (66.81%)

Branch coverage included in aggregate %.

36 of 42 new or added lines in 9 files covered. (85.71%)

9 existing lines in 3 files now uncovered.

16792 of 19529 relevant lines covered (85.98%)

411.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.87
/packages/lib-classifier/src/store/subjects/Subject/Subject.js
1
import asyncStates from '@zooniverse/async-states'
1✔
2
import { getRoot, getSnapshot, tryReference, types } from 'mobx-state-tree'
1✔
3
import Resource from '@store/Resource'
1✔
4
import { createLocationCounts, subjectsSeenThisSession, subjectViewers } from '@helpers'
1✔
5
import StepHistory from './StepHistory'
1✔
6
import SubjectLocation from './SubjectLocation'
1✔
7
import MachineLearntReductions from './MachineLearntReductions'
1✔
8
import TranscriptionReductions from './TranscriptionReductions'
6✔
9

10
const CaesarReductions = types.union(MachineLearntReductions, TranscriptionReductions)
1✔
11

12
const Subject = types
1✔
13
  .model('Subject', {
14
    already_seen: types.optional(types.boolean, false),
15
    favorite: types.optional(types.boolean, false),
16
    finished_workflow: types.optional(types.boolean, false),
17
    locations: types.array(SubjectLocation),
18
    metadata: types.frozen({}),
19
    retired: types.optional(types.boolean, false),
20
    selected_at: types.maybe(types.string),
21
    selection_state: types.maybe(types.string),
22
    shouldDiscuss: types.maybe(types.frozen()),
23
    stepHistory: types.maybe(StepHistory),
24
    user_has_finished_workflow: types.optional(types.boolean, false),
25
    caesarReductions: types.maybeNull(CaesarReductions),
26
  })
27

28
  .volatile(self => ({
3,178✔
29
    caesarReductionsLoadedForStep: types.array(types.boolean)
30
  }))
31

32
  .postProcessSnapshot(snapshot => {
33
    const newSnapshot = Object.assign({}, snapshot)
6,846✔
34
    delete newSnapshot.stepHistory
6,846✔
35
    return newSnapshot
6,846✔
36
  })
37

38
  .views(self => ({
3,178✔
39
    get talkURL() {
40
      if (self.project) {
11✔
41
        const projectSlug = self.project.slug
11✔
42
        const { origin } = window.location
11✔
43
        return `${origin}/projects/${projectSlug}/talk/subjects/${self.id}`
11✔
44
      }
45

46
      return ''
×
47
    },
48

49
    get viewer() {
50
      let viewer = null
39✔
51
      const counts = createLocationCounts(getSnapshot(self))
39✔
52
      if (self.workflow) {
39✔
53
        const { configuration } = self.workflow
39✔
54

55
        // If the Workflow configuration specifies a subject viewer, use that.
56
        // Otherwise, take a guess using the Subject.
57

58
        viewer = configuration.viewerType
39✔
59

60
        // Volumetric Viewer is set at the Project level
61
        if (!viewer && self.project?.isVolumetricViewer)
39!
NEW
62
          viewer = subjectViewers.volumetric
×
63
      
64
        if (!viewer && counts.total === 1) {
39✔
65
          if (counts.images) {
30✔
66
            viewer = subjectViewers.singleImage
25✔
67
          }
68
          if (counts.videos) {
30✔
69
            viewer = subjectViewers.singleVideo
1✔
70
          }
71
          if (counts.json) {
30✔
72
            viewer = subjectViewers.jsonData
1✔
73
          }
74
          if (counts.text) {
30✔
75
            viewer = subjectViewers.singleText
3✔
76
          }
77
        }
78

79
        if (!viewer && counts.total > 1) {
39✔
80
          // This is a subject pattern for the flipbook - Note that projects that want to use the multiFrame viewer should specify in workflow config
81
          if (counts.total === counts.images) {
7✔
82
            viewer = subjectViewers.flipbook
4✔
83
          }
84
          // This is a subject pattern for the image and text viewer
85
          // Note that workflows with subjects that have the same subject pattern that want to use a different viewer (i.e. light curve viewer)
86
          // should specify which viewer in the workflow configuration
87
          if (counts.total === 2 && counts.images === 1 && counts.text === 1) {
7✔
88
            viewer = subjectViewers.imageAndText
2✔
89
          }
90
        }
91
      }
92
      return viewer
39✔
93
    },
94

95
    get viewerConfiguration() {
96
      if (self.workflow) {
114✔
97
        return self.workflow.configuration.subject_viewer_configuration
113✔
98
      }
99

100
      return undefined
1✔
101
    },
102

103
    get project() {
104
      return tryReference(() => getRoot(self).projects?.active)
54!
105
    },
106

107
    get workflow() {
108
      return tryReference(() => getRoot(self).workflows?.active)
97✔
109
    },
110

111
    get priority() {
112
      const priority = self.metadata['#priority'] ?? self.metadata.priority
61✔
113
      if (priority !== undefined) {
61✔
114
        return parseFloat(priority)
31✔
115
      }
116
      return undefined
30✔
117
    },
118

119
    get alreadySeen() {
120
      return self.already_seen || subjectsSeenThisSession.check(self.workflow?.id, self.id)
88!
121
    }
122
  }))
123

124
  .actions(self => {
125
    function addToCollection() {
126
      const rootStore = getRoot(self)
1✔
127
      rootStore.onAddToCollection(self.id)
1✔
128
    }
129

130
    function markAsSeen() {
131
      self.already_seen = true
2✔
132
    }
133

134
    function openInTalk(newTab = false) {
10✔
135
      self.shouldDiscuss = {
10✔
136
        newTab,
137
        url: self.talkURL
138
      }
139
    }
140

141
    function setCaesarReductions({ reducer, reductions, subjectId, workflowId }) {
41✔
142
      if (reducer) {
41✔
143
        self.caesarReductions = CaesarReductions.create({
41✔
144
          loadingState: asyncStates.success,
145
          reducer,
146
          reductions,
147
          subjectId,
148
          workflowId
149
        })
150
      }
151
    }
152

153
    function startClassification() {
154
      self.stepHistory = StepHistory.create({})
348✔
155
      self.stepHistory.start()
348✔
156
    }
157

158
    function toggleFavorite() {
159
      const rootStore = getRoot(self)
2✔
160
      self.favorite = !self.favorite
2✔
161
      rootStore.onToggleFavourite(self.id, self.favorite)
2✔
162
    }
163

164
    function setCaesarReductionsLoadedForStep(stepIndex) {
165
      self.caesarReductionsLoadedForStep[stepIndex] = true
×
166
    }
167

168
    return {
3,178✔
169
      addToCollection,
170
      markAsSeen,
171
      openInTalk,
172
      setCaesarReductions,
173
      startClassification,
174
      toggleFavorite,
175
      setCaesarReductionsLoadedForStep
176
    }
177
  })
1✔
178

179
export default types.compose('SubjectResource', Resource, Subject)
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc