fix(branding): remove "Powered by Chatwoot" footer from widget
Branding.vue's template conditionally rendered a "Powered by ..." link in the website chat widget footer (and survey screens that mount the same component). Replace the component with an empty placeholder that preserves original spacing. Script logic dropped along with the now-unused prop, imports, data, and computed — original template was the only thing referencing them. Callers passing `:disable-branding="..."` (ViewWithHeader.vue) keep working since Vue 3 ignores unknown props on single-root components. The enterprise `disable_branding` feature flag isn't a viable approach because Internal::ReconcilePlanConfigService resets it on every run (brand-reset cat-and-mouse). Direct edit with marker comments is the durable fix. Documented in LEADCHAT.md.
This commit is contained in:
@@ -33,6 +33,7 @@ LeadChat is a white-label Chatwoot fork maintained on the `leadchat` branch. Cus
|
||||
| `config/routes.rb` (3 separate blocks) | (1) `app_new_microsoft_shared_inbox` dashboard route; (2) account-namespaced `microsoft_shared/authorization` API endpoint; (3) `microsoft_shared/callback` OAuth callback | `# === LeadChat: microsoft_shared ===` |
|
||||
| `app/javascript/dashboard/routes/dashboard/settings/inbox/channels/Email.vue` (3 separate blocks) | (1) import `MicrosoftShared.vue`; (2) `emailProviderList` entry for `microsoft_shared`; (3) router slot `<MicrosoftShared v-else-if="provider === 'microsoft_shared'"/>` | `<!-- === LeadChat: microsoft_shared === -->` and `// === LeadChat: microsoft_shared ===` |
|
||||
| `app/javascript/dashboard/i18n/locale/en/inboxMgmt.json` | New keys: `INBOX_MGMT.ADD.MICROSOFT_SHARED.*` and `INBOX_MGMT.EMAIL_PROVIDERS.MICROSOFT_SHARED.*` | (no comment markers — JSON; flagged here in LEADCHAT.md instead) |
|
||||
| `app/javascript/shared/components/Branding.vue` (template only) | Replace conditional "Powered by ..." footer link with the empty placeholder div that the original v-else already used. Removes branding from the website chat widget, survey screens, and any other component that mounts `<Branding/>`. Enterprise's `disable_branding` feature flag gets reset by `Internal::ReconcilePlanConfigService`, so a feature-flag approach is unreliable. | `<!-- === LeadChat: branding-removal === -->` |
|
||||
|
||||
### C. New top-level files (no upstream conflict potential)
|
||||
|
||||
|
||||
@@ -1,76 +1,22 @@
|
||||
<script>
|
||||
import { useBranding } from 'shared/composables/useBranding';
|
||||
|
||||
const {
|
||||
LOGO_THUMBNAIL: logoThumbnail,
|
||||
BRAND_NAME: brandName,
|
||||
WIDGET_BRAND_URL: widgetBrandURL,
|
||||
} = window.globalConfig || {};
|
||||
|
||||
export default {
|
||||
props: {
|
||||
disableBranding: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
const { replaceInstallationName } = useBranding();
|
||||
return {
|
||||
replaceInstallationName,
|
||||
};
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
globalConfig: {
|
||||
brandName,
|
||||
logoThumbnail,
|
||||
widgetBrandURL,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
brandRedirectURL() {
|
||||
try {
|
||||
const referrerHost = this.$store.getters['appConfig/getReferrerHost'];
|
||||
const url = new URL(this.globalConfig.widgetBrandURL);
|
||||
if (referrerHost) {
|
||||
url.searchParams.set('utm_source', referrerHost);
|
||||
url.searchParams.set('utm_medium', 'widget');
|
||||
} else {
|
||||
url.searchParams.set('utm_medium', 'survey');
|
||||
}
|
||||
url.searchParams.set('utm_campaign', 'branding');
|
||||
return url.toString();
|
||||
} catch (e) {
|
||||
// Suppressing the error as getter is not defined in some cases
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
};
|
||||
// === LeadChat: branding-removal (start) ===
|
||||
// Original component rendered a "Powered by Chatwoot" link in the website
|
||||
// chat widget footer and survey screens. We don't want any branding there
|
||||
// (neither Chatwoot nor LeadChat). Enterprise's `disable_branding` feature
|
||||
// flag isn't a viable alternative because Internal::ReconcilePlanConfigService
|
||||
// resets it on every run, so a direct edit is the durable fix.
|
||||
//
|
||||
// Component reduced to an empty placeholder div that preserves the original
|
||||
// spacing. Script logic and props that the original template referenced
|
||||
// (logoThumbnail, brandName, widgetBrandURL, brandRedirectURL,
|
||||
// replaceInstallationName, disableBranding prop) are dropped because the
|
||||
// template no longer uses them. Callers passing `:disable-branding="..."`
|
||||
// (e.g. ViewWithHeader.vue) keep working — Vue silently ignores unknown
|
||||
// props on single-root components.
|
||||
export default {};
|
||||
// === LeadChat: branding-removal (end) ===
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="globalConfig.brandName && !disableBranding"
|
||||
class="px-0 py-3 flex justify-center"
|
||||
>
|
||||
<a
|
||||
:href="brandRedirectURL"
|
||||
rel="noreferrer noopener nofollow"
|
||||
target="_blank"
|
||||
class="branding--link text-n-slate-11 hover:text-n-slate-12 cursor-pointer text-xs inline-flex grayscale-[1] hover:grayscale-0 hover:opacity-100 opacity-90 no-underline justify-center items-center leading-3"
|
||||
>
|
||||
<img
|
||||
class="ltr:mr-1 rtl:ml-1 max-w-3 max-h-3"
|
||||
:alt="globalConfig.brandName"
|
||||
:src="globalConfig.logoThumbnail"
|
||||
/>
|
||||
<span>
|
||||
{{ replaceInstallationName($t('POWERED_BY')) }}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div v-else class="p-3" />
|
||||
<div class="p-3" />
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user