Skip to content

Commit

Permalink
chore: add first draft for ui5 association handling
Browse files Browse the repository at this point in the history
  • Loading branch information
Thodd committed Aug 22, 2024
1 parent 44cc9ab commit d01534d
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 30 deletions.
27 changes: 24 additions & 3 deletions packages/ui5-tooling-modules/lib/utils/WebComponentRegistry.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,18 @@ class RegistryEntry {
// Does that make sense? Probably should be an empty array instead of undefined?
let parsedType = typeInfo?.text;
if (parsedType?.indexOf("|") > 0) {
parsedType = parsedType.replace(/ \| undefined/g, "");
const types = parsedType.split("|").map((s) => s.trim());
// "htmlelement | string" is an association, e.g. the @ui5-webcomponents/Popover#opener
if (types[0] === "HTMLElement" && types[1] === "string") {
return {
isAssociation: true,
origType: "HTMLElement",
ui5Type: "sap.ui.core.Control",
};
}
// UI5 normally accepts only one type for a property, except if "any" is used
// in this case we just use the first one as the primary type
parsedType = types[0];
}

// check if we have an array type
Expand Down Expand Up @@ -164,7 +175,7 @@ class RegistryEntry {
};
}

// case 3: hm... neither primitive, nor enum or interface/class type
// case 3: check for cross package type reference
const refPackage = WebComponentRegistry.getPackage(typeInfo.references[0]?.package);
if (refPackage?.enums?.[parsedType]) {
return {
Expand Down Expand Up @@ -223,7 +234,17 @@ class RegistryEntry {
if (propDef.readonly) {
// s.a.
console.log(`[readonly field] ${classDef.name} - property ${propDef.name}`);
} else if (!ui5TypeInfo.isInterfaceOrClassType) {
} else if (ui5TypeInfo.isInterfaceOrClassType) {
console.warn(`[interface or class type given for property] ${classDef.name} - property ${propDef.name}`);
} else if (ui5TypeInfo.isAssociation) {
ui5metadata.associations[propDef.name] = {
type: ui5TypeInfo.ui5Type,
mapping: {
type: "property", // assoc. are always property mappings
to: propDef.name, // the name of the webc's attribute
},
};
} else {
let defaultValue = propDef.default;
if (defaultValue) {
// TODO: Why are the default value strings escaped?
Expand Down
30 changes: 30 additions & 0 deletions showcases/ui5-tsapp-simple/webapp/controller/Main.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ import Popup from "sap/ui/core/Popup";
import Event from "sap/ui/base/Event";
import { AvatarSize } from "@ui5/webcomponents/library";

function injectStyle() {
const sheet = new CSSStyleSheet();
sheet.replaceSync(`
.panelSpacing {
margin: 10px;
}
.popover-content {
display: flex;
flex-direction: column;
justify-content: center;
}
`);
document.adoptedStyleSheets.push(sheet);
}

WebComponentRenderer.renderAttributeProperties = function (oRm, oWebComponent) {
var oAttrProperties = oWebComponent.getMetadata().getPropertiesByMapping("property");
var aPropsToAlwaysSet = ["enabled"].concat(
Expand Down Expand Up @@ -54,6 +69,8 @@ WebComponentRenderer.renderAttributeProperties = function (oRm, oWebComponent) {
*/
export default class Main extends Controller {
public onInit(): void {
injectStyle();

const button = new Button({ text: "👻", click: this.onBoo });
if (button instanceof Control) {
(this.getView()?.byId("contentArea") as VBox).addItem(button);
Expand All @@ -67,13 +84,26 @@ export default class Main extends Controller {
(this.getView()?.byId("contentArea") as VBox).addItem(input);
}
}

public onNavToDynamicPage(): void {
this.getOwnerComponent().getRouter().navTo("DynamicPage");
}

public onBoo(): void {
MessageToast.show(`👻`);
}

public onLiveChange(e: Event): void {
MessageToast.show(`🛠️ liveChange: ${e.getParameter("selectedOption").getText()}`, { at: Popup.Dock.CenterCenter });
}

// wire popover opener buttons
public onPopoverOpener1Click(e: Event): void {
const poppy1 = this.byId("popover1");
poppy1?.setOpen(!poppy1?.getOpen());
}
public onPopoverOpener2Click(e: Event): void {
const poppy2 = this.byId("popover2");
poppy2?.setOpen(!poppy2?.getOpen());
}
}
131 changes: 104 additions & 27 deletions showcases/ui5-tsapp-simple/webapp/view/Main.view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:mvc="sap.ui.core.mvc"
xmlns:control="ui5.ecosystem.demo.simpletsapp.control"
xmlns:c="ui5.ecosystem.demo.simpletsapp.control"
xmlns:webc="@ui5/webcomponents"
core:require="{
Formatter: 'ui5/ecosystem/demo/simpletsapp/model/Formatter',
Expand All @@ -21,33 +21,110 @@
<core:Icon color="#1873B4" src="sap-icon://sap-ui5" size="2rem" />
</headerContent>
<content>
<VBox id="contentArea" alignItems="Center" justifyContent="Center" height="100%">
<control:SimpleControl text="Hello World" />
<webc:Button text="nav to DynamicPage" click=".onNavToDynamicPage" design="Attention" endIcon="slim-arrow-right" />
<Button text="Don't press me!" press="onBoo" />
<webc:Button text="Hello World 123" />
<webc:Input value="Hello World 123" change="onBoo" />
<webc:AvatarGroup type="Individual">
<webc:Avatar initials="PM" colorScheme="Accent1" />
<webc:Avatar initials="XX" colorScheme="Accent4" shape="Square" />
<webc:Avatar icon="ai" colorScheme="Accent7" />
</webc:AvatarGroup>
<webc:DateRangePicker />
<webc:CheckBox text="Hello World 123" />
<webc:List>
<webc:ListItemStandard text="Item 1" />
<webc:ListItemStandard text="Item 2" />
<webc:ListItemStandard text="Item 3" />
</webc:List>
<webc:Select liveChange=".onLiveChange">
<webc:Option text="AI" icon="ai" />
<webc:Option text="Biometric" icon="biometric-face" />
<webc:Option text="Security" icon="badge" />
</webc:Select>

<!-- fragment uses "@ui5/webcomponents-fiori" package -->
<webc:Panel headerText="Buttons" class="panelSpacing">
<VBox alignItems="Center" justifyContent="Center" height="100%">
<webc:Button text="nav to DynamicPage" click=".onNavToDynamicPage" design="Attention" endIcon="slim-arrow-right" />
<Button text="Don't press me!" press="onBoo" />
<webc:Button text="Hello World 123" />
</VBox>
</webc:Panel>

<webc:Panel headerText="Simple Controls" class="panelSpacing">
<VBox alignItems="Center" justifyContent="Center" height="100%">
<webc:Input value="Hello World 123" change="onBoo" />
<webc:AvatarGroup type="Individual">
<webc:Avatar initials="PM" colorScheme="Accent1" />
<webc:Avatar initials="XX" colorScheme="Accent4" shape="Square" />
<webc:Avatar icon="ai" colorScheme="Accent7" />
</webc:AvatarGroup>
<webc:CheckBox text="Hello World 123" />
</VBox>
</webc:Panel>

<webc:Panel headerText="More complex controls" class="panelSpacing">
<VBox alignItems="Center" justifyContent="Center" height="100%">
<webc:DateRangePicker />
<webc:List>
<webc:ListItemStandard text="Item 1" />
<webc:ListItemStandard text="Item 2" />
<webc:ListItemStandard text="Item 3" />
</webc:List>
<webc:Select liveChange=".onLiveChange">
<webc:Option text="AI" icon="ai" />
<webc:Option text="Biometric" icon="biometric-face" />
<webc:Option text="Security" icon="badge" />
</webc:Select>
</VBox>
</webc:Panel>

<webc:Panel headerText="Controls created from Main.controller.ts" class="panelSpacing">
<VBox id="contentArea" alignItems="Center" justifyContent="Center" height="100%" />
</webc:Panel>

<webc:Panel headerText="Popovers + Associations" class="panelSpacing">
<HBox alignItems="Center" justifyContent="Center" height="100%">
<webc:Button id="popoverOpenerButton1" text="Open Popover to Bottom" click=".onPopoverOpener1Click" />
<webc:Button id="popoverOpenerButton2" text="Open Popover to Left" click=".onPopoverOpener2Click" />

<webc:Popover id="popover1" opener="popoverOpenerButton1" headerText="Newsletter subscription" placement="Bottom">
<c:HTMLElement tag="div" class="popover-content">
<webc:Label for="emailInput" required="true" showColon="true" text="Email" />
<webc:Input id="emailInput1" placeholder="Enter Email" />
<!-- TODO: support for inline styles = style="min-width: 150px;" -->
<webc:Label text="The popover is associated with the Button. Calling getOpener() returns the ID of the Button." />
</c:HTMLElement>
<webc:footer>
<c:HTMLElement tag="div" class="popover-footer">
<webc:Button id="closePopoverButton1" design="Emphasized" text="Subscribe" />
</c:HTMLElement>
</webc:footer>
</webc:Popover>

<webc:Popover id="popover2" opener="popoverOpenerButton2" headerText="Newsletter subscription" placement="Start">
<c:HTMLElement tag="div" class="popover-content">
<webc:Label for="emailInput" required="true" showColon="true" text="Email" />
<webc:Input id="emailInput2" placeholder="Enter Email" />
<!-- TODO: support for inline styles = style="min-width: 150px;" -->
<webc:Label text="The popover is associated with the Button. Calling getOpener() returns the ID of the Button." />
</c:HTMLElement>
<webc:footer>
<c:HTMLElement tag="div" class="popover-footer">
<webc:Button id="closePopoverButton2" design="Emphasized" text="Subscribe" />
</c:HTMLElement>
</webc:footer>
</webc:Popover>
</HBox>
</webc:Panel>

<!-- fragment uses "@ui5/webcomponents-fiori" package -->
<webc:Panel headerText="@ui5/webcomponents-fiori.NotificationList" class="panelSpacing">
<core:Fragment fragmentName="ui5.ecosystem.demo.simpletsapp.view.fiori.NotificationList" />
</VBox>
</webc:Panel>

<!-- Not supported as of now, but would be nice to have -->
<!-- <h:div style="
background: #FAFAFA;
border-bottom: 2px solid #777777;
border-radius: 5px;
box-shadow: 0px 5px 10px #999999;
padding: 10px;
margin: 10px">
<h:div style="border-bottom: 1px solid #D0D0D0; padding: 2px;">
I'm a self made card :)
</h:div>
<h:div>
<h:p>This is a checkbox:</h:p>
<webc:CheckBox text="inside div" />
<h:p>
<h:a href="https://ui5.sap.com" data-sap-ui-test="12" enabled="true">link to demokit</h:a>
</h:p>
<h:p>
text content before the &lt;hr&gt;...
<h:hr />
... and text content after the &lt;hr&gt;.
</h:p>
</h:div>
</h:div> -->
</content>
</Page>
</mvc:View>
12 changes: 12 additions & 0 deletions showcases/ui5-tsapp-simple/webapp/view/fiori/DynamicPage.view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,18 @@
</webc:ListItemStandard>
</webc:List>

<!-- pure HTML sample, not supported as of now... but would be nice to have in the future -->
<!-- <h:div children="{dpModel>/items}">
<h:div>
<h:span>
<webc:Avatar size="S" shape="Square" colorScheme="Accent10">
<m:Image src="{dpModel>imageSrc}" />
</webc:Avatar>
</h:span>
<h:span>{dpModel&gt;productID}<h:span/>
</h:div>
</h:div> -->

<fiori:footerArea>
<webc:Bar design="FloatingFooter">
<webc:endContent>
Expand Down

0 comments on commit d01534d

Please sign in to comment.