Skip to content

Commit

Permalink
Profile frontend
Browse files Browse the repository at this point in the history
Signed-off-by: Christopher Ng <chrng8@gmail.com>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
  • Loading branch information
Pytal authored and skjnldsv committed Oct 18, 2021
1 parent 7787682 commit 727250a
Show file tree
Hide file tree
Showing 62 changed files with 3,553 additions and 340 deletions.
16 changes: 11 additions & 5 deletions apps/settings/css/settings.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,20 @@ input {
#personal-settings-avatar-container {
display: inline-grid;
grid-template-columns: 1fr;
grid-template-rows: 2fr 1fr;
grid-template-rows: 2fr 1fr 2fr;
vertical-align: top;
}

.profile-settings-container {
display: inline-grid;
grid-template-columns: 1fr;
grid-template-rows: 1fr 2fr 1fr;
grid-template-rows: 1fr 1fr 1fr 2fr;

#locale {
h3 {
height: 32px;
}
}
}

.personal-show-container {
Expand Down Expand Up @@ -217,7 +223,7 @@ select {

.personal-settings-container {
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}

.profile-settings-container {
Expand All @@ -239,7 +245,7 @@ select {

.personal-settings-container {
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr 1fr;
}

.profile-settings-container {
Expand Down Expand Up @@ -273,7 +279,7 @@ select {
.personal-settings-container {
display: inline-grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr 2fr;
grid-template-rows: 1fr 1fr 1fr 1fr 1fr;

&:after {
clear: both;
Expand Down
4 changes: 2 additions & 2 deletions apps/settings/js/vue-settings-apps.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/settings/js/vue-settings-apps.js.map

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions apps/settings/js/vue-settings-users.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/settings/js/vue-settings-users.js.map

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions apps/settings/js/vue-vendors-settings-apps-settings-users.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions apps/settings/js/vue-vendors-settings-apps.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/settings/js/vue-vendors-settings-apps.js.map

Large diffs are not rendered by default.

52 changes: 26 additions & 26 deletions apps/settings/js/vue-vendors-settings-users.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion apps/settings/js/vue-vendors-settings-users.js.map

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<!--
- @copyright 2021, Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- 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>
<div class="biography">
<textarea
id="biography"
:placeholder="t('settings', 'Your biography')"
:value="biography"
rows="8"
autocapitalize="none"
autocomplete="off"
autocorrect="off"
@input="onBiographyChange" />

<div class="biography__actions-container">
<transition name="fade">
<span v-if="showCheckmarkIcon" class="icon-checkmark" />
<span v-else-if="showErrorIcon" class="icon-error" />
</transition>
</div>
</div>
</template>

<script>
import { showError } from '@nextcloud/dialogs'
import { emit } from '@nextcloud/event-bus'
import debounce from 'debounce'

import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'

export default {
name: 'Biography',

props: {
biography: {
type: String,
required: true,
},
scope: {
type: String,
required: true,
},
},

data() {
return {
initialBiography: this.biography,
localScope: this.scope,
showCheckmarkIcon: false,
showErrorIcon: false,
}
},

methods: {
onBiographyChange(e) {
this.$emit('update:biography', e.target.value)
this.debounceBiographyChange(e.target.value.trim())
},

debounceBiographyChange: debounce(async function(biography) {
await this.updatePrimaryBiography(biography)
}, 500),

async updatePrimaryBiography(biography) {
try {
const responseData = await savePrimaryAccountProperty(ACCOUNT_PROPERTY_ENUM.BIOGRAPHY, biography)
this.handleResponse({
biography,
status: responseData.ocs?.meta?.status,
})
} catch (e) {
this.handleResponse({
errorMessage: t('settings', 'Unable to update biography'),
error: e,
})
}
},

handleResponse({ biography, status, errorMessage, error }) {
if (status === 'ok') {
// Ensure that local state reflects server state
this.initialBiography = biography
emit('settings:biography:updated', biography)
this.showCheckmarkIcon = true
setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
} else {
showError(errorMessage)
this.logger.error(errorMessage, error)
this.showErrorIcon = true
setTimeout(() => { this.showErrorIcon = false }, 2000)
}
},

onScopeChange(scope) {
this.$emit('update:scope', scope)
},
},
}
</script>

<style lang="scss" scoped>
.biography {
display: grid;
align-items: center;

textarea {
resize: none;
grid-area: 1 / 1;
width: 100%;
margin: 3px 3px 3px 0;
padding: 7px 6px;
color: var(--color-main-text);
border: 1px solid var(--color-border-dark);
border-radius: var(--border-radius);
background-color: var(--color-main-background);
font-family: var(--font-face);
cursor: text;

&:hover {
border-color: var(--color-primary-element) !important;
outline: none !important;
}
}

.biography__actions-container {
grid-area: 1 / 1;
justify-self: flex-end;
align-self: flex-end;
height: 30px;

display: flex;
gap: 0 2px;
margin-right: 5px;
margin-bottom: 5px;

.icon-checkmark,
.icon-error {
height: 30px !important;
min-height: 30px !important;
width: 30px !important;
min-width: 30px !important;
top: 0;
right: 0;
float: none;
}
}
}

.fade-enter,
.fade-leave-to {
opacity: 0;
}

.fade-enter-active {
transition: opacity 200ms ease-out;
}

.fade-leave-active {
transition: opacity 300ms ease-out;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<!--
- @copyright 2021, Christopher Ng <chrng8@gmail.com>
-
- @author Christopher Ng <chrng8@gmail.com>
-
- @license GNU AGPL version 3 or any later version
-
- 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>
<section>
<HeaderBar
:account-property="accountProperty"
label-for="biography"
:scope.sync="primaryBiography.scope" />

<Biography
:biography.sync="primaryBiography.value"
:scope.sync="primaryBiography.scope" />

<VisibilityDropdown
:param-id="accountPropertyId"
:display-id="accountProperty"
:visibility.sync="visibility" />
</section>
</template>

<script>
import { loadState } from '@nextcloud/initial-state'

import Biography from './Biography'
import HeaderBar from '../shared/HeaderBar'
import VisibilityDropdown from '../shared/VisibilityDropdown'

import { ACCOUNT_PROPERTY_ENUM, ACCOUNT_PROPERTY_READABLE_ENUM } from '../../../constants/AccountPropertyConstants'

const { biographyMap: { primaryBiography } } = loadState('settings', 'personalInfoParameters', {})
const { profileConfig: { biography: { visibility } } } = loadState('settings', 'profileParameters', {})

export default {
name: 'BiographySection',

components: {
Biography,
HeaderBar,
VisibilityDropdown,
},

data() {
return {
accountProperty: ACCOUNT_PROPERTY_READABLE_ENUM.BIOGRAPHY,
accountPropertyId: ACCOUNT_PROPERTY_ENUM.BIOGRAPHY,
primaryBiography,
visibility,
}
},
}
</script>

<style lang="scss" scoped>
section {
padding: 10px 10px;

&::v-deep button:disabled {
cursor: default;
}
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,19 @@
-
- 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>
<div class="displayname">
<input
id="displayname"
ref="displayName"
type="text"
name="displayname"
:placeholder="t('settings', 'Your full name')"
:value="displayName"
autocapitalize="none"
autocomplete="on"
autocorrect="off"
required
@input="onDisplayNameChange">

<div class="displayname__actions-container">
Expand All @@ -45,10 +43,12 @@

<script>
import { showError } from '@nextcloud/dialogs'
import { emit } from '@nextcloud/event-bus'
import debounce from 'debounce'

import { savePrimaryDisplayName } from '../../../service/PersonalInfo/DisplayNameService'
import { validateDisplayName } from '../../../utils/validate'
import { ACCOUNT_PROPERTY_ENUM } from '../../../constants/AccountPropertyConstants'
import { savePrimaryAccountProperty } from '../../../service/PersonalInfo/PersonalInfoService'
import { validateStringInput } from '../../../utils/validate'

// TODO Global avatar updating on events (e.g. updating the displayname) is currently being handled by global js, investigate using https://github.com/nextcloud/nextcloud-event-bus for global avatar updating

Expand Down Expand Up @@ -82,21 +82,21 @@ export default {
},

debounceDisplayNameChange: debounce(async function(displayName) {
if (validateDisplayName(displayName)) {
if (validateStringInput(displayName)) {
await this.updatePrimaryDisplayName(displayName)
}
}, 500),

async updatePrimaryDisplayName(displayName) {
try {
const responseData = await savePrimaryDisplayName(displayName)
const responseData = await savePrimaryAccountProperty(ACCOUNT_PROPERTY_ENUM.DISPLAYNAME, displayName)
this.handleResponse({
displayName,
status: responseData.ocs?.meta?.status,
})
} catch (e) {
this.handleResponse({
errorMessage: 'Unable to update full name',
errorMessage: t('settings', 'Unable to update full name'),
error: e,
})
}
Expand All @@ -106,10 +106,11 @@ export default {
if (status === 'ok') {
// Ensure that local state reflects server state
this.initialDisplayName = displayName
emit('settings:display-name:updated', displayName)
this.showCheckmarkIcon = true
setTimeout(() => { this.showCheckmarkIcon = false }, 2000)
} else {
showError(t('settings', errorMessage))
showError(errorMessage)
this.logger.error(errorMessage, error)
this.showErrorIcon = true
setTimeout(() => { this.showErrorIcon = false }, 2000)
Expand Down
Loading

0 comments on commit 727250a

Please sign in to comment.