Merge remote-tracking branch 'origin/master'
authorMaciej Tronowski <mtro@man.poznan.pl>
Wed, 4 Mar 2015 09:22:22 +0000 (10:22 +0100)
committerMaciej Tronowski <mtro@man.poznan.pl>
Wed, 4 Mar 2015 09:22:22 +0000 (10:22 +0100)
# Conflicts:
# qcg/fields.py
# qcg/forms.py
# qcg/templates/qcg/job_new.html

1  2 
qcg/fields.py
qcg/forms.py
qcg/templates/qcg/job_new.html

diff --combined qcg/fields.py
index 0000000,3e5ec44..e067f46
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,65 +1,55 @@@
+ # coding=utf-8
+ from datetime import timedelta
+ from django import forms
+ from django.core.exceptions import ValidationError
 -class PredefinedChoiceField(forms.ChoiceField):
 -    def valid_value(self, value):
 -        # any value is valid
 -        return True
 -
 -
 -class MultiplePredefinedChoiceField(forms.MultipleChoiceField, PredefinedChoiceField):
 -    pass
 -
 -
+ class TimeRangeWidget(forms.MultiWidget):
+     def decompress(self, value):
+         if not value:
+             return [0, TimeRangeField.SECONDS]
+         seconds = value.seconds + 86400 * value.days
+         if seconds % 60 != 0:
+             return [seconds, TimeRangeField.SECONDS]
+         elif seconds % 3600 != 0:
+             return [seconds / 60, TimeRangeField.MINUTES]
+         elif seconds % 86400 != 0:
+             return [seconds / 3600, TimeRangeField.HOURS]
+         else:
+             return [seconds / 86400, TimeRangeField.DAYS]
+ class TimeRangeField(forms.MultiValueField):
+     SECONDS, MINUTES, HOURS, DAYS = range(4)
+     UNIT_CHOICES = (
+         (SECONDS, u"Sekund"),
+         (MINUTES, u"Minut"),
+         (HOURS, u"Godzin"),
+         (DAYS, u"Dni"),
+     )
+     value = forms.IntegerField(min_value=0)
+     unit = forms.ChoiceField(choices=UNIT_CHOICES)
+     widget = TimeRangeWidget(widgets=(value.widget, unit.widget))
+     def __init__(self, *args, **kwargs):
+         super(TimeRangeField, self).__init__((self.value, self.unit), *args, **kwargs)
+     def compress(self, data_list):
+         try:
+             unit = int(data_list[1])
+             if unit == self.SECONDS:
+                 return timedelta(seconds=data_list[0])
+             elif unit == self.MINUTES:
+                 return timedelta(minutes=data_list[0])
+             elif unit == self.HOURS:
+                 return timedelta(hours=data_list[0])
+             elif unit == self.DAYS:
+                 return timedelta(days=data_list[0])
+             else:
+                 raise ValidationError(u"Nieprawidłowa jednostka")
+         except ValueError:
+             raise ValidationError(u"Nieprawidłowa jednostka")
diff --combined qcg/forms.py
@@@ -4,6 -4,7 +4,7 @@@ from django.core.validators import Rege
  from django.template.defaultfilters import capfirst
  from pyqcg.utils import TaskStatus
  
 -from qcg.fields import PredefinedChoiceField, MultiplePredefinedChoiceField, TimeRangeField
++from qcg.fields import TimeRangeField
  from qcg.models import Task, Allocation
  
  
@@@ -83,9 -84,8 +84,9 @@@ class JobDescriptionForm(forms.Form)
      APPLICATION_CHOICES = (
          CHOICES_PLACEHOLDER,
          ('bash', 'BASH'),
 -        ('python', 'Python'),
 +        ('gromacs/4.6.3', 'GROMACS 4.6.3'),
          ('matlab', 'MATLAB'),
 +        ('python', 'Python'),
      )
      QUEUE_CHOICES = (
          CHOICES_PLACEHOLDER,
      )
  
      application = forms.ChoiceField(choices=APPLICATION_CHOICES, label=u"Aplikacja", required=False)  # TODO choices
 -    executable = forms.CharField(label=u"Polecenie", max_length=500, required=False)  # TODO grid ftp
 -    arguments = forms.CharField(label=u"Argumenty", max_length=1000, required=False)
 -
 -    name = forms.CharField(label=u"Nazwa", max_length=100, required=False)
 -    note = forms.CharField(label=u"Notatka", widget=forms.Textarea(attrs={'rows': 2, 'cols': 40}), required=False)
 +    executable = forms.CharField(label=u"Plik wykonywalny", max_length=500, required=False)  # TODO grid ftp
 +    script = forms.CharField(label=u"Skrypt", widget=forms.Textarea(attrs={'rows': 2, 'cols': 40}), required=False)  # TODO saving to grid ftp
 +    arguments = forms.MultipleChoiceField(label=u"Argumenty", required=False)
 +    note = forms.CharField(label=u"Opis", widget=forms.Textarea(attrs={'rows': 2, 'cols': 40}), required=False)
      grant = forms.CharField(label=u"Grant", max_length=100, required=False)
  
      host = forms.ChoiceField(label=u"Host", choices=Host.CHOICES, required=False)
 -    queue = PredefinedChoiceField(choices=QUEUE_CHOICES, label=u"Kolejka", required=False)
 +    properties = forms.MultipleChoiceField(label=u"Właściwości węzłów", required=False)
 +    queue = forms.ChoiceField(choices=QUEUE_CHOICES, label=u"Kolejka", required=False)
      procs = forms.IntegerField(label=u"Liczba procesów", min_value=0, required=False)
      nodes = forms.CharField(label=u"Topologia węzłów", max_length=10, validators=[nodes_validator], required=False)
 -    wall_time = TimeRangeField(label=u"Wall time", required=False)
 +    wall_time = forms.IntegerField(label=u"Wall time (s)", min_value=0, required=False)  # TODO duration field
      memory = forms.IntegerField(label=u"Pamięć (MB)", min_value=0, required=False)
      memory_per_slot = forms.IntegerField(label=u"Pamięci per proces (MB)", min_value=0, required=False)
 +    modules = forms.MultipleChoiceField(label=u"Moduły", choices=MODULES_CHOICES, required=False)  # TODO choices
 +    reservation = forms.CharField(label=u"Rezerwacja", max_length=100, required=False)
  
      # TODO grid ftp
      input = forms.CharField(label=u"Standardowe wejście", max_length=500, required=False)
      stage_in = forms.CharField(label=u"Stage in", max_length=500, required=False)
      stage_out = forms.CharField(label=u"Stage out", max_length=500, required=False)
  
 -    properties = MultiplePredefinedChoiceField(label=u"Właściwości węzłów", required=False)
 -    modules = forms.MultipleChoiceField(label=u"Moduły", choices=MODULES_CHOICES, required=False)  # TODO choices
 -
 -    not_after = forms.DateTimeField(label=u"Nie później niż", required=False)
 -    not_before = forms.DateTimeField(label=u"Nie wcześniej niż", required=False)
 -    deadline = TimeRangeField(label=u"Deadline", required=False)
 -    reservation = forms.CharField(label=u"Rezerwacja", max_length=100, required=False)
 -
      monitoring = forms.BooleanField(label=u"Portal QCG-Monitoring", required=False)
      notify_type = forms.ChoiceField(label=u"Monitorowanie stanu", choices=NOTIFY_CHOICES, required=False, initial=0,
                                      widget=forms.RadioSelect)
                                           widget=forms.RadioSelect)
      postprocess_cmd = forms.CharField(label=u"Polecenie", max_length=1000, required=False)
      postprocess_script = forms.CharField(label=u"Skrypt", max_length=500, required=False)  # TODO grid ftp
 -    native = MultiplePredefinedChoiceField(label=u"Parametry natywne", required=False)
 +    native = forms.MultipleChoiceField(label=u"Opcje systemu kolejkowego", required=False)
      persistent = forms.BooleanField(label=u"Trwałe", required=False)
 -    use_scratch = forms.BooleanField(label=u"Scratch", required=False)
 +
 +    def __init__(self, data=None, *args, **kwargs):
 +        super(JobDescriptionForm, self).__init__(data, *args, **kwargs)
 +
 +        if data is not None:
 +            # accept user defined choices
 +            self.fields['queue'].choices += ((data.get('queue'), data.get('queue')), )
 +            self.fields['arguments'].choices += ((v, v) for v in data.getlist('arguments'))
 +            self.fields['properties'].choices += ((v, v) for v in data.getlist('properties'))
 +            self.fields['native'].choices += ((v, v) for v in data.getlist('native'))
  
  
  class EnvForm(forms.Form):
@@@ -184,5 -183,5 +185,5 @@@ class ColumnsForm(forms.Form)
          (HOST, u"Host"),
      )
  
 -    columns = forms.MultipleChoiceField(choices=COLUMNS_CHOICES, label=u"Kolumny", required=False,
 -                                        widget=forms.CheckboxSelectMultiple)
 +    columns = forms.MultipleChoiceField(choices=COLUMNS_CHOICES, initial=[k for k, v in COLUMNS_CHOICES[1:]],
 +                                        label=u"Kolumny", required=False, widget=forms.CheckboxSelectMultiple)
@@@ -96,6 -96,7 +96,6 @@@
              <li role="presentation"><a href="#resources" data-toggle="tab">Zasoby</a></li>
              <li role="presentation"><a href="#files" data-toggle="tab">Pliki</a></li>
              <li role="presentation"><a href="#environment" data-toggle="tab">Środowisko</a></li>
 -            <li role="presentation"><a href="#reservation" data-toggle="tab">Rezerwacja</a></li>
              <li role="presentation"><a href="#monitoring" data-toggle="tab">Powiadomienia</a></li>
              <li role="presentation"><a href="#other" data-toggle="tab">Inne</a></li>
          </ul>
                      </div>
                  </div>
  
 -                {% bootstrap_field form.executable layout="horizontal" form_group_class="form-group collapse"  %}
 +                {% bootstrap_field form.executable layout="horizontal" form_group_class="form-group collapse" %}
 +                {% bootstrap_field form.script layout="horizontal" form_group_class="form-group collapse" %}
                  {% bootstrap_field form.arguments layout="horizontal" %}
 -                {% bootstrap_field form.name layout="horizontal" %}
                  {% bootstrap_field form.note layout="horizontal" %}
                  {% bootstrap_field form.grant layout="horizontal" %}
              </fieldset>
              <fieldset id="resources" class="tab-pane" role="tabpanel">
                  {% bootstrap_field form.host layout="horizontal" %}
                  {% bootstrap_field form.queue layout="horizontal" %}
 +                {% bootstrap_field form.properties layout="horizontal" form_group_class="form-group collapse" %}
 +                {% bootstrap_field form.modules layout="horizontal" form_group_class="form-group collapse" %}
                  {% bootstrap_field form.procs layout="horizontal" %}
                  {% bootstrap_field form.nodes layout="horizontal" form_group_class="form-group collapse" %}
-                 {% bootstrap_field form.wall_time layout="horizontal" %}
+                 {% include 'qcg/time_range_field.html' with field_name='wall_time' field=form.wall_time %}
 -                {% bootstrap_field form.memory layout="horizontal" %}
 -                {% bootstrap_field form.memory_per_slot layout="horizontal" %}
 +                {% bootstrap_field form.memory layout="horizontal" form_group_class="form-group collapse" %}
 +                {% bootstrap_field form.memory_per_slot layout="horizontal" form_group_class="form-group collapse" %}
 +                {% bootstrap_field form.reservation layout="horizontal" form_group_class="form-group collapse" %}
              </fieldset>
  
              <fieldset id="files" class="tab-pane" role="tabpanel">
                  {% bootstrap_field form.input layout="horizontal" %}
 -                {% bootstrap_field form.output layout="horizontal" %}
 -                {% bootstrap_field form.error layout="horizontal" %}
                  {% bootstrap_field form.stage_in layout="horizontal" %}
 -                {% bootstrap_field form.stage_out layout="horizontal" %}
 +                {% bootstrap_field form.stage_out layout="horizontal" form_group_class="form-group collapse" %}
              </fieldset>
  
              <fieldset id="environment" class="tab-pane" role="tabpanel">
 -                {% bootstrap_field form.properties layout="horizontal" %}
                  {{ env_formset.management_form }}
  
                  <div class="form-group">
                          </div>
                      </div>
                  </div>
 -
 -                {% bootstrap_field form.modules layout="horizontal" %}
 -            </fieldset>
 -
 -            <fieldset id="reservation" class="tab-pane" role="tabpanel">
 -                {% bootstrap_field form.not_before layout="horizontal" %}
 -                {% bootstrap_field form.not_after layout="horizontal" %}
 -                {% include 'qcg/time_range_field.html' with field_name='deadline' field=form.deadline %}
 -                {% bootstrap_field form.reservation layout="horizontal" form_group_class="form-group collapse" %}
              </fieldset>
  
              <fieldset id="monitoring" class="tab-pane" role="tabpanel">
                      </div>
                  </div>
  
 -                <div class="form-group">
 -                    <label class="col-sm-3 col-md-4 control-label">Monitorowanie wyjścia</label>
 -                    <div class="col-sm-9 col-md-6">
 -                        <div class="btn-group" data-toggle="buttons">
 -                            {% for option in form.watch_output_type %}
 -                                <label class="btn btn-default">
 -                                    <input type="radio" autocomplete="off" name="{{ option.name }}" value="{{ option.choice_value }}"
 -                                            {% if option.is_checked %}checked{% endif %}
 -                                            data-target=".watch-output-type-{{ option.choice_value }}"> {{ option.choice_label }}
 -                                </label>
 -                            {% endfor %}
 +                <div class="collapse">
 +                    <div class="form-group">
 +                        <label class="col-sm-3 col-md-4 control-label">Monitorowanie wyjścia</label>
 +                        <div class="col-sm-9 col-md-6">
 +                            <div class="btn-group" data-toggle="buttons">
 +                                {% for option in form.watch_output_type %}
 +                                    <label class="btn btn-default">
 +                                        <input type="radio" autocomplete="off" name="{{ option.name }}" value="{{ option.choice_value }}"
 +                                                {% if option.is_checked %}checked{% endif %}
 +                                                data-target=".watch-output-type-{{ option.choice_value }}"> {{ option.choice_label }}
 +                                    </label>
 +                                {% endfor %}
 +                            </div>
                          </div>
                      </div>
 -                </div>
  
 -                <div class="tab-content">
 -                    <div class="tab-pane watch-output-type-0"></div>
 +                    <div class="tab-content">
 +                        <div class="tab-pane watch-output-type-0"></div>
  
 -                    <div class="tab-pane watch-output-type-1 watch-output-type-2" style="margin-top: 15px">
 -                        {% bootstrap_field form.watch_output_address layout="horizontal" %}
 -                        {% bootstrap_field form.watch_output_pattern layout="horizontal" %}
 +                        <div class="tab-pane watch-output-type-1 watch-output-type-2" style="margin-top: 15px">
 +                            {% bootstrap_field form.watch_output_address layout="horizontal" %}
 +                            {% bootstrap_field form.watch_output_pattern layout="horizontal" %}
 +                        </div>
                      </div>
                  </div>
              </fieldset>
  
                  {% bootstrap_field form.native layout="horizontal" %}
                  {% bootstrap_checkbox form.persistent %}
 -                {% bootstrap_checkbox form.use_scratch %}
              </fieldset>
          </div>