- Deprecate use of build.json - *.bundle.js files placed anywhere in the public folder are bundled - Built files are created in public/build folder which is gitignored WIPversion-14
@@ -9,6 +9,7 @@ locale | |||
dist/ | |||
# build/ | |||
frappe/docs/current | |||
frappe/public/build | |||
.vscode | |||
node_modules | |||
.kdev4/ | |||
@@ -0,0 +1,44 @@ | |||
module.exports = { | |||
name: "frappe-html", | |||
setup(build) { | |||
let path = require("path"); | |||
let fs = require("fs/promises"); | |||
build.onResolve({ filter: /\.html$/ }, args => { | |||
return { | |||
path: path.join(args.resolveDir, args.path), | |||
namespace: "frappe-html" | |||
}; | |||
}); | |||
build.onLoad({ filter: /.*/, namespace: "frappe-html" }, args => { | |||
let filepath = args.path; | |||
let filename = path.basename(filepath).split(".")[0]; | |||
return fs | |||
.readFile(filepath, "utf-8") | |||
.then(content => { | |||
content = scrub_html_template(content); | |||
return { | |||
contents: `\n\tfrappe.templates['${filename}'] = '${content}';\n` | |||
}; | |||
}) | |||
.catch(() => { | |||
return { | |||
contents: "", | |||
warnings: [ | |||
{ | |||
text: `There was an error importing ${filepath}` | |||
} | |||
] | |||
}; | |||
}); | |||
}); | |||
} | |||
}; | |||
function scrub_html_template(content) { | |||
content = content.replace(/\s/g, " "); | |||
content = content.replace(/(<!--.*?-->)/g, ""); | |||
return content.replace("'", "'"); // eslint-disable-line | |||
} |
@@ -0,0 +1,69 @@ | |||
let esbuild = require("esbuild"); | |||
let htmlPlugin = require("./esbuild-plugin-html"); | |||
let vue = require("esbuild-vue"); | |||
let http = require("http"); | |||
let httpProxy = require("http-proxy"); | |||
let path = require("path"); | |||
const { get_public_path, apps_list } = require("../rollup/rollup.utils"); | |||
let proxy = httpProxy.createProxyServer({}); | |||
proxy.on("error", function(e) { | |||
console.error(e); | |||
}); | |||
let server = http.createServer((req, res) => { | |||
if (req.url.includes("/public/")) { | |||
buildAsset(req.url).then(result => { | |||
if (!result) { | |||
proxy_request(); | |||
return; | |||
} | |||
res.setHeader("Content-Header", "application/javascript"); | |||
res.writeHead(200); | |||
res.end(result); | |||
}); | |||
} else { | |||
proxy_request(); | |||
} | |||
function proxy_request() { | |||
proxy.web(req, res, { target: "http://localhost:8000" }); | |||
} | |||
}); | |||
server.listen(8080); | |||
server.on("listening", () => { | |||
console.log("dev server started at http:localhost:8080"); | |||
}); | |||
function buildAsset(url) { | |||
if (url.startsWith("/")) { | |||
url = url.substr(1); | |||
} | |||
let app; | |||
let parts = url.split(path.sep); | |||
if (apps_list.includes(parts[0])) { | |||
app = parts[0]; | |||
} | |||
if (!app) return; | |||
let filepath = path.resolve(get_public_path(app), url.split("public/")[1]); | |||
console.log("building " + url); | |||
return esbuild | |||
.build({ | |||
entryPoints: [filepath], | |||
write: false, | |||
bundle: true, | |||
plugins: [htmlPlugin, vue()], | |||
define: { | |||
"process.env.NODE_ENV": "'development'" | |||
} | |||
}) | |||
.then(result => { | |||
return result.outputFiles[0].text; | |||
}); | |||
} |
@@ -0,0 +1,11 @@ | |||
module.exports = { | |||
name: "frappe-ignore-asset", | |||
setup(build) { | |||
build.onResolve({ filter: /^\/assets\// }, args => { | |||
return { | |||
path: args.path, | |||
external: true | |||
}; | |||
}); | |||
} | |||
}; |
@@ -0,0 +1,79 @@ | |||
let glob = require("fast-glob"); | |||
let esbuild = require("esbuild"); | |||
let html_plugin = require("./esbuild-plugin-html"); | |||
let vue = require("esbuild-vue"); | |||
let postCssPlugin = require("esbuild-plugin-postcss2").default; | |||
let ignore_assets = require("./ignore-assets"); | |||
let { get_options_for_scss } = require("../rollup/rollup.utils"); | |||
console.time("Build time"); | |||
glob(["frappe/public/js/**/*.bundle.js"]).then(entry_files => { | |||
esbuild | |||
.build({ | |||
entryPoints: entry_files, | |||
outdir: "frappe/public/build", | |||
outbase: "frappe/public", | |||
sourcemap: true, | |||
bundle: true, | |||
metafile: true, | |||
minify: true, | |||
define: { | |||
"process.env.NODE_ENV": "'development'" | |||
}, | |||
plugins: [ | |||
html_plugin, | |||
ignore_assets, | |||
vue(), | |||
postCssPlugin({ | |||
plugins: [require("autoprefixer")], | |||
sassOptions: { | |||
...get_options_for_scss(), | |||
importer: function(url) { | |||
if (url.startsWith("~")) { | |||
// strip ~ so that it can resolve from node_modules | |||
url = url.slice(1); | |||
} | |||
if (url.endsWith(".css")) { | |||
// strip .css from end of path | |||
url = url.slice(0, -4); | |||
} | |||
// normal file, let it go | |||
return { | |||
file: url | |||
}; | |||
} | |||
} | |||
}) | |||
], | |||
// watch: { | |||
// onRebuild(error, result) { | |||
// if (error) console.error("watch build failed:", error); | |||
// else { | |||
// console.log("watch build succeeded:"); | |||
// log_build_meta(result.metafile); | |||
// } | |||
// } | |||
// } | |||
}) | |||
.then(result => { | |||
log_build_meta(result.metafile); | |||
if (result.warnings.length) { | |||
console.warn(result.warnings); | |||
} | |||
}) | |||
.catch(e => console.error("error")) | |||
.finally(() => { | |||
console.timeEnd("Build time"); | |||
}); | |||
}); | |||
function log_build_meta(metafile) { | |||
for (let outfile in metafile.outputs) { | |||
if (outfile.endsWith('.map')) continue; | |||
let data = metafile.outputs[outfile]; | |||
console.log(outfile, data.bytes / 1000 + " Kb"); | |||
} | |||
} |
@@ -0,0 +1,110 @@ | |||
const path = require("path"); | |||
const fs = require("fs"); | |||
const frappe_path = path.resolve(__dirname, ".."); | |||
const bench_path = path.resolve(frappe_path, "..", ".."); | |||
const sites_path = path.resolve(bench_path, "sites"); | |||
const assets_path = path.resolve(sites_path, "assets"); | |||
const app_list = get_apps_list(); | |||
const app_paths = app_list.reduce((out, app) => { | |||
out[app] = path.resolve(bench_path, "apps", app, app); | |||
return out; | |||
}, {}); | |||
const public_paths = app_list.reduce((out, app) => { | |||
out[app] = path.resolve(app_paths[app], "public"); | |||
return out; | |||
}, {}); | |||
const public_js_paths = app_list.reduce((out, app) => { | |||
out[app] = path.resolve(app_paths[app], "public/js"); | |||
return out; | |||
}, {}); | |||
const bundle_map = app_list.reduce((out, app) => { | |||
const public_js_path = public_js_paths[app]; | |||
if (fs.existsSync(public_js_path)) { | |||
const all_files = fs.readdirSync(public_js_path); | |||
const js_files = all_files.filter(file => file.endsWith(".js")); | |||
for (let js_file of js_files) { | |||
const filename = path.basename(js_file).split(".")[0]; | |||
out[path.join(app, "js", filename)] = path.resolve( | |||
public_js_path, | |||
js_file | |||
); | |||
} | |||
} | |||
return out; | |||
}, {}); | |||
const get_public_path = app => public_paths[app]; | |||
const get_build_json_path = app => | |||
path.resolve(get_public_path(app), "build.json"); | |||
function get_build_json(app) { | |||
try { | |||
return require(get_build_json_path(app)); | |||
} catch (e) { | |||
// build.json does not exist | |||
return null; | |||
} | |||
} | |||
function delete_file(path) { | |||
if (fs.existsSync(path)) { | |||
fs.unlinkSync(path); | |||
} | |||
} | |||
function run_serially(tasks) { | |||
let result = Promise.resolve(); | |||
tasks.forEach(task => { | |||
if (task) { | |||
result = result.then ? result.then(task) : Promise.resolve(); | |||
} | |||
}); | |||
return result; | |||
} | |||
const get_app_path = app => app_paths[app]; | |||
const get_options_for_scss = () => { | |||
const node_modules_path = path.resolve( | |||
get_app_path("frappe"), | |||
"..", | |||
"node_modules" | |||
); | |||
const app_paths = app_list | |||
.map(get_app_path) | |||
.map(app_path => path.resolve(app_path, "..")); | |||
return { | |||
includePaths: [node_modules_path, ...app_paths] | |||
}; | |||
}; | |||
function get_apps_list() { | |||
return fs | |||
.readFileSync(path.resolve(sites_path, "apps.txt"), { | |||
encoding: "utf-8" | |||
}) | |||
.split("\n") | |||
.filter(Boolean); | |||
} | |||
module.exports = { | |||
app_list, | |||
bench_path, | |||
assets_path, | |||
sites_path, | |||
bundle_map, | |||
get_public_path, | |||
get_build_json_path, | |||
get_build_json, | |||
get_app_path, | |||
delete_file, | |||
run_serially, | |||
get_options_for_scss | |||
}; |
@@ -30,11 +30,11 @@ page_js = { | |||
# website | |||
app_include_js = [ | |||
"/assets/js/libs.min.js", | |||
"/assets/js/desk.min.js", | |||
"/assets/js/list.min.js", | |||
"/assets/js/form.min.js", | |||
"/assets/js/control.min.js", | |||
"/assets/js/report.min.js", | |||
"frappe/public/js/desk.bundle.js", | |||
"frappe/public/js/list.bundle.js", | |||
"frappe/public/js/form.bundle.js", | |||
"frappe/public/js/controls.bundle.js", | |||
"frappe/public/js/report.bundle.js", | |||
] | |||
app_include_css = [ | |||
"/assets/css/desk.min.css", | |||
@@ -0,0 +1,20 @@ | |||
import "air-datepicker/dist/js/datepicker.min.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.cs.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.da.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.de.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.en.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.es.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.fi.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.fr.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.hu.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.nl.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.pl.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.pt-BR.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.pt.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.ro.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.sk.js"; | |||
import "air-datepicker/dist/js/i18n/datepicker.zh.js"; | |||
import "./frappe/ui/capture.js"; | |||
import "./frappe/form/controls/control.js"; | |||
console.log('controls') |
@@ -0,0 +1,107 @@ | |||
import '../scss/desk.scss'; | |||
import "./frappe/translate.js"; | |||
import "./frappe/class.js"; | |||
import "./frappe/polyfill.js"; | |||
import "./frappe/provide.js"; | |||
import "./frappe/assets.js"; | |||
import "./frappe/format.js"; | |||
import "./frappe/form/formatters.js"; | |||
import "./frappe/dom.js"; | |||
import "./frappe/ui/messages.js"; | |||
import "./frappe/ui/keyboard.js"; | |||
import "./frappe/ui/colors.js"; | |||
import "./frappe/ui/sidebar.js"; | |||
import "./frappe/ui/link_preview.js"; | |||
import "./frappe/request.js"; | |||
import "./frappe/socketio_client.js"; | |||
import "./frappe/utils/utils.js"; | |||
import "./frappe/event_emitter.js"; | |||
import "./frappe/router.js"; | |||
import "./frappe/router_history.js"; | |||
import "./frappe/defaults.js"; | |||
import "./frappe/roles_editor.js"; | |||
import "./frappe/module_editor.js"; | |||
import "./frappe/microtemplate.js"; | |||
import "./frappe/ui/page.html"; | |||
import "./frappe/ui/page.js"; | |||
import "./frappe/ui/slides.js"; | |||
// import "./frappe/ui/onboarding_dialog.js"; | |||
import "./frappe/ui/find.js"; | |||
import "./frappe/ui/iconbar.js"; | |||
import "./frappe/form/layout.js"; | |||
import "./frappe/ui/field_group.js"; | |||
import "./frappe/form/link_selector.js"; | |||
import "./frappe/form/multi_select_dialog.js"; | |||
import "./frappe/ui/dialog.js"; | |||
import "./frappe/ui/capture.js"; | |||
import "./frappe/ui/app_icon.js"; | |||
import "./frappe/ui/theme_switcher.js"; | |||
import "./frappe/model/model.js"; | |||
import "./frappe/db.js"; | |||
import "./frappe/model/meta.js"; | |||
import "./frappe/model/sync.js"; | |||
import "./frappe/model/create_new.js"; | |||
import "./frappe/model/perm.js"; | |||
import "./frappe/model/workflow.js"; | |||
import "./frappe/model/user_settings.js"; | |||
import "./frappe/utils/user.js"; | |||
import "./frappe/utils/common.js"; | |||
import "./frappe/utils/urllib.js"; | |||
import "./frappe/utils/pretty_date.js"; | |||
import "./frappe/utils/test_utils.js"; | |||
import "./frappe/utils/tools.js"; | |||
import "./frappe/utils/datetime.js"; | |||
import "./frappe/utils/number_format.js"; | |||
import "./frappe/utils/help.js"; | |||
import "./frappe/utils/help_links.js"; | |||
import "./frappe/utils/address_and_contact.js"; | |||
import "./frappe/utils/preview_email.js"; | |||
import "./frappe/utils/file_manager.js"; | |||
import "./frappe/upload.js"; | |||
import "./frappe/ui/tree.js"; | |||
import "./frappe/views/container.js"; | |||
import "./frappe/views/breadcrumbs.js"; | |||
import "./frappe/views/factory.js"; | |||
import "./frappe/views/pageview.js"; | |||
import "./frappe/ui/toolbar/awesome_bar.js"; | |||
// import "./frappe/ui/toolbar/energy_points_notifications.js"; | |||
import "./frappe/ui/notifications/notifications.js"; | |||
import "./frappe/ui/toolbar/search.js"; | |||
import "./frappe/ui/toolbar/tag_utils.js"; | |||
import "./frappe/ui/toolbar/search.html"; | |||
import "./frappe/ui/toolbar/search_utils.js"; | |||
import "./frappe/ui/toolbar/about.js"; | |||
import "./frappe/ui/toolbar/navbar.html"; | |||
import "./frappe/ui/toolbar/toolbar.js"; | |||
// import "./frappe/ui/toolbar/notifications.js"; | |||
import "./frappe/views/communication.js"; | |||
import "./frappe/views/translation_manager.js"; | |||
import "./frappe/views/workspace/workspace.js"; | |||
import "./frappe/widgets/widget_group.js"; | |||
import "./frappe/ui/sort_selector.html"; | |||
import "./frappe/ui/sort_selector.js"; | |||
import "./frappe/change_log.html"; | |||
import "./frappe/ui/workspace_loading_skeleton.html"; | |||
import "./frappe/desk.js"; | |||
import "./frappe/query_string.js"; | |||
// import "./frappe/ui/comment.js"; | |||
import "./frappe/chat.js"; | |||
import "./frappe/utils/energy_point_utils.js"; | |||
import "./frappe/utils/dashboard_utils.js"; | |||
import "./frappe/ui/chart.js"; | |||
import "./frappe/ui/datatable.js"; | |||
import "./frappe/ui/driver.js"; | |||
import "./frappe/ui/plyr.js"; | |||
import "./frappe/barcode_scanner/index.js"; |
@@ -0,0 +1,18 @@ | |||
import "./frappe/form/templates/address_list.html"; | |||
import "./frappe/form/templates/attachment.html"; | |||
import "./frappe/form/templates/contact_list.html"; | |||
import "./frappe/form/templates/form_dashboard.html"; | |||
import "./frappe/form/templates/form_footer.html"; | |||
import "./frappe/form/templates/form_links.html"; | |||
import "./frappe/form/templates/form_sidebar.html"; | |||
import "./frappe/form/templates/print_layout.html"; | |||
import "./frappe/form/templates/report_links.html"; | |||
import "./frappe/form/templates/set_sharing.html"; | |||
import "./frappe/form/templates/timeline_message_box.html"; | |||
import "./frappe/form/templates/users_in_sidebar.html"; | |||
import "./frappe/form/controls/control.js"; | |||
import "./frappe/views/formview.js"; | |||
import "./frappe/form/form.js"; | |||
import "./frappe/meta_tag.js"; | |||
@@ -0,0 +1,25 @@ | |||
import "./frappe/class.js"; | |||
import "./frappe/polyfill.js"; | |||
import "./lib/md5.min.js"; | |||
import "./frappe/provide.js"; | |||
import "./frappe/format.js"; | |||
import "./frappe/utils/number_format.js"; | |||
import "./frappe/utils/utils.js"; | |||
import "./frappe/utils/common.js"; | |||
import "./frappe/ui/messages.js"; | |||
import "./frappe/translate.js"; | |||
import "./frappe/utils/pretty_date.js"; | |||
import "./frappe/microtemplate.js"; | |||
import "./frappe/query_string.js"; | |||
import "./frappe/upload.js"; | |||
import "./frappe/model/meta.js"; | |||
import "./frappe/model/model.js"; | |||
import "./frappe/model/perm.js"; | |||
import "./web/bootstrap-4"; | |||
import "../../website/js/website.js"; | |||
import "./frappe/socketio_client.js"; |
@@ -80,4 +80,4 @@ To subclass, use: | |||
// export | |||
global.Class = Class; | |||
})(this); | |||
})(window); |
@@ -543,7 +543,7 @@ frappe.ui.form.Layout = Class.extend({ | |||
} else if (expression.substr(0, 5)=='eval:') { | |||
try { | |||
out = eval(expression.substr(5)); | |||
out = frappe.utils.eval(expression.substr(5), { doc }); | |||
if (parent && parent.istable && expression.includes('is_submittable')) { | |||
out = true; | |||
} | |||
@@ -1,4 +1,5 @@ | |||
// common file between desk and website | |||
import md5 from 'md5' | |||
frappe.avatar = function (user, css_class, title, image_url=null, remove_color=false, filterable=false) { | |||
let user_info; | |||
@@ -375,4 +376,4 @@ frappe.utils.get_page_view_count = function (route) { | |||
return frappe.call("frappe.website.doctype.web_page_view.web_page_view.get_page_view_count", { | |||
path: route | |||
}); | |||
}; | |||
}; |
@@ -954,6 +954,14 @@ Object.assign(frappe.utils, { | |||
return $el; | |||
}, | |||
eval(code, context={}) { | |||
let variable_names = Object.keys(context); | |||
let variables = Object.values(context); | |||
code = `return (${code})`; | |||
let expression_function = new Function(...variable_names, code); | |||
return expression_function(...variables); | |||
}, | |||
get_browser() { | |||
let ua = navigator.userAgent; | |||
let tem; | |||
@@ -445,7 +445,7 @@ frappe.views.QueryReport = class QueryReport extends frappe.views.BaseList { | |||
out = expression; | |||
} else if (expression.substr(0, 5) == 'eval:') { | |||
try { | |||
out = eval(expression.substr(5)); | |||
out = frappe.utils.eval(expression.substr(5), { doc }); | |||
} catch (e) { | |||
frappe.throw(__('Invalid "depends_on" expression set in filter {0}', [filter_label])); | |||
} | |||
@@ -0,0 +1,11 @@ | |||
import "bootstrap/dist/js/bootstrap.bundle.js"; | |||
import Vue from "vue/dist/vue.esm.js"; | |||
import moment from "moment/min/moment-with-locales.js"; | |||
import momentTimezone from "moment-timezone/builds/moment-timezone-with-data.js"; | |||
import "socket.io-client/dist/socket.io.slim.js"; | |||
import "./lib/Sortable.min.js"; | |||
import "./lib/jquery/jquery.hotkeys.js"; | |||
import "./lib/jSignature.min.js"; | |||
window.moment = momentTimezone; | |||
window.Vue = Vue; |
@@ -0,0 +1,42 @@ | |||
import "./frappe/ui/listing.html"; | |||
import "./frappe/model/indicator.js"; | |||
import "./frappe/ui/filters/filter.js"; | |||
import "./frappe/ui/filters/filter_list.js"; | |||
import "./frappe/ui/filters/field_select.js"; | |||
import "./frappe/ui/filters/edit_filter.html"; | |||
import "./frappe/ui/tags.js"; | |||
import "./frappe/ui/tag_editor.js"; | |||
import "./frappe/ui/like.js"; | |||
// import "./frappe/ui/liked_by.html"; | |||
import "../html/print_template.html"; | |||
import "./frappe/list/base_list.js"; | |||
import "./frappe/list/list_view.js"; | |||
import "./frappe/list/list_factory.js"; | |||
import "./frappe/list/list_view_select.js"; | |||
import "./frappe/list/list_sidebar.js"; | |||
import "./frappe/list/list_sidebar.html"; | |||
import "./frappe/list/list_sidebar_stat.html"; | |||
import "./frappe/list/list_sidebar_group_by.js"; | |||
import "./frappe/list/list_view_permission_restrictions.html"; | |||
import "./frappe/views/gantt/gantt_view.js"; | |||
import "./frappe/views/calendar/calendar.js"; | |||
import "./frappe/views/dashboard/dashboard_view.js"; | |||
import "./frappe/views/image/image_view.js"; | |||
import "./frappe/views/map/map_view.js"; | |||
import "./frappe/views/kanban/kanban_view.js"; | |||
import "./frappe/views/inbox/inbox_view.js"; | |||
import "./frappe/views/file/file_view.js"; | |||
import "./frappe/views/treeview.js"; | |||
import "./frappe/views/interaction.js"; | |||
import "./frappe/views/image/image_view_item_row.html"; | |||
import "./frappe/views/image/photoswipe_dom.html"; | |||
import "./frappe/views/kanban/kanban_board.html"; | |||
import "./frappe/views/kanban/kanban_column.html"; | |||
import "./frappe/views/kanban/kanban_card.html"; |
@@ -0,0 +1,9 @@ | |||
import "./lib/clusterize.min.js"; | |||
import "./frappe/views/reports/report_factory.js"; | |||
import "./frappe/views/reports/report_view.js"; | |||
import "./frappe/views/reports/query_report.js"; | |||
import "./frappe/views/reports/print_grid.html"; | |||
import "./frappe/views/reports/print_tree.html"; | |||
import "./frappe/ui/group_by/group_by.html"; | |||
import "./frappe/ui/group_by/group_by.js"; | |||
import "./frappe/views/reports/report_utils.js"; |
@@ -0,0 +1,65 @@ | |||
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 () { | |||
$('.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 modal-dialog-scrollable" 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"> | |||
${frappe.utils.icon('close-alt', 'sm', 'close-alt')} | |||
</button> | |||
</div> | |||
<div class="modal-body"> | |||
${content} | |||
</div> | |||
<div class="modal-footer hidden"> | |||
<button type="button" class="btn btn-default btn-sm btn-modal-close" data-dismiss="modal"> | |||
<i class="octicon octicon-x visible-xs" style="padding: 1px 0px;"></i> | |||
<span class="hidden-xs">${__("Close")}</span> | |||
</button> | |||
<button type="button" class="btn btn-sm btn-primary hidden"></button> | |||
</div> | |||
</div> | |||
</div> | |||
</div>` | |||
); | |||
}; | |||
frappe.ui.Dialog = class Dialog extends frappe.ui.Dialog { | |||
get_primary_btn() { | |||
return this.$wrapper.find(".modal-footer .btn-primary"); | |||
} | |||
set_primary_action(label, click) { | |||
this.$wrapper.find('.modal-footer').removeClass('hidden'); | |||
return super.set_primary_action(label, click) | |||
.removeClass('hidden'); | |||
} | |||
make() { | |||
super.make(); | |||
if (this.fields) { | |||
this.$wrapper.find('.section-body').addClass('w-100'); | |||
} | |||
} | |||
}; |
@@ -1,4 +1,4 @@ | |||
@import "~air-datepicker/dist/css/datepicker.min.css"; | |||
@import "~air-datepicker/dist/css/datepicker.min"; | |||
.datepicker { | |||
@@ -1,5 +1,5 @@ | |||
@import '~quill/dist/quill.snow.css'; | |||
@import '~quill/dist/quill.bubble.css'; | |||
@import '~quill/dist/quill.snow'; | |||
@import '~quill/dist/quill.bubble'; | |||
.ql-toolbar.ql-snow, | |||
.ql-container.ql-snow { | |||
@@ -97,8 +97,7 @@ | |||
{% block base_scripts %} | |||
<!-- js should be loaded in body! --> | |||
<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?ver={{ build_version }}"></script> | |||
<script type="text/javascript" src="/assets/js/bootstrap-4-web.min.js"></script> | |||
<script type="text/javascript" src="/assets/frappe/build/js/frappe-web.bundle.js"></script> | |||
{% endblock %} | |||
{%- for link in web_include_js %} | |||
@@ -23,7 +23,8 @@ def get_jenv(): | |||
'resolve_class': resolve_class, | |||
'inspect': inspect, | |||
'web_blocks': web_blocks, | |||
'web_block': web_block | |||
'web_block': web_block, | |||
'js_asset': js_asset | |||
}) | |||
frappe.local.jenv = jenv | |||
@@ -228,3 +229,9 @@ def web_blocks(blocks): | |||
html += '<script>{}</script>'.format(script) | |||
return html | |||
def js_asset(path): | |||
import frappe | |||
if not frappe.local.dev_server or True: | |||
path = path.replace('frappe/public/', '/assets/frappe/build/') | |||
return f'<script type="text/javascript" src="{path}"></script>' |
@@ -605,7 +605,8 @@ $(document).ready(function() { | |||
$(document).on("page-change", function() { | |||
$(document).trigger("apply_permissions"); | |||
$('.dropdown-toggle').dropdown(); | |||
// TODO: esbuild | |||
// $('.dropdown-toggle').dropdown(); | |||
//multilevel dropdown fix | |||
$('.dropdown-menu .dropdown-submenu .dropdown-toggle').on('click', function(e) { | |||
@@ -52,11 +52,14 @@ | |||
</script> | |||
{% for include in include_js %} | |||
<script type="text/javascript" src="{{ include }}?ver={{ build_version }}"></script> | |||
{% endfor %} | |||
{% include "templates/includes/app_analytics/google_analytics.html" %} | |||
{% include "templates/includes/app_analytics/mixpanel_analytics.html" %} | |||
{% for include in include_js %} | |||
{{ js_asset(include) }} | |||
{% endfor %} | |||
{{ js_asset('frappe/public/js/test.bundle.js') }} | |||
{% include "templates/includes/app_analytics/google_analytics.html" %} | |||
{% include "templates/includes/app_analytics/mixpanel_analytics.html" %} | |||
{% for sound in (sounds or []) %} | |||
<audio preload="auto" id="sound-{{ sound.name }}" volume={{ sound.volume or 1 }}> | |||
@@ -4,8 +4,7 @@ | |||
"build": "node rollup/build.js", | |||
"production": "FRAPPE_ENV=production node rollup/build.js", | |||
"watch": "node rollup/watch.js", | |||
"snyk-protect": "snyk protect", | |||
"prepare": "yarn run snyk-protect" | |||
"snyk-protect": "snyk protect" | |||
}, | |||
"repository": { | |||
"type": "git", | |||
@@ -50,14 +49,20 @@ | |||
"socket.io": "^2.4.0", | |||
"superagent": "^3.8.2", | |||
"touch": "^3.1.0", | |||
"vue": "^2.6.11", | |||
"vue": "2.6.12", | |||
"vue-router": "^2.0.0" | |||
}, | |||
"devDependencies": { | |||
"babel-runtime": "^6.26.0", | |||
"chalk": "^2.3.2", | |||
"esbuild": "^0.11.11", | |||
"esbuild-plugin-postcss2": "^0.0.9", | |||
"esbuild-vue": "^0.2.0", | |||
"fast-glob": "^3.2.5", | |||
"graphlib": "^2.1.8", | |||
"http-proxy": "^1.18.1", | |||
"less": "^3.11.1", | |||
"md5": "^2.3.0", | |||
"rollup": "^1.2.2", | |||
"rollup-plugin-buble": "^0.19.2", | |||
"rollup-plugin-commonjs": "^8.3.0", | |||
@@ -66,8 +71,7 @@ | |||
"rollup-plugin-postcss": "^2.0.3", | |||
"rollup-plugin-terser": "^4.0.4", | |||
"rollup-plugin-vue": "4.2.0", | |||
"svg-sprite": "^1.5.0", | |||
"vue-template-compiler": "^2.6.11" | |||
"svg-sprite": "^1.5.0" | |||
}, | |||
"snyk": true | |||
} |