From 6c738d6e7c60600da8e9d00d82caae5c71f7011f Mon Sep 17 00:00:00 2001 From: Eduardo Teixeira Date: Mon, 6 Apr 2026 17:19:09 +0100 Subject: [PATCH] update ui for representation information. --- .../config/i18n/client/ClientMessages.java | 9 + .../BrowseRepresentationInformationTabs.java | 114 ++++++ .../wui/client/browse/tabs/DetailsTab.java | 9 + ...presentationInformationActionsToolbar.java | 33 ++ .../RepresentationInformationActions.java | 4 +- .../roda/wui/client/common/resources/main.gss | 1 + .../roda/wui/client/main/BreadcrumbUtils.java | 20 + ...DetailsPanelRepresentationInformation.java | 189 ++++++++++ ...tailsPanelRepresentationInformation.ui.xml | 9 + .../ShowRepresentationInformation.java | 347 ++---------------- .../ShowRepresentationInformation.ui.xml | 88 +---- .../i18n/client/ClientMessages.properties | 8 +- 12 files changed, 431 insertions(+), 400 deletions(-) create mode 100644 roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/BrowseRepresentationInformationTabs.java create mode 100644 roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/BrowseRepresentationInformationActionsToolbar.java create mode 100644 roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.java create mode 100644 roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.ui.xml diff --git a/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java b/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java index 135c05fdf1..52eb703443 100644 --- a/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java +++ b/roda-ui/roda-wui/src/main/java/config/i18n/client/ClientMessages.java @@ -1018,6 +1018,10 @@ SafeHtml searchPreFilterLongRangeFilterParameterGreaterThan(String searchPreFilt String detailsCreatedBy(); + String detailsUpdatedOn(); + + String detailsUpdatedBy(); + String detailsModifiedOn(); String detailsModifiedBy(); @@ -1322,10 +1326,15 @@ SafeHtml searchPreFilterLongRangeFilterParameterGreaterThan(String searchPreFilt String representationInformationIntellectualEntities(@PluralCount int size, String link); + String representationInformationIntellectualEntitiesAssociations(); + String representationInformationRepresentations(@PluralCount int size, String link); + String representationInformationRepresentationsAssociations(); + String representationInformationFiles(@PluralCount int size, String link); + String representationInformationFilesAssociations(); /****** Descriptive Metadata ****/ String metadataType(); diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/BrowseRepresentationInformationTabs.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/BrowseRepresentationInformationTabs.java new file mode 100644 index 0000000000..5cb7184b55 --- /dev/null +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/BrowseRepresentationInformationTabs.java @@ -0,0 +1,114 @@ +package org.roda.wui.client.browse.tabs; + +import java.util.ArrayList; +import java.util.List; + +import org.roda.core.data.common.RodaConstants; +import org.roda.core.data.utils.RepresentationInformationUtils; +import org.roda.core.data.v2.index.IsIndexed; +import org.roda.core.data.v2.index.filter.Filter; +import org.roda.core.data.v2.index.filter.FilterParameter; +import org.roda.core.data.v2.index.filter.OrFiltersParameters; +import org.roda.core.data.v2.index.filter.SimpleFilterParameter; +import org.roda.core.data.v2.ip.IndexedAIP; +import org.roda.core.data.v2.ip.IndexedFile; +import org.roda.core.data.v2.ip.IndexedRepresentation; +import org.roda.core.data.v2.ri.RepresentationInformation; +import org.roda.wui.client.common.lists.utils.AsyncTableCellOptions; +import org.roda.wui.client.common.lists.utils.ConfigurableAsyncTableCell; +import org.roda.wui.client.common.lists.utils.ListBuilder; +import org.roda.wui.client.common.search.SearchWrapper; + +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.Widget; + +/** + * + * @author Eduardo Teixeira + */ +public class BrowseRepresentationInformationTabs extends Tabs { + public void init(RepresentationInformation ri) { + + List aipParams = new ArrayList<>(); + List representationParams = new ArrayList<>(); + List fileParams = new ArrayList<>(); + initEntityFilters(ri, aipParams, representationParams, fileParams); + + createAndAddTab(SafeHtmlUtils.fromSafeConstant(messages.detailsTab()), new TabContentBuilder() { + @Override + public Widget buildTabWidget() { + return new DetailsTab(ri); + } + }); + + createAndAddTab(SafeHtmlUtils.fromString(messages.representationInformationIntellectualEntitiesAssociations()), + () -> buildAssociationsTab(IndexedAIP.class, aipParams, "Search_AIPs")); + + createAndAddTab(SafeHtmlUtils.fromString(messages.representationInformationRepresentationsAssociations()), + () -> buildAssociationsTab(IndexedRepresentation.class, representationParams, "Search_representations")); + + createAndAddTab(SafeHtmlUtils.fromString(messages.representationInformationFilesAssociations()), + () -> buildAssociationsTab(IndexedFile.class, fileParams, "Search_files")); + } + + private void initEntityFilters(RepresentationInformation ri, List aipParams, + List representationParams, List fileParams) { + for (String filter : ri.getFilters()) { + String[] parts = filter.split(RepresentationInformationUtils.REPRESENTATION_INFORMATION_FILTER_SEPARATOR); + if (parts.length < 3) { + continue; + } + + if (RodaConstants.INDEX_AIP.equals(parts[0])) { + aipParams.add(new SimpleFilterParameter(parts[1], parts[2])); + } else if (RodaConstants.INDEX_REPRESENTATION.equals(parts[0])) { + representationParams.add(new SimpleFilterParameter(parts[1], parts[2])); + } else if (RodaConstants.INDEX_FILE.equals(parts[0])) { + fileParams.add(new SimpleFilterParameter(parts[1], parts[2])); + } + } + } + + private Widget buildAssociationsTab(Class clazz, List params, + String listId) { + + if (params == null || params.isEmpty()) { + if (IndexedAIP.class.equals(clazz)) { + return buildEmptyAssociationsCardLikeTab(messages.representationInformationIntellectualEntities(0, "")); + } + if (IndexedRepresentation.class.equals(clazz)) { + return buildEmptyAssociationsCardLikeTab(messages.representationInformationRepresentations(0, "")); + } + return buildEmptyAssociationsCardLikeTab(messages.representationInformationFiles(0, "")); + } + Filter filter = new Filter(new OrFiltersParameters(params)); + + ListBuilder listBuilder = new ListBuilder<>(() -> new ConfigurableAsyncTableCell<>(), + new AsyncTableCellOptions<>(clazz, listId).withFilter(filter).withJustActive(false).bindOpener()); + + return new SearchWrapper(false).createListAndSearchPanel(listBuilder); + } + + private Widget buildEmptyAssociationsCardLikeTab(String messageHtml) { + FlowPanel card = new FlowPanel(); + card.addStyleName("roda6CardWithHeader"); + card.addStyleName("wrapper"); + card.addStyleName("skip_padding"); + + FlowPanel body = new FlowPanel(); + body.addStyleName("cardBody"); + + SimplePanel info = new SimplePanel(); + info.addStyleName("table-empty-inner"); + HTML label = new HTML(messageHtml); + label.addStyleName("table-empty-inner-label"); + info.setWidget(label); + + body.add(info); + card.add(body); + return card; + } +} diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/DetailsTab.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/DetailsTab.java index c6f11dcb8b..7bf777e351 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/DetailsTab.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/browse/tabs/DetailsTab.java @@ -11,10 +11,12 @@ import org.roda.core.data.v2.ip.IndexedFile; import org.roda.core.data.v2.ip.TransferredResource; +import org.roda.core.data.v2.ri.RepresentationInformation; import org.roda.core.data.v2.notifications.Notification; import org.roda.core.data.v2.log.LogEntry; import org.roda.wui.client.common.model.BrowseAIPResponse; import org.roda.wui.client.common.model.BrowseRepresentationResponse; +import org.roda.wui.client.planning.DetailsPanelRepresentationInformation; import org.roda.wui.client.management.DetailsPanelNotification; import org.roda.wui.client.management.DetailsPanelLogEntry; import org.roda.wui.client.ingest.transfer.DetailsPanelTransferredResource; @@ -62,6 +64,13 @@ public DetailsTab(IndexedFile file, List riRules) { content.add(detailsPanel); } + public DetailsTab(RepresentationInformation ri){ + initWidget(uiBinder.createAndBindUi(this)); + + DetailsPanelRepresentationInformation detailsPanel = new DetailsPanelRepresentationInformation(ri); + content.add(detailsPanel); + } + public DetailsTab(TransferredResource resource) { initWidget(uiBinder.createAndBindUi(this)); diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/BrowseRepresentationInformationActionsToolbar.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/BrowseRepresentationInformationActionsToolbar.java new file mode 100644 index 0000000000..08d48a1839 --- /dev/null +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/BrowseRepresentationInformationActionsToolbar.java @@ -0,0 +1,33 @@ +package org.roda.wui.client.common; + +import java.util.List; + +import org.roda.core.data.v2.ri.RepresentationInformation; +import org.roda.wui.client.common.actions.RepresentationInformationActions; +import org.roda.wui.client.common.actions.model.ActionableObject; +import org.roda.wui.client.common.actions.widgets.ActionableWidgetBuilder; + +/** + * + * @author Eduardo Teixeira + */ +public class BrowseRepresentationInformationActionsToolbar + extends BrowseObjectActionsToolbar { + public void buildIcon() { + setIcon(null); + } + + public void buildTags() { + // do nothing + } + + public void buildActions() { + this.actions.clear(); + RepresentationInformationActions representationInformationActions; + representationInformationActions = RepresentationInformationActions.get(); + this.actions.add(new ActionableWidgetBuilder(representationInformationActions) + .buildGroupedListWithObjects(new ActionableObject<>(object), List.of(), + List.of(RepresentationInformationActions.RepresentationInformationAction.START_PROCESS))); + } + +} diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/RepresentationInformationActions.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/RepresentationInformationActions.java index 1e791fa7a5..76bd9b67bb 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/RepresentationInformationActions.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/actions/RepresentationInformationActions.java @@ -45,8 +45,6 @@ import config.i18n.client.ClientMessages; -import javax.naming.Context; - public class RepresentationInformationActions extends AbstractActionable { private static final RepresentationInformationActions INSTANCE = new RepresentationInformationActions(); private static final ClientMessages messages = GWT.create(ClientMessages.class); @@ -328,7 +326,7 @@ public ActionableBundle createActionsBundle() { ActionableBundle formatActionableBundle = new ActionableBundle<>(); // MANAGEMENT - ActionableGroup managementGroup = new ActionableGroup<>(messages.sidebarActionsTitle()); + ActionableGroup managementGroup = new ActionableGroup<>(messages.manage(), "btn-edit"); managementGroup.addButton(messages.newButton(), RepresentationInformationAction.NEW, ActionImpact.UPDATED, "btn-plus-circle"); managementGroup.addButton(messages.createNewRepresentationInformation(), diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/resources/main.gss b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/resources/main.gss index 5597ef3d8f..92ef24eced 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/resources/main.gss +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/common/resources/main.gss @@ -2581,6 +2581,7 @@ td.datePickerMonth, td.datePickerYear { .main .wui-breadcrumbPanel .breadcrumb-root { color: COLOR_PRIMARY; font-weight: bold; + max-width: none !important; } .main .wui-breadcrumbPanel .breadcrumb-last { diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/main/BreadcrumbUtils.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/main/BreadcrumbUtils.java index f70a2386c4..ef342d269d 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/main/BreadcrumbUtils.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/main/BreadcrumbUtils.java @@ -21,6 +21,7 @@ import org.roda.core.data.v2.ip.TransferredResource; import org.roda.core.data.v2.user.RODAMember; import org.roda.core.data.v2.log.LogEntry; +import org.roda.core.data.v2.ri.RepresentationInformation; import org.roda.wui.client.browse.BrowseTop; import org.roda.wui.client.management.ShowLogEntry; import org.roda.wui.client.management.UserLog; @@ -30,6 +31,8 @@ import org.roda.wui.client.ingest.transfer.IngestTransfer; import org.roda.wui.client.management.members.MemberManagement; import org.roda.wui.client.management.members.ShowMember; +import org.roda.wui.client.planning.RepresentationInformationNetwork; +import org.roda.wui.client.planning.ShowRepresentationInformation; import org.roda.wui.common.client.tools.DescriptionLevelUtils; import org.roda.wui.common.client.tools.HistoryUtils; import org.roda.wui.common.client.tools.ListUtils; @@ -389,6 +392,23 @@ public static List getNotificationBreadcrumbs(Notification notif return ret; } + public static List getRepresentationInformationBreadCrumbs(RepresentationInformation ri){ + List ret = new ArrayList<>(); + ret.add(new BreadcrumbItem( + SafeHtmlUtils.fromSafeConstant(messages.representationInformationTitle()), + messages.representationInformationTitle(), + RepresentationInformationNetwork.RESOLVER.getHistoryPath())); + + if (ri != null) { + List path = new ArrayList<>(ShowRepresentationInformation.RESOLVER.getHistoryPath()); + path.add(ri.getUUID()); + String label = ri.getName() != null ? ri.getName() : ri.getId(); + ret.add(new BreadcrumbItem(SafeHtmlUtils.fromString(label), label, path)); + } + + return ret; + } + public static List getDipBreadcrumbs(IndexedDIP dip, DIPFile dipFile, List dipFileAncestors) { List ret = new ArrayList<>(); diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.java new file mode 100644 index 0000000000..7a82e7a941 --- /dev/null +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.java @@ -0,0 +1,189 @@ +package org.roda.wui.client.planning; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +import org.roda.core.data.common.RodaConstants; +import org.roda.core.data.v2.ri.RelationObjectType; +import org.roda.core.data.v2.ri.RepresentationInformation; +import org.roda.core.data.v2.ri.RepresentationInformationRelation; +import org.roda.wui.client.common.utils.HtmlSnippetUtils; +import org.roda.wui.client.search.Search; +import org.roda.wui.client.services.Services; +import org.roda.wui.common.client.tools.HistoryUtils; +import org.roda.wui.common.client.tools.Humanize; +import org.roda.wui.common.client.tools.StringUtils; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.i18n.client.LocaleInfo; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Anchor; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.InlineHTML; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.Widget; + +import config.i18n.client.ClientMessages; + +/** + * + * @author Eduardo Teixeira + */ +public class DetailsPanelRepresentationInformation extends Composite { + private static final ClientMessages messages = GWT.create(ClientMessages.class); + private static final MyUiBinder uiBinder = GWT.create(MyUiBinder.class); + + @UiField + FlowPanel details; + + public DetailsPanelRepresentationInformation(RepresentationInformation ri) { + initWidget(uiBinder.createAndBindUi(this)); + init(ri); + } + + private void init(RepresentationInformation ri) { + if (ri.getCreatedOn() != null && StringUtils.isNotBlank(ri.getCreatedBy())) { + addIfNotBlank(messages.detailsCreatedOn(), Humanize.formatDateTime(ri.getCreatedOn())); + addIfNotBlank(messages.detailsCreatedBy(), ri.getCreatedBy()); + } + + if (ri.getUpdatedOn() != null && StringUtils.isNotBlank(ri.getUpdatedBy())) { + addIfNotBlank(messages.detailsUpdatedOn(), Humanize.formatDateTime(ri.getUpdatedOn())); + addIfNotBlank(messages.detailsUpdatedBy(), ri.getUpdatedBy()); + } + addIfNotBlank(messages.representationInformationIdentifier(), ri.getId()); + addIfNotBlank(messages.representationInformationName(), ri.getName()); + addIfNotBlank(messages.representationInformationDescription(), ri.getDescription()); + addIfNotBlank(messages.representationInformationFamily(), ri.getFamilyI18n()); + + if (ri.getSupport() != null) { + addIfNotBlank(messages.representationInformationSupport(), + messages.representationInformationSupportValue(ri.getSupport().toString())); + } + + addTagsField(ri); + addExtrasField(ri); + initRelations(ri); + + } + + private void addIfNotBlank(String label, String value) { + if (StringUtils.isNotBlank(value)) { + details.add(buildField(label, new InlineHTML(SafeHtmlUtils.htmlEscape(value)))); + } + } + + private Widget buildField(String label, Widget valueWidget) { + FlowPanel fieldPanel = new FlowPanel(); + fieldPanel.setStyleName("field"); + + Label fieldLabel = new Label(label); + fieldLabel.setStyleName("label"); + + FlowPanel fieldValuePanel = new FlowPanel(); + fieldValuePanel.setStyleName("value"); + fieldValuePanel.add(valueWidget); + + fieldPanel.add(fieldLabel); + fieldPanel.add(fieldValuePanel); + + return fieldPanel; + } + + private void addTagsField(RepresentationInformation ri) { + List tags = ri.getTags(); + if (tags == null || tags.isEmpty()) + return; + + FlowPanel tagsPanel = new FlowPanel(); + tagsPanel.addStyleName("value"); + for (String category : tags) { + InlineHTML tag = new InlineHTML("" + + messages.representationInformationListItems(SafeHtmlUtils.htmlEscape(category)) + ""); + tag.addClickHandler(event -> { + List history = new ArrayList<>(RepresentationInformationNetwork.RESOLVER.getHistoryPath()); + history.add(Search.RESOLVER.getHistoryToken()); + history.add(RodaConstants.REPRESENTATION_INFORMATION_TAGS); + history.add(category); + HistoryUtils.newHistory(history); + }); + tagsPanel.add(tag); + } + + details.add(buildField(messages.representationInformationTags(), tagsPanel)); + } + + private void addExtrasField(RepresentationInformation ri) { + Services services = new Services("Retrieve representation information family metadata", "get"); + services + .representationInformationResource( + s -> s.retrieveRepresentationInformationFamily(ri.getId(), LocaleInfo.getCurrentLocale().getLocaleName())) + .whenComplete((family, throwable) -> { + if (throwable == null && family != null && family.getFamilyValues() != null + && !family.getFamilyValues().isEmpty()) { + + FlowPanel extrasContent = new FlowPanel(); + extrasContent.addStyleName("ri-extras-panel"); + + HtmlSnippetUtils.createExtraShow(extrasContent, family.getFamilyValues(), false); + + if (extrasContent.getWidgetCount() > 0) { + details.add(extrasContent); + } + } + }); + } + + private void initRelations(RepresentationInformation ri) { + if (ri.getRelations() == null) { + return; + } + + ri.getRelations().sort(Comparator.comparingInt(o -> o.getObjectType().getWeight())); + for (RepresentationInformationRelation relation : ri.getRelations()) { + Widget relationValue = createRelationViewer(relation); + if (relationValue != null) { + relationValue.addStyleName("ri-links-panel"); + details.add(buildField(relation.getRelationTypeI18n(), relationValue)); + } + } + } + + private Widget createRelationViewer(RepresentationInformationRelation relation) { + Widget widgetToAdd = null; + String title = StringUtils.isNotBlank(relation.getTitle()) ? relation.getTitle() : relation.getLink(); + + if (relation.getObjectType().equals(RelationObjectType.TEXT)) { + widgetToAdd = new Label(title); + } else { + Anchor anchor = null; + + if (relation.getObjectType().equals(RelationObjectType.AIP)) { + anchor = new Anchor(title, + HistoryUtils.createHistoryHashLink(HistoryUtils.getHistoryBrowse(relation.getLink()))); + } else if (relation.getObjectType().equals(RelationObjectType.REPRESENTATION_INFORMATION)) { + List history = new ArrayList<>(); + history.addAll(ShowRepresentationInformation.RESOLVER.getHistoryPath()); + history.add(relation.getLink()); + anchor = new Anchor(title, HistoryUtils.createHistoryHashLink(history)); + } else if (relation.getObjectType().equals(RelationObjectType.WEB)) { + anchor = new Anchor(title, relation.getLink()); + anchor.getElement().setAttribute("target", "_blank"); + } + + if (anchor != null) { + widgetToAdd = anchor; + } + } + + return widgetToAdd; + } + + interface MyUiBinder extends UiBinder { + Widget createAndBindUi(DetailsPanelRepresentationInformation representationInformationPanel); + } +} diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.ui.xml b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.ui.xml new file mode 100644 index 0000000000..b875eb3ac9 --- /dev/null +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/DetailsPanelRepresentationInformation.ui.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.java b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.java index 60522efa74..7fd0a89407 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.java +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.java @@ -10,58 +10,27 @@ */ package org.roda.wui.client.planning; -import java.util.ArrayList; -import java.util.Comparator; import java.util.List; -import org.roda.core.data.common.RodaConstants; -import org.roda.core.data.utils.RepresentationInformationUtils; -import org.roda.core.data.v2.index.CountRequest; -import org.roda.core.data.v2.index.filter.Filter; -import org.roda.core.data.v2.index.filter.FilterParameter; -import org.roda.core.data.v2.index.filter.OrFiltersParameters; -import org.roda.core.data.v2.index.filter.SimpleFilterParameter; -import org.roda.core.data.v2.ip.IndexedAIP; -import org.roda.core.data.v2.ip.IndexedFile; -import org.roda.core.data.v2.ip.IndexedRepresentation; -import org.roda.core.data.v2.ri.RelationObjectType; import org.roda.core.data.v2.ri.RepresentationInformation; -import org.roda.core.data.v2.ri.RepresentationInformationCreateRequest; -import org.roda.core.data.v2.ri.RepresentationInformationRelation; -import org.roda.wui.client.common.NoAsyncCallback; +import org.roda.wui.client.browse.tabs.BrowseRepresentationInformationTabs; +import org.roda.wui.client.common.BrowseRepresentationInformationActionsToolbar; +import org.roda.wui.client.common.NavigationToolbar; import org.roda.wui.client.common.TitlePanel; import org.roda.wui.client.common.UserLogin; -import org.roda.wui.client.common.actions.Actionable; -import org.roda.wui.client.common.actions.RepresentationInformationActions; -import org.roda.wui.client.common.actions.model.ActionableObject; -import org.roda.wui.client.common.actions.widgets.ActionableWidgetBuilder; -import org.roda.wui.client.common.dialogs.RepresentationInformationDialogs; -import org.roda.wui.client.common.utils.AsyncCallbackUtils; -import org.roda.wui.client.common.utils.HtmlSnippetUtils; -import org.roda.wui.client.common.utils.SidebarUtils; -import org.roda.wui.client.search.Search; +import org.roda.wui.client.main.BreadcrumbUtils; import org.roda.wui.client.services.Services; import org.roda.wui.common.client.HistoryResolver; import org.roda.wui.common.client.tools.HistoryUtils; -import org.roda.wui.common.client.tools.Humanize; import org.roda.wui.common.client.tools.ListUtils; -import org.roda.wui.common.client.tools.StringUtils; import com.google.gwt.core.client.GWT; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.i18n.client.LocaleInfo; -import com.google.gwt.safehtml.shared.SafeHtmlUtils; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.rpc.AsyncCallback; -import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.InlineHTML; -import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.FocusPanel; import com.google.gwt.user.client.ui.Widget; import config.i18n.client.ClientMessages; @@ -100,49 +69,21 @@ public String getHistoryToken() { private static MyUiBinder uiBinder = GWT.create(MyUiBinder.class); @UiField - Label representationInformationId; + NavigationToolbar navigationToolbar; + @UiField - Label dateCreated; + BrowseRepresentationInformationActionsToolbar actionsToolbar; + @UiField - Label dateUpdated; + FocusPanel keyboardFocus; + @UiField TitlePanel title; + @UiField - Label representationInformationDescriptionKey; - @UiField - HTML representationInformationDescriptionValue; - @UiField - Label representationInformationFamilyKey; - @UiField - Label representationInformationFamilyValue; - @UiField - Label representationInformationTagKey; - @UiField - FlowPanel representationInformationTagValue; - @UiField - Label representationInformationSupportKey; - @UiField - Label representationInformationSupportValue; - @UiField - FlowPanel representationInformationRelationsValue; - @UiField - FlowPanel objectPanel; - @UiField - FlowPanel additionalSeparator; - @UiField - FlowPanel extras; - @UiField - SimplePanel actionsSidebar; - @UiField - FlowPanel contentFlowPanel; - @UiField - FlowPanel sidebarFlowPanel; + BrowseRepresentationInformationTabs browseRepresentationInformationTabs; private RepresentationInformation ri; - private ActionableWidgetBuilder actionableWidgetBuilder; - private List aipParams = new ArrayList<>(); - private List representationParams = new ArrayList<>(); - private List fileParams = new ArrayList<>(); public ShowRepresentationInformation() { this.ri = new RepresentationInformation(); @@ -153,268 +94,26 @@ public ShowRepresentationInformation(final RepresentationInformation ri) { this.ri = ri; initWidget(uiBinder.createAndBindUi(this)); - initEntityFilters(); - objectPanel.addStyleName("ri-entity-relation-section"); - initElements(); - } - public static ShowRepresentationInformation getInstance() { - if (instance == null) { - instance = new ShowRepresentationInformation(); - } - return instance; - } + navigationToolbar.withoutButtons().build(); + navigationToolbar.updateBreadcrumbPath(BreadcrumbUtils.getRepresentationInformationBreadCrumbs(ri)); - public void initElements() { title.setText(ri.getName()); - representationInformationId.setText(messages.representationInformationIdentifier() + ": " + ri.getId()); - - if (ri.getCreatedOn() != null && StringUtils.isNotBlank(ri.getCreatedBy())) { - dateCreated.setText(messages.dateCreated(Humanize.formatDateTime(ri.getCreatedOn()), ri.getCreatedBy())); - } - - if (ri.getUpdatedOn() != null && StringUtils.isNotBlank(ri.getUpdatedBy())) { - dateUpdated.setText(messages.dateUpdated(Humanize.formatDateTime(ri.getUpdatedOn()), ri.getUpdatedBy())); - } - - String description = (ri.getDescription() == null) ? "" : ri.getDescription(); - representationInformationDescriptionValue.setHTML(SafeHtmlUtils.fromString(description)); - representationInformationDescriptionKey.setVisible(StringUtils.isNotBlank(ri.getDescription())); - - representationInformationFamilyKey.setVisible(StringUtils.isNotBlank(ri.getFamily())); - representationInformationFamilyValue.setText(ri.getFamilyI18n()); - - List tagsList = ri.getTags(); - representationInformationTagValue.setVisible(tagsList != null && !tagsList.isEmpty()); - representationInformationTagKey.setVisible(tagsList != null && !tagsList.isEmpty()); - - if (tagsList != null) { - for (final String category : tagsList) { - InlineHTML parPanel = new InlineHTML(); - parPanel.setHTML("" - + messages.representationInformationListItems(SafeHtmlUtils.htmlEscape(category)) + ""); - parPanel.addClickHandler(event -> { - List history = new ArrayList<>(RepresentationInformationNetwork.RESOLVER.getHistoryPath()); - history.add(Search.RESOLVER.getHistoryToken()); - history.add(RodaConstants.REPRESENTATION_INFORMATION_TAGS); - history.add(category); - HistoryUtils.newHistory(history); - }); - representationInformationTagValue.add(parPanel); - } - } - - if (ri.getSupport() != null) { - representationInformationSupportValue - .setText(messages.representationInformationSupportValue(ri.getSupport().toString())); - representationInformationSupportKey.setVisible(true); - } else { - representationInformationSupportKey.setVisible(false); - } - - Services services = new Services("Retrieve representation information family metadata", "get"); - services - .representationInformationResource( - s -> s.retrieveRepresentationInformationFamily(ri.getId(), LocaleInfo.getCurrentLocale().getLocaleName())) - .whenComplete((representationInformationFamily, throwable) -> { - if (throwable == null) { - HtmlSnippetUtils.createExtraShow(extras, representationInformationFamily.getFamilyValues(), false); - } - }); + actionsToolbar.setObjectAndBuild(ri, null, null); + browseRepresentationInformationTabs.init(ri); - RepresentationInformationActions representationInformationActions = RepresentationInformationActions.get(); - - actionableWidgetBuilder = new ActionableWidgetBuilder<>(representationInformationActions) - .withActionCallback(new NoAsyncCallback() { - @Override - public void onSuccess(Actionable.ActionImpact result) { - if (result.equals(Actionable.ActionImpact.DESTROYED)) { - HistoryUtils.newHistory(RepresentationInformationNetwork.RESOLVER); - } - } - }); - - SidebarUtils.toggleSidebar(contentFlowPanel, sidebarFlowPanel, representationInformationActions.hasAnyRoles()); - actionsSidebar.setWidget(actionableWidgetBuilder.buildListWithObjects(new ActionableObject<>(ri))); - - initRelations(); + keyboardFocus.setFocus(true); + keyboardFocus.addStyleName("browse browse-file browse_main_panel"); } - public void updateLists() { - aipParams.clear(); - representationParams.clear(); - fileParams.clear(); - - initEntityFilters(); - initRelations(); - } - - private void initEntityFilters() { - for (String filter : ri.getFilters()) { - String[] splittedFilter = filter - .split(RepresentationInformationUtils.REPRESENTATION_INFORMATION_FILTER_SEPARATOR); - - if (splittedFilter[0].equals(RodaConstants.INDEX_AIP)) { - aipParams.add(new SimpleFilterParameter(splittedFilter[1], splittedFilter[2])); - } else if (splittedFilter[0].equals(RodaConstants.INDEX_REPRESENTATION)) { - representationParams.add(new SimpleFilterParameter(splittedFilter[1], splittedFilter[2])); - } else if (splittedFilter[0].equals(RodaConstants.INDEX_FILE)) { - fileParams.add(new SimpleFilterParameter(splittedFilter[1], splittedFilter[2])); - } - } - - if (!aipParams.isEmpty()) { - Filter aipFilter = new Filter(); - aipFilter.add(new OrFiltersParameters(aipParams)); - Services services = new Services("Count AIPs associated with representation information", "count"); - CountRequest countRequest = new CountRequest(aipFilter, true); - services.rodaEntityRestService(s -> s.count(countRequest), IndexedAIP.class).whenComplete((count, - throwable) -> initEntityFiltersObjectPanel(count.getResult(), throwable, IndexedAIP.class.getSimpleName())); - } else if (!representationParams.isEmpty()) { - Filter representationFilter = new Filter(); - representationFilter.add(new OrFiltersParameters(representationParams)); - - Services services = new Services("Count Representations associated with representation information", "count"); - CountRequest countRequest = new CountRequest(representationFilter, true); - services.rodaEntityRestService(s -> s.count(countRequest), IndexedRepresentation.class) - .whenComplete((count, throwable) -> initEntityFiltersObjectPanel(count.getResult(), throwable, - IndexedRepresentation.class.getSimpleName())); - } else if (!fileParams.isEmpty()) { - Filter fileFilter = new Filter(); - fileFilter.add(new OrFiltersParameters(fileParams)); - - Services services = new Services("Count Files associated with representation information", "count"); - CountRequest countRequest = new CountRequest(fileFilter, true); - services.rodaEntityRestService(s -> s.count(countRequest), IndexedFile.class).whenComplete((count, - throwable) -> initEntityFiltersObjectPanel(count.getResult(), throwable, IndexedFile.class.getSimpleName())); - } else { - initEntityFiltersObjectPanel(0L, null, IndexedAIP.class.getSimpleName()); - } - } - - private void initEntityFiltersObjectPanel(final Long count, final Throwable throwable, final String searchType) { - if (throwable != null) { - AsyncCallbackUtils.defaultFailureTreatment(throwable); - } else { - ShowRepresentationInformation.this.objectPanel.clear(); - String url = HistoryUtils.getSearchHistoryByRepresentationInformationFilter( - ShowRepresentationInformation.this.ri.getFilters(), searchType); - - InlineHTML label = new InlineHTML(); - label.addStyleName("ri-form-label-inline"); - if (IndexedAIP.class.getSimpleName().equals(searchType)) { - label.setHTML(messages.representationInformationIntellectualEntities(count.intValue(), url)); - } else if (IndexedRepresentation.class.getSimpleName().equals(searchType)) { - label.setHTML(messages.representationInformationRepresentations(count.intValue(), url)); - } else if (IndexedFile.class.getSimpleName().equals(searchType)) { - label.setHTML(messages.representationInformationFiles(count.intValue(), url)); - } - - ShowRepresentationInformation.this.objectPanel.add(label); - - InlineHTML edit = new InlineHTML(""); - edit.setTitle("Edit association rules"); - edit.addStyleName("ri-category link-color"); - - edit.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - RepresentationInformationDialogs.showPromptDialogRepresentationInformation( - messages.representationInformationEditAssociations(), messages.cancelButton(), messages.confirmButton(), - messages.searchButton(), ShowRepresentationInformation.this.ri, - new AsyncCallback() { - @Override - public void onFailure(Throwable caught) { - // do nothing - } - - @Override - public void onSuccess(RepresentationInformation result) { - // result is ri with updated filters - Services services = new Services("Update representation information", "update"); - RepresentationInformationCreateRequest createRequest = new RepresentationInformationCreateRequest(); - createRequest.setRepresentationInformation(result); - services.representationInformationResource(s -> s.updateRepresentationInformation(createRequest)) - .whenComplete((representationInformation, throwable1) -> { - if (throwable1 == null) { - ShowRepresentationInformation.getInstance().updateLists(); - } - }); - } - }); - } - }); - - ShowRepresentationInformation.this.objectPanel.add(edit); - } - } - - private void initRelations() { - additionalSeparator.setVisible(!ri.getRelations().isEmpty()); - - ri.getRelations().sort(Comparator.comparingInt(o -> o.getObjectType().getWeight())); - - for (RepresentationInformationRelation relation : ri.getRelations()) { - representationInformationRelationsValue.add(createRelationsLayout(relation)); - } - } - - private FlowPanel createRelationsLayout(RepresentationInformationRelation relation) { - FlowPanel panel = new FlowPanel(); - FlowPanel linksPanel = new FlowPanel(); - - Label entryLabel = new Label(relation.getRelationTypeI18n()); - entryLabel.setStyleName("label"); - panel.add(entryLabel); - - Widget w = createRelationViewer(relation); - if (w != null) { - w.addStyleName("ri-links-panel"); - linksPanel.add(w); - } - - panel.add(w); - - return panel; - } - - private Widget createRelationViewer(RepresentationInformationRelation relation) { - Widget widgetToAdd = null; - String title = StringUtils.isNotBlank(relation.getTitle()) ? relation.getTitle() : relation.getLink(); - - if (relation.getObjectType().equals(RelationObjectType.TEXT)) { - widgetToAdd = new Label(title); - } else { - Anchor anchor = null; - - if (relation.getObjectType().equals(RelationObjectType.AIP)) { - anchor = new Anchor(title, - HistoryUtils.createHistoryHashLink(HistoryUtils.getHistoryBrowse(relation.getLink()))); - } else if (relation.getObjectType().equals(RelationObjectType.REPRESENTATION_INFORMATION)) { - List history = new ArrayList<>(); - history.addAll(ShowRepresentationInformation.RESOLVER.getHistoryPath()); - history.add(relation.getLink()); - anchor = new Anchor(title, HistoryUtils.createHistoryHashLink(history)); - } else if (relation.getObjectType().equals(RelationObjectType.WEB)) { - anchor = new Anchor(title, relation.getLink()); - anchor.getElement().setAttribute("target", "_blank"); - } - - if (anchor != null) { - widgetToAdd = anchor; - } + public static ShowRepresentationInformation getInstance() { + if (instance == null) { + instance = new ShowRepresentationInformation(); } - - return widgetToAdd; + return instance; } - // Java method - public native boolean isValidUrl(String url) /*-{ - var pattern = /(http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/; - return pattern.test(url); - }-*/; - void resolve(List historyTokens, final AsyncCallback callback) { if (historyTokens.size() == 1) { Services services = new Services("Retrieve representation information", "get"); diff --git a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.ui.xml b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.ui.xml index 26591826cf..440ef146e8 100644 --- a/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.ui.xml +++ b/roda-ui/roda-wui/src/main/java/org/roda/wui/client/planning/ShowRepresentationInformation.ui.xml @@ -1,78 +1,22 @@ + xmlns:common="urn:import:org.roda.wui.client.common" + xmlns:tabs="urn:import:org.roda.wui.client.browse.tabs"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties b/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties index 0055a2f6c5..49ec68b320 100644 --- a/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties +++ b/roda-ui/roda-wui/src/main/resources/config/i18n/client/ClientMessages.properties @@ -874,6 +874,10 @@ representationInformationRepresentations[\=1]:There is one represe representationInformationFiles:There are {0,number} files associated with this representation information representationInformationFiles[\=0]:There are no files associated with this representation information representationInformationFiles[\=1]:There is one file associated with this representation information +representationInformationIntellectualEntitiesAssociations=Intellectual entities associations +representationInformationRepresentationsAssociations=Representation associations +representationInformationFilesAssociations=File associations + # Descriptive Metadata metadataType:Type @@ -1810,7 +1814,9 @@ detailsIdentifier: Identifier detailsLevel: Level detailsType: Type detailsState: State -detailsCreatedOn: Created +detailsCreatedOn: Created on +detailsUpdatedOn: Updated on +detailsUpdatedBy: Updated by detailsCreatedBy: Creator detailsModifiedOn: Modified detailsModifiedBy: Modifier