1. ホーム
  2. jsf

[解決済み] p:dashboardが終了してもソート順を維持する。

2022-03-01 18:37:59

質問

このprimefacesのダッシュボードを使いたいのですが。 https://www.primefaces.org/showcase/ui/panel/dashboard.xhtml

ダッシュボード.xhtml

<div style="height:500px">
    <h:form>
        <p:growl id="msgs" showDetail="true" />

        <p:dashboard id="board" model="#{dashboardView.model}">
            <p:ajax event="reorder" listener="#{dashboardView.handleReorder}" update="msgs" />

            <p:panel id="sports" header="Sports">
                <h:outputText value="Sports Content" />
            </p:panel>

            <p:panel id="finance" header="Finance">
                <h:outputText value="Finance Content" />
            </p:panel>

            <p:panel id="lifestyle" header="Lifestyle">
                <h:outputText value="Lifestyle Content"  />
            </p:panel>

            <p:panel id="weather" header="Weather">
                <h:outputText value="Weather Content" />
            </p:panel>

            <p:panel id="politics" header="Politics">
                <h:outputText value="Politics Content" />
            </p:panel>
        </p:dashboard>

        <div style="clear:both" />
    </h:form>
</div>

DashBoardView.java

package org.primefaces.showcase.view.panel;

import java.io.Serializable;
import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.primefaces.event.CloseEvent;
import org.primefaces.event.DashboardReorderEvent;
import org.primefaces.event.ToggleEvent;
import org.primefaces.model.DashboardColumn;
import org.primefaces.model.DashboardModel;
import org.primefaces.model.DefaultDashboardColumn;
import org.primefaces.model.DefaultDashboardModel;

@ManagedBean
@ViewScoped
public class DashboardView implements Serializable {

    private DashboardModel model;

    @PostConstruct
    public void init() {
        model = new DefaultDashboardModel();
        DashboardColumn column1 = new DefaultDashboardColumn();
        DashboardColumn column2 = new DefaultDashboardColumn();
        DashboardColumn column3 = new DefaultDashboardColumn();

        column1.addWidget("sports");
        column1.addWidget("finance");

        column2.addWidget("lifestyle");
        column2.addWidget("weather");

        column3.addWidget("politics");

        model.addColumn(column1);
        model.addColumn(column2);
        model.addColumn(column3);
    }

    public void handleReorder(DashboardReorderEvent event) {
        FacesMessage message = new FacesMessage();
        message.setSeverity(FacesMessage.SEVERITY_INFO);
        message.setSummary("Reordered: " + event.getWidgetId());
        message.setDetail("Item index: " + event.getItemIndex() + ", Column index: " + event.getColumnIndex() + ", Sender index: " + event.getSenderColumnIndex());

        addMessage(message);
    }

    public void handleClose(CloseEvent event) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, "Panel Closed", "Closed panel id:'" + event.getComponent().getId() + "'");

        addMessage(message);
    }

    public void handleToggle(ToggleEvent event) {
        FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO, event.getComponent().getId() + " toggled", "Status:" + event.getVisibility().name());

        addMessage(message);
    }

    private void addMessage(FacesMessage message) {
        FacesContext.getCurrentInstance().addMessage(null, message);
    }

    public DashboardModel getModel() {
        return model;
    }
}

とてもクールな機能です。

ドラッグ&ドロップで作る

をクリックし、ブラウザのタブを閉じてからもう一度開くと、すべてデフォルトになります。

どうにかしてこの順番を守りたい。

おそらく、何らかの方法でクッキーを使用するか、その他の方法をとると思います。それは可能ですか、もし可能ならどのようにするのですか?

重要なのは、ウィジェットの順序がすべてのユーザーに対して保存されるべきであるということです。これは、次の2つのオプションのうちの1つを意味します。 :

  1. すべてのログインユーザーは、すべてのデバイスでこの順序を見ることができます。
  2. ブラウザにログインせず、新しいブラウザを開いたときに、デフォルトで表示されるようにする。または、他のユーザーが開いたとき、その順序はデフォルトであるべきです。

解決方法は?

確かにベストな解決策ではありませんが、解決策はあります。

handleReorder(DashboardReorderEvent event)のイベントをデータベースかファイルに保存することでしょうかね。そして、ポストコンストラクトのinitでオーダーをロードします。どうでしょうか?

コメントで書いたように、私の場合、イベントをシリアライズすることは不可能です。

2回目の挑戦はこのような感じです。

public void handleReorder(DashboardReorderEvent event) {
        FacesMessage message = new FacesMessage();
        message.setSeverity(FacesMessage.SEVERITY_INFO);
        message.setSummary("Reordered: " + event.getWidgetId());
        message.setDetail("Item index: " + event.getItemIndex() + ", Column index: " + event.getColumnIndex() + ", Sender index: " + event.getSenderColumnIndex());

        addMessage(message);

        serializeEvent(event);
    }

serializeEventメソッドは、私に失敗したので、イベントをシリアライズしませんが、必要な情報を持つオブジェクトをシリアライズします。

private void serializeEvent(DashboardReorderEvent event) {
        String userName = userBean.getUserName();
        StackoverflowObject e = new StackoverflowObject(event);
        try {
            FileOutputStream fileOut =
            new FileOutputStream("c:/tmp/events"+userName+".txt");
            ObjectOutputStream out = new ObjectOutputStream(fileOut);
            out.writeObject(e);
            //out.writeObject(event.getWidgetId()+";"+  event.getItemIndex()+";"+ event.getColumnIndex());
            out.close();
            fileOut.close();

         } catch (Exception i) {
            i.printStackTrace();
         }
    }

で、シリアライズされたオブジェクトを読み込んで、ウィジェットをどこに配置するかを決めます。これはそのアイデアを示すものです(午前1時近くなので、冒頭部分のみをお見せします)。

@PostConstruct
    public void init() {
        model = new DefaultDashboardModel();
        DashboardColumn column1 = new DefaultDashboardColumn();
        DashboardColumn column2 = new DefaultDashboardColumn();
        DashboardColumn column3 = new DefaultDashboardColumn();
        StackoverflowObject e =   deserializeEvent("politics");

        if (e != null &&"politics".equalsIgnoreCase(e.getWidgetId()) && e.getColumnId() == 0){
            column1.addWidget("politics");
        } else   if (e != null &&"politics".equalsIgnoreCase(e.getWidgetId()) && e.getColumnId() == 1){
            column2.addWidget("politics");
        }
        else{
            column3.addWidget("politics");
        }

... 他のすべてのウィジェットにも同じことをします。

ここで、ユーザーごとに行うかという問題もあります。deserializeEventメソッドはユーザーを決定し、そのユーザーのために正しいファイルを読み取ります。

どうやってユーザーを取得するのかというと。ほとんどの場合、次のようになります。

FacesContext.getCurrentInstance().getExternalContext().getRemoteUser()

私の例のようにloginbeanを持っている場合、userBeanからそれを取得することができます。

stackoverflowObjectを編集すると、次のようになります。

public class StackoverflowObject implements Serializable{


/**
 * 
 */
private static final long serialVersionUID = -4921468076398836905L;
private String widgetId;
private int columnId;
private int itenId;
public StackoverflowObject(DashboardReorderEvent event) {
    this.setWidgetId(event.getWidgetId());
    this.setColumnId(event.getColumnIndex());
    this.setItenId(event.getItemIndex());
}

// +getterとsetter