Mercurial > moin-2.0
changeset 2086:a5b0f7551a56
merged
| author | Thomas Waldmann <tw AT waldmann-edv DOT de> |
|---|---|
| date | Thu, 11 Apr 2013 21:00:12 +0200 |
| parents | d1f6f392cdf6 (current diff) 7f4520c9b5f1 (diff) |
| children | d050c88db976 |
| files | MoinMoin/themes/foobar/static/css/stylus/main.styl |
| diffstat | 6 files changed, 44 insertions(+), 105 deletions(-) [+] |
line wrap: on
line diff
--- a/MoinMoin/forms.py Thu Apr 11 21:23:36 2013 +0530 +++ b/MoinMoin/forms.py Thu Apr 11 21:00:12 2013 +0200 @@ -20,10 +20,12 @@ from flatland.validation import Validator, Present, IsEmail, ValueBetween, URLValidator, Converted, ValueAtLeast from flatland.exc import AdaptationError +from whoosh.query import Term, Or, Not, And + from flask import g as flaskg from MoinMoin.constants.forms import * -from MoinMoin.constants.keys import ITEMID, NAME +from MoinMoin.constants.keys import ITEMID, NAME, LATEST_REVS from MoinMoin.i18n import _, L_, N_ from MoinMoin.util.forms import FileStorage @@ -71,12 +73,36 @@ """Validator for JSON """ invalid_json_msg = L_('Invalid JSON.') + invalid_name_msg = "" + + def validname(self, meta, name, itemid): + names = meta.get(NAME) + if names is None: + self.invalid_name_msg = L_("No name field in the JSON meta.") + return False + if len(names) != len(set(names)): + self.invalid_name_msg = L_("The names in the JSON name list must be unique.") + return False + query = Or([Term(NAME, x) for x in names]) + if itemid is not None: + query = And([query, Not(Term(ITEMID, itemid))]) + duplicate_names = set() + with flaskg.storage.indexer.ix[LATEST_REVS].searcher() as searcher: + results = searcher.search(query) + for result in results: + duplicate_names |= set([x for x in result[NAME] if x in names]) + if duplicate_names: + self.invalid_name_msg = L_("Item(s) named %(duplicate_names)s already exist.", duplicate_names=", ".join(duplicate_names)) + return False + return True def validate(self, element, state): try: - json.loads(element.value) + meta = json.loads(element.value) except: # catch ANY exception that happens due to unserializing return self.note_error(element, state, 'invalid_json_msg') + if not self.validname(meta, state[NAME], state[ITEMID]): + return self.note_error(element, state, 'invalid_name_msg') return True JSON = OptionalMultilineText.with_properties(lang='en', dir='ltr').validated_by(ValidJSON())
--- a/MoinMoin/items/__init__.py Thu Apr 11 21:23:36 2013 +0530 +++ b/MoinMoin/items/__init__.py Thu Apr 11 21:00:12 2013 +0200 @@ -727,7 +727,8 @@ # break them return "OK" form = self.ModifyForm.from_request(request) - if form.validate(): + state = dict(name=self.name, itemid=self.meta.get(ITEMID)) + if form.validate(state): meta, data, contenttype_guessed, comment = form._dump(self) contenttype_qs = request.values.get('contenttype') try:
--- a/MoinMoin/templates/common.js Thu Apr 11 21:23:36 2013 +0530 +++ b/MoinMoin/templates/common.js Thu Apr 11 21:00:12 2013 +0200 @@ -228,92 +228,18 @@ -// guessContentType is a helper function for the transcludeSubitem and linkSubItem functions defined below. -function guessContentType() { - "use strict"; - // Used in the modify_text template to guess the data content type client-side - // This approach has the advantage of reacting to content type changes for the - // link/transclude code without having to re-fetch the page - var match, - meta_text = $("#f_meta_text").val(), - ctype_regex = /["']contenttype["']\s*:\s*["']([\w-_+.]+\/[\w-_+.]+)(;|["'])/; - if (meta_text) { - match = ctype_regex.exec(meta_text); - if (match) {return match[1]; } - } - // text/plain is the default value - return "text/plain"; -} - -// Executed when user clicks transclude-action button defined in modify_text.html. +// Executed when user clicks insert-name button defined in modify.html. // When a page with subitems is modified, a subitems sidebar is present. User may -// position caret in textarea and click button to insert transclusion into textarea. -function transcludeSubitem(subitem_name, fullname) { +// position caret in textarea and click button to insert name into textarea. +function InsertName(fullname) { "use strict"; - function moinwiki(subitem_name, fullname) { - // note: keep the many plusses, to avoid jinja2 templating kicking in - // when seeing two curly opening / closing braces - return "{" + "{" + fullname.replace("{" + "{", "\\" + "}" + "}") + "}" + "} "; - } - function mediawiki(subitem_name, fullname) { - // note: keep the many plusses, to avoid jinja2 templating kicking in - // when seeing two curly opening / closing braces - return "{" + "{:" + fullname.replace("}" + "}", "\\" + "}" + "}") + "}" + "} "; - } - function rst(subitem_name, fullname) { - return "\n.. include:: " + subitem_name + "\n"; - } - function docbook(subitem_name, fullname) { - return ""; //XXX: the docbook converter currently doesn't handle transclusion with <ref> tags - } - var transclude_formats = { - "text/x.moin.wiki" : moinwiki, - "text/x.moin.creole" : moinwiki, - "text/x-mediawiki" : mediawiki, - "text/x-rst" : rst, - "application/docbook+xml" : docbook, - "text/plain" : function (x) {return x + " "; } - }, - ctype = guessContentType(), - input_element = $("#f_content_form_data_text"), - ctype_format = transclude_formats[ctype]; - if (!ctype_format) { - ctype_format = transclude_formats["text/plain"]; - } - input_element.val(input_element.val() + ctype_format(subitem_name, fullname)); - input_element.focus(); -} - -// Executed when user clicks link-action button defined in modify_text.html. -// When a page with subitems is modified, a subitems sidebar is present. User may -// position caret in textarea and click button to insert link into textarea. -function linkSubitem(subitem_name, fullname) { - "use strict"; - function moinwiki(subitem_name, fullname) { - return "[[" + fullname.replace("]", "\\]") + "|" + subitem_name.replace("]", "\\]") + "]] "; - } - function rst(subitem_name, fullname) { - return "`" + subitem_name.replace(">", "\\>").replace("`", "\\`") + " <" + fullname.replace(">", "\\>") + ">`_ "; - } - function docbook(subitem_name, fullname) { - return '<ulink url="/' + fullname.replace('"', '\\"') + '">' + subitem_name + "</ulink>"; - } - var link_formats = { - "text/x.moin.wiki" : moinwiki, - "text/x.moin.creole" : moinwiki, - "text/x-mediawiki" : moinwiki, - "text/x-rst" : rst, - "application/docbook+xml" : docbook, - "text/plain" : function (x) {return x + " "; } - }, - ctype = guessContentType(), - input_element = $("#f_content_form_data_text"), - ctype_format = link_formats[ctype]; - if (!ctype_format) { - ctype_format = link_formats["text/plain"]; - } - input_element.val(input_element.val() + ctype_format(subitem_name, fullname)); - input_element.focus(); + var textArea, scrollTop, endPos, startPos; + textArea = document.getElementById('f_content_form_data_text'); + startPos = textArea.selectionStart; + endPos = textArea.selectionEnd; + textArea.value = textArea.value.substring(0, startPos) + fullname + textArea.value.substring(endPos, textArea.value.length); + textArea.focus(); + textArea.setSelectionRange(startPos+fullname.length,startPos+fullname.length); }
--- a/MoinMoin/templates/modify.html Thu Apr 11 21:23:36 2013 +0530 +++ b/MoinMoin/templates/modify.html Thu Apr 11 21:00:12 2013 +0200 @@ -23,11 +23,8 @@ {% call(fullname, shortname, contenttype, has_children) utils.render_subitem_navigation(item_name, True) %} {% set shortname = shortname|json_dumps %} {% set fullname = fullname|json_dumps %} - <button class="link-action" onclick='linkSubitem({{ shortname }}, {{ fullname }})' - title="{{ _('Link to Subitem') }}">{{ _('Link') }}</button> - <button class="transclude-action" - onclick='transcludeSubitem({{ shortname }}, {{ fullname }})' - title="{{ _('Transclude Subitem') }}">{{ _('Transclude') }}</button> + <button class="moin-insertname-action" onclick='InsertName({{ fullname }})' + title="{{ _('Insert Name') }}">{{ _('Insert Name') }}</button> {% endcall %} {% endblock %}
--- a/MoinMoin/themes/foobar/static/css/stylus/main.styl Thu Apr 11 21:23:36 2013 +0530 +++ b/MoinMoin/themes/foobar/static/css/stylus/main.styl Thu Apr 11 21:00:12 2013 +0200 @@ -1038,8 +1038,7 @@ text-indent -9000% box-shadow none -.link-action, -.transclude-action +.moin-insertname-action border: hidden text-indent: -9000% padding: 0 @@ -1050,12 +1049,8 @@ overflow: hidden cursor: pointer box-shadow none - -.link-action background: url(../img/moin-link.png) no-repeat center center -.transclude-action - background: url(../img/moin-transclusion.png) no-repeat center center // transclusion .moin-transclusion
--- a/MoinMoin/themes/modernized/static/css/stylus/main.styl Thu Apr 11 21:23:36 2013 +0530 +++ b/MoinMoin/themes/modernized/static/css/stylus/main.styl Thu Apr 11 21:00:12 2013 +0200 @@ -1412,8 +1412,7 @@ border hidden text-indent -9000% -.link-action, -.transclude-action +.moin-insertname-action border hidden text-indent -9000% padding 0 @@ -1424,13 +1423,8 @@ overflow hidden cursor pointer box-shadow none - -.moin-subitem-navigation .link-action background url(../img/moin-link.png) no-repeat center center -.moin-subitem-navigation .transclude-action - background url(../img/moin-transclusion.png) no-repeat center center - #moin-footer clear both margin 0 0
