add read only tree table and value help

This commit is contained in:
D070615
2025-03-20 16:20:20 +01:00
parent 737e766d53
commit 5f5b32043c
16 changed files with 249 additions and 140 deletions

View File

@@ -1,16 +1,34 @@
ID,parent_ID,name
10,,Fiction
11,10,Drama
12,10,Poetry
13,10,Fantasy
14,10,Science Fiction
15,10,Romance
16,10,Mystery
17,10,Thriller
18,10,Dystopia
19,10,Fairy Tale
20,,Non-Fiction
21,20,Biography
22,21,Autobiography
23,20,Essay
24,20,Speech
8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,,Fiction
08467c69-4b69-4b30-bf51-998f9c4b8a12,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Action
c5247996-2516-40c5-b3ea-02492a1e1f4d,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Adventure
d74eb118-ff57-4776-96d3-0d649278bf6b,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Drama
b84a7e92-cc0c-4599-8b62-9e3ae39e343f,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Poetry
445a6c1e-071f-4e9d-b0bb-670ec73b0a49,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Fantasy
0d4f268f-c5c5-4a82-b54a-2120271cf54e,445a6c1e-071f-4e9d-b0bb-670ec73b0a49,Epic fantasy
5ccfe8e7-009f-4744-91fd-c1c1e9a0c9c6,445a6c1e-071f-4e9d-b0bb-670ec73b0a49,High fantasy
86e9f4d5-3e7c-4c06-8421-8b6d72fe9c93,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Science Fiction
9f8653a2-6d6d-4fd7-b02f-b90d15d6f67f,86e9f4d5-3e7c-4c06-8421-8b6d72fe9c93,Utopian and Dystopian
7c7b2c30-c24e-4627-bb84-0f9d09f9e91b,9f8653a2-6d6d-4fd7-b02f-b90d15d6f67f,Dystopia
34f6a939-2708-4cc0-9882-daf36a8ed5e6,7c7b2c30-c24e-4627-bb84-0f9d09f9e91b,Cyberpunk
4297bff9-c4b3-4097-b68f-5605f89c6e4c,34f6a939-2708-4cc0-9882-daf36a8ed5e6,Steampunk
f283b1b3-b763-42f9-95f0-38e1d78a1d7e,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Romance
5d2c5060-84cf-4a94-9118-8d9ad88f2a24,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Mystery
7d6cc413-cf8c-4cf9-b30a-bf8cf6f97b72,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Graphic Novel
f846b0b9-01d4-4f6d-82a4-d79204f62576,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Thriller
82f9a2d9-bd77-4cfd-9c76-d03b8f6827a3,f846b0b9-01d4-4f6d-82a4-d79204f62576,Suspense
a7b5b4d7-bff3-430d-9d7e-25fd67b66022,f846b0b9-01d4-4f6d-82a4-d79204f62576,Crime thriller
5f93c395-6f8a-43de-84c1-bf22cfba8f56,f846b0b9-01d4-4f6d-82a4-d79204f62576,Spy thriller
3ff51d9c-5ff5-421f-8d0d-d75b08e32a25,f846b0b9-01d4-4f6d-82a4-d79204f62576,Political thriller
a530cd31-b0cf-4a32-9f28-72ee7b9f29fc,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Short Story
5b091c64-8b4f-401a-a06d-61b19857635b,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Fairy Tale
7125da65-b3ae-4a0b-a735-1db410a3e079,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Horror
a02b5c9b-b79f-43ef-b2ab-28e4b431cc18,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Historical Fiction
d6c3448e-d771-47f0-b6c7-8d2159b29d2a,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Contemporary Fiction
7ed5cfab-8c4d-46a3-b89b-c5b8fa74f049,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Magical Realism
23e86990-66d3-4488-8272-98ed056710b5,8bbf14c6-b378-4e35-9b4f-5a9c8b8762da,Literary Fiction
85b5a640-7e9a-468e-80e2-e9268486031b,,Non-Fiction
10d19b1a-832b-4d60-bf9b-88dcd089db85,85b5a640-7e9a-468e-80e2-e9268486031b,Biography
1f1c8b5b-451e-48f6-bdbb-759be4ea1a8f,10d19b1a-832b-4d60-bf9b-88dcd089db85,Autobiography
4bc5ad4d-b7a3-47a7-9938-325c6fdf8041,85b5a640-7e9a-468e-80e2-e9268486031b,Essay
e0d350c2-1f42-45b5-b768-67cccd997b56,85b5a640-7e9a-468e-80e2-e9268486031b,Speech
1 ID parent_ID name
2 10 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Fiction
3 11 08467c69-4b69-4b30-bf51-998f9c4b8a12 10 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Drama Action
4 12 c5247996-2516-40c5-b3ea-02492a1e1f4d 10 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Poetry Adventure
5 13 d74eb118-ff57-4776-96d3-0d649278bf6b 10 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Fantasy Drama
6 14 b84a7e92-cc0c-4599-8b62-9e3ae39e343f 10 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Science Fiction Poetry
7 15 445a6c1e-071f-4e9d-b0bb-670ec73b0a49 10 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Romance Fantasy
8 16 0d4f268f-c5c5-4a82-b54a-2120271cf54e 10 445a6c1e-071f-4e9d-b0bb-670ec73b0a49 Mystery Epic fantasy
9 17 5ccfe8e7-009f-4744-91fd-c1c1e9a0c9c6 10 445a6c1e-071f-4e9d-b0bb-670ec73b0a49 Thriller High fantasy
10 18 86e9f4d5-3e7c-4c06-8421-8b6d72fe9c93 10 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Dystopia Science Fiction
11 19 9f8653a2-6d6d-4fd7-b02f-b90d15d6f67f 10 86e9f4d5-3e7c-4c06-8421-8b6d72fe9c93 Fairy Tale Utopian and Dystopian
12 20 7c7b2c30-c24e-4627-bb84-0f9d09f9e91b 9f8653a2-6d6d-4fd7-b02f-b90d15d6f67f Non-Fiction Dystopia
13 21 34f6a939-2708-4cc0-9882-daf36a8ed5e6 20 7c7b2c30-c24e-4627-bb84-0f9d09f9e91b Biography Cyberpunk
14 22 4297bff9-c4b3-4097-b68f-5605f89c6e4c 21 34f6a939-2708-4cc0-9882-daf36a8ed5e6 Autobiography Steampunk
15 23 f283b1b3-b763-42f9-95f0-38e1d78a1d7e 20 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Essay Romance
16 24 5d2c5060-84cf-4a94-9118-8d9ad88f2a24 20 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Speech Mystery
17 7d6cc413-cf8c-4cf9-b30a-bf8cf6f97b72 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Graphic Novel
18 f846b0b9-01d4-4f6d-82a4-d79204f62576 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Thriller
19 82f9a2d9-bd77-4cfd-9c76-d03b8f6827a3 f846b0b9-01d4-4f6d-82a4-d79204f62576 Suspense
20 a7b5b4d7-bff3-430d-9d7e-25fd67b66022 f846b0b9-01d4-4f6d-82a4-d79204f62576 Crime thriller
21 5f93c395-6f8a-43de-84c1-bf22cfba8f56 f846b0b9-01d4-4f6d-82a4-d79204f62576 Spy thriller
22 3ff51d9c-5ff5-421f-8d0d-d75b08e32a25 f846b0b9-01d4-4f6d-82a4-d79204f62576 Political thriller
23 a530cd31-b0cf-4a32-9f28-72ee7b9f29fc 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Short Story
24 5b091c64-8b4f-401a-a06d-61b19857635b 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Fairy Tale
25 7125da65-b3ae-4a0b-a735-1db410a3e079 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Horror
26 a02b5c9b-b79f-43ef-b2ab-28e4b431cc18 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Historical Fiction
27 d6c3448e-d771-47f0-b6c7-8d2159b29d2a 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Contemporary Fiction
28 7ed5cfab-8c4d-46a3-b89b-c5b8fa74f049 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Magical Realism
29 23e86990-66d3-4488-8272-98ed056710b5 8bbf14c6-b378-4e35-9b4f-5a9c8b8762da Literary Fiction
30 85b5a640-7e9a-468e-80e2-e9268486031b Non-Fiction
31 10d19b1a-832b-4d60-bf9b-88dcd089db85 85b5a640-7e9a-468e-80e2-e9268486031b Biography
32 1f1c8b5b-451e-48f6-bdbb-759be4ea1a8f 10d19b1a-832b-4d60-bf9b-88dcd089db85 Autobiography
33 4bc5ad4d-b7a3-47a7-9938-325c6fdf8041 85b5a640-7e9a-468e-80e2-e9268486031b Essay
34 e0d350c2-1f42-45b5-b768-67cccd997b56 85b5a640-7e9a-468e-80e2-e9268486031b Speech

View File

@@ -25,7 +25,7 @@ entity Authors : managed {
/** Hierarchically organized Code List for Genres */
entity Genres : sap.common.CodeList {
key ID : Integer;
key ID : UUID;
parent : Association to Genres;
children : Composition of many Genres on children.parent = $self;
}

View File

@@ -2,4 +2,5 @@ using { sap.capire.bookshop as my } from '../db/schema';
service AdminService @(requires:'admin', path:'/admin') {
entity Books as projection on my.Books;
entity Authors as projection on my.Authors;
entity GenreHierarchy as projection on my.Genres
}

View File

@@ -1,4 +1,7 @@
using { sap.capire.bookshop as my } from '../db/schema';
using {my.common.Hierarchy as Hierarchy} from './hierarchy';
extend my.Genres with Hierarchy;
service CatalogService @(path:'/browse') {
/** For displaying lists of Books */
@@ -10,6 +13,9 @@ service CatalogService @(path:'/browse') {
author.name as author
} excluding { createdBy, modifiedBy };
@readonly
entity GenreHierarchy as projection on my.Genres;
@requires: 'authenticated-user'
action submitOrder ( book: Books:ID, quantity: Integer ) returns { stock: Integer };
event OrderedBook : { book: Books:ID; quantity: Integer; buyer: String };

View File

@@ -0,0 +1,29 @@
namespace my.common;
aspect Hierarchy {
virtual LimitedDescendantCount : Integer64;
virtual DistanceFromRoot : Integer64;
virtual DrillState : String;
virtual Matched : Boolean;
virtual MatchedDescendantCount : Integer64;
virtual LimitedRank : Integer64;
}
annotate Hierarchy with @Capabilities.FilterRestrictions.NonFilterableProperties: [
'LimitedDescendantCount',
'DistanceFromRoot',
'DrillState',
'Matched',
'MatchedDescendantCount',
'LimitedRank'
];
annotate Hierarchy with @Capabilities.SortRestrictions.NonSortableProperties: [
'LimitedDescendantCount',
'DistanceFromRoot',
'DrillState',
'Matched',
'MatchedDescendantCount',
'LimitedRank'
];

View File

@@ -40,7 +40,68 @@ annotate AdminService.Books with @(
}
);
////////////////////////////////////////////////////////////////////////////
//
// Value Help for Tree Table
//
annotate AdminService.Books with {
genre @(Common: {
Label : 'Genre',
ValueList: {
CollectionPath : 'GenreHierarchy',
Parameters : [
{
$Type : 'Common.ValueListParameterDisplayOnly',
ValueListProperty: 'name',
},
{
$Type : 'Common.ValueListParameterInOut',
LocalDataProperty: genre_ID,
ValueListProperty: 'ID',
}
],
PresentationVariantQualifier: 'VH',
}
});
}
annotate AdminService.GenreHierarchy with @UI: {
PresentationVariant #VH: {
$Type : 'UI.PresentationVariantType',
Visualizations : ['@UI.LineItem'],
RecursiveHierarchyQualifier: 'GenreHierarchy'
},
LineItem : [{
$Type: 'UI.DataField',
Value: name,
Label : 'Genre'
}],
};
// Hide ID because of the ValueHelp
annotate AdminService.GenreHierarchy with {
ID @UI.Hidden;
};
////////////////////////////////////////////////////////////////////////////
//
// Tree Table
//
annotate AdminService.GenreHierarchy with @Aggregation.RecursiveHierarchy#GenreHierarchy: {
$Type: 'Aggregation.RecursiveHierarchyType',
NodeProperty: ID, // identifies a node
ParentNavigationProperty: parent // navigates to a node's parent
};
annotate AdminService.GenreHierarchy with @Hierarchy.RecursiveHierarchy#GenreHierarchy: {
$Type: 'Hierarchy.RecursiveHierarchyType',
LimitedDescendantCount: LimitedDescendantCount,
DistanceFromRoot: DistanceFromRoot,
DrillState: DrillState,
Matched: Matched,
MatchedDescendantCount: MatchedDescendantCount,
LimitedRank: LimitedRank
};
////////////////////////////////////////////////////////////
//
@@ -82,5 +143,3 @@ extend service AdminService {
// Workaround for Fiori popup for asking user to enter a new UUID on Create
annotate AdminService.Books with { ID @Core.Computed; }
// Show Genre as drop down, not a dialog
annotate AdminService.Books with { genre @Common.ValueListWithFixedValues; }

View File

@@ -24,7 +24,7 @@
"id": "BrowseGenres",
"tileType": "sap.ushell.ui.tile.StaticTile",
"properties": {
"title": "Browse Genres (OData v2)",
"title": "Browse Genres",
"targetURL": "#Genres-display"
}
}

View File

@@ -55,3 +55,16 @@ annotate CatalogService.Books with @(UI : {
{Value : currency.symbol},
]
}, );
annotate CatalogService.GenreHierarchy with @UI: {
PresentationVariant : {
$Type : 'UI.PresentationVariantType',
RequestAtLeast: [name],
Visualizations: ['@UI.LineItem'],
},
LineItem : [{
$Type: 'UI.DataField',
Value: name,
Label : 'Genre'
}],
};

View File

@@ -80,7 +80,8 @@ annotate my.Genres with @(
LineItem : [
{ Value: name },
{
Value : parent.name,
Value : name,
// TODO: i18n
Label: 'Main Genre'
},
],
@@ -115,7 +116,6 @@ annotate my.Genres with @(UI : {
// Genres Elements
//
annotate my.Genres with {
ID @title: '{i18n>ID}';
name @title: '{i18n>Genre}';
}

View File

@@ -1,8 +1,20 @@
using { sap.capire.bookshop } from '../../db/common';
/*
UI annotations for the Browse GenreHierarchy App
*/
using CatalogService from '@capire/bookstore';
annotate bookshop.GenreHierarchy {
ID @sap.hierarchy.node.for;
parent @sap.hierarchy.parent.node.for;
hierarchyLevel @sap.hierarchy.level.for;
drillState @sap.hierarchy.drill.state.for;
}
annotate CatalogService.GenreHierarchy with @Aggregation.RecursiveHierarchy#GenreHierarchy: {
$Type: 'Aggregation.RecursiveHierarchyType',
NodeProperty: ID, // identifies a node
ParentNavigationProperty: parent // navigates to a node's parent
};
annotate CatalogService.GenreHierarchy with @Hierarchy.RecursiveHierarchy#GenreHierarchy: {
$Type: 'Hierarchy.RecursiveHierarchyType',
LimitedDescendantCount: LimitedDescendantCount,
DistanceFromRoot: DistanceFromRoot,
DrillState: DrillState,
Matched: Matched,
MatchedDescendantCount: MatchedDescendantCount,
LimitedRank: LimitedRank
};

View File

@@ -1,7 +1,3 @@
sap.ui.define(["sap/suite/ui/generic/template/lib/AppComponent"], (AppComponent) =>
AppComponent.extend("genres.Component", {
metadata: {
manifest: "json",
},
})
);
sap.ui.define(["sap/fe/core/AppComponent"], ac => ac.extend("genres.Component", {
metadata:{ manifest:'json' }
}))

View File

@@ -1,4 +1,4 @@
#XTIT
appTitle=Genres
appTitle=Browse Genres
#XTXT
appDescription=Browse Genres
appDescription=Genres as Tree View

View File

@@ -0,0 +1,2 @@
appTitle=Zeige Genres
appDescription=Genres als Baumansicht

View File

@@ -3,18 +3,31 @@
"sap.app": {
"id": "genres",
"type": "application",
"title": "Browse genres",
"description": "Sample Application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "Browse Genres Hierarchy (OData v2)",
"description": "{{appDescription}}",
"dataSources": {
"CatalogService": {
"uri": "browse/",
"type": "OData",
"settings": {
"odataVersion": "4.0"
}
}
},
"tags": {
"keywords": []
},
"crossNavigation": {
"inbounds": {
"appShow": {
"Genres-display": {
"signature": {
"parameters": {},
"additionalParameters": "allowed"
},
"title": "{{appTitle}}",
"semanticObject": "GenreHierarchy",
"action": "display",
@@ -29,25 +42,6 @@
},
"outbounds": {}
},
"ach": "",
"resources": "resources.json",
"dataSources": {
"main": {
"uri": "/odata/v2/browse",
"type": "OData",
"settings": {
"annotations": ["localAnnotations"],
"localUri": "localService/metadata.xml"
}
},
"localAnnotations": {
"type": "ODataAnnotation",
"uri": "annotations/localAnnotations.xml",
"settings": {
"localUri": "annotations/localAnnotations.xml"
}
}
},
"offline": false,
"sourceTemplate": {
"id": "ui5template.smartTemplate",
@@ -86,70 +80,79 @@
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/i18n.properties"
},
"@i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/i18n.properties"
},
"json": {
"type": "sap.ui.model.json.JSONModel"
},
"i18n|sap.suite.ui.generic.template.ListReport|Genres": {
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/ListReport/Genres/i18n.properties"
},
"": {
"dataSource": "main",
"preload": true,
"dataSource": "CatalogService",
"settings": {
"useBatch": true,
"defaultBindingMode": "TwoWay",
"defaultCountMode": "Inline",
"refreshAfterChange": true,
"metadataUrlParams": {
"sap-value-list": "none"
"synchronizationMode": "None",
"operationMode": "Server",
"autoExpandSelect": true,
"earlyRequests": true,
"groupProperties": {
"default": {
"submit": "Auto"
}
}
}
}
},
"routing": {
"routes": [
{
"pattern": ":?query:",
"name": "GenreHierarchyList",
"target": "GenreHierarchyList"
},
{
"pattern": "GenreHierarchy({key}):?query:",
"name": "GenreHierarchyDetails",
"target": "GenreHierarchyDetails"
}
],
"targets": {
"GenreHierarchyList": {
"type": "Component",
"id": "GenreHierarchyList",
"name": "sap.fe.templates.ListReport",
"options": {
"settings" : {
"contextPath" : "/GenreHierarchy",
"navigation" : {
"GenreHierarchy" : {
"detail" : {
"route" : "GenreHierarchyDetails"
}
}
},
"controlConfiguration": {
"@com.sap.vocabularies.UI.v1.LineItem": {
"tableSettings": {
"hierarchyQualifier": "GenreHierarchy",
"type": "TreeTable"
}
}
}
}
}
},
"GenreHierarchyDetails": {
"type": "Component",
"id": "GenreHierarchyDetails",
"name": "sap.fe.templates.ObjectPage",
"options": {
"settings" : {
"contextPath" : "/GenreHierarchy"
}
}
}
}
},
"contentDensities": {
"compact": true,
"cozy": true
}
},
"sap.ui.generic.app": {
"_version": "1.3.0",
"settings": {
"forceGlobalRefresh": false,
"useColumnLayoutForSmartForm": false,
"showBasicSearch": false
},
"pages": {
"ListReport|Genres": {
"entitySet": "GenreHierarchy",
"component": {
"name": "sap.suite.ui.generic.template.ListReport",
"list": true,
"settings": {
"condensedTableLayout": true,
"smartVariantManagement": true,
"tableType": "TreeTable",
"enableTableFilterInPageVariant": true,
"dataLoadSettings": {
"loadDataOnAppLaunch": "always"
}
}
}
}
}
},
"sap.fiori": {
"registrationIds": [],
"archeType": "transactional"
},
"sap.platform.hcp": {
"uri": ""
},
"sap.platform.cf": {
"oAuthScopes": []
}
}

View File

@@ -1,14 +0,0 @@
namespace sap.capire.bookshop;
using { sap.capire.bookshop } from '@capire/bookstore/srv/mashup';
entity GenreHierarchy : bookshop.Genres {
hierarchyLevel : Integer default 0;
drillState : String default 'leaf';
parent : Association to GenreHierarchy;
children : Composition of many GenreHierarchy on children.parent = $self;
}
extend service CatalogService with {
@readonly entity GenreHierarchy as projection on bookshop.GenreHierarchy;
}

View File

@@ -1,16 +0,0 @@
ID;parent_ID;name;hierarchyLevel;drillState
10;;Fiction;0;expanded
11;10;Drama;1;leaf
12;10;Poetry;1;leaf
13;10;Fantasy;1;leaf
14;10;Science Fiction;1;leaf
15;10;Romance;1;leaf
16;10;Mystery;1;leaf
17;10;Thriller;1;leaf
18;10;Dystopia;1;leaf
20;;Non-Fiction;0;expanded
19;10;Fairy Tale;1;leaf
21;20;Biography;1;expanded
22;21;Autobiography;2;leaf
23;20;Essay;1;leaf
24;20;Speech;1;leaf
1 ID parent_ID name hierarchyLevel drillState
2 10 Fiction 0 expanded
3 11 10 Drama 1 leaf
4 12 10 Poetry 1 leaf
5 13 10 Fantasy 1 leaf
6 14 10 Science Fiction 1 leaf
7 15 10 Romance 1 leaf
8 16 10 Mystery 1 leaf
9 17 10 Thriller 1 leaf
10 18 10 Dystopia 1 leaf
11 20 Non-Fiction 0 expanded
12 19 10 Fairy Tale 1 leaf
13 21 20 Biography 1 expanded
14 22 21 Autobiography 2 leaf
15 23 20 Essay 1 leaf
16 24 20 Speech 1 leaf