Skip to content

Commit 6daf7f0

Browse files
committed
fix: reorganize certificate data to use Nextcloud components
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
1 parent 8e082e7 commit 6daf7f0

1 file changed

Lines changed: 67 additions & 84 deletions

File tree

src/views/ReadCertificate/CertificateContent.vue

Lines changed: 67 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
-->
55
<template>
66
<div v-if="Object.keys(certificate).length" class="certificate-content">
7-
<!-- Owner Section -->
87
<NcSettingsSection :name="t('libresign', 'Owner of certificate')">
98
<div class="certificate-fields">
109
<div v-for="(value, customName) in orderList(certificate.subject)"
@@ -34,7 +33,7 @@
3433
<div v-for="(extra, key) in certificate.extracerts"
3534
:key="`extracerts-${key}`"
3635
class="chain-certificate">
37-
<h4 class="chain-title">
36+
<h4 class="chain-certificate-title">
3837
{{ getChainCertificateLabel(key, extra) }}
3938
</h4>
4039
<CertificateContent :certificate="extra" :index="index + '_' + key" />
@@ -81,26 +80,25 @@
8180
<div v-for="(value, name) in certificate.extensions"
8281
:key="name"
8382
class="certificate-field">
84-
<span class="field-label">{{ name }}</span>
83+
<span class="field-label">{{ camelCaseToTitleCase(name) }}</span>
8584
<span class="field-value">{{ value }}</span>
8685
</div>
8786
</div>
8887
</NcSettingsSection>
8988

90-
<NcSettingsSection v-if="certificate.purposes && Object.keys(certificate.purposes).length && index === '0'"
89+
<NcSettingsSection v-if="shouldShowPurposes"
9190
:name="t('libresign', 'Certificate purposes')">
9291
<div class="purposes-grid">
93-
<div v-for="(purpose, purposeIndex) in certificate.purposes"
92+
<NcNoteCard v-for="(purpose, purposeIndex) in certificate.purposes"
9493
:key="purposeIndex"
95-
class="purpose-item"
96-
:class="{ 'purpose-allowed': purpose[0], 'purpose-denied': !purpose[0] }">
97-
<div class="purpose-name">{{ formatPurposeName(purpose[2]) }}</div>
94+
:type="purpose[0] ? 'success' : 'error'"
95+
:heading="formatPurposeName(purpose[2])">
9896
<div class="purpose-status">
99-
<span v-if="purpose[0]" class="status-allowed">✓ {{ t('libresign', 'Allowed') }}</span>
100-
<span v-else class="status-denied">✗ {{ t('libresign', 'Not allowed') }}</span>
101-
<span v-if="purpose[1]" class="ca-badge">CA</span>
97+
<span v-if="purpose[0]">{{ t('libresign', 'Allowed') }}</span>
98+
<span v-else>{{ t('libresign', 'Not allowed') }}</span>
99+
<NcChip v-if="purpose[1]" no-close>CA</NcChip>
102100
</div>
103-
</div>
101+
</NcNoteCard>
104102
</div>
105103
</NcSettingsSection>
106104
</div>
@@ -110,11 +108,15 @@
110108
111109
import { selectCustonOption } from '../../helpers/certification.js'
112110
import NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection.js'
111+
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
112+
import NcChip from '@nextcloud/vue/dist/Components/NcChip.js'
113113
114114
export default {
115115
name: 'CertificateContent',
116116
components: {
117117
NcSettingsSection,
118+
NcNoteCard,
119+
NcChip,
118120
},
119121
props: {
120122
certificate: {
@@ -130,6 +132,13 @@ export default {
130132
data() {
131133
return {}
132134
},
135+
computed: {
136+
shouldShowPurposes() {
137+
return this.certificate.purposes &&
138+
Object.keys(this.certificate.purposes).length &&
139+
this.index === '0'
140+
},
141+
},
133142
methods: {
134143
orderList(data) {
135144
const sorted = {};
@@ -146,12 +155,25 @@ export default {
146155
return sorted
147156
},
148157
getLabelFromId(id) {
149-
try {
150-
const item = selectCustonOption(id).unwrap()
151-
return item.label
152-
} catch (error) {
153-
return id
158+
const option = selectCustonOption(id)
159+
if (option.isSome()) {
160+
return this.camelCaseToTitleCase(option.unwrap().label)
154161
}
162+
return this.camelCaseToTitleCase(id)
163+
},
164+
camelCaseToTitleCase(text) {
165+
if (text.includes(' ')) {
166+
return text.replace(/^./, str => str.toUpperCase())
167+
}
168+
169+
return text
170+
// Handle acronyms (consecutive uppercase letters)
171+
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
172+
// Add space before uppercase letters that follow lowercase
173+
.replace(/([a-z])([A-Z])/g, '$1 $2')
174+
// Capitalize first letter
175+
.replace(/^./, str => str.toUpperCase())
176+
.trim()
155177
},
156178
formatPurposeName(purpose) {
157179
const purposeNames = {
@@ -183,109 +205,70 @@ export default {
183205
</script>
184206

185207
<style lang="scss" scoped>
186-
.certificate-content {
187-
max-width: 900px;
188-
}
208+
$border: 1px solid var(--color-border-dark);
209+
$desktop: 768px;
189210
190211
.certificate-field {
191212
display: flex;
192213
flex-direction: column;
193214
padding: 12px 0;
194-
border-bottom: 1px solid var(--color-border-dark);
215+
border-bottom: $border;
195216
gap: 4px;
196217
197-
&:last-child {
198-
border-bottom: none;
199-
}
218+
&:last-child { border-bottom: none; }
200219
201-
@media (min-width: 768px) {
220+
@media (min-width: $desktop) {
202221
flex-direction: row;
203222
gap: 16px;
204223
}
205224
}
206225
207-
.field-label {
208-
font-size: 12px;
209-
color: var(--color-text-maxcontrast);
210-
font-weight: 500;
226+
.field {
227+
&-label {
228+
color: var(--color-text-maxcontrast);
229+
align-self: flex-start;
211230
212-
@media (min-width: 768px) {
213-
min-width: 140px;
214-
text-align: right;
215-
padding-right: 16px;
216-
border-right: 1px solid var(--color-border-dark);
231+
@media (min-width: $desktop) {
232+
min-width: 140px;
233+
max-width: 140px;
234+
text-align: right;
235+
padding-right: 16px;
236+
border-right: $border;
237+
word-wrap: break-word;
238+
}
217239
}
218-
}
219240
220-
.field-value {
221-
color: var(--color-main-text);
222-
word-break: break-all;
223-
flex: 1;
241+
&-value {
242+
word-break: break-all;
243+
align-self: flex-start;
244+
}
224245
}
225246
226247
.chain-certificate {
227248
background: var(--color-background-hover);
228249
border-radius: var(--border-radius);
229250
margin-bottom: 16px;
230251
231-
.chain-title {
252+
&-title {
232253
background: var(--color-background-dark);
233254
padding: 12px 16px;
234255
font-weight: 600;
235256
border-radius: var(--border-radius) var(--border-radius) 0 0;
236257
}
237-
238-
.certificate-content {
239-
padding: 16px;
240-
}
241258
}
242259
243-
.purposes-grid {
244-
display: grid;
245-
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
246-
gap: 12px;
247-
}
248-
249-
.purpose-item {
250-
background: var(--color-background-hover);
251-
border: 1px solid var(--color-border);
252-
border-radius: var(--border-radius);
253-
padding: 12px;
254-
255-
&.purpose-allowed {
256-
border-left: 4px solid var(--color-success);
257-
}
260+
.purposes {
261+
&-grid {
262+
display: grid;
263+
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
264+
gap: 12px;
258265
259-
&.purpose-denied {
260-
border-left: 4px solid var(--color-error);
266+
:deep(.notecard__heading) { font-size: unset; }
261267
}
262268
}
263269
264270
.purpose-status {
265271
display: flex;
266-
align-items: center;
267272
gap: 8px;
268-
font-size: 12px;
269-
margin-top: 4px;
270-
}
271-
272-
.status-allowed {
273-
color: var(--color-success);
274-
font-weight: bold;
275-
}
276-
277-
.status-denied {
278-
color: var(--color-error);
279-
font-weight: bold;
280-
}
281-
282-
.ca-badge {
283-
background: var(--color-warning);
284-
color: white;
285-
padding: 2px 6px;
286-
border-radius: 10px;
287-
font-size: 10px;
288-
font-weight: bold;
289-
text-transform: uppercase;
290273
}
291274
</style>

0 commit comments

Comments
 (0)