Signed-off-by: Arthur Schiwon <blizzz@arthur-schiwon.de>tags/v14.0.0beta1
@@ -28,7 +28,7 @@ | |||
visibility: hidden; | |||
} | |||
form.uploadButton { | |||
width: 356px; | |||
width: 411px; | |||
} | |||
form .theme-undo, | |||
.theme-remove-bg { | |||
@@ -52,7 +52,7 @@ | |||
label span { | |||
display: inline-block; | |||
min-width: 120px; | |||
min-width: 175px; | |||
padding: 8px 0px; | |||
vertical-align: top; | |||
} | |||
@@ -88,7 +88,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 +117,4 @@ | |||
background-repeat: no-repeat; | |||
background-size: contain; | |||
} | |||
} | |||
} |
@@ -175,7 +175,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 +186,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 +202,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'); |
@@ -161,6 +161,16 @@ class ThemingController extends Controller { | |||
]); | |||
} | |||
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 @@ class ThemingController extends Controller { | |||
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) . ' | |||
}; |
@@ -84,6 +84,7 @@ class Admin implements ISettings { | |||
'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, ''); |
@@ -141,12 +141,26 @@ class ThemingDefaults extends \OC_Defaults { | |||
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 = '<a href="'. $this->getBaseUrl() . '" target="_blank"' . | |||
' rel="noreferrer noopener">' .$this->getEntity() . '</a>'. | |||
($slogan !== '' ? ' – ' . $slogan : ''); | |||
$imprintUrl = (string)$this->getImprintUrl(); | |||
if($imprintUrl !== '' | |||
&& filter_var($imprintUrl, FILTER_VALIDATE_URL, [ | |||
'flags' => FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED | |||
]) | |||
) { | |||
$footer .= '<br/><a href="' . $imprintUrl . '" class="legal" target="_blank"' . | |||
' rel="noreferrer noopener">' . $this->l->t('Legal notice') . '</a>'; | |||
} | |||
return $footer; | |||
} | |||
@@ -94,6 +94,13 @@ style('theming', 'settings-admin'); | |||
<h2 class="inlineblock"><?php p($l->t('Advanced options')); ?></h2> | |||
<div class="advanced-options"> | |||
<div> | |||
<label> | |||
<span><?php p($l->t('Legal notice address')) ?></span> | |||
<input id="theming-imprintUrl" type="url" placeholder="<?php p($l->t('Legal notice address https://…')); ?>" value="<?php p($_['imprintUrl']) ?>" maxlength="500" /> | |||
<div data-setting="imprintUrl" data-toggle="tooltip" data-original-title="<?php p($l->t('Reset to default')); ?>" class="theme-undo icon icon-history"></div> | |||
</label> | |||
</div> | |||
<div class="advanced-option-logoheader"> | |||
<form class="uploadButton" method="post" action="<?php p($_['uploadLogoRoute']) ?>" data-image-key="logoheader"> | |||
<input type="hidden" id="theming-logoheaderMime" value="<?php p($_['images']['logoheader']['mime']); ?>" /> |
@@ -195,6 +195,27 @@ class ThemingDefaultsTest extends TestCase { | |||
$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 @@ class ThemingDefaultsTest extends TestCase { | |||
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('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan', $this->template->getShortFooter()); | |||
@@ -230,17 +252,62 @@ class ThemingDefaultsTest extends TestCase { | |||
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('<a href="url" target="_blank" rel="noreferrer noopener">Name</a>', $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('<a href="url" target="_blank" rel="noreferrer noopener">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 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('<a href="url" target="_blank" rel="noreferrer noopener">Name</a> – Slogan', $this->template->getShortFooter()); | |||
} | |||
public function testgetColorPrimaryWithDefault() { | |||
$this->config | |||
->expects($this->once()) |
@@ -744,6 +744,11 @@ footer .info a { | |||
overflow: hidden; | |||
} | |||
a.legal { | |||
font-size: smaller; | |||
text-decoration: underline; | |||
} | |||
/* 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 { |