@@ -0,0 +1,12 @@ | |||
# Since version 2.23 (released in August 2019), git-blame has a feature | |||
# to ignore or bypass certain commits. | |||
# | |||
# This file contains a list of commits that are not likely what you | |||
# are looking for in a blame, such as mass reformatting or renaming. | |||
# You can set this file as a default ignore file for blame by running | |||
# the following command. | |||
# | |||
# $ git config blame.ignoreRevsFile .git-blame-ignore-revs | |||
# Replace use of Class.extend with native JS class | |||
fe20515c23a3ac41f1092bf0eaf0a0a452ec2e85 |
@@ -15,11 +15,11 @@ jobs: | |||
path: 'frappe' | |||
- uses: actions/setup-node@v1 | |||
with: | |||
python-version: '12.x' | |||
node-version: 14 | |||
- uses: actions/setup-python@v2 | |||
with: | |||
python-version: '3.6' | |||
- name: Set up bench for current push | |||
- name: Set up bench and build assets | |||
run: | | |||
npm install -g yarn | |||
pip3 install -U frappe-bench | |||
@@ -29,7 +29,7 @@ jobs: | |||
- name: Package assets | |||
run: | | |||
mkdir -p $GITHUB_WORKSPACE/build | |||
tar -cvpzf $GITHUB_WORKSPACE/build/$GITHUB_SHA.tar.gz ./frappe-bench/sites/assets/js ./frappe-bench/sites/assets/css | |||
tar -cvpzf $GITHUB_WORKSPACE/build/$GITHUB_SHA.tar.gz ./frappe-bench/sites/assets/frappe/dist | |||
- name: Publish assets to S3 | |||
uses: jakejarvis/s3-sync-action@master | |||
@@ -22,7 +22,7 @@ jobs: | |||
- uses: actions/setup-python@v2 | |||
with: | |||
python-version: '3.6' | |||
- name: Set up bench for current push | |||
- name: Set up bench and build assets | |||
run: | | |||
npm install -g yarn | |||
pip3 install -U frappe-bench | |||
@@ -32,7 +32,7 @@ jobs: | |||
- name: Package assets | |||
run: | | |||
mkdir -p $GITHUB_WORKSPACE/build | |||
tar -cvpzf $GITHUB_WORKSPACE/build/assets.tar.gz ./frappe-bench/sites/assets/js ./frappe-bench/sites/assets/css | |||
tar -cvpzf $GITHUB_WORKSPACE/build/assets.tar.gz ./frappe-bench/sites/assets/frappe/dist | |||
- name: Get release | |||
id: get_release | |||
@@ -35,7 +35,7 @@ jobs: | |||
- uses: actions/setup-node@v2 | |||
with: | |||
node-version: '14' | |||
node-version: 14 | |||
check-latest: true | |||
- name: Add to Hosts | |||
@@ -35,7 +35,7 @@ jobs: | |||
- uses: actions/setup-node@v2 | |||
with: | |||
node-version: '12' | |||
node-version: 14 | |||
check-latest: true | |||
- name: Add to Hosts | |||
@@ -9,6 +9,7 @@ locale | |||
dist/ | |||
# build/ | |||
frappe/docs/current | |||
frappe/public/dist | |||
.vscode | |||
node_modules | |||
.kdev4/ | |||
@@ -50,7 +50,7 @@ context('Recorder', () => { | |||
cy.get('.result-list').should('contain', '/api/method/frappe.desk.reportview.get'); | |||
}); | |||
it.only('Recorder View Request', () => { | |||
it('Recorder View Request', () => { | |||
cy.get('.primary-action').should('contain', 'Start').click(); | |||
cy.visit('/app/List/DocType/List'); | |||
@@ -0,0 +1,486 @@ | |||
/* eslint-disable no-console */ | |||
let path = require("path"); | |||
let fs = require("fs"); | |||
let glob = require("fast-glob"); | |||
let esbuild = require("esbuild"); | |||
let vue = require("esbuild-vue"); | |||
let yargs = require("yargs"); | |||
let cliui = require("cliui")(); | |||
let chalk = require("chalk"); | |||
let html_plugin = require("./frappe-html"); | |||
let postCssPlugin = require("esbuild-plugin-postcss2").default; | |||
let ignore_assets = require("./ignore-assets"); | |||
let sass_options = require("./sass_options"); | |||
let { | |||
app_list, | |||
assets_path, | |||
apps_path, | |||
sites_path, | |||
get_app_path, | |||
get_public_path, | |||
log, | |||
log_warn, | |||
log_error, | |||
bench_path, | |||
get_redis_subscriber | |||
} = require("./utils"); | |||
let argv = yargs | |||
.usage("Usage: node esbuild [options]") | |||
.option("apps", { | |||
type: "string", | |||
description: "Run build for specific apps" | |||
}) | |||
.option("skip_frappe", { | |||
type: "boolean", | |||
description: "Skip building frappe assets" | |||
}) | |||
.option("files", { | |||
type: "string", | |||
description: "Run build for specified bundles" | |||
}) | |||
.option("watch", { | |||
type: "boolean", | |||
description: "Run in watch mode and rebuild on file changes" | |||
}) | |||
.option("production", { | |||
type: "boolean", | |||
description: "Run build in production mode" | |||
}) | |||
.option("run-build-command", { | |||
type: "boolean", | |||
description: "Run build command for apps" | |||
}) | |||
.example( | |||
"node esbuild --apps frappe,erpnext", | |||
"Run build only for frappe and erpnext" | |||
) | |||
.example( | |||
"node esbuild --files frappe/website.bundle.js,frappe/desk.bundle.js", | |||
"Run build only for specified bundles" | |||
) | |||
.version(false).argv; | |||
const APPS = (!argv.apps ? app_list : argv.apps.split(",")).filter( | |||
app => !(argv.skip_frappe && app == "frappe") | |||
); | |||
const FILES_TO_BUILD = argv.files ? argv.files.split(",") : []; | |||
const WATCH_MODE = Boolean(argv.watch); | |||
const PRODUCTION = Boolean(argv.production); | |||
const RUN_BUILD_COMMAND = !WATCH_MODE && Boolean(argv["run-build-command"]); | |||
const TOTAL_BUILD_TIME = `${chalk.black.bgGreen(" DONE ")} Total Build Time`; | |||
const NODE_PATHS = [].concat( | |||
// node_modules of apps directly importable | |||
app_list | |||
.map(app => path.resolve(get_app_path(app), "../node_modules")) | |||
.filter(fs.existsSync), | |||
// import js file of any app if you provide the full path | |||
app_list | |||
.map(app => path.resolve(get_app_path(app), "..")) | |||
.filter(fs.existsSync) | |||
); | |||
execute() | |||
.then(() => RUN_BUILD_COMMAND && run_build_command_for_apps(APPS)) | |||
.catch(e => console.error(e)); | |||
if (WATCH_MODE) { | |||
// listen for open files in editor event | |||
open_in_editor(); | |||
} | |||
async function execute() { | |||
console.time(TOTAL_BUILD_TIME); | |||
if (!FILES_TO_BUILD.length) { | |||
await clean_dist_folders(APPS); | |||
} | |||
let result; | |||
try { | |||
result = await build_assets_for_apps(APPS, FILES_TO_BUILD); | |||
} catch (e) { | |||
log_error("There were some problems during build"); | |||
log(); | |||
log(chalk.dim(e.stack)); | |||
return; | |||
} | |||
if (!WATCH_MODE) { | |||
log_built_assets(result.metafile); | |||
console.timeEnd(TOTAL_BUILD_TIME); | |||
log(); | |||
} else { | |||
log("Watching for changes..."); | |||
} | |||
return await write_assets_json(result.metafile); | |||
} | |||
function build_assets_for_apps(apps, files) { | |||
let { include_patterns, ignore_patterns } = files.length | |||
? get_files_to_build(files) | |||
: get_all_files_to_build(apps); | |||
return glob(include_patterns, { ignore: ignore_patterns }).then(files => { | |||
let output_path = assets_path; | |||
let file_map = {}; | |||
for (let file of files) { | |||
let relative_app_path = path.relative(apps_path, file); | |||
let app = relative_app_path.split(path.sep)[0]; | |||
let extension = path.extname(file); | |||
let output_name = path.basename(file, extension); | |||
if ( | |||
[".css", ".scss", ".less", ".sass", ".styl"].includes(extension) | |||
) { | |||
output_name = path.join("css", output_name); | |||
} else if ([".js", ".ts"].includes(extension)) { | |||
output_name = path.join("js", output_name); | |||
} | |||
output_name = path.join(app, "dist", output_name); | |||
if (Object.keys(file_map).includes(output_name)) { | |||
log_warn( | |||
`Duplicate output file ${output_name} generated from ${file}` | |||
); | |||
} | |||
file_map[output_name] = file; | |||
} | |||
return build_files({ | |||
files: file_map, | |||
outdir: output_path | |||
}); | |||
}); | |||
} | |||
function get_all_files_to_build(apps) { | |||
let include_patterns = []; | |||
let ignore_patterns = []; | |||
for (let app of apps) { | |||
let public_path = get_public_path(app); | |||
include_patterns.push( | |||
path.resolve( | |||
public_path, | |||
"**", | |||
"*.bundle.{js,ts,css,sass,scss,less,styl}" | |||
) | |||
); | |||
ignore_patterns.push( | |||
path.resolve(public_path, "node_modules"), | |||
path.resolve(public_path, "dist") | |||
); | |||
} | |||
return { | |||
include_patterns, | |||
ignore_patterns | |||
}; | |||
} | |||
function get_files_to_build(files) { | |||
// files: ['frappe/website.bundle.js', 'erpnext/main.bundle.js'] | |||
let include_patterns = []; | |||
let ignore_patterns = []; | |||
for (let file of files) { | |||
let [app, bundle] = file.split("/"); | |||
let public_path = get_public_path(app); | |||
include_patterns.push(path.resolve(public_path, "**", bundle)); | |||
ignore_patterns.push( | |||
path.resolve(public_path, "node_modules"), | |||
path.resolve(public_path, "dist") | |||
); | |||
} | |||
return { | |||
include_patterns, | |||
ignore_patterns | |||
}; | |||
} | |||
function build_files({ files, outdir }) { | |||
return esbuild.build({ | |||
entryPoints: files, | |||
entryNames: "[dir]/[name].[hash]", | |||
outdir, | |||
sourcemap: true, | |||
bundle: true, | |||
metafile: true, | |||
minify: PRODUCTION, | |||
nodePaths: NODE_PATHS, | |||
define: { | |||
"process.env.NODE_ENV": JSON.stringify( | |||
PRODUCTION ? "production" : "development" | |||
) | |||
}, | |||
plugins: [ | |||
html_plugin, | |||
ignore_assets, | |||
vue(), | |||
postCssPlugin({ | |||
plugins: [require("autoprefixer")], | |||
sassOptions: sass_options | |||
}) | |||
], | |||
watch: get_watch_config() | |||
}); | |||
} | |||
function get_watch_config() { | |||
if (WATCH_MODE) { | |||
return { | |||
async onRebuild(error, result) { | |||
if (error) { | |||
log_error("There was an error during rebuilding changes."); | |||
log(); | |||
log(chalk.dim(error.stack)); | |||
notify_redis({ error }); | |||
} else { | |||
let { | |||
assets_json, | |||
prev_assets_json | |||
} = await write_assets_json(result.metafile); | |||
if (prev_assets_json) { | |||
log_rebuilt_assets(prev_assets_json, assets_json); | |||
} | |||
notify_redis({ success: true }); | |||
} | |||
} | |||
}; | |||
} | |||
return null; | |||
} | |||
async function clean_dist_folders(apps) { | |||
for (let app of apps) { | |||
let public_path = get_public_path(app); | |||
await fs.promises.rmdir(path.resolve(public_path, "dist", "js"), { | |||
recursive: true | |||
}); | |||
await fs.promises.rmdir(path.resolve(public_path, "dist", "css"), { | |||
recursive: true | |||
}); | |||
} | |||
} | |||
function log_built_assets(metafile) { | |||
let column_widths = [60, 20]; | |||
cliui.div( | |||
{ | |||
text: chalk.cyan.bold("File"), | |||
width: column_widths[0] | |||
}, | |||
{ | |||
text: chalk.cyan.bold("Size"), | |||
width: column_widths[1] | |||
} | |||
); | |||
cliui.div(""); | |||
let output_by_dist_path = {}; | |||
for (let outfile in metafile.outputs) { | |||
if (outfile.endsWith(".map")) continue; | |||
let data = metafile.outputs[outfile]; | |||
outfile = path.resolve(outfile); | |||
outfile = path.relative(assets_path, outfile); | |||
let filename = path.basename(outfile); | |||
let dist_path = outfile.replace(filename, ""); | |||
output_by_dist_path[dist_path] = output_by_dist_path[dist_path] || []; | |||
output_by_dist_path[dist_path].push({ | |||
name: filename, | |||
size: (data.bytes / 1000).toFixed(2) + " Kb" | |||
}); | |||
} | |||
for (let dist_path in output_by_dist_path) { | |||
let files = output_by_dist_path[dist_path]; | |||
cliui.div({ | |||
text: dist_path, | |||
width: column_widths[0] | |||
}); | |||
for (let i in files) { | |||
let file = files[i]; | |||
let branch = ""; | |||
if (i < files.length - 1) { | |||
branch = "├─ "; | |||
} else { | |||
branch = "└─ "; | |||
} | |||
let color = file.name.endsWith(".js") ? "green" : "blue"; | |||
cliui.div( | |||
{ | |||
text: branch + chalk[color]("" + file.name), | |||
width: column_widths[0] | |||
}, | |||
{ | |||
text: file.size, | |||
width: column_widths[1] | |||
} | |||
); | |||
} | |||
cliui.div(""); | |||
} | |||
log(cliui.toString()); | |||
} | |||
// to store previous build's assets.json for comparison | |||
let prev_assets_json; | |||
let curr_assets_json; | |||
async function write_assets_json(metafile) { | |||
prev_assets_json = curr_assets_json; | |||
let out = {}; | |||
for (let output in metafile.outputs) { | |||
let info = metafile.outputs[output]; | |||
let asset_path = "/" + path.relative(sites_path, output); | |||
if (info.entryPoint) { | |||
out[path.basename(info.entryPoint)] = asset_path; | |||
} | |||
} | |||
let assets_json_path = path.resolve( | |||
assets_path, | |||
"frappe", | |||
"dist", | |||
"assets.json" | |||
); | |||
let assets_json; | |||
try { | |||
assets_json = await fs.promises.readFile(assets_json_path, "utf-8"); | |||
} catch (error) { | |||
assets_json = "{}"; | |||
} | |||
assets_json = JSON.parse(assets_json); | |||
// update with new values | |||
assets_json = Object.assign({}, assets_json, out); | |||
curr_assets_json = assets_json; | |||
await fs.promises.writeFile( | |||
assets_json_path, | |||
JSON.stringify(assets_json, null, 4) | |||
); | |||
await update_assets_json_in_cache(assets_json); | |||
return { | |||
assets_json, | |||
prev_assets_json | |||
}; | |||
} | |||
function update_assets_json_in_cache(assets_json) { | |||
// update assets_json cache in redis, so that it can be read directly by python | |||
return new Promise(resolve => { | |||
let client = get_redis_subscriber("redis_cache"); | |||
// handle error event to avoid printing stack traces | |||
client.on("error", _ => { | |||
log_warn("Cannot connect to redis_cache to update assets_json"); | |||
}); | |||
client.set("assets_json", JSON.stringify(assets_json), err => { | |||
client.unref(); | |||
resolve(); | |||
}); | |||
}); | |||
} | |||
function run_build_command_for_apps(apps) { | |||
let cwd = process.cwd(); | |||
let { execSync } = require("child_process"); | |||
for (let app of apps) { | |||
if (app === "frappe") continue; | |||
let root_app_path = path.resolve(get_app_path(app), ".."); | |||
let package_json = path.resolve(root_app_path, "package.json"); | |||
if (fs.existsSync(package_json)) { | |||
let { scripts } = require(package_json); | |||
if (scripts && scripts.build) { | |||
log("\nRunning build command for", chalk.bold(app)); | |||
process.chdir(root_app_path); | |||
execSync("yarn build", { encoding: "utf8", stdio: "inherit" }); | |||
} | |||
} | |||
} | |||
process.chdir(cwd); | |||
} | |||
async function notify_redis({ error, success }) { | |||
// notify redis which in turns tells socketio to publish this to browser | |||
let subscriber = get_redis_subscriber("redis_socketio"); | |||
subscriber.on("error", _ => { | |||
log_warn("Cannot connect to redis_socketio for browser events"); | |||
}); | |||
let payload = null; | |||
if (error) { | |||
let formatted = await esbuild.formatMessages(error.errors, { | |||
kind: "error", | |||
terminalWidth: 100 | |||
}); | |||
let stack = error.stack.replace(new RegExp(bench_path, "g"), ""); | |||
payload = { | |||
error, | |||
formatted, | |||
stack | |||
}; | |||
} | |||
if (success) { | |||
payload = { | |||
success: true | |||
}; | |||
} | |||
subscriber.publish( | |||
"events", | |||
JSON.stringify({ | |||
event: "build_event", | |||
message: payload | |||
}) | |||
); | |||
} | |||
function open_in_editor() { | |||
let subscriber = get_redis_subscriber("redis_socketio"); | |||
subscriber.on("error", _ => { | |||
log_warn("Cannot connect to redis_socketio for open_in_editor events"); | |||
}); | |||
subscriber.on("message", (event, file) => { | |||
if (event === "open_in_editor") { | |||
file = JSON.parse(file); | |||
let file_path = path.resolve(file.file); | |||
log("Opening file in editor:", file_path); | |||
let launch = require("launch-editor"); | |||
launch(`${file_path}:${file.line}:${file.column}`); | |||
} | |||
}); | |||
subscriber.subscribe("open_in_editor"); | |||
} | |||
function log_rebuilt_assets(prev_assets, new_assets) { | |||
let added_files = []; | |||
let old_files = Object.values(prev_assets); | |||
let new_files = Object.values(new_assets); | |||
for (let filepath of new_files) { | |||
if (!old_files.includes(filepath)) { | |||
added_files.push(filepath); | |||
} | |||
} | |||
log( | |||
chalk.yellow( | |||
`${new Date().toLocaleTimeString()}: Compiled ${ | |||
added_files.length | |||
} files...` | |||
) | |||
); | |||
for (let filepath of added_files) { | |||
let filename = path.basename(filepath); | |||
log(" " + filename); | |||
} | |||
log(); | |||
} |
@@ -0,0 +1,43 @@ | |||
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(/`/g, "\\`"); | |||
return content; | |||
} |
@@ -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 @@ | |||
require("./esbuild"); |
@@ -0,0 +1,29 @@ | |||
let path = require("path"); | |||
let { get_app_path, app_list } = require("./utils"); | |||
let node_modules_path = path.resolve( | |||
get_app_path("frappe"), | |||
"..", | |||
"node_modules" | |||
); | |||
let app_paths = app_list | |||
.map(get_app_path) | |||
.map(app_path => path.resolve(app_path, "..")); | |||
module.exports = { | |||
includePaths: [node_modules_path, ...app_paths], | |||
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 | |||
}; | |||
} | |||
}; |
@@ -0,0 +1,145 @@ | |||
const path = require("path"); | |||
const fs = require("fs"); | |||
const chalk = require("chalk"); | |||
const frappe_path = path.resolve(__dirname, ".."); | |||
const bench_path = path.resolve(frappe_path, "..", ".."); | |||
const sites_path = path.resolve(bench_path, "sites"); | |||
const apps_path = path.resolve(bench_path, "apps"); | |||
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(apps_path, 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]; | |||
function get_apps_list() { | |||
return fs | |||
.readFileSync(path.resolve(sites_path, "apps.txt"), { | |||
encoding: "utf-8" | |||
}) | |||
.split("\n") | |||
.filter(Boolean); | |||
} | |||
function get_cli_arg(name) { | |||
let args = process.argv.slice(2); | |||
let arg = `--${name}`; | |||
let index = args.indexOf(arg); | |||
let value = null; | |||
if (index != -1) { | |||
value = true; | |||
} | |||
if (value && args[index + 1]) { | |||
value = args[index + 1]; | |||
} | |||
return value; | |||
} | |||
function log_error(message, badge = "ERROR") { | |||
badge = chalk.white.bgRed(` ${badge} `); | |||
console.error(`${badge} ${message}`); // eslint-disable-line no-console | |||
} | |||
function log_warn(message, badge = "WARN") { | |||
badge = chalk.black.bgYellowBright(` ${badge} `); | |||
console.warn(`${badge} ${message}`); // eslint-disable-line no-console | |||
} | |||
function log(...args) { | |||
console.log(...args); // eslint-disable-line no-console | |||
} | |||
function get_redis_subscriber(kind) { | |||
// get redis subscriber that aborts after 10 connection attempts | |||
let { get_redis_subscriber: get_redis } = require("../node_utils"); | |||
return get_redis(kind, { | |||
retry_strategy: function(options) { | |||
// abort after 10 connection attempts | |||
if (options.attempt > 10) { | |||
return undefined; | |||
} | |||
return Math.min(options.attempt * 100, 2000); | |||
} | |||
}); | |||
} | |||
module.exports = { | |||
app_list, | |||
bench_path, | |||
assets_path, | |||
sites_path, | |||
apps_path, | |||
bundle_map, | |||
get_public_path, | |||
get_build_json_path, | |||
get_build_json, | |||
get_app_path, | |||
delete_file, | |||
run_serially, | |||
get_cli_arg, | |||
log, | |||
log_warn, | |||
log_error, | |||
get_redis_subscriber | |||
}; |
@@ -10,9 +10,16 @@ be used to build database driven apps. | |||
Read the documentation: https://frappeframework.com/docs | |||
""" | |||
import os, warnings | |||
_dev_server = os.environ.get('DEV_SERVER', False) | |||
if _dev_server: | |||
warnings.simplefilter('always', DeprecationWarning) | |||
warnings.simplefilter('always', PendingDeprecationWarning) | |||
from werkzeug.local import Local, release_local | |||
import os, sys, importlib, inspect, json, warnings | |||
import sys, importlib, inspect, json | |||
import typing | |||
from past.builtins import cmp | |||
import click | |||
@@ -31,8 +38,6 @@ __title__ = "Frappe Framework" | |||
local = Local() | |||
controllers = {} | |||
warnings.simplefilter('always', DeprecationWarning) | |||
warnings.simplefilter('always', PendingDeprecationWarning) | |||
class _dict(dict): | |||
"""dict like object that exposes keys as attributes""" | |||
@@ -197,7 +202,7 @@ def init(site, sites_path=None, new_site=False): | |||
local.meta_cache = {} | |||
local.form_dict = _dict() | |||
local.session = _dict() | |||
local.dev_server = os.environ.get('DEV_SERVER', False) | |||
local.dev_server = _dev_server | |||
setup_module_map() | |||
@@ -5,6 +5,7 @@ import os | |||
import re | |||
import json | |||
import shutil | |||
import subprocess | |||
from tempfile import mkdtemp, mktemp | |||
from distutils.spawn import find_executable | |||
@@ -15,6 +16,7 @@ import click | |||
import psutil | |||
from urllib.parse import urlparse | |||
from simple_chalk import green | |||
from semantic_version import Version | |||
timestamps = {} | |||
@@ -36,35 +38,36 @@ def download_file(url, prefix): | |||
def build_missing_files(): | |||
# check which files dont exist yet from the build.json and tell build.js to build only those! | |||
'''Check which files dont exist yet from the assets.json and run build for those files''' | |||
missing_assets = [] | |||
current_asset_files = [] | |||
frappe_build = os.path.join("..", "apps", "frappe", "frappe", "public", "build.json") | |||
for type in ["css", "js"]: | |||
current_asset_files.extend( | |||
[ | |||
"{0}/{1}".format(type, name) | |||
for name in os.listdir(os.path.join(sites_path, "assets", type)) | |||
] | |||
) | |||
folder = os.path.join(sites_path, "assets", "frappe", "dist", type) | |||
current_asset_files.extend(os.listdir(folder)) | |||
with open(frappe_build) as f: | |||
all_asset_files = json.load(f).keys() | |||
development = frappe.local.conf.developer_mode or frappe.local.dev_server | |||
build_mode = "development" if development else "production" | |||
for asset in all_asset_files: | |||
if asset.replace("concat:", "") not in current_asset_files: | |||
missing_assets.append(asset) | |||
assets_json = frappe.read_file(frappe.get_app_path('frappe', 'public', 'dist', 'assets.json')) | |||
if assets_json: | |||
assets_json = frappe.parse_json(assets_json) | |||
if missing_assets: | |||
from subprocess import check_call | |||
from shlex import split | |||
for bundle_file, output_file in assets_json.items(): | |||
if not output_file.startswith('/assets/frappe'): | |||
continue | |||
click.secho("\nBuilding missing assets...\n", fg="yellow") | |||
command = split( | |||
"node rollup/build.js --files {0} --no-concat".format(",".join(missing_assets)) | |||
) | |||
check_call(command, cwd=os.path.join("..", "apps", "frappe")) | |||
if os.path.basename(output_file) not in current_asset_files: | |||
missing_assets.append(bundle_file) | |||
if missing_assets: | |||
click.secho("\nBuilding missing assets...\n", fg="yellow") | |||
files_to_build = ["frappe/" + name for name in missing_assets] | |||
bundle(build_mode, files=files_to_build) | |||
else: | |||
# no assets.json, run full build | |||
bundle(build_mode, apps="frappe") | |||
def get_assets_link(frappe_head): | |||
@@ -200,49 +203,51 @@ def setup(): | |||
assets_path = os.path.join(frappe.local.sites_path, "assets") | |||
def get_node_pacman(): | |||
exec_ = find_executable("yarn") | |||
if exec_: | |||
return exec_ | |||
raise ValueError("Yarn not found") | |||
def bundle(no_compress, app=None, hard_link=False, verbose=False, skip_frappe=False): | |||
def bundle(mode, apps=None, hard_link=False, make_copy=False, restore=False, verbose=False, skip_frappe=False, files=None): | |||
"""concat / minify js files""" | |||
setup() | |||
make_asset_dirs(hard_link=hard_link) | |||
pacman = get_node_pacman() | |||
mode = "build" if no_compress else "production" | |||
command = "{pacman} run {mode}".format(pacman=pacman, mode=mode) | |||
mode = "production" if mode == "production" else "build" | |||
command = "yarn run {mode}".format(mode=mode) | |||
if app: | |||
command += " --app {app}".format(app=app) | |||
if apps: | |||
command += " --apps {apps}".format(apps=apps) | |||
if skip_frappe: | |||
command += " --skip_frappe" | |||
frappe_app_path = os.path.abspath(os.path.join(app_paths[0], "..")) | |||
check_yarn() | |||
if files: | |||
command += " --files {files}".format(files=','.join(files)) | |||
command += " --run-build-command" | |||
check_node_executable() | |||
frappe_app_path = frappe.get_app_path("frappe", "..") | |||
frappe.commands.popen(command, cwd=frappe_app_path, env=get_node_env()) | |||
def watch(no_compress): | |||
def watch(apps=None): | |||
"""watch and rebuild if necessary""" | |||
setup() | |||
pacman = get_node_pacman() | |||
command = "yarn run watch" | |||
if apps: | |||
command += " --apps {apps}".format(apps=apps) | |||
frappe_app_path = os.path.abspath(os.path.join(app_paths[0], "..")) | |||
check_yarn() | |||
check_node_executable() | |||
frappe_app_path = frappe.get_app_path("frappe", "..") | |||
frappe.commands.popen("{pacman} run watch".format(pacman=pacman), | |||
cwd=frappe_app_path, env=get_node_env()) | |||
frappe.commands.popen(command, cwd=frappe_app_path, env=get_node_env()) | |||
def check_yarn(): | |||
def check_node_executable(): | |||
node_version = Version(subprocess.getoutput('node -v')[1:]) | |||
warn = '⚠️ ' | |||
if node_version.major < 14: | |||
click.echo(f"{warn} Please update your node version to 14") | |||
if not find_executable("yarn"): | |||
print("Please install yarn using below command and try again.\nnpm install -g yarn") | |||
click.echo(f"{warn} Please install yarn using below command and try again.\nnpm install -g yarn") | |||
click.echo() | |||
def get_node_env(): | |||
node_env = { | |||
@@ -312,13 +317,20 @@ def clear_broken_symlinks(): | |||
def unstrip(message): | |||
def unstrip(message: str) -> str: | |||
"""Pads input string on the right side until the last available column in the terminal | |||
""" | |||
_len = len(message) | |||
try: | |||
max_str = os.get_terminal_size().columns | |||
except Exception: | |||
max_str = 80 | |||
_len = len(message) | |||
_rem = max_str - _len | |||
if _len < max_str: | |||
_rem = max_str - _len | |||
else: | |||
_rem = max_str % _len | |||
return f"{message}{' ' * _rem}" | |||
@@ -331,6 +343,7 @@ def make_asset_dirs(hard_link=False): | |||
start_message = unstrip(f"{'Copying assets from' if hard_link else 'Linking'} {source} to {target}") | |||
fail_message = unstrip(f"Cannot {'copy' if hard_link else 'link'} {source} to {target}") | |||
# Used '\r' instead of '\x1b[1K\r' to print entire lines in smaller terminal sizes | |||
try: | |||
print(start_message, end="\r") | |||
link_assets_dir(source, target, hard_link=hard_link) | |||
@@ -13,6 +13,8 @@ common_default_keys = ["__default", "__global"] | |||
doctype_map_keys = ('energy_point_rule_map', 'assignment_rule_map', | |||
'milestone_tracker_map', 'event_consumer_document_type_map') | |||
bench_cache_keys = ('assets_json',) | |||
global_cache_keys = ("app_hooks", "installed_apps", 'all_apps', | |||
"app_modules", "module_app", "system_settings", | |||
'scheduler_events', 'time_zone', 'webhooks', 'active_domains', | |||
@@ -58,6 +60,7 @@ def clear_global_cache(): | |||
clear_doctype_cache() | |||
clear_website_cache() | |||
frappe.cache().delete_value(global_cache_keys) | |||
frappe.cache().delete_value(bench_cache_keys) | |||
frappe.setup_module_map() | |||
def clear_defaults_cache(user=None): | |||
@@ -16,24 +16,34 @@ from frappe.utils import get_bench_path, update_progress_bar, cint | |||
@click.command('build') | |||
@click.option('--app', help='Build assets for app') | |||
@click.option('--apps', help='Build assets for specific apps') | |||
@click.option('--hard-link', is_flag=True, default=False, help='Copy the files instead of symlinking') | |||
@click.option('--make-copy', is_flag=True, default=False, help='[DEPRECATED] Copy the files instead of symlinking') | |||
@click.option('--restore', is_flag=True, default=False, help='[DEPRECATED] Copy the files instead of symlinking with force') | |||
@click.option('--production', is_flag=True, default=False, help='Build assets in production mode') | |||
@click.option('--verbose', is_flag=True, default=False, help='Verbose') | |||
@click.option('--force', is_flag=True, default=False, help='Force build assets instead of downloading available') | |||
def build(app=None, hard_link=False, make_copy=False, restore=False, verbose=False, force=False): | |||
"Minify + concatenate JS and CSS files, build translations" | |||
def build(app=None, apps=None, hard_link=False, make_copy=False, restore=False, production=False, verbose=False, force=False): | |||
"Compile JS and CSS source files" | |||
from frappe.build import bundle, download_frappe_assets | |||
frappe.init('') | |||
# don't minify in developer_mode for faster builds | |||
no_compress = frappe.local.conf.developer_mode or False | |||
if not apps and app: | |||
apps = app | |||
# dont try downloading assets if force used, app specified or running via CI | |||
if not (force or app or os.environ.get('CI')): | |||
if not (force or apps or os.environ.get('CI')): | |||
# skip building frappe if assets exist remotely | |||
skip_frappe = frappe.build.download_frappe_assets(verbose=verbose) | |||
skip_frappe = download_frappe_assets(verbose=verbose) | |||
else: | |||
skip_frappe = False | |||
# don't minify in developer_mode for faster builds | |||
development = frappe.local.conf.developer_mode or frappe.local.dev_server | |||
mode = "development" if development else "production" | |||
if production: | |||
mode = "production" | |||
if make_copy or restore: | |||
hard_link = make_copy or restore | |||
click.secho( | |||
@@ -41,21 +51,17 @@ def build(app=None, hard_link=False, make_copy=False, restore=False, verbose=Fal | |||
fg="yellow", | |||
) | |||
frappe.build.bundle( | |||
skip_frappe=skip_frappe, | |||
no_compress=no_compress, | |||
hard_link=hard_link, | |||
verbose=verbose, | |||
app=app, | |||
) | |||
bundle(mode, apps=apps, hard_link=hard_link, verbose=verbose, skip_frappe=skip_frappe) | |||
@click.command('watch') | |||
def watch(): | |||
"Watch and concatenate JS and CSS files as and when they change" | |||
import frappe.build | |||
@click.option('--apps', help='Watch assets for specific apps') | |||
def watch(apps=None): | |||
"Watch and compile JS and CSS files as and when they change" | |||
from frappe.build import watch | |||
frappe.init('') | |||
frappe.build.watch(True) | |||
watch(apps) | |||
@click.command('clear-cache') | |||
@@ -501,8 +507,6 @@ frappe.db.connect() | |||
@pass_context | |||
def console(context): | |||
"Start ipython console for a site" | |||
import warnings | |||
site = get_site(context) | |||
frappe.init(site=site) | |||
frappe.connect() | |||
@@ -523,7 +527,6 @@ def console(context): | |||
if failed_to_import: | |||
print("\nFailed to import:\n{}".format(", ".join(failed_to_import))) | |||
warnings.simplefilter('ignore') | |||
IPython.embed(display_banner="", header="", colors="neutral") | |||
@@ -203,7 +203,7 @@ frappe.ui.form.on('Data Import', { | |||
}, | |||
download_template(frm) { | |||
frappe.require('/assets/js/data_import_tools.min.js', () => { | |||
frappe.require('data_import_tools.bundle.js', () => { | |||
frm.data_exporter = new frappe.data_import.DataExporter( | |||
frm.doc.reference_doctype, | |||
frm.doc.import_type | |||
@@ -287,7 +287,7 @@ frappe.ui.form.on('Data Import', { | |||
return; | |||
} | |||
frappe.require('/assets/js/data_import_tools.min.js', () => { | |||
frappe.require('data_import_tools.bundle.js', () => { | |||
frm.import_preview = new frappe.data_import.ImportPreview({ | |||
wrapper: frm.get_field('import_preview').$wrapper, | |||
doctype: frm.doc.reference_doctype, | |||
@@ -11,7 +11,7 @@ frappe.pages['recorder'].on_page_load = function(wrapper) { | |||
frappe.recorder.show(); | |||
}); | |||
frappe.require('/assets/js/frappe-recorder.min.js'); | |||
frappe.require('recorder.bundle.js'); | |||
}; | |||
class Recorder { | |||
@@ -67,8 +67,8 @@ frappe.pages['activity'].on_page_show = function () { | |||
} | |||
frappe.activity.last_feed_date = false; | |||
frappe.activity.Feed = Class.extend({ | |||
init: function (row, data) { | |||
frappe.activity.Feed = class Feed { | |||
constructor(row, data) { | |||
this.scrub_data(data); | |||
this.add_date_separator(row, data); | |||
if (!data.add_class) | |||
@@ -97,8 +97,9 @@ frappe.activity.Feed = Class.extend({ | |||
$(row) | |||
.append(frappe.render_template("activity_row", data)) | |||
.find("a").addClass("grey"); | |||
}, | |||
scrub_data: function (data) { | |||
} | |||
scrub_data(data) { | |||
data.by = frappe.user.full_name(data.owner); | |||
data.avatar = frappe.avatar(data.owner); | |||
@@ -113,9 +114,9 @@ frappe.activity.Feed = Class.extend({ | |||
data.when = comment_when(data.creation); | |||
data.feed_type = data.comment_type || data.communication_medium; | |||
}, | |||
} | |||
add_date_separator: function (row, data) { | |||
add_date_separator(row, data) { | |||
var date = frappe.datetime.str_to_obj(data.creation); | |||
var last = frappe.activity.last_feed_date; | |||
@@ -137,7 +138,7 @@ frappe.activity.Feed = Class.extend({ | |||
} | |||
frappe.activity.last_feed_date = date; | |||
} | |||
}); | |||
}; | |||
frappe.activity.render_heatmap = function (page) { | |||
$('<div class="heatmap-container" style="text-align:center">\ | |||
@@ -292,18 +292,12 @@ def inline_style_in_html(html): | |||
''' Convert email.css and html to inline-styled html | |||
''' | |||
from premailer import Premailer | |||
from frappe.utils.jinja_globals import bundled_asset | |||
apps = frappe.get_installed_apps() | |||
# add frappe email css file | |||
css_files = ['assets/css/email.css'] | |||
if 'frappe' in apps: | |||
apps.remove('frappe') | |||
for app in apps: | |||
path = 'assets/{0}/css/email.css'.format(app) | |||
css_files.append(path) | |||
# get email css files from hooks | |||
css_files = frappe.get_hooks('email_css') | |||
css_files = [bundled_asset(path) for path in css_files] | |||
css_files = [path.lstrip('/') for path in css_files] | |||
css_files = [css_file for css_file in css_files if os.path.exists(os.path.abspath(css_file))] | |||
p = Premailer(html=html, external_styles=css_files, strip_important=False) | |||
@@ -29,16 +29,16 @@ 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", | |||
"libs.bundle.js", | |||
"desk.bundle.js", | |||
"list.bundle.js", | |||
"form.bundle.js", | |||
"controls.bundle.js", | |||
"report.bundle.js", | |||
] | |||
app_include_css = [ | |||
"/assets/css/desk.min.css", | |||
"/assets/css/report.min.css", | |||
"desk.bundle.css", | |||
"report.bundle.css", | |||
] | |||
doctype_js = { | |||
@@ -52,6 +52,8 @@ web_include_js = [ | |||
web_include_css = [] | |||
email_css = ['email.bundle.css'] | |||
website_route_rules = [ | |||
{"from_route": "/blog/<category>", "to_route": "Blog Post"}, | |||
{"from_route": "/kb/<category>", "to_route": "Help Article"}, | |||
@@ -408,14 +408,17 @@ frappe.ui.form.PrintView = class { | |||
setup_print_format_dom(out, $print_format) { | |||
this.print_wrapper.find('.print-format-skeleton').remove(); | |||
let base_url = frappe.urllib.get_base_url(); | |||
let print_css = frappe.assets.bundled_asset('print.bundle.css'); | |||
this.$print_format_body.find('head').html( | |||
`<style type="text/css">${out.style}</style> | |||
<link href="${frappe.urllib.get_base_url()}/assets/css/printview.css" rel="stylesheet">` | |||
<link href="${base_url}${print_css}" rel="stylesheet">` | |||
); | |||
if (frappe.utils.is_rtl(this.lang_code)) { | |||
let rtl_css = frappe.assets.bundled_asset('frappe-rtl.bundle.css'); | |||
this.$print_format_body.find('head').append( | |||
`<link type="text/css" rel="stylesheet" href="${frappe.urllib.get_base_url()}/assets/css/frappe-rtl.css"></link>` | |||
`<link type="text/css" rel="stylesheet" href="${base_url}${rtl_css}"></link>` | |||
); | |||
} | |||
@@ -23,13 +23,13 @@ frappe.pages['print-format-builder'].on_page_show = function(wrapper) { | |||
} | |||
} | |||
frappe.PrintFormatBuilder = Class.extend({ | |||
init: function(parent) { | |||
frappe.PrintFormatBuilder = class PrintFormatBuilder { | |||
constructor(parent) { | |||
this.parent = parent; | |||
this.make(); | |||
this.refresh(); | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
this.custom_html_count = 0; | |||
if(!this.print_format) { | |||
this.show_start(); | |||
@@ -37,8 +37,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
this.page.set_title(this.print_format.name); | |||
this.setup_print_format(); | |||
} | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
this.page = frappe.ui.make_app_page({ | |||
parent: this.parent, | |||
title: __("Print Format Builder"), | |||
@@ -56,15 +56,15 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
this.setup_edit_custom_html(); | |||
// $(this.page.sidebar).css({"position": 'fixed'}); | |||
// $(this.page.main).parent().css({"margin-left": '16.67%'}); | |||
}, | |||
show_start: function() { | |||
} | |||
show_start() { | |||
this.page.main.html(frappe.render_template("print_format_builder_start", {})); | |||
this.page.clear_actions(); | |||
this.page.set_title(__("Print Format Builder")); | |||
this.start_edit_print_format(); | |||
this.start_new_print_format(); | |||
}, | |||
start_edit_print_format: function() { | |||
} | |||
start_edit_print_format() { | |||
// print format control | |||
var me = this; | |||
this.print_format_input = frappe.ui.form.make_control({ | |||
@@ -89,8 +89,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
frappe.set_route('print-format-builder', name); | |||
}); | |||
}); | |||
}, | |||
start_new_print_format: function() { | |||
} | |||
start_new_print_format() { | |||
var me = this; | |||
this.doctype_input = frappe.ui.form.make_control({ | |||
parent: this.page.main.find(".doctype-selector"), | |||
@@ -125,8 +125,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
me.setup_new_print_format(doctype, name); | |||
}); | |||
}, | |||
setup_new_print_format: function(doctype, name, based_on) { | |||
} | |||
setup_new_print_format(doctype, name, based_on) { | |||
frappe.call({ | |||
method: 'frappe.printing.page.print_format_builder.print_format_builder.create_custom_format', | |||
args: { | |||
@@ -143,8 +143,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
} | |||
}, | |||
}); | |||
}, | |||
setup_print_format: function() { | |||
} | |||
setup_print_format() { | |||
var me = this; | |||
frappe.model.with_doctype(this.print_format.doc_type, function(doctype) { | |||
me.meta = frappe.get_meta(me.print_format.doc_type); | |||
@@ -163,23 +163,23 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
frappe.set_route("Form", "Print Format", me.print_format.name); | |||
}); | |||
}); | |||
}, | |||
setup_sidebar: function() { | |||
} | |||
setup_sidebar() { | |||
// prepend custom HTML field | |||
var fields = [this.get_custom_html_field()].concat(this.meta.fields); | |||
this.page.sidebar.html( | |||
$(frappe.render_template("print_format_builder_sidebar", {fields: fields})) | |||
); | |||
this.setup_field_filter(); | |||
}, | |||
get_custom_html_field: function() { | |||
} | |||
get_custom_html_field() { | |||
return { | |||
fieldtype: "Custom HTML", | |||
fieldname: "_custom_html", | |||
label: __("Custom HTML") | |||
} | |||
}, | |||
render_layout: function() { | |||
}; | |||
} | |||
render_layout() { | |||
this.page.main.empty(); | |||
this.prepare_data(); | |||
$(frappe.render_template("print_format_builder_layout", { | |||
@@ -190,8 +190,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
this.setup_edit_heading(); | |||
this.setup_field_settings(); | |||
this.setup_html_data(); | |||
}, | |||
prepare_data: function() { | |||
} | |||
prepare_data() { | |||
this.print_heading_template = null; | |||
this.data = JSON.parse(this.print_format.format_data || "[]"); | |||
if(!this.data.length) { | |||
@@ -280,22 +280,22 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
this.layout_data = $.map(this.layout_data, function(s) { | |||
return s.has_fields ? s : null | |||
}); | |||
}, | |||
get_new_section: function() { | |||
} | |||
get_new_section() { | |||
return {columns: [], no_of_columns: 0, label:''}; | |||
}, | |||
get_new_column: function() { | |||
} | |||
get_new_column() { | |||
return {fields: []} | |||
}, | |||
add_table_properties: function(f) { | |||
} | |||
add_table_properties(f) { | |||
// build table columns and widths in a dict | |||
// visible_columns | |||
var me = this; | |||
if(!f.visible_columns) { | |||
me.init_visible_columns(f); | |||
} | |||
}, | |||
init_visible_columns: function(f) { | |||
} | |||
init_visible_columns(f) { | |||
f.visible_columns = [] | |||
$.each(frappe.get_meta(f.options).fields, function(i, _f) { | |||
if(!in_list(["Section Break", "Column Break"], _f.fieldtype) && | |||
@@ -306,8 +306,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
print_width: (_f.width || ""), print_hide:0}); | |||
} | |||
}); | |||
}, | |||
setup_sortable: function() { | |||
} | |||
setup_sortable() { | |||
var me = this; | |||
// drag from fields library | |||
@@ -332,8 +332,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
Sortable.create(this.page.main.find(".print-format-builder-layout").get(0), | |||
{ handle: ".print-format-builder-section-head" } | |||
); | |||
}, | |||
setup_sortable_for_column: function(col) { | |||
} | |||
setup_sortable_for_column(col) { | |||
var me = this; | |||
Sortable.create(col, { | |||
group: { | |||
@@ -363,8 +363,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
} | |||
}); | |||
}, | |||
setup_field_filter: function() { | |||
} | |||
setup_field_filter() { | |||
var me = this; | |||
this.page.sidebar.find(".filter-fields").on("keyup", function() { | |||
var text = $(this).val(); | |||
@@ -373,8 +373,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
$(this).parent().toggle(show); | |||
}) | |||
}); | |||
}, | |||
setup_section_settings: function() { | |||
} | |||
setup_section_settings() { | |||
var me = this; | |||
this.page.main.on("click", ".section-settings", function() { | |||
var section = $(this).parent().parent(); | |||
@@ -431,8 +431,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
return false; | |||
}); | |||
}, | |||
setup_field_settings: function() { | |||
} | |||
setup_field_settings() { | |||
this.page.main.find(".field-settings").on("click", e => { | |||
const field = $(e.currentTarget).parent(); | |||
// new dialog | |||
@@ -482,8 +482,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
return false; | |||
}); | |||
}, | |||
setup_html_data: function() { | |||
} | |||
setup_html_data() { | |||
// set JQuery `data` for Custom HTML fields, since editing the HTML | |||
// directly causes problem becuase of HTML reformatting | |||
// | |||
@@ -496,8 +496,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
var html = me.custom_html_dict[parseInt(content.attr('data-custom-html-id'))].options; | |||
content.data('content', html); | |||
}) | |||
}, | |||
update_columns_in_section: function(section, no_of_columns, new_no_of_columns) { | |||
} | |||
update_columns_in_section(section, no_of_columns, new_no_of_columns) { | |||
var col_size = 12 / new_no_of_columns, | |||
me = this, | |||
resize = function() { | |||
@@ -539,8 +539,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
resize(); | |||
} | |||
}, | |||
setup_add_section: function() { | |||
} | |||
setup_add_section() { | |||
var me = this; | |||
this.page.main.find(".print-format-builder-add-section").on("click", function() { | |||
// boostrap new section info | |||
@@ -554,8 +554,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
me.setup_sortable_for_column($section.find(".print-format-builder-column").get(0)); | |||
}); | |||
}, | |||
setup_edit_heading: function() { | |||
} | |||
setup_edit_heading() { | |||
var me = this; | |||
var $heading = this.page.main.find(".print-format-builder-print-heading"); | |||
@@ -565,8 +565,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
this.page.main.find(".edit-heading").on("click", function() { | |||
var d = me.get_edit_html_dialog(__("Edit Heading"), __("Heading"), $heading); | |||
}) | |||
}, | |||
setup_column_selector: function() { | |||
} | |||
setup_column_selector() { | |||
var me = this; | |||
this.page.main.on("click", ".select-columns", function() { | |||
var parent = $(this).parents(".print-format-builder-field:first"), | |||
@@ -657,24 +657,24 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
return false; | |||
}); | |||
}, | |||
get_visible_columns_string: function(f) { | |||
} | |||
get_visible_columns_string(f) { | |||
if(!f.visible_columns) { | |||
this.init_visible_columns(f); | |||
} | |||
return $.map(f.visible_columns, function(v) { return v.fieldname + "|" + (v.print_width || "") }).join(","); | |||
}, | |||
get_no_content: function() { | |||
} | |||
get_no_content() { | |||
return __("Edit to add content") | |||
}, | |||
setup_edit_custom_html: function() { | |||
} | |||
setup_edit_custom_html() { | |||
var me = this; | |||
this.page.main.on("click", ".edit-html", function() { | |||
me.get_edit_html_dialog(__("Edit Custom HTML"), __("Custom HTML"), | |||
$(this).parents(".print-format-builder-field:first").find(".html-content")); | |||
}); | |||
}, | |||
get_edit_html_dialog: function(title, label, $content) { | |||
} | |||
get_edit_html_dialog(title, label, $content) { | |||
var me = this; | |||
var d = new frappe.ui.Dialog({ | |||
title: title, | |||
@@ -710,8 +710,8 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
d.show(); | |||
return d; | |||
}, | |||
save_print_format: function() { | |||
} | |||
save_print_format() { | |||
var data = [], | |||
me = this; | |||
@@ -789,4 +789,4 @@ frappe.PrintFormatBuilder = Class.extend({ | |||
} | |||
}); | |||
} | |||
}); | |||
}; |
@@ -7,7 +7,7 @@ | |||
<meta name="description" content=""> | |||
<meta name="author" content=""> | |||
<title>{{ title }}</title> | |||
<link href="{{ base_url }}/assets/css/printview.css" rel="stylesheet"> | |||
<link href="{{ base_url }}{{ frappe.assets.bundled_asset('print.bundle.css') }}" rel="stylesheet"> | |||
<style> | |||
{{ print_css }} | |||
</style> | |||
@@ -0,0 +1 @@ | |||
import "./frappe/barcode_scanner/quagga"; |
@@ -0,0 +1,64 @@ | |||
// 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'); | |||
} | |||
} | |||
}; |
@@ -0,0 +1 @@ | |||
import "./frappe/chat"; |
@@ -0,0 +1 @@ | |||
import "./integrations/razorpay"; |
@@ -0,0 +1,18 @@ | |||
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"; |
@@ -0,0 +1 @@ | |||
import "./frappe/data_import"; |
@@ -0,0 +1,105 @@ | |||
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/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,7 @@ | |||
import "./frappe/dom.js"; | |||
import "./frappe/form/formatters.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"; |
@@ -0,0 +1,17 @@ | |||
import "./frappe/form/templates/address_list.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,26 @@ | |||
import "./jquery-bootstrap"; | |||
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 "./bootstrap-4-web.bundle"; | |||
import "../../website/js/website.js"; | |||
import "./frappe/socketio_client.js"; |
@@ -9,7 +9,14 @@ frappe.require = function(items, callback) { | |||
if(typeof items === "string") { | |||
items = [items]; | |||
} | |||
frappe.assets.execute(items, callback); | |||
items = items.map(item => frappe.assets.bundled_asset(item)); | |||
return new Promise(resolve => { | |||
frappe.assets.execute(items, () => { | |||
resolve(); | |||
callback && callback(); | |||
}); | |||
}); | |||
}; | |||
frappe.assets = { | |||
@@ -160,4 +167,11 @@ frappe.assets = { | |||
frappe.dom.set_style(txt); | |||
} | |||
}, | |||
bundled_asset(path) { | |||
if (!path.startsWith('/assets') && path.includes('.bundle.')) { | |||
return frappe.boot.assets_json[path] || path; | |||
} | |||
return path; | |||
} | |||
}; |
@@ -13,7 +13,7 @@ frappe.barcode.scan_barcode = function() { | |||
} | |||
}, reject); | |||
} else { | |||
frappe.require('/assets/js/barcode_scanner.min.js', () => { | |||
frappe.require('barcode_scanner.bundle.js', () => { | |||
frappe.barcode.get_barcode().then(barcode => { | |||
resolve(barcode); | |||
}); | |||
@@ -0,0 +1,111 @@ | |||
<template> | |||
<div class="build-error-overlay" @click.self="data = null" v-show="data"> | |||
<div class="window" v-if="data"> | |||
<div v-for="(error, i) in data.formatted" :key="i"> | |||
<!-- prettier-ignore --> | |||
<pre class="frame"><component :is="error_component(error, i)" /></pre> | |||
</div> | |||
<pre class="stack">{{ data.stack }}</pre> | |||
</div> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: "BuildError", | |||
data() { | |||
return { | |||
data: null | |||
}; | |||
}, | |||
methods: { | |||
show(data) { | |||
this.data = data; | |||
}, | |||
hide() { | |||
this.data = null; | |||
}, | |||
open_in_editor(location) { | |||
frappe.socketio.socket.emit("open_in_editor", location); | |||
}, | |||
error_component(error, i) { | |||
let location = this.data.error.errors[i].location; | |||
let location_string = `${location.file}:${location.line}:${ | |||
location.column | |||
}`; | |||
let template = error.replace( | |||
" > " + location_string, | |||
` > <a class="file-link" @click="open">${location_string}</a>` | |||
); | |||
return { | |||
template: `<div>${template}</div>`, | |||
methods: { | |||
open() { | |||
frappe.socketio.socket.emit("open_in_editor", location); | |||
} | |||
} | |||
}; | |||
} | |||
} | |||
}; | |||
</script> | |||
<style> | |||
.build-error-overlay { | |||
position: fixed; | |||
top: 0; | |||
left: 0; | |||
width: 100%; | |||
height: 100%; | |||
z-index: 9999; | |||
margin: 0; | |||
background: rgba(0, 0, 0, 0.66); | |||
--monospace: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, | |||
monospace; | |||
--dim: var(--gray-400); | |||
} | |||
.window { | |||
font-family: var(--monospace); | |||
line-height: 1.5; | |||
width: 800px; | |||
color: #d8d8d8; | |||
margin: 30px auto; | |||
padding: 25px 40px; | |||
position: relative; | |||
background: #181818; | |||
border-radius: 6px 6px 8px 8px; | |||
box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3), 0 15px 12px rgba(0, 0, 0, 0.22); | |||
overflow: hidden; | |||
border-top: 8px solid var(--red); | |||
} | |||
pre { | |||
font-family: var(--monospace); | |||
font-size: 13px; | |||
margin-top: 0; | |||
margin-bottom: 1em; | |||
overflow-x: auto; | |||
scrollbar-width: none; | |||
} | |||
code { | |||
font-size: 13px; | |||
font-family: var(--monospace); | |||
color: var(--yellow); | |||
} | |||
.message { | |||
line-height: 1.3; | |||
font-weight: 600; | |||
white-space: pre-wrap; | |||
} | |||
.frame { | |||
color: var(--yellow); | |||
} | |||
.stack { | |||
font-size: 13px; | |||
color: var(--dim); | |||
} | |||
.file-link { | |||
text-decoration: underline !important; | |||
cursor: pointer; | |||
} | |||
</style> |
@@ -0,0 +1,52 @@ | |||
<template> | |||
<div | |||
v-if="is_shown" | |||
class="flex justify-between build-success-message align-center" | |||
> | |||
<div class="mr-4">Compiled successfully</div> | |||
<a class="text-white underline" href="/" @click.prevent="reload"> | |||
Refresh | |||
</a> | |||
</div> | |||
</template> | |||
<script> | |||
export default { | |||
name: "BuildSuccess", | |||
data() { | |||
return { | |||
is_shown: false | |||
}; | |||
}, | |||
methods: { | |||
show() { | |||
this.is_shown = true; | |||
if (this.timeout) { | |||
clearTimeout(this.timeout); | |||
} | |||
this.timeout = setTimeout(() => { | |||
this.hide(); | |||
}, 10000); | |||
}, | |||
hide() { | |||
this.is_shown = false; | |||
}, | |||
reload() { | |||
window.location.reload(); | |||
} | |||
} | |||
}; | |||
</script> | |||
<style> | |||
.build-success-message { | |||
position: fixed; | |||
z-index: 9999; | |||
bottom: 0; | |||
right: 0; | |||
background: rgba(0, 0, 0, 0.6); | |||
border-radius: var(--border-radius); | |||
padding: 0.5rem 1rem; | |||
color: white; | |||
font-weight: 500; | |||
margin: 1rem; | |||
} | |||
</style> |
@@ -0,0 +1,48 @@ | |||
import BuildError from "./BuildError.vue"; | |||
import BuildSuccess from "./BuildSuccess.vue"; | |||
let $container = $("#build-events-overlay"); | |||
let success = null; | |||
let error = null; | |||
frappe.realtime.on("build_event", data => { | |||
if (data.success) { | |||
show_build_success(data); | |||
} else if (data.error) { | |||
show_build_error(data); | |||
} | |||
}); | |||
function show_build_success() { | |||
if (error) { | |||
error.hide(); | |||
} | |||
if (!success) { | |||
let target = $('<div class="build-success-container">') | |||
.appendTo($container) | |||
.get(0); | |||
let vm = new Vue({ | |||
el: target, | |||
render: h => h(BuildSuccess) | |||
}); | |||
success = vm.$children[0]; | |||
} | |||
success.show(); | |||
} | |||
function show_build_error(data) { | |||
if (success) { | |||
success.hide(); | |||
} | |||
if (!error) { | |||
let target = $('<div class="build-error-container">') | |||
.appendTo($container) | |||
.get(0); | |||
let vm = new Vue({ | |||
el: target, | |||
render: h => h(BuildError) | |||
}); | |||
error = vm.$children[0]; | |||
} | |||
error.show(data); | |||
} |
@@ -80,4 +80,4 @@ To subclass, use: | |||
// export | |||
global.Class = Class; | |||
})(this); | |||
})(window); |
@@ -24,12 +24,12 @@ $(document).ready(function() { | |||
frappe.start_app(); | |||
}); | |||
frappe.Application = Class.extend({ | |||
init: function() { | |||
frappe.Application = class Application { | |||
constructor() { | |||
this.startup(); | |||
}, | |||
} | |||
startup: function() { | |||
startup() { | |||
frappe.socketio.init(); | |||
frappe.model.init(); | |||
@@ -115,7 +115,7 @@ frappe.Application = Class.extend({ | |||
}); | |||
// listen to build errors | |||
this.setup_build_error_listener(); | |||
this.setup_build_events(); | |||
if (frappe.sys_defaults.email_user_password) { | |||
var email_list = frappe.sys_defaults.email_user_password.split(','); | |||
@@ -160,7 +160,7 @@ frappe.Application = Class.extend({ | |||
}, 600000); // check every 10 minutes | |||
} | |||
} | |||
}, | |||
} | |||
set_route() { | |||
frappe.flags.setting_original_route = true; | |||
@@ -175,14 +175,14 @@ frappe.Application = Class.extend({ | |||
frappe.router.on('change', () => { | |||
$(".tooltip").hide(); | |||
}); | |||
}, | |||
} | |||
setup_frappe_vue() { | |||
Vue.prototype.__ = window.__; | |||
Vue.prototype.frappe = window.frappe; | |||
}, | |||
} | |||
set_password: function(user) { | |||
set_password(user) { | |||
var me=this; | |||
frappe.call({ | |||
method: 'frappe.core.doctype.user.user.get_email_awaiting', | |||
@@ -199,9 +199,9 @@ frappe.Application = Class.extend({ | |||
} | |||
} | |||
}); | |||
}, | |||
} | |||
email_password_prompt: function(email_account,user,i) { | |||
email_password_prompt(email_account,user,i) { | |||
var me = this; | |||
let d = new frappe.ui.Dialog({ | |||
title: __('Password missing in Email Account'), | |||
@@ -255,8 +255,8 @@ frappe.Application = Class.extend({ | |||
}); | |||
}); | |||
d.show(); | |||
}, | |||
load_bootinfo: function() { | |||
} | |||
load_bootinfo() { | |||
if(frappe.boot) { | |||
this.setup_workspaces(); | |||
frappe.model.sync(frappe.boot.docs); | |||
@@ -278,7 +278,7 @@ frappe.Application = Class.extend({ | |||
} else { | |||
this.set_as_guest(); | |||
} | |||
}, | |||
} | |||
setup_workspaces() { | |||
frappe.modules = {}; | |||
@@ -289,26 +289,26 @@ frappe.Application = Class.extend({ | |||
} | |||
if (!frappe.workspaces['home']) { | |||
// default workspace is settings for Frappe | |||
frappe.workspaces['home'] = frappe.workspaces['build']; | |||
frappe.workspaces['home'] = frappe.workspaces[Object.keys(frappe.workspaces)[0]]; | |||
} | |||
}, | |||
} | |||
load_user_permissions: function() { | |||
load_user_permissions() { | |||
frappe.defaults.update_user_permissions(); | |||
frappe.realtime.on('update_user_permissions', frappe.utils.debounce(() => { | |||
frappe.defaults.update_user_permissions(); | |||
}, 500)); | |||
}, | |||
} | |||
check_metadata_cache_status: function() { | |||
check_metadata_cache_status() { | |||
if(frappe.boot.metadata_version != localStorage.metadata_version) { | |||
frappe.assets.clear_local_storage(); | |||
frappe.assets.init_local_storage(); | |||
} | |||
}, | |||
} | |||
set_globals: function() { | |||
set_globals() { | |||
frappe.session.user = frappe.boot.user.name; | |||
frappe.session.logged_in_user = frappe.boot.user.name; | |||
frappe.session.user_email = frappe.boot.user.email; | |||
@@ -360,8 +360,8 @@ frappe.Application = Class.extend({ | |||
} | |||
} | |||
}); | |||
}, | |||
sync_pages: function() { | |||
} | |||
sync_pages() { | |||
// clear cached pages if timestamp is not found | |||
if(localStorage["page_info"]) { | |||
frappe.boot.allowed_pages = []; | |||
@@ -376,8 +376,8 @@ frappe.Application = Class.extend({ | |||
frappe.boot.allowed_pages = Object.keys(frappe.boot.page_info); | |||
} | |||
localStorage["page_info"] = JSON.stringify(frappe.boot.page_info); | |||
}, | |||
set_as_guest: function() { | |||
} | |||
set_as_guest() { | |||
frappe.session.user = 'Guest'; | |||
frappe.session.user_email = ''; | |||
frappe.session.user_fullname = 'Guest'; | |||
@@ -385,23 +385,23 @@ frappe.Application = Class.extend({ | |||
frappe.user_defaults = {}; | |||
frappe.user_roles = ['Guest']; | |||
frappe.sys_defaults = {}; | |||
}, | |||
make_page_container: function() { | |||
} | |||
make_page_container() { | |||
if ($("#body").length) { | |||
$(".splash").remove(); | |||
frappe.temp_container = $("<div id='temp-container' style='display: none;'>") | |||
.appendTo("body"); | |||
frappe.container = new frappe.views.Container(); | |||
} | |||
}, | |||
make_nav_bar: function() { | |||
} | |||
make_nav_bar() { | |||
// toolbar | |||
if(frappe.boot && frappe.boot.home_page!=='setup-wizard') { | |||
frappe.frappe_toolbar = new frappe.ui.toolbar.Toolbar(); | |||
} | |||
}, | |||
logout: function() { | |||
} | |||
logout() { | |||
var me = this; | |||
me.logged_out = true; | |||
return frappe.call({ | |||
@@ -413,8 +413,8 @@ frappe.Application = Class.extend({ | |||
me.redirect_to_login(); | |||
} | |||
}); | |||
}, | |||
handle_session_expired: function() { | |||
} | |||
handle_session_expired() { | |||
if(!frappe.app.session_expired_dialog) { | |||
var dialog = new frappe.ui.Dialog({ | |||
title: __('Session Expired'), | |||
@@ -464,16 +464,16 @@ frappe.Application = Class.extend({ | |||
'background-color': '#4B4C9D' | |||
}); | |||
} | |||
}, | |||
redirect_to_login: function() { | |||
} | |||
redirect_to_login() { | |||
window.location.href = '/'; | |||
}, | |||
set_favicon: function() { | |||
} | |||
set_favicon() { | |||
var link = $('link[type="image/x-icon"]').remove().attr("href"); | |||
$('<link rel="shortcut icon" href="' + link + '" type="image/x-icon">').appendTo("head"); | |||
$('<link rel="icon" href="' + link + '" type="image/x-icon">').appendTo("head"); | |||
}, | |||
trigger_primary_action: function() { | |||
} | |||
trigger_primary_action() { | |||
// to trigger change event on active input before triggering primary action | |||
$(document.activeElement).blur(); | |||
// wait for possible JS validations triggered after blur (it might change primary button) | |||
@@ -487,20 +487,20 @@ frappe.Application = Class.extend({ | |||
frappe.container.page.save_action(); | |||
} | |||
}, 100); | |||
}, | |||
} | |||
set_rtl: function() { | |||
set_rtl() { | |||
if (frappe.utils.is_rtl()) { | |||
var ls = document.createElement('link'); | |||
ls.rel="stylesheet"; | |||
ls.type = "text/css"; | |||
ls.href= "/assets/css/frappe-rtl.css"; | |||
ls.href= frappe.assets.bundled_asset("frappe-rtl.bundle.css"); | |||
document.getElementsByTagName('head')[0].appendChild(ls); | |||
$('body').addClass('frappe-rtl'); | |||
} | |||
}, | |||
} | |||
show_change_log: function() { | |||
show_change_log() { | |||
var me = this; | |||
let change_log = frappe.boot.change_log; | |||
@@ -531,15 +531,15 @@ frappe.Application = Class.extend({ | |||
}); | |||
me.show_notes(); | |||
}; | |||
}, | |||
} | |||
show_update_available: () => { | |||
show_update_available() { | |||
frappe.call({ | |||
"method": "frappe.utils.change_log.show_update_popup" | |||
}); | |||
}, | |||
} | |||
setup_analytics: function() { | |||
setup_analytics() { | |||
if(window.mixpanel) { | |||
window.mixpanel.identify(frappe.session.user); | |||
window.mixpanel.people.set({ | |||
@@ -549,17 +549,17 @@ frappe.Application = Class.extend({ | |||
"$email": frappe.session.user | |||
}); | |||
} | |||
}, | |||
} | |||
add_browser_class() { | |||
$('html').addClass(frappe.utils.get_browser().name.toLowerCase()); | |||
}, | |||
} | |||
set_fullwidth_if_enabled() { | |||
frappe.ui.toolbar.set_fullwidth_if_enabled(); | |||
}, | |||
} | |||
show_notes: function() { | |||
show_notes() { | |||
var me = this; | |||
if(frappe.boot.notes.length) { | |||
frappe.boot.notes.forEach(function(note) { | |||
@@ -586,21 +586,19 @@ frappe.Application = Class.extend({ | |||
} | |||
}); | |||
} | |||
}, | |||
} | |||
setup_build_error_listener() { | |||
setup_build_events() { | |||
if (frappe.boot.developer_mode) { | |||
frappe.realtime.on('build_error', (data) => { | |||
console.log(data); | |||
}); | |||
frappe.require("build_events.bundle.js"); | |||
} | |||
}, | |||
} | |||
setup_energy_point_listeners() { | |||
frappe.realtime.on('energy_point_alert', (message) => { | |||
frappe.show_alert(message); | |||
}); | |||
}, | |||
} | |||
setup_copy_doc_listener() { | |||
$('body').on('paste', (e) => { | |||
@@ -634,7 +632,7 @@ frappe.Application = Class.extend({ | |||
} | |||
}); | |||
} | |||
}); | |||
} | |||
frappe.get_module = function(m, default_module) { | |||
var module = frappe.modules[m] || default_module; | |||
@@ -1,5 +1,5 @@ | |||
frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({ | |||
make_input: function() { | |||
frappe.ui.form.ControlAttach = class ControlAttach extends frappe.ui.form.ControlData { | |||
make_input() { | |||
let me = this; | |||
this.$input = $('<button class="btn btn-default btn-sm btn-attach">') | |||
.html(__("Attach")) | |||
@@ -26,8 +26,8 @@ frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({ | |||
frappe.utils.bind_actions_with_object(this.$value, this); | |||
this.toggle_reload_button(); | |||
}, | |||
clear_attachment: function() { | |||
} | |||
clear_attachment() { | |||
let me = this; | |||
if(this.frm) { | |||
me.parse_validate_and_set_in_model(null); | |||
@@ -44,16 +44,16 @@ frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({ | |||
this.parse_validate_and_set_in_model(null); | |||
this.refresh(); | |||
} | |||
}, | |||
} | |||
reload_attachment() { | |||
if (this.file_uploader) { | |||
this.file_uploader.uploader.upload_files(); | |||
} | |||
}, | |||
} | |||
on_attach_click() { | |||
this.set_upload_options(); | |||
this.file_uploader = new frappe.ui.FileUploader(this.upload_options); | |||
}, | |||
} | |||
set_upload_options() { | |||
let options = { | |||
allow_multiple: false, | |||
@@ -73,9 +73,9 @@ frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({ | |||
Object.assign(options, this.df.options); | |||
} | |||
this.upload_options = options; | |||
}, | |||
} | |||
set_input: function(value, dataurl) { | |||
set_input(value, dataurl) { | |||
this.value = value; | |||
if(this.value) { | |||
this.$input.toggle(false); | |||
@@ -94,23 +94,23 @@ frappe.ui.form.ControlAttach = frappe.ui.form.ControlData.extend({ | |||
this.$input.toggle(true); | |||
this.$value.toggle(false); | |||
} | |||
}, | |||
} | |||
get_value: function() { | |||
get_value() { | |||
return this.value || null; | |||
}, | |||
} | |||
on_upload_complete: function(attachment) { | |||
on_upload_complete(attachment) { | |||
if(this.frm) { | |||
this.parse_validate_and_set_in_model(attachment.file_url); | |||
this.frm.attachments.update_attachment(attachment); | |||
this.frm.doc.docstatus == 1 ? this.frm.save('Update') : this.frm.save(); | |||
} | |||
this.set_value(attachment.file_url); | |||
}, | |||
} | |||
toggle_reload_button() { | |||
this.$value.find('[data-action="reload_attachment"]') | |||
.toggle(this.file_uploader && this.file_uploader.uploader.files.length > 0); | |||
} | |||
}); | |||
}; |
@@ -1,6 +1,6 @@ | |||
frappe.ui.form.ControlAttachImage = frappe.ui.form.ControlAttach.extend({ | |||
frappe.ui.form.ControlAttachImage = class ControlAttachImage extends frappe.ui.form.ControlAttach { | |||
make_input() { | |||
this._super(); | |||
super.make_input(); | |||
let $file_link = this.$value.find('.attached-file-link'); | |||
$file_link.popover({ | |||
@@ -16,10 +16,10 @@ frappe.ui.form.ControlAttachImage = frappe.ui.form.ControlAttach.extend({ | |||
}, | |||
html: true | |||
}); | |||
}, | |||
} | |||
set_upload_options() { | |||
this._super(); | |||
super.set_upload_options(); | |||
this.upload_options.restrictions = {}; | |||
this.upload_options.restrictions.allowed_file_types = ['image/*']; | |||
} | |||
}); | |||
}; |
@@ -1,19 +1,19 @@ | |||
import Awesomplete from 'awesomplete'; | |||
frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ | |||
trigger_change_on_input_event: false, | |||
frappe.ui.form.ControlAutocomplete = class ControlAutoComplete extends frappe.ui.form.ControlData { | |||
static trigger_change_on_input_event = false | |||
make_input() { | |||
this._super(); | |||
super.make_input(); | |||
this.setup_awesomplete(); | |||
this.set_options(); | |||
}, | |||
} | |||
set_options() { | |||
if (this.df.options) { | |||
let options = this.df.options || []; | |||
this._data = this.parse_options(options); | |||
} | |||
}, | |||
} | |||
get_awesomplete_settings() { | |||
var me = this; | |||
@@ -63,7 +63,7 @@ frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ | |||
return 0; | |||
} | |||
}; | |||
}, | |||
} | |||
setup_awesomplete() { | |||
this.awesomplete = new Awesomplete( | |||
@@ -100,7 +100,7 @@ frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ | |||
this.$input.on('awesomplete-selectcomplete', () => { | |||
this.$input.trigger('change'); | |||
}); | |||
}, | |||
} | |||
validate(value) { | |||
if (this.df.ignore_validation) { | |||
@@ -115,7 +115,7 @@ frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ | |||
} else { | |||
return ''; | |||
} | |||
}, | |||
} | |||
parse_options(options) { | |||
if (typeof options === 'string') { | |||
@@ -125,11 +125,11 @@ frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ | |||
options = options.map(o => ({ label: o, value: o })); | |||
} | |||
return options; | |||
}, | |||
} | |||
get_data() { | |||
return this._data || []; | |||
}, | |||
} | |||
set_data(data) { | |||
data = this.parse_options(data); | |||
@@ -138,4 +138,4 @@ frappe.ui.form.ControlAutocomplete = frappe.ui.form.ControlData.extend({ | |||
} | |||
this._data = data; | |||
} | |||
}); | |||
}; |
@@ -1,9 +1,9 @@ | |||
import JsBarcode from 'jsbarcode'; | |||
frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ | |||
frappe.ui.form.ControlBarcode = class ControlBarcode extends frappe.ui.form.ControlData { | |||
make_wrapper() { | |||
// Create the elements for barcode area | |||
this._super(); | |||
super.make_wrapper(); | |||
this.default_svg = '<svg height=80></svg>'; | |||
let $input_wrapper = this.$wrapper.find('.control-input-wrapper'); | |||
@@ -11,7 +11,7 @@ frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ | |||
`<div class="barcode-wrapper">${this.default_svg}</div>` | |||
); | |||
this.barcode_area.appendTo($input_wrapper); | |||
}, | |||
} | |||
parse(value) { | |||
// Parse raw value | |||
@@ -22,7 +22,7 @@ frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ | |||
return this.get_barcode_html(value); | |||
} | |||
return ''; | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
// Set values to display | |||
@@ -40,7 +40,7 @@ frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ | |||
this.$input.val(barcode_value || value); | |||
this.barcode_area.html(svg || this.default_svg); | |||
}, | |||
} | |||
get_barcode_html(value) { | |||
if (value) { | |||
@@ -51,7 +51,7 @@ frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ | |||
$(svg).attr('width', '100%'); | |||
return this.barcode_area.html(); | |||
} | |||
}, | |||
} | |||
get_options(value) { | |||
// get JsBarcode options | |||
@@ -76,4 +76,4 @@ frappe.ui.form.ControlBarcode = frappe.ui.form.ControlData.extend({ | |||
} | |||
return options; | |||
} | |||
}); | |||
}; |
@@ -1,5 +1,5 @@ | |||
frappe.ui.form.Control = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.Control = class BaseControl { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.make(); | |||
@@ -11,31 +11,31 @@ frappe.ui.form.Control = Class.extend({ | |||
if(this.render_input) { | |||
this.refresh(); | |||
} | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
this.make_wrapper(); | |||
this.$wrapper | |||
.attr("data-fieldtype", this.df.fieldtype) | |||
.attr("data-fieldname", this.df.fieldname); | |||
this.wrapper = this.$wrapper.get(0); | |||
this.wrapper.fieldobj = this; // reference for event handlers | |||
}, | |||
} | |||
make_wrapper: function() { | |||
make_wrapper() { | |||
this.$wrapper = $("<div class='frappe-control'></div>").appendTo(this.parent); | |||
// alias | |||
this.wrapper = this.$wrapper; | |||
}, | |||
} | |||
toggle: function(show) { | |||
toggle(show) { | |||
this.df.hidden = show ? 0 : 1; | |||
this.refresh(); | |||
}, | |||
} | |||
// returns "Read", "Write" or "None" | |||
// as strings based on permissions | |||
get_status: function(explain) { | |||
get_status(explain) { | |||
if (this.df.get_status) { | |||
return this.df.get_status(this); | |||
} | |||
@@ -93,8 +93,8 @@ frappe.ui.form.Control = Class.extend({ | |||
} | |||
return status; | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
this.disp_status = this.get_status(); | |||
this.$wrapper | |||
&& this.$wrapper.toggleClass("hide-control", this.disp_status=="None") | |||
@@ -104,7 +104,7 @@ frappe.ui.form.Control = Class.extend({ | |||
var value = this.get_value(); | |||
this.show_translatable_button(value); | |||
}, | |||
} | |||
show_translatable_button(value) { | |||
// Disable translation non-string fields or special string fields | |||
if (!frappe.model | |||
@@ -138,26 +138,26 @@ frappe.ui.form.Control = Class.extend({ | |||
} | |||
}); | |||
}, | |||
get_doc: function() { | |||
} | |||
get_doc() { | |||
return this.doctype && this.docname | |||
&& locals[this.doctype] && locals[this.doctype][this.docname] || {}; | |||
}, | |||
get_model_value: function() { | |||
} | |||
get_model_value() { | |||
if(this.doc) { | |||
return this.doc[this.df.fieldname]; | |||
} | |||
}, | |||
set_value: function(value) { | |||
} | |||
set_value(value) { | |||
return this.validate_and_set_in_model(value); | |||
}, | |||
parse_validate_and_set_in_model: function(value, e) { | |||
} | |||
parse_validate_and_set_in_model(value, e) { | |||
if(this.parse) { | |||
value = this.parse(value); | |||
} | |||
return this.validate_and_set_in_model(value, e); | |||
}, | |||
validate_and_set_in_model: function(value, e) { | |||
} | |||
validate_and_set_in_model(value, e) { | |||
var me = this; | |||
let force_value_set = (this.doc && this.doc.__run_link_triggers); | |||
let is_value_same = (this.get_model_value() === value); | |||
@@ -193,8 +193,8 @@ frappe.ui.form.Control = Class.extend({ | |||
// all clear | |||
return set(value); | |||
} | |||
}, | |||
get_value: function() { | |||
} | |||
get_value() { | |||
if(this.get_status()==='Write') { | |||
return this.get_input_value ? | |||
(this.parse ? this.parse(this.get_input_value()) : this.get_input_value()) : | |||
@@ -202,8 +202,8 @@ frappe.ui.form.Control = Class.extend({ | |||
} else { | |||
return this.value || undefined; | |||
} | |||
}, | |||
set_model_value: function(value) { | |||
} | |||
set_model_value(value) { | |||
if(this.frm) { | |||
this.last_value = value; | |||
return frappe.model.set_value(this.doctype, this.docname, this.df.fieldname, | |||
@@ -215,11 +215,11 @@ frappe.ui.form.Control = Class.extend({ | |||
this.set_input(value); | |||
return Promise.resolve(); | |||
} | |||
}, | |||
set_focus: function() { | |||
} | |||
set_focus() { | |||
if(this.$input) { | |||
this.$input.get(0).focus(); | |||
return true; | |||
} | |||
} | |||
}); | |||
}; |
@@ -1,14 +1,14 @@ | |||
frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
horizontal: true, | |||
make: function() { | |||
frappe.ui.form.ControlInput = class ControlInput extends frappe.ui.form.Control { | |||
static horizontal = true | |||
make() { | |||
// parent element | |||
this._super(); | |||
super.make(); | |||
this.set_input_areas(); | |||
// set description | |||
this.set_max_width(); | |||
}, | |||
make_wrapper: function() { | |||
} | |||
make_wrapper() { | |||
if(this.only_input) { | |||
this.$wrapper = $('<div class="form-group frappe-control">').appendTo(this.parent); | |||
} else { | |||
@@ -25,14 +25,14 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
</div>\ | |||
</div>').appendTo(this.parent); | |||
} | |||
}, | |||
toggle_label: function(show) { | |||
} | |||
toggle_label(show) { | |||
this.$wrapper.find(".control-label").toggleClass("hide", !show); | |||
}, | |||
toggle_description: function(show) { | |||
} | |||
toggle_description(show) { | |||
this.$wrapper.find(".help-box").toggleClass("hide", !show); | |||
}, | |||
set_input_areas: function() { | |||
} | |||
set_input_areas() { | |||
if(this.only_input) { | |||
this.input_area = this.wrapper; | |||
} else { | |||
@@ -43,17 +43,17 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
// like links, currencies, HTMLs etc. | |||
this.disp_area = this.$wrapper.find(".control-value").get(0); | |||
} | |||
}, | |||
set_max_width: function() { | |||
if(this.horizontal) { | |||
} | |||
set_max_width() { | |||
if(this.constructor.horizontal) { | |||
this.$wrapper.addClass("input-max-width"); | |||
} | |||
}, | |||
} | |||
// update input value, label, description | |||
// display (show/hide/read-only), | |||
// mandatory style on refresh | |||
refresh_input: function() { | |||
refresh_input() { | |||
var me = this; | |||
var make_input = function() { | |||
if (!me.has_input) { | |||
@@ -106,13 +106,13 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
me.set_bold(); | |||
me.set_required(); | |||
} | |||
}, | |||
} | |||
can_write() { | |||
return this.disp_status == "Write"; | |||
}, | |||
} | |||
set_disp_area: function(value) { | |||
set_disp_area(value) { | |||
if(in_list(["Currency", "Int", "Float"], this.df.fieldtype) | |||
&& (this.value === 0 || value === 0)) { | |||
// to set the 0 value in readonly for currency, int, float field | |||
@@ -126,8 +126,8 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
let doc = this.doc || (this.frm && this.frm.doc); | |||
let display_value = frappe.format(value, this.df, { no_icon: true, inline: true }, doc); | |||
this.disp_area && $(this.disp_area).html(display_value); | |||
}, | |||
set_label: function(label) { | |||
} | |||
set_label(label) { | |||
if(label) this.df.label = label; | |||
if(this.only_input || this.df.label==this._label) | |||
@@ -137,8 +137,8 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
this.label_span.innerHTML = (icon ? '<i class="'+icon+'"></i> ' : "") + | |||
__(this.df.label) || " "; | |||
this._label = this.df.label; | |||
}, | |||
set_description: function(description) { | |||
} | |||
set_description(description) { | |||
if (description !== undefined) { | |||
this.df.description = description; | |||
} | |||
@@ -151,17 +151,17 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
this.set_empty_description(); | |||
} | |||
this._description = this.df.description; | |||
}, | |||
set_new_description: function(description) { | |||
} | |||
set_new_description(description) { | |||
this.$wrapper.find(".help-box").html(description); | |||
}, | |||
set_empty_description: function() { | |||
} | |||
set_empty_description() { | |||
this.$wrapper.find(".help-box").html(""); | |||
}, | |||
set_mandatory: function(value) { | |||
} | |||
set_mandatory(value) { | |||
this.$wrapper.toggleClass("has-error", Boolean(this.df.reqd && is_null(value))); | |||
}, | |||
set_invalid: function () { | |||
} | |||
set_invalid () { | |||
let invalid = !!this.df.invalid; | |||
if (this.grid) { | |||
this.$wrapper.parents('.grid-static-col').toggleClass('invalid', invalid); | |||
@@ -170,11 +170,11 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
} else { | |||
this.$wrapper.toggleClass('has-error', invalid); | |||
} | |||
}, | |||
} | |||
set_required() { | |||
this.label_area && $(this.label_area).toggleClass('reqd', Boolean(this.df.reqd)); | |||
}, | |||
set_bold: function() { | |||
} | |||
set_bold() { | |||
if(this.$input) { | |||
this.$input.toggleClass("bold", !!(this.df.bold || this.df.reqd)); | |||
} | |||
@@ -182,4 +182,4 @@ frappe.ui.form.ControlInput = frappe.ui.form.Control.extend({ | |||
$(this.disp_area).toggleClass("bold", !!(this.df.bold || this.df.reqd)); | |||
} | |||
} | |||
}); | |||
}; |
@@ -1,9 +1,9 @@ | |||
frappe.ui.form.ControlButton = frappe.ui.form.ControlData.extend({ | |||
frappe.ui.form.ControlButton = class ControlButton extends frappe.ui.form.ControlData { | |||
can_write() { | |||
// should be always true in case of button | |||
return true; | |||
}, | |||
make_input: function() { | |||
} | |||
make_input() { | |||
var me = this; | |||
const btn_type = this.df.primary ? 'btn-primary': 'btn-default'; | |||
const btn_size = this.df.btn_size | |||
@@ -18,8 +18,8 @@ frappe.ui.form.ControlButton = frappe.ui.form.ControlData.extend({ | |||
this.set_input_attributes(); | |||
this.has_input = true; | |||
this.toggle_label(false); | |||
}, | |||
onclick: function() { | |||
} | |||
onclick() { | |||
if (this.frm && this.frm.doc) { | |||
if (this.frm.script_manager.has_handlers(this.df.fieldname, this.doctype)) { | |||
this.frm.script_manager.trigger(this.df.fieldname, this.doctype, this.docname); | |||
@@ -31,8 +31,8 @@ frappe.ui.form.ControlButton = frappe.ui.form.ControlData.extend({ | |||
} else if (this.df.click) { | |||
this.df.click(); | |||
} | |||
}, | |||
run_server_script: function() { | |||
} | |||
run_server_script() { | |||
// DEPRECATE | |||
var me = this; | |||
if(this.frm && this.frm.docname) { | |||
@@ -47,18 +47,18 @@ frappe.ui.form.ControlButton = frappe.ui.form.ControlData.extend({ | |||
} | |||
}); | |||
} | |||
}, | |||
} | |||
hide() { | |||
this.$input.hide(); | |||
}, | |||
set_input_areas: function() { | |||
this._super(); | |||
} | |||
set_input_areas() { | |||
super.set_input_areas(); | |||
$(this.disp_area).removeClass().addClass("hide"); | |||
}, | |||
set_empty_description: function() { | |||
} | |||
set_empty_description() { | |||
this.$wrapper.find(".help-box").empty().toggle(false); | |||
}, | |||
set_label: function(label) { | |||
} | |||
set_label(label) { | |||
if (label) { | |||
this.df.label = label; | |||
} | |||
@@ -66,4 +66,4 @@ frappe.ui.form.ControlButton = frappe.ui.form.ControlData.extend({ | |||
$(this.label_span).html(" "); | |||
this.$input && this.$input.html(label); | |||
} | |||
}); | |||
}; |
@@ -1,6 +1,7 @@ | |||
frappe.ui.form.ControlCheck = frappe.ui.form.ControlData.extend({ | |||
input_type: "checkbox", | |||
make_wrapper: function() { | |||
frappe.ui.form.ControlCheck = class ControlCheck extends frappe.ui.form.ControlData { | |||
static html_element = "input" | |||
static input_type = "checkbox" | |||
make_wrapper() { | |||
this.$wrapper = $(`<div class="form-group frappe-control"> | |||
<div class="checkbox"> | |||
<label> | |||
@@ -11,23 +12,23 @@ frappe.ui.form.ControlCheck = frappe.ui.form.ControlData.extend({ | |||
<p class="help-box small text-muted"></p> | |||
</div> | |||
</div>`).appendTo(this.parent); | |||
}, | |||
set_input_areas: function() { | |||
} | |||
set_input_areas() { | |||
this.label_area = this.label_span = this.$wrapper.find(".label-area").get(0); | |||
this.input_area = this.$wrapper.find(".input-area").get(0); | |||
this.disp_area = this.$wrapper.find(".disp-area").get(0); | |||
}, | |||
make_input: function() { | |||
this._super(); | |||
} | |||
make_input() { | |||
super.make_input(); | |||
this.$input.removeClass("form-control"); | |||
}, | |||
get_input_value: function() { | |||
} | |||
get_input_value() { | |||
return this.input && this.input.checked ? 1 : 0; | |||
}, | |||
validate: function(value) { | |||
} | |||
validate(value) { | |||
return cint(value); | |||
}, | |||
set_input: function(value) { | |||
} | |||
set_input(value) { | |||
value = cint(value); | |||
if(this.input) { | |||
this.input.checked = (value ? 1 : 0); | |||
@@ -36,4 +37,4 @@ frappe.ui.form.ControlCheck = frappe.ui.form.ControlData.extend({ | |||
this.set_mandatory(value); | |||
this.set_disp_area(value); | |||
} | |||
}); | |||
}; |
@@ -1,8 +1,8 @@ | |||
frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({ | |||
frappe.ui.form.ControlCode = class ControlCode extends frappe.ui.form.ControlText { | |||
make_input() { | |||
if (this.editor) return; | |||
this.load_lib().then(() => this.make_ace_editor()); | |||
}, | |||
} | |||
make_ace_editor() { | |||
if (this.editor) return; | |||
@@ -34,6 +34,7 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({ | |||
// setup autocompletion when it is set the first time | |||
Object.defineProperty(this.df, 'autocompletions', { | |||
configurable: true, | |||
get() { | |||
return this._autocompletions || []; | |||
}, | |||
@@ -42,7 +43,7 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({ | |||
this.df._autocompletions = value; | |||
} | |||
}); | |||
}, | |||
} | |||
setup_autocompletion() { | |||
if (this._autocompletion_setup) return; | |||
@@ -82,20 +83,20 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({ | |||
}); | |||
}); | |||
this._autocompletion_setup = true; | |||
}, | |||
} | |||
refresh_height() { | |||
this.ace_editor_target.css('height', this.expanded ? 600 : 300); | |||
this.editor.resize(); | |||
}, | |||
} | |||
toggle_label() { | |||
this.$expand_button && this.$expand_button.text(this.get_button_label()); | |||
}, | |||
} | |||
get_button_label() { | |||
return this.expanded ? __('Collapse', null, 'Shrink code field.') : __('Expand', null, 'Enlarge code field.'); | |||
}, | |||
} | |||
set_language() { | |||
const language_map = { | |||
@@ -122,14 +123,14 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({ | |||
const ace_language_mode = language_map[language] || ''; | |||
this.editor.session.setMode(ace_language_mode); | |||
this.editor.setKeyboardHandler('ace/keyboard/vscode'); | |||
}, | |||
} | |||
parse(value) { | |||
if (value == null) { | |||
value = ""; | |||
} | |||
return value; | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
return this.load_lib().then(() => { | |||
@@ -138,11 +139,11 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({ | |||
if (value === this.get_input_value()) return; | |||
this.editor.session.setValue(value); | |||
}); | |||
}, | |||
} | |||
get_input_value() { | |||
return this.editor ? this.editor.session.getValue() : ''; | |||
}, | |||
} | |||
load_lib() { | |||
if (this.library_loaded) return this.library_loaded; | |||
@@ -162,4 +163,4 @@ frappe.ui.form.ControlCode = frappe.ui.form.ControlText.extend({ | |||
return this.library_loaded; | |||
} | |||
}); | |||
}; |
@@ -1,12 +1,13 @@ | |||
import Picker from '../../color_picker/color_picker'; | |||
frappe.ui.form.ControlColor = frappe.ui.form.ControlData.extend({ | |||
make_input: function () { | |||
frappe.ui.form.ControlColor = class ControlColor extends frappe.ui.form.ControlData { | |||
make_input() { | |||
this.df.placeholder = this.df.placeholder || __('Choose a color'); | |||
this._super(); | |||
super.make_input(); | |||
this.make_color_input(); | |||
}, | |||
make_color_input: function () { | |||
} | |||
make_color_input() { | |||
let picker_wrapper = $('<div>'); | |||
this.picker = new Picker({ | |||
parent: picker_wrapper[0], | |||
@@ -73,27 +74,31 @@ frappe.ui.form.ControlColor = frappe.ui.form.ControlData.extend({ | |||
this.$wrapper.popover('hide'); | |||
}); | |||
}); | |||
}, | |||
} | |||
refresh() { | |||
this._super(); | |||
super.refresh(); | |||
let color = this.get_color(); | |||
if (this.picker && this.picker.color !== color) { | |||
this.picker.color = color; | |||
this.picker.refresh(); | |||
} | |||
}, | |||
set_formatted_input: function(value) { | |||
this._super(value); | |||
} | |||
set_formatted_input(value) { | |||
super.set_formatted_input(value); | |||
this.$input.val(value); | |||
this.selected_color.css({ | |||
"background-color": value || 'transparent', | |||
}); | |||
this.selected_color.toggleClass('no-value', !value); | |||
}, | |||
} | |||
get_color() { | |||
return this.validate(this.get_value()); | |||
}, | |||
validate: function (value) { | |||
} | |||
validate(value) { | |||
if (value === '') { | |||
return ''; | |||
} | |||
@@ -103,4 +108,4 @@ frappe.ui.form.ControlColor = frappe.ui.form.ControlData.extend({ | |||
} | |||
return null; | |||
} | |||
}); | |||
}; |
@@ -3,7 +3,7 @@ import Mention from './quill-mention/quill.mention'; | |||
Quill.register('modules/mention', Mention, true); | |||
frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({ | |||
frappe.ui.form.ControlComment = class ControlComment extends frappe.ui.form.ControlTextEditor { | |||
make_wrapper() { | |||
this.comment_wrapper = !this.no_wrapper ? $(` | |||
<div class="comment-input-wrapper"> | |||
@@ -32,10 +32,10 @@ frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({ | |||
this.wrapper = this.$wrapper; | |||
this.button = this.comment_wrapper.find('.btn-comment'); | |||
}, | |||
} | |||
bind_events() { | |||
this._super(); | |||
super.bind_events(); | |||
this.button.click(() => { | |||
this.submit(); | |||
@@ -52,11 +52,11 @@ frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({ | |||
this.quill.on('text-change', frappe.utils.debounce(() => { | |||
this.update_state(); | |||
}, 300)); | |||
}, | |||
} | |||
submit() { | |||
this.on_submit && this.on_submit(this.get_value()); | |||
}, | |||
} | |||
update_state() { | |||
const value = this.get_value(); | |||
@@ -65,17 +65,17 @@ frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({ | |||
} else { | |||
this.button.addClass('btn-default').removeClass('btn-primary'); | |||
} | |||
}, | |||
} | |||
get_quill_options() { | |||
const options = this._super(); | |||
const options = super.get_quill_options(); | |||
return Object.assign(options, { | |||
theme: 'bubble', | |||
modules: Object.assign(options.modules, { | |||
mention: this.get_mention_options() | |||
}) | |||
}); | |||
}, | |||
} | |||
get_mention_options() { | |||
if (!this.enable_mentions) { | |||
@@ -98,7 +98,7 @@ frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({ | |||
return `${value} ${item.is_group ? frappe.utils.icon('users') : ''}`; | |||
} | |||
}; | |||
}, | |||
} | |||
get_toolbar_options() { | |||
return [ | |||
@@ -108,19 +108,19 @@ frappe.ui.form.ControlComment = frappe.ui.form.ControlTextEditor.extend({ | |||
[{ 'list': 'ordered' }, { 'list': 'bullet' }], | |||
['clean'] | |||
]; | |||
}, | |||
} | |||
clear() { | |||
this.quill.setText(''); | |||
}, | |||
} | |||
disable() { | |||
this.quill.disable(); | |||
this.button.prop('disabled', true); | |||
}, | |||
} | |||
enable() { | |||
this.quill.enable(); | |||
this.button.prop('disabled', false); | |||
} | |||
}); | |||
}; |
@@ -1,10 +1,10 @@ | |||
frappe.ui.form.ControlCurrency = frappe.ui.form.ControlFloat.extend({ | |||
format_for_input: function(value) { | |||
frappe.ui.form.ControlCurrency = class ControlCurrency extends frappe.ui.form.ControlFloat { | |||
format_for_input(value) { | |||
var formatted_value = format_number(value, this.get_number_format(), this.get_precision()); | |||
return isNaN(Number(value)) ? "" : formatted_value; | |||
}, | |||
} | |||
get_precision: function() { | |||
get_precision() { | |||
// always round based on field precision or currency's precision | |||
// this method is also called in this.parse() | |||
if (!this.df.precision) { | |||
@@ -17,4 +17,4 @@ frappe.ui.form.ControlCurrency = frappe.ui.form.ControlFloat.extend({ | |||
return this.df.precision; | |||
} | |||
}); | |||
}; |
@@ -1,14 +1,16 @@ | |||
frappe.provide('frappe.phone_call'); | |||
frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
html_element: "input", | |||
input_type: "text", | |||
trigger_change_on_input_event: true, | |||
make_input: function() { | |||
frappe.ui.form.ControlData = class ControlData extends frappe.ui.form.ControlInput { | |||
static html_element = "input"; | |||
static input_type = "text"; | |||
static trigger_change_on_input_event = true; | |||
make_input() { | |||
if(this.$input) return; | |||
this.$input = $("<"+ this.html_element +">") | |||
.attr("type", this.input_type) | |||
let { html_element, input_type } = this.constructor; | |||
this.$input = $("<"+ html_element +">") | |||
.attr("type", input_type) | |||
.attr("autocomplete", "off") | |||
.addClass("input-with-feedback form-control") | |||
.prependTo(this.input_area); | |||
@@ -32,7 +34,7 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
let doctype_edit_link = null; | |||
if (this.frm.meta.custom) { | |||
doctype_edit_link = frappe.utils.get_form_link( | |||
'DocType', | |||
'DocType', | |||
this.frm.doctype, true, | |||
__('this form') | |||
); | |||
@@ -65,8 +67,9 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
if (this.df.options == 'URL') { | |||
this.setup_url_field(); | |||
} | |||
}, | |||
setup_url_field: function() { | |||
} | |||
setup_url_field() { | |||
this.$wrapper.find('.control-input').append( | |||
`<span class="link-btn"> | |||
<a class="btn-open no-decoration" title="${__("Open Link")}" target="_blank"> | |||
@@ -74,14 +77,14 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
</a> | |||
</span>` | |||
); | |||
this.$link = this.$wrapper.find('.link-btn'); | |||
this.$link_open = this.$link.find('.btn-open'); | |||
this.$input.on("focus", () => { | |||
setTimeout(() => { | |||
let inputValue = this.get_input_value(); | |||
if (inputValue && validate_url(inputValue)) { | |||
this.$link.toggle(true); | |||
this.$link_open.attr('href', this.get_input_value()); | |||
@@ -100,7 +103,7 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
this.$link.toggle(false); | |||
} | |||
}); | |||
this.$input.on("blur", () => { | |||
// if this disappears immediately, the user's click | |||
// does not register, hence timeout | |||
@@ -108,8 +111,9 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
this.$link.toggle(false); | |||
}, 500); | |||
}); | |||
}, | |||
bind_change_event: function() { | |||
} | |||
bind_change_event() { | |||
const change_handler = e => { | |||
if (this.change) this.change(e); | |||
else { | |||
@@ -118,12 +122,12 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
} | |||
}; | |||
this.$input.on("change", change_handler); | |||
if (this.trigger_change_on_input_event) { | |||
if (this.constructor.trigger_change_on_input_event) { | |||
// debounce to avoid repeated validations on value change | |||
this.$input.on("input", frappe.utils.debounce(change_handler, 500)); | |||
} | |||
}, | |||
setup_autoname_check: function() { | |||
} | |||
setup_autoname_check() { | |||
if (!this.df.parent) return; | |||
this.meta = frappe.get_meta(this.df.parent); | |||
if (this.meta && ((this.meta.autoname | |||
@@ -152,8 +156,8 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
} | |||
}); | |||
} | |||
}, | |||
set_input_attributes: function() { | |||
} | |||
set_input_attributes() { | |||
this.$input | |||
.attr("data-fieldtype", this.df.fieldtype) | |||
.attr("data-fieldname", this.df.fieldname) | |||
@@ -167,24 +171,24 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
if(this.df.input_class) { | |||
this.$input.addClass(this.df.input_class); | |||
} | |||
}, | |||
set_input: function(value) { | |||
} | |||
set_input(value) { | |||
this.last_value = this.value; | |||
this.value = value; | |||
this.set_formatted_input(value); | |||
this.set_disp_area(value); | |||
this.set_mandatory && this.set_mandatory(value); | |||
}, | |||
set_formatted_input: function(value) { | |||
} | |||
set_formatted_input(value) { | |||
this.$input && this.$input.val(this.format_for_input(value)); | |||
}, | |||
get_input_value: function() { | |||
} | |||
get_input_value() { | |||
return this.$input ? this.$input.val() : undefined; | |||
}, | |||
format_for_input: function(val) { | |||
} | |||
format_for_input(val) { | |||
return val==null ? "" : val; | |||
}, | |||
validate: function(v) { | |||
} | |||
validate(v) { | |||
if (!v) { | |||
return ''; | |||
} | |||
@@ -217,9 +221,9 @@ frappe.ui.form.ControlData = frappe.ui.form.ControlInput.extend({ | |||
} else { | |||
return v; | |||
} | |||
}, | |||
toggle_container_scroll: function(el_class, scroll_class, add=false) { | |||
} | |||
toggle_container_scroll(el_class, scroll_class, add=false) { | |||
let el = this.$input.parents(el_class)[0]; | |||
if (el) $(el).toggleClass(scroll_class, add); | |||
} | |||
}); | |||
}; |
@@ -1,16 +1,16 @@ | |||
frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | |||
trigger_change_on_input_event: false, | |||
make_input: function() { | |||
this._super(); | |||
frappe.ui.form.ControlDate = class ControlDate extends frappe.ui.form.ControlData { | |||
static trigger_change_on_input_event = false | |||
make_input() { | |||
super.make_input(); | |||
this.make_picker(); | |||
}, | |||
make_picker: function() { | |||
} | |||
make_picker() { | |||
this.set_date_options(); | |||
this.set_datepicker(); | |||
this.set_t_for_today(); | |||
}, | |||
set_formatted_input: function(value) { | |||
this._super(value); | |||
} | |||
set_formatted_input(value) { | |||
super.set_formatted_input(value); | |||
if (this.timepicker_only) return; | |||
if (!this.datepicker) return; | |||
if (!value) { | |||
@@ -39,8 +39,8 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | |||
if(should_refresh) { | |||
this.datepicker.selectDate(frappe.datetime.str_to_obj(value)); | |||
} | |||
}, | |||
set_date_options: function() { | |||
} | |||
set_date_options() { | |||
// webformTODO: | |||
let sysdefaults = frappe.boot.sysdefaults; | |||
@@ -75,8 +75,8 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | |||
this.update_datepicker_position(); | |||
} | |||
}; | |||
}, | |||
set_datepicker: function() { | |||
} | |||
set_datepicker() { | |||
this.$input.datepicker(this.datepicker_options); | |||
this.datepicker = this.$input.data('datepicker'); | |||
@@ -87,8 +87,8 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | |||
.click(() => { | |||
this.datepicker.selectDate(this.get_now_date()); | |||
}); | |||
}, | |||
update_datepicker_position: function() { | |||
} | |||
update_datepicker_position() { | |||
if(!this.frm) return; | |||
// show datepicker above or below the input | |||
// based on scroll position | |||
@@ -110,11 +110,11 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | |||
} | |||
this.datepicker.update('position', position); | |||
}, | |||
get_now_date: function() { | |||
} | |||
get_now_date() { | |||
return frappe.datetime.now_date(true); | |||
}, | |||
set_t_for_today: function() { | |||
} | |||
set_t_for_today() { | |||
var me = this; | |||
this.$input.on("keydown", function(e) { | |||
if(e.which===84) { // 84 === t | |||
@@ -128,19 +128,19 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | |||
return false; | |||
} | |||
}); | |||
}, | |||
parse: function(value) { | |||
} | |||
parse(value) { | |||
if(value) { | |||
return frappe.datetime.user_to_str(value); | |||
} | |||
}, | |||
format_for_input: function(value) { | |||
} | |||
format_for_input(value) { | |||
if(value) { | |||
return frappe.datetime.str_to_user(value); | |||
} | |||
return ""; | |||
}, | |||
validate: function(value) { | |||
} | |||
validate(value) { | |||
if(value && !frappe.datetime.validate(value)) { | |||
let sysdefaults = frappe.sys_defaults; | |||
let date_format = sysdefaults && sysdefaults.date_format | |||
@@ -150,4 +150,4 @@ frappe.ui.form.ControlDate = frappe.ui.form.ControlData.extend({ | |||
} | |||
return value; | |||
} | |||
}); | |||
}; |
@@ -1,11 +1,11 @@ | |||
frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({ | |||
make_input: function() { | |||
this._super(); | |||
frappe.ui.form.ControlDateRange = class ControlDateRange extends frappe.ui.form.ControlData { | |||
make_input() { | |||
super.make_input(); | |||
this.set_date_options(); | |||
this.set_datepicker(); | |||
this.refresh(); | |||
}, | |||
set_date_options: function() { | |||
} | |||
set_date_options() { | |||
var me = this; | |||
this.datepicker_options = { | |||
language: "en", | |||
@@ -18,12 +18,12 @@ frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({ | |||
this.datepicker_options.onSelect = function() { | |||
me.$input.trigger('change'); | |||
}; | |||
}, | |||
set_datepicker: function() { | |||
} | |||
set_datepicker() { | |||
this.$input.datepicker(this.datepicker_options); | |||
this.datepicker = this.$input.data('datepicker'); | |||
}, | |||
set_input: function(value, value2) { | |||
} | |||
set_input(value, value2) { | |||
this.last_value = this.value; | |||
if (value && value2) { | |||
this.value = [value, value2]; | |||
@@ -38,8 +38,8 @@ frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({ | |||
} | |||
this.set_disp_area(value || ''); | |||
this.set_mandatory && this.set_mandatory(value); | |||
}, | |||
parse: function(value) { | |||
} | |||
parse(value) { | |||
// replace the separator (which can be in user language) with comma | |||
const to = __('{0} to {1}').replace('{0}', '').replace('{1}', ''); | |||
value = value.replace(to, ','); | |||
@@ -50,8 +50,8 @@ frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({ | |||
var to_date = moment(frappe.datetime.user_to_obj(vals[vals.length-1])).format('YYYY-MM-DD'); | |||
return [from_date, to_date]; | |||
} | |||
}, | |||
format_for_input: function(value1, value2) { | |||
} | |||
format_for_input(value1, value2) { | |||
if(value1 && value2) { | |||
value1 = frappe.datetime.str_to_user(value1); | |||
value2 = frappe.datetime.str_to_user(value2); | |||
@@ -59,4 +59,4 @@ frappe.ui.form.ControlDateRange = frappe.ui.form.ControlData.extend({ | |||
} | |||
return ""; | |||
} | |||
}); | |||
}; |
@@ -1,6 +1,6 @@ | |||
frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ | |||
set_date_options: function() { | |||
this._super(); | |||
frappe.ui.form.ControlDatetime = class ControlDatetime extends frappe.ui.form.ControlDate { | |||
set_date_options() { | |||
super.set_date_options(); | |||
this.today_text = __("Now"); | |||
let sysdefaults = frappe.boot.sysdefaults; | |||
this.date_format = frappe.defaultDatetimeFormat; | |||
@@ -10,11 +10,11 @@ frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ | |||
timepicker: true, | |||
timeFormat: time_format.toLowerCase().replace("mm", "ii") | |||
}); | |||
}, | |||
get_now_date: function() { | |||
} | |||
get_now_date() { | |||
return frappe.datetime.now_datetime(true); | |||
}, | |||
set_description: function() { | |||
} | |||
set_description() { | |||
const { description } = this.df; | |||
const { time_zone } = frappe.sys_defaults; | |||
if (!this.df.hide_timezone && !frappe.datetime.is_timezone_same()) { | |||
@@ -24,10 +24,10 @@ frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ | |||
this.df.description += '<br>' + time_zone; | |||
} | |||
} | |||
this._super(); | |||
}, | |||
set_datepicker: function() { | |||
this._super(); | |||
super.set_description(); | |||
} | |||
set_datepicker() { | |||
super.set_datepicker(); | |||
if (this.datepicker.opts.timeFormat.indexOf('s') == -1) { | |||
// No seconds in time format | |||
const $tp = this.datepicker.timepicker; | |||
@@ -36,4 +36,4 @@ frappe.ui.form.ControlDatetime = frappe.ui.form.ControlDate.extend({ | |||
$tp.$secondsText.prev().css('display', 'none'); | |||
} | |||
} | |||
}); | |||
}; |
@@ -1,10 +1,10 @@ | |||
frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({ | |||
make_input: function() { | |||
this._super(); | |||
frappe.ui.form.ControlDuration = class ControlDuration extends frappe.ui.form.ControlData { | |||
make_input() { | |||
super.make_input(); | |||
this.make_picker(); | |||
}, | |||
} | |||
make_picker: function() { | |||
make_picker() { | |||
this.inputs = []; | |||
this.set_duration_options(); | |||
this.$picker = $( | |||
@@ -21,9 +21,9 @@ frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({ | |||
this.$picker.hide(); | |||
this.bind_events(); | |||
this.refresh(); | |||
}, | |||
} | |||
build_numeric_input: function(label, hidden, max) { | |||
build_numeric_input(label, hidden, max) { | |||
let $duration_input = $(` | |||
<input class="input-sm duration-input" data-duration="${label}" type="number" min="0" value="0"> | |||
`); | |||
@@ -47,13 +47,13 @@ frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({ | |||
} | |||
$control.prepend($input); | |||
$control.appendTo(this.$picker.find(".picker-row")); | |||
}, | |||
} | |||
set_duration_options() { | |||
this.duration_options = frappe.utils.get_duration_options(this.df); | |||
}, | |||
} | |||
set_duration_picker_value: function(value) { | |||
set_duration_picker_value(value) { | |||
let total_duration = frappe.utils.seconds_to_duration(value, this.duration_options); | |||
if (this.$picker) { | |||
@@ -61,9 +61,9 @@ frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({ | |||
this.inputs[duration].prop("value", total_duration[duration]); | |||
}); | |||
} | |||
}, | |||
} | |||
bind_events: function() { | |||
bind_events() { | |||
// flag to handle the display property of the picker | |||
let clicked = false; | |||
@@ -103,21 +103,21 @@ frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({ | |||
this.$picker.hide(); | |||
} | |||
}); | |||
}, | |||
} | |||
get_value() { | |||
return cint(this.value); | |||
}, | |||
} | |||
refresh_input: function() { | |||
this._super(); | |||
refresh_input() { | |||
super.refresh_input(); | |||
this.set_duration_options(); | |||
this.set_duration_picker_value(this.value); | |||
}, | |||
} | |||
format_for_input: function(value) { | |||
format_for_input(value) { | |||
return frappe.utils.get_formatted_duration(value, this.duration_options); | |||
}, | |||
} | |||
get_duration() { | |||
// returns an object of days, hours, minutes and seconds from the inputs array | |||
@@ -138,7 +138,7 @@ frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({ | |||
} | |||
} | |||
return total_duration; | |||
}, | |||
} | |||
is_duration_picker_set(inputs) { | |||
let is_set = false; | |||
@@ -149,4 +149,4 @@ frappe.ui.form.ControlDuration = frappe.ui.form.ControlData.extend({ | |||
}); | |||
return is_set; | |||
} | |||
}); | |||
}; |
@@ -1,5 +1,5 @@ | |||
frappe.ui.form.ControlDynamicLink = frappe.ui.form.ControlLink.extend({ | |||
get_options: function() { | |||
frappe.ui.form.ControlDynamicLink = class ControlDynamicLink extends frappe.ui.form.ControlLink { | |||
get_options() { | |||
let options = ''; | |||
if (this.df.get_options) { | |||
options = this.df.get_options(); | |||
@@ -28,5 +28,5 @@ frappe.ui.form.ControlDynamicLink = frappe.ui.form.ControlLink.extend({ | |||
} | |||
return options; | |||
}, | |||
}); | |||
} | |||
}; |
@@ -1,27 +1,27 @@ | |||
frappe.ui.form.ControlFloat = frappe.ui.form.ControlInt.extend({ | |||
parse: function(value) { | |||
frappe.ui.form.ControlFloat = class ControlFloat extends frappe.ui.form.ControlInt { | |||
parse(value) { | |||
value = this.eval_expression(value); | |||
return isNaN(parseFloat(value)) ? null : flt(value, this.get_precision()); | |||
}, | |||
} | |||
format_for_input: function(value) { | |||
format_for_input(value) { | |||
var number_format; | |||
if (this.df.fieldtype==="Float" && this.df.options && this.df.options.trim()) { | |||
number_format = this.get_number_format(); | |||
} | |||
var formatted_value = format_number(value, number_format, this.get_precision()); | |||
return isNaN(Number(value)) ? "" : formatted_value; | |||
}, | |||
} | |||
get_number_format: function() { | |||
get_number_format() { | |||
var currency = frappe.meta.get_field_currency(this.df, this.get_doc()); | |||
return get_number_format(currency); | |||
}, | |||
} | |||
get_precision: function() { | |||
get_precision() { | |||
// round based on field precision or float precision, else don't round | |||
return this.df.precision || cint(frappe.boot.sysdefaults.float_precision, null); | |||
} | |||
}); | |||
}; | |||
frappe.ui.form.ControlPercent = frappe.ui.form.ControlFloat; |
@@ -1,11 +1,11 @@ | |||
frappe.provide('frappe.utils.utils'); | |||
frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({ | |||
horizontal: false, | |||
frappe.ui.form.ControlGeolocation = class ControlGeolocation extends frappe.ui.form.ControlData { | |||
static horizontal = false | |||
make_wrapper() { | |||
// Create the elements for map area | |||
this._super(); | |||
super.make_wrapper(); | |||
let $input_wrapper = this.$wrapper.find('.control-input-wrapper'); | |||
this.map_id = frappe.dom.get_unique_id(); | |||
@@ -24,14 +24,14 @@ frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({ | |||
this.make_map(); | |||
}); | |||
} | |||
}, | |||
} | |||
make_map() { | |||
this.bind_leaflet_map(); | |||
this.bind_leaflet_draw_control(); | |||
this.bind_leaflet_locate_control(); | |||
this.bind_leaflet_refresh_button(); | |||
}, | |||
} | |||
format_for_input(value) { | |||
if (!this.map) return; | |||
@@ -65,7 +65,7 @@ frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({ | |||
} else if ((value===undefined) || (value == JSON.stringify(new L.FeatureGroup().toGeoJSON()))) { | |||
this.locate_control.start(); | |||
} | |||
}, | |||
} | |||
bind_leaflet_map() { | |||
var circleToGeoJSON = L.Circle.prototype.toGeoJSON; | |||
@@ -97,13 +97,13 @@ frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({ | |||
L.tileLayer(frappe.utils.map_defaults.tiles, | |||
frappe.utils.map_defaults.options).addTo(this.map); | |||
}, | |||
} | |||
bind_leaflet_locate_control() { | |||
// To request location update and set location, sets current geolocation on load | |||
this.locate_control = L.control.locate({position:'topright'}); | |||
this.locate_control.addTo(this.map); | |||
}, | |||
} | |||
bind_leaflet_draw_control() { | |||
this.editableLayers = new L.FeatureGroup(); | |||
@@ -160,7 +160,7 @@ frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({ | |||
this.editableLayers.removeLayer(layer); | |||
this.set_value(JSON.stringify(this.editableLayers.toGeoJSON())); | |||
}); | |||
}, | |||
} | |||
bind_leaflet_refresh_button() { | |||
L.easyButton({ | |||
@@ -177,7 +177,7 @@ frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({ | |||
icon: 'fa fa-refresh' | |||
}] | |||
}).addTo(this.map); | |||
}, | |||
} | |||
add_non_group_layers(source_layer, target_group) { | |||
// https://gis.stackexchange.com/a/203773 | |||
@@ -189,11 +189,11 @@ frappe.ui.form.ControlGeolocation = frappe.ui.form.ControlData.extend({ | |||
} else { | |||
target_group.addLayer(source_layer); | |||
} | |||
}, | |||
} | |||
clear_editable_layers() { | |||
this.editableLayers.eachLayer((l)=>{ | |||
this.editableLayers.removeLayer(l); | |||
}); | |||
} | |||
}); | |||
}; |
@@ -1,5 +1,5 @@ | |||
frappe.ui.form.ControlHeading = frappe.ui.form.ControlHTML.extend({ | |||
get_content: function() { | |||
frappe.ui.form.ControlHeading = class ControlHeading extends frappe.ui.form.ControlHTML { | |||
get_content() { | |||
return "<h4>" + __(this.df.label) + "</h4>"; | |||
} | |||
}); | |||
}; |
@@ -1,13 +1,13 @@ | |||
frappe.ui.form.ControlHTML = frappe.ui.form.Control.extend({ | |||
make: function() { | |||
this._super(); | |||
frappe.ui.form.ControlHTML = class ControlHTML extends frappe.ui.form.Control { | |||
make() { | |||
super.make(); | |||
this.disp_area = this.wrapper; | |||
}, | |||
refresh_input: function() { | |||
} | |||
refresh_input() { | |||
var content = this.get_content(); | |||
if(content) this.$wrapper.html(content); | |||
}, | |||
get_content: function() { | |||
} | |||
get_content() { | |||
var content = this.df.options || ""; | |||
content = __(content); | |||
try { | |||
@@ -15,11 +15,11 @@ frappe.ui.form.ControlHTML = frappe.ui.form.Control.extend({ | |||
} catch (e) { | |||
return content; | |||
} | |||
}, | |||
html: function(html) { | |||
} | |||
html(html) { | |||
this.$wrapper.html(html || this.get_content()); | |||
}, | |||
set_value: function(html) { | |||
} | |||
set_value(html) { | |||
if(html.appendTo) { | |||
// jquery object | |||
html.appendTo(this.$wrapper.empty()); | |||
@@ -29,4 +29,4 @@ frappe.ui.form.ControlHTML = frappe.ui.form.Control.extend({ | |||
this.html(html); | |||
} | |||
} | |||
}); | |||
}; |
@@ -1,13 +1,13 @@ | |||
frappe.ui.form.ControlHTMLEditor = frappe.ui.form.ControlMarkdownEditor.extend({ | |||
editor_class: 'html', | |||
frappe.ui.form.ControlHTMLEditor = class ControlHTMLEditor extends frappe.ui.form.ControlMarkdownEditor { | |||
static editor_class = 'html'; | |||
set_language() { | |||
this.df.options = 'HTML'; | |||
this._super(); | |||
}, | |||
super.set_language(); | |||
} | |||
update_preview() { | |||
if (!this.markdown_preview) return; | |||
let value = this.get_value() || ''; | |||
value = frappe.dom.remove_script_and_style(value); | |||
this.markdown_preview.html(value); | |||
} | |||
}); | |||
}; |
@@ -1,12 +1,12 @@ | |||
frappe.ui.form.ControlImage = frappe.ui.form.Control.extend({ | |||
make: function() { | |||
this._super(); | |||
frappe.ui.form.ControlImage = class ControlImage extends frappe.ui.form.Control { | |||
make() { | |||
super.make(); | |||
this.$wrapper.css({"margin": "0px"}); | |||
this.$body = $("<div></div>").appendTo(this.$wrapper) | |||
.css({"margin-bottom": "10px"}); | |||
$('<div class="clearfix"></div>').appendTo(this.$wrapper); | |||
}, | |||
refresh_input: function() { | |||
} | |||
refresh_input() { | |||
this.$body.empty(); | |||
var doc = this.get_doc(); | |||
@@ -19,4 +19,4 @@ frappe.ui.form.ControlImage = frappe.ui.form.Control.extend({ | |||
} | |||
return false; | |||
} | |||
}); | |||
}; |
@@ -1,13 +1,13 @@ | |||
frappe.ui.form.ControlInt = frappe.ui.form.ControlData.extend({ | |||
trigger_change_on_input_event: false, | |||
make: function () { | |||
this._super(); | |||
frappe.ui.form.ControlInt = class ControlInt extends frappe.ui.form.ControlData { | |||
static trigger_change_on_input_event = false | |||
make () { | |||
super.make(); | |||
// $(this.label_area).addClass('pull-right'); | |||
// $(this.disp_area).addClass('text-right'); | |||
}, | |||
make_input: function () { | |||
} | |||
make_input () { | |||
var me = this; | |||
this._super(); | |||
super.make_input(); | |||
this.$input | |||
// .addClass("text-right") | |||
.on("focus", function () { | |||
@@ -19,11 +19,11 @@ frappe.ui.form.ControlInt = frappe.ui.form.ControlData.extend({ | |||
}, 100); | |||
return false; | |||
}); | |||
}, | |||
validate: function (value) { | |||
} | |||
validate (value) { | |||
return this.parse(value); | |||
}, | |||
eval_expression: function (value) { | |||
} | |||
eval_expression (value) { | |||
if (typeof value === 'string') { | |||
if (value.match(/^[0-9+\-/* ]+$/)) { | |||
// If it is a string containing operators | |||
@@ -36,8 +36,8 @@ frappe.ui.form.ControlInt = frappe.ui.form.ControlData.extend({ | |||
} | |||
} | |||
return value; | |||
}, | |||
parse: function (value) { | |||
} | |||
parse (value) { | |||
return cint(this.eval_expression(value), null); | |||
} | |||
}); | |||
}; |
@@ -8,9 +8,9 @@ import Awesomplete from 'awesomplete'; | |||
frappe.ui.form.recent_link_validations = {}; | |||
frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
trigger_change_on_input_event: false, | |||
make_input: function() { | |||
frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlData { | |||
static trigger_change_on_input_event = false | |||
make_input() { | |||
var me = this; | |||
$(`<div class="link-field ui-front" style="position: relative;"> | |||
<input type="text" class="input-with-feedback form-control"> | |||
@@ -53,23 +53,23 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
this.setup_buttons(); | |||
this.setup_awesomeplete(); | |||
this.bind_change_event(); | |||
}, | |||
get_options: function() { | |||
} | |||
get_options() { | |||
return this.df.options; | |||
}, | |||
} | |||
get_reference_doctype() { | |||
// this is used to get the context in which link field is loaded | |||
if (this.doctype) return this.doctype; | |||
else { | |||
return frappe.get_route && frappe.get_route()[0] === 'List' ? frappe.get_route()[1] : null; | |||
} | |||
}, | |||
setup_buttons: function() { | |||
} | |||
setup_buttons() { | |||
if(this.only_input && !this.with_link_btn) { | |||
this.$input_area.find(".link-btn").remove(); | |||
} | |||
}, | |||
open_advanced_search: function() { | |||
} | |||
open_advanced_search() { | |||
var doctype = this.get_options(); | |||
if(!doctype) return; | |||
new frappe.ui.form.LinkSelector({ | |||
@@ -78,8 +78,8 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
txt: this.get_input_value() | |||
}); | |||
return false; | |||
}, | |||
new_doc: function() { | |||
} | |||
new_doc() { | |||
var doctype = this.get_options(); | |||
var me = this; | |||
@@ -109,8 +109,8 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
}); | |||
return false; | |||
}, | |||
setup_awesomeplete: function() { | |||
} | |||
setup_awesomeplete() { | |||
var me = this; | |||
this.$input.cache = {}; | |||
@@ -284,7 +284,7 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
me.$input.val(""); | |||
} | |||
}); | |||
}, | |||
} | |||
merge_duplicates(results) { | |||
// in case of result like this | |||
@@ -301,7 +301,7 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
return [...newArr, currElem]; | |||
}, []); | |||
// returns [{value: 'Manufacturer 1', 'description': 'mobile part 1, mobile part 2'}] | |||
}, | |||
} | |||
toggle_href(doctype) { | |||
if (frappe.model.can_select(doctype) && !frappe.model.can_read(doctype)) { | |||
@@ -310,7 +310,7 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
} else { | |||
this.$input_area.find(".link-btn").removeClass('hide'); | |||
} | |||
}, | |||
} | |||
get_filter_description(filters) { | |||
let doctype = this.get_options(); | |||
@@ -369,9 +369,9 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
.join(', '); | |||
return __('Filters applied for {0}', [filter_string]); | |||
}, | |||
} | |||
set_custom_query: function(args) { | |||
set_custom_query(args) { | |||
var set_nulls = function(obj) { | |||
$.each(obj, function(key, value) { | |||
if(value!==undefined) { | |||
@@ -439,8 +439,8 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
if(!args.filters) args.filters = {}; | |||
$.extend(args.filters, this.df.filters); | |||
} | |||
}, | |||
validate: function(value) { | |||
} | |||
validate(value) { | |||
// validate the value just entered | |||
if(this.df.options=="[Select]" || this.df.ignore_link_validation) { | |||
return value; | |||
@@ -448,8 +448,8 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
return this.validate_link_and_fetch(this.df, this.get_options(), | |||
this.docname, value); | |||
}, | |||
validate_link_and_fetch: function(df, doctype, docname, value) { | |||
} | |||
validate_link_and_fetch(df, doctype, docname, value) { | |||
if(value) { | |||
return new Promise((resolve) => { | |||
var fetch = ''; | |||
@@ -464,7 +464,7 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
this.fetch_and_validate_link(resolve, df, doctype, docname, value, fetch); | |||
}); | |||
} | |||
}, | |||
} | |||
fetch_and_validate_link(resolve, df, doctype, docname, value, fetch) { | |||
frappe.call({ | |||
@@ -487,15 +487,15 @@ frappe.ui.form.ControlLink = frappe.ui.form.ControlData.extend({ | |||
} | |||
} | |||
}); | |||
}, | |||
} | |||
set_fetch_values: function(df, docname, fetch_values) { | |||
set_fetch_values(df, docname, fetch_values) { | |||
var fl = this.frm.fetch_dict[df.fieldname].fields; | |||
for(var i=0; i < fl.length; i++) { | |||
frappe.model.set_value(df.parent, docname, fl[i], fetch_values[i], df.fieldtype); | |||
} | |||
}, | |||
}); | |||
} | |||
}; | |||
if (Awesomplete) { | |||
Awesomplete.prototype.get_item = function(value) { | |||
@@ -1,10 +1,10 @@ | |||
frappe.ui.form.ControlMarkdownEditor = frappe.ui.form.ControlCode.extend({ | |||
editor_class: 'markdown', | |||
frappe.ui.form.ControlMarkdownEditor = class ControlMarkdownEditor extends frappe.ui.form.ControlCode { | |||
static editor_class = 'markdown' | |||
make_ace_editor() { | |||
this._super(); | |||
super.make_ace_editor(); | |||
this.ace_editor_target.wrap(`<div class="${this.editor_class}-container">`); | |||
this.markdown_container = this.$input_wrapper.find(`.${this.editor_class}-container`); | |||
this.markdown_container = this.$input_wrapper.find(`.${this.constructor.editor_class}-container`); | |||
this.editor.getSession().setUseWrapMode(true); | |||
@@ -27,26 +27,26 @@ frappe.ui.form.ControlMarkdownEditor = frappe.ui.form.ControlCode.extend({ | |||
this.markdown_preview = $(`<div class="${this.editor_class}-preview border rounded">`).hide(); | |||
this.markdown_container.append(this.markdown_preview); | |||
}, | |||
} | |||
set_language() { | |||
this.df.options = 'Markdown'; | |||
this._super(); | |||
}, | |||
super.set_language(); | |||
} | |||
update_preview() { | |||
const value = this.get_value() || ""; | |||
this.markdown_preview.html(frappe.markdown(value)); | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
this._super(value) | |||
super.set_formatted_input(value) | |||
.then(() => { | |||
this.update_preview(); | |||
}); | |||
}, | |||
} | |||
set_disp_area(value) { | |||
this.disp_area && $(this.disp_area).text(value); | |||
} | |||
}); | |||
}; |
@@ -1,10 +1,10 @@ | |||
frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
frappe.ui.form.ControlMultiCheck = class ControlMultiCheck extends frappe.ui.form.Control { | |||
// UI: multiple checkboxes | |||
// Value: Array of values | |||
// Options: Array of label/value/checked option objects | |||
make() { | |||
this._super(); | |||
super.make(); | |||
if (this.df.label) { | |||
this.$label = $(`<label class="control-label">${this.df.label}</label>`).appendTo(this.wrapper); | |||
} | |||
@@ -15,18 +15,18 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
const row = this.get_column_size() === 12 ? '' : 'row'; | |||
this.$checkbox_area = $(`<div class="checkbox-options ${row}"></div>`).appendTo(this.wrapper); | |||
this.refresh(); | |||
}, | |||
} | |||
refresh() { | |||
this.set_options(); | |||
this.bind_checkboxes(); | |||
this.refresh_input(); | |||
this._super(); | |||
}, | |||
super.refresh(); | |||
} | |||
refresh_input() { | |||
this.select_options(this.selected_options); | |||
}, | |||
} | |||
set_options() { | |||
@@ -47,7 +47,7 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
} else { | |||
this.make_checkboxes(); | |||
} | |||
}, | |||
} | |||
parse_df_options() { | |||
if(Array.isArray(this.df.options)) { | |||
@@ -62,7 +62,7 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
} else { | |||
this.options = []; | |||
} | |||
}, | |||
} | |||
make_checkboxes() { | |||
this.$load_state.hide(); | |||
@@ -78,7 +78,7 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
this.setup_select_all(); | |||
} | |||
this.set_checked_options(); | |||
}, | |||
} | |||
bind_checkboxes() { | |||
$(this.wrapper).on('change', ':checkbox', e => { | |||
@@ -95,14 +95,14 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
} | |||
this.df.on_change && this.df.on_change(); | |||
}); | |||
}, | |||
} | |||
set_checked_options() { | |||
this.selected_options = this.options | |||
.filter(o => o.checked) | |||
.map(o => o.value); | |||
this.select_options(this.selected_options); | |||
}, | |||
} | |||
setup_select_all() { | |||
this.$select_buttons.show(); | |||
@@ -112,31 +112,31 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
this.$select_buttons.find('.deselect-all').on('click', () => { | |||
this.select_all(true); | |||
}); | |||
}, | |||
} | |||
select_all(deselect=false) { | |||
$(this.wrapper).find(`:checkbox`).prop("checked", deselect).trigger('click'); | |||
}, | |||
} | |||
select_options(selected_options) { | |||
this.options.map(option => option.value).forEach(value => { | |||
let $checkbox = $(this.wrapper).find(`:checkbox[data-unit="${value}"]`)[0]; | |||
if($checkbox) $checkbox.checked = selected_options.includes(value); | |||
}); | |||
}, | |||
} | |||
get_value() { | |||
return this.selected_options; | |||
}, | |||
} | |||
get_checked_options() { | |||
return this.get_value(); | |||
}, | |||
} | |||
get_unchecked_options() { | |||
return this.options.map(o => o.value) | |||
.filter(value => !this.selected_options.includes(value)); | |||
}, | |||
} | |||
get_checkbox_element(option) { | |||
const column_size = this.get_column_size(); | |||
@@ -148,7 +148,7 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
</label> | |||
</div> | |||
`); | |||
}, | |||
} | |||
get_select_buttons() { | |||
return $(` | |||
@@ -161,9 +161,9 @@ frappe.ui.form.ControlMultiCheck = frappe.ui.form.Control.extend({ | |||
</button> | |||
</div> | |||
`); | |||
}, | |||
} | |||
get_column_size() { | |||
return 12 / (+this.df.columns || 1); | |||
} | |||
}); | |||
}; |
@@ -1,8 +1,8 @@ | |||
import Awesomplete from 'awesomplete'; | |||
frappe.ui.form.ControlMultiSelect = frappe.ui.form.ControlAutocomplete.extend({ | |||
frappe.ui.form.ControlMultiSelect = class ControlMultiSelect extends frappe.ui.form.ControlAutocomplete { | |||
get_awesomplete_settings() { | |||
const settings = this._super(); | |||
const settings = super.get_awesomplete_settings(); | |||
return Object.assign(settings, { | |||
filter: function(text, input) { | |||
@@ -30,10 +30,10 @@ frappe.ui.form.ControlMultiSelect = frappe.ui.form.ControlAutocomplete.extend({ | |||
this.input.value = before + text + ", "; | |||
} | |||
}); | |||
}, | |||
} | |||
get_value() { | |||
let data = this._super(); | |||
let data = super.get_value(); | |||
// find value of label from option list and return actual value string | |||
if (this.df.options && this.df.options.length && this.df.options[0].label) { | |||
data = data.split(',').map(op => op.trim()); | |||
@@ -43,7 +43,7 @@ frappe.ui.form.ControlMultiSelect = frappe.ui.form.ControlAutocomplete.extend({ | |||
}).filter(n => n != null).join(', '); | |||
} | |||
return data; | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
if (!value) return; | |||
@@ -54,15 +54,15 @@ frappe.ui.form.ControlMultiSelect = frappe.ui.form.ControlAutocomplete.extend({ | |||
return option ? option.label : val; | |||
}).filter(n => n != null).join(', '); | |||
} | |||
this._super(value); | |||
}, | |||
super.set_formatted_input(value); | |||
} | |||
get_values() { | |||
const value = this.get_value() || ''; | |||
const values = value.split(/\s*,\s*/).filter(d => d); | |||
return values; | |||
}, | |||
} | |||
get_data() { | |||
let data; | |||
@@ -70,7 +70,7 @@ frappe.ui.form.ControlMultiSelect = frappe.ui.form.ControlAutocomplete.extend({ | |||
data = this.df.get_data(); | |||
if (data) this.set_data(data); | |||
} else { | |||
data = this._super(); | |||
data = super.get_data(); | |||
} | |||
const values = this.get_values() || []; | |||
@@ -78,4 +78,4 @@ frappe.ui.form.ControlMultiSelect = frappe.ui.form.ControlAutocomplete.extend({ | |||
if(data) data.filter(d => !values.includes(d)); | |||
return data; | |||
} | |||
}); | |||
}; |
@@ -1,5 +1,5 @@ | |||
frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
trigger_change_on_input_event: false, | |||
frappe.ui.form.ControlMultiSelectList = class ControlMultiSelectList extends frappe.ui.form.ControlData { | |||
static trigger_change_on_input_event = false | |||
make_input() { | |||
let template = ` | |||
<div class="multiselect-list dropdown"> | |||
@@ -84,7 +84,7 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
this._options = []; | |||
this._selected_values = []; | |||
this.highlighted = -1; | |||
}, | |||
} | |||
set_input_attributes() { | |||
this.$list_wrapper | |||
@@ -102,7 +102,7 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
if(this.df.input_class) { | |||
this.$list_wrapper.addClass(this.df.input_class); | |||
} | |||
}, | |||
} | |||
toggle_select_item($selectable_item) { | |||
$selectable_item.toggleClass('selected'); | |||
@@ -116,7 +116,7 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
this.update_selected_values(value); | |||
this.parse_validate_and_set_in_model(''); | |||
this.update_status(); | |||
}, | |||
} | |||
set_value(value) { | |||
if (!value) return Promise.resolve(); | |||
@@ -130,7 +130,7 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
this.parse_validate_and_set_in_model(''); | |||
this.update_status(); | |||
return Promise.resolve(); | |||
}, | |||
} | |||
update_selected_values(value) { | |||
this._selected_values = this._selected_values || []; | |||
@@ -142,7 +142,7 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
this._selected_values = this._selected_values.filter(opt => opt.value !== value); | |||
} | |||
} | |||
}, | |||
} | |||
update_status() { | |||
let text; | |||
@@ -156,15 +156,15 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
text = __('{0} values selected', [this.values.length]); | |||
} | |||
this.set_status(text); | |||
}, | |||
} | |||
get_placeholder_text() { | |||
return `<span class="text-extra-muted">${this.df.placeholder || ''}</span>`; | |||
}, | |||
} | |||
set_status(text) { | |||
this.$list_wrapper.find('.status-text').html(text); | |||
}, | |||
} | |||
set_options() { | |||
let promise = Promise.resolve(); | |||
@@ -200,7 +200,7 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
this._options = process_options(this.df.options); | |||
} | |||
return promise; | |||
}, | |||
} | |||
set_selectable_items(options) { | |||
let html = options.map(option => { | |||
@@ -222,11 +222,11 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
.html(html); | |||
this.highlighted = -1; | |||
}, | |||
} | |||
get_value() { | |||
return this.values; | |||
}, | |||
} | |||
highlight_item(value) { | |||
this.highlighted += value; | |||
@@ -246,7 +246,7 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
} | |||
this._$last_highlighted = $($item).addClass('highlighted'); | |||
this.scroll_dropdown_if_needed($item); | |||
}, | |||
} | |||
scroll_dropdown_if_needed($item) { | |||
if ($item.scrollIntoView) { | |||
@@ -255,4 +255,4 @@ frappe.ui.form.ControlMultiSelectList = frappe.ui.form.ControlData.extend({ | |||
$item.parentNode.scrollTop = $item.offsetTop - $item.parentNode.offsetTop; | |||
} | |||
} | |||
}); | |||
}; |
@@ -1,8 +1,8 @@ | |||
import Awesomplete from 'awesomplete'; | |||
frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.extend({ | |||
frappe.ui.form.ControlMultiSelectPills = class ControlMultiSelectPills extends frappe.ui.form.ControlAutocomplete { | |||
make_input() { | |||
this._super(); | |||
super.make_input(); | |||
this.$input_area = $(this.input_area); | |||
this.$multiselect_wrapper = $('<div>') | |||
.addClass('form-control table-multiselect') | |||
@@ -35,7 +35,7 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
this.parse_validate_and_set_in_model(''); | |||
} | |||
}); | |||
}, | |||
} | |||
parse(value) { | |||
if (value) { | |||
@@ -43,7 +43,7 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
} | |||
return this.rows; | |||
}, | |||
} | |||
validate(value) { | |||
const rows = (value || []).slice(); | |||
@@ -66,12 +66,12 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
} | |||
return rows; | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
this.rows = value || []; | |||
this.set_pill_html(this.rows); | |||
}, | |||
} | |||
set_pill_html(values) { | |||
const html = values | |||
@@ -80,7 +80,7 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
this.$multiselect_wrapper.find('.tb-selected-value').remove(); | |||
this.$multiselect_wrapper.prepend(html); | |||
}, | |||
} | |||
get_pill_html(value) { | |||
const encoded_value = encodeURIComponent(value); | |||
@@ -90,10 +90,10 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
<span class="btn-remove">${frappe.utils.icon('close')}</span> | |||
</button> | |||
`; | |||
}, | |||
} | |||
get_awesomplete_settings() { | |||
const settings = this._super(); | |||
const settings = super.get_awesomplete_settings(); | |||
return Object.assign(settings, { | |||
filter: function(text, input) { | |||
@@ -116,15 +116,15 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
return v; | |||
} | |||
}); | |||
}, | |||
} | |||
get_value() { | |||
return this.rows; | |||
}, | |||
} | |||
get_values() { | |||
return this.rows; | |||
}, | |||
} | |||
get_data() { | |||
let data; | |||
@@ -140,7 +140,7 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
this.set_data(data); | |||
} | |||
} else { | |||
data = this._super(); | |||
data = super.get_data(); | |||
} | |||
const values = this.get_values() || []; | |||
@@ -148,4 +148,4 @@ frappe.ui.form.ControlMultiSelectPills = frappe.ui.form.ControlAutocomplete.exte | |||
if (data) data.filter(d => !values.includes(d)); | |||
return data; | |||
} | |||
}); | |||
}; |
@@ -1,11 +1,11 @@ | |||
frappe.ui.form.ControlPassword = frappe.ui.form.ControlData.extend({ | |||
input_type: "password", | |||
make: function() { | |||
this._super(); | |||
}, | |||
make_input: function() { | |||
frappe.ui.form.ControlPassword = class ControlPassword extends frappe.ui.form.ControlData { | |||
static input_type = "password" | |||
make() { | |||
super.make(); | |||
} | |||
make_input() { | |||
var me = this; | |||
this._super(); | |||
super.make_input(); | |||
this.$input.parent().append($('<span class="password-strength-indicator indicator"></span>')); | |||
this.$wrapper.find('.control-input-wrapper').append($('<p class="password-strength-message text-muted small hidden"></p>')); | |||
@@ -18,8 +18,8 @@ frappe.ui.form.ControlPassword = frappe.ui.form.ControlData.extend({ | |||
me.get_password_strength(me.$input.val()); | |||
}, 500); | |||
}); | |||
}, | |||
get_password_strength: function(value) { | |||
} | |||
get_password_strength(value) { | |||
var me = this; | |||
frappe.call({ | |||
type: 'POST', | |||
@@ -41,10 +41,10 @@ frappe.ui.form.ControlPassword = frappe.ui.form.ControlData.extend({ | |||
} | |||
}); | |||
}, | |||
set_strength_indicator: function(color) { | |||
} | |||
set_strength_indicator(color) { | |||
var message = __("Include symbols, numbers and capital letters in the password"); | |||
this.indicator.removeClass().addClass('password-strength-indicator indicator ' + color); | |||
this.message.html(message).removeClass('hidden'); | |||
} | |||
}); | |||
}; |
@@ -1,6 +1,6 @@ | |||
frappe.ui.form.ControlRating = frappe.ui.form.ControlInt.extend({ | |||
frappe.ui.form.ControlRating = class ControlRating extends frappe.ui.form.ControlInt { | |||
make_input() { | |||
this._super(); | |||
super.make_input(); | |||
let stars = ''; | |||
[1, 2, 3, 4, 5].forEach(i => { | |||
stars += `<svg class="icon icon-md" data-rating=${i}> | |||
@@ -47,10 +47,10 @@ frappe.ui.form.ControlRating = frappe.ui.form.ControlInt.extend({ | |||
this.set_input(star_value); | |||
} | |||
}); | |||
}, | |||
} | |||
get_value() { | |||
return cint(this.value, null); | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
let el = $(this.input_area).find('svg'); | |||
el.children('svg').prevObject.each( function(e) { | |||
@@ -61,4 +61,4 @@ frappe.ui.form.ControlRating = frappe.ui.form.ControlInt.extend({ | |||
} | |||
}); | |||
} | |||
}); | |||
}; |
@@ -1,8 +1,8 @@ | |||
frappe.ui.form.ControlReadOnly = frappe.ui.form.ControlData.extend({ | |||
get_status: function(explain) { | |||
var status = this._super(explain); | |||
frappe.ui.form.ControlReadOnly = class ControlReadOnly extends frappe.ui.form.ControlData { | |||
get_status(explain) { | |||
var status = super.get_status(explain); | |||
if(status==="Write") | |||
status = "Read"; | |||
return; | |||
}, | |||
}); | |||
} | |||
}; |
@@ -1,7 +1,7 @@ | |||
frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({ | |||
html_element: 'select', | |||
make_input: function() { | |||
this._super(); | |||
frappe.ui.form.ControlSelect = class ControlSelect extends frappe.ui.form.ControlData { | |||
static html_element = 'select'; | |||
make_input() { | |||
super.make_input(); | |||
const is_xs_input = this.df.input_class | |||
&& this.df.input_class.includes('input-xs'); | |||
@@ -10,8 +10,8 @@ frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({ | |||
this.$input.addClass('ellipsis'); | |||
this.set_options(); | |||
}, | |||
set_icon: function(is_xs_input) { | |||
} | |||
set_icon(is_xs_input) { | |||
const select_icon_html = | |||
`<div class="select-icon ${is_xs_input ? 'xs' : ''}"> | |||
${frappe.utils.icon('select', is_xs_input ? 'xs' : 'sm')} | |||
@@ -23,8 +23,8 @@ frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({ | |||
.addClass('flex align-center') | |||
.append(select_icon_html); | |||
} | |||
}, | |||
set_placeholder: function(is_xs_input) { | |||
} | |||
set_placeholder(is_xs_input) { | |||
const placeholder_html = | |||
`<div class="placeholder ellipsis text-extra-muted ${is_xs_input ? 'xs' : ''}"> | |||
<span>${this.df.placeholder}</span> | |||
@@ -36,14 +36,14 @@ frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({ | |||
} | |||
this.toggle_placeholder(); | |||
this.$input && this.$input.on('select-change', () => this.toggle_placeholder()); | |||
}, | |||
set_formatted_input: function(value) { | |||
} | |||
set_formatted_input(value) { | |||
// refresh options first - (new ones??) | |||
if(value==null) value = ''; | |||
this.set_options(value); | |||
// set in the input element | |||
this._super(value); | |||
super.set_formatted_input(value); | |||
// check if the value to be set is selected | |||
var input_value = ''; | |||
@@ -56,8 +56,8 @@ frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({ | |||
// model value must be same as whatever the input is | |||
this.set_model_value(input_value); | |||
} | |||
}, | |||
set_options: function(value) { | |||
} | |||
set_options(value) { | |||
// reset options, if something new is set | |||
var options = this.df.options || []; | |||
@@ -79,8 +79,8 @@ frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({ | |||
this.$input.val(selected); | |||
} | |||
} | |||
}, | |||
get_file_attachment_list: function() { | |||
} | |||
get_file_attachment_list() { | |||
if(!this.frm) return; | |||
var fl = frappe.model.docinfo[this.frm.doctype][this.frm.docname]; | |||
if(fl && fl.attachments) { | |||
@@ -94,12 +94,12 @@ frappe.ui.form.ControlSelect = frappe.ui.form.ControlData.extend({ | |||
this.set_description(__("Please attach a file first.")); | |||
return [""]; | |||
} | |||
}, | |||
toggle_placeholder: function() { | |||
} | |||
toggle_placeholder() { | |||
const input_set = Boolean(this.$input.find('option:selected').text()); | |||
this.$wrapper.find('.placeholder').toggle(!input_set); | |||
} | |||
}); | |||
}; | |||
// add <option> list to <select> | |||
(function($) { | |||
@@ -1,31 +1,24 @@ | |||
frappe.ui.form.ControlSignature = frappe.ui.form.ControlData.extend({ | |||
saving: false, | |||
loading: false, | |||
make: function() { | |||
frappe.ui.form.ControlSignature = class ControlSignature extends frappe.ui.form.ControlData { | |||
make() { | |||
var me = this; | |||
this._super(); | |||
this.saving = false; | |||
this.loading = false; | |||
super.make(); | |||
// make jSignature field | |||
this.body = $('<div class="signature-field"></div>').appendTo(me.wrapper); | |||
this.load_lib().then(() => { | |||
// make jSignature field | |||
this.body = $('<div class="signature-field"></div>').appendTo(me.wrapper); | |||
if (this.body.is(':visible')) { | |||
this.make_pad(); | |||
} else { | |||
$(document).on('frappe.ui.Dialog:shown', () => { | |||
if (this.body.is(':visible')) { | |||
this.make_pad(); | |||
}); | |||
} | |||
this.img_wrapper = $(`<div class="signature-display"> | |||
<div class="missing-image attach-missing-image"> | |||
${frappe.utils.icon('restriction', 'md')}</i> | |||
</div></div>`) | |||
.appendTo(this.wrapper); | |||
this.img = $("<img class='img-responsive attach-image-display'>") | |||
.appendTo(this.img_wrapper).toggle(false); | |||
}, | |||
make_pad: function() { | |||
} else { | |||
$(document).on('frappe.ui.Dialog:shown', () => { | |||
this.make_pad(); | |||
}); | |||
} | |||
}); | |||
} | |||
make_pad() { | |||
let width = this.body.width(); | |||
if (width > 0 && !this.$pad) { | |||
this.$pad = this.body.jSignature({ | |||
@@ -51,8 +44,16 @@ frappe.ui.form.ControlSignature = frappe.ui.form.ControlData.extend({ | |||
}); | |||
} | |||
}, | |||
refresh_input: function(e) { | |||
this.img_wrapper = $(`<div class="signature-display"> | |||
<div class="missing-image attach-missing-image"> | |||
${frappe.utils.icon('restriction', 'md')}</i> | |||
</div></div>`) | |||
.appendTo(this.wrapper); | |||
this.img = $("<img class='img-responsive attach-image-display'>") | |||
.appendTo(this.img_wrapper).toggle(false); | |||
} | |||
refresh_input(e) { | |||
// prevent to load the second time | |||
this.make_pad(); | |||
this.$wrapper.find(".control-input").toggle(false); | |||
@@ -61,8 +62,8 @@ frappe.ui.form.ControlSignature = frappe.ui.form.ControlData.extend({ | |||
if(this.get_status()=="Read") { | |||
$(this.disp_area).toggle(false); | |||
} | |||
}, | |||
set_image: function(value) { | |||
} | |||
set_image(value) { | |||
if(value) { | |||
$(this.img_wrapper).find(".missing-image").toggle(false); | |||
this.img.attr("src", value).toggle(true); | |||
@@ -70,8 +71,8 @@ frappe.ui.form.ControlSignature = frappe.ui.form.ControlData.extend({ | |||
$(this.img_wrapper).find(".missing-image").toggle(true); | |||
this.img.toggle(false); | |||
} | |||
}, | |||
load_pad: function() { | |||
} | |||
load_pad() { | |||
// make sure not triggered during saving | |||
if (this.saving) return; | |||
// get value | |||
@@ -95,8 +96,8 @@ frappe.ui.form.ControlSignature = frappe.ui.form.ControlData.extend({ | |||
this.loading = false; | |||
} | |||
}, | |||
set_editable: function(editable) { | |||
} | |||
set_editable(editable) { | |||
this.$pad && this.$pad.toggle(editable); | |||
this.img_wrapper.toggle(!editable); | |||
if (this.$reset_button_wrapper) { | |||
@@ -108,26 +109,33 @@ frappe.ui.form.ControlSignature = frappe.ui.form.ControlData.extend({ | |||
this.$reset_button_wrapper.removeClass('editing'); | |||
} | |||
} | |||
}, | |||
set_my_value: function(value) { | |||
} | |||
set_my_value(value) { | |||
if (this.saving || this.loading) return; | |||
this.saving = true; | |||
this.set_value(value); | |||
this.saving = false; | |||
}, | |||
get_value: function() { | |||
} | |||
get_value() { | |||
return this.value ? this.value: this.get_model_value(); | |||
}, | |||
} | |||
// reset signature canvas | |||
on_reset_sign: function() { | |||
on_reset_sign() { | |||
this.$pad.jSignature("reset"); | |||
this.set_my_value(""); | |||
}, | |||
} | |||
// save signature value to model and display | |||
on_save_sign: function() { | |||
on_save_sign() { | |||
if (this.saving || this.loading) return; | |||
var base64_img = this.$pad.jSignature("getData"); | |||
this.set_my_value(base64_img); | |||
this.set_image(this.get_value()); | |||
} | |||
}); | |||
load_lib() { | |||
if (!this.load_lib_promise) { | |||
this.load_lib_promise = frappe.require('/assets/frappe/js/lib/jSignature.min.js'); | |||
} | |||
return this.load_lib_promise; | |||
} | |||
}; |
@@ -1,8 +1,8 @@ | |||
import Grid from '../grid'; | |||
frappe.ui.form.ControlTable = frappe.ui.form.Control.extend({ | |||
make: function() { | |||
this._super(); | |||
frappe.ui.form.ControlTable = class ControlTable extends frappe.ui.form.Control { | |||
make() { | |||
super.make(); | |||
// add title if prev field is not column / section heading or html | |||
this.grid = new Grid({ | |||
@@ -84,19 +84,20 @@ frappe.ui.form.ControlTable = frappe.ui.form.Control.extend({ | |||
}); | |||
return false; // Prevent the default handler from running. | |||
}); | |||
}, | |||
} | |||
get_field(field_name) { | |||
let fieldname; | |||
field_name = field_name.toLowerCase(); | |||
this.grid.meta.fields.some(field => { | |||
if (frappe.model.no_value_type.includes(field.fieldtype)) { | |||
return false; | |||
} | |||
field_name = field_name.toLowerCase(); | |||
const is_field_matching = field_name => { | |||
const is_field_matching = () => { | |||
return ( | |||
field.fieldname.toLowerCase() === field_name || | |||
(field.label || '').toLowerCase() === field_name | |||
(field.label || '').toLowerCase() === field_name || | |||
(__(field.label) || '').toLowerCase() === field_name | |||
); | |||
}; | |||
@@ -106,22 +107,22 @@ frappe.ui.form.ControlTable = frappe.ui.form.Control.extend({ | |||
} | |||
}); | |||
return fieldname; | |||
}, | |||
refresh_input: function() { | |||
} | |||
refresh_input() { | |||
this.grid.refresh(); | |||
}, | |||
get_value: function() { | |||
} | |||
get_value() { | |||
if(this.grid) { | |||
return this.grid.get_data(); | |||
} | |||
}, | |||
set_input: function( ) { | |||
} | |||
set_input( ) { | |||
// | |||
}, | |||
validate: function() { | |||
} | |||
validate() { | |||
return this.get_value(); | |||
}, | |||
} | |||
check_all_rows() { | |||
this.$wrapper.find('.grid-row-check')[0].click(); | |||
} | |||
}); | |||
}; |
@@ -1,6 +1,6 @@ | |||
frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
frappe.ui.form.ControlTableMultiSelect = class ControlTableMultiSelect extends frappe.ui.form.ControlLink { | |||
make_input() { | |||
this._super(); | |||
super.make_input(); | |||
this.$input_area.addClass('form-control table-multiselect'); | |||
this.$input.removeClass('form-control'); | |||
@@ -45,10 +45,10 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
this.parse_validate_and_set_in_model(''); | |||
} | |||
}); | |||
}, | |||
} | |||
setup_buttons() { | |||
this.$input_area.find('.link-btn').remove(); | |||
}, | |||
} | |||
parse(value) { | |||
const link_field = this.get_link_field(); | |||
@@ -65,11 +65,11 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
} | |||
this._rows_list = this.rows.map(row => row[link_field.fieldname]); | |||
return this.rows; | |||
}, | |||
} | |||
get_model_value() { | |||
let value = this._super(); | |||
let value = super.get_model_value(); | |||
return value ? value.filter(d => !d.__islocal) : value; | |||
}, | |||
} | |||
validate(value) { | |||
const rows = (value || []).slice(); | |||
@@ -110,13 +110,13 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
return rows; | |||
} | |||
}); | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
this.rows = value || []; | |||
const link_field = this.get_link_field(); | |||
const values = this.rows.map(row => row[link_field.fieldname]); | |||
this.set_pill_html(values); | |||
}, | |||
} | |||
set_pill_html(values) { | |||
const html = values | |||
.map(value => this.get_pill_html(value)) | |||
@@ -124,7 +124,7 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
this.$input_area.find('.tb-selected-value').remove(); | |||
this.$input_area.prepend(html); | |||
}, | |||
} | |||
get_pill_html(value) { | |||
const encoded_value = encodeURIComponent(value); | |||
return ` | |||
@@ -133,10 +133,10 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
<span class="btn-remove">${frappe.utils.icon('close')}</span> | |||
</button> | |||
`; | |||
}, | |||
} | |||
get_options() { | |||
return (this.get_link_field() || {}).options; | |||
}, | |||
} | |||
get_link_field() { | |||
if (!this._link_field) { | |||
const meta = frappe.get_meta(this.df.options); | |||
@@ -146,8 +146,8 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
} | |||
} | |||
return this._link_field; | |||
}, | |||
custom_awesomplete_filter: function(awesomplete) { | |||
} | |||
custom_awesomplete_filter(awesomplete) { | |||
let me = this; | |||
awesomplete.filter = function(item) { | |||
@@ -158,4 +158,4 @@ frappe.ui.form.ControlTableMultiSelect = frappe.ui.form.ControlLink.extend({ | |||
return true; | |||
}; | |||
} | |||
}); | |||
}; |
@@ -1,20 +1,20 @@ | |||
frappe.ui.form.ControlText = frappe.ui.form.ControlData.extend({ | |||
html_element: "textarea", | |||
horizontal: false, | |||
make_wrapper: function() { | |||
this._super(); | |||
frappe.ui.form.ControlText = class ControlText extends frappe.ui.form.ControlData { | |||
static html_element = "textarea" | |||
static horizontal = false | |||
make_wrapper() { | |||
super.make_wrapper(); | |||
this.$wrapper.find(".like-disabled-input").addClass("for-description"); | |||
}, | |||
make_input: function() { | |||
this._super(); | |||
} | |||
make_input() { | |||
super.make_input(); | |||
this.$input.css({'height': '300px'}); | |||
} | |||
}); | |||
}; | |||
frappe.ui.form.ControlLongText = frappe.ui.form.ControlText; | |||
frappe.ui.form.ControlSmallText = frappe.ui.form.ControlText.extend({ | |||
make_input: function() { | |||
this._super(); | |||
frappe.ui.form.ControlSmallText = class ControlSmallText extends frappe.ui.form.ControlText { | |||
make_input() { | |||
super.make_input(); | |||
this.$input.css({'height': '150px'}); | |||
} | |||
}); | |||
}; |
@@ -68,22 +68,22 @@ CustomColor.tagName = "font"; | |||
Quill.register(CustomColor, true); | |||
frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({ | |||
frappe.ui.form.ControlTextEditor = class ControlTextEditor extends frappe.ui.form.ControlCode { | |||
make_wrapper() { | |||
this._super(); | |||
}, | |||
super.make_wrapper(); | |||
} | |||
make_input() { | |||
this.has_input = true; | |||
this.make_quill_editor(); | |||
}, | |||
} | |||
make_quill_editor() { | |||
if (this.quill) return; | |||
this.quill_container = $('<div>').appendTo(this.input_area); | |||
this.quill = new Quill(this.quill_container[0], this.get_quill_options()); | |||
this.bind_events(); | |||
}, | |||
} | |||
bind_events() { | |||
this.quill.on('text-change', frappe.utils.debounce((delta, oldDelta, source) => { | |||
@@ -135,13 +135,13 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({ | |||
e.preventDefault(); | |||
}); | |||
}, | |||
} | |||
is_quill_dirty(source) { | |||
if (source === 'api') return false; | |||
let input_value = this.get_input_value(); | |||
return this.value !== input_value; | |||
}, | |||
} | |||
get_quill_options() { | |||
return { | |||
@@ -152,7 +152,7 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({ | |||
}, | |||
theme: 'snow' | |||
}; | |||
}, | |||
} | |||
get_toolbar_options() { | |||
return [ | |||
@@ -174,14 +174,14 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({ | |||
'delete-table', | |||
]}], | |||
]; | |||
}, | |||
} | |||
parse(value) { | |||
if (value == null) { | |||
value = ""; | |||
} | |||
return frappe.dom.remove_script_and_style(value); | |||
}, | |||
} | |||
set_formatted_input(value) { | |||
if (!this.quill) return; | |||
@@ -195,7 +195,7 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({ | |||
// set html without triggering a focus | |||
const delta = this.quill.clipboard.convert({ html: value, text: '' }); | |||
this.quill.setContents(delta); | |||
}, | |||
} | |||
get_input_value() { | |||
let value = this.quill ? this.quill.root.innerHTML : ''; | |||
@@ -211,9 +211,9 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({ | |||
} | |||
return value; | |||
}, | |||
} | |||
set_focus() { | |||
this.quill.focus(); | |||
} | |||
}); | |||
}; |
@@ -1,17 +1,17 @@ | |||
frappe.ui.form.ControlTime = frappe.ui.form.ControlDate.extend({ | |||
set_formatted_input: function(value) { | |||
this._super(value); | |||
}, | |||
make_input: function() { | |||
frappe.ui.form.ControlTime = class ControlTime extends frappe.ui.form.ControlDate { | |||
set_formatted_input(value) { | |||
super.set_formatted_input(value); | |||
} | |||
make_input() { | |||
this.timepicker_only = true; | |||
this._super(); | |||
}, | |||
make_picker: function() { | |||
super.make_input(); | |||
} | |||
make_picker() { | |||
this.set_time_options(); | |||
this.set_datepicker(); | |||
this.refresh(); | |||
}, | |||
set_time_options: function() { | |||
} | |||
set_time_options() { | |||
let sysdefaults = frappe.boot.sysdefaults; | |||
let time_format = sysdefaults && sysdefaults.time_format | |||
@@ -38,9 +38,9 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlDate.extend({ | |||
keyboardNav: false, | |||
todayButton: true | |||
}; | |||
}, | |||
set_input: function(value) { | |||
this._super(value); | |||
} | |||
set_input(value) { | |||
super.set_input(value); | |||
if (value | |||
&& ((this.last_value && this.last_value !== this.value) | |||
|| (!this.datepicker.selectedDates.length))) { | |||
@@ -49,8 +49,8 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlDate.extend({ | |||
var date_obj = frappe.datetime.moment_to_date_obj(moment(value, time_format)); | |||
this.datepicker.selectDate(date_obj); | |||
} | |||
}, | |||
set_datepicker: function() { | |||
} | |||
set_datepicker() { | |||
this.$input.datepicker(this.datepicker_options); | |||
this.datepicker = this.$input.data('datepicker'); | |||
@@ -67,8 +67,8 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlDate.extend({ | |||
$tp.$secondsText.css('display', 'none'); | |||
$tp.$secondsText.prev().css('display', 'none'); | |||
} | |||
}, | |||
set_description: function() { | |||
} | |||
set_description() { | |||
const { description } = this.df; | |||
const { time_zone } = frappe.sys_defaults; | |||
if (!frappe.datetime.is_timezone_same()) { | |||
@@ -78,20 +78,20 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlDate.extend({ | |||
this.df.description += '<br>' + time_zone; | |||
} | |||
} | |||
this._super(); | |||
}, | |||
parse: function(value) { | |||
super.set_description(); | |||
} | |||
parse(value) { | |||
if (value) { | |||
return frappe.datetime.user_to_str(value, true); | |||
} | |||
}, | |||
format_for_input: function(value) { | |||
} | |||
format_for_input(value) { | |||
if (value) { | |||
return frappe.datetime.str_to_user(value, true); | |||
} | |||
return ""; | |||
}, | |||
validate: function(value) { | |||
} | |||
validate(value) { | |||
if (value && !frappe.datetime.validate(value)) { | |||
let sysdefaults = frappe.sys_defaults; | |||
let time_format = sysdefaults && sysdefaults.time_format | |||
@@ -101,4 +101,4 @@ frappe.ui.form.ControlTime = frappe.ui.form.ControlDate.extend({ | |||
} | |||
return value; | |||
} | |||
}); | |||
}; |
@@ -1,8 +1,8 @@ | |||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
import FormTimeline from "./form_timeline"; | |||
frappe.ui.form.Footer = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.Footer = class FormFooter { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.make(); | |||
this.make_comment_box(); | |||
@@ -11,15 +11,15 @@ frappe.ui.form.Footer = Class.extend({ | |||
$(this.frm.wrapper).on("render_complete", () => { | |||
this.refresh(); | |||
}); | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
this.wrapper = $(frappe.render_template("form_footer", {})) | |||
.appendTo(this.parent); | |||
this.wrapper.find(".btn-save").click(() => { | |||
this.frm.save('Save', null, this); | |||
}); | |||
}, | |||
make_comment_box: function() { | |||
} | |||
make_comment_box() { | |||
this.frm.comment_box = frappe.ui.form.make_control({ | |||
parent: this.wrapper.find(".comment-box"), | |||
render_input: true, | |||
@@ -50,19 +50,19 @@ frappe.ui.form.Footer = Class.extend({ | |||
} | |||
} | |||
}); | |||
}, | |||
} | |||
make_timeline() { | |||
this.frm.timeline = new FormTimeline({ | |||
parent: this.wrapper.find(".timeline"), | |||
frm: this.frm | |||
}); | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
if (this.frm.doc.__islocal) { | |||
this.parent.addClass("hide"); | |||
} else { | |||
this.parent.removeClass("hide"); | |||
this.frm.timeline.refresh(); | |||
} | |||
}, | |||
}); | |||
} | |||
}; |
@@ -13,11 +13,11 @@ import './script_helpers'; | |||
import './sidebar/form_sidebar'; | |||
import './footer/footer'; | |||
frappe.ui.form.Controller = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.Controller = class FormController { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
} | |||
}); | |||
}; | |||
frappe.ui.form.Form = class FrappeForm { | |||
constructor(doctype, parent, in_form, doctype_layout_name) { | |||
@@ -1125,9 +1125,17 @@ frappe.ui.form.Form = class FrappeForm { | |||
add_custom_button(label, fn, group) { | |||
// temp! old parameter used to be icon | |||
if(group && group.indexOf("fa fa-")!==-1) group = null; | |||
var btn = this.page.add_inner_button(label, fn, group); | |||
if(btn) { | |||
if (group && group.indexOf("fa fa-") !== -1) | |||
group = null; | |||
let btn = this.page.add_inner_button(label, fn, group); | |||
if (btn) { | |||
// Add actions as menu item in Mobile View | |||
let menu_item_label = group ? `${group} > ${label}` : label; | |||
let menu_item = this.page.add_menu_item(menu_item_label, fn, false); | |||
menu_item.parent().addClass("hidden-lg"); | |||
this.custom_buttons[label] = btn; | |||
} | |||
return btn; | |||
@@ -1,7 +1,7 @@ | |||
import '../class'; | |||
frappe.ui.form.Layout = Class.extend({ | |||
init: function (opts) { | |||
frappe.ui.form.Layout = class Layout { | |||
constructor (opts) { | |||
this.views = {}; | |||
this.pages = []; | |||
this.sections = []; | |||
@@ -9,8 +9,8 @@ frappe.ui.form.Layout = Class.extend({ | |||
this.fields_dict = {}; | |||
$.extend(this, opts); | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
if (!this.parent && this.body) { | |||
this.parent = this.body; | |||
} | |||
@@ -21,14 +21,14 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
this.setup_tabbing(); | |||
this.render(); | |||
}, | |||
show_empty_form_message: function() { | |||
} | |||
show_empty_form_message() { | |||
if (!(this.wrapper.find(".frappe-control:visible").length || this.wrapper.find(".section-head.collapsed").length)) { | |||
this.show_message(__("This form does not have any input")); | |||
} | |||
}, | |||
} | |||
get_doctype_fields: function() { | |||
get_doctype_fields() { | |||
let fields = [ | |||
this.get_new_name_field() | |||
]; | |||
@@ -39,7 +39,7 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
return fields; | |||
}, | |||
} | |||
get_new_name_field() { | |||
return { | |||
@@ -58,7 +58,7 @@ frappe.ui.form.Layout = Class.extend({ | |||
return 'None'; | |||
} | |||
}; | |||
}, | |||
} | |||
get_fields_from_layout() { | |||
const fields = []; | |||
@@ -68,9 +68,9 @@ frappe.ui.form.Layout = Class.extend({ | |||
fields.push(docfield); | |||
} | |||
return fields; | |||
}, | |||
} | |||
show_message: function(html, color) { | |||
show_message(html, color) { | |||
if (this.message_color) { | |||
// remove previous color | |||
this.message.removeClass(this.message_color); | |||
@@ -86,8 +86,8 @@ frappe.ui.form.Layout = Class.extend({ | |||
} else { | |||
this.message.empty().addClass('hidden'); | |||
} | |||
}, | |||
render: function (new_fields) { | |||
} | |||
render (new_fields) { | |||
var me = this; | |||
var fields = new_fields || this.fields; | |||
@@ -117,19 +117,19 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
}); | |||
}, | |||
} | |||
no_opening_section: function () { | |||
no_opening_section () { | |||
return (this.fields[0] && this.fields[0].fieldtype != "Section Break") || !this.fields.length; | |||
}, | |||
} | |||
setup_dashboard_section: function () { | |||
setup_dashboard_section () { | |||
if (this.no_opening_section()) { | |||
this.fields.unshift({fieldtype: 'Section Break'}); | |||
} | |||
}, | |||
} | |||
replace_field: function (fieldname, df, render) { | |||
replace_field (fieldname, df, render) { | |||
df.fieldname = fieldname; // change of fieldname is avoided | |||
if (this.fields_dict[fieldname] && this.fields_dict[fieldname].df) { | |||
const fieldobj = this.init_field(df, render); | |||
@@ -143,9 +143,9 @@ frappe.ui.form.Layout = Class.extend({ | |||
this.section.fields_dict[fieldname] = fieldobj; | |||
this.refresh_fields([df]); | |||
} | |||
}, | |||
} | |||
make_field: function (df, colspan, render) { | |||
make_field (df, colspan, render) { | |||
!this.section && this.make_section(); | |||
!this.column && this.make_column(); | |||
@@ -159,9 +159,9 @@ frappe.ui.form.Layout = Class.extend({ | |||
this.section.fields_list.push(fieldobj); | |||
this.section.fields_dict[df.fieldname] = fieldobj; | |||
fieldobj.section = this.section; | |||
}, | |||
} | |||
init_field: function (df, render = false) { | |||
init_field (df, render = false) { | |||
const fieldobj = frappe.ui.form.make_control({ | |||
df: df, | |||
doctype: this.doctype, | |||
@@ -174,9 +174,9 @@ frappe.ui.form.Layout = Class.extend({ | |||
fieldobj.layout = this; | |||
return fieldobj; | |||
}, | |||
} | |||
make_page: function (df) { // eslint-disable-line no-unused-vars | |||
make_page (df) { // eslint-disable-line no-unused-vars | |||
var me = this, | |||
head = $('<div class="form-clickable-section text-center">\ | |||
<a class="btn-fold h6 text-muted">' + __("Show more details") + '</a>\ | |||
@@ -200,13 +200,13 @@ frappe.ui.form.Layout = Class.extend({ | |||
this.section = null; | |||
this.folded = true; | |||
}, | |||
} | |||
unfold: function () { | |||
unfold () { | |||
this.fold_btn.trigger('click'); | |||
}, | |||
} | |||
make_section: function (df) { | |||
make_section (df) { | |||
this.section = new frappe.ui.form.Section(this, df); | |||
// append to layout fields | |||
@@ -216,16 +216,16 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
this.column = null; | |||
}, | |||
} | |||
make_column: function (df) { | |||
make_column (df) { | |||
this.column = new frappe.ui.form.Column(this.section, df); | |||
if (df && df.fieldname) { | |||
this.fields_list.push(this.column); | |||
} | |||
}, | |||
} | |||
refresh: function (doc) { | |||
refresh (doc) { | |||
var me = this; | |||
if (doc) this.doc = doc; | |||
@@ -250,9 +250,9 @@ frappe.ui.form.Layout = Class.extend({ | |||
// collapse sections | |||
this.refresh_section_collapse(); | |||
} | |||
}, | |||
} | |||
refresh_sections: function() { | |||
refresh_sections() { | |||
// hide invisible sections | |||
this.wrapper.find(".form-section:not(.hide-control)").each(function() { | |||
const section = $(this).removeClass("empty-section visible-section"); | |||
@@ -266,9 +266,9 @@ frappe.ui.form.Layout = Class.extend({ | |||
this.frm && this.frm.dashboard.refresh(); | |||
}, | |||
} | |||
refresh_fields: function (fields) { | |||
refresh_fields (fields) { | |||
let fieldnames = fields.map((field) => { | |||
if (field.fieldname) return field.fieldname; | |||
}); | |||
@@ -281,14 +281,14 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
} | |||
}); | |||
}, | |||
} | |||
add_fields: function (fields) { | |||
add_fields (fields) { | |||
this.render(fields); | |||
this.refresh_fields(fields); | |||
}, | |||
} | |||
refresh_section_collapse: function () { | |||
refresh_section_collapse () { | |||
if (!(this.sections && this.sections.length)) return; | |||
for (var i = 0; i < this.sections.length; i++) { | |||
@@ -308,9 +308,9 @@ frappe.ui.form.Layout = Class.extend({ | |||
section.collapse(collapse); | |||
} | |||
} | |||
}, | |||
} | |||
attach_doc_and_docfields: function (refresh) { | |||
attach_doc_and_docfields (refresh) { | |||
var me = this; | |||
for (var i = 0, l = this.fields_list.length; i < l; i++) { | |||
var fieldobj = this.fields_list[i]; | |||
@@ -328,14 +328,14 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
refresh && fieldobj.df && fieldobj.refresh && fieldobj.refresh(); | |||
} | |||
}, | |||
} | |||
refresh_section_count: function () { | |||
refresh_section_count () { | |||
this.wrapper.find(".section-count-label:visible").each(function (i) { | |||
$(this).html(i + 1); | |||
}); | |||
}, | |||
setup_tabbing: function () { | |||
} | |||
setup_tabbing () { | |||
var me = this; | |||
this.wrapper.on("keydown", function (ev) { | |||
if (ev.which == 9) { | |||
@@ -346,8 +346,8 @@ frappe.ui.form.Layout = Class.extend({ | |||
return me.handle_tab(doctype, fieldname, ev.shiftKey); | |||
} | |||
}); | |||
}, | |||
handle_tab: function (doctype, fieldname, shift) { | |||
} | |||
handle_tab (doctype, fieldname, shift) { | |||
var me = this, | |||
grid_row = null, | |||
prev = null, | |||
@@ -405,8 +405,8 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
return false; | |||
}, | |||
focus_on_next_field: function (start_idx, fields) { | |||
} | |||
focus_on_next_field (start_idx, fields) { | |||
// loop to find next eligible fields | |||
for (var i = start_idx + 1, len = fields.length; i < len; i++) { | |||
var field = fields[i]; | |||
@@ -427,11 +427,11 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
} | |||
} | |||
}, | |||
is_visible: function (field) { | |||
} | |||
is_visible (field) { | |||
return field.disp_status === "Write" && (field.$wrapper && field.$wrapper.is(":visible")); | |||
}, | |||
set_focus: function (field) { | |||
} | |||
set_focus (field) { | |||
// next is table, show the table | |||
if (field.df.fieldtype=="Table") { | |||
if (!field.grid.grid_rows.length) { | |||
@@ -444,11 +444,11 @@ frappe.ui.form.Layout = Class.extend({ | |||
} else if (field.$input) { | |||
field.$input.focus(); | |||
} | |||
}, | |||
get_open_grid_row: function () { | |||
} | |||
get_open_grid_row () { | |||
return $(".grid-row-open").data("grid_row"); | |||
}, | |||
refresh_dependency: function () { | |||
} | |||
refresh_dependency () { | |||
// Resolve "depends_on" and show / hide accordingly | |||
var me = this; | |||
@@ -498,8 +498,8 @@ frappe.ui.form.Layout = Class.extend({ | |||
} | |||
this.refresh_section_count(); | |||
}, | |||
set_dependant_property: function (condition, fieldname, property) { | |||
} | |||
set_dependant_property (condition, fieldname, property) { | |||
let set_property = this.evaluate_depends_on_value(condition); | |||
let value = set_property ? 1 : 0; | |||
let form_obj; | |||
@@ -520,8 +520,8 @@ frappe.ui.form.Layout = Class.extend({ | |||
form_obj.set_df_property(fieldname, property, value); | |||
} | |||
} | |||
}, | |||
evaluate_depends_on_value: function (expression) { | |||
} | |||
evaluate_depends_on_value (expression) { | |||
var out = null; | |||
var doc = this.doc; | |||
@@ -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; | |||
} | |||
@@ -564,10 +564,10 @@ frappe.ui.form.Layout = Class.extend({ | |||
return out; | |||
} | |||
}); | |||
}; | |||
frappe.ui.form.Section = Class.extend({ | |||
init: function(layout, df) { | |||
frappe.ui.form.Section = class FormSection { | |||
constructor(layout, df) { | |||
this.layout = layout; | |||
this.df = df || {}; | |||
this.fields_list = []; | |||
@@ -581,8 +581,8 @@ frappe.ui.form.Section = Class.extend({ | |||
}; | |||
this.refresh(); | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
if (!this.layout.page) { | |||
this.layout.page = $('<div class="form-page"></div>').appendTo(this.layout.wrapper); | |||
} | |||
@@ -609,9 +609,9 @@ frappe.ui.form.Section = Class.extend({ | |||
// for bc | |||
this.body = $('<div class="section-body">').appendTo(this.wrapper); | |||
}, | |||
} | |||
make_head: function () { | |||
make_head () { | |||
this.head = $(`<div class="section-head"> | |||
${__(this.df.label)} | |||
<span class="ml-2 collapse-indicator mb-1"> | |||
@@ -628,8 +628,8 @@ frappe.ui.form.Section = Class.extend({ | |||
this.indicator.show(); | |||
} | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
if (!this.df) | |||
return; | |||
@@ -642,8 +642,8 @@ frappe.ui.form.Section = Class.extend({ | |||
} | |||
this.wrapper.toggleClass("hide-control", !!hide); | |||
}, | |||
collapse: function (hide) { | |||
} | |||
collapse (hide) { | |||
// unknown edge case | |||
if (!(this.head && this.body)) { | |||
return; | |||
@@ -666,13 +666,13 @@ frappe.ui.form.Section = Class.extend({ | |||
f.refresh(); | |||
} | |||
}); | |||
}, | |||
} | |||
is_collapsed() { | |||
return this.body.hasClass('hide'); | |||
}, | |||
} | |||
has_missing_mandatory: function () { | |||
has_missing_mandatory () { | |||
var missing_mandatory = false; | |||
for (var j = 0, l = this.fields_list.length; j < l; j++) { | |||
var section_df = this.fields_list[j].df; | |||
@@ -683,18 +683,18 @@ frappe.ui.form.Section = Class.extend({ | |||
} | |||
return missing_mandatory; | |||
} | |||
}); | |||
}; | |||
frappe.ui.form.Column = Class.extend({ | |||
init: function(section, df) { | |||
frappe.ui.form.Column = class FormColumn { | |||
constructor(section, df) { | |||
if (!df) df = {}; | |||
this.df = df; | |||
this.section = section; | |||
this.make(); | |||
this.resize_all_columns(); | |||
}, | |||
make: function () { | |||
} | |||
make () { | |||
this.wrapper = $('<div class="form-column">\ | |||
<form>\ | |||
</form>\ | |||
@@ -708,8 +708,8 @@ frappe.ui.form.Column = Class.extend({ | |||
$('<label class="control-label">' + __(this.df.label) | |||
+ '</label>').appendTo(this.wrapper); | |||
} | |||
}, | |||
resize_all_columns: function () { | |||
} | |||
resize_all_columns () { | |||
// distribute all columns equally | |||
var colspan = cint(12 / this.section.wrapper.find(".form-column").length); | |||
@@ -717,8 +717,8 @@ frappe.ui.form.Column = Class.extend({ | |||
.addClass("form-column") | |||
.addClass("col-sm-" + colspan); | |||
}, | |||
refresh: function () { | |||
} | |||
refresh () { | |||
this.section.refresh(); | |||
} | |||
}); | |||
}; |
@@ -1,8 +1,8 @@ | |||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
frappe.ui.form.LinkSelector = Class.extend({ | |||
init: function (opts) { | |||
frappe.ui.form.LinkSelector = class LinkSelector { | |||
constructor (opts) { | |||
/* help: Options: doctype, get_query, target */ | |||
$.extend(this, opts); | |||
@@ -14,8 +14,8 @@ frappe.ui.form.LinkSelector = Class.extend({ | |||
} else { | |||
this.make(); | |||
} | |||
}, | |||
make: function () { | |||
} | |||
make () { | |||
var me = this; | |||
this.start = 0; | |||
@@ -54,8 +54,8 @@ frappe.ui.form.LinkSelector = Class.extend({ | |||
}); | |||
this.dialog.show(); | |||
this.search(); | |||
}, | |||
search: function () { | |||
} | |||
search () { | |||
var args = { | |||
txt: this.dialog.fields_dict.txt.get_value(), | |||
searchfield: "name", | |||
@@ -129,8 +129,8 @@ frappe.ui.form.LinkSelector = Class.extend({ | |||
}, this.dialog.get_primary_btn()); | |||
}, | |||
set_in_grid: function (value) { | |||
} | |||
set_in_grid (value) { | |||
var me = this, updated = false; | |||
var d = null; | |||
if (this.qty_fieldname) { | |||
@@ -174,7 +174,7 @@ frappe.ui.form.LinkSelector = Class.extend({ | |||
frappe.show_alert(__("{0} added", [value])); | |||
} | |||
} | |||
}); | |||
}; | |||
frappe.link_search = function (doctype, args, callback, btn) { | |||
if (!args) { | |||
@@ -18,16 +18,16 @@ frappe.ui.form.make_quick_entry = (doctype, after_insert, init_callback, doc, fo | |||
return frappe.quick_entry.setup(); | |||
}; | |||
frappe.ui.form.QuickEntryForm = Class.extend({ | |||
init: function(doctype, after_insert, init_callback, doc, force) { | |||
frappe.ui.form.QuickEntryForm = class QuickEntryForm { | |||
constructor(doctype, after_insert, init_callback, doc, force) { | |||
this.doctype = doctype; | |||
this.after_insert = after_insert; | |||
this.init_callback = init_callback; | |||
this.doc = doc; | |||
this.force = force ? force : false; | |||
}, | |||
} | |||
setup: function() { | |||
setup() { | |||
return new Promise(resolve => { | |||
frappe.model.with_doctype(this.doctype, () => { | |||
this.check_quick_entry_doc(); | |||
@@ -47,9 +47,9 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
} | |||
}); | |||
}); | |||
}, | |||
} | |||
set_meta_and_mandatory_fields: function() { | |||
set_meta_and_mandatory_fields() { | |||
this.meta = frappe.get_meta(this.doctype); | |||
let fields = this.meta.fields; | |||
@@ -57,15 +57,15 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
this.mandatory = fields.filter(df => { | |||
return ((df.reqd || df.bold || df.allow_in_quick_entry) && !df.read_only); | |||
}); | |||
}, | |||
} | |||
check_quick_entry_doc: function() { | |||
check_quick_entry_doc() { | |||
if (!this.doc) { | |||
this.doc = frappe.model.get_new_doc(this.doctype, null, null, true); | |||
} | |||
}, | |||
} | |||
is_quick_entry: function() { | |||
is_quick_entry() { | |||
if(this.meta.quick_entry != 1) { | |||
return false; | |||
} | |||
@@ -77,33 +77,33 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
} | |||
return true; | |||
}, | |||
} | |||
too_many_mandatory_fields: function() { | |||
too_many_mandatory_fields() { | |||
if(this.mandatory.length > 7) { | |||
// too many fields, show form | |||
return true; | |||
} | |||
return false; | |||
}, | |||
} | |||
has_child_table: function(){ | |||
has_child_table(){ | |||
if($.map(this.mandatory, function(d) { | |||
return d.fieldtype==='Table' ? d : null; }).length) { | |||
// has mandatory table, quit! | |||
return true; | |||
} | |||
return false; | |||
}, | |||
} | |||
validate_for_prompt_autoname: function() { | |||
validate_for_prompt_autoname() { | |||
if(this.meta.autoname && this.meta.autoname.toLowerCase()==='prompt') { | |||
this.mandatory = [{fieldname:'__newname', label:__('{0} Name', [this.meta.name]), | |||
reqd: 1, fieldtype:'Data'}].concat(this.mandatory); | |||
} | |||
}, | |||
} | |||
render_dialog: function() { | |||
render_dialog() { | |||
var me = this; | |||
this.dialog = new frappe.ui.Dialog({ | |||
title: __("New {0}", [__(this.doctype)]), | |||
@@ -134,9 +134,9 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
if (this.init_callback) { | |||
this.init_callback(this.dialog); | |||
} | |||
}, | |||
} | |||
register_primary_action: function() { | |||
register_primary_action() { | |||
var me = this; | |||
this.dialog.set_primary_action(__('Save'), function() { | |||
if(me.dialog.working) { | |||
@@ -152,9 +152,9 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
}); | |||
} | |||
}); | |||
}, | |||
} | |||
insert: function() { | |||
insert() { | |||
let me = this; | |||
return new Promise(resolve => { | |||
me.update_doc(); | |||
@@ -202,9 +202,9 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
freeze: true | |||
}); | |||
}); | |||
}, | |||
} | |||
submit: function(doc) { | |||
submit(doc) { | |||
var me = this; | |||
frappe.call({ | |||
method: "frappe.client.submit", | |||
@@ -229,9 +229,9 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
cur_frm && cur_frm.reload_doc(); | |||
} | |||
}); | |||
}, | |||
} | |||
open_form_if_not_list: function() { | |||
open_form_if_not_list() { | |||
let route = frappe.get_route(); | |||
let doc = this.dialog.doc; | |||
if (route && !(route[0]==='List' && route[1]===doc.doctype)) { | |||
@@ -239,9 +239,9 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
() => frappe.set_route('Form', doc.doctype, doc.name) | |||
]); | |||
} | |||
}, | |||
} | |||
update_doc: function(){ | |||
update_doc(){ | |||
var me = this; | |||
var data = this.dialog.get_values(true); | |||
$.each(data, function(key, value) { | |||
@@ -250,9 +250,9 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
} | |||
}); | |||
return this.dialog.doc; | |||
}, | |||
} | |||
open_doc: function(set_hooks) { | |||
open_doc(set_hooks) { | |||
this.dialog.hide(); | |||
this.update_doc(); | |||
if (set_hooks && this.after_insert) { | |||
@@ -262,17 +262,17 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
}; | |||
} | |||
frappe.set_route('Form', this.doctype, this.doc.name); | |||
}, | |||
} | |||
render_edit_in_full_page_link: function() { | |||
render_edit_in_full_page_link() { | |||
var me = this; | |||
this.dialog.add_custom_action( | |||
`${frappe.utils.icon('edit', 'xs')} ${__("Edit in full page")}`, | |||
() => me.open_doc(true) | |||
); | |||
}, | |||
} | |||
set_defaults: function() { | |||
set_defaults() { | |||
var me = this; | |||
// set defaults | |||
$.each(this.dialog.fields_dict, function(fieldname, field) { | |||
@@ -284,4 +284,4 @@ frappe.ui.form.QuickEntryForm = Class.extend({ | |||
} | |||
}); | |||
} | |||
}); | |||
}; |
@@ -69,15 +69,15 @@ frappe.ui.form.trigger = function(doctype, fieldname) { | |||
cur_frm.script_manager.trigger(fieldname, doctype); | |||
} | |||
frappe.ui.form.ScriptManager = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.ScriptManager = class ScriptManager { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
}, | |||
make: function(ControllerClass) { | |||
} | |||
make(ControllerClass) { | |||
this.frm.cscript = $.extend(this.frm.cscript, | |||
new ControllerClass({frm: this.frm})); | |||
}, | |||
trigger: function(event_name, doctype, name) { | |||
} | |||
trigger(event_name, doctype, name) { | |||
// trigger all the form level events that | |||
// are bound to this event_name | |||
let me = this; | |||
@@ -130,12 +130,12 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
// run them serially | |||
return frappe.run_serially(tasks); | |||
}, | |||
has_handlers: function(event_name, doctype) { | |||
} | |||
has_handlers(event_name, doctype) { | |||
let handlers = this.get_handlers(event_name, doctype); | |||
return handlers && (handlers.old_style.length || handlers.new_style.length); | |||
}, | |||
get_handlers: function(event_name, doctype) { | |||
} | |||
get_handlers(event_name, doctype) { | |||
// returns list of all functions to be called (old style and new style) | |||
let me = this; | |||
let handlers = { | |||
@@ -154,8 +154,8 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
handlers.old_style.push("custom_" + event_name); | |||
} | |||
return handlers; | |||
}, | |||
setup: function() { | |||
} | |||
setup() { | |||
const doctype = this.frm.meta; | |||
const me = this; | |||
let client_script; | |||
@@ -206,8 +206,8 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
doctype.__css && frappe.dom.set_style(doctype.__css); | |||
this.trigger('setup'); | |||
}, | |||
log_error: function(caller, e) { | |||
} | |||
log_error(caller, e) { | |||
frappe.show_alert({message: __("Error in Client Script."), indicator: "error"}); | |||
console.group && console.group(); | |||
console.log("----- error in client script -----"); | |||
@@ -217,8 +217,8 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
console.trace && console.trace(); | |||
console.log("----- end of error message -----"); | |||
console.group && console.groupEnd(); | |||
}, | |||
copy_from_first_row: function(parentfield, current_row, fieldnames) { | |||
} | |||
copy_from_first_row(parentfield, current_row, fieldnames) { | |||
var data = this.frm.doc[parentfield]; | |||
if(data.length===1 || data[0]===current_row) return; | |||
@@ -231,4 +231,4 @@ frappe.ui.form.ScriptManager = Class.extend({ | |||
data[0][fieldname]); | |||
}); | |||
} | |||
}); | |||
}; |
@@ -3,23 +3,23 @@ | |||
frappe.ui.form.AssignTo = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.AssignTo = class AssignTo { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.btn = this.parent.find(".add-assignment-btn").on("click", () => this.add()); | |||
this.btn_wrapper = this.btn.parent(); | |||
this.refresh(); | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
if(this.frm.doc.__islocal) { | |||
this.parent.toggle(false); | |||
return; | |||
} | |||
this.parent.toggle(true); | |||
this.render(this.frm.get_docinfo().assignments); | |||
}, | |||
render: function(assignments) { | |||
} | |||
render(assignments) { | |||
this.frm.get_docinfo().assignments = assignments; | |||
let assignments_wrapper = this.parent.find('.assignments'); | |||
@@ -42,8 +42,8 @@ frappe.ui.form.AssignTo = Class.extend({ | |||
frm: this.frm | |||
}); | |||
}); | |||
}, | |||
add: function() { | |||
} | |||
add() { | |||
var me = this; | |||
if (this.frm.is_new()) { | |||
@@ -64,8 +64,8 @@ frappe.ui.form.AssignTo = Class.extend({ | |||
} | |||
me.assign_to.dialog.clear(); | |||
me.assign_to.dialog.show(); | |||
}, | |||
remove: function(owner) { | |||
} | |||
remove(owner) { | |||
if (this.frm.is_new()) { | |||
frappe.throw(__("Please save the document before removing assignment")); | |||
return; | |||
@@ -79,17 +79,17 @@ frappe.ui.form.AssignTo = Class.extend({ | |||
this.render(assignments); | |||
}); | |||
} | |||
}); | |||
}; | |||
frappe.ui.form.AssignToDialog = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.AssignToDialog = class AssignToDialog { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.make(); | |||
this.set_description_from_doc(); | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
let me = this; | |||
me.dialog = new frappe.ui.Dialog({ | |||
@@ -126,8 +126,8 @@ frappe.ui.form.AssignToDialog = Class.extend({ | |||
} | |||
}, | |||
}); | |||
}, | |||
assign_to_me: function() { | |||
} | |||
assign_to_me() { | |||
let me = this; | |||
let assign_to = []; | |||
@@ -136,15 +136,15 @@ frappe.ui.form.AssignToDialog = Class.extend({ | |||
} | |||
me.dialog.set_value("assign_to", assign_to); | |||
}, | |||
set_description_from_doc: function() { | |||
} | |||
set_description_from_doc() { | |||
let me = this; | |||
if (me.frm && me.frm.meta.title_field) { | |||
me.dialog.set_value("description", me.frm.doc[me.frm.meta.title_field]); | |||
} | |||
}, | |||
get_fields: function() { | |||
} | |||
get_fields() { | |||
let me = this; | |||
return [ | |||
@@ -206,7 +206,7 @@ frappe.ui.form.AssignToDialog = Class.extend({ | |||
} | |||
]; | |||
} | |||
}); | |||
}; | |||
frappe.ui.form.AssignmentDialog = class { | |||
@@ -1,20 +1,20 @@ | |||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
frappe.ui.form.Attachments = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.Attachments = class Attachments { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.make(); | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
var me = this; | |||
this.parent.find(".add-attachment-btn").click(function() { | |||
me.new_attachment(); | |||
}); | |||
this.add_attachment_wrapper = this.parent.find(".add_attachment").parent(); | |||
this.attachments_label = this.parent.find(".attachments-label"); | |||
}, | |||
max_reached: function(raise_exception=false) { | |||
} | |||
max_reached(raise_exception=false) { | |||
const attachment_count = Object.keys(this.get_attachments()).length; | |||
const attachment_limit = this.frm.meta.max_attachments; | |||
if (attachment_limit && attachment_count >= attachment_limit) { | |||
@@ -27,8 +27,8 @@ frappe.ui.form.Attachments = Class.extend({ | |||
return true; | |||
} | |||
return false; | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
var me = this; | |||
if(this.frm.doc.__islocal) { | |||
@@ -51,11 +51,11 @@ frappe.ui.form.Attachments = Class.extend({ | |||
this.attachments_label.removeClass("has-attachments"); | |||
} | |||
}, | |||
get_attachments: function() { | |||
} | |||
get_attachments() { | |||
return this.frm.get_docinfo().attachments; | |||
}, | |||
add_attachment: function(attachment) { | |||
} | |||
add_attachment(attachment) { | |||
var file_name = attachment.file_name; | |||
var file_url = this.get_file_url(attachment); | |||
var fileid = attachment.name; | |||
@@ -95,8 +95,8 @@ frappe.ui.form.Attachments = Class.extend({ | |||
)) | |||
.insertAfter(this.attachments_label.addClass("has-attachments")); | |||
}, | |||
get_file_url: function(attachment) { | |||
} | |||
get_file_url(attachment) { | |||
var file_url = attachment.file_url; | |||
if (!file_url) { | |||
if (attachment.file_name.indexOf('files/') === 0) { | |||
@@ -108,8 +108,8 @@ frappe.ui.form.Attachments = Class.extend({ | |||
} | |||
// hash is not escaped, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI | |||
return encodeURI(file_url).replace(/#/g, '%23'); | |||
}, | |||
get_file_id_from_file_url: function(file_url) { | |||
} | |||
get_file_id_from_file_url(file_url) { | |||
var fid; | |||
$.each(this.get_attachments(), function(i, attachment) { | |||
if (attachment.file_url === file_url) { | |||
@@ -118,11 +118,11 @@ frappe.ui.form.Attachments = Class.extend({ | |||
} | |||
}); | |||
return fid; | |||
}, | |||
remove_attachment_by_filename: function(filename, callback) { | |||
} | |||
remove_attachment_by_filename(filename, callback) { | |||
this.remove_attachment(this.get_file_id_from_file_url(filename), callback); | |||
}, | |||
remove_attachment: function(fileid, callback) { | |||
} | |||
remove_attachment(fileid, callback) { | |||
if (!fileid) { | |||
if (callback) callback(); | |||
return; | |||
@@ -147,8 +147,8 @@ frappe.ui.form.Attachments = Class.extend({ | |||
if (callback) callback(); | |||
} | |||
}); | |||
}, | |||
new_attachment: function(fieldname) { | |||
} | |||
new_attachment(fieldname) { | |||
if (this.dialog) { | |||
// remove upload dialog | |||
this.dialog.$wrapper.remove(); | |||
@@ -163,15 +163,15 @@ frappe.ui.form.Attachments = Class.extend({ | |||
this.attachment_uploaded(file_doc); | |||
} | |||
}); | |||
}, | |||
get_args: function() { | |||
} | |||
get_args() { | |||
return { | |||
from_form: 1, | |||
doctype: this.frm.doctype, | |||
docname: this.frm.docname, | |||
} | |||
}, | |||
attachment_uploaded: function(attachment) { | |||
} | |||
attachment_uploaded(attachment) { | |||
this.dialog && this.dialog.hide(); | |||
this.update_attachment(attachment); | |||
this.frm.sidebar.reload_docinfo(); | |||
@@ -179,22 +179,22 @@ frappe.ui.form.Attachments = Class.extend({ | |||
if(this.fieldname) { | |||
this.frm.set_value(this.fieldname, attachment.file_url); | |||
} | |||
}, | |||
update_attachment: function(attachment) { | |||
} | |||
update_attachment(attachment) { | |||
if(attachment.name) { | |||
this.add_to_attachments(attachment); | |||
this.refresh(); | |||
} | |||
}, | |||
add_to_attachments: function (attachment) { | |||
} | |||
add_to_attachments (attachment) { | |||
var form_attachments = this.get_attachments(); | |||
for(var i in form_attachments) { | |||
// prevent duplicate | |||
if(form_attachments[i]["name"] === attachment.name) return; | |||
} | |||
form_attachments.push(attachment); | |||
}, | |||
remove_fileid: function(fileid) { | |||
} | |||
remove_fileid(fileid) { | |||
var attachments = this.get_attachments(); | |||
var new_attachments = []; | |||
$.each(attachments, function(i, attachment) { | |||
@@ -205,4 +205,4 @@ frappe.ui.form.Attachments = Class.extend({ | |||
this.frm.get_docinfo().attachments = new_attachments; | |||
this.refresh(); | |||
} | |||
}); | |||
}; |
@@ -3,15 +3,15 @@ | |||
frappe.ui.form.Share = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.Share = class Share { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.shares = this.parent.find('.shares'); | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
this.render_sidebar(); | |||
}, | |||
render_sidebar: function() { | |||
} | |||
render_sidebar() { | |||
const shared = this.shared || this.frm.get_docinfo().shared; | |||
const shared_users = shared.filter(Boolean).map(s => s.user); | |||
@@ -33,8 +33,8 @@ frappe.ui.form.Share = Class.extend({ | |||
this.shares.show(); | |||
// REDESIGN-TODO: handle "shared with everyone" | |||
this.shares.append(frappe.avatar_group(shared_users, 5, {'align': 'left', 'overlap': true})); | |||
}, | |||
show: function() { | |||
} | |||
show() { | |||
var me = this; | |||
var d = new frappe.ui.Dialog({ | |||
title: __("Share {0} with", [this.frm.doc.name]), | |||
@@ -62,8 +62,8 @@ frappe.ui.form.Share = Class.extend({ | |||
} | |||
d.show(); | |||
}, | |||
render_shared: function(shared) { | |||
} | |||
render_shared(shared) { | |||
if(shared) | |||
this.shared = shared; | |||
var d = this.dialog; | |||
@@ -88,8 +88,8 @@ frappe.ui.form.Share = Class.extend({ | |||
// if cannot share, disable sharing settings. | |||
$(d.body).find(".edit-share").prop("disabled", true); | |||
} | |||
}, | |||
make_user_input: function() { | |||
} | |||
make_user_input() { | |||
// make add-user input | |||
this.dialog.share_with = frappe.ui.form.make_control({ | |||
parent: $(this.dialog.body).find(".input-wrapper-add-share"), | |||
@@ -107,8 +107,8 @@ frappe.ui.form.Share = Class.extend({ | |||
render_input: true | |||
}); | |||
}, | |||
add_share_button: function() { | |||
} | |||
add_share_button() { | |||
var me = this, d = this.dialog; | |||
$(d.body).find(".btn-add-share").on("click", function() { | |||
var user = d.share_with.get_value(); | |||
@@ -142,8 +142,8 @@ frappe.ui.form.Share = Class.extend({ | |||
} | |||
}); | |||
}); | |||
}, | |||
set_edit_share_events: function() { | |||
} | |||
set_edit_share_events() { | |||
var me = this, d = this.dialog; | |||
$(d.body).find(".edit-share").on("click", function() { | |||
var user = $(this).parents(".shared-user:first").attr("data-user") || "", | |||
@@ -186,5 +186,5 @@ frappe.ui.form.Share = Class.extend({ | |||
} | |||
}); | |||
}); | |||
}, | |||
}); | |||
} | |||
}; |
@@ -1,8 +1,8 @@ | |||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
frappe.ui.form.States = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.form.States = class FormStates { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.state_fieldname = frappe.workflow.get_state_fieldname(this.frm.doctype); | |||
@@ -16,9 +16,9 @@ frappe.ui.form.States = Class.extend({ | |||
$(this.frm.wrapper).bind("render_complete", function() { | |||
me.refresh(); | |||
}); | |||
}, | |||
} | |||
setup_help: function() { | |||
setup_help() { | |||
var me = this; | |||
this.frm.page.add_action_item(__("Help"), function() { | |||
frappe.workflow.setup(me.frm.doctype); | |||
@@ -44,9 +44,9 @@ frappe.ui.form.States = Class.extend({ | |||
d.show(); | |||
}); | |||
}, true); | |||
}, | |||
} | |||
refresh: function() { | |||
refresh() { | |||
// hide if its not yet saved | |||
if(this.frm.doc.__islocal) { | |||
this.set_default_state(); | |||
@@ -60,9 +60,9 @@ frappe.ui.form.States = Class.extend({ | |||
// show actions from that state | |||
this.show_actions(state); | |||
} | |||
}, | |||
} | |||
show_actions: function() { | |||
show_actions() { | |||
var added = false; | |||
var me = this; | |||
@@ -107,28 +107,28 @@ frappe.ui.form.States = Class.extend({ | |||
this.setup_btn(added); | |||
}); | |||
}, | |||
} | |||
setup_btn: function(action_added) { | |||
setup_btn(action_added) { | |||
if(action_added) { | |||
this.frm.page.btn_primary.addClass("hide"); | |||
this.frm.page.btn_secondary.addClass("hide"); | |||
this.frm.toolbar.current_status = ""; | |||
this.setup_help(); | |||
} | |||
}, | |||
} | |||
set_default_state: function() { | |||
set_default_state() { | |||
var default_state = frappe.workflow.get_default_state(this.frm.doctype, this.frm.doc.docstatus); | |||
if(default_state) { | |||
this.frm.set_value(this.state_fieldname, default_state); | |||
} | |||
}, | |||
} | |||
get_state: function() { | |||
get_state() { | |||
if(!this.frm.doc[this.state_fieldname]) { | |||
this.set_default_state(); | |||
} | |||
return this.frm.doc[this.state_fieldname]; | |||
} | |||
}); | |||
}; |
@@ -1,10 +1,10 @@ | |||
frappe.ModuleEditor = Class.extend({ | |||
init: function(frm, wrapper) { | |||
frappe.ModuleEditor = class ModuleEditor { | |||
constructor(frm, wrapper) { | |||
this.wrapper = $('<div class="row module-block-list"></div>').appendTo(wrapper); | |||
this.frm = frm; | |||
this.make(); | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
var me = this; | |||
this.frm.doc.__onload.all_modules.forEach(function(m) { | |||
$(repl('<div class="col-sm-6"><div class="checkbox">\ | |||
@@ -12,15 +12,15 @@ frappe.ModuleEditor = Class.extend({ | |||
%(module)s</label></div></div>', {module: m})).appendTo(me.wrapper); | |||
}); | |||
this.bind(); | |||
}, | |||
refresh: function() { | |||
} | |||
refresh() { | |||
var me = this; | |||
this.wrapper.find(".block-module-check").prop("checked", true); | |||
$.each(this.frm.doc.block_modules, function(i, d) { | |||
me.wrapper.find(".block-module-check[data-module='"+ d.module +"']").prop("checked", false); | |||
}); | |||
}, | |||
bind: function() { | |||
} | |||
bind() { | |||
var me = this; | |||
this.wrapper.on("change", ".block-module-check", function() { | |||
var module = $(this).attr('data-module'); | |||
@@ -36,4 +36,4 @@ frappe.ModuleEditor = Class.extend({ | |||
} | |||
}); | |||
} | |||
}); | |||
}; |
@@ -1,3 +1,3 @@ | |||
import { Chart } from "frappe-charts" | |||
import { Chart } from "frappe-charts/dist/frappe-charts.esm"; | |||
frappe.Chart = Chart; |
@@ -232,6 +232,7 @@ frappe.ui.Dialog = class Dialog extends frappe.ui.FieldGroup { | |||
this.get_minimize_btn().html(frappe.utils.icon(icon)); | |||
this.on_minimize_toggle && this.on_minimize_toggle(this.is_minimized); | |||
this.header.find('.modal-title').toggleClass('cursor-pointer'); | |||
$("body").css("overflow", this.is_minimized ? "auto" : "hidden"); | |||
} | |||
add_custom_action(label, action, css_class=null) { | |||
@@ -2,11 +2,11 @@ import '../form/layout'; | |||
frappe.provide('frappe.ui'); | |||
frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
init: function(opts) { | |||
$.extend(this, opts); | |||
frappe.ui.FieldGroup = class FieldGroup extends frappe.ui.form.Layout { | |||
constructor(opts) { | |||
super(opts); | |||
this.first_button = false; | |||
this.dirty = false; | |||
this._super(); | |||
$.each(this.fields || [], function(i, f) { | |||
if(!f.fieldname && f.label) { | |||
f.fieldname = f.label.replace(/ /g, "_").toLowerCase(); | |||
@@ -15,11 +15,11 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
if(this.values) { | |||
this.set_values(this.values); | |||
} | |||
}, | |||
make: function() { | |||
} | |||
make() { | |||
var me = this; | |||
if(this.fields) { | |||
this._super(); | |||
super.make(); | |||
this.refresh(); | |||
// set default | |||
$.each(this.fields_list, function(i, field) { | |||
@@ -50,9 +50,9 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
}); | |||
} | |||
}, | |||
first_button: false, | |||
focus_on_first_input: function() { | |||
} | |||
focus_on_first_input() { | |||
if(this.no_focus) return; | |||
$.each(this.fields_list, function(i, f) { | |||
if(!in_list(['Date', 'Datetime', 'Time', 'Check'], f.df.fieldtype) && f.set_focus) { | |||
@@ -60,8 +60,8 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
return false; | |||
} | |||
}); | |||
}, | |||
catch_enter_as_submit: function() { | |||
} | |||
catch_enter_as_submit() { | |||
var me = this; | |||
$(this.body).find('input[type="text"], input[type="password"], select').keypress(function(e) { | |||
if(e.which==13) { | |||
@@ -71,15 +71,15 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
} | |||
} | |||
}); | |||
}, | |||
get_input: function(fieldname) { | |||
} | |||
get_input(fieldname) { | |||
var field = this.fields_dict[fieldname]; | |||
return $(field.txt ? field.txt : field.input); | |||
}, | |||
get_field: function(fieldname) { | |||
} | |||
get_field(fieldname) { | |||
return this.fields_dict[fieldname]; | |||
}, | |||
get_values: function(ignore_errors) { | |||
} | |||
get_values(ignore_errors) { | |||
var ret = {}; | |||
var errors = []; | |||
for (var key in this.fields_dict) { | |||
@@ -110,12 +110,12 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
return null; | |||
} | |||
return ret; | |||
}, | |||
get_value: function(key) { | |||
} | |||
get_value(key) { | |||
var f = this.fields_dict[key]; | |||
return f && (f.get_value ? f.get_value() : null); | |||
}, | |||
set_value: function(key, val){ | |||
} | |||
set_value(key, val){ | |||
return new Promise(resolve => { | |||
var f = this.fields_dict[key]; | |||
if(f) { | |||
@@ -128,11 +128,11 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
resolve(); | |||
} | |||
}); | |||
}, | |||
set_input: function(key, val) { | |||
} | |||
set_input(key, val) { | |||
return this.set_value(key, val); | |||
}, | |||
set_values: function(dict) { | |||
} | |||
set_values(dict) { | |||
let promises = []; | |||
for(var key in dict) { | |||
if(this.fields_dict[key]) { | |||
@@ -141,18 +141,18 @@ frappe.ui.FieldGroup = frappe.ui.form.Layout.extend({ | |||
} | |||
return Promise.all(promises); | |||
}, | |||
clear: function() { | |||
} | |||
clear() { | |||
for(var key in this.fields_dict) { | |||
var f = this.fields_dict[key]; | |||
if(f && f.set_input) { | |||
f.set_input(f.df['default'] || ''); | |||
} | |||
} | |||
}, | |||
set_df_property: function (fieldname, prop, value) { | |||
} | |||
set_df_property (fieldname, prop, value) { | |||
const field = this.get_field(fieldname); | |||
field.df[prop] = value; | |||
field.refresh(); | |||
} | |||
}); | |||
}; |
@@ -1,7 +1,7 @@ | |||
// <select> widget with all fields of a doctype as options | |||
frappe.ui.FieldSelect = Class.extend({ | |||
frappe.ui.FieldSelect = class FieldSelect { | |||
// opts parent, doctype, filter_fields, with_blank, select | |||
init(opts) { | |||
constructor(opts) { | |||
var me = this; | |||
$.extend(this, opts); | |||
this.fields_by_name = {}; | |||
@@ -44,22 +44,22 @@ frappe.ui.FieldSelect = Class.extend({ | |||
this.build_options(); | |||
} | |||
this.set_value(this.doctype, "name"); | |||
}, | |||
} | |||
get_value() { | |||
return this.selected_doctype ? this.selected_doctype + "." + this.selected_fieldname : null; | |||
}, | |||
} | |||
val(value) { | |||
if(value===undefined) { | |||
return this.get_value(); | |||
} else { | |||
this.set_value(value); | |||
} | |||
}, | |||
} | |||
clear() { | |||
this.selected_doctype = null; | |||
this.selected_fieldname = null; | |||
this.$input.val(""); | |||
}, | |||
} | |||
set_value(doctype, fieldname) { | |||
var me = this; | |||
this.clear(); | |||
@@ -80,7 +80,7 @@ frappe.ui.FieldSelect = Class.extend({ | |||
return false; | |||
} | |||
}); | |||
}, | |||
} | |||
build_options() { | |||
var me = this; | |||
me.table_fields = []; | |||
@@ -135,7 +135,7 @@ frappe.ui.FieldSelect = Class.extend({ | |||
}); | |||
} | |||
}); | |||
}, | |||
} | |||
add_field_option(df) { | |||
let me = this; | |||
@@ -170,5 +170,5 @@ frappe.ui.FieldSelect = Class.extend({ | |||
if(!me.fields_by_name[df.parent]) me.fields_by_name[df.parent] = {}; | |||
me.fields_by_name[df.parent][df.fieldname] = df; | |||
} | |||
}, | |||
}); | |||
} | |||
}; |
@@ -1,19 +1,19 @@ | |||
// Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors | |||
// MIT License. See license.txt | |||
frappe.ui.IconBar = Class.extend({ | |||
init: function(parent, n_groups) { | |||
frappe.ui.IconBar = class IconBar { | |||
constructor(parent, n_groups) { | |||
this.parent = parent; | |||
this.buttons = {}; | |||
this.make(n_groups); | |||
}, | |||
make: function(n_groups) { | |||
} | |||
make(n_groups) { | |||
this.$wrapper = $('<div class="iconbar-wrapper hide"></div>').appendTo(this.parent); | |||
for(var i=0; i<n_groups; i++) { | |||
this.get_group(i+1); | |||
} | |||
}, | |||
get_group: function(group) { | |||
} | |||
get_group(group) { | |||
var $ul = this.$wrapper.find(".iconbar-"+group+" ul"); | |||
if(!$ul.length) | |||
@@ -21,8 +21,8 @@ frappe.ui.IconBar = Class.extend({ | |||
.appendTo(this.$wrapper).find("ul"); | |||
return $ul; | |||
}, | |||
add_btn: function(group, icon, label, click) { | |||
} | |||
add_btn(group, icon, label, click) { | |||
var $ul = this.get_group(group); | |||
var $li = $('<li><i class="'+icon+'"></i></li>') | |||
.appendTo($ul) | |||
@@ -37,16 +37,16 @@ frappe.ui.IconBar = Class.extend({ | |||
this.$wrapper.find(".iconbar-" + group).removeClass("hide") | |||
this.show(); | |||
return $li; | |||
}, | |||
hide: function(group) { | |||
} | |||
hide(group) { | |||
if(group) { | |||
this.$wrapper.find(".iconbar-" + group).addClass("hide"); | |||
this.check_if_all_hidden(); | |||
} else { | |||
this.$wrapper.addClass("hide").trigger("hidden"); | |||
} | |||
}, | |||
show: function(group) { | |||
} | |||
show(group) { | |||
if(group) { | |||
this.$wrapper.find(".iconbar-" + group).removeClass("hide"); | |||
this.show(); | |||
@@ -54,15 +54,15 @@ frappe.ui.IconBar = Class.extend({ | |||
if(this.$wrapper.hasClass("hide")) | |||
this.$wrapper.removeClass("hide").trigger("shown"); | |||
} | |||
}, | |||
clear: function(group) { | |||
} | |||
clear(group) { | |||
var me = this; | |||
this.$wrapper.find(".iconbar-" + group).addClass("hide").find("ul").empty(); | |||
this.check_if_all_hidden(); | |||
}, | |||
check_if_all_hidden: function() { | |||
} | |||
check_if_all_hidden() { | |||
if(!this.$wrapper.find(".iconbar:visible").length) { | |||
this.hide(); | |||
} | |||
} | |||
}) | |||
}; |
@@ -26,8 +26,8 @@ frappe.ui.make_app_page = function(opts) { | |||
frappe.ui.pages = {}; | |||
frappe.ui.Page = Class.extend({ | |||
init: function(opts) { | |||
frappe.ui.Page = class Page { | |||
constructor(opts) { | |||
$.extend(this, opts); | |||
this.set_document_title = true; | |||
@@ -37,14 +37,14 @@ frappe.ui.Page = Class.extend({ | |||
this.make(); | |||
frappe.ui.pages[frappe.get_route_str()] = this; | |||
}, | |||
} | |||
make: function() { | |||
make() { | |||
this.wrapper = $(this.parent); | |||
this.add_main_section(); | |||
this.setup_scroll_handler(); | |||
this.setup_sidebar_toggle(); | |||
}, | |||
} | |||
setup_scroll_handler() { | |||
window.addEventListener('scroll', () => { | |||
@@ -54,9 +54,9 @@ frappe.ui.Page = Class.extend({ | |||
$('.page-head').removeClass('drop-shadow'); | |||
} | |||
}); | |||
}, | |||
} | |||
get_empty_state: function(title, message, primary_action) { | |||
get_empty_state(title, message, primary_action) { | |||
let $empty_state = $(`<div class="page-card-container"> | |||
<div class="page-card"> | |||
<div class="page-card-head"> | |||
@@ -71,13 +71,13 @@ frappe.ui.Page = Class.extend({ | |||
</div>`); | |||
return $empty_state; | |||
}, | |||
} | |||
load_lib: function(callback) { | |||
load_lib(callback) { | |||
frappe.require(this.required_libs, callback); | |||
}, | |||
} | |||
add_main_section: function() { | |||
add_main_section() { | |||
$(frappe.render_template("page", {})).appendTo(this.wrapper); | |||
if (this.single_column) { | |||
// nesting under col-sm-12 for consistency | |||
@@ -100,9 +100,9 @@ frappe.ui.Page = Class.extend({ | |||
} | |||
this.setup_page(); | |||
}, | |||
} | |||
setup_page: function() { | |||
setup_page() { | |||
this.$title_area = this.wrapper.find(".title-area"); | |||
this.$sub_title_area = this.wrapper.find("h6"); | |||
@@ -154,7 +154,7 @@ frappe.ui.Page = Class.extend({ | |||
frappe.ui.keys | |||
.get_shortcut_group(this.page_actions[0]) | |||
.add(action_btn, action_btn.find('.actions-btn-group-label')); | |||
}, | |||
} | |||
setup_sidebar_toggle() { | |||
let sidebar_toggle = $('.page-head').find('.sidebar-toggle-btn'); | |||
@@ -176,7 +176,7 @@ frappe.ui.Page = Class.extend({ | |||
this.update_sidebar_icon(); | |||
}); | |||
} | |||
}, | |||
} | |||
setup_overlay_sidebar() { | |||
let overlay_sidebar = this.sidebar.find('.overlay-sidebar') | |||
@@ -196,7 +196,7 @@ frappe.ui.Page = Class.extend({ | |||
.removeClass('text-muted'); | |||
}); | |||
}; | |||
}, | |||
} | |||
update_sidebar_icon() { | |||
let sidebar_toggle = $('.page-head').find('.sidebar-toggle-btn'); | |||
@@ -204,13 +204,13 @@ frappe.ui.Page = Class.extend({ | |||
let sidebar_wrapper = this.wrapper.find('.layout-side-section'); | |||
let is_sidebar_visible = $(sidebar_wrapper).is(":visible"); | |||
sidebar_toggle_icon.html(frappe.utils.icon(is_sidebar_visible ? 'sidebar-collapse' : 'sidebar-expand', 'md')); | |||
}, | |||
} | |||
set_indicator: function(label, color) { | |||
set_indicator(label, color) { | |||
this.clear_indicator().removeClass("hide").html(`<span>${label}</span>`).addClass(color); | |||
}, | |||
} | |||
add_action_icon: function(icon, click, css_class='', tooltip_label) { | |||
add_action_icon(icon, click, css_class='', tooltip_label) { | |||
const button = $(` | |||
<button class="text-muted btn btn-default ${css_class} icon-btn"> | |||
${frappe.utils.icon(icon)} | |||
@@ -223,13 +223,13 @@ frappe.ui.Page = Class.extend({ | |||
.tooltip({ delay: { "show": 600, "hide": 100 }, trigger: "hover" }); | |||
return button; | |||
}, | |||
} | |||
clear_indicator: function() { | |||
clear_indicator() { | |||
return this.indicator.removeClass().addClass("indicator-pill whitespace-nowrap hide"); | |||
}, | |||
} | |||
get_icon_label: function(icon, label) { | |||
get_icon_label(icon, label) { | |||
let icon_name = icon; | |||
let size = 'xs'; | |||
if (typeof icon === 'object') { | |||
@@ -237,9 +237,9 @@ frappe.ui.Page = Class.extend({ | |||
size = icon.size || 'xs'; | |||
} | |||
return `${icon ? frappe.utils.icon(icon_name, size) : ''} <span class="hidden-xs"> ${__(label)} </span>`; | |||
}, | |||
} | |||
set_action: function(btn, opts) { | |||
set_action(btn, opts) { | |||
let me = this; | |||
if (opts.icon) { | |||
opts.label = this.get_icon_label(opts.icon, opts.label); | |||
@@ -264,9 +264,9 @@ frappe.ui.Page = Class.extend({ | |||
frappe.ui.keys | |||
.get_shortcut_group(this) | |||
.add(btn, text_span.length ? text_span : btn); | |||
}, | |||
} | |||
set_primary_action: function(label, click, icon, working_label) { | |||
set_primary_action(label, click, icon, working_label) { | |||
this.set_action(this.btn_primary, { | |||
label: label, | |||
click: click, | |||
@@ -275,9 +275,9 @@ frappe.ui.Page = Class.extend({ | |||
}); | |||
return this.btn_primary; | |||
}, | |||
} | |||
set_secondary_action: function(label, click, icon, working_label) { | |||
set_secondary_action(label, click, icon, working_label) { | |||
this.set_action(this.btn_secondary, { | |||
label: label, | |||
click: click, | |||
@@ -286,37 +286,37 @@ frappe.ui.Page = Class.extend({ | |||
}); | |||
return this.btn_secondary; | |||
}, | |||
} | |||
clear_action_of: function(btn) { | |||
clear_action_of(btn) { | |||
btn.addClass("hide").unbind("click").removeAttr("data-working-label"); | |||
}, | |||
} | |||
clear_primary_action: function() { | |||
clear_primary_action() { | |||
this.clear_action_of(this.btn_primary); | |||
}, | |||
} | |||
clear_secondary_action: function() { | |||
clear_secondary_action() { | |||
this.clear_action_of(this.btn_secondary); | |||
}, | |||
} | |||
clear_actions: function() { | |||
clear_actions() { | |||
this.clear_primary_action(); | |||
this.clear_secondary_action(); | |||
}, | |||
} | |||
clear_custom_actions() { | |||
this.custom_actions.addClass("hide").empty(); | |||
}, | |||
} | |||
clear_icons: function() { | |||
clear_icons() { | |||
this.icon_group.addClass("hide").empty(); | |||
}, | |||
} | |||
//--- Menu --// | |||
add_menu_item: function(label, click, standard, shortcut) { | |||
add_menu_item(label, click, standard, shortcut) { | |||
return this.add_dropdown_item({ | |||
label, | |||
click, | |||
@@ -324,9 +324,9 @@ frappe.ui.Page = Class.extend({ | |||
parent: this.menu, | |||
shortcut | |||
}); | |||
}, | |||
} | |||
add_custom_menu_item: function(parent, label, click, standard, shortcut, icon=null) { | |||
add_custom_menu_item(parent, label, click, standard, shortcut, icon=null) { | |||
return this.add_dropdown_item({ | |||
label, | |||
click, | |||
@@ -335,49 +335,49 @@ frappe.ui.Page = Class.extend({ | |||
shortcut, | |||
icon | |||
}); | |||
}, | |||
} | |||
clear_menu: function() { | |||
clear_menu() { | |||
this.clear_btn_group(this.menu); | |||
}, | |||
} | |||
show_menu: function() { | |||
show_menu() { | |||
this.menu_btn_group.removeClass("hide"); | |||
}, | |||
} | |||
hide_menu: function() { | |||
hide_menu() { | |||
this.menu_btn_group.addClass("hide"); | |||
}, | |||
} | |||
show_icon_group: function() { | |||
show_icon_group() { | |||
this.icon_group.removeClass("hide"); | |||
}, | |||
} | |||
hide_icon_group: function() { | |||
hide_icon_group() { | |||
this.icon_group.addClass("hide"); | |||
}, | |||
} | |||
//--- Actions Menu--// | |||
show_actions_menu: function() { | |||
show_actions_menu() { | |||
this.actions_btn_group.removeClass("hide"); | |||
}, | |||
} | |||
hide_actions_menu: function() { | |||
hide_actions_menu() { | |||
this.actions_btn_group.addClass("hide"); | |||
}, | |||
} | |||
add_action_item: function(label, click, standard) { | |||
add_action_item(label, click, standard) { | |||
return this.add_dropdown_item({ | |||
label, | |||
click, | |||
standard, | |||
parent: this.actions | |||
}); | |||
}, | |||
} | |||
add_actions_menu_item: function(label, click, standard) { | |||
add_actions_menu_item(label, click, standard) { | |||
return this.add_dropdown_item({ | |||
label, | |||
click, | |||
@@ -385,11 +385,11 @@ frappe.ui.Page = Class.extend({ | |||
parent: this.actions, | |||
show_parent: false | |||
}); | |||
}, | |||
} | |||
clear_actions_menu: function() { | |||
clear_actions_menu() { | |||
this.clear_btn_group(this.actions); | |||
}, | |||
} | |||
//-- Generic --// | |||
@@ -404,7 +404,7 @@ frappe.ui.Page = Class.extend({ | |||
* @param {string} shortcut - Keyboard shortcut associated with the element | |||
* @param {Boolean} show_parent - Whether to show the dropdown button if dropdown item is added | |||
*/ | |||
add_dropdown_item: function({label, click, standard, parent, shortcut, show_parent=true, icon=null}) { | |||
add_dropdown_item({label, click, standard, parent, shortcut, show_parent=true, icon=null}) { | |||
if (show_parent) { | |||
parent.parent().removeClass("hide"); | |||
} | |||
@@ -460,7 +460,7 @@ frappe.ui.Page = Class.extend({ | |||
.add($link, $link.find('.menu-item-label')); | |||
return $link; | |||
}, | |||
} | |||
prepare_shortcut_obj(shortcut, click, label) { | |||
let shortcut_obj; | |||
@@ -489,7 +489,7 @@ frappe.ui.Page = Class.extend({ | |||
// page | |||
shortcut_obj.page = this; | |||
return shortcut_obj; | |||
}, | |||
} | |||
/* | |||
* Check if there already exists a button with a specified label in a specified button group | |||
@@ -497,7 +497,7 @@ frappe.ui.Page = Class.extend({ | |||
* @param {string} selector - CSS Selector of the button to be searched for. By default, it is `li`. | |||
* @param {string} label - Label of the button | |||
*/ | |||
is_in_group_button_dropdown: function(parent, selector, label) { | |||
is_in_group_button_dropdown(parent, selector, label) { | |||
if (!selector) selector = 'li'; | |||
@@ -509,18 +509,18 @@ frappe.ui.Page = Class.extend({ | |||
return $(item).attr('data-label') === label; | |||
}); | |||
return result.length > 0; | |||
}, | |||
} | |||
clear_btn_group: function(parent) { | |||
clear_btn_group(parent) { | |||
parent.empty(); | |||
parent.parent().addClass("hide"); | |||
}, | |||
} | |||
add_divider: function() { | |||
add_divider() { | |||
return $('<li class="dropdown-divider"></li>').appendTo(this.menu); | |||
}, | |||
} | |||
get_or_add_inner_group_button: function(label) { | |||
get_or_add_inner_group_button(label) { | |||
var $group = this.inner_toolbar.find(`.inner-group-button[data-label="${encodeURIComponent(label)}"]`); | |||
if (!$group.length) { | |||
$group = $( | |||
@@ -534,17 +534,17 @@ frappe.ui.Page = Class.extend({ | |||
).appendTo(this.inner_toolbar); | |||
} | |||
return $group; | |||
}, | |||
} | |||
get_inner_group_button: function(label) { | |||
get_inner_group_button(label) { | |||
return this.inner_toolbar.find(`.inner-group-button[data-label="${encodeURIComponent(label)}"]`); | |||
}, | |||
} | |||
set_inner_btn_group_as_primary: function(label) { | |||
set_inner_btn_group_as_primary(label) { | |||
this.get_or_add_inner_group_button(label).find("button").removeClass("btn-default").addClass("btn-primary"); | |||
}, | |||
} | |||
btn_disable_enable: function(btn, response) { | |||
btn_disable_enable(btn, response) { | |||
if (response && response.then) { | |||
btn.prop('disabled', true); | |||
response.then(() => { | |||
@@ -556,7 +556,7 @@ frappe.ui.Page = Class.extend({ | |||
btn.prop('disabled', false); | |||
}); | |||
} | |||
}, | |||
} | |||
/* | |||
* Add button to button group. If there exists another button with the same label, | |||
@@ -567,7 +567,7 @@ frappe.ui.Page = Class.extend({ | |||
* @param {object} action - function to be called when button is clicked | |||
* @param {string} group - Label of the group button | |||
*/ | |||
add_inner_button: function(label, action, group, type="default") { | |||
add_inner_button(label, action, group, type="default") { | |||
var me = this; | |||
let _action = function() { | |||
let btn = $(this); | |||
@@ -595,9 +595,9 @@ frappe.ui.Page = Class.extend({ | |||
} | |||
return button; | |||
} | |||
}, | |||
} | |||
remove_inner_button: function(label, group) { | |||
remove_inner_button(label, group) { | |||
if (typeof label === 'string') { | |||
label = [label]; | |||
} | |||
@@ -613,23 +613,23 @@ frappe.ui.Page = Class.extend({ | |||
} else { | |||
this.inner_toolbar.find(`button[data-label="${encodeURIComponent(label)}"]`).remove(); | |||
} | |||
}, | |||
} | |||
add_inner_message: function(message) { | |||
add_inner_message(message) { | |||
let $message = $(`<span class='inner-page-message text-muted small'>${message}</div>`); | |||
this.inner_toolbar.find('.inner-page-message').remove(); | |||
this.inner_toolbar.removeClass("hide").prepend($message); | |||
return $message; | |||
}, | |||
} | |||
clear_inner_toolbar: function() { | |||
clear_inner_toolbar() { | |||
this.inner_toolbar.empty().addClass("hide"); | |||
}, | |||
} | |||
//-- Sidebar --// | |||
add_sidebar_item: function(label, action, insert_after, prepend) { | |||
add_sidebar_item(label, action, insert_after, prepend) { | |||
var parent = this.sidebar.find(".sidebar-menu.standard-actions"); | |||
var li = $('<li>'); | |||
var link = $('<a>').html(label).on("click", action).appendTo(li); | |||
@@ -644,20 +644,20 @@ frappe.ui.Page = Class.extend({ | |||
} | |||
} | |||
return link; | |||
}, | |||
} | |||
//---// | |||
clear_user_actions: function() { | |||
clear_user_actions() { | |||
this.menu.find(".user-action").remove(); | |||
}, | |||
} | |||
// page::title | |||
get_title_area: function() { | |||
get_title_area() { | |||
return this.$title_area; | |||
}, | |||
} | |||
set_title: function(title, icon=null, strip=true, tab_title="") { | |||
set_title(title, icon=null, strip=true, tab_title="") { | |||
if (!title) title = ""; | |||
if (strip) { | |||
title = strip_html(title); | |||
@@ -670,24 +670,24 @@ frappe.ui.Page = Class.extend({ | |||
let title_wrapper = this.$title_area.find(".title-text"); | |||
title_wrapper.html(title); | |||
title_wrapper.attr('title', this.title); | |||
}, | |||
} | |||
set_title_sub: function(txt) { | |||
set_title_sub(txt) { | |||
// strip icon | |||
this.$sub_title_area.html(txt).toggleClass("hide", !!!txt); | |||
}, | |||
} | |||
get_main_icon: function(icon) { | |||
get_main_icon(icon) { | |||
return this.$title_area.find(".title-icon") | |||
.html('<i class="'+icon+' fa-fw"></i> ') | |||
.toggle(true); | |||
}, | |||
} | |||
add_help_button: function(txt) { | |||
add_help_button(txt) { | |||
// | |||
}, | |||
} | |||
add_button: function(label, click, opts) { | |||
add_button(label, click, opts) { | |||
if (!opts) opts = {}; | |||
let button = $(`<button | |||
class="btn ${opts.btn_class || 'btn-default'} ${opts.btn_size || 'btn-sm'} ellipsis"> | |||
@@ -699,9 +699,9 @@ frappe.ui.Page = Class.extend({ | |||
this.custom_actions.removeClass('hide'); | |||
return button; | |||
}, | |||
} | |||
add_custom_button_group: function(label, icon, parent) { | |||
add_custom_button_group(label, icon, parent) { | |||
let dropdown_label = `<span class="hidden-xs"> | |||
<span class="custom-btn-group-label">${__(label)}</span> | |||
${frappe.utils.icon('select', 'xs')} | |||
@@ -731,40 +731,40 @@ frappe.ui.Page = Class.extend({ | |||
parent.removeClass('hide').append(custom_btn_group); | |||
return custom_btn_group.find('.dropdown-menu'); | |||
}, | |||
} | |||
add_dropdown_button: function(parent, label, click, icon) { | |||
add_dropdown_button(parent, label, click, icon) { | |||
frappe.ui.toolbar.add_dropdown_button(parent, label, click, icon); | |||
}, | |||
} | |||
// page::form | |||
add_label: function(label) { | |||
add_label(label) { | |||
this.show_form(); | |||
return $("<label class='col-md-1 page-only-label'>"+label+" </label>") | |||
.appendTo(this.page_form); | |||
}, | |||
add_select: function(label, options) { | |||
} | |||
add_select(label, options) { | |||
var field = this.add_field({label:label, fieldtype:"Select"}); | |||
return field.$wrapper.find("select").empty().add_options(options); | |||
}, | |||
add_data: function(label) { | |||
} | |||
add_data(label) { | |||
var field = this.add_field({label: label, fieldtype: "Data"}); | |||
return field.$wrapper.find("input").attr("placeholder", label); | |||
}, | |||
add_date: function(label, date) { | |||
} | |||
add_date(label, date) { | |||
var field = this.add_field({label: label, fieldtype: "Date", "default": date}); | |||
return field.$wrapper.find("input").attr("placeholder", label); | |||
}, | |||
add_check: function(label) { | |||
} | |||
add_check(label) { | |||
return $("<div class='checkbox'><label><input type='checkbox'>" + label + "</label></div>") | |||
.appendTo(this.page_form) | |||
.find("input"); | |||
}, | |||
add_break: function() { | |||
} | |||
add_break() { | |||
// add further fields in the next line | |||
this.page_form.append('<div class="clearfix invisible-xs"></div>'); | |||
}, | |||
add_field: function(df, parent) { | |||
} | |||
add_field(df, parent) { | |||
this.show_form(); | |||
if (!df.placeholder) { | |||
@@ -810,24 +810,24 @@ frappe.ui.Page = Class.extend({ | |||
f.set_input(df["default"]) | |||
this.fields_dict[df.fieldname || df.label] = f; | |||
return f; | |||
}, | |||
clear_fields: function() { | |||
} | |||
clear_fields() { | |||
this.page_form.empty(); | |||
}, | |||
show_form: function() { | |||
} | |||
show_form() { | |||
this.page_form.removeClass("hide"); | |||
}, | |||
hide_form: function() { | |||
} | |||
hide_form() { | |||
this.page_form.addClass("hide"); | |||
}, | |||
get_form_values: function() { | |||
} | |||
get_form_values() { | |||
var values = {}; | |||
this.page_form.fields_dict.forEach(function(field, key) { | |||
values[key] = field.get_value(); | |||
}); | |||
return values; | |||
}, | |||
add_view: function(name, html) { | |||
} | |||
add_view(name, html) { | |||
let element = html; | |||
if(typeof (html) === "string") { | |||
element = $(html); | |||
@@ -839,8 +839,8 @@ frappe.ui.Page = Class.extend({ | |||
this.views[name].toggle(false); | |||
} | |||
return this.views[name]; | |||
}, | |||
set_view: function(name) { | |||
} | |||
set_view(name) { | |||
if(this.current_view_name===name) | |||
return; | |||
this.current_view && this.current_view.toggle(false); | |||
@@ -852,5 +852,5 @@ frappe.ui.Page = Class.extend({ | |||
this.views[name].toggle(true); | |||
this.wrapper.trigger('view-change'); | |||
}, | |||
}); | |||
} | |||
}; |