소스 검색

Merge branch 'develop' into wspace-new-design

version-14
Shariq Ansari 3 년 전
committed by GitHub
부모
커밋
3b188e92e6
No known key found for this signature in database GPG 키 ID: 4AEE18F83AFDEB23
24개의 변경된 파일445개의 추가작업 그리고 139개의 파일을 삭제
  1. +2
    -1
      frappe/core/doctype/language/language.py
  2. +4
    -3
      frappe/core/doctype/role/role.json
  3. +2
    -2
      frappe/integrations/doctype/connected_app/connected_app.json
  4. +6
    -0
      frappe/public/images/ui-states/empty-app-state.svg
  5. +3
    -1
      frappe/public/js/frappe/form/controls/markdown_editor.js
  6. +12
    -5
      frappe/public/js/frappe/request.js
  7. +0
    -2
      frappe/public/js/frappe/web_form/web_form_list.js
  8. +10
    -0
      frappe/public/scss/common/css_variables.scss
  9. +0
    -9
      frappe/public/scss/desk/css_variables.scss
  10. +3
    -1
      frappe/public/scss/login.bundle.scss
  11. +2
    -0
      frappe/public/scss/website/footer.scss
  12. +16
    -0
      frappe/public/scss/website/index.scss
  13. +116
    -0
      frappe/public/scss/website/my_account.scss
  14. +47
    -0
      frappe/public/scss/website/web_form.scss
  15. +8
    -3
      frappe/sessions.py
  16. +3
    -2
      frappe/templates/includes/list/list.html
  17. +49
    -41
      frappe/templates/styles/card_style.css
  18. +63
    -38
      frappe/tests/test_auth.py
  19. +4
    -4
      frappe/website/doctype/web_form/templates/web_form.html
  20. +1
    -1
      frappe/website/doctype/web_form/test_web_form.py
  21. +4
    -6
      frappe/www/list.html
  22. +80
    -17
      frappe/www/me.html
  23. +2
    -1
      frappe/www/me.py
  24. +8
    -2
      frappe/www/third_party_apps.html

+ 2
- 1
frappe/core/doctype/language/language.py 파일 보기

@@ -39,7 +39,8 @@ def sync_languages():
frappe.get_doc({
'doctype': 'Language',
'language_code': l['code'],
'language_name': l['name']
'language_name': l['name'],
'enabled': 1,
}).insert()

def update_language_names():


+ 4
- 3
frappe/core/doctype/role/role.json 파일 보기

@@ -12,6 +12,7 @@
"restrict_to_domain",
"column_break_4",
"disabled",
"is_custom",
"desk_access",
"two_factor_auth",
"navigation_settings_section",
@@ -24,8 +25,7 @@
"form_settings_section",
"form_sidebar",
"timeline",
"dashboard",
"is_custom"
"dashboard"
],
"fields": [
{
@@ -148,7 +148,7 @@
"idx": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2021-10-08 14:06:55.729364",
"modified": "2022-01-12 20:18:18.496230",
"modified_by": "Administrator",
"module": "Core",
"name": "Role",
@@ -170,5 +170,6 @@
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "ASC",
"states": [],
"track_changes": 1
}

+ 2
- 2
frappe/integrations/doctype/connected_app/connected_app.json 파일 보기

@@ -96,7 +96,7 @@
},
{
"fieldname": "authorization_uri",
"fieldtype": "Data",
"fieldtype": "Small Text",
"label": "Authorization URI",
"mandatory_depends_on": "eval:doc.redirect_uri"
},
@@ -139,7 +139,7 @@
"link_fieldname": "connected_app"
}
],
"modified": "2021-05-10 05:03:06.296863",
"modified": "2022-01-07 05:28:45.073041",
"modified_by": "Administrator",
"module": "Integrations",
"name": "Connected App",


+ 6
- 0
frappe/public/images/ui-states/empty-app-state.svg 파일 보기

@@ -0,0 +1,6 @@
<svg width="70" height="70" viewBox="0 0 70 70" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26.4844 25.3281V16.0781" stroke="#F56B6B" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M42.6719 25.3281V16.0781" stroke="#F56B6B" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M34.5781 50.7656C30.8982 50.7656 27.3691 49.3038 24.767 46.7017C22.165 44.0997 20.7031 40.5705 20.7031 36.8906V25.3281H48.4531V36.8906C48.4531 40.5705 46.9913 44.0997 44.3892 46.7017C41.7872 49.3038 38.258 50.7656 34.5781 50.7656Z" stroke="#98A1A9" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M57.7032 58.8594C63.3462 53.4851 66.9411 46.3131 67.8703 38.576C68.7994 30.8388 67.0046 23.0197 62.7944 16.4622C58.5842 9.90464 52.2215 5.01829 44.7997 2.64279C37.3778 0.267296 29.3604 0.550997 22.125 3.44515C14.8896 6.33929 8.8882 11.6632 5.15204 18.5018C1.41588 25.3405 0.178293 33.267 1.65196 40.9191C3.12562 48.5713 7.21851 55.4712 13.2273 60.4332C19.236 65.3952 26.7855 68.1094 34.5782 68.1094V56.5469" stroke="#98A1A9" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

+ 3
- 1
frappe/public/js/frappe/form/controls/markdown_editor.js 파일 보기

@@ -32,7 +32,9 @@ frappe.ui.form.ControlMarkdownEditor = class ControlMarkdownEditor extends frapp
}

set_language() {
this.df.options = 'Markdown';
if (!this.df.options) {
this.df.options = 'Markdown';
}
super.set_language();
}



+ 12
- 5
frappe/public/js/frappe/request.js 파일 보기

@@ -291,11 +291,18 @@ frappe.request.call = function(opts) {
})
.fail(function(xhr, textStatus) {
try {
if (xhr.responseText) {
var data = JSON.parse(xhr.responseText);
if (data.exception) {
// frappe.exceptions.CustomError -> CustomError
var exception = data.exception.split('.').at(-1);
if (xhr.getResponseHeader('content-type') == 'application/json' && xhr.responseText) {
var data;
try {
data = JSON.parse(xhr.responseText);
} catch (e) {
console.log("Unable to parse reponse text");
console.log(xhr.responseText);
console.log(e);
}
if (data && data.exception) {
// frappe.exceptions.CustomError: (1024, ...) -> CustomError
var exception = data.exception.split('.').at(-1).split(':').at(0);
var exception_handler = exception_handlers[exception];
if (exception_handler) {
exception_handler(data);


+ 0
- 2
frappe/public/js/frappe/web_form/web_form_list.js 파일 보기

@@ -139,8 +139,6 @@ export default class WebFormList {
make_table_head() {
// Create Heading
let thead = this.table.createTHead();
thead.style.backgroundColor = "#f7fafc";
thead.style.color = "#8d99a6";
let row = thead.insertRow();

let th = document.createElement("th");


+ 10
- 0
frappe/public/scss/common/css_variables.scss 파일 보기

@@ -165,6 +165,16 @@
--bg-pink: var(--pink-50);
--bg-cyan: var(--cyan-50);

//font sizes
--text-xs: 11px;
--text-sm: 12px;
--text-md: 13px;
--text-base: 14px;
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 20px;
--text-3xl: 22px;

--text-on-blue: var(--blue-600);
--text-on-light-blue: var(--blue-500);
--text-on-dark-blue: var(--blue-700);


+ 0
- 9
frappe/public/scss/desk/css_variables.scss 파일 보기

@@ -4,15 +4,6 @@ $input-height: 28px !default;

:root,
[data-theme="light"] {
--text-xs: 11px;
--text-sm: 12px;
--text-md: 13px;
--text-base: 14px;
--text-lg: 16px;
--text-xl: 18px;
--text-2xl: 20px;
--text-3xl: 22px;

// breakpoints
--xxl-width: map-get($grid-breakpoints, '2xl');
--xl-width: map-get($grid-breakpoints, 'xl');


+ 3
- 1
frappe/public/scss/login.bundle.scss 파일 보기

@@ -1,7 +1,9 @@
@import "./desk/variables";

body {
background-color: var(--bg-light-gray);
@include media-breakpoint-up(sm) {
background-color: var(--bg-light-gray);
}
}

.for-forgot,


+ 2
- 0
frappe/public/scss/website/footer.scss 파일 보기

@@ -94,6 +94,8 @@
max-width: 300px;
border: 1px solid var(--dark-border-color);
box-shadow: none;
border-radius: var(--border-radius);
font-size: $font-size-sm;
}
}
}

+ 16
- 0
frappe/public/scss/website/index.scss 파일 보기

@@ -27,6 +27,14 @@
@import 'navbar';
@import 'footer';
@import 'error-state';
@import 'my_account';


body {
@include media-breakpoint-up(sm) {
background-color: var(--bg-color);
}
}

.ql-editor.read-mode {
padding: 0;
@@ -166,6 +174,10 @@ a.card {
font-size: inherit;
}

.indicator-pill {
font-size: var(--font-size-xs)
}

h4.modal-title {
font-size: 1em;
}
@@ -298,3 +310,7 @@ h5.modal-title {
margin: 70px auto;
font-size: $font-size-sm;
}

.empty-list-icon {
height: 70px;
}

+ 116
- 0
frappe/public/scss/website/my_account.scss 파일 보기

@@ -0,0 +1,116 @@
//styles for my account and edit-profile page
@include media-breakpoint-up(sm) {
body[data-path="me"],
body[data-path="list"] {
background-color: var(--bg-color);
}
}

@include media-breakpoint-down(sm) {
#page-me {
.side-list {
.list-group {
display: none;
}
}
}
}

.my-account-header {
color: var(--gray-900);
margin-bottom: var(--margin-lg);
font-weight: bold;

@include media-breakpoint-down(sm) {
margin-left: -1rem;
}
}

.account-info {
background-color: var(--fg-color);
border-radius: var(--border-radius-md);
padding: var(--padding-sm) 25px;
max-width: 850px;

@include media-breakpoint-up(sm) {
margin-left: 0;
}

@include media-breakpoint-down(sm) {
padding: 0;
}

.my-account-name,
.my-account-item {
color: var(--gray-900);
font-weight: var(--text-bold);
}

.my-account-avatar {

.avatar {
height: 60px;
width: 60px;
}
}

.my-account-item-desc {
color: var(--gray-700);
font-size: var(--text-md);
}

.my-account-item-link {
font-size: var(--text-md);

a {
text-decoration: none;

.edit-profile-icon {
stroke: var(--blue-500);
}
}

.right-icon {
@include media-breakpoint-up(sm) {
display: none;
}
}

.item-link-text {
@include media-breakpoint-down(sm) {
display: none;
}
}
}

.col {
padding: var(--padding-md) 0;
border-bottom: 1px solid var(--border-color);

.form-group {
margin-right: var(--margin-lg);
}
}

:last-child {
border: 0;
}
}

//styles for third party apps page
//center wrt to outer most container and not immediate parent
.empty-apps-state {
position: relative;
padding-top: 10rem;
margin-left: -250px;
text-align: center;

@include media-breakpoint-down(sm) {
margin: auto;
padding-top: 5rem;
}

@include media-breakpoint-down(md) {
margin-left: 0;
}
}

+ 47
- 0
frappe/public/scss/website/web_form.scss 파일 보기

@@ -1,5 +1,31 @@
@import "../common/form";


[data-doctype="Web Form"] {
.page-content-wrapper {
.breadcrumb-container.container {
@include media-breakpoint-up(sm) {
padding-left: var(--padding-sm);
}
}

.container {
max-width: 800px;

&.my-4 {
background-color: var(--fg-color);

@include media-breakpoint-up(sm) {
padding: 1.8rem;
border-radius: var(--border-radius-md);
box-shadow: var(--card-shadow);
}
}
}
}
}

.web-form-wrapper {
.form-control {
color: var(--text-color);
@@ -16,6 +42,7 @@

.form-column {
padding: 0 var(--padding-md);

&:first-child {
padding-left: 0;
}
@@ -24,4 +51,24 @@
padding-right: 0;
}
}
}

.web-form-wrapper~#datatable {
.table {
thead {
th {
border: 0;
font-weight: normal;
color: var(--text-muted)
}
}

tr {
color: var(--text-color);

td {
border-top: 1px solid var(--border-color);
}
}
}
}

+ 8
- 3
frappe/sessions.py 파일 보기

@@ -68,9 +68,14 @@ def get_sessions_to_clear(user=None, keep_current=False, device=None):
session = DocType("Sessions")
session_id = frappe.qb.from_(session).where((session.user == user) & (session.device.isin(device)))
if keep_current:
session_id = session_id.where(session.sid != frappe.db.escape(frappe.session.sid))

query = session_id.select(session.sid).offset(offset).limit(100).orderby(session.lastupdate, order=Order.desc)
session_id = session_id.where(session.sid != frappe.session.sid)

query = (
session_id.select(session.sid)
.offset(offset)
.limit(100)
.orderby(session.lastupdate, order=Order.desc)
)

return query.run(pluck=True)



+ 3
- 2
frappe/templates/includes/list/list.html 파일 보기

@@ -2,8 +2,9 @@
<h4 class="text-muted">{{ sub_title }}</h4>
{% endif %}
{% if not result -%}
<div class="text-muted" style="min-height: 300px;">
{{ no_result_message or _("Nothing to show") }}
<div class="empty-apps-state">
<img class="empty-list-icon" src="/assets/frappe/images/ui-states/list-empty-state.svg"/>
<div class="mt-4">{{ no_result_message or _("Nothing to show") }}</div>
</div>
{% else %}
<div class="website-list" data-doctype="{{ doctype }}"


+ 49
- 41
frappe/templates/styles/card_style.css 파일 보기

@@ -2,79 +2,87 @@
background-color: var(--bg-color);
}

body {
background-color: var(--bg-color);
}


.page-card {
max-width: 360px;
padding: 15px;
margin: 70px auto;
border-radius: 4px;
background-color: var(--fg-color);
box-shadow: var(--shadow-base);
max-width: 360px;
padding: 15px;
margin: 70px auto;
border-radius: 4px;
background-color: var(--fg-color);
/* box-shadow: var(--shadow-base); */
}

.for-reset-password {
margin: 80px 0;
}
margin: 80px 0;
}

.for-reset-password .page-card {
border: 0;
max-width: 450px;
margin: auto;
padding: 40px 60px;
border-radius: 10px;
box-shadow: var(--shadow-base);
border: 0;
max-width: 450px;
margin: auto;
border-radius: 10px;
}

@media (min-width: 567px) {
.for-reset-password .page-card {
box-shadow: var(--shadow-base);
padding: 40px 60px;

}
}

.page-card .page-card-head {
padding: 10px 15px;
margin: -15px;
margin-bottom: 15px;
border-bottom: 1px solid var(--border-color);
padding: 10px 15px;
margin: -15px;
margin-bottom: 15px;
border-bottom: 1px solid var(--border-color);
}

.for-reset-password .page-card .page-card-head {
border-bottom: 0;
.for-reset-password .page-card .page-card-head {
border-bottom: 0;
}

.page-card-head h4 {
font-size: 18px;
font-weight: 600;
font-size: 18px;
font-weight: 600;
}

#reset-password .form-group {
margin-bottom: 10px;
font-size: var(--font-size-sm);
margin-bottom: 10px;
font-size: var(--font-size-sm);
}

.page-card .page-card-head .indicator {
color: #36414C;
font-size: 14px;
color: #36414C;
font-size: 14px;
}

.sign-up-message {
margin-top: 20px;
font-size: 13px;
color: var(--text-color);
margin-top: 20px;
font-size: 13px;
color: var(--text-color);
}

.page-card .page-card-head .indicator::before {
margin: 0 6px 0.5px 0px;
margin: 0 6px 0.5px 0px;
}

button#update {
font-size: var(--font-size-sm);
font-size: var(--font-size-sm);
}

.page-card .btn {
margin-top: 30px;
margin-top: 30px;
}

.page-card p {
font-size: 14px;
font-size: 14px;
}

.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
vertical-align: middle;
}
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
vertical-align: middle;
}

+ 63
- 38
frappe/tests/test_auth.py 파일 보기

@@ -4,38 +4,44 @@ import time
import unittest

import frappe
from frappe.auth import HTTPRequest, LoginAttemptTracker
import frappe.utils
from frappe.auth import LoginAttemptTracker
from frappe.frappeclient import FrappeClient, AuthError
from frappe.utils import set_request


def add_user(email, password, username=None, mobile_no=None):
first_name = email.split('@', 1)[0]
user = frappe.get_doc(
dict(doctype='User', email=email, first_name=first_name, username=username, mobile_no=mobile_no)
).insert()
user.new_password = password
user.add_roles("System Manager")
frappe.db.commit()


class TestAuth(unittest.TestCase):
def __init__(self, *args, **kwargs):
super(TestAuth, self).__init__(*args, **kwargs)
self.test_user_email = 'test_auth@test.com'
self.test_user_name = 'test_auth_user'
self.test_user_mobile = '+911234567890'
self.test_user_password = 'pwd_012'

def setUp(self):
self.tearDown()

self.add_user(self.test_user_email, self.test_user_password,
username=self.test_user_name, mobile_no=self.test_user_mobile)

def tearDown(self):
frappe.delete_doc('User', self.test_user_email, force=True)

def add_user(self, email, password, username=None, mobile_no=None):
first_name = email.split('@', 1)[0]
user = frappe.get_doc(
dict(doctype='User', email=email, first_name=first_name, username=username, mobile_no=mobile_no)
).insert()
user.new_password = password
user.save()
frappe.db.commit()
@classmethod
def setUpClass(cls):
cls.HOST_NAME = (
frappe.get_site_config().host_name
or frappe.utils.get_site_url(frappe.local.site)
)
cls.test_user_email = 'test_auth@test.com'
cls.test_user_name = 'test_auth_user'
cls.test_user_mobile = '+911234567890'
cls.test_user_password = 'pwd_012'

cls.tearDownClass()
add_user(email=cls.test_user_email, password=cls.test_user_password,
username=cls.test_user_name, mobile_no=cls.test_user_mobile)

@classmethod
def tearDownClass(cls):
frappe.delete_doc('User', cls.test_user_email, force=True)

def set_system_settings(self, k, v):
frappe.db.set_value("System Settings", "System Settings", k, v)
frappe.clear_cache()
frappe.db.commit()

def test_allow_login_using_mobile(self):
@@ -43,12 +49,12 @@ class TestAuth(unittest.TestCase):
self.set_system_settings('allow_login_using_user_name', 0)

# Login by both email and mobile should work
FrappeClient(frappe.get_site_config().host_name, self.test_user_mobile, self.test_user_password)
FrappeClient(frappe.get_site_config().host_name, self.test_user_email, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_mobile, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_email, self.test_user_password)

# login by username should fail
with self.assertRaises(AuthError):
FrappeClient(frappe.get_site_config().host_name, self.test_user_name, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_name, self.test_user_password)

def test_allow_login_using_only_email(self):
self.set_system_settings('allow_login_using_mobile_number', 0)
@@ -56,14 +62,14 @@ class TestAuth(unittest.TestCase):

# Login by mobile number should fail
with self.assertRaises(AuthError):
FrappeClient(frappe.get_site_config().host_name, self.test_user_mobile, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_mobile, self.test_user_password)

# login by username should fail
with self.assertRaises(AuthError):
FrappeClient(frappe.get_site_config().host_name, self.test_user_name, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_name, self.test_user_password)

# Login by email should work
FrappeClient(frappe.get_site_config().host_name, self.test_user_email, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_email, self.test_user_password)

def test_allow_login_using_username(self):
self.set_system_settings('allow_login_using_mobile_number', 0)
@@ -71,20 +77,39 @@ class TestAuth(unittest.TestCase):

# Mobile login should fail
with self.assertRaises(AuthError):
FrappeClient(frappe.get_site_config().host_name, self.test_user_mobile, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_mobile, self.test_user_password)

# Both email and username logins should work
FrappeClient(frappe.get_site_config().host_name, self.test_user_email, self.test_user_password)
FrappeClient(frappe.get_site_config().host_name, self.test_user_name, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_email, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_name, self.test_user_password)

def test_allow_login_using_username_and_mobile(self):
self.set_system_settings('allow_login_using_mobile_number', 1)
self.set_system_settings('allow_login_using_user_name', 1)

# Both email and username and mobile logins should work
FrappeClient(frappe.get_site_config().host_name, self.test_user_mobile, self.test_user_password)
FrappeClient(frappe.get_site_config().host_name, self.test_user_email, self.test_user_password)
FrappeClient(frappe.get_site_config().host_name, self.test_user_name, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_mobile, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_email, self.test_user_password)
FrappeClient(self.HOST_NAME, self.test_user_name, self.test_user_password)

def test_deny_multiple_login(self):
self.set_system_settings('deny_multiple_sessions', 1)

first_login = FrappeClient(self.HOST_NAME, self.test_user_email, self.test_user_password)
first_login.get_list("ToDo")

second_login = FrappeClient(self.HOST_NAME, self.test_user_email, self.test_user_password)
second_login.get_list("ToDo")
with self.assertRaises(Exception):
first_login.get_list("ToDo")

third_login = FrappeClient(self.HOST_NAME, self.test_user_email, self.test_user_password)
with self.assertRaises(Exception):
first_login.get_list("ToDo")
with self.assertRaises(Exception):
second_login.get_list("ToDo")
third_login.get_list("ToDo")


class TestLoginAttemptTracker(unittest.TestCase):
def test_account_lock(self):


+ 4
- 4
frappe/website/doctype/web_form/templates/web_form.html 파일 보기

@@ -3,7 +3,7 @@
{% block title %}{{ _(title) }}{% endblock %}

{% block header %}
<h2>{{ _(title) }}</h2>
<h3>{{ _(title) }}</h3>
{% endblock %}

{% block breadcrumbs %}
@@ -29,8 +29,8 @@ data-web-form="{{ name }}" data-web-form-doctype="{{ doc_type }}" data-login-req
{% if is_list %}
{# web form list #}
<div class="web-form-wrapper" {{ container_attributes() }}></div>
<div id="list-filters" class="row"></div>
<div id="datatable" class="pt-4"></div>
<div id="list-filters" class="row mt-4"></div>
<div id="datatable" class="pt-4 overflow-auto"></div>
<div class="list-view-footer text-right"></div>
{% else %}
{# web form #}
@@ -38,7 +38,7 @@ data-web-form="{{ name }}" data-web-form-doctype="{{ doc_type }}" data-login-req
<div id="introduction" class="text-muted"></div>
<hr>
<div class="web-form-wrapper" {{ container_attributes() }}></div>
<div class="web-form-footer pull-right"></div>
<div class="web-form-footer text-right"></div>
</div>

{% if show_attachments and not frappe.form_dict.new and attachments %}


+ 1
- 1
frappe/website/doctype/web_form/test_web_form.py 파일 보기

@@ -66,7 +66,7 @@ class TestWebForm(unittest.TestCase):

def test_webform_render(self):
content = get_response_content('request-data')
self.assertIn('<h2>Request Data</h2>', content)
self.assertIn('<h3>Request Data</h3>', content)
self.assertIn('data-doctype="Web Form"', content)
self.assertIn('data-path="request-data"', content)
self.assertIn('source-type="Generator"', content)

+ 4
- 6
frappe/www/list.html 파일 보기

@@ -5,7 +5,7 @@
{% endblock %}

{% block header %}
<h1>{{ title or (_("{0} List").format(_(doctype))) }}</h1>
<h3 class="my-account-header">{{ title or (_("{0} List").format(_(doctype))) }}</h3>
{% endblock %}

{% block breadcrumbs %}
@@ -23,11 +23,9 @@
{% endblock %}

{% block page_content %}

{% if introduction %}<p>{{ introduction }}</p>{% endif %}
{% include list_template or "templates/includes/list/list.html" %}
{% if list_footer %}{{ list_footer }}{% endif %}

{% if introduction %}<p>{{ introduction }}</p>{% endif %}
{% include list_template or "templates/includes/list/list.html" %}
{% if list_footer %}{{ list_footer }}{% endif %}
{% endblock %}

{% block script %}


+ 80
- 17
frappe/www/me.html 파일 보기

@@ -1,31 +1,94 @@
{% from "frappe/templates/includes/avatar_macro.html" import avatar %}
{% extends "templates/web.html" %}

{% block title %}{{ _("My Account") }}{% endblock %}
{% block header %}<h1>{{ _("My Account") }}</h1>{% endblock %}

{% block title %}
{{ _("My Account") }}
{% endblock %}
{% block header %}
<h3 class="my-account-header">{{_("My Account") }}</h3>
{% endblock %}
{% block page_content %}
<div class="row your-account-info d-none d-sm-block">
<div class="col-sm-4">
<ul class="list-unstyled">
<li><a href="/update-password">{{ _("Reset Password") }}</a></li>
<li><a href="/update-profile?name={{ user }}">{{ _("Edit Profile") }}</a></li>
<li><a href="/third_party_apps">{{ _("Manage Third Party Apps") }}</a></li>
{% if frappe.db.get_single_value("Website Settings", "show_account_deletion_link") %}
<li><a href="/request-for-account-deletion?new=1">{{ _("Request for Account Deletion") }}</a></li>
{% endif %}
</ul>
<div class="row account-info d-flex flex-column">
<div class="col d-flex justify-content-between align-items-center">
<div>
<span class="my-account-avatar">
{{avatar(current_user.name)}}
</span>
<span class="my-account-name ml-4">
{{current_user.full_name }}
</span>
</div>
<div>
<span class="my-account-item-link">
<a href="/update-profile?name={{ user }}">
<svg class="edit-profile-icon icon icon-md">
<use xlink:href="#icon-edit">
</use>
</svg>
<span class="item-link-text pl-2">
{{_("Edit Profile") }}
</span>
</a>
</span>
</div>
</div>
<div class="col d-flex justify-content-between align-items-center">
<span>
<div class="my-account-item">{{_("Reset Password") }}</div>
<div class="my-account-item-desc">{{_("Reset the password for your account") }}</div>
</span>
<span class="my-account-item-link">
<a href="/update-password">
<svg class="right-icon icon icon-md">
<use xlink:href="#icon-right">
</use>
</svg>
<span class="item-link-text">{{_("Reset Password") }}</span>
</a>
</span>
</div>
<div class="col d-flex justify-content-between align-items-center">
<span>
<div class="my-account-item">{{_("Manage third party apps") }}</div>
<div class="my-account-item-desc">{{_("To manage your authorized third party apps") }}</div>
</span>
<span class="my-account-item-link">
<a href="/third_party_apps">
<svg class="right-icon icon icon-md">
<use xlink:href="#icon-right">
</use>
</svg>
<span class="item-link-text">{{_("Manage your apps") }}</span>
</a>
</span>
</div>
{% if frappe.db.get_single_value("Website Settings", "show_account_deletion_link") %}
<div class="col d-flex justify-content-between align-items-center">
<span>
<div class="my-account-item">{{_("Request Account Deletion") }}</div>
<div class="my-account-item-desc">{{_("Send a request to delete your account") }}</div>
</span>
<span class="my-account-item-link">
<a href="/request-for-account-deletion?new=1">
<svg class="right-icon icon icon-md">
<use xlink:href="#icon-right">
</use>
</svg>
<span class="item-link-text">{{_("Delete Account") }}</span>
</a>
</span>
</div>
{% endif %}
</div>
<div class="row d-block d-sm-none">
<div class="col-12">
<div class="col-12 side-list">
<ul class="list-group">
{% for item in sidebar_items -%}
<a class="list-group-item" href="{{ item.route }}"
{% if item.target %}target="{{ item.target }}"{% endif %}>
{{ _(item.title or item.label) }}
</a>
{%- endfor %}
{%- endfor %}
</ul>
</div>
</div>
{% endblock %}
{% endblock %}

+ 2
- 1
frappe/www/me.py 파일 보기

@@ -10,5 +10,6 @@ no_cache = 1
def get_context(context):
if frappe.session.user=='Guest':
frappe.throw(_("You need to be logged in to access this page"), frappe.PermissionError)

context.current_user = frappe.get_doc("User", frappe.session.user)
context.show_sidebar=True

+ 8
- 2
frappe/www/third_party_apps.html 파일 보기

@@ -2,7 +2,7 @@

{% block title %} {{ _("Third Party Apps") }} {% endblock %}
{% block header %}
<h1>{{ _("Third Party Apps") }}</h1>
<h3 class="my-account-header">{{ _("Third Party Apps") }}</h3>
{% endblock %}

{% block page_sidebar %}
@@ -52,9 +52,15 @@
</div>
{% endfor %}
{% else %}
<div class="text-muted">
<div class="empty-apps-state">
<img src="/assets/frappe/images/ui-states/empty-app-state.svg"/>
<div class="font-weight-bold mt-4">
{{ _("No Active Sessions")}}
</div>
<div class="text-muted mt-2">
{{ _("Looks like you haven’t added any third party apps.")}}
</div>
</div>
{% endif %}
<div class="padding"></div>
<script>


불러오는 중...
취소
저장