[PATCH v3 3/5] patch-list: style modification forms as an action bar

Raxel Gutierrez raxel at google.com
Thu Jul 29 01:24:17 AEST 2021


Added styling to the new patch list html code to make the change
property and bundle action forms more usable. Before [1] and after [2]
images for reference.

[1] https://imgur.com/Pzelipp
[2] https://imgur.com/UtNJXuf

Signed-off-by: Raxel Gutierrez <raxel at google.com>
---
 htdocs/css/style.css | 77 ++++++++++++++++++++++++++++++++++++--------
 patchwork/forms.py   | 44 +++++++++++++++++++------
 2 files changed, 99 insertions(+), 22 deletions(-)

diff --git a/htdocs/css/style.css b/htdocs/css/style.css
index 1bcc93e..9982f92 100644
--- a/htdocs/css/style.css
+++ b/htdocs/css/style.css
@@ -1,3 +1,7 @@
+:root {
+    --light-color: #F7F7F7;
+}
+
 h2 {
     font-size: 25px;
     margin: 18px 0 18px 0;
@@ -122,10 +126,6 @@ a.colinactive:hover {
 div.filters {
 }
 
-div.patch-forms {
-    margin-top: 1em;
-}
-
 /* list order manipulation */
 
 table.patchlist tr.draghover {
@@ -149,7 +149,7 @@ input#reorder-change {
 .paginator {
     text-align: right;
     clear: both;
-        margin: 8px 0 15px;
+    margin: 8px 0 15px;
 }
 
 .paginator .prev-na,
@@ -346,13 +346,62 @@ table.bundlelist td
     padding-right: 2em;
 }
 
+.patch-list-actions {
+    width: 100%;
+    display: inline-flex;
+    flex-wrap: wrap;
+    justify-content: space-between;
+}
+
 /* forms that appear for a patch */
+.patch-forms {
+    display: inline-flex;
+    flex-wrap: wrap;
+    margin: 16px 0px;
+}
+
 div.patch-form {
-    border: thin solid #080808;
-    padding-left: 0.6em;
-    padding-right: 0.6em;
-    float: left;
-    margin: 0.5em 5em 0.5em 10px;
+    display: flex;
+    flex-wrap: wrap;
+    align-items: center;
+}
+
+select[class^=change-property-], .archive-patch-select, .add-bundle {
+    padding: 4px;
+    margin-right: 8px;
+    box-sizing: border-box;
+    border-radius: 4px;
+    background-color: var(--light-color);
+}
+
+#patch-form-archive {
+    display: flex;
+    align-items: center;
+    margin-right: 4px;
+}
+
+#patch-form-archive > label {
+    margin: 0px;
+}
+
+#patch-form-archive > select, #patch-form-archive > input {
+    margin: 0px 4px 0px 4px;
+}
+
+.patch-form-submit {
+    font-weight: bold;
+    padding: 4px;
+}
+
+#patch-form-bundle, #add-to-bundle, #remove-bundle {
+    margin-left: 16px;
+}
+
+.create-bundle {
+    padding: 4px;
+    margin-right: 8px;
+    box-sizing: border-box;
+    border-radius: 4px;
 }
 
 div.patch-form h3 {
@@ -371,15 +420,17 @@ div.patch-form ul {
     margin-top: 0em;
 }
 
-/* forms */
-table.form {
+.create-bundle {
+    padding: 4px;
+    margin-right: 8px;
+    box-sizing: border-box;
+    border-radius: 4px;
 }
 
 span.help_text {
     font-size: 80%;
 }
 
-
 table.form td {
     padding: 0.6em;
     vertical-align: top;
diff --git a/patchwork/forms.py b/patchwork/forms.py
index 3670142..a8d5fb2 100644
--- a/patchwork/forms.py
+++ b/patchwork/forms.py
@@ -53,7 +53,10 @@ class BundleForm(forms.ModelForm):
     field_mapping = {'name': 'bundle_name'}
     name = forms.RegexField(
         regex=r'^[^/]+$', min_length=1, max_length=50, required=False,
-        error_messages={'invalid': 'Bundle names can\'t contain slashes'})
+        error_messages={'invalid': 'Bundle names can\'t contain slashes'},
+        widget=forms.TextInput(
+            attrs={'class': 'create-bundle',
+                   'placeholder': 'Bundle name'}))
 
     # Changes the HTML 'name' attr of the input element from "name"
     # (inherited from the model field 'name' of the Bundle object)
@@ -128,18 +131,28 @@ class PatchForm(forms.ModelForm):
     def __init__(self, instance=None, project=None, *args, **kwargs):
         super(PatchForm, self).__init__(instance=instance, *args, **kwargs)
         self.fields['delegate'] = forms.ModelChoiceField(
-            queryset=_get_delegate_qs(project, instance), required=False)
+            queryset=_get_delegate_qs(project, instance),
+            widget=forms.Select(attrs={'class': 'change-property-delegate'}),
+            required=False)
 
     class Meta:
         model = Patch
         fields = ['state', 'archived', 'delegate']
+        widgets = {
+            'state': forms.Select(
+                attrs={'class': 'change-property-state'}),
+            'archived': forms.CheckboxInput(
+                attrs={'class': 'archive-patch-check'}),
+        }
 
 
 class OptionalModelChoiceField(forms.ModelChoiceField):
-    no_change_choice = ('*', 'no change')
+    no_change_choice = ('*', 'No change')
     to_field_name = None
 
-    def __init__(self, *args, **kwargs):
+    def __init__(self, *args, placeholder, className, **kwargs):
+        self.no_change_choice = ('*', placeholder)
+        self.widget = forms.Select(attrs={'class': className})
         super(OptionalModelChoiceField, self).__init__(
             initial=self.no_change_choice[0], *args, **kwargs)
 
@@ -168,6 +181,10 @@ class OptionalModelChoiceField(forms.ModelChoiceField):
 
 class OptionalBooleanField(forms.TypedChoiceField):
 
+    def __init__(self, className, *args, **kwargs):
+        self.widget = forms.Select(attrs={'class': className})
+        super(OptionalBooleanField, self).__init__(*args, **kwargs)
+
     def is_no_change(self, value):
         return value == self.empty_value
 
@@ -175,17 +192,26 @@ class OptionalBooleanField(forms.TypedChoiceField):
 class MultiplePatchForm(forms.Form):
     action = 'update'
     archived = OptionalBooleanField(
-        choices=[('*', 'no change'), ('True', 'Archived'),
-                 ('False', 'Unarchived')],
+        className="archive-patch-select",
+        choices=[('*', 'No change'), ('True', 'Archive'),
+                 ('False', 'Unarchive')],
         coerce=lambda x: x == 'True',
-        empty_value='*')
+        empty_value='*',
+        label="Archived")
 
     def __init__(self, project, *args, **kwargs):
         super(MultiplePatchForm, self).__init__(*args, **kwargs)
         self.fields['delegate'] = OptionalModelChoiceField(
-            queryset=_get_delegate_qs(project=project), required=False)
+            queryset=_get_delegate_qs(project=project),
+            placeholder="Delegate to",
+            className="change-property-delegate",
+            label="Delegate to",
+            required=False)
         self.fields['state'] = OptionalModelChoiceField(
-            queryset=State.objects.all())
+            queryset=State.objects.all(),
+            placeholder="Change state",
+            className="change-property-state",
+            label="Change state")
 
     def save(self, instance, commit=True):
         opts = instance.__class__._meta
-- 
2.32.0.554.ge1b32706d8-goog



More information about the Patchwork mailing list