src/pyams_content/shared/common/zmi/search.py
changeset 0 7c0001cacf8e
child 3 cdcc8fa70047
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_content/shared/common/zmi/search.py	Thu Oct 08 13:37:29 2015 +0200
@@ -0,0 +1,250 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+
+# import standard library
+
+# import interfaces
+from hypatia.interfaces import ICatalog
+from pyams_content.profile.interfaces import IAdminProfile
+from pyams_content.shared.common.interfaces import ISharedTool
+from pyams_content.shared.common.interfaces.zmi import ISharedToolDashboardTable
+from pyams_pagelet.interfaces import PageletCreatedEvent
+from pyams_sequence.interfaces import ISequentialIntIds
+from pyams_skin.interfaces import IPageHeader, IContentSearch
+from pyams_skin.layer import IPyAMSLayer
+from pyams_utils.interfaces import VIEW_SYSTEM_PERMISSION
+from pyams_workflow.interfaces import IWorkflowVersions, IWorkflow
+from pyams_zmi.interfaces import IAdminView
+from z3c.table.interfaces import IValues
+from zope.dublincore.interfaces import IZopeDublinCore
+
+# import packages
+from hypatia.catalog import CatalogQuery
+from hypatia.query import Eq, Contains, Ge, Le
+from pyams_content.workflow import STATES_VOCABULARY
+from pyams_catalog.query import CatalogResultSet
+from pyams_form.search import SearchView, SearchForm, SearchResultsView, ISearchFields
+from pyams_pagelet.pagelet import pagelet_config
+from pyams_security.schema import Principal
+from pyams_skin.page import DefaultPageHeaderAdapter
+from pyams_skin.table import BaseTable
+from pyams_template.template import template_config
+from pyams_utils.adapter import adapter_config, ContextRequestViewAdapter
+from pyams_utils.list import unique
+from pyams_utils.registry import get_utility
+from pyams_zmi.view import AdminView
+from pyramid.response import Response
+from pyramid.view import view_config
+from z3c.form import field
+from zope.interface import implementer
+from zope.schema import Date, Choice
+
+from pyams_content import _
+
+
+#
+# Quick search adapters
+#
+
+@view_config(name='quick-search.html', context=ISharedTool, request_type=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+def shared_tool_quick_search_view(request):
+    """Shared tool quick search view"""
+    results = SharedToolQuickSearchResults(request.context, request)
+    results.update()
+    return Response(results.render())
+
+
+@implementer(ISharedToolDashboardTable)
+class SharedToolQuickSearchResults(BaseTable):
+    """Shared tool quick search results table"""
+
+    title = _("Quick search results")
+
+    sortOn = None
+
+    @property
+    def data_attributes(self):
+        attributes = super(SharedToolQuickSearchResults, self).data_attributes
+        attributes['table'] = {'data-ams-datatable-sorting': '[]',
+                               'data-ams-datatable-display-length':
+                                   IAdminProfile(self.request.principal).table_page_length}
+        return attributes
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolQuickSearchResults), provides=IValues)
+class SharedToolQuickSearchValues(ContextRequestViewAdapter):
+    """Shared tool quick search results view values adapter"""
+
+    @property
+    def values(self):
+        catalog = get_utility(ICatalog)
+        params = Eq(catalog['content_type'], self.context.shared_content_type)
+        query = self.request.params.get('query')
+        if query:
+            sequence = get_utility(ISequentialIntIds)
+            if query.startswith('+'):
+                params &= Eq(catalog['oid'], sequence.get_full_oid(query))
+            else:
+                query_params = Eq(catalog['oid'], sequence.get_full_oid(query))
+                index = catalog['title:' + self.request.registry.settings.get('pyramid.default_locale_name', 'en')]
+                if index.check_query(query):
+                    query_params |= Contains(index, ' and '.join((w+'*' for w in query.split())))
+                params &= query_params
+        return unique(map(lambda x: IWorkflowVersions(x).get_last_versions()[0],
+                          CatalogResultSet(CatalogQuery(catalog).query(params,
+                                                                       sort_index='modified_date',
+                                                                       reverse=True))))
+
+
+#
+# Advanced search adapters
+#
+
+class ISharedToolAdvancedSearchFields(ISearchFields):
+    """Shared tool advanced search fields"""
+
+    owner = Principal(title=_("Owner"),
+                      required=False)
+
+    status = Choice(title=_("Status"),
+                    vocabulary=STATES_VOCABULARY,
+                    required=False)
+
+    created_after = Date(title=_("Created after..."),
+                         required=False)
+
+    created_before = Date(title=_("Created before..."),
+                          required=False)
+
+    modified_after = Date(title=_("Modified after..."),
+                          required=False)
+
+    modified_before = Date(title=_("Modified before..."),
+                           required=False)
+
+
+@template_config(template='templates/advanced-search.pt', layer=IPyAMSLayer)
+@implementer(IAdminView)
+class SharedToolAdvancedSearchForm(SearchForm):
+    """Shared tool advanced search form"""
+
+    legend = _("Advanced search")
+
+    ajax_handler = 'advanced-search-results.html'
+
+    def __init__(self, context, request):
+        super(SharedToolAdvancedSearchForm, self).__init__(context, request)
+        request.registry.notify(PageletCreatedEvent(self))
+
+    @property
+    def fields(self):
+        workflow = IWorkflow(self.context)
+        fields = field.Fields(ISharedToolAdvancedSearchFields)
+        fields['status'].vocabulary = workflow.states
+        return fields
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolAdvancedSearchForm), provides=IContentSearch)
+class SharedToolAdvancedSearchFormSearchAdapter(ContextRequestViewAdapter):
+    """Shared tool adavanced search form search adapter"""
+
+    def get_search_results(self, data):
+        catalog = get_utility(ICatalog)
+        params = Eq(catalog['content_type'], self.context.shared_content_type)
+        query = data.get('query')
+        if query:
+            sequence = get_utility(ISequentialIntIds)
+            if query.startswith('+'):
+                params &= Eq(catalog['oid'], sequence.get_full_oid(query))
+            else:
+                query_params = Eq(catalog['oid'], sequence.get_full_oid(query))
+                index = catalog['title:' + self.request.registry.settings.get('pyramid.default_locale_name', 'en')]
+                if index.check_query(query):
+                    query_params |= Contains(index, ' and '.join((w+'*' for w in query.split())))
+                params &= query_params
+        if data.get('owner'):
+            params &= Eq(catalog['owner'], data['owner'])
+        if data.get('status'):
+            params &= Eq(catalog['workflow_state'], data['status'])
+        if data.get('created_after'):
+            params &= Ge(catalog['created_date'], data['created_after'])
+        if data.get('created_before'):
+            params &= Le(catalog['created_date'], data['created_before'])
+        if data.get('modified_after'):
+            params &= Ge(catalog['modified_date'], data['modified_after'])
+        if data.get('modified_before'):
+            params &= Le(catalog['modified_date'], data['modified_before'])
+        if data.get('status'):
+            return unique(map(lambda x: sorted(IWorkflowVersions(x).get_versions(data['status']),
+                                               key=lambda y: IZopeDublinCore(y).modified)[0],
+                              CatalogResultSet(CatalogQuery(catalog).query(params,
+                                                                           sort_index='modified_date',
+                                                                           reverse=True))))
+        else:
+            return unique(map(lambda x: IWorkflowVersions(x).get_last_versions()[0],
+                              CatalogResultSet(CatalogQuery(catalog).query(params,
+                                                                           sort_index='modified_date',
+                                                                           reverse=True))))
+
+
+@pagelet_config(name='advanced-search.html', context=ISharedTool, layer=IPyAMSLayer, permission=VIEW_SYSTEM_PERMISSION)
+class SharedToolAdvancedSearchView(AdminView, SearchView):
+    """Shared tool advanced search view"""
+
+    search_form_factory = SharedToolAdvancedSearchForm
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolAdvancedSearchView), provides=IPageHeader)
+class SharedToolAdvancedSearchHeaderAdapter(DefaultPageHeaderAdapter):
+    """Shared tool advanced search header adapter"""
+
+    back_url = '#dashboard.html'
+    back_target = None
+
+    icon_class = 'fa fa-fw fa-search'
+
+
+@view_config(name='advanced-search-results.html', context=ISharedTool, request_type=IPyAMSLayer,
+             permission=VIEW_SYSTEM_PERMISSION)
+@implementer(ISharedToolDashboardTable)
+class SharedToolAdvancedSearchResultsView(AdminView, SearchResultsView):
+    """Shared tool advanced search results view"""
+
+    title = _("Advanced search results")
+    search_form_factory = SharedToolAdvancedSearchForm
+
+    sortOn = None
+
+    def __init__(self, context, request):
+        super(SharedToolAdvancedSearchResultsView, self).__init__(context, request)
+        request.registry.notify(PageletCreatedEvent(self))
+
+    @property
+    def data_attributes(self):
+        attributes = super(SharedToolAdvancedSearchResultsView, self).data_attributes
+        attributes['table'] = {'data-ams-datatable-sorting': '[]',
+                               'data-ams-datatable-display-length':
+                                   IAdminProfile(self.request.principal).table_page_length}
+        return attributes
+
+
+@adapter_config(context=(ISharedTool, IPyAMSLayer, SharedToolAdvancedSearchResultsView), provides=IValues)
+class SearchResultsViewValuesAdapter(ContextRequestViewAdapter):
+    """Search results view values adapter"""
+
+    @property
+    def values(self):
+        form = self.view.search_form_factory(self.context, self.request)
+        return form.get_search_results()