Merge branch 'versions/next' into feature/quick_label

Signed-off-by: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>
This commit is contained in:
Roberto Rosario
2018-08-14 00:57:41 -04:00
21 changed files with 673 additions and 1629 deletions

View File

@@ -21,8 +21,16 @@
document (document stub that has no document version).
- Add support for client side caching of document page images. The time
the images are cached is controlled by the new setting
DOCUMENTS_PAGE_IMAGE_CACHE_TIME which defaults to 3600 seconds (1 hour).
DOCUMENTS_PAGE_IMAGE_CACHE_TIME which defaults to 31556926 seconds (1 year).
- The document quick label selection field now uses a select2 widget.
- Include querystring when force reload of a bare template view.
- Speed up document image fade in reveal.
- Use reseteable timer to ensure more document panels heights are matched.
- Rewrote Mayan's Javascript suite MayanApp into ECMAScript2015.
- Remove use is waitForJQuery.
- Remove code statistics from the documentation.
- Remove the pending work chapter. This is now available in the Wiki:
wiki.mayan-edms.com
3.0.1 (2018-07-08)
=================

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,4 @@ Introductions to all the key parts of Mayan EDMS you'll need to know:
file_storage
backups
upload_wizard
pending_work
code_statistics
docker

View File

@@ -1,312 +0,0 @@
============
Pending work
============
Release blockers
----------------
These are errors or issues that are blocking a release.
- None
Pending work
------------
These are tasks that need to be completed but are missing a dependency or
a design decision. As more information is added to each, they should be
converted into a MERC.
API
~~~
- User API edit view: Should not be able to add of remove groups without
corresponding group access.
- User group list API get & post views: Should adding a group to an user
via the API return 201 or 200. Currently returns 201.
- Consistent API return code for delete views without access. Some views
return 403 other return 404.
- Update API docstrings. The upgrade to the latest DRF broke all formatting.
- Make views smaller. Much as much as possible to serializers.
- Switch to ViewSets.
- Add API filtering. Example unread notifications.
Documents
~~~~~~~~~
- Navigating to the interactive document page image is not triggering
the document view event.
Events
~~~~~~
- New event: document emailed.
Forms processing
~~~~~~~~~~~~~~~~
- Remove usage of self.cleaned_data. Use self.clean_data instead.
Permissions
~~~~~~~~~~~
- Permission should be reciprocal. Example: To be able to add a tag to a
document, the user must hold the tag add permission for the document
and for the tag to be added. To be able to enable a metadata type to a
document type, the user must hold the metadata add permissions for the
metadata type and for the document type.
- Edit type permissions should only grant the ability to edit the properties
of an object. To modify its relationship with other objects a reciprocal
permission check should be instead.
Search
~~~~~~
- Rename SearchModel.pk to id
Sources
~~~~~~~
- Add ACLs support to sources.
- Provide error message/feedback when scanning from a remote scanner fails.
- Require a permission for document types to avoid a user that has the workflow
creation permission to attach a workflow to a document type they don't
control.
- Research making APIWorkflowDocumentTypeList a subclass of documents.api_views.APIDocumentTypeList
- A POST request to APIWorkflowDocumentTypeList should require some permission
on the document type part to avoid adding non controlled document types
to a new workflow.
- To transition a workflow, the transition permission is only needed for the
workflow. Make it necesary to have the same permission for the document
of document type.
- To view the transition log, the workflow view permission is only needed for the
document. Make it necesary to have the same permission for the workflow or
for the transition and the states.
- Render date time of scanned documents using SANE to a better output
(like document versions).
Testing
~~~~~~~
- Add document test mixin that creates documents types and documents
(to be used in dynamic_search.test_api).
- Update all API tests using self.client to just self. and the HTTP method.
- Add test for searches for each app that uses search.
UI - Frontend
~~~~~~~~~~~~~
- Fix menu not collapsing at the same width of nav parent.
- Move direct CSS style from code into base.css. grep 'style' * -R. Style code in:
* appearance/templates/appearance/generic_list_items_subtemplate.html
* appearance/templates/appearance/base.html
* appearance/templates/appearance/generic_list_subtemplate.html
* appearance/templates/navigation/generic_link_instance.html
- Check if location is found in partial and remove it. Avoid circular loading.
- Add location to history after a form submit redirect.
UI
~~
- Shift click select to seletect multiple documents.
- During the document upload wizard and the option to double click to
select document type and submit the form. The purpose is to speed up
the step with less mouse travel since this is a common screen.
- Add metadata to the Menu class to allow UI code to decide where and how
to display each menu.
- Reduce the facet buttons paddings.
- Make facet action button smaller. Reduce margin-bottom.
- Remove previous from the views.py. It is not longer used by the form's cancel button.
Workflows
~~~~~~~~~
- Workflow trigger filters. Example: {{ document.document_type.name = 'invoice' }}
or same UI as the smart links app. Will allow restricting the firing of workflow
actions by an user defined filter criteria.
- Require a permission for document types to avoid a user that has the workflow
creation permission to attach a workflow to a document type they don't
control.
- Research making APIWorkflowDocumentTypeList a subclass of
documents.api_views.APIDocumentTypeList
- A POST request to APIWorkflowDocumentTypeList should require some permission
on the document type part to avoid adding non controlled document types
to a new workflow.
- To transition a workflow, the transition permission is only needed for the
workflow. Make it necesary to have the same permission for the document
of document type.
- To view the transition log, the workflow view permission is only needed for
the document. Make it necesary to have the same permission for the workflow or
for the transition and the states.
New features
------------
API
~~~
- Add converter API
- Document signatures API
- Smart settings API
- Use REST_API's 'mayan_permission_attribute_check' to simplify API views access checking and filtering.
- DRF filtering using the URL query.
Converter
~~~~~~~~~
- New zoom transformation. Resample, not just bigger final size but do
a resize * zoom multiple before. Produces a bigger image or higher
quality than the original.
Caching
~~~~~~~
- Size limited caching. A new model in the common app will keep track
of all cache files. A manager method will be provided that will
return the cache files in other of age to be deleted.
Distribution
~~~~~~~~~~~~
- Python based Javascript package manager. Each app specifies what
library and version needs. The common app (or a new app) will add all
the JS loading lines automatically so that compress can detect them.
Metadata
~~~~~~~~
- Metadata lookup memory. Add a select2 style widget that will query a
new metadata API endpoint that will return all used values so far.
- Metadata validation_choices and parser_choices as static model methods
- Metadata.api as Metadata.utils and manager
Search
~~~~~~
- Add support for highlighting the search results in pages.
Settings
~~~~~~~~
- Database based settings.
Sources
~~~~~~~
- UI improvement for staging folders files selection. GitLab issue.
UI
~~
- Upgrade to Bootstrap 4.
- Upgrade to Flatly 4.
- Better workflow transition UI. Instead of a dropdown show all the
available transitions as buttons.
Workflows
~~~~~~~~~
- Workflow trigger filters. Example: {{ document.document_type.name = 'invoice' }} or same
UI as the smart links app. Will allow restricting the firing of workflow
actions by an user defined filter criteria.
- New workflow action: send email. Subject and content are templates.
Other
~~~~~
- Python based Javascript package manager. Each app specifies what
library and version needs. The common app (or a new app) will add all
the JS loading lines automatically so that compress can detect them.
- When moving documents to the trash update the message to "submitted"
and not "moved" or "deleted" since this is handled by a task queue
and is not immediate and doesn't delete the document.
- When emptying the trash update the message to "submitted"
since this is handled by a task queue and is not immediate.
- New app that allows creating user document filters. Will provide the
same service as the document filters class. Interface can be made
using the template language or the same UI as the smart links.
- Allow add queue metadata that can be exported via a management command.
This will allow creating supervisor templates without all the worker
entries being hardcoded.
- Delete .gitignore files from copied packages. Include .gitignore files
keep compiled or distributable files from being included in the main
repository. Temporary measure until a Javascript library manager is
added.
- Automatically capture license information from installed Javascript
libraries.
- Automatically capture license information from installed Python
packages.
- Update celery to 4.1.0
- Update to use the new class based views in the authentication app.
password_change(), password_change_done(), password_reset(),
password_reset_done(), password_reset_confirm(), and password_reset_complete()
function-based views are deprecated in favor of new class-based views
PasswordChangeView, PasswordChangeDoneView, PasswordResetView,
PasswordResetDoneView, PasswordResetConfirmView, and PasswordResetCompleteView.
- django.utils.translation.string_concat() is deprecated in favor of
django.utils.text.format_lazy(). string_concat(strings) can be
replaced by format_lazy('{}' x len(strings), strings).
Found in converter/classes.py and metadata/forms.py.
- Fix warnings in preparation for Django 2.0.
- Update all tempfile.mkstemp() to tempfile.mkstemp(dir=setting_temporary_directory.value)
- Get rid of common.utils.get_descriptor only used by common.utils.copyfile
- Update common.utils.copyfile to use only file objects.
- Change metadata label column from CharField to Label
- Start testing to Python 3 compatibility.
- Unify all RelationshipForms into a common class.
- Add test for event subscription view.
- Repeated templates: password_reset_confirm.html and password_reset_form.html
- Remove unused text=get_notification_count from events.links
- Reduce number of languages so dropzone view starts faster.
- In DocumentComment model, rename comment field to text.
- class MultipleInstanceActionMixin is deprecated. Replace views using this with
MultipleObjectFormActionView or MultipleObjectConfirmActionView
- Subscribe to tag events
- Subscribe to workflow events
- Subscribe to workflow state events
- Link to go from event notification to view. Example document workflow notification to document workflow views.
- Find replacement for ``python-gnupg``. Unstable & inconsistent API.
- New app that allows creating user document filters. Will provide the
same service as the document filters class. Interface can be made
using the template language or the same UI as the smart links.
- Allow add queue metadata that can be exported via a management command.
This will allow creating supervisor templates without all the worker
entries being hardcoded.
- Automatically capture license information from installed Javascript
libraries.
- Automatically capture license information from installed Python
packages.
- Finish and merge improved compressed file branch.
- Improve and merge PCL support branch.
- Swtich to self hosted documentation.
- Unify error logs in a common model. Fields: Datetime, namespace,
message, content type, object id.
- Export documents as PDF. Each document image is used to create a PDF
dinamycally.
- Document splitting. Only for PDF files first. A document versions
relationship between the documents has to be designed.
- Manually linking documents.
- Migrate settings/base.py to Django's 1.11 format.
- Rename model methods to use ``get_`` or ``do_``
- Hunt TODO
- Hunt FIXME
- Convert SETTING_GPG_BACKEND into a setting option similar to converter and converter options.
- Reorganize modelForms Meta class and methods.
- Periodic messages, like notifications. Using an AJAX worker.
- Find replacement for ``python-gnupg``. Unstable & inconsistent API.
- Google docs integration. Upload document from Google Drive.
- Get ``dumpdata`` and ``loaddata`` working flawlessly. Will allow for easier backups, restores and database backend migrations.
- Add generic list ordering. ``django.views.generic.list.MultipleObjectMixin`` (https://docs.djangoproject.com/en/1.8/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin) now supports an ``ordering`` parameter.
- Add support to convert any document to PDF. https://gitlab.mister-muffin.de/josch/img2pdf
- Add support for combining documents.
- Add support for splitting documents.
- Add new document source to get documents from an URL.
- Add support for metadata mapping files. CSV file containing filename to metadata values mapping, useful for bulk upload and migrations.
- Add support for registering widgets to the home screen.
- Merge mimetype and converter apps.
- Metadata widgets (Date, time, timedate).
- Datatime widget: https://github.com/smalot/bootstrap-datetimepicker
- Add events for document signing app (uploaded detached signateure, signed document, deleted signature)
- A configurable conversion process. Being able to invoke different binaries for file conversion, as opposed to the current libreoffice only solution.
- A tool in the admin interface to mass (re)convert the files (basically the page count function, but then applied on all documents).

View File

@@ -1,26 +1,12 @@
'use strict';
var app = new App();
// Make it globally available. Used by event.links
var MayanAppClass = MayanApp;
var partialNavigation = new PartialNavigation({
initialURL: initialURL,
disabledAnchorClasses: ['disabled'],
excludeAnchorClasses: ['fancybox', 'new_window', 'non-ajax'],
formBeforeSerializeCallbacks: [App.MultiObjectFormProcess],
formBeforeSerializeCallbacks: [MayanApp.MultiObjectFormProcess],
});
jQuery(document).ready(function() {
app.setupAutoSubmit();
app.setupFullHeightResizing();
app.setupItemsSelector();
app.setupNavbarCollapse();
app.setupNewWindowAnchor();
app.setupAJAXperiodicWorkers();
partialNavigation.initialize();
});
var afterBaseLoad = function () {
MayanImage.intialize();
app.doToastrMessages();
app.resizeFullHeight();
app.setupSelect2();
app.setupScrollView();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +1,80 @@
'use strict';
var MayanImage = function (options) {
this.element = options.element;
this.load();
}
class MayanImage {
constructor (options) {
this.element = options.element;
this.load();
}
MayanImage.intialize = function () {
var app = this;
static intialize () {
var app = this;
this.fancybox = $().fancybox({
animationDuration : 400,
buttons : [
'fullScreen',
'close',
],
selector: 'a.fancybox',
afterShow: function (instance, current) {
$('a.a-caption').on('click', function(event) {
instance.close(true);
});
},
infobar: true,
this.fancybox = $().fancybox({
animationDuration : 300,
buttons : [
'fullScreen',
'close',
],
selector: 'a.fancybox',
afterShow: function (instance, current) {
$('a.a-caption').on('click', function(event) {
instance.close(true);
});
},
infobar: true,
});
});
$('img.lazy-load').lazyload({
appear: function(elements_left, settings) {
new MayanImage({element: $(this)});
},
threshold: 400,
});
$('img.lazy-load').lazyload({
appear: function(elements_left, settings) {
new MayanImage({element: $(this)});
},
threshold: 400,
});
$('img.lazy-load-carousel').lazyload({
appear: function(elements_left, settings) {
new MayanImage({element: $(this)});
},
container: $('#carousel-container'),
threshold: 2000,
});
$('img.lazy-load-carousel').lazyload({
appear: function(elements_left, settings) {
new MayanImage({element: $(this)});
},
container: $('#carousel-container'),
threshold: 2000,
});
$('.lazy-load').on('load', function() {
$(this).hide();
$(this).fadeIn();
$(this).siblings('.spinner-container').remove();
$(this).removeClass('lazy-load pull-left');
});
$('.lazy-load').on('load', function() {
$(this).hide();
$(this).fadeIn(300);
$(this).siblings('.spinner-container').remove();
$(this).removeClass('lazy-load pull-left');
});
$('.lazy-load-carousel').on('load', function() {
$(this).hide();
$(this).fadeIn();
$(this).siblings('.spinner-container').remove();
$(this).removeClass('lazy-load-carousel pull-left');
});
$('.lazy-load-carousel').on('load', function() {
$(this).hide();
$(this).fadeIn(300);
$(this).siblings('.spinner-container').remove();
$(this).removeClass('lazy-load-carousel pull-left');
});
}
static timerFunction () {
$.fn.matchHeight._maintainScroll = true;
$.fn.matchHeight._update();
}
load () {
var self = this;
var container = this.element.parent().parent().parent();
this.element.on('error', (function(event) {
container.html(MayanImage.templateInvalidDocument);
}));
this.element.attr('src', this.element.attr('data-url'));
$.fn.matchHeight._maintainScroll = true;
clearTimeout(MayanImage.timer);
MayanImage.timer = setTimeout(MayanImage.timerFunction, 100);
};
}
MayanImage.templateInvalidDocument = $('#template-invalid-document').html();
MayanImage.prototype.load = function () {
var self = this;
var container = this.element.parent().parent().parent();
this.element.on('error', (function(event) {
container.html(MayanImage.templateInvalidDocument);
}));
this.element.attr('src', this.element.attr('data-url'));
$.fn.matchHeight._update();
$.fn.matchHeight._maintainScroll = true;
};
MayanImage.timer = setTimeout(null);

View File

@@ -11,7 +11,7 @@
* current location's path as the new hash
*/
document.write('<script type="text/undefined">')
var currentPath = window.location.pathname;
var currentPath = window.location.pathname + window.location.search;
window.location = '/#' + currentPath;
}
</script>

View File

@@ -31,16 +31,6 @@
if (currentHash.length) {
window.location = currentHash.substring(1);
}
function waitForJQuery(func) {
if (window.jQuery) {
func();
} else {
setTimeout(function() {
waitForJQuery(func)
}, 50);
}
}
</script>
</head>
<body>

View File

@@ -4,18 +4,6 @@
{% load common_tags %}
{% load navigation_tags %}
<script>
'use strict';
waitForJQuery(function() {
$(function() {
$('.panel-item').matchHeight({
byRow: false,
});
});
});
</script>
<div class="row">
<div class="col-xs-12">
<h4>
@@ -53,12 +41,11 @@
<hr style="border-bottom: 1px solid lightgrey;">
{% endif %}
<div class="row">
<div class="row row-items">
{% for object in object_list %}
<div class="{{ column_class|default:'col-xs-12 col-sm-4 col-md-3 col-lg-2' }}">
<div class="panel panel-primary panel-item">
<div class="panel-heading">
<div class="form-group">
<div class="checkbox">
<label for="id_indexes_0">
@@ -125,3 +112,13 @@
</div>
</div>
</div>
<script>
'use strict';
$(function() {
$('.row-items > [class*="col"] .panel-item .panel-heading').matchHeight();
$('.row-items > [class*="col"] .panel-item .panel-body').matchHeight();
$('.row-items > [class*="col"] .panel-item').matchHeight();
});
</script>

View File

@@ -27,17 +27,6 @@
<link href="{% static 'appearance/vendors/pace-0.7.8/themes/pace-theme-flash.css' %}" media="screen" rel="stylesheet" type="text/css" />
<link href="{% static 'appearance/css/base.css' %}" media="screen" rel="stylesheet" type="text/css" />
{% block stylesheets %}{% endblock %}
<script>
function waitForJQuery(func) {
if (window.jQuery) {
func();
} else {
setTimeout(function() {
waitForJQuery(func)
}, 50);
}
}
</script>
</head>
<body>
{% if appearance_type == 'plain' %}
@@ -152,15 +141,28 @@
<script src="{% static 'appearance/js/mayan_app.js' %}" type="text/javascript"></script>
<script src="{% static 'appearance/js/mayan_image.js' %}" type="text/javascript"></script>
<script src="{% static 'appearance/js/partial_navigation.js' %}" type="text/javascript"></script>
<script>
{# Transfer variable from Django to javascript #}
var initialURL = '{% url home_view %}';
var djangoDEBUG = {% if debug %}true{% else %}false{% endif %};
Dropzone.autoDiscover = false;
</script>
<script src="{% static 'appearance/js/base.js' %}" type="text/javascript"></script>
<script>
var app = new MayanApp();
var afterBaseLoad = function () {
MayanImage.intialize();
app.doToastrMessages();
app.resizeFullHeight();
app.setupSelect2();
app.setupScrollView();
}
jQuery(document).ready(function() {
app.initialize();
});
</script>
</body>
</html>
{% endspaceless %}

View File

@@ -7,10 +7,10 @@ icon_dashboard_document_types = Icon(
driver_name='fontawesome', symbol='book'
)
icon_dashboard_documents_in_trash = Icon(
driver_name='fontawesome', symbol='book'
driver_name='fontawesome', symbol='trash'
)
icon_dashboard_pages_per_month = Icon(
driver_name='fontawesome', symbol='trash'
driver_name='fontawesome', symbol='copy'
)
icon_dashboard_new_documents_this_month = Icon(
driver_name='fontawesome', symbol='calendar'

View File

@@ -152,7 +152,7 @@ link_document_multiple_document_type_edit = Link(
view='documents:document_multiple_document_type_edit'
)
link_document_multiple_download = Link(
text=_('Download'), view='documents:document_multiple_download_form'
text=_('Advanced download'), view='documents:document_multiple_download_form'
)
link_document_multiple_update_page_count = Link(
text=_('Recalculate page count'),

View File

@@ -32,7 +32,7 @@ setting_display_width = namespace.add_setting(
global_name='DOCUMENTS_DISPLAY_WIDTH', default='3600'
)
settings_document_page_image_cache_time = namespace.add_setting(
global_name='DOCUMENTS_PAGE_IMAGE_CACHE_TIME', default='3600'
global_name='DOCUMENTS_PAGE_IMAGE_CACHE_TIME', default='31556926'
)
setting_documentimagecache_storage = namespace.add_setting(
global_name='DOCUMENTS_CACHE_STORAGE_BACKEND',

View File

@@ -1,7 +1,7 @@
{% load documents_tags %}
{% extends 'appearance/base_plain.html' %}
{% load documents_tags %}
{% block title %}{{ title }}{% endblock title %}
{% block content_plain %}

View File

@@ -1,16 +1,16 @@
{% load documents_tags %}
<div class="instance-image-widget {{ container_class }}">
<div class="spinner-container text-primary"
style="height: {% if display_full_height %}100%{% else %}{{ display_height|default:150 }}px{% endif %};"
<span class="instance-image-widget {{ container_class }}">
<span class="spinner-container text-primary"
style="height: {% if display_full_height %}100%{% else %}{{ display_height|default:150 }}px{% endif %}; display: block;"
>
<i class="far fa-clock fa-2x"></i>
</div>
</span>
<img
class="thin_border {{ image_classes }}"
data-url="{% get_api_image_url instance width=image_width height=image_height zoom=image_zoom rotation=image_rotation %}"
src="#"
style="{% if image_max_height %}max-height: {{ image_max_height }}; {% endif %}"
/>
</div>
</span>

View File

@@ -80,7 +80,7 @@ link_user_notifications_list = Link(
html_data={
'apw-attribute': 'count', 'apw-interval': '5000',
'apw-url': '/api/notifications/?read=False',
'apw-callback': 'App.mayanNotificationBadge'
'apw-callback': 'MayanAppClass.mayanNotificationBadge'
}, icon_class=icon_user_notifications_list, text='',
view='events:user_notifications_list'
)

View File

@@ -1,11 +1,9 @@
'use strict';
waitForJQuery(function() {
jQuery(document).ready(function() {
$('.metadata-value').on('input', function(event) {
// Check the checkbox next to a metadata value input when there is
// data entry in the value's input.
$(event.target).parents('tr').find(':checkbox').prop('checked', true);
});
jQuery(document).ready(function() {
$('.metadata-value').on('input', function(event) {
// Check the checkbox next to a metadata value input when there is
// data entry in the value's input.
$(event.target).parents('tr').find(':checkbox').prop('checked', true);
});
});

View File

@@ -143,8 +143,8 @@ class Menu(object):
result = []
try:
request = Variable('request').resolve(context)
except VariableDoesNotExist:
request = context.request
except AttributeError:
# There is no request variable, most probable a 500 in a test view
# Don't return any resolved links then.
logger.warning('No request variable, aborting menu resolution')
@@ -286,7 +286,7 @@ class Link(object):
app_label='acls', model_name='AccessControlList'
)
request = Variable('request').resolve(context)
request = context.request
current_path = request.META['PATH_INFO']
current_view = resolve(current_path).view_name

View File

@@ -62,8 +62,6 @@ PyYAML==3.13
celery==3.1.24
django-activity-stream==0.6.5
django-autoadmin==1.1.1
#django-celery==3.2.1 - Use fork below until patch https://github.com/celery/django-celery/pull/552 is accepted.
https://github.com/mayan-edms/django-celery/zipball/master#egg=django-celery
django-colorful==1.2
django-cors-headers==2.2.0
django-downloadview==1.9
@@ -128,6 +126,9 @@ setup(
'Topic :: Communications :: File Sharing',
],
description='Free Open Source Electronic Document Management System',
dependency_links=[
"https://github.com/mayan-edms/django-celery/zipball/master#egg=django-celery"
],
include_package_data=True,
install_requires=install_requires,
license='Apache 2.0',