@@ -278,6 +278,135 @@ const highlightCode = (json) => {
278278 )
279279 }
280280}
281+ const submitSingleEntitlement = async (formRole : any , idx : number ) => {
282+ const role = roleForm [` role${formRole .role }${idx } ` ]
283+
284+ if (formRole .requires_bank_id ) {
285+ // Bank-level entitlement
286+ const bankId = roleForm [` bankId${formRole .role }${idx } ` ]
287+
288+ if (! role || ! bankId ) {
289+ ElNotification ({
290+ duration: elMessageDuration ,
291+ title: ' Validation Error' ,
292+ message: ' Please fill in both Role and Bank ID fields' ,
293+ position: ' bottom-right' ,
294+ type: ' warning'
295+ })
296+ return
297+ }
298+
299+ try {
300+ const response = await createEntitlement (bankId , role )
301+
302+ // Check if response is an error object (from superagent)
303+ const isError = response && typeof response === ' object' && ' error' in response
304+ const errorBody = isError ? response .error : null
305+
306+ if (isError && errorBody && errorBody .code >= 400 ) {
307+ // Parse error message from body
308+ let errorMessage = ' Failed to create entitlement'
309+ if (errorBody .message ) {
310+ // Message might be double-encoded JSON string
311+ try {
312+ const parsed = JSON .parse (errorBody .message )
313+ errorMessage = parsed .message || parsed .error || errorBody .message
314+ } catch {
315+ errorMessage = errorBody .message
316+ }
317+ }
318+
319+ ElNotification ({
320+ duration: elMessageDuration ,
321+ title: ' Request Failed' ,
322+ message: errorMessage ,
323+ position: ' bottom-right' ,
324+ type: ' error'
325+ })
326+ } else {
327+ ElNotification ({
328+ duration: elMessageDuration ,
329+ title: ' Success' ,
330+ message: ` Entitlement "${role }" requested successfully for bank "${bankId }" ` ,
331+ position: ' bottom-right' ,
332+ type: ' success'
333+ })
334+ // Refresh entitlements after successful request
335+ await refreshEntitlements ()
336+ }
337+ } catch (error : any ) {
338+ ElNotification ({
339+ duration: elMessageDuration ,
340+ title: ' Request Failed' ,
341+ message: error .message || ' An error occurred while requesting the entitlement' ,
342+ position: ' bottom-right' ,
343+ type: ' error'
344+ })
345+ }
346+ } else {
347+ // System-wide entitlement (no bank_id required)
348+ if (! role ) {
349+ ElNotification ({
350+ duration: elMessageDuration ,
351+ title: ' Validation Error' ,
352+ message: ' Please select a role' ,
353+ position: ' bottom-right' ,
354+ type: ' warning'
355+ })
356+ return
357+ }
358+
359+ try {
360+ // System-wide entitlement uses empty string for bank_id
361+ const response = await createEntitlement (' ' , role )
362+
363+ // Check if response is an error object (from superagent)
364+ const isError = response && typeof response === ' object' && ' error' in response
365+ const errorBody = isError ? response .error : null
366+
367+ if (isError && errorBody && errorBody .code >= 400 ) {
368+ // Parse error message from body
369+ let errorMessage = ' Failed to create entitlement'
370+ if (errorBody .message ) {
371+ // Message might be double-encoded JSON string
372+ try {
373+ const parsed = JSON .parse (errorBody .message )
374+ errorMessage = parsed .message || parsed .error || errorBody .message
375+ } catch {
376+ errorMessage = errorBody .message
377+ }
378+ }
379+
380+ ElNotification ({
381+ duration: elMessageDuration ,
382+ title: ' Request Failed' ,
383+ message: errorMessage ,
384+ position: ' bottom-right' ,
385+ type: ' error'
386+ })
387+ } else {
388+ ElNotification ({
389+ duration: elMessageDuration ,
390+ title: ' Success' ,
391+ message: ` System-wide entitlement "${role }" requested successfully ` ,
392+ position: ' bottom-right' ,
393+ type: ' success'
394+ })
395+ // Refresh entitlements after successful request
396+ await refreshEntitlements ()
397+ }
398+ } catch (error : any ) {
399+ ElNotification ({
400+ duration: elMessageDuration ,
401+ title: ' Request Failed' ,
402+ message: error .message || ' An error occurred while requesting the entitlement' ,
403+ position: ' bottom-right' ,
404+ type: ' error'
405+ })
406+ }
407+ }
408+ }
409+
281410const submitEntitlement = async () => {
282411 for (const [idx, formRole] of requiredRoles .value .entries ()) {
283412 const role = roleForm [` role${formRole .role }${idx } ` ]
@@ -581,7 +710,7 @@ const onError = (error) => {
581710 <div v-show =" showRequiredRoles" >
582711 <p >{{ $t('preview.required_roles') }}:</p >
583712 <el-alert v-show =" !isUserLogon" type =" info" show-icon :closable =" false" >
584- <p >Please login to request this Role .</p >
713+ <p >Please login to request Roles .</p >
585714 </el-alert >
586715 <ul >
587716 <li
@@ -591,34 +720,36 @@ const onError = (error) => {
591720
592721 >
593722 <div class =" role-header" >
594- <p >{{ role.role }}</p >
723+ <div class =" role-name-section" >
724+ <p >{{ role.role }}</p >
725+ <el-form-item
726+ v-show =" isUserLogon && role.requires_bank_id && !hasEntitlement(role.role, roleForm[`bankId${role.role}${idx}`], role.requires_bank_id)"
727+ :prop =" `bankId${role.role}${idx}`"
728+ class =" role-bank-id-input"
729+ >
730+ <input
731+ type =" text"
732+ v-model =" roleForm[`bankId${role.role}${idx}`]"
733+ placeholder =" Bank ID"
734+ />
735+ </el-form-item >
736+ </div >
595737 <span
596738 v-if =" hasEntitlement(role.role, roleForm[`bankId${role.role}${idx}`], role.requires_bank_id)"
597739 class =" entitlement-owned-text"
598740 >
599741 You have this Entitlement
600742 </span >
601- </div >
602- <div class =" flex-role-preview-panel" id =" request-role-button-panel" >
603- <el-form-item
604- v-show =" isUserLogon && role.requires_bank_id && !hasEntitlement(role.role, roleForm[`bankId${role.role}${idx}`], role.requires_bank_id)"
605- :prop =" `bankId${role.role}${idx}`"
743+ <el-button
744+ class =" role-request-button"
745+ v-show =" isUserLogon && !hasEntitlement(role.role, roleForm[`bankId${role.role}${idx}`], role.requires_bank_id)"
746+ @click =" submit(roleFormRef, () => submitSingleEntitlement(role, idx))"
747+ size =" small"
748+ >Request</el-button
606749 >
607- <input
608- type =" text"
609- v-model =" roleForm[`bankId${role.role}${idx}`]"
610- placeholder =" Bank ID"
611- />
612- </el-form-item >
613750 </div >
614751 </li >
615752 </ul >
616- <el-button
617- id =" request-role-button"
618- v-show =" isUserLogon && requiredRoles.length > 0 && (requiredRoles.some((role) => role.requires_bank_id) || requiredRoles.some((role, idx) => !hasEntitlement(role.role, roleForm[`bankId${role.role}${idx}`], role.requires_bank_id)))"
619- @click =" submit(roleFormRef, submitEntitlement)"
620- >Request</el-button
621- >
622753 </div >
623754 </el-form >
624755 <!-- <div v-show="showValidations">-->
@@ -708,9 +839,18 @@ input[type='text']:focus {
708839}
709840ul {
710841 margin-left : -10px ;
842+ list-style : none ;
843+ padding : 0 ;
711844}
712845li {
713- padding : 5px 0 5px 0 ;
846+ padding : 15px ;
847+ margin-bottom : 15px ;
848+ border : 1px solid #414d63 ;
849+ border-radius : 6px ;
850+ background-color : rgba (65 , 77 , 99 , 0.2 );
851+ }
852+ li :last-child {
853+ margin-bottom : 0 ;
714854}
715855.content p a ::after {
716856 content : ' ' ;
@@ -807,9 +947,26 @@ li {
807947 display : flex ;
808948 align-items : center ;
809949 gap : 15px ;
950+ justify-content : space-between ;
951+ }
952+ .role-name-section {
953+ display : flex ;
954+ align-items : center ;
955+ gap : 15px ;
956+ flex : 1 ;
957+ }
958+ .role-bank-id-input {
959+ margin-bottom : 0 ;
960+ }
961+ .role-bank-id-input input {
962+ width : 200px ;
963+ }
964+ .role-request-button {
965+ margin-left : auto ;
810966}
811967.role-header p {
812968 margin : 0 ;
969+ white-space : nowrap ;
813970}
814971.entitlement-owned-text {
815972 color : #67c23a ;
0 commit comments