if form.cleaned_data['generate_dc']:
data = librarian.wrap_text(data, unicode(date.today()))
+ # TODO: what if the file exists ?
doc = cab.create(form.cleaned_data['bookname'], initial_data=data)
return {
shared = lib.main_cabinet.retrieve(docid)
+ is_shared = document.ancestorof(shared)
+ # is_uptodate = is_shared or shared.ancestorof(document)
+
result = {
'name': document.name,
'size': document.size,
'parts_url': reverse('docparts_view', args=[docid]),
'latest_rev': document.shelf(),
'latest_shared_rev': shared.shelf(),
- #'shared': lib.isparentof(document, shared),
- #'up_to_date': lib.isparentof(shared, document),
+ 'shared': is_shared,
+ # 'up_to_date': is_uptodate,
}
- if request.GET.get('with_part', 'no') == 'yes':
- result['parts'] = document.parts()
+ #if request.GET.get('with_part', 'no') == 'yes':
+ # result['parts'] = document.parts()
return result
def read(self, request, docid):
"""Read document as raw text"""
lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
- try:
+ try:
+ # latest rev
+ # comment
return lib.document(docid, request.user.username).read()
except CabinetNotFound:
return rc.NOT_HERE
def update(self, request, docid):
lib = MercurialLibrary(path=settings.REPOSITORY_PATH)
try:
+ # check latest REV
data = request.PUT['contents']
lib.document(docid, request.user.username).write(data)
return rc.ALL_OK
{% endfor %}
</span>
- <div class="toolbar-tabs-container">
+ <div class="toolbar-tabs-container toolbar-buttons-container">
<p>
{% for group in toolbar_groups %}
<button ui:group="{{ group.slug }}" {% if forloop.first %}class="active"{% endif %}>
pass
+ def document(self, docid, user, part=None, shelve=None):
+ pass
+
+
class Cabinet(object):
def __init__(self, library, name=None, doc=None, user=None):
def __str__(self):
return "Cabinet(%s)" % self._name
- def documents(self):
- """Lists all documents and sub-documents in this cabinet."""
+ def parts(self):
+ """Lists all parts in this cabinet."""
pass
- def retrieve(self, parts=None, shelve=None):
+ def retrieve(self, part='xml', shelve=None):
"""Retrieve a document from a given shelve in the cabinet. If no
part is given, the main document is retrieved. If no shelve is given,
the top-most shelve is used.
pass
def create(self, name, initial_data=''):
- """Create a new sub-document in the cabinet with the given name."""
+ """Create a new part in the cabinet with the given name."""
pass
@property
@property
def parts(self):
raise NotImplemented()
+
+ def parentof(self, other):
+ return self.shelf().parentof(other.shelf())
+
+ def ancestorof(self, other):
+ return self.shelf().ancestorof(other.shelf())
class Shelf(object):
def __init__(self, lib):
- self._library = lib
+ self._library = lib
+
+
+ def parentof(self, other):
+ return False
+
+ def ancestorof(self, other):
+ return False
#
# Exception classes
def main_cabinet(self):
return self._maincab
- def document(self, docid, user):
- return self.cabinet(docid, user, create=False).retrieve()
+ def document(self, docid, user, part=None, shelve=None):
+ return self.cabinet(docid, user, create=False).retrieve(part=part, shelve=shelve)
def cabinet(self, docid, user, create=False):
docid = self._sanitize_string(docid)
else:
raise ValueError("Provide either doc/user or branchname")
- def shelf(self, selector=None):
+ def shelf(self):
return self._library.shelf(self._branchname)
- def documents(self):
+ def parts(self):
return self._execute_in_branch(action=lambda l, c: (e[1] for e in l._filelist()))
def retrieve(self, part=None, shelf=None):
return self._library._transaction(write_mode=write, action=switch_action)
- def _filename(self, part):
- part = self._library._sanitize_string(part)
- docid = None
- if self._maindoc == '':
- if part is None: rreeturn [None, None]
- docid = part
- else:
- docid = self._maindoc + (('$' + part) if part else '')
+ def _filename(self, docid):
+ return self._partname(docid, 'xml')
+
+ def _partname(self, docid, part):
+ docid = self._library._sanitize_string(part)
+ part = self._library._sanitize_string(part)
- return docid, 'pub_' + docid + '.xml'
+ if part is None:
+ part = 'xml'
+ if self._maindoc == '' and docid is None:
+ return None
+
+ return 'pub_' + docid + '.' + part
+
def _fileopener(self):
return self._library._fileopener()
class MercurialDocument(wlrepo.Document):
- def __init__(self, cabinet, name, fileid):
- super(MercurialDocument, self).__init__(cabinet, name=name)
+ def __init__(self, cabinet, docid):
+ super(MercurialDocument, self).__init__(cabinet, name=docid)
self._opener = self._cabinet._fileopener()
- self._fileid = fileid
- self.refresh()
+ self._docid = docid
+ self._ctxs = {}
+
+ def _ctx(self, part):
+ if not self._ctxs.has_key(part):
+ self._ctxs[part] = self._cabinet._filectx(self._fileid())
+ return self._ctxs[part]
- def refresh(self):
- self._filectx = self._cabinet._filectx(self._fileid)
+ def _fileid(self, part='xml'):
+ return self._cabinet._partname(self._docid, part)
- def read(self):
- return self._opener(self._filectx.path(), "r").read()
+ def read(self, part='xml'):
+ return self._opener(self._ctx(part).path(), "r").read()
- def write(self, data):
- return self._opener(self._filectx.path(), "w").write(data)
+ def write(self, data, part='xml'):
+ return self._opener(self._ctx(part).path(), "w").write(data)
def commit(self, message, user):
+ """Commit all parts of the document."""
self.library._fileadd(self._fileid)
self.library._commit(self._fileid, message, user)
def update(self):
+ """Update parts of the document."""
lock = self.library._lock()
try:
if self._cabinet.ismain():
def shared(self):
return self.library.main_cabinet.retrieve(self._name)
- def exists(self):
- return self._cabinet.exists(self._fileid)
+ def exists(self, part='xml'):
+ return self._cabinet.exists(self._fileid(part))
@property
def size(self):
return self._filectx.size()
def shelf(self):
- return MercurialShelf(self.library, self._filectx.node())
+ return self._cabinet.shelf()
@property
def last_modified(self):
mcab = library.main_cabinet
assert_equal(mcab.maindoc_name, '')
- doclist = mcab.documents()
+ doclist = mcab.parts()
assert_equal( list(doclist), ['valid_file'])
@temprepo('simple')
@temprepo('branched')
def test_switch_branch(library):
tester_cab = library.cabinet("valid_file", "tester", create=False)
- assert_equal( list(tester_cab.documents()), ['valid_file'])
+ assert_equal( list(tester_cab.parts()), ['valid_file'])
@raises(wlrepo.CabinetNotFound)
@temprepo('branched')
@temprepo('clean')
def test_create_branch(library):
tester_cab = library.cabinet("anotherone", "tester", create=True)
- assert_equal( list(tester_cab.documents()), ['anotherone'])
+ assert_equal( list(tester_cab.parts()), ['anotherone'])
'explorer',
'toolbar',
'api',
+ 'wysiwyg',
)
#split-dialog .container-box fieldset {
margin: 0.5em;
+}
+
+.CodeMirror-line-numbers
+{
+ text-align: right;
+ padding-top: 0.4em;
+ padding-right: 2px;
+ width: 28px;
+ font-size: 10pt;
+ background: black;
+ color: white;
}
\ No newline at end of file
padding: 0px;
}
-.toolbar-tabs-container button.active {
- background: #DDD;
-}
-
.toolbar-buttons-container {
background: #DDD;
padding-top: 2px;
background: inherit;
}
-/*
-.toolbar, .toolbar ol {
- display: block;
- margin: 0;
- padding: 0;
- background-color: #CCC;
- border-top: 1px solid #AAA;
-}
-
-.toolbar-tabs li {
- font-size: 14px;
- display: block;
- float: left;
- margin: 4px 0 -1px 4px;
- padding: 2px 10px 0 10px;
- background-color: #CCC;
- border: 1px solid #AAA;
- border-radius-topleft: 8px;
- border-radius-topright: 8px;
- -moz-border-radius-topleft: 8px;
- -moz-border-radius-topright: 8px;
- -webkit-border-top-left-radius: 8px;
- -webkit-border-top-right-radius: 8px;
-}
-
-.toolbar-tabs {
- height: 21px;
+.toolbar-tabs-container > p {
+ background: #CCC;
}
-.toolbar-tabs li:hover, .toolbar-tabs li.active {
- cursor: default;
- background-color: #EEE;
- border-bottom: 1px solid #EEE;
+.toolbar-tabs-container > p button {
+ background: #CCC;
}
-.toolbar-buttons {
- background-color: #EEE;
- border-bottom: 1px solid #AAA;
- z-index: 71;
-}
-
-.toolbar-buttons li {
- display: block;
- font-size: 12px;
- padding: 1px 8px;
- margin: 4px;
- border-radius: 10px;
- -moz-border-radius: 10px;
- -webkit-border-radius: 8px;
- float: left;
-}
-
-.toolbar-buttons li:hover {
- background-color: #777;
- color: #FFF;
- cursor: default;
-} */
-
+.toolbar-tabs-container button.active {
+ background: #DDD;
+}
\ No newline at end of file
// move the extra
var extra_buttons = $('span.panel-toolbar-extra button', toolbar);
var placeholder = $('div.panel-toolbar span.panel-toolbar-extra > span', this.wrap);
- placeholder.replaceWith(extra_buttons);
-
- var action_buttons = $('button', extra_buttons);
+ placeholder.replaceWith(extra_buttons);
// connect group-switch buttons
var group_buttons = $('*.toolbar-tabs-container button', toolbar);
});
// connect action buttons
- var allbuttons = $.makeArray(action_buttons);
+ var allbuttons = $.makeArray(extra_buttons);
$.merge(allbuttons,
$.makeArray($('*.toolbar-button-groups-container button', toolbar)) );
function wrapLineNumberDiv(place) {
return function(node) {
+
var container = document.createElement("DIV"),
nums = document.createElement("DIV"),
scroller = document.createElement("DIV");
- container.style.position = "relative";
+
nums.style.position = "absolute";
- nums.style.height = "100%";
+ nums.style.height = "100%";
if (nums.style.setExpression) {
try {nums.style.setExpression("height", "this.previousSibling.offsetHeight + 'px'");}
catch(e) {} // Seems to throw 'Not Implemented' on some IE8 versions
}
nums.style.top = "0px";
- nums.style.overflow = "hidden";
+ nums.style.overflow = "hidden";
+
+ container.style.position = "absolute";
+ container.style.left = "0px";
+ container.style.right = "0px";
+ container.style.bottom = "0px";
+ container.style.top = "0px";
+
+ node.style.position = "absolute";
+ node.style.top = "0px";
+ node.style.right = "0px";
+ node.style.bottom = "0px";
+ node.style.left = "16px"
+
place(container);
- container.appendChild(node);
+ container.appendChild(node);
container.appendChild(nums);
scroller.className = "CodeMirror-line-numbers";
nums.appendChild(scroller);
function applyLineNumbers(frame) {
var win = frame.contentWindow, doc = win.document,
- nums = frame.nextSibling, scroller = nums.firstChild;
+ nums = frame.parentNode.nextSibling, scroller = nums.firstChild;
var nextNum = 1, barWidth = null;
function sizeBar() {
if (nums.offsetWidth != barWidth) {
barWidth = nums.offsetWidth;
- nums.style.left = "-" + (frame.parentNode.style.marginLeft = barWidth + "px");
+ // nums.style.left = "-" + (frame.parentNode.style.marginLeft = barWidth + "px");
}
}
function update() {
frame.frameBorder = 0;
frame.src = "javascript:false;";
frame.style.border = "0";
- frame.style.width = options.width;
- frame.style.height = options.height;
+ frame.style.width = "100%";
+ frame.style.height = "100%";
// display: block occasionally suppresses some Firefox bugs, so we
// always add it, redundant as it sounds.
frame.style.display = "block";
var node = place;
place = function(n){node.appendChild(n);};
}
- if (options.lineNumbers) place = wrapLineNumberDiv(place);
- place(frame);
+
+ var iframe_container = document.createElement("DIV");
+ iframe_container.appendChild(frame);
+
+ var content_wrapper = document.createElement("DIV");
+ content_wrapper.appendChild(iframe_container);
+ content_wrapper.style.position = 'relative';
+ content_wrapper.className = 'CodeMirror-content-wrapper';
+
+ iframe_container.style.position = 'absolute';
+ iframe_container.style.top = '0px';
+ iframe_container.style.right = '0px';
+ iframe_container.style.bottom = '0px';
+ iframe_container.style.left = '28px';
+
+ if (options.lineNumbers) {
+ var nums = document.createElement("DIV"),
+ scroller = document.createElement("DIV");
+
+ nums.style.position = "absolute";
+ nums.style.height = "100%";
+
+ nums.style.top = "0px";
+ nums.style.left = "0px";
+ nums.style.overflow = "hidden";
+
+ scroller.className = "CodeMirror-line-numbers";
+ nums.appendChild(scroller);
+ content_wrapper.appendChild(nums);
+
+ iframe_container.style.right = nums.width;
+ }
+
+ place(content_wrapper);
// Link back to this object, so that the editor can fetch options
// and add a reference to itself.
<title>{% block title %}Platforma Redakcyjna{% block subtitle %}{% endblock subtitle %}{% endblock title%}</title>
<link rel="stylesheet" href="{{ STATIC_URL }}css/master.css" type="text/css" />
<script src="{{ STATIC_URL }}js/lib/jquery.js" type="text/javascript" charset="utf-8"></script>
- <script src="{{ STATIC_URL }}js/lib/jquery.logging.js" type="text/javascript" charset="utf-8"></script>
+ <script src="{{ STATIC_URL }}js/lib/jquery.logging.js" type="text/javascript" charset="utf-8"></script>
{% block extrahead %}
{% endblock %}
</head>
</div>
<div id="content">{% block maincontent %} {% endblock %}</div>
- {% block extrabody %} {% endblock %}
+ {% block extrabody %}{% endblock %}
</body>
</html>
var texteditor = CodeMirror.fromTextArea(textareaId, {
parserfile: 'parsexml.js',
path: "{{STATIC_URL}}js/lib/codemirror/",
+ width: 'auto',
stylesheet: "{{STATIC_URL}}css/xmlcolors.css",
parserConfig: {useHTMLKludges: false},
+ textWrapping: false,
+ lineNumbers: true,
onChange: function() {
self.fireEvent('contentChanged');
},
}
})
- $(texteditor.frame).css({width: '100%', height: '100%'});
+ $('.CodeMirror-content-wrapper').css({
+ width: '100%', height: '100%' });
+
this.texteditor = texteditor;
self._endload();
},
+# -*- coding: utf-8 -*-
+
from django.conf.urls.defaults import *
from django.contrib import admin
from django.conf import settings
url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'redirect_field_name': 'next'}),
url(r'^accounts/logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}),
- # Our uber-restful api
+ # Prototypes
+ url(r'^wysiwyg-proto/', include('wysiwyg.urls')),
+
+ # Our über-restful api
url(r'^api/', include('api.urls') ),
)
Publication.delete_all()
repos = Repository.all
if repos
- repos.each do |repo|
- repo_status = []
- if repo.entries
- repo.entries.each do |entry|
- match = entry.path.match(regexp)
- if match
- Publication.find_or_create_by_name(:name => match[1],
- :source_file => entry.path, :repository_id => repo.id)
- repo_status += [{:path => entry.path, :match => match[1], :matched => true}]
- else
- repo_status += [{:path => entry.path, :match =>nil, :matched => false}]
+ repos.each do |repo|
+ repo_status = []
+ if repo.entries
+ repo.entries.each do |entry|
+ match = entry.path.match(regexp)
+ if match
+ Publication.find_or_create_by_name(:name => match[1],
+ :source_file => entry.path, :repository_id => repo.id)
+ repo_status += [{:path => entry.path, :match => match[1], :matched => true}]
+ else
+ repo_status += [{:path => entry.path, :match =>nil, :matched => false}]
+ end
+ end
+ @match_status += [{:repo => repo, :status => repo_status}]
end
end
- @match_status += [{:repo => repo, :status => repo_status}]
- end
- end
- respond_to do |format|
- format.html
- format.xml { render :xml => @match_status}
- format.json { render :json => @match_status }
- end
+ respond_to do |format|
+ format.html
+ format.xml { render :xml => @match_status}
+ format.json { render :json => @match_status }
+ end
end
end
@issues = Issue.all(:joins => joins, :conditions => conditions)
respond_to do |fmt|
- fmt.json { render :json => @issues, :callback => params[:callback] }
+ fmt.json { render :json => @issues, :callback => params[:callback] }
end
end
<div>
-<p><label for="issue_source_files">Publication(s)</label>
+<p><label for="issue_source_files"><%= l(:field_publications) %>:</label>
<input type='text' id='publications' name="publications" size="50"
value='<%= @issue.publication_names.join(', ') %>' />
</div>
<tr>
- <td><b>Publication(s)</b></td>
+ <td><b><%= l(:field_publications) %>:</b></td>
<td>
<% @issue.publication_names.each do |pub| %>
<a href="<%= Setting.plugin_redmine_publications[:editorurl].sub(':pubid', pub) %>"><%= pub %></a><br />
unless Issue.included_modules.include? RedminePublications::IssuePatch
Issue.send(:include, RedminePublications::IssuePatch)
end
+
+ unless Change.included_modules.include? RedminePublications::ChangePatch
+ Change.send(:include, RedminePublications::ChangePatch)
+ end
end
require_dependency 'issue_publication_hook'
--- /dev/null
+module RedminePublications
+ # Patches Redmine's Issues dynamically. Adds a +after_save+ filter.
+
+ module ChangePatch
+ def self.included(base) # :nodoc:
+ base.extend(ClassMethods)
+
+ base.send(:include, InstanceMethods)
+
+ # Same as typing in the class
+ base.class_eval do
+ unloadable # Send unloadable so it will not be unloaded in development
+ after_save :update_publication
+ end
+
+ end
+
+ module ClassMethods
+ end
+
+ module InstanceMethods
+
+ def update_publication
+ if self.action == 'A'
+ regexp = Regexp.new(Setting.plugin_redmine_publications[:pattern])
+ match = self.path.match(regexp)
+ Rails.logger.info('[INFO] Adding publication: "' << match[1])
+ Publication.find_or_create_by_name(:name => match[1],
+ :source_file => self.path, :repository_id => self.changeset.repository.id )
+ end
+ end
+
+ end
+
+ end
+
+
+end
base.class_eval do
unloadable # Send unloadable so it will not be unloaded in development
- validate :check_relations
- after_save :update_relations
+ validate :check_relations
+ after_save :update_relations
end
end
module InstanceMethods
def publication_names
- if not @pubnames
- self.publications.map { |pub| pub.name }
+ if not @pubnames
+ self.publications.map { |pub| pub.name }
else
- @pubnames
- end
+ @pubnames
+ end
end
def publication_names=(value)
- @pubnames = value.sort!
+ @pubnames = value.sort!
end
def publications
Publication.all(
- :joins =>
- "JOIN issue_publications ON (issue_publications.publication_id = publications.id)",
- :conditions =>
- ["issue_publications.issue_id = ? ", self.id] )
+ :joins =>
+ "JOIN issue_publications ON (issue_publications.publication_id = publications.id)",
+ :conditions =>
+ ["issue_publications.issue_id = ? ", self.id] )
end
def check_relations
- current_names = self.publication_names
- non_existant = []
+ current_names = self.publication_names
+ non_existant = []
- pubs = Publication.find_all_by_name(current_names).map {|i| i.name}
- missing = current_names.select {|name| not pubs.include?name }
+ pubs = Publication.find_all_by_name(current_names).map {|i| i.name}
+ missing = current_names.select {|name| not pubs.include?name }
- if not missing.empty?
- errors.add("publications", "Missing publication(s): " + missing.join(', '))
- end
- end
+ if not missing.empty?
+ errors.add("publications", "Missing publication(s): " + missing.join(', '))
+ end
+ end
- def update_relations
- old = self.publications
- current_names = self.publication_names
- Rails.logger.info('[INFO] Updating relations: old= ' << old.inspect << ' current=' << current_names.inspect)
+ def update_relations
+ old = self.publications
+ current_names = self.publication_names
+ Rails.logger.info('[INFO] Updating relations: old= ' << old.inspect << ' current=' << current_names.inspect)
- # delete unused relations
- deleted = old.select { |v| not (current_names.include?(v.name)) }
- deleted.each do |pub|
- IssuePublication.delete_all(["issue_publications.issue_id = ? AND issue_publications.publication_id = ?", self.id, pub.id])
- end
+ # delete unused relations
+ deleted = old.select { |v| not (current_names.include?(v.name)) }
+ deleted.each do |pub|
+ IssuePublication.delete_all(["issue_publications.issue_id = ? AND issue_publications.publication_id = ?", self.id, pub.id])
+ end
- current_names.each do |name|
- pub = Publication.find_by_name(name)
- IssuePublication.find_or_create_by_publication_id_and_issue_id(pub.id, self.id)
- end
+ current_names.each do |name|
+ pub = Publication.find_by_name(name)
+ IssuePublication.find_or_create_by_publication_id_and_issue_id(pub.id, self.id)
+ end
return true
- end
+ end
end
end
--- /dev/null
+## YAML Template.
+en:
+ field_publications: Publications
--- /dev/null
+## YAML Template.
+pl:
+ field_publications: Publikacje