Formatting issues with the virtual list in Vaadin 23 - list

I have created a VirtualList to display books information. My renderer presents each book information as an accordion, where first panel is generic book information (author, title, etc.) and it might have three more panels: annotation, commentary, reviews.
It is working as expected, but I do have formatting problems.
Here is my book renderer:
private final ComponentRenderer<Component, Book> bookRenderer = new ComponentRenderer<>(
book -> {
//info panel
Accordion bookPresentation = new Accordion();
HorizontalLayout bookInfo = new HorizontalLayout();
bookInfo.getStyle().set("background-color", book.getHighlight());
bookInfo.setWidth("100%");
UnorderedList authorsList = createAuthorsList(book.getAuthors());
authorsList.setMinWidth("24%");
VerticalLayout taggedTitle = createTaggedTitle(book);
VerticalLayout stars = createStarRating(book);
VerticalLayout readerRating = createReaderRating(book);
VerticalLayout bookStatus = createStatusField(book);
bookInfo.add(authorsList, taggedTitle, stars, readerRating, bookStatus);
AccordionPanel summary = new AccordionPanel(bookInfo);
summary.addThemeVariants(DetailsVariant.SMALL);
summary.addClassName("book-item");
bookPresentation.add(summary);
//annotation panel
if (book.getAnnotation() != null && !book.getAnnotation().isBlank()) {
TextArea annotation = new TextArea();
annotation.setWidth("75%");
annotation.setValue(book.getAnnotation());
annotation.setReadOnly(true);
annotation.setMaxHeight(MAX_HIGHT);
bookPresentation.add("Аннотация", annotation);
}
if (book.getCommentary() != null && !book.getCommentary().isBlank()) {
TextArea comment = new TextArea();
comment.setValue(book.getCommentary());
comment.setReadOnly(true);
comment.setMaxHeight(MAX_HIGHT);
bookPresentation.add("Комментарий", comment);
}
if (book.getReadersReviews() != null && !book.getReadersReviews().isEmpty()) {
Accordion reviews = new Accordion();
for (ReadersReview review : book.getReadersReviews()) {
TextArea reviewText = new TextArea();
reviewText.setMaxHeight(MAX_HIGHT);
reviewText.setValue(review.getReaderComment());
if(user == null || !user.getReaderName().equalsIgnoreCase(review.getReviewerName())) {
reviewText.setReadOnly(true);
}
reviews.add(review.getReviewerName(), reviewText);
}
bookPresentation.add("Мнение читателей", reviews);
}
return bookPresentation;
});
And here is what I am getting on the screen:
I have separation line between accordion panels, but no separation between two items (books) in the list. I'd prefer to have it otherwise. At least I do need to separate one book from another. I did search Vaadin documentation but didn't find any settings that can display such separator between VirtualList items. I'd like to have this separator to be of a different color and line width than accordion panel separator. I followed Joel advise and added border to the styles.css file and added CSS class to the accordion or to its first panel, but it didn't have any effect.
The gap between items in the displayed VirtualList varies significantly as it can be seen on the screenshot. Sometimes items go one after another, and sometimes distance between them can reach 2+ inches. How can I set a fixed distance between these items?
I have set the width of bookInfo panel to 100% but as you can see, it occupies significantly less. I also specify the width of every component and sum of them should be equal to 100%, but as you can see they aren't aligned. What I am missing there?

To put a separator line between items, you'll want to use CSS. One way to do it is to set a CSS class name on your VirtualList items (via your renderer), say "book-item", and then use some CSS like the following:
.book-item {
border-top: 3px solid darkgray;
}
.book-item:first-of-type {
border-top: none;
}

Related

Acumatica-LotSerialNbrAttribute screen on mobile app

I'm using Acumatica customization Acumatica-LotSerialNbrAttribute
This customization adds a new screen for look for InventoryID and LotSerialNbr and visualize its attributes.
I'm trying to add this window to the acumatica mobile app.
Here my code:
add screen IN202501 {
add container "InventoryLotSerialContainers" {
add field "InventoryID"
add field "LotSerialNbr"
add group "Attributes" {
displayName = "Attributes"
collapsable = True
add attributes "AttributesAttributes"
}
add recordAction "Save" {
behavior = Save
}
add recordAction "Cancel" {
behavior = Cancel
}
attachments {
}
}
}
And the screen is visible on the mobile app with the 2 selectors
Then I select Inventory and when I select Lot Serial Nbr, the first selector is in blank, causing that I can't review the attributtes neither save the information.
Here the InventoryID selector in blank.
Hope you can help me to successfully publish this screen on acumatica mobile app.
Thanks.
Attributes are a grid style representation in Acumatica. That means you need a container that will show multiple records. I'm getting rusty on mobile pretty quickly, but I believe your definition is set to display a single value value only.
Try adding a separate container for attributes:
add container "AttributesAttributes" {
add field "Attribute"
add field "Value"
}
This should open into a view of multiple records, showing all of your attributes. By specifying the Attribute and Value fields, you should see both data elements in the container.

Qt/QML: Text with inline QML elements

We are building a graphical user interface with QtQuick/QML. We have some dynamic, multi-line text coming from a database, which should be displayed in the application. Currently, we are using the Text element to display the text. However, we need some QML components inline embedded into the text. For this, the text coming from the database contains placeholders such as ::checkbox|1:: which should then be replaced and displayed by the program.
In HTML, this is easy, you can simply mix inline elements with text to produce a result like this:
but in QML, this seems to be more difficult, as Text elements cannot be word-wrapped into two halves if there is not enough space (both the text and the container size should be dynamic).
The best solution we could come up with, is creating a Flow layout with one Text element for each word, but this seems too hacky.
Using RichText with HTML is not enogh, since we really need our custom QML elements in the text.
Also, we want to avoid using a WebView due to performance reasons.
Is there a sophisticated way to implement this with QML/C++ only?
You can create custom widgets and embed them into QML:
Writing QML Extensions with C++
I haven't tried placing something in the middle, but I did try adding a tag to the beginning (and I might try adding a tag at the end).
QML's Text has a lineLaidOut signal that let's you indent the first line of text.
http://doc.qt.io/qt-5/qml-qtquick-text.html#lineLaidOut-signal
Here's what I did:
Text {
text: issue.summary
onLineLaidOut: {
if (line.number == 0) {
var indent = tagRect.width + tagRect.rightMargin
line.x += indent
line.width -= indent
}
}
Rectangle {
id: tagRect
implicitWidth: padding + tagText.implicitWidth + padding
implicitHeight: padding + tagText.implicitHeight + padding
color: "#400"
property int padding: 2
property int rightMargin: 8
radius: 3
Text {
id: tagText
anchors.centerIn: parent
text: issue.product
color: "#fff"
}
}
}

Sitecore 8: Automatically fill a placeholder by a default rendering

I was playing around with dynamic placeholders and was struck by a prefilling concept.Is there a way to select a default rendering for one of my placeholders which would avoid the "select rendering" dialog in experience editor ??
Scenario: I have a rendeing called "PageHead" which has three renderings. One of them is a placeholder "PageTeaserPh" which currently allows two renderings: one is "PageTeaser" and second "PageTeaserWithImage". I want the placeholder "PageTeaserPh" to always have the rendering selected as "PageTeaser" and therefore avoid the dialog "Select rendering" .
I did some homework and was wondering if this is something related to Standard values (we can have it at template level; not sure for renderings though) and also i have heard of command template concept (not in-depth).
Any and all help appreciated.
You can have renderings assigned on standard values of templates, each new item would then have your PageTeaser rendering.
If you wanted to automate this process have a look at the <mvc.getXmlBasedLayoutDefinition> pipeline, we are injected common renderings by extending this pipeline.
Updated
I've found some code samples and blog posts that should help point you in the right direction for manipulating the layout details.
public void AddSublayoutToItem(string itemId, string sublayoutId)
{
using (new Sitecore.SecurityModel.SecurityDisabler())
{
if (Sitecore.Data.ID.IsID(itemId) && Sitecore.Data.ID.IsID(sublayoutId))
{
//Get the master database and get the item on which you want to add sublayout
Database masterDatabase = Database.GetDatabase("master");
Item item = masterDatabase.GetItem(Sitecore.Data.ID.Parse(itemId));
// Or you can also get Sitecore Item from Context Database as per your requirement
// Item item = Sitecore.Context.Database.GetItem(Sitecore.Data.ID.Parse(itemId));
if (item != null)
{
// Get the layout definitions and the device definition
LayoutField layoutField = new LayoutField(item.Fields[Sitecore.FieldIDs.LayoutField]);
LayoutDefinition layoutDefinition = LayoutDefinition.Parse(layoutField.Value);
DeviceDefinition deviceDefinition = layoutDefinition.GetDevice(Sitecore.Context.Device.ID.ToString());
//Create a RenderingDefinition and add the reference of sublayout or rendering
RenderingDefinition renderingDefinition = new RenderingDefinition();
renderingDefinition.ItemID = sublayoutId;
//Set placeholder where the rendering should be displayed
renderingDefinition.Placeholder = "content";
// Set the datasource of sublayout, if any
renderingDefinition.Datasource = "{24240FF2-B4AA-4EB2-B0A4-63E027934C38}";
// you can also set datasource of sublayout using Sitecore Path
// renderingDefinition.Datasource = "/sitecore/content/Home/Books";
//Add the RenderingReference to the DeviceDefinition
deviceDefinition.AddRendering(renderingDefinition);
// Save the layout changes
item.Editing.BeginEdit();
layoutField.Value = layoutDefinition.ToXml(); ;
item.Editing.EndEdit();
}
}
}
}
Taken from here - http://www.bugdebugzone.com/2014/06/how-to-add-sublayout-to-sitecore-item.html
Also a couple of other blogs on the topic

How to flag new items as unpublished items?

In sitecore, if I add a new item to the master database(Unpublished), it does not show any indication regarding the published state.
For an example, if a user has added 10 items, he might get confused to figureout the items added by him which are pending for publishing.
Is there a way to identify newly added items as unpublished or in new and display a validation in the "Quick action bar"?
Never thought about this, but it's actually pretty easy to fix.
I created a GutterRenderer that indicates wether an item has been published to at least one, to all, or to none of the publishing targets.
EDIT: Added Click behaviour. When you click the gutter icon, the Publish dialog will be shown for that item.
First I will show you the code that I wrote for this and then I'll show you screenshots of the setup and the result.
Here is the code:
using System.Collections.Generic;
using System.Linq;
using Sitecore;
using Sitecore.Data;
using Sitecore.Data.Items;
using Sitecore.Globalization;
using Sitecore.Shell.Applications.ContentEditor.Gutters;
namespace ParTech.Library.Gutters
{
public class PublicationStatus : GutterRenderer
{
private readonly ID publishingTargetsFolderId = new ID("{D9E44555-02A6-407A-B4FC-96B9026CAADD}");
private readonly ID targetDatabaseFieldId = new ID("{39ECFD90-55D2-49D8-B513-99D15573DE41}");
protected override GutterIconDescriptor GetIconDescriptor(Item item)
{
bool existsInAll = true;
bool existsInOne = false;
// Find the publishing targets item folder
Item publishingTargetsFolder = Context.ContentDatabase.GetItem(publishingTargetsFolderId);
if (publishingTargetsFolder == null)
{
return null;
}
// Retrieve the publishing targets database names
List<string> publishingTargetsDatabases = publishingTargetsFolder.GetChildren()
.Select(x => x[targetDatabaseFieldId])
.ToList();
// Check for item existance in publishing targets
publishingTargetsDatabases.ForEach(delegate(string databaseName)
{
if (Database.GetDatabase(databaseName).GetItem(item.ID) != null)
{
existsInOne = true;
}
else
{
existsInAll = false;
}
});
// Return descriptor with tooltip and icon
string tooltip = Translate.Text("This item has not yet been published");
string icon = "People/16x16/flag_red.png";
if (existsInAll)
{
tooltip = Translate.Text("This item has been published to all targets");
icon = "People/16x16/flag_green.png";
}
else if (existsInOne)
{
tooltip = Translate.Text("This item has been published to at least one target");
icon = "People/16x16/flag_yellow.png";
}
return new GutterIconDescriptor()
{
Icon = icon,
Tooltip = tooltip,
Click = string.Format("item:publish(id={0})", item.ID)
};
}
}
}
And this is how so set it up and how it will look once it's running:
Figure 1: Create a new Gutter item in the Core database:
Figure 2: Switch back to your Master database and activate the Gutter by right-clicking in the gutter area.
Figure 3: The Gutter now indicates the publication status of your items
From the top of my head it's not available out of the box. In the core database however, there's the definitions of the gutter, etc. You could create your own.
There's the 'published' field on items though, but I'm not sure if that takes different versions into account.
Maybe you can check the differences between the item in the master and web (i.e. Item doesn't exist or is different version in web, then it's waiting to be published).
Alternatively, have a read through this: http://webcmd.wordpress.com/2011/08/31/sitecore-ribbon-that-displays-published-state-of-an-item/
It'll explain how to check if an item is published as a ribbon.

How to add a new template to Typo3 "Layouts" drop-down list

I have a Typo3 installation with 3 existing layout options. These are all declared in the page.ts file like so:
#normal layout:
[globalVar=TSFE:page|layout=0]
page.10.template.file = fileadmin/template/classic-page.html
page.includeCSS.screen = fileadmin/template/css/style.css
page.includeCSS.screen.media = screen
[global]
And they are all in this list further down the page.ts file, like so:
TCEFORM.pages {
layout.altLabels.0 = Normal
layout.altLabels.1 = Startpage
layout.altLabels.2 = Landing page
}
All of these layout options are displayed in the CMS on the "Edit Page (X)" > Appearance page, in a drop-down list of possible layout options. Handy!
Now I have a shiny new template that I want to add as an option. I can apply it to a specific page id (say, page id #563) by adding this code to the page.ts:
[globalVar = TSFE:id=563]
page.10.template.file = fileadmin/template/shinynewtemplate.html
[GLOBAL]
But I can't seem to add it as a new layout option in the drop-down menu. I have tried this:
#shiny new layout:
[globalVar=TSFE:page|layout=3]
page.10.template.file = fileadmin/template/shinynewtemplate.html
page.includeCSS.screen = fileadmin/template/css/style.css
page.includeCSS.screen.media = screen
[global]
TCEFORM.pages {
layout.altLabels.0 = Normal
layout.altLabels.1 = Startpage
layout.altLabels.2 = Landing page
layout.altLabels.3 = Shiny new page
}
But no banana. It doesn't show up in the Appearance layout list, so I can't apply it to a page.
What am I missing? Is there somewhere else that I need to declare this template file so that it will show up as an option in the drop-down list?
An alternative label does not help, if there is no item which will use your label.
You need to add the new item (Page TS Config!):
TCEFORM.pages {
layout.addItems.3 = Shiny new page
}
See TSconfig