@@ -132,7 +132,8 @@ | |||
field === 'email' || | |||
field === 'displayname' || | |||
field === 'twitter' || | |||
field === 'address' | |||
field === 'address' || | |||
field === 'website' | |||
) { | |||
return; | |||
} |
@@ -149,9 +149,6 @@ class PersonalInfo implements ISettings { | |||
'avatarScope' => $account->getProperty(IAccountManager::PROPERTY_AVATAR)->getScope(), | |||
'phone' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getValue(), | |||
'phoneScope' => $account->getProperty(IAccountManager::PROPERTY_PHONE)->getScope(), | |||
'website' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getValue(), | |||
'websiteScope' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getScope(), | |||
'websiteVerification' => $account->getProperty(IAccountManager::PROPERTY_WEBSITE)->getVerified(), | |||
'groups' => $this->getGroups($user), | |||
'isFairUseOfFreePushService' => $this->isFairUseOfFreePushService(), | |||
'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), | |||
@@ -162,6 +159,7 @@ class PersonalInfo implements ISettings { | |||
'displayName' => $this->getProperty($account, IAccountManager::PROPERTY_DISPLAYNAME), | |||
'emailMap' => $this->getEmailMap($account), | |||
'location' => $this->getProperty($account, IAccountManager::PROPERTY_ADDRESS), | |||
'website' => $this->getProperty($account, IAccountManager::PROPERTY_WEBSITE), | |||
'twitter' => $this->getProperty($account, IAccountManager::PROPERTY_TWITTER), | |||
'languageMap' => $this->getLanguageMap($user), | |||
'profileEnabledGlobally' => $this->profileManager->isProfileEnabled(), |
@@ -0,0 +1,59 @@ | |||
<!-- | |||
- @copyright 2022 Christopher Ng <chrng8@gmail.com> | |||
- | |||
- @author Christopher Ng <chrng8@gmail.com> | |||
- | |||
- @license AGPL-3.0-or-later | |||
- | |||
- This program is free software: you can redistribute it and/or modify | |||
- it under the terms of the GNU Affero General Public License as | |||
- published by the Free Software Foundation, either version 3 of the | |||
- License, or (at your option) any later version. | |||
- | |||
- This program is distributed in the hope that it will be useful, | |||
- but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
- GNU Affero General Public License for more details. | |||
- | |||
- You should have received a copy of the GNU Affero General Public License | |||
- along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
- | |||
--> | |||
<template> | |||
<AccountPropertySection v-bind.sync="website" | |||
:placeholder="t('settings', 'Your website')" | |||
type="url" | |||
:on-validate="onValidate" /> | |||
</template> | |||
<script> | |||
import { loadState } from '@nextcloud/initial-state' | |||
import AccountPropertySection from './shared/AccountPropertySection.vue' | |||
import { NAME_READABLE_ENUM } from '../../constants/AccountPropertyConstants.js' | |||
import { validateUrl } from '../../utils/validate.js' | |||
const { website } = loadState('settings', 'personalInfoParameters', {}) | |||
export default { | |||
name: 'WebsiteSection', | |||
components: { | |||
AccountPropertySection, | |||
}, | |||
data() { | |||
return { | |||
website: { ...website, readable: NAME_READABLE_ENUM[website.name] }, | |||
} | |||
}, | |||
methods: { | |||
onValidate(value) { | |||
return validateUrl(value) | |||
}, | |||
}, | |||
} | |||
</script> |
@@ -29,6 +29,7 @@ import '@nextcloud/dialogs/styles/toast.scss' | |||
import DisplayNameSection from './components/PersonalInfo/DisplayNameSection.vue' | |||
import EmailSection from './components/PersonalInfo/EmailSection/EmailSection.vue' | |||
import LocationSection from './components/PersonalInfo/LocationSection.vue' | |||
import WebsiteSection from './components/PersonalInfo/WebsiteSection.vue' | |||
import TwitterSection from './components/PersonalInfo/TwitterSection.vue' | |||
import LanguageSection from './components/PersonalInfo/LanguageSection/LanguageSection.vue' | |||
import ProfileSection from './components/PersonalInfo/ProfileSection/ProfileSection.vue' | |||
@@ -51,12 +52,14 @@ Vue.mixin({ | |||
const DisplayNameView = Vue.extend(DisplayNameSection) | |||
const EmailView = Vue.extend(EmailSection) | |||
const LocationView = Vue.extend(LocationSection) | |||
const WebsiteView = Vue.extend(WebsiteSection) | |||
const TwitterView = Vue.extend(TwitterSection) | |||
const LanguageView = Vue.extend(LanguageSection) | |||
new DisplayNameView().$mount('#vue-displayname-section') | |||
new EmailView().$mount('#vue-email-section') | |||
new LocationView().$mount('#vue-location-section') | |||
new WebsiteView().$mount('#vue-website-section') | |||
new TwitterView().$mount('#vue-twitter-section') | |||
new LanguageView().$mount('#vue-language-section') | |||
@@ -26,7 +26,7 @@ | |||
* TODO add nice validation errors for Profile page settings modal | |||
*/ | |||
import { VALIDATE_EMAIL_REGEX } from '../constants/AccountPropertyConstants' | |||
import { VALIDATE_EMAIL_REGEX } from '../constants/AccountPropertyConstants.js' | |||
/** | |||
* Validate the email input | |||
@@ -46,6 +46,22 @@ export function validateEmail(input) { | |||
&& encodeURIComponent(input).replace(/%../g, 'x').length <= 320 | |||
} | |||
/** | |||
* Validate the URL input | |||
* | |||
* @param {string} input the input | |||
* @return {boolean} | |||
*/ | |||
export function validateUrl(input) { | |||
try { | |||
// eslint-disable-next-line no-new | |||
new URL(input) | |||
return true | |||
} catch (e) { | |||
return false | |||
} | |||
} | |||
/** | |||
* Validate the language input | |||
* |
@@ -139,48 +139,7 @@ script('settings', [ | |||
<div id="vue-location-section"></div> | |||
</div> | |||
<div class="personal-settings-setting-box"> | |||
<form id="websiteform" class="section"> | |||
<h3> | |||
<label for="website"><?php p($l->t('Website')); ?></label> | |||
<a href="#" class="federation-menu" aria-label="<?php p($l->t('Change privacy level of website')); ?>"> | |||
<span class="icon-federation-menu icon-password"> | |||
<span class="icon-triangle-s"></span> | |||
</span> | |||
</a> | |||
</h3> | |||
<?php if ($_['lookupServerUploadEnabled']) { ?> | |||
<div class="verify <?php if ($_['website'] === '' || $_['websiteScope'] !== 'public') { | |||
p('hidden'); | |||
} ?>"> | |||
<img id="verify-website" title="<?php p($_['websiteMessage']); ?>" data-status="<?php p($_['websiteVerification']) ?>" src=" | |||
<?php | |||
switch ($_['websiteVerification']) { | |||
case \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS: | |||
p(image_path('core', 'actions/verifying.svg')); | |||
break; | |||
case \OC\Accounts\AccountManager::VERIFIED: | |||
p(image_path('core', 'actions/verified.svg')); | |||
break; | |||
default: | |||
p(image_path('core', 'actions/verify.svg')); | |||
} | |||
?>" <?php if ($_['websiteVerification'] === \OC\Accounts\AccountManager::VERIFICATION_IN_PROGRESS || $_['websiteVerification'] === \OC\Accounts\AccountManager::NOT_VERIFIED) { | |||
print_unescaped(' class="verify-action"'); | |||
} ?>> | |||
<div class="verification-dialog popovermenu bubble menu"> | |||
<div class="verification-dialog-content"> | |||
<p class="explainVerification"></p> | |||
<p class="verificationCode"></p> | |||
<p><?php p($l->t('It can take up to 24 hours before the account is displayed as verified.')); ?></p> | |||
</div> | |||
</div> | |||
</div> | |||
<?php } ?> | |||
<input type="url" name="website" id="website" value="<?php p($_['website']); ?>" placeholder="<?php p($l->t('Link https://…')); ?>" autocomplete="on" autocapitalize="none" autocorrect="off" /> | |||
<span class="icon-checkmark hidden"></span> | |||
<span class="icon-error hidden"></span> | |||
<input type="hidden" id="websitescope" value="<?php p($_['websiteScope']) ?>"> | |||
</form> | |||
<div id="vue-website-section"></div> | |||
</div> | |||
<div class="personal-settings-setting-box"> | |||
<div id="vue-twitter-section"></div> |