Procházet zdrojové kódy

Merge branch 'develop' of https://github.com/frappe/frappe into report-fix

version-14
scmmishra před 6 roky
rodič
revize
950934ddda
10 změnil soubory, kde provedl 245 přidání a 156 odebrání
  1. +11
    -1
      frappe/core/doctype/user/user.py
  2. +0
    -4
      frappe/public/js/frappe/social/Home.vue
  3. +25
    -22
      frappe/public/js/frappe/social/components/EnergyPointHistory.vue
  4. +9
    -16
      frappe/public/js/frappe/social/components/ProfileBanner.vue
  5. +93
    -29
      frappe/public/js/frappe/social/components/ProfileSidebar.vue
  6. +90
    -52
      frappe/public/js/frappe/social/pages/UserList.vue
  7. +0
    -27
      frappe/public/js/frappe/social/social_home.js
  8. +4
    -4
      frappe/public/js/frappe/ui/page.html
  9. +1
    -1
      frappe/public/js/frappe/ui/page.js
  10. +12
    -0
      frappe/public/less/desk.less

+ 11
- 1
frappe/core/doctype/user/user.py Zobrazit soubor

@@ -12,6 +12,8 @@ from frappe.utils.user import get_system_managers
import frappe.permissions
import frappe.share
import re
import json

from frappe.limits import get_limits
from frappe.website.utils import is_signup_enabled
from frappe.utils.background_jobs import enqueue
@@ -1086,4 +1088,12 @@ def generate_keys(user):
user_details.save()

return {"api_secret": api_secret}
frappe.throw(frappe._("Not Permitted"), frappe.PermissionError)
frappe.throw(frappe._("Not Permitted"), frappe.PermissionError)

@frappe.whitelist()
def update_profile_info(profile_info):
profile_info = json.loads(profile_info)
user = frappe.get_doc('User', frappe.session.user)
user.update(profile_info)
user.save()
return user

+ 0
- 4
frappe/public/js/frappe/social/Home.vue Zobrazit soubor

@@ -60,10 +60,6 @@ export default {
this.show_preview = false;
})

frappe.app_updates.on('user_image_updated', () => {
this.$root.$emit('user_image_updated')
})

this.update_primary_action(frappe.get_route()[1])
},
mounted() {


+ 25
- 22
frappe/public/js/frappe/social/components/EnergyPointHistory.vue Zobrazit soubor

@@ -22,13 +22,13 @@
</template>
<script>
export default {
props: ['user'],
props: ['user', 'from_date'],
data() {
return {
history_logs: [],
fetching: false,
has_more_logs: true
}
};
},
created() {
this.get_logs();
@@ -37,34 +37,37 @@ export default {
get_logs() {
this.fetching = true;
const pull_limit = 10;
frappe.db.get_list('Energy Point Log', {
filters: {
user: this.user,
type: ['!=', 'Review']
},
fields: ['*'],
limit: pull_limit,
limit_start: this.history_logs.length
}).then(data => {
this.history_logs = this.history_logs.concat(data);
this.has_more_logs = data.length === pull_limit;
}).finally(() => {
this.fetching = false;
})
frappe.db
.get_list('Energy Point Log', {
filters: {
user: this.user,
type: ['!=', 'Review'],
creation: ['>=', this.from_date]
},
fields: ['*'],
limit: pull_limit,
limit_start: this.history_logs.length
})
.then(data => {
this.history_logs = this.history_logs.concat(data);
this.has_more_logs = data.length === pull_limit;
})
.finally(() => {
this.fetching = false;
});
}
},

}
}
};
</script>
<style lang="less">
@import "frappe/public/less/common";
@import 'frappe/public/less/common';
.log-list {
padding: 15px;
padding-left: 0px;
position: relative;
}
.log-list:before {
content: " ";
content: ' ';
border-left: 1px solid @border-color;
position: absolute;
top: 0px;
@@ -82,7 +85,7 @@ export default {
position: relative;
}
.history-log:before {
content: " ";
content: ' ';
width: 7px;
height: 7px;
background-color: @border-color;


+ 9
- 16
frappe/public/js/frappe/social/components/ProfileBanner.vue Zobrazit soubor

@@ -2,8 +2,6 @@
<div ref="banner" class="banner" :style="background_style">
<div
class="user-avatar container"
:class="{'editable-image': is_own_profile}"
@click="update_image"
v-html="user_avatar">
</div>
</div>
@@ -13,29 +11,23 @@ export default {
props: ['user_id'],
data() {
return {
is_own_profile: this.user_id === frappe.session.user,
user_avatar: frappe.avatar(this.user_id, 'avatar-xl'),
background_style: {
'background': '#262626'
}
user_banner: frappe.user_info(this.user_id).banner_image
}
},
created() {
this.$root.$on('user_image_updated', () => {
this.user_avatar = frappe.avatar(this.user_id, 'avatar-xl')
this.user_banner = frappe.user_info(this.user_id).banner_image
})
const user_banner = frappe.user_info(this.user_id).banner_image;
if (user_banner) {
this.background_style = {
'background-image': `url('${user_banner}')`
}
}
},
methods: {
update_image() {
if (this.is_own_profile) {
frappe.social.update_user_image.show()
computed: {
background_style() {
const style = {}
if (this.user_banner) {
style['background-image'] = `url('${this.user_banner}')`
}
return style;
}
},
}
@@ -51,6 +43,7 @@ export default {
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-color: '#262626';
.user-avatar {
position: relative;
/deep/ .avatar {


+ 93
- 29
frappe/public/js/frappe/social/components/ProfileSidebar.vue Zobrazit soubor

@@ -4,62 +4,126 @@
<h3>{{ user.fullname }}</h3>
<p>{{ user.bio }}</p>
<div class="location" v-if="user.location">
<span class="text-muted"><i class="fa fa-map-marker">&nbsp;</i>{{ user.location }}</span>
<span class="text-muted">
<i class="fa fa-map-marker">&nbsp;</i>
{{ user.location }}
</span>
</div>
<div class="interest" v-if="user.interest">
<span class="text-muted"><i class="fa fa-puzzle-piece">&nbsp;</i>{{ user.interest }}</span>
<span class="text-muted">
<i class="fa fa-puzzle-piece">&nbsp;</i>
{{ user.interest }}
</span>
</div>
<a v-if="show_add_info_link" @click="go_to_user_settings">{{ __('Add your information') }}</a>
</div>
<a class="home-link" @click="go_to_home()"> ← {{ __('Back To Home') }}</a>
<a
class="edit-profile-link"
v-if="can_edit_profile"
@click="edit_profile()"
>{{ __('Edit Profile') }}</a>
</div>
</template>
<script>
export default {
props: {
'user_id': String,
user_id: String
},
data() {
return {
'user': frappe.user_info(this.user_id),
'show_add_info_link': false
}
},
created() {
if (frappe.social.is_session_user_page() && this.is_info_missing()) {
this.show_add_info_link = true;
}
user: frappe.user_info(this.user_id),
can_edit_profile: frappe.social.is_session_user_page()
};
},
methods: {
is_info_missing() {
return !this.user.location || !this.user.interest || !this.user.bio;
},
go_to_home() {
frappe.set_route('social', 'home');
},
go_to_user_settings() {
frappe.set_route('Form', 'User', this.user_id).then(()=> {
frappe.dom.scroll_to_section('More Information');
})
edit_profile() {
const edit_profile_dialog = new frappe.ui.Dialog({
title: __('Edit Profile'),
fields: [
{
fieldtype: 'Attach Image',
fieldname: 'user_image',
label: 'Profile Image',
reqd: 1
},
{
fieldtype: 'Data',
fieldname: 'interest',
label: 'Interests',
reqd: 1
},
{
fieldtype: 'Column Break'
},
{
fieldtype: 'Attach Image',
fieldname: 'banner_image',
label: 'Banner Image',
reqd: 1
},
{
fieldtype: 'Data',
fieldname: 'location',
label: 'Location',
reqd: 1
},
{
fieldtype: 'Section Break',
fieldname: 'Interest'
},
{
fieldtype: 'Small Text',
fieldname: 'bio',
label: 'Bio',
reqd: 1
}
],
primary_action: values => {
edit_profile_dialog.disable_primary_action();
frappe
.xcall('frappe.core.doctype.user.user.update_profile_info', {
profile_info: values
})
.then(user => {
user.image = user.user_image;
let user_info = frappe.user_info(this.user_id);
this.user = Object.assign(user_info, user);
this.$root.$emit('user_image_updated');
edit_profile_dialog.hide();
})
.finally(() => {
edit_profile_dialog.enable_primary_action();
});
},
primary_action_label: __('Save')
});
edit_profile_dialog.set_values({
user_image: this.user.image,
banner_image: this.user.banner_image,
location: this.user.location,
interest: this.user.interest,
bio: this.user.bio
});
edit_profile_dialog.show();
}
}
}
};
</script>

<style lang="less" scoped>
.profile-sidebar {
padding: 10px 10px 0 0
padding: 10px 10px 0 0;
}
.user-details {
min-height: 150px;
.location, .interest {
.location,
.interest {
margin-bottom: 10px;
i {
width: 15px;
}
}
.home-link {
margin-top: 15px;
}
}
.edit-profile-link {
margin-top: 15px;
}
</style>

+ 90
- 52
frappe/public/js/frappe/social/pages/UserList.vue Zobrazit soubor

@@ -3,47 +3,53 @@
<ul class="list-unstyled user-list">
<li class="user-card user-list-header text-medium">
<span class="user-details text-muted">
{{ __('User') }}
<input
class="form-control"
type="search"
placeholder="Search User"
v-model="filter_users_by"
>
</span>
<span class="user-points text-muted">
{{ __('Energy Points') }}
</span>
<span class="user-points text-muted">
{{ __('Review Points') }}
</span>
<span class="user-points text-muted">
{{ __('Points Given') }}
<span class="flex-40"></span>
<span class="flex-20 text-muted">
<select class="form-control" data-toggle="tooltip" title="Period" v-model="period">
<option v-for="value in period_options" :key="value" :value="value">{{ value }}</option>
</select>
</span>
</li>
<li
v-for="user in filtered_users"
:key="user.name">
<li class="user-card user-list-header text-medium">
<span class="user-details text-muted">{{ __('User') }}</span>
<span
class="flex-20 text-muted"
v-for="title in ['Energy Points', 'Review Points', 'Points Given']"
:key="title"
>{{ __(title) }}</span>
</li>
<li v-for="user in filtered_users" :key="user.name">
<div class="user-card" @click="toggle_log(user.name)">
<div class="user-details flex">
<span class="user-details flex">
<span v-html="get_avatar(user.name)"></span>
<span>
<a @click="go_to_profile_page(user.name)">{{ user.fullname }}</a>
<div class="text-muted text-medium" :class="{'italic': !user.bio}">
{{ frappe.ellipsis(user.bio, 100) || 'No Bio'}}
</div>
<div
class="text-muted text-medium"
:class="{'italic': !user.bio}"
>{{ frappe.ellipsis(user.bio, 100) || 'No Bio'}}</div>
</span>
</div>
<span class="text-muted text-nowrap user-points">
{{ user.energy_points }}
</span>
<span class="text-muted text-nowrap user-points">
{{ user.review_points }}
</span>
<span class="text-muted text-nowrap user-points">
{{ user.given_points }}
</span>
<span
class="text-muted text-nowrap flex-20"
v-for="key in ['energy_points', 'review_points', 'given_points']"
:key="key"
>{{ user[key] }}</span>
</div>
<energy-point-history
v-show="show_log_for===user.name"
class="energy-point-history"
:user="user.name"
:key="user.name + user.energy_points">
</energy-point-history>
:from_date="from_date"
:key="user.name + user.energy_points"
></energy-point-history>
</li>
<li class="user-card text-muted" v-if="!filtered_users.length">{{__('No user found')}}</li>
</ul>
@@ -61,17 +67,33 @@ export default {
filter_users_by: null,
sort_users_by: 'energy_points',
sort_order: 'desc',
show_log_for: null
}
show_log_for: null,
period_options: ['Lifetime', 'Last Month', 'Last Week', 'Today'],
period: 'Lifetime'
};
},
computed: {
from_date() {
const days_to_deduct = {
'Last Week': 7,
'Last Month': 30
};
if (this.period === 'Lifetime') {
return null;
}
if (this.period === 'Today') {
return frappe.datetime.get_today();
}
return frappe.datetime.add_days(moment(), -days_to_deduct[this.period]);
},
filtered_users() {
let filtered = this.users.slice();

if (this.filter_users_by) {
filtered = filtered.filter(user =>
user.fullname.toLowerCase().includes(this.filter_users_by.toLowerCase())
)
user.fullname
.toLowerCase()
.includes(this.filter_users_by.toLowerCase())
);
}

if (this.sort_users_by) {
@@ -89,15 +111,23 @@ export default {
}

if (this.sort_order === 'desc') {
return_value = -return_value
return_value = -return_value;
}

return return_value
return return_value;
});
}
return filtered;
}
},
watch: {
period() {
this.fetch_users_energy_points_and_update_users();
}
},
mounted() {
$('[data-toggle="tooltip"]').tooltip();
},
created() {
const standard_users = ['Administrator', 'Guest', 'guest@example.com'];
this.users = frappe.boot.user_info;
@@ -111,37 +141,42 @@ export default {
},
methods: {
get_avatar(user) {
return frappe.avatar(user, 'avatar-medium')
return frappe.avatar(user, 'avatar-medium');
},
go_to_profile_page(user) {
frappe.set_route('social', 'profile', user)
frappe.set_route('social', 'profile', user);
},
fetch_users_energy_points_and_update_users() {
frappe.xcall(
'frappe.social.doctype.energy_point_log.energy_point_log.get_user_energy_and_review_points'
).then(data => {
let users = this.users.slice();
this.users = users.map(user => {
const points = data[user.name] || {};
user.energy_points = points.energy_points || 0;
user.review_points = points.review_points || 0;
user.given_points = points.given_points || 0;
return user;
frappe
.xcall(
'frappe.social.doctype.energy_point_log.energy_point_log.get_user_energy_and_review_points',
{
from_date: this.from_date
}
)
.then(data => {
let users = this.users.slice();
this.users = users.map(user => {
const points = data[user.name] || {};
user.energy_points = points.energy_points || 0;
user.review_points = points.review_points || 0;
user.given_points = points.given_points || 0;
return user;
});
});
});
},
toggle_log(user) {
if (this.show_log_for === user) {
this.show_log_for = null
this.show_log_for = null;
} else {
this.show_log_for = user
this.show_log_for = user;
}
}
}
}
};
</script>
<style lang="less" scoped>
@import "frappe/public/less/variables";
@import 'frappe/public/less/variables';
.user-list {
border-left: 1px solid @border-color;
border-right: 1px solid @border-color;
@@ -158,11 +193,14 @@ export default {
}
}
}
.user-points {
.flex-20 {
flex: 0 0 20%;
text-align: right;
align-self: center;
}
.flex-40 {
flex: 0 0 40%;
}
.user-list-header {
background-color: @light-bg;
}


+ 0
- 27
frappe/public/js/frappe/social/social_home.js Zobrazit soubor

@@ -48,33 +48,6 @@ frappe.social.post_dialog = new frappe.ui.Dialog({
}
});

frappe.social.update_user_image = new frappe.ui.Dialog({
title: __("User Image"),
fields: [
{
fieldtype: "Attach Image",
fieldname: "image",
label: __("Image"),
reqd: 1,
default: frappe.user.image()
},
],
primary_action_label: __('Set Image'),
primary_action: (values) => {
const user = frappe.session.user;
frappe.db.set_value('User', user, 'user_image', values.image)
.then((resp) => {
frappe.boot.user_info[user].image = resp.message.user_image;
frappe.app_updates.trigger('user_image_updated');
frappe.social.update_user_image.clear();
frappe.social.update_user_image.hide();
})
.fail((err) => {
frappe.msgprint(err);
});
}
});

frappe.social.is_home_page = () => {
return frappe.get_route()[0] === 'social' && frappe.get_route()[1] === 'home';
};


+ 4
- 4
frappe/public/js/frappe/ui/page.html Zobrazit soubor

@@ -1,13 +1,13 @@
<div class="page-head">
<div class="page-head flex align-center">
<div class="container">
<div class="row">
<div class="row flex align-center">
<div class="col-md-7 col-sm-8 col-xs-6 page-title">
<!-- title -->
<h1>
<h1 class="flex" style="margin: auto;">
<div class="title-image hide hidden-md hidden-lg">
</div>
<div class="ellipsis title-text"></div>
<span class="indicator hide"></span>
<span class="indicator whitespace-nowrap hide"></span>
</h1>
</div>
<div class="text-right col-md-5 col-sm-4 col-xs-6 page-actions">


+ 1
- 1
frappe/public/js/frappe/ui/page.js Zobrazit soubor

@@ -138,7 +138,7 @@ frappe.ui.Page = Class.extend({
},

clear_indicator: function() {
return this.indicator.removeClass().addClass("indicator hide");
return this.indicator.removeClass().addClass("indicator whitespace-nowrap hide");
},

get_icon_label: function(icon, label) {


+ 12
- 0
frappe/public/less/desk.less Zobrazit soubor

@@ -1054,6 +1054,12 @@ img.img-loading:after {
content: "\f00b";
}

// utilities

.whitespace-nowrap {
white-space: nowrap;
}

// popover
.popover {
border-radius: 4px;
@@ -1070,3 +1076,9 @@ body.full-width {
}
}
}

// utilities

.whitespace-nowrap {
white-space: nowrap;
}

Načítá se…
Zrušit
Uložit