Skip to content

Commit 5d949f8

Browse files
committed
claim rendering improvements
1 parent 9f4ab16 commit 5d949f8

2 files changed

Lines changed: 90 additions & 2 deletions

File tree

client/src/App.tsx

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export function App() {
8383
<Detail label="User ID" value={state.user.sub} />
8484
<Detail label="Name" value={state.user.name} />
8585
<Detail label="Email" value={state.user.email} />
86-
<Detail label="Roles" value={state.user.roles} />
86+
<RolesDetail roles={state.user.roles} />
8787
<Detail label="Context" value={state.user.context_title} />
8888
<Detail label="Issuer" value={state.user.issuer} />
8989
<Detail label="Audience" value={state.user.audience} />
@@ -106,3 +106,27 @@ function Detail({ label, value }: { label: string; value: string }) {
106106
</div>
107107
);
108108
}
109+
110+
function RolesDetail({ roles }: { roles: string }) {
111+
const items = roles
112+
.split(",")
113+
.map((role) => role.trim())
114+
.filter((role) => role.length > 0);
115+
116+
return (
117+
<div className="grid gap-1 border-b border-gray-100 pb-3 sm:grid-cols-[9rem_1fr] sm:gap-3">
118+
<dt className="font-medium text-gray-700">Roles</dt>
119+
<dd className="text-gray-900">
120+
{items.length > 0 ? (
121+
<ul className="list-disc pl-6">
122+
{items.map((role) => (
123+
<li key={role}>{role}</li>
124+
))}
125+
</ul>
126+
) : (
127+
"None"
128+
)}
129+
</dd>
130+
</div>
131+
);
132+
}

src/lti_example_tool_web/html/lti_html.gleam

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import gleam/dict.{type Dict}
22
import gleam/dynamic.{type Dynamic}
33
import gleam/dynamic/decode
44
import gleam/int
5+
import gleam/json
6+
import gleam/list
57
import gleam/option.{Some}
68
import gleam/result
79
import gleam/string
@@ -80,7 +82,11 @@ fn claims_section(claims: Dict(String, Dynamic)) -> Node {
8082
}),
8183
Column("Value", fn(record: #(String, Dynamic)) {
8284
let #(_key, value) = record
83-
html.Text(string.inspect(value))
85+
86+
html.pre_text(
87+
[class("whitespace-pre-wrap break-all font-mono text-xs")],
88+
claim_value_json(value),
89+
)
8490
}),
8591
],
8692
dict.to_list(claims),
@@ -89,6 +95,64 @@ fn claims_section(claims: Dict(String, Dynamic)) -> Node {
8995
])
9096
}
9197

98+
fn claim_value_json(value: Dynamic) -> String {
99+
value
100+
|> dynamic_to_json()
101+
|> json.to_string()
102+
}
103+
104+
fn dynamic_to_json(value: Dynamic) -> json.Json {
105+
case decode.run(value, decode.string) {
106+
Ok(v) -> json.string(v)
107+
Error(_) ->
108+
case decode.run(value, decode.bool) {
109+
Ok(v) -> json.bool(v)
110+
Error(_) ->
111+
case decode.run(value, decode.int) {
112+
Ok(v) -> json.int(v)
113+
Error(_) ->
114+
case decode.run(value, decode.float) {
115+
Ok(v) -> json.float(v)
116+
Error(_) ->
117+
case decode.run(value, decode.list(decode.dynamic)) {
118+
Ok(values) -> json.array(values, dynamic_to_json)
119+
Error(_) ->
120+
case
121+
decode.run(
122+
value,
123+
decode.dict(decode.dynamic, decode.dynamic),
124+
)
125+
{
126+
Ok(values) ->
127+
json.object(
128+
list.map(dict.to_list(values), fn(entry) {
129+
let #(k, v) = entry
130+
#(dynamic_key_to_string(k), dynamic_to_json(v))
131+
}),
132+
)
133+
Error(_) ->
134+
case
135+
decode.run(value, decode.optional(decode.dynamic))
136+
{
137+
Ok(Some(v)) -> dynamic_to_json(v)
138+
Ok(_) -> json.null()
139+
Error(_) -> json.string(string.inspect(value))
140+
}
141+
}
142+
}
143+
}
144+
}
145+
}
146+
}
147+
}
148+
149+
fn dynamic_key_to_string(key: Dynamic) -> String {
150+
case decode.run(key, decode.string) {
151+
Ok(value) -> value
152+
Error(_) -> string.inspect(key)
153+
}
154+
}
155+
92156
fn decode_string(d: Dynamic) -> Result(String, String) {
93157
decode.run(d, decode.string)
94158
|> result.replace_error("Invalid string: " <> string.inspect(d))

0 commit comments

Comments
 (0)