diff --git a/.snyk b/.snyk index b39169dcee..0dfecc6136 100644 --- a/.snyk +++ b/.snyk @@ -1,5 +1,5 @@ # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. -version: v1.13.5 +version: v1.14.1 # ignores vulnerabilities until expiry date; change duration by modifying expiry date ignore: SNYK-JS-AWESOMPLETE-174474: @@ -22,3 +22,44 @@ patch: SNYK-JS-LODASH-450202: - frappe-datatable > lodash: patched: '2020-01-31T01:33:09.889Z' + SNYK-JS-LODASH-567746: + - frappe-datatable > lodash: + patched: '2020-04-30T23:02:32.330Z' + - quagga > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > lodash: + patched: '2020-04-30T23:02:32.330Z' + - tailwindcss > lodash: + patched: '2020-04-30T23:02:32.330Z' + - '@tailwindcss/ui > @tailwindcss/custom-forms > lodash': + patched: '2020-04-30T23:02:32.330Z' + - snyk > @snyk/dep-graph > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > inquirer > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-config > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-mvn-plugin > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-nodejs-lockfile-parser > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-nuget-plugin > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > @snyk/dep-graph > graphlib > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-go-plugin > graphlib > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-nodejs-lockfile-parser > graphlib > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > @snyk/snyk-cocoapods-plugin > @snyk/dep-graph > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-nuget-plugin > dotnet-deps-parser > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > snyk-php-plugin > @snyk/composer-lockfile-parser > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > @snyk/snyk-cocoapods-plugin > @snyk/dep-graph > graphlib > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > @snyk/snyk-cocoapods-plugin > @snyk/cocoapods-lockfile-parser > @snyk/ruby-semver > lodash: + patched: '2020-04-30T23:02:32.330Z' + - snyk > @snyk/snyk-cocoapods-plugin > @snyk/cocoapods-lockfile-parser > @snyk/dep-graph > graphlib > lodash: + patched: '2020-04-30T23:02:32.330Z' diff --git a/.travis.yml b/.travis.yml index 174f92ea11..30eb882256 100644 --- a/.travis.yml +++ b/.travis.yml @@ -102,7 +102,13 @@ install: - if [ $TYPE == "server" ]; then sed -i 's/socketio:/# socketio:/g' Procfile; fi - if [ $TYPE == "server" ]; then sed -i 's/redis_socketio:/# redis_socketio:/g' Procfile; fi - - bench setup requirements --node + - if [ $TYPE == "ui" ]; then bench setup requirements --node; fi + + # install node-sass which is required for website theme test + - cd ./apps/frappe + - yarn add node-sass@4.13.1 + - cd ../.. + - bench start & - bench --site test_site reinstall --yes - bench --site test_site_producer reinstall --yes diff --git a/frappe/commands/utils.py b/frappe/commands/utils.py index da9d67be3b..3610393d9a 100644 --- a/frappe/commands/utils.py +++ b/frappe/commands/utils.py @@ -443,7 +443,7 @@ def console(context): for app in all_apps: locals()[app] = __import__(app) print("Apps in this namespace:\n{}".format(", ".join(all_apps))) - IPython.embed(display_banner="", header="") + IPython.embed(display_banner="", header="", colors="neutral") @click.command('run-tests') diff --git a/frappe/core/doctype/data_import/test_exporter_new.py b/frappe/core/doctype/data_import/test_exporter_new.py index faa48a35f4..0d3aedb033 100644 --- a/frappe/core/doctype/data_import/test_exporter_new.py +++ b/frappe/core/doctype/data_import/test_exporter_new.py @@ -20,7 +20,7 @@ class TestExporter(unittest.TestCase): e = Exporter('Web Page', export_fields='All') csv_array = e.get_csv_array() header = csv_array[0] - self.assertEqual(len(header), 36) + self.assertEqual(len(header), 37) def test_exports_selected_fields(self): diff --git a/frappe/desk/query_report.py b/frappe/desk/query_report.py index 164f6389eb..74e841f107 100644 --- a/frappe/desk/query_report.py +++ b/frappe/desk/query_report.py @@ -299,7 +299,6 @@ def export_query(): _("You can try changing the filters of your report.")) return - data.columns = [col for col in data.columns if isinstance(col, dict) and not col.get('hidden')] columns = get_columns_dict(data.columns) from frappe.utils.xlsxutils import make_xlsx @@ -316,7 +315,8 @@ def build_xlsx_data(columns, data, visible_idx, include_indentation): # add column headings for idx in range(len(data.columns)): - result[0].append(columns[idx]["label"]) + if not columns[idx].get("hidden"): + result[0].append(columns[idx]["label"]) # build table from result for i, row in enumerate(data.result): diff --git a/frappe/website/web_template/footer_horizontal/__init__.py b/frappe/email/doctype/newsletter/newsletter..json similarity index 100% rename from frappe/website/web_template/footer_horizontal/__init__.py rename to frappe/email/doctype/newsletter/newsletter..json diff --git a/frappe/email/doctype/newsletter/newsletter.json b/frappe/email/doctype/newsletter/newsletter.json index 719d51c176..01f75be954 100644 --- a/frappe/email/doctype/newsletter/newsletter.json +++ b/frappe/email/doctype/newsletter/newsletter.json @@ -17,7 +17,7 @@ "subject", "message", "send_unsubscribe_link", - "send_attachements", + "send_attachments", "published", "route", "test_the_newsletter", @@ -73,12 +73,6 @@ "fieldtype": "Check", "label": "Send Unsubscribe Link" }, - { - "default": "0", - "fieldname": "send_attachements", - "fieldtype": "Check", - "label": "Send Attachements" - }, { "default": "0", "fieldname": "published", @@ -127,6 +121,12 @@ { "fieldname": "column_break_2", "fieldtype": "Column Break" + }, + { + "default": "0", + "fieldname": "send_attachments", + "fieldtype": "Check", + "label": "Send Attachments" } ], "has_web_view": 1, @@ -135,7 +135,7 @@ "is_published_field": "published", "links": [], "max_attachments": 3, - "modified": "2020-03-02 06:26:51.622521", + "modified": "2020-05-12 18:09:40.137138", "modified_by": "Administrator", "module": "Email", "name": "Newsletter", diff --git a/frappe/email/doctype/newsletter/newsletter.py b/frappe/email/doctype/newsletter/newsletter.py index 2469569892..2dccfbead4 100755 --- a/frappe/email/doctype/newsletter/newsletter.py +++ b/frappe/email/doctype/newsletter/newsletter.py @@ -67,7 +67,7 @@ class Newsletter(WebsiteGenerator): frappe.db.auto_commit_on_many_writes = True attachments = [] - if self.send_attachements: + if self.send_attachments: files = frappe.get_all("File", fields=["name"], filters={"attached_to_doctype": "Newsletter", "attached_to_name": self.name}, order_by="creation desc") diff --git a/frappe/integrations/offsite_backup_utils.py b/frappe/integrations/offsite_backup_utils.py index c280a1d9dd..7e80cb68c4 100644 --- a/frappe/integrations/offsite_backup_utils.py +++ b/frappe/integrations/offsite_backup_utils.py @@ -10,7 +10,7 @@ from frappe.utils import split_emails, get_backups_path def send_email(success, service_name, doctype, email_field, error_status=None): - recipients = get_recipients(service_name, email_field) + recipients = get_recipients(doctype, email_field) if not recipients: frappe.log_error("No Email Recipient found for {0}".format(service_name), "{0}: Failed to send backup status email".format(service_name)) @@ -36,11 +36,11 @@ def send_email(success, service_name, doctype, email_field, error_status=None): frappe.sendmail(recipients=recipients, subject=subject, message=message) -def get_recipients(service_name, email_field): +def get_recipients(doctype, email_field): if not frappe.db: frappe.connect() - return split_emails(frappe.db.get_value(service_name, None, email_field)) + return split_emails(frappe.db.get_value(doctype, None, email_field)) def get_latest_backup_file(with_files=False): diff --git a/frappe/model/meta.py b/frappe/model/meta.py index cb7c77c57d..7bf93d1968 100644 --- a/frappe/model/meta.py +++ b/frappe/model/meta.py @@ -452,6 +452,7 @@ class Meta(Document): for link in self.links: link.added = False for group in data.transactions: + group = frappe._dict(group) # group found if link.group and group.label == link.group: if link.link_doctype not in group.get('items'): @@ -460,7 +461,7 @@ class Meta(Document): if not link.added: # group not found, make a new group - data.transactions.append(frappe._dict( + data.transactions.append(dict( label = link.group, items = [link.link_doctype] )) diff --git a/frappe/patches.txt b/frappe/patches.txt index a086fa6f4a..b73f2aea83 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -278,3 +278,4 @@ frappe.patches.v13_0.set_path_for_homepage_in_web_page_view frappe.patches.v13_0.migrate_translation_column_data frappe.patches.v13_0.set_read_times frappe.patches.v13_0.remove_web_view +frappe.patches.v13_0.remove_tailwind_from_page_builder diff --git a/frappe/patches/v13_0/remove_tailwind_from_page_builder.py b/frappe/patches/v13_0/remove_tailwind_from_page_builder.py new file mode 100644 index 0000000000..6e7bf67bac --- /dev/null +++ b/frappe/patches/v13_0/remove_tailwind_from_page_builder.py @@ -0,0 +1,13 @@ +# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors +# MIT License. See license.txt + +from __future__ import unicode_literals +import frappe + + +def execute(): + frappe.reload_doc("website", "doctype", "web_page_block") + # remove unused templates + frappe.delete_doc("Web Template", "Navbar with Links on Right", force=1) + frappe.delete_doc("Web Template", "Footer Horizontal", force=1) + diff --git a/frappe/public/build.json b/frappe/public/build.json index e4c90cb708..30cb2adf87 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -1,7 +1,4 @@ { - "css/tailwind.css": [ - "public/tailwind.css" - ], "css/frappe-web-b4.css": [ "public/scss/website.scss", "public/less/indicator.less" diff --git a/frappe/public/js/frappe/recorder/RequestDetail.vue b/frappe/public/js/frappe/recorder/RequestDetail.vue index 804c1c2f55..60795076ec 100644 --- a/frappe/public/js/frappe/recorder/RequestDetail.vue +++ b/frappe/public/js/frappe/recorder/RequestDetail.vue @@ -126,27 +126,9 @@ @@ -244,7 +226,6 @@ export default { }, group_duplicates: false, showing: null, - showing_traceback: null, request: { calls: [], }, diff --git a/frappe/public/scss/base.scss b/frappe/public/scss/base.scss new file mode 100644 index 0000000000..36a1df55ac --- /dev/null +++ b/frappe/public/scss/base.scss @@ -0,0 +1,43 @@ +html { + height: 100%; +} + +body { + -webkit-font-smoothing: antialiased; + font-size: 16px; + color: $body-color; +} + +img { + max-width: 100%; + height: auto; +} + +h1 { + font-size: $font-size-3xl; + font-weight: 800; + line-height: 1.25; + letter-spacing: -0.025em; + + @include media-breakpoint-up(sm) { + line-height: 2.5rem; + font-size: $font-size-4xl; + } + @include media-breakpoint-up(xl) { + line-height: 1; + font-size: $font-size-5xl; + } +} + +h2 { + font-size: $font-size-xl; + font-weight: bold; + + @include media-breakpoint-up(sm) { + font-size: $font-size-2xl; + } + @include media-breakpoint-up(md) { + font-size: $font-size-3xl; + } +} + diff --git a/frappe/public/scss/markdown.scss b/frappe/public/scss/markdown.scss new file mode 100644 index 0000000000..440a4cfe88 --- /dev/null +++ b/frappe/public/scss/markdown.scss @@ -0,0 +1,117 @@ +.from-markdown { + line-height: 1.625; + + > * + * { + margin-top: 1rem; + } + + > :first-child { + margin-top: 0; + } + + ul, + ol { + padding-left: 2.5rem; + } + + ul { + list-style-type: disc; + } + + ol { + list-style: decimal; + } + + li > * + * { + margin-top: 1rem; + } + + > ul > * + *, + > ol > * + * { + margin-top: 1rem; + } + + > blockquote { + padding: 0.75rem 1rem; + font-size: $font-size-sm; + font-weight: 500; + color: $gray-900; + border-left: 4px solid $yellow; + background-color: lighten($yellow, 42%); + border-top-left-radius: 0.1rem; + border-bottom-left-radius: 0.1rem; + border-top-right-radius: 0.375rem; + border-bottom-right-radius: 0.375rem; + margin: 1.5rem 0; + } + + blockquote p:last-child { + margin-bottom: 0; + } + + h1 + p { + max-width: 42rem; + margin-top: 0.75rem; + font-size: $font-size-base; + color: $gray-900; + + @include media-breakpoint-up(sm) { + margin-top: 1.25rem; + font-size: 1.125rem; + } + @include media-breakpoint-up(md) { + font-size: 1.25rem; + } + } + + h2 { + margin-bottom: 1rem; + margin-top: 3.5rem; + } + + h3 { + margin-top: 3rem; + margin-bottom: 1rem; + font-weight: 600; + line-height: 1.25; + font-size: $font-size-xl; + } + + h4 { + margin-top: 2.5rem; + margin-bottom: 1rem; + font-size: 1.125rem; + font-weight: 600; + line-height: 1.25; + } + + h5 { + margin-top: 2rem; + margin-bottom: 1rem; + font-size: $font-size-base; + font-weight: 600; + line-height: 1.25; + } + + h6 { + margin-top: 1.5rem; + margin-bottom: 1rem; + font-size: $font-size-sm; + font-weight: 600; + line-height: 1.25; + } + + tr > td, + tr > th { + font-size: $font-size-sm; + } + + th:empty { + display: none; + } + + .screenshot { + border: 1px solid $gray-400; + border-radius: 0.375rem; + } +} diff --git a/frappe/public/scss/page-builder.scss b/frappe/public/scss/page-builder.scss new file mode 100644 index 0000000000..f792209c24 --- /dev/null +++ b/frappe/public/scss/page-builder.scss @@ -0,0 +1,252 @@ +.hero-subtitle { + @extend .lead; + max-width: 42rem; +} + +.section-description { + max-width: 56rem; + margin-top: 0.5rem; + font-size: $font-size-base; + color: $gray-900; + + @include media-breakpoint-up(lg) { + font-size: $font-size-lg; + } +} + +.section-image { + margin-top: 2rem; + border-radius: 0.75rem; + width: 100%; +} + +.section-padding { + padding-top: 3rem; + padding-bottom: 3rem; + + @include media-breakpoint-up(sm) { + padding-top: 5rem; + padding-bottom: 5rem; + } + @include media-breakpoint-up(xl) { + padding-top: 8rem; + padding-bottom: 8rem; + } +} + +.section-padding-top { + padding-top: 3rem; + + @include media-breakpoint-up(sm) { + padding-top: 5rem; + } + @include media-breakpoint-up(xl) { + padding-top: 8rem; + } +} + +.section-padding-bottom { + padding-bottom: 3rem; + + @include media-breakpoint-up(sm) { + padding-bottom: 5rem; + } + @include media-breakpoint-up(xl) { + padding-bottom: 8rem; + } +} + +.hero-with-right-image { + position: relative; + + .hero-content { + display: flex; + align-items: center; + } + + .hero-image { + width: auto; + display: none; + object-fit: contain; + max-height: 36rem; + + &.contain-image { + right: 0; + } + + @include media-breakpoint-up(md) { + display: block; + max-width: 28rem; + } + @include media-breakpoint-up(lg) { + max-width: 32rem; + } + @include media-breakpoint-up(xl) { + max-width: 42rem; + } + } +} + +.card { + .card-title { + color: $black; + } + + .card-body { + color: $gray-900; + } + + &:hover { + border-color: $gray-600; + } + + &.card-sm { + .card-body { + padding: 1.5rem; + } + + .card-title { + font-size: $font-size-base; + font-weight: 600; + } + + .card-text { + font-size: $font-size-sm; + } + } + &.card-md { + .card-body { + padding: 1.75rem; + } + + .card-title { + font-size: $font-size-lg; + font-weight: 600; + + @include media-breakpoint-up(md) { + font-size: $font-size-xl; + } + } + .card-text { + font-size: $font-size-base; + } + } + &.card-lg { + .card-body { + padding: 2rem; + } + + .card-title { + font-size: $font-size-xl; + font-weight: bold; + + @include media-breakpoint-up(md) { + font-size: $font-size-2xl; + } + } + + .card-text { + font-size: $font-size-base; + + @include media-breakpoint-up(xl) { + font-size: $font-size-lg; + } + } + } +} + +.nav-tabs { + .nav-link { + color: $gray-700; + font-weight: 500; + border: none; + padding: 1rem 0.5rem; + margin-right: 2rem; + + &:hover { + color: $primary; + } + } + + .nav-link.active, + .nav-item.show .nav-link { + color: darken($primary, 5%); + background-color: #fff; + border-bottom: 2px solid $primary; + } +} + +.section-markdown > .from-markdown { + max-width: 42rem; +} + +.section-cta { + padding: 3rem 2rem; + text-align: center; + background-color: lighten($primary, 42%); + border-radius: 0.75rem; + + @include media-breakpoint-up(sm) { + padding-left: 3rem; + padding-right: 3rem; + } + @include media-breakpoint-up(md) { + padding-top: 5rem; + padding-bottom: 5rem; + } + + .title { + margin: 0 auto; + max-width: 36rem; + font-size: $font-size-2xl; + font-weight: 800; + line-height: 1.25; + @include media-breakpoint-up(md) { + font-size: $font-size-4xl; + } + } + .subtitle { + max-width: 36rem; + margin: 0 auto; + margin-top: 0.5rem; + font-size: $font-size-base; + color: $gray-900; + @include media-breakpoint-up(md) { + font-size: $font-size-lg; + } + } + .description { + max-width: 36rem; + margin: 0 auto; + margin-top: 0.5rem; + font-size: $font-size-xs; + color: $gray-900; + } +} + +.section-cta-container { + position: relative; + .confetti { + position: absolute; + width: 1rem; + height: 1rem; + border-radius: 99999px; + } + .confetti-1 { + top: 0; + margin-top: -0.5rem; + background-color: #84e1bc; + left: 25%; + } + .confetti-2 { + background-color: #fdba8c; + top: 66.67%; + right: 16.67%; + } + .confetti-3 { + bottom: 0; + margin-bottom: -0.5rem; + background-color: #f8b4b4; + left: 16.67%; + } +} diff --git a/frappe/public/scss/variables.scss b/frappe/public/scss/variables.scss index 6ee7cda884..e5f3a47f6f 100644 --- a/frappe/public/scss/variables.scss +++ b/frappe/public/scss/variables.scss @@ -8,14 +8,45 @@ $gray-600: #8d99a6 !default; $gray-700: #495057 !default; $gray-800: #36414c !default; $gray-900: #2e3338 !default; -$primary: #5e64ff !default; +$primary: #2490ef !default; $black: #000 !default; $body-color: $gray-800 !default; $text-muted: $gray-600 !default; -$border-color: $gray-200 !default; +$border-color: $gray-300 !default; -@import "~bootstrap/scss/functions"; -@import "~bootstrap/scss/variables"; +$font-size-xs: 0.75rem !default; +$font-size-sm: 0.875rem !default; +$font-size-base: 1rem !default; +$font-size-lg: 1.125rem !default; +$font-size-xl: 1.25rem !default; +$font-size-2xl: 1.5rem !default; +$font-size-3xl: 1.875rem !default; +$font-size-4xl: 2.25rem !default; +$font-size-5xl: 3rem !default; +$font-size-6xl: 4rem !default; +$btn-padding-y-lg: 1rem !default; +$btn-padding-x-lg: 2.5rem !default; +$btn-font-size-lg: 1.125rem !default; +$btn-line-height-lg: 1 !default; +$btn-border-radius-lg: 0.5rem !default; +$btn-border-radius: 0.375rem !default; +$btn-font-size: $font-size-sm; +$btn-padding-x: 1rem !default; +$btn-padding-y: 0.5rem !default; +$btn-font-weight: 500 !default; + +$navbar-nav-link-padding-x: 1rem !default; +$navbar-padding-y: 1rem; +$card-border-radius: 0.75rem !default; +$card-spacer-y: 1rem !default; + +$dropdown-font-size: $font-size-sm !default; +$dropdown-border-radius: 0.375rem !default; +$dropdown-item-padding-y: 0.5rem !default; +$dropdown-item-padding-x: 0.5rem !default; + +@import '~bootstrap/scss/functions'; +@import '~bootstrap/scss/variables'; diff --git a/frappe/public/scss/website-image.scss b/frappe/public/scss/website-image.scss index 18adae4acc..8c32e821fe 100644 --- a/frappe/public/scss/website-image.scss +++ b/frappe/public/scss/website-image.scss @@ -34,7 +34,7 @@ img:after { display: flex; justify-content: center; align-items: center; - font-size: 3rem; + font-size: $font-size-5xl; color: $gray-300; background: $light; } @@ -85,4 +85,4 @@ img:after { .object-fit-cover { object-fit: cover; -} \ No newline at end of file +} diff --git a/frappe/public/scss/website.scss b/frappe/public/scss/website.scss index 546110bd5c..30781c52c1 100644 --- a/frappe/public/scss/website.scss +++ b/frappe/public/scss/website.scss @@ -1,42 +1,71 @@ -@import "variables"; -@import "frappe/public/css/font-awesome"; -@import "~bootstrap/scss/bootstrap"; -@import "multilevel-dropdown"; -@import "website-image"; +@import 'variables'; +@import 'frappe/public/css/font-awesome'; +@import '~bootstrap/scss/bootstrap'; +@import 'base'; +@import 'multilevel-dropdown'; +@import 'website-image'; +@import 'page-builder'; +@import 'markdown'; -html { - height: 100%; +.container { + padding-left: 1.25rem; + padding-right: 1.25rem; } -body { - min-height: 100%; - display: flex; - flex-direction: column; - font-size: 16px; - - > div { - flex: 1 0 auto; - } -} - -footer { - flex-shrink: 0; -} - -// make navbar padding consistent with the page -.navbar { - padding-left: 0; - padding-right: 0; - +@include media-breakpoint-up(sm) { .container { - padding-left: 15px; - padding-right: 15px; + padding-left: 1rem; + padding-right: 1rem; } } +@include media-breakpoint-up(md) { + .container { + padding-left: 1rem; + padding-right: 1rem; + } +} + +@include media-breakpoint-up(lg) { + .container { + padding-left: 1rem; + padding-right: 1rem; + } +} + +@include media-breakpoint-up(xl) { + .container { + padding-left: 1.5rem; + padding-right: 1.5rem; + } +} + +.navbar-light { + border-bottom: 1px solid $border-color; +} + +.navbar-light .navbar-nav .nav-link { + color: $gray-900; + font-size: $font-size-sm; + font-weight: 500; + + &:hover, + &:focus, &.active { + color: $primary; + } +} + +.dropdown-menu { + padding: 0.25rem; +} + +.dropdown-item { + border-radius: $dropdown-border-radius; +} + .navbar.bg-dark { .dropdown-menu { - font-size: .75rem; + font-size: 0.75rem; background-color: $dark; border-radius: 0; } @@ -64,7 +93,6 @@ footer { } } - .input-dark { background-color: $dark; border-color: darken($primary, 40%); @@ -72,25 +100,21 @@ footer { } .breadcrumb { - padding-left: 0; - padding-right: 0; - background-color: white; + padding-left: 0; + padding-right: 0; + background-color: white; } a.card { text-decoration: none; } -img { - max-width: 100%; -} - .hidden { @extend .d-none; } .hide-control { - @extend .d-none; + @extend .d-none; } .text-underline { @@ -101,10 +125,49 @@ img { color: #d1d8dd !important; } +// footer + .web-footer { padding: 5rem 0; min-height: 140px; - border-top: 1px solid $border-color; +} + +.footer-logo { + width: 5rem; + height: 2rem; +} + +.footer-link, .footer-child-item a { + font-weight: 500; + color: $gray-900; + + &:hover { + color: $primary; + text-decoration: none; + } +} + +.footer-col-left, .footer-col-right { + padding-top: 1rem; + padding-bottom: 1rem; +} + +.footer-col-right { + @include media-breakpoint-up(sm) { + text-align: right; + } +} + +.footer-col-left .footer-link { + margin-right: 1rem; +} + +.footer-col-right .footer-link { + margin-right: 1rem; + @include media-breakpoint-up(sm) { + margin-right: 0; + margin-left: 1rem; + } } .footer-group-label { @@ -112,41 +175,75 @@ img { } .footer-parent-item { - margin-bottom: 1rem; + margin-bottom: 0.5rem; +} + +.footer-info { + border-top: 1px solid $border-color; + color: $text-muted; + font-size: $font-size-sm; } .no-underline { - text-decoration: none !important; + text-decoration: none !important; } .indicator { - font-size: inherit; + font-size: inherit; } h4.modal-title { - font-size: 1em; + font-size: 1em; } h5.modal-title { - margin: 0px !important; + margin: 0px !important; } -.col-xs-1 { @extend .col-1; } -.col-xs-2 { @extend .col-2; } -.col-xs-3 { @extend .col-3; } -.col-xs-4 { @extend .col-4; } -.col-xs-5 { @extend .col-5; } -.col-xs-6 { @extend .col-6; } -.col-xs-7 { @extend .col-7; } -.col-xs-8 { @extend .col-8; } -.col-xs-9 { @extend .col-9; } -.col-xs-10 { @extend .col-10; } -.col-xs-11 { @extend .col-11; } -.col-xs-12 { @extend .col-12; } +.col-xs-1 { + @extend .col-1; +} +.col-xs-2 { + @extend .col-2; +} +.col-xs-3 { + @extend .col-3; +} +.col-xs-4 { + @extend .col-4; +} +.col-xs-5 { + @extend .col-5; +} +.col-xs-6 { + @extend .col-6; +} +.col-xs-7 { + @extend .col-7; +} +.col-xs-8 { + @extend .col-8; +} +.col-xs-9 { + @extend .col-9; +} +.col-xs-10 { + @extend .col-10; +} +.col-xs-11 { + @extend .col-11; +} +.col-xs-12 { + @extend .col-12; +} -.btn-default { @extend .btn-light; } +.btn-default { + @extend .btn-light; +} -.btn-xs { @extend .btn-sm; } +.btn-xs { + @extend .btn-sm; +} .hidden-xs { @extend .d-none; @@ -171,3 +268,29 @@ h5.modal-title { .pull-right { float: right; } + +.btn-primary-light { + $primary-light: lighten($primary, 42%); + @include button-variant( + $background: $primary-light, + $border: $primary-light, + $hover-background: lighten($primary-light, 1%), + $hover-border: $primary-light, + $active-background: lighten($primary-light, 1%), + $active-border: darken($primary-light, 12.5%) + ); + + color: darken($primary, 5%); + &:hover { + color: darken($primary, 5%); + } +} + +.image-with-blur { + transition: filter 300ms ease-in-out; + filter: blur(1.5rem); +} + +.image-loaded { + filter: blur(0rem); +} diff --git a/frappe/public/tailwind.css b/frappe/public/tailwind.css deleted file mode 100644 index 89595f95ba..0000000000 --- a/frappe/public/tailwind.css +++ /dev/null @@ -1,141 +0,0 @@ -@tailwind base; - -html, -body { - @apply antialiased; - @apply text-black; -} - -@tailwind components; - -details.hide-summary-arrow summary::-webkit-details-marker { - display: none; -} - -.from-markdown { - @apply leading-relaxed; - - > * + * { - @apply mt-4; - } - - > :first-child { - margin-top: 0; - } - - ul, - ol { - @apply pl-10; - } - - ul { - @apply list-disc; - } - - ol { - @apply list-decimal; - } - - li > * + * { - @apply mt-4; - } - - > ul > * + *, - > ol > * + * { - @apply mt-4; - } - - > blockquote { - @apply px-4 py-3 text-sm font-medium text-gray-900 border border-gray-400 rounded-md bg-gray-50; - } - - h1 { - @apply mt-16 mb-4 text-3xl font-extrabold leading-tight tracking-tight; - @screen sm { - @apply text-4xl leading-10; - } - @screen xl { - @apply text-5xl leading-none; - } - } - - h1 + p { - @apply max-w-2xl mt-3 text-base text-gray-900; - - @screen sm { - @apply mt-5 text-lg; - } - @screen md { - @apply mt-5 text-xl; - } - } - - h2 { - @apply mb-4 text-2xl font-bold leading-tight mt-14; - } - - h3 { - @apply mt-12 mb-4 text-xl font-semibold leading-tight; - } - - h4 { - @apply mt-10 mb-4 text-lg font-semibold leading-tight; - } - - h5 { - @apply mt-8 mb-4 text-base font-semibold leading-tight; - } - - h6 { - @apply mt-6 mb-4 text-sm font-semibold leading-tight; - } - - > a, - > p a, - > ul li a, - > ol li a { - @apply border-b border-gray-800; - &:hover { - @apply text-gray-700; - } - } - - table { - @apply w-full my-8 border-t; - } - - tbody { - @apply border-t; - } - - tr > td, - tr > th { - @apply py-4 pr-6 text-sm leading-6 text-left border-b; - } - - th:empty { - display: none; - } - - .screenshot { - @apply border border-gray-400 rounded-md; - } -} - -@tailwind utilities; - -.blur-none { - filter: blur(0rem); -} - -.blur-sm { - filter: blur(1rem); -} - -.blur-md { - filter: blur(1.5rem); -} - -.blur-lg { - filter: blur(2rem); -} diff --git a/frappe/recorder.py b/frappe/recorder.py index ffafffb93f..388efcbf6e 100644 --- a/frappe/recorder.py +++ b/frappe/recorder.py @@ -9,12 +9,8 @@ import inspect import json import re import time -import traceback import frappe import sqlparse -from pygments import highlight -from pygments.lexers import PythonLexer -from pygments.formatters import HtmlFormatter from frappe import _ @@ -30,7 +26,7 @@ def sql(*args, **kwargs): stack = list(get_current_stack_frames()) - if frappe.db.db_type == 'postgres': + if frappe.db.db_type == "postgres": query = frappe.db._cursor.query else: query = frappe.db._cursor._executed @@ -65,9 +61,6 @@ def get_current_stack_frames(): "filename": re.sub(".*/apps/", "", filename), "lineno": lineno, "function": function, - "context": "".join(context), - "index": index, - "locals": json.dumps(frame.f_locals, skipkeys=True, default=str) } @@ -83,7 +76,7 @@ def dump(): frappe.local._recorder.dump() -class Recorder(): +class Recorder: def __init__(self): self.uuid = frappe.generate_hash(length=10) self.time = datetime.datetime.now() @@ -105,12 +98,18 @@ class Recorder(): "cmd": self.cmd, "time": self.time, "queries": len(self.calls), - "time_queries": float("{:0.3f}".format(sum(call["duration"] for call in self.calls))), - "duration": float("{:0.3f}".format((datetime.datetime.now() - self.time).total_seconds() * 1000)), + "time_queries": float( + "{:0.3f}".format(sum(call["duration"] for call in self.calls)) + ), + "duration": float( + "{:0.3f}".format((datetime.datetime.now() - self.time).total_seconds() * 1000) + ), "method": self.method, } frappe.cache().hset(RECORDER_REQUEST_SPARSE_HASH, self.uuid, request_data) - frappe.publish_realtime(event="recorder-dump-event", message=json.dumps(request_data, default=str)) + frappe.publish_realtime( + event="recorder-dump-event", message=json.dumps(request_data, default=str) + ) self.mark_duplicates() @@ -137,6 +136,7 @@ def do_not_record(function): del frappe.local._recorder frappe.db.sql = frappe.db._sql return function(*args, **kwargs) + return wrapper @@ -145,6 +145,7 @@ def administrator_only(function): if frappe.session.user != "Administrator": frappe.throw(_("Only Administrator is allowed to use Recorder")) return function(*args, **kwargs) + return wrapper @@ -175,11 +176,6 @@ def stop(*args, **kwargs): def get(uuid=None, *args, **kwargs): if uuid: result = frappe.cache().hget(RECORDER_REQUEST_HASH, uuid) - lexer = PythonLexer(tabsize=4) - for call in result["calls"]: - for stack in call["stack"]: - formatter = HtmlFormatter(noclasses=True, hl_lines=[stack["index"] + 1]) - stack["context"] = highlight(stack["context"], lexer, formatter) else: result = list(frappe.cache().hgetall(RECORDER_REQUEST_SPARSE_HASH).values()) return result diff --git a/frappe/templates/base.html b/frappe/templates/base.html index 907a7b6113..5688ce4fc3 100644 --- a/frappe/templates/base.html +++ b/frappe/templates/base.html @@ -25,26 +25,10 @@ {{ head_html or "" }} {%- endif %} - {%- if theme.based_on == 'Bootstrap 4' or doctype != 'Web Page' -%} - {%- if theme.theme_url -%} - - {%- else -%} - - {%- endif -%} - {% else %} - {%- if developer_mode -%} - - - {%- else -%} - - - - {% endif %} - {%- if theme.theme_css -%} - - {%- endif -%} + {%- if theme.name != 'Standard' -%} + + {%- else -%} + {%- endif -%} {%- for link in web_include_css %} @@ -65,7 +49,7 @@ frappe.ready_events.push(fn); } window.dev_server = {{ dev_server }}; - window.socketio_port = {{ frappe.socketio_port }}; + window.socketio_port = {{ (frappe.socketio_port or 'null') }}; @@ -78,11 +62,7 @@ {%- endblock -%} {%- block navbar -%} - {%- if navbar_content -%} - {{ navbar_content }} - {%- else -%} - {% include "templates/includes/navbar/navbar.html" %} - {%- endif -%} + {% include "templates/includes/navbar/navbar.html" %} {%- endblock -%} {% block content %} @@ -90,11 +70,7 @@ {% endblock %} {%- block footer -%} - {%- if footer_content -%} - {{ footer_content }} - {%- else -%} - {% include "templates/includes/footer/footer.html" %} - {%- endif -%} + {% include "templates/includes/footer/footer.html" %} {%- endblock -%} {% block base_scripts %} diff --git a/frappe/templates/components/button.html b/frappe/templates/components/button.html deleted file mode 100644 index d2655b4371..0000000000 --- a/frappe/templates/components/button.html +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: "button" -variant: "secondary" -size: "small" -disabled: 0 -url: null ---- - -{%- set static_classes = "border inline-flex justify-center items-center focus:outline-none font-medium transition duration-150 ease-in-out" -%} -{%- set dynamic_classes = { - "px-4 py-2 text-sm leading-5 rounded-md": size == "small", - "px-8 py-3 sm:px-10 sm:py-4 text-base sm:text-lg leading-6 rounded-lg": size == "large", - "opacity-50 cursor-not-allowed pointer-events-none": disabled, - "bg-primary-500 border-transparent hover:bg-primary-400 text-white focus:shadow-outline-primary focus:border-primary-600": - variant == "primary", - "bg-primary-100 border-transparent text-primary-700 hover:text-primary-600 hover:bg-primary-50 focus:shadow-outline-primary focus:border-primary-300": - variant == "secondary", - "bg-red-500 border-transparent hover:bg-red-400 text-white focus:shadow-outline-red focus:border-red-700": - variant == "danger" - } --%} -{%- set html_tag = "a" if url else "button" -%} - -<{{html_tag}} - class="{{ resolve_class([static_classes, dynamic_classes, class]) }}" - {{ 'disabled' if disabled else '' }} - {{ ('href="' + url + '"') if url else '' }}> - {{ label }} - diff --git a/frappe/templates/components/dropdown.html b/frappe/templates/components/dropdown.html deleted file mode 100644 index f73bdf9304..0000000000 --- a/frappe/templates/components/dropdown.html +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/frappe/templates/components/navbar_link.html b/frappe/templates/components/navbar_link.html deleted file mode 100644 index 170247dca5..0000000000 --- a/frappe/templates/components/navbar_link.html +++ /dev/null @@ -1,3 +0,0 @@ - - {{ label }} - diff --git a/frappe/templates/components/web_blocks.html b/frappe/templates/components/web_blocks.html deleted file mode 100644 index 3a9e3c5944..0000000000 --- a/frappe/templates/components/web_blocks.html +++ /dev/null @@ -1,3 +0,0 @@ -{%- for web_block in web_blocks -%} -{{ c('web_block', web_block=web_block, htmltag=htmltag) }} -{%- endfor -%} diff --git a/frappe/templates/includes/footer/footer.html b/frappe/templates/includes/footer/footer.html index 7fe6a955f7..671e928d32 100644 --- a/frappe/templates/includes/footer/footer.html +++ b/frappe/templates/includes/footer/footer.html @@ -1,45 +1,46 @@ -{%- if theme.based_on == 'Bootstrap 4' or doctype != 'Web Page' -%} - -{%- else -%} - -{%- endif -%} diff --git a/frappe/templates/includes/footer/footer_grouped_links.html b/frappe/templates/includes/footer/footer_grouped_links.html new file mode 100644 index 0000000000..6e20c51279 --- /dev/null +++ b/frappe/templates/includes/footer/footer_grouped_links.html @@ -0,0 +1,28 @@ +{% for page in footer_items if page.child_items %} + +{% endfor %} diff --git a/frappe/templates/includes/footer/footer_links.html b/frappe/templates/includes/footer/footer_links.html new file mode 100644 index 0000000000..fe9f69fed3 --- /dev/null +++ b/frappe/templates/includes/footer/footer_links.html @@ -0,0 +1,27 @@ +{% macro footer_link(item) %} + + {%- if item.icon -%} + {{ item.label }} + {%- else -%} + {{ item.label }} + {%- endif -%} + +{% endmacro %} + +{% if footer_items -%} + +{% endif %} diff --git a/frappe/templates/components/image_with_blur.html b/frappe/templates/includes/image_with_blur.html similarity index 79% rename from frappe/templates/components/image_with_blur.html rename to frappe/templates/includes/image_with_blur.html index cbee369608..20b0380b88 100644 --- a/frappe/templates/components/image_with_blur.html +++ b/frappe/templates/includes/image_with_blur.html @@ -1,6 +1,6 @@ {%- set res = frappe.utils.get_thumbnail_base64_for_image(src) if src else false -%} {%- if res and res['base64'].startswith('data:') -%} -{{ alt or '' }} {%- else -%} {{ alt or '' }} @@ -18,8 +18,7 @@ img.onload = function () { image.src = image_source; - image.classList.remove('blur-md'); - image.classList.add('blur-none'); + image.classList.add('image-loaded'); }; if (image_source) { diff --git a/frappe/templates/includes/navbar/navbar.html b/frappe/templates/includes/navbar/navbar.html index 379c6660fc..d669eee9d3 100644 --- a/frappe/templates/includes/navbar/navbar.html +++ b/frappe/templates/includes/navbar/navbar.html @@ -1,5 +1,4 @@ -{%- if theme.based_on == 'Bootstrap 4' or doctype != 'Web Page' -%} -