0013222: Allow to filter for rrule
authorMichael Spahn <m.spahn@metaways.de>
Fri, 16 Jun 2017 09:55:10 +0000 (11:55 +0200)
committersstamer <s.stamer@metaways.de>
Fri, 16 Jun 2017 15:25:29 +0000 (17:25 +0200)
https://forge.tine20.org/view.php?id=13222

Change-Id: I424f2cef55d747bbc5339acf7c5ef3f47663e290
Reviewed-on: http://gerrit.tine20.com/customers/4883
Reviewed-by: sstamer <s.stamer@metaways.de>
Tested-by: sstamer <s.stamer@metaways.de>
tine20/Calendar/Calendar.jsb2
tine20/Calendar/Model/EventFilter.php
tine20/Calendar/Model/RruleFilter.php [new file with mode: 0644]
tine20/Calendar/js/Model.js
tine20/Calendar/js/RruleFilter.js [new file with mode: 0644]

index fde33c7..f71ee63 100644 (file)
         {
           "text": "CalendarPanelSplitPlugin.js",
           "path": "js/"
+        },
+        {
+          "text": "RruleFilter.js",
+          "path": "js/"
         }
       ]
     },
index 81f112e..44070d6 100644 (file)
@@ -59,7 +59,7 @@ class Calendar_Model_EventFilter extends Tinebase_Model_Filter_FilterGroup
         'dtstart'               => array('filter' => 'Tinebase_Model_Filter_DateTime'),
         'dtend'                 => array('filter' => 'Tinebase_Model_Filter_DateTime'),
         'transp'                => array('filter' => 'Tinebase_Model_Filter_Text'),
-        'rrule'                 => array('filter' => 'Tinebase_Model_Filter_Text'),
+        'rrule'                 => array('filter' => 'Calendar_Model_RruleFilter'),
         'recurid'               => array('filter' => 'Tinebase_Model_Filter_Text'),
         'base_event_id'         => array('filter' => 'Tinebase_Model_Filter_Text'),
         'rrule_until'           => array('filter' => 'Tinebase_Model_Filter_DateTime'),
diff --git a/tine20/Calendar/Model/RruleFilter.php b/tine20/Calendar/Model/RruleFilter.php
new file mode 100644 (file)
index 0000000..f74fb7e
--- /dev/null
@@ -0,0 +1,46 @@
+<?php
+
+/**
+ * Tine 2.0
+ *
+ * @package     Calendar
+ * @subpackage  Model
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Michael Spahn <m.spahn@metaways.de>
+ * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
+ */
+class Calendar_Model_RruleFilter extends Tinebase_Model_Filter_Text
+{
+    protected $_operators = [
+        'in',
+        'notin',
+        'isnull',
+        'notnull'
+    ];
+
+    /**
+     * appends sql to given select statement
+     *
+     * @param Zend_Db_Select $_select
+     * @param Tinebase_Backend_Sql_Abstract $_backend
+     *
+     */
+    public function appendFilterSql($_select, $_backend)
+    {
+        if (in_array($this->_operator, ['isnull', 'notnull'], true) || 0 === count($this->getValue())) {
+            parent::appendFilterSql($_select, $_backend);
+            return;
+        }
+
+        foreach (array_shift($this->getValue()) as $key => $value) {
+            if (false === $value) {
+                continue;
+            }
+            if ('notin' === $this->_operator) {
+                $_select->where('rrule NOT LIKE ?', '%' . strtoupper($key) . '%');
+            } else {
+                $_select->orWhere('rrule LIKE ?', '%' . strtoupper($key) . '%');
+            }
+        }
+    }
+}
\ No newline at end of file
index ecd635c..0fc9e0c 100644 (file)
@@ -352,7 +352,11 @@ Tine.Calendar.Model.Event.getFilterModel = function() {
             keyfieldName: 'attendeeRoles'
         },
         {filtertype: 'addressbook.contact', field: 'organizer', label: app.i18n._('Organizer')},
-        {filtertype: 'tinebase.tag', app: app}
+        {filtertype: 'tinebase.tag', app: app},
+        {
+            filtertype: 'calendar.rrule',
+            app: app
+        }
     ];
 };
 
diff --git a/tine20/Calendar/js/RruleFilter.js b/tine20/Calendar/js/RruleFilter.js
new file mode 100644 (file)
index 0000000..005f85b
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Tine 2.0
+ * 
+ * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
+ * @author      Michael Spahn <m.spahn@metaways.de>
+ * @copyright   Copyright (c) 2017 Metaways Infosystems GmbH (http://www.metaways.de)
+ */
+Ext.ns('Tine.Calendar');
+
+/**
+ * @namespace   Tine.Calendar
+ * @class       Tine.Calendar.RruleFilter
+ * @extends     Tine.widgets.grid.FilterModel
+ *
+ * @author      Michael Spahn <m.spahn@metaways.de>
+ */
+Tine.Calendar.RruleFilter = Ext.extend(Tine.widgets.grid.FilterModel, {
+    app: null,
+
+    field: 'rrule',
+
+    defaultOperator: 'in',
+
+    operators: ['in', 'notin'],
+
+    initComponent: function () {
+        Tine.Calendar.AttendeeFilterModel.superclass.initComponent.call(this);
+
+        this.app = this.app || Tine.Tinebase.appMgr.get('Calendar');
+
+        this.label = this.app.i18n._('Rrule');
+
+        this.defaultValue = [{
+            'daily': true,
+            'weekly': true,
+            'monthly': true,
+            'yearly': true
+        }];
+    },
+
+    valueRenderer: function (filter, el) {
+        var value  = new Tine.Calendar.RruleFilterValueField({
+            app: this.app,
+            filter: filter,
+            width: this.filterValueWidth,
+            id: 'tw-ftb-frow-valuefield-' + filter.id,
+            value: filter.data.value ? filter.data.value : this.defaultValue,
+            renderTo: el
+        });
+
+        value.on('select', this.onFiltertrigger, this);
+        value.onCheckboxSelect(null, null);
+
+        return value;
+    }
+});
+
+Tine.widgets.grid.FilterToolbar.FILTERS['calendar.rrule'] = Tine.Calendar.RruleFilter;
+
+/**
+ * @namespace   Tine.Calendar
+ * @class       Tine.Calendar.RruleFilterValueField
+ * @extends     Ext.ux.form.LayerCombo
+ *
+ * @author      Michael Spahn <m.spahn@metaways.de>
+ */
+Tine.Calendar.RruleFilterValueField = Ext.extend(Ext.ux.form.LayerCombo, {
+    hideButtons: false,
+    layerAlign: 'tr-br?',
+    layerHeight: 200,
+
+    lazyInit: false,
+
+    formConfig: {
+        labelAlign: 'left',
+        labelWidth: 30
+    },
+
+    dailyCheckbox: null,
+    weeklyCheckbox: null,
+    monthlyCheckbox: null,
+    yearlyCheckbox: null,
+
+    initComponent: function () {
+        this.supr().initComponent.apply(this, arguments);
+    },
+
+    getFormValue: function () {
+        return [{
+            'daily': this.dailyCheckbox.getValue(),
+            'weekly': this.weeklyCheckbox.getValue(),
+            'monthly': this.monthlyCheckbox.getValue(),
+            'yearly': this.yearlyCheckbox.getValue()
+        }];
+    },
+
+    getItems: function () {
+        this.dailyCheckbox = new Ext.form.Checkbox({
+            boxLabel: this.app.i18n._('Daily'),
+            name: 'daily',
+            columnWidth: 1,
+            readOnly: false,
+            disabled: false,
+            checked: true,
+            listeners: {scope: this, check: this.onCheckboxSelect}
+        });
+
+        this.weeklyCheckbox = new Ext.form.Checkbox({
+            xtype: 'checkbox',
+            boxLabel: this.app.i18n._('Weekly'),
+            name: 'weekly',
+            columnWidth: 1,
+            readOnly: false,
+            disabled: false,
+            checked: true,
+            listeners: {scope: this, check: this.onCheckboxSelect}
+        });
+
+        this.monthlyCheckbox = new Ext.form.Checkbox({
+            boxLabel: this.app.i18n._('Monthly'),
+            name: 'monthly',
+            columnWidth: 1,
+            readOnly: false,
+            disabled: false,
+            checked: true,
+            listeners: {scope: this, check: this.onCheckboxSelect}
+        });
+
+        this.yearlyCheckbox = new Ext.form.Checkbox({
+            boxLabel: this.app.i18n._('Yearly'),
+            name: 'yearly',
+            columnWidth: 1,
+            readOnly: false,
+            disabled: false,
+            checked: true,
+            listeners: {scope: this, check: this.onCheckboxSelect}
+        });
+
+        return [
+            this.dailyCheckbox,
+            this.weeklyCheckbox,
+            this.monthlyCheckbox,
+            this.yearlyCheckbox
+        ];
+    },
+
+    onCheckboxSelect: function (cb, checked) {
+        var selection = [];
+
+        if (this.dailyCheckbox.getValue()) {
+            selection.push(this.dailyCheckbox.boxLabel);
+        }
+
+        if (this.weeklyCheckbox.getValue()) {
+            selection.push(this.weeklyCheckbox.boxLabel);
+        }
+
+        if (this.monthlyCheckbox.getValue()) {
+            selection.push(this.monthlyCheckbox.boxLabel);
+        }
+
+        if (this.yearlyCheckbox.getValue()) {
+            selection.push(this.yearlyCheckbox.boxLabel);
+        }
+
+        this.setRawValue(selection.join(', '));
+        this.setValue(this.getFormValue());
+    },
+
+    setValue: function (value) {
+        value = Ext.isArray(value) ? value : [value];
+
+        this.setFormValue(value);
+
+        return this.supr().setValue.apply(this, [value]);
+    },
+
+    setFormValue: function(value) {
+        this.dailyCheckbox.setValue(value[0].daily || false);
+        this.weeklyCheckbox.setValue(value[0].weekly || false);
+        this.monthlyCheckbox.setValue(value[0].monthly || false);
+        this.yearlyCheckbox.setValue(value[0].yearly || false);
+    }
+});