Test htsworkflow under several different django & python versions
[htsworkflow.git] / experiments / admin.py
1 from __future__ import absolute_import, print_function, unicode_literals
2
3 from itertools import chain
4
5 from django.contrib import admin
6 from django.forms import ModelForm
7 from django.forms.fields import CharField
8 from django.forms.widgets import TextInput, Select
9 from django.utils.encoding import force_text
10 from django.utils.html import escape, conditional_escape
11
12 from .models import (
13     FlowCell,
14     SequencingRun,
15     DataFile,
16     FileType,
17     ClusterStation,
18     Sequencer,
19     Lane
20 )
21
22
23 class DataFileForm(ModelForm):
24     class Meta:
25         model = DataFile
26         fields = ('random_key', 'sequencing_run', 'library',
27                   'file_type', 'relative_pathname')
28
29
30 class DataFileInline(admin.TabularInline):
31     model = DataFile
32     form = DataFileForm
33     raw_id_fields = ('library',)
34     extra = 0
35
36
37 @admin.register(SequencingRun)
38 class SequencingRunOptions(admin.ModelAdmin):
39     search_fields = [
40         'flowcell_id',
41         'run_folder',
42         'run_note',
43     ]
44     list_display = [
45         'runfolder_name',
46         'result_dir',
47         'run_start_time',
48     ]
49     fieldsets = (
50         (None, {
51             'fields': (
52                 ('flowcell', 'run_status'),
53                 ('runfolder_name', 'cycle_start', 'cycle_stop'),
54                 ('result_dir',),
55                 ('last_update_time'),
56                 ('image_software', 'image_version'),
57                 ('basecall_software', 'basecall_version'),
58                 ('alignment_software', 'alignment_version'),
59                 ('comment',))
60         }),
61     )
62     inlines = [DataFileInline]
63     # list_filter = ('run_status', 'run_start_time')
64
65
66 @admin.register(FileType)
67 class FileTypeAdmin(admin.ModelAdmin):
68     list_display = ('name', 'mimetype', 'regex')
69
70
71 # lane form setup needs to come before Flowcell form config
72 # as flowcell refers to the LaneInline class
73 class LaneForm(ModelForm):
74     comment = CharField(
75         widget=TextInput(attrs={'size': '80'}),
76         required=False)
77
78     class Meta:
79         model = Lane
80         fields = ('flowcell', 'lane_number', 'library',
81                   'pM', 'cluster_estimate',
82                   'status', 'comment')
83
84
85 class LaneInline(admin.StackedInline):
86     """Controls display of Lanes on the Flowcell form.
87     """
88     model = Lane
89     extra = 8
90     form = LaneForm
91     raw_id_fields = ('library',)
92     fieldsets = (
93         (None, {
94             'fields': ('lane_number', 'flowcell',
95                        ('library',),
96                        ('pM', 'cluster_estimate', 'status'),
97                        'comment',)
98         }),
99     )
100
101
102 @admin.register(Lane)
103 class LaneOptions(admin.ModelAdmin):
104     """Controls display of Lane browser
105     """
106     search_fields = (
107         '=flowcell__flowcell_id',
108         'library__id',
109         'library__library_name')
110     list_display = ('flowcell', 'lane_number', 'library', 'comment')
111     fieldsets = (
112         (None, {
113             'fields': ('lane_number', 'flowcell',
114                        ('library'),
115                        ('pM', 'cluster_estimate'))
116         }),
117         ('Optional', {
118             'classes': ('collapse', ),
119             'fields': ('comment', )
120         }),
121     )
122
123
124 @admin.register(FlowCell)
125 class FlowCellOptions(admin.ModelAdmin):
126     class Media:
127         css = {'all': ('css/admin_flowcell.css',)}
128     date_hierarchy = "run_date"
129     save_on_top = True
130     search_fields = (
131         'flowcell_id',
132         'sequencer__name',
133         'cluster_station__name',
134         '=lane__library__id',
135         'lane__library__library_name')
136     list_display = ('flowcell_id', 'run_date', 'Lanes')
137     list_filter = ('sequencer', 'cluster_station', 'paired_end')
138     fieldsets = (
139         (None, {
140             'fields': ('run_date',
141                        ('flowcell_id', 'cluster_station', 'sequencer'),
142                        ('read_length', 'control_lane', 'paired_end'),)
143         }),
144         ('Notes:', {'fields': ('notes',), }),
145     )
146     inlines = [
147         LaneInline,
148     ]
149
150     def formfield_for_dbfield(self, db_field, **kwargs):
151         field = super(FlowCellOptions, self).formfield_for_dbfield(db_field,
152                                                                    **kwargs)
153
154         # Override field attributes
155         if db_field.name == 'sequencer':
156             # seems kind of clunky.
157             # the goal is to replace the default select/combo box with one
158             # that can strike out disabled options.
159             attrs = field.widget.widget.attrs
160             field.widget.widget = SequencerSelect(
161                 attrs=attrs,
162                 queryset=field.queryset)
163         elif db_field.name == "notes":
164             field.widget.attrs["rows"] = "3"
165         return field
166
167
168 @admin.register(ClusterStation)
169 class ClusterStationOptions(admin.ModelAdmin):
170     list_display = ('name', 'isdefault',)
171     fieldsets = ((None, {'fields': ('name', 'isdefault')}),)
172
173
174 class SequencerSelect(Select):
175     def __init__(self, queryset=None, *args, **kwargs):
176         super(SequencerSelect, self).__init__(*args, **kwargs)
177         self.queryset = queryset
178
179     def render_option(self, selected_choices, option_value, option_label):
180         disabled_sequencers = [str(s.id) for s in
181                                self.queryset.filter(active=False)]
182         option_value = str(option_value)
183         selected_html = (option_value in selected_choices) and \
184                         u' selected="selected"' or ''
185         cssclass = "strikeout" if option_value in disabled_sequencers else ''
186         return u'<option class="%s" value="%s"%s>%s</option>' % (
187             cssclass, escape(option_value), selected_html,
188             conditional_escape(force_text(option_label)))
189
190
191 @admin.register(Sequencer)
192 class SequencerOptions(admin.ModelAdmin):
193     list_display = ('name', 'active', 'isdefault', 'instrument_name', 'model')
194     fieldsets = ((None,
195                   {'fields': (
196                       'name',
197                       ('active', 'isdefault'),
198                       'instrument_name',
199                       'serial_number',
200                       'model', 'comment')}), )