Better pull/push handling.
import re
from django.utils import simplejson as json
-
class MergeRequestForm(forms.Form):
# should the target document revision be updated or shared
type = forms.ChoiceField(choices=(('update', 'Update'), ('share', 'Share')) )
class DocumentRetrieveForm(forms.Form):
revision = forms.RegexField(regex=r'latest|[0-9a-z]{40}', required=False)
user = forms.CharField(required=False)
-
+
def clean_user(self):
- # why, oh why does django doesn't implement this!!!
+ # why, oh why doesn't django implement this!!!
# value = super(DocumentRetrieveForm, self).clean_user()
value = self.cleaned_data['user']
class TextRetrieveForm(DocumentRetrieveForm):
- part = forms.CharField(required=False)
+ chunk = forms.CharField(required=False)
+ format = forms.CharField(required=False)
+
+ def clean_format(self):
+ value = self.cleaned_data['format']
+ if not value:
+ return 'raw'
+
+ if value not in ('nl', 'raw'):
+ raise forms.ValidationError("Invalid text format")
+ return value
class TextUpdateForm(DocumentRetrieveForm):
message = forms.CharField(required=False)
contents = forms.CharField(required=False)
chunks = forms.CharField(required=False)
+ format = forms.CharField(required=False)
+
+ def clean_format(self):
+ value = self.cleaned_data['format']
+ if not value:
+ return 'raw'
+
+ if value not in ('nl', 'raw'):
+ raise forms.ValidationError("Invalid text format")
+ return value
+
def clean_message(self):
value = self.cleaned_data['message']
from piston.handler import BaseHandler, AnonymousBaseHandler
-import re
from datetime import date
from django.core.urlresolvers import reverse
-from django.utils import simplejson as json
from django.db import IntegrityError
import librarian
import librarian.html
-from librarian import dcparser, parser
from wlrepo import *
from api.models import PullRequest
return galleries
-#
-# Document Text View
-#
-
-XINCLUDE_REGEXP = r"""<(?:\w+:)?include\s+[^>]*?href=("|')wlrepo://(?P<link>[^\1]+?)\1\s*[^>]*?>"""
-#
-#
-#
-
-class DocumentTextHandler(BaseHandler):
- allowed_methods = ('GET', 'POST')
-
- @validate_form(forms.TextRetrieveForm, 'GET')
- @hglibrary
- def read(self, request, form, docid, lib):
- """Read document as raw text"""
- try:
- revision = form.cleaned_data['revision']
- part = form.cleaned_data['part']
- user = form.cleaned_data['user'] or request.user.username
-
- document = lib.document_for_rev(revision)
-
- if document.id != docid:
- return response.BadRequest().django_response({
- 'reason': 'name-mismatch',
- 'message': 'Provided revision is not valid for this document'
- })
-
- if document.owner != user:
- return response.BadRequest().django_response({
- 'reason': 'user-mismatch',
- 'message': "Provided revision doesn't belong to user %s" % user
- })
-
- for error in check_user(request, user):
- return error
-
- if not part:
- return document.data('xml')
-
- xdoc = parser.WLDocument.from_string(document.data('xml'),\
- parse_dublincore=False)
- ptext = xdoc.part_as_text(part)
-
- if ptext is None:
- return response.EntityNotFound().django_response({
- 'reason': 'no-part-in-document'
- })
-
- return ptext
- except librarian.ParseError, e:
- return response.EntityNotFound().django_response({
- 'reason': 'invalid-document-state',
- 'exception': type(e),
- 'message': e.message
- })
- except (EntryNotFound, RevisionNotFound), e:
- return response.EntityNotFound().django_response({
- 'reason': 'not-found',
- 'exception': type(e), 'message': e.message
- })
-
- @validate_form(forms.TextUpdateForm, 'POST')
- @hglibrary
- def create(self, request, form, docid, lib):
- try:
- revision = form.cleaned_data['revision']
- msg = form.cleaned_data['message']
- user = form.cleaned_data['user'] or request.user.username
-
- # do not allow changing not owned documents
- # (for now... )
-
-
- if user != request.user.username:
- return response.AccessDenied().django_response({
- 'reason': 'insufficient-priviliges',
- })
-
- current = lib.document(docid, user)
- orig = lib.document_for_rev(revision)
-
- if current != orig:
- return response.EntityConflict().django_response({
- "reason": "out-of-date",
- "provided_revision": orig.revision,
- "latest_revision": current.revision })
-
- if form.cleaned_data.has_key('contents'):
- data = form.cleaned_data['contents']
- else:
- chunks = form.cleaned_data['chunks']
- xdoc = parser.WLDocument.from_string(current.data('xml'))
- errors = xdoc.merge_chunks(chunks)
-
- if len(errors):
- return response.EntityConflict().django_response({
- "reason": "invalid-chunks",
- "message": "Unable to merge following parts into the document: %s " % ",".join(errors)
- })
-
- data = xdoc.serialize()
-
- # try to find any Xinclude tags
- includes = [m.groupdict()['link'] for m in (re.finditer(\
- XINCLUDE_REGEXP, data, flags=re.UNICODE) or []) ]
-
- log.info("INCLUDES: %s", includes)
-
- # TODO: provide useful routines to make this simpler
- def xml_update_action(lib, resolve):
- try:
- f = lib._fileopen(resolve('parts'), 'r')
- stored_includes = json.loads(f.read())
- f.close()
- except:
- stored_includes = []
-
- if stored_includes != includes:
- f = lib._fileopen(resolve('parts'), 'w+')
- f.write(json.dumps(includes))
- f.close()
-
- lib._fileadd(resolve('parts'))
-
- # update the parts cache
- PartCache.update_cache(docid, current.owner,\
- stored_includes, includes)
-
- # now that the parts are ok, write xml
- f = lib._fileopen(resolve('xml'), 'w+')
- f.write(data.encode('utf-8'))
- f.close()
-
- ndoc = None
- ndoc = current.invoke_and_commit(\
- xml_update_action, lambda d: (msg, user) )
-
- try:
- # return the new revision number
- return response.SuccessAllOk().django_response({
- "document": ndoc.id,
- "user": user,
- "subview": "xml",
- "previous_revision": current.revision,
- "revision": ndoc.revision,
- 'timestamp': ndoc.revision.timestamp,
- "url": reverse("doctext_view", args=[ndoc.id])
- })
- except Exception, e:
- if ndoc: lib._rollback()
- raise e
- except RevisionNotFound, e:
- return response.EntityNotFound(mimetype="text/plain").\
- django_response(e.message)
#
# update is always performed from the file branch
# to the user branch
user_doc_new = base_doc.update(request.user.username)
+
+ if user_doc_new == user_doc:
+ return response.SuccessAllOk().django_response({
+ "result": "no-op"
+ })
# shared document is the same
doc_new = doc
if not base_doc.up_to_date():
return response.BadRequest().django_response({
"reason": "not-fast-forward",
- "message": "You must first update yout branch to the latest version."
+ "message": "You must first update your branch to the latest version."
+ })
+
+ if base_doc.parentof(doc) or base_doc.has_parent_from(doc):
+ return response.SuccessAllOk().django_response({
+ "result": "no-op"
})
# check for unresolved conflicts
if base_doc.has_conflict_marks():
- return response.BadRequest().django_response({
+ return response.BadRequest().django_response({
"reason": "unresolved-conflicts",
"message": "There are unresolved conflicts in your file. Fix them, and try again."
})
# Same goes for shared view
return response.SuccessAllOk().django_response({
+ "result": "success",
"name": user_doc_new.id,
"user": user_doc_new.owner,
--- /dev/null
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-10-19 14:34:42$"
+__doc__ = "Module documentation."
+
+#import api.forms as forms
+#import api.response as response
+#
+#from api.utils import validate_form, hglibrary
+#from api.models import PartCache
+#
+
+#
+#from piston.handler import BaseHandler
+#
+#from wlrepo import *
+
+import re
+from library_handlers import *
+
+import librarian
+from librarian import parser
+
+#
+# Document Text View
+#
+
+XINCLUDE_REGEXP = r"""<(?:\w+:)?include\s+[^>]*?href=("|')wlrepo://(?P<link>[^\1]+?)\1\s*[^>]*?>"""
+#
+#
+#
+
+class DocumentTextHandler(BaseHandler):
+ allowed_methods = ('GET', 'POST')
+
+ @validate_form(forms.TextRetrieveForm, 'GET')
+ @hglibrary
+ def read(self, request, form, docid, lib):
+ """Read document as raw text"""
+ try:
+ revision = form.cleaned_data['revision']
+ chunk = form.cleaned_data['chunk']
+ user = form.cleaned_data['user'] or request.user.username
+ format = form.cleaned_data['format']
+
+ document = lib.document_for_rev(revision)
+
+ if document.id != docid:
+ return response.BadRequest().django_response({
+ 'reason': 'name-mismatch',
+ 'message': 'Provided revision is not valid for this document'
+ })
+
+ if document.owner != user:
+ return response.BadRequest().django_response({
+ 'reason': 'user-mismatch',
+ 'message': "Provided revision doesn't belong to user %s" % user
+ })
+
+ for error in check_user(request, user):
+ return error
+
+ if not chunk:
+ return document.data('xml')
+
+ xdoc = parser.WLDocument.from_string(document.data('xml'),\
+ parse_dublincore=False)
+
+ xchunk = xdoc.chunk(chunk)
+
+ if xchunk is None:
+ return response.EntityNotFound().django_response({
+ 'reason': 'no-part-in-document',
+ 'path': chunk
+ })
+
+ return librarian.serialize_children(xchunk, format=format)
+
+ except librarian.ParseError, e:
+ return response.EntityNotFound().django_response({
+ 'reason': 'invalid-document-state',
+ 'exception': type(e),
+ 'message': e.message
+ })
+ except (EntryNotFound, RevisionNotFound), e:
+ return response.EntityNotFound().django_response({
+ 'reason': 'not-found',
+ 'exception': type(e), 'message': e.message
+ })
+
+ @validate_form(forms.TextUpdateForm, 'POST')
+ @hglibrary
+ def create(self, request, form, docid, lib):
+ try:
+ revision = form.cleaned_data['revision']
+ msg = form.cleaned_data['message']
+ user = form.cleaned_data['user'] or request.user.username
+
+ # do not allow changing not owned documents
+ # (for now... )
+
+
+ if user != request.user.username:
+ return response.AccessDenied().django_response({
+ 'reason': 'insufficient-priviliges',
+ })
+
+ current = lib.document(docid, user)
+ orig = lib.document_for_rev(revision)
+
+ if current != orig:
+ return response.EntityConflict().django_response({
+ "reason": "out-of-date",
+ "provided_revision": orig.revision,
+ "latest_revision": current.revision })
+
+ if form.cleaned_data.has_key('contents'):
+ data = form.cleaned_data['contents']
+ else:
+ chunks = form.cleaned_data['chunks']
+ xdoc = parser.WLDocument.from_string(current.data('xml'))
+ errors = xdoc.merge_chunks(chunks)
+
+ if len(errors):
+ return response.EntityConflict().django_response({
+ "reason": "invalid-chunks",
+ "message": "Unable to merge following parts into the document: %s " % ",".join(errors)
+ })
+
+ data = xdoc.serialize()
+
+ # try to find any Xinclude tags
+ includes = [m.groupdict()['link'] for m in (re.finditer(\
+ XINCLUDE_REGEXP, data, flags=re.UNICODE) or []) ]
+
+ log.info("INCLUDES: %s", includes)
+
+ # TODO: provide useful routines to make this simpler
+ def xml_update_action(lib, resolve):
+ try:
+ f = lib._fileopen(resolve('parts'), 'r')
+ stored_includes = json.loads(f.read())
+ f.close()
+ except:
+ stored_includes = []
+
+ if stored_includes != includes:
+ f = lib._fileopen(resolve('parts'), 'w+')
+ f.write(json.dumps(includes))
+ f.close()
+
+ lib._fileadd(resolve('parts'))
+
+ # update the parts cache
+ PartCache.update_cache(docid, current.owner,\
+ stored_includes, includes)
+
+ # now that the parts are ok, write xml
+ f = lib._fileopen(resolve('xml'), 'w+')
+ f.write(data.encode('utf-8'))
+ f.close()
+
+ ndoc = None
+ ndoc = current.invoke_and_commit(\
+ xml_update_action, lambda d: (msg, user) )
+
+ try:
+ # return the new revision number
+ return response.SuccessAllOk().django_response({
+ "document": ndoc.id,
+ "user": user,
+ "subview": "xml",
+ "previous_revision": current.revision,
+ "revision": ndoc.revision,
+ 'timestamp': ndoc.revision.timestamp,
+ "url": reverse("doctext_view", args=[ndoc.id])
+ })
+ except Exception, e:
+ if ndoc: lib._rollback()
+ raise e
+ except RevisionNotFound, e:
+ return response.EntityNotFound(mimetype="text/plain").\
+ django_response(e.message)
#
import api.handlers.library_handlers as dh
+from api.handlers.text_handler import DocumentTextHandler
+
library_resource = Resource(dh.LibraryHandler, **authdata)
document_resource = Resource(dh.DocumentHandler, **authdata)
-document_text_resource = Resource(dh.DocumentTextHandler, **authdata)
+document_text_resource = Resource(DocumentTextHandler, **authdata)
document_html_resource = Resource(dh.DocumentHTMLHandler, **authdata)
# document_dc_resource = Resource(dh.DocumentDublinCoreHandler, **authdata)
document_gallery = Resource(dh.DocumentGalleryHandler, **authdata)
def django_response(self, ticket_status, ticket_uri):
return ResponseObject.django_response(self, {
+ 'result': 'accepted',
'status': ticket_status,
'refer_to': ticket_uri })
def parentof(self, other):
return self._revision.parentof(other._revision)
+ def has_parent_from(self, other):
+ return self._revision.has_parent_from(other._revision)
+
def ancestorof(self, other):
return self._revision.ancestorof(other._revision)
def open_library(path, proto, *args, **kwargs):
if proto == 'hg':
- import wlrepo.mercurial_backend
- return wlrepo.mercurial_backend.MercurialLibrary(path, *args, **kwargs)
+ import wlrepo.mercurial_backend.library
+ return wlrepo.mercurial_backend.library.MercurialLibrary(path, *args, **kwargs)
raise NotImplemented()
\ No newline at end of file
__doc__ = "Module documentation."
import wlrepo
-from mercurial.node import nullid
-
-from mercurial import encoding
-encoding.encoding = 'utf-8'
-
-class MercurialRevision(wlrepo.Revision):
-
- def __init__(self, lib, changectx):
- super(MercurialRevision, self).__init__(lib)
- self._changectx = changectx
-
- branchname = self._changectx.branch()
- if branchname.startswith("$doc:"):
- self._docname = branchname[5:]
- self._username = None
- elif branchname.startswith("$user:"):
- idx = branchname.find("$doc:")
- if(idx < 0):
- raise ValueError("Revision %s is not a valid document revision." % changectx.hex());
- self._username = branchname[6:idx]
- self._docname = branchname[idx+5:]
- else:
- raise ValueError("Revision %s is not a valid document revision." % changectx.hex());
-
- @property
- def document_name(self):
- return self._docname and self._docname.decode('utf-8')
-
- @property
- def user_name(self):
- return self._username and self._username.decode('utf-8')
-
- def hgrev(self):
- return self._changectx.node()
-
- def hgcontext(self):
- return self._changectx
-
- def hgbranch(self):
- return self._changectx.branch()
-
- @property
- def timestamp(self):
- return self._changectx.date()[0]
-
- def __unicode__(self):
- return u"%s" % self._changectx.hex()
-
- def __str__(self):
- return self.__unicode__().encode('utf-8')
-
- def __repr__(self):
- return "%s" % self._changectx.hex()
-
- def ancestorof(self, other):
- nodes = list(other._changectx._parents)
- while nodes[0].node() != nullid:
- v = nodes.pop(0)
- if v == self._changectx:
- return True
- nodes.extend( v._parents )
- return False
-
- def parentof(self, other):
- return self._changectx in other._changectx._parents
-
- def has_common_ancestor(self, other):
- a = self._changectx.ancestor(other._changectx)
- return (a.branch() == self._changectx.branch())
-
- def has_children(self):
- return bool(self._library._hgrepo.changelog.children(self.hgrev()))
-
- def merge_with(self, other, user, message):
- message = self._library._sanitize_string(message)
- lock = self._library.lock(True)
- try:
- self._library._checkout(self._changectx.node())
- status = self._library._merge(other._changectx.node())
- if status.isclean():
- self._library._commit(user=user, message=message)
- return True
- else:
- return False
- finally:
- lock.release()
-
- def __eq__(self, other):
- return self._changectx.node() == other._changectx.node()
-
-
-from wlrepo.mercurial_backend.library import MercurialLibrary
+from mercurial import encoding
+encoding.encoding = 'utf-8'
\ No newline at end of file
return self._library.document_for_rev(fullid)
def up_to_date(self):
- return self.ismain() or (\
- self.shared().ancestorof(self) )
+ if self.ismain():
+ return True
+
+ shared = self.shared()
-
+ if shared.parentof(self):
+ return True
+
+ if shared.has_parent_from(self):
+ return True
+
+ return False
+
def update(self, user):
"""Update parts of the document."""
lock = self.library.lock()
if self.ismain():
# main revision of the document
return self
-
- if self._revision.has_children():
- raise UpdateException("Revision has children.")
- sv = self.shared()
+ # check for children in this branch
+ if self._revision.has_children(limit_branch=True):
+ raise wlrepo.UpdateException("Revision %s has children." % self.revision)
- if self.parentof(sv):
+ shared = self.shared()
+
+ # the shared version comes from our version
+ if self.parentof(self.shared()):
+ return self
+
+ # no changes since last update
+ if shared.ancestorof(self):
return self
- if sv.ancestorof(self):
+ # last share was from this branch
+ if shared.has_parent_from(self):
return self
if self._revision.merge_with(sv._revision, user=user,\
message="$AUTO$ Personal branch update."):
return self.latest()
else:
- raise UpdateException("Merge failed.")
+ raise wlrepo.UpdateException("Merge failed.")
finally:
lock.release()
def share(self, message):
lock = self.library.lock()
try:
+
+ # nothing to do
if self.ismain():
- return False # always shared
+ return self
- user = self._revision.user_name
- main = self.shared()._revision
- local = self._revision
+ shared = self.shared()
- # Case 1:
+ # we just did this - move on
+ if self.parentof(shared):
+ return shared
+
+ # No changes since update
+ if shared.parentof(self):
+ return shared
+
+ # The good situation
+ #
# * local
# |
- # * <- can also be here!
- # /|
+ # >*
+ # ||
# / |
# main * *
# | |
- # The local branch has been recently updated,
- # so we don't need to update yet again, but we need to
- # merge down to default branch, even if there was
- # no commit's since last update
- #
- # This is actually the only good case!
- if main.ancestorof(local):
- success, changed = main.merge_with(local, user=user, message=message)
+ if shared.ancestorof(self):
+ success = shared._revision.merge_with(self._revision, user=self.owner, message=message)
if not success:
- raise LibraryException("Merge failed.")
-
- return changed
-
- # Case 2:
- # main *
- # |
- # * <- this case overlaps with previos one
- # |\
- # | \
- # | * local
- # | |
- #
- # There was a recent merge to the defaul branch and
- # no changes to local branch recently.
- #
- # Nothing to do
- elif local.ancestorof(main):
- return False
+ raise wlrepo.LibraryException("Merge failed.")
+
+ return shared.latest()
- # In all other cases, the local needs an update
- # and possibly conflict resolution, so fail
- raise LibraryExcepton("Document not prepared for sharing.")
-
+ raise wlrepo.LibraryException("Unrecognized share-state.")
finally:
lock.release()
from mercurial import error
import wlrepo
-from wlrepo.mercurial_backend import MercurialRevision
+from wlrepo.mercurial_backend.revision import MercurialRevision
from wlrepo.mercurial_backend.document import MercurialDocument
class MergeStatus(object):
--- /dev/null
+# -*- encoding: utf-8 -*-
+
+__author__= "Łukasz Rekucki"
+__date__ = "$2009-10-20 12:31:48$"
+__doc__ = "Module documentation."
+
+import wlrepo
+from mercurial.node import nullid
+
+class MercurialRevision(wlrepo.Revision):
+ def __init__(self, lib, changectx):
+ super(MercurialRevision, self).__init__(lib)
+ self._changectx = changectx
+
+ branchname = self._changectx.branch()
+ if branchname.startswith("$doc:"):
+ self._docname = branchname[5:]
+ self._username = None
+ elif branchname.startswith("$user:"):
+ idx = branchname.find("$doc:")
+ if(idx < 0):
+ raise ValueError("Revision %s is not a valid document revision." % changectx.hex());
+ self._username = branchname[6:idx]
+ self._docname = branchname[idx+5:]
+ else:
+ raise ValueError("Revision %s is not a valid document revision." % changectx.hex());
+
+ @property
+ def document_name(self):
+ return self._docname and self._docname.decode('utf-8')
+
+ @property
+ def user_name(self):
+ return self._username and self._username.decode('utf-8')
+
+ def hgrev(self):
+ return self._changectx.node()
+
+ def hgcontext(self):
+ return self._changectx
+
+ def hgbranch(self):
+ return self._changectx.branch()
+
+ @property
+ def timestamp(self):
+ return self._changectx.date()[0]
+
+ def __unicode__(self):
+ return u"%s" % self._changectx.hex()
+
+ def __str__(self):
+ return self.__unicode__().encode('utf-8')
+
+ def __repr__(self):
+ return "%s" % self._changectx.hex()
+
+ def ancestorof(self, other):
+ nodes = list(other._changectx._parents)
+ while nodes[0].node() != nullid:
+ v = nodes.pop(0)
+ if v == self._changectx:
+ return True
+ nodes.extend( v._parents )
+ return False
+
+ def parentof(self, other):
+ return self._changectx in other._changectx._parents
+
+ def has_common_ancestor(self, other):
+ a = self._changectx.ancestor(other._changectx)
+ return (a.branch() == self._changectx.branch())
+
+ def has_children(self, limit_branch=False):
+ for child in self._changectx.children():
+ cbranch = child.branch()
+ if (not limit_branch) or (cbranch == self.hgbranch()):
+ return True
+ return False
+
+ def has_parent_from(self, rev):
+ branch = rev.hgbranch()
+ for parent in self._changectx.parents():
+ if parent.branch() == branch:
+ return True
+ return False
+
+ def merge_with(self, other, user, message):
+ message = self._library._sanitize_string(message)
+ lock = self._library.lock(True)
+ try:
+ self._library._checkout(self._changectx.node())
+ status = self._library._merge(other._changectx.node())
+ if status.isclean():
+ self._library._commit(user=user, message=message)
+ return True
+ else:
+ return False
+ finally:
+ lock.release()
+
+ def __eq__(self, other):
+ return self._changectx.node() == other._changectx.node()
/* Style widoku HTML. Nie należy tu ustawiać position ani marginesów */
.htmlview {
font-size: 16px;
- font: Georgia, "Times New Roman", serif;
+ font-family: "Georgia", "Times New Roman", serif;
line-height: 1.5em;
padding: 3em;
}
font-style: normal;
font-variant: small-caps;
}
+
+.htmlview .parse-warning {
+ display: block;
+ font-size: 10pt;
+ background: #C0C0C0;
+ margin: 1em;
+}
+
+.parse-warning .message {
+ color: purple;
+ font-weight: bold;
+}
\ No newline at end of file
// Handle JSON error responses in uniform way
function parseXHRError(response)
{
- var message = ""
+ var message = "";
+ var level = "";
+
try {
var json = $.evalJSON(response.responseText);
message = message.replace(/(line\s+)(\d+)(\,\s*column\s+)(\d+)/i,
"<a class='xml-editor-ref' href='#xml-$2-$4'>$1$2$3$4</a>");
+
+ level = "warning";
}
else {
- message = json.message || json.reason || "Nieznany błąd :((";
+ message = json.message || json.reason || "Nieznany błąd :((";
+ level = "error";
}
-
} catch(e) {
// not a valid JSON response
- message = response.statusText;
+ message = response.statusText || 'Brak połączenia z serwerem';
+ level = "error";
+ }
+
+ return {error_message: message, error_level: level};
+}
+
+function parseXHRResponse(xhr) {
+ var response = {}
+
+ if(xhr.status >= 200 && xhr.status < 300)
+ {
+ response.success = true;
+ try {
+ response.data = $.evalJSON(xhr.responseText);
+ } catch(e) {
+ response.data = {};
+ }
+
+ return response;
}
- return message;
+
+ return parseXHRError(xhr);
}
Editor.Object._lastGuid = 0;
messageCenter.addMessage('success', 'xmlload', 'Wczytałem XML :-)');
},
- loadingFailed: function() {
+ loadingFailed: function(response)
+ {
if (this.get('state') != 'loading') {
alert('erroneous state:', this.get('state'));
}
+
var message = parseXHRError(response);
this.set('error', '<h2>Błąd przy ładowaniu XML</h2><p>'+message+'</p>');
alert('erroneous state:', this.get('state'));
}
- var message = parseXHRError(response);
+ var err = parseXHRError(response);
- this.set('error', '<p>Nie udało się wczytać widoku HTML: </p>' + message);
+ this.set('error', '<p>Nie udało się wczytać widoku HTML: </p>' + err.error_message);
this.set('state', 'error');
},
data: {
revision: this.get('revision'),
user: this.document.get('user'),
- part: path
+ chunk: path,
+ format: 'nl'
},
success: function(data) {
self.xmlParts[path] = data;
+ console.log(data);
callback(path, data);
},
// TODO: error handling
dataType: 'text; charset=utf-8',
data: {
fragment: data,
- part: path
+ chunk: path,
+ format: 'nl'
},
success: function(htmldata) {
elem.replaceWith(htmldata);
alert('erroneous state:', this.get('state'));
}
- var message = parseXHRError(response);
- this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+message+"</p>");
+ var err = parseXHRError(response);
+ this.set('error', '<h2>Nie udało się wczytać dokumentu</h2><p>'+err.error_message+"</p>");
this.set('state', 'error');
},
revision: this.get('revision'),
user: this.get('user')
},
- complete: this.updateCompleted.bind(this),
- success: function(data) {
- this.set('updateData', data);
- console.log("new data:", data)
- }.bind(this)
+ complete: this.updateCompleted.bind(this),
});
},
- updateCompleted: function(xhr, textStatus) {
- console.log(xhr.status, textStatus);
-
- if (xhr.status == 200)
+ updateCompleted: function(xhr, textStatus)
+ {
+ console.log(xhr.status, xhr.responseText);
+ var response = parseXHRResponse(xhr);
+ if(response.success)
{
- var udata = this.get('updateData');
- if(udata.timestamp == udata.parent_timestamp)
+ if( (response.data.result == 'no-op')
+ || (response.data.timestamp == response.data.parent_timestamp))
{
- // no change
+ if( (response.data.revision) && (response.data.revision != this.get('revision')) )
+ {
+ // we're out of sync
+ this.set('state', 'unsynced');
+ return;
+ }
+
messageCenter.addMessage('info', 'doc_update',
- 'Nic się nie zmieniło od ostatniej aktualizacji. Po co mam uaktualniać?');
+ 'Już posiadasz najbardziej aktualną wersję.');
+ this.set('state', 'synced');
+ return;
+ }
+
+ // result: success
+ this.set('revision', response.data.revision);
+ this.set('user', response.data.user);
+ messageCenter.addMessage('info', 'doc_update',
+ 'Uaktualnienie dokumentu do wersji ' + response.data.revision);
+
+ for (var key in this.contentModels) {
+ this.contentModels[key].set('revision', this.get('revision') );
+ this.contentModels[key].set('state', 'empty');
}
- else {
- this.set('revision', udata.revision);
- this.set('user', udata.user);
- messageCenter.addMessage('info', 'doc_update',
- 'Uaktualnienie dokumentu do wersji ' + udata.revision);
-
- for (var key in this.contentModels) {
- this.contentModels[key].set('revision', this.get('revision') );
- this.contentModels[key].set('state', 'empty');
- }
- }
- } else if (xhr.status == 409) { // Konflikt podczas operacji
- messageCenter.addMessage('error', 'doc_update',
- 'Wystąpił konflikt podczas aktualizacji. Pędź po programistów! :-(');
- } else {
- messageCenter.addMessage('critical', 'doc_update',
- 'Nieoczekiwany błąd. Pędź po programistów! :-(');
+
+ this.set('state', 'synced');
+ return;
}
+
+ // no success means trouble
+ messageCenter.addMessage(response.error_level, 'doc_update',
+ response.error_message);
- this.set('state', 'synced');
- this.set('updateData', null);
+ this.set('state', 'unsynced');
},
merge: function(message) {
this.set('state', 'loading');
- messageCenter.addMessage('info', null,
+ messageCenter.addMessage('info', 'doc_merge',
'Scalam dokument z głównym repozytorium...');
$.ajax({
},
mergeCompleted: function(xhr, textStatus) {
- console.log(xhr.status, textStatus);
- if (xhr.status == 200) { // Sukces
- this.set('revision', this.get('updateData').revision);
- this.set('user', this.get('updateData').user);
-
- for (var key in this.contentModels) {
- this.contentModels[key].set('revision', this.get('revision'));
- this.contentModels[key].set('state', 'empty');
+ console.log(xhr.status, xhr.responseText);
+ var response = parseXHRResponse(xhr);
+ if(response.success)
+ {
+ if( (response.data.result == 'no-op')
+ || (response.data.shared_timestamp == response.data.shared_parent_timestamp))
+ {
+ if( (response.data.revision) && (response.data.revision != this.get('revision')) )
+ {
+ // we're out of sync
+ this.set('state', 'unsynced');
+ return;
+ }
+
+ messageCenter.addMessage('info', 'doc_merge',
+ 'Twoja aktualna wersja nie różni się od ostatnio zatwierdzonej.');
+ this.set('state', 'synced');
+ return;
+ }
+
+ if( response.data.result == 'accepted')
+ {
+ messageCenter.addMessage('info', 'doc_merge',
+ 'Prośba o zatwierdzenie została przyjęta i oczekuję na przyjęcie.');
+ this.set('state', 'synced');
+ return;
}
- messageCenter.addMessage('success', null, 'Scaliłem dokument z głównym repozytorium :-)');
- } else if (xhr.status == 202) { // Wygenerowano PullRequest
- messageCenter.addMessage('success', null, 'Wysłałem prośbę o scalenie dokumentu z głównym repozytorium.');
- } else if (xhr.status == 204) { // Nic nie zmieniono
- messageCenter.addMessage('info', null, 'Nic się nie zmieniło od ostatniego scalenia. Po co mam scalać?');
- } else if (xhr.status == 409) { // Konflikt podczas operacji
- messageCenter.addMessage('error', null, 'Wystąpił konflikt podczas scalania. Pędź po programistów! :-(');
- } else if (xhr.status == 500) {
- messageCenter.addMessage('critical', null, 'Błąd serwera. Pędź po programistów! :-(');
+ // result: success
+ this.set('revision', response.data.revision);
+ this.set('user', response.data.user);
+
+ messageCenter.addMessage('info', 'doc_merge',
+ 'Twoja wersja dokumentu została zatwierdzona.');
+
+ this.set('state', 'synced');
+ return;
}
- this.set('state', 'synced');
- this.set('mergeData', null);
+
+ // no success means trouble
+ messageCenter.addMessage(response.error_level, 'doc_merge',
+ response.error_message);
+
+ this.set('state', 'unsynced');
},
// For debbuging
$('#commit-dialog').jqmHide();
});
+ $('#commit-dialog-save-button').click(function(event, data)
+ {
+ if ($('#commit-dialog-message').val().match(/^\s*$/)) {
+ $('#commit-dialog-error-empty-message').fadeIn();
+ } else {
+ $('#commit-dialog-error-empty-message').hide();
+ $('#commit-dialog').jqmHide();
+
+ var message = $('#commit-dialog-message').val();
+ $('#commit-dialog-related-issues input:checked')
+ .each(function() {
+ message += ' refs #' + $(this).val();
+ });
+
+ var ctx = $('#commit-dialog').data('context');
+ console.log("COMMIT APROVED", ctx);
+ ctx.callback(message);
+ }
+ return false;
+ });
+
// $('#split-dialog').jqm({
// modal: true,
loadRelatedIssues: function(hash) {
var self = this;
var c = $('#commit-dialog-related-issues');
-
- $('#commit-dialog-save-button').click(function(event, data)
- {
- if ($('#commit-dialog-message').val().match(/^\s*$/)) {
- $('#commit-dialog-error-empty-message').fadeIn();
- } else {
- $('#commit-dialog-error-empty-message').hide();
- $('#commit-dialog').jqmHide();
-
- var message = $('#commit-dialog-message').val();
- $('#commit-dialog-related-issues input:checked')
- .each(function() {
- message += ' refs #' + $(this).val();
- });
- console.log("COMMIT APROVED", hash.t);
- hash.t.callback(message);
- }
- return false;
- });
+
+ $('#commit-dialog').data('context', hash.t);
$("div.loading-box", c).show();
$("div.fatal-error-box", c).hide();
this.commitButton.attr('disabled', null);
this.updateButton.attr('disabled', 'disabled');
this.mergeButton.attr('disabled', 'disabled');
- } else if (value == 'synced') {
+ } else if (value == 'synced' || value == 'unsynced') {
this.quickSaveButton.attr('disabled', 'disabled');
this.commitButton.attr('disabled', 'disabled');
this.updateButton.attr('disabled', null);
url(r'^file/upload', 'explorer.views.file_upload', name='file_upload'),
- url(r'^managment/pull-requests$', 'explorer.views.pull_requests'),
+ url(r'^management/pull-requests$', 'explorer.views.pull_requests'),
# url(r'^images/(?P<folder>[^/]+)/$', 'explorer.views.folder_images', name='folder_image'),
# url(r'^images/$', 'explorer.views.folder_images', {'folder': '.'}, name='folder_image_ajax'),