diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 878b6c6..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,25 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file, in reverse chronological order by release. - -## 1.0.0 - TBD - -### Added - -- Its a composer package now - -### Changed - -- 100% of 0.9.x Codebase - -### Deprecated - -- 100% of 0.9.x Codebase - -### Removed - -- 100% of 0.9.x Codebase - -### Fixed - -- Removed dependencies diff --git a/composer.json b/composer.json index c4a2581..6fa5b44 100644 --- a/composer.json +++ b/composer.json @@ -8,6 +8,7 @@ "mvc", "project", "oneplace", + "oneplace-module", "framework" ], "require-dev": { diff --git a/config/module.config.php b/config/module.config.php index 212defb..e7be104 100644 --- a/config/module.config.php +++ b/config/module.config.php @@ -61,4 +61,16 @@ 'project' => __DIR__ . '/../view', ], ], + + # Translator + 'translator' => [ + 'locale' => 'de_DE', + 'translation_file_patterns' => [ + [ + 'type' => 'gettext', + 'base_dir' => __DIR__ . '/../language', + 'pattern' => '%s.mo', + ], + ], + ], ]; diff --git a/data/createmodulefromskeleton.ps1 b/data/createmodulefromskeleton.ps1 deleted file mode 100644 index d1f6127..0000000 --- a/data/createmodulefromskeleton.ps1 +++ /dev/null @@ -1,6 +0,0 @@ -$sModuleName = "Article" -$sModuleKey = "article" -$sTargetDir = "C:\Users\Praesidiarius\PhpstormProjects\OS\PLC_X_Article_NoGIT" - -# Copy Project -Copy-Item -Path "..\*" -Destination "$sTargetDir" -recurse -Force \ No newline at end of file diff --git a/data/install.sql b/data/install.sql index 3418b4c..90fb55b 100644 --- a/data/install.sql +++ b/data/install.sql @@ -29,7 +29,8 @@ INSERT INTO `permission` (`permission_key`, `module`, `label`, `nav_label`, `nav -- -- Form -- -INSERT INTO `core_form` (`form_key`, `label`) VALUES ('project-single', 'Project'); +INSERT INTO `core_form` (`form_key`, `label`, `entity_class`, `entity_tbl_class`) VALUES +('project-single', 'Project', 'OnePlace\\Project\\Model\\Project', 'OnePlace\\Project\\Model\\ProjectTable'); -- -- Index List @@ -56,4 +57,11 @@ INSERT INTO `core_form_button` (`Button_ID`, `label`, `icon`, `title`, `href`, ` INSERT INTO `core_form_field` (`Field_ID`, `type`, `label`, `fieldkey`, `tab`, `form`, `class`, `url_view`, `url_ist`, `show_widget_left`, `allow_clear`, `readonly`, `tbl_cached_name`, `tbl_class`, `tbl_permission`) VALUES (NULL, 'text', 'Name', 'label', 'project-base', 'project-single', 'col-md-3', '/project/view/##ID##', '', 0, 1, 0, '', '', ''); +-- +-- Default Widgets +-- +INSERT INTO `core_widget` (`Widget_ID`, `widget_name`, `label`, `permission`) VALUES +(NULL, 'project_dailystats', 'Project - Daily Stats', 'index-Project\\Controller\\ProjectController'), +(NULL, 'project_taginfo', 'Project - Tag Info', 'index-Project\\Controller\\ProjectController'); + COMMIT; \ No newline at end of file diff --git a/docs/book/index.md b/docs/book/index.md deleted file mode 100644 index e69de29..0000000 diff --git a/docs/book/quick-start.md b/docs/book/quick-start.md deleted file mode 100644 index dda57e9..0000000 --- a/docs/book/quick-start.md +++ /dev/null @@ -1,28 +0,0 @@ -# Quick Start - -Now that you have basic knowledge of oneplace, we'll show you the easy way to get started. - -## Install onePlace Project - -The easiest way to get started is to install the project module via -Composer. - -If you have not yet done so, [install Composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-osx). - -Go to the directory, where you installed oneplace core and run: - -```bash -$ composer require oneplace/oneplace-project -``` - -## Setup -Open the browser and login to your oneplace app. - -Go to /update - -You will see that a new module is detected and it needs db install. - -click "Update" - -now you have the module enabled and active. you can now add new fields / tabs -and manage permissions with the user module \ No newline at end of file diff --git a/language/de_DE.mo b/language/de_DE.mo new file mode 100644 index 0000000..7ef8e49 Binary files /dev/null and b/language/de_DE.mo differ diff --git a/language/de_DE.po b/language/de_DE.po new file mode 100644 index 0000000..5d21779 --- /dev/null +++ b/language/de_DE.po @@ -0,0 +1,68 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2019-02-13 18:38+0100\n" +"PO-Revision-Date: 2020-01-30 18:54+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.2.4\n" +"X-Poedit-Basepath: .\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: de_DE\n" + +msgid "Model" +msgstr "Modell" + +msgid "Coolant" +msgstr "Kühlmittel" + +msgid "Internal" +msgstr "Intern" + +msgid "State" +msgstr "Status" + +msgid "Year of Construction" +msgstr "Baujahr" + +msgid "Origin" +msgstr "Ursprungsland" + +msgid "Categories" +msgstr "Kategorien" + +msgid "Condition" +msgstr "Zustand" + +msgid "Owner" +msgstr "Eigentümer" + +msgid "Loadbase" +msgstr "Frachtbasis" + +msgid "Specialaddons" +msgstr "Spezialzubehör" + +msgid "Description" +msgstr "Beschreibung" + +msgid "Created" +msgstr "Erstellt" + +msgid "Last Edited" +msgstr "Zuletzt bearbeitet" + +msgid "Edit Project" +msgstr "Project bearbeiten" + +msgid "Add Project" +msgstr "Project erfassen" + +msgid "Dates" +msgstr "Daten" + +msgid "Images" +msgstr "Bilder" diff --git a/language/en_US.mo b/language/en_US.mo new file mode 100644 index 0000000..b3f03cd Binary files /dev/null and b/language/en_US.mo differ diff --git a/language/en_US.po b/language/en_US.po new file mode 100644 index 0000000..e22de4b --- /dev/null +++ b/language/en_US.po @@ -0,0 +1,20 @@ +msgid "" +msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: 2019-02-13 18:38+0100\n" +"PO-Revision-Date: 2020-01-30 18:55+0100\n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Poedit 2.2.4\n" +"X-Poedit-Basepath: .\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Language: en_US\n" + +msgid "Testmodell" +msgstr "Testmodel" + +msgid "Neue Location" +msgstr "New Location" diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index 4e0b24b..0000000 --- a/mkdocs.yml +++ /dev/null @@ -1,15 +0,0 @@ -docs_dir: docs/book -site_dir: docs/html -nav: - - Home: index.md - - Introduction: intro.md - - 'Quick Start': quick-start.md - - Reference: - - 'Dynamic Fields': dynamic-fields.md - - Examples: examples.md -site_name: oneplace-project -site_description: "onePlace Application Project Module" -repo_url: 'https://github.com/OnePlc/PLC_X_Project' -theme: readthedocs -extra: - project: onePlc \ No newline at end of file diff --git a/src/Controller/ApiController.php b/src/Controller/ApiController.php index ec55452..3bf5a30 100644 --- a/src/Controller/ApiController.php +++ b/src/Controller/ApiController.php @@ -21,6 +21,7 @@ use OnePlace\Project\Model\ProjectTable; use Laminas\View\Model\ViewModel; use Laminas\Db\Adapter\AdapterInterface; +use Zend\I18n\Translator\Translator; class ApiController extends CoreController { /** @@ -67,7 +68,46 @@ public function indexAction() { public function listAction() { $this->layout('layout/json'); + # Check license + if(!$this->checkLicense('project')) { + $aReturn = ['state'=>'error','message'=>'no valid license for project found']; + echo json_encode($aReturn); + return false; + } + + # Set default values $bSelect2 = true; + $sListLabel = 'label'; + + # Get list mode from query + if(isset($_REQUEST['listmode'])) { + if($_REQUEST['listmode'] == 'entity') { + $bSelect2 = false; + } + } + + # get list label from query + if(isset($_REQUEST['listlabel'])) { + $sListLabel = $_REQUEST['listlabel']; + } + + # get list label from query + $sLang = 'en_US'; + if(isset($_REQUEST['lang'])) { + $sLang = $_REQUEST['lang']; + } + + // translating system + $translator = new Translator(); + $aLangs = ['en_US','de_DE']; + foreach($aLangs as $sLoadLang) { + if(file_exists(__DIR__.'/../../../oneplace-translation/language/'.$sLoadLang.'.mo')) { + $translator->addTranslationFile('gettext', __DIR__.'/../../../oneplace-translation/language/'.$sLang.'.mo', 'project', $sLoadLang); + } + } + + $translator->setLocale($sLang); + /** * todo: enforce to use /api/contact instead of /contact/api so we can do security checks in main api controller @@ -79,16 +119,94 @@ public function listAction() { } **/ + # Init Item List for Response $aItems = []; + $aFields = $this->getFormFields('project-single'); + $aFieldsByKey = []; + # fields are sorted by tab , we need an index with all fields + foreach($aFields as $oField) { + $aFieldsByKey[$oField->fieldkey] = $oField; + } + + # only allow form fields as list labels + if(!array_key_exists($sListLabel,$aFieldsByKey)) { + $aReturn = [ + 'state'=>'error', + 'results' => [], + 'message' => 'invalid list label', + ]; + + # Print List with all Entities + echo json_encode($aReturn); + return false; + } + # Get All Project Entities from Database $oItemsDB = $this->oTableGateway->fetchAll(false); if(count($oItemsDB) > 0) { + # Loop all items foreach($oItemsDB as $oItem) { + + # Output depending on list mode if($bSelect2) { - $aItems[] = ['id'=>$oItem->getID(),'text'=>$oItem->getLabel()]; + $sVal = null; + # get value for list label field + switch($aFieldsByKey[$sListLabel]->type) { + case 'select': + $oTag = $oItem->getSelectField($aFieldsByKey[$sListLabel]->fieldkey); + if($oTag) { + $sVal = $oTag->getLabel(); + } + break; + case 'text': + case 'date': + case 'textarea': + $sVal = $oItem->getTextField($aFieldsByKey[$sListLabel]->fieldkey); + break; + default: + break; + } + $aItems[] = ['id'=>$oItem->getID(),'text'=>$sVal]; } else { - $aItems[] = $oItem; + # Init public item + $aPublicItem = []; + + # add all fields to item + foreach($aFields as $oField) { + switch($oField->type) { + case 'multiselect': + # get selected + $oTags = $oItem->getMultiSelectField($oField->fieldkey); + $aTags = []; + foreach($oTags as $oTag) { + $aTags[] = ['id'=>$oTag->id,'label'=>$translator->translate($oTag->text,'project',$sLang)]; + } + $aPublicItem[$oField->fieldkey] = $aTags; + break; + case 'select': + # get selected + $oTag = $oItem->getSelectField($oField->fieldkey); + if($oTag) { + if (property_exists($oTag, 'tag_value')) { + $aPublicItem[$oField->fieldkey] = ['id' => $oTag->id, 'label' => $translator->translate($oTag->tag_value,'project',$sLang)]; + } else { + $aPublicItem[$oField->fieldkey] = ['id' => $oTag->getID(), 'label' => $translator->translate($oTag->getLabel(),'project',$sLang)]; + } + } + break; + case 'text': + case 'date': + case 'textarea': + $aPublicItem[$oField->fieldkey] = $translator->translate($oItem->getTextField($oField->fieldkey),'project',$sLang); + break; + default: + break; + } + } + + # add item to list + $aItems[] = $aPublicItem; } } @@ -118,6 +236,13 @@ public function listAction() { public function getAction() { $this->layout('layout/json'); + # Check license + if(!$this->checkLicense('project')) { + $aReturn = ['state'=>'error','message'=>'no valid license for project found']; + echo json_encode($aReturn); + return false; + } + # Get Project ID from route $iItemID = $this->params()->fromRoute('id', 0); diff --git a/src/Controller/SkeletonController.php b/src/Controller/ProjectController.php similarity index 88% rename from src/Controller/SkeletonController.php rename to src/Controller/ProjectController.php index 6af2a0a..a828a01 100644 --- a/src/Controller/SkeletonController.php +++ b/src/Controller/ProjectController.php @@ -62,6 +62,12 @@ public function indexAction() { # Set Layout based on users theme $this->setThemeBasedLayout('project'); + # Check license + if(!$this->checkLicense('project')) { + $this->flashMessenger()->addErrorMessage('You have no active license for project'); + $this->redirect()->toRoute('home'); + } + # Add Buttons for breadcrumb $this->setViewButtons('project-index'); @@ -95,6 +101,12 @@ public function addAction() { # Set Layout based on users theme $this->setThemeBasedLayout('project'); + # Check license + if(!$this->checkLicense('project')) { + $this->flashMessenger()->addErrorMessage('You have no active license for project'); + $this->redirect()->toRoute('home'); + } + # Get Request to decide wether to save or display form $oRequest = $this->getRequest(); @@ -149,6 +161,12 @@ public function editAction() { # Set Layout based on users theme $this->setThemeBasedLayout('project'); + # Check license + if(!$this->checkLicense('project')) { + $this->flashMessenger()->addErrorMessage('You have no active license for project'); + $this->redirect()->toRoute('home'); + } + # Get Request to decide wether to save or display form $oRequest = $this->getRequest(); @@ -199,8 +217,11 @@ public function editAction() { $this->layout('layout/json'); + # Parse Form Data + $aFormData = $this->parseFormData($_REQUEST); + # Save Multiselect - $this->updateMultiSelectFields($_REQUEST,$oProject,'project-single'); + $this->updateMultiSelectFields($aFormData,$oProject,'project-single'); # Log Performance in DB $aMeasureEnd = getrusage(); @@ -221,6 +242,12 @@ public function viewAction() { # Set Layout based on users theme $this->setThemeBasedLayout('project'); + # Check license + if(!$this->checkLicense('project')) { + $this->flashMessenger()->addErrorMessage('You have no active license for project'); + $this->redirect()->toRoute('home'); + } + # Get Project ID from URL $iProjectID = $this->params()->fromRoute('id', 0); diff --git a/src/Model/Skeleton.php b/src/Model/Project.php similarity index 100% rename from src/Model/Skeleton.php rename to src/Model/Project.php diff --git a/src/Model/SkeletonTable.php b/src/Model/ProjectTable.php similarity index 71% rename from src/Model/SkeletonTable.php rename to src/Model/ProjectTable.php index a666976..dd4f111 100644 --- a/src/Model/SkeletonTable.php +++ b/src/Model/ProjectTable.php @@ -43,12 +43,31 @@ public function __construct(TableGateway $tableGateway) { * Fetch All Project Entities based on Filters * * @param bool $bPaginated + * @param array $aWhere * @return Paginator Paginated Table Connection * @since 1.0.0 */ - public function fetchAll($bPaginated = false) { + public function fetchAll($bPaginated = false,$aWhere = []) { $oSel = new Select($this->oTableGateway->getTable()); + # Build where + $oWh = new Where(); + foreach(array_keys($aWhere) as $sWh) { + $bIsLike = stripos($sWh,'-like'); + if($bIsLike === false) { + + } else { + # its a like + $oWh->like(substr($sWh,0,strlen($sWh)-strlen('-like')),$aWhere[$sWh].'%'); + } + } + if(array_key_exists('multi_tag',$aWhere)) { + $oSel->join(['category_tag'=>'core_entity_tag_entity'],'category_tag.entity_idfs = article.Article_ID'); + $oWh->equalTo('category_tag.entity_tag_idfs',$aWhere['multi_tag']); + $oWh->like('category_tag.entity_type',explode('-',$this->sSingleForm)[0]); + } + $oSel->where($oWh); + # Return Paginator or Raw ResultSet based on selection if ($bPaginated) { # Create result set for user entity @@ -77,12 +96,13 @@ public function fetchAll($bPaginated = false) { * Get Project Entity * * @param int $id + * @param string $sKey custom key * @return mixed * @since 1.0.0 */ - public function getSingle($id) { + public function getSingle($id,$sKey = 'Project_ID') { $id = (int) $id; - $rowset = $this->oTableGateway->select(['Project_ID' => $id]); + $rowset = $this->oTableGateway->select([$sKey => $id]); $row = $rowset->current(); if (! $row) { throw new \RuntimeException(sprintf( @@ -143,4 +163,23 @@ public function saveSingle(Project $oProject) { return $id; } + + /** + * Generate daily stats for project + * + * @since 1.0.5 + */ + public function generateDailyStats() { + # get all projects + $iTotal = count($this->fetchAll(false)); + # get newly created projects + $iNew = count($this->fetchAll(false,['created_date-like'=>date('Y-m-d',time())])); + + # add statistics + CoreController::$aCoreTables['core-statistic']->insert([ + 'stats_key'=>'project-daily', + 'data'=>json_encode(['new'=>$iNew,'total'=>$iTotal]), + 'date'=>date('Y-m-d H:i:s',time()), + ]); + } } \ No newline at end of file diff --git a/src/Module.php b/src/Module.php index 6b5d73f..95c8897 100644 --- a/src/Module.php +++ b/src/Module.php @@ -23,15 +23,15 @@ use Laminas\Session\Config\StandardConfig; use Laminas\Session\SessionManager; use Laminas\Session\Container; +use Application\Controller\CoreController; class Module { /** * Module Version * - * @since 1.0.5 + * @since 1.0.0 */ - const VERSION = '1.0.5'; - + const VERSION = '1.0.0'; /** * Load module config file * diff --git a/test/Controller/SkeletonControllerTest.php b/test/Controller/ProjectControllerTest.php similarity index 100% rename from test/Controller/SkeletonControllerTest.php rename to test/Controller/ProjectControllerTest.php diff --git a/view/layout/skeleton-default.phtml b/view/layout/skeleton-default.phtml deleted file mode 100644 index db080ce..0000000 --- a/view/layout/skeleton-default.phtml +++ /dev/null @@ -1,67 +0,0 @@ -= $this->doctype() ?> - -
- - = $this->headTitle('Project - onePlace X - RC 1')->setSeparator(' - ')->setAutoEscape(false) ?> - - = $this->headMeta() - ->appendName('viewport', 'width=device-width, initial-scale=1.0') - ->appendHttpEquiv('X-UA-Compatible', 'IE=edge') - ?> - - - = $this->headLink(['rel' => 'shortcut icon', 'type' => 'image/vnd.microsoft.icon', 'href' => $this->basePath() . '/img/favicon.ico']) - ->prependStylesheet($this->basePath('css/style.css')) - ->prependStylesheet($this->basePath('vendor/jquery-ui/jquery-uia.min.css')) - ->prependStylesheet($this->basePath('vendor/fontawesome/css/all.min.css')) - ->prependStylesheet($this->basePath('css/bootstrap.min.css')) - ?> - - - = $this->inlineScript() - ->prependFile($this->basePath('js/listener.js')) - ->prependFile($this->basePath('vendor/jquery-ui/jquery-ui.min.js')) - ->prependFile($this->basePath('js/bootstrap.min.js')) - ->prependFile($this->basePath('js/jquery-3.4.1.min.js')) - ?> - - - -