@@ -22,6 +22,21 @@ SPDX-License-Identifier: AGPL-3.0-or-later
2222 <NcNoteCard v-if =" errorMessage" type =" error" data-testid =" profile-fields-admin-error" >
2323 {{ errorMessage }}
2424 </NcNoteCard >
25+ <NcNoteCard v-if =" showSupportBanner" type =" info" data-testid =" profile-fields-admin-support-banner" >
26+ <div class =" profile-fields-admin__support-banner" >
27+ <p >
28+ This app is open source and released under the AGPL license.
29+ To keep development and maintenance active, please
30+ <a href =" https://github.com/sponsors/LibreSign" target =" _blank" rel =" noopener noreferrer" >sponsor LibreSign on GitHub Sponsors</a >
31+ If possible, choose a monthly sponsorship.
32+ </p >
33+ <div class =" profile-fields-admin__support-banner-actions" >
34+ <NcButton class =" profile-fields-admin__support-banner-action" variant =" tertiary-no-background" @click =" dismissSupportBanner" >
35+ Not now
36+ </NcButton >
37+ </div >
38+ </div >
39+ </NcNoteCard >
2540 <span
2641 class =" profile-fields-admin__success-announcement"
2742 data-testid =" profile-fields-admin-success"
@@ -421,12 +436,23 @@ const definitions = ref<FieldDefinition[]>([])
421436const isLoading = ref (true )
422437const isSaving = ref (false )
423438const errorMessage = ref (' ' )
439+ const supportBannerStorageKey = ' profile_fields_support_banner_dismissed'
440+ const showSupportBanner = ref (true )
424441const selectedId = ref <number | null >(null )
425442const justSavedId = ref <number | null >(null )
426443let justSavedTimeout: ReturnType <typeof setTimeout > | null = null
427444const successMessage = ref (' ' )
428445let successMessageTimeout: ReturnType <typeof setTimeout > | null = null
429446
447+ const dismissSupportBanner = () => {
448+ showSupportBanner .value = false
449+ try {
450+ window .localStorage .setItem (supportBannerStorageKey , ' 1' )
451+ } catch {
452+ // Ignore storage errors and keep only in-memory dismissal.
453+ }
454+ }
455+
430456const setSuccessMessage = (message : string ) => {
431457 if (successMessageTimeout !== null ) {
432458 clearTimeout (successMessageTimeout )
@@ -1002,6 +1028,11 @@ watch(() => form.type, (newType: FieldType) => {
10021028
10031029onMounted (() => {
10041030 loadDefinitions ()
1031+ try {
1032+ showSupportBanner .value = window .localStorage .getItem (supportBannerStorageKey ) !== ' 1'
1033+ } catch {
1034+ showSupportBanner .value = true
1035+ }
10051036 compactLayoutMediaQuery = window .matchMedia (' (max-width: 1024px)' )
10061037 updateCompactLayout (compactLayoutMediaQuery .matches )
10071038 compactLayoutMediaQuery .addEventListener (' change' , handleCompactLayoutChange )
@@ -1081,6 +1112,35 @@ onBeforeUnmount(() => {
10811112 gap : 20px ;
10821113 }
10831114
1115+ & __support-banner {
1116+ display : grid ;
1117+ grid-template-columns : minmax (0 , 1fr );
1118+ gap : 10px ;
1119+ width : 100% ;
1120+
1121+ p {
1122+ margin : 0 ;
1123+ overflow-wrap : anywhere;
1124+ line-height : 1.5 ;
1125+ }
1126+
1127+ a {
1128+ font-weight : 600 ;
1129+ overflow-wrap : anywhere;
1130+ }
1131+ }
1132+
1133+ & __support-banner-actions {
1134+ display : flex ;
1135+ justify-content : flex-end ;
1136+ width : 100% ;
1137+ }
1138+
1139+ & __support-banner-action {
1140+ flex : 0 0 auto ;
1141+ white-space : nowrap ;
1142+ }
1143+
10841144 & __field-helper {
10851145 margin : 8px 0 0 ;
10861146 color : var (--color-text-maxcontrast );
@@ -1601,6 +1661,18 @@ onBeforeUnmount(() => {
16011661 width : 100% ;
16021662 }
16031663
1664+ & __support-banner {
1665+ gap : 8px ;
1666+
1667+ :deep (.button-vue ) {
1668+ max-width : 100% ;
1669+ }
1670+ }
1671+
1672+ & __support-banner-actions {
1673+ justify-content : flex-start ;
1674+ }
1675+
16041676 & __submit-row ,
16051677 & __editor-actions {
16061678 flex-wrap : wrap ;
0 commit comments