44 v-for =" banner in localBanners "
55 :key =" banner .name "
66 :class =" disableLastChildBottomMargin ? ` mb-5 last:mb-0 ` : ` mb-5 ` "
7- :title =" ` <b>${ banner .title }:</b> ${ banner .message } ` "
7+ :title =" getAlertTitle ( banner .title , banner .message ) "
88 :type =" banner .type .toLowerCase ()"
99 :isDismissible =" banner .is_dismissible "
1010 @dismissBanner =" closeBanner (banner .name )"
1111 >
12- <template v-if =" !! banner .help_url " >
12+ <template
13+ v-if ="
14+ !! banner .help_url ||
15+ (banner .has_action && banner .action_label && banner .action_script )
16+ "
17+ >
1318 <Button
14- class="ml-auto flex flex-row items-center gap-1"
15- @click =" openHelp (banner .help_url )"
19+ size="sm"
20+ class="ml-auto flex flex-row items-center gap-x-1"
21+ @click ="
22+ banner .has_action
23+ ? exec (banner .action_script )
24+ : openHelp (banner .help_url )
25+ "
1626 variant="outline"
1727 >
18- Open help
28+ {{ banner.has_action ? banner.action_label : ' Open help' }}
1929 <lucide-external-link class =" inline h-4 w-3 pb-0.5" />
2030 </Button >
2131 </template >
@@ -36,10 +46,13 @@ export default {
3646 validator : (value ) => ! value || [' Site' , ' Server' ].includes (value),
3747 },
3848 ctx_name: {
39- type: String ,
4049 required: false ,
4150 validator : (value ) =>
42- ! value || (typeof value === ' string' && value .length > 0 ),
51+ ! value ||
52+ (typeof value === ' string' && value .length > 0 ) ||
53+ (Array .isArray (value) &&
54+ value .every ((el ) => typeof el === ' string' ) &&
55+ value .length > 0 ),
4356 },
4457 containerClass: {
4558 type: String ,
@@ -58,7 +71,23 @@ export default {
5871 localDismissedBanners: {},
5972 };
6073 },
74+ computed: {
75+ ctxNames () {
76+ return Array .isArray (this .ctx_name )
77+ ? this .ctx_name
78+ : this .ctx_name
79+ ? [this .ctx_name ]
80+ : [];
81+ },
82+ },
6183 methods: {
84+ getAlertTitle (bannerTitle , bannerMessage ) {
85+ let str = ' ' ;
86+ if (bannerTitle) str = str .concat (` <b>${ bannerTitle} </b>` );
87+ if (!! bannerTitle && !! bannerMessage) str = str .concat (' : ' );
88+ if (bannerMessage) str = str .concat (bannerMessage);
89+ return str;
90+ },
6291 closeBanner (bannerName ) {
6392 const banner = this .localBanners .find ((b ) => b .name === bannerName);
6493 if (! banner) return ;
@@ -67,7 +96,7 @@ export default {
6796 (b ) => b .name !== bannerName,
6897 );
6998
70- if (banner .is_global ) {
99+ if (banner .is_global || banner . type_of_scope == ' Cluster ' ) {
71100 // Persist dismissal to local storage
72101 this .localDismissedBanners [bannerName] = Date .now ();
73102 localStorage .setItem (
@@ -82,16 +111,23 @@ export default {
82111 openHelp (url ) {
83112 window .open (url, ' _blank' );
84113 },
114+ exec (action_script ) {
115+ const actionFn = new Function (
116+ ' _this' ,
117+ action_script + ' \n onClickAction(_this)' ,
118+ );
119+ actionFn (this );
120+ },
85121 trimOldDismissedBanners () {
86- // Remove dismissed banners older than 30 days from local storage
87- const THIRTY_DAYS = 30 * 24 * 60 * 60 * 1000 ;
122+ // Remove dismissed banners older than 60 days from local storage
123+ const SIXTY_DAYS_IN_MS = 60 * 24 * 60 * 60 * 1000 ;
88124 const now = Date .now ();
89125 let diff = false ;
90126
91127 for (const [bannerName , timestamp ] of Object .entries (
92128 this .localDismissedBanners ,
93129 )) {
94- if (now - timestamp > THIRTY_DAYS ) {
130+ if (now - timestamp > SIXTY_DAYS_IN_MS ) {
95131 delete this .localDismissedBanners [bannerName];
96132 diff = true ;
97133 }
@@ -104,6 +140,34 @@ export default {
104140 );
105141 }
106142 },
143+ isRelevantBanner (banner ) {
144+ if (banner .is_global ) return true ;
145+
146+ const ctxMatches = (list ) =>
147+ Array .isArray (list) &&
148+ list .some ((item ) => this .ctxNames .includes (item));
149+
150+ switch (this .ctx_type ) {
151+ case ' Server' :
152+ return (
153+ (banner .type_of_scope === ' Server' && ctxMatches (banner .server )) ||
154+ (banner .type_of_scope === ' Cluster' && ctxMatches (banner .cluster ))
155+ );
156+
157+ case ' Site' :
158+ return (
159+ (banner .type_of_scope === ' Site' && ctxMatches (banner .site )) ||
160+ (banner .type_of_scope === ' Server' && ctxMatches (banner .server )) ||
161+ (banner .type_of_scope === ' Cluster' && ctxMatches (banner .cluster ))
162+ );
163+
164+ case ' List Page' :
165+ return [' Team' , ' Cluster' , ' Server' ].includes (banner .type_of_scope );
166+
167+ default :
168+ return true ;
169+ }
170+ },
107171 },
108172 resources: {
109173 banners () {
@@ -126,24 +190,10 @@ export default {
126190
127191 this .trimOldDismissedBanners ();
128192
129- this .localBanners = (
130- this .ctx_type === ' Server'
131- ? data .filter (
132- (banner ) =>
133- banner .server === this .ctx_name || banner .is_global ,
134- )
135- : this .ctx_type === ' Site'
136- ? data .filter (
137- (banner ) =>
138- banner .site === this .ctx_name || banner .is_global ,
139- )
140- : this .ctx_type === ' List Page'
141- ? data .filter (
142- (banner ) =>
143- banner .type_of_scope === ' Team' || banner .is_global ,
144- )
145- : data
146- ).filter ((banner ) => ! (banner .name in this .localDismissedBanners ));
193+ this .localBanners = data
194+ .filter (this .isRelevantBanner )
195+ .filter ((banner ) => banner .title || banner .message )
196+ .filter ((banner ) => ! (banner .name in this .localDismissedBanners ));
147197 },
148198 };
149199 },
0 commit comments