Skip to content

Commit f6d3a37

Browse files
authored
+ layout, tooltips filtering, features
Improved Azure Database Selector UI/UX: enhanced layout, added tooltips, dynamic filtering, and accessibility features
1 parent c4baf36 commit f6d3a37

3 files changed

Lines changed: 163 additions & 33 deletions

File tree

tool/web-app/index.html

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,86 +11,99 @@
1111
<h1>Azure Database Selector</h1>
1212
</header>
1313
<main>
14-
<form id="advisor-form">
14+
<form id="advisor-form" aria-labelledby="form-title">
15+
<h2 id="form-title">Select Your Database Preferences</h2>
1516
<label for="data-volume">Data Volume:</label>
16-
<select id="data-volume" name="data-volume" required title="Select the expected size of your data.">
17+
<select id="data-volume" name="data-volume" required title="Select the expected size of your data." aria-describedby="data-volume-desc">
1718
<option value="<10GB">Less than 10GB</option>
1819
<option value="10GB-1TB">10GB to 1TB</option>
1920
<option value=">1TB">More than 1TB</option>
2021
</select>
22+
<span id="data-volume-desc">Choose the size of your data storage needs. For example, less than 10GB is suitable for small applications like blogs, while more than 1TB is ideal for enterprise systems.</span>
2123

2224
<label for="data-type">Data Type:</label>
23-
<select id="data-type" name="data-type" required title="Choose the type of data you will store.">
25+
<select id="data-type" name="data-type" required title="Choose the type of data you will store." aria-describedby="data-type-desc">
2426
<option value="structured">Structured (e.g., tables)</option>
2527
<option value="semi-structured">Semi-structured (e.g., JSON, XML)</option>
2628
<option value="unstructured">Unstructured (e.g., images, videos)</option>
2729
</select>
30+
<span id="data-type-desc">Select the format of the data you will be storing. For instance, structured data is used for relational databases, while unstructured data is common for media files.</span>
2831

2932
<label for="latency">Latency Requirements:</label>
30-
<select id="latency" name="latency" required title="Select the maximum acceptable delay for database operations.">
33+
<select id="latency" name="latency" required title="Select the maximum acceptable delay for database operations." aria-describedby="latency-desc">
3134
<option value="<10ms">Less than 10ms</option>
3235
<option value="10-100ms">10ms to 100ms</option>
3336
<option value=">100ms">More than 100ms</option>
3437
</select>
38+
<span id="latency-desc">Indicate how quickly you need the database to respond. For example, less than 10ms is critical for real-time applications like gaming.</span>
3539

3640
<label for="scalability">Scalability Needs:</label>
37-
<select id="scalability" name="scalability" required title="Choose whether the database needs to scale globally or locally.">
41+
<select id="scalability" name="scalability" required title="Choose whether the database needs to scale globally or locally." aria-describedby="scalability-desc">
3842
<option value="global">Global</option>
3943
<option value="local">Local</option>
4044
</select>
45+
<span id="scalability-desc">Specify if the database should support global or local scaling. For instance, global scaling is essential for multinational companies.</span>
4146

4247
<label for="consistency">Consistency Model:</label>
43-
<select id="consistency" name="consistency" required title="Select the consistency model for your database.">
48+
<select id="consistency" name="consistency" required title="Select the consistency model for your database." aria-describedby="consistency-desc">
4449
<option value="strong">Strong</option>
4550
<option value="eventual">Eventual</option>
4651
</select>
52+
<span id="consistency-desc">Choose the consistency model that fits your application's needs. Strong consistency ensures immediate updates, while eventual consistency is suitable for distributed systems.</span>
4753

4854
<label for="integration-needs">Integration Needs:</label>
49-
<select id="integration-needs" name="integration-needs" title="Specify if the database needs to integrate with other Azure services.">
55+
<select id="integration-needs" name="integration-needs" title="Specify if the database needs to integrate with other Azure services." aria-describedby="integration-needs-desc">
5056
<option value="yes">Yes</option>
5157
<option value="no">No</option>
5258
</select>
59+
<span id="integration-needs-desc">Indicate if you require integration with other services. For example, integration is necessary for analytics pipelines.</span>
5360

5461
<label for="security">Security Requirements:</label>
55-
<select id="security" name="security" title="Select the security features required for your database.">
62+
<select id="security" name="security" title="Select the security features required for your database." aria-describedby="security-desc">
5663
<option value="encryption">Encryption</option>
5764
<option value="rbac">Role-based Access Control</option>
5865
<option value="compliance">Compliance</option>
5966
</select>
67+
<span id="security-desc">Select the security measures that are necessary for your data. Encryption is ideal for sensitive data, while compliance is crucial for regulated industries.</span>
6068

6169
<label for="budget">Budget:</label>
62-
<select id="budget" name="budget" required title="Choose your monthly budget for database services.">
70+
<select id="budget" name="budget" required title="Choose your monthly budget for database services." aria-describedby="budget-desc">
6371
<option value="<100 USD">Less than 100 USD</option>
6472
<option value="100-500 USD">100 to 500 USD</option>
6573
<option value=">500 USD">More than 500 USD</option>
6674
</select>
75+
<span id="budget-desc">Specify your budget range for database solutions. For example, less than 100 USD is suitable for startups, while more than 500 USD is common for large enterprises.</span>
6776

6877
<label for="use-case">Use Case:</label>
69-
<select id="use-case" name="use-case" required title="Select the primary use case for your database.">
78+
<select id="use-case" name="use-case" required title="Select the primary use case for your database." aria-describedby="use-case-desc">
7079
<option value="OLTP">Transactional Processing (OLTP)</option>
7180
<option value="OLAP">Analytical Processing (OLAP)</option>
7281
<option value="AI/ML">AI/ML Workloads</option>
7382
</select>
83+
<span id="use-case-desc">Choose the main purpose of the database you are selecting. For instance, OLTP is used for transactional systems, while OLAP is for analytics.</span>
7484

7585
<label for="backup-recovery">Backup and Disaster Recovery:</label>
76-
<select id="backup-recovery" name="backup-recovery" title="Specify if automated backups and disaster recovery are required.">
86+
<select id="backup-recovery" name="backup-recovery" title="Specify if automated backups and disaster recovery are required." aria-describedby="backup-recovery-desc">
7787
<option value="yes">Yes</option>
7888
<option value="no">No</option>
7989
</select>
90+
<span id="backup-recovery-desc">Indicate if you need automated backup and recovery options. For example, disaster recovery is essential for mission-critical systems.</span>
8091

8192
<label for="query-complexity">Query Complexity:</label>
82-
<select id="query-complexity" name="query-complexity" title="Select the expected complexity of database queries.">
93+
<select id="query-complexity" name="query-complexity" title="Select the expected complexity of database queries." aria-describedby="query-complexity-desc">
8394
<option value="simple">Simple (e.g., basic CRUD operations)</option>
8495
<option value="moderate">Moderate (e.g., joins, aggregations)</option>
8596
<option value="complex">Complex (e.g., advanced analytics, AI/ML queries)</option>
8697
</select>
98+
<span id="query-complexity-desc">Select the complexity level of the queries you will perform. For instance, simple queries are used for CRUD operations, while complex queries are needed for AI/ML workloads.</span>
8799

88100
<label for="data-retention">Data Retention Policy:</label>
89-
<select id="data-retention" name="data-retention" title="Choose the expected retention period for your data.">
101+
<select id="data-retention" name="data-retention" title="Choose the expected retention period for your data." aria-describedby="data-retention-desc">
90102
<option value="short-term">Short-term (e.g., days or weeks)</option>
91103
<option value="medium-term">Medium-term (e.g., months)</option>
92104
<option value="long-term">Long-term (e.g., years)</option>
93105
</select>
106+
<span id="data-retention-desc">Specify how long you need to retain your data. For example, short-term retention is suitable for temporary logs, while long-term retention is needed for compliance data.</span>
94107

95108
<button type="submit">Get Recommendation</button>
96109
</form>

tool/web-app/script.js

Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,35 @@
1+
document.addEventListener('DOMContentLoaded', () => {
2+
const steps = document.querySelectorAll('.step');
3+
let currentStep = 0;
4+
5+
function showStep(stepIndex) {
6+
steps.forEach((step, index) => {
7+
step.style.display = index === stepIndex ? 'block' : 'none';
8+
});
9+
}
10+
11+
showStep(currentStep);
12+
13+
document.getElementById('next-step').addEventListener('click', () => {
14+
if (currentStep < steps.length - 1) {
15+
currentStep++;
16+
showStep(currentStep);
17+
}
18+
});
19+
20+
document.getElementById('prev-step').addEventListener('click', () => {
21+
if (currentStep > 0) {
22+
currentStep--;
23+
showStep(currentStep);
24+
}
25+
});
26+
27+
// Pre-fill defaults
28+
document.getElementById('data-volume').value = '<10GB';
29+
document.getElementById('data-type').value = 'structured';
30+
document.getElementById('latency').value = '<10ms';
31+
});
32+
133
document.getElementById('advisor-form').addEventListener('submit', async (event) => {
234
event.preventDefault();
335

@@ -12,23 +44,66 @@ document.getElementById('advisor-form').addEventListener('submit', async (event)
1244
const useCase = document.getElementById('use-case').value;
1345
const backupRecovery = document.getElementById('backup-recovery').value;
1446

15-
const response = await fetch('http://your-backend-url/recommend', {
16-
method: 'POST',
17-
headers: { 'Content-Type': 'application/json' },
18-
body: JSON.stringify({
19-
data_volume: dataVolume,
20-
data_type: dataType,
21-
latency,
22-
scalability,
23-
consistency,
24-
integration_needs: integrationNeeds,
25-
security,
26-
budget,
27-
use_case: useCase,
28-
backup_recovery: backupRecovery
29-
})
30-
});
47+
try {
48+
const response = await fetch('http://your-backend-url/recommend', {
49+
method: 'POST',
50+
headers: { 'Content-Type': 'application/json' },
51+
body: JSON.stringify({
52+
data_volume: dataVolume,
53+
data_type: dataType,
54+
latency,
55+
scalability,
56+
consistency,
57+
integration_needs: integrationNeeds,
58+
security,
59+
budget,
60+
use_case: useCase,
61+
backup_recovery: backupRecovery
62+
})
63+
});
64+
65+
if (!response.ok) {
66+
throw new Error('Failed to fetch recommendation. Please check the backend URL or try again later.');
67+
}
68+
69+
const result = await response.json();
70+
document.getElementById('recommendation').innerText = `Recommended Database: ${result.recommendation}`;
71+
72+
// Save configuration to local storage
73+
localStorage.setItem('databaseConfig', JSON.stringify({
74+
dataVolume,
75+
dataType,
76+
latency,
77+
scalability,
78+
consistency,
79+
integrationNeeds,
80+
security,
81+
budget,
82+
useCase,
83+
backupRecovery
84+
}));
85+
86+
// Export results as PDF
87+
const pdfContent = `Recommended Database: ${result.recommendation}\n\nConfiguration:\n${JSON.stringify({
88+
dataVolume,
89+
dataType,
90+
latency,
91+
scalability,
92+
consistency,
93+
integrationNeeds,
94+
security,
95+
budget,
96+
useCase,
97+
backupRecovery
98+
}, null, 2)}`;
99+
100+
const blob = new Blob([pdfContent], { type: 'application/pdf' });
101+
const link = document.createElement('a');
102+
link.href = URL.createObjectURL(blob);
103+
link.download = 'database-recommendation.pdf';
104+
link.click();
31105

32-
const result = await response.json();
33-
document.getElementById('recommendation').innerText = `Recommended Database: ${result.recommendation}`;
106+
} catch (error) {
107+
document.getElementById('recommendation').innerText = `Error: ${error.message}`;
108+
}
34109
});

tool/web-app/styles.css

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ main {
1818

1919
form {
2020
margin-bottom: 2rem;
21+
display: flex;
22+
flex-direction: column;
23+
gap: 1.5rem;
2124
}
2225

2326
label {
@@ -32,18 +35,57 @@ select, button {
3235
}
3336

3437
button {
35-
background-color: #0078d4;
38+
background-color: #ff5722; /* Contrasting color */
3639
color: white;
40+
font-weight: bold;
3741
border: none;
3842
cursor: pointer;
43+
padding: 0.75rem;
44+
border-radius: 5px;
3945
}
4046

4147
button:hover {
42-
background-color: #005a9e;
48+
background-color: #e64a19;
4349
}
4450

4551
#recommendation {
4652
background-color: white;
4753
padding: 1rem;
4854
border: 1px solid #ddd;
55+
}
56+
57+
/* Add tooltips for dropdowns */
58+
select {
59+
position: relative;
60+
}
61+
62+
select:hover::after {
63+
content: attr(title);
64+
position: absolute;
65+
top: 100%;
66+
left: 0;
67+
background-color: #333;
68+
color: #fff;
69+
padding: 0.5rem;
70+
border-radius: 5px;
71+
font-size: 0.875rem;
72+
white-space: nowrap;
73+
z-index: 10;
74+
}
75+
76+
/* Ensure mobile responsiveness */
77+
@media (max-width: 768px) {
78+
form {
79+
padding: 1rem;
80+
font-size: 0.9rem;
81+
}
82+
83+
select, button {
84+
padding: 0.5rem;
85+
font-size: 0.9rem;
86+
}
87+
88+
button {
89+
width: 100%;
90+
}
4991
}

0 commit comments

Comments
 (0)