django-transcribe 0.6.0__py3-none-any.whl → 0.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- Transcribe was created at the BYU Library in 2012 by Geoff Groberg with UX design help from Grant Zabriskie. In 2014 Chad Hansen helped port the project from PHP to Python. In 2019 it was open sourced and as of this writing it is maintained by Geoff Groberg.
1
+ Transcribe was created at the BYU Library in 2012 by Geoff Groberg with UX design help from Grant Zabriskie. In 2014 Chad Hansen helped port the project from PHP to Python. In 2019 it was open sourced.
2
2
 
3
3
  Here is an incomplete list of people who have contributed to Transcribe:
4
4
 
@@ -6,4 +6,8 @@ Here is an incomplete list of people who have contributed to Transcribe:
6
6
  Chad Hansen <cgh@byu.edu>
7
7
  Grant Zabriskie <grant_zabriskie@byu.edu>
8
8
  Ben Crowder <ben_crowder@byu.edu>
9
- Scott Eldredge <scott_eldredge@byu.edu>
9
+ Scott Eldredge <scott_eldredge@byu.edu>
10
+ Taylor Payne <taylor_payne@byu.edu>
11
+ Mathew Behling <mathew_behling@byu.edu>
12
+ Russell Memory <russell_memory@byu.edu>
13
+ Winn Madesn <winn_madsen@byu.edu>
@@ -1,19 +1,27 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: django-transcribe
3
- Version: 0.6.0
3
+ Version: 0.7.1
4
4
  Summary: crowd source transcription
5
5
  Home-page: https://gitlab.com/byuhbll/lib/python/django-transcribe
6
- Author: BYU HBLL WebDev team
6
+ Author: BYU Library Software Engineering
7
7
  Author-email: support@lib.byu.edu
8
8
  Classifier: Intended Audience :: Developers
9
9
  Classifier: License :: OSI Approved :: BSD License
10
10
  Classifier: Operating System :: OS Independent
11
+ Classifier: Framework :: Django
12
+ Classifier: Framework :: Django :: 3.2
13
+ Classifier: Framework :: Django :: 4.1
14
+ Classifier: Framework :: Django :: 4.2
11
15
  Classifier: Programming Language :: Python
12
- Classifier: Programming Language :: Python :: 3.6
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
13
21
  License-File: LICENSE
14
22
  License-File: AUTHORS
15
23
  Requires-Dist: django-model-utils
16
24
  Requires-Dist: lxml
17
- Requires-Dist: Django <2.3.0,>=2.2.0
25
+ Requires-Dist: Django <5.0.0,>=3.2.0
18
26
 
19
27
  Crowd source the transcription of texts, audio, and video.
@@ -1,12 +1,12 @@
1
- transcribe/__init__.py,sha256=qFp_T9xwXsjX5GhZe6N2ShySfSHh7oBCM8OlR_KtO4Y,78
1
+ transcribe/__init__.py,sha256=WYosA-Pf6uytFfAdwJzG8DXM_qOmYzj1ORX25HtLENM,78
2
2
  transcribe/admin.py,sha256=HwrJafMjSoIKgb_En0zNvZ3nk5rCZWtJ5n0DdGU9nfI,6512
3
3
  transcribe/api.py,sha256=2m_y44ilQh87CWksHHqiE4A14javR8omlXEXm65lmC4,74
4
4
  transcribe/apps.py,sha256=XUdPQkCjpqWAKDCIaE6Mh8Q4xN5upKv95MG1u2_5pig,246
5
5
  transcribe/diff_match_patch.py,sha256=HZC5DNab5OVwbB4Zc7G17l1OHbBlH2g9-xOtT1zkQ1A,84937
6
6
  transcribe/filters.py,sha256=_ANh6XGDXgmD_wxQo5IPReQsv3_MDqThOwB06LKfbac,1264
7
- transcribe/forms.py,sha256=iEeZsgWGlYGw0mw81puzhxv91nDefmrjwQ_TdSr7Zfc,5117
7
+ transcribe/forms.py,sha256=6j-MtheDtDeBo9B_hlKhkWkWkKVJsLrJIlSsZAlB7ic,5612
8
8
  transcribe/middleware.py,sha256=3SvvNmJMlVohD_4Liv1yT3hc_nudpvt2giAE7Wt9rx4,485
9
- transcribe/models.py,sha256=g0_rtkLKbrkwxbWQbfZ3q5rnug235aEzFCI5DAUrcI4,38965
9
+ transcribe/models.py,sha256=mcAs_mwX2ROgB5OjlY2ceu_yL34nr4K5wiRrPz3XCf8,38870
10
10
  transcribe/settings.py,sha256=TNRFJstZF9X3l5qZSzv3xcrEuPMmOQbB-59mqADn9Dk,569
11
11
  transcribe/signals.py,sha256=pvRSWobg__Jw5ZvlFBZZAw3rDk1dvVyiq8Ka2lBGeSY,1105
12
12
  transcribe/urls.py,sha256=xgTkOdeC1cWmQAMzAp-VRwvmwyEAfEabncGgHyZiAL0,2040
@@ -17,12 +17,13 @@ transcribe/management/commands/check_media_size.py,sha256=ZT8KT-whEA7-uLqxa3Q10H
17
17
  transcribe/management/commands/fix_permissions.py,sha256=2CYzjkD8YMw6CqRCr5LIvXlNom-3NrPm69buaArOiE4,1558
18
18
  transcribe/management/commands/functional_tests.py,sha256=flJXZUPbsjbC51KEFaz5TXQLxf4GXHbbKd4diopVMDI,1634
19
19
  transcribe/migrations/0001_initial.py,sha256=IuhmY5SWSZ4rVSOtvoQOeQmgSLryPiK98rubp91o0j8,7132
20
- transcribe/migrations/0002_initial_data.py,sha256=Z5jtudsGAwNuxrw0Jt1FnEVAod1u5H-SuyXjA0laLZA,3352
20
+ transcribe/migrations/0001_initial_squashed_0021_point_fks_to_transcribe_user.py,sha256=u9xq3C4kCKE_o251AaOLXr08ataRkAceaJ7hxt_d3aw,18319
21
+ transcribe/migrations/0002_initial_data.py,sha256=BXK8sjEEV3ACR9u98RRMxI0T1mDIM_QILobFrGIZMGg,3383
21
22
  transcribe/migrations/0003_transcribeuser.py,sha256=dYz_tEvCgJBM5sP631AWOK_aMg1VpYRg9xlXWJI-bSw,443
22
23
  transcribe/migrations/0004_auto_20150716_1639.py,sha256=BgwqqK2BxbPmUaUQO5RBPIZeZnUphTADAoViFxWMGfQ,512
23
24
  transcribe/migrations/0005_auto_20150717_0829.py,sha256=W0l8re8Zp5-Xg_N8wHeWAMaT2SAgFAdlJmWQjx4hU_4,553
24
25
  transcribe/migrations/0006_project_archived.py,sha256=N4bfvX_wmRr9OHAoeosZbtKLGUhZchhJF6bH-tQByUY,428
25
- transcribe/migrations/0007_reviewer_group_addition.py,sha256=SyuuNgk5HLQH5IT60JV63q5Z1scDFCFnbNOeAVL9omk,2376
26
+ transcribe/migrations/0007_reviewer_group_addition.py,sha256=08uhIphclTOXVf5QIlykrXW_I8e4KdOW-Zcw1hC5JOE,2384
26
27
  transcribe/migrations/0008_auto_20150925_1522.py,sha256=ujH1uAuTRNJOMw5dWRFPqT2mnkjaC5xAYljL9yJElHg,1266
27
28
  transcribe/migrations/0009_auto_20150929_1314.py,sha256=lXElv1W2T0fTggdEnW7ssApkVgGcrD9ZA_i6Ud5vAqk,350
28
29
  transcribe/migrations/0010_userprojectpreferences.py,sha256=GGbG-O5OflRcyirhG9uHY7H12yIn0fCwdw6nLNmtv4k,1641
@@ -114,13 +115,10 @@ transcribe/static/transcribe/js/lib/rangy/rangy-highlighter.js,sha256=a0giQ-8tEi
114
115
  transcribe/static/transcribe/js/lib/rangy/rangy-selectionsaverestore.js,sha256=KEy_pZhmL1iO_lsmC_ow_oWfNjIfd19Ryw0kJZ974Ik,9546
115
116
  transcribe/static/transcribe/js/lib/rangy/rangy-serializer.js,sha256=yjtEFLyoUlDtOM1RPECLtWeIypXprTPFFqaVAkxqCGs,12705
116
117
  transcribe/static/transcribe/js/lib/rangy/rangy-textrange.js,sha256=oRuHe4BE3_QpKwVQ457PNs4PBrz7UQ2V6Mu7dva9R7s,81964
117
- transcribe/templates/.DS_Store,sha256=u7RGGZNMR9uNjsIsfBEMx2fJBjTsIvOsIHHTFaSxm1U,6148
118
- transcribe/templates/admin/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
119
- transcribe/templates/admin/base_site.html,sha256=epIGPdKgYnSRMx49oYkcJm6WX1gIXdal4Q_advX-Nyw,589
118
+ transcribe/templates/admin/base_site.html,sha256=ITfmNHf0qOdJ5VJWxya5W4p4qtDsPSXPCaiUQJSp-G8,286
120
119
  transcribe/templates/admin/show_hide_filter.html,sha256=WBKFzDAK93yigz1p7NE0Yzh_iBIUm67Rf_pkskubW1k,416
121
120
  transcribe/templates/admin/transcribe/project/delete_confirmation.html,sha256=1b0L81DZ7LhPVRcMQmsq7PhzoPG9pQqsAD7xzSs56oM,2584
122
121
  transcribe/templates/registration/login.html,sha256=Hh0FFE270p5eyTFbZLWB_K1KfBKyHmrdl9Ylh18cPqA,257
123
- transcribe/templates/transcribe/.DS_Store,sha256=1lFlJ5EFymdzGAUAaI30vcaaLHt3F1LwpG7xILf9jsM,6148
124
122
  transcribe/templates/transcribe/errors/404.html,sha256=sWTl4eyIg0ysMiOo6wLg9egGGDLJ9BELoOhLXEEnGrg,178
125
123
  transcribe/templates/transcribe/errors/500.html,sha256=B0W2NZiGcQrnFgQIXPefF02ZVAwrXEAm8Ohjnnps-hQ,195
126
124
  transcribe/templates/transcribe/reports/list.html,sha256=ovEtVFknwhz89wS1nQjeQ1xwk3acmmtCEgZFKw_KuqI,3848
@@ -144,10 +142,10 @@ transcribe/templates/transcribe/xsl/tei-html.xsl,sha256=oOVnAZhDVDVzrQR5UEbNV-97
144
142
  transcribe/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
145
143
  transcribe/views/mixins.py,sha256=QmFDhWb5VCEaGatLdbsTK72jiBG2OKrlncnz79FUmto,2727
146
144
  transcribe/views/reports.py,sha256=7YD5E6CPsIfWP8hG8IFTek29cM2T29NHuowAdlTAyBs,13408
147
- transcribe/views/web.py,sha256=sU5FNh0jl1yKSRZFo5CvdD5CVV9sb9vtUNdLRZuzAQg,15213
148
- django_transcribe-0.6.0.dist-info/AUTHORS,sha256=o63LB-1ge8sViGo8pRhfL8KTfgnwoSqAhTR7_iEkJXo,527
149
- django_transcribe-0.6.0.dist-info/LICENSE,sha256=I9xp13yeayqZikrv7rQrzsDWviTwy1R0phFlKtM1meg,1472
150
- django_transcribe-0.6.0.dist-info/METADATA,sha256=a9Q9OZ44OUSDojSBX3-cx-jFVZ_1l7uGh1MGYQ5F7-I,657
151
- django_transcribe-0.6.0.dist-info/WHEEL,sha256=uCRv0ZEik_232NlR4YDw4Pv3Ajt5bKvMH13NUU7hFuI,91
152
- django_transcribe-0.6.0.dist-info/top_level.txt,sha256=NljSay7zO6czcjqjVmivw6VW58aXlYHVZQvnwmpy08g,11
153
- django_transcribe-0.6.0.dist-info/RECORD,,
145
+ transcribe/views/web.py,sha256=WoVs-iwYc2hesuBxCmwfo-wza15C1fiMRY6S0TAdxQs,15213
146
+ django_transcribe-0.7.1.dist-info/AUTHORS,sha256=rNmFConshTlNpyhcu4CKZSeQQMwuyVYXbeqXgRko-Yc,640
147
+ django_transcribe-0.7.1.dist-info/LICENSE,sha256=I9xp13yeayqZikrv7rQrzsDWviTwy1R0phFlKtM1meg,1472
148
+ django_transcribe-0.7.1.dist-info/METADATA,sha256=kJaWnePuAJ0UvPfFaqmjN0-jjv5RVVW36tcjWHTd2WM,1021
149
+ django_transcribe-0.7.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
150
+ django_transcribe-0.7.1.dist-info/top_level.txt,sha256=NljSay7zO6czcjqjVmivw6VW58aXlYHVZQvnwmpy08g,11
151
+ django_transcribe-0.7.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.1)
2
+ Generator: setuptools (74.1.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
transcribe/__init__.py CHANGED
@@ -1,2 +1,2 @@
1
1
  default_app_config = 'transcribe.apps.transcribeConfig'
2
- __version__ = '0.6.0'
2
+ __version__ = '0.7.1'
transcribe/forms.py CHANGED
@@ -9,6 +9,24 @@ from .models import Project, Task, task_file_name
9
9
  log = logging.getLogger(__name__)
10
10
 
11
11
 
12
+ class MultipleFileInput(forms.ClearableFileInput):
13
+ allow_multiple_selected = True
14
+
15
+
16
+ class MultipleFileField(forms.FileField):
17
+ def __init__(self, *args, **kwargs):
18
+ kwargs.setdefault('widget', MultipleFileInput())
19
+ super().__init__(*args, **kwargs)
20
+
21
+ def clean(self, data, initial=None):
22
+ single_file_clean = super().clean
23
+ if isinstance(data, (list, tuple)):
24
+ result = [single_file_clean(d, initial) for d in data]
25
+ else:
26
+ result = single_file_clean(data, initial)
27
+ return result
28
+
29
+
12
30
  class NoColon(forms.ModelForm):
13
31
  def __init__(self, *args, **kwargs):
14
32
  kwargs.setdefault('label_suffix', '')
@@ -19,9 +37,8 @@ class NoColon(forms.ModelForm):
19
37
 
20
38
 
21
39
  class ProjectForm(NoColon):
22
- upload_media_files = forms.FileField(
40
+ upload_media_files = MultipleFileField(
23
41
  required=False,
24
- widget=forms.FileInput(attrs={'multiple': 'multiple'}),
25
42
  label='Upload media files',
26
43
  )
27
44
 
@@ -0,0 +1,555 @@
1
+ # Generated by Django 3.2.20 on 2024-08-29 03:24
2
+
3
+ import django.db.migrations.operations.special
4
+ import django.db.models.deletion
5
+ import django.utils.timezone
6
+ import model_utils.fields
7
+ from django.conf import settings
8
+ from django.contrib.auth.management import create_permissions
9
+ from django.db import migrations, models
10
+
11
+ import transcribe.models
12
+
13
+ INITIAL_TAG_DATA = [
14
+ {
15
+ 'id': 1,
16
+ 'name': 'Heading',
17
+ 'description': 'a heading or chapter title',
18
+ 'open_tag': '<head>',
19
+ 'close_tag': '</head>',
20
+ }, # noqa
21
+ {
22
+ 'id': 2,
23
+ 'name': 'Quote',
24
+ 'description': 'quoted text',
25
+ 'open_tag': '<q>',
26
+ 'close_tag': '</q>',
27
+ }, # noqa
28
+ {
29
+ 'id': 3,
30
+ 'name': 'Person',
31
+ 'description': 'the name of a person (e.g. John Doe)',
32
+ 'open_tag': '<name type="person">',
33
+ 'close_tag': '</name>',
34
+ }, # noqa
35
+ {
36
+ 'id': 4,
37
+ 'name': 'Place',
38
+ 'description': 'the name of a place (e.g. New York City)',
39
+ 'open_tag': '<name type="place">',
40
+ 'close_tag': '</name>',
41
+ }, # noqa
42
+ {
43
+ 'id': 5,
44
+ 'name': 'Date',
45
+ 'description': 'Mark a text string as a date. (Include a normalize...',
46
+ 'open_tag': '<date when="YYYY-MM-DD">',
47
+ 'close_tag': '</date>',
48
+ }, # noqa
49
+ {
50
+ 'id': 6,
51
+ 'name': 'Add',
52
+ 'description': 'an addition or insertion',
53
+ 'open_tag': '<add>',
54
+ 'close_tag': '</add>',
55
+ }, # noqa
56
+ {
57
+ 'id': 7,
58
+ 'name': 'Del',
59
+ 'description': 'as strikeout or deletion',
60
+ 'open_tag': '<del rend="overstrike">',
61
+ 'close_tag': '</del>',
62
+ }, # noqa
63
+ {
64
+ 'id': 8,
65
+ 'name': 'Note',
66
+ 'description': 'a note in the margin, or elsewhere',
67
+ 'open_tag': '<note place="margin">',
68
+ 'close_tag': '</note>',
69
+ }, # noqa
70
+ {
71
+ 'id': 9,
72
+ 'name': 'Unclear',
73
+ 'description': 'mark something as unclear/illegible',
74
+ 'open_tag': '<unclear reason="illegible">',
75
+ 'close_tag': '</unclear>',
76
+ }, # noqa
77
+ {
78
+ 'id': 10,
79
+ 'name': 'Page #',
80
+ 'description': 'mark a new page break along with the printed page ...',
81
+ 'open_tag': '<pb n="',
82
+ 'close_tag': '"/>',
83
+ }, # noqa
84
+ {
85
+ 'id': 11,
86
+ 'name': 'Underline',
87
+ 'description': 'underlined text',
88
+ 'open_tag': '<hi rend="underline">',
89
+ 'close_tag': '</hi>',
90
+ }, # noqa
91
+ {
92
+ 'id': 12,
93
+ 'name': 'Bold',
94
+ 'description': 'bold text',
95
+ 'open_tag': '<hi rend="bold">',
96
+ 'close_tag': '</hi>',
97
+ }, # noqa
98
+ {
99
+ 'id': 13,
100
+ 'name': 'Italic',
101
+ 'description': 'italicized text',
102
+ 'open_tag': '<hi rend="italic">',
103
+ 'close_tag': '</hi>',
104
+ }, # noqa
105
+ {
106
+ 'id': 14,
107
+ 'name': 'Superscript',
108
+ 'description': 'superscript text',
109
+ 'open_tag': '<hi rend="sup">',
110
+ 'close_tag': '</hi>',
111
+ }, # noqa
112
+ {
113
+ 'id': 15,
114
+ 'name': 'Subscript',
115
+ 'description': 'subscript text',
116
+ 'open_tag': '<hi rend="sub">',
117
+ 'close_tag': '</hi>',
118
+ }, # noqa
119
+ ]
120
+
121
+
122
+ def initial_tag_data(apps, schema_editor):
123
+ Tag = apps.get_model('transcribe', 'Tag')
124
+ Tag.objects.all().delete()
125
+ for data in INITIAL_TAG_DATA:
126
+ Tag.objects.get_or_create(**data)
127
+
128
+
129
+ def add_reviewer_group(apps, schema_editor):
130
+ Group = apps.get_model('auth', 'Group')
131
+ Group.objects.get_or_create(name='Reviewer')
132
+
133
+
134
+ def add_admin_group(apps, schema_editor):
135
+ Group = apps.get_model('auth', 'Group')
136
+ Permission = apps.get_model('auth', 'Permission')
137
+ admin_group, _ = Group.objects.get_or_create(name='Admin')
138
+
139
+ # Make sure permissions have been created
140
+ for app_config in apps.get_app_configs():
141
+ app_config.models_module = True
142
+ create_permissions(app_config, verbosity=0)
143
+ app_config.models_module = None
144
+
145
+ permission_codenames = [
146
+ 'add_project',
147
+ 'change_project',
148
+ 'delete_project',
149
+ 'add_task',
150
+ 'change_task',
151
+ 'delete_task',
152
+ 'add_usertask',
153
+ 'change_usertask',
154
+ 'delete_usertask',
155
+ 'add_tag',
156
+ 'change_tag',
157
+ 'delete_tag',
158
+ 'add_transcribeuser',
159
+ 'change_transcribeuser',
160
+ ]
161
+
162
+ permissions = []
163
+ for codename in permission_codenames:
164
+ try:
165
+ permission = Permission.objects.get(codename=codename)
166
+ permissions.append(permission)
167
+ except Permission.DoesNotExist:
168
+ # Optionally log the missing permission
169
+ print(f"Warning: Permission with codename '{codename}' not found.")
170
+
171
+ admin_group.permissions.set(permissions)
172
+
173
+
174
+ def create_transcribe_users(apps, schema_editor):
175
+ User = apps.get_model(settings.AUTH_USER_MODEL)
176
+ TranscribeUser = apps.get_model('transcribe', 'TranscribeUser')
177
+
178
+ for user in User.objects.all():
179
+ TranscribeUser.objects.get_or_create(user=user)
180
+
181
+
182
+ class Migration(migrations.Migration):
183
+
184
+ replaces = [
185
+ ('transcribe', '0001_initial'),
186
+ ('transcribe', '0002_initial_data'),
187
+ ('transcribe', '0003_transcribeuser'),
188
+ ('transcribe', '0004_auto_20150716_1639'),
189
+ ('transcribe', '0005_auto_20150717_0829'),
190
+ ('transcribe', '0006_project_archived'),
191
+ ('transcribe', '0007_reviewer_group_addition'),
192
+ ('transcribe', '0008_auto_20150925_1522'),
193
+ ('transcribe', '0009_auto_20150929_1314'),
194
+ ('transcribe', '0010_userprojectpreferences'),
195
+ ('transcribe', '0011_project_finding_aid_url'),
196
+ ('transcribe', '0012_auto_20160107_1410'),
197
+ ('transcribe', '0013_userpreferences'),
198
+ ('transcribe', '0014_auto_20160203_1544'),
199
+ ('transcribe', '0015_auto_20160309_1342'),
200
+ ('transcribe', '0016_auto_20160817_1343'),
201
+ ('transcribe', '0017_auto_20191115_1123'),
202
+ ('transcribe', '0018_point_fks_to_user'),
203
+ ('transcribe', '0019_create_transcribeuser'),
204
+ ('transcribe', '0020_populate_transcribe_users'),
205
+ ('transcribe', '0021_point_fks_to_transcribe_user'),
206
+ ]
207
+
208
+ dependencies = [
209
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
210
+ ('auth', '0001_initial'),
211
+ ]
212
+
213
+ operations = [
214
+ migrations.CreateModel(
215
+ name='Project',
216
+ fields=[
217
+ (
218
+ 'id',
219
+ models.AutoField(
220
+ auto_created=True,
221
+ primary_key=True,
222
+ serialize=False,
223
+ verbose_name='ID',
224
+ ),
225
+ ),
226
+ (
227
+ 'created',
228
+ model_utils.fields.AutoCreatedField(
229
+ default=django.utils.timezone.now,
230
+ editable=False,
231
+ verbose_name='created',
232
+ ),
233
+ ),
234
+ (
235
+ 'modified',
236
+ model_utils.fields.AutoLastModifiedField(
237
+ default=django.utils.timezone.now,
238
+ editable=False,
239
+ verbose_name='modified',
240
+ ),
241
+ ),
242
+ ('title', models.CharField(db_index=True, max_length=255)),
243
+ ('description', models.TextField()),
244
+ ('guidelines', models.TextField(blank=True)),
245
+ ('priority', models.IntegerField(default=0)),
246
+ ('transcribers_per_task', models.IntegerField(default=2)),
247
+ (
248
+ 'media_type',
249
+ models.CharField(
250
+ choices=[
251
+ ('audio', 'audio'),
252
+ ('text', 'text'),
253
+ ('video', 'video'),
254
+ ],
255
+ default='text',
256
+ max_length=6,
257
+ ),
258
+ ),
259
+ ('archived', models.BooleanField(default=False)),
260
+ (
261
+ 'finding_aid_url',
262
+ models.CharField(blank=True, max_length=2083),
263
+ ),
264
+ (
265
+ 'allow_global_transcriptions',
266
+ models.BooleanField(default=False),
267
+ ),
268
+ ],
269
+ options={
270
+ 'ordering': ['-priority', 'title'],
271
+ },
272
+ ),
273
+ migrations.CreateModel(
274
+ name='Tag',
275
+ fields=[
276
+ (
277
+ 'id',
278
+ models.AutoField(
279
+ auto_created=True,
280
+ primary_key=True,
281
+ serialize=False,
282
+ verbose_name='ID',
283
+ ),
284
+ ),
285
+ ('name', models.CharField(blank=True, max_length=255)),
286
+ ('description', models.CharField(blank=True, max_length=255)),
287
+ ('open_tag', models.TextField()),
288
+ ('close_tag', models.TextField()),
289
+ ],
290
+ ),
291
+ migrations.CreateModel(
292
+ name='Task',
293
+ fields=[
294
+ (
295
+ 'id',
296
+ models.AutoField(
297
+ auto_created=True,
298
+ primary_key=True,
299
+ serialize=False,
300
+ verbose_name='ID',
301
+ ),
302
+ ),
303
+ (
304
+ 'created',
305
+ model_utils.fields.AutoCreatedField(
306
+ default=django.utils.timezone.now,
307
+ editable=False,
308
+ verbose_name='created',
309
+ ),
310
+ ),
311
+ (
312
+ 'modified',
313
+ model_utils.fields.AutoLastModifiedField(
314
+ default=django.utils.timezone.now,
315
+ editable=False,
316
+ verbose_name='modified',
317
+ ),
318
+ ),
319
+ (
320
+ 'file',
321
+ models.FileField(
322
+ upload_to=transcribe.models.task_file_name
323
+ ),
324
+ ),
325
+ ('transcription', models.TextField(blank=True)),
326
+ (
327
+ 'finished_transcription',
328
+ models.BooleanField(
329
+ blank=True, db_index=True, default=False
330
+ ),
331
+ ),
332
+ (
333
+ 'finished_review',
334
+ models.BooleanField(
335
+ blank=True, db_index=True, default=False
336
+ ),
337
+ ),
338
+ (
339
+ 'project',
340
+ models.ForeignKey(
341
+ on_delete=django.db.models.deletion.CASCADE,
342
+ related_name='tasks',
343
+ to='transcribe.project',
344
+ ),
345
+ ),
346
+ ],
347
+ options={
348
+ 'abstract': False,
349
+ },
350
+ ),
351
+ migrations.CreateModel(
352
+ name='TranscribeUser',
353
+ fields=[
354
+ (
355
+ 'id',
356
+ models.AutoField(
357
+ auto_created=True,
358
+ primary_key=True,
359
+ serialize=False,
360
+ verbose_name='ID',
361
+ ),
362
+ ),
363
+ (
364
+ 'user',
365
+ models.OneToOneField(
366
+ on_delete=django.db.models.deletion.CASCADE,
367
+ related_name='transcribe_user',
368
+ to=settings.AUTH_USER_MODEL,
369
+ ),
370
+ ),
371
+ ],
372
+ options={
373
+ 'verbose_name': 'Transcribe user',
374
+ 'verbose_name_plural': 'Transcribe users',
375
+ 'ordering': ['user__last_name', 'user__first_name'],
376
+ },
377
+ ),
378
+ migrations.CreateModel(
379
+ name='UserTask',
380
+ fields=[
381
+ (
382
+ 'id',
383
+ models.AutoField(
384
+ auto_created=True,
385
+ primary_key=True,
386
+ serialize=False,
387
+ verbose_name='ID',
388
+ ),
389
+ ),
390
+ (
391
+ 'created',
392
+ model_utils.fields.AutoCreatedField(
393
+ default=django.utils.timezone.now,
394
+ editable=False,
395
+ verbose_name='created',
396
+ ),
397
+ ),
398
+ (
399
+ 'modified',
400
+ model_utils.fields.AutoLastModifiedField(
401
+ default=django.utils.timezone.now,
402
+ editable=False,
403
+ verbose_name='modified',
404
+ ),
405
+ ),
406
+ (
407
+ 'task_type',
408
+ models.CharField(
409
+ choices=[
410
+ ('transcription', 'transcription'),
411
+ ('review', 'review'),
412
+ ],
413
+ db_index=True,
414
+ default='transcription',
415
+ max_length=13,
416
+ ),
417
+ ),
418
+ ('transcription', models.TextField(blank=True, default='')),
419
+ (
420
+ 'status',
421
+ models.CharField(
422
+ choices=[
423
+ ('in progress', 'in progress'),
424
+ ('skipped', 'skipped'),
425
+ ('finished', 'finished'),
426
+ ],
427
+ db_index=True,
428
+ default='in progress',
429
+ max_length=11,
430
+ ),
431
+ ),
432
+ (
433
+ 'task',
434
+ models.ForeignKey(
435
+ on_delete=django.db.models.deletion.CASCADE,
436
+ related_name='usertasks',
437
+ to='transcribe.task',
438
+ ),
439
+ ),
440
+ (
441
+ 'user',
442
+ models.ForeignKey(
443
+ on_delete=django.db.models.deletion.CASCADE,
444
+ related_name='tasks',
445
+ to='transcribe.transcribeuser',
446
+ ),
447
+ ),
448
+ ],
449
+ options={
450
+ 'ordering': ['-modified', 'user'],
451
+ },
452
+ ),
453
+ migrations.CreateModel(
454
+ name='UserProjectPreferences',
455
+ fields=[
456
+ (
457
+ 'id',
458
+ models.AutoField(
459
+ auto_created=True,
460
+ primary_key=True,
461
+ serialize=False,
462
+ verbose_name='ID',
463
+ ),
464
+ ),
465
+ (
466
+ 'transcription_width',
467
+ models.IntegerField(blank=True, null=True),
468
+ ),
469
+ (
470
+ 'transcription_height',
471
+ models.IntegerField(blank=True, null=True),
472
+ ),
473
+ (
474
+ 'transcription_stacked',
475
+ models.BooleanField(blank=True, default=True),
476
+ ),
477
+ (
478
+ 'project',
479
+ models.ForeignKey(
480
+ on_delete=django.db.models.deletion.CASCADE,
481
+ related_name='userprojects',
482
+ to='transcribe.project',
483
+ ),
484
+ ),
485
+ (
486
+ 'user',
487
+ models.ForeignKey(
488
+ on_delete=django.db.models.deletion.CASCADE,
489
+ related_name='projects',
490
+ to='transcribe.transcribeuser',
491
+ ),
492
+ ),
493
+ ],
494
+ ),
495
+ migrations.CreateModel(
496
+ name='UserPreferences',
497
+ fields=[
498
+ (
499
+ 'id',
500
+ models.AutoField(
501
+ auto_created=True,
502
+ primary_key=True,
503
+ serialize=False,
504
+ verbose_name='ID',
505
+ ),
506
+ ),
507
+ (
508
+ 'uses_serif_transcription_font',
509
+ models.BooleanField(default=True),
510
+ ),
511
+ (
512
+ 'user',
513
+ models.OneToOneField(
514
+ on_delete=django.db.models.deletion.CASCADE,
515
+ related_name='preferences',
516
+ to='transcribe.transcribeuser',
517
+ ),
518
+ ),
519
+ ],
520
+ ),
521
+ migrations.AddField(
522
+ model_name='project',
523
+ name='reviewers',
524
+ field=models.ManyToManyField(
525
+ blank=True,
526
+ related_name='review_projects',
527
+ to='transcribe.TranscribeUser',
528
+ ),
529
+ ),
530
+ migrations.AddField(
531
+ model_name='project',
532
+ name='transcribers',
533
+ field=models.ManyToManyField(
534
+ blank=True,
535
+ related_name='transcription_projects',
536
+ to='transcribe.TranscribeUser',
537
+ ),
538
+ ),
539
+ migrations.RunPython(
540
+ code=initial_tag_data,
541
+ reverse_code=django.db.migrations.operations.special.RunPython.noop,
542
+ ),
543
+ migrations.RunPython(
544
+ code=add_reviewer_group,
545
+ reverse_code=django.db.migrations.operations.special.RunPython.noop,
546
+ ),
547
+ migrations.RunPython(
548
+ code=add_admin_group,
549
+ reverse_code=django.db.migrations.operations.special.RunPython.noop,
550
+ ),
551
+ migrations.RunPython(
552
+ code=create_transcribe_users,
553
+ reverse_code=django.db.migrations.operations.special.RunPython.noop,
554
+ ),
555
+ ]
@@ -124,5 +124,7 @@ class Migration(migrations.Migration):
124
124
  dependencies = [('transcribe', '0001_initial')]
125
125
 
126
126
  operations = [
127
- migrations.RunPython(initial_tag_data, reverse_code=lambda a, b: None)
127
+ migrations.RunPython(
128
+ initial_tag_data, reverse_code=migrations.RunPython.noop
129
+ ),
128
130
  ]
@@ -2,8 +2,8 @@
2
2
  from __future__ import unicode_literals
3
3
 
4
4
  from django.db import migrations
5
- from transcribe.management.commands.fix_permissions import Command
6
5
 
6
+ from transcribe.management.commands.fix_permissions import Command
7
7
 
8
8
  """
9
9
  Note:
@@ -81,6 +81,6 @@ class Migration(migrations.Migration):
81
81
 
82
82
  operations = [
83
83
  migrations.RunPython(add_reviewer_group, remove_reviewer_group),
84
- migrations.RunPython(fix_permissions, lambda x, y: None),
84
+ migrations.RunPython(fix_permissions, migrations.RunPython.noop),
85
85
  migrations.RunPython(add_admin_group, remove_admin_group),
86
86
  ]
transcribe/models.py CHANGED
@@ -1,17 +1,19 @@
1
1
  """Models for transcribe."""
2
2
  import logging
3
3
  import re
4
- from datetime import datetime, timedelta
4
+ from datetime import timedelta
5
5
  from os import path
6
6
 
7
7
  from django.contrib.auth import get_user_model
8
8
  from django.db import models
9
9
  from django.db.models import Count, Q
10
10
  from django.urls import reverse
11
+ from django.utils import timezone
11
12
  from django.utils.functional import cached_property
12
13
  from django.utils.html import format_html, strip_tags
13
14
  from model_utils import Choices
14
15
  from model_utils.models import TimeStampedModel
16
+
15
17
  from transcribe import settings
16
18
  from transcribe.diff_match_patch import diff_match_patch
17
19
  from transcribe.utils import html_diffs, remove_markup
@@ -408,8 +410,7 @@ class Project(TimeStampedModel):
408
410
 
409
411
  @cached_property
410
412
  def percent_done(self):
411
- """Returns an integer indicating the percent complete for the project.
412
- """
413
+ """Returns an integer indicating the percent complete for the project."""
413
414
  counts = Task.objects.filter(project_id=self.pk).aggregate(
414
415
  total_tasks=Count('id'),
415
416
  finished_review_tasks=Count('id', filter=Q(finished_review=1)),
@@ -487,9 +488,7 @@ class Project(TimeStampedModel):
487
488
  # exclude tasks that:
488
489
  # - have enough user tasks in progress AND
489
490
  # - those user tasks are not too old (expired)
490
- expired_dt = (
491
- datetime.today() - timedelta(days=settings.TASK_EXPIRE_DAYS)
492
- ).strftime('%Y-%m-%d %H:%M:%S')
491
+ expired_dt = timezone.now() - timedelta(days=settings.TASK_EXPIRE_DAYS)
493
492
  task_ids_to_exclude.update(
494
493
  self.tasks.defer('transcription')
495
494
  .filter(
@@ -557,9 +556,7 @@ class Project(TimeStampedModel):
557
556
  ).values_list('id', flat=True)
558
557
 
559
558
  # in progress tasks that are recent
560
- expired_dt = (
561
- datetime.today() - timedelta(days=settings.TASK_EXPIRE_DAYS)
562
- ).strftime('%Y-%m-%d %H:%M:%S')
559
+ expired_dt = timezone.now() - timedelta(days=settings.TASK_EXPIRE_DAYS)
563
560
  task_ids_already_being_reviewed = self.tasks.filter(
564
561
  usertasks__status='in progress',
565
562
  usertasks__task_type='review',
@@ -698,9 +695,10 @@ class Project(TimeStampedModel):
698
695
 
699
696
  def generate_html(self):
700
697
  """Generates and returns an HTML representation of the project."""
701
- from lxml import etree
702
698
  import tempfile
703
699
 
700
+ from lxml import etree
701
+
704
702
  xml = self.generate_xml()
705
703
  html = ''
706
704
  temp = tempfile.NamedTemporaryFile(mode='w+t', delete=False)
@@ -1,13 +1,4 @@
1
- {% extends "admin/base.html" %}
2
- {% load admin_static %}
3
-
4
- {% block title %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}
5
-
6
- {% block branding %}
7
- <h1 id="site-name"><a href="{% url 'admin:index' %}">{{ site_header|default:_('Django administration') }}</a></h1>
8
- {% endblock %}
9
-
10
- {% block nav-global %}{% endblock %}
1
+ {% extends "admin/base_site.html" %}
11
2
 
12
3
  {% block userlinks %}
13
4
  <a href="{% url 'reports:list' %}">Reports</a>
transcribe/views/web.py CHANGED
@@ -10,6 +10,7 @@ from django.views.generic import View
10
10
  from django.views.generic.detail import DetailView
11
11
  from django.views.generic.edit import UpdateView
12
12
  from django.views.generic.list import ListView
13
+
13
14
  from transcribe import models, settings
14
15
  from transcribe.views import mixins
15
16
 
@@ -19,7 +20,7 @@ log = logging.getLogger(__name__)
19
20
  def get_project_with_tasks(project, user):
20
21
  """Return project with transcription and review tasks attached."""
21
22
  if not isinstance(user, models.TranscribeUser):
22
- user = models.TranscribeUser.objects.get(pk=user.pk)
23
+ user = models.TranscribeUser.objects.get(user=user)
23
24
  project.pending_trans_task = project.pending_transcription_task(user)
24
25
  project.avail_trans_task = False
25
26
  if not project.pending_trans_task:
Binary file
Binary file
Binary file