diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7443bde6a8..7161bb90ae 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,7 +35,7 @@ repos: rev: v2.7.1 hooks: - id: prettier - types_or: [javascript] + types_or: [javascript, vue, scss] # Ignore any files that might contain jinja / bundles exclude: | (?x)^( @@ -44,7 +44,8 @@ repos: .*boilerplate.*| frappe/www/website_script.js| frappe/templates/includes/.*| - frappe/public/js/lib/.* + frappe/public/js/lib/.*| + frappe/website/doctype/website_theme/website_theme_template.scss )$ diff --git a/cypress/fixtures/form_builder_doctype.js b/cypress/fixtures/form_builder_doctype.js index 08b598f82a..995971bed4 100644 --- a/cypress/fixtures/form_builder_doctype.js +++ b/cypress/fixtures/form_builder_doctype.js @@ -10,6 +10,12 @@ export default { fieldtype: "Data", label: "Data 3", }, + { + fieldname: "gender", + fieldtype: "Link", + label: "Gender", + options: "Gender", + }, { fieldname: "tab", fieldtype: "Tab Break", diff --git a/cypress/integration/control_float.js b/cypress/integration/control_float.js index e7d6b398f1..08b71eb870 100644 --- a/cypress/integration/control_float.js +++ b/cypress/integration/control_float.js @@ -32,10 +32,13 @@ context("Control Float", () => { cy.wait(200); cy.fill_field("float_number", d.input, "Float").blur(); cy.get_field("float_number", "Float").should("have.value", d.blur_expected); - + cy.wait(100); cy.get_field("float_number", "Float").focus(); + cy.wait(100); cy.get_field("float_number", "Float").blur(); + cy.wait(100); cy.get_field("float_number", "Float").focus(); + cy.wait(100); cy.get_field("float_number", "Float").should("have.value", d.focus_expected); }); }); @@ -49,17 +52,17 @@ context("Control Float", () => { { input: "364.87,334", blur_expected: "36.487,334", - focus_expected: "36487.334", + focus_expected: "36.487,334", }, { - input: "36487,334", - blur_expected: "36.487,334", - focus_expected: "36487.334", + input: "36487,335", + blur_expected: "36.487,335", + focus_expected: "36.487,335", }, { - input: "100", - blur_expected: "100,000", - focus_expected: "100", + input: "2*(2+47)+1,5+1", + blur_expected: "100,500", + focus_expected: "100,500", }, ], }, @@ -67,19 +70,19 @@ context("Control Float", () => { number_format: "#,###.##", values: [ { - input: "364,87.334", - blur_expected: "36,487.334", - focus_expected: "36487.334", + input: "464,87.334", + blur_expected: "46,487.334", + focus_expected: "46,487.334", }, { - input: "36487.334", - blur_expected: "36,487.334", - focus_expected: "36487.334", + input: "46487.335", + blur_expected: "46,487.335", + focus_expected: "46,487.335", }, { - input: "100", - blur_expected: "100.000", - focus_expected: "100", + input: "3*(2+47)+1.5+1", + blur_expected: "149.500", + focus_expected: "149.500", }, ], }, @@ -90,13 +93,13 @@ context("Control Float", () => { { input: "12.345", blur_expected: "12.345,000", - focus_expected: "12345", + focus_expected: "12.345,000", }, { // parseFloat would reduce 12,340 to 12,34 if this string was ever to be parsed input: "12.340", blur_expected: "12.340,000", - focus_expected: "12340", + focus_expected: "12.340,000", }, ], }, diff --git a/cypress/integration/customize_form.js b/cypress/integration/customize_form.js index 07bf139da1..bd8ca1d73b 100644 --- a/cypress/integration/customize_form.js +++ b/cypress/integration/customize_form.js @@ -5,6 +5,8 @@ context("Customize Form", () => { }); it("Changing to naming rule should update autoname", () => { cy.fill_field("doc_type", "ToDo", "Link").blur(); + cy.wait(2000); + cy.findByRole("tab", { name: "Details" }).click(); cy.click_form_section("Naming"); const naming_rule_default_autoname_map = { "Set by user": "prompt", diff --git a/cypress/integration/form_builder.js b/cypress/integration/form_builder.js index 2a5865b904..4f7a1c5b1f 100644 --- a/cypress/integration/form_builder.js +++ b/cypress/integration/form_builder.js @@ -35,6 +35,40 @@ context("Form Builder", () => { cy.get(".title-area .indicator-pill.orange").should("have.text", "Not Saved"); }); + it("Check if Filters are applied to the link field", () => { + // Visit the Form Builder + cy.visit(`/app/doctype/${doctype_name}`); + cy.findByRole("tab", { name: "Form" }).click(); + + cy.get("[data-fieldname='gender']").click(); + + // click on filter action button + cy.get('[data-fieldname="gender"] .field-actions button:first').click(); + + // add filter + cy.get(".modal-body .clear-filters").click(); + cy.get(".modal-body .filter-action-buttons .add-filter").click(); + cy.wait(100); + cy.get(".modal-body .filter-box .list_filter .filter-field .link-field input").type( + "Male" + ); + cy.get(".btn-modal-primary").click(); + + // Save the document + cy.click_doc_primary_button("Save"); + + // Open a new Form + cy.new_form(doctype_name); + // Click on the "salutation" field + cy.get_field("gender").clear().click(); + + cy.intercept("POST", "/api/method/frappe.desk.search.search_link").as("search_link"); + cy.wait("@search_link").then((data) => { + expect(data.response.body.message.length).to.eq(1); + expect(data.response.body.message[0].value).to.eq("Male"); + }); + }); + it("Add empty section and save", () => { cy.visit(`/app/doctype/${doctype_name}`); cy.findByRole("tab", { name: "Form" }).click(); @@ -43,7 +77,8 @@ context("Form Builder", () => { // add new section cy.get(first_section).click(15, 10); - cy.get(first_section).find(".section-actions button:first").click(); + cy.get(first_section).find(".dropdown-btn:first").click(); + cy.get(".dropdown-options:visible .dropdown-item:first").click(); // save cy.click_doc_primary_button("Save"); @@ -184,12 +219,14 @@ context("Form Builder", () => { // add new section cy.get(first_section).click(15, 10); - cy.get(first_section).find(".section-actions button:first").click(); + cy.get(first_section).find(".dropdown-btn:first").click(); + cy.get(".dropdown-options:visible .dropdown-item:first").click(); cy.get(".tab-content.active .form-section-container").should("have.length", 2); // add new column - cy.get(first_section).find(".column:first").click(15, 10); - cy.get(first_section).find(".column:first .column-actions button:first").click(); + cy.get(first_section).click(15, 10); + cy.get(first_section).find(".dropdown-btn:first").click(); + cy.get(".dropdown-options:visible .dropdown-item:last").click(); cy.get(first_section).find(".column").should("have.length", 2); }); @@ -197,13 +234,15 @@ context("Form Builder", () => { let first_section = ".tab-content.active .form-section-container:first"; // remove column - cy.get(first_section).find(".column:first").click(15, 10); - cy.get(first_section).find(".column:first .column-actions button:last").click(); + cy.get(first_section).click(15, 10); + cy.get(first_section).find(".dropdown-btn:first").click(); + cy.get(".dropdown-options:visible .dropdown-item:last").click(); cy.get(first_section).find(".column").should("have.length", 1); // remove section cy.get(first_section).click(15, 10); - cy.get(first_section).find(".section-actions button:last").click(); + cy.get(first_section).find(".dropdown-btn:first").click(); + cy.get(".dropdown-options:visible .dropdown-item").eq(1).click(); cy.get(".tab-content.active .form-section-container").should("have.length", 1); // remove tab diff --git a/cypress/integration/grid_configuration.js b/cypress/integration/grid_configuration.js index 3d49ed1503..b94028a42d 100644 --- a/cypress/integration/grid_configuration.js +++ b/cypress/integration/grid_configuration.js @@ -4,7 +4,7 @@ context("Grid Configuration", () => { cy.visit("/app/doctype/User"); }); it("Set user wise grid settings", () => { - cy.findByRole("tab", { name: "Form" }).click(); + cy.findByRole("tab", { name: "Settings" }).click(); cy.get('.form-section[data-fieldname="fields_section"]').click(); cy.wait(100); cy.get('.frappe-control[data-fieldname="fields"]').as("table"); diff --git a/cypress/integration/web_form.js b/cypress/integration/web_form.js index f6268b69cd..9db8b09ada 100644 --- a/cypress/integration/web_form.js +++ b/cypress/integration/web_form.js @@ -156,6 +156,7 @@ context("Web Form", () => { cy.findByRole("tab", { name: "Customization" }).click(); cy.fill_field("breadcrumbs", '[{"label": _("Notes"), "route":"note"}]', "Code"); + cy.wait(2000); cy.get(".form-tabs .nav-item .nav-link").contains("Customization").click(); cy.save(); diff --git a/cypress/integration/workspace.js b/cypress/integration/workspace.js index d52417b234..1499c8772e 100644 --- a/cypress/integration/workspace.js +++ b/cypress/integration/workspace.js @@ -20,7 +20,6 @@ context("Workspace 2.0", () => { cy.get(".codex-editor__redactor .ce-block"); cy.get('.custom-actions button[data-label="Create%20Workspace"]').click(); cy.fill_field("title", "Test Private Page", "Data"); - cy.fill_field("icon", "edit", "Icon"); cy.get_open_dialog().find(".modal-header").click(); cy.get_open_dialog().find(".btn-primary").click(); @@ -52,7 +51,6 @@ context("Workspace 2.0", () => { cy.get('.custom-actions button[data-label="Create%20Workspace"]').click(); cy.fill_field("title", "Test Child Page", "Data"); cy.fill_field("parent", "Test Private Page", "Select"); - cy.fill_field("icon", "edit", "Icon"); cy.get_open_dialog().find(".modal-header").click(); cy.get_open_dialog().find(".btn-primary").click(); diff --git a/cypress/integration/workspace_blocks.js b/cypress/integration/workspace_blocks.js index 3b75ffb8c1..7744bfd4da 100644 --- a/cypress/integration/workspace_blocks.js +++ b/cypress/integration/workspace_blocks.js @@ -20,7 +20,6 @@ context("Workspace Blocks", () => { cy.get(".codex-editor__redactor .ce-block"); cy.get('.custom-actions button[data-label="Create%20Workspace"]').click(); cy.fill_field("title", "Test Block Page", "Data"); - cy.fill_field("icon", "edit", "Icon"); cy.get_open_dialog().find(".modal-header").click(); cy.get_open_dialog().find(".btn-primary").click(); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index a2d0eb2698..50d86d42b1 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -37,22 +37,16 @@ Cypress.Commands.add("login", (email, password) => { // cy.session clears all localStorage on new login, so we need to retain the last route const session_last_route = window.localStorage.getItem("session_last_route"); return cy - .session( - [email, password] || "", - () => { - return cy.request({ - url: "/api/method/login", - method: "POST", - body: { - usr: email, - pwd: password, - }, - }); - }, - { - cacheAcrossSpecs: true, - } - ) + .session([email, password] || "", () => { + return cy.request({ + url: "/api/method/login", + method: "POST", + body: { + usr: email, + pwd: password, + }, + }); + }) .then(() => { if (session_last_route) { window.localStorage.setItem("session_last_route", session_last_route); diff --git a/frappe/commands/site.py b/frappe/commands/site.py index a833431142..28d6cac695 100644 --- a/frappe/commands/site.py +++ b/frappe/commands/site.py @@ -48,6 +48,11 @@ from frappe.exceptions import SiteNotSpecifiedError @click.option( "--set-default", is_flag=True, default=False, help="Set the new site as default site" ) +@click.option( + "--setup-db/--no-setup-db", + default=True, + help="Create user and database in mariadb/postgres; only bootstrap if false", +) def new_site( site, db_root_username=None, @@ -64,6 +69,7 @@ def new_site( db_host=None, db_port=None, set_default=False, + setup_db=True, ): "Create a new site" from frappe.installer import _new_site, extract_sql_from_archive @@ -88,6 +94,7 @@ def new_site( db_type=db_type, db_host=db_host, db_port=db_port, + setup_db=setup_db, ) if set_default: diff --git a/frappe/core/doctype/communication/communication.py b/frappe/core/doctype/communication/communication.py index 0e089edb6c..9000901be2 100644 --- a/frappe/core/doctype/communication/communication.py +++ b/frappe/core/doctype/communication/communication.py @@ -162,8 +162,6 @@ class Communication(Document, CommunicationEmailMixin): self.seen = 1 self.sent_or_received = "Sent" - self.set_status() - validate_email(self) if self.communication_medium == "Email": @@ -173,6 +171,10 @@ class Communication(Document, CommunicationEmailMixin): self.set_sender_full_name() + if self.is_new(): + self.set_status() + self.mark_email_as_spam() + def validate_reference(self): if self.reference_doctype and self.reference_name: if not self.reference_owner: @@ -333,9 +335,6 @@ class Communication(Document, CommunicationEmailMixin): ) def set_status(self): - if not self.is_new(): - return - if self.reference_doctype and self.reference_name: self.status = "Linked" elif self.communication_type == "Communication": @@ -343,15 +342,13 @@ class Communication(Document, CommunicationEmailMixin): else: self.status = "Closed" - # set email status to spam - email_rule = frappe.db.get_value("Email Rule", {"email_id": self.sender, "is_spam": 1}) + def mark_email_as_spam(self): if ( self.communication_type == "Communication" and self.communication_medium == "Email" - and self.sent_or_received == "Sent" - and email_rule + and self.sent_or_received == "Received" + and frappe.db.exists("Email Rule", {"email_id": self.sender, "is_spam": 1}) ): - self.email_status = "Spam" @classmethod @@ -433,7 +430,18 @@ class Communication(Document, CommunicationEmailMixin): frappe.db.commit() def parse_email_for_timeline_links(self): - parse_email(self, [self.recipients, self.cc, self.bcc]) + if not frappe.db.get_value("Email Account", self.email_account, "enable_automatic_linking"): + return + + for doctype, docname in parse_email([self.recipients, self.cc, self.bcc]): + if not frappe.db.get_value(doctype, docname, ignore=True): + continue + + self.add_link(doctype, docname) + + if not self.reference_doctype: + self.reference_doctype = doctype + self.reference_name = docname # Timeline Links def set_timeline_links(self): @@ -452,20 +460,13 @@ class Communication(Document, CommunicationEmailMixin): add_contact_links_to_communication(self, contact_name) def deduplicate_timeline_links(self): - if self.timeline_links: - links, duplicate = [], False + if not self.timeline_links: + return - for l in self.timeline_links: - t = (l.link_doctype, l.link_name) - if not t in links: - links.append(t) - else: - duplicate = True - - if duplicate: - self.timeline_links.clear() - for l in links: - self.add_link(link_doctype=l[0], link_name=l[1]) + unique_links = {(link.link_doctype, link.link_name) for link in self.timeline_links} + self.timeline_links = [] + for doctype, name in unique_links: + self.add_link(doctype, name) def add_link(self, link_doctype, link_name, autosave=False): self.append("timeline_links", {"link_doctype": link_doctype, "link_name": link_name}) @@ -574,36 +575,35 @@ def add_contact_links_to_communication(communication, contact_name): communication.add_link(contact_link.link_doctype, contact_link.link_name) -def parse_email(communication, email_strings): +def parse_email(email_strings): """ Parse email to add timeline links. When automatic email linking is enabled, an email from email_strings can contain a doctype and docname ie in the format `admin+doctype+docname@example.com` or `admin+doctype=docname@example.com`, - the email is parsed and doctype and docname is extracted and timeline link is added. + the email is parsed and doctype and docname is extracted. """ - if not frappe.db.get_value("Email Account", filters={"enable_automatic_linking": 1}): - return - for email_string in email_strings: - if email_string: - for email in email_string.split(","): - email_username = email.split("@", 1)[0] - email_local_parts = email_username.split("+") - docname = doctype = None - if len(email_local_parts) == 3: - doctype = unquote(email_local_parts[1]) - docname = unquote(email_local_parts[2]) + if not email_string: + continue - elif len(email_local_parts) == 2: - document_parts = email_local_parts[1].split("=", 1) - if len(document_parts) != 2: - continue + for email in email_string.split(","): + email_username = email.split("@", 1)[0] + email_local_parts = email_username.split("+") + docname = doctype = None + if len(email_local_parts) == 3: + doctype = unquote(email_local_parts[1]) + docname = unquote(email_local_parts[2]) - doctype = unquote(document_parts[0]) - docname = unquote(document_parts[1]) + elif len(email_local_parts) == 2: + document_parts = email_local_parts[1].split("=", 1) + if len(document_parts) != 2: + continue - if doctype and docname and frappe.db.get_value(doctype, docname, ignore=True): - communication.add_link(doctype, docname) + doctype = unquote(document_parts[0]) + docname = unquote(document_parts[1]) + + if doctype and docname: + yield doctype, docname def get_email_without_link(email): diff --git a/frappe/core/doctype/communication/test_communication.py b/frappe/core/doctype/communication/test_communication.py index 90b2c624ec..bab2d2e019 100644 --- a/frappe/core/doctype/communication/test_communication.py +++ b/frappe/core/doctype/communication/test_communication.py @@ -1,10 +1,9 @@ # Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors # License: MIT. See LICENSE from typing import TYPE_CHECKING -from urllib.parse import quote import frappe -from frappe.core.doctype.communication.communication import Communication, get_emails +from frappe.core.doctype.communication.communication import Communication, get_emails, parse_email from frappe.core.doctype.communication.email import add_attachments from frappe.email.doctype.email_queue.email_queue import EmailQueue from frappe.tests.utils import FrappeTestCase @@ -219,36 +218,25 @@ class TestCommunication(FrappeTestCase): self.assertIn(comm_note_1.name, data) self.assertIn(comm_note_2.name, data) - def test_link_in_email(self): - create_email_account() + def test_parse_email(self): + to = "Jon Doe " + cc = """=?UTF-8?Q?Max_Mu=C3=9F?= , + erp+Customer+that%20company@example.org""" + bcc = "" - notes = {} - for i in range(2): - frappe.delete_doc_if_exists("Note", f"test document link in email {i}") - notes[i] = frappe.get_doc( - { - "doctype": "Note", - "title": f"test document link in email {i}", - } - ).insert(ignore_permissions=True) + results = list(parse_email([to, cc, bcc])) + self.assertEqual([("Customer", "that company")], results) - comm = frappe.get_doc( - { - "doctype": "Communication", - "communication_medium": "Email", - "subject": "Document Link in Email", - "sender": "comm_sender@example.com", - "recipients": f'comm_recipient+{quote("Note")}+{quote(notes[0].name)}@example.com,comm_recipient+{quote("Note")}={quote(notes[1].name)}@example.com', - } - ).insert(ignore_permissions=True) + results = list(parse_email([to, bcc])) + self.assertEqual(results, []) - doc_links = [ - (timeline_link.link_doctype, timeline_link.link_name) for timeline_link in comm.timeline_links - ] - self.assertIn(("Note", notes[0].name), doc_links) - self.assertIn(("Note", notes[1].name), doc_links) + to = "jane.doe+A+Test@example.org" + cc = "" + bcc = "=?UTF-8?Q?Max_Mu=C3=9F?= " + results = list(parse_email([to, cc, bcc])) + self.assertEqual([("A", "Test"), ("Note", "Very important")], results) - def test_parse_emails(self): + def test_get_emails(self): emails = get_emails( [ "comm_recipient+DocType+DocName@example.com", @@ -293,6 +281,40 @@ class TestCommunication(FrappeTestCase): self.assertEqual(comm_with_signature.content.count(signature), 1) self.assertEqual(comm_without_signature.content.count(signature), 1) + def test_mark_as_spam(self): + frappe.get_doc( + { + "doctype": "Email Rule", + "email_id": "spammer@example.com", + "is_spam": 1, + } + ).insert(ignore_permissions=True) + + spam_comm: Communication = frappe.get_doc( + { + "doctype": "Communication", + "communication_medium": "Email", + "subject": "This is spam", + "sender": "spammer@example.com", + "recipients": "comm_recipient@example.com", + "sent_or_received": "Received", + } + ).insert(ignore_permissions=True) + + self.assertEqual(spam_comm.email_status, "Spam") + + normal_comm: Communication = frappe.get_doc( + { + "doctype": "Communication", + "communication_medium": "Email", + "subject": "This is spam", + "sender": "friendlyhuman@example.com", + "recipients": "comm_recipient@example.com", + "sent_or_received": "Received", + } + ).insert(ignore_permissions=True) + self.assertNotEqual(normal_comm.email_status, "Spam") + class TestCommunicationEmailMixin(FrappeTestCase): def new_communication(self, recipients=None, cc=None, bcc=None) -> Communication: diff --git a/frappe/core/doctype/docfield/docfield.json b/frappe/core/doctype/docfield/docfield.json index 6b8469bd48..f67969f43e 100644 --- a/frappe/core/doctype/docfield/docfield.json +++ b/frappe/core/doctype/docfield/docfield.json @@ -23,6 +23,7 @@ "options", "sort_options", "show_dashboard", + "link_filters", "defaults_section", "default", "column_break_6", @@ -560,13 +561,18 @@ "fieldname": "sort_options", "fieldtype": "Check", "label": "Sort Options" + }, + { + "fieldname": "link_filters", + "fieldtype": "JSON", + "label": "Link Filters" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-10-25 06:53:45.194081", + "modified": "2023-11-13 11:48:51.502812", "modified_by": "Administrator", "module": "Core", "name": "DocField", diff --git a/frappe/core/doctype/docfield/docfield.py b/frappe/core/doctype/docfield/docfield.py index c4067646e6..351dd0caae 100644 --- a/frappe/core/doctype/docfield/docfield.py +++ b/frappe/core/doctype/docfield/docfield.py @@ -87,6 +87,7 @@ class DocField(Document): is_virtual: DF.Check label: DF.Data | None length: DF.Int + link_filters: DF.JSON | None mandatory_depends_on: DF.Code | None max_height: DF.Data | None no_copy: DF.Check diff --git a/frappe/core/doctype/doctype/doctype.py b/frappe/core/doctype/doctype/doctype.py index 7b5c58dedd..c3a1aa0e41 100644 --- a/frappe/core/doctype/doctype/doctype.py +++ b/frappe/core/doctype/doctype/doctype.py @@ -136,6 +136,7 @@ class DocType(Document): is_virtual: DF.Check issingle: DF.Check istable: DF.Check + link_filters: DF.JSON links: DF.Table[DocTypeLink] make_attachments_public: DF.Check max_attachments: DF.Int diff --git a/frappe/core/doctype/doctype/doctype_list.js b/frappe/core/doctype/doctype/doctype_list.js index 963e863380..56f345420f 100644 --- a/frappe/core/doctype/doctype/doctype_list.js +++ b/frappe/core/doctype/doctype/doctype_list.js @@ -101,6 +101,7 @@ frappe.listview_settings["DocType"] = { role: "System Manager", share: 1, write: 1, + submit: values.is_submittable ? 1 : 0, }, ], fields: [{ fieldtype: "Section Break" }], diff --git a/frappe/core/doctype/file/utils.py b/frappe/core/doctype/file/utils.py index 3bb69e72ac..9795c73d9e 100644 --- a/frappe/core/doctype/file/utils.py +++ b/frappe/core/doctype/file/utils.py @@ -376,7 +376,7 @@ def relink_files(doc, fieldname, temp_doc_name): "attached_to_field": fieldname, "creation": ( "between", - [now_datetime() - add_to_date(date=now_datetime(), minutes=-60), now_datetime()], + [add_to_date(date=now_datetime(), minutes=-60), now_datetime()], ), }, ) diff --git a/frappe/core/doctype/rq_job/rq_job.py b/frappe/core/doctype/rq_job/rq_job.py index b6a6f99b57..453a375a5a 100644 --- a/frappe/core/doctype/rq_job/rq_job.py +++ b/frappe/core/doctype/rq_job/rq_job.py @@ -87,7 +87,9 @@ class RQJob(Document): matched_job_ids = RQJob.get_matching_job_ids(args)[start : start + page_length] conn = get_redis_conn() - jobs = [serialize_job(job) for job in Job.fetch_many(job_ids=matched_job_ids, connection=conn)] + jobs = [ + serialize_job(job) for job in Job.fetch_many(job_ids=matched_job_ids, connection=conn) if job + ] return sorted(jobs, key=lambda j: j.modified, reverse=order_desc) diff --git a/frappe/custom/doctype/custom_field/custom_field.json b/frappe/custom/doctype/custom_field/custom_field.json index 53a003c88e..332969b036 100644 --- a/frappe/custom/doctype/custom_field/custom_field.json +++ b/frappe/custom/doctype/custom_field/custom_field.json @@ -15,6 +15,7 @@ "fieldname", "insert_after", "length", + "link_filters", "column_break_6", "fieldtype", "precision", @@ -444,6 +445,12 @@ "fieldname": "sort_options", "fieldtype": "Check", "label": "Sort Options" + }, + { + "fieldname": "link_filters", + "fieldtype": "JSON", + "hidden": 1, + "label": "Link Filters" } ], "icon": "fa fa-glass", diff --git a/frappe/custom/doctype/custom_field/custom_field.py b/frappe/custom/doctype/custom_field/custom_field.py index a1aa4fd342..c77d2f4bb2 100644 --- a/frappe/custom/doctype/custom_field/custom_field.py +++ b/frappe/custom/doctype/custom_field/custom_field.py @@ -94,6 +94,7 @@ class CustomField(Document): is_virtual: DF.Check label: DF.Data | None length: DF.Int + link_filters: DF.JSON | None mandatory_depends_on: DF.Code | None module: DF.Link | None no_copy: DF.Check diff --git a/frappe/custom/doctype/customize_form/customize_form.js b/frappe/custom/doctype/customize_form/customize_form.js index c2e2e83d7f..c64d690fbc 100644 --- a/frappe/custom/doctype/customize_form/customize_form.js +++ b/frappe/custom/doctype/customize_form/customize_form.js @@ -149,6 +149,7 @@ frappe.ui.form.on("Customize Form", { ); render_form_builder(frm); + frm.get_field("form_builder").tab.set_active(); }); } diff --git a/frappe/custom/doctype/customize_form/customize_form.json b/frappe/custom/doctype/customize_form/customize_form.json index 32fd3302ec..aad7a59b37 100644 --- a/frappe/custom/doctype/customize_form/customize_form.json +++ b/frappe/custom/doctype/customize_form/customize_form.json @@ -7,10 +7,12 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "details_tab", "doc_type", "properties", "label", "search_fields", + "link_filters", "column_break_5", "istable", "is_calendar_and_gantt", @@ -24,17 +26,6 @@ "naming_section", "naming_rule", "autoname", - "document_actions_section", - "actions", - "document_links_section", - "links", - "document_states_section", - "states", - "form_tab", - "form_builder", - "fields_section_break", - "fields", - "settings_tab", "form_settings_section", "image_field", "max_attachments", @@ -59,7 +50,17 @@ "section_break_8", "sort_field", "column_break_10", - "sort_order" + "sort_order", + "document_actions_section", + "actions", + "document_links_section", + "links", + "document_states_section", + "states", + "fields_section_break", + "fields", + "form_tab", + "form_builder" ], "fields": [ { @@ -180,7 +181,6 @@ "depends_on": "doc_type", "fieldname": "fields_section_break", "fieldtype": "Section Break", - "hidden": 1, "label": "Fields" }, { @@ -372,11 +372,6 @@ "fieldtype": "Check", "label": "Is Calendar and Gantt" }, - { - "fieldname": "settings_tab", - "fieldtype": "Tab Break", - "label": "Settings" - }, { "fieldname": "form_builder", "fieldtype": "HTML", @@ -386,6 +381,17 @@ "fieldname": "form_tab", "fieldtype": "Tab Break", "label": "Form" + }, + { + "fieldname": "link_filters", + "fieldtype": "JSON", + "hidden": 1, + "label": "Link Filters" + }, + { + "fieldname": "details_tab", + "fieldtype": "Tab Break", + "label": "Details" } ], "hide_toolbar": 1, @@ -394,7 +400,7 @@ "index_web_pages_for_search": 1, "issingle": 1, "links": [], - "modified": "2023-10-31 02:04:25.955931", + "modified": "2023-11-16 11:23:06.427432", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form", diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 730d3dfc6c..34933978a6 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -54,6 +54,7 @@ class CustomizeForm(Document): is_calendar_and_gantt: DF.Check istable: DF.Check label: DF.Data | None + link_filters: DF.JSON | None links: DF.Table[DocTypeLink] make_attachments_public: DF.Check max_attachments: DF.Int @@ -681,6 +682,17 @@ def is_standard_or_system_generated_field(df): return not df.get("is_custom_field") or df.get("is_system_generated") +@frappe.whitelist() +def get_link_filters_from_doc_without_customisations(doctype, fieldname): + """Get the filters of a link field from a doc without customisations + In backend the customisations are not applied. + Customisations are applied in the client side. + """ + doc = frappe.get_doc("DocType", doctype) + field = list(filter(lambda x: x.fieldname == fieldname, doc.fields)) + return field[0].link_filters + + doctype_properties = { "search_fields": "Data", "title_field": "Data", @@ -761,6 +773,7 @@ docfield_properties = { "hide_days": "Check", "hide_seconds": "Check", "is_virtual": "Check", + "link_filters": "JSON", } doctype_link_properties = { diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index fa86df2735..aebb143677 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -24,6 +24,7 @@ "no_copy", "allow_in_quick_entry", "translatable", + "link_filters", "column_break_7", "default", "precision", @@ -471,13 +472,18 @@ "fieldname": "sort_options", "fieldtype": "Check", "label": "Sort Options" + }, + { + "fieldname": "link_filters", + "fieldtype": "JSON", + "label": "Link Filters" } ], "idx": 1, "index_web_pages_for_search": 1, "istable": 1, "links": [], - "modified": "2023-10-25 06:55:50.718441", + "modified": "2023-11-07 13:17:21.373626", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.py b/frappe/custom/doctype/customize_form_field/customize_form_field.py index 1afb5ad34b..59b0155a98 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.py +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.py @@ -86,6 +86,7 @@ class CustomizeFormField(Document): is_virtual: DF.Check label: DF.Data | None length: DF.Int + link_filters: DF.JSON | None mandatory_depends_on: DF.Code | None no_copy: DF.Check non_negative: DF.Check diff --git a/frappe/database/__init__.py b/frappe/database/__init__.py index 76ad24b6e6..6fa92e5282 100644 --- a/frappe/database/__init__.py +++ b/frappe/database/__init__.py @@ -7,21 +7,34 @@ from frappe.database.database import savepoint -def setup_database(force, source_sql=None, verbose=None, no_mariadb_socket=False): +def setup_database(force, verbose=None, no_mariadb_socket=False): import frappe if frappe.conf.db_type == "postgres": import frappe.database.postgres.setup_db - return frappe.database.postgres.setup_db.setup_database(force, source_sql, verbose) + return frappe.database.postgres.setup_db.setup_database() else: import frappe.database.mariadb.setup_db return frappe.database.mariadb.setup_db.setup_database( - force, source_sql, verbose, no_mariadb_socket=no_mariadb_socket + force, verbose, no_mariadb_socket=no_mariadb_socket ) +def bootstrap_database(db_name, verbose=None, source_sql=None): + import frappe + + if frappe.conf.db_type == "postgres": + import frappe.database.postgres.setup_db + + return frappe.database.postgres.setup_db.bootstrap_database(db_name, verbose, source_sql) + else: + import frappe.database.mariadb.setup_db + + return frappe.database.mariadb.setup_db.bootstrap_database(db_name, verbose, source_sql) + + def drop_user_and_database(db_name, root_login=None, root_password=None): import frappe diff --git a/frappe/database/mariadb/setup_db.py b/frappe/database/mariadb/setup_db.py index 87a7f6d343..4cc11988f8 100644 --- a/frappe/database/mariadb/setup_db.py +++ b/frappe/database/mariadb/setup_db.py @@ -23,7 +23,7 @@ def get_mariadb_version(version_string: str = ""): return version.rsplit(".", 1) -def setup_database(force, source_sql, verbose, no_mariadb_socket=False): +def setup_database(force, verbose, no_mariadb_socket=False): frappe.local.session = frappe._dict({"user": "Administrator"}) db_name = frappe.local.conf.db_name @@ -55,8 +55,6 @@ def setup_database(force, source_sql, verbose, no_mariadb_socket=False): # close root connection root_conn.close() - bootstrap_database(db_name, verbose, source_sql) - def drop_user_and_database(db_name, root_login, root_password): frappe.local.db = get_root_connection(root_login, root_password) @@ -75,8 +73,8 @@ def bootstrap_database(db_name, verbose, source_sql=None): sys.exit(1) import_db_from_sql(source_sql, verbose) - frappe.connect(db_name=db_name) + if "tabDefaultValue" not in frappe.db.get_tables(cached=False): from click import secho diff --git a/frappe/database/postgres/database.py b/frappe/database/postgres/database.py index edb2dc745a..f0a75e2e68 100644 --- a/frappe/database/postgres/database.py +++ b/frappe/database/postgres/database.py @@ -160,11 +160,16 @@ class PostgresDatabase(PostgresExceptionUtil, Database): return LazyDecode(self._cursor.query) def get_connection(self): - conn = psycopg2.connect( - "host='{}' dbname='{}' user='{}' password='{}' port={}".format( - self.host, self.user, self.user, self.password, self.port - ) - ) + conn_settings = { + "user": self.user, + "dbname": self.user, + "host": self.host, + "password": self.password, + } + if self.port: + conn_settings["port"] = self.port + + conn = psycopg2.connect(**conn_settings) conn.set_isolation_level(ISOLATION_LEVEL_REPEATABLE_READ) return conn diff --git a/frappe/database/postgres/setup_db.py b/frappe/database/postgres/setup_db.py index 9d1d045b04..bf0cf5cef4 100644 --- a/frappe/database/postgres/setup_db.py +++ b/frappe/database/postgres/setup_db.py @@ -3,7 +3,7 @@ import os import frappe -def setup_database(force, source_sql=None, verbose=False): +def setup_database(): root_conn = get_root_connection(frappe.flags.root_login, frappe.flags.root_password) root_conn.commit() root_conn.sql("end") @@ -14,9 +14,6 @@ def setup_database(force, source_sql=None, verbose=False): root_conn.sql("GRANT ALL PRIVILEGES ON DATABASE `{0}` TO {0}".format(frappe.conf.db_name)) root_conn.close() - bootstrap_database(frappe.conf.db_name, verbose, source_sql=source_sql) - frappe.connect() - def bootstrap_database(db_name, verbose, source_sql=None): frappe.connect(db_name=db_name) diff --git a/frappe/desk/reportview.py b/frappe/desk/reportview.py index fd299af819..8f2f7f8dca 100644 --- a/frappe/desk/reportview.py +++ b/frappe/desk/reportview.py @@ -215,12 +215,12 @@ def clean_params(data): def parse_json(data): - if isinstance(data.get("filters"), str): - data["filters"] = json.loads(data["filters"]) - if isinstance(data.get("or_filters"), str): - data["or_filters"] = json.loads(data["or_filters"]) - if isinstance(data.get("fields"), str): - data["fields"] = ["*"] if data["fields"] == "*" else json.loads(data["fields"]) + if (filters := data.get("filters")) and isinstance(filters, str): + data["filters"] = json.loads(filters) + if (or_filters := data.get("or_filters")) and isinstance(or_filters, str): + data["or_filters"] = json.loads(or_filters) + if (fields := data.get("fields")) and isinstance(fields, str): + data["fields"] = ["*"] if fields == "*" else json.loads(fields) if isinstance(data.get("docstatus"), str): data["docstatus"] = json.loads(data["docstatus"]) if isinstance(data.get("save_user_settings"), str): diff --git a/frappe/email/doctype/email_group/email_group.py b/frappe/email/doctype/email_group/email_group.py index 7afd349804..c866beebee 100755 --- a/frappe/email/doctype/email_group/email_group.py +++ b/frappe/email/doctype/email_group/email_group.py @@ -123,6 +123,5 @@ def send_welcome_email(welcome_email, email, email_group): return args = dict(email=email, email_group=email_group) - email_message = welcome_email.response or welcome_email.response_html - message = frappe.render_template(email_message, args) + message = frappe.render_template(welcome_email.response_, args) frappe.sendmail(email, subject=welcome_email.subject, message=message) diff --git a/frappe/email/doctype/newsletter/newsletter_list.js b/frappe/email/doctype/newsletter/newsletter_list.js index 0921de02b4..71e9423b7e 100644 --- a/frappe/email/doctype/newsletter/newsletter_list.js +++ b/frappe/email/doctype/newsletter/newsletter_list.js @@ -2,11 +2,11 @@ frappe.listview_settings["Newsletter"] = { add_fields: ["subject", "email_sent", "schedule_sending"], get_indicator: function (doc) { if (doc.email_sent) { - return [__("Sent"), "green", "email_sent,=,Yes"]; + return [__("Sent"), "green", "email_sent,=,1"]; } else if (doc.schedule_sending) { - return [__("Scheduled"), "purple", "email_sent,=,No|schedule_sending,=,Yes"]; + return [__("Scheduled"), "purple", "email_sent,=,0|schedule_sending,=,1"]; } else { - return [__("Not Sent"), "gray", "email_sent,=,No"]; + return [__("Not Sent"), "gray", "email_sent,=,0"]; } }, }; diff --git a/frappe/email/receive.py b/frappe/email/receive.py index 0d1e7393c3..381d43a124 100644 --- a/frappe/email/receive.py +++ b/frappe/email/receive.py @@ -220,6 +220,9 @@ class EmailServer: ).where(Communication.email_account == self.settings.email_account).run() if self.settings.use_imap: + # Remove {"} quotes that are added to handle spaces in IMAP Folder names + if folder[0] == folder[-1] == '"': + folder = folder[1:-2] # new update for the IMAP Folder DocType IMAPFolder = frappe.qb.DocType("IMAP Folder") frappe.qb.update(IMAPFolder).set(IMAPFolder.uidvalidity, current_uid_validity).set( diff --git a/frappe/installer.py b/frappe/installer.py index 93facf2b0e..5d807f0405 100644 --- a/frappe/installer.py +++ b/frappe/installer.py @@ -48,6 +48,7 @@ def _new_site( db_type=None, db_host=None, db_port=None, + setup_db=True, ): """Install a new Frappe site""" @@ -91,6 +92,7 @@ def _new_site( db_host=db_host, db_port=db_port, no_mariadb_socket=no_mariadb_socket, + setup=setup_db, ) apps_to_install = ( @@ -128,9 +130,10 @@ def install_db( db_host=None, db_port=None, no_mariadb_socket=False, + setup=True, ): import frappe.database - from frappe.database import setup_database + from frappe.database import bootstrap_database, setup_database if not db_type: db_type = frappe.conf.db_type @@ -152,7 +155,15 @@ def install_db( frappe.flags.root_login = root_login frappe.flags.root_password = root_password - setup_database(force, source_sql, verbose, no_mariadb_socket) + + if setup: + setup_database(force, verbose, no_mariadb_socket) + + bootstrap_database( + db_name=frappe.conf.db_name, + verbose=verbose, + source_sql=source_sql, + ) frappe.conf.admin_password = frappe.conf.admin_password or admin_password diff --git a/frappe/integrations/doctype/integration_request/integration_request.py b/frappe/integrations/doctype/integration_request/integration_request.py index c3cd8d061c..a81e702dfc 100644 --- a/frappe/integrations/doctype/integration_request/integration_request.py +++ b/frappe/integrations/doctype/integration_request/integration_request.py @@ -4,7 +4,7 @@ import json import frappe -from frappe.integrations.utils import json_handler +from frappe.integrations.utils import get_json, json_handler from frappe.model.document import Document @@ -45,7 +45,7 @@ class IntegrationRequest(Document): data = json.loads(self.data) data.update(params) - self.data = json.dumps(data) + self.data = get_json(data) self.status = status self.save(ignore_permissions=True) frappe.db.commit() diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index 3f43f2a5f2..ade401a83c 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -69,9 +69,25 @@ def get_mapped_doc( # main if not target_doc: - target_doc = frappe.new_doc(table_maps[from_doctype]["doctype"]) + target_doctype = table_maps[from_doctype]["doctype"] + if table_maps[from_doctype].get("on_parent"): + target_parent = table_maps[from_doctype].get("on_parent") + if isinstance(target_parent, str): + target_parent = frappe.get_doc(json.loads(target_parent)) + target_parentfield = target_parent.get_parentfield_of_doctype(target_doctype) + target_doc = frappe.new_doc( + target_doctype, parent_doc=target_parent, parentfield=target_parentfield + ) + target_parent.append(target_parentfield, target_doc) + ret_doc = target_parent + else: + target_doc = frappe.new_doc(target_doctype) + ret_doc = target_doc elif isinstance(target_doc, str): target_doc = frappe.get_doc(json.loads(target_doc)) + ret_doc = target_doc + else: + ret_doc = target_doc if ( not apply_strict_user_permissions @@ -147,16 +163,14 @@ def get_mapped_doc( if postprocess: postprocess(source_doc, target_doc) - target_doc.set_onload("load_after_mapping", True) + ret_doc.set_onload("load_after_mapping", True) if ( - apply_strict_user_permissions - and not ignore_permissions - and not target_doc.has_permission("create") + apply_strict_user_permissions and not ignore_permissions and not ret_doc.has_permission("create") ): - target_doc.raise_no_permission_to("create") + ret_doc.raise_no_permission_to("create") - return target_doc + return ret_doc def map_doc(source_doc, target_doc, table_map, source_parent=None): diff --git a/frappe/model/rename_doc.py b/frappe/model/rename_doc.py index 11821ffb19..e6cc83874d 100644 --- a/frappe/model/rename_doc.py +++ b/frappe/model/rename_doc.py @@ -201,8 +201,9 @@ def rename_doc( # call after_rename new_doc = frappe.get_doc(doctype, new) - # copy any flags if required - new_doc._local = getattr(old_doc, "_local", None) + if validate: + # copy any flags if required + new_doc._local = getattr(old_doc, "_local", None) new_doc.run_method("after_rename", old, new, merge) diff --git a/frappe/model/utils/rename_field.py b/frappe/model/utils/rename_field.py index c17d01183b..e3b0835ddd 100644 --- a/frappe/model/utils/rename_field.py +++ b/frappe/model/utils/rename_field.py @@ -8,19 +8,21 @@ from frappe.model.utils.user_settings import sync_user_settings, update_user_set from frappe.utils.password import rename_password_field -def rename_field(doctype, old_fieldname, new_fieldname): +def rename_field(doctype, old_fieldname, new_fieldname, validate=True): """This functions assumes that doctype is already synced""" meta = frappe.get_meta(doctype, cached=False) new_field = meta.get_field(new_fieldname) - if not new_field: - print("rename_field: " + (new_fieldname) + " not found in " + doctype) - return - if not meta.issingle and not frappe.db.has_column(doctype, old_fieldname): - print("rename_field: " + (old_fieldname) + " not found in table for: " + doctype) - # never had the field? - return + if validate: + if not new_field: + print("rename_field: " + (new_fieldname) + " not found in " + doctype) + return + + if not meta.issingle and not frappe.db.has_column(doctype, old_fieldname): + print("rename_field: " + (old_fieldname) + " not found in table for: " + doctype) + # never had the field? + return if new_field.fieldtype in table_fields: # change parentfield of table mentioned in options diff --git a/frappe/public/css/fonts/inter/inter.scss b/frappe/public/css/fonts/inter/inter.scss index d3565415a3..705fe2badd 100644 --- a/frappe/public/css/fonts/inter/inter.scss +++ b/frappe/public/css/fonts/inter/inter.scss @@ -1,164 +1,167 @@ // TODO instead of making copy of inter.css find a way to import it. // workaround for css import as it fails for custom website_theme_template @font-face { - font-family: 'Inter V'; + font-family: "Inter V"; font-weight: 100 900; font-display: swap; font-style: normal; - src: url('/assets/frappe/css/fonts/inter/Inter.var.woff2?v=3.19') format('woff2-variations'), - url('/assets/frappe/css/fonts/inter/Inter.var.woff2?v=3.19') format('woff2'); - src: url('/assets/frappe/css/fonts/inter/Inter.var.woff2?v=3.19') format('woff2') tech('variations'); - } - @font-face { - font-family: 'Inter V'; + src: url("/assets/frappe/css/fonts/inter/Inter.var.woff2?v=3.19") format("woff2-variations"), + url("/assets/frappe/css/fonts/inter/Inter.var.woff2?v=3.19") format("woff2"); + src: url("/assets/frappe/css/fonts/inter/Inter.var.woff2?v=3.19") format("woff2") + tech("variations"); +} +@font-face { + font-family: "Inter V"; font-weight: 100 900; font-display: swap; font-style: italic; - src: url('/assets/frappe/css/fonts/inter/Inter-Italic.var.woff2?v=3.19') format('woff2-variations'), - url('/assets/frappe/css/fonts/inter/Inter-Italic.var.woff2?v=3.19') format('woff2'); - src: url('/assets/frappe/css/fonts/inter/Inter-Italic.var.woff2?v=3.19') format('woff2') tech('variations'); - } + src: url("/assets/frappe/css/fonts/inter/Inter-Italic.var.woff2?v=3.19") + format("woff2-variations"), + url("/assets/frappe/css/fonts/inter/Inter-Italic.var.woff2?v=3.19") format("woff2"); + src: url("/assets/frappe/css/fonts/inter/Inter-Italic.var.woff2?v=3.19") format("woff2") + tech("variations"); +} @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 100; src: url("/assets/frappe/css/fonts/inter/inter_thinitalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_thinitalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_thinitalic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 200; src: url("/assets/frappe/css/fonts/inter/inter_extralight.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_extralight.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_extralight.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 200; src: url("/assets/frappe/css/fonts/inter/inter_extralightitalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_extralightitalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_extralightitalic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 300; src: url("/assets/frappe/css/fonts/inter/inter_light.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_light.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_light.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 300; src: url("/assets/frappe/css/fonts/inter/inter_lightitalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_lightitalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_lightitalic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 400; src: url("/assets/frappe/css/fonts/inter/inter_regular.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_regular.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_regular.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 400; src: url("/assets/frappe/css/fonts/inter/inter_italic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_italic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_italic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 500; src: url("/assets/frappe/css/fonts/inter/inter_medium.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_medium.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_medium.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 500; src: url("/assets/frappe/css/fonts/inter/inter_mediumitalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_mediumitalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_mediumitalic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 600; src: url("/assets/frappe/css/fonts/inter/inter_semibold.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_semibold.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_semibold.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 600; src: url("/assets/frappe/css/fonts/inter/inter_semibolditalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_semibolditalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_semibolditalic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 700; src: url("/assets/frappe/css/fonts/inter/inter_bold.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_bold.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_bold.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 700; src: url("/assets/frappe/css/fonts/inter/inter_bolditalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_bolditalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_bolditalic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 800; src: url("/assets/frappe/css/fonts/inter/inter_extrabold.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_extrabold.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_extrabold.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 800; src: url("/assets/frappe/css/fonts/inter/inter_extrabolditalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_extrabolditalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_extrabolditalic.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: normal; + font-style: normal; font-weight: 900; src: url("/assets/frappe/css/fonts/inter/inter_black.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_black.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_black.woff") format("woff"); } @font-face { - font-family: 'Inter'; + font-family: "Inter"; font-display: swap; - font-style: italic; + font-style: italic; font-weight: 900; src: url("/assets/frappe/css/fonts/inter/inter_blackitalic.woff2") format("woff2"), - url("/assets/frappe/css/fonts/inter/inter_blackitalic.woff") format("woff"); + url("/assets/frappe/css/fonts/inter/inter_blackitalic.woff") format("woff"); } diff --git a/frappe/public/css/octicons/octicons.scss b/frappe/public/css/octicons/octicons.scss index 0902cedce8..81e7d52d78 100755 --- a/frappe/public/css/octicons/octicons.scss +++ b/frappe/public/css/octicons/octicons.scss @@ -1,220 +1,548 @@ $octicons-font-path: "." !default; -$octicons-version: "396334ee3da78f4302d25c758ae3e3ce5dc3c97d"; +$octicons-version: "396334ee3da78f4302d25c758ae3e3ce5dc3c97d"; @font-face { - font-family: 'octicons'; - src: url('#{$octicons-font-path}/octicons.eot?#iefix&v=#{$octicons-version}') format('embedded-opentype'), - url('#{$octicons-font-path}/octicons.woff?v=#{$octicons-version}') format('woff'), - url('#{$octicons-font-path}/octicons.ttf?v=#{$octicons-version}') format('truetype'), - url('#{$octicons-font-path}/octicons.svg?v=#{$octicons-version}#octicons') format('svg'); - font-weight: normal; - font-style: normal; + font-family: "octicons"; + src: url("#{$octicons-font-path}/octicons.eot?#iefix&v=#{$octicons-version}") + format("embedded-opentype"), + url("#{$octicons-font-path}/octicons.woff?v=#{$octicons-version}") format("woff"), + url("#{$octicons-font-path}/octicons.ttf?v=#{$octicons-version}") format("truetype"), + url("#{$octicons-font-path}/octicons.svg?v=#{$octicons-version}#octicons") format("svg"); + font-weight: normal; + font-style: normal; } // .octicon is optimized for 16px. // .mega-octicon is optimized for 32px but can be used larger. -.octicon, .mega-octicon { - font: normal normal normal 16px/1 octicons; - display: inline-block; - text-decoration: none; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; +.octicon, +.mega-octicon { + font: normal normal normal 16px/1 octicons; + display: inline-block; + text-decoration: none; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.mega-octicon { + font-size: 32px; } -.mega-octicon { font-size: 32px; } -.octicon-alert:before { content: '\f02d'} /*  */ -.octicon-arrow-down:before { content: '\f03f'} /*  */ -.octicon-arrow-left:before { content: '\f040'} /*  */ -.octicon-arrow-right:before { content: '\f03e'} /*  */ -.octicon-arrow-small-down:before { content: '\f0a0'} /*  */ -.octicon-arrow-small-left:before { content: '\f0a1'} /*  */ -.octicon-arrow-small-right:before { content: '\f071'} /*  */ -.octicon-arrow-small-up:before { content: '\f09f'} /*  */ -.octicon-arrow-up:before { content: '\f03d'} /*  */ +.octicon-alert:before { + content: "\f02d"; +} /*  */ +.octicon-arrow-down:before { + content: "\f03f"; +} /*  */ +.octicon-arrow-left:before { + content: "\f040"; +} /*  */ +.octicon-arrow-right:before { + content: "\f03e"; +} /*  */ +.octicon-arrow-small-down:before { + content: "\f0a0"; +} /*  */ +.octicon-arrow-small-left:before { + content: "\f0a1"; +} /*  */ +.octicon-arrow-small-right:before { + content: "\f071"; +} /*  */ +.octicon-arrow-small-up:before { + content: "\f09f"; +} /*  */ +.octicon-arrow-up:before { + content: "\f03d"; +} /*  */ .octicon-microscope:before, -.octicon-beaker:before { content: '\f0dd'} /*  */ -.octicon-bell:before { content: '\f0de'} /*  */ -.octicon-book:before { content: '\f007'} /*  */ -.octicon-bookmark:before { content: '\f07b'} /*  */ -.octicon-briefcase:before { content: '\f0d3'} /*  */ -.octicon-broadcast:before { content: '\f048'} /*  */ -.octicon-browser:before { content: '\f0c5'} /*  */ -.octicon-bug:before { content: '\f091'} /*  */ -.octicon-calendar:before { content: '\f068'} /*  */ -.octicon-check:before { content: '\f03a'} /*  */ -.octicon-checklist:before { content: '\f076'} /*  */ -.octicon-chevron-down:before { content: '\f0a3'} /*  */ -.octicon-chevron-left:before { content: '\f0a4'} /*  */ -.octicon-chevron-right:before { content: '\f078'} /*  */ -.octicon-chevron-up:before { content: '\f0a2'} /*  */ -.octicon-circle-slash:before { content: '\f084'} /*  */ -.octicon-circuit-board:before { content: '\f0d6'} /*  */ -.octicon-clippy:before { content: '\f035'} /*  */ -.octicon-clock:before { content: '\f046'} /*  */ -.octicon-cloud-download:before { content: '\f00b'} /*  */ -.octicon-cloud-upload:before { content: '\f00c'} /*  */ -.octicon-code:before { content: '\f05f'} /*  */ -.octicon-color-mode:before { content: '\f065'} /*  */ +.octicon-beaker:before { + content: "\f0dd"; +} /*  */ +.octicon-bell:before { + content: "\f0de"; +} /*  */ +.octicon-book:before { + content: "\f007"; +} /*  */ +.octicon-bookmark:before { + content: "\f07b"; +} /*  */ +.octicon-briefcase:before { + content: "\f0d3"; +} /*  */ +.octicon-broadcast:before { + content: "\f048"; +} /*  */ +.octicon-browser:before { + content: "\f0c5"; +} /*  */ +.octicon-bug:before { + content: "\f091"; +} /*  */ +.octicon-calendar:before { + content: "\f068"; +} /*  */ +.octicon-check:before { + content: "\f03a"; +} /*  */ +.octicon-checklist:before { + content: "\f076"; +} /*  */ +.octicon-chevron-down:before { + content: "\f0a3"; +} /*  */ +.octicon-chevron-left:before { + content: "\f0a4"; +} /*  */ +.octicon-chevron-right:before { + content: "\f078"; +} /*  */ +.octicon-chevron-up:before { + content: "\f0a2"; +} /*  */ +.octicon-circle-slash:before { + content: "\f084"; +} /*  */ +.octicon-circuit-board:before { + content: "\f0d6"; +} /*  */ +.octicon-clippy:before { + content: "\f035"; +} /*  */ +.octicon-clock:before { + content: "\f046"; +} /*  */ +.octicon-cloud-download:before { + content: "\f00b"; +} /*  */ +.octicon-cloud-upload:before { + content: "\f00c"; +} /*  */ +.octicon-code:before { + content: "\f05f"; +} /*  */ +.octicon-color-mode:before { + content: "\f065"; +} /*  */ .octicon-comment-add:before, -.octicon-comment:before { content: '\f02b'} /*  */ -.octicon-comment-discussion:before { content: '\f04f'} /*  */ -.octicon-credit-card:before { content: '\f045'} /*  */ -.octicon-dash:before { content: '\f0ca'} /*  */ -.octicon-dashboard:before { content: '\f07d'} /*  */ -.octicon-database:before { content: '\f096'} /*  */ +.octicon-comment:before { + content: "\f02b"; +} /*  */ +.octicon-comment-discussion:before { + content: "\f04f"; +} /*  */ +.octicon-credit-card:before { + content: "\f045"; +} /*  */ +.octicon-dash:before { + content: "\f0ca"; +} /*  */ +.octicon-dashboard:before { + content: "\f07d"; +} /*  */ +.octicon-database:before { + content: "\f096"; +} /*  */ .octicon-clone:before, -.octicon-desktop-download:before { content: '\f0dc'} /*  */ -.octicon-device-camera:before { content: '\f056'} /*  */ -.octicon-device-camera-video:before { content: '\f057'} /*  */ -.octicon-device-desktop:before { content: '\f27c'} /*  */ -.octicon-device-mobile:before { content: '\f038'} /*  */ -.octicon-diff:before { content: '\f04d'} /*  */ -.octicon-diff-added:before { content: '\f06b'} /*  */ -.octicon-diff-ignored:before { content: '\f099'} /*  */ -.octicon-diff-modified:before { content: '\f06d'} /*  */ -.octicon-diff-removed:before { content: '\f06c'} /*  */ -.octicon-diff-renamed:before { content: '\f06e'} /*  */ -.octicon-ellipsis:before { content: '\f09a'} /*  */ +.octicon-desktop-download:before { + content: "\f0dc"; +} /*  */ +.octicon-device-camera:before { + content: "\f056"; +} /*  */ +.octicon-device-camera-video:before { + content: "\f057"; +} /*  */ +.octicon-device-desktop:before { + content: "\f27c"; +} /*  */ +.octicon-device-mobile:before { + content: "\f038"; +} /*  */ +.octicon-diff:before { + content: "\f04d"; +} /*  */ +.octicon-diff-added:before { + content: "\f06b"; +} /*  */ +.octicon-diff-ignored:before { + content: "\f099"; +} /*  */ +.octicon-diff-modified:before { + content: "\f06d"; +} /*  */ +.octicon-diff-removed:before { + content: "\f06c"; +} /*  */ +.octicon-diff-renamed:before { + content: "\f06e"; +} /*  */ +.octicon-ellipsis:before { + content: "\f09a"; +} /*  */ .octicon-eye-unwatch:before, .octicon-eye-watch:before, -.octicon-eye:before { content: '\f04e'} /*  */ -.octicon-file-binary:before { content: '\f094'} /*  */ -.octicon-file-code:before { content: '\f010'} /*  */ -.octicon-file-directory:before { content: '\f016'} /*  */ -.octicon-file-media:before { content: '\f012'} /*  */ -.octicon-file-pdf:before { content: '\f014'} /*  */ -.octicon-file-submodule:before { content: '\f017'} /*  */ -.octicon-file-symlink-directory:before { content: '\f0b1'} /*  */ -.octicon-file-symlink-file:before { content: '\f0b0'} /*  */ -.octicon-file-text:before { content: '\f011'} /*  */ -.octicon-file-zip:before { content: '\f013'} /*  */ -.octicon-flame:before { content: '\f0d2'} /*  */ -.octicon-fold:before { content: '\f0cc'} /*  */ -.octicon-gear:before { content: '\f02f'} /*  */ -.octicon-gift:before { content: '\f042'} /*  */ -.octicon-gist:before { content: '\f00e'} /*  */ -.octicon-gist-secret:before { content: '\f08c'} /*  */ +.octicon-eye:before { + content: "\f04e"; +} /*  */ +.octicon-file-binary:before { + content: "\f094"; +} /*  */ +.octicon-file-code:before { + content: "\f010"; +} /*  */ +.octicon-file-directory:before { + content: "\f016"; +} /*  */ +.octicon-file-media:before { + content: "\f012"; +} /*  */ +.octicon-file-pdf:before { + content: "\f014"; +} /*  */ +.octicon-file-submodule:before { + content: "\f017"; +} /*  */ +.octicon-file-symlink-directory:before { + content: "\f0b1"; +} /*  */ +.octicon-file-symlink-file:before { + content: "\f0b0"; +} /*  */ +.octicon-file-text:before { + content: "\f011"; +} /*  */ +.octicon-file-zip:before { + content: "\f013"; +} /*  */ +.octicon-flame:before { + content: "\f0d2"; +} /*  */ +.octicon-fold:before { + content: "\f0cc"; +} /*  */ +.octicon-gear:before { + content: "\f02f"; +} /*  */ +.octicon-gift:before { + content: "\f042"; +} /*  */ +.octicon-gist:before { + content: "\f00e"; +} /*  */ +.octicon-gist-secret:before { + content: "\f08c"; +} /*  */ .octicon-git-branch-create:before, .octicon-git-branch-delete:before, -.octicon-git-branch:before { content: '\f020'} /*  */ -.octicon-git-commit:before { content: '\f01f'} /*  */ -.octicon-git-compare:before { content: '\f0ac'} /*  */ -.octicon-git-merge:before { content: '\f023'} /*  */ +.octicon-git-branch:before { + content: "\f020"; +} /*  */ +.octicon-git-commit:before { + content: "\f01f"; +} /*  */ +.octicon-git-compare:before { + content: "\f0ac"; +} /*  */ +.octicon-git-merge:before { + content: "\f023"; +} /*  */ .octicon-git-pull-request-abandoned:before, -.octicon-git-pull-request:before { content: '\f009'} /*  */ -.octicon-globe:before { content: '\f0b6'} /*  */ -.octicon-graph:before { content: '\f043'} /*  */ -.octicon-heart:before { content: '\2665'} /* ♥ */ -.octicon-history:before { content: '\f07e'} /*  */ -.octicon-home:before { content: '\f08d'} /*  */ -.octicon-horizontal-rule:before { content: '\f070'} /*  */ -.octicon-hubot:before { content: '\f09d'} /*  */ -.octicon-inbox:before { content: '\f0cf'} /*  */ -.octicon-info:before { content: '\f059'} /*  */ -.octicon-issue-closed:before { content: '\f028'} /*  */ -.octicon-issue-opened:before { content: '\f026'} /*  */ -.octicon-issue-reopened:before { content: '\f027'} /*  */ -.octicon-jersey:before { content: '\f019'} /*  */ -.octicon-key:before { content: '\f049'} /*  */ -.octicon-keyboard:before { content: '\f00d'} /*  */ -.octicon-law:before { content: '\f0d8'} /*  */ -.octicon-light-bulb:before { content: '\f000'} /*  */ -.octicon-link:before { content: '\f05c'} /*  */ -.octicon-link-external:before { content: '\f07f'} /*  */ -.octicon-list-ordered:before { content: '\f062'} /*  */ -.octicon-list-unordered:before { content: '\f061'} /*  */ -.octicon-location:before { content: '\f060'} /*  */ +.octicon-git-pull-request:before { + content: "\f009"; +} /*  */ +.octicon-globe:before { + content: "\f0b6"; +} /*  */ +.octicon-graph:before { + content: "\f043"; +} /*  */ +.octicon-heart:before { + content: "\2665"; +} /* ♥ */ +.octicon-history:before { + content: "\f07e"; +} /*  */ +.octicon-home:before { + content: "\f08d"; +} /*  */ +.octicon-horizontal-rule:before { + content: "\f070"; +} /*  */ +.octicon-hubot:before { + content: "\f09d"; +} /*  */ +.octicon-inbox:before { + content: "\f0cf"; +} /*  */ +.octicon-info:before { + content: "\f059"; +} /*  */ +.octicon-issue-closed:before { + content: "\f028"; +} /*  */ +.octicon-issue-opened:before { + content: "\f026"; +} /*  */ +.octicon-issue-reopened:before { + content: "\f027"; +} /*  */ +.octicon-jersey:before { + content: "\f019"; +} /*  */ +.octicon-key:before { + content: "\f049"; +} /*  */ +.octicon-keyboard:before { + content: "\f00d"; +} /*  */ +.octicon-law:before { + content: "\f0d8"; +} /*  */ +.octicon-light-bulb:before { + content: "\f000"; +} /*  */ +.octicon-link:before { + content: "\f05c"; +} /*  */ +.octicon-link-external:before { + content: "\f07f"; +} /*  */ +.octicon-list-ordered:before { + content: "\f062"; +} /*  */ +.octicon-list-unordered:before { + content: "\f061"; +} /*  */ +.octicon-location:before { + content: "\f060"; +} /*  */ .octicon-gist-private:before, .octicon-mirror-private:before, .octicon-git-fork-private:before, -.octicon-lock:before { content: '\f06a'} /*  */ -.octicon-logo-github:before { content: '\f092'} /*  */ -.octicon-mail:before { content: '\f03b'} /*  */ -.octicon-mail-read:before { content: '\f03c'} /*  */ -.octicon-mail-reply:before { content: '\f051'} /*  */ -.octicon-mark-github:before { content: '\f00a'} /*  */ -.octicon-markdown:before { content: '\f0c9'} /*  */ -.octicon-megaphone:before { content: '\f077'} /*  */ -.octicon-mention:before { content: '\f0be'} /*  */ -.octicon-milestone:before { content: '\f075'} /*  */ +.octicon-lock:before { + content: "\f06a"; +} /*  */ +.octicon-logo-github:before { + content: "\f092"; +} /*  */ +.octicon-mail:before { + content: "\f03b"; +} /*  */ +.octicon-mail-read:before { + content: "\f03c"; +} /*  */ +.octicon-mail-reply:before { + content: "\f051"; +} /*  */ +.octicon-mark-github:before { + content: "\f00a"; +} /*  */ +.octicon-markdown:before { + content: "\f0c9"; +} /*  */ +.octicon-megaphone:before { + content: "\f077"; +} /*  */ +.octicon-mention:before { + content: "\f0be"; +} /*  */ +.octicon-milestone:before { + content: "\f075"; +} /*  */ .octicon-mirror-public:before, -.octicon-mirror:before { content: '\f024'} /*  */ -.octicon-mortar-board:before { content: '\f0d7'} /*  */ -.octicon-mute:before { content: '\f080'} /*  */ -.octicon-no-newline:before { content: '\f09c'} /*  */ -.octicon-octoface:before { content: '\f008'} /*  */ -.octicon-organization:before { content: '\f037'} /*  */ -.octicon-package:before { content: '\f0c4'} /*  */ -.octicon-paintcan:before { content: '\f0d1'} /*  */ -.octicon-pencil:before { content: '\f058'} /*  */ +.octicon-mirror:before { + content: "\f024"; +} /*  */ +.octicon-mortar-board:before { + content: "\f0d7"; +} /*  */ +.octicon-mute:before { + content: "\f080"; +} /*  */ +.octicon-no-newline:before { + content: "\f09c"; +} /*  */ +.octicon-octoface:before { + content: "\f008"; +} /*  */ +.octicon-organization:before { + content: "\f037"; +} /*  */ +.octicon-package:before { + content: "\f0c4"; +} /*  */ +.octicon-paintcan:before { + content: "\f0d1"; +} /*  */ +.octicon-pencil:before { + content: "\f058"; +} /*  */ .octicon-person-add:before, .octicon-person-follow:before, -.octicon-person:before { content: '\f018'} /*  */ -.octicon-pin:before { content: '\f041'} /*  */ -.octicon-plug:before { content: '\f0d4'} /*  */ +.octicon-person:before { + content: "\f018"; +} /*  */ +.octicon-pin:before { + content: "\f041"; +} /*  */ +.octicon-plug:before { + content: "\f0d4"; +} /*  */ .octicon-repo-create:before, .octicon-gist-new:before, .octicon-file-directory-create:before, .octicon-file-add:before, -.octicon-plus:before { content: '\f05d'} /*  */ -.octicon-primitive-dot:before { content: '\f052'} /*  */ -.octicon-primitive-square:before { content: '\f053'} /*  */ -.octicon-pulse:before { content: '\f085'} /*  */ -.octicon-question:before { content: '\f02c'} /*  */ -.octicon-quote:before { content: '\f063'} /*  */ -.octicon-radio-tower:before { content: '\f030'} /*  */ +.octicon-plus:before { + content: "\f05d"; +} /*  */ +.octicon-primitive-dot:before { + content: "\f052"; +} /*  */ +.octicon-primitive-square:before { + content: "\f053"; +} /*  */ +.octicon-pulse:before { + content: "\f085"; +} /*  */ +.octicon-question:before { + content: "\f02c"; +} /*  */ +.octicon-quote:before { + content: "\f063"; +} /*  */ +.octicon-radio-tower:before { + content: "\f030"; +} /*  */ .octicon-repo-delete:before, -.octicon-repo:before { content: '\f001'} /*  */ -.octicon-repo-clone:before { content: '\f04c'} /*  */ -.octicon-repo-force-push:before { content: '\f04a'} /*  */ +.octicon-repo:before { + content: "\f001"; +} /*  */ +.octicon-repo-clone:before { + content: "\f04c"; +} /*  */ +.octicon-repo-force-push:before { + content: "\f04a"; +} /*  */ .octicon-gist-fork:before, -.octicon-repo-forked:before { content: '\f002'} /*  */ -.octicon-repo-pull:before { content: '\f006'} /*  */ -.octicon-repo-push:before { content: '\f005'} /*  */ -.octicon-rocket:before { content: '\f033'} /*  */ -.octicon-rss:before { content: '\f034'} /*  */ -.octicon-ruby:before { content: '\f047'} /*  */ -.octicon-screen-full:before { content: '\f066'} /*  */ -.octicon-screen-normal:before { content: '\f067'} /*  */ +.octicon-repo-forked:before { + content: "\f002"; +} /*  */ +.octicon-repo-pull:before { + content: "\f006"; +} /*  */ +.octicon-repo-push:before { + content: "\f005"; +} /*  */ +.octicon-rocket:before { + content: "\f033"; +} /*  */ +.octicon-rss:before { + content: "\f034"; +} /*  */ +.octicon-ruby:before { + content: "\f047"; +} /*  */ +.octicon-screen-full:before { + content: "\f066"; +} /*  */ +.octicon-screen-normal:before { + content: "\f067"; +} /*  */ .octicon-search-save:before, -.octicon-search:before { content: '\f02e'} /*  */ -.octicon-server:before { content: '\f097'} /*  */ -.octicon-settings:before { content: '\f07c'} /*  */ -.octicon-shield:before { content: '\f0e1'} /*  */ +.octicon-search:before { + content: "\f02e"; +} /*  */ +.octicon-server:before { + content: "\f097"; +} /*  */ +.octicon-settings:before { + content: "\f07c"; +} /*  */ +.octicon-shield:before { + content: "\f0e1"; +} /*  */ .octicon-log-in:before, -.octicon-sign-in:before { content: '\f036'} /*  */ +.octicon-sign-in:before { + content: "\f036"; +} /*  */ .octicon-log-out:before, -.octicon-sign-out:before { content: '\f032'} /*  */ -.octicon-squirrel:before { content: '\f0b2'} /*  */ +.octicon-sign-out:before { + content: "\f032"; +} /*  */ +.octicon-squirrel:before { + content: "\f0b2"; +} /*  */ .octicon-star-add:before, .octicon-star-delete:before, -.octicon-star:before { content: '\f02a'} /*  */ -.octicon-stop:before { content: '\f08f'} /*  */ +.octicon-star:before { + content: "\f02a"; +} /*  */ +.octicon-stop:before { + content: "\f08f"; +} /*  */ .octicon-repo-sync:before, -.octicon-sync:before { content: '\f087'} /*  */ +.octicon-sync:before { + content: "\f087"; +} /*  */ .octicon-tag-remove:before, .octicon-tag-add:before, -.octicon-tag:before { content: '\f015'} /*  */ -.octicon-telescope:before { content: '\f088'} /*  */ -.octicon-terminal:before { content: '\f0c8'} /*  */ -.octicon-three-bars:before { content: '\f05e'} /*  */ -.octicon-thumbsdown:before { content: '\f0db'} /*  */ -.octicon-thumbsup:before { content: '\f0da'} /*  */ -.octicon-tools:before { content: '\f031'} /*  */ -.octicon-trashcan:before { content: '\f0d0'} /*  */ -.octicon-triangle-down:before { content: '\f05b'} /*  */ -.octicon-triangle-left:before { content: '\f044'} /*  */ -.octicon-triangle-right:before { content: '\f05a'} /*  */ -.octicon-triangle-up:before { content: '\f0aa'} /*  */ -.octicon-unfold:before { content: '\f039'} /*  */ -.octicon-unmute:before { content: '\f0ba'} /*  */ -.octicon-versions:before { content: '\f064'} /*  */ -.octicon-watch:before { content: '\f0e0'} /*  */ +.octicon-tag:before { + content: "\f015"; +} /*  */ +.octicon-telescope:before { + content: "\f088"; +} /*  */ +.octicon-terminal:before { + content: "\f0c8"; +} /*  */ +.octicon-three-bars:before { + content: "\f05e"; +} /*  */ +.octicon-thumbsdown:before { + content: "\f0db"; +} /*  */ +.octicon-thumbsup:before { + content: "\f0da"; +} /*  */ +.octicon-tools:before { + content: "\f031"; +} /*  */ +.octicon-trashcan:before { + content: "\f0d0"; +} /*  */ +.octicon-triangle-down:before { + content: "\f05b"; +} /*  */ +.octicon-triangle-left:before { + content: "\f044"; +} /*  */ +.octicon-triangle-right:before { + content: "\f05a"; +} /*  */ +.octicon-triangle-up:before { + content: "\f0aa"; +} /*  */ +.octicon-unfold:before { + content: "\f039"; +} /*  */ +.octicon-unmute:before { + content: "\f0ba"; +} /*  */ +.octicon-versions:before { + content: "\f064"; +} /*  */ +.octicon-watch:before { + content: "\f0e0"; +} /*  */ .octicon-remove-close:before, -.octicon-x:before { content: '\f081'} /*  */ -.octicon-zap:before { content: '\26A1'} /* ⚡ */ +.octicon-x:before { + content: "\f081"; +} /*  */ +.octicon-zap:before { + content: "\26A1"; +} /* ⚡ */ diff --git a/frappe/public/css/octicons/sprockets-octicons.scss b/frappe/public/css/octicons/sprockets-octicons.scss index cef21ae62e..84cd64d260 100755 --- a/frappe/public/css/octicons/sprockets-octicons.scss +++ b/frappe/public/css/octicons/sprockets-octicons.scss @@ -1,217 +1,543 @@ @font-face { - font-family: 'octicons'; - src: font-url('octicons.eot?#iefix') format('embedded-opentype'), - font-url('octicons.woff') format('woff'), - font-url('octicons.ttf') format('truetype'), - font-url('octicons.svg#octicons') format('svg'); - font-weight: normal; - font-style: normal; + font-family: "octicons"; + src: font-url("octicons.eot?#iefix") format("embedded-opentype"), + font-url("octicons.woff") format("woff"), font-url("octicons.ttf") format("truetype"), + font-url("octicons.svg#octicons") format("svg"); + font-weight: normal; + font-style: normal; } // .octicon is optimized for 16px. // .mega-octicon is optimized for 32px but can be used larger. -.octicon, .mega-octicon { - font: normal normal normal 16px/1 octicons; - display: inline-block; - text-decoration: none; - text-rendering: auto; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; +.octicon, +.mega-octicon { + font: normal normal normal 16px/1 octicons; + display: inline-block; + text-decoration: none; + text-rendering: auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.mega-octicon { + font-size: 32px; } -.mega-octicon { font-size: 32px; } -.octicon-alert:before { content: '\f02d'} /*  */ -.octicon-arrow-down:before { content: '\f03f'} /*  */ -.octicon-arrow-left:before { content: '\f040'} /*  */ -.octicon-arrow-right:before { content: '\f03e'} /*  */ -.octicon-arrow-small-down:before { content: '\f0a0'} /*  */ -.octicon-arrow-small-left:before { content: '\f0a1'} /*  */ -.octicon-arrow-small-right:before { content: '\f071'} /*  */ -.octicon-arrow-small-up:before { content: '\f09f'} /*  */ -.octicon-arrow-up:before { content: '\f03d'} /*  */ +.octicon-alert:before { + content: "\f02d"; +} /*  */ +.octicon-arrow-down:before { + content: "\f03f"; +} /*  */ +.octicon-arrow-left:before { + content: "\f040"; +} /*  */ +.octicon-arrow-right:before { + content: "\f03e"; +} /*  */ +.octicon-arrow-small-down:before { + content: "\f0a0"; +} /*  */ +.octicon-arrow-small-left:before { + content: "\f0a1"; +} /*  */ +.octicon-arrow-small-right:before { + content: "\f071"; +} /*  */ +.octicon-arrow-small-up:before { + content: "\f09f"; +} /*  */ +.octicon-arrow-up:before { + content: "\f03d"; +} /*  */ .octicon-microscope:before, -.octicon-beaker:before { content: '\f0dd'} /*  */ -.octicon-bell:before { content: '\f0de'} /*  */ -.octicon-book:before { content: '\f007'} /*  */ -.octicon-bookmark:before { content: '\f07b'} /*  */ -.octicon-briefcase:before { content: '\f0d3'} /*  */ -.octicon-broadcast:before { content: '\f048'} /*  */ -.octicon-browser:before { content: '\f0c5'} /*  */ -.octicon-bug:before { content: '\f091'} /*  */ -.octicon-calendar:before { content: '\f068'} /*  */ -.octicon-check:before { content: '\f03a'} /*  */ -.octicon-checklist:before { content: '\f076'} /*  */ -.octicon-chevron-down:before { content: '\f0a3'} /*  */ -.octicon-chevron-left:before { content: '\f0a4'} /*  */ -.octicon-chevron-right:before { content: '\f078'} /*  */ -.octicon-chevron-up:before { content: '\f0a2'} /*  */ -.octicon-circle-slash:before { content: '\f084'} /*  */ -.octicon-circuit-board:before { content: '\f0d6'} /*  */ -.octicon-clippy:before { content: '\f035'} /*  */ -.octicon-clock:before { content: '\f046'} /*  */ -.octicon-cloud-download:before { content: '\f00b'} /*  */ -.octicon-cloud-upload:before { content: '\f00c'} /*  */ -.octicon-code:before { content: '\f05f'} /*  */ -.octicon-color-mode:before { content: '\f065'} /*  */ +.octicon-beaker:before { + content: "\f0dd"; +} /*  */ +.octicon-bell:before { + content: "\f0de"; +} /*  */ +.octicon-book:before { + content: "\f007"; +} /*  */ +.octicon-bookmark:before { + content: "\f07b"; +} /*  */ +.octicon-briefcase:before { + content: "\f0d3"; +} /*  */ +.octicon-broadcast:before { + content: "\f048"; +} /*  */ +.octicon-browser:before { + content: "\f0c5"; +} /*  */ +.octicon-bug:before { + content: "\f091"; +} /*  */ +.octicon-calendar:before { + content: "\f068"; +} /*  */ +.octicon-check:before { + content: "\f03a"; +} /*  */ +.octicon-checklist:before { + content: "\f076"; +} /*  */ +.octicon-chevron-down:before { + content: "\f0a3"; +} /*  */ +.octicon-chevron-left:before { + content: "\f0a4"; +} /*  */ +.octicon-chevron-right:before { + content: "\f078"; +} /*  */ +.octicon-chevron-up:before { + content: "\f0a2"; +} /*  */ +.octicon-circle-slash:before { + content: "\f084"; +} /*  */ +.octicon-circuit-board:before { + content: "\f0d6"; +} /*  */ +.octicon-clippy:before { + content: "\f035"; +} /*  */ +.octicon-clock:before { + content: "\f046"; +} /*  */ +.octicon-cloud-download:before { + content: "\f00b"; +} /*  */ +.octicon-cloud-upload:before { + content: "\f00c"; +} /*  */ +.octicon-code:before { + content: "\f05f"; +} /*  */ +.octicon-color-mode:before { + content: "\f065"; +} /*  */ .octicon-comment-add:before, -.octicon-comment:before { content: '\f02b'} /*  */ -.octicon-comment-discussion:before { content: '\f04f'} /*  */ -.octicon-credit-card:before { content: '\f045'} /*  */ -.octicon-dash:before { content: '\f0ca'} /*  */ -.octicon-dashboard:before { content: '\f07d'} /*  */ -.octicon-database:before { content: '\f096'} /*  */ +.octicon-comment:before { + content: "\f02b"; +} /*  */ +.octicon-comment-discussion:before { + content: "\f04f"; +} /*  */ +.octicon-credit-card:before { + content: "\f045"; +} /*  */ +.octicon-dash:before { + content: "\f0ca"; +} /*  */ +.octicon-dashboard:before { + content: "\f07d"; +} /*  */ +.octicon-database:before { + content: "\f096"; +} /*  */ .octicon-clone:before, -.octicon-desktop-download:before { content: '\f0dc'} /*  */ -.octicon-device-camera:before { content: '\f056'} /*  */ -.octicon-device-camera-video:before { content: '\f057'} /*  */ -.octicon-device-desktop:before { content: '\f27c'} /*  */ -.octicon-device-mobile:before { content: '\f038'} /*  */ -.octicon-diff:before { content: '\f04d'} /*  */ -.octicon-diff-added:before { content: '\f06b'} /*  */ -.octicon-diff-ignored:before { content: '\f099'} /*  */ -.octicon-diff-modified:before { content: '\f06d'} /*  */ -.octicon-diff-removed:before { content: '\f06c'} /*  */ -.octicon-diff-renamed:before { content: '\f06e'} /*  */ -.octicon-ellipsis:before { content: '\f09a'} /*  */ +.octicon-desktop-download:before { + content: "\f0dc"; +} /*  */ +.octicon-device-camera:before { + content: "\f056"; +} /*  */ +.octicon-device-camera-video:before { + content: "\f057"; +} /*  */ +.octicon-device-desktop:before { + content: "\f27c"; +} /*  */ +.octicon-device-mobile:before { + content: "\f038"; +} /*  */ +.octicon-diff:before { + content: "\f04d"; +} /*  */ +.octicon-diff-added:before { + content: "\f06b"; +} /*  */ +.octicon-diff-ignored:before { + content: "\f099"; +} /*  */ +.octicon-diff-modified:before { + content: "\f06d"; +} /*  */ +.octicon-diff-removed:before { + content: "\f06c"; +} /*  */ +.octicon-diff-renamed:before { + content: "\f06e"; +} /*  */ +.octicon-ellipsis:before { + content: "\f09a"; +} /*  */ .octicon-eye-unwatch:before, .octicon-eye-watch:before, -.octicon-eye:before { content: '\f04e'} /*  */ -.octicon-file-binary:before { content: '\f094'} /*  */ -.octicon-file-code:before { content: '\f010'} /*  */ -.octicon-file-directory:before { content: '\f016'} /*  */ -.octicon-file-media:before { content: '\f012'} /*  */ -.octicon-file-pdf:before { content: '\f014'} /*  */ -.octicon-file-submodule:before { content: '\f017'} /*  */ -.octicon-file-symlink-directory:before { content: '\f0b1'} /*  */ -.octicon-file-symlink-file:before { content: '\f0b0'} /*  */ -.octicon-file-text:before { content: '\f011'} /*  */ -.octicon-file-zip:before { content: '\f013'} /*  */ -.octicon-flame:before { content: '\f0d2'} /*  */ -.octicon-fold:before { content: '\f0cc'} /*  */ -.octicon-gear:before { content: '\f02f'} /*  */ -.octicon-gift:before { content: '\f042'} /*  */ -.octicon-gist:before { content: '\f00e'} /*  */ -.octicon-gist-secret:before { content: '\f08c'} /*  */ +.octicon-eye:before { + content: "\f04e"; +} /*  */ +.octicon-file-binary:before { + content: "\f094"; +} /*  */ +.octicon-file-code:before { + content: "\f010"; +} /*  */ +.octicon-file-directory:before { + content: "\f016"; +} /*  */ +.octicon-file-media:before { + content: "\f012"; +} /*  */ +.octicon-file-pdf:before { + content: "\f014"; +} /*  */ +.octicon-file-submodule:before { + content: "\f017"; +} /*  */ +.octicon-file-symlink-directory:before { + content: "\f0b1"; +} /*  */ +.octicon-file-symlink-file:before { + content: "\f0b0"; +} /*  */ +.octicon-file-text:before { + content: "\f011"; +} /*  */ +.octicon-file-zip:before { + content: "\f013"; +} /*  */ +.octicon-flame:before { + content: "\f0d2"; +} /*  */ +.octicon-fold:before { + content: "\f0cc"; +} /*  */ +.octicon-gear:before { + content: "\f02f"; +} /*  */ +.octicon-gift:before { + content: "\f042"; +} /*  */ +.octicon-gist:before { + content: "\f00e"; +} /*  */ +.octicon-gist-secret:before { + content: "\f08c"; +} /*  */ .octicon-git-branch-create:before, .octicon-git-branch-delete:before, -.octicon-git-branch:before { content: '\f020'} /*  */ -.octicon-git-commit:before { content: '\f01f'} /*  */ -.octicon-git-compare:before { content: '\f0ac'} /*  */ -.octicon-git-merge:before { content: '\f023'} /*  */ +.octicon-git-branch:before { + content: "\f020"; +} /*  */ +.octicon-git-commit:before { + content: "\f01f"; +} /*  */ +.octicon-git-compare:before { + content: "\f0ac"; +} /*  */ +.octicon-git-merge:before { + content: "\f023"; +} /*  */ .octicon-git-pull-request-abandoned:before, -.octicon-git-pull-request:before { content: '\f009'} /*  */ -.octicon-globe:before { content: '\f0b6'} /*  */ -.octicon-graph:before { content: '\f043'} /*  */ -.octicon-heart:before { content: '\2665'} /* ♥ */ -.octicon-history:before { content: '\f07e'} /*  */ -.octicon-home:before { content: '\f08d'} /*  */ -.octicon-horizontal-rule:before { content: '\f070'} /*  */ -.octicon-hubot:before { content: '\f09d'} /*  */ -.octicon-inbox:before { content: '\f0cf'} /*  */ -.octicon-info:before { content: '\f059'} /*  */ -.octicon-issue-closed:before { content: '\f028'} /*  */ -.octicon-issue-opened:before { content: '\f026'} /*  */ -.octicon-issue-reopened:before { content: '\f027'} /*  */ -.octicon-jersey:before { content: '\f019'} /*  */ -.octicon-key:before { content: '\f049'} /*  */ -.octicon-keyboard:before { content: '\f00d'} /*  */ -.octicon-law:before { content: '\f0d8'} /*  */ -.octicon-light-bulb:before { content: '\f000'} /*  */ -.octicon-link:before { content: '\f05c'} /*  */ -.octicon-link-external:before { content: '\f07f'} /*  */ -.octicon-list-ordered:before { content: '\f062'} /*  */ -.octicon-list-unordered:before { content: '\f061'} /*  */ -.octicon-location:before { content: '\f060'} /*  */ +.octicon-git-pull-request:before { + content: "\f009"; +} /*  */ +.octicon-globe:before { + content: "\f0b6"; +} /*  */ +.octicon-graph:before { + content: "\f043"; +} /*  */ +.octicon-heart:before { + content: "\2665"; +} /* ♥ */ +.octicon-history:before { + content: "\f07e"; +} /*  */ +.octicon-home:before { + content: "\f08d"; +} /*  */ +.octicon-horizontal-rule:before { + content: "\f070"; +} /*  */ +.octicon-hubot:before { + content: "\f09d"; +} /*  */ +.octicon-inbox:before { + content: "\f0cf"; +} /*  */ +.octicon-info:before { + content: "\f059"; +} /*  */ +.octicon-issue-closed:before { + content: "\f028"; +} /*  */ +.octicon-issue-opened:before { + content: "\f026"; +} /*  */ +.octicon-issue-reopened:before { + content: "\f027"; +} /*  */ +.octicon-jersey:before { + content: "\f019"; +} /*  */ +.octicon-key:before { + content: "\f049"; +} /*  */ +.octicon-keyboard:before { + content: "\f00d"; +} /*  */ +.octicon-law:before { + content: "\f0d8"; +} /*  */ +.octicon-light-bulb:before { + content: "\f000"; +} /*  */ +.octicon-link:before { + content: "\f05c"; +} /*  */ +.octicon-link-external:before { + content: "\f07f"; +} /*  */ +.octicon-list-ordered:before { + content: "\f062"; +} /*  */ +.octicon-list-unordered:before { + content: "\f061"; +} /*  */ +.octicon-location:before { + content: "\f060"; +} /*  */ .octicon-gist-private:before, .octicon-mirror-private:before, .octicon-git-fork-private:before, -.octicon-lock:before { content: '\f06a'} /*  */ -.octicon-logo-github:before { content: '\f092'} /*  */ -.octicon-mail:before { content: '\f03b'} /*  */ -.octicon-mail-read:before { content: '\f03c'} /*  */ -.octicon-mail-reply:before { content: '\f051'} /*  */ -.octicon-mark-github:before { content: '\f00a'} /*  */ -.octicon-markdown:before { content: '\f0c9'} /*  */ -.octicon-megaphone:before { content: '\f077'} /*  */ -.octicon-mention:before { content: '\f0be'} /*  */ -.octicon-milestone:before { content: '\f075'} /*  */ +.octicon-lock:before { + content: "\f06a"; +} /*  */ +.octicon-logo-github:before { + content: "\f092"; +} /*  */ +.octicon-mail:before { + content: "\f03b"; +} /*  */ +.octicon-mail-read:before { + content: "\f03c"; +} /*  */ +.octicon-mail-reply:before { + content: "\f051"; +} /*  */ +.octicon-mark-github:before { + content: "\f00a"; +} /*  */ +.octicon-markdown:before { + content: "\f0c9"; +} /*  */ +.octicon-megaphone:before { + content: "\f077"; +} /*  */ +.octicon-mention:before { + content: "\f0be"; +} /*  */ +.octicon-milestone:before { + content: "\f075"; +} /*  */ .octicon-mirror-public:before, -.octicon-mirror:before { content: '\f024'} /*  */ -.octicon-mortar-board:before { content: '\f0d7'} /*  */ -.octicon-mute:before { content: '\f080'} /*  */ -.octicon-no-newline:before { content: '\f09c'} /*  */ -.octicon-octoface:before { content: '\f008'} /*  */ -.octicon-organization:before { content: '\f037'} /*  */ -.octicon-package:before { content: '\f0c4'} /*  */ -.octicon-paintcan:before { content: '\f0d1'} /*  */ -.octicon-pencil:before { content: '\f058'} /*  */ +.octicon-mirror:before { + content: "\f024"; +} /*  */ +.octicon-mortar-board:before { + content: "\f0d7"; +} /*  */ +.octicon-mute:before { + content: "\f080"; +} /*  */ +.octicon-no-newline:before { + content: "\f09c"; +} /*  */ +.octicon-octoface:before { + content: "\f008"; +} /*  */ +.octicon-organization:before { + content: "\f037"; +} /*  */ +.octicon-package:before { + content: "\f0c4"; +} /*  */ +.octicon-paintcan:before { + content: "\f0d1"; +} /*  */ +.octicon-pencil:before { + content: "\f058"; +} /*  */ .octicon-person-add:before, .octicon-person-follow:before, -.octicon-person:before { content: '\f018'} /*  */ -.octicon-pin:before { content: '\f041'} /*  */ -.octicon-plug:before { content: '\f0d4'} /*  */ +.octicon-person:before { + content: "\f018"; +} /*  */ +.octicon-pin:before { + content: "\f041"; +} /*  */ +.octicon-plug:before { + content: "\f0d4"; +} /*  */ .octicon-repo-create:before, .octicon-gist-new:before, .octicon-file-directory-create:before, .octicon-file-add:before, -.octicon-plus:before { content: '\f05d'} /*  */ -.octicon-primitive-dot:before { content: '\f052'} /*  */ -.octicon-primitive-square:before { content: '\f053'} /*  */ -.octicon-pulse:before { content: '\f085'} /*  */ -.octicon-question:before { content: '\f02c'} /*  */ -.octicon-quote:before { content: '\f063'} /*  */ -.octicon-radio-tower:before { content: '\f030'} /*  */ +.octicon-plus:before { + content: "\f05d"; +} /*  */ +.octicon-primitive-dot:before { + content: "\f052"; +} /*  */ +.octicon-primitive-square:before { + content: "\f053"; +} /*  */ +.octicon-pulse:before { + content: "\f085"; +} /*  */ +.octicon-question:before { + content: "\f02c"; +} /*  */ +.octicon-quote:before { + content: "\f063"; +} /*  */ +.octicon-radio-tower:before { + content: "\f030"; +} /*  */ .octicon-repo-delete:before, -.octicon-repo:before { content: '\f001'} /*  */ -.octicon-repo-clone:before { content: '\f04c'} /*  */ -.octicon-repo-force-push:before { content: '\f04a'} /*  */ +.octicon-repo:before { + content: "\f001"; +} /*  */ +.octicon-repo-clone:before { + content: "\f04c"; +} /*  */ +.octicon-repo-force-push:before { + content: "\f04a"; +} /*  */ .octicon-gist-fork:before, -.octicon-repo-forked:before { content: '\f002'} /*  */ -.octicon-repo-pull:before { content: '\f006'} /*  */ -.octicon-repo-push:before { content: '\f005'} /*  */ -.octicon-rocket:before { content: '\f033'} /*  */ -.octicon-rss:before { content: '\f034'} /*  */ -.octicon-ruby:before { content: '\f047'} /*  */ -.octicon-screen-full:before { content: '\f066'} /*  */ -.octicon-screen-normal:before { content: '\f067'} /*  */ +.octicon-repo-forked:before { + content: "\f002"; +} /*  */ +.octicon-repo-pull:before { + content: "\f006"; +} /*  */ +.octicon-repo-push:before { + content: "\f005"; +} /*  */ +.octicon-rocket:before { + content: "\f033"; +} /*  */ +.octicon-rss:before { + content: "\f034"; +} /*  */ +.octicon-ruby:before { + content: "\f047"; +} /*  */ +.octicon-screen-full:before { + content: "\f066"; +} /*  */ +.octicon-screen-normal:before { + content: "\f067"; +} /*  */ .octicon-search-save:before, -.octicon-search:before { content: '\f02e'} /*  */ -.octicon-server:before { content: '\f097'} /*  */ -.octicon-settings:before { content: '\f07c'} /*  */ -.octicon-shield:before { content: '\f0e1'} /*  */ +.octicon-search:before { + content: "\f02e"; +} /*  */ +.octicon-server:before { + content: "\f097"; +} /*  */ +.octicon-settings:before { + content: "\f07c"; +} /*  */ +.octicon-shield:before { + content: "\f0e1"; +} /*  */ .octicon-log-in:before, -.octicon-sign-in:before { content: '\f036'} /*  */ +.octicon-sign-in:before { + content: "\f036"; +} /*  */ .octicon-log-out:before, -.octicon-sign-out:before { content: '\f032'} /*  */ -.octicon-squirrel:before { content: '\f0b2'} /*  */ +.octicon-sign-out:before { + content: "\f032"; +} /*  */ +.octicon-squirrel:before { + content: "\f0b2"; +} /*  */ .octicon-star-add:before, .octicon-star-delete:before, -.octicon-star:before { content: '\f02a'} /*  */ -.octicon-stop:before { content: '\f08f'} /*  */ +.octicon-star:before { + content: "\f02a"; +} /*  */ +.octicon-stop:before { + content: "\f08f"; +} /*  */ .octicon-repo-sync:before, -.octicon-sync:before { content: '\f087'} /*  */ +.octicon-sync:before { + content: "\f087"; +} /*  */ .octicon-tag-remove:before, .octicon-tag-add:before, -.octicon-tag:before { content: '\f015'} /*  */ -.octicon-telescope:before { content: '\f088'} /*  */ -.octicon-terminal:before { content: '\f0c8'} /*  */ -.octicon-three-bars:before { content: '\f05e'} /*  */ -.octicon-thumbsdown:before { content: '\f0db'} /*  */ -.octicon-thumbsup:before { content: '\f0da'} /*  */ -.octicon-tools:before { content: '\f031'} /*  */ -.octicon-trashcan:before { content: '\f0d0'} /*  */ -.octicon-triangle-down:before { content: '\f05b'} /*  */ -.octicon-triangle-left:before { content: '\f044'} /*  */ -.octicon-triangle-right:before { content: '\f05a'} /*  */ -.octicon-triangle-up:before { content: '\f0aa'} /*  */ -.octicon-unfold:before { content: '\f039'} /*  */ -.octicon-unmute:before { content: '\f0ba'} /*  */ -.octicon-versions:before { content: '\f064'} /*  */ -.octicon-watch:before { content: '\f0e0'} /*  */ +.octicon-tag:before { + content: "\f015"; +} /*  */ +.octicon-telescope:before { + content: "\f088"; +} /*  */ +.octicon-terminal:before { + content: "\f0c8"; +} /*  */ +.octicon-three-bars:before { + content: "\f05e"; +} /*  */ +.octicon-thumbsdown:before { + content: "\f0db"; +} /*  */ +.octicon-thumbsup:before { + content: "\f0da"; +} /*  */ +.octicon-tools:before { + content: "\f031"; +} /*  */ +.octicon-trashcan:before { + content: "\f0d0"; +} /*  */ +.octicon-triangle-down:before { + content: "\f05b"; +} /*  */ +.octicon-triangle-left:before { + content: "\f044"; +} /*  */ +.octicon-triangle-right:before { + content: "\f05a"; +} /*  */ +.octicon-triangle-up:before { + content: "\f0aa"; +} /*  */ +.octicon-unfold:before { + content: "\f039"; +} /*  */ +.octicon-unmute:before { + content: "\f0ba"; +} /*  */ +.octicon-versions:before { + content: "\f064"; +} /*  */ +.octicon-watch:before { + content: "\f0e0"; +} /*  */ .octicon-remove-close:before, -.octicon-x:before { content: '\f081'} /*  */ -.octicon-zap:before { content: '\26A1'} /* ⚡ */ +.octicon-x:before { + content: "\f081"; +} /*  */ +.octicon-zap:before { + content: "\26A1"; +} /* ⚡ */ diff --git a/frappe/public/icons/timeless/icons.svg b/frappe/public/icons/timeless/icons.svg index 856e743bc2..58665bd20b 100644 --- a/frappe/public/icons/timeless/icons.svg +++ b/frappe/public/icons/timeless/icons.svg @@ -815,7 +815,7 @@ + stroke="none" fill="var(--icon-stroke)"> diff --git a/frappe/public/js/form_builder/components/Autocomplete.vue b/frappe/public/js/form_builder/components/Autocomplete.vue index 2ded948e27..3bbaf8b298 100644 --- a/frappe/public/js/form_builder/components/Autocomplete.vue +++ b/frappe/public/js/form_builder/components/Autocomplete.vue @@ -113,10 +113,11 @@ watch(showOptions, (val) => { .combo-box-options { width: 100%; - background-color: var(--white); + background-color: var(--fg-color); border-radius: var(--border-radius-lg); box-shadow: var(--shadow-2xl); padding: 0; + border: 1px solid var(--subtle-accent); } .combo-box-option { diff --git a/frappe/public/js/form_builder/components/Column.vue b/frappe/public/js/form_builder/components/Column.vue index f6a3cfbe51..3fbc67e115 100644 --- a/frappe/public/js/form_builder/components/Column.vue +++ b/frappe/public/js/form_builder/components/Column.vue @@ -1,113 +1,3 @@ - - -
+
@@ -182,6 +45,30 @@ function move_columns_to_section() {
+ + diff --git a/frappe/public/js/form_builder/components/Field.vue b/frappe/public/js/form_builder/components/Field.vue index 6bae5bd35f..08e65473ee 100644 --- a/frappe/public/js/form_builder/components/Field.vue +++ b/frappe/public/js/form_builder/components/Field.vue @@ -75,6 +75,110 @@ function duplicate_field() { store.form.selected_field = duplicate_field.df; } +function make_dialog(frm) { + frm.dialog = new frappe.ui.Dialog({ + title: __("Set Filters"), + fields: [ + { + fieldtype: "HTML", + fieldname: "filter_area", + }, + ], + primary_action: () => { + let fieldname = props.field.df.fieldname; + let field_option = props.field.df.options; + let filters = frm.filter_group.get_filters().map((filter) => { + // last element is a boolean which hides the filter hence not required to store in meta + filter.pop(); + + // filter_group component requires options and frm.set_query requires fieldname so storing both + filter[0] = { fieldname, field_option }; + return filter; + }); + + props.field.df.link_filters = JSON.stringify(filters); + frm.dialog.hide(); + }, + primary_action_label: __("Apply"), + }); + + if (frm.doctype === "Customize Form") { + let current_doctype = frm.doc.doc_type; + let fieldname = props.field.df.fieldname; + let property = "link_filters"; + let property_setter_id = current_doctype + "-" + fieldname + "-" + property; + + frappe.db.exists("Property Setter", property_setter_id).then((exits) => { + if (exits) { + frm.dialog.set_secondary_action_label(__("Reset To Default")); + frm.dialog.set_secondary_action(() => { + frappe.call({ + method: "frappe.custom.doctype.customize_form.customize_form.get_link_filters_from_doc_without_customisations", + args: { + doctype: current_doctype, + fieldname: fieldname, + }, + callback: function (r) { + if (r.message) { + props.field.df.link_filters = r.message; + + frm.filter_group.clear_filters(); + add_existing_filter(frm, props.field.df); + // hide the secondary action button + frm.dialog.get_secondary_btn().addClass("hidden"); + } + }, + }); + }); + } + }); + } + + // Setting selected field in store because when we click on the dialog the selected field is set to null + frm.dialog.$wrapper.on("click", () => { + store.form.selected_field = props.field.df; + }); +} + +function make_filter_area(frm, doctype) { + frm.filter_group = new frappe.ui.FilterGroup({ + parent: frm.dialog.get_field("filter_area").$wrapper, + doctype: doctype, + on_change: () => {}, + }); +} + +function add_existing_filter(frm, df) { + if (df.link_filters) { + let filters = JSON.parse(df.link_filters); + filters.map((filter) => { + // filter_group component requires options and frm.set_query requires fieldname + filter[0] = filter[0].field_option; + }); + if (filters) { + frm.filter_group.add_filters_to_filter_group(filters); + } + } +} + +function edit_filters() { + let field_doctype = props.field.df.options; + const { frm } = store; + + make_dialog(frm); + make_filter_area(frm, field_doctype); + frappe.model.with_doctype(field_doctype, () => { + frm.dialog.show(); + add_existing_filter(frm, props.field.df); + }); +} + +function is_filter_applied() { + if (props.field.df.link_filters && JSON.parse(props.field.df.link_filters).length > 0) { + return "btn-filter-applied"; + } +} + onMounted(() => selected.value && label_input.value.focus_on_label()); @@ -111,22 +215,17 @@ onMounted(() => selected.value && label_input.value.focus_on_label());