├── update.php ├── pages ├── index.php ├── info.licence.php ├── info.changelog.php ├── info.help.php ├── exim.export.php ├── categories.php ├── settings.php └── kanban.php ├── uninstall.sql ├── package.yml ├── .github └── workflows │ └── publish-to-redaxo-org.yml ├── LICENSE.md ├── README.md ├── assets └── js │ ├── custom.js │ ├── jquery.simplecolorpicker.js │ ├── kanban.js │ └── jquery.sumoselect.js ├── scss ├── _simplecolorpicker.scss ├── master.scss ├── _pickaday.scss ├── _sumoselect.scss └── _kanban.scss ├── lib ├── testen.php └── aufgaben_functions.php ├── install.php ├── boot.php ├── lang ├── en_gb.lang ├── sv_se.lang ├── de_de.lang ├── pt_br.lang └── es_es.lang └── CHANGELOG.md /update.php: -------------------------------------------------------------------------------- 1 | i18n('aufgaben_title')); 3 | rex_be_controller::includeCurrentPageSubPath(); 4 | -------------------------------------------------------------------------------- /uninstall.sql: -------------------------------------------------------------------------------- 1 | 2 | DROP TABLE IF EXISTS `%TABLE_PREFIX%aufgaben`; 3 | DROP TABLE IF EXISTS `%TABLE_PREFIX%aufgaben_categories`; 4 | DROP TABLE IF EXISTS `%TABLE_PREFIX%aufgaben_status`; 5 | DROP TABLE IF EXISTS `%TABLE_PREFIX%aufgaben_filter`; 6 | DROP TABLE IF EXISTS `%TABLE_PREFIX%aufgaben_user_settings`; 7 | 8 | -------------------------------------------------------------------------------- /pages/info.licence.php: -------------------------------------------------------------------------------- 1 | '.$Parsedown->text($file).''; 6 | 7 | $fragment = new rex_fragment(); 8 | $fragment->setVar('title', $this->i18n('aufgaben_licence')); 9 | $fragment->setVar('body', $content, false); 10 | echo $fragment->parse('core/page/section.php'); 11 | -------------------------------------------------------------------------------- /pages/info.changelog.php: -------------------------------------------------------------------------------- 1 | '.$Parsedown->text($file).''; 7 | 8 | $fragment = new rex_fragment(); 9 | $fragment->setVar('title', $this->i18n('aufgaben_changelog')); 10 | $fragment->setVar('body', $content, false); 11 | echo $fragment->parse('core/page/section.php'); 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.yml: -------------------------------------------------------------------------------- 1 | # Alle hier gesetzten Werte können über $addon->getProperty($key) abgefragt werden 2 | 3 | package: aufgaben 4 | version: '4.1.5-dev-2025-02-17' 5 | author: Friends Of REDAXO 6 | supportpage: https://github.com/FriendsOfREDAXO/aufgaben 7 | info: Idee und Realisierung der ersten Version concedra.de / Oliver Kreischer 8 | compile: 0 9 | 10 | page: 11 | title: 'Aufgaben' 12 | perm: aufgaben[] 13 | pjax: true 14 | icon: rex-icon fa-calendar-check-o 15 | 16 | requires: 17 | redaxo: '>=5.2.0, <6' 18 | packages: 19 | be_style: '>=2.1.0, <4' 20 | phpmailer: '>=2.0.1' 21 | 22 | -------------------------------------------------------------------------------- /.github/workflows/publish-to-redaxo-org.yml: -------------------------------------------------------------------------------- 1 | # Instructions: https://github.com/FriendsOfREDAXO/installer-action/ 2 | 3 | name: Publish to REDAXO.org 4 | on: 5 | release: 6 | types: 7 | - published 8 | 9 | jobs: 10 | redaxo_publish: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - if: hashFiles('composer.json') != '' 15 | uses: shivammathur/setup-php@v2 16 | with: 17 | php-version: "8.2" 18 | - if: hashFiles('composer.json') != '' 19 | uses: ramsey/composer-install@v2 20 | with: 21 | composer-options: "--no-dev" 22 | - uses: FriendsOfREDAXO/installer-action@v1 23 | with: 24 | myredaxo-username: ${{ secrets.MYREDAXO_USERNAME }} 25 | myredaxo-api-key: ${{ secrets.MYREDAXO_API_KEY }} 26 | description: ${{ github.event.release.body }} 27 | version: ${{ github.event.release.tag_name }} 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Friends Of REDAXO 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ***Falls jemand das AddOn "übernehmen" möchte bitte gerne :-)*** 2 | 3 | --- 4 | 5 | 6 | 7 | # Aufgaben - AddOn für REDAXO 5 ### 8 | 9 | ***Eine ToDo Verwaltung für das Redaxo Backend.*** 10 | 11 | 12 | 13 | 14 | * durch Klick auf "blaue" Aufgaben wird die Beschreibung angezeigt. 15 | * durch Klick auf die Überschriften wird die Tabelle entsprechend sortiert. 16 | * durch Klick auf das Wort "Aufgaben" können die erledigten Aufgaben dauerhaft ein- bzw. ausgeblendet werden. 17 | * Kategorien werden durch den Admin gepflegt. 18 | 19 | 20 | 21 | 22 | --- 23 | 24 | ## Autor 25 | 26 | **Friends Of REDAXO** 27 | 28 | * http://www.redaxo.org 29 | * https://github.com/FriendsOfREDAXO 30 | 31 | **Projekt-Lead** 32 | 33 | * [Oliver Kreischer](https://github.com/olien) 34 | 35 | ___ 36 | 37 | ## Credits 38 | 39 | * [jquery.sumoselect](https://github.com/HemantNegi/jquery.sumoselect) von Hemant Negi 40 | * [Pikaday](https://github.com/dbushell/Pikaday) von David Bushell 41 | * [moment.js](https://github.com/moment/moment/) 42 | * [jquery-simplecolorpicker](https://github.com/tkrotoff/jquery-simplecolorpicker) von Tanguy Krotoff 43 | 44 | --- 45 | 46 | * Idee und Realisierung der ersten Version: [concedra.de / Oliver Kreischer](http://concedra.de) 47 | -------------------------------------------------------------------------------- /pages/info.help.php: -------------------------------------------------------------------------------- 1 | getId(); 8 | $sql = rex_sql::factory(); 9 | //$sql->setDebug(); 10 | $sql->setQuery('SELECT * FROM rex_user WHERE id = '.$current_user); 11 | $user = $sql->getValue('login'); 12 | 13 | $qry = " 14 | 15 | -- Aufgaben 16 | 17 | INSERT IGNORE `rex_aufgaben` VALUES 18 | (1, 'Fav Icon erstellen', 'Wird immer benötigt',1,1,0,1,now(),now(),'$user','$user','','','2'), 19 | (2, 'Touch Icon erstellen', '',1,1,0,1,now(),now(),'$user','$user','','','1'), 20 | (3, 'Meta Infos erstellen', 'Sind Ortsbezogene meta Infos wichtig?',1,1,0,1,now(),now(),'$user','$user','','','2'), 21 | (4, 'Print.css entwickeln', 'Wird immer vergessen',1,1,0,1,now(),now(),'$user','$user','','','1'), 22 | (5, 'robots.txt prüfen', ':-)',7,1,0,1,now(),now(),'$user','$user','','','2'); 23 | 24 | -- Kategorien 25 | 26 | INSERT IGNORE `rex_aufgaben_categories` VALUES 27 | (1,'Grundlagen','#9EAEC2'), 28 | (2,'Backend','#588D76'), 29 | (3,'Design','#8D588A'), 30 | (4,'Funktion','#9EAEC2'), 31 | (5,'Fehler','#72A3A7'), 32 | (6,'Wunsch','#FFD83D'), 33 | (7,'SEO','#437047'); 34 | 35 | -- User Settings 36 | 37 | INSERT IGNORE `rex_aufgaben_user_settings` VALUES (1,$current_user,5); 38 | "; 39 | 40 | $sql = rex_sql::factory(); 41 | // $sql->setDebug(); 42 | $sql->setQuery($qry); 43 | 44 | echo '
Der Beispieldaten wurden eingefügt.
'; 45 | $func = ''; 46 | } 47 | 48 | $file = rex_file::get(rex_path::addon('aufgaben','README.md')); 49 | $Parsedown = new Parsedown(); 50 | $content = '
'.$Parsedown->text($file); 51 | 52 | $content .= ' 53 |
54 |

Beispieldaten importieren 55 |

56 |
57 | '; 58 | $fragment = new rex_fragment(); 59 | $fragment->setVar('title', 'Hilfe'); 60 | $fragment->setVar('body', $content, false); 61 | echo $fragment->parse('core/page/section.php'); 62 | -------------------------------------------------------------------------------- /assets/js/custom.js: -------------------------------------------------------------------------------- 1 | $('#kategoriefilter').SumoSelect({okCancelInMulti: true }); 2 | 3 | $('#priofilter').SumoSelect({ okCancelInMulti: true }); 4 | $('#eigentuemerfilter').SumoSelect({ okCancelInMulti: true }); 5 | $('#statusfilter').SumoSelect({ okCancelInMulti: true }); 6 | 7 | $("#kategoriefilter").change(function(){ 8 | $value_k = $("#kategoriefilter").val(); 9 | if ($value_k == null) {$value_k = '0'}; 10 | location.replace("index.php?page=aufgaben/aufgaben&func=filter&filter_kategorien="+$value_k ); 11 | }); 12 | $("#eigentuemerfilter").change(function(){ 13 | $value_e = $("#eigentuemerfilter").val(); 14 | if ($value_e == null) $value_e = '0'; 15 | location.replace("index.php?page=aufgaben/aufgaben&func=filter&filter_eigentuemer="+$value_e ); 16 | }); 17 | $("#priofilter").change(function(){ 18 | $value_p = $("#priofilter").val(); 19 | if ($value_p == null) {$value_p = '0'}; 20 | location.replace("index.php?page=aufgaben/aufgaben&func=filter&filter_prio="+$value_p ); 21 | }); 22 | $("#statusfilter").change(function(){ 23 | $value_s = $("#statusfilter").val(); 24 | if ($value_s == null) {$value_s = '0'}; 25 | location.replace("index.php?page=aufgaben/aufgaben&func=filter&filter_status="+$value_s ); 26 | }); 27 | 28 | $("#erledigtverbergen").click(function(){ 29 | location.replace("index.php?page=aufgaben/aufgaben&func=erledigtfilter&filter_erledigt=1" ); 30 | }); 31 | $("#erledigtanzeigen").click(function(){ 32 | location.replace("index.php?page=aufgaben/aufgaben&func=erledigtfilter&filter_erledigt=0" ); 33 | }); 34 | 35 | $(".watch").click(function(){ 36 | 37 | // location.replace("index.php?page=aufgaben/aufgaben&func=erledigtfilter&filter_erledigt=0" ); 38 | 39 | $(this).toggleClass( "enabled" ); 40 | }); 41 | 42 | $("select.form-control").on('change', function () { 43 | $(this).blur(); 44 | }); 45 | 46 | var picker = new Pikaday( 47 | { 48 | field: $('#datepicker')[0] , 49 | format: 'DD.MM.YYYY', 50 | i18n: { 51 | previousMonth : 'Nächster Monat', 52 | nextMonth : 'Vorheriger Monat', 53 | months : ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'], 54 | weekdays : ['Sonntag','Montag','Dienstag','Mittwoch','Donjnerstag','Freitag','Samstag'], 55 | weekdaysShort : ['So','Mo','Di','Mi','Do','Fr','Sa'] 56 | } 57 | } 58 | ); 59 | -------------------------------------------------------------------------------- /scss/_simplecolorpicker.scss: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Very simple jQuery Color Picker 4 | * https://github.com/tkrotoff/jquery-.aufgabensimplecolorpicker 5 | * 6 | * Copyright (C) 2012-2013 Tanguy Krotoff 7 | * 8 | * Licensed under the MIT license 9 | */ 10 | 11 | /** 12 | * Inspired by Bootstrap Twitter. 13 | * See https://github.com/twbs/bootstrap/blob/master/less/navbar.less 14 | * See https://github.com/twbs/bootstrap/blob/master/less/dropdowns.less 15 | */ 16 | 17 | .aufgabensimplecolorpicker.picker { 18 | position: absolute; 19 | top: 100%; 20 | left: 0; 21 | z-index: 1051; /* Above Bootstrap modal (@zindex-modal = 1050) */ 22 | display: none; 23 | float: left; 24 | 25 | min-width: 160px; 26 | max-width: 90%; /* @popover-max-width = 276px + 7 */ 27 | 28 | padding: 5px 0 0 5px; 29 | margin: 2px 0 0; 30 | list-style: none; 31 | background-color: #fff; /* @dropdown-bg */ 32 | 33 | border: 1px solid #ccc; /* @dropdown-fallback-border */ 34 | border: 1px solid rgba(0, 0, 0, .15); /* @dropdown-border */ 35 | 36 | -webkit-border-radius: 4px; /* @border-radius-base */ 37 | -moz-border-radius: 4px; 38 | border-radius: 4px; 39 | 40 | -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); 41 | -moz-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); 42 | box-shadow: 0 6px 12px rgba(0, 0, 0, .175); 43 | 44 | -webkit-background-clip: padding-box; 45 | -moz-background-clip: padding; 46 | background-clip: padding-box; 47 | } 48 | 49 | .aufgabensimplecolorpicker.inline { 50 | display: inline-block; 51 | padding: 6px 0; 52 | } 53 | 54 | .aufgabensimplecolorpicker span { 55 | margin: 0 5px 5px 0; 56 | } 57 | 58 | .aufgabensimplecolorpicker.icon { 59 | margin: 1px; 60 | } 61 | 62 | 63 | .aufgabensimplecolorpicker.icon, 64 | .aufgabensimplecolorpicker span.color { 65 | display: inline-block; 66 | cursor: pointer; 67 | border: 1px solid transparent; 68 | } 69 | 70 | .aufgabensimplecolorpicker.icon:after, 71 | .aufgabensimplecolorpicker span.color:after { 72 | content: '\00a0\00a0\00a0\00a0'; /* Spaces */ 73 | } 74 | 75 | .aufgabensimplecolorpicker span.color[data-disabled]:hover { 76 | cursor: not-allowed; 77 | border: 1px solid transparent; 78 | } 79 | 80 | .aufgabensimplecolorpicker span.color:hover, 81 | .aufgabensimplecolorpicker span.color[data-selected], 82 | .aufgabensimplecolorpicker span.color[data-selected]:hover { 83 | border: 1px solid #222; /* @gray-dark */ 84 | } 85 | .aufgabensimplecolorpicker span.color[data-selected]:after { 86 | color: #fff; 87 | } 88 | 89 | /* Vertical separator, replaces optgroup. */ 90 | .aufgabensimplecolorpicker span.vr { 91 | border-left: 1px solid #222; /* @gray-dark */ 92 | } 93 | -------------------------------------------------------------------------------- /lib/testen.php: -------------------------------------------------------------------------------- 1 | function save_datas($aktuelle_id, $aufgabe) { 2 | if ($aufgabe != '') { 3 | 4 | // Aufgabe holen 5 | if ($aktuelle_id == 0) { 6 | $expand_query = 'ORDER BY id DESC LIMIT 1'; 7 | $aufagen_art = 'new'; 8 | } else { 9 | $expand_query = 'WHERE id = '.$aktuelle_id; 10 | $aufagen_art = 'edit'; 11 | } 12 | $sql_aufgabe = rex_sql::factory(); 13 | // $sql_aufgabe->setDebug(); 14 | $sql_aufgabe->setQuery('SELECT * FROM rex_aufgaben '.$expand_query); 15 | 16 | if ($sql_aufgabe->getRows()) { 17 | // Mailinhalt 18 | $mail_titel = $sql_aufgabe->getValue('title'); 19 | $mail_beschreibung = $sql_aufgabe->getValue('description'); 20 | $mail_prio = $sql_aufgabe->getValue('prio'); 21 | $mail_status = $sql_aufgabe->getValue('status'); 22 | $mail_eigentuemer = $sql_aufgabe->getValue('responsible'); 23 | $creatuser_realname = $sql_aufgabe->getValue('createuser'); 24 | $creatuser_sql = rex_sql::factory(); 25 | $creatuser_sql->setQuery("SELECT name FROM rex_user WHERE login = '$creatuser_realname'"); 26 | $mail_creatuser = $creatuser_sql->getValue('name'); 27 | $updateuser_realname = $sql_aufgabe->getValue('updateuser'); 28 | $updateuser_sql = rex_sql::factory(); 29 | $updateuser_sql->setQuery("SELECT name FROM rex_user WHERE login = '$updateuser_realname'"); 30 | $mail_updateuser = $updateuser_sql->getValue('name'); 31 | 32 | $mail_finaldate = $sql_aufgabe->getValue('finaldate'); 33 | 34 | if ($mail_finaldate == '') { 35 | $mail_finaldate = '--'; 36 | } 37 | 38 | $data = array($mail_titel, $mail_beschreibung, $mail_prio, $mail_status, $mail_eigentuemer, $creatuser_realname, $creatuser_sql, $mail_creatuser, $updateuser_realname, $updateuser_sql, $mail_updateuser, $mail_finaldate); 39 | dump($data); 40 | 41 | $sql_status_name = rex_sql::factory(); 42 | // $sql_status_name->setDebug(); 43 | $sql_status_name->setQuery('SELECT status FROM rex_aufgaben_status WHERE id = '.$mail_status); 44 | $mail_status = $sql_status_name->getValue('status'); 45 | 46 | 47 | $sql_eigentuemer_name = rex_sql::factory(); 48 | $sql_eigentuemer_name->setQuery('SELECT * FROM rex_user WHERE id = '.$mail_eigentuemer); 49 | $mail_eigentuemer = $sql_eigentuemer_name->getValue('name'); 50 | 51 | 52 | if(rex_addon::get('textile')->isAvailable()) { 53 | $text_beschreibung = str_replace('
', '', $mail_beschreibung); 54 | $text_beschreibung = rex_textile::parse($text_beschreibung); 55 | $text_beschreibung = str_replace('###', ' ', $text_beschreibung); 56 | } else { 57 | $text_beschreibung = str_replace(PHP_EOL,'
', $mail_beschreibung ); 58 | } 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /install.php: -------------------------------------------------------------------------------- 1 | hasConfig()) { 4 | $this->setConfig('ansicht', 'liste'); 5 | $this->setConfig('mails', []); 6 | $this->setConfig('time', 5); 7 | $this->setConfig('send-to-all', '0'); 8 | $this->setConfig('betreff', ""); 9 | $this->setConfig('absender', ""); 10 | } 11 | 12 | rex_sql_table::get(rex::getTable('aufgaben')) 13 | ->ensurePrimaryIdColumn() 14 | ->ensureColumn(new rex_sql_column('title', 'varchar(255)', true)) 15 | ->ensureColumn(new rex_sql_column('description', 'longtext', true)) 16 | ->ensureColumn(new rex_sql_column('category', 'int(10)', true)) 17 | ->ensureColumn(new rex_sql_column('responsible', 'int(10)', true)) 18 | ->ensureColumn(new rex_sql_column('prio', 'int(10)', true)) 19 | ->ensureColumn(new rex_sql_column('status', 'int(10)', true)) 20 | ->ensureColumn(new rex_sql_column('createdate', 'datetime', true)) 21 | ->ensureColumn(new rex_sql_column('updatedate', 'datetime', true)) 22 | ->ensureColumn(new rex_sql_column('createuser', 'varchar(255)', true)) 23 | ->ensureColumn(new rex_sql_column('updateuser', 'varchar(255)', true)) 24 | ->ensureColumn(new rex_sql_column('observer', 'varchar(255)', true)) 25 | ->ensureColumn(new rex_sql_column('finaldate', 'varchar(255)', true)) 26 | ->ensureColumn(new rex_sql_column('versendet', 'varchar(255)', true, '2')) 27 | ->ensure(); 28 | 29 | 30 | rex_sql_table::get(rex::getTable('aufgaben_categories')) 31 | ->ensurePrimaryIdColumn() 32 | ->ensureColumn(new rex_sql_column('category', 'varchar(255)', true)) 33 | ->ensureColumn(new rex_sql_column('color', 'varchar(255)', true)) 34 | ->ensure(); 35 | 36 | 37 | rex_sql_table::get(rex::getTable('aufgaben_filter')) 38 | ->ensurePrimaryIdColumn() 39 | ->ensureColumn(new rex_sql_column('user', 'varchar(255)', true)) 40 | ->ensureColumn(new rex_sql_column('category', 'varchar(255)', true)) 41 | ->ensureColumn(new rex_sql_column('responsible', 'varchar(255)', true)) 42 | ->ensureColumn(new rex_sql_column('prio', 'varchar(255)', true)) 43 | ->ensureColumn(new rex_sql_column('status', 'varchar(255)', true)) 44 | ->ensureColumn(new rex_sql_column('done', 'varchar(255)', true)) 45 | ->ensure(); 46 | 47 | rex_sql_table::get(rex::getTable('aufgaben_status')) 48 | ->ensurePrimaryIdColumn() 49 | ->ensureColumn(new rex_sql_column('status', 'varchar(255)', true)) 50 | ->ensureColumn(new rex_sql_column('icon', 'varchar(255)', true)) 51 | ->ensure(); 52 | 53 | rex_sql_table::get(rex::getTable('aufgaben_user_settings')) 54 | ->ensurePrimaryIdColumn() 55 | ->ensureColumn(new rex_sql_column('user', 'int(10)', true)) 56 | ->ensureColumn(new rex_sql_column('counter', 'int(10)', true)) 57 | ->ensure(); 58 | 59 | 60 | $sql = rex_sql::factory(); 61 | $sql->setQuery(" 62 | REPLACE INTO `rex_aufgaben_status` VALUES 63 | (1,'Offen','fa-folder-open-o'), 64 | (2,'Wird bearbeitet','fa-gears'), 65 | (3,'Frage','fa-question'), 66 | (4,'Warten auf etwas','fa-hourglass-start'), 67 | (5,'Auf später verschoben','fa-calendar'), 68 | (6,'Erledigt','fa-check'); 69 | "); 70 | 71 | $error = ''; 72 | 73 | if(!$error) { 74 | $this->setConfig('install', true); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /scss/master.scss: -------------------------------------------------------------------------------- 1 | @import "../aufgaben/scss/sumoselect"; 2 | @import "../aufgaben/scss/pickaday"; 3 | @import "../aufgaben/scss/simplecolorpicker"; 4 | @import "../aufgaben/scss/kanban"; 5 | 6 | // Status 7 | #aufgaben { 8 | // border: 1px solid green; 9 | .status { 10 | display: inline-block; 11 | min-width: 156px; 12 | a i { 13 | float: left; 14 | display: inline-block; 15 | width: 23px; 16 | margin-right: 3px; 17 | border: 1px solid #ccc; 18 | padding: 3px 2px 3px 2px; 19 | font-size: 14px; 20 | text-align: center; 21 | color: #ccc; 22 | transition: all 0.3s ease 0s; 23 | &:hover { 24 | border: 1px solid #000; 25 | color: #000; 26 | } 27 | } 28 | .current { 29 | color: #555; 30 | &.fa-check { 31 | color: #3CB594; 32 | } 33 | } 34 | } 35 | } 36 | 37 | // Prio 38 | #aufgaben { 39 | .priowrapper { 40 | display: inline-block; 41 | min-width: 110px; 42 | a i { 43 | float: left; 44 | display: inline-block; 45 | width: 23px; 46 | margin-right: 3px; 47 | border: 1px solid #ccc; 48 | padding: 2px; 49 | font-size: 16px; 50 | text-align: center; 51 | color: #ccc; 52 | transition: all 0.3s ease 0s; 53 | &:hover { 54 | border: 1px solid #000; 55 | color: #000; 56 | } 57 | &.fa-star { 58 | padding: 2px; 59 | color: #f0ad4e; 60 | } 61 | &.fa-star-o { 62 | padding: 2px; 63 | &:hover { 64 | color: #f0ad4e; 65 | } 66 | } 67 | } 68 | } 69 | } 70 | 71 | 72 | // Tabelle 73 | #aufgaben { 74 | 75 | 76 | 77 | .collapsetitle { 78 | display: inline-block; 79 | color: #4B9AD9; 80 | &:hover { 81 | cursor: pointer; 82 | color: #000; 83 | } 84 | } 85 | .td_aufgaben { 86 | width: auto; 87 | } 88 | 89 | .td_category { 90 | min-width: 150px; 91 | font-size: 12px; 92 | } 93 | 94 | .td_prio { 95 | width: 120px; 96 | font-size: 14px; 97 | } 98 | 99 | .td_responsible { 100 | min-width: 150px; 101 | font-size: 12px; 102 | .single { 103 | position: absolute; 104 | padding-top: 2px; 105 | 106 | } 107 | } 108 | 109 | .td_updatedate { 110 | width: 150px; 111 | font-size: 12px; 112 | span { 113 | font-size: 10px; 114 | color: #999; 115 | } 116 | } 117 | 118 | .td_finaldate { 119 | width: 90px; 120 | font-size: 12px; 121 | } 122 | .td_status { 123 | width: 156px; 124 | } 125 | .td_edit { 126 | width: 35px; 127 | i { 128 | padding: 2px 2px 2px 3px; 129 | width: 23px; 130 | font-size: 17px; 131 | border: 1px solid #eee; 132 | } 133 | } 134 | tbody tr:nth-child(odd) { 135 | background-color: #efefef; 136 | } 137 | thead { 138 | font-size: 12px; 139 | } 140 | form table { 141 | margin-bottom: 0; 142 | } 143 | } 144 | 145 | 146 | // Trenner 147 | #aufgaben { 148 | .aufgabentrenner { 149 | border-top: 1px solid #ddd; 150 | border-bottom: 1px solid #ddd; 151 | font-size: 12px; 152 | padding: 4px 0 4px 0; 153 | margin: 4px 0 4px 0; 154 | color: #555; 155 | } 156 | } 157 | 158 | // Erledigtschalter 159 | #aufgaben { 160 | .erledigtschalter { 161 | position: relative; 162 | display: inline-block; 163 | font-size: 12px; 164 | } 165 | .erledigtschalter i { 166 | position: absolute; 167 | bottom: 1px; 168 | font-size: 14px; 169 | margin-left: 5px; 170 | } 171 | } 172 | 173 | // Navi 174 | #rex-navi-page-aufgaben .label { 175 | margin-top: 2px; 176 | float: right; 177 | } 178 | 179 | // Watch 180 | #aufgaben { 181 | a.watch { 182 | color: #ddd !important; 183 | i { 184 | color: #ddd !important; 185 | font-size: 15px; 186 | &:hover { 187 | transition: all 0.3s ease 0s; 188 | color: #000 !important; 189 | } 190 | } 191 | &.enabled i{ 192 | color: #555 !important; 193 | } 194 | } 195 | } 196 | 197 | #aufgaben { 198 | .rex-nav-pagination { 199 | font-size: 10px; 200 | padding: 10px; 201 | ul { 202 | font-size: 10px; 203 | li { 204 | a { 205 | padding: 6px 8px 6px 8px; 206 | } 207 | } 208 | } 209 | } 210 | 211 | } 212 | 213 | #aufgaben .rex-select-style.intable { 214 | border: none; 215 | padding-right: 20px; 216 | background: transparent url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAR0lEQVQokWNgGH6AEZnz//9/ghp+/PjBxIgm5otL8f///zfD2Ey4JPCJMxFSgMsgZAVwzMDA4Pv//3+G48ePCyKLE+PvoQgAyHozRmwVt2MAAAAASUVORK5CYII=') no-repeat 97.5% 50%; 217 | &:hover { 218 | background: transparent url("data:image/png;base64,R0lGODlhDwAUAIABAAAAAP///yH5BAEAAAEALAAAAAAPABQAAAIXjI+py+0Po5wH2HsXzmw//lHiSJZmUAAAOw==") no-repeat 98% 50%; 219 | } 220 | select { 221 | padding: 2px 0 2px 0; 222 | width: 100%; 223 | overflow: hidden; 224 | text-overflow: ellipsis; 225 | } 226 | option { 227 | background: #ff0 !important; 228 | } 229 | } 230 | 231 | 232 | #rex-page-aufgaben-aufgaben .markitupEditor-simple { 233 | margin-top: -10px; 234 | min-height: 300px; 235 | } 236 | 237 | -------------------------------------------------------------------------------- /boot.php: -------------------------------------------------------------------------------- 1 | getAssetsUrl('js/jquery.sumoselect.js')); 11 | rex_view::addJSFile($this->getAssetsUrl('js/kanban.js')); 12 | rex_view::addJSFile($this->getAssetsUrl('js/jquery.simplecolorpicker.js')); 13 | rex_view::addJSFile($this->getAssetsUrl('js/moments.js')); 14 | rex_view::addJSFile($this->getAssetsUrl('js/pikaday.js')); 15 | rex_view::addJSFile($this->getAssetsUrl('js/custom.js')); 16 | 17 | /////////// 18 | // SCSS 19 | /////////// 20 | rex_extension::register('PACKAGES_INCLUDED', function () { 21 | if (rex::getUser() && $this->getProperty('compile')) { 22 | 23 | $compiler = new rex_scss_compiler(); 24 | 25 | $scss_files = rex_extension::registerPoint(new rex_extension_point('BE_STYLE_SCSS_FILES', [$this->getPath('scss/master.scss')])); 26 | $compiler->setScssFile($scss_files); 27 | $compiler->setCssFile($this->getPath('assets/css/styles.css')); 28 | $compiler->compile(); 29 | rex_file::copy($this->getPath('assets/css/styles.css'), $this->getAssetsPath('css/styles.css')); 30 | } 31 | }); 32 | rex_view::addCssFile($this->getAssetsUrl('css/styles.css')); 33 | 34 | 35 | /////////// 36 | // Subpages 37 | /////////// 38 | 39 | // aufgaben Listenansicht 40 | if ($this->getConfig('ansicht') == 'liste' OR $this->getConfig('ansicht') == 'beide') { 41 | $page = $this->getProperty('page'); 42 | $page['subpages']['aufgaben'] = ['title' => $this->i18n('aufgaben_title')]; 43 | $this->setProperty('page', $page); 44 | } 45 | if ($this->getConfig('time') == '5Minuten') { 46 | $this->setConfig('time', 5); 47 | // dump($this->getConfig('time')); 48 | }if ($this->getConfig('time') == '15Minuten') { 49 | $this->setConfig('time', 15); 50 | // dump($this->getConfig('time')); 51 | }if ($this->getConfig('time') == '30Minuten') { 52 | $this->setConfig('time', 30); 53 | // dump($this->getConfig('time')); 54 | 55 | } 56 | if ($this->getConfig('time') == '60Minuten') { 57 | $this->setConfig('time', 60); 58 | // dump($this->getConfig('time')); 59 | }if ($this->getConfig('time') == '120Minuten') { 60 | $this->setConfig('time', 120); 61 | // dump($this->getConfig('time')); 62 | }if ($this->getConfig('time') == '0Minuten') { 63 | $this->setConfig('time', 0); 64 | // dump($this->getConfig('time')); 65 | 66 | } 67 | if ($this->getConfig('absender') != null) { 68 | $absender = $this->getConfig('absender'); 69 | $this->setConfig('absender',$absender); 70 | } 71 | if ($this->getConfig('betreff') != null) { 72 | $betreff = $this->getConfig('betreff'); 73 | $this->setConfig('betreff',$betreff); 74 | } 75 | if($this->getConfig('send-to-all') == 1) { 76 | $checkbox = $this->getConfig('send-to-all'); 77 | $this->setConfig('send-to-all', $checkbox); 78 | // dump($checkbox); 79 | } 80 | if($this->getConfig('send-to-all') == 0) { 81 | $checkbox = $this->getConfig('send-to-all'); 82 | $this->setConfig('send-to-all', $checkbox); 83 | // dump($checkbox); 84 | } 85 | 86 | 87 | // Kanban Ansicht 88 | if ($this->getConfig('ansicht') == 'kanban' OR $this->getConfig('ansicht') == 'beide') { 89 | $page = $this->getProperty('page'); 90 | $page['subpages']['kanban'] = ['title' => 'Kanban Ansicht']; 91 | $this->setProperty('page', $page); 92 | } 93 | // Kategorien 94 | $page = $this->getProperty('page'); 95 | $page['subpages']['categories'] = ['title' => $this->i18n('aufgaben_categories'), 'perm' => 'aufgaben[categories]']; 96 | $this->setProperty('page', $page); 97 | 98 | // Einstellungen 99 | $page = $this->getProperty('page'); 100 | $page['subpages']['settings'] = ['title' => 'Einstellungen', 'perm' =>'admin[]']; 101 | $this->setProperty('page', $page); 102 | 103 | // Import /( Export) 104 | $page = $this->getProperty('page'); 105 | $page['subpages']['exim'] = ['title' => 'Export', 'perm' =>'admin[]' ]; 106 | $page['subpages']['exim']['subpages']['export'] = ['title' => 'Export']; 107 | // $page['subpages']['exim']['subpages']['import'] = ['title' => 'Import']; 108 | $this->setProperty('page', $page); 109 | 110 | 111 | // Info 112 | $page = $this->getProperty('page'); 113 | $page['subpages']['info'] = ['title' => $this->i18n('aufgaben_info')]; 114 | $page['subpages']['info']['subpages']['help'] = ['title' => $this->i18n('aufgaben_help')]; 115 | $page['subpages']['info']['subpages']['changelog'] = ['title' => $this->i18n('aufgaben_changelog')]; 116 | $page['subpages']['info']['subpages']['licence'] = ['title' => $this->i18n('aufgaben_licence')]; 117 | $this->setProperty('page', $page); 118 | 119 | //Standard-Delay 120 | 121 | if ($this->getConfig('install') == 'true' && rex::getUser()) { 122 | $current_page = rex_be_controller::getCurrentPage(); 123 | if ($current_page != 'aufgaben/aufgaben') { 124 | $counter = new rex_aufgaben(); 125 | $counter->show_counter(); 126 | } 127 | } 128 | 129 | 130 | 131 | } 132 | 133 | -------------------------------------------------------------------------------- /pages/exim.export.php: -------------------------------------------------------------------------------- 1 | setTable('rex_aufgaben'); 4 | $qry->select('*'); 5 | 6 | if (rex_post('export', 'bool')) { 7 | $filename = 'aufgaben_' . date('Ymd_Hi'); 8 | 9 | // kategorie 10 | 11 | $sql = rex_sql::factory(); 12 | $sql->setTable('rex_aufgaben_categories'); 13 | $sql->select("*"); 14 | $kategorien = $sql->getArray(); 15 | $kategorienArray = []; 16 | foreach($kategorien as $kategorie) { 17 | $kategorienArray[$kategorie["id"]] = $kategorie["category"]; 18 | } 19 | 20 | // user 21 | 22 | $sql->setTable('rex_user'); 23 | $sql->select("*"); 24 | $eigentuemer = $sql->getArray(); 25 | $eigentuemerArray = []; 26 | foreach($eigentuemer as $eigentuem) { 27 | $eigentuemerArray[$eigentuem["id"]] = $eigentuem["login"]; 28 | } 29 | 30 | // status 31 | 32 | $sql->setTable('rex_aufgaben_status'); 33 | $sql->select("*"); 34 | $stati = $sql->getArray(); 35 | $statiArray = []; 36 | foreach($stati as $status) { 37 | $statiArray[$status["id"]] = $status["status"]; 38 | } 39 | 40 | // get all todos 41 | 42 | $qryArray = []; 43 | $firstLineKeys = false; 44 | foreach($qry->getArray() as $line) { 45 | if (empty($firstLineKeys)) { 46 | $firstLineKeys = array_keys($line); 47 | $firstLineKeys = array_flip($firstLineKeys); 48 | } 49 | 50 | // -----set values 51 | 52 | $line["kategorie"] = $kategorienArray[$line["category"]]; 53 | $line["eigentuemer"] = $eigentuemerArray[$line["responsible"]]; 54 | $line["prio"] = "Prio: " . $line["prio"]; 55 | $line["status"] = $statiArray[$line["status"]]; 56 | array_push($qryArray, array_merge($firstLineKeys, $line)); 57 | } 58 | 59 | if (rex_post('type') === "json") { 60 | 61 | // ------JSON EXPORT 62 | 63 | ob_end_clean(); 64 | header('Content-Type: application/json'); 65 | header('Content-Disposition: attachment; filename="' . $filename . '.json"'); 66 | echo json_encode($qryArray, JSON_UNESCAPED_UNICODE); 67 | exit; 68 | 69 | // -----/JSON EXPORT 70 | 71 | } 72 | 73 | if (rex_post('type') === "csv") { 74 | 75 | // ------CSV EXPORT 76 | 77 | ob_end_clean(); 78 | header('Content-Type: application/excel'); 79 | header('Content-Disposition: attachment; filename="' . $filename . '.csv"'); 80 | $file = fopen('php://output', 'w'); 81 | $firstLineKeys = false; 82 | function encode_items($array) 83 | { 84 | foreach($array as $key => $value) { 85 | if (is_array($value)) { 86 | $array[$key] = encode_items($value); 87 | } 88 | else { 89 | $array[$key] = mb_convert_encoding($value, 'Windows-1252', 'UTF-8'); 90 | } 91 | } 92 | 93 | return $array; 94 | } 95 | 96 | foreach(encode_items($qryArray) as $line) { 97 | if (empty($firstLineKeys)) { 98 | $firstLineKeys = array_keys($line); 99 | fputcsv($file, $firstLineKeys); 100 | $firstLineKeys = array_flip($firstLineKeys); 101 | } 102 | 103 | fputcsv($file, array_merge($firstLineKeys, $line)); 104 | } 105 | 106 | fclose($file); 107 | exit; 108 | 109 | // -----/CSV EXPORT 110 | 111 | } 112 | } 113 | 114 | $content = '
'; 115 | $content.= '
'; 116 | $content.= '
'; 117 | $content.= '
118 |
Dateityp wählen
119 |
120 |
121 |
122 |
123 | 124 | 125 |
126 |
127 |
128 |
129 |
130 |
131 | 132 | 133 |
134 |
135 |
136 |
137 |
138 |
139 | 140 |
141 |
142 |
143 |
'; 144 | $content.= '
'; 145 | $content.= '
'; 146 | $content.= '
'; 147 | $fragment = new rex_fragment(); 148 | $fragment->setVar('class', 'edit', false); 149 | $fragment->setVar('title', $this->i18n('aufgaben_exim_export')); 150 | $fragment->setVar('body', $content, false); 151 | echo $fragment->parse('core/page/section.php'); 152 | ?> 153 | -------------------------------------------------------------------------------- /pages/categories.php: -------------------------------------------------------------------------------- 1 | setDebug(); 10 | 11 | $sql->setQuery('SELECT * FROM rex_aufgaben WHERE category =' . $id); 12 | 13 | if ($sql->getRows() > 0) 14 | { 15 | echo '
'.$this->i18n('aufgaben_categories_category_in_use').'
'; 16 | } 17 | else 18 | { 19 | $sql->setTable('rex_aufgaben_categories'); 20 | $sql->setWhere('id = ' . $id); 21 | 22 | if ($sql->delete()) 23 | { 24 | echo '
'.$this->i18n('aufgaben_categories_category_deleted').'
'; 25 | } 26 | } 27 | 28 | $func = ''; 29 | } 30 | 31 | if ($func == '') { 32 | $list = rex_list::factory("SELECT * FROM " . rex::getTablePrefix() . "aufgaben_categories ORDER BY category ASC"); 33 | $list->addTableAttribute('class', 'table-striped'); 34 | $list->setNoRowsMessage(''); 35 | 36 | // icon column 37 | $thIcon = ''; 38 | $tdIcon = ''; 39 | $list->addColumn($thIcon, $tdIcon, 0, ['###VALUE###', '###VALUE###']); 40 | $list->setColumnParams($thIcon, ['func' => 'edit', 'id' => '###id###']); 41 | 42 | $list->setColumnLabel('category', $this->i18n('aufgaben_categories_category')); 43 | $list->setColumnParams('category', ['func' => 'edit', 'id' => '###id###']); 44 | 45 | 46 | $list->setColumnLabel('color', $this->i18n('aufgaben_categories_color')); 47 | $list->setColumnLayout('color', ['###VALUE###', '###VALUE###']); 48 | 49 | 50 | $delete = 'deleteCol'; 51 | $list->addColumn($delete, ' '.$this->i18n('aufgaben_categories_category_delete'), -1, ['', '###VALUE###']); 52 | $list->setColumnParams($delete, ['id' => '###id###', 'func' => 'delete']); 53 | 54 | $list->addLinkAttribute($delete, 'data-confirm', rex_i18n::msg('delete') . ' ?'); 55 | $list->removeColumn('id'); 56 | $content = '
' . $list->get() . '
'; 57 | $fragment = new rex_fragment(); 58 | $fragment->setVar('title', $this->i18n('aufgaben_categories_title')); 59 | $fragment->setVar('content', $content, false); 60 | $content = $fragment->parse('core/page/section.php'); 61 | echo $content; 62 | } 63 | elseif ($func == 'edit' || $func == 'add') { 64 | $fieldset = $func == 'edit' ? $this->i18n('aufgaben_categories_category_edit') : $this->i18n('aufgaben_categories_category_add'); 65 | $id = rex_request('id', 'int'); 66 | $form = rex_form::factory(rex::getTablePrefix() . 'aufgaben_categories', '', 'id=' . $id); 67 | $field = $form->addTextField('category'); 68 | $field->setLabel($this->i18n('aufgaben_categories_category')); 69 | 70 | $field->getValidator()->add('notEmpty', $this->i18n('aufgaben_categories_category_empty')); 71 | 72 | $field = $form->addSelectField('color'); 73 | $field->setPrefix('
'); 74 | $field->setSuffix('
'); 75 | $field->setLabel($this->i18n('aufgaben_categories_color')); 76 | $select =$field->getSelect(); 77 | $select->addOption('#000000','#000'); 78 | $select->addOption('#607D8B','#607D8B'); 79 | $select->addOption('#9E9E9E','#9E9E9E'); 80 | $select->addOption('#795548','#795548'); 81 | $select->addOption('#FF5722','#FF5722'); 82 | $select->addOption('#FF9800','#FF9800'); 83 | $select->addOption('#FFC107','#FFC107'); 84 | $select->addOption('#FFEB3B','#FFEB3B'); 85 | $select->addOption('#CDDC39','#CDDC39'); 86 | $select->addOption('#8BC34A','#8BC34A'); 87 | $select->addOption('#4CAF50','#4CAF50'); 88 | $select->addOption('#009688','#009688'); 89 | $select->addOption('#00BCD4','#00BCD4'); 90 | $select->addOption('#03A9F4','#03A9F4'); 91 | $select->addOption('#2196F3','#2196F3'); 92 | $select->addOption('#3F51B5','#3F51B5'); 93 | $select->addOption('#673AB7','#673AB7'); 94 | $select->addOption('#9C27B0','#9C27B0'); 95 | $select->addOption('#E91E63','#E91E63'); 96 | $select->addOption('#F44336','#F44336'); 97 | if ($field->getValue()== "") { 98 | $field->setValue('#000000'); 99 | } 100 | 101 | if ($func == 'edit') { 102 | $form->addParam('id', $id); 103 | } 104 | 105 | $content = $form->get(); 106 | $fragment = new rex_fragment(); 107 | $fragment->setVar('class', 'edit', false); 108 | $fragment->setVar('title', "$fieldset"); 109 | $fragment->setVar('body', $content, false); 110 | $content = '
' . $fragment->parse('core/page/section.php') . '
'; 111 | echo $content; 112 | } 113 | ?> 114 | 121 | 122 | -------------------------------------------------------------------------------- /lang/en_gb.lang: -------------------------------------------------------------------------------- 1 | // 2 | // General 3 | // 4 | aufgaben_title = Tasks 5 | aufgaben_info = Info 6 | aufgaben_help = Help 7 | aufgaben_licence = Licence 8 | aufgaben_changelog = Change log 9 | 10 | aufgaben_description = Description 11 | 12 | aufgaben_task = Task 13 | aufgaben_task_hide = Hide task 14 | aufgaben_last_update = Last update 15 | 16 | aufgaben_task = Task 17 | aufgaben_task_hide_title = Hide completed tasks 18 | aufgaben_task_hide = Hide tasks 19 | aufgaben_task_show_title = Show all Tasks 20 | aufgaben_task_show = Show all Tasks 21 | aufgaben_last_update = Last update 22 | 23 | aufgaben_last_update 24 | aufgaben_due = Due 25 | aufgaben_due_date = Due date 26 | 27 | aufgaben_category = Category 28 | aufgaben_categories = Categories 29 | 30 | aufgaben_responsible = Responsible 31 | 32 | aufgaben_prio = Prio 33 | 34 | aufgaben_status = Status 35 | 36 | aufgaben_edit = Edit task 37 | aufgaben_add = Add task 38 | aufgaben_title_empty = Please enter a title. 39 | aufgaben_category_empty = Please choose a category. 40 | aufgaben_responsible_empty = Please specify who is responsible for this task. 41 | 42 | aufgaben_please_choose = Please choose 43 | aufgaben_last_change = Last updated 44 | aufgaben_create_on = Created 45 | 46 | aufgaben_by = by 47 | 48 | aufgaben_mail_could_not_sent = E-mail could not be sent. 49 | aufgaben_mail_sent_to = E-mail sent to: 50 | 51 | aufgaben_markitupinfo = Created by AddOn Tasks 52 | 53 | aufgaben_mail_change = Task updated: 54 | aufgaben_mail_change_eigentuemer = Owner updated: 55 | aufgaben_mail_new = New task: 56 | aufgaben_mail_change_status = Task - status updated: 57 | aufgaben_mail_change_prio = Task - priority updated: 58 | aufgaben_mail_change_responsible = Task - responsibility updated: 59 | aufgaben_mail_change_cat = Task - category updated: 60 | 61 | aufgaben_versendet = Mail 62 | 63 | aufgaben_no_task = No tasks found.

Possible reasons:

- no tasks were created
- the currently applied filter excludes all of the existing tasks
- completed tasks are set to be hidden 64 | 65 | aufgaben_prev_month = Previous month 66 | aufgaben_next_month = Next month 67 | aufgaben_januar = January 68 | aufgaben_februar = February 69 | aufgaben_maerz = March 70 | aufgaben_april = April 71 | aufgaben_mai = May 72 | aufgaben_juni = June 73 | aufgaben_juli = July 74 | aufgaben_august = August 75 | aufgaben_september = September 76 | aufgaben_oktober = October 77 | aufgaben_november = November 78 | aufgaben_dezember = December 79 | aufgaben_sonntag = Sunday 80 | aufgaben_montag = Monday 81 | aufgaben_dienstag = Tuesday 82 | aufgaben_mittwoch = Wednesday 83 | aufgaben_donnerstag = Thursday 84 | aufgaben_freitag = Friday 85 | aufgaben_samstag = Saturday 86 | aufgaben_so = Sun 87 | aufgaben_mo = Mon 88 | aufgaben_di = Tue 89 | aufgaben_mi = Wed 90 | aufgaben_do = Thu 91 | aufgaben_fr = Fri 92 | aufgaben_sa = Sat 93 | 94 | 95 | 96 | 97 | // 98 | // Kategorien 99 | // 100 | aufgaben_categories_title = Categories 101 | aufgaben_categories_category = Category 102 | aufgaben_categories_color = Color 103 | aufgaben_categories_no_category = No categories found.
Please create a category or speak to your administrator 104 | aufgaben_categories_category_add = Add category 105 | aufgaben_categories_category_edit = Edit category 106 | aufgaben_categories_category_empty = Please assign a category 107 | aufgaben_categories_category_delete = Delete category 108 | aufgaben_categories_category_deleted = Category has been deleted 109 | aufgaben_categories_category_in_use = There are tasks assigned to this category.
The category has not been deleted! 110 | 111 | 112 | // 113 | // Einstellungen 114 | // 115 | 5_minuten_verzoegerung = 5 Minutes 116 | 15_minuten_verzoegerung = 15 Minutes 117 | 30_minuten_verzoegerung = 30 Minutes 118 | 60_minuten_verzoegerung = 1 hour 119 | 120_minuten_verzoegerung = 2 hours 120 | 0_minuten_verzoegerung = No delay 121 | aufgaben_settings_title = Settings 122 | aufgaben_settings_ansicht = View 123 | aufgaben_settings_beide = Both views 124 | aufgaben_settings_liste = List 125 | aufgaben_settings_kanban = Kanban 126 | aufgaben_settings_e_mails_an = Send e-mails to 127 | aufgaben_settings_e_mails_empty = None of the users in the user management have e-mail addresses supplied. 128 | aufgaben_settings_save = Save settings 129 | absender_Email = Sender 130 | absender_Email_placeholder = Please enter your E-Mail address 131 | betreff_Email_placeholder = Please enter the subject for the e-mail 132 | betreff_Email = Subject 133 | send-to-all-checkbox = Send mail to all 134 | zeit_ansicht = Automatic send Mail intervall 135 | 136 | // 137 | // Export / Import 138 | // 139 | aufgaben_exim_export = Export 140 | aufgaben_exim_dateityp = Filetype 141 | aufgaben_exim_dateityp_csv = Export tasks as .csv 142 | aufgaben_exim_dateityp_json = Export tasks as .json 143 | aufgaben_exim_export_save = Export task 144 | 145 | 146 | 147 | // 148 | // Kanban Ansicht 149 | // 150 | aufgaben_kanban = Kanban 151 | aufgaben_kanban_aufgabe_hinzufuegen = Add task 152 | aufgaben_kanban_title = Title 153 | aufgaben_kanban_error_title = Please enter a title 154 | aufgaben_kanban_description = Description 155 | aufgaben_kanban_category = Category 156 | aufgaben_kanban_responsible = Responsible 157 | aufgaben_kanban_status = Status 158 | aufgaben_kanban_abort = Cancel 159 | aufgaben_kanban_save = Save 160 | aufgaben_kanban_edit = Edit task 161 | aufgaben_kanban_delete = Delete Task 162 | aufgaben_kanban_delete_confirm = Would you like to delete the following task? 163 | -------------------------------------------------------------------------------- /lang/sv_se.lang: -------------------------------------------------------------------------------- 1 | // 2 | // General 3 | // 4 | aufgaben_title = Uppgifter 5 | aufgaben_info = Info 6 | aufgaben_help = Hjälp 7 | aufgaben_licence = Licens 8 | aufgaben_changelog = Changelog 9 | 10 | aufgaben_description = Beskrivning 11 | 12 | aufgaben_task = Uppgift 13 | aufgaben_task_hide_title = Dölj slutförda uppgifter 14 | aufgaben_task_hide = Dölj slutförda uppgifter 15 | aufgaben_task_show_title = Visa alla uppgifter 16 | aufgaben_task_show = Visa alla uppgifter 17 | aufgaben_last_update = Senaste aktualisering 18 | 19 | aufgaben_last_update 20 | aufgaben_due = Due 21 | aufgaben_due_date = Förfallodatum 22 | 23 | aufgaben_category = Kategori 24 | aufgaben_categories = Kategorier 25 | 26 | aufgaben_responsible = Ansvarig 27 | 28 | aufgaben_prio = Prio 29 | 30 | aufgaben_status = Status 31 | 32 | aufgaben_edit = Redigera uppgift 33 | aufgaben_add = Tillfoga uppgift 34 | aufgaben_title_empty = Var god ange en titel. 35 | aufgaben_category_empty = Var god välj en kategori. 36 | aufgaben_responsible_empty = Var god ange vem som är ansvarig för uppgiften. 37 | 38 | aufgaben_please_choose = Var god välj 39 | aufgaben_last_change = Senaste ändring 40 | aufgaben_create_on = Skapat den 41 | 42 | aufgaben_by = av 43 | 44 | aufgaben_mail_could_not_sent = E-posten kunde inte skickas 45 | aufgaben_mail_sent_to = E-post har skickats till: 46 | 47 | aufgaben_markitupinfo = Created by AddOn Tasks 48 | 49 | aufgaben_mail_change = Uppgiften ändrades: 50 | aufgaben_mail_change_eigentuemer = Ändrat uppgift: 51 | aufgaben_mail_new = Ny uppgift 52 | aufgaben_mail_change_status = Uppgift - status ändrades: 53 | aufgaben_mail_change_prio = Uppgift - prioritet ändrades: 54 | aufgaben_mail_change_responsible = Uppgift - behörighet ändrades: 55 | aufgaben_mail_change_cat = Uppgift - kategori ändrades: 56 | 57 | aufgaben_versendet = E-post 58 | 59 | aufgaben_no_task = Inga uppgifter hittades.

Möjliga orsaker:

- inga uppgifter skapades
- det aktuella filtret filterar bort alla befintliga uppgifter
- slutförda uppgifter är inställda att vara dolda 60 | 61 | aufgaben_prev_month = Förra månad 62 | aufgaben_next_month = Nästa månad 63 | aufgaben_januar = Januari 64 | aufgaben_februar = Februari 65 | aufgaben_maerz = Mars 66 | aufgaben_april = April 67 | aufgaben_mai = Maj 68 | aufgaben_juni = Juni 69 | aufgaben_juli = Juli 70 | aufgaben_august = Augusti 71 | aufgaben_september = September 72 | aufgaben_oktober = Oktober 73 | aufgaben_november = November 74 | aufgaben_dezember = December 75 | aufgaben_sonntag = Söndag 76 | aufgaben_montag = Måndag 77 | aufgaben_dienstag = Tisdag 78 | aufgaben_mittwoch = Onsdag 79 | aufgaben_donnerstag = Torsdag 80 | aufgaben_freitag = Fredag 81 | aufgaben_samstag = Lördag 82 | aufgaben_so = Sö 83 | aufgaben_mo = Må 84 | aufgaben_di = Ti 85 | aufgaben_mi = On 86 | aufgaben_do = To 87 | aufgaben_fr = Fr 88 | aufgaben_sa = Lö 89 | 90 | 91 | 92 | 93 | // 94 | // Kategorien 95 | // 96 | aufgaben_categories_title = Kategorier 97 | aufgaben_categories_category = Kategori 98 | aufgaben_categories_color = Färg 99 | aufgaben_categories_no_category = Inga kategorier hittades.
Vänligen skapa en kategori eller kontakta din administratör 100 | aufgaben_categories_category_add = Skapa kategori 101 | aufgaben_categories_category_edit = Redigera kategori 102 | aufgaben_categories_category_empty = Var god ange en kategori. 103 | aufgaben_categories_category_delete = Radera kategori 104 | aufgaben_categories_category_deleted = Kategorien raderades. 105 | aufgaben_categories_category_in_use = Det finns uppgifter kvar som tilldelats den här kategorin.
Kategorien har inte raderats! 106 | 107 | 108 | // 109 | // Einstellungen 110 | // 111 | 5_minuten_verzoegerung = 5 minuter 112 | 15_minuten_verzoegerung = 15 minuter 113 | 30_minuten_verzoegerung = 30 minuter 114 | 60_minuten_verzoegerung = 1 timme 115 | 120_minuten_verzoegerung = 2 timmar 116 | 0_minuten_verzoegerung = Inga fördröjningar 117 | aufgaben_settings_title = Inställningar 118 | aufgaben_settings_ansicht = Synhåll 119 | aufgaben_settings_beide = Båda synhåll 120 | aufgaben_settings_liste = Lista 121 | aufgaben_settings_kanban = Kanban 122 | aufgaben_settings_e_mails_an = Skicka e-post till 123 | aufgaben_settings_e_mails_empty = Det finns inga e-postadresser lämnade till någon av användare i användarförvaltning 124 | aufgaben_settings_save = Spara inställningarna 125 | absender_Email = Avsändare 126 | absender_Email_placeholder = Vänligen ange din e-postadress 127 | betreff_Email_placeholder = Vänligen ange ett ämne 128 | betreff_Email = Ämne 129 | send-to-all-checkbox = Skicka e-postmeddelande till alla 130 | zeit_ansicht = E-post leveransintervall 131 | 132 | // 133 | // Export / Import 134 | // 135 | aufgaben_exim_export = Export 136 | aufgaben_exim_dateityp = Filtyp 137 | aufgaben_exim_dateityp_csv = Exportera uppgifter som .csv 138 | aufgaben_exim_dateityp_json = Exportera uppgifter som .json 139 | aufgaben_exim_export_save = Exportera uppgifter 140 | 141 | 142 | 143 | // 144 | // Kanban Ansicht 145 | // 146 | aufgaben_kanban = Kanban 147 | aufgaben_kanban_aufgabe_hinzufuegen = Tillfoga uppgift 148 | aufgaben_kanban_title = Titel 149 | aufgaben_kanban_error_title = Var god ange en titel 150 | aufgaben_kanban_description = Beskrivning 151 | aufgaben_kanban_category = Kategori 152 | aufgaben_kanban_responsible = Ansvarig 153 | aufgaben_kanban_status = Status 154 | aufgaben_kanban_abort = Avbryta 155 | aufgaben_kanban_save = Spara 156 | aufgaben_kanban_edit = Redigera uppgift 157 | aufgaben_kanban_delete = Radera uppgift 158 | aufgaben_kanban_delete_confirm = Vill du verkligen radera uppgiften? 159 | -------------------------------------------------------------------------------- /pages/settings.php: -------------------------------------------------------------------------------- 1 | '; 6 | 7 | $func = rex_request('func', 'string'); 8 | if ($func == 'update') { 9 | $this->setConfig(rex_post('config', [ 10 | ['ansicht', 'string'], 11 | ['mails', 'array[string]'], 12 | ['time', 'integer'], 13 | ['absender', 'string'], 14 | ['betreff', 'string'], 15 | ['send-to-all', 'string'] 16 | ])); 17 | 18 | header('Location: '.rex_getUrl(rex_url::currentBackendPage())); 19 | exit; 20 | } 21 | 22 | $content .= ' 23 |
24 |
25 |
26 | '; 27 | 28 | 29 | //DELAY TIME 30 | $del_Time = new rex_select(); 31 | $del_Time->setId('delay_Time'); 32 | $del_Time->setName('config[time]'); 33 | $del_Time->setSize(1); 34 | $del_Time->setAttribute('class', 'form-control'); 35 | $del_Time->setSelected($this->getConfig('time')); 36 | foreach ([ 5 => $this->i18n('5_minuten_verzoegerung'), 15 => $this->i18n('15_minuten_verzoegerung'), 30 => $this->i18n('30_minuten_verzoegerung'), 60 => $this->i18n('60_minuten_verzoegerung'), 120 => $this->i18n('120_minuten_verzoegerung'), 0 => $this->i18n('0_minuten_verzoegerung') ] as $type1 => $time) { 37 | $del_Time->addOption($time, $type1); 38 | } 39 | 40 | $n = []; 41 | $formElements = []; 42 | 43 | $n['label'] = ''; 44 | $n['field'] = '
'.$del_Time->get().'
'; 45 | $formElements[] = $n; 46 | 47 | //Empfänger setzen 48 | $n = []; 49 | $n['label'] = ''; 50 | $n['field'] = ''; 51 | $formElements[] = $n; 52 | 53 | 54 | 55 | //Betreff der Mail setzen 56 | $n = []; 57 | $n['label'] = ''; 58 | $n['field'] = ''; 59 | $formElements[] = $n; 60 | 61 | 62 | 63 | //ANSICHT SETZEN 64 | $sel_ansicht = new rex_select(); 65 | $sel_ansicht->setId('aufgaben-ansicht'); 66 | $sel_ansicht->setName('config[ansicht]'); 67 | 68 | $sel_ansicht->setSize(1); 69 | $sel_ansicht->setAttribute('class', 'form-control'); 70 | $sel_ansicht->setSelected($this->getConfig('ansicht')); 71 | foreach (['beide' => $this->i18n('aufgaben_settings_beide'), 'liste' => $this->i18n('aufgaben_settings_liste'), 'kanban' => $this->i18n('aufgaben_settings_kanban')] as $type => $name) { 72 | $sel_ansicht->addOption($name, $type); 73 | } 74 | 75 | $n = []; 76 | 77 | $n['label'] = ''; 78 | $n['field'] = '
'.$sel_ansicht->get().'
'; 79 | $formElements[] = $n; 80 | 81 | 82 | 83 | $tableSelect = new rex_select(); 84 | $tableSelect->setMultiple(); 85 | $tableSelect->setId('aufgabe-mails'); 86 | $tableSelect->setName('config[mails][]'); 87 | $tableSelect->setAttribute('class', 'form-control'); 88 | 89 | // Alle E-Mail Adressen holen 90 | $sql_mail = rex_sql::factory(); 91 | //$sql_admin->setDebug(); 92 | $sql_mail->setTable('rex_user'); 93 | $sql_mail->setWhere('email !="" AND status = 1'); 94 | $sql_mail->select(); 95 | if ($sql_mail->getRows()) { 96 | for($i=0; $i<$sql_mail->getRows(); $i++) { 97 | $tableSelect->addOption($sql_mail->getValue('email'), $sql_mail->getValue('email')); 98 | if (in_array($sql_mail->getValue('email'), $this->getConfig('mails'))) { 99 | $tableSelect->setSelected($sql_mail->getValue('email')); 100 | } 101 | $sql_mail->next(); 102 | } 103 | } 104 | 105 | $n = []; 106 | $n['label'] = ''; 107 | $n['field'] = $tableSelect->get(); 108 | 109 | $formElements[] = $n; 110 | 111 | //send-to-all or send-to-responsible 112 | $n['label'] = ''; 113 | $n['field'] = 'getConfig('send-to-all')) && $this->getConfig('send-to-all') == '1' ? ' checked="checked"' : '') . ' value="1" />'; 114 | $formElements[] = $n; 115 | 116 | 117 | $fragment = new rex_fragment(); 118 | $fragment->setVar('elements', $formElements, false); 119 | $content .= $fragment->parse('core/form/form.php'); 120 | 121 | $content .= ' 122 |
123 |
'; 124 | 125 | 126 | 127 | $formElements = []; 128 | 129 | $n = []; 130 | $n['field'] = '
'; 131 | $formElements[] = $n; 132 | 133 | $fragment = new rex_fragment(); 134 | $fragment->setVar('elements', $formElements, false); 135 | $content .= $fragment->parse('core/form/submit.php'); 136 | 137 | $content .= ' 138 |
139 |
140 |
141 | '; 142 | 143 | 144 | $fragment = new rex_fragment(); 145 | $fragment->setVar('id', 'aufgaben'); 146 | $fragment->setVar('class', 'edit'); 147 | $fragment->setVar('title', $this->i18n('aufgaben_settings_title')); 148 | $fragment->setVar('body', $content, false); 149 | echo $fragment->parse('core/page/section.php'); 150 | 151 | 152 | -------------------------------------------------------------------------------- /lang/de_de.lang: -------------------------------------------------------------------------------- 1 | // 2 | // General 3 | // 4 | aufgaben_title = Aufgaben 5 | aufgaben_info = Info 6 | aufgaben_help = Hilfe 7 | aufgaben_licence = Lizenz 8 | aufgaben_changelog = Changelog 9 | 10 | aufgaben_description = Beschreibung 11 | 12 | aufgaben_task = Aufgabe 13 | aufgaben_task_hide_title = Erledigte Aufgaben verbergen 14 | aufgaben_task_hide = Aufgaben verbergen 15 | aufgaben_task_show_title = Alle Aufgaben anzeigen 16 | aufgaben_task_show = alle Aufgaben anzeigen 17 | aufgaben_last_update = Letze Aktualisierung 18 | 19 | aufgaben_last_update 20 | aufgaben_due = Fällig 21 | aufgaben_due_date = Fälligkeitsdatum 22 | 23 | aufgaben_category = Kategorie 24 | aufgaben_categories = Kategorien 25 | 26 | aufgaben_responsible = Zuständig 27 | 28 | aufgaben_prio = Prio 29 | 30 | aufgaben_status = Status 31 | 32 | aufgaben_edit = Aufgabe editieren 33 | aufgaben_add = Aufgabe hinzufügen 34 | aufgaben_title_empty = Bitte geben Sie einen Titel an. 35 | aufgaben_category_empty = Bitte wählen Sie eine Kategorie aus. 36 | aufgaben_responsible_empty = Bitte geben Sie an wer für diese Aufgabe zuständig ist. 37 | 38 | aufgaben_please_choose = Bitte wählen 39 | aufgaben_last_change = Letzte Änderung am 40 | aufgaben_create_on = Erstellt am 41 | 42 | aufgaben_by = von 43 | 44 | aufgaben_mail_could_not_sent = E-Mail konnte nicht gesendet werden. 45 | aufgaben_mail_sent_to = E-Mail gesendet an: 46 | 47 | aufgaben_markitupinfo = Angelegt durch das Addon Aufgaben 48 | 49 | aufgaben_mail_change = Aufgabe geändert: 50 | aufgaben_mail_change_eigentuemer = Aufgabe geändert: 51 | aufgaben_mail_new = Neue Aufgabe: 52 | aufgaben_mail_change_status = Aufgabe - Status geändert: 53 | aufgaben_mail_change_prio = Aufgabe - Priorität geändert: 54 | aufgaben_mail_change_responsible = Aufgabe - Zuständigkeit geändert: 55 | aufgaben_mail_change_cat = Aufgabe - Kategorie geändert: 56 | 57 | aufgaben_versendet = Mail 58 | 59 | aufgaben_no_task = Keine Aufgaben vorhanden.

Mögliche Ursachen:

- es ist keine Aufgabe angelegt
- keine der vorhandenen Aufgaben erfüllt auf die eingestellten Filterkriterien
- die Ausgabe der erledigten Aufgaben ist abgeschaltet 60 | 61 | aufgaben_prev_month = Vorheriger Monat 62 | aufgaben_next_month = Nächster Monat 63 | aufgaben_januar = Januar 64 | aufgaben_februar = Februar 65 | aufgaben_maerz = März 66 | aufgaben_april = April 67 | aufgaben_mai = Mai 68 | aufgaben_juni = Juni 69 | aufgaben_juli = Juli 70 | aufgaben_august = August 71 | aufgaben_september = September 72 | aufgaben_oktober = Oktober 73 | aufgaben_november = November 74 | aufgaben_dezember = Dezember 75 | aufgaben_sonntag = Sonntag 76 | aufgaben_montag = Montag 77 | aufgaben_dienstag = Dienstag 78 | aufgaben_mittwoch = Mittwoch 79 | aufgaben_donnerstag = Donnerstag 80 | aufgaben_freitag = Freitag 81 | aufgaben_samstag = Samstag 82 | aufgaben_so = So 83 | aufgaben_mo = Mo 84 | aufgaben_di = Di 85 | aufgaben_mi = Mi 86 | aufgaben_do = Do 87 | aufgaben_fr = Fr 88 | aufgaben_sa = Sa 89 | 90 | 91 | 92 | 93 | // 94 | // Kategorien 95 | // 96 | aufgaben_categories_title = Kategorien 97 | aufgaben_categories_category = Kategorie 98 | aufgaben_categories_color = Farbe 99 | aufgaben_categories_no_category = Keine Kategorie vorhanden.
Bitte legen Sie eine Kategorie an bzw. informieren Ihren Administrator. 100 | aufgaben_categories_category_add = Kategorie hinzufügen 101 | aufgaben_categories_category_edit = Kategorie editieren 102 | aufgaben_categories_category_empty = Bitte geben Sie eine Kategorie an. 103 | aufgaben_categories_category_delete = Kategorie löschen 104 | aufgaben_categories_category_deleted = Die Kategorie wurde gelöscht. 105 | aufgaben_categories_category_in_use = Dieser Kategorie sind noch Aufgaben zugeordnet.
Die Kategorie wurde nicht gelöscht! 106 | 107 | 108 | // 109 | // Einstellungen 110 | // 111 | 5_minuten_verzoegerung = 5 Minuten 112 | 15_minuten_verzoegerung = 15 Minuten 113 | 30_minuten_verzoegerung = 30 Minuten 114 | 60_minuten_verzoegerung = 1 Stunde 115 | 120_minuten_verzoegerung = 2 Stunden 116 | 0_minuten_verzoegerung = Keine Verzögerung 117 | aufgaben_settings_title = Einstellungen 118 | aufgaben_settings_ansicht = Ansicht 119 | aufgaben_settings_beide = Beide Ansichten 120 | aufgaben_settings_liste = Liste 121 | aufgaben_settings_kanban = Kanban 122 | aufgaben_settings_e_mails_an = E-Mails an 123 | aufgaben_settings_e_mails_empty = Bei keinem User ist in der Benutzerverwaltung eine E-Mail Adresse eingetragen. 124 | aufgaben_settings_save = Einstellungen speichern 125 | absender_Email = Absender 126 | absender_Email_placeholder = Bitte geben Sie ihre E-Mail Adresse ein 127 | betreff_Email_placeholder = Bitte geben Sie den Betreff für die E-Mail ein 128 | betreff_Email = Betreff 129 | send-to-all-checkbox = E-Mail an alle 130 | zeit_ansicht = E-Mail Versand Intervall 131 | 132 | // 133 | // Export / Import 134 | // 135 | aufgaben_exim_export = Export 136 | aufgaben_exim_dateityp = Dateityp 137 | aufgaben_exim_dateityp_csv = Aufgaben als .csv exportieren 138 | aufgaben_exim_dateityp_json = Aufgaben als .json exportieren 139 | aufgaben_exim_export_save = Aufgaben exportieren 140 | 141 | 142 | 143 | // 144 | // Kanban Ansicht 145 | // 146 | aufgaben_kanban = Kanban 147 | aufgaben_kanban_aufgabe_hinzufuegen = Aufgabe hinzügen 148 | aufgaben_kanban_title = Titel 149 | aufgaben_kanban_error_title = Bitte geben Sie einen Titel an 150 | aufgaben_kanban_description = Beschreibung 151 | aufgaben_kanban_category = Kategorie 152 | aufgaben_kanban_responsible = Zuständig 153 | aufgaben_kanban_status = Status 154 | aufgaben_kanban_abort = Abbrechen 155 | aufgaben_kanban_save = Speichern 156 | aufgaben_kanban_edit = Aufgabe bearbeiten 157 | aufgaben_kanban_delete = Aufgabe löschen 158 | aufgaben_kanban_delete_confirm = Soll folgene Aufgabe wirklich gelöscht werden? 159 | -------------------------------------------------------------------------------- /lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | // 2 | // General 3 | // 4 | aufgaben_title = Tarefas 5 | aufgaben_info = Informações 6 | aufgaben_help = Ajuda 7 | aufgaben_licence = Licença 8 | aufgaben_changelog = Mudar log 9 | 10 | aufgaben_description = Descrição 11 | 12 | aufgaben_task = Tarefa 13 | aufgaben_task_hide = Esconder tarefa 14 | aufgaben_last_update = Última atualização 15 | 16 | aufgaben_task = Tarefa 17 | aufgaben_task_hide_title = Ocultar tarefas concluídas 18 | aufgaben_task_hide = Ocultar tarefas concluídas 19 | aufgaben_task_show_title = Mostrar todas as tarefas 20 | aufgaben_task_show = Mostrar todas as tarefas 21 | aufgaben_last_update = Última atualização 22 | 23 | aufgaben_last_update 24 | aufgaben_due = Devido 25 | aufgaben_due_date = Vencimento 26 | 27 | aufgaben_category = Categoria 28 | aufgaben_categories = Categorias 29 | 30 | aufgaben_responsible = Responsável 31 | 32 | aufgaben_prio = Prio 33 | 34 | aufgaben_status = Status 35 | 36 | aufgaben_edit = Editar tarefas 37 | aufgaben_add = Adicionar tarefas 38 | aufgaben_title_empty = Por favor, insira um título. 39 | aufgaben_category_empty = Por favor, escolha uma categoria. 40 | aufgaben_responsible_empty = Por favor, especifique quem é o responsável pela tarefa. 41 | 42 | aufgaben_please_choose = Por favor, escolha 43 | aufgaben_last_change = última atualização 44 | aufgaben_create_on = Criado 45 | 46 | aufgaben_by = por 47 | 48 | aufgaben_mail_could_not_sent = O e-mail não pôde ser enviado. 49 | aufgaben_mail_sent_to = E-mail enviado para: 50 | 51 | aufgaben_markitupinfo = Criado pelo AddOn tarefas: 52 | 53 | aufgaben_mail_change = Tarefa atualizada: 54 | aufgaben_mail_new = Nova tarefa: 55 | aufgaben_mail_change_status = Tarefa - status atualizado: 56 | aufgaben_mail_change_prio = Tarefa - prioridade atualizada: 57 | aufgaben_mail_change_responsible = Tarefa - responsabilidade atualizada: 58 | aufgaben_mail_change_cat = Tarefa - categoria atualizada: 59 | 60 | aufgaben_versendet = Mail 61 | 62 | aufgaben_no_task = Nenhuma tarefa encontrada.

Possíveis motivos:

- nenhuma tarefa foi criada
- o filtro atualizado exclui todas as tarefas existentes
-tarefas completadas estão programadas para não serem exibidas 63 | 64 | aufgaben_prev_month = Mês anterior 65 | aufgaben_next_month = Próximo mês 66 | aufgaben_januar = Janeiro 67 | aufgaben_februar = Fevereiro 68 | aufgaben_maerz = Março 69 | aufgaben_april = Abril 70 | aufgaben_mai = Maio 71 | aufgaben_juni = Junho 72 | aufgaben_juli = Julho 73 | aufgaben_august = Agosto 74 | aufgaben_september = Setembro 75 | aufgaben_oktober = Outubro 76 | aufgaben_november = Novembro 77 | aufgaben_dezember = Dezembro 78 | aufgaben_sonntag = Domingo 79 | aufgaben_montag = Segunda-feira 80 | aufgaben_dienstag = Terça-feira 81 | aufgaben_mittwoch = Quarta-feira 82 | aufgaben_donnerstag = Quinta-feira 83 | aufgaben_freitag = Sexta-feira 84 | aufgaben_samstag = Sábado 85 | aufgaben_so = Do 86 | aufgaben_mo = Se 87 | aufgaben_di = Te 88 | aufgaben_mi = Qa 89 | aufgaben_do = Qi 90 | aufgaben_fr = Sx 91 | aufgaben_sa = Sa 92 | 93 | 94 | 95 | 96 | // 97 | // Kategorien 98 | // 99 | 100 | aufgaben_categories_title = Categorias 101 | aufgaben_categories_category = Categoria 102 | aufgaben_categories_color = Cor 103 | aufgaben_categories_no_category = Nenhuma categoria encontrada.
Por favor, crie uma categoria ou entre em contato com o seu administrador 104 | aufgaben_categories_category_add = Adicionar categoria 105 | aufgaben_categories_category_edit = Editar categoria 106 | aufgaben_categories_category_empty = Por favor, atribua uma categoria 107 | aufgaben_categories_category_delete = Deletar categoria 108 | aufgaben_categories_category_deleted = Categoria foi deletada 109 | aufgaben_categories_category_in_use = Há tarefas atribuídas a esta categoria.
A categoria não foi deletada! 110 | 111 | 112 | // 113 | // Einstellungen 114 | // 115 | 5_minuten_verzoegerung = 5 Minutos 116 | 15_minuten_verzoegerung = 15 Minutos 117 | 30_minuten_verzoegerung = 30 Minutos 118 | 60_minuten_verzoegerung = 1 hora 119 | 120_minuten_verzoegerung = 2 horas 120 | 0_minuten_verzoegerung = Sem atraso 121 | aufgaben_settings_title = Configurações 122 | aufgaben_settings_ansicht = Vista 123 | aufgaben_settings_beide = Ambas as vistas 124 | aufgaben_settings_liste = Lista 125 | aufgaben_settings_kanban = Kanban 126 | aufgaben_settings_e_mails_an = Enviar e-emails para 127 | aufgaben_settings_e_mails_empty = Nenhum dos usuários da gestão de usuários inseriu um e-mail. 128 | aufgaben_settings_save = Salvar configurações 129 | absender_Email = Remetente 130 | absender_Email_placeholder = Digite seu endereço de e-mail 131 | betreff_Email_placeholder = Digite o assunto para o e-mail 132 | betreff_Email = Assunto do E-Mail 133 | send-to-all-checkbox = todos notificam 134 | zeit_ansicht = intervalo de tempo automático (E-Mail) 135 | 136 | // 137 | // Export / Import 138 | // 139 | aufgaben_exim_export = Exportar 140 | aufgaben_exim_dateityp = Tipo do arquivo 141 | aufgaben_exim_dateityp_csv = Exportar tarefas como .csv 142 | aufgaben_exim_dateityp_json = Exportar tarefas como .json 143 | aufgaben_exim_export_save = Exportar tarefas 144 | 145 | 146 | 147 | // 148 | // Kanban Ansicht 149 | // 150 | aufgaben_kanban = Kanban 151 | aufgaben_kanban_aufgabe_hinzufuegen = Adicionar tarefas 152 | aufgaben_kanban_title = Título 153 | aufgaben_kanban_error_title = Por favor, insira um título 154 | aufgaben_kanban_description = Descrição 155 | aufgaben_kanban_category = Categoria 156 | aufgaben_kanban_responsible = Responsável 157 | aufgaben_kanban_status = Status 158 | aufgaben_kanban_abort = Cancelar 159 | aufgaben_kanban_save = Salvar 160 | aufgaben_kanban_edit = Editar tarefa 161 | aufgaben_kanban_delete = Deletar tarefa 162 | aufgaben_kanban_delete_confirm = Você gostaria de deletar a tarefa a seguir? 163 | -------------------------------------------------------------------------------- /lang/es_es.lang: -------------------------------------------------------------------------------- 1 | // 2 | // General 3 | // 4 | aufgaben_title = Tareas 5 | aufgaben_info = Info 6 | aufgaben_help = Ayuda 7 | aufgaben_licence = Licencia 8 | aufgaben_changelog = Cambios 9 | 10 | aufgaben_description = Descripción 11 | 12 | aufgaben_task = Tarea 13 | aufgaben_task_hide = Ocultar tareas 14 | aufgaben_last_update = Última actualización 15 | 16 | aufgaben_task = Tarea 17 | aufgaben_task_hide_title = Ocultar tareas completadas 18 | aufgaben_task_hide = Ocultar tareas completadas 19 | aufgaben_task_show_title = Mostrar todas las tareas 20 | aufgaben_task_show = Mostrar todas las tareas 21 | aufgaben_last_update = Última actualización 22 | 23 | aufgaben_last_update 24 | aufgaben_due = Vencido 25 | aufgaben_due_date = Fecha de vencimiento 26 | 27 | aufgaben_category = Categoría 28 | aufgaben_categories = Categorías 29 | 30 | aufgaben_responsible = Responsable 31 | 32 | aufgaben_prio = Prio 33 | 34 | aufgaben_status = Estado 35 | 36 | aufgaben_edit = Editar tarea 37 | aufgaben_add = Añadir una tarea 38 | aufgaben_title_empty = Por favor ingrese un título. 39 | aufgaben_category_empty = Por favor seleccione una categoría 40 | aufgaben_responsible_empty = Por favor, indique quién es el responsable de esta tarea. 41 | 42 | aufgaben_please_choose = Por favor elija 43 | aufgaben_last_change = Último cambio en 44 | aufgaben_create_on = Creado en 45 | 46 | aufgaben_by = de 47 | 48 | aufgaben_mail_could_not_sent = El e-mail no pudo ser enviado. 49 | aufgaben_mail_sent_to = E-mail enviado a: 50 | 51 | aufgaben_markitupinfo = Creado por las tareas de complemento 52 | 53 | aufgaben_mail_change = Tarea modificada: 54 | aufgaben_mail_change_eigentuemer = Tarea modificada: 55 | aufgaben_mail_new = Nueva tarea: 56 | aufgaben_mail_change_status = Tarea - Estado cambiado: 57 | aufgaben_mail_change_prio = Tarea: Cambio de prioridad: 58 | aufgaben_mail_change_responsible = Tarea: Responsabilidad modificada: 59 | aufgaben_mail_change_cat = Tarea - Categoría modificada: 60 | 61 | aufgaben_versendet = Correo 62 | 63 | aufgaben_no_task = No hay tareas.

Posibles causas:

- no se crea ninguna tarea
- ninguna de las tareas existentes se cumple con los criterios de filtro establecidos
- la salida de las tareas completadas se desactiva 64 | 65 | aufgaben_prev_month = Mes anterior 66 | aufgaben_next_month = El próximo mes 67 | aufgaben_januar = Enero 68 | aufgaben_februar = Febrero 69 | aufgaben_maerz = Marzo 70 | aufgaben_april = Abril 71 | aufgaben_mai = Mayo 72 | aufgaben_juni = Junio 73 | aufgaben_juli = Julio 74 | aufgaben_august = Agosto 75 | aufgaben_september = Septiembre 76 | aufgaben_oktober = Octubre 77 | aufgaben_november = Noviembre 78 | aufgaben_dezember = Diciembre 79 | aufgaben_sonntag = Domingo 80 | aufgaben_montag = Lunes 81 | aufgaben_dienstag = Martes 82 | aufgaben_mittwoch = Miércoles 83 | aufgaben_donnerstag = Jueves 84 | aufgaben_freitag = Viernes 85 | aufgaben_samstag = Sábado 86 | aufgaben_so = Dom 87 | aufgaben_mo = Lun 88 | aufgaben_di = Mar 89 | aufgaben_mi = Mié 90 | aufgaben_do = Jue 91 | aufgaben_fr = Vie 92 | aufgaben_sa = Sáb 93 | 94 | 95 | 96 | 97 | // 98 | // Kategorien 99 | // 100 | aufgaben_categories_title = Categorías 101 | aufgaben_categories_category = Categoría 102 | aufgaben_categories_color = Color 103 | aufgaben_categories_no_category = No hay categoría disponible.
Por favor crea una categoría o informa a tu administrador. 104 | aufgaben_categories_category_add = Añadir una categoría 105 | aufgaben_categories_category_edit = Editar categoría 106 | aufgaben_categories_category_empty = Por favor ingrese una categoría. 107 | aufgaben_categories_category_delete = Eliminar categoría 108 | aufgaben_categories_category_deleted = La categoría ha sido eliminada. 109 | aufgaben_categories_category_in_use = Las tareas aún se asignan a esta categoría.
¡La categoría no se ha eliminado! 110 | 111 | 112 | // 113 | // Einstellungen 114 | // 115 | 5_minuten_verzoegerung = 5 minutos 116 | 15_minuten_verzoegerung = 15 minutos 117 | 30_minuten_verzoegerung = 30 minutos 118 | 60_minuten_verzoegerung = 1 hora 119 | 120_minuten_verzoegerung = 2 horas 120 | 0_minuten_verzoegerung = Sin demora 121 | aufgaben_settings_title = Ajustes 122 | aufgaben_settings_ansicht = Ver 123 | aufgaben_settings_beide = Ambas vistas 124 | aufgaben_settings_liste = Lista 125 | aufgaben_settings_kanban = Kanban 126 | aufgaben_settings_e_mails_an = E-Mails a 127 | aufgaben_settings_e_mails_empty = Para ningún usuario, se ingresa una dirección de correo electrónico en la administración del usuario. 128 | aufgaben_settings_save = Guardar configuraciones 129 | absender_Email = Remitente 130 | absender_Email_placeholder = Por favor ingrese su dirección de correo electrónico 131 | betreff_Email_placeholder = Por favor ingrese el asunto para el correo electrónico 132 | betreff_Email = Respecto 133 | send-to-all-checkbox = E-mail a todos 134 | zeit_ansicht = Intervalo de entrega de correo electrónico 135 | 136 | // 137 | // Export / Import 138 | // 139 | aufgaben_exim_export = Exportación 140 | aufgaben_exim_dateityp = Tipo de archivo 141 | aufgaben_exim_dateityp_csv = Exportar tareas como .csv 142 | aufgaben_exim_dateityp_json = Exportar tareas como .json 143 | aufgaben_exim_export_save = Tareas de exportación 144 | 145 | 146 | 147 | // 148 | // Kanban Ansicht 149 | // 150 | aufgaben_kanban = Kanban 151 | aufgaben_kanban_aufgabe_hinzufuegen = Agregar tarea 152 | aufgaben_kanban_title = Título 153 | aufgaben_kanban_error_title = Por favor ingrese un título 154 | aufgaben_kanban_description = Descripción 155 | aufgaben_kanban_category = Categoría 156 | aufgaben_kanban_responsible = Responsable 157 | aufgaben_kanban_status = Estado 158 | aufgaben_kanban_abort = Cancelar 159 | aufgaben_kanban_save = Guardar 160 | aufgaben_kanban_edit = Editar tarea 161 | aufgaben_kanban_delete = Eliminar tarea 162 | aufgaben_kanban_delete_confirm = ¿Debería eliminarse realmente la siguiente tarea? 163 | -------------------------------------------------------------------------------- /scss/_pickaday.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Pikaday 3 | * Copyright © 2014 David Bushell | BSD & MIT license | http://dbushell.com/ 4 | */ 5 | 6 | // Variables 7 | // Declare any of these variables before importing this SCSS file to easily override defaults 8 | // Variables are namespaced with the pd (pikaday) prefix 9 | 10 | // Colours 11 | $pd-text-color: #333 !default; 12 | $pd-title-color: #333 !default; 13 | $pd-title-bg: #fff !default; 14 | $pd-picker-bg: #fff !default; 15 | $pd-picker-border: #ccc !default; 16 | $pd-picker-border-bottom: #bbb !default; 17 | $pd-picker-shadow: rgba(0,0,0,.5) !default; 18 | $pd-th-color: #999 !default; 19 | $pd-day-color: #666 !default; 20 | $pd-day-bg: #f5f5f5 !default; 21 | $pd-day-hover-color: #fff !default; 22 | $pd-day-hover-bg: #ff8000 !default; 23 | $pd-day-today-color: #33aaff !default; 24 | $pd-day-selected-color: #fff !default; 25 | $pd-day-selected-bg: #33aaff !default; 26 | $pd-day-selected-shadow: #178fe5 !default; 27 | $pd-day-disabled-color: #999 !default; 28 | $pd-week-color: #999 !default; 29 | 30 | // Font 31 | $pd-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !default; 32 | 33 | 34 | .pika-single { 35 | z-index: 9999; 36 | display: block; 37 | position: relative; 38 | color: $pd-text-color; 39 | background: $pd-picker-bg; 40 | border: 1px solid $pd-picker-border; 41 | border-bottom-color: $pd-picker-border-bottom; 42 | font-family: $pd-font-family; 43 | 44 | &.is-hidden { 45 | display: none; 46 | } 47 | 48 | &.is-bound { 49 | position: absolute; 50 | box-shadow: 0 5px 15px -5px $pd-picker-shadow; 51 | } 52 | } 53 | 54 | // clear child float (pika-lendar), using the famous micro clearfix hack 55 | // http://nicolasgallagher.com/micro-clearfix-hack/ 56 | .pika-single { 57 | *zoom: 1; 58 | 59 | &:before, 60 | &:after { 61 | content: " "; 62 | display: table; 63 | } 64 | 65 | &:after { clear: both } 66 | } 67 | 68 | .pika-lendar { 69 | float: left; 70 | width: 240px; 71 | margin: 8px; 72 | } 73 | 74 | .pika-title { 75 | position: relative; 76 | text-align: center; 77 | 78 | select { 79 | cursor: pointer; 80 | position: absolute; 81 | z-index: 9998; 82 | margin: 0; 83 | left: 0; 84 | top: 5px; 85 | filter: alpha(opacity=0); 86 | opacity: 0; 87 | } 88 | } 89 | 90 | .pika-label { 91 | display: inline-block; 92 | *display: inline; 93 | position: relative; 94 | z-index: 9999; 95 | overflow: hidden; 96 | margin: 0; 97 | padding: 5px 3px; 98 | font-size: 14px; 99 | line-height: 20px; 100 | font-weight: bold; 101 | color: $pd-title-color; 102 | background-color: $pd-title-bg; 103 | } 104 | 105 | .pika-prev, 106 | .pika-next { 107 | display: block; 108 | cursor: pointer; 109 | position: relative; 110 | outline: none; 111 | border: 0; 112 | padding: 0; 113 | width: 20px; 114 | height: 30px; 115 | text-indent: 20px; // hide text using text-indent trick, using width value (it's enough) 116 | white-space: nowrap; 117 | overflow: hidden; 118 | background-color: transparent; 119 | background-position: center center; 120 | background-repeat: no-repeat; 121 | background-size: 75% 75%; 122 | opacity: .5; 123 | *position: absolute; 124 | *top: 0; 125 | 126 | &:hover { 127 | opacity: 1; 128 | } 129 | 130 | &.is-disabled { 131 | cursor: default; 132 | opacity: .2; 133 | } 134 | } 135 | 136 | .pika-prev, 137 | .is-rtl .pika-next { 138 | float: left; 139 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg=='); 140 | *left: 0; 141 | } 142 | 143 | .pika-next, 144 | .is-rtl .pika-prev { 145 | float: right; 146 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII='); 147 | *right: 0; 148 | } 149 | 150 | .pika-select { 151 | display: inline-block; 152 | *display: inline; 153 | } 154 | 155 | .pika-table { 156 | width: 100%; 157 | border-collapse: collapse; 158 | border-spacing: 0; 159 | border: 0; 160 | 161 | th, 162 | td { 163 | width: 14.285714285714286%; 164 | padding: 0; 165 | } 166 | 167 | th { 168 | color: $pd-th-color; 169 | font-size: 12px; 170 | line-height: 25px; 171 | font-weight: bold; 172 | text-align: center; 173 | } 174 | 175 | abbr { 176 | border-bottom: none; 177 | cursor: help; 178 | } 179 | } 180 | 181 | .pika-button { 182 | cursor: pointer; 183 | display: block; 184 | -moz-box-sizing: border-box; 185 | box-sizing: border-box; 186 | outline: none; 187 | border: 0; 188 | margin: 0; 189 | width: 100%; 190 | padding: 5px; 191 | color: $pd-day-color; 192 | font-size: 12px; 193 | line-height: 15px; 194 | text-align: right; 195 | background: $pd-day-bg; 196 | 197 | .is-today & { 198 | color: $pd-day-today-color; 199 | font-weight: bold; 200 | } 201 | 202 | .is-selected & { 203 | color: $pd-day-selected-color; 204 | font-weight: bold; 205 | background: $pd-day-selected-bg; 206 | box-shadow: inset 0 1px 3px $pd-day-selected-shadow; 207 | border-radius: 3px; 208 | } 209 | 210 | .is-disabled &, 211 | .is-outside-current-month & { 212 | pointer-events: none; 213 | cursor: default; 214 | color: $pd-day-disabled-color; 215 | opacity: .3; 216 | } 217 | 218 | &:hover { 219 | color: $pd-day-hover-color; 220 | background: $pd-day-hover-bg; 221 | box-shadow: none; 222 | border-radius: 3px; 223 | } 224 | } 225 | 226 | .pika-week { 227 | font-size: 11px; 228 | color: $pd-week-color; 229 | } 230 | 231 | .is-inrange .pika-button { 232 | background: #D5E9F7; 233 | } 234 | 235 | .is-startrange .pika-button { 236 | color: #fff; 237 | background: #6CB31D; 238 | box-shadow: none; 239 | border-radius: 3px; 240 | } 241 | 242 | .is-endrange .pika-button { 243 | color: #fff; 244 | background: #33aaff; 245 | box-shadow: none; 246 | border-radius: 3px; 247 | } 248 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ##### ToDo siehe [ISSUES](https://github.com/FriendsOfREDAXO/aufgaben/issues) ##### 2 | 3 | --- 4 | 5 | ### Changelog ### 6 | 7 | ### 04.04.2017 Version 4.1.2 ### 8 | 9 | - Kanban Ansicht inital ausgeschaltet 10 | - "Status" Werte werden jetzt bei der Installation wieder in die DB geschrieben 11 | 12 | 13 | ### 17.03.2019 Version 4.1.1 ### 14 | 15 | ... 16 | 17 | ### 07.09.2017 Version 4.1.0 ### 18 | 19 | - E-Mail Versand entsprechend eingestelltem Intervall 20 | - E-Mails werden je Nutzer gesammelt 21 | - Der E-Mail-Betreff kann gesetzt werden 22 | - Absemder-E-Mail-Adresse kann festgelegt werden 23 | - E-Mails können an alle Empfänger oder nur an die Zuständigen geschickt werden 24 | Danke an @chrison94! 25 | 26 | ### 25.02.2017 Version 4.0.2 ### 27 | 28 | -Update en_gb.lang - Danke an @ynamite! 29 | 30 | ### 18.01.2017 Version 4.0.1 ### 31 | 32 | - Beta entfernt 33 | - Fehlerkorrektur 34 | - Projektlead hinzugefügt 35 | 36 | ___ 37 | 38 | ### 10.08.2016 Version 4.0 Beta 1 ### 39 | 40 | _ACHTUNG: Es ist kein Update von früheren Versionen möglich_ 41 | 42 | 43 | - Tabellen umbenannt 44 | - Kanban-Darstellung angepasst 45 | - Listen-Darstellung angepasst 46 | - E-Mail-Ausgabe angepasst 47 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/79 48 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/78 49 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/77 50 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/71 51 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/67 52 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/62 53 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/48 54 | - Fixed: https://github.com/FriendsOfREDAXO/aufgaben/issues/39 55 | 56 | 57 | ### 28.06.2016 Version 3.2.2 ### 58 | 59 | - MarkItUp Unterstützung eingebaut 60 | - Bei Eigentümer / Kategorieänderungen in der Listenanbsicht werden jetzt auch Mails verschickt 61 | 62 | ### 28.06.2016 Version 3.2.1 ### 63 | 64 | - Kategorien und Eigentümer sind jetzt in der Listenansicht änderbar 65 | 66 | ### 22.06.2016 Version 3.2.0 ### 67 | 68 | - Ansichten waren nach der Installation nicht verfügbar 69 | 70 | ### 22.06.2016 Version 3.1.9 ### 71 | 72 | - Lizenz geändert 73 | - E-Mail Adressen in den Einstellungen auswählbar 74 | - Mailinhalt erweitert 75 | 76 | 77 | ### 22.06.2016 Version 3.1.8 ### 78 | 79 | - Export Funktionalität gefixt :-) 80 | 81 | ### 22.06.2016 Version 3.1.7 ### 82 | 83 | - Einstellungsseite hinzugefügt 84 | - Export Funktionalität geschossen :-( 85 | - E-Mail Funktion ausgelagert (Muss noch optimiert werden :-) 86 | 87 | ### 21.06.2016 Version 3.1.6 ### 88 | 89 | - Bei nur einer Kategorie bzw nur einem Benutzer werden die Select Felder nicht mehr angezeigt 90 | 91 | ### 21.06.2016 Version 3.1.5 ### 92 | 93 | - aufgaben_functions.php angelegt 94 | 95 | ### 20.06.2016 Version 3.1.4 ### 96 | 97 | - SCSS Datei für den Export entfernt 98 | 99 | ### 10.06.2016 Version 3.1.3 ### 100 | 101 | - Schreibfehler beseitigt 102 | 103 | ### 06.06.2016 Version 3.1.2 ### 104 | 105 | - Löschen von benutzten Kategorien wird verhindert 106 | 107 | ### 05.06.2016 Version 3.1.1 ### 108 | 109 | - Kanban erweitert um Edit Funktion 110 | - Code aufgeräumt 111 | - Bootstrap Modal issue gelöst 112 | 113 | 114 | ### 03.06.2016 Version 3.1 ### 115 | 116 | - Kanban Ansicht hinzugefügt 117 | 118 | 119 | ### 03.06.2016 Version 3.0 ### 120 | 121 | - Readme aktualisiert 122 | 123 | 124 | ### Changelog ### 125 | 126 | ### 02.06.2016 Version 3.0 ### 127 | 128 | - Versionsupdate - Umzug zu FOR 129 | - Lizenz angepasst -> MIT 130 | 131 | 132 | ### 30.05.2016 Version 2.1.7 ### 133 | 134 | - Export hinzugefügt 135 | 136 | 137 | ### 09.05.2016 Version 2.1.6 ### 138 | 139 | - Neue Kategoriefarben vergeben 140 | 141 | 142 | ### 25.04.2016 Version 2.1.5 ### 143 | 144 | - simplecolorpicker eingebaut 145 | 146 | 147 | ### 25.04.2016 Version 2.1 ### 148 | 149 | - Fehler beseitigt 150 | - Überall "name" durch "login" getauscht ("name" ist kein Pflichtfeld in der rex_user Tabelle) 151 | - Paginierung angepasst 152 | 153 | ### 25.04.2016 Version 2.0 ### 154 | 155 | - Benachrichtigungsmails erweitert 156 | - Datepicker ausgetauscht :-) 157 | 158 | 159 | ### 21.04.2016 Version 2.0 ### 160 | 161 | - Filter neu gebaut (Multiselect) 162 | - Nutzung von SCSS 163 | - Datepicker ausgetauscht 164 | 165 | ### 18.04.2016 Version 1.9.5 ### 166 | 167 | - E-Mail Benachrichtigung bei geänderten Aufgaben 168 | 169 | ### 18.04.2016 Version 1.9.4 ### 170 | 171 | - Fälligkeitsdatum hinzugefügt 172 | 173 | ### 16.04.2016 Version 1.9.3 ### 174 | 175 | - Title = Pflichtfeld 176 | - Vorbereitung für das Hinzufügen eines Fälligkeitsdatums 177 | 178 | ### 16.04.2016 Version 1.9.2 ### 179 | 180 | - Tabelle für die User Setting hinzugefügt 181 | - Fehler bei der Anzeige der "offenen" Aufgaben gefixt. 182 | 183 | ### 15.04.2016 Version 1.9.1 ### 184 | 185 | - Die Anzahl der Aufgaben in der Navi wird bei 0 Aufgaben ausgeblendet 186 | - Farben angepasst 187 | - Vorbereitungen für die "Beobachten" Funktion 188 | 189 | ### 15.04.2016 Version 1.9 ### 190 | 191 | - CSS Anpassung für die Tabellen 192 | - CSS Anpassungen einiger Select Felder 193 | - Nutzung von Pjax bei der Änderung von "Status" und "Priorität" 194 | - Anzeige der Anzahl der "eigenen" Aufgaben in der Navigation 195 | - Lizenz geändert (Beerware - Danke an Thomas) 196 | 197 | 198 | ### 22.03.2016 Version 1.8.7 ### 199 | 200 | - E-Mail an Zuständigen nach dem Anlegen einer neuen Aufgaben 201 | (Fallback bei leeren E-Mail Feld auf ErrorMail Adresse) 202 | 203 | ### 25.02.2016 Version 1.8.6 ### 204 | 205 | - Beim Update werden jetzt die neuen Felder richtig berüksichtigt (hoffentlich :-)) 206 | 207 | ### 24.02.2016 Version 1.8.5 ### 208 | 209 | - creatuser/creatdate und updateuser/updatedate hinzugefügt 210 | 211 | ### 17.02.2016 Version 1.8 ### 212 | 213 | - Anpassung der install.php und update.php (https://github.com/olien/aufgaben/issues/26) 214 | - install.sql gelöscht 215 | - Abhängigkeit phpmailer hinzugefügt 216 | - Bei einer neuen Aufgabe wird eine E-Mail an die unter "System" eingetragenen E-Mail Adresse gesendet 217 | 218 | 219 | ### 27.01.2016 Version 1.7.5 ### 220 | 221 | - Änderungen des UI. Danke an Thomas Kaegi (https://github.com/phoebusryan) für den PR 222 | - "Parsedown" hinzugefügt. Abgeguckt bei SEO 42 von RexDude https://github.com/RexDude :-) 223 | - Hilfe Seiten entwicklet 224 | 225 | 226 | ### 27.01.2016 Version 1.7.2 ### 227 | 228 | - Nicht zugewiesene Optionen werden im Filter angezeigt 229 | Danke an Thomas Kaegi (https://github.com/phoebusryan) für die Anpassung 230 | 231 | ### 14.01.2016 Version 1.7.1 ### 232 | 233 | - Filter Tabelle löschen in uninstall.php 234 | 235 | ### 14.01.2016 Version 1.7 ### 236 | 237 | - Fehler beim Priofilter behoben 238 | - erledigt Status (Auge) hinzugefügt 239 | 240 | ### 14.01.2016 Version 1.5.1 ### 241 | 242 | - Fehler gefixt 243 | - Filter alphabetisch sortiert 244 | - Neue Aufgabe > Aktueller User vorausgewählt 245 | 246 | -------------------------------------------------------------------------------- /assets/js/jquery.simplecolorpicker.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Very simple jQuery Color Picker 3 | * https://github.com/tkrotoff/jquery-simplecolorpicker 4 | * 5 | * Copyright (C) 2012-2013 Tanguy Krotoff 6 | * 7 | * Licensed under the MIT license 8 | */ 9 | 10 | (function($) { 11 | 'use strict'; 12 | 13 | /** 14 | * Constructor. 15 | */ 16 | var SimpleColorPicker = function(select, options) { 17 | this.init('simplecolorpicker', select, options); 18 | }; 19 | 20 | /** 21 | * SimpleColorPicker class. 22 | */ 23 | SimpleColorPicker.prototype = { 24 | constructor: SimpleColorPicker, 25 | 26 | init: function(type, select, options) { 27 | var self = this; 28 | 29 | self.type = type; 30 | 31 | self.$select = $(select); 32 | self.$select.hide(); 33 | 34 | self.options = $.extend({}, $.fn.simplecolorpicker.defaults, options); 35 | 36 | self.$colorList = null; 37 | 38 | if (self.options.picker === true) { 39 | var selectText = self.$select.find('> option:selected').text(); 40 | self.$icon = $('' 44 | + '').insertAfter(self.$select); 45 | self.$icon.on('click.' + self.type, $.proxy(self.showPicker, self)); 46 | 47 | self.$picker = $('').appendTo(document.body); 48 | self.$colorList = self.$picker; 49 | 50 | // Hide picker when clicking outside 51 | $(document).on('mousedown.' + self.type, $.proxy(self.hidePicker, self)); 52 | self.$picker.on('mousedown.' + self.type, $.proxy(self.mousedown, self)); 53 | } else { 54 | self.$inline = $('').insertAfter(self.$select); 55 | self.$colorList = self.$inline; 56 | } 57 | 58 | // Build the list of colors 59 | // 60 | self.$select.find('> option').each(function() { 61 | var $option = $(this); 62 | var color = $option.val(); 63 | 64 | var isSelected = $option.is(':selected'); 65 | var isDisabled = $option.is(':disabled'); 66 | 67 | var selected = ''; 68 | if (isSelected === true) { 69 | selected = ' data-selected'; 70 | } 71 | 72 | var disabled = ''; 73 | if (isDisabled === true) { 74 | disabled = ' data-disabled'; 75 | } 76 | 77 | var title = ''; 78 | if (isDisabled === false) { 79 | title = ' title="' + $option.text() + '"'; 80 | } 81 | 82 | var role = ''; 83 | if (isDisabled === false) { 84 | role = ' role="button" tabindex="0"'; 85 | } 86 | 87 | var $colorSpan = $('' 94 | + ''); 95 | 96 | self.$colorList.append($colorSpan); 97 | $colorSpan.on('click.' + self.type, $.proxy(self.colorSpanClicked, self)); 98 | 99 | var $next = $option.next(); 100 | if ($next.is('optgroup') === true) { 101 | // Vertical break, like hr 102 | self.$colorList.append(''); 103 | } 104 | }); 105 | }, 106 | 107 | /** 108 | * Changes the selected color. 109 | * 110 | * @param color the hexadecimal color to select, ex: '#fbd75b' 111 | */ 112 | selectColor: function(color) { 113 | var self = this; 114 | 115 | var $colorSpan = self.$colorList.find('> span.color').filter(function() { 116 | return $(this).data('color').toLowerCase() === color.toLowerCase(); 117 | }); 118 | 119 | if ($colorSpan.length > 0) { 120 | self.selectColorSpan($colorSpan); 121 | } else { 122 | console.error("The given color '" + color + "' could not be found"); 123 | } 124 | }, 125 | 126 | showPicker: function() { 127 | var pos = this.$icon.offset(); 128 | this.$picker.css({ 129 | // Remove some pixels to align the picker icon with the icons inside the dropdown 130 | left: pos.left - 6, 131 | top: pos.top + this.$icon.outerHeight() 132 | }); 133 | 134 | this.$picker.show(this.options.pickerDelay); 135 | }, 136 | 137 | hidePicker: function() { 138 | this.$picker.hide(this.options.pickerDelay); 139 | }, 140 | 141 | /** 142 | * Selects the given span inside $colorList. 143 | * 144 | * The given span becomes the selected one. 145 | * It also changes the HTML select value, this will emit the 'change' event. 146 | */ 147 | selectColorSpan: function($colorSpan) { 148 | var color = $colorSpan.data('color'); 149 | var title = $colorSpan.prop('title'); 150 | 151 | // Mark this span as the selected one 152 | $colorSpan.siblings().removeAttr('data-selected'); 153 | $colorSpan.attr('data-selected', ''); 154 | 155 | if (this.options.picker === true) { 156 | this.$icon.css('background-color', color); 157 | this.$icon.prop('title', title); 158 | this.hidePicker(); 159 | } 160 | 161 | // Change HTML select value 162 | this.$select.val(color); 163 | }, 164 | 165 | /** 166 | * The user clicked on a color inside $colorList. 167 | */ 168 | colorSpanClicked: function(e) { 169 | // When a color is clicked, make it the new selected one (unless disabled) 170 | if ($(e.target).is('[data-disabled]') === false) { 171 | this.selectColorSpan($(e.target)); 172 | this.$select.trigger('change'); 173 | } 174 | }, 175 | 176 | /** 177 | * Prevents the mousedown event from "eating" the click event. 178 | */ 179 | mousedown: function(e) { 180 | e.stopPropagation(); 181 | e.preventDefault(); 182 | }, 183 | 184 | destroy: function() { 185 | if (this.options.picker === true) { 186 | this.$icon.off('.' + this.type); 187 | this.$icon.remove(); 188 | $(document).off('.' + this.type); 189 | } 190 | 191 | this.$colorList.off('.' + this.type); 192 | this.$colorList.remove(); 193 | 194 | this.$select.removeData(this.type); 195 | this.$select.show(); 196 | } 197 | }; 198 | 199 | /** 200 | * Plugin definition. 201 | * How to use: $('#id').simplecolorpicker() 202 | */ 203 | $.fn.simplecolorpicker = function(option) { 204 | var args = $.makeArray(arguments); 205 | args.shift(); 206 | 207 | // For HTML element passed to the plugin 208 | return this.each(function() { 209 | var $this = $(this), 210 | data = $this.data('simplecolorpicker'), 211 | options = typeof option === 'object' && option; 212 | if (data === undefined) { 213 | $this.data('simplecolorpicker', (data = new SimpleColorPicker(this, options))); 214 | } 215 | if (typeof option === 'string') { 216 | data[option].apply(data, args); 217 | } 218 | }); 219 | }; 220 | 221 | /** 222 | * Default options. 223 | */ 224 | $.fn.simplecolorpicker.defaults = { 225 | // No theme by default 226 | theme: '', 227 | 228 | // Show the picker or make it inline 229 | picker: false, 230 | 231 | // Animation delay in milliseconds 232 | pickerDelay: 0 233 | }; 234 | 235 | })(jQuery); 236 | -------------------------------------------------------------------------------- /scss/_sumoselect.scss: -------------------------------------------------------------------------------- 1 | 2 | #aufgaben { 3 | .SumoSelect p {margin: 0;} 4 | .SumoSelect{width: 200px;} 5 | 6 | .SelectBox {padding: 5px 8px;} 7 | 8 | /* Filtering style */ 9 | .SumoSelect .hidden { display:none; } 10 | .SumoSelect .search-txt{display:none;outline:none;} 11 | .SumoSelect .no-match{display:none;padding: 6px;} 12 | .SumoSelect.open .search-txt{display: inline-block;position: absolute;top: 0;left: 0;width: 100%;margin: 0;padding: 5px 8px;border: none;-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;border-radius: 5px;} 13 | .SumoSelect.open>.search>span, .SumoSelect.open>.search>label{visibility:hidden;} 14 | 15 | /*this is applied on that hidden select. DO NOT USE display:none; or visiblity:hidden; and Do not override any of these properties. */ 16 | .SelectClass,.SumoUnder { position: absolute; top: 0; left: 0; right: 0; height: 100%; width: 100%; border: none; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); -moz-opacity: 0; -khtml-opacity: 0; opacity: 0; } 17 | .SelectClass{z-index: 1;} 18 | 19 | .SumoSelect > .optWrapper > .options li.opt label, .SumoSelect > .CaptionCont,.SumoSelect .select-all > label { user-select: none; -o-user-select: none; -moz-user-select: none; -khtml-user-select: none; -webkit-user-select: none; } 20 | 21 | .SumoSelect { display: inline-block; position: relative;outline:none;} 22 | .SumoSelect:focus > .CaptionCont,.SumoSelect:hover > .CaptionCont, .SumoSelect.open > .CaptionCont {} 23 | .SumoSelect > .CaptionCont { position: relative; border: 1px solid #A4A4A4; min-height: 14px; background-color: #fff;border-radius:2px;margin:0;} 24 | .SumoSelect > .CaptionCont > span { display: block; padding-right: 30px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden;cursor:default;} 25 | /*placeholder style*/ 26 | .SumoSelect > .CaptionCont > span.placeholder { color: #ccc; font-style: italic; } 27 | 28 | .SumoSelect > .CaptionCont > label { position: absolute; top: 0; right: 0; bottom: 0; width: 30px;} 29 | .SumoSelect > .CaptionCont > label > i { background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3wMdBhAJ/fwnjwAAAGFJREFUKM9jYBh+gBFKuzEwMKQwMDB8xaOWlYGB4T4DA0MrsuapDAwM//HgNwwMDDbYTJuGQ8MHBgYGJ1xOYGNgYJiBpuEpAwODHSF/siDZ+ISBgcGClEDqZ2Bg8B6CkQsAPRga0cpRtDEAAAAASUVORK5CYII='); 30 | background-position: center center; width: 16px; height: 16px; display: block; position: absolute; top: 0; left: 0; right: 0; bottom: 0; margin: auto;background-repeat: no-repeat;opacity: 0.8;} 31 | 32 | .SumoSelect > .optWrapper {display:none; z-index: 1000; top: 30px; width: 100%; position: absolute; left: 0; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; background: #fff; border: 1px solid #ddd; box-shadow: 2px 3px 3px rgba(0, 0, 0, 0.11); border-radius: 3px;overflow: hidden;} 33 | .SumoSelect.open > .optWrapper {top: 30px; display:block;} 34 | .SumoSelect.open > .optWrapper.up {top: auto;bottom: 100%;margin-bottom: 5px;} 35 | 36 | .SumoSelect > .optWrapper ul {list-style: none; display: block; padding: 0; margin: 0; overflow: auto;} 37 | .SumoSelect > .optWrapper > .options { border-radius: 2px;position:relative; 38 | /*Set the height of pop up here (only for desktop mode)*/ 39 | max-height: 250px; 40 | /*height*/ } 41 | .SumoSelect > .optWrapper > .options li.group.disabled > label{opacity:0.5;} 42 | .SumoSelect > .optWrapper > .options li ul li.opt{padding-left: 22px;} 43 | .SumoSelect > .optWrapper.multiple > .options li ul li.opt{padding-left: 50px;} 44 | .SumoSelect > .optWrapper.isFloating > .options {max-height: 100%;box-shadow: 0 0 100px #595959;} 45 | .SumoSelect > .optWrapper > .options li.opt { padding: 6px 6px; position: relative;border-bottom: 1px solid #f5f5f5;} 46 | .SumoSelect > .optWrapper > .options > li.opt:first-child { border-radius: 2px 2px 0 0; } 47 | .SumoSelect > .optWrapper > .options > li.opt:last-child {border-radius: 0 0 2px 2px; border-bottom: none;} 48 | .SumoSelect > .optWrapper > .options li.opt:hover { background-color: #E4E4E4; } 49 | .SumoSelect > .optWrapper > .options li.opt.sel{background-color: #a1c0e4; border-bottom: 1px solid #a1c0e4;} 50 | 51 | .SumoSelect > .optWrapper > .options li label { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; display: block;cursor: pointer;} 52 | .SumoSelect > .optWrapper > .options li span { display: none; } 53 | .SumoSelect > .optWrapper > .options li.group > label {cursor: default;padding: 8px 6px;font-weight: bold;} 54 | 55 | /*Floating styles*/ 56 | .SumoSelect > .optWrapper.isFloating { position: fixed; top: 0px; left: 0; right: 0; width: 90%; bottom: 0; margin: auto; max-height: 90%; } 57 | 58 | /*disabled state*/ 59 | .SumoSelect > .optWrapper > .options li.opt.disabled { background-color: inherit;pointer-events: none;} 60 | .SumoSelect > .optWrapper > .options li.opt.disabled * { -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; /* IE 5-7 */ filter: alpha(opacity=50); /* Netscape */ -moz-opacity: 0.5; /* Safari 1.x */ -khtml-opacity: 0.5; /* Good browsers */ opacity: 0.5; } 61 | 62 | 63 | /*styling for multiple select*/ 64 | .SumoSelect > .optWrapper.multiple > .options li.opt { padding-left: 35px;cursor: pointer;} 65 | .SumoSelect > .optWrapper.multiple > .options li.opt span, 66 | .SumoSelect .select-all > span{position:absolute;display:block;width:30px;top:0;bottom:0;margin-left:-35px;} 67 | .SumoSelect > .optWrapper.multiple > .options li.opt span i, 68 | .SumoSelect .select-all > span i{position: absolute;margin: auto;left: 0;right: 0;top: 0;bottom: 0;width: 14px;height: 14px;border: 1px solid #AEAEAE;border-radius: 2px;box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.15);background-color: #fff;} 69 | .SumoSelect > .optWrapper > .MultiControls { display: none; border-top: 1px solid #ddd; background-color: #fff; box-shadow: 0 0 2px rgba(0, 0, 0, 0.13); border-radius: 0 0 3px 3px; } 70 | .SumoSelect > .optWrapper.multiple.isFloating > .MultiControls { display: block; margin-top: 5px; position: absolute; bottom: 0; width: 100%; } 71 | 72 | .SumoSelect > .optWrapper.multiple.okCancelInMulti > .MultiControls { display: block; } 73 | .SumoSelect > .optWrapper.multiple.okCancelInMulti > .MultiControls > p { padding: 6px; } 74 | 75 | .SumoSelect > .optWrapper.multiple > .MultiControls > p { display: inline-block; cursor: pointer; padding: 12px; width: 50%; box-sizing: border-box; text-align: center; } 76 | .SumoSelect > .optWrapper.multiple > .MultiControls > p:hover { background-color: #f1f1f1; } 77 | .SumoSelect > .optWrapper.multiple > .MultiControls > p.btnOk { border-right: 1px solid #DBDBDB; border-radius: 0 0 0 3px; } 78 | .SumoSelect > .optWrapper.multiple > .MultiControls > p.btnCancel { border-radius: 0 0 3px 0; } 79 | /*styling for select on popup mode*/ 80 | .SumoSelect > .optWrapper.isFloating > .options li.opt { padding: 12px 6px; } 81 | 82 | /*styling for only multiple select on popup mode*/ 83 | .SumoSelect > .optWrapper.multiple.isFloating > .options li.opt { padding-left: 35px; } 84 | .SumoSelect > .optWrapper.multiple.isFloating { padding-bottom: 143px; } 85 | 86 | .SumoSelect > .optWrapper.multiple > .options li.opt.selected span i, 87 | .SumoSelect .select-all.selected > span i, 88 | .SumoSelect .select-all.partial > span i{background-color: rgb(17, 169, 17);box-shadow: none;border-color: transparent;background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAGCAYAAAD+Bd/7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNXG14zYAAABMSURBVAiZfc0xDkAAFIPhd2Kr1WRjcAExuIgzGUTIZ/AkImjSofnbNBAfHvzAHjOKNzhiQ42IDFXCDivaaxAJd0xYshT3QqBxqnxeHvhunpu23xnmAAAAAElFTkSuQmCC');background-repeat: no-repeat;background-position: center center;} 89 | /*disabled state*/ 90 | .SumoSelect.disabled { opacity: 0.7;cursor: not-allowed;} 91 | .SumoSelect.disabled > .CaptionCont{border-color:#ccc;box-shadow:none;} 92 | 93 | /**Select all button**/ 94 | .SumoSelect .select-all{border-radius: 3px 3px 0 0;position: relative;border-bottom: 1px solid #ddd;background-color: #fff;padding: 8px 0 3px 35px;height: 20px;cursor: pointer;} 95 | .SumoSelect .select-all > label, .SumoSelect .select-all > span i{cursor: pointer;} 96 | .SumoSelect .select-all.partial > span i{background-color:#ccc;} 97 | 98 | 99 | /*styling for optgroups*/ 100 | .SumoSelect > .optWrapper > .options li.optGroup { padding-left: 5px; text-decoration: underline; } 101 | 102 | 103 | .SumoSelect .SumoUnder{ 104 | height: 0px; 105 | } 106 | .SumoSelect { 107 | font-size: 10px; 108 | } 109 | 110 | .SumoSelect{width: 100% !important;} 111 | .SelectBox {padding: 3px 4px !important; 112 | border: 1px solid #e0e3e9 !important; 113 | margin-top: 5px !important; 114 | } 115 | .SumoSelect > .CaptionCont > span.placeholder { color: #ccc; font-style: normal !important; } 116 | 117 | .SumoSelect > .CaptionCont > label > i { 118 | margin-top: 1px !important; 119 | opacity: 0.3 !important; 120 | } 121 | 122 | .SumoSelect:focus > .CaptionCont,.SumoSelect:hover > .CaptionCont, .SumoSelect.open > .CaptionCont { 123 | border: 1px solid #222 !important; 124 | } 125 | 126 | .SumoSelect:hover > .CaptionCont > label > i { 127 | opacity: 1 !important; 128 | } 129 | 130 | .SumoSelect.open > .optWrapper { 131 | min-width: 180px !important; 132 | } 133 | 134 | } 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /scss/_kanban.scss: -------------------------------------------------------------------------------- 1 | #aufgaben.kanban-wrapper { 2 | width: 100%; 3 | position:relative; 4 | overflow-X: scroll; 5 | 6 | a:hover, a:active, a:focus, a:link, a:visited 7 | { 8 | outline: 0; 9 | outline: 0 !important; 10 | outline-style:none; 11 | } 12 | 13 | h4 14 | { 15 | color: #555; 16 | font-size: 16px; 17 | 18 | a 19 | { 20 | color: #555; 21 | display: block; 22 | position:relative; 23 | padding-left: 17px; 24 | 25 | &:hover, &:focus, &:active 26 | { 27 | text-decoration: none; 28 | } 29 | 30 | &.expand 31 | { 32 | &:after 33 | { 34 | content: "\f077"; 35 | font-family: FontAwesome; 36 | font-size: 12px; 37 | position:absolute; 38 | left: 0; 39 | top: 2px; 40 | height: 15px; 41 | width: 15px; 42 | } 43 | 44 | &.collapsed 45 | { 46 | &:after 47 | { 48 | content: "\f078"; 49 | } 50 | } 51 | } 52 | } 53 | } 54 | 55 | .kanban-heading { 56 | font-size: 14px; 57 | } 58 | 59 | .kanban-centered { 60 | position: relative; 61 | margin-bottom: 30px; 62 | 63 | &:before, &:after 64 | { 65 | content: " "; 66 | display: table; 67 | } 68 | 69 | &:after 70 | { 71 | clear: both; 72 | } 73 | 74 | &:before 75 | { 76 | content: ''; 77 | position: absolute; 78 | display: block; 79 | width: 2px; 80 | top: 20px; 81 | bottom: 20px; 82 | } 83 | } 84 | 85 | 86 | .kanban-entry { 87 | position: relative; 88 | clear: both; 89 | 90 | &:before, &:after 91 | { 92 | content: " "; 93 | display: table; 94 | } 95 | 96 | &:after 97 | { 98 | clear: both; 99 | } 100 | 101 | &:before 102 | { 103 | content: ''; 104 | position: absolute; 105 | display: block; 106 | width: 2px; 107 | top: 20px; 108 | bottom: 20px; 109 | } 110 | 111 | &.begin 112 | { 113 | margin-bottom: 0; 114 | } 115 | 116 | &.left-aligned 117 | { 118 | float: left; 119 | 120 | .kanban-entry-inner 121 | { 122 | margin-left: 0; 123 | margin-right: -18px; 124 | } 125 | } 126 | } 127 | 128 | .kanban-label 129 | { 130 | margin-left: 0; 131 | width: 100%; 132 | 133 | &:after 134 | { 135 | left: auto; 136 | right: 0; 137 | margin-left: 0; 138 | margin-right: -9px; 139 | -moz-transform: rotate(180deg); 140 | -o-transform: rotate(180deg); 141 | -webkit-transform: rotate(180deg); 142 | -ms-transform: rotate(180deg); 143 | transform: rotate(180deg); 144 | } 145 | } 146 | 147 | .kanban-entry-inner 148 | { 149 | position: relative; 150 | 151 | &:before, &:after 152 | { 153 | content: " "; 154 | display: table; 155 | } 156 | 157 | &:after 158 | { 159 | clear: both; 160 | } 161 | 162 | &:before 163 | { 164 | content: ''; 165 | position: absolute; 166 | display: block; 167 | width: 2px; 168 | top: 20px; 169 | bottom: 20px; 170 | } 171 | 172 | .kanban-label 173 | { 174 | position: relative; 175 | padding: 0.75em; 176 | -webkit-background-clip: padding-box; 177 | -moz-background-clip: padding; 178 | background-clip: padding-box; 179 | } 180 | } 181 | 182 | 183 | .kanban-centered .kanban-entry .kanban-entry-inner .kanban-label h2, .kanban-centered .kanban-entry .kanban-entry-inner .kanban-label p { 184 | font-size: 12px; 185 | line-height: 1.428571429; 186 | } 187 | 188 | .kanban-centered .kanban-entry .kanban-entry-inner .kanban-label p + p { 189 | margin-top: 15px; 190 | } 191 | 192 | .kanban-centered .kanban-entry .kanban-entry-inner .kanban-label h2 { 193 | font-size: 16px; 194 | margin-bottom: 10px; 195 | } 196 | 197 | .kanban-centered .kanban-entry .kanban-entry-inner .kanban-label h2 a 198 | { 199 | color: #303641; 200 | } 201 | 202 | .kanban-centered .kanban-entry .kanban-entry-inner .kanban-label h2 span 203 | { 204 | -webkit-opacity: .6; 205 | -moz-opacity: .6; 206 | opacity: .6; 207 | -ms-filter: alpha(opacity=60); 208 | filter: alpha(opacity=60); 209 | } 210 | 211 | .kanban-col { 212 | width: 280px; 213 | margin-right: 10px; 214 | float: left; 215 | } 216 | 217 | .panel-body { 218 | padding: 0; 219 | overflow-y: auto; 220 | } 221 | 222 | 223 | .panel-heading { 224 | cursor: default; 225 | 226 | i { 227 | cursor: pointer; 228 | } 229 | } 230 | 231 | .status { 232 | display: table; 233 | width: 100%; 234 | 235 | .change-status { 236 | text-align: center; 237 | display: table-cell; 238 | width: 16.66666666666667%; 239 | text-align: center !important; 240 | i { 241 | border: none; 242 | margin-left: 9px; 243 | } 244 | } 245 | 246 | .change-status.current i { 247 | color: black; 248 | padding: 3px; 249 | } 250 | .change-status.current.done i 251 | { 252 | color: #3CB594; 253 | } 254 | } 255 | 256 | 257 | hr 258 | { 259 | border-top: 1px solid #DFE3E9; 260 | margin: 3px 0; 261 | } 262 | 263 | .responsible { 264 | font-size: 10px; 265 | } 266 | 267 | 268 | 269 | .kanban-entry 270 | { 271 | 272 | margin-top: 20px; 273 | background: #f9f9f9; 274 | border-top: 1px solid #aaa; 275 | border-bottom: 1px solid #aaa; 276 | 277 | .prio-wrapper 278 | { 279 | position:absolute; 280 | right: 8px; 281 | top: 4px; 282 | z-index: 50; 283 | opacity: 0; 284 | -moz-transition-property: all; 285 | -o-transition-property: all; 286 | -webkit-transition-property: all; 287 | transition-property: all; 288 | -moz-transition-duration: 0.3s; 289 | -o-transition-duration: 0.3s; 290 | -webkit-transition-duration: 0.3s; 291 | transition-duration: 0.3s; 292 | -moz-transition-timing-function: ease-in-out; 293 | -o-transition-timing-function: ease-in-out; 294 | -webkit-transition-timing-function: ease-in-out; 295 | transition-timing-function: ease-in-out; 296 | 297 | .current 298 | { 299 | color: #F0AD4E; 300 | } 301 | .change-prio 302 | { 303 | padding: 2px; 304 | } 305 | } 306 | 307 | .date { 308 | display: inline; 309 | font-size: 10px; 310 | } 311 | 312 | .well { 313 | font-size: 10px; 314 | } 315 | 316 | .delete-kanban-entry 317 | { 318 | position:absolute; 319 | right: 8px; 320 | bottom: 8px; 321 | font-size: 9px; 322 | color: #C9302C; 323 | z-index: 50; 324 | opacity: 0; 325 | -moz-transition-property: all; 326 | -o-transition-property: all; 327 | -webkit-transition-property: all; 328 | transition-property: all; 329 | -moz-transition-duration: 0.3s; 330 | -o-transition-duration: 0.3s; 331 | -webkit-transition-duration: 0.3s; 332 | transition-duration: 0.3s; 333 | -moz-transition-timing-function: ease-in-out; 334 | -o-transition-timing-function: ease-in-out; 335 | -webkit-transition-timing-function: ease-in-out; 336 | transition-timing-function: ease-in-out; 337 | 338 | i 339 | { 340 | opacity: 0.5; 341 | } 342 | 343 | &:hover 344 | { 345 | i 346 | { 347 | opacity: 1; 348 | } 349 | } 350 | } 351 | 352 | .edit-kanban-entry 353 | { 354 | position:absolute; 355 | right: 28px; 356 | bottom: 7px; 357 | font-size: 9px; 358 | color: #008803; 359 | z-index: 50; 360 | opacity: 0; 361 | -moz-transition-property: all; 362 | -o-transition-property: all; 363 | -webkit-transition-property: all; 364 | transition-property: all; 365 | -moz-transition-duration: 0.3s; 366 | -o-transition-duration: 0.3s; 367 | -webkit-transition-duration: 0.3s; 368 | transition-duration: 0.3s; 369 | -moz-transition-timing-function: ease-in-out; 370 | -o-transition-timing-function: ease-in-out; 371 | -webkit-transition-timing-function: ease-in-out; 372 | transition-timing-function: ease-in-out; 373 | 374 | i 375 | { 376 | opacity: 0.5; 377 | } 378 | 379 | &:hover 380 | { 381 | i 382 | { 383 | opacity: 1; 384 | } 385 | } 386 | } 387 | 388 | &:hover 389 | { 390 | .prio-wrapper 391 | { 392 | opacity: 1; 393 | } 394 | 395 | .delete-kanban-entry, .edit-kanban-entry 396 | { 397 | opacity: 1; 398 | } 399 | } 400 | } 401 | 402 | #drop-helper 403 | { 404 | font-size: 30px; 405 | color: black; 406 | } 407 | 408 | #kanban-drag-helper 409 | { 410 | -moz-transition-property: color; 411 | -o-transition-property: color; 412 | -webkit-transition-property: color; 413 | transition-property: color; 414 | -moz-transition-duration: 0.3s; 415 | -o-transition-duration: 0.3s; 416 | -webkit-transition-duration: 0.3s; 417 | transition-duration: 0.3s; 418 | -moz-transition-timing-function: ease-in-out; 419 | -o-transition-timing-function: ease-in-out; 420 | -webkit-transition-timing-function: ease-in-out; 421 | transition-timing-function: ease-in-out; 422 | } 423 | 424 | 425 | } 426 | -------------------------------------------------------------------------------- /assets/js/kanban.js: -------------------------------------------------------------------------------- 1 | var redaxo = redaxo || {}; 2 | redaxo.Kanban = redaxo.Kanban || (function (jQuery) 3 | { 4 | var jRexLoader; 5 | 6 | var Kanban = function () 7 | { 8 | var jKanbanStage = jQuery('.kanban-stage'); 9 | var jKanbanCol = jQuery('.panel-body'); 10 | var jChangePrioTrigger = jQuery(".change-prio"); 11 | var jChangeStatusTrigger = jQuery(".change-status"); 12 | var jDeleteEntryTrigger = jQuery(".delete-kanban-entry"); 13 | var jAddEntryTrigger = jQuery(".add-kanban-entry"); 14 | var jEditEntryTrigger = jQuery(".edit-kanban-entry"); 15 | var jDraggableContainer = jQuery(".grab"); 16 | var jDropContainer = jQuery(".panel-body"); 17 | 18 | jQuery.extend(true, this, 19 | { 20 | jKanbanStage: jKanbanStage, 21 | jKanbanCol: jKanbanCol, 22 | jChangePrioTrigger: jChangePrioTrigger, 23 | jChangeStatusTrigger: jChangeStatusTrigger, 24 | jDeleteEntryTrigger: jDeleteEntryTrigger, 25 | jAddEntryTrigger: jAddEntryTrigger, 26 | jEditEntryTrigger: jEditEntryTrigger, 27 | jDraggableContainer: jDraggableContainer, 28 | jDropContainer: jDropContainer 29 | }); 30 | 31 | initView.call(this); 32 | }; 33 | 34 | var getRexLoader = function getRexLoader() 35 | { 36 | var that = this; 37 | 38 | var checkExist = setInterval(function () 39 | { 40 | if (jQuery('#rex-js-ajax-loader').length) 41 | { 42 | jRexLoader = jQuery('#rex-js-ajax-loader'); 43 | attachEventHandler.call(that); 44 | clearInterval(checkExist); 45 | } 46 | }, 100); 47 | }; 48 | 49 | 50 | var initView = function initView() 51 | { 52 | getRexLoader.call(this); 53 | initKanban.call(this); 54 | }; 55 | 56 | 57 | // init kanban view 58 | var initKanban = function initKanban() 59 | { 60 | var kanbanColCount = parseInt(this.jKanbanCol.length); 61 | 62 | this.jKanbanCol.css('max-height', (window.innerHeight - 150) + 'px'); 63 | this.jKanbanStage.css('min-width', (kanbanColCount * 325) + 'px'); 64 | }; 65 | 66 | var kanbanAjax = function kanbanAjax(postData, successCallback) 67 | { 68 | jQuery.ajax( 69 | { 70 | method: "POST", 71 | url: kanbanAjaxUrl, 72 | data: postData, 73 | beforeSend: function (xhr) 74 | { 75 | jRexLoader.addClass('rex-visible'); 76 | }, 77 | success: function (data, textStatus, jqXHR) 78 | { 79 | successCallback(); 80 | }, 81 | error: function (jqXHR, textStatus, errorThrown) 82 | { 83 | jRexLoader.removeClass('rex-visible'); 84 | console.error("#ERROR: jqXHR, textStatus, errorThrown", jqXHR, textStatus, errorThrown); 85 | } 86 | }); 87 | }; 88 | 89 | 90 | // change kanban entry prio 91 | var changePrioHandler = function changePrioHandler() 92 | { 93 | var jThis = jQuery(this); 94 | var jPrioWrapper = jThis.parent(); 95 | var jPrioItems = jPrioWrapper.find(".change-prio"); 96 | var id = jThis.data("id"); 97 | var thisPrioID = jThis.data("prioid"); 98 | var hasClass = jThis.hasClass("current"); 99 | 100 | if (!hasClass) 101 | { 102 | prioId = thisPrioID; 103 | } 104 | 105 | var postSuccessCallback = function postSuccessCallback() 106 | { 107 | if (hasClass) 108 | { 109 | jThis.removeClass("current"); 110 | } 111 | else 112 | { 113 | jPrioItems.removeClass("current"); 114 | 115 | if (prioId > 0) 116 | { 117 | jThis.addClass("current"); 118 | } 119 | } 120 | 121 | jRexLoader.removeClass('rex-visible'); 122 | }; 123 | 124 | kanbanAjax({"updateprio": "true", "prioid": prioId, "id": id}, postSuccessCallback); 125 | }; 126 | 127 | 128 | // change kanban entry status 129 | var changeStatusHandler = function changeStatusHandler() 130 | { 131 | var jThis = jQuery(this); 132 | var jStatusWrapper = jThis.parent(); 133 | var jStatusItems = jStatusWrapper.find(".change-status"); 134 | var id = jThis.data("id"); 135 | var thisStatusID = jThis.data("statusid"); 136 | var hasClass = jThis.hasClass("current"); 137 | var statusId = thisStatusID; 138 | 139 | var postSuccessCallback = function postSuccessCallback() 140 | { 141 | if (hasClass) 142 | { 143 | jThis.addClass("current"); 144 | } 145 | else 146 | { 147 | jStatusItems.removeClass("current"); 148 | jThis.addClass("current"); 149 | } 150 | 151 | jRexLoader.removeClass('rex-visible'); 152 | }; 153 | 154 | kanbanAjax({"updatestatus": "true", "statusid": statusId, "id": id}, postSuccessCallback); 155 | }; 156 | 157 | 158 | // delete kanban entry 159 | var deleteEntryHandler = function deleteEntryHandler(event) 160 | { 161 | event.preventDefault(); 162 | 163 | var jThis = jQuery(this); 164 | var jEntry = jThis.closest("article.kanban-entry"); 165 | var id = jEntry.data("id"); 166 | var title = jEntry.data("title"); 167 | var item = jEntry.data("item"); 168 | var jItem = jQuery("#" + item); 169 | var jDeleteEntryModal = jQuery('#confirm'); 170 | var jConfirmItemTitle = jDeleteEntryModal.find(".delete-title"); 171 | 172 | jConfirmItemTitle.text(title); 173 | 174 | var postSuccessCallback = function postSuccessCallback() 175 | { 176 | jItem.slideUp("fast", function () 177 | { 178 | jItem.remove(); 179 | jRexLoader.removeClass('rex-visible'); 180 | }); 181 | }; 182 | 183 | jDeleteEntryModal.modal().one('click', '#delete-entry', function (event) 184 | { 185 | kanbanAjax({"deletetodo": "true", "id": id}, postSuccessCallback); 186 | }); 187 | }; 188 | 189 | 190 | // add kanban entry 191 | var addEntryHandler = function addEntryHandler(event) 192 | { 193 | event.preventDefault(); 194 | 195 | var jThis = jQuery(this); 196 | var jAddEntryModal = jQuery("#add-modal"); 197 | var categoryId = jThis.data("categoryid"); 198 | var categoryName = jThis.data("categoryname"); 199 | var jForm = jAddEntryModal.find("form"); 200 | var jTitle = jForm.find("#rex-aufgaben-title"); 201 | var jDescription = jForm.find("#rex-aufgaben-description"); 202 | var jCategoryID = jForm.find("#rex-aufgaben-category"); 203 | var jCategoryName = jForm.find("#rex-aufgaben-category-name"); 204 | var jErrorContainer = jQuery("#missing-values"); 205 | 206 | // console.log(jThis); 207 | // console.log("categoryId", categoryId); 208 | 209 | jErrorContainer.hide(); 210 | 211 | jTitle.val(""); 212 | jDescription.val(""); 213 | jCategoryName.val(categoryName); 214 | jCategoryID.val(parseFloat(categoryId)); 215 | 216 | var checkForm = function checkForm(event) 217 | { 218 | var formData = jForm.serialize(); 219 | 220 | if (jTitle.val() === "" || jCategoryName.val() === "") 221 | { 222 | jErrorContainer.slideDown(); 223 | jAddEntryModal.modal().one('click', '#save-add-entry', checkForm); 224 | } 225 | else 226 | { 227 | jErrorContainer.slideUp(); 228 | 229 | var postSuccessCallback = function postSuccessCallback() 230 | { 231 | jAddEntryModal.modal('hide'); 232 | window.location.reload(); 233 | }; 234 | 235 | kanbanAjax(formData, postSuccessCallback); 236 | } 237 | }; 238 | 239 | jAddEntryModal.modal().one('click', '#save-add-entry', checkForm); 240 | }; 241 | 242 | 243 | // edit kanban entry 244 | var editEntryHandler = function editEntryHandler(event) 245 | { 246 | event.preventDefault(); 247 | 248 | var jThis = jQuery(this); 249 | var jEntry = jThis.closest("article.kanban-entry"); 250 | var jEditEntryModal = jQuery("#edit-modal"); 251 | var categoryId = jEntry.data("categoryid"); 252 | var id = jEntry.data("id"); 253 | var title = jEntry.data("title"); 254 | var description = jEntry.data("description"); 255 | var owner = jEntry.data("owner"); 256 | var status = jEntry.data("status"); 257 | var jForm = jEditEntryModal.find("form"); 258 | var jTitle = jForm.find("#rex-aufgaben-title"); 259 | var jId = jForm.find("#entry-id"); 260 | var jDescription = jForm.find("#rex-aufgaben-description"); 261 | var jStatus = jForm.find("#rex-aufgaben-status"); 262 | var jowner = jForm.find("#rex-aufgaben-owner"); 263 | var jCategory = jForm.find("#rex-aufgaben-category"); 264 | var jErrorContainer = jQuery("#missing-values"); 265 | 266 | // console.log(id); 267 | // console.log(jEntry.data()); 268 | 269 | jErrorContainer.hide(); 270 | 271 | jId.val(id); 272 | jTitle.val(title); 273 | 274 | jDescription.val(description); 275 | jCategory.val(categoryId); 276 | jStatus.val(status); 277 | jowner.val(owner); 278 | 279 | var checkForm = function checkForm(event) 280 | { 281 | var formData = jForm.serialize(); 282 | 283 | if (jTitle.val() === "" || jCategory.val() === "") 284 | { 285 | jErrorContainer.slideDown(); 286 | jEditEntryModal.modal().one('click', '#save-edit-entry', checkForm); 287 | } 288 | else 289 | { 290 | jErrorContainer.slideUp(); 291 | 292 | var postSuccessCallback = function postSuccessCallback() 293 | { 294 | jEditEntryModal.modal('hide'); 295 | window.location.reload(); 296 | }; 297 | 298 | kanbanAjax(formData, postSuccessCallback); 299 | } 300 | }; 301 | 302 | jEditEntryModal.modal().one('click', '#save-edit-entry', checkForm); 303 | }; 304 | 305 | 306 | // draggable settings 307 | var draggableSettings = { 308 | appendTo: 'body', 309 | helper: function () 310 | { 311 | var dom = []; 312 | var jThis = jQuery(this); 313 | var color = jThis.data("color"); 314 | 315 | dom.push('
'); 316 | 317 | return $(dom.join('')); 318 | }, 319 | cursorAt: {right: 15, bottom: 20}, 320 | cursor: "move" 321 | }; 322 | 323 | 324 | // droppable settings 325 | var droppableSettings = { 326 | activeClass: "ui-state-default", 327 | hoverClass: "ui-state-hover", 328 | accept: ":not(.ui-sortable-helper)", 329 | over: function (event, ui) 330 | { 331 | var jThis = jQuery(this); 332 | var jHelperItem = jQuery(ui.helper); 333 | var color = jThis.data("color"); 334 | jHelperItem.css({"color": color}); 335 | }, 336 | drop: function (event, ui) 337 | { 338 | var jThis = jQuery(this); 339 | var categoryid = jThis.data("categoryid"); 340 | var jAppendContainer = jThis.find(".kanban-centered"); 341 | var jDraggedItem = jQuery(ui.draggable); 342 | var id = jDraggedItem.data("id"); 343 | var draggedcategoryid = jDraggedItem.data("categoryid"); 344 | var color = jThis.data("color"); 345 | 346 | if (draggedcategoryid === categoryid) 347 | { 348 | return false; 349 | } 350 | 351 | var postSuccessCallback = function postSuccessCallback() 352 | { 353 | jRexLoader.removeClass('rex-visible'); 354 | jThis.find(".placeholder").remove(); 355 | jDraggedItem.appendTo(jAppendContainer); 356 | jDraggedItem.data("categoryid", categoryid); 357 | jDraggedItem.find(".kanban-entry-inner").css({"border-color": color}); 358 | }; 359 | 360 | kanbanAjax({"updatecategory": "true", "id": id, "categoryid": categoryid}, postSuccessCallback); 361 | } 362 | }; 363 | 364 | 365 | var attachEventHandler = function attachEventHandler() 366 | { 367 | this.jChangePrioTrigger.on("click", changePrioHandler); 368 | this.jChangeStatusTrigger.on("click", changeStatusHandler); 369 | this.jDeleteEntryTrigger.on("click", deleteEntryHandler); 370 | this.jAddEntryTrigger.on("click", addEntryHandler); 371 | this.jEditEntryTrigger.on("click", editEntryHandler); 372 | this.jDraggableContainer.draggable(draggableSettings); 373 | this.jDropContainer.droppable(droppableSettings); 374 | }; 375 | 376 | return Kanban; 377 | 378 | }(jQuery)); 379 | -------------------------------------------------------------------------------- /lib/aufgaben_functions.php: -------------------------------------------------------------------------------- 1 | zaehler += $var; 11 | } 12 | } 13 | 14 | /* 15 | $aufgaben = new rex_aufgaben(); 16 | 17 | $aufgaben->test(1); 18 | echo $aufgaben->zaehler; // ausgabe 1 19 | $aufgaben->test(10); 20 | echo $aufgaben->zaehler; // ausgabe 11 21 | */ 22 | 23 | // SHOW COUNTER 24 | public function show_counter() { 25 | $counter = 0; 26 | $current_user = rex::getUser()->getId(); 27 | 28 | $sql_counter = rex_sql::factory(); 29 | //$sql_counter->setDebug(); 30 | $sql_counter->setQuery('SELECT counter FROM rex_aufgaben_user_settings WHERE user = '.$current_user); 31 | 32 | if ($sql_counter->getRows() > 0) { 33 | $ersetzen = ' Aufgaben '.$counter.''; 34 | $counter = $sql_counter->getValue('counter'); 35 | if ($counter > 0) { 36 | $ersetzen = ' Aufgaben '.$counter.''; 37 | } else { 38 | $ersetzen = ' Aufgaben '.$counter.''; 39 | } 40 | 41 | rex_extension::register('OUTPUT_FILTER',function(rex_extension_point $ep) use ($ersetzen){ 42 | $suchmuster = ' Aufgaben'; 43 | $ersetzen = $ersetzen; 44 | $ep->setSubject(str_replace($suchmuster, $ersetzen, $ep->getSubject())); 45 | }); 46 | } 47 | } 48 | function createMailText($aktuelle_id) { 49 | $body = "Beispiel"; 50 | $sql = rex_sql::factory(); 51 | $sql->setQuery('SELECT * FROM rex_aufgaben WHERE id = ' .$aktuelle_id); 52 | if($sql -> getRows()) { 53 | $mail_titel = $sql->getValue('title'); 54 | $mail_beschreibung = $sql->getValue('description'); 55 | $mail_prio = $sql->getValue('prio'); 56 | $mail_status = $sql->getValue('status'); 57 | $mail_eigentuemer = $sql->getValue('responsible'); 58 | $creatuser_realname = $sql->getValue('createuser'); 59 | $creatuser_sql = rex_sql::factory(); 60 | $creatuser_sql->setQuery("SELECT name FROM rex_user WHERE login = '$creatuser_realname'"); 61 | $mail_creatuser = $creatuser_sql->getValue('name'); 62 | $updateuser_realname = $sql->getValue('updateuser'); 63 | $updateuser_sql = rex_sql::factory(); 64 | $updateuser_sql->setQuery("SELECT name FROM rex_user WHERE login = '$updateuser_realname'"); 65 | $mail_updateuser = $updateuser_sql->getValue('name'); 66 | $mail_finaldate = $sql->getValue('finaldate'); 67 | 68 | if ($mail_finaldate == '') { 69 | $mail_finaldate = '--'; 70 | } 71 | 72 | $sql_status_name = rex_sql::factory(); 73 | // $sql_status_name->setDebug(); 74 | $sql_status_name->setQuery('SELECT status FROM rex_aufgaben_status WHERE id = '.$mail_status); 75 | $mail_status = $sql_status_name->getValue('status'); 76 | 77 | 78 | $sql_eigentuemer_name = rex_sql::factory(); 79 | $sql_eigentuemer_name->setQuery('SELECT * FROM rex_user WHERE id = '.$mail_eigentuemer); 80 | $mail_eigentuemer = $sql_eigentuemer_name->getValue('name'); 81 | 82 | if(rex_addon::get('textile')->isAvailable()) { 83 | $text_beschreibung = str_replace('
', '', $mail_beschreibung); 84 | $text_beschreibung = rex_textile::parse($text_beschreibung); 85 | $text_beschreibung = str_replace('###', ' ', $text_beschreibung); 86 | } else { 87 | $text_beschreibung = str_replace(PHP_EOL,'
', $mail_beschreibung ); 88 | } 89 | 90 | $body = ' 91 | 92 | 93 | 94 | 97 | 98 | 99 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 |
95 |

'.$mail_titel.'

96 |
100 | '.$text_beschreibung.' 101 |
Prio '.$mail_prio.' Status '.$mail_status.'
Zuständig '.$mail_eigentuemer.' Erstellt von '.$mail_creatuser.'
Fälligkeitsdatum '.$mail_finaldate.' Aktualisiert von '.$mail_updateuser.'
'; 125 | 126 | } 127 | return $body; 128 | 129 | } 130 | function checkTime($aktuelle_id) { 131 | $delay = rex_config::get('aufgaben', 'time'); 132 | $sql_aufgabe = rex_sql::factory(); 133 | $sql_aufgabe->setQuery('SELECT * FROM rex_aufgaben WHERE id = '.$aktuelle_id); 134 | 135 | if ($sql_aufgabe->getRows()) { 136 | $mail_versendet = $sql_aufgabe->getValue('versendet'); 137 | $currentDate = rex_sql::factory(); 138 | $currentDate = $sql_aufgabe->setQuery("SELECT *, TIME_FORMAT (updatedate, '%H') FROM rex_aufgaben WHERE id = " .$aktuelle_id); 139 | $mail_currentDate = $currentDate->getValue('updatedate'); 140 | $mail_checkCurrentDate = new DateTime($mail_currentDate); 141 | $mail_checkDelayDate = new DateTime($mail_currentDate); 142 | $mail_checkDelayDate->add(new DateInterval('PT'. $delay . 'M')); 143 | $mail_checkDelayDateFinal = $mail_checkDelayDate->format('Y-m-d H:i:s'); 144 | $mail_checkTimeNow = date('Y-m-d H:i:s'); 145 | if($mail_checkDelayDateFinal < $mail_checkTimeNow && $mail_versendet == '2') { 146 | return true; 147 | $sql_aufgabe->setQuery("UPDATE rex_aufgaben SET versendet = '1' WHERE id = " .$aktuelle_id); 148 | } 149 | } 150 | } 151 | 152 | // MAILS 153 | function send_mails($email_adressen, $aktuelle_id, $aufgabe, $betreff, $bodyText, $responseId) { 154 | $sender = rex_config::get('aufgaben', 'absender'); 155 | $betreffMail = rex_config::get('aufgaben', 'betreff'); 156 | $checkbox = rex_config::get('aufgaben', 'send-to-all'); 157 | $body = ""; 158 | 159 | 160 | if ($aufgabe != '') { 161 | $mail_receiver = $email_adressen; 162 | // Aufgabe holen 163 | if ($aktuelle_id == 0) { 164 | $expand_query = 'ORDER BY id DESC LIMIT 1'; 165 | $aufagen_art = 'new'; 166 | } else { 167 | $expand_query = 'WHERE id = '.$aktuelle_id; 168 | $aufagen_art = 'edit'; 169 | } 170 | $sql_aufgabe = rex_sql::factory(); 171 | // $sql_aufgabe->setDebug(); 172 | $sql_aufgabe->setQuery('SELECT * FROM rex_aufgaben '.$expand_query); 173 | if ($sql_aufgabe->getRows()) { 174 | /* 175 | // Eigentümer holen 176 | $sql_email_eigentuemer = rex_sql::factory(); 177 | // $sql_email_eigentuemer->setDebug(); 178 | $sql_email_eigentuemer->setQuery('SELECT email FROM rex_user WHERE id = '.$sql_aufgabe->getValue('eigentuemer').' AND email != ""'); 179 | $mail_receiver[] = $sql_email_eigentuemer->getValue('email'); 180 | 181 | // Updateuser holen 182 | $sql_email_updateuser = rex_sql::factory(); 183 | // $sql_email_updateuser->setDebug(); 184 | $sql_email_updateuser->setQuery('SELECT email FROM rex_user WHERE login = "'.$sql_aufgabe->getValue('updateuser').'" AND email != ""'); 185 | $mail_receiver[] = $sql_email_updateuser->getValue('email'); 186 | 187 | // creatuser holen 188 | $sql_email_creatuser = rex_sql::factory(); 189 | // $sql_email_creatuser->setDebug(); 190 | $sql_email_creatuser->setQuery('SELECT email FROM rex_user WHERE login = "'.$sql_aufgabe->getValue('creatuser').'" AND email != ""'); 191 | $mail_receiver[] = $sql_email_creatuser->getValue('email'); 192 | */ 193 | // Doppelte Mail Empfänger entfernen 194 | $mail_adressen = ''; 195 | $mail_adressen = array_unique($mail_receiver); 196 | 197 | // Mailinhalt 198 | 199 | $mail_beschreibung = $sql_aufgabe->getValue('description'); 200 | $mail_prio = $sql_aufgabe->getValue('prio'); 201 | $mail_status = $sql_aufgabe->getValue('status'); 202 | $mail_eigentuemer = $sql_aufgabe->getValue('responsible'); 203 | 204 | $creatuser_realname = $sql_aufgabe->getValue('createuser'); 205 | $creatuser_sql = rex_sql::factory(); 206 | $creatuser_sql->setQuery("SELECT name FROM rex_user WHERE login = '$creatuser_realname'"); 207 | $mail_creatuser = $creatuser_sql->getValue('name'); 208 | $updateuser_realname = $sql_aufgabe->getValue('updateuser'); 209 | $updateuser_sql = rex_sql::factory(); 210 | $updateuser_sql->setQuery("SELECT name FROM rex_user WHERE login = '$updateuser_realname'"); 211 | $mail_updateuser = $updateuser_sql->getValue('name'); 212 | $mail_finaldate = $sql_aufgabe->getValue('finaldate'); 213 | $get_responseId = rex_sql::factory(); 214 | $responsibleRequest = rex_sql::factory(); 215 | $responsibleRequest->setQuery('SELECT * FROM rex_aufgaben WHERE responsible = ' .$responseId); 216 | $mail_responseId = $responsibleRequest->getValue('responsible'); 217 | 218 | 219 | if ($mail_finaldate == '') { 220 | $mail_finaldate = '--'; 221 | } 222 | 223 | $sql_status_name = rex_sql::factory(); 224 | // $sql_status_name->setDebug(); 225 | $sql_status_name->setQuery('SELECT status FROM rex_aufgaben_status WHERE id = '.$mail_status); 226 | $mail_status = $sql_status_name->getValue('status'); 227 | 228 | 229 | $sql_eigentuemer_name = rex_sql::factory(); 230 | $sql_eigentuemer_name->setQuery('SELECT * FROM rex_user WHERE id = '.$mail_eigentuemer); 231 | $mail_eigentuemer = $sql_eigentuemer_name->getValue('name'); 232 | $mail_titel = " Update zu deinen Aufgaben ".$mail_eigentuemer; 233 | $sql_eigentuemer_name->setQuery('SELECT * FROM rex_user WHERE id = ' .$responseId); 234 | 235 | // Mails senden 236 | if (count($mail_adressen) == 0){ 237 | echo "
Es wurde keine E-Mail versendet.

"; 238 | } else { 239 | foreach($mail_adressen as $email_adresse) { 240 | $mail_responseId = $sql_eigentuemer_name->getValue('name'); 241 | if($mail_responseId == $mail_eigentuemer) { 242 | 243 | // E-Mail Adresse nochmal prüfen 244 | $sql_email_pruefung = rex_sql::factory(); 245 | // $sql_email_pruefung->setDebug(); 246 | $sql_email_pruefung->setQuery('SELECT email FROM rex_user WHERE name = "'.$mail_responseId.'"'); 247 | if($checkbox == "") { 248 | $email_adresse = $sql_email_pruefung->getValue('email'); 249 | } 250 | 251 | 252 | if ($sql_email_pruefung->getRows() > 0) { 253 | 254 | $mail = new rex_mailer(); 255 | if(empty($bodyText)) { 256 | 257 | } 258 | else { 259 | $body = $bodyText; 260 | } 261 | } 262 | $text_body = $mail_titel."\n\n"; 263 | $text_body .= $mail_beschreibung."\n\n"; 264 | if($sender != "") { 265 | $mail->From = $sender; 266 | $mail->FromName = $betreffMail; 267 | } 268 | $mail->Subject = $betreff.$mail_titel; 269 | 270 | $mail->Body = $body; 271 | $mail->AltBody = $text_body; 272 | 273 | $mail->AddAddress($email_adresse); 274 | 275 | 276 | if(!$mail->Send()) { 277 | // echo "
E-Mail konnte nicht gesendet werden
"; 278 | } else { 279 | echo "
E-Mail an ".$email_adresse." wurde gesendet.
"; 280 | } 281 | } 282 | } 283 | } 284 | $mail_adressen = ''; 285 | $mail_receiver = ''; 286 | } 287 | 288 | } 289 | } 290 | 291 | } 292 | -------------------------------------------------------------------------------- /pages/kanban.php: -------------------------------------------------------------------------------- 1 | setTable('rex_aufgaben'); 4 | $qry->select('*'); 5 | 6 | if (rex_post('addtodo') == "true") 7 | { 8 | ob_end_clean(); 9 | 10 | $sql_add = rex_sql::factory(); 11 | $sql_add->setTable('rex_aufgaben'); 12 | $sql_add->setWhere('id = ' . rex_post('id')); 13 | $sql_add->setValue('title', rex_post('title')); 14 | $sql_add->setValue('description', rex_post('description')); 15 | $sql_add->setValue('category', rex_post('category')); 16 | $sql_add->setValue('responsible', rex_post('responsible')); 17 | $sql_add->setValue('updatedate', date('Y-m-d H:i:s')); 18 | $sql_add->setValue('createdate', date('Y-m-d H:i:s')); 19 | $sql_add->setValue('createuser', rex::getUser()->getName()); 20 | $sql_add->setValue('updateuser', rex::getUser()->getName()); 21 | $sql_add->setValue('observer', ''); 22 | $sql_add->setValue('finaldate', ''); 23 | $sql_add->setValue('status', rex_post('status')); 24 | $sql_add->setValue('versendet', 2); 25 | 26 | if ($sql_add->insert()) 27 | { 28 | http_response_code(200); 29 | } 30 | else 31 | { 32 | http_response_code(500); 33 | } 34 | exit; 35 | } 36 | 37 | if (rex_post('edittodo') == "true") 38 | { 39 | ob_end_clean(); 40 | 41 | $sql_edit = rex_sql::factory(); 42 | $sql_edit->setTable('rex_aufgaben'); 43 | $sql_edit->setValue('status', rex_post('status')); 44 | $sql_edit->setValue('title', rex_post('title')); 45 | $sql_edit->setValue('description', rex_post('description')); 46 | $sql_edit->setValue('category', rex_post('category')); 47 | $sql_edit->setValue('responsible', rex_post('responsible')); 48 | $sql_edit->setValue('updatedate', date('Y-m-d H:i:s')); 49 | $sql_edit->setValue('updateuser', rex::getUser()->getName()); 50 | $sql_edit->setWhere('id=' . rex_post('entry-id')); 51 | 52 | if ($sql_edit->update()) 53 | { 54 | http_response_code(200); 55 | } 56 | else 57 | { 58 | http_response_code(500); 59 | } 60 | 61 | exit; 62 | } 63 | 64 | if (rex_post('deletetodo') == "true") 65 | { 66 | ob_end_clean(); 67 | 68 | $sql_delete = rex_sql::factory(); 69 | $sql_delete->setTable('rex_aufgaben'); 70 | $sql_delete->setWhere('id = ' . rex_post('id')); 71 | 72 | if ($sql_delete->delete()) 73 | { 74 | http_response_code(200); 75 | } 76 | else 77 | { 78 | http_response_code(500); 79 | } 80 | exit; 81 | } 82 | 83 | if (rex_post('updatecategory') == "true") 84 | { 85 | ob_end_clean(); 86 | 87 | $sql_update_category = rex_sql::factory(); 88 | $sql_update_category->setTable('rex_aufgaben'); 89 | $sql_update_category->setWhere('id = ' . rex_post('id')); 90 | $sql_update_category->setValue('category', rex_post('categoryid')); 91 | $sql_update_category->update(); 92 | 93 | exit; 94 | } 95 | 96 | if (rex_post('updatestatus') == "true") 97 | { 98 | ob_end_clean(); 99 | 100 | $sql_update_status = rex_sql::factory(); 101 | $sql_update_status->setTable('rex_aufgaben'); 102 | $sql_update_status->setWhere('id = ' . rex_post('id')); 103 | $sql_update_status->setValue('status', rex_post('statusid')); 104 | $sql_update_status->update(); 105 | 106 | exit; 107 | } 108 | 109 | if (rex_post('updateprio') == "true") 110 | { 111 | ob_end_clean(); 112 | 113 | $sql_update_prio = rex_sql::factory(); 114 | $sql_update_prio->setTable('rex_aufgaben'); 115 | $sql_update_prio->setWhere('id = ' . rex_post('id')); 116 | $sql_update_prio->setValue('prio', rex_post('prioid')); 117 | $sql_update_prio->update(); 118 | 119 | exit; 120 | } 121 | ?> 122 | 123 |
124 |
125 |
126 | 127 | setDebug(); 130 | $sql_categories->setTable('rex_aufgaben_categories'); 131 | $sql_categories->select('*'); 132 | 133 | $sql_zustaendig = rex_sql::factory(); 134 | // $sql_zustaendig->setDebug(); 135 | $sql_zustaendig->setTable('rex_user'); 136 | $sql_zustaendig->select('*'); 137 | 138 | $sql_status = rex_sql::factory(); 139 | // $sql_status->setDebug(); 140 | $sql_status->setTable('rex_aufgaben_status'); 141 | $sql_status->select('*'); 142 | 143 | function getresponsible($responsibleId) 144 | { 145 | $sql_responsible = rex_sql::factory(); 146 | // $sql_responsible->setDebug(); 147 | $sql_responsible->setTable('rex_user'); 148 | $sql_responsible->setWhere('id = ' . $responsibleId); 149 | $sql_responsible->select('*'); 150 | 151 | if ($sql_responsible->getRows() >= 1) { 152 | ##taskreturn $sql_responsible->getValue('login'); 153 | return $sql_responsible->getValue('name'); 154 | } else { 155 | return '--'; 156 | } 157 | } 158 | 159 | function getStatusLinks($currentid, $itemid) 160 | { 161 | $statussql = rex_sql::factory(); 162 | // $statussql->setDebug(); 163 | $statussql->setTable(rex::getTablePrefix() . 'aufgaben_status'); 164 | $statussql->select(); 165 | 166 | $currentclass = ""; 167 | 168 | $status = "
"; 169 | $status .= "
"; 170 | for ($i = 0; $i < $statussql->getRows(); $i++) 171 | { 172 | if($currentid == $statussql->getValue('id')) 173 | { 174 | $currentclass = "current"; 175 | } 176 | else 177 | { 178 | $currentclass = ""; 179 | } 180 | 181 | if($statussql->getValue('id') == 6) 182 | { 183 | $currentclass .= " done"; 184 | } 185 | 186 | $status .= ""; 187 | $statussql->next(); 188 | } 189 | $status .= "
"; 190 | 191 | return $status; 192 | } 193 | 194 | 195 | function getPrioLinks($currentid, $itemid) 196 | { 197 | $priosql = rex_sql::factory(); 198 | // $priosql->setDebug(); 199 | $priosql->setTable(rex::getTablePrefix() . 'aufgaben'); 200 | $priosql->setTable('rex_aufgaben'); 201 | $priosql->setWhere('id = ' . $itemid); 202 | $priosql->select('*'); 203 | $prioArray = $priosql->getArray(); 204 | $currentclass = ""; 205 | 206 | $prio = "
"; 207 | $prio .= ""; 208 | for ($i = 0; $i < 3; $i++) 209 | { 210 | if ($i+1 == $prioArray[0]["prio"]) 211 | { 212 | $currentclass = "current"; 213 | } 214 | else 215 | { 216 | $currentclass = ""; 217 | } 218 | 219 | $prio .= ""; 220 | } 221 | $prio .= "
"; 222 | 223 | return $prio; 224 | } 225 | 226 | 227 | foreach ($sql_categories->getArray() as $category) 228 | { 229 | $sql_aufgaben = rex_sql::factory(); 230 | // $sql_aufgaben->setDebug(); 231 | $sql_aufgaben->setTable('rex_aufgaben'); 232 | $sql_aufgaben->setWhere('category = ' . $category["id"]); 233 | $sql_aufgaben->select('*'); 234 | $aufgaben_array = $sql_aufgaben->getArray(); 235 | $color = ""; 236 | ?> 237 | 238 |
239 |
;"> 240 | 241 | 242 | 243 |
244 |
" data-color=""> 245 |
246 | 254 |
" data-id="" data-categoryid="" data-item="" data-status="" data-responsible="" data-title="" data-id="" data-description="" data-categoryname="" > 255 | 256 | 257 | 258 |
259 |
260 | 264 |
265 | 266 |
267 | 268 | 273 |

274 | 277 |

278 |
279 |
280 | isAvailable()) { 282 | $description = str_replace('
', '', $description); 283 | $description = rex_textile::parse($description); 284 | $description = str_replace('###', ' ', $description); 285 | } 286 | if (rex_addon::get('rex_markitup')->isAvailable()) { 287 | $description = rex_markitup::parseOutput('textile', $description); 288 | } 289 | echo $description; 290 | ?> 291 |
292 |
293 | 298 |

299 | 304 |
305 | 306 | i18n('aufgaben_kanban_responsible'); ?>: 307 | 308 |
309 |
310 |
311 | 314 |
315 |
316 | 319 |
320 | 321 | 325 |
326 |
327 |
328 | 329 | 330 | 417 | 418 | 512 | 513 | 514 | 515 | 529 | 530 | 550 | -------------------------------------------------------------------------------- /assets/js/jquery.sumoselect.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jquery.sumoselect - v3.0.0 3 | * http://hemantnegi.github.io/jquery.sumoselect 4 | * 2014-04-08 5 | * 6 | * Copyright 2015 Hemant Negi 7 | * Email : hemant.frnz@gmail.com 8 | * Compressor http://refresh-sf.com/ 9 | */ 10 | 11 | (function ($) { 12 | 13 | 'namespace sumo'; 14 | $.fn.SumoSelect = function (options) { 15 | 16 | // This is the easiest way to have default options. 17 | var settings = $.extend({ 18 | placeholder: 'Anzeige filtern', // Dont change it here. 19 | csvDispCount: 2, // display no. of items in multiselect. 0 to display all. 20 | captionFormat:'{0} ausgewählt', // format of caption text. you can set your locale. 21 | captionFormatAllSelected:'Alle ausgewählt!', // format of caption text when all elements are selected. set null to use captionFormat. It will not work if there are disabled elements in select. 22 | floatWidth: 400, // Screen width of device at which the list is rendered in floating popup fashion. 23 | forceCustomRendering: false, // force the custom modal on all devices below floatWidth resolution. 24 | nativeOnDevice: ['Android', 'BlackBerry', 'iPhone', 'iPad', 'iPod', 'Opera Mini', 'IEMobile', 'Silk'], // 25 | outputAsCSV: false, // true to POST data as csv ( false for Html control array ie. default select ) 26 | csvSepChar: ',', // separation char in csv mode 27 | okCancelInMulti: false, // display ok cancel buttons in desktop mode multiselect also. 28 | triggerChangeCombined: true, // im multi select mode wether to trigger change event on individual selection or combined selection. 29 | selectAll: false, // to display select all button in multiselect mode.|| also select all will not be available on mobile devices. 30 | 31 | search: false, // to display input for filtering content. selectAlltext will be input text placeholder 32 | searchText: 'Suche...', // placeholder for search input 33 | noMatch: 'No matches for "{0}"', 34 | prefix: '', // some prefix usually the field name. eg. 'Hello' 35 | locale: ['OK', 'Abbruch', 'Alles auswählen'], // all text that is used. don't change the index. 36 | up: false // set true to open upside. 37 | }, options); 38 | 39 | var ret = this.each(function () { 40 | var selObj = this; // the original select object. 41 | if (this.sumo || !$(this).is('select')) return; //already initialized 42 | 43 | this.sumo = { 44 | E: $(selObj), //the jquery object of original select element. 45 | is_multi: $(selObj).attr('multiple'), //if its a multiple select 46 | select: '', 47 | caption: '', 48 | placeholder: '', 49 | optDiv: '', 50 | CaptionCont: '', 51 | ul:'', 52 | is_floating: false, 53 | is_opened: false, 54 | //backdrop: '', 55 | mob:false, // if to open device default select 56 | Pstate: [], 57 | 58 | createElems: function () { 59 | var O = this; 60 | O.E.wrap('
'); 61 | O.select = O.E.parent(); 62 | O.caption = $(''); 63 | O.CaptionCont = $('

').addClass('SelectBox').attr('style', O.E.attr('style')).prepend(O.caption); 64 | O.select.append(O.CaptionCont); 65 | 66 | // default turn off if no multiselect 67 | if(!O.is_multi)settings.okCancelInMulti = false 68 | 69 | if(O.E.attr('disabled')) 70 | O.select.addClass('disabled').removeAttr('tabindex'); 71 | 72 | //if output as csv and is a multiselect. 73 | if (settings.outputAsCSV && O.is_multi && O.E.attr('name')) { 74 | //create a hidden field to store csv value. 75 | O.select.append($('').attr('name', O.E.attr('name')).val(O.getSelStr())); 76 | 77 | // so it can not post the original select. 78 | O.E.removeAttr('name'); 79 | } 80 | 81 | //break for mobile rendring.. if forceCustomRendering is false 82 | if (O.isMobile() && !settings.forceCustomRendering) { 83 | O.setNativeMobile(); 84 | return; 85 | } 86 | 87 | // if there is a name attr in select add a class to container div 88 | if(O.E.attr('name')) O.select.addClass('sumo_'+O.E.attr('name')) 89 | 90 | //hide original select 91 | O.E.addClass('SumoUnder').attr('tabindex','-1'); 92 | 93 | //## Creating the list... 94 | O.optDiv = $('
'); 95 | 96 | //branch for floating list in low res devices. 97 | O.floatingList(); 98 | 99 | //Creating the markup for the available options 100 | O.ul = $('
    '); 101 | O.optDiv.append(O.ul); 102 | 103 | // Select all functionality 104 | if(settings.selectAll) O.selAll(); 105 | 106 | // search functionality 107 | if(settings.search) O.Search(); 108 | 109 | O.ul.append(O.prepItems(O.E.children())); 110 | 111 | //if multiple then add the class multiple and add OK / CANCEL button 112 | if (O.is_multi) O.multiSelelect(); 113 | 114 | O.select.append(O.optDiv); 115 | O.basicEvents(); 116 | O.selAllState(); 117 | }, 118 | 119 | prepItems: function(opts, d){ 120 | var lis = [], O=this; 121 | $(opts).each(function (i, opt) { // parsing options to li 122 | opt = $(opt); 123 | lis.push(opt.is('optgroup')? 124 | $('
    • ') 125 | .find('ul') 126 | .append(O.prepItems(opt.children(), opt[0].disabled)) 127 | .end() 128 | : 129 | O.createLi(opt, d) 130 | ); 131 | }); 132 | return lis; 133 | }, 134 | 135 | //## Creates a LI element from a given option and binds events to it 136 | //## returns the jquery instance of li (not inserted in dom) 137 | createLi: function (opt, d) { 138 | var O = this; 139 | 140 | if(!opt.attr('value'))opt.attr('value',opt.val()); 141 | // todo: remove this data val 142 | li = $('
    • ');//.data('val',opt.val()); 143 | li.data('opt', opt); // store a direct reference to option. 144 | if (O.is_multi) li.prepend(''); 145 | 146 | if (opt[0].disabled || d) 147 | li = li.addClass('disabled'); 148 | 149 | O.onOptClick(li); 150 | 151 | if (opt[0].selected) 152 | li.addClass('selected'); 153 | 154 | if (opt.attr('class')) 155 | li.addClass(opt.attr('class')); 156 | 157 | return li; 158 | }, 159 | 160 | //## Returns the selected items as string in a Multiselect. 161 | getSelStr: function () { 162 | // get the pre selected items. 163 | sopt = []; 164 | this.E.find('option:selected').each(function () { sopt.push($(this).val()); }); 165 | return sopt.join(settings.csvSepChar); 166 | }, 167 | 168 | //## THOSE OK/CANCEL BUTTONS ON MULTIPLE SELECT. 169 | multiSelelect: function () { 170 | var O = this; 171 | O.optDiv.addClass('multiple'); 172 | O.okbtn = $('

      '+settings.locale[0]+'

      ').click(function () { 173 | 174 | //if combined change event is set. 175 | if (settings.triggerChangeCombined) { 176 | 177 | //check for a change in the selection. 178 | changed = false; 179 | if (O.E.find('option:selected').length != O.Pstate.length) { 180 | changed = true; 181 | } 182 | else { 183 | O.E.find('option').each(function (i,e) { 184 | if(e.selected && O.Pstate.indexOf(i) < 0) changed = true; 185 | }); 186 | } 187 | 188 | if (changed) { 189 | O.callChange(); 190 | O.setText(); 191 | } 192 | } 193 | O.hideOpts(); 194 | }); 195 | O.cancelBtn = $('

      '+settings.locale[1]+'

      ').click(function () { 196 | O._cnbtn(); 197 | O.hideOpts(); 198 | }); 199 | O.optDiv.append($('
      ').append(O.okbtn).append(O.cancelBtn)); 200 | }, 201 | 202 | _cnbtn:function(){ 203 | var O = this; 204 | //remove all selections 205 | O.E.find('option:selected').each(function () { this.selected = false; }); 206 | O.optDiv.find('li.selected').removeClass('selected') 207 | 208 | //restore selections from saved state. 209 | for(var i = 0; i < O.Pstate.length; i++) { 210 | O.E.find('option')[O.Pstate[i]].selected = true; 211 | O.ul.find('li.opt').eq(O.Pstate[i]).addClass('selected'); 212 | } 213 | O.selAllState(); 214 | }, 215 | 216 | selAll:function(){ 217 | var O = this; 218 | if(!O.is_multi)return; 219 | O.selAll = $('

      '); 220 | O.selAll.on('click',function(){ 221 | //O.toggSelAll(!); 222 | O.selAll.toggleClass('selected'); 223 | O.optDiv.find('li.opt').not('.hidden').each(function(ix,e){ 224 | e = $(e); 225 | if(O.selAll.hasClass('selected')){ 226 | if(!e.hasClass('selected'))e.trigger('click'); 227 | } 228 | else 229 | if(e.hasClass('selected'))e.trigger('click'); 230 | }); 231 | }); 232 | 233 | O.optDiv.prepend(O.selAll); 234 | }, 235 | 236 | // search module (can be removed if not required.) 237 | Search: function(){ 238 | var O = this, 239 | cc = O.CaptionCont.addClass('search'), 240 | P = $('

      '); 241 | 242 | O.ftxt = $('') 243 | .on('click', function(e){ 244 | e.stopPropagation(); 245 | }); 246 | cc.append(O.ftxt); 247 | O.optDiv.children('ul').after(P); 248 | 249 | O.ftxt.on('keyup.sumo',function(){ 250 | var hid = O.optDiv.find('ul.options li.opt').each(function(ix,e){ 251 | e = $(e); 252 | if(e.text().toLowerCase().indexOf(O.ftxt.val().toLowerCase()) > -1) 253 | e.removeClass('hidden'); 254 | else 255 | e.addClass('hidden'); 256 | }).not('.hidden'); 257 | 258 | P.html(settings.noMatch.replace(/\{0\}/g, O.ftxt.val())).toggle(!hid.length); 259 | 260 | O.selAllState(); 261 | }); 262 | }, 263 | 264 | selAllState: function () { 265 | var O = this; 266 | if (settings.selectAll) { 267 | var sc = 0, vc = 0; 268 | O.optDiv.find('li.opt').not('.hidden').each(function (ix, e) { 269 | if ($(e).hasClass('selected')) sc++; 270 | if (!$(e).hasClass('disabled')) vc++; 271 | }); 272 | //select all checkbox state change. 273 | if (sc == vc) O.selAll.removeClass('partial').addClass('selected'); 274 | else if (sc == 0) O.selAll.removeClass('selected partial'); 275 | else O.selAll.addClass('partial')//.removeClass('selected'); 276 | } 277 | }, 278 | 279 | showOpts: function () { 280 | var O = this; 281 | if (O.E.attr('disabled')) return; // if select is disabled then retrun 282 | O.is_opened = true; 283 | O.select.addClass('open'); 284 | 285 | if(O.ftxt)O.ftxt.focus(); 286 | else O.select.focus(); 287 | 288 | // hide options on click outside. 289 | $(document).on('click.sumo', function (e) { 290 | if (!O.select.is(e.target) // if the target of the click isn't the container... 291 | && O.select.has(e.target).length === 0){ // ... nor a descendant of the container 292 | if(!O.is_opened)return; 293 | O.hideOpts(); 294 | if (settings.okCancelInMulti)O._cnbtn(); 295 | } 296 | }); 297 | 298 | if (O.is_floating) { 299 | H = O.optDiv.children('ul').outerHeight() + 2; // +2 is clear fix 300 | if (O.is_multi) H = H + parseInt(O.optDiv.css('padding-bottom')); 301 | O.optDiv.css('height', H); 302 | } 303 | 304 | O.setPstate(); 305 | }, 306 | 307 | //maintain state when ok/cancel buttons are available storing the indexes. 308 | setPstate: function(){ 309 | var O = this; 310 | if (O.is_multi && (O.is_floating || settings.okCancelInMulti)){ 311 | O.Pstate = []; 312 | // assuming that find returns elements in tree order 313 | O.E.find('option').each(function (i, e){if(e.selected) O.Pstate.push(i);}); 314 | } 315 | }, 316 | 317 | callChange:function(){ 318 | this.E.trigger('change').trigger('click'); 319 | }, 320 | 321 | hideOpts: function () { 322 | var O = this; 323 | if(O.is_opened){ 324 | O.is_opened = false; 325 | O.select.removeClass('open').find('ul li.sel').removeClass('sel'); 326 | $(document).off('click.sumo'); 327 | O.select.focus(); 328 | 329 | // clear the search 330 | if(settings.search){ 331 | O.ftxt.val(''); 332 | O.optDiv.find('ul.options li').removeClass('hidden'); 333 | O.optDiv.find('.no-match').toggle(false); 334 | } 335 | } 336 | }, 337 | setOnOpen: function () { 338 | var O = this, 339 | li = O.optDiv.find('li.opt:not(.hidden)').eq(settings.search?0:O.E[0].selectedIndex); 340 | 341 | O.optDiv.find('li.sel').removeClass('sel'); 342 | li.addClass('sel'); 343 | O.showOpts(); 344 | }, 345 | nav: function (up) { 346 | var O = this, c, 347 | s=O.ul.find('li.opt:not(.disabled, .hidden)'), 348 | sel = O.ul.find('li.opt.sel:not(.hidden)'), 349 | idx = s.index(sel); 350 | if (O.is_opened && sel.length) { 351 | 352 | if (up && idx > 0) 353 | c = s.eq(idx-1); 354 | else if(!up && idx < s.length-1 && idx > -1) 355 | c = s.eq(idx+1); 356 | else return; // if no items before or after 357 | 358 | sel.removeClass('sel'); 359 | sel = c.addClass('sel'); 360 | 361 | // setting sel item to visible view. 362 | var ul = O.ul, 363 | st = ul.scrollTop(), 364 | t = sel.position().top + st; 365 | if(t >= st + ul.height()-sel.outerHeight()) 366 | ul.scrollTop(t - ul.height() + sel.outerHeight()); 367 | if(t= settings.csvDispCount && settings.csvDispCount) { 453 | if (sels.length == O.E.find('option').length && settings.captionFormatAllSelected) { 454 | O.placeholder = settings.captionFormatAllSelected.replace(/\{0\}/g, sels.length); 455 | } else { 456 | O.placeholder = settings.captionFormat.replace(/\{0\}/g, sels.length); 457 | } 458 | 459 | break; 460 | } 461 | else O.placeholder += $(sels[i]).text() + ", "; 462 | } 463 | O.placeholder = O.placeholder.replace(/,([^,]*)$/, '$1'); //remove unexpected "," from last. 464 | } 465 | else { 466 | O.placeholder = O.E.find(':selected').not(':disabled').text(); 467 | } 468 | 469 | is_placeholder = false; 470 | 471 | if (!O.placeholder) { 472 | 473 | is_placeholder = true; 474 | 475 | O.placeholder = O.E.attr('placeholder'); 476 | if (!O.placeholder) //if placeholder is there then set it 477 | O.placeholder = O.E.find('option:disabled:selected').text(); 478 | } 479 | 480 | O.placeholder = O.placeholder ? (settings.prefix + ' ' + O.placeholder) : settings.placeholder 481 | 482 | //set display text 483 | O.caption.html(O.placeholder); 484 | O.CaptionCont.attr('title', O.placeholder); 485 | 486 | //set the hidden field if post as csv is true. 487 | csvField = O.select.find('input.HEMANT123'); 488 | if (csvField.length) csvField.val(O.getSelStr()); 489 | 490 | //add class placeholder if its a placeholder text. 491 | if (is_placeholder) O.caption.addClass('placeholder'); else O.caption.removeClass('placeholder'); 492 | return O.placeholder; 493 | }, 494 | 495 | isMobile: function () { 496 | 497 | // Adapted from http://www.detectmobilebrowsers.com 498 | var ua = navigator.userAgent || navigator.vendor || window.opera; 499 | 500 | // Checks for iOs, Android, Blackberry, Opera Mini, and Windows mobile devices 501 | for (var i = 0; i < settings.nativeOnDevice.length; i++) if (ua.toString().toLowerCase().indexOf(settings.nativeOnDevice[i].toLowerCase()) > 0) return settings.nativeOnDevice[i]; 502 | return false; 503 | }, 504 | 505 | setNativeMobile: function () { 506 | var O = this; 507 | O.E.addClass('SelectClass')//.css('height', O.select.outerHeight()); 508 | O.mob = true; 509 | O.E.change(function () { 510 | O.setText(); 511 | }); 512 | }, 513 | 514 | floatingList: function () { 515 | var O = this; 516 | //called on init and also on resize. 517 | //O.is_floating = true if window width is < specified float width 518 | O.is_floating = $(window).width() <= settings.floatWidth; 519 | 520 | //set class isFloating 521 | O.optDiv.toggleClass('isFloating', O.is_floating); 522 | 523 | //remove height if not floating 524 | if (!O.is_floating) O.optDiv.css('height', ''); 525 | 526 | //toggle class according to okCancelInMulti flag only when it is not floating 527 | O.optDiv.toggleClass('okCancelInMulti', settings.okCancelInMulti && !O.is_floating); 528 | }, 529 | 530 | //HELPERS FOR OUTSIDERS 531 | // validates range of given item operations 532 | vRange: function (i) { 533 | var O = this; 534 | opts = O.E.find('option'); 535 | if (opts.length <= i || i < 0) throw "index out of bounds" 536 | return O; 537 | }, 538 | 539 | //toggles selection on c as boolean. 540 | toggSel: function (c, i) { 541 | var O = this; 542 | if (typeof(i) === "number"){ 543 | O.vRange(i); 544 | opt = O.E.find('option')[i]; 545 | } 546 | else{ 547 | opt = O.E.find('option[value="'+i+'"]')[0]||0; 548 | } 549 | if (!opt || opt.disabled) 550 | return; 551 | 552 | if(opt.selected != c){ 553 | opt.selected = c; 554 | if(!O.mob)O.optDiv.find('ul.options li.opt').eq(i).toggleClass('selected',c); 555 | 556 | O.callChange(); 557 | O.setPstate(); 558 | O.setText(); 559 | O.selAllState(); 560 | } 561 | }, 562 | 563 | //toggles disabled on c as boolean. 564 | toggDis: function (c, i) { 565 | var O = this.vRange(i); 566 | O.E.find('option')[i].disabled = c; 567 | if(c)O.E.find('option')[i].selected = false; 568 | if(!O.mob)O.optDiv.find('ul.options li').eq(i).toggleClass('disabled', c).removeClass('selected'); 569 | O.setText(); 570 | }, 571 | 572 | // toggle disable/enable on complete select control 573 | toggSumo: function(val) { 574 | var O = this; 575 | O.enabled = val; 576 | O.select.toggleClass('disabled', val); 577 | 578 | if (val) { 579 | O.E.attr('disabled', 'disabled'); 580 | O.select.removeAttr('tabindex'); 581 | } 582 | else{ 583 | O.E.removeAttr('disabled'); 584 | O.select.attr('tabindex','0'); 585 | } 586 | 587 | return O; 588 | }, 589 | 590 | //toggles alloption on c as boolean. 591 | toggSelAll: function (c) { 592 | var O = this; 593 | O.E.find('option').each(function (ix, el) { 594 | if (O.E.find('option')[$(this).index()].disabled) return; 595 | O.E.find('option')[$(this).index()].selected = c; 596 | if (!O.mob) 597 | O.optDiv.find('ul.options li').eq($(this).index()).toggleClass('selected', c); 598 | O.setText(); 599 | }); 600 | if(!O.mob && (settings.selectAll || settings.search))O.selAll.removeClass('partial').toggleClass('selected',c); 601 | O.callChange(); 602 | O.setPstate(); 603 | }, 604 | 605 | /* outside accessibility options 606 | which can be accessed from the element instance. 607 | */ 608 | reload:function(){ 609 | var elm = this.unload(); 610 | return $(elm).SumoSelect(settings); 611 | }, 612 | 613 | unload: function () { 614 | var O = this; 615 | O.select.before(O.E); 616 | O.E.show(); 617 | 618 | if (settings.outputAsCSV && O.is_multi && O.select.find('input.HEMANT123').length) { 619 | O.E.attr('name', O.select.find('input.HEMANT123').attr('name')); // restore the name; 620 | } 621 | O.select.remove(); 622 | delete selObj.sumo; 623 | return selObj; 624 | }, 625 | 626 | //## add a new option to select at a given index. 627 | add: function (val, txt, i) { 628 | if (typeof val == "undefined") throw "No value to add" 629 | 630 | var O = this; 631 | opts=O.E.find('option') 632 | if (typeof txt == "number") { i = txt; txt = val; } 633 | if (typeof txt == "undefined") { txt = val; } 634 | 635 | opt = $("").val(val).html(txt); 636 | 637 | if (opts.length < i) throw "index out of bounds" 638 | 639 | if (typeof i == "undefined" || opts.length == i) { // add it to the last if given index is last no or no index provides. 640 | O.E.append(opt); 641 | if(!O.mob)O.ul.append(O.createLi(opt)); 642 | } 643 | else { 644 | opts.eq(i).before(opt); 645 | if(!O.mob)O.ul.find('li.opt').eq(i).before(O.createLi(opt)); 646 | } 647 | 648 | return selObj; 649 | }, 650 | 651 | //## removes an item at a given index. 652 | remove: function (i) { 653 | var O = this.vRange(i); 654 | O.E.find('option').eq(i).remove(); 655 | if(!O.mob)O.optDiv.find('ul.options li').eq(i).remove(); 656 | O.setText(); 657 | }, 658 | 659 | //## Select an item at a given index. 660 | selectItem: function (i) { this.toggSel(true, i); }, 661 | 662 | //## UnSelect an iten at a given index. 663 | unSelectItem: function (i) { this.toggSel(false, i); }, 664 | 665 | //## Select all items of the select. 666 | selectAll: function () { this.toggSelAll(true); }, 667 | 668 | //## UnSelect all items of the select. 669 | unSelectAll: function () { this.toggSelAll(false); }, 670 | 671 | //## Disable an iten at a given index. 672 | disableItem: function (i) { this.toggDis(true, i) }, 673 | 674 | //## Removes disabled an iten at a given index. 675 | enableItem: function (i) { this.toggDis(false, i) }, 676 | 677 | //## New simple methods as getter and setter are not working fine in ie8- 678 | //## variable to check state of control if enabled or disabled. 679 | enabled : true, 680 | //## Enables the control 681 | enable: function(){return this.toggSumo(false)}, 682 | 683 | //## Disables the control 684 | disable: function(){return this.toggSumo(true)}, 685 | 686 | 687 | init: function () { 688 | var O = this; 689 | O.createElems(); 690 | O.setText(); 691 | return O 692 | } 693 | 694 | }; 695 | 696 | selObj.sumo.init(); 697 | }); 698 | 699 | return ret.length == 1 ? ret[0] : ret; 700 | }; 701 | 702 | 703 | }(jQuery)); 704 | --------------------------------------------------------------------------------