Merge branch 'wsgi' of github.com:webnotes/wnframework into wsgi
This commit is contained in:
commit
e7fda4c4a4
38 changed files with 709 additions and 787 deletions
|
|
@ -1,10 +0,0 @@
|
|||
cur_frm.cscript.refresh = function(doc, dt, dn) {
|
||||
if (doc.script_type == 'Server' && user!="Administrator") {
|
||||
cur_frm.set_df_property('script', 'read_only', 1);
|
||||
cur_frm.set_df_property('dt', 'read_only', 1);
|
||||
}
|
||||
|
||||
if(user=="Administrator") {
|
||||
cur_frm.set_df_property('script_type', 'read_only', 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -61,8 +61,8 @@ class CustomDocType(DocType):
|
|||
f.write(custom_script)
|
||||
|
||||
def get_custom_server_script_path(doctype, plugin=None):
|
||||
from webnotes.modules import scrub
|
||||
from webnotes.utils import get_site_base_path, get_site_path
|
||||
from webnotes.modules import scrub, get_plugin_path
|
||||
from webnotes.utils import get_site_base_path
|
||||
import os
|
||||
|
||||
# check if doctype exists
|
||||
|
|
@ -75,7 +75,7 @@ def get_custom_server_script_path(doctype, plugin=None):
|
|||
plugin = doctype_plugin or os.path.basename(get_site_base_path())
|
||||
|
||||
# site_abs_path/plugin_name/module_name/doctype/doctype_name/doctype_name.py
|
||||
path = get_site_path(webnotes.conf.get("plugins_path"), scrub(plugin),
|
||||
scrub(module), "doctype", scrub(doctype), scrub(doctype) + ".py")
|
||||
path = os.path.join(get_plugin_path(scrub(plugin)), scrub(module),
|
||||
"doctype", scrub(doctype), scrub(doctype) + ".py")
|
||||
|
||||
return path
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"creation": "2013-01-10 16:34:01",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-10-14 15:50:29",
|
||||
"modified": "2013-10-16 16:56:41",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
|
|
@ -23,14 +23,18 @@
|
|||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"name": "__common__",
|
||||
"parent": "Custom Script",
|
||||
"parentfield": "permissions",
|
||||
"parenttype": "DocType",
|
||||
"permlevel": 0,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"submit": 0
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"doctype": "DocType",
|
||||
|
|
@ -50,6 +54,7 @@
|
|||
"doctype": "DocField",
|
||||
"fieldname": "script_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"label": "Script Type",
|
||||
"oldfieldname": "script_type",
|
||||
"oldfieldtype": "Select",
|
||||
|
|
@ -66,19 +71,11 @@
|
|||
"options": "Script"
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"permlevel": 0,
|
||||
"role": "System Manager",
|
||||
"write": 1
|
||||
"role": "System Manager"
|
||||
},
|
||||
{
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"doctype": "DocPerm",
|
||||
"permlevel": 0,
|
||||
"role": "Administrator",
|
||||
"write": 1
|
||||
"role": "Administrator"
|
||||
}
|
||||
]
|
||||
|
|
@ -15,6 +15,9 @@ class DocType():
|
|||
def __init__(self, d, dl):
|
||||
self.doc, self.doclist = d, dl
|
||||
|
||||
def before_insert(self):
|
||||
webnotes.local.rollback_observers.append(self)
|
||||
|
||||
def on_update(self):
|
||||
# check duplicate assignement
|
||||
n_records = webnotes.conn.sql("""select count(*) from `tabFile Data`
|
||||
|
|
@ -27,12 +30,6 @@ class DocType():
|
|||
raise webnotes.DuplicateEntryError
|
||||
|
||||
def on_trash(self):
|
||||
if self.doc.file_name and webnotes.conn.sql("""select count(*) from `tabFile Data`
|
||||
where file_name=%s""", self.doc.file_name)[0][0]==1:
|
||||
path = webnotes.utils.get_site_path(conf.files_path, self.doc.file_name)
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
|
||||
if self.doc.attached_to_name:
|
||||
# check persmission
|
||||
try:
|
||||
|
|
@ -41,4 +38,14 @@ class DocType():
|
|||
webnotes.msgprint(webnotes._("No permission to write / remove."),
|
||||
raise_exception=True)
|
||||
except webnotes.DoesNotExistError:
|
||||
pass
|
||||
pass
|
||||
|
||||
# if file not attached to any other record, delete it
|
||||
if self.doc.file_name and webnotes.conn.sql("""select count(*) from `tabFile Data`
|
||||
where file_name=%s and name!=%s""", (self.doc.file_name, self.doc.name)):
|
||||
path = webnotes.utils.get_site_path(conf.files_path, self.doc.file_name)
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
|
||||
def on_rollback(self):
|
||||
self.on_trash()
|
||||
|
|
@ -28,7 +28,6 @@ class DocType:
|
|||
self.add_system_manager_role()
|
||||
self.check_enable_disable()
|
||||
if self.in_insert:
|
||||
self.autoname()
|
||||
if self.doc.name not in ("Guest", "Administrator"):
|
||||
self.send_welcome_mail()
|
||||
webnotes.msgprint(_("Welcome Email Sent"))
|
||||
|
|
@ -392,3 +391,22 @@ def profile_query(doctype, txt, searchfield, start, page_len, filters):
|
|||
name asc
|
||||
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
|
||||
'mcond':get_match_cond(doctype, searchfield), 'start': start, 'page_len': page_len})
|
||||
|
||||
def get_total_users():
|
||||
total_users = webnotes.conn.sql("""select count(*) from `tabProfile`
|
||||
where ifnull(enabled, 0) = 1
|
||||
and docstatus < 2
|
||||
and name not in ('Administrator', 'Guest')""")
|
||||
if total_users:
|
||||
return total_users[0][0]
|
||||
return 0
|
||||
|
||||
def get_active_users():
|
||||
active_users = webnotes.conn.sql("""select count(*) from `tabProfile`
|
||||
where ifnull(enabled, 0) = 1
|
||||
and docstatus < 2
|
||||
and name not in ('Administrator', 'Guest')
|
||||
and hour(timediff(now(), last_login)) < 72""")
|
||||
if active_users:
|
||||
return active_users[0][0]
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -13,10 +13,18 @@
|
|||
"lib/public/js/lib/bootstrap.min.js",
|
||||
"lib/public/js/wn/misc/number_format.js",
|
||||
"lib/public/js/lib/nprogress.js",
|
||||
"lib/public/js/wn/class.js",
|
||||
"lib/website/js/website.js"
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"public/js/editor.min.js": [
|
||||
"lib/public/js/lib/jquery/jquery.hotkeys.js",
|
||||
"lib/public/js/wn/class.js",
|
||||
"lib/public/js/lib/beautify-html.js",
|
||||
"lib/public/js/wn/ui/editor.js",
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
"public/css/all-app.css": [
|
||||
|
|
@ -43,6 +51,7 @@
|
|||
"lib/public/js/lib/center_image.js",
|
||||
"lib/public/js/lib/bootstrap.min.js",
|
||||
"lib/public/js/lib/nprogress.js",
|
||||
"lib/public/js/lib/beautify-html.js",
|
||||
|
||||
"lib/public/js/wn/provide.js",
|
||||
"lib/public/js/wn/class.js",
|
||||
|
|
@ -115,6 +124,7 @@
|
|||
"lib/public/js/wn/ui/toolbar/recent.js",
|
||||
"lib/public/js/wn/ui/toolbar/bookmarks.js",
|
||||
"lib/public/js/wn/ui/toolbar/toolbar.js",
|
||||
"lib/public/js/wn/ui/editor.js",
|
||||
|
||||
"lib/public/js/legacy/form.js",
|
||||
"lib/public/js/legacy/print_format.js",
|
||||
|
|
|
|||
|
|
@ -395,26 +395,11 @@ div#freeze {
|
|||
font-size: 32px;
|
||||
color: #888;
|
||||
}
|
||||
/* form */
|
||||
|
||||
.wysiwyg-editor {
|
||||
height: 400px;
|
||||
background-color: white;
|
||||
border-collapse: separate;
|
||||
border: 1px solid rgb(204, 204, 204);
|
||||
padding: 4px;
|
||||
box-sizing: content-box;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset;
|
||||
box-shadow: rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset;
|
||||
border-top-right-radius: 3px; border-bottom-right-radius: 3px;
|
||||
border-bottom-left-radius: 3px; border-top-left-radius: 3px;
|
||||
overflow: scroll;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.wysiwyg-editor img {
|
||||
.wn-editor img {
|
||||
max-width: 100%;
|
||||
}
|
||||
/* form */
|
||||
|
||||
textarea[data-fieldtype="Small Text"] {
|
||||
height: 60px;
|
||||
|
|
|
|||
193
public/js/lib/bootstrap-wysiwyg.js
vendored
193
public/js/lib/bootstrap-wysiwyg.js
vendored
|
|
@ -1,193 +0,0 @@
|
|||
/* http://github.com/mindmup/bootstrap-wysiwyg */
|
||||
/*global jQuery, $, FileReader*/
|
||||
/*jslint browser:true*/
|
||||
jQuery(function ($) {
|
||||
'use strict';
|
||||
var readFileIntoDataUrl = function (fileInfo) {
|
||||
var loader = $.Deferred(),
|
||||
fReader = new FileReader();
|
||||
|
||||
wn.upload.upload_file(fileInfo, {
|
||||
from_form: 1,
|
||||
doctype: cur_frm.doctype,
|
||||
docname: cur_frm.docname
|
||||
}, function(fileid, filename, r) {
|
||||
if(!r.exc) {
|
||||
if(fileid)
|
||||
cur_frm.attachments.update_attachment(fileid, filename);
|
||||
loader.resolve(filename);
|
||||
}
|
||||
});
|
||||
return loader.promise();
|
||||
};
|
||||
$.fn.cleanHtml = function () {
|
||||
var html = $(this).html();
|
||||
html = html && html.replace(/(<br>|\s|<div><br><\/div>| )*$/, '');
|
||||
|
||||
// remove custom typography (use CSS!)
|
||||
html = html && html.replace(/(font-family|font-size|line-height):[^;]*;/g, '');
|
||||
html = html && html.replace(/<[^>]*(font=['"][^'"]*['"])>/g, function(a,b) { return a.replace(b, ''); });
|
||||
html = html && html.replace(/\s*style\s*=\s*["']\s*["']/g, '');
|
||||
return html;
|
||||
};
|
||||
$.fn.wysiwyg = function (userOptions) {
|
||||
var editor = this,
|
||||
selectedRange,
|
||||
defaultOptions = {
|
||||
hotKeys: {
|
||||
'ctrl+b meta+b': 'bold',
|
||||
'ctrl+i meta+i': 'italic',
|
||||
'ctrl+u meta+u': 'underline',
|
||||
'ctrl+z meta+z': 'undo',
|
||||
'ctrl+y meta+y meta+shift+z': 'redo',
|
||||
'ctrl+l meta+l': 'justifyleft',
|
||||
'ctrl+e meta+e': 'justifycenter',
|
||||
'ctrl+j meta+j': 'justifyfull',
|
||||
'shift+tab': 'outdent',
|
||||
'tab': 'indent'
|
||||
},
|
||||
toolbarSelector: '[data-role=editor-toolbar]',
|
||||
commandRole: 'edit',
|
||||
activeToolbarClass: 'btn-info',
|
||||
selectionMarker: 'edit-focus-marker',
|
||||
selectionColor: 'darkgrey'
|
||||
},
|
||||
options,
|
||||
updateToolbar = function () {
|
||||
if (options.activeToolbarClass) {
|
||||
$(options.toolbarSelector).find('.btn[data-' + options.commandRole + ']').each(function () {
|
||||
var command = $(this).data(options.commandRole);
|
||||
if (document.queryCommandState(command)) {
|
||||
$(this).addClass(options.activeToolbarClass);
|
||||
} else {
|
||||
$(this).removeClass(options.activeToolbarClass);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
execCommand = function (commandWithArgs, valueArg) {
|
||||
var commandArr = commandWithArgs.split(' '),
|
||||
command = commandArr.shift(),
|
||||
args = commandArr.join(' ') + (valueArg || '');
|
||||
document.execCommand(command, 0, args);
|
||||
updateToolbar();
|
||||
},
|
||||
bindHotkeys = function (hotKeys) {
|
||||
$.each(hotKeys, function (hotkey, command) {
|
||||
editor.keydown(hotkey, function (e) {
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
execCommand(command);
|
||||
}
|
||||
}).keyup(hotkey, function (e) {
|
||||
if (editor.attr('contenteditable') && editor.is(':visible')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getCurrentRange = function () {
|
||||
var sel = window.getSelection();
|
||||
if (sel.getRangeAt && sel.rangeCount) {
|
||||
return sel.getRangeAt(0);
|
||||
}
|
||||
},
|
||||
saveSelection = function () {
|
||||
selectedRange = getCurrentRange();
|
||||
},
|
||||
restoreSelection = function () {
|
||||
var selection = window.getSelection();
|
||||
if (selectedRange) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(selectedRange);
|
||||
}
|
||||
},
|
||||
insertFiles = function (files) {
|
||||
editor.focus();
|
||||
$.each(files, function (idx, fileInfo) {
|
||||
if (/^image\//.test(fileInfo.type)) {
|
||||
$.when(readFileIntoDataUrl(fileInfo)).done(function (dataUrl) {
|
||||
execCommand('insertimage', dataUrl);
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
markSelection = function (input, color) {
|
||||
restoreSelection();
|
||||
document.execCommand('hiliteColor', 0, color || 'transparent');
|
||||
saveSelection();
|
||||
input.data(options.selectionMarker, color);
|
||||
},
|
||||
bindToolbar = function (toolbar, options) {
|
||||
toolbar.find('a[data-' + options.commandRole + ']').click(function () {
|
||||
restoreSelection();
|
||||
editor.focus();
|
||||
execCommand($(this).data(options.commandRole));
|
||||
saveSelection();
|
||||
});
|
||||
toolbar.find('[data-toggle=dropdown]').click(restoreSelection);
|
||||
|
||||
toolbar.find('input[type=text][data-' + options.commandRole + ']').on('webkitspeechchange change', function () {
|
||||
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
|
||||
this.value = '';
|
||||
restoreSelection();
|
||||
if (newValue) {
|
||||
editor.focus();
|
||||
execCommand($(this).data(options.commandRole), newValue);
|
||||
}
|
||||
saveSelection();
|
||||
}).on('focus', function () {
|
||||
var input = $(this);
|
||||
if (!input.data(options.selectionMarker)) {
|
||||
markSelection(input, options.selectionColor);
|
||||
input.focus();
|
||||
}
|
||||
}).on('blur', function () {
|
||||
var input = $(this);
|
||||
if (input.data(options.selectionMarker)) {
|
||||
markSelection(input, false);
|
||||
}
|
||||
});
|
||||
toolbar.find('input[type=file][data-' + options.commandRole + ']').change(function () {
|
||||
restoreSelection();
|
||||
if (this.type === 'file' && this.files && this.files.length > 0) {
|
||||
insertFiles(this.files);
|
||||
}
|
||||
saveSelection();
|
||||
this.value = '';
|
||||
});
|
||||
},
|
||||
initFileDrops = function () {
|
||||
editor.on('dragenter dragover', false)
|
||||
.on('drop', function (e) {
|
||||
var dataTransfer = e.originalEvent.dataTransfer;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
|
||||
insertFiles(dataTransfer.files);
|
||||
}
|
||||
});
|
||||
};
|
||||
options = $.extend({}, defaultOptions, userOptions);
|
||||
bindHotkeys(options.hotKeys);
|
||||
initFileDrops();
|
||||
bindToolbar($(options.toolbarSelector), options);
|
||||
editor.attr('contenteditable', true)
|
||||
.on('mouseup keyup mouseout', function () {
|
||||
saveSelection();
|
||||
updateToolbar();
|
||||
});
|
||||
$(window).bind('touchend', function (e) {
|
||||
var isInside = (editor.is(e.target) || editor.has(e.target).length > 0),
|
||||
currentRange = getCurrentRange(),
|
||||
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
|
||||
if (!clear || isInside) {
|
||||
saveSelection();
|
||||
updateToolbar();
|
||||
}
|
||||
});
|
||||
return this;
|
||||
};
|
||||
});
|
||||
|
|
@ -64,9 +64,9 @@ To subclass, use:
|
|||
// The dummy class constructor
|
||||
function Class() {
|
||||
// All construction is actually done in the init method
|
||||
this._type = "instance";
|
||||
if ( !initializing && this.init )
|
||||
this.init.apply(this, arguments);
|
||||
this._type = "instance";
|
||||
}
|
||||
|
||||
// Populate our constructed prototype object
|
||||
|
|
|
|||
|
|
@ -105,6 +105,24 @@ wn.dom = {
|
|||
}
|
||||
}
|
||||
|
||||
wn.get_modal = function(title, body_html) {
|
||||
var modal = $('<div class="modal" style="overflow: auto;" tabindex="-1">\
|
||||
<div class="modal-dialog">\
|
||||
<div class="modal-content">\
|
||||
<div class="modal-header">\
|
||||
<a type="button" class="close"\
|
||||
data-dismiss="modal" aria-hidden="true">×</a>\
|
||||
<h4 class="modal-title">'+title+'</h4>\
|
||||
</div>\
|
||||
<div class="modal-body ui-front">'+body_html+'\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>').appendTo(document.body);
|
||||
|
||||
return modal;
|
||||
};
|
||||
|
||||
var pending_req = 0
|
||||
wn.set_loading = function() {
|
||||
pending_req++;
|
||||
|
|
|
|||
|
|
@ -853,11 +853,11 @@ wn.ui.form.ControlLink = wn.ui.form.ControlData.extend({
|
|||
});
|
||||
|
||||
wn.ui.form.ControlCode = wn.ui.form.ControlInput.extend({
|
||||
editor_name: "ACE",
|
||||
editor_name: "wn.editors.ACE",
|
||||
make_input: function() {
|
||||
$(this.input_area).css({"min-height":"360px"});
|
||||
var me = this;
|
||||
this.editor = new wn.editors[this.editor_name]({
|
||||
this.editor = new (wn.provide(this.editor_name))({
|
||||
parent: this.input_area,
|
||||
change: function(value) {
|
||||
me.parse_validate_and_set_in_model(value);
|
||||
|
|
@ -865,12 +865,6 @@ wn.ui.form.ControlCode = wn.ui.form.ControlInput.extend({
|
|||
field: this
|
||||
});
|
||||
this.has_input = true;
|
||||
|
||||
if(this.editor.$editor) {
|
||||
this.editor.$editor.keypress("ctrl+s meta+s", function() {
|
||||
me.frm.save_or_update();
|
||||
});
|
||||
}
|
||||
},
|
||||
get_value: function() {
|
||||
return this.editor.get_value();
|
||||
|
|
@ -882,7 +876,13 @@ wn.ui.form.ControlCode = wn.ui.form.ControlInput.extend({
|
|||
});
|
||||
|
||||
wn.ui.form.ControlTextEditor = wn.ui.form.ControlCode.extend({
|
||||
editor_name: "BootstrapWYSIWYG"
|
||||
editor_name: "bsEditor",
|
||||
make_input: function() {
|
||||
this._super();
|
||||
this.editor.editor.keypress("ctrl+s meta+s", function() {
|
||||
me.frm.save_or_update();
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
wn.ui.form.ControlTable = wn.ui.form.Control.extend({
|
||||
|
|
|
|||
|
|
@ -12,187 +12,6 @@
|
|||
|
||||
wn.provide("wn.editors");
|
||||
|
||||
wn.editors.BootstrapWYSIWYG = Class.extend({
|
||||
init: function(opts) {
|
||||
wn.require("lib/js/lib/bootstrap-wysiwyg.js");
|
||||
this.opts = opts;
|
||||
this.make_body();
|
||||
this.make_bindings();
|
||||
},
|
||||
make_body: function() {
|
||||
var me = this;
|
||||
this.myid = "editor-" + wn.dom.set_unique_id();
|
||||
$('<div class="for-rich-text">\
|
||||
<div class="btn-toolbar" data-role="editor-toolbar" style="margin-bottom: 7px;"\
|
||||
data-target="#'+ this.myid +'">\
|
||||
<div class="btn-group hidden-xs form-group">\
|
||||
<a class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown" title="Font"><i class="icon-font"></i><b class="caret"></b></a>\
|
||||
<ul class="dropdown-menu"></ul>\
|
||||
</div>\
|
||||
<div class="btn-group form-group">\
|
||||
<a class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown" title="Font Size"><i class="icon-text-height"></i> <b class="caret"></b></a>\
|
||||
<ul class="dropdown-menu">\
|
||||
<li><a data-edit="formatBlock <p>"><p>Paragraph</p></a></li>\
|
||||
<li><a data-edit="formatBlock <h1>"><h1>Heading 1</h1></a></li>\
|
||||
<li><a data-edit="formatBlock <h2>"><h2>Heading 2</h2></a></li>\
|
||||
<li><a data-edit="formatBlock <h3>"><h3>Heading 3</h3></a></li>\
|
||||
<li><a data-edit="formatBlock <h4>"><h4>Heading 4</h4></a></li>\
|
||||
<li><a data-edit="formatBlock <h5>"><h5>Heading 5</h5></a></li>\
|
||||
</ul>\
|
||||
</div>\
|
||||
<div class="btn-group form-group">\
|
||||
<a class="btn btn-default btn-small" data-edit="bold" title="Bold (Ctrl/Cmd+B)"><i class="icon-bold"></i></a>\
|
||||
<a class="btn btn-default btn-small" data-edit="insertunorderedlist" title="Bullet list"><i class="icon-list-ul"></i></a>\
|
||||
<a class="btn btn-default btn-small" data-edit="insertorderedlist" title="Number list"><i class="icon-list-ol"></i></a>\
|
||||
<a class="btn btn-default btn-small" data-edit="outdent" title="Reduce indent (Shift+Tab)"><i class="icon-indent-left"></i></a>\
|
||||
<a class="btn btn-default btn-small" data-edit="indent" title="Indent (Tab)"><i class="icon-indent-right"></i></a>\
|
||||
</div>\
|
||||
<div class="btn-group hidden-xs form-group">\
|
||||
<a class="btn btn-default btn-small" data-edit="justifyleft" title="Align Left (Ctrl/Cmd+L)"><i class="icon-align-left"></i></a>\
|
||||
<a class="btn btn-default btn-small" data-edit="justifycenter" title="Center (Ctrl/Cmd+E)"><i class="icon-align-center"></i></a>\
|
||||
<a class="btn btn-default btn-small btn-add-link" title="Insert Link">\
|
||||
<i class="icon-link"></i></a>\
|
||||
<a class="btn btn-default btn-small" title="Remove Link" data-edit="unlink">\
|
||||
<i class="icon-unlink"></i></a>\
|
||||
<a class="btn btn-default btn-small" title="Insert picture (or just drag & drop)" id="pictureBtn-'+this.myid+'"><i class="icon-picture"></i></a>\
|
||||
<input type="file" data-role="magic-overlay" data-target="#pictureBtn-'+this.myid+'" data-edit="insertImage" />\
|
||||
<a class="btn btn-default btn-small" data-edit="insertHorizontalRule" title="Horizontal Line Break">-</a>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div id="'+this.myid+'" class="wysiwyg-editor">\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="for-html" style="display:none">\
|
||||
<textarea class="html-editor" style="width:95%; height: 440px;\
|
||||
font-family: Monaco, Menlo, Consolas, Courier, monospace;\
|
||||
font-size: 11px;"></textarea>\
|
||||
</div>\
|
||||
<div class="btn-toolbar pull-right" style="margin-top: 7px;">\
|
||||
<div class="btn-group">\
|
||||
<a class="btn btn-default btn-small btn-info btn-rich-text" title="Rich Text" disabled="disabled"><i class="icon-reorder"></i></a>\
|
||||
<a class="btn btn-default btn-small btn-html" title="HTML"><i class="icon-wrench"></i></a>\
|
||||
</div>\
|
||||
</div><div class="clearfix"></div>').appendTo(this.opts.parent);
|
||||
this.$parent = $(this.opts.parent);
|
||||
this.$editor = $("#" + this.myid);
|
||||
this.$parent.find(".btn-add-link").click(function() {
|
||||
me.show_link_dialog();
|
||||
return false;
|
||||
})
|
||||
this.$editor.on("keyup", function() { me.save_selection() });
|
||||
this.$editor.on("mouseup", function() { me.save_selection() });
|
||||
this.$textarea = this.$parent.find(".html-editor");
|
||||
this.input = this.$editor.get(0);
|
||||
},
|
||||
set_focus: function() {
|
||||
this.$editor.focus();
|
||||
},
|
||||
save_selection: function() {
|
||||
this.saved_selection = wn.dom.save_selection();
|
||||
},
|
||||
show_link_dialog: function() {
|
||||
var me = this;
|
||||
var d = new wn.ui.Dialog({
|
||||
title: "Add Link",
|
||||
fields: [
|
||||
{fieldtype: "Data", label:"Link", fieldname: "link", reqd: 1,
|
||||
description:"example: http://example.com"},
|
||||
{fieldtype: "Button", label:"Add", fieldname: "add"},
|
||||
]
|
||||
});
|
||||
d.show();
|
||||
d.fields_dict.link.set_input("http://");
|
||||
$(d.fields_dict.add.input).click(function() {
|
||||
var values = d.get_values();
|
||||
if(values) {
|
||||
d.hide();
|
||||
wn.dom.restore_selection(me.saved_selection);
|
||||
document.execCommand("CreateLink", false, values.link);
|
||||
}
|
||||
});
|
||||
d.onhide = function() {
|
||||
wn.dom.restore_selection(me.saved_selection);
|
||||
}
|
||||
},
|
||||
make_bindings: function() {
|
||||
var me = this;
|
||||
var fonts = ['Serif', 'Sans', 'Arial', 'Arial Black', 'Courier',
|
||||
'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande',
|
||||
'Lucida Sans', 'Tahoma', 'Times', 'Times New Roman', 'Verdana'],
|
||||
fontTarget = this.$parent.find('[title=Font]').siblings('.dropdown-menu');
|
||||
|
||||
$.each(fonts, function (idx, fontName) {
|
||||
fontTarget.append($('<li><a data-edit="fontName ' +
|
||||
fontName +'" style="font-family:\''+ fontName +'\'">'+
|
||||
fontName + '</a></li>'));
|
||||
});
|
||||
|
||||
// magic-overlay
|
||||
this.$parent.find('[data-role=magic-overlay]').each(function () {
|
||||
var overlay = $(this), target = $(overlay.data('target'));
|
||||
overlay.css('opacity', 0).css('position', 'absolute')
|
||||
//.offset(target.offset())
|
||||
.css("left", 157) // use this because in dialogs, can't find the offset
|
||||
.width(38).height(33);
|
||||
});
|
||||
|
||||
this.$editor
|
||||
.wysiwyg()
|
||||
.on("mouseup keyup mouseout", function() {
|
||||
var value = $(this).html();
|
||||
if(value==null) value="";
|
||||
me.opts.change(value);
|
||||
})
|
||||
this.$textarea
|
||||
.on("change", function() {
|
||||
var value = $(this).val();
|
||||
if(value==null) value="";
|
||||
me.opts.change(value);
|
||||
});
|
||||
|
||||
this.current_editor = this.$editor;
|
||||
this.$parent.find(".btn-html").click(function() {
|
||||
if($(this).prop("disabled")==true) return;
|
||||
wn.require("lib/js/lib/beautify-html.js");
|
||||
me.$textarea.val(html_beautify(me.$editor.cleanHtml()));
|
||||
me.$parent.find(".for-rich-text").toggle(false);
|
||||
me.$parent.find(".for-html").toggle(true);
|
||||
me.$parent.find(".btn-html").attr("disabled", "disabled");
|
||||
me.$parent.find(".btn-rich-text").attr("disabled", false);
|
||||
me.current_editor = me.$textarea;
|
||||
});
|
||||
|
||||
this.$parent.find(".btn-rich-text").click(function() {
|
||||
if($(this).prop("disabled")==true) return;
|
||||
me.$editor.html(me.$textarea.val());
|
||||
me.$parent.find(".for-rich-text").toggle(true);
|
||||
me.$parent.find(".for-html").toggle(false);
|
||||
|
||||
me.$parent.find(".btn-rich-text").attr("disabled", "disabled");
|
||||
me.$parent.find(".btn-html").attr("disabled", false);
|
||||
me.current_editor = me.$editor;
|
||||
});
|
||||
|
||||
},
|
||||
set_input: function(value) {
|
||||
if(this.opts.field.inside_change_event)
|
||||
return;
|
||||
|
||||
if(this.value!=value) {
|
||||
this.value = value==null ? "" : value;
|
||||
this.$editor.html(this.value);
|
||||
this.$textarea.val(this.value);
|
||||
}
|
||||
},
|
||||
get_value: function() {
|
||||
if(this.current_editor==this.$editor)
|
||||
return this.$editor.cleanHtml();
|
||||
else
|
||||
return this.$textarea.val();
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
wn.editors.ACE = Class.extend({
|
||||
init: function(opts) {
|
||||
this.opts = opts;
|
||||
|
|
@ -258,7 +77,4 @@ wn.editors.ACE = Class.extend({
|
|||
});
|
||||
}
|
||||
},
|
||||
set_focus: function() {
|
||||
this.$editor.focus();
|
||||
},
|
||||
})
|
||||
|
|
@ -15,7 +15,7 @@ wn.tools.downloadify = function(data, roles, me) {
|
|||
|
||||
// save file > abt 200 kb using server call
|
||||
if((_get_data().length > 200000) || flash_disabled) {
|
||||
open_url_post("server.py?cmd=webnotes.utils.datautils.send_csv_to_client",
|
||||
open_url_post("/?cmd=webnotes.utils.datautils.send_csv_to_client",
|
||||
{args: {data: data, filename: me.title}}, true);
|
||||
} else {
|
||||
wn.require("lib/js/lib/downloadify/downloadify.min.js");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
// My HTTP Request
|
||||
|
||||
wn.provide('wn.request');
|
||||
wn.request.url = 'server.py';
|
||||
wn.request.url = '/';
|
||||
|
||||
// generic server call (call page, object)
|
||||
wn.call = function(opts) {
|
||||
|
|
|
|||
|
|
@ -28,21 +28,7 @@ wn.ui.Dialog = wn.ui.FieldGroup.extend({
|
|||
this.make();
|
||||
},
|
||||
make: function() {
|
||||
// ui-front class is used as appendTo by jquery.autocomplete
|
||||
this.$wrapper = $('<div class="modal" style="overflow: auto;">\
|
||||
<div class="modal-dialog">\
|
||||
<div class="modal-content">\
|
||||
<div class="modal-header">\
|
||||
<a type="button" class="close" \
|
||||
data-dismiss="modal" aria-hidden="true">×</a>\
|
||||
<h4 class="modal-title"></h4>\
|
||||
</div>\
|
||||
<div class="modal-body ui-front">\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>')
|
||||
.appendTo(document.body);
|
||||
this.$wrapper = wn.get_modal("", "");
|
||||
this.wrapper = this.$wrapper.find('.modal-dialog').get(0);
|
||||
this.make_head();
|
||||
this.body = this.$wrapper.find(".modal-body").get(0);
|
||||
|
|
|
|||
|
|
@ -4,52 +4,68 @@
|
|||
/* Inspired from: http://github.com/mindmup/bootstrap-wysiwyg */
|
||||
|
||||
// todo
|
||||
// html editing
|
||||
// image
|
||||
// links
|
||||
// onsave, oncancel
|
||||
// make it inline friendly
|
||||
|
||||
wn.provide("wn.ui");
|
||||
wn.ui.Editor = Class.extend({
|
||||
init: function(editor, options) {
|
||||
bsEditor = Class.extend({
|
||||
init: function(options) {
|
||||
this.options = $.extend(options || {}, this.default_options);
|
||||
if(this.options.editor) {
|
||||
this.setup_editor(this.options.editor);
|
||||
this.setup_fixed_toolbar();
|
||||
} else if(this.options.parent) {
|
||||
this.wrapper = $("<div></div>").appendTo(this.options.parent);
|
||||
this.setup_editor($("<div class='wn-editor'></div>").appendTo(this.wrapper));
|
||||
this.setup_inline_toolbar();
|
||||
this.editor.css(this.options.inline_editor_style);
|
||||
this.set_editing();
|
||||
}
|
||||
},
|
||||
setup_editor: function(editor) {
|
||||
var me = this;
|
||||
this.editor = $(editor);
|
||||
this.options = $.extend(options || {}, this.default_options);
|
||||
this.files = [];
|
||||
|
||||
this.editor.on("click", function() {
|
||||
if(!this.editing) {
|
||||
me.make();
|
||||
me.editor.attr('contenteditable', true);
|
||||
me.original_html = me.editor.html();
|
||||
wn._editor_toolbar.show();
|
||||
wn._current_editor = me.editor.focus();
|
||||
me.editing = true;
|
||||
if(!me.editing) {
|
||||
me.set_editing();
|
||||
}
|
||||
}).on("mouseup keyup mouseout", function() {
|
||||
if(me.editing) {
|
||||
wn._editor_toolbar.saveSelection();
|
||||
wn._editor_toolbar.update();
|
||||
me.toolbar.save_selection();
|
||||
me.toolbar.update();
|
||||
me.options.change && me.options.change(me.clean_html());
|
||||
}
|
||||
}).on("blur", function() {
|
||||
if(wn._editor_toolbar.clicked.parents(".wn-editor-toolbar").length)
|
||||
return;
|
||||
wn._editor_toolbar.toolbar.find("[data-action='Save']").trigger("click");
|
||||
}).data("object", this);
|
||||
|
||||
this.bind_hotkeys();
|
||||
this.init_file_drops();
|
||||
|
||||
},
|
||||
make: function() {
|
||||
if(!wn._editor_toolbar) {
|
||||
wn._editor_toolbar = new wn.ui.EditorToolbar(this.options)
|
||||
|
||||
set_editing: function() {
|
||||
this.editor.attr('contenteditable', true);
|
||||
this.original_html = this.editor.html();
|
||||
this.toolbar.show();
|
||||
this.toolbar.editor = this.editor.focus();
|
||||
this.editing = true;
|
||||
},
|
||||
|
||||
setup_fixed_toolbar: function() {
|
||||
if(!window.bs_editor_toolbar) {
|
||||
window.bs_editor_toolbar = new bsEditorToolbar(this.options)
|
||||
}
|
||||
this.toolbar = window.bs_editor_toolbar;
|
||||
},
|
||||
setup_inline_toolbar: function() {
|
||||
this.toolbar = new bsEditorToolbar(this.options, this.wrapper);
|
||||
},
|
||||
onhide: function(action) {
|
||||
this.editing = false;
|
||||
if(action==="Cancel") {
|
||||
this.editor.html(this.original_html);
|
||||
}
|
||||
this.options.oncancel && this.options.oncancel(this);
|
||||
} else {
|
||||
this.options.onsave && this.options.onsave(this);
|
||||
this.options.change && this.options.change(this.get_value());
|
||||
}
|
||||
},
|
||||
default_options: {
|
||||
hotKeys: {
|
||||
|
|
@ -64,17 +80,28 @@ wn.ui.Editor = Class.extend({
|
|||
'shift+tab': 'outdent',
|
||||
'tab': 'indent'
|
||||
},
|
||||
toolbarSelector: '[data-role=editor-toolbar]',
|
||||
commandRole: 'edit',
|
||||
activeToolbarClass: 'btn-info',
|
||||
selectionMarker: 'edit-focus-marker',
|
||||
selectionColor: 'darkgrey',
|
||||
inline_editor_style: {
|
||||
"height": "400px",
|
||||
"background-color": "white",
|
||||
"border-collapse": "separate",
|
||||
"border": "1px solid rgb(204, 204, 204)",
|
||||
"padding": "4px",
|
||||
"box-sizing": "content-box",
|
||||
"-webkit-box-shadow": "rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset",
|
||||
"box-shadow": "rgba(0, 0, 0, 0.0745098) 0px 1px 1px 0px inset",
|
||||
"border-radius": "3px",
|
||||
"overflow": "scroll",
|
||||
"outline": "none"
|
||||
},
|
||||
toolbar_selector: '[data-role=editor-toolbar]',
|
||||
command_role: 'edit',
|
||||
active_toolbar_class: 'btn-info',
|
||||
selection_marker: 'edit-focus-marker',
|
||||
selection_color: 'darkgrey',
|
||||
remove_typography: true,
|
||||
max_file_size: 1,
|
||||
},
|
||||
|
||||
show: function() {
|
||||
},
|
||||
|
||||
bind_hotkeys: function () {
|
||||
var me = this;
|
||||
$.each(this.options.hotKeys, function (hotkey, command) {
|
||||
|
|
@ -82,7 +109,7 @@ wn.ui.Editor = Class.extend({
|
|||
if (me.editor.attr('contenteditable') && me.editor.is(':visible')) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
wn._editor_toolbar.execCommand(command);
|
||||
me.toolbar.execCommand(command);
|
||||
}
|
||||
}).keyup(hotkey, function (e) {
|
||||
if (me.editor.attr('contenteditable') && me.editor.is(':visible')) {
|
||||
|
|
@ -125,7 +152,7 @@ wn.ui.Editor = Class.extend({
|
|||
$.each(files, function (i, file) {
|
||||
if (/^image\//.test(file.type)) {
|
||||
me.get_image(file, function(image_url) {
|
||||
wn._editor_toolbar.execCommand('insertimage', image_url);
|
||||
me.toolbar.execCommand('insertimage', image_url);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
|
@ -137,52 +164,73 @@ wn.ui.Editor = Class.extend({
|
|||
|
||||
freader.onload = function() {
|
||||
var dataurl = freader.result;
|
||||
me.files.push(dataurl);
|
||||
// add filename to dataurl
|
||||
var parts = dataurl.split(",");
|
||||
parts[0] += ";filename=" + fileobj.name;
|
||||
dataurl = parts[0] + ',' + parts[1];
|
||||
if(me.options.max_file_size) {
|
||||
if(dataurl.length > (me.options.max_file_size * 1024 * 1024 * 1.4)) {
|
||||
bs_get_modal("Upload Error", "Max file size (" + me.options.max_file_size + "M) exceeded.").modal("show");
|
||||
throw "file size exceeded";
|
||||
}
|
||||
}
|
||||
callback(dataurl);
|
||||
}
|
||||
freader.readAsDataURL(fileobj);
|
||||
},
|
||||
|
||||
get_value: function() {
|
||||
return this.clean_html()
|
||||
},
|
||||
|
||||
set_input: function(value) {
|
||||
if(this.options.field && this.options.field.inside_change_event)
|
||||
return;
|
||||
this.editor.html(value==null ? "" : value);
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
wn.ui.EditorToolbar = Class.extend({
|
||||
init: function(options) {
|
||||
bsEditorToolbar = Class.extend({
|
||||
init: function(options, parent) {
|
||||
this.options = options;
|
||||
this.options.toolbar_style = $.extend(this.options.toolbar_style || {}, this.style);
|
||||
this.make();
|
||||
this.toolbar = $(".wn-editor-toolbar").css(this.options.toolbar_style);
|
||||
this.overlay_image_button();
|
||||
this.inline = !!parent;
|
||||
this.options.toolbar_style = $.extend((this.inline ? this.inline_style : this.fixed_style),
|
||||
this.options.toolbar_style || {});
|
||||
this.make(parent);
|
||||
this.toolbar.css(this.options.toolbar_style);
|
||||
this.setup_image_button();
|
||||
this.bind_events();
|
||||
this.bind_touch();
|
||||
|
||||
var me = this;
|
||||
$(document).mousedown(function(e) {
|
||||
me.clicked = $(e.target);
|
||||
});
|
||||
//this.bind_touch();
|
||||
},
|
||||
style: {
|
||||
fixed_style: {
|
||||
position: "fixed",
|
||||
top: "0px",
|
||||
padding: "5px",
|
||||
width: "100%",
|
||||
height: "45px",
|
||||
"background-color": "#ddd",
|
||||
"z-index": "1001" // more than navbar
|
||||
"background-color": "black",
|
||||
display: "none"
|
||||
},
|
||||
make: function() {
|
||||
if(!$(".wn-editor-toolbar").length) {
|
||||
$('<div class="wn-editor-toolbar for-rich-text text-center">\
|
||||
inline_style: {
|
||||
padding: "5px",
|
||||
},
|
||||
make: function(parent) {
|
||||
if(!parent)
|
||||
parent = $("body");
|
||||
if(!parent.find(".wn-editor-toolbar").length) {
|
||||
this.toolbar = $('<div class="wn-editor-toolbar wn-ignore-click">\
|
||||
<div class="btn-toolbar" data-role="editor-toolbar" style="margin-bottom: 7px;">\
|
||||
<div class="btn-group form-group">\
|
||||
<a class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown" \
|
||||
title="Font Size"><i class="icon-text-height"></i> <b class="caret"></b></a>\
|
||||
<ul class="dropdown-menu">\
|
||||
<li><a data-edit="formatBlock <p>"><p>Paragraph</p></a></li>\
|
||||
<li><a data-edit="formatBlock <h1>"><h1>Heading 1</h1></a></li>\
|
||||
<li><a data-edit="formatBlock <h2>"><h2>Heading 2</h2></a></li>\
|
||||
<li><a data-edit="formatBlock <h3>"><h3>Heading 3</h3></a></li>\
|
||||
<li><a data-edit="formatBlock <h4>"><h4>Heading 4</h4></a></li>\
|
||||
<li><a data-edit="formatBlock <h5>"><h5>Heading 5</h5></a></li>\
|
||||
<ul class="dropdown-menu" role="menu">\
|
||||
<li><a href="#" data-edit="formatBlock <p>"><p>Paragraph</p></a></li>\
|
||||
<li><a href="#" data-edit="formatBlock <h1>"><h1>Heading 1</h1></a></li>\
|
||||
<li><a href="#" data-edit="formatBlock <h2>"><h2>Heading 2</h2></a></li>\
|
||||
<li><a href="#" data-edit="formatBlock <h3>"><h3>Heading 3</h3></a></li>\
|
||||
<li><a href="#" data-edit="formatBlock <h4>"><h4>Heading 4</h4></a></li>\
|
||||
<li><a href="#" data-edit="formatBlock <h5>"><h5>Heading 5</h5></a></li>\
|
||||
</ul>\
|
||||
</div>\
|
||||
<div class="btn-group form-group">\
|
||||
|
|
@ -206,118 +254,133 @@ wn.ui.EditorToolbar = Class.extend({
|
|||
<i class="icon-link"></i></a>\
|
||||
<a class="btn btn-default btn-small" title="Remove Link" data-edit="unlink">\
|
||||
<i class="icon-unlink"></i></a>\
|
||||
<a class="btn btn-default btn-small" title="Insert picture (or just drag & drop)">\
|
||||
<a class="btn btn-default btn-small btn-insert-img" title="Insert picture (or just drag & drop)">\
|
||||
<i class="icon-picture"></i></a>\
|
||||
<input type="file" data-role="magic-overlay" data-edit="insertImage" />\
|
||||
<a class="btn btn-default btn-small" data-edit="insertHorizontalRule" \
|
||||
title="Horizontal Line Break">-</a>\
|
||||
</div>\
|
||||
<div class="btn-group hidden-xs form-group">\
|
||||
<a class="btn btn-default btn-small btn-info btn-rich-text" title="Rich Text" disabled="disabled">\
|
||||
<i class="icon-reorder"></i></a>\
|
||||
<a class="btn btn-default btn-small btn-html" title="HTML">\
|
||||
<i class="icon-wrench"></i></a>\
|
||||
title="Horizontal Line Break">─</a>\
|
||||
</div>\
|
||||
<div class="btn-group form-group">\
|
||||
<a class="btn btn-default btn-small btn-primary" data-action="Save" title="Save">\
|
||||
<i class="icon-save"></i></a>\
|
||||
<a class="btn btn-default btn-small btn-html" data-action="Cancel" title="Cancel">\
|
||||
<a class="btn btn-default btn-small btn-html" title="HTML">\
|
||||
<i class="icon-code"></i></a>\
|
||||
<a class="btn btn-default btn-small btn-cancel" data-action="Cancel" title="Cancel">\
|
||||
<i class="icon-remove"></i></a>\
|
||||
<a class="btn btn-default btn-small btn-success" data-action="Save" title="Save">\
|
||||
<i class="icon-save"></i></a>\
|
||||
</div>\
|
||||
</div>').prependTo("body");
|
||||
<input type="file" data-edit="insertImage" />\
|
||||
</div>').prependTo(parent);
|
||||
|
||||
if(this.inline) {
|
||||
this.toolbar.find("[data-action]").remove();
|
||||
} else {
|
||||
this.toolbar.find(".btn-toolbar").addClass("container");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
overlay_image_button: function() {
|
||||
setup_image_button: function() {
|
||||
// magic-overlay
|
||||
this.toolbar.find('[data-role=magic-overlay]').each(function () {
|
||||
var overlay = $(this), target=overlay.prev();
|
||||
overlay.css('opacity', 0).css('position', 'absolute')
|
||||
.css("left", 155)
|
||||
.width(38).height(33);
|
||||
});
|
||||
var me = this;
|
||||
this.file_input = this.toolbar.find('input[type="file"]')
|
||||
.css({
|
||||
'opacity':0,
|
||||
'position':'absolute',
|
||||
'left':0,
|
||||
'width':0,
|
||||
'height':0
|
||||
});
|
||||
this.toolbar.find(".btn-insert-img").on("click", function() {
|
||||
me.file_input.trigger("click");
|
||||
})
|
||||
},
|
||||
|
||||
show: function() {
|
||||
$("body").animate({"padding-top": this.toolbar.outerHeight() });
|
||||
var me = this;
|
||||
this.toolbar.toggle(true);
|
||||
if(!this.inline) {
|
||||
$("body").animate({"padding-top": this.toolbar.outerHeight() }, {
|
||||
complete: function() { me.toolbar.css("z-index", 1001); }
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
hide: function(action) {
|
||||
$("body").animate({"padding-top": 0 });
|
||||
this.toolbar.toggle(false);
|
||||
wn._current_editor.attr('contenteditable', false).data("object").onhide(action);
|
||||
wn._current_editor = null;
|
||||
if(!this.editor)
|
||||
return;
|
||||
var me = this;
|
||||
this.toolbar.css("z-index", 0);
|
||||
if(!this.inline) {
|
||||
$("body").animate({"padding-top": 0 }, {complete: function() {
|
||||
me.toolbar.toggle(false);
|
||||
}});
|
||||
}
|
||||
|
||||
this.editor && this.editor.attr('contenteditable', false).data("object").onhide(action);
|
||||
this.editor = null;
|
||||
},
|
||||
|
||||
bind_events: function () {
|
||||
var me = this;
|
||||
|
||||
// standard button events
|
||||
this.toolbar.find('a[data-' + me.options.commandRole + ']').click(function () {
|
||||
me.restoreSelection();
|
||||
wn._current_editor.focus();
|
||||
me.execCommand($(this).data(me.options.commandRole));
|
||||
me.saveSelection();
|
||||
this.toolbar.find('a[data-' + me.options.command_role + ']').click(function () {
|
||||
me.restore_selection();
|
||||
me.editor.focus();
|
||||
me.execCommand($(this).data(me.options.command_role));
|
||||
me.save_selection();
|
||||
// close dropdown
|
||||
me.toolbar.find('[data-toggle=dropdown]').dropdown("hide");
|
||||
return false;
|
||||
});
|
||||
this.toolbar.find('[data-toggle=dropdown]').click(function() { me.restoreSelection() });
|
||||
this.toolbar.find('[data-toggle=dropdown]').click(function() { me.restore_selection() });
|
||||
|
||||
// link
|
||||
this.toolbar.find('input[type=text][data-' + this.options.commandRole + ']')
|
||||
.on('webkitspeechchange change', function () {
|
||||
var newValue = this.value; /* ugly but prevents fake double-calls due to selection restoration */
|
||||
this.value = '';
|
||||
me.restoreSelection();
|
||||
if (newValue) {
|
||||
wn._current_editor.focus();
|
||||
me.execCommand($(this).data(me.options.commandRole), newValue);
|
||||
this.toolbar.find(".btn-add-link").on("click", function() {
|
||||
if(!window.bs_link_editor) {
|
||||
window.bs_link_editor = new bsLinkEditor(me);
|
||||
}
|
||||
me.saveSelection();
|
||||
return false;
|
||||
}).on('focus', function () {
|
||||
var input = $(this);
|
||||
if (!input.data(me.options.selectionMarker)) {
|
||||
me.markSelection(input, me.options.selectionColor);
|
||||
input.focus();
|
||||
}
|
||||
}).on('blur', function () {
|
||||
var input = $(this);
|
||||
if (input.data(me.options.selectionMarker)) {
|
||||
me.markSelection(input, false);
|
||||
}
|
||||
});
|
||||
window.bs_link_editor.show();
|
||||
})
|
||||
|
||||
// file event
|
||||
this.toolbar.find('input[type=file][data-' + me.options.commandRole + ']').change(function () {
|
||||
me.restoreSelection();
|
||||
this.toolbar.find('input[type=file][data-' + me.options.command_role + ']').change(function () {
|
||||
me.restore_selection();
|
||||
if (this.type === 'file' && this.files && this.files.length > 0) {
|
||||
wn._current_editor.data("object").insert_files(this.files);
|
||||
me.editor.data("object").insert_files(this.files);
|
||||
}
|
||||
me.saveSelection();
|
||||
me.save_selection();
|
||||
this.value = '';
|
||||
return false;
|
||||
});
|
||||
|
||||
// cancel
|
||||
// save
|
||||
this.toolbar.find("[data-action='Save']").on("click", function() {
|
||||
me.hide("Save");
|
||||
})
|
||||
|
||||
// cancel
|
||||
this.toolbar.find("[data-action='Cancel']").on("click", function() {
|
||||
me.hide("Cancel");
|
||||
})
|
||||
|
||||
// edit html
|
||||
this.toolbar.find(".btn-html").on("click", function() {
|
||||
if(!window.bs_html_editor)
|
||||
window.bs_html_editor = new bsHTMLEditor();
|
||||
|
||||
window.bs_html_editor.show(me.editor);
|
||||
})
|
||||
},
|
||||
|
||||
update: function () {
|
||||
var me = this;
|
||||
if (this.options.activeToolbarClass) {
|
||||
$(this.options.toolbarSelector).find('.btn[data-' + this.options.commandRole + ']').each(function () {
|
||||
var command = $(this).data(me.options.commandRole);
|
||||
if (this.toolbar) {
|
||||
$(this.toolbar).find('.btn[data-' + this.options.command_role + ']').each(function () {
|
||||
var command = $(this).data(me.options.command_role);
|
||||
if (document.queryCommandState(command)) {
|
||||
$(this).addClass(me.options.activeToolbarClass);
|
||||
$(this).addClass(me.options.active_toolbar_class);
|
||||
} else {
|
||||
$(this).removeClass(me.options.activeToolbarClass);
|
||||
$(this).removeClass(me.options.active_toolbar_class);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -331,42 +394,114 @@ wn.ui.EditorToolbar = Class.extend({
|
|||
this.update();
|
||||
},
|
||||
|
||||
getCurrentRange: function () {
|
||||
get_current_range: function () {
|
||||
var sel = window.getSelection();
|
||||
if (sel.getRangeAt && sel.rangeCount) {
|
||||
return sel.getRangeAt(0);
|
||||
}
|
||||
},
|
||||
|
||||
saveSelection: function () {
|
||||
this.selectedRange = this.getCurrentRange();
|
||||
save_selection: function () {
|
||||
this.selected_range = this.get_current_range();
|
||||
},
|
||||
|
||||
restoreSelection: function () {
|
||||
|
||||
restore_selection: function () {
|
||||
var selection = window.getSelection();
|
||||
if (this.selectedRange) {
|
||||
if (this.selected_range) {
|
||||
selection.removeAllRanges();
|
||||
selection.addRange(this.selectedRange);
|
||||
selection.addRange(this.selected_range);
|
||||
}
|
||||
},
|
||||
|
||||
markSelection: function (input, color) {
|
||||
this.restoreSelection();
|
||||
mark_selection: function (input, color) {
|
||||
this.restore_selection();
|
||||
document.execCommand('hiliteColor', 0, color || 'transparent');
|
||||
this.saveSelection();
|
||||
input.data(this.options.selectionMarker, color);
|
||||
this.save_selection();
|
||||
input.data(this.options.selection_marker, color);
|
||||
},
|
||||
|
||||
bind_touch: function() {
|
||||
// bind_touch: function() {
|
||||
// var me = this;
|
||||
// $(window).bind('touchend', function (e) {
|
||||
// var isInside = (me.editor.is(e.target) || me.editor.has(e.target).length > 0),
|
||||
// current_range = me.get_current_range(),
|
||||
// clear = current_range && (current_range.startContainer === current_range.endContainer && current_range.startOffset === current_range.endOffset);
|
||||
// if (!clear || isInside) {
|
||||
// me.save_selection();
|
||||
// me.update();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
});
|
||||
|
||||
bsHTMLEditor = Class.extend({
|
||||
init: function() {
|
||||
var me = this;
|
||||
$(window).bind('touchend', function (e) {
|
||||
var isInside = (wn._current_editor.is(e.target) || wn._current_editor.has(e.target).length > 0),
|
||||
currentRange = me.getCurrentRange(),
|
||||
clear = currentRange && (currentRange.startContainer === currentRange.endContainer && currentRange.startOffset === currentRange.endOffset);
|
||||
if (!clear || isInside) {
|
||||
me.saveSelection();
|
||||
me.update();
|
||||
}
|
||||
this.modal = bs_get_modal("<i class='icon-code'></i> Edit HTML", '<textarea class="form-control" \
|
||||
style="height: 400px; width: 100%; font-family: Monaco, Courier New, Fixed; font-size: 11px">\
|
||||
</textarea><br>\
|
||||
<button class="btn btn-primary" style="margin-top: 7px;">Save</button>');
|
||||
this.modal.addClass("wn-ignore-click");
|
||||
this.modal.find(".btn-primary").on("click", function() {
|
||||
var html = me.modal.find("textarea").val();
|
||||
$.each(me.dataurls, function(key, val) {
|
||||
html = html.replace(key, val);
|
||||
})
|
||||
me.editor.html();
|
||||
me.modal.modal("hide");
|
||||
});
|
||||
}
|
||||
})
|
||||
},
|
||||
show: function(editor) {
|
||||
var me = this;
|
||||
this.editor = editor;
|
||||
this.modal.modal("show")
|
||||
var html = me.editor.html();
|
||||
// pack dataurls so that html display is faster
|
||||
this.dataurls = {}
|
||||
html = html.replace(/<img\s*src=\s*["\'](data:[^,]*),([^"\']*)["\']/g, function(full, g1, g2) {
|
||||
var key = g2.slice(0,5) + "..." + g2.slice(-5);
|
||||
me.dataurls[key] = g1 + "," + g2;
|
||||
return '<img src="'+g1 + "," + key+'"';
|
||||
})
|
||||
this.modal.find("textarea").html(html_beautify(html));
|
||||
}
|
||||
});
|
||||
|
||||
bsLinkEditor = Class.extend({
|
||||
init: function(toolbar) {
|
||||
var me = this;
|
||||
this.toolbar = toolbar;
|
||||
this.modal = bs_get_modal("<i class='icon-globe'></i> Insert Link", '<div class="form-group">\
|
||||
<input type="text" class="form-control" placeholder="http://example.com" />\
|
||||
</div>\
|
||||
<div class="checkbox" style="position: static;">\
|
||||
<label>\
|
||||
<input type="checkbox"> <span>Open Link in a new Window</span>\
|
||||
</label>\
|
||||
</div>\
|
||||
<button class="btn btn-primary" style="margin-top: 7px;">Insert</button>');
|
||||
|
||||
this.modal.addClass("wn-ignore-click");
|
||||
this.modal.find(".btn-primary").on("click", function() {
|
||||
me.toolbar.restore_selection();
|
||||
var url = me.modal.find("input[type=text]").val();
|
||||
var selection = me.toolbar.selected_range.toString();
|
||||
if(url) {
|
||||
if(me.modal.find("input[type=checkbox]:checked").length) {
|
||||
var html = "<a href='" + url + "' target='_blank'>" + selection + "</a>";
|
||||
document.execCommand("insertHTML", false, html);
|
||||
} else {
|
||||
document.execCommand("CreateLink", false, url);
|
||||
}
|
||||
}
|
||||
me.modal.modal("hide");
|
||||
return false;
|
||||
});
|
||||
},
|
||||
show: function() {
|
||||
this.modal.find("input[type=text]").val("");
|
||||
this.modal.modal("show");
|
||||
}
|
||||
});
|
||||
|
||||
bs_get_modal = wn.get_modal;
|
||||
|
|
|
|||
|
|
@ -136,7 +136,6 @@ wn.views.CommunicationComposer = Class.extend({
|
|||
make: function() {
|
||||
var me = this;
|
||||
this.dialog = new wn.ui.Dialog({
|
||||
width: 640,
|
||||
title: wn._("Add Reply") + ": " + (this.subject || ""),
|
||||
no_submit_on_enter: true,
|
||||
fields: [
|
||||
|
|
@ -166,6 +165,9 @@ wn.views.CommunicationComposer = Class.extend({
|
|||
fieldname:"select_attachments"}
|
||||
]
|
||||
});
|
||||
|
||||
this.dialog.$wrapper.find("[data-edit='outdent']").remove();
|
||||
|
||||
$(document).on("upload_complete", function(event, filename, fileurl) {
|
||||
if(me.dialog.display) {
|
||||
var wrapper = $(me.dialog.fields_dict.select_attachments.wrapper);
|
||||
|
|
|
|||
23
public/js/wn/website/editable.js
Normal file
23
public/js/wn/website/editable.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
wn.make_editable = function(editor, doctype, name, fieldname) {
|
||||
wn.require("js/editor.min.js");
|
||||
bseditor = new bsEditor({
|
||||
editor: editor,
|
||||
onsave: function(bseditor) {
|
||||
wn.call({
|
||||
type: "POST",
|
||||
method: "webnotes.client.set_value",
|
||||
args: {
|
||||
doctype: doctype,
|
||||
name: name,
|
||||
fieldname: fieldname,
|
||||
value: editor.html()
|
||||
},
|
||||
callback: function(r) {
|
||||
wn.msgprint(r.exc ? "Error" : "Saved");
|
||||
if(!r.exc)
|
||||
editor.html(r.message[0][fieldname]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
$(function() {
|
||||
$('<br><button class="editable-button btn btn-default">Edit</button>').appendTo($("footer.container"))
|
||||
$(".editable-button").click(function() {
|
||||
if(window.editable) {
|
||||
$(".web-page-content").attr("contentEditable", false).removeClass("web-page-editable");
|
||||
window.editable = false;
|
||||
$(this).html("Edit");
|
||||
var html = $(".web-page-content").html() || "";
|
||||
html = html.replace(/(font-family|font-size|line-height):[^;]*;/g, '');
|
||||
html = html.replace(/<[^>]*(font=['"][^'"]*['"])>/g, function(a,b) { return a.replace(b, ''); });
|
||||
html = html.replace(/\s*style\s*=\s*["']\s*["']/g, '');
|
||||
$(".web-page-content").html(html);
|
||||
|
||||
wn.call({
|
||||
type: "POST",
|
||||
method: "webnotes.client.set_value",
|
||||
args: {
|
||||
doctype:"Web Page",
|
||||
name: window.name,
|
||||
fieldname: "main_section",
|
||||
value: html
|
||||
},
|
||||
callback: function(r) {
|
||||
wn.msgprint(r.exc ? "Error" : "Saved");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$(".web-page-content").attr("contentEditable", true).addClass("web-page-editable").focus();
|
||||
$(this).html("Save");
|
||||
window.editable = true;
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
@ -89,6 +89,7 @@ def init(site=None):
|
|||
local.conf = get_conf(site)
|
||||
local.initialised = True
|
||||
local.flags = _dict({})
|
||||
local.rollback_observers = []
|
||||
|
||||
def destroy():
|
||||
"""closes connection and releases werkzeug local"""
|
||||
|
|
|
|||
|
|
@ -103,14 +103,17 @@ class LoginManager:
|
|||
self.post_login()
|
||||
info = webnotes.conn.get_value("Profile", self.user, ["user_type", "first_name", "last_name"], as_dict=1)
|
||||
if info.user_type=="Website User":
|
||||
webnotes._response.set_cookie("system_user", "no")
|
||||
webnotes.response["message"] = "No App"
|
||||
else:
|
||||
webnotes._response.set_cookie("system_user", "yes")
|
||||
webnotes.response['message'] = 'Logged In'
|
||||
|
||||
full_name = " ".join(filter(None, [info.first_name, info.last_name]))
|
||||
webnotes.response["full_name"] = full_name
|
||||
webnotes._response.set_cookie("full_name", full_name)
|
||||
webnotes._response.set_cookie("user_id", self.user)
|
||||
|
||||
|
||||
def post_login(self):
|
||||
self.run_trigger()
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ class Database:
|
|||
use_unicode=True, charset='utf8')
|
||||
self._conn.converter[246]=float
|
||||
self._cursor = self._conn.cursor()
|
||||
webnotes.local.rollback_observers = []
|
||||
|
||||
def use(self, db_name):
|
||||
"""
|
||||
|
|
@ -152,7 +153,7 @@ class Database:
|
|||
if self.transaction_writes and query and query.strip().split()[0].lower() in ['start', 'alter', 'drop', 'create', "begin"]:
|
||||
raise Exception, 'This statement can cause implicit commit'
|
||||
|
||||
if query and query.strip().lower()=='commit':
|
||||
if query and query.strip().lower() in ('commit', 'rollback'):
|
||||
self.transaction_writes = 0
|
||||
|
||||
if query[:6].lower() in ['update', 'insert']:
|
||||
|
|
@ -439,10 +440,14 @@ class Database:
|
|||
|
||||
def commit(self):
|
||||
self.sql("commit")
|
||||
webnotes.local.rollback_observers = []
|
||||
|
||||
def rollback(self):
|
||||
self.sql("ROLLBACK")
|
||||
self.transaction_writes = 0
|
||||
self.sql("rollback")
|
||||
for obj in webnotes.local.rollback_observers:
|
||||
if hasattr(obj, "on_rollback"):
|
||||
obj.on_rollback()
|
||||
webnotes.local.rollback_observers = []
|
||||
|
||||
def field_exists(self, dt, fn):
|
||||
return self.sql("select name from tabDocField where fieldname=%s and parent=%s", (dt, fn))
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ class Bean:
|
|||
elif isinstance(dt, dict):
|
||||
self.set_doclist([dt])
|
||||
|
||||
def load_from_db(self, dt=None, dn=None, prefix='tab'):
|
||||
def load_from_db(self, dt=None, dn=None):
|
||||
"""
|
||||
Load doclist from dt
|
||||
"""
|
||||
|
|
@ -49,7 +49,7 @@ class Bean:
|
|||
if not dt: dt = self.doc.doctype
|
||||
if not dn: dn = self.doc.name
|
||||
|
||||
doc = Document(dt, dn, prefix=prefix)
|
||||
doc = Document(dt, dn)
|
||||
|
||||
# get all children types
|
||||
tablefields = webnotes.model.meta.get_table_fields(dt)
|
||||
|
|
@ -57,7 +57,7 @@ class Bean:
|
|||
# load chilren
|
||||
doclist = webnotes.doclist([doc,])
|
||||
for t in tablefields:
|
||||
doclist += getchildren(doc.name, t[0], t[1], dt, prefix=prefix)
|
||||
doclist += getchildren(doc.name, t[0], t[1], dt)
|
||||
|
||||
self.set_doclist(doclist)
|
||||
|
||||
|
|
@ -191,6 +191,7 @@ class Bean:
|
|||
self.check_if_latest(method)
|
||||
|
||||
if method != "cancel":
|
||||
self.extract_images_from_text_editor()
|
||||
self.check_links()
|
||||
|
||||
self.update_timestamps_and_docstatus()
|
||||
|
|
@ -238,45 +239,6 @@ class Bean:
|
|||
self.make_controller()
|
||||
return getattr(self.controller, method, None)
|
||||
|
||||
def save_main(self):
|
||||
try:
|
||||
self.doc.save(check_links = False, ignore_fields = self.ignore_fields)
|
||||
except NameError, e:
|
||||
webnotes.msgprint('%s "%s" already exists' % (self.doc.doctype, self.doc.name))
|
||||
|
||||
# prompt if cancelled
|
||||
if webnotes.conn.get_value(self.doc.doctype, self.doc.name, 'docstatus')==2:
|
||||
webnotes.msgprint('[%s "%s" has been cancelled]' % (self.doc.doctype, self.doc.name))
|
||||
webnotes.errprint(webnotes.utils.getTraceback())
|
||||
raise e
|
||||
|
||||
def save_children(self):
|
||||
child_map = {}
|
||||
for d in self.doclist[1:]:
|
||||
if d.fields.get("parent") or d.fields.get("parentfield"):
|
||||
d.parent = self.doc.name # rename if reqd
|
||||
d.parenttype = self.doc.doctype
|
||||
|
||||
d.save(check_links=False, ignore_fields = self.ignore_fields)
|
||||
|
||||
child_map.setdefault(d.doctype, []).append(d.name)
|
||||
|
||||
# delete all children in database that are not in the child_map
|
||||
|
||||
# get all children types
|
||||
tablefields = webnotes.model.meta.get_table_fields(self.doc.doctype)
|
||||
|
||||
for dt in tablefields:
|
||||
if dt[0] not in self.ignore_children_type:
|
||||
cnames = child_map.get(dt[0]) or []
|
||||
if cnames:
|
||||
webnotes.conn.sql("""delete from `tab%s` where parent=%s and parenttype=%s and
|
||||
name not in (%s)""" % (dt[0], '%s', '%s', ','.join(['%s'] * len(cnames))),
|
||||
tuple([self.doc.name, self.doc.doctype] + cnames))
|
||||
else:
|
||||
webnotes.conn.sql("""delete from `tab%s` where parent=%s and parenttype=%s""" \
|
||||
% (dt[0], '%s', '%s'), (self.doc.name, self.doc.doctype))
|
||||
|
||||
def insert(self):
|
||||
self.doc.fields["__islocal"] = 1
|
||||
|
||||
|
|
@ -324,6 +286,11 @@ class Bean:
|
|||
if self.ignore_permissions or webnotes.has_permission(self.doc.doctype, perm_to_check, self.doc):
|
||||
self.to_docstatus = 0
|
||||
self.prepare_for_save("save")
|
||||
if self.doc.fields.get("__islocal"):
|
||||
# set name before validate
|
||||
self.doc.set_new_name()
|
||||
self.run_method('before_insert')
|
||||
|
||||
if not self.ignore_validate:
|
||||
self.run_method('validate')
|
||||
if not self.ignore_mandatory:
|
||||
|
|
@ -379,6 +346,45 @@ class Bean:
|
|||
self.no_permission_to(_("Update"))
|
||||
|
||||
return self
|
||||
|
||||
def save_main(self):
|
||||
try:
|
||||
self.doc.save(check_links = False, ignore_fields = self.ignore_fields)
|
||||
except NameError, e:
|
||||
webnotes.msgprint('%s "%s" already exists' % (self.doc.doctype, self.doc.name))
|
||||
|
||||
# prompt if cancelled
|
||||
if webnotes.conn.get_value(self.doc.doctype, self.doc.name, 'docstatus')==2:
|
||||
webnotes.msgprint('[%s "%s" has been cancelled]' % (self.doc.doctype, self.doc.name))
|
||||
webnotes.errprint(webnotes.utils.getTraceback())
|
||||
raise e
|
||||
|
||||
def save_children(self):
|
||||
child_map = {}
|
||||
for d in self.doclist[1:]:
|
||||
if d.fields.get("parent") or d.fields.get("parentfield"):
|
||||
d.parent = self.doc.name # rename if reqd
|
||||
d.parenttype = self.doc.doctype
|
||||
|
||||
d.save(check_links=False, ignore_fields = self.ignore_fields)
|
||||
|
||||
child_map.setdefault(d.doctype, []).append(d.name)
|
||||
|
||||
# delete all children in database that are not in the child_map
|
||||
|
||||
# get all children types
|
||||
tablefields = webnotes.model.meta.get_table_fields(self.doc.doctype)
|
||||
|
||||
for dt in tablefields:
|
||||
if dt[0] not in self.ignore_children_type:
|
||||
cnames = child_map.get(dt[0]) or []
|
||||
if cnames:
|
||||
webnotes.conn.sql("""delete from `tab%s` where parent=%s and parenttype=%s and
|
||||
name not in (%s)""" % (dt[0], '%s', '%s', ','.join(['%s'] * len(cnames))),
|
||||
tuple([self.doc.name, self.doc.doctype] + cnames))
|
||||
else:
|
||||
webnotes.conn.sql("""delete from `tab%s` where parent=%s and parenttype=%s""" \
|
||||
% (dt[0], '%s', '%s'), (self.doc.name, self.doc.doctype))
|
||||
|
||||
def delete(self):
|
||||
webnotes.delete_doc(self.doc.doctype, self.doc.name)
|
||||
|
|
@ -426,6 +432,12 @@ class Bean:
|
|||
doc.fields[df.fieldname] = flt(doc.fields.get(df.fieldname))
|
||||
|
||||
doc.docstatus = cint(doc.docstatus)
|
||||
|
||||
def extract_images_from_text_editor(self):
|
||||
from webnotes.utils.file_manager import extract_images_from_html
|
||||
if self.doc.doctype != "DocType":
|
||||
for df in self.meta.get({"doctype": "DocField", "parent": self.doc.doctype, "fieldtype":"Text Editor"}):
|
||||
extract_images_from_html(self.doc, df.fieldname)
|
||||
|
||||
def clone(source_wrapper):
|
||||
""" make a clone of a document"""
|
||||
|
|
|
|||
|
|
@ -76,8 +76,12 @@ def load_doctype_module(doctype, module, prefix=""):
|
|||
return None
|
||||
|
||||
def get_obj(dt = None, dn = None, doc=None, doclist=[], with_children = 0):
|
||||
import webnotes.model.doc
|
||||
if dt:
|
||||
import webnotes.model.doc
|
||||
if isinstance(dt, list):
|
||||
return get_server_obj(dt[0], dt)
|
||||
if isinstance(dt, webnotes.model.doc.Document):
|
||||
return get_server_obj(dt, [dt])
|
||||
if not dn:
|
||||
dn = dt
|
||||
if with_children:
|
||||
|
|
|
|||
|
|
@ -50,11 +50,12 @@ class Document:
|
|||
* `idx` : Index (sequence) of the child record
|
||||
"""
|
||||
|
||||
def __init__(self, doctype = None, name = None, fielddata = None, prefix='tab'):
|
||||
def __init__(self, doctype = None, name = None, fielddata = None):
|
||||
self._roles = []
|
||||
self._perms = []
|
||||
self._user_defaults = {}
|
||||
self._prefix = prefix
|
||||
self._new_name_set = False
|
||||
self._meta = None
|
||||
|
||||
if isinstance(doctype, dict):
|
||||
fielddata = doctype
|
||||
|
|
@ -130,7 +131,7 @@ class Document:
|
|||
self._loadsingle()
|
||||
else:
|
||||
try:
|
||||
dataset = webnotes.conn.sql('select * from `%s%s` where name="%s"' % (self._prefix, self.doctype, self.name.replace('"', '\"')))
|
||||
dataset = webnotes.conn.sql('select * from `tab%s` where name="%s"' % (self.doctype, self.name.replace('"', '\"')))
|
||||
except MySQLdb.ProgrammingError, e:
|
||||
if e.args[0]==1146:
|
||||
dataset = None
|
||||
|
|
@ -179,6 +180,46 @@ class Document:
|
|||
|
||||
def get(self, name, value=None):
|
||||
return self.fields.get(name, value)
|
||||
|
||||
def insert(self):
|
||||
self.fields['__islocal'] = 1
|
||||
self.save()
|
||||
return self
|
||||
|
||||
def save(self, new=0, check_links=1, ignore_fields=0, make_autoname=1,
|
||||
keep_timestamps=False):
|
||||
|
||||
self.get_meta()
|
||||
|
||||
if new:
|
||||
self.fields["__islocal"] = 1
|
||||
|
||||
# add missing parentinfo (if reqd)
|
||||
if self.parent and not (self.parenttype and self.parentfield):
|
||||
self.update_parentinfo()
|
||||
|
||||
if self.parent and not self.idx:
|
||||
self.set_idx()
|
||||
|
||||
# if required, make new
|
||||
if not self._meta.issingle:
|
||||
if self.fields.get('__islocal'):
|
||||
r = self._insert(make_autoname=make_autoname, keep_timestamps = keep_timestamps)
|
||||
if r:
|
||||
return r
|
||||
else:
|
||||
if not webnotes.conn.exists(self.doctype, self.name):
|
||||
print self.fields
|
||||
webnotes.msgprint(webnotes._("Cannot update a non-exiting record, try inserting.") + ": " + self.doctype + " / " + self.name,
|
||||
raise_exception=1)
|
||||
|
||||
|
||||
# save the values
|
||||
self._update_values(self._meta.issingle,
|
||||
check_links and self.make_link_list() or {}, ignore_fields=ignore_fields,
|
||||
keep_timestamps=keep_timestamps)
|
||||
self._clear_temp_fields()
|
||||
|
||||
|
||||
def _get_amended_name(self):
|
||||
am_id = 1
|
||||
|
|
@ -189,23 +230,35 @@ class Document:
|
|||
|
||||
self.name = am_prefix + '-' + str(am_id)
|
||||
|
||||
def _set_name(self, autoname, istable):
|
||||
def set_new_name(self, controller=None):
|
||||
if self._new_name_set:
|
||||
# already set by bean
|
||||
return
|
||||
|
||||
self._new_name_set = True
|
||||
|
||||
self.get_meta()
|
||||
autoname = self._meta.autoname
|
||||
|
||||
|
||||
self.localname = self.name
|
||||
|
||||
# get my object
|
||||
import webnotes.model.code
|
||||
so = webnotes.model.code.get_server_obj(self, [])
|
||||
|
||||
# amendments
|
||||
if self.amended_from:
|
||||
self._get_amended_name()
|
||||
|
||||
# by method
|
||||
elif so and hasattr(so, 'autoname'):
|
||||
r = webnotes.model.code.run_server_obj(so, 'autoname')
|
||||
if r: return r
|
||||
else:
|
||||
# get my object
|
||||
if not controller:
|
||||
controller = webnotes.get_obj([self])
|
||||
|
||||
if hasattr(controller, 'autoname'):
|
||||
return controller.autoname()
|
||||
|
||||
# based on a field
|
||||
elif autoname and autoname.startswith('field:'):
|
||||
if autoname and autoname.startswith('field:'):
|
||||
n = self.fields[autoname[6:]]
|
||||
if not n:
|
||||
raise Exception, 'Name is required'
|
||||
|
|
@ -231,13 +284,13 @@ class Document:
|
|||
self.name = self.fields['__newname']
|
||||
|
||||
# default name for table
|
||||
elif istable:
|
||||
elif self._meta.istable:
|
||||
self.name = make_autoname('#########', self.doctype)
|
||||
|
||||
# unable to determine a name, use a serial number!
|
||||
# unable to determine a name, use global series
|
||||
if not self.name:
|
||||
self.name = make_autoname('#########', self.doctype)
|
||||
|
||||
|
||||
def set_naming_series(self):
|
||||
if not self.naming_series:
|
||||
# pick default naming series
|
||||
|
|
@ -247,13 +300,13 @@ class Document:
|
|||
self.naming_series = self.naming_series.split("\n")
|
||||
self.naming_series = self.naming_series[0] or self.naming_series[1]
|
||||
|
||||
def _insert(self, autoname, istable, case='', make_autoname=1, keep_timestamps=False):
|
||||
def _insert(self, make_autoname=True, keep_timestamps=False):
|
||||
# set name
|
||||
if make_autoname:
|
||||
self._set_name(autoname, istable)
|
||||
self.set_new_name()
|
||||
|
||||
# validate name
|
||||
self.name = validate_name(self.doctype, self.name, case)
|
||||
self.name = validate_name(self.doctype, self.name, self._meta.name_case)
|
||||
|
||||
# insert!
|
||||
if not keep_timestamps:
|
||||
|
|
@ -370,10 +423,12 @@ class Document:
|
|||
if getattr(webnotes.local, "valid_fields_map", None) is None:
|
||||
webnotes.local.valid_fields_map = {}
|
||||
|
||||
self.get_meta()
|
||||
|
||||
valid_fields_map = webnotes.local.valid_fields_map
|
||||
|
||||
if not valid_fields_map.get(self.doctype):
|
||||
if cint(webnotes.conn.get_value("DocType", self.doctype, "issingle")):
|
||||
if cint( self._meta.issingle):
|
||||
doctypelist = webnotes.model.doctype.get(self.doctype)
|
||||
valid_fields_map[self.doctype] = doctypelist.get_fieldnames({
|
||||
"fieldtype": ["not in", webnotes.model.no_value_fields]})
|
||||
|
|
@ -382,47 +437,13 @@ class Document:
|
|||
webnotes.conn.get_table_columns(self.doctype)
|
||||
|
||||
return valid_fields_map.get(self.doctype)
|
||||
|
||||
def save(self, new=0, check_links=1, ignore_fields=0, make_autoname=1,
|
||||
keep_timestamps=False):
|
||||
res = webnotes.model.meta.get_dt_values(self.doctype,
|
||||
'autoname, issingle, istable, name_case', as_dict=1)
|
||||
res = res and res[0] or {}
|
||||
|
||||
if new:
|
||||
self.fields["__islocal"] = 1
|
||||
|
||||
# add missing parentinfo (if reqd)
|
||||
if self.parent and not (self.parenttype and self.parentfield):
|
||||
self.update_parentinfo()
|
||||
def get_meta(self):
|
||||
if not self._meta:
|
||||
self._meta = webnotes.conn.get_value("DocType", self.doctype, ["autoname", "issingle",
|
||||
"istable", "name_case"], as_dict=True) or webnotes._dict()
|
||||
return self._meta
|
||||
|
||||
if self.parent and not self.idx:
|
||||
self.set_idx()
|
||||
|
||||
# if required, make new
|
||||
if not res.get('issingle'):
|
||||
if self.fields.get('__islocal'):
|
||||
r = self._insert(res.get('autoname'), res.get('istable'), res.get('name_case'),
|
||||
make_autoname, keep_timestamps = keep_timestamps)
|
||||
if r:
|
||||
return r
|
||||
else:
|
||||
if not webnotes.conn.exists(self.doctype, self.name):
|
||||
print self.fields
|
||||
webnotes.msgprint(webnotes._("Cannot update a non-exiting record, try inserting.") + ": " + self.doctype + " / " + self.name,
|
||||
raise_exception=1)
|
||||
|
||||
|
||||
# save the values
|
||||
self._update_values(res.get('issingle'),
|
||||
check_links and self.make_link_list() or {}, ignore_fields=ignore_fields,
|
||||
keep_timestamps=keep_timestamps)
|
||||
self._clear_temp_fields()
|
||||
|
||||
def insert(self):
|
||||
self.fields['__islocal'] = 1
|
||||
self.save()
|
||||
return self
|
||||
|
||||
def update_parentinfo(self):
|
||||
"""update parent type and parent field, if not explicitly specified"""
|
||||
|
|
@ -574,22 +595,18 @@ def make_autoname(key, doctype=''):
|
|||
|
||||
def getseries(key, digits, doctype=''):
|
||||
# series created ?
|
||||
if webnotes.conn.sql("select name from tabSeries where name='%s'" % key):
|
||||
|
||||
current = cint(webnotes.conn.get_value("Series", key, "current"))
|
||||
if current:
|
||||
# yes, update it
|
||||
webnotes.conn.sql("update tabSeries set current = current+1 where name='%s'" % key)
|
||||
|
||||
# find the series counter
|
||||
r = webnotes.conn.sql("select current from tabSeries where name='%s'" % key)
|
||||
n = r[0][0]
|
||||
webnotes.conn.sql("update tabSeries set current = current+1 where name=%s", key)
|
||||
current = current + 1
|
||||
else:
|
||||
|
||||
# no, create it
|
||||
webnotes.conn.sql("insert into tabSeries (name, current) values ('%s', 1)" % key)
|
||||
n = 1
|
||||
return ('%0'+str(digits)+'d') % n
|
||||
current = 1
|
||||
return ('%0'+str(digits)+'d') % current
|
||||
|
||||
def getchildren(name, childtype, field='', parenttype='', from_doctype=0, prefix='tab'):
|
||||
def getchildren(name, childtype, field='', parenttype='', from_doctype=0):
|
||||
import webnotes
|
||||
from webnotes.model.doclist import DocList
|
||||
|
||||
|
|
@ -603,8 +620,8 @@ def getchildren(name, childtype, field='', parenttype='', from_doctype=0, prefix
|
|||
condition += ' and parenttype=%s '
|
||||
values.append(parenttype)
|
||||
|
||||
dataset = webnotes.conn.sql("""select * from `%s%s` where parent=%s %s order by idx""" \
|
||||
% (prefix, childtype, "%s", condition), tuple([name]+values))
|
||||
dataset = webnotes.conn.sql("""select * from `tab%s` where parent=%s %s order by idx""" \
|
||||
% (childtype, "%s", condition), tuple([name]+values))
|
||||
desc = webnotes.conn.get_description()
|
||||
|
||||
l = DocList()
|
||||
|
|
@ -627,7 +644,7 @@ def check_page_perm(doc):
|
|||
webnotes.response['403'] = 1
|
||||
raise webnotes.PermissionError, '[WNF] No read permission for %s %s' % ('Page', doc.name)
|
||||
|
||||
def get(dt, dn='', with_children = 1, from_controller = 0, prefix = 'tab'):
|
||||
def get(dt, dn='', with_children = 1, from_controller = 0):
|
||||
"""
|
||||
Returns a doclist containing the main record and all child records
|
||||
"""
|
||||
|
|
@ -638,7 +655,7 @@ def get(dt, dn='', with_children = 1, from_controller = 0, prefix = 'tab'):
|
|||
dn = dn or dt
|
||||
|
||||
# load the main doc
|
||||
doc = Document(dt, dn, prefix=prefix)
|
||||
doc = Document(dt, dn)
|
||||
|
||||
if dt=='Page' and webnotes.session['user'] == 'Guest':
|
||||
check_page_perm(doc)
|
||||
|
|
@ -653,7 +670,7 @@ def get(dt, dn='', with_children = 1, from_controller = 0, prefix = 'tab'):
|
|||
# load chilren
|
||||
doclist = DocList([doc,])
|
||||
for t in tablefields:
|
||||
doclist += getchildren(doc.name, t[0], t[1], dt, prefix=prefix)
|
||||
doclist += getchildren(doc.name, t[0], t[1], dt)
|
||||
|
||||
return doclist
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ def get_module_path(module):
|
|||
return os.path.join(app_path, 'lib', m)
|
||||
else:
|
||||
return os.path.join(app_path, 'app', m)
|
||||
|
||||
def get_plugin_path(plugin):
|
||||
from webnotes.utils import get_site_path
|
||||
return get_site_path(webnotes.conf.get("plugins_path"), scrub(plugin))
|
||||
|
||||
def get_doc_path(module, doctype, name):
|
||||
dt, dn = scrub_dt_dn(doctype, name)
|
||||
|
|
@ -41,13 +45,13 @@ def reload_doc(module, dt=None, dn=None, force=True):
|
|||
from webnotes.modules.import_file import import_files
|
||||
return import_files(module, dt, dn, force)
|
||||
|
||||
def export_doc(doctype, name, module=None):
|
||||
def export_doc(doctype, name, module=None, plugin=None):
|
||||
"""write out a doc"""
|
||||
from webnotes.modules.export_file import write_document_file
|
||||
import webnotes.model.doc
|
||||
|
||||
if not module: module = webnotes.conn.get_value(doctype, name, 'module')
|
||||
write_document_file(webnotes.model.doc.get(doctype, name), module)
|
||||
write_document_file(webnotes.model.doc.get(doctype, name), module, plugin=plugin)
|
||||
|
||||
def get_doctype_module(doctype):
|
||||
return webnotes.conn.get_value('DocType', doctype, 'module')
|
||||
|
|
|
|||
|
|
@ -5,25 +5,25 @@ from __future__ import unicode_literals
|
|||
|
||||
import webnotes, os
|
||||
import webnotes.model.doc
|
||||
from webnotes.modules import scrub, get_module_path, lower_case_files_for, scrub_dt_dn
|
||||
from webnotes.modules import scrub, get_module_path, lower_case_files_for, scrub_dt_dn, get_plugin_path
|
||||
|
||||
def export_doc(doc):
|
||||
export_to_files([[doc.doctype, doc.name]])
|
||||
|
||||
def export_to_files(record_list=[], record_module=None, verbose=0):
|
||||
def export_to_files(record_list=None, record_module=None, verbose=0, plugin=None):
|
||||
"""
|
||||
Export record_list to files. record_list is a list of lists ([doctype],[docname] ) ,
|
||||
"""
|
||||
if webnotes.flags.in_import:
|
||||
return
|
||||
|
||||
|
||||
module_doclist =[]
|
||||
if record_list:
|
||||
for record in record_list:
|
||||
write_document_file(webnotes.model.doc.get(record[0], record[1]),
|
||||
record_module)
|
||||
record_module, plugin=plugin)
|
||||
|
||||
def write_document_file(doclist, record_module=None):
|
||||
def write_document_file(doclist, record_module=None, plugin=None):
|
||||
from webnotes.modules.utils import pprint_doclist
|
||||
|
||||
doclist = [filter_fields(d.fields) for d in doclist]
|
||||
|
|
@ -32,7 +32,7 @@ def write_document_file(doclist, record_module=None):
|
|||
code_type = doclist[0]['doctype'] in lower_case_files_for
|
||||
|
||||
# create folder
|
||||
folder = create_folder(module, doclist[0]['doctype'], doclist[0]['name'], code_type)
|
||||
folder = create_folder(module, doclist[0]['doctype'], doclist[0]['name'], code_type, plugin=plugin)
|
||||
|
||||
# write the data file
|
||||
fname = (code_type and scrub(doclist[0]['name'])) or doclist[0]['name']
|
||||
|
|
@ -71,9 +71,11 @@ def get_module_name(doclist):
|
|||
|
||||
return module
|
||||
|
||||
def create_folder(module, dt, dn, code_type):
|
||||
# get module path by importing the module
|
||||
module_path = get_module_path(module)
|
||||
def create_folder(module, dt, dn, code_type, plugin=None):
|
||||
if plugin:
|
||||
module_path = os.path.join(get_plugin_path(plugin), scrub(module))
|
||||
else:
|
||||
module_path = get_module_path(module)
|
||||
|
||||
dt, dn = scrub_dt_dn(dt, dn)
|
||||
|
||||
|
|
|
|||
30
webnotes/tests/test_hash.py
Normal file
30
webnotes/tests/test_hash.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
from webnotes import HashAuthenticatedCommand, whitelist
|
||||
|
||||
class HashCommand(HashAuthenticatedCommand):
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
signature = kwargs.pop('signature')
|
||||
if self.verify_signature(kwargs, signature):
|
||||
return self.command(*args, **kwargs)
|
||||
else:
|
||||
raise Exception
|
||||
|
||||
def command(self, *args, **kwargs):
|
||||
return "Hello World"
|
||||
|
||||
def get_nonce(self):
|
||||
return "5"
|
||||
|
||||
hash_cmd = (HashCommand())
|
||||
|
||||
# @whitelist(allow_guest=True)
|
||||
# def get_hash():
|
||||
# return hash_cmd.get_signature({})
|
||||
#
|
||||
# def get_nonce(self):
|
||||
# return "5"
|
||||
|
||||
@whitelist(allow_guest=True)
|
||||
@HashAuthenticatedCommand(nonce_function=get_nonce)
|
||||
def hash_cmd(*args, **kwargs):
|
||||
return "Hello World"
|
||||
|
|
@ -35,7 +35,7 @@ def send(recipients=None, sender=None, doctype='Profile', email_field='email',
|
|||
import urllib
|
||||
updated = message + """<div style="padding: 7px; border-top: 1px solid #aaa;
|
||||
margin-top: 17px;">
|
||||
<small><a href="%s/server.py?%s">
|
||||
<small><a href="%s/?%s">
|
||||
Unsubscribe</a> from this list.</small></div>""" % (get_url(),
|
||||
urllib.urlencode({
|
||||
"cmd": "webnotes.utils.email_lib.bulk.unsubscribe",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
import os, base64
|
||||
import os, base64, re
|
||||
from webnotes.utils import cstr, cint, get_site_path
|
||||
from webnotes import _
|
||||
from webnotes import conf
|
||||
|
|
@ -61,6 +61,25 @@ def get_uploaded_content():
|
|||
webnotes.msgprint('No File')
|
||||
return None, None
|
||||
|
||||
def extract_images_from_html(doc, fieldname):
|
||||
content = doc.get(fieldname)
|
||||
webnotes.flags.has_dataurl = False
|
||||
|
||||
def _save_file(match):
|
||||
data = match.group(1)
|
||||
headers, content = data.split(",")
|
||||
filename = headers.split("filename=")[-1]
|
||||
filename = save_file(filename, content, doc.doctype, doc.name, decode=True).get("file_name")
|
||||
if not webnotes.flags.has_dataurl:
|
||||
webnotes.flags.has_dataurl = True
|
||||
|
||||
return '<img src="{filename}"'.format(filename = filename)
|
||||
|
||||
if content:
|
||||
content = re.sub('<img\s*src=\s*["\'](data:[^"\']*)["\']', _save_file, content)
|
||||
if webnotes.flags.has_dataurl:
|
||||
doc.fields[fieldname] = content
|
||||
|
||||
def save_file(fname, content, dt, dn, decode=False):
|
||||
if decode:
|
||||
if isinstance(content, unicode):
|
||||
|
|
@ -114,13 +133,17 @@ def save_file(fname, content, dt, dn, decode=False):
|
|||
|
||||
f = webnotes.bean({
|
||||
"doctype": "File Data",
|
||||
"file_name": os.path.relpath(os.path.join(files_path, fname), get_site_path(conf.get("public_path", "public"))),
|
||||
"file_name": os.path.relpath(os.path.join(files_path, fname),
|
||||
get_site_path(conf.get("public_path", "public"))),
|
||||
"attached_to_doctype": dt,
|
||||
"attached_to_name": dn,
|
||||
"file_size": file_size
|
||||
})
|
||||
f.ignore_permissions = True
|
||||
f.insert();
|
||||
try:
|
||||
f.insert();
|
||||
except webnotes.DuplicateEntryError:
|
||||
return {"file_name": f.doc.file_name}
|
||||
|
||||
return f.doc
|
||||
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ def get_website_settings():
|
|||
"utils": webnotes.utils,
|
||||
"post_login": [
|
||||
{"label": "Reset Password", "url": "update-password", "icon": "icon-key"},
|
||||
{"label": "Logout", "url": "server.py?cmd=web_logout", "icon": "icon-signout"}
|
||||
{"label": "Logout", "url": "/?cmd=web_logout", "icon": "icon-signout"}
|
||||
]
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ class DocType:
|
|||
from webnotes.utils import global_date_format, get_fullname
|
||||
self.doc.full_name = get_fullname(self.doc.owner)
|
||||
self.doc.updated = global_date_format(self.doc.published_on)
|
||||
self.doc.content_html = self.doc.content
|
||||
|
||||
if self.doc.blogger:
|
||||
self.doc.blogger_info = webnotes.doc("Blogger", self.doc.blogger).fields
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<span itemprop="dateCreated">{{ updated }}</span></div>
|
||||
<br>
|
||||
<div itemprop="articleBody">
|
||||
{{ content_html }}
|
||||
{{ content }}
|
||||
</div>
|
||||
<!-- end blog content -->
|
||||
{% if blogger_info %}
|
||||
|
|
@ -21,5 +21,13 @@
|
|||
<h3>Comments</h3>
|
||||
{% include 'lib/website/templates/includes/comments.html' %}
|
||||
</div>
|
||||
<script>
|
||||
$(function() {
|
||||
if(window.logged_in && getCookie("system_user")==="yes") {
|
||||
wn.require("lib/js/wn/website/editable.js");
|
||||
wn.make_editable($('[itemprop="articleBody"]'), "Blog Post", "{{ name }}", "content");
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{% include 'lib/website/doctype/blog_post/templates/includes/blog_footer.html' %}
|
||||
{% endblock %}
|
||||
|
|
@ -26,7 +26,7 @@ var blog = {
|
|||
get_list: function() {
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
url: "server.py",
|
||||
url: "/",
|
||||
data: {
|
||||
cmd: "website.doctype.blog_post.blog_post.get_blog_list",
|
||||
start: blog.start,
|
||||
|
|
@ -42,6 +42,7 @@ var blog = {
|
|||
});
|
||||
},
|
||||
render: function(data) {
|
||||
if(!data) data = [];
|
||||
var $wrap = $("#blog-list");
|
||||
$.each(data, function(i, b) {
|
||||
// comments
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
{% extends base_template %}
|
||||
|
||||
{% block head %}
|
||||
<!--script src="lib/js/lib/jquery/jquery.hotkeys.js"></script>
|
||||
<script src="lib/js/wn/ui/editor.js"></script-->
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="col-md-12" style="margin-top: 15px;">
|
||||
{% include "lib/website/doctype/website_slideshow/templates/includes/slideshow.html" %}
|
||||
|
|
@ -14,9 +9,9 @@
|
|||
</div>
|
||||
<script>
|
||||
$(function() {
|
||||
window.name = "{{ name }}";
|
||||
if(getCookie("full_name")) {
|
||||
wn.editor = new wn.ui.Editor($(".web-page-content"));
|
||||
if(window.logged_in && getCookie("system_user")==="yes") {
|
||||
wn.require("lib/js/wn/website/editable.js");
|
||||
wn.make_editable($(".web-page-content"), "Web Page", "{{ name }}", "main_section");
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,18 @@ $.extend(wn, {
|
|||
}
|
||||
return parent;
|
||||
},
|
||||
require: function(url) {
|
||||
$.ajax({
|
||||
url: url + "?q=" + Math.floor(Math.random() * 1000),
|
||||
async: false,
|
||||
dataType: "text",
|
||||
success: function(data) {
|
||||
var el = document.createElement('script');
|
||||
el.appendChild(document.createTextNode(data));
|
||||
document.getElementsByTagName('head')[0].appendChild(el);
|
||||
}
|
||||
});
|
||||
},
|
||||
hide_message: function(text) {
|
||||
$('.message-overlay').remove();
|
||||
},
|
||||
|
|
@ -29,7 +41,7 @@ $.extend(wn, {
|
|||
wn.prepare_call(opts);
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "server.py",
|
||||
url: "/",
|
||||
data: opts.args,
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ login.do_login = function(){
|
|||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "server.py",
|
||||
url: "/",
|
||||
data: args,
|
||||
dataType: "json",
|
||||
success: function(data) {
|
||||
|
|
|
|||
47
wnf.py
47
wnf.py
|
|
@ -41,7 +41,7 @@ def run(fn, args):
|
|||
out = globals().get(fn)(*args.get(fn), **args)
|
||||
else:
|
||||
out = globals().get(fn)(**args)
|
||||
webnotes.destroy()
|
||||
|
||||
return out
|
||||
|
||||
def get_function(args):
|
||||
|
|
@ -135,6 +135,7 @@ def setup_utilities(parser):
|
|||
help="Set administrator password")
|
||||
parser.add_argument("--mysql", action="store_true", help="get mysql shell for a site")
|
||||
parser.add_argument("--serve", action="store_true", help="Run development server")
|
||||
parser.add_argument("--get_site_details", action="store_true", help="Get site details")
|
||||
parser.add_argument("--port", default=8000, type=int, help="port for development server")
|
||||
|
||||
# clear
|
||||
|
|
@ -205,6 +206,7 @@ def install(db_name, source_sql=None, site=None, verbose=True, force=False, root
|
|||
from webnotes.install_lib.install import Installer
|
||||
inst = Installer('root', db_name=db_name, site=site, root_password=root_password, site_config=site_config)
|
||||
inst.install(db_name, source_sql=source_sql, verbose=verbose, force=force, admin_password=admin_password)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def reinstall(site=None, verbose=True):
|
||||
|
|
@ -220,6 +222,7 @@ def install_fixtures(site=None):
|
|||
webnotes.init(site=site)
|
||||
from webnotes.install_lib.install import install_fixtures
|
||||
install_fixtures()
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def add_system_manager(email, first_name=None, last_name=None, site=None):
|
||||
|
|
@ -233,12 +236,14 @@ def make_demo(site=None):
|
|||
import utilities.demo.make_demo
|
||||
webnotes.init(site=site)
|
||||
utilities.demo.make_demo.make()
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def make_demo_fresh(site=None):
|
||||
import utilities.demo.make_demo
|
||||
webnotes.init(site=site)
|
||||
utilities.demo.make_demo.make(reset=True)
|
||||
webnotes.destroy()
|
||||
|
||||
# utilities
|
||||
|
||||
|
|
@ -270,12 +275,15 @@ def latest(site=None, verbose=True):
|
|||
except webnotes.modules.patch_handler.PatchError, e:
|
||||
print "\n".join(webnotes.local.patch_log_list)
|
||||
raise e
|
||||
finally:
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def sync_all(site=None, force=False):
|
||||
import webnotes.model.sync
|
||||
webnotes.connect(site=site)
|
||||
webnotes.model.sync.sync_all(force=force)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def patch(patch_module, site=None, force=False):
|
||||
|
|
@ -284,6 +292,7 @@ def patch(patch_module, site=None, force=False):
|
|||
webnotes.local.patch_log_list = []
|
||||
webnotes.modules.patch_handler.run_single(patch_module, force=force)
|
||||
print "\n".join(webnotes.local.patch_log_list)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def update_all_sites(remote=None, branch=None, verbose=True):
|
||||
|
|
@ -296,6 +305,7 @@ def update_all_sites(remote=None, branch=None, verbose=True):
|
|||
def reload_doc(module, doctype, docname, site=None, force=False):
|
||||
webnotes.connect(site=site)
|
||||
webnotes.reload_doc(module, doctype, docname, force=force)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def build():
|
||||
|
|
@ -355,6 +365,7 @@ def domain(host_url=None, site=None):
|
|||
webnotes.conn.commit()
|
||||
else:
|
||||
print webnotes.conn.get_value("Website Settings", None, "subdomain")
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def make_conf(db_name=None, db_password=None, site=None, site_config=None):
|
||||
|
|
@ -366,6 +377,7 @@ def make_custom_server_script(doctype, site=None):
|
|||
from core.doctype.custom_script.custom_script import make_custom_server_script_file
|
||||
webnotes.connect(site=site)
|
||||
make_custom_server_script_file(doctype)
|
||||
webnotes.destroy()
|
||||
|
||||
# clear
|
||||
@cmd
|
||||
|
|
@ -373,12 +385,14 @@ def clear_cache(site=None):
|
|||
import webnotes.sessions
|
||||
webnotes.connect(site=site)
|
||||
webnotes.sessions.clear_cache()
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def clear_web(site=None):
|
||||
import webnotes.webutils
|
||||
webnotes.connect(site=site)
|
||||
webnotes.webutils.clear_cache()
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def reset_perms(site=None):
|
||||
|
|
@ -387,6 +401,7 @@ def reset_perms(site=None):
|
|||
where ifnull(istable, 0)=0 and ifnull(custom, 0)=0"""):
|
||||
webnotes.clear_cache(doctype=d)
|
||||
webnotes.reset_perms(d)
|
||||
webnotes.destroy()
|
||||
|
||||
# scheduler
|
||||
@cmd
|
||||
|
|
@ -394,12 +409,14 @@ def run_scheduler(site=None):
|
|||
import webnotes.utils.scheduler
|
||||
webnotes.connect(site=site)
|
||||
print webnotes.utils.scheduler.execute()
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def run_scheduler_event(event, site=None):
|
||||
import webnotes.utils.scheduler
|
||||
webnotes.connect(site=site)
|
||||
print webnotes.utils.scheduler.trigger("execute_" + event)
|
||||
webnotes.destroy()
|
||||
|
||||
# replace
|
||||
@cmd
|
||||
|
|
@ -413,24 +430,28 @@ def export_doc(doctype, docname, site=None):
|
|||
import webnotes.modules
|
||||
webnotes.connect(site=site)
|
||||
webnotes.modules.export_doc(doctype, docname)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def export_doclist(doctype, name, path, site=None):
|
||||
from core.page.data_import_tool import data_import_tool
|
||||
webnotes.connect(site=site)
|
||||
data_import_tool.export_json(doctype, name, path)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def export_csv(doctype, path, site=None):
|
||||
from core.page.data_import_tool import data_import_tool
|
||||
webnotes.connect(site=site)
|
||||
data_import_tool.export_csv(doctype, path)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def import_doclist(path, site=None):
|
||||
from core.page.data_import_tool import data_import_tool
|
||||
webnotes.connect(site=site)
|
||||
data_import_tool.import_doclist(path)
|
||||
webnotes.destroy()
|
||||
|
||||
# translation
|
||||
@cmd
|
||||
|
|
@ -438,30 +459,35 @@ def build_message_files(site=None):
|
|||
import webnotes.translate
|
||||
webnotes.connect(site=site)
|
||||
webnotes.translate.build_message_files()
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def export_messages(lang, outfile, site=None):
|
||||
import webnotes.translate
|
||||
webnotes.connect(site=site)
|
||||
webnotes.translate.export_messages(lang, outfile)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def import_messages(lang, infile, site=None):
|
||||
import webnotes.translate
|
||||
webnotes.connect(site=site)
|
||||
webnotes.translate.import_messages(lang, infile)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def google_translate(lang, infile, outfile, site=None):
|
||||
import webnotes.translate
|
||||
webnotes.connect(site=site)
|
||||
webnotes.translate.google_translate(lang, infile, outfile)
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def translate(lang, site=None):
|
||||
import webnotes.translate
|
||||
webnotes.connect(site=site)
|
||||
webnotes.translate.translate(lang)
|
||||
webnotes.destroy()
|
||||
|
||||
# git
|
||||
@cmd
|
||||
|
|
@ -522,6 +548,7 @@ def mysql(site=None):
|
|||
msq = commands.getoutput('which mysql')
|
||||
webnotes.init(site=site)
|
||||
os.execv(msq, [msq, '-u', webnotes.conf.db_name, '-p'+webnotes.conf.db_password, webnotes.conf.db_name])
|
||||
webnotes.destroy()
|
||||
|
||||
@cmd
|
||||
def serve(port=8000):
|
||||
|
|
@ -573,6 +600,24 @@ def search_replace_with_prompt(fpath, txt1, txt2, force=False):
|
|||
with open(fpath, 'w') as f:
|
||||
f.write(''.join(tmp))
|
||||
print colored('Updated', 'green')
|
||||
|
||||
@cmd
|
||||
def get_site_details(site=None, verbose=False):
|
||||
import webnotes
|
||||
from webnotes.profile import get_system_managers
|
||||
from core.doctype.profile.profile import get_total_users, get_active_users
|
||||
import json
|
||||
webnotes.connect(site=site)
|
||||
ret = {
|
||||
'last_backup_on': webnotes.local.conf.last_backup_on,
|
||||
'active_users': get_active_users(),
|
||||
'total_users': get_total_users(),
|
||||
'system_managers': get_system_managers()
|
||||
}
|
||||
webnotes.destroy()
|
||||
if verbose:
|
||||
print json.dumps(ret, indent=4)
|
||||
return ret
|
||||
|
||||
if __name__=="__main__":
|
||||
main()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue