Skip to content

Commit a00d0fb

Browse files
Copilotphrocker
andcommitted
Complete modernization with updated OpenAI template and improved test coverage
Co-authored-by: phrocker <[email protected]>
1 parent bbe2aa0 commit a00d0fb

File tree

2 files changed

+121
-50
lines changed

2 files changed

+121
-50
lines changed

api/src/main/resources/templates/sso/integrations/add_openai.html

Lines changed: 96 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,69 @@
22
<html xmlns:th="http://www.thymeleaf.org" class="dark" data-bs-theme="dark">
33
<head>
44
<meta th:replace="~{fragments/header}">
5-
<title>[[${systemOptions.systemLogoName}]] - Add Integrations</title>
5+
<title>[[${systemOptions.systemLogoName}]] - Add OpenAI Integration</title>
66

77
<style>
8-
.grid {
9-
display: grid;
10-
gap: 1.5rem;
8+
.integration-form {
9+
max-width: 600px;
10+
margin: 2rem auto;
11+
background: var(--bs-dark);
12+
border: 1px solid #404040;
13+
border-radius: 12px;
14+
padding: 2rem;
1115
}
1216

13-
.sm\\:grid-cols-2 {
14-
grid-template-columns: repeat(2, minmax(0, 1fr));
17+
.integration-header {
18+
text-align: center;
19+
margin-bottom: 2rem;
1520
}
1621

17-
.lg\\:grid-cols-3 {
18-
grid-template-columns: repeat(3, minmax(0, 1fr));
22+
.integration-icon {
23+
font-size: 3rem;
24+
color: #0d6efd;
25+
margin-bottom: 1rem;
1926
}
2027

21-
.xl\\:grid-cols-4 {
22-
grid-template-columns: repeat(4, minmax(0, 1fr));
28+
.form-group {
29+
margin-bottom: 1.5rem;
2330
}
2431

25-
.card {
26-
border: 1px solid #ddd;
27-
border-radius: 8px;
28-
padding: 1rem;
29-
transition: background-color 0.2s;
30-
text-decoration: none;
31-
color: inherit;
32+
.form-label {
33+
font-weight: 600;
34+
margin-bottom: 0.5rem;
35+
color: #fff;
3236
}
3337

34-
.card:hover {
35-
background-color: #f9f9f9;
38+
.form-control {
39+
background: var(--bs-dark);
40+
border: 1px solid #404040;
41+
color: #fff;
3642
}
3743

38-
.card-header {
39-
display: flex;
40-
justify-content: space-between;
41-
align-items: center;
44+
.form-control:focus {
45+
background: var(--bs-dark);
46+
border-color: #0d6efd;
47+
color: #fff;
48+
box-shadow: 0 0 0 0.2rem rgba(13, 110, 253, 0.25);
4249
}
4350

44-
.card-title {
45-
font-size: 1rem;
46-
font-weight: 500;
51+
.btn-primary {
52+
background: linear-gradient(135deg, #0d6efd, #6610f2);
53+
border: none;
54+
padding: 0.75rem 2rem;
55+
font-weight: 600;
4756
}
4857

49-
.card-description {
50-
font-size: 0.875rem;
51-
color: #666;
58+
.btn-secondary {
59+
background: transparent;
60+
border: 1px solid #404040;
61+
color: #adb5bd;
5262
}
5363

54-
.icon {
55-
font-size: 1.25rem;
56-
color: #888;
64+
.help-text {
65+
font-size: 0.875rem;
66+
color: #adb5bd;
67+
margin-top: 0.25rem;
5768
}
5869
</style>
5970

@@ -65,6 +76,13 @@
6576
const formData = new FormData(form);
6677
const jsonData = Object.fromEntries(formData.entries());
6778
var csrf = "[[${_csrf.token}]]"
79+
80+
// Show loading state
81+
const submitBtn = form.querySelector('button[type="submit"]');
82+
const originalText = submitBtn.innerHTML;
83+
submitBtn.disabled = true;
84+
submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Connecting...';
85+
6886
try {
6987
const response = await fetch(form.action, {
7088
method: "POST",
@@ -76,15 +94,19 @@
7694
});
7795

7896
if (response.ok) {
79-
const redirectUrl = "/sso/v1/integrations"; // Modify as needed
80-
window.location.href = redirectUrl;
97+
submitBtn.innerHTML = '<i class="fas fa-check me-2"></i>Connected!';
98+
setTimeout(() => {
99+
const redirectUrl = "/sso/v1/integrations";
100+
window.location.href = redirectUrl;
101+
}, 1000);
81102
} else {
82-
const errorText = await response.text();
83-
alert("Error: " + errorText);
103+
throw new Error("Failed to create integration");
84104
}
85105
} catch (error) {
86-
console.error("Request failed", error);
87-
alert("Failed to save integration.");
106+
submitBtn.disabled = false;
107+
submitBtn.innerHTML = originalText;
108+
console.error("Error:", error);
109+
alert("An error occurred while creating the integration.");
88110
}
89111
}
90112
</script>
@@ -97,37 +119,61 @@
97119
<div class="col py-4">
98120
<div class="main-content">
99121
<div th:replace="~{fragments/alerts}"></div>
100-
<div class="container">
101-
<h1>Set Up OpenAI Integration</h1>
102-
<form th:action="@{/api/v1/integrations/openai/add}" th:object="${openaiIntegration}" method="post" onsubmit="submitIntegration(event)">
122+
123+
<div class="integration-form">
124+
<div class="integration-header">
125+
<i class="fa-solid fa-robot integration-icon"></i>
126+
<h1>Connect OpenAI</h1>
127+
<p class="text-muted">Integrate AI capabilities and natural language processing into your workflows.</p>
128+
</div>
103129

130+
<form th:action="@{/api/v1/integrations/openai/add}" th:object="${openaiIntegration}" method="post" onsubmit="submitIntegration(event)">
104131
<div class="form-group">
105-
<label for="name">Integration Name</label>
132+
<label for="name" class="form-label">Integration Name</label>
106133
<input type="text" id="name" name="name" class="form-control"
107-
th:field="*{name}" placeholder="Enter your Integration Name" required>
134+
th:field="*{name}" placeholder="My OpenAI Integration" required>
135+
<div class="help-text">Choose a name to identify this integration</div>
108136
</div>
109137

110138
<div class="form-group">
111-
<label for="username">OpenAI Principal</label>
139+
<label for="username" class="form-label">OpenAI Organization ID</label>
112140
<input type="text" id="username" name="username" class="form-control"
113-
th:field="*{username}" placeholder="Enter your Jira username" required>
141+
th:field="*{username}" placeholder="org-xxxxxxxxx (optional)">
142+
<div class="help-text">Your OpenAI organization ID (optional for personal accounts)</div>
114143
</div>
115144

116145
<div class="form-group">
117-
<label for="apiToken">Open AI Token</label>
146+
<label for="apiToken" class="form-label">OpenAI API Key</label>
118147
<input type="password" id="apiToken" name="apiToken" class="form-control"
119-
th:field="*{apiToken}" placeholder="Enter your Jira API token" required>
148+
th:field="*{apiToken}" placeholder="sk-xxxxxxxxx" required>
149+
<div class="help-text">
150+
<i class="fas fa-info-circle me-1"></i>
151+
Generate an API key at <a href="https://platform.openai.com/api-keys" target="_blank" class="text-primary">OpenAI Platform</a>
152+
</div>
120153
</div>
121154

122-
<div class="form-actions">
123-
<button type="submit" class="btn btn-primary">Save Integration</button>
155+
<div class="form-group">
156+
<label for="baseUrl" class="form-label">API Base URL</label>
157+
<input type="text" id="baseUrl" name="baseUrl" class="form-control"
158+
th:field="*{baseUrl}" placeholder="https://api.openai.com/v1" value="https://api.openai.com/v1">
159+
<div class="help-text">Use default URL unless you're using a custom endpoint</div>
124160
</div>
161+
162+
<div class="d-flex gap-2 justify-content-end">
163+
<a href="/sso/v1/integrations" class="btn btn-secondary">Cancel</a>
164+
<button type="submit" class="btn btn-primary">
165+
<i class="fas fa-plug me-2"></i>Connect OpenAI
166+
</button>
167+
</div>
168+
169+
<input type="hidden" name="_csrf" th:value="${_csrf.token}"/>
125170
</form>
126171
</div>
172+
127173
</div>
128174
</div>
129175
</div>
130176
</div>
131177

132178
</body>
133-
</html>
179+
</html>

api/src/test/java/io/sentrius/sso/controllers/api/IntegrationApiControllerTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,31 @@ void setUp() {
5858
);
5959
}
6060

61+
@Test
62+
void addGitHubIntegrationReturnsSuccessForValidDTO() throws JsonProcessingException, GeneralSecurityException {
63+
ExternalIntegrationDTO dto = new ExternalIntegrationDTO();
64+
dto.setName("TestGitHub");
65+
dto.setUsername("testuser");
66+
dto.setApiToken("ghp_test-token");
67+
dto.setBaseUrl("https://github.com");
68+
69+
IntegrationSecurityToken savedToken = IntegrationSecurityToken.builder()
70+
.id(1L)
71+
.connectionType("github")
72+
.name("TestGitHub")
73+
.connectionInfo("{\"name\":\"TestGitHub\",\"username\":\"testuser\",\"apiToken\":\"ghp_test-token\",\"baseUrl\":\"https://github.com\"}")
74+
.build();
75+
76+
when(integrationService.save(any(IntegrationSecurityToken.class))).thenReturn(savedToken);
77+
78+
ResponseEntity<ExternalIntegrationDTO> result = controller.addGitHubIntegration(request, response, dto);
79+
80+
assertEquals(HttpStatus.OK, result.getStatusCode());
81+
assertNotNull(result.getBody());
82+
assertEquals("TestGitHub", result.getBody().getName());
83+
verify(integrationService).save(any(IntegrationSecurityToken.class));
84+
}
85+
6186
@Test
6287
void addOpenaiIntegrationReturnsSuccessForValidDTO() throws JsonProcessingException, GeneralSecurityException {
6388
ExternalIntegrationDTO dto = new ExternalIntegrationDTO();

0 commit comments

Comments
 (0)