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)"
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" />
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 >
110108
111109import { selectCustonOption } from ' ../../helpers/certification.js'
112110import 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
114114export 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 : 1 px 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 : 768 px ) {
220+ @media (min-width : $desktop ) {
202221 flex-direction : row ;
203222 gap : 16px ;
204223 }
205224}
206225
207- .field-label {
208- font-size : 12 px ;
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