Active Sessions Page (Card Design/Frontend Recipe)

Preview:
image

Card Component:

package de.bytestore.hostinger.components.cards;

import com.vaadin.flow.component.orderedlayout.VerticalLayout;

public class Card extends VerticalLayout {
    /**
     * Constructs an empty layout with spacing and padding on by default.
     */
    public Card() {
        this.addClassName("card");
    }
}

SessionCard Component:

package de.bytestore.hostinger.components.cards;

import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.H5;
import com.vaadin.flow.component.html.Image;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.dom.Style;
import de.bytestore.hostinger.components.Badge;
import de.bytestore.hostinger.components.ImageText;
import lombok.Getter;

public class SessionCard extends Card {
    @Getter
    private final Button logout = new Button(VaadinIcon.SIGN_OUT.create());

    @Getter
    private Span hostname = new Span("IP-Address: 0.0.0.0");

    @Getter
    private Span browser = new Span("Browser: Mozilla");

    @Getter
    private ImageText location = new ImageText();

    @Getter
    protected Badge badge = new Badge("Placeholder");

    @Getter
    protected H5 title = new H5("Session Placeholder");

    @Getter
    protected Image icon = new Image("icons/windows.svg", "Client Icon");

    public SessionCard() {
        HorizontalLayout containerIO = new HorizontalLayout();
        containerIO.setAlignItems(Alignment.STRETCH);
        containerIO.setJustifyContentMode(JustifyContentMode.BETWEEN);
        containerIO.setWidthFull();
        containerIO.setDefaultVerticalComponentAlignment(Alignment.CENTER);

        HorizontalLayout leftIO = new HorizontalLayout();
        leftIO.setAlignItems(Alignment.CENTER);
        leftIO.setDefaultVerticalComponentAlignment(Alignment.CENTER);

        // Add Left Layout to Container.
        containerIO.add(leftIO);

        icon.setWidth("3rem");
        icon.setHeight("3rem");

        // Add Left Icon to Container.
        leftIO.add(icon);

        VerticalLayout textLayout = new VerticalLayout();

        // Set Text Layout.
        textLayout.setJustifyContentMode(JustifyContentMode.BETWEEN);
        textLayout.setAlignItems(Alignment.CENTER);
        textLayout.setSpacing(false);

        // Create new Title Container.
        HorizontalLayout titleLayout = new HorizontalLayout();
        titleLayout.setAlignItems(Alignment.CENTER);
        titleLayout.setWidthFull();
        titleLayout.setJustifyContentMode(JustifyContentMode.START);

        // Add Title Element to Container.
        titleLayout.add(title);

        // Set Badge Small.
        badge.getElement().getThemeList().add("small");

        // Add Badge Element to Container.
        titleLayout.add(badge);

        // Add Title Container.
        textLayout.add(titleLayout);

        // Create new Container for Description.
        VerticalLayout descriptionLayout = new VerticalLayout();
        descriptionLayout.setSpacing(false);
        descriptionLayout.setPadding(false);

        // Add Image Layout to Description Container.
        descriptionLayout.add(location);

        // Add Hostname Item.
        descriptionLayout.add(hostname);

        // Add Browser Item.
        descriptionLayout.add(browser);

        // Add Image Layout to Text Layout.
        textLayout.add(descriptionLayout);

        // Add Text Layout.
        leftIO.add(textLayout);

        // Create new Logout Button.
        logout.setDisableOnClick(true);
        logout.getElement().getStyle().setFloat(Style.FloatCss.RIGHT);

        // Add Logout Button to Container.
        containerIO.add(logout);


        add(containerIO);
    }
}

Stylesheet:

.card {
    background-color: var(--lumo-contrast-5pct);
    border-radius: 0.5rem;
}

.card.hover:hover {
    background-color: var(--lumo-contrast-10pct);
}

Icons and Pictures are from: Download 1,328,900 free icons (SVG, PNG)

The backend part is a bit more complicated and will follow on occasion :slight_smile:

I hope I could inspire you for a session page.

Have fun putting it into practice :slight_smile:

7 Likes

Is that Cards in a list? How did you use a data source?

Because Vaadin/JMIX stores Sessions inside an Array, I don’t use a DataSource (Just a forEach Loop).

The Card is appended to a VerticalLayout.

1 Like

Thanks.
Did you consider this option dynamically switched between desktop user and small device users?

As I tested it in JMIX 2.3 there were no responsive problems on mobile devices.