| 163 | |
| 164 | |
| 165 | class Project(ProjectMixin, FsmHistoryStateModel): |
| 166 | class SkipQueue(models.TextChoices): |
| 167 | # requeue to the end of the same annotator’s queue => annotator gets this task at the end of the queue |
| 168 | REQUEUE_FOR_ME = 'REQUEUE_FOR_ME', 'Requeue for me' |
| 169 | # requeue skipped tasks back to the common queue, excluding skipping annotator [current default] => another annotator gets this task |
| 170 | REQUEUE_FOR_OTHERS = 'REQUEUE_FOR_OTHERS', 'Requeue for others' |
| 171 | # ignore skipped tasks => skip is a valid annotation, task is completed (finished=True) |
| 172 | IGNORE_SKIPPED = 'IGNORE_SKIPPED', 'Ignore skipped' |
| 173 | |
| 174 | # Managers: default (visible only) and explicit unfiltered |
| 175 | objects = ProjectVisibleManager() |
| 176 | all_objects = ProjectManager() |
| 177 | __original_label_config = None |
| 178 | |
| 179 | title = models.CharField( |
| 180 | _('title'), |
| 181 | null=True, |
| 182 | blank=True, |
| 183 | default='', |
| 184 | max_length=settings.PROJECT_TITLE_MAX_LEN, |
| 185 | help_text=f'Project name. Must be between {settings.PROJECT_TITLE_MIN_LEN} and {settings.PROJECT_TITLE_MAX_LEN} characters long.', |
| 186 | validators=[ |
| 187 | MinLengthValidator(settings.PROJECT_TITLE_MIN_LEN), |
| 188 | MaxLengthValidator(settings.PROJECT_TITLE_MAX_LEN), |
| 189 | ], |
| 190 | ) |
| 191 | description = models.TextField( |
| 192 | _('description'), blank=True, null=True, default='', help_text='Project description' |
| 193 | ) |
| 194 | |
| 195 | organization = models.ForeignKey( |
| 196 | 'organizations.Organization', on_delete=models.CASCADE, related_name='projects', null=True |
| 197 | ) |
| 198 | label_config = models.TextField( |
| 199 | _('label config'), |
| 200 | blank=True, |
| 201 | null=True, |
| 202 | default='<View></View>', |
| 203 | help_text='Label config in XML format. See more about it in documentation', |
| 204 | ) |
| 205 | parsed_label_config = models.JSONField( |
| 206 | _('parsed label config'), |
| 207 | blank=True, |
| 208 | null=True, |
| 209 | default=None, |
| 210 | help_text='Parsed label config in JSON format. See more about it in documentation', |
| 211 | ) |
| 212 | label_config_hash = models.BigIntegerField(null=True, default=None) |
| 213 | expert_instruction = models.TextField( |
| 214 | _('expert instruction'), blank=True, null=True, default='', help_text='Labeling instructions in HTML format' |
| 215 | ) |
| 216 | show_instruction = models.BooleanField( |
| 217 | _('show instruction'), default=False, help_text='Show instructions to the annotator before they start' |
| 218 | ) |
| 219 | |
| 220 | show_skip_button = models.BooleanField( |
| 221 | _('show skip button'), |
| 222 | default=True, |