diff --git a/apps/theming/css/settings-admin.scss b/apps/theming/css/settings-admin.scss index ceb560f0f02fd..7753540ccd27c 100644 --- a/apps/theming/css/settings-admin.scss +++ b/apps/theming/css/settings-admin.scss @@ -28,7 +28,7 @@ visibility: hidden; } form.uploadButton { - width: 356px; + width: 411px; } form .theme-undo, .theme-remove-bg { @@ -46,13 +46,17 @@ input[type='text']:hover + .theme-undo, input[type='text'] + .theme-undo:hover, input[type='text']:focus + .theme-undo, - input[type='text']:active + .theme-undo { + input[type='text']:active + .theme-undo, + input[type='url']:hover + .theme-undo, + input[type='url'] + .theme-undo:hover, + input[type='url']:focus + .theme-undo, + input[type='url']:active + .theme-undo{ visibility: visible; } label span { display: inline-block; - min-width: 120px; + min-width: 175px; padding: 8px 0px; vertical-align: top; } @@ -88,7 +92,7 @@ background-size: cover; background-position: center center; text-align: center; - margin-left: 123px; + margin-left: 178px; margin-top: 10px; margin-bottom: 20px; cursor: pointer; @@ -117,4 +121,4 @@ background-repeat: no-repeat; background-size: contain; } -} \ No newline at end of file +} diff --git a/apps/theming/js/settings-admin.js b/apps/theming/js/settings-admin.js index 25ac092a96417..76d9fb965ca56 100644 --- a/apps/theming/js/settings-admin.js +++ b/apps/theming/js/settings-admin.js @@ -83,7 +83,8 @@ function hideUndoButton(setting, value) { url: 'https://nextcloud.com', color: '#0082c9', logoMime: '', - backgroundMime: '' + backgroundMime: '', + imprintUrl: '' }; if (value === themingDefaults[setting] || value === '') { @@ -175,7 +176,7 @@ $(document).ready(function () { var el = $(this); }); - $('#theming input[type=text]').change(function(e) { + function onChange(e) { var el = $(this); var setting = el.parent().find('div[data-setting]').data('setting'); var value = $(this).val(); @@ -186,14 +187,14 @@ $(document).ready(function () { } } if(setting === 'name') { - if(checkName()){ - $.when(el.focusout()).then(function() { - setThemingValue('name', value); - }); - if (e.keyCode == 13) { - setThemingValue('name', value); - } - } + if(checkName()){ + $.when(el.focusout()).then(function() { + setThemingValue('name', value); + }); + if (e.keyCode == 13) { + setThemingValue('name', value); + } + } } $.when(el.focusout()).then(function() { @@ -202,7 +203,10 @@ $(document).ready(function () { if (e.keyCode == 13) { setThemingValue(setting, value); } - }); + }; + + $('#theming input[type="text"]').change(onChange); + $('#theming input[type="url"]').change(onChange); $('.theme-undo').click(function (e) { var setting = $(this).data('setting'); diff --git a/apps/theming/lib/Controller/ThemingController.php b/apps/theming/lib/Controller/ThemingController.php index 421af05199842..27daf756d4806 100644 --- a/apps/theming/lib/Controller/ThemingController.php +++ b/apps/theming/lib/Controller/ThemingController.php @@ -161,6 +161,16 @@ public function updateStylesheet($setting, $value) { ]); } break; + case 'imprintUrl': + if (strlen($value) > 500) { + return new DataResponse([ + 'data' => [ + 'message' => $this->l10n->t('The given legal notice address is too long'), + ], + 'status' => 'error' + ]); + } + break; case 'slogan': if (strlen($value) > 500) { return new DataResponse([ @@ -406,6 +416,7 @@ public function getJavascript() { url: ' . json_encode($this->themingDefaults->getBaseUrl()) . ', slogan: ' . json_encode($this->themingDefaults->getSlogan()) . ', color: ' . json_encode($this->themingDefaults->getColorPrimary()) . ', + imprintUrl: ' . json_encode($this->themingDefaults->getImprintUrl()) . ', inverted: ' . json_encode($this->util->invertTextColor($this->themingDefaults->getColorPrimary())) . ', cacheBuster: ' . json_encode($cacheBusterValue) . ' }; diff --git a/apps/theming/lib/Settings/Admin.php b/apps/theming/lib/Settings/Admin.php index 7c937f1979090..ef296688ed2ce 100644 --- a/apps/theming/lib/Settings/Admin.php +++ b/apps/theming/lib/Settings/Admin.php @@ -84,6 +84,7 @@ public function getForm(): TemplateResponse { 'canThemeIcons' => $this->themingDefaults->shouldReplaceIcons(), 'iconDocs' => $this->urlGenerator->linkToDocs('admin-theming-icons'), 'images' => $this->imageManager->getCustomImages(), + 'imprintUrl' => $this->themingDefaults->getImprintUrl(), ]; return new TemplateResponse('theming', 'settings-admin', $parameters, ''); diff --git a/apps/theming/lib/ThemingDefaults.php b/apps/theming/lib/ThemingDefaults.php index 2e6b667b1f66f..d2f5747124235 100644 --- a/apps/theming/lib/ThemingDefaults.php +++ b/apps/theming/lib/ThemingDefaults.php @@ -141,12 +141,26 @@ public function getSlogan() { return \OCP\Util::sanitizeHTML($this->config->getAppValue('theming', 'slogan', $this->slogan)); } + public function getImprintUrl() { + return $this->config->getAppValue('theming', 'imprintUrl', ''); + } + public function getShortFooter() { $slogan = $this->getSlogan(); $footer = '' .$this->getEntity() . ''. ($slogan !== '' ? ' – ' . $slogan : ''); + $imprintUrl = (string)$this->getImprintUrl(); + if($imprintUrl !== '' + && filter_var($imprintUrl, FILTER_VALIDATE_URL, [ + 'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED + ]) + ) { + $footer .= '
' . $this->l->t('Legal notice') . ''; + } + return $footer; } diff --git a/apps/theming/templates/settings-admin.php b/apps/theming/templates/settings-admin.php index ea9925f3a64f5..26ab78637c911 100644 --- a/apps/theming/templates/settings-admin.php +++ b/apps/theming/templates/settings-admin.php @@ -47,8 +47,8 @@
@@ -94,6 +94,13 @@

t('Advanced options')); ?>

+
+ +
diff --git a/apps/theming/tests/Controller/ThemingControllerTest.php b/apps/theming/tests/Controller/ThemingControllerTest.php index dda881525f0ca..f2f14e44a02b2 100644 --- a/apps/theming/tests/Controller/ThemingControllerTest.php +++ b/apps/theming/tests/Controller/ThemingControllerTest.php @@ -814,6 +814,7 @@ public function testGetJavascript() { url: "", slogan: "", color: "#000", + imprintUrl: null, inverted: false, cacheBuster: null }; @@ -848,6 +849,7 @@ public function testGetJavascriptInverted() { url: "nextcloudurl", slogan: "awesome", color: "#ffffff", + imprintUrl: null, inverted: true, cacheBuster: null }; diff --git a/apps/theming/tests/Settings/AdminTest.php b/apps/theming/tests/Settings/AdminTest.php index 4eac689fb3ff8..f7361677d77ef 100644 --- a/apps/theming/tests/Settings/AdminTest.php +++ b/apps/theming/tests/Settings/AdminTest.php @@ -81,6 +81,10 @@ public function testGetFormNoErrors() { ->expects($this->once()) ->method('getBaseUrl') ->willReturn('https://example.com'); + $this->themingDefaults + ->expects($this->once()) + ->method('getImprintUrl') + ->willReturn(''); $this->themingDefaults ->expects($this->once()) ->method('getSlogan') @@ -105,6 +109,7 @@ public function testGetFormNoErrors() { 'canThemeIcons' => null, 'iconDocs' => null, 'images' => [], + 'imprintUrl' => '', ]; $expected = new TemplateResponse('theming', 'settings-admin', $params, ''); @@ -130,6 +135,10 @@ public function testGetFormWithErrors() { ->expects($this->once()) ->method('getBaseUrl') ->willReturn('https://example.com'); + $this->themingDefaults + ->expects($this->once()) + ->method('getImprintUrl') + ->willReturn(''); $this->themingDefaults ->expects($this->once()) ->method('getSlogan') @@ -154,6 +163,7 @@ public function testGetFormWithErrors() { 'canThemeIcons' => null, 'iconDocs' => '', 'images' => [], + 'imprintUrl' => '', ]; $expected = new TemplateResponse('theming', 'settings-admin', $params, ''); diff --git a/apps/theming/tests/ThemingDefaultsTest.php b/apps/theming/tests/ThemingDefaultsTest.php index c943af01c6c51..b454b21f84091 100644 --- a/apps/theming/tests/ThemingDefaultsTest.php +++ b/apps/theming/tests/ThemingDefaultsTest.php @@ -195,6 +195,27 @@ public function testGetBaseUrlWithCustom() { $this->assertEquals('https://example.com/', $this->template->getBaseUrl()); } + public function imprintUrlProvider() { + return [ + [ '' ], + [ 'https://example.com/imprint.html'] + ]; + } + + /** + * @param $imprintUrl + * @dataProvider imprintUrlProvider + */ + public function testGetImprintURL($imprintUrl) { + $this->config + ->expects($this->once()) + ->method('getAppValue') + ->with('theming', 'imprintUrl', '') + ->willReturn($imprintUrl); + + $this->assertEquals($imprintUrl, $this->template->getImprintUrl()); + } + public function testGetSloganWithDefault() { $this->config ->expects($this->once()) @@ -217,12 +238,13 @@ public function testGetSloganWithCustom() { public function testGetShortFooter() { $this->config - ->expects($this->exactly(3)) + ->expects($this->exactly(4)) ->method('getAppValue') ->willReturnMap([ ['theming', 'url', $this->defaults->getBaseUrl(), 'url'], ['theming', 'name', 'Nextcloud', 'Name'], ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'], + ['theming', 'imprintUrl', '', ''], ]); $this->assertEquals('Name – Slogan', $this->template->getShortFooter()); @@ -230,17 +252,62 @@ public function testGetShortFooter() { public function testGetShortFooterEmptySlogan() { $this->config - ->expects($this->exactly(3)) + ->expects($this->exactly(4)) ->method('getAppValue') ->willReturnMap([ ['theming', 'url', $this->defaults->getBaseUrl(), 'url'], ['theming', 'name', 'Nextcloud', 'Name'], ['theming', 'slogan', $this->defaults->getSlogan(), ''], + ['theming', 'imprintUrl', '', ''], ]); $this->assertEquals('Name', $this->template->getShortFooter()); } + public function testGetShortFooterImprint() { + $this->config + ->expects($this->exactly(4)) + ->method('getAppValue') + ->willReturnMap([ + ['theming', 'url', $this->defaults->getBaseUrl(), 'url'], + ['theming', 'name', 'Nextcloud', 'Name'], + ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'], + ['theming', 'imprintUrl', '', 'https://example.com/imprint'], + ]); + + $this->l10n + ->expects($this->any()) + ->method('t') + ->willReturnArgument(0); + + $this->assertEquals('Name – Slogan
Legal notice', $this->template->getShortFooter()); + } + + public function invalidImprintUrlProvider() { + return [ + ['example.com/imprint'], # missing scheme + ['https:///imprint'], # missing host + ]; + } + + /** + * @param $invalidImprintUrl + * @dataProvider invalidImprintUrlProvider + */ + public function testGetShortFooterInvalidImprint($invalidImprintUrl) { + $this->config + ->expects($this->exactly(4)) + ->method('getAppValue') + ->willReturnMap([ + ['theming', 'url', $this->defaults->getBaseUrl(), 'url'], + ['theming', 'name', 'Nextcloud', 'Name'], + ['theming', 'slogan', $this->defaults->getSlogan(), 'Slogan'], + ['theming', 'imprintUrl', '', $invalidImprintUrl], + ]); + + $this->assertEquals('Name – Slogan', $this->template->getShortFooter()); + } + public function testgetColorPrimaryWithDefault() { $this->config ->expects($this->once()) diff --git a/core/css/guest.css b/core/css/guest.css index e0e639252eeec..88341fb903a33 100644 --- a/core/css/guest.css +++ b/core/css/guest.css @@ -744,6 +744,10 @@ footer .info a { overflow: hidden; } +a.legal { + font-size: smaller; +} + /* for low-res screens, use Regular font-weight instead of Light */ @media (-webkit-max-device-pixel-ratio: 1.3), (max-resolution: 124.8dpi) { @font-face {