I'm building a new block type for use in the StreamField. It's called an FAQModule and it should allow a title and 1 or more question/answer pairs.
class FAQBlock(blocks.StructBlock):
headline = blocks.TextBlock(help_text="Enter headline / question")
text = blocks.TextBlock(help_text="Enter a description / answer ")
class FAQCardsWithListBlock(blocks.StructBlock):
title = blocks.TextBlock(help_text="Enter FAQ title")
questions = blocks.ListBlock(FAQBlock())
class Meta:
label = 'FAQ Block'
icon = 'help'
It works exactly as expected, and looks like this:
However I want to enforce a min/max number of Q/A blocks. I see that the StreamBlock allows for this but my team and I agree that the interface for the ListBlock implementation is exactly what we want. So I'm working to add a min/max enforcement to our feature based off what's in the StreamBlock implementation. I've gotten it to error on submit, but I can't get the badge to show up in the Content tab, nor can I get the error to show itself in the block.
Does anyone have thoughts on how this might be accomplished?
ListBlock has optional min_num and max_num parameters nowadays. (Official documentation)
In the case of the original question, the solution would look something like:
class FAQCardsWithListBlock(blocks.StructBlock):
questions = blocks.ListBlock(FAQBlock(), min_num=1)
i don't have use StreamBlock for the moment, but the InlinePanel have parameters for minimum / maximum item relation.
http://docs.wagtail.io/en/v2.0/reference/pages/panels.html#inlinepanel
Related
In ReactJS, I get the point of SRP. But I think I'm thinking about it the wrong way. My problem is I don't know when to stop with regards to SRP. Like for the example in Thinking in React. I could easily say that the ProductRow component could be further be broken down to this:
ProductRow - displays a row for each product
ProductRowName - displays the name for each product row
ProductRowPrice - displays the price for each product row
My question now is, how do you know when enough is enough for SRP? What's your cue? I'm hoping to pick up how react devs think so I could apply it on my codes.
Functionality first.
The great thing about react is how it handles reusability of your code. You want to take advantage of that as much as possible. And to best do that, I think both the example and your changes to it fall short of the real goal.
What is the functionality of ProductRow? It's meant to take in an object and then output a table row with information from that object.
If we define exactly what the object is, or exactly which pieces of the object should be output, then we've boxed ourselves into a corner. ProductRow is now only usable for product objects, and requires that those objects have a name and price attribute.
Can we strip some of that specificity out? Can we make a component that has a single responsibility, but without dictating the shape of it's input?
Sure!
var Row = React.createClass({
render: function() {
var item = this.props.item;
var columnNames = this.props.columnNames;
return (
<tr>
{columnNames.map(function(columnName){
return <td> {item[columnName]} </td>;
})}
</tr>
);
}
});
//USAGE: <Row item={product} columnNames={['name', 'price']} />
Now the failing here is that we no longer have unique formatting per column (red name depending on stock status). But that is where we actually reach an issue for SRP. It's time to make a second component, who's responsibility is to create a color map, based on conditions of the input.
I'm trying to use FlxUICheckBox. In the official documentation, the constructor looks like this:
new(X:Float = 0, Y:Float = 0, ?Box:Dynamic, ..)
What is the Box object?
How should I send a Box object as a parameter to this constructor?
I should probably change it to BoxAsset. It's the image asset you want to use for the box part of the checkbox.
A simple checkbox has three components, and looks a bit like this:
[X] Checkbox
Box means the box part, "[ ]"
Check means the check part, "X"
Label means the text that goes in the textfield next to the checkbox
If you don't provide Box or Check, it will use default FlxUIAssets automatically to skin your checkbox. If you provide your own asset (such as "assets/mybox.png" for example), it will use that instead. It is expecting the same sort of thing you would pass into FlxSprite.loadGraphic() -- a String, a BitmapData, or a FlxGraphic.
I should probably also update the type from :Dynamic to :FlxGraphicAsset, I originally wrote this code a long time ago before they added that new helper type.
Edit: To clarify, each of these models are mapped to a database table.
Consider the following scenario. I have a model detailing a payment:
class Payment:
type = ChoiceField(['CASH', 'CREDIT_CARD'])
amount = MoneyField()
One day, the company would like to also store the last four digits of the credit card used, if paying with credit card. Now I have several options:
Option 1: add an "optional" field to Payment that only gets filled if type is CREDIT_CARD:
class Payment:
...
credit_card_no = StringField(required=False)
Option 2: create another class that points to Payment if it's a Credit Card payment:
class CreditCardNumber:
credit_card_no = StringField()
payment = OneToOneRelation(Payment)
But I am unsure which option is preferrable. What is the usual / preferred way to do this?
Well, it really depends on which language platform you are on. I will give you an answer for a Javascript app.
Even if in JS you can add custom properties to any instance completely freely my opinion is that you should keep original properties and optional properties under control with something like this (pseudo code):
class Payment:
type = ...
amount = ...
optional_fields = {}
setField(name, val) ->
this.optional_fields[name] = val
getField(name) ->
return this.optional_fields[name]
This approach let your class to be a well defined entity in your system with no random amount of properties but you are still able to extend it at your will to host optional informations.
If you go with the sub-class approach you may find yourself in defining a high number of sub-classes... like 'PaymentWithCreditCard', 'PaymentWithPayPalAccount', etc... what if you discover that you need to combine different sub-classes? you can easily loose control of it!
I'm trying to use the Stanford OWL API, and I find the documentation a bit unclear. Using Java, I load an ontology which has been prepared by some user via Protégé, and get to a DefaultOWLObjectProperty. The value of that property is meant to be an individual in some class in the ontology. How can I find the class? Code snippet below:
OWLNamedClass cls = (OWLNamedClass) it.next();
Collection instances = cls.getInstances(false);
for (Iterator jt = instances.iterator(); jt.hasNext();) {
OWLIndividual individual = (OWLIndividual) jt.next();
Collection props = individual.getRDFProperties();
for (Object prop : props) {
DefaultOWLObjectProperty obj = (DefaultOWLObjectProperty) prop;
Object val = individual.getPropertyValue(obj);
DefaultRDFIndividual valInd = (DefaultRDFIndividual) val;
…
}
I'd like to get the class of valInd.
There are two methods in OWLIndividual that will make this easier for you. Let's assume you've got your OWLOntology as ontology. Then, using getObjectPropertyValues(OWLOntology), you can get a map that maps a property expression to the set of individuals that are related to individual by that property. You can iterate over the entries of that map, and then iterate over the set of individuals. Then, for each of those individuals, you can use getTypes(OWLOntology) to get the set of OWLClassExpressions that are its types. (You get a set of these rather than a single type, because OWL individuals can, and usually do, have more than one type.)
If you're just interested in the values of certain properties, then you can use the more specialized getObjectPropertyValues(OWLObjectPropertyExpression,OWLOntology) to get just the values of a specific property for an individual.
In general, I'd suggest at least skimming over all the methods that the OWLIndividual interface provides, just to have a general awareness of what you can do with it. You don't need to memorize all the details, but when you are approaching a problem, you'll have at least a vague thought that "I think the interface has something like that…" and you'll know where to look. This is good practice with any API or tool, not just the OWL API.
Can anybody point me in the right direction to how I could use UICollectionViewLayout to create an interface similar to the Pinterest column layout?
I tried searching online, but it looks like there are not many examples out there yet.
The 1000memories "Quilt" view is pinterest-like and open source: http://blog.1000memories.com/168-opensourcing-quilt, and you can dig through that to see how it works.
If you're looking for a more conceptual overview, here's the basic idea of what you're going to want to do. The easiest thing by far, if you just need a Pinterest-style layout, is to subclass UICollectionViewFlowLayout. You get a lot of layout help from this class, and Pinterest style is within its capabilities. You only need to override one method.
Set up a normal UICollectionView using UICollectionViewFlow layout. A quick way to do this is:
Drag a UIViewController onto a storyboard, drop a UICollectionView on that. Set the classes to match your custom classes, etc. You can use a delegate and create a delegate class here but strictly speaking that is not necessary to achieve JUST the Pinterest flow layout (you will almost definitely want to break the selection responsibility stuff into a delegate class in reality though).
Stub out a data source. Implementing the data source protocol for UICollectionView (http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewDataSource_protocol/Reference/Reference.html) is trivially simple. Make sure you set a reuse identifier on your UICollectionViewCell. You need:
(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
just return 1 for now;
(NSInteteger)collectionView:numberOfItemsInSection:
hardcode a number for now, make it 20.
– (UICollectionViewCell *)collectionView:cellForItemAtIndexPath:
This is one of the places where subclassing the flow layout's gonna do you a favor. All you really need to do here is call dequeueReusableCellWithReuseIdentifier:forIndexPath: with the index path. If you added a UIImageView or some labels to the cell, this would be a great place to actually assign the image, text, etc.
In the viewController's viewDidLoad instantiate a UICollectionViewFlowLayout and set the UICollectionView's datasource to yours and layout to flowlayout. Remember, this class is a subclass of UICollectionViewViewController.
self.collectionView.dataSource = [[YourDataSource alloc] init];
self.collectionView.collectionViewLayout = [[UICollectionViewFlowLayout alloc] init];
Ok. At this point you should be able to run your app and see some stuff on the screen. This is a whirlwind overview. If you need more details about how to set up ViewControllers and so on there's tons of stuff available about that.
Now comes the important part, Pinterest-izing the flow layout.
First, add a new class that is a subclass of UIViewControllerFlowLayout. Change your ViewController's viewDidLoad to instantiate this class and assign as the UICollectionView's collectionViewLayout.
The method you are going to need to implement is - (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect.
Here's the thing: The superclass is going to do almost all the work for you. Your code is going to look something like this:
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray *attributes = [super layoutAttributesForElementsInRect:rect];
[attributes enumerateObjectsUsingBlock:^(id attr, NSUInteger idx, BOOL *stop) {
float newYCoord = [calculationMethodYouHaveToWriteFor:attr.frame];
attr.frame = CGRectMake(attr.frame.origin.x, newYCoord, attr.size.width, attr.size.height];
}];
}
Pinterest uses fixed-width columns, all you need to do in your calculation method is figure out what column you are in (`attr.origin.x / _columnWidth), and look up the total height in that column from the ivar you've been saving it in. Don't forget to add it to the new object's height and save it back for the next pass.
The flow layout superclass handles: making cells, determining which cells are visible, figuring out the contents size, figuring out the arrangement of the rows in the x direction, assigning index paths to cells. Lots of junk. And overriding that one method lets you fiddle with the y-pos to your heart's desire.
Heres two from github
https://github.com/jayslu/JSPintDemo
https://github.com/chiahsien/UICollectionViewWaterfallLayout
I've used a modified version of Waterfall in a project now, and I'm investigating JSPint now.
I have created a custom uicollectionviewlayout which is used in my personal project. Here is the link. Hope it helps.
https://github.com/johnny0614/YJZAlbumCollectionViewLayout
You can get anything you want from here:
https://github.com/ParsifalC/CPCollectionViewKit
For example(Both these two layouts are custom UICollectionViewLayout):