-
Notifications
You must be signed in to change notification settings - Fork 22
Label/header customisation and better defaults #16
Conversation
@kaedroho I can't seem to get this to compile. I'm not much of a frontend developer and I haven't touched typescript before, so I may have made some mistakes. Error is:
Which doesn't look related to my change though. Can you have a look? All I'm trying to do is pass through the label value to the right place. |
This compiled for me, what version of Typescript do you have installed? (i'm using |
@@ -178,7 +179,7 @@ export class CardSet extends React.Component<CardSetProps, {}> { | |||
e.preventDefault(); | |||
return false; | |||
}; | |||
addButton = <button className="condensed-inline-panel__top-add-button button bicolor icon icon-plus" type="button" onClick={onClickAddButton}>Add</button>; | |||
addButton = <button className="condensed-inline-panel__top-add-button button bicolor icon icon-plus" type="button" onClick={onClickAddButton}>Add {this.props.panelLabel}</button>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm thinking it might be nicer to make the panelLabel
argument replace the whole label, including "Add". This would be useful for people working in languages that might put the word for "Add" after the label.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me. I was mainly mimicking what inline panel did, but this also solves my problem.
We should then put Add as the default where the string constant is set.
and looks like my version of typescript is I downgraded to your version, and that fared somewhat better, but for some reason the webpack bundle had a ton of random little changes. |
Ok, have played with this a bit. Gotten it to work. Missed some bits, and have decided to also tweak things a little. Silly thing that Inline panel does is use the label for both the ADD button and the Heading. Which is weird, but whatever. I've added a heading value to this panel, but have it default to label is not set, so that it doesn't break existing usage. I'll propose a patch to fix that in core wagtail for the inlinepanel because it makes sense there too provided it still works the same until the use the heading value itself. Will submit a new patch. I've gotten it to compile myself, but my version of webpack is different, so it adds a lot of random stuff which is unrelated. Better for you to just recompile it and test that it makes sense. |
Ok, cool. That should do it! Please compile and test yourself, and see if that works for you. :) |
@@ -176,7 +177,8 @@ def bind_to_model(self, model): | |||
'relation_name': self.relation_name, | |||
'related': related, | |||
'panels': self.panels, | |||
'heading': self.label, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should leave the heading field called label
so it's the same as Wagtail's builtin InlinePanel
.
EDIT: Scratch that. What you suggested in your last comment sounds good to me
@@ -176,7 +177,8 @@ def bind_to_model(self, model): | |||
'relation_name': self.relation_name, | |||
'related': related, | |||
'panels': self.panels, | |||
'heading': self.label, | |||
'heading': self.heading, | |||
'label': self.label, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be really nice is the add label defaulted to "add {{ model name }}", so it works the same as InlinePanel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will add that in tomorrow (hopefully).
Thanks @Adrian-Turjak!
Yeah, this is rather annoying. I've noticed it happens when two people are using different OSes (I'm using Linux). |
So i'm looking at having the default be "Add {model name}" but... I can't seem to see how if at all
I'll add this to the condensed version, and potentially also to the core one since that does appear odd. @kaedroho Can you a double check I'm not going mad and that |
* label now defaults to "Add {model name}" * heading defaults to "{model name}" * card heading now defaults to __str__() for the related model rather than an empty string, and the heading for new cards will be "New {model name}" until the page is saved. * When card_header_from_field is used, new cards will at first have "New {model name}" as the heading until the card is closed and updated. * Default new card heading of "New {model name}" will not be set for card_header_from_js as it is unsafe to assume status of 'value' var and it is better to allow a default to be set in the user defined js.
latest commit handles default cases a little better, and also deals with #5 while I'm at it. I think we're pretty much done. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Adrian-Turjak. Thanks for putting this together. As promised, I had time to check things out. It's very nearly there. I just have a few recommendations for where things might be improved.
@@ -171,12 +174,17 @@ def bind_to_model(self, model): | |||
else: | |||
related = getattr(model, self.relation_name).related | |||
|
|||
related_name = camelcase_to_underscore( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The labelling of Django models is conventionally configured by setting verbose_name
and verbose_name_plural
strings on a model's Meta
class. It's quite common for those strings to be marked for translation too (as they are in wagtailmenus) to adjust labelling appropriately for different languages. So, I think we need to be making better use of those here.
related.related_model._meta.verbose_name_plural.capitalize()
would be a better fit for a default heading
. I suggest using capitalize()
instead of title()
too, as it doesn't make sense to mess with a developer's specified labelling any more than necessary (this is more in keeping with treatment of verbose names within the rest of Wagtail also).
And _("New {model_verbose_name}").format(model_verbose_name=related.related_model._meta.verbose_name)
would be a better choice the new item card header (with no case manipulation at all).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! This is much better. I just blanked on this and didn't think it through. Will follow up with that change.
@@ -154,9 +156,10 @@ def required_formsets(cls): | |||
|
|||
|
|||
class CondensedInlinePanel(object): | |||
def __init__(self, relation_name, panels=None, label='', help_text='', min_num=None, max_num=None, card_header_from_field=None, card_header_from_js=None, card_header_from_js_safe=None): | |||
def __init__(self, relation_name, panels=None, heading='', label='', help_text='', min_num=None, max_num=None, card_header_from_field=None, card_header_from_js=None, card_header_from_js_safe=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we are allowing heading
and label
to be set independently, for completeness, should we add a new argument to allow the new item header text to be set independently too? Maybe as new_card_header_text
? I think this could be quite useful (For example, I would probably use this in wagtailmenus to set this text to just "New item"
, because with the heading and add button both mentioning 'menu items', repeating that again in card headers seems a little unnecessary).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why not. It's easy and can just be one extra arg most people can ignore if not needed.
* switch to using verbose_name * add basic translation support for these values * add new_card_header_text arg to panel for an easy user set override.
@ababic Back to you. :) And when/if you use this for wagtailmenus, I will be more than happy to review and test! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking very nice indeed! Just a few more tiny things.
related.related_model.__name__).replace("_", " ").title() | ||
heading = self.heading or _(related.related_model._meta.verbose_name_plural.capitalize()) | ||
new_card_header = self.new_card_header_text or _("New %s" % related.related_model._meta.verbose_name) | ||
label = self.label or _('Add %s' % related.related_model._meta.verbose_name.capitalize()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say that capitalising verbose_name
for label
here probably isn't necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might not be priority for the project at this point in time, but using named parameter substitution for translatable strings helps to generate much nicer source files for translators to work from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will drop the capitalising.
Also will redo the translations. I actually haven't played with translations much and didn't actually realise that in your examples you were calling .format
after the _
call. I've just had a quick read through the django docs and realised that with their example:
output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d}
I'll update with a new commit.
Although because I find it less verbose and easier to read, I tend to stick with old style string formatting unless I explicitly need new style features, so apologies in advance for that. They can take it away from me when they deprecate it (which probably won't happen). :P
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I must admit I still find myself using both in different places. I have a mild preference for format() recently though. Happy with this 😀
@@ -156,7 +156,7 @@ def required_formsets(cls): | |||
|
|||
|
|||
class CondensedInlinePanel(object): | |||
def __init__(self, relation_name, panels=None, heading='', label='', help_text='', min_num=None, max_num=None, card_header_from_field=None, card_header_from_js=None, card_header_from_js_safe=None): | |||
def __init__(self, relation_name, panels=None, heading='', label='', help_text='', min_num=None, max_num=None, card_header_from_field=None, card_header_from_js=None, card_header_from_js_safe=None, new_card_header_text=""): | |||
self.relation_name = relation_name | |||
self.panels = panels | |||
self.heading = heading or label |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure using label
for heading
here under these conditions is very intuitive now that we define a more sensible default for heading lower down. I think we're just doing this for the sake of backwards compatibility, but I think it would be better instead to decouple the two completely and include some guidance in the release notes. Any thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I think this panel type isn't being used widely, I tend to lean towards backwards compatibility for any changes unless entirely unavoidable.
Plus, a lot of what I've ended up doing here, even with the defaults we've now added, I actually want to move to the standard wagtail inline panel, so keeping the changes here, and there in sync so the two are pretty much drop in replacements for each other (apart from card_header args) is useful. I've already started with: wagtail/wagtail#3765
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with that. Might be a good idea to mark it with a TODO comment or something though, to make that clear. Maybe somethings like:
# TODO: label is used below for backwards compatibility. We may want to rethink this later.
self.heading = heading or label
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done :)
{% endif %} | ||
|
||
if (value==null){ | ||
var value = ""; | ||
var needsEscaping = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for var
here
renderCardHeader: function(form) { | ||
{% if self.card_header_from_field %} | ||
{# Get the card header value from a field and escape it #} | ||
var value = form.fields['{{ self.card_header_from_field|escapejs }}']; | ||
if (value===null){ | ||
var value = "{{ self.new_card_header }}"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for var
here too
renderCardHeader: function(form) { | ||
{% if self.card_header_from_field %} | ||
{# Get the card header value from a field and escape it #} | ||
var value = form.fields['{{ self.card_header_from_field|escapejs }}']; | ||
if (value===null){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the form is not new but the value of the specified field is null
? Perhaps we should check form.isNew
here instead?
@@ -108,6 +109,7 @@ def get_form_extra_data(form): | |||
'forms': [ | |||
{ | |||
'id': i, | |||
'as_str': str(form.instance), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attributes on the form should be camel case and we should also add this to the Form
interface in types.ts
.
I wonder if as_str
is descriptive enough, perhaps we should name it instanceAsStr
to make it clearer it's referring to the saved instance rather than the form's current state?
Thanks both of you for your continued effort on this, it's looking good! Just a couple of small issues remaining. |
* some minor js clean up
@kaedroho I've added six support since I ran into a unicode error with str in py27, and hopefully also addressed all your comments. Needs a js recompile which i've left for you, since my webpack is different. :P |
@kaedroho Any chance to recompile and review my last few changes? Want to get this merged, since then you can release a new version on pypi and I can start using it in my projects. ;) |
Apologies for the delay (been on holiday). These changes look good to me, thanks! |
@kaedroho more than welcome! And when you publish a new version to pypi I'll start using this in my current project. ;) |
Deals with #15
Needs to be compiled and tested, but this should achieve what we want, or be close to it.