diff --git a/docs/ref-arch/RA0001/5-aws-iot-integration/readme.md b/docs/ref-arch/RA0001/5-aws-iot-integration/readme.md index 002336e12e..126caa0b8b 100644 --- a/docs/ref-arch/RA0001/5-aws-iot-integration/readme.md +++ b/docs/ref-arch/RA0001/5-aws-iot-integration/readme.md @@ -3,24 +3,24 @@ id: id-ra0001-5 slug: /ref-arch/fbdc46aaae/5 sidebar_position: 1 sidebar_custom_props: - category_index: [] + category_index: [] title: Build Events-to-Business Actions Scenarios with SAP BTP and AWS IoT SiteWise description: >- - Create event-driven architecture with AWS IoT SiteWise and SAP BTP for - seamless business process integration. + Create event-driven architecture with AWS IoT SiteWise and SAP BTP for + seamless business process integration. keywords: - - sap - - aws iot integration - - event-to-business actions - - cloud application programming + - sap + - aws iot integration + - event-to-business actions + - cloud application programming sidebar_label: Integration with Amazon Web Services image: img/ac-soc-med.png tags: - - cap - - aws - - appdev - - integration - - eda + - cap + - aws + - appdev + - integration + - eda hide_table_of_contents: false hide_title: false toc_min_heading_level: 2 @@ -28,14 +28,14 @@ toc_max_heading_level: 4 draft: false unlisted: false contributors: - - anbazhagan-uma - - pra1veenk - - AjitKP91 - - swatimaste00 -discussion: + - anbazhagan-uma + - pra1veenk + - AjitKP91 + - swatimaste00 +discussion: last_update: - author: swatimaste00 - date: 2025-05-10 + author: swatimaste00 + date: 2025-05-10 --- ## Introduction @@ -53,20 +53,21 @@ The following steps depicts the information flow across systems: 1. An application administrator logs into SAP BTP Extension application based on Events to Business Actions Framework via SAP Build Work Zone, standard edition, to configure the business rules/decisions and the business actions that needs to be triggered in the business systems. 2. AWS IoT SiteWise Edge at the factory captures the equipment parameters like vibration, temperature, and forwards it to AWS IoT SiteWise which then dumps these events into Amazon S3, which triggers an AWS Lambda function. It detects anomaly in these events and publishes such events to the SAP Integration Suite, Advanced Event Mesh. - + 3. As the processor module's (part of the Events-to-Business-Action framework) subscribes to Advanced event mesh, the event is received. - + 4. Processor module (part of the Events-to-Business-Action framework) leverages the Decisions capability of SAP Build Process Automation to derive business action (for example, plant Maintenance Notification/purchase order requisition creation in SAP S/4HANA) based on certain characteristics of incoming event. - + 5. The framework integrates with SAP AI Core to invoke a deployed Amazon Bedrock Claude 3 Sonnet model. This model processes raw, hard-to-read incoming IoT event data and generates easy-to-read summaries of the event payload. These summaries are then automatically populated into the maintenance notification description, improving readability and providing enhanced clarity for maintenance teams. With this we prepare a complete payload which is used to execute the business action in SAP S/4HANA system (in this PoC we create a Plant Maintenance Notification) - + 6. The defined action is triggered in SAP S/4HANA using the SAP Destination service and SAP Connectivity service leveraging Private Link setup. In case SAP S/4HANA and SAP BTP are not on same Hyperscaler, communication with SAP S/4HANA happens via SAP Cloud Connector service. ## List of Services and Components -These are the technical prerequisites for integration between AWS IoT SiteWise, SAP BTP and SAP S/4HANA. +These are the technical prerequisites for integration between AWS IoT SiteWise, SAP BTP and SAP S/4HANA. ### SAP BTP Services + - **SAP Cloud Foundry Runtime** - Foundation for running the CAP extension application for translating events to business actions. - **Authorization and Trust Management Service** @@ -89,6 +90,7 @@ These are the technical prerequisites for integration between AWS IoT SiteWise, - SAP AI Launchpad is a multi-tenant software as a service (SaaS) application in SAP Business Technology Platform that provides generative AI capabilities via the Generative AI Hub. Customers and partners can use SAP AI Launchpad to manage AI use cases (scenarios) across multiple instances of AI runtimes (such as SAP AI Core). ### AWS Cloud Products + - **A valid Amazon AWS subscription** - **AWS IoT SiteWise** - Required for receiving and sending the events whenever an abnormality is detected in the equipment. @@ -97,8 +99,8 @@ These are the technical prerequisites for integration between AWS IoT SiteWise, - **AWS Secret Manager** - Required to store the SAP Integration,advanced event mesh credentials that are accessed by the Amazon Lambda Function. - **Amazon Lambda Function** - - Required to orchestrate the process of detecting a stream contains any alerts related to failure or warnings, and then the inference result is passed to SAP Integration Suite Advanced Event Mesh. + - Required to orchestrate the process of detecting a stream contains any alerts related to failure or warnings, and then the inference result is passed to SAP Integration Suite Advanced Event Mesh. For detailed step by step information and to try out the integration, go to [GitHub Samples](https://github.com/SAP-samples/btp-events-to-business-actions-framework/tree/main/scenarios/Integration-with-AWS/IoTSiteWise) -Refer to [Integrating Amazon Rekognition and SAP EHS with SAP BTP for PPE Detection](https://github.com/SAP-samples/btp-events-to-business-actions-framework/tree/main/scenarios/Integration-with-AWS/PPE) for another reference application implementation. \ No newline at end of file +Refer to [Integrating Amazon Rekognition and SAP EHS with SAP BTP for PPE Detection](https://github.com/SAP-samples/btp-events-to-business-actions-framework/tree/main/scenarios/Integration-with-AWS/PPE) for another reference application implementation. diff --git a/docs/ref-arch/RA0007/readme.md b/docs/ref-arch/RA0007/readme.md index 06d4bd92ce..051e858464 100644 --- a/docs/ref-arch/RA0007/readme.md +++ b/docs/ref-arch/RA0007/readme.md @@ -3,18 +3,18 @@ id: id-ra0007 slug: /ref-arch/d31bedf420 sidebar_position: 80 sidebar_custom_props: - category_index: - - appdev + category_index: + - appdev title: Multitenant SaaS Application using CAP description: >- - Develop scalable multitenant SaaS applications on SAP BTP using CAP for - cost-effective, tailored solutions. + Develop scalable multitenant SaaS applications on SAP BTP using CAP for + cost-effective, tailored solutions. keywords: - - sap - - multitenant saas - - application scalability - - btp innovation - - industry solutions + - sap + - multitenant saas + - application scalability + - btp innovation + - industry solutions sidebar_label: Multitenant SaaS Application using CAP image: img/ac-soc-med.png tags: @@ -27,12 +27,12 @@ toc_max_heading_level: 4 draft: false unlisted: false contributors: - - AjitKP91 - - alperdedeoglu -discussion: + - AjitKP91 + - alperdedeoglu +discussion: last_update: - author: Ajit Kumar Panda - date: 2025-01-31 + author: Ajit Kumar Panda + date: 2025-01-31 --- In today's rapidly evolving digital landscape, multitenancy has become a crucial concept in the context of SAP architecture, particularly for SAP partners and line of business (LoB) teams developing applications on [SAP Business Technology Platform (SAP BTP)](https://www.sap.com/india/products/technology-platform.html). As businesses increasingly turn to SaaS solutions for their needs, understanding and leveraging multitenancy has become essential for creating innovative, scalable, and cost-effective applications within the SAP ecosystem. @@ -47,42 +47,44 @@ In this reference architecture, we will explore the key components and best prac **_Multitenancy_** is a software architecture in which a single instance of a software application serves multiple customers, known as tenants. Each tenant is logically separated and operates as if they have their own isolated environment, even though they share the same underlying resources, such as the application itself, databases, and infrastructure. This allows for cost-efficient resource sharing and centralized management, making it an attractive model for SaaS providers. -| Single Tenancy | Multitenancy | -|:---:|:---:| -|![single-tenant](images/single-tenant.svg)|![multi-tenant](images/multi-tenant.svg)| -|In single tenancy design, for each customer, a separate instance of the application is deployed|In multitenancy design, a single application instance is deployed which severs multiple customers | +| Single Tenancy | Multitenancy | +| :---------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------: | +| ![single-tenant](images/single-tenant.svg) | ![multi-tenant](images/multi-tenant.svg) | +| In single tenancy design, for each customer, a separate instance of the application is deployed | In multitenancy design, a single application instance is deployed which severs multiple customers | ## Key Aspects 1. ### Tenants and Tenant Isolation - A **_Tenant_** represents a group of users (a company, a department, or an organization) who share common access privileges, configuration and data. In a multitenant environment, tenants may share the same software, infrastructure, and resources but should experience the application as if they have their own separate system. - **_Tenant Isolation_** ensures that each tenant's data and configurations are kept separate from other tenants. This is crucial for maintaining data privacy, security, and compliance. -2. ### Single Software Instance +2. ### Single Software Instance - Multitenancy allows for a **_single instance_** of the software application (or service) to serve multiple tenants simultaneously. This is key to the architecture's efficiency, as it minimizes resource usage by reducing duplication of infrastructure, application code, and maintenance efforts. - Despite running a single software instance, Tenants are unaware of each other's existence, and each tenant's users and data remains isolated. -3. ### Shared Resources +3. ### Shared Resources - One of the most important aspects of multitenancy is the ability to **share resources** across multiple tenants without them being aware of it. Resources shared can include: - - **Compute Resources**: CPU, memory, and network bandwidth are shared to ensure efficient use of server resources. - - **Storage Resources**: File systems or databases are partitioned or shared depending on the level of tenant isolation. - - Multitenant systems can dynamically allocate resources based on demand, scaling up or down as necessary. -4. ### Data Isolation and Security + - **Compute Resources**: CPU, memory, and network bandwidth are shared to ensure efficient use of server resources. + - **Storage Resources**: File systems or databases are partitioned or shared depending on the level of tenant isolation. + - Multitenant systems can dynamically allocate resources based on demand, scaling up or down as necessary. +4. ### Data Isolation and Security - While tenants share the same application instance, their data and configurations are isolated to ensure privacy and security. This can be achieved in several ways: - - **Logical Separation**: Separate database tables, schemas, or databases can be used for each tenant. - - **Access Controls**: Enterprise-Grade security models are implemented to restrict access to resources and ensure each tenant can only view and manipulate their own data. - - **Compliance**: Multitenant architectures must comply with various data protection laws like GDPR, HIPAA, or SOC 2, especially when dealing with sensitive or regulated industries. - - **Identity Management**: Identities, identity management and authentication shall be maintainable and configurable per tenant. -5. ### Performance and Resource Contention + - **Logical Separation**: Separate database tables, schemas, or databases can be used for each tenant. + - **Access Controls**: Enterprise-Grade security models are implemented to restrict access to resources and ensure each tenant can only view and manipulate their own data. + - **Compliance**: Multitenant architectures must comply with various data protection laws like GDPR, HIPAA, or SOC 2, especially when dealing with sensitive or regulated industries. + - **Identity Management**: Identities, identity management and authentication shall be maintainable and configurable per tenant. +5. ### Performance and Resource Contention - In a multitenant environment, performance is a key concern because multiple tenants are competing for the same set of resources. Resource contention can occur when one tenant’s usage affects the performance experienced by other tenants. This is managed through: - - **Resource Allocation and Throttling**: The system allocates resources based on tenant needs and may throttle tenants who exceed their usage quotas to prevent them from affecting others. - - **Horizontal Scalability**: Multitenant systems are typically designed to scale horizontally by adding more servers or instances when demand increases. This allows the system to handle large numbers of tenants without performance degradation. - - **Load Balancing**: Ensures even distribution of traffic and resource usage across servers to avoid bottlenecks and ensure consistent performance. + - **Resource Allocation and Throttling**: The system allocates resources based on tenant needs and may throttle tenants who exceed their usage quotas to prevent them from affecting others. + - **Horizontal Scalability**: Multitenant systems are typically designed to scale horizontally by adding more servers or instances when demand increases. This allows the system to handle large numbers of tenants without performance degradation. + - **Load Balancing**: Ensures even distribution of traffic and resource usage across servers to avoid bottlenecks and ensure consistent performance. 6. ### Tenant Onboarding and Offboarding - Multitenant systems typically have processes in place to efficiently onboard new tenants and offboard existing ones. - - **Onboarding**: New tenants can be added dynamically without requiring additional infrastructure setup. The application automatically provisions resources (e.g., database schemas) and configures settings specific to the tenant. - - **Offboarding**: When a tenant decides to leave, their data can be removed without affecting the rest of the system. + - **Onboarding**: New tenants can be added dynamically without requiring additional infrastructure setup. The application automatically provisions resources (e.g., database schemas) and configures settings specific to the tenant. + - **Offboarding**: When a tenant decides to leave, their data can be removed without affecting the rest of the system. ## Deep Dive + Implementing multitenant application on SAP BTP is a journey that involves understanding, planning, implementation, and continuous improvement. You can deep dive into various concepts, services and architecture before developing a multitenant application. + - [Benefits of Multitenant Applications](2-mt-benefits/readme.md) - [Tenant Model on SAP BTP](3-mt-models/readme.md) - [Reference Architecture](5-mt-architecture/readme.md) @@ -91,5 +93,6 @@ Implementing multitenant application on SAP BTP is a journey that involves under - [Authentication Strategies](7-mt-authentication/readme.md) ## References + - [SAP Blog - Fundamentals of Multitenancy in SAP BTP](https://community.sap.com/t5/technology-blogs-by-sap/fundamentals-of-multitenancy-in-sap-btp/ba-p/13527283) -- [Tenant Isolation](https://docs.aws.amazon.com/whitepapers/latest/saas-architecture-fundamentals/tenant-isolation.html) \ No newline at end of file +- [Tenant Isolation](https://docs.aws.amazon.com/whitepapers/latest/saas-architecture-fundamentals/tenant-isolation.html) diff --git a/src/components/ArticleHeader/index.module.css b/src/components/ArticleHeader/index.module.css index e0acbe300a..2878f29be4 100644 --- a/src/components/ArticleHeader/index.module.css +++ b/src/components/ArticleHeader/index.module.css @@ -26,6 +26,7 @@ line-height: var(--sapContent_LineHeight); color: var(--sapTextColor); margin: 0 0 1.5rem 0; + padding-right: 50px; font-family: var(--sapFontHeaderFamily); letter-spacing: var(--sapFontHeaderLetterSpacing); } @@ -139,3 +140,23 @@ .cancelButton { margin-left: 0.5rem; } + +/* Dark mode styles */ +:root[data-theme='dark'] .tag { + background-color: #1e3a5f; + color: #60a5fa; + border-color: #374151; +} + +:root[data-theme='dark'] .tag:hover { + background-color: #2d4a6f; + border-color: #60a5fa; +} + +:root[data-theme='dark'] .updateInfo { + color: #9ca3af; +} + +:root[data-theme='dark'] .updateInfo strong { + color: #e5e7eb; +} diff --git a/src/components/ArticleHeader/index.tsx b/src/components/ArticleHeader/index.tsx index b8d798c3aa..c2184fe53a 100644 --- a/src/components/ArticleHeader/index.tsx +++ b/src/components/ArticleHeader/index.tsx @@ -10,29 +10,22 @@ const formatDate = (timestamp: string | null | undefined): string => { if (!timestamp) return 'N/A'; try { - const datePart = timestamp.split(',')[0]; - - const parts = datePart.split('/'); - - if (parts.length !== 3) { - return datePart; - } - - const [day, month, year] = parts; - - const date = new Date(Number(year), Number(month) - 1, Number(day)); + // Parse ISO date string or existing Date + const date = new Date(timestamp); if (isNaN(date.getTime())) { - return datePart; + return timestamp; } - return date.toLocaleDateString('en-US', { - year: 'numeric', - month: 'short', - day: 'numeric', - }); + // Format: Mon DD, YYYY (e.g., May 22, 2026) + const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; + const month = months[date.getMonth()]; + const day = date.getDate(); + const year = date.getFullYear(); + + return `${month} ${day}, ${year}`; } catch { - return timestamp.split(',')[0]; + return timestamp; } }; @@ -53,11 +46,19 @@ interface EditableData { description: string; } -export default function ArticleHeader() { +interface ArticleHeaderProps { + readOnly?: boolean; + onEditMeta?: () => void; +} + +export default function ArticleHeader({ readOnly = false, onEditMeta }: ArticleHeaderProps) { const { getActiveDocument, updateDocument, lastSaveTimestamp } = usePageDataStore(); const activeDocument = getActiveDocument(); const globalTagsData = useGlobalData()['docusaurus-tags']['default']['tags'] as Record | undefined; + // Use lastSaveTimestamp from store, fallback to document's updatedAt + const displayTimestamp = lastSaveTimestamp || activeDocument?.updatedAt || null; + const { availableTags, tagKeyToLabelMap } = useMemo(() => { const tagsData = globalTagsData || {}; if (Object.keys(tagsData).length === 0) { @@ -175,9 +176,11 @@ export default function ArticleHeader() { return (

{activeDocument.title || 'Untitled Page'}

-
-
+ {!readOnly && ( +
+
+ )} {/*

{activeDocument.description || 'No description provided.'}

*/}
{activeDocument.tags.length > 0 && @@ -188,7 +191,7 @@ export default function ArticleHeader() { ))}

- Last updated on {formatDate(lastSaveTimestamp)} by{' '} + Last updated on {formatDate(displayTimestamp)} by{' '} {activeDocument.authors.length > 0 ? activeDocument.authors.join(', ') : 'Unknown'}

diff --git a/src/components/Breadcrumbs/index.module.css b/src/components/Breadcrumbs/index.module.css index 5f7fa7e6c1..6fca40ce89 100644 --- a/src/components/Breadcrumbs/index.module.css +++ b/src/components/Breadcrumbs/index.module.css @@ -25,11 +25,18 @@ transition: background-color 0.2s ease; display: flex; align-items: center; + background: none; + border: none; + font-size: inherit; + font-family: inherit; + cursor: pointer; } .breadcrumbCurrent { margin-left: 10px; + cursor: default; } + .breadcrumbLink:hover { background-color: #f0f1f2; color: #1c2a38; @@ -51,3 +58,31 @@ color: #aeb8c4; font-size: 14px; } + +/* Dark mode styles */ +:root[data-theme='dark'] .breadcrumbLink, +:root[data-theme='dark'] .breadcrumbCurrent { + color: #9ca3af; +} + +:root[data-theme='dark'] .breadcrumbLink:hover { + background-color: #374151; + color: #e5e7eb; +} + +:root[data-theme='dark'] .breadcrumbCurrent { + color: #60a5fa; + background-color: #1e3a5f; +} + +:root[data-theme='dark'] .separator { + color: #6b7280; +} + +:root[data-theme='dark'] .homeIcon { + color: #d1d5db; +} + +:root[data-theme='dark'] .breadcrumbLink:hover .homeIcon { + color: #ffffff; +} diff --git a/src/components/Breadcrumbs/index.tsx b/src/components/Breadcrumbs/index.tsx index 5f331df250..2522bc0464 100644 --- a/src/components/Breadcrumbs/index.tsx +++ b/src/components/Breadcrumbs/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Document } from '@site/src/store/pageDataStore'; +import { Document, usePageDataStore } from '@site/src/store/pageDataStore'; import { Icon } from '@ui5/webcomponents-react'; import '@ui5/webcomponents-icons/dist/home.js'; import '@ui5/webcomponents-icons/dist/slim-arrow-right.js'; @@ -10,10 +10,17 @@ interface BreadcrumbsProps { } const Breadcrumbs: React.FC = ({ path }) => { + const { setActiveDocumentId } = usePageDataStore(); + if (!path || path.length === 0) { return null; } + const handleBreadcrumbClick = (e: React.MouseEvent, docId: string) => { + e.preventDefault(); + setActiveDocumentId(docId); + }; + return (