diff --git a/_snippets/btp-trial-setup.md b/_snippets/btp-trial-setup.md new file mode 100644 index 0000000..736b77b --- /dev/null +++ b/_snippets/btp-trial-setup.md @@ -0,0 +1,14 @@ +--- +params: + - name: region + required: true + default: us10 +--- + +Follow these steps to create a BTP Trial account in region **{{param:region}}**: + +1. Navigate to [SAP BTP Trial](https://account.hanatrial.ondemand.com/). +2. Select region `{{param:region}}` during signup. +3. Complete the registration form and confirm your email. + +> **Note:** Free trial accounts expire after 365 days. Renew before expiry to keep your data. diff --git a/tutorials/directive-authoring-aids/directive-authoring-aids.md b/tutorials/directive-authoring-aids/directive-authoring-aids.md new file mode 100644 index 0000000..db4bda8 --- /dev/null +++ b/tutorials/directive-authoring-aids/directive-authoring-aids.md @@ -0,0 +1,142 @@ +--- +parser: v2 +auto_validation: false +time: 10 +tags: [ tutorial>beginner, topic>developer-tools ] +primary_tag: topic>developer-tools +author_name: SAP Developer Advocates +author_profile: https://github.com/sap-tutorials +--- + +# Use Authoring Aids to Annotate and Review Tutorials + Demonstrate the three authoring aids built into the tutorial platform: inline and block author notes (`%% … %%`), QA-only content blocks (`:::qa-only`), and the `deprecated-cli` freshness lint rule — tools that help authors and reviewers collaborate without affecting what production readers see. + +## You will learn +- How to embed reviewer comments directly in tutorial source with author notes +- How to include content that is visible only on the QA channel +- How the CLI freshness linter catches outdated commands at build time + +## Prerequisites + +- You have write access to a repository under the `sap-tutorials` GitHub organization +- You have the QA author-preview channel available at `/tutorials-qa/` +- You have Node.js installed locally + +--- + +### Step 1: Add Author Notes to Mark Content for Review + +Author notes let you leave comments for co-authors and reviewers directly in the +tutorial markdown. They are stripped before the HTML reaches production readers. + +An inline note sits on the same line as prose, delimited by `%%`: + +```markdown +Run the deployment command below %% @reviewer: confirm this works with SDK v4 — see issue #321 %% and wait for the output. +``` + + + +A block note spans multiple lines. A bare `%%` opens it and a bare `%%` closes it: + +```markdown +%% +@author: The screenshot below is from the old tenant. Replace once the +new BTP tenant is provisioned — tracked in https://github.com/sap-tutorials/…/issues/88. +%% +``` + + + +%% @reviewer: Does the step flow here feel natural for a new author? Consider splitting into sub-steps if needed. %% + +After you add a note, open the tutorial on the QA channel to verify it renders +as a callout. When the content is finalized, remove the notes before promoting +the tutorial to PROD. + +### Step 2: Add QA-only Blocks for Reviewer Context + +Sometimes you want to leave instructions for your reviewer that are not part of +the published content at all. Use a `:::qa-only` directive for this. + +The block below is visible on the QA channel only. On PROD it is stripped +entirely, including this sentence: + +:::qa-only[Reviewer checklist — remove or resolve before PROD promotion] +Before approving this tutorial for PROD, verify: + +- The screenshots in Step 1 match the current BTP Cockpit UI +- The time estimate (10 minutes) is realistic for a new developer +- All code fences use the correct language tag (`bash`, `typescript`, etc.) +- No author notes (`%% … %%`) remain in the source + +This block will not appear in the published tutorial. It is visible only on +`/tutorials-qa/` when you are logged in with the `Tutorial.Author` scope. +::: + + + +After reviewing the tutorial on QA, the block can stay in the source until the +review is complete. Remove it (or leave it if it is permanently useful for +future reviewers) before the final PROD push. + +%% +@author: We could keep this qa-only block permanently as a standard review checklist. +Check with the team whether we want a shared template or per-tutorial checklists. +%% + +### Step 3: Understand CLI Freshness Lint Findings + +The tutorial platform runs `lint-tutorial-markdown` during `npm run build:all`. +One of its rules, `deprecated-cli`, scans every shell code fence for known +deprecated CLI commands. + +The following example contains a deprecated `cf push` flag that the linter +catches at build time: + +```bash +cf push myapp --hostname myhost +``` + + + +The corrected command uses an application manifest instead: + +```yaml +# manifest.yml +applications: + - name: myapp + routes: + - route: myhost.cfapps.eu10.hana.ondemand.com +``` + +```bash +cf push myapp +``` + +%% @author: The deprecated example above is intentional — it demonstrates what the linter catches. Do NOT fix it before the sample is reviewed by the team. %% + +To run the linter locally against a single tutorial: + +```bash +npx tsx scripts/lint-tutorial-markdown.ts directive-authoring-aids +``` + +Pass `--strict` if you want a non-zero exit code when findings are present (useful in CI pre-checks). diff --git a/tutorials/directive-callouts/directive-callouts.md b/tutorials/directive-callouts/directive-callouts.md new file mode 100644 index 0000000..1016f0e --- /dev/null +++ b/tutorials/directive-callouts/directive-callouts.md @@ -0,0 +1,184 @@ +--- +parser: v2 +auto_validation: false +time: 10 +tags: [ tutorial>beginner, topic>abap-development ] +primary_tag: topic>abap-development +author_name: Platform Team +author_profile: https://github.com/sap-tutorials +--- + +# Tutorial Callout Enhancements + Demonstrate every callout the platform renders: the five standard alerts (NOTE, TIP, IMPORTANT, WARNING, CAUTION), collapsible DETAILS / TROUBLESHOOT / HINT / SOLUTION / RESULT callouts, inline spoilers, and the `:::type[Title]` directive equivalents. + +## You will learn +- Which alert designators the platform recognizes and when to reach for each +- How to use collapsible DETAILS, TROUBLESHOOT, HINT, SOLUTION, and RESULT callouts +- How to blur an answer inline with `:spoiler[...]` +- How the `:::type[Title]` directive form maps to the blockquote form + +## Prerequisites +- Familiarity with the basic tutorial markdown structure (see [v2-example-tutorial](../v2-example-tutorial/v2-example-tutorial.md)) + +--- + +### Step 1: Standard alert callouts + +The five standard alert types (NOTE, TIP, IMPORTANT, WARNING, CAUTION) are non-collapsible +and render with an icon. Use them for emphasis, not decoration. + +> [!NOTE] +> This is a note. Use it for supplementary information that doesn't interrupt the flow. + +> [!TIP] +> This is a tip. Use it for helpful shortcuts or best practices. + +> [!WARNING] +> This is a warning. Use it when the reader could lose work or cause unexpected behavior. + +> [!CAUTION] +> This is a caution. Use it for severe or irreversible consequences. + +> [!IMPORTANT] +> This is important. Use it for key information the reader must not miss. + +Any alert type accepts an optional title after the designator: + +> [!NOTE] Custom heading +> This note has a custom heading above its body text. + +### Step 2: DETAILS callouts + +DETAILS is a collapsible section. A title is **required**. By default the section starts +closed; append `+` to start it open. + +> [!DETAILS] Closed by default — click to expand +> This content is hidden until the reader clicks the heading. +> +> It can contain multiple paragraphs, lists, and code blocks. +> +> ```yaml +> key: value +> ``` + +> [!DETAILS+] Open by default — click to collapse +> This content is visible immediately. Use `+` when the reader is likely to need the +> content on a first pass but it would clutter the step if always-visible. + +### Step 3: TROUBLESHOOT callouts + +TROUBLESHOOT callouts are collapsible and contribute to the auto-generated troubleshooting +index at the bottom of the tutorial. A title is optional but recommended. + +> [!TROUBLESHOOT] `cds watch` exits immediately with "No service definition found" +> Ensure at least one `.cds` file in `srv/` contains a `service` definition. Check that +> `package.json` lists the correct `cds.roots` paths. +> +> ```bash +> ls srv/*.cds +> ``` +> +> If the folder is empty, you may have cloned the wrong branch. + +> [!TROUBLESHOOT] Port 4004 is already in use +> Another `cds watch` process is running. Kill it first: +> +> ```bash +> npx kill-port 4004 +> ``` + +### Step 4: RESULT callouts + +RESULT marks the expected outcome after completing an action. It has a default title of +"You should see" and a checkmark icon. Place it immediately after the action step. + +Run the build: + +```bash +npm run build +``` + +> [!RESULT] +> The terminal prints `Build succeeded` and exits with code 0. The `dist/` folder now +> contains `index.html`. + +You can also provide a custom title: + +> [!RESULT] Terminal output +> ``` +> ✓ 3 tests passed +> ``` + +> **Note:** Automatic verification links (assert-link) for RESULT callouts are deferred +> to a follow-up feature. + +### Step 5: HINT and SOLUTION callouts + +Multiple HINT callouts in the same step unlock one at a time — the reader must open the +first before the second becomes visible. Place SOLUTION at the end of the exercise. + +**Exercise:** What CAP annotation marks a service endpoint as read-only? + +> [!HINT] +> Look at the service definition in `srv/cat-service.cds`. + +> [!HINT] +> The annotation starts with `@readonly`. + +> [!HINT] +> It is placed before the entity projection inside the `service` block. + +> [!SOLUTION] +> Add `@readonly` before the entity projection: +> +> ```cds +> service CatalogService { +> @readonly entity Books as SELECT from my.Books; +> } +> ``` + +### Step 6: Inline spoilers and directive syntax + +Use `:spoiler[text]` to blur an answer inline — useful for quiz-style prompts: + +Which SAP framework is used to build cloud-native business applications? :spoiler[CAP (Cloud Application Programming Model)] + +In plain-text contexts (MCP tool, email) the spoiler renders as `||CAP (Cloud Application Programming Model)||`. + +The `:::details[Title]` directive syntax is equivalent to `> [!DETAILS] Title` and is +useful when the body contains content that is awkward inside a `>` blockquote: + +:::details[Full configuration file] +```yaml +cds: + requires: + db: + kind: hana + features: + ieee754compatible: true +``` +::: + +### Step 7: Directive equivalents for HINT and SOLUTION + +All collapsible callout types have a `:::type[Title]` directive equivalent. This form is +interchangeable with the blockquote form. + +:::hint[Need a hint?] +Check the CAP documentation for `cds.ql` query examples. +::: + +:::solution[Full solution] +```js +const books = await SELECT.from('my.Books').where({ author_ID: authorId }) +``` +::: + +:::troubleshoot[Module not found: @sap/cds] +Run `npm install` to restore node_modules, then verify `@sap/cds` is listed in +`dependencies` (not `devDependencies`) in `package.json`. +::: + +:::result +The application starts without errors and the terminal shows `Server is listening on port 4004`. +::: diff --git a/tutorials/directive-code-blocks/directive-code-blocks.md b/tutorials/directive-code-blocks/directive-code-blocks.md new file mode 100644 index 0000000..d221d11 --- /dev/null +++ b/tutorials/directive-code-blocks/directive-code-blocks.md @@ -0,0 +1,171 @@ +--- +parser: v2 +auto_validation: false +time: 10 +tags: [ tutorial>beginner, software-product>sap-business-technology-platform ] +primary_tag: software-product>sap-business-technology-platform +author_name: SAP Developer Advocates +author_profile: https://github.com/sap-tutorials +placeholders: auto +--- + +# Code Block Enhancements + Demonstrate the five code-block enhancements: console blocks that separate prompts from output, diff markers, fill-in placeholders, file-tree fences, and `:::walkthrough` code-plus-notes. + +## You will learn +- How console fences separate commands from output and copy commands only +- How diff markers (`// [!code ++]` / `--` / `focus` / `highlight`) annotate changes +- How `placeholders: auto` turns `` tokens into fillable chips +- How `tree` fences render project structure, and how `:::walkthrough` pairs code with notes + +## Prerequisites + +- A BTP trial account (you will need `` below) +- Node.js 18+ installed + +--- + +### Step 1: Console blocks — prompts and output separation + +Console blocks separate command lines from output. Tag your fence `console`, `shell-session`, or `terminal-session`. Lines starting with `$`, `>`, or `PS>` are commands; all other lines are output. The copy button copies **commands only**, without prompts. + +```console +$ cf login -a https://api.cf.eu10.hana.ondemand.com +API endpoint: https://api.cf.eu10.hana.ondemand.com + +Email: user@example.com +Password: •••••••• + +$ cf target -s dev +API endpoint: https://api.cf.eu10.hana.ondemand.com (v3) +Org: myorg Space: dev + +$ cf apps +Getting apps in org myorg / space dev... +name requested state processes +tutorials-srv started web:1/1 +``` + +Copying this block yields three lines: the three `cf` commands, prompts stripped. + +Multi-line continuation works too: + +```console +$ cf create-service hana hdi-shared \ + my-hdi-container +Creating service instance my-hdi-container... +``` + +### Step 2: Diff markers — annotate changes + +Use inline markers to highlight what changed. Add `// [!code ++]`, `// [!code --]`, `// [!code focus]`, or `// [!code highlight]` as trailing comments (adjust for your language). + +```js +function greet(name) { // [!code --] +function greet(name = 'World') { // [!code ++] + const msg = `Hello, ${name}!` + console.log(msg) // [!code focus] + return msg +} +``` + +Copying this fence produces only the **final** version (the added line; removed line excluded): + +``` +function greet(name = 'World') { + const msg = `Hello, ${name}!` + console.log(msg) + return msg +} +``` + +Use `{copy=raw}` to get the original source with markers for teaching diffs: + +```js {copy=raw} +export const VERSION = '1.0.0' // [!code --] +export const VERSION = '1.1.0' // [!code ++] +``` + +Focus mode dims non-focused lines until the reader hovers the block: + +```cds +entity Books : managed { + key ID : UUID; // [!code focus] + title : String(111); // [!code focus] + author : Association to Authors; +} +``` + +### Step 3: Fill-in placeholders + +This tutorial has `placeholders: auto` in its frontmatter. Any token matching ``, ``, or `` becomes a fillable chip. Fill it once and every occurrence updates. + +Target your BTP subaccount: + +```console +$ cf target -o -s +``` + +Or in YAML config: + +```yaml +services: + hana: + subaccount: + space: +``` + +The tokens ``, ``, and `` are all automatically detected. Readers who fill one field see it updated everywhere. + +Unfilled tokens display and copy as their original text (e.g. ``). + +### Step 4: File tree fences + +Show project structure with a `tree` fence. Use `+` / `~` / `-` state prefixes and `# text` annotations. + +```tree +my-cap-project/ + package.json + .cdsrc.json + db/ + schema.cds ++ srv/ ++ cat-service.cds # new: service definition ++ cat-service.js # new: custom handlers +~ mta.yaml # modified: added hana binding + app/ + fiori-ui/ +- old-approuter/ # deleted: replaced by AppRouter MTA module +``` + +The copy button returns the **plain ASCII** source. + +### Step 5: Walkthrough — code + notes + +A `:::walkthrough` directive pairs a code fence with a numbered list. Each list item starts with `{N}` or `{N-M}` to reference line numbers. Clicking a note highlights the corresponding lines. + +:::walkthrough +```js +import cds from '@sap/cds' + +const srv = await cds.connect.to('CatalogService') +const { Books } = srv.entities + +srv.on('READ', Books, async (req) => { + const results = await srv.read(Books) + .where({ stock: { '>': 0 } }) + return results +}) +``` + +1. {1} Import the CAP runtime SDK. +2. {3} Connect to the catalog service — returns a proxy to the remote service. +3. {4} Destructure the `Books` entity from the service definition. +4. {6-9} Register a `READ` handler that filters to in-stock books only. +::: + +Line references out of bounds (e.g. `{40}` in a 9-line fence) fail the build with a clear error. + +## Next Steps + +Now you know how to use all five code-block enhancements. For full reference, see the authoring docs in the [tutorials-ims repository](https://github.com/sap-tutorials/tutorials-ims/blob/main/docs/authors/writing-tutorials.md) and the related [variables personalisation feature](../use-variables-in-tutorials/use-variables-in-tutorials.md). diff --git a/tutorials/directive-content-reuse/directive-content-reuse.md b/tutorials/directive-content-reuse/directive-content-reuse.md new file mode 100644 index 0000000..73fab0f --- /dev/null +++ b/tutorials/directive-content-reuse/directive-content-reuse.md @@ -0,0 +1,69 @@ +--- +parser: v2 +auto_validation: false +time: 20 +tags: [ tutorial>beginner, topic>cloud ] +primary_tag: topic>cloud +author_name: SAP Developer Advocates +author_profile: https://github.com/sap-tutorials +testedWith: + "@sap/cds": "10.x" + node: "22" +requires: + - hana-cloud-tutorial-1 +--- + +# Content Reuse and References + Demonstrate the four content-reuse features available to tutorial authors: `::include` snippets with parameters, smart reference links (`:note`, `:help`, `:api`, `:tutorial`, `:since`), the `testedWith` panel, and `::requires` prerequisite cards. + +## You will learn +- How to inline reusable snippet content with `::include[name]{params}` +- How to link to SAP Notes, Help Portal, APIs, and other tutorials with smart reference directives +- How to declare tested tool versions with `testedWith` frontmatter +- How to render a prerequisite card with `::requires` + +## Prerequisites +- Basic familiarity with the tutorial markdown structure (see [v2-example-tutorial](../v2-example-tutorial/v2-example-tutorial.md)) + +--- + +### Step 1: Prerequisites and Versions + +This tutorial requires :tutorial[hana-cloud-tutorial-1] to be completed first. + +The tested environment is declared in the `testedWith` frontmatter above — you will see a collapsible "Tested with" panel at the top of the rendered tutorial. + +### Step 2: Inline Snippets with Parameters + +Reusable snippets let you share common setup steps across tutorials. The snippet below is fetched from the `_snippets/` directory at the root of the source repository. + +::include[btp-trial-setup]{region=eu10} + +> The `{region=eu10}` parameter substitutes `{{param:region}}` in the snippet with `eu10`. + +### Step 3: Smart Reference Links + +Reference SAP resources inline without hard-coding URLs: + +- SAP Note: :note[2471802] — links to the SAP Note on me.sap.com +- Help Portal: :help[cap/docs/about-cap] — links to help.sap.com/docs/cap/docs/about-cap +- API reference: :api[cds.ql.SELECT]{lib=cap-node} — links to the CAP Node.js API docs +- Tutorial cross-reference: :tutorial[hana-cloud-tutorial-1] — links to another tutorial +- Version badge: :since[CAP 10] — renders a version tag + +### Step 4: Prerequisite Cards + +The `::requires` directive renders a card linking to a prerequisite tutorial. + +::requires[hana-cloud-tutorial-1] + +When you are authenticated, the card shows your completion status (Completed, In progress, or Start). + +### Step 5: Summary + +You have seen how to: + +1. Inline reusable snippet content with `::include[name]{params}` +2. Link to SAP Notes, Help Portal, APIs, and other tutorials using `:note`, `:help`, `:api`, `:tutorial` +3. Declare tested tool versions with `testedWith` frontmatter +4. Show prerequisite cards with `::requires` diff --git a/tutorials/directive-rich-media/directive-rich-media.md b/tutorials/directive-rich-media/directive-rich-media.md new file mode 100644 index 0000000..dc0350b --- /dev/null +++ b/tutorials/directive-rich-media/directive-rich-media.md @@ -0,0 +1,105 @@ +--- +parser: v2 +auto_validation: false +time: 30 +tags: [ tutorial>beginner, software-product>sap-business-technology-platform ] +primary_tag: software-product>sap-business-technology-platform +author_name: SAP Developer +author_profile: https://github.com/sap-tutorials +--- + +# Rich Media and Tables + Demonstrate every rich-media directive — `:::figure`, `:image`, `::compare`, `::diagram`, image hotspots, screencast `::cast`, and sortable/filterable tables — in a realistic "Deploy a CAP Application to SAP BTP Cloud Foundry" authoring context. + +## You will learn +- How to group images with `:::figure` and reference an inline `:image` +- How to show before/after comparisons with `::compare` and architecture with `::diagram` +- How to annotate a screenshot with image hotspots and embed a screencast with `::cast` +- How to mark a table sortable and filterable + +## Prerequisites + +- An SAP BTP trial or productive account +- The Cloud Foundry CLI installed (`cf --version` ≥ 8) +- The `@sap/cds-dk` package installed globally (`npm i -g @sap/cds-dk`) +- A modern browser (Chrome, Edge, or Firefox) + +> [!NOTE] +> The image, diagram, and cast files referenced below are illustrative placeholders that show the directive syntax in context. Supply your own assets when adapting these directives in a real tutorial. + +--- + +### Step 1: Understand the BTP Cockpit Layout + +Before you deploy, familiarise yourself with the main areas of the SAP BTP Cockpit. Two views are most important: the **Global Account overview** and the **Subaccount detail**. + +:::figure[SAP BTP Cockpit — global account and subaccount views]{width=90% align=center} +![BTP Cockpit global account screen](cockpit-global-account.png) +![BTP Cockpit subaccount detail screen](cockpit-subaccount-detail.png) +::: + +In the global account view you manage entitlements across all subaccounts. Drill into a subaccount to see its spaces, service instances, and routes. + +To reach the subaccount overview, click :image[Go to subaccount button]{src=icon-goto-subaccount.png width=18} next to the subaccount name, or click the name itself. + +### Step 2: Log In and Select a Target Space + +Run the following commands to log in to Cloud Foundry and point the CLI at the space where you will deploy. + +```bash +cf login -a https://api.cf.eu10-005.hana.ondemand.com --sso +cf target -o -s dev +``` + +After login, the terminal confirms the API endpoint, organisation, and space. The comparison below shows the difference between a first-time login (which prompts for SSO) and a subsequent re-authentication (which reuses a cached token). + +::compare{before=cf-login-first-time.png after=cf-login-cached-token.png labels="First-time login (SSO prompt)|Re-authentication (cached token)"} + +### Step 3: Understand the Deployment Architecture + +The diagram below shows how the three tiers of a standard CAP application map to BTP Cloud Foundry components after deployment. + +::diagram[cap-cf-architecture.svg]{alt="CAP application architecture: AppRouter in front, CAP srv in the middle, SAP HANA Cloud at the back, connected by service bindings" caption="CAP three-tier deployment on BTP Cloud Foundry" src-dark=cap-cf-architecture-dark.svg} + +The key connection points are: + +- The **AppRouter** authenticates users via XSUAA and proxies requests to the CAP service. +- The **CAP service** (`tutorials-srv`) serves OData endpoints and reads/writes data through the HDI container binding. +- **SAP HANA Cloud** stores all business data; the HDI container manages schema migrations. + +Now annotate this on a real screenshot to see exactly where each component appears in the BTP Cockpit. + +![Deployed applications in the BTP Cockpit space view](cockpit-space-apps.png){hotspots="1:22%,34% 2:55%,34% 3:80%,60%"} + +1. The **AppRouter** (`tutorials-approuter`) — the public-facing entry point. Check that it shows **1/1** running instances. +2. The **CAP service** (`tutorials-srv`) — the backend API. It should also show **1/1** running instances. +3. The **HANA Cloud service instance** (`tutorials-hana`) in the service instances list — bound to both apps. + +### Step 4: Build and Deploy + +Run the Multi-Target Application (MTA) build and deploy commands. The recording below shows a complete `mbt build` + `cf deploy` sequence on a minimal CAP project. + +::cast[mbt-build-and-deploy.cast]{rows=26 cols=100 speed=1.3 poster="0:05" idle-limit=2} + +If the deploy fails with `No credentials configured for HDI container`, the HANA service binding is missing. Bind it manually: + +```bash +cf bind-service tutorials-srv tutorials-hana +cf restart tutorials-srv +``` + +### Step 5: Verify the Deployment + +After deploy completes, open the AppRouter URL and confirm that each surface is reachable. + +| Surface | URL pattern | Expected response | +|---------|-------------|-------------------| +| Root | `https:///` | Redirects to `/browse` | +| OData metadata | `https:///srv/catalog/$metadata` | Returns EDMX XML | +| Admin UI | `https:///admin-ui/` | Requires `Tutorial.Admin` scope | +| Health check | `https:///health` | `{ "status": "UP" }` | +{.sortable .filterable} + +The table above lists all surfaces you should verify. Use the filter box to narrow by surface name, or click the **URL pattern** column header to sort alphabetically. + +**Congratulations — your CAP application is live on SAP BTP Cloud Foundry.** diff --git a/tutorials/directive-synced-option-tabs/directive-synced-option-tabs.md b/tutorials/directive-synced-option-tabs/directive-synced-option-tabs.md new file mode 100644 index 0000000..a65ff37 --- /dev/null +++ b/tutorials/directive-synced-option-tabs/directive-synced-option-tabs.md @@ -0,0 +1,126 @@ +--- +parser: v2 +auto_validation: false +time: 10 +tags: [ tutorial>beginner, software-product>sap-business-technology-platform ] +primary_tag: software-product>sap-business-technology-platform +author_name: SAP Developer Advocates +author_profile: https://github.com/sap-tutorials +--- + +# Synced Option Tabs + Demonstrate synced OPTION tab groups that remember the reader's choice across every step of a tutorial, using the `syncTabs` frontmatter flag and the `sync=` qualifier on OPTION blocks. + +## You will learn +- How to turn on synced option tabs with the `syncTabs: auto` frontmatter flag +- How to group OPTION blocks into a synchronized set with the `sync=` qualifier +- How a reader's choice in one step carries to every other step automatically + +## Prerequisites +- Basic familiarity with the tutorial OPTION block syntax (see [v2-example-tutorial](../v2-example-tutorial/v2-example-tutorial.md)) +- Basic familiarity with CAP + +--- + +### Step 1: Initialize the project + +Pick your runtime and initialize a new CAP project. + +[OPTION BEGIN [Node.js] sync=runtime] +Run `npm init -y && npm add @sap/cds-dk` to initialize a Node.js CAP project. + +Then scaffold the project structure: + +```bash +cds init my-cap-app +cd my-cap-app +npm install +``` +[OPTION END] +[OPTION BEGIN [Java] sync=runtime] +Run `mvn archetype:generate` to initialize a Java CAP project: + +```bash +mvn archetype:generate \ + -DarchetypeGroupId=com.sap.cds \ + -DarchetypeArtifactId=com.sap.cds.archetype \ + -DarchetypeVersion=RELEASE +``` + +Follow the prompts to set your project name and package. +[OPTION END] + +### Step 2: Add a service + +Define a simple CDS service, then add the runtime-specific handler. + +[OPTION BEGIN [Node.js] sync=runtime] +Create `srv/hello-service.cds`: + +```cds +service HelloService { + function greet(name : String) returns String; +} +``` + +Then create `srv/hello-service.js`: + +```js +module.exports = (srv) => { + srv.on('greet', ({ data: { name } }) => `Hello, ${name}!`) +} +``` +[OPTION END] +[OPTION BEGIN [Java] sync=runtime] +Create `Application.java` in your main source folder: + +```java +@Component +public class HelloServiceHandler implements EventHandler { + + @On(event = "greet", service = "HelloService") + public void onGreet(CdsCreateEventContext ctx) { + String name = ctx.getData().get("name").toString(); + ctx.setResult("Hello, " + name + "!"); + } +} +``` +[OPTION END] + +### Step 3: Run and test + +Start the server and try the endpoint. + +[OPTION BEGIN [Node.js] sync=runtime] +Run the development server: + +```bash +cds watch +``` + +Open a browser or use `curl` to test: + +```bash +curl "http://localhost:4004/hello/greet(name='World')" +``` +[OPTION END] +[OPTION BEGIN [Java] sync=runtime] +Run the Spring Boot server: + +```bash +mvn spring-boot:run +``` + +Open a browser or use `curl` to test: + +```bash +curl "http://localhost:8080/hello/greet(name='World')" +``` +[OPTION END] + +### Step 4: Review what happened + +You have now tried synced option tabs. The picker bar at the top of the page remembers your runtime choice and applies it to every group automatically — each OPTION block carrying the same `sync=runtime` qualifier switches together. + +- Read the [CAP documentation](https://cap.cloud.sap/docs/) for more +- Explore the other directive-syntax samples in this repository diff --git a/tutorials/directive-ui-instructions/directive-ui-instructions.md b/tutorials/directive-ui-instructions/directive-ui-instructions.md new file mode 100644 index 0000000..95fa76b --- /dev/null +++ b/tutorials/directive-ui-instructions/directive-ui-instructions.md @@ -0,0 +1,65 @@ +--- +parser: v2 +auto_validation: false +time: 15 +tags: [ tutorial>beginner, software-product>sap-business-technology-platform ] +primary_tag: software-product>sap-business-technology-platform +author_name: SAP Tutorial Team +author_profile: https://github.com/sap-tutorials +--- + +# UI Instruction Directives + Demonstrate the UI-instruction directives (`:menu`, `:ui`, `:icon`, `:kbd`, `:ask`) that render consistent, styled references to menu paths, UI controls, icons, and keyboard shortcuts — shown here in a realistic "Configure an SAP BTP Destination" walkthrough. + +## You will learn +- How to reference a menu path with `:menu[A > B > C]` +- How to render a UI control (button, field) with `:ui[Label]{type=button|field}` +- How to show an icon with `:icon[name]{label="..."}` and a keyboard shortcut with `:kbd[Mod+S]` +- How to offer an inline follow-up question with `:ask[...]` + +## Prerequisites + +- An SAP BTP subaccount +- Editor access to the BTP cockpit + +--- + +### Step 1: Open the Destinations panel + +1. Log in to the [SAP BTP Cockpit](https://cockpit.btp.cloud.sap) and navigate to your subaccount. + +2. In the left navigation, choose :menu[Connectivity > Destinations]. + +3. Click :ui[New Destination]{type=button} in the toolbar. + +:ask[What types of destinations are supported in SAP BTP Connectivity?] + +### Step 2: Enter the destination details + +1. Fill in the **Name** field. Destination names must be unique within a subaccount and may only contain letters, digits, hyphens, and underscores. + +2. Set the **Type** to :ui[HTTP]{type=field}. + +3. Enter the URL of your target API in the :ui[URL]{type=field} field. + +4. Under **Authentication**, select :ui[BasicAuthentication]{type=field} and provide the credentials. + +5. Click :ui[Save]{type=button} to store the destination. + +:ask[How do I configure OAuth2 client credentials authentication for a BTP destination?] + +### Step 3: Test the connection + +1. In the destination list, find your new destination and click the :icon[play]{label="Test Connection"} button to the right of the row. + +2. A panel appears with the connection test result. If the test succeeds, the status reads **200 OK**. If it fails, check that the URL is reachable from the BTP connectivity proxy — some on-premise targets require the Cloud Connector. + +3. To bind this destination to your CAP application locally, press :kbd[Mod+`] in Business Application Studio to open a terminal and run: + + ```bash + cds bind --to your-destination-name + ``` + +4. Save the binding file with :kbd[Mod+S]. + +Congratulations — your destination is configured and ready to use from your CAP application via the `@sap/cds` Connectivity API.