Skip to content

Commit 3c9abc5

Browse files
committed
system-views
1 parent c2fbd4c commit 3c9abc5

File tree

6 files changed

+981
-0
lines changed

6 files changed

+981
-0
lines changed

src/lib/config/navigation.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
FileCheck,
1515
Plus,
1616
Building2,
17+
Eye,
18+
Landmark,
1719
} from "@lucide/svelte";
1820
import { env } from "$env/dynamic/public";
1921

@@ -211,3 +213,40 @@ export function getActiveRbacMenuItem(pathname: string) {
211213

212214
return found || rbacItems[0]; // fallback to first item
213215
}
216+
217+
// Account Access navigation items
218+
function buildAccountAccessItems(): NavigationItem[] {
219+
const items: NavigationItem[] = [
220+
{
221+
href: "/account-access/system-views",
222+
label: "System Views",
223+
iconComponent: Eye,
224+
},
225+
{
226+
href: "/account-access/custom-views",
227+
label: "Custom Views",
228+
iconComponent: Eye,
229+
},
230+
{
231+
href: "/account-access/accounts",
232+
label: "Accounts",
233+
iconComponent: Landmark,
234+
},
235+
];
236+
237+
return items;
238+
}
239+
240+
export const accountAccessItems = buildAccountAccessItems();
241+
242+
export function getActiveAccountAccessMenuItem(pathname: string) {
243+
const found = accountAccessItems.find((item) => {
244+
// Skip external links for active menu detection
245+
if (item.external) {
246+
return false;
247+
}
248+
return pathname.startsWith(item.href);
249+
});
250+
251+
return found || accountAccessItems[0]; // fallback to first item
252+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<script lang="ts">
2+
import { Landmark } from "@lucide/svelte";
3+
</script>
4+
5+
<svelte:head>
6+
<title>Accounts - API Manager II</title>
7+
</svelte:head>
8+
9+
<div class="container mx-auto px-4 py-8">
10+
<div class="panel">
11+
<div class="panel-header">
12+
<h1 class="panel-title">Accounts</h1>
13+
<div class="panel-subtitle">
14+
Manage bank accounts and access control
15+
</div>
16+
</div>
17+
18+
<div class="panel-content">
19+
<div class="empty-state">
20+
<div class="empty-icon">
21+
<Landmark size={48} />
22+
</div>
23+
<h4 class="empty-title">Accounts</h4>
24+
<p class="empty-description">
25+
Account management coming soon.
26+
</p>
27+
</div>
28+
</div>
29+
</div>
30+
</div>
31+
32+
<style>
33+
.container {
34+
max-width: 1400px;
35+
}
36+
37+
.panel {
38+
background: white;
39+
border-radius: 8px;
40+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
41+
overflow: hidden;
42+
}
43+
44+
:global([data-mode="dark"]) .panel {
45+
background: rgb(var(--color-surface-800));
46+
}
47+
48+
.panel-header {
49+
padding: 1.5rem;
50+
border-bottom: 1px solid #e5e7eb;
51+
}
52+
53+
:global([data-mode="dark"]) .panel-header {
54+
border-bottom-color: rgb(var(--color-surface-700));
55+
}
56+
57+
.panel-title {
58+
font-size: 1.5rem;
59+
font-weight: 600;
60+
color: #111827;
61+
margin: 0;
62+
}
63+
64+
:global([data-mode="dark"]) .panel-title {
65+
color: var(--color-surface-100);
66+
}
67+
68+
.panel-subtitle {
69+
font-size: 0.875rem;
70+
color: #6b7280;
71+
margin-top: 0.5rem;
72+
}
73+
74+
:global([data-mode="dark"]) .panel-subtitle {
75+
color: var(--color-surface-400);
76+
}
77+
78+
.panel-content {
79+
padding: 2rem;
80+
}
81+
82+
.empty-state {
83+
text-align: center;
84+
padding: 3rem;
85+
color: #6b7280;
86+
}
87+
88+
:global([data-mode="dark"]) .empty-state {
89+
color: var(--color-surface-400);
90+
}
91+
92+
.empty-icon {
93+
display: flex;
94+
justify-content: center;
95+
margin-bottom: 1rem;
96+
color: #d1d5db;
97+
}
98+
99+
:global([data-mode="dark"]) .empty-icon {
100+
color: var(--color-surface-600);
101+
}
102+
103+
.empty-title {
104+
font-size: 1.125rem;
105+
font-weight: 600;
106+
color: #4a5568;
107+
margin: 0 0 0.5rem 0;
108+
}
109+
110+
:global([data-mode="dark"]) .empty-title {
111+
color: var(--color-surface-300);
112+
}
113+
114+
.empty-description {
115+
margin: 0;
116+
color: #6b7280;
117+
}
118+
119+
:global([data-mode="dark"]) .empty-description {
120+
color: var(--color-surface-400);
121+
}
122+
</style>
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<script lang="ts">
2+
import { Eye } from "@lucide/svelte";
3+
</script>
4+
5+
<svelte:head>
6+
<title>Custom Views - API Manager II</title>
7+
</svelte:head>
8+
9+
<div class="container mx-auto px-4 py-8">
10+
<div class="panel">
11+
<div class="panel-header">
12+
<h1 class="panel-title">Custom Views</h1>
13+
<div class="panel-subtitle">Manage custom account views</div>
14+
</div>
15+
16+
<div class="panel-content">
17+
<div class="empty-state">
18+
<div class="empty-icon">
19+
<Eye size={48} />
20+
</div>
21+
<h4 class="empty-title">Custom Views</h4>
22+
<p class="empty-description">Custom view management coming soon.</p>
23+
</div>
24+
</div>
25+
</div>
26+
</div>
27+
28+
<style>
29+
.container {
30+
max-width: 1400px;
31+
}
32+
33+
.panel {
34+
background: white;
35+
border-radius: 8px;
36+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
37+
overflow: hidden;
38+
}
39+
40+
:global([data-mode="dark"]) .panel {
41+
background: rgb(var(--color-surface-800));
42+
}
43+
44+
.panel-header {
45+
padding: 1.5rem;
46+
border-bottom: 1px solid #e5e7eb;
47+
}
48+
49+
:global([data-mode="dark"]) .panel-header {
50+
border-bottom-color: rgb(var(--color-surface-700));
51+
}
52+
53+
.panel-title {
54+
font-size: 1.5rem;
55+
font-weight: 600;
56+
color: #111827;
57+
margin: 0;
58+
}
59+
60+
:global([data-mode="dark"]) .panel-title {
61+
color: var(--color-surface-100);
62+
}
63+
64+
.panel-subtitle {
65+
font-size: 0.875rem;
66+
color: #6b7280;
67+
margin-top: 0.5rem;
68+
}
69+
70+
:global([data-mode="dark"]) .panel-subtitle {
71+
color: var(--color-surface-400);
72+
}
73+
74+
.panel-content {
75+
padding: 2rem;
76+
}
77+
78+
.empty-state {
79+
text-align: center;
80+
padding: 3rem;
81+
color: #6b7280;
82+
}
83+
84+
:global([data-mode="dark"]) .empty-state {
85+
color: var(--color-surface-400);
86+
}
87+
88+
.empty-icon {
89+
display: flex;
90+
justify-content: center;
91+
margin-bottom: 1rem;
92+
color: #d1d5db;
93+
}
94+
95+
:global([data-mode="dark"]) .empty-icon {
96+
color: var(--color-surface-600);
97+
}
98+
99+
.empty-title {
100+
font-size: 1.125rem;
101+
font-weight: 600;
102+
color: #4a5568;
103+
margin: 0 0 0.5rem 0;
104+
}
105+
106+
:global([data-mode="dark"]) .empty-title {
107+
color: var(--color-surface-300);
108+
}
109+
110+
.empty-description {
111+
margin: 0;
112+
color: #6b7280;
113+
}
114+
115+
:global([data-mode="dark"]) .empty-description {
116+
color: var(--color-surface-400);
117+
}
118+
</style>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import type { PageServerLoad } from "./$types";
2+
import { error } from "@sveltejs/kit";
3+
import { createLogger } from "$lib/utils/logger";
4+
import { obp_requests } from "$lib/obp/requests";
5+
import { SessionOAuthHelper } from "$lib/oauth/sessionHelper";
6+
7+
const logger = createLogger("SystemViewsPageServer");
8+
9+
interface SystemView {
10+
id: string;
11+
short_name: string;
12+
description: string;
13+
is_public: boolean;
14+
alias?: string;
15+
hide_metadata_if_alias_used?: boolean;
16+
}
17+
18+
interface ViewsResponse {
19+
views: SystemView[];
20+
}
21+
22+
export const load: PageServerLoad = async ({ locals }) => {
23+
const session = locals.session;
24+
25+
if (!session?.data?.user) {
26+
throw error(401, "Unauthorized");
27+
}
28+
29+
// Get the OAuth session data
30+
const sessionOAuth = SessionOAuthHelper.getSessionOAuth(session);
31+
const accessToken = sessionOAuth?.accessToken;
32+
33+
if (!accessToken) {
34+
logger.warn("No access token available for system views page");
35+
return {
36+
views: [],
37+
hasApiAccess: false,
38+
error: "No API access token available",
39+
};
40+
}
41+
42+
try {
43+
logger.info("=== FETCHING SYSTEM VIEWS ===");
44+
const endpoint = `/obp/v6.0.0/management/system-views`;
45+
logger.info(`Request: ${endpoint}`);
46+
47+
const response: ViewsResponse = await obp_requests.get(
48+
endpoint,
49+
accessToken,
50+
);
51+
52+
logger.info(`Response received with ${response.views?.length || 0} views`);
53+
54+
if (response.views) {
55+
logger.info(`First view sample: ${JSON.stringify(response.views[0])}`);
56+
}
57+
58+
return {
59+
views: response.views || [],
60+
hasApiAccess: true,
61+
};
62+
} catch (err) {
63+
logger.error("Error loading system views:", err);
64+
logger.error(
65+
`Error message: ${err instanceof Error ? err.message : String(err)}`,
66+
);
67+
68+
return {
69+
views: [],
70+
hasApiAccess: true,
71+
error: err instanceof Error ? err.message : "Failed to load system views",
72+
};
73+
}
74+
};

0 commit comments

Comments
 (0)