Kaynağa Gözat

feat: Migrate Website to Bootstrap 4

- Use bootstrap 4 base for website assets
- hooks.py: Remove bootstrap hook
- Upgrade navbar, breadcrumbs to 4
- Support multi-level dropdown

BREAKING CHANGE
version-14
Faris Ansari 6 yıl önce
ebeveyn
işleme
68a7b81374
20 değiştirilmiş dosya ile 369 ekleme ve 230 silme
  1. +1
    -2
      frappe/hooks.py
  2. +6
    -0
      frappe/public/build.json
  3. +17
    -17
      frappe/public/less/website.less
  4. +95
    -0
      frappe/public/scss/bootstrap-4.scss
  5. +17
    -0
      frappe/public/scss/multilevel-dropdown.scss
  6. +8
    -0
      frappe/public/scss/variables.scss
  7. +48
    -70
      frappe/templates/base.html
  8. +19
    -12
      frappe/templates/includes/breadcrumbs.html
  9. +19
    -20
      frappe/templates/includes/navbar/navbar.html
  10. +31
    -8
      frappe/templates/includes/navbar/navbar_items.html
  11. +0
    -20
      frappe/templates/includes/navbar/navbar_link.html
  12. +11
    -17
      frappe/templates/includes/navbar/navbar_login.html
  13. +3
    -13
      frappe/templates/includes/search_box.html
  14. +40
    -44
      frappe/templates/web.html
  15. +1
    -1
      frappe/website/doctype/website_settings/website_settings.js
  16. +1
    -2
      frappe/website/doctype/website_settings/website_settings.py
  17. +3
    -4
      frappe/website/doctype/website_theme/website_theme.py
  18. +43
    -0
      frappe/website/js/bootstrap-4.js
  19. +1
    -0
      package.json
  20. +5
    -0
      yarn.lock

+ 1
- 2
frappe/hooks.py Dosyayı Görüntüle

@@ -47,9 +47,8 @@ web_include_js = [
"website_script.js"
]

bootstrap = "assets/frappe/css/bootstrap.css"
web_include_css = [
"assets/css/frappe-web.css"
"assets/css/bootstrap-4-web.css"
]

website_route_rules = [


+ 6
- 0
frappe/public/build.json Dosyayı Görüntüle

@@ -11,6 +11,9 @@
"public/less/form_grid.less",
"node_modules/frappe-datatable/dist/frappe-datatable.css"
],
"css/bootstrap-4-web.css": [
"public/scss/bootstrap-4.scss"
],
"concat:js/moment-bundle.min.js": [
"node_modules/moment/min/moment-with-locales.min.js",
"node_modules/moment-timezone/builds/moment-timezone-with-data.min.js"
@@ -45,6 +48,9 @@
"public/js/frappe/misc/rating_icons.html",
"public/js/frappe/socketio_client.js"
],
"js/bootstrap-4-web.min.js": [
"website/js/bootstrap-4.js"
],
"js/control.min.js": [
"public/js/frappe/ui/capture.js",
"public/js/frappe/form/controls/base_control.js",


+ 17
- 17
frappe/public/less/website.less Dosyayı Görüntüle

@@ -124,8 +124,8 @@ li {
}

.page_content {
padding-top: 30px;
padding-bottom: 30px;
padding-top: 2rem;
padding-bottom: 2rem;
}

.carousel-control .icon {
@@ -405,12 +405,12 @@ a.active {
// background-color: #ffa;
// }

.page-breadcrumbs .breadcrumb {
padding: 0px;
background-color: transparent;
border-radius: 0px;
font-size: 12px;
}
// .page-breadcrumbs .breadcrumb {
// padding: 0px;
// background-color: transparent;
// border-radius: 0px;
// font-size: 12px;
// }

.breadcrumb a {
color: inherit;
@@ -594,15 +594,15 @@ li.footer-child-item {
padding-bottom:2000px; margin-bottom:-2000px;}

.shopping-cart {
.cart-icon {
.dropdown-toggle {
text-decoration: none !important;
}
}
margin-top:12px;
margin-bottom:8px;
padding-right:15px;
border-right: 1px solid @border-color;
// .cart-icon {
// .dropdown-toggle {
// text-decoration: none !important;
// }
// }
// margin-top:12px;
// margin-bottom:8px;
// padding-right:15px;
// border-right: 1px solid @border-color;
}
.badge-wrapper {
display: inline-block;


+ 95
- 0
frappe/public/scss/bootstrap-4.scss Dosyayı Görüntüle

@@ -0,0 +1,95 @@
@import "variables";
@import "~bootstrap/scss/bootstrap";
@import "multilevel-dropdown";


body {
font-size: 16px;
}

.navbar.bg-dark {
.dropdown-menu {
font-size: .75rem;
background-color: $dark;
border-radius: 0;
}

.nav-link {
white-space: nowrap;
color: $light;

&:hover {
color: $primary;
}
}

.nav-item {
padding: 0rem 1rem;
}

.dropdown-item {
color: $light;

&:hover {
background-color: $dark;
color: $primary;
}
}
}


.input-dark {
background-color: $dark;
border-color: darken($primary, 40%);
color: $light;
}

.breadcrumb {
font-size: 0.75rem;
}

a.card {
text-decoration: none;
}

img {
max-width: 100%;
}

.hidden {
@extend .d-none;
}

.video-background {
width: 100vw;
position: absolute;
top: 0;
left: 0;
z-index: -1;

&-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
width: 100%;
height: 100%;
background-color: var(--dark);
opacity: 0.4;
}
}

.hero-section {
background-image: url("/assets/rigpl_theme/images/hero-image.jpg");
background-size: cover;
background-position-y: 15%;
background-position-y: 27%;
}

.btn-primary {
color: $white;
}

.text-underline {
text-decoration: underline;
}

+ 17
- 0
frappe/public/scss/multilevel-dropdown.scss Dosyayı Görüntüle

@@ -0,0 +1,17 @@
.dropdown-submenu {
position: relative;
}

.dropdown-submenu a::after {
transform: rotate(-90deg);
position: absolute;
right: 6px;
top: .8em;
}

.dropdown-submenu .dropdown-menu {
top: 0;
left: 100%;
margin-left: .1rem;
margin-right: .1rem;
}

+ 8
- 0
frappe/public/scss/variables.scss Dosyayı Görüntüle

@@ -0,0 +1,8 @@
// $midnight_blue: #18427B;
// $dark_purple: #191B69;
// $light_grey: #E2DBD4;
// $green: #8BBF46;
// $slate_grey: #7F8487;

// $primary: $green;
// $dark: $dark_purple;

+ 48
- 70
frappe/templates/base.html Dosyayı Görüntüle

@@ -3,101 +3,79 @@
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %} {{ title | striptags }} {% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="generator" content="frappe">
{% block favicon %}
<link rel="shortcut icon"
href="{{ (favicon or "/assets/frappe/images/favicon.png") | abs_url }}"
type="image/x-icon">
<link rel="icon"

{% block meta_block %}{% endblock %}

<title>{% block title %} {{ title | striptags }} {% endblock %}</title>

{% block favicon %}
<link
rel="shortcut icon"
href="{{ (favicon or "/assets/frappe/images/favicon.png") | abs_url }}"
type="image/x-icon">
{% endblock %}
type="image/x-icon"
>
{% endblock %}

{%- block head -%}
{% block meta_block %}{% endblock %}
{% if head_html is defined -%}
{{ head_html or "" }}
{%- endif %}
{%- for link in web_include_css %}
<link type="text/css" rel="stylesheet" href="{{ link|abs_url }}">
{%- endfor -%}
{%- block head_include %}{{ head_include or "" }}{% endblock -%}
{%- block style %}{%- endblock -%}
{%- endblock -%}
<script>

{%- block head_include %}
{{ head_include or "" }}
{% endblock -%}

{%- block style %}{%- endblock -%}

<script>
window.frappe = {};
frappe.ready_events = [];
frappe.ready = function(fn) {
frappe.ready_events.push(fn);
}
window.dev_server = {{ dev_server }};
</script>
</script>
</head>
{% block body %}
<body data-path="{{ path }}">
<div class="main-section">
<div>
<header>
{%- block banner -%}
{% include "templates/includes/banner_extension.html" ignore missing %}
{% if banner_html -%}
<div class="container">
<div class='banner'>
{{ banner_html or "" }}
</div>
</div>
{%- endif %}
{%- endblock -%}
{%- block navbar -%}
{% include "templates/includes/navbar/navbar.html" %}
{%- endblock -%}

{%- block navbar -%}
{% include "templates/includes/navbar/navbar.html" %}
{%- endblock -%}
</header>
{% block content %}
{{ content }}
{% endblock %}

{%- block footer -%}
{% include "templates/includes/footer/footer.html" %}
{%- endblock -%}

<div class="hero-and-content">
<div data-html-block="hero">
{%- block hero -%}{%- endblock -%}
</div>
<div class="container">
{% block content %}{% endblock %}
</div>
</div>
{%- if footer is defined -%}
<footer class="page-footer">
<div class="container">
{{ footer }}
</div>
</footer>
{%- endif -%}
</div>
<div>
{%- block footer -%}{% include "templates/includes/footer/footer.html" %}{%- endblock -%}
</div>
</div>
{% block base_scripts %}
<!-- js should be loaded in body! -->
<script type="text/javascript"
src="/assets/frappe/js/lib/jquery/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.slim.js"></script>
<script type="text/javascript"
src="/assets/js/frappe-web.min.js"></script>
<script type="text/javascript"
src="/assets/frappe/js/lib/bootstrap.min.js"></script>
<script type="text/javascript" src="/assets/frappe/js/lib/jquery/jquery.min.js"></script>
<script type="text/javascript" src="/assets/js/frappe-web.min.js"></script>
<script type="text/javascript" src="/assets/js/bootstrap-4-web.min.js"></script>
{% endblock %}
{%- if js_globals is defined %}
<script>
{%- for key, value in js_globals.iteritems() %}
window.{{ key }} = "{{ value[0] }}";
{%- endfor -%}
</script>
{% endif -%}

{%- if js_globals is defined %}
<script>
{%- for key, value in js_globals.iteritems() %}
window.{{ key }} = "{{ value[0] }}";
{%- endfor -%}
</script>
{% endif -%}

{%- for link in web_include_js %}
<script type="text/javascript" src="{{ link|abs_url }}"></script>
<script type="text/javascript" src="{{ link | abs_url }}"></script>
{%- endfor -%}
{%- block script %}{%- endblock %}

{%- block script %}{%- endblock %}
<!-- csrf_token -->
{%- block body_include %}{{ body_include or "" }}{% endblock -%}
{%- block body_include %}{{ body_include or "" }}{% endblock -%}
</body>
{% endblock %}
</html>

+ 19
- 12
frappe/templates/includes/breadcrumbs.html Dosyayı Görüntüle

@@ -1,12 +1,19 @@
{% if parents and parents|length > 0 %}
<ul class="breadcrumb" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
{% for parent in parents %}
<li>
<a href="{{ url_prefix }}{{ parent.route | abs_url }}" itemprop="url">
<span itemprop="title">{{ parent.title or parent.label or parent.name or "" }}</span>
</a>
</li>
{% endfor %}
<li class="active"><span itemprop="title">{{ title or "" }}</span></li>
</ul>
{% endif %}
<div class="container mt-3">
{% if not no_breadcrumbs and parents %}
<nav aria-label="breadcrumb">
<ol class="breadcrumb" itemscope itemtype="http://data-vocabulary.org/Breadcrumb">
{%- set parents = parents[-3:] %}
{% for parent in parents %}
<li class="breadcrumb-item">
<a href="{{ url_prefix }}{{ parent.route | abs_url }}" itemprop="url">
{{ parent.title or parent.label or parent.name or "" }}
</a>
</li>
{% endfor %}
<li class="breadcrumb-item active" aria-current="page">
{{ title or "" }}
</li>
</ol>
</nav>
{% endif %}
</div>

+ 19
- 20
frappe/templates/includes/navbar/navbar.html Dosyayı Görüntüle

@@ -1,21 +1,20 @@
<nav class="navbar navbar-default navbar-main" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand ellipsis"
href="{{ url_prefix }}{{ home_page or "/"}}">
<span>{{ brand_html or (frappe.get_hooks("brand_html") or ["Home"])[0] }}</span>
</a>
<div class="dropdown">
<button class="btn btn-default navbar-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<i class="octicon octicon-three-bars"></i>
</button>
{% include "templates/includes/navbar/dropdown_items.html" %}
</div>
</div>
<div class="hidden-xs">
{% block navbar_items %}
{% include "templates/includes/navbar/navbar_items.html" %}
{% endblock %}
</div>
<nav class="navbar navbar-expand-lg navbar-light bg-light sticky-top shadow-sm">
<div class="container">
<a class="navbar-brand" href="{{ url_prefix }}{{ home_page or "/" }}">
<span>{{ brand_html or (frappe.get_hooks("brand_html") or ["Home"])[0] }}</span>
</a>
<button class="navbar-toggler" type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>

<div class="collapse navbar-collapse" id="navbarSupportedContent">
{% include "templates/includes/navbar/navbar_items.html" %}
</div>
</nav>
</div>
</nav>

+ 31
- 8
frappe/templates/includes/navbar/navbar_items.html Dosyayı Görüntüle

@@ -1,16 +1,39 @@
{% macro render_item(item, submenu=False) %}
{% if item.child_items %}
<li class="nav-item dropdown {% if submenu %} dropdown-submenu {% endif %}">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ item.label }}
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
{% for child in item.child_items %}
{{ render_item(child, True) }}
{% endfor %}
</ul>
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{{ (item.url or '')|abs_url }}"
{{ item.target or ''}}>
{{ item.label }}
</a>
</li>
{% endif %}
{% endmacro %}

{% if top_bar_items -%}
<ul class="nav navbar-nav navbar-left">
{%- for page in top_bar_items -%}
{% if not page.parent_label and not page.right -%}
{% include "templates/includes/navbar/navbar_link.html" %}
<ul class="navbar-nav mr-auto">
{%- for item in top_bar_items -%}
{% if not item.parent_label and not item.right -%}
{{ render_item(item) }}
{%- endif -%}
{%- endfor %}
</ul>
{%- endif %}
<ul class="nav navbar-nav navbar-right">
{%- for page in top_bar_items -%}
{% if not page.parent_label and page.right -%}
{% include "templates/includes/navbar/navbar_link.html" %}
<ul class="navbar-nav ml-auto">
{%- for item in top_bar_items -%}
{% if not item.parent_label and item.right -%}
{{ render_item(item) }}
{%- endif -%}
{%- endfor %}
{% if not only_static %}


+ 0
- 20
frappe/templates/includes/navbar/navbar_link.html Dosyayı Görüntüle

@@ -1,20 +0,0 @@
<li data-label='{{ page.label }}' {% if page.child_items %} class="dropdown dropdown-submenu"{% endif %}>
<a {% if not page.child_items -%} href="{{ (page.url or '')|abs_url }}" {%- endif %}
{% if page.child_items %} class="dropdown-toggle" onclick="return false;" data-toggle="dropdown"{% endif %}
{{ page.target or ''}}>
{{ page.label }}
{%- if page.child_items -%}
<span class="caret"></span>
</a>
<ul class="dropdown-menu" role="menu">
{%- for child in page.child_items -%}
<li data-label='{{ child.label }}'>
<a {% if child.indent %} style="padding-left: {{((child.indent|int)+1)*15 }}px"{% endif %}
href="{{ child.url | abs_url }}" {{ child.target or '' }}>{{ child.label }}</a>
</li>
{%- endfor -%}
</ul>
{%- else -%}
</a>
{%- endif -%}
</li>

+ 11
- 17
frappe/templates/includes/navbar/navbar_login.html Dosyayı Görüntüle

@@ -1,29 +1,23 @@
<!-- post login tools -->
{% if not only_static %}
<li class="dropdown logged-in" id="website-post-login"
data-label="website-post-login" style="display: none">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<li class="dropdown logged-in" id="website-post-login" data-label="website-post-login" style="display: none">
<a href="#" class="nav-item nav-link dropdown-toggle" data-toggle="dropdown">
<span class="user-image-wrapper"></span>
<span class="full-name"></span>
<b class="caret"></b>
</a>
<ul class="dropdown-menu" role="menu">
<ul class="dropdown-menu dropdown-menu-right" role="menu">
{%- for child in post_login -%}
<li {% if child.label %}data-label="{{ child.label }}" {% endif %}
{% if child.class %} class="{{ child.class }}" {% endif %}>

{%- if child.url -%}
<a href="{{ child.url | abs_url }}" {{ child.target or '' }}
rel="nofollow">
{{ child.label }}
</a>
{%- endif -%}
</li>
{%- if child.url -%}
<a class="dropdown-item" href="{{ child.url | abs_url }}" {{ child.target or '' }} rel="nofollow">
{{ child.label }}
</a>
{%- endif -%}
{%- endfor -%}
<li class='switch-to-desk hidden'><a href="/desk">{{ _('Switch To Desk') }}</a></li>
<a class="dropdown-item switch-to-desk hidden" href="/desk">{{ _('Switch To Desk') }}</a>
</ul>
</li>
{% if not hide_login %}
<li class="btn-login-area"><a href="/login">{{ _("Login") }}</a></li>
{% endif %}
<a class="dropdown-item btn-login-area" href="/login">{{ _("Login") }}</a>
{% endif %}
{% endif %}

+ 3
- 13
frappe/templates/includes/search_box.html Dosyayı Görüntüle

@@ -1,16 +1,6 @@
<div class="item-search text-muted pull-right">
<div class='input-wrapper'>
<input type="text" class="item-search-input form-control"
placeholder="{{ _("Search") }}" autocomplete="off">
<i class="octicon octicon-search pull-right" style='cursor: pointer;'></i>
</div>
</div>
<div class="clearfix pull-right" style="width:100%;">
<h5 class="item-search-results" style="margin-right: 30px;"></h5>
<p class="pull-right" style="margin-top: -28px;">
<a style="display: none;" href="javascript:history.back();" class="octicon octicon-x text-extra-muted clear" title="{{ _("Clear Search") }}" ></a>
</p>
</div>
<form class="form-inline search-box justify-content-end">
<input type="text" class="item-search-input form-control" placeholder="{{ _("Search...") }}" autocomplete="off">
</form>

<script>
frappe.ready(function() {


+ 40
- 44
frappe/templates/web.html Dosyayı Görüntüle

@@ -1,55 +1,51 @@
{% extends base_template_path %}
{% block hero %}{% endblock %}

{% macro container_attributes() %}
id="page-{{ name or route }}" data-path="{{ pathname }}"
{%- if page_or_generator=="Generator" %}source-type="Generator" data-doctype="{{ doctype }}"{% endif %}
{% endmacro %}

{% block content %}
<div class="page-container" {{ container_attributes() }}>
{% if show_sidebar %}
<div class="sidebar-block">
{% include "templates/includes/web_sidebar.html" %}

{% macro main_content() %}
<!-- breadcrumbs -->
<div class="page-breadcrumbs">
{% block breadcrumbs %}
{% include 'templates/includes/breadcrumbs.html' %}
{% endblock %}
</div>

<main class="container">
<div class="page-header">
{% block header %}{% endblock %}
</div>
{% endif %}
<div class="{% if show_sidebar %}page-content with-sidebar{% else %}page-content without-sidebar{% endif %}">
<div class="page-content-wrapper">
<div class="row page-head">
<div class='col-sm-12'>
{% if not no_breadcrumbs and parents %}
<div class="page-breadcrumbs">
{% block breadcrumbs %}
{% include 'templates/includes/breadcrumbs.html' %}
{% endblock %}
</div>
{% endif %}
</div>
<div class="col-sm-8 col-xs-6">
{% block header %}{% endblock %}
</div>
<div class="col-sm-4 col-xs-6">
{% if show_search %}
<div class="page-search-block">
{% block search %}
{% include
'templates/includes/search_box.html' %}
{% endblock %}
</div>
{% endif %}

{% if self.header_actions() %}
<div class="page-header-actions-block">
{% block header_actions %}{% endblock %}
</div>
{% endif %}
</div>
</div>
<div class="page_content">
{%- block page_content -%}{%- endblock -%}
{% if self.header_actions() %}
<div class="page-header-actions-block">
{% block header_actions %}{% endblock %}
</div>
{% endif %}

<div class="page_content">
{%- block page_content -%}{%- endblock -%}
</div>
</main>
{% endmacro %}

{% macro container_attributes() %}
id="page-{{ name or route }}" data-path="{{ pathname }}" {%- if page_or_generator=="Generator" %}source-type="Generator" data-doctype="{{ doctype }}"{% endif %}
{% endmacro %}

{% if show_sidebar %}
<div class="container">
<div class="row" {{ container_attributes() }}>
<div class="pt-4 col-sm-2 border-right sidebar-column">
{% include "templates/includes/web_sidebar.html" %}
</div>
<div class="col-sm-10 main-column">
{{ main_content() }}
</div>
<!-- sidebar ends -->
</div>
</div>
{% else %}
<div {{ container_attributes() }}>
{{ main_content() }}
</div>
{% endif %}
{% endblock %}

+ 1
- 1
frappe/website/doctype/website_settings/website_settings.js Dosyayı Görüntüle

@@ -50,7 +50,7 @@ frappe.ui.form.on('Website Settings', {
var main_items = [''];
for (var i in items) {
var d = items[i];
if(!d.parent_label && !d.url && d.label) {
if(!d.url && d.label) {
main_items.push(d.label);
}
}


+ 1
- 2
frappe/website/doctype/website_settings/website_settings.py Dosyayı Görüntüle

@@ -74,7 +74,6 @@ def get_website_settings():
'footer_items': get_items('footer_items'),
"post_login": [
{"label": _("My Account"), "url": "/me"},
# {"class": "divider"},
{"label": _("Logout"), "url": "/?cmd=web_logout"}
]
})
@@ -129,7 +128,7 @@ def get_items(parentfield):
where parent='Website Settings' and parentfield= %s
order by idx asc""", parentfield, as_dict=1)

top_items = [d for d in all_top_items if not d['parent_label']]
top_items = all_top_items[:]

# attach child items to top bar
for d in all_top_items:


+ 3
- 4
frappe/website/doctype/website_theme/website_theme.py Dosyayı Görüntüle

@@ -63,8 +63,7 @@ def use_theme(theme):
website_settings.save()

def add_website_theme(context):
bootstrap = frappe.get_hooks("bootstrap")[0]
bootstrap = [bootstrap]
custom_bootstrap_theme = []
context.theme = frappe._dict()

if not context.disable_website_theme:
@@ -73,11 +72,11 @@ def add_website_theme(context):

if website_theme:
if website_theme.bootstrap:
bootstrap.append(website_theme.bootstrap)
custom_bootstrap_theme.append(website_theme.bootstrap)

context.web_include_css = context.web_include_css + ["website_theme.css"]

context.web_include_css = bootstrap + context.web_include_css
context.web_include_css = custom_bootstrap_theme + context.web_include_css

def get_active_theme():
website_theme = frappe.db.get_value("Website Settings", "Website Settings", "website_theme")


+ 43
- 0
frappe/website/js/bootstrap-4.js Dosyayı Görüntüle

@@ -0,0 +1,43 @@
import 'bootstrap/dist/js/bootstrap.bundle';

// multilevel dropdown
$('.dropdown-menu a.dropdown-toggle').on('click', function (e) {
e.preventDefault();
e.stopImmediatePropagation();
if (!$(this).next().hasClass('show')) {
$(this).parents('.dropdown-menu').first().find('.show').removeClass("show");
}
var $subMenu = $(this).next(".dropdown-menu");
$subMenu.toggleClass('show');


$(this).parents('li.nav-item.dropdown.show').on('hidden.bs.dropdown', function (e) {
$('.dropdown-submenu .show').removeClass("show");
});


return false;
});

frappe.get_modal = function(title, content) {
return $(
`<div class="modal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">${title}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body py-4">
${content}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>`
);
};

+ 1
- 0
package.json Dosyayı Görüntüle

@@ -18,6 +18,7 @@
"dependencies": {
"ace-builds": "^1.4.1",
"awesomplete": "^1.1.2",
"bootstrap": "^4.1.3",
"cookie": "^0.3.1",
"express": "^4.16.2",
"frappe-datatable": "^1.5.3",


+ 5
- 0
yarn.lock Dosyayı Görüntüle

@@ -357,6 +357,11 @@ boom@2.x.x:
dependencies:
hoek "2.x.x"

bootstrap@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.1.3.tgz#0eb371af2c8448e8c210411d0cb824a6409a12be"
integrity sha512-rDFIzgXcof0jDyjNosjv4Sno77X4KuPeFxG2XZZv1/Kc8DRVGVADdoQyyOVDwPqL36DDmtCQbrpMCqvpPLJQ0w==

brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"


Yükleniyor…
İptal
Kaydet