Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add customer support link in the short footer #39291

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/theming/lib/Command/UpdateConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@

class UpdateConfig extends Command {
public const SUPPORTED_KEYS = [
'name', 'url', 'imprintUrl', 'privacyUrl', 'slogan', 'color', 'disable-user-theming'
'name', 'url', 'supportUrl', 'imprintUrl', 'privacyUrl', 'slogan', 'color', 'disable-user-theming'
];

private $themingDefaults;
Expand Down
8 changes: 8 additions & 0 deletions apps/theming/lib/Controller/ThemingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ public function updateStylesheet($setting, $value) {
$error = $this->l10n->t('The given web address is not a valid URL');
}
break;
case 'supportUrl':
if (strlen($value) > 500) {
$error = $this->l10n->t('The given customer support address is too long');
}
if (!$this->isValidUrl($value)) {
$error = $this->l10n->t('The given customer support address is not a valid URL');
}
break;
case 'imprintUrl':
if (strlen($value) > 500) {
$error = $this->l10n->t('The given legal notice address is too long');
Expand Down
1 change: 1 addition & 0 deletions apps/theming/lib/Service/JSDataService.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function jsonSerialize(): array {
'slogan' => $this->themingDefaults->getSlogan(),
'color' => $this->themingDefaults->getColorPrimary(),
'defaultColor' => $this->themingDefaults->getDefaultColorPrimary(),
'supportUrl' => $this->themingDefaults->getSupportUrl(),
'imprintUrl' => $this->themingDefaults->getImprintUrl(),
'privacyUrl' => $this->themingDefaults->getPrivacyUrl(),
'inverted' => $this->util->invertTextColor($this->themingDefaults->getColorPrimary()),
Expand Down
1 change: 1 addition & 0 deletions apps/theming/lib/Settings/Admin.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ public function getForm(): TemplateResponse {
'backgroundMime' => $this->config->getAppValue(Application::APP_ID, 'backgroundMime', ''),
'logoheaderMime' => $this->config->getAppValue(Application::APP_ID, 'logoheaderMime', ''),
'faviconMime' => $this->config->getAppValue(Application::APP_ID, 'faviconMime', ''),
'customerSupportUrl' => $this->themingDefaults->getSupportUrl(),
'legalNoticeUrl' => $this->themingDefaults->getImprintUrl(),
'privacyPolicyUrl' => $this->themingDefaults->getPrivacyUrl(),
'docUrl' => $this->urlGenerator->linkToDocs('admin-theming'),
Expand Down
10 changes: 9 additions & 1 deletion apps/theming/lib/ThemingDefaults.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ public function getSlogan(?string $lang = null) {
return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', parent::getSlogan($lang)));
}

public function getSupportUrl(): string {
return $this->config->getAppValue('theming', 'supportUrl', '');
}

public function getImprintUrl() {
return (string)$this->config->getAppValue('theming', 'imprintUrl', '');
}
Expand All @@ -181,6 +185,10 @@ public function getShortFooter() {
$footer .= ($slogan !== '' ? ' – ' . $slogan : '');

$links = [
[
'text' => $this->l->t('Customer support'),
'url' => $this->getSupportUrl()
],
[
'text' => $this->l->t('Legal notice'),
'url' => (string)$this->getImprintUrl()
Expand Down Expand Up @@ -371,7 +379,7 @@ public function getScssVariables() {
}

$variables['has-legal-links'] = 'false';
if ($this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
if ($this->getSupportUrl() !== '' || $this->getImprintUrl() !== '' || $this->getPrivacyUrl() !== '') {
$variables['has-legal-links'] = 'true';
}

Expand Down
10 changes: 10 additions & 0 deletions apps/theming/src/AdminTheming.vue
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ const {
slogan,
url,
userThemingDisabled,
customerSupportUrl,
} = loadState('theming', 'adminThemingParameters')

const textFields = [
Expand Down Expand Up @@ -195,6 +196,15 @@ const fileInputFields = [
]

const advancedTextFields = [
{
name: 'supportUrl',
value: customerSupportUrl,
defaultValue: '',
type: 'url',
displayName: t('theming', 'Customer support link'),
placeholder: 'https://…',
maxlength: 500,
},
{
name: 'imprintUrl',
value: legalNoticeUrl,
Expand Down
81 changes: 73 additions & 8 deletions apps/theming/tests/ThemingDefaultsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,20 @@ public function legalUrlProvider() {
];
}

/**
* @param $supportUrl
* @dataProvider legalUrlProvider
*/
public function testGetSupportURL($supportUrl) {
$this->config
->expects($this->once())
->method('getAppValue')
->with('theming', 'supportUrl', '')
->willReturn($supportUrl);

$this->assertEquals($supportUrl, $this->template->getSupportUrl());
}

/**
* @param $imprintUrl
* @dataProvider legalUrlProvider
Expand Down Expand Up @@ -267,12 +281,13 @@ public function testGetSloganWithCustom() {

public function testGetShortFooter() {
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', ''],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', ''],
]);
Expand All @@ -283,12 +298,13 @@ public function testGetShortFooter() {
public function testGetShortFooterEmptyUrl() {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), ''],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', ''],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', ''],
]);
Expand All @@ -299,28 +315,52 @@ public function testGetShortFooterEmptyUrl() {
public function testGetShortFooterEmptySlogan() {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), ''],
['theming', 'supportUrl', '', ''],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', ''],
]);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a>', $this->template->getShortFooter());
}

public function testGetShortFooterSupport() {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', 'https://example.com/support'],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', ''],
]);

$this->l10n
->expects($this->any())
->method('t')
->willReturnArgument(0);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan<br/><a href="https://example.com/imprint" class="legal" target="_blank" rel="noreferrer noopener">Legal notice</a>', $this->template->getShortFooter());
}

public function testGetShortFooterImprint() {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', ''],
['theming', 'imprintUrl', '', 'https://example.com/imprint'],
['theming', 'privacyUrl', '', ''],
]);
Expand All @@ -336,12 +376,13 @@ public function testGetShortFooterImprint() {
public function testGetShortFooterPrivacy() {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', ''],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', 'https://example.com/privacy'],
]);
Expand All @@ -357,12 +398,13 @@ public function testGetShortFooterPrivacy() {
public function testGetShortFooterAllLegalLinks() {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', 'https://example.com/support'],
['theming', 'imprintUrl', '', 'https://example.com/imprint'],
['theming', 'privacyUrl', '', 'https://example.com/privacy'],
]);
Expand All @@ -382,19 +424,41 @@ public function invalidLegalUrlProvider() {
];
}

/**
* @param $invalidSupportUrl
* @dataProvider invalidLegalUrlProvider
*/
public function testGetShortFooterInvalidSupport($invalidSupportUrl) {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', $invalidSupportUrl],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', ''],
]);

$this->assertEquals('<a href="url" target="_blank" rel="noreferrer noopener" class="entity-name">Name</a> – Slogan', $this->template->getShortFooter());
}

/**
* @param $invalidImprintUrl
* @dataProvider invalidLegalUrlProvider
*/
public function testGetShortFooterInvalidImprint($invalidImprintUrl) {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', ''],
['theming', 'imprintUrl', '', $invalidImprintUrl],
['theming', 'privacyUrl', '', ''],
]);
Expand All @@ -409,12 +473,13 @@ public function testGetShortFooterInvalidImprint($invalidImprintUrl) {
public function testGetShortFooterInvalidPrivacy($invalidPrivacyUrl) {
$this->navigationManager->expects($this->once())->method('getAll')->with(INavigationManager::TYPE_GUEST)->willReturn([]);
$this->config
->expects($this->exactly(5))
->expects($this->exactly(6))
->method('getAppValue')
->willReturnMap([
['theming', 'url', $this->defaults->getBaseUrl(), 'url'],
['theming', 'name', 'Nextcloud', 'Name'],
['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'],
['theming', 'supportUrl', '', ''],
['theming', 'imprintUrl', '', ''],
['theming', 'privacyUrl', '', $invalidPrivacyUrl],
]);
Expand Down
4 changes: 2 additions & 2 deletions dist/theming-admin-theming.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/theming-admin-theming.js.map

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions lib/private/AppConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ class AppConfig implements IAppConfig {
'/^subscription_key$/',
],
'theming' => [
'/^supportUrl$/',
'/^imprintUrl$/',
'/^privacyUrl$/',
'/^slogan$/',
Expand Down