From patchwork Thu Jul 22 17:12:49 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Raxel Gutierrez X-Patchwork-Id: 1508811 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=2404:9400:2:0:216:3eff:fee1:b9f1; helo=lists.ozlabs.org; envelope-from=patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=G9cQAfDi; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2404:9400:2:0:216:3eff:fee1:b9f1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GVzYr1wxbz9sRR for ; Fri, 23 Jul 2021 03:13:36 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4GVzYr10Vwz30Jf for ; Fri, 23 Jul 2021 03:13:36 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=G9cQAfDi; dkim-atps=neutral X-Original-To: patchwork@lists.ozlabs.org Delivered-To: patchwork@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=flex--raxel.bounces.google.com (client-ip=2607:f8b0:4864:20::74a; helo=mail-qk1-x74a.google.com; envelope-from=3mkf5yaukcxmirovcxffxcv.tfdgrktynfibczjkj.fqcrsj.fix@flex--raxel.bounces.google.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20161025 header.b=G9cQAfDi; dkim-atps=neutral Received: from mail-qk1-x74a.google.com (mail-qk1-x74a.google.com [IPv6:2607:f8b0:4864:20::74a]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4GVzYb3f8qz30Cd for ; Fri, 23 Jul 2021 03:13:23 +1000 (AEST) Received: by mail-qk1-x74a.google.com with SMTP id h22-20020a05620a13f6b02903b94aaa0909so4581881qkl.15 for ; Thu, 22 Jul 2021 10:13:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=+GgBjVmdgDR9Oe4Ovm4XJT9/d0WTTG9IOLj9PqK2H7I=; b=G9cQAfDi924tokWW96ZcK/SxS5VoiEGrAsGcT8I3EeVSsgNyOAp/HldXhHrd/teRQP FFhA0tP8z6ys/DjND9bOQGM3LGts6gNbVb3wDOlm1pMBT2DwDozOoZJZJt0FQyzPmtTs mUstGDrY+15xheJSyvuGa4o5GybMSSIB7SMrLg9EcStPeK5gHKvCLRJAxpSZ10YVo7Hp 6WwTkyVFYfwj+y9CWH2Tnx1UIaoJgiphmD2NwfKh6fQszjOXuimxRSjaAjWzTkdG/ASj ENX4Rpfe4XYHA1PHHpZX/pfrXba7t7curW0tN5suB0HOc+t8o9TNsa3PbSLJA3RL5lCd IMqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=+GgBjVmdgDR9Oe4Ovm4XJT9/d0WTTG9IOLj9PqK2H7I=; b=XrcN86WeBbtCzULD3ugA5kDiiUbXMd1n3mhH0T4sfIvwBnV/dE3WOZzrOXOrnoMEdP o7COTJPCd5Uq7FJ3bCqP5qRqj1hG8tspe2V5EWtehjt2V1RFtQCdmuD+lnNLSalMb2s1 t6HG/k27gg0Gx68cHR6V7+LhTaelW5wl4W41ASHzbhTYmGpbSxLXj2iEwOqrQSP6rowS tvpdbCmTaRlNKeJo1GYu/2wxyP+cFMJqFTTcTnj9qNy+cnft4gJaCbCeQm4vFsamv9Vk QNQtrV85ZtFB6GNiihmyJ4hWSPcayXQQZhSIB+6J7JGZVPVZFwQO4lu04sh8nmy5AqpU NluA== X-Gm-Message-State: AOAM533XV2wHW5PDbS72fL4C93YPaKFCXxoPYD0FnzILJ/9byn5Kcmgy pgr6acOJpM7XZxVn8Z55K3nPKagihb3QFRxc1da2vo6chBYseM25RHcoWgkfr1U1yGerH/swL+G 2T3vNfQARHzABj2jwhhwf/IWWSvjPKQ3KQq9LW6zUys2Vqt6eIbVWm7CEb0TU7BB+ X-Google-Smtp-Source: ABdhPJxJbcv6pMOSVoGSUqrY5PjBqz5SpYF7NTzKaMpcg/DdFhqFcMLp3KarNBRE6mLIXIuMrN/zZduAXA== X-Received: from raxel-pw.c.googlers.com ([fda3:e722:ac3:cc00:14:4d90:c0a8:2fda]) (user=raxel job=sendgmr) by 2002:a05:6214:3004:: with SMTP id ke4mr976381qvb.52.1626974000646; Thu, 22 Jul 2021 10:13:20 -0700 (PDT) Date: Thu, 22 Jul 2021 17:12:49 +0000 In-Reply-To: <20210722171251.2554142-1-raxel@google.com> Message-Id: <20210722171251.2554142-4-raxel@google.com> Mime-Version: 1.0 References: <20210722171251.2554142-1-raxel@google.com> X-Mailer: git-send-email 2.32.0.432.gabb21c7263-goog Subject: [PATCH v2 3/5] patch-list: style modification forms as an action bar From: Raxel Gutierrez To: patchwork@lists.ozlabs.org X-BeenThere: patchwork@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Patchwork development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: patchwork-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Patchwork" 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 Reviewed-by: Jonathan Nieder --- 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 7f1fd31..9727932 100644 --- a/patchwork/forms.py +++ b/patchwork/forms.py @@ -54,7 +54,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'})) # Maps form fields 'name' attr rendered in HTML element def add_prefix(self, field_name): @@ -126,18 +129,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) @@ -166,6 +179,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 @@ -173,17 +190,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