Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 69 additions & 0 deletions alm/ui-examples/templates/page1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<!-- Copyright 2026 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->

<!-- [START alm_ui_sample] -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Generate API</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>

<div class="gcp-header">
<h1>Market Place Integration</h1>
</div>

<div class="card" style="max-width: 550px;">
<h2>Step 1: Generate API</h2>

<form method="POST" action="/">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using hardcoded paths like action="/" can break if the application is hosted under a subdirectory or behind a reverse proxy with path-based routing. It is highly recommended to use Flask's url_for to dynamically generate the form action URL.

        <form method="POST" action="{{ url_for('generate_api') }}">


<div class="form-group">
<label for="apigee_org">Apigee Organization (APIGEE_ORG)</label>
<input type="text" name="apigee_org" id="apigee_org" value="PROJECT_ID" required>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using value="PROJECT_ID" pre-fills the input field with a literal placeholder string. If the user submits the form without modifying this field, the application will attempt to use the literal string "PROJECT_ID" as the Apigee organization, leading to API errors. Using the placeholder attribute instead of value ensures the field remains empty by default, allowing the required attribute to prevent accidental submissions of placeholder values.

                <input type="text" name="apigee_org" id="apigee_org" placeholder="PROJECT_ID" required>

</div>

<div class="form-group">
<label for="service_account">Service Account (For gcloud Impersonation)</label>
<input type="text" name="service_account" id="service_account" value="SERVICE_ACCOUNT" required>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using value="SERVICE_ACCOUNT" pre-fills the input field with a literal placeholder string. If the user submits the form without modifying this field, the application will attempt to use the literal string "SERVICE_ACCOUNT" as the service account name, which will fail during gcloud impersonation. Using the placeholder attribute instead of value ensures the field remains empty by default, allowing the required attribute to prevent accidental submissions of placeholder values.

                <input type="text" name="service_account" id="service_account" placeholder="SERVICE_ACCOUNT" required>

</div>

<button type="submit">Generate API</button>
</form>

{% if action_result %}
<div class="result-alert">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"/></svg>
<span><strong>{{ action_result }}</strong></span>
</div>
{% endif %}

{% if error %}
<div class="result-alert" style="background-color: #fce8e6; color: #c5221f;">
<span><strong>Deployment Failed:</strong> {{ error }}</span>
</div>
{% endif %}

<hr style="margin: 30px 0 20px 0; border: 0; border-top: 1px solid #dadce0;">

<a href="{{ url_for('deploy_page') }}" class="secondary-btn">Next Page &rarr;</a>
</div>

</body>
</html>
<!-- [END alm_ui_sample] -->
80 changes: 80 additions & 0 deletions alm/ui-examples/templates/page2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<!-- Copyright 2026 Google LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. -->

<!-- [START alm_ui_sample] -->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>GCP Region Selector</title>
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<style>
.button-group {
display: flex;
gap: 10px;
margin-top: 15px;
}
.back-btn { display: inline-block; margin-bottom: 20px; color: #1a73e8; text-decoration: none;}
</style>
</head>
<body>

<div class="gcp-header">
<h1>Market Place Integration</h1>
</div>

<div class="card">
<a href="{{ url_for('generate_api') }}" class="back-btn">&larr; Back to Step 1</a>
<h2>Apigee to ALM</h2>

<form method="POST" action="/deploy">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using hardcoded paths like action="/deploy" can break if the application is hosted under a subdirectory or behind a reverse proxy with path-based routing. It is highly recommended to use Flask's url_for to dynamically generate the form action URL.

        <form method="POST" action="{{ url_for('deploy_page') }}">

<div class="form-group">
<label for="region">Location</label>
<select name="region" id="region" required>
<option value="" disabled selected>Select a region...</option>
{% for region in regions %}
<option value="{{ region }}" {% if selected_region == region %}selected{% endif %}>
{{ region }}
</option>
{% endfor %}
</select>
</div>

<div class="button-group">
<button type="submit" name="action" value="deploy">Deploy to Region</button>
<button type="submit" name="action" value="status">Get Status</button>
</div>
</form>

{% if api_response and not api_response.error %}
<div class="result-alert">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"/></svg>
<span>Successfully configured for <strong>{{ selected_region }}</strong></span>
</div>
{% endif %}

{% if operation_state %}
<div class="result-alert" style="margin-top: 15px; background-color: #f0f4f8;">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M382-240 154-468l57-57 171 171 367-367 57 57-424 424Z"/></svg>
<span>State: <strong>{{ operation_state }}</strong></span>
</div>
{% endif %}
</div>

</body>
</html>
<!-- [END alm_ui_sample] -->