partkeepr

fork of partkeepr
git clone https://git.e1e0.net/partkeepr.git
Log | Files | Refs | Submodules | README | LICENSE

commit 1b3a11ebe4436fde76577164addaff2b811db476
parent ab88a1cb26f5dfd873eeaa24b794823da03d6bc9
Author: Timo A. Hummel <felicitus@felicitus.org>
Date:   Sun,  8 Apr 2018 22:34:12 +0200

Added initial PartKeepr Mobile Frontend Proof of Concept

Diffstat:
Mapp/AppKernel.php | 1+
Mapp/config/config.yml | 2+-
Mapp/config/routing.yml | 5+++++
Msrc/PartKeepr/FrontendBundle/Controller/IndexController.php | 6+++++-
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Auth/LoginManager.js | 12+++++++++---
Asrc/PartKeepr/MobileFrontendBundle/Controller/IndexController.php | 18++++++++++++++++++
Asrc/PartKeepr/MobileFrontendBundle/DependencyInjection/PartKeeprFrontendExtension.php | 19+++++++++++++++++++
Asrc/PartKeepr/MobileFrontendBundle/PartKeeprMobileFrontendBundle.php | 9+++++++++
Asrc/PartKeepr/MobileFrontendBundle/Resources/public/js/PartKeeprMobile.js | 290+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/PartKeepr/MobileFrontendBundle/Resources/views/index.html.twig | 122+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10 files changed, 479 insertions(+), 5 deletions(-)

diff --git a/app/AppKernel.php b/app/AppKernel.php @@ -67,6 +67,7 @@ class AppKernel extends Kernel $bundles[] = new PartKeepr\ImportBundle\PartKeeprImportBundle(); $bundles[] = new PartKeepr\BatchJobBundle\PartKeeprBatchJobBundle(); $bundles[] = new PartKeepr\OctoPartBundle\PartKeeprOctoPartBundle(); + $bundles[] = new PartKeepr\MobileFrontendBundle\PartKeeprMobileFrontendBundle(); return array_merge($bundles, $this->getCustomBundles()); } diff --git a/app/config/config.yml b/app/config/config.yml @@ -39,7 +39,7 @@ sensio_framework_extra: assetic: debug: %kernel.debug% use_controller: false - bundles: [ PartKeeprFrontendBundle ] + bundles: [ PartKeeprFrontendBundle, PartKeeprMobileFrontendBundle ] #java: /usr/bin/java filters: cssrewrite: ~ diff --git a/app/config/routing.yml b/app/config/routing.yml @@ -38,6 +38,11 @@ PartKeeprPartBundle: type: annotation prefix: / +PartKeeprMobileFrontendBundle: + resource: "@PartKeeprMobileFrontendBundle/Controller/" + type: annotation + prefix: / + _frontend: resource: "@PartKeeprFrontendBundle/Resources/config/routing.yml" diff --git a/src/PartKeepr/FrontendBundle/Controller/IndexController.php b/src/PartKeepr/FrontendBundle/Controller/IndexController.php @@ -17,6 +17,10 @@ class IndexController extends Controller */ public function indexAction() { + return $this->render('PartKeeprFrontendBundle::index.html.twig', $this->getRenderParameters()); + } + + public function getRenderParameters () { if ($this->getParameter('partkeepr.maintenance') !== false) { $renderParams['maintenanceTitle'] = $this->getParameter('partkeepr.maintenance.title'); $renderParams['maintenanceMessage'] = $this->getParameter('partkeepr.maintenance.message'); @@ -72,7 +76,7 @@ class IndexController extends Controller $renderParams['parameters'] = $aParameters; $renderParams['debug'] = $this->get('kernel')->isDebug(); - return $this->render('PartKeeprFrontendBundle::index.html.twig', $renderParams); + return $renderParams; } public function getParameterWithDefault($name, $default) diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Auth/LoginManager.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Auth/LoginManager.js @@ -44,8 +44,11 @@ Ext.define('PartKeepr.Auth.LoginManager', { this.provider = PartKeepr.Auth.AuthenticationProvider.getAuthenticationProvider(); this.provider.on("authenticate", this.onAuthenticate, this); - this.loginDialog = Ext.create("PartKeepr.LoginDialog"); - this.loginDialog.on("login", this.onLoginDialog, this); + if (!this.config.autoLogin) + { + this.loginDialog = Ext.create("PartKeepr.LoginDialog"); + this.loginDialog.on("login", this.onLoginDialog, this); + } }, /** * Triggers the login process. If auto-login is required, directly calls authenticate(). If not, the @@ -90,7 +93,10 @@ Ext.define('PartKeepr.Auth.LoginManager', { onAuthenticate: function (success) { if (success) { - this.loginDialog.hide(); + if (!this.config.autoLogin) + { + this.loginDialog.hide(); + } this.fireEvent("login"); this.loggedIn = true; } else { diff --git a/src/PartKeepr/MobileFrontendBundle/Controller/IndexController.php b/src/PartKeepr/MobileFrontendBundle/Controller/IndexController.php @@ -0,0 +1,18 @@ +<?php + +namespace PartKeepr\MobileFrontendBundle\Controller; + +use Symfony\Component\Routing\Annotation\Route; + +class IndexController extends \PartKeepr\FrontendBundle\Controller\IndexController +{ + /** + * This is basically a copy of the PartKeepr's legacy index.php. + * + * @Route("/mobile/") + */ + public function indexAction() + { + return $this->render('PartKeeprMobileFrontendBundle::index.html.twig', $this->getRenderParameters()); + } +} diff --git a/src/PartKeepr/MobileFrontendBundle/DependencyInjection/PartKeeprFrontendExtension.php b/src/PartKeepr/MobileFrontendBundle/DependencyInjection/PartKeeprFrontendExtension.php @@ -0,0 +1,18 @@ +<?php +namespace PartKeepr\MobileFrontendBundle\DependencyInjection; + +use Symfony\Component\Config\FileLocator; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; + +class PartKeeprMobileFrontendExtension extends Extension +{ + /** + * {@inheritdoc} + */ + public function load(array $configs, ContainerBuilder $container) + { + $loader = new Loader\XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); + } +}+ \ No newline at end of file diff --git a/src/PartKeepr/MobileFrontendBundle/PartKeeprMobileFrontendBundle.php b/src/PartKeepr/MobileFrontendBundle/PartKeeprMobileFrontendBundle.php @@ -0,0 +1,9 @@ +<?php + +namespace PartKeepr\MobileFrontendBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class PartKeeprMobileFrontendBundle extends Bundle +{ +} diff --git a/src/PartKeepr/MobileFrontendBundle/Resources/public/js/PartKeeprMobile.js b/src/PartKeepr/MobileFrontendBundle/Resources/public/js/PartKeeprMobile.js @@ -0,0 +1,289 @@ +Ext.application({ + name: 'PartKeepr', + + launch: function () { + Ext.get("loader-wrapper").hide(); + + PartKeepr.application = this; + + var authenticationProvider = Ext.create(window.parameters.authentication_provider); + PartKeepr.Auth.AuthenticationProvider.setAuthenticationProvider(authenticationProvider); + + var config = {}; + + if (window.parameters.autoLoginUsername) { + config.autoLogin = true; + config.autoLoginUsername = window.parameters.autoLoginUsername; + config.autoLoginPassword = window.parameters.autoLoginPassword; + } + + this.loginManager = Ext.create("PartKeepr.Auth.LoginManager", config); + this.loginManager.on("login", this.onLogin, this); + this.loginManager.on("logout", this.onLogout, this); + this.loginManager.login(); + }, + + test: function () { + var config = { + autoLoad: true, + model: "PartKeepr.PartBundle.Entity.Part", + autoSync: false, // Do not change. If true, new (empty) records would be immediately committed to the database. + remoteFilter: true, + remoteSort: true, + pageSize: 15 + }; + + var store = Ext.create("Ext.data.Store", config); + + Ext.create('Ext.grid.Grid', { + title: 'PartKeepr: Parts List', + + store: store, + + columns: [ + { + text: i18n("Name"), + dataIndex: 'name', + flex: 1, + minWidth: 150 + }, { + text: i18n("Description"), + dataIndex: 'description', + flex: 2, + minWidth: 150 + }, { + text: i18n("Storage Location"), + dataIndex: 'storageLocation.name' + } + ], + + layout: 'fit', + fullscreen: true + }); + }, + getLoginManager: function () + { + return this.loginManager; + }, + /** + * Queries for a specific user preference. Returns either the value or a default value if + * the preference was not found. + * @param key The key to query + * @param defaultValue A default value to return (optional) + * @returns the key value, or defaultValue if preference key was not found + */ + getUserPreference: function (key, defaultValue) + { + var record = this.userPreferenceStore.findRecord("preferenceKey", key); + + if (record) { + var value = record.get("preferenceValue"); + var decodedValue = Ext.decode(value, true); + + if (decodedValue === null) { + return value; + } else { + return decodedValue; + } + } else { + return (typeof defaultValue == "undefined") ? null : defaultValue; + } + }, + /** + * Sets a specific user preference. Directly commits the change to the server. + * + * @param key The key to set + * @param value The value to set + */ + setUserPreference: function (key, value) + { + var record = this.userPreferenceStore.findRecord("preferenceKey", key); + value = Ext.encode(value); + + if (record) { + if (record.get("preferenceValue") != value) { + record.set("preferenceValue", value); + record.save(); + } + } else { + var j = new PartKeepr.AuthBundle.Entity.UserPreference(); + j.set("preferenceKey", key); + j.set("preferenceValue", value); + j.save(); + this.userPreferenceStore.add(j); + } + }, + getUserPreferenceStore: function () + { + return this.userPreferenceStore; + }, + + /** + * Handles the login function. Initializes the part manager window, + * enables the menu bar and creates the stores+loads them. + */ + onLogin: function () { + this.createGlobalStores(); + + var initialUserPreferences = Ext.decode(this.getLoginManager().getUser().get("initialUserPreferences")); + + var records = this.getUserPreferenceStore().getProxy().getReader().read(initialUserPreferences); + + this.getUserPreferenceStore().loadRecords(records.records); + + this.test(); + }, + + onLogout: function () + { + this.menuBar.disable(); + this.centerPanel.removeAll(true); + this.getStatusbar().setDisconnected(); + + Ext.TaskManager.stop(this.unacknowledgedNoticesTask); + }, + + createGlobalStores: function () + { + this.footprintStore = Ext.create("Ext.data.Store", + { + model: 'PartKeepr.FootprintBundle.Entity.Footprint', + pageSize: 99999999, + autoLoad: true + }); + + this.siPrefixStore = Ext.create("Ext.data.Store", + { + model: 'PartKeepr.SiPrefixBundle.Entity.SiPrefix', + pageSize: 99999999, + autoLoad: true + }); + + this.currencyStore = Ext.create("PartKeepr.Data.Store.CurrencyStore", { + autoLoad: true + }); + + this.distributorStore = Ext.create("Ext.data.Store", + { + model: 'PartKeepr.DistributorBundle.Entity.Distributor', + pageSize: 99999999, + autoLoad: true + }); + + this.manufacturerStore = Ext.create("Ext.data.Store", + { + model: 'PartKeepr.ManufacturerBundle.Entity.Manufacturer', + pageSize: 99999999, + autoLoad: true + }); + + this.partUnitStore = Ext.create("Ext.data.Store", + { + model: 'PartKeepr.PartBundle.Entity.PartMeasurementUnit', + pageSize: 99999999, + autoLoad: true + }); + + this.unitStore = Ext.create("Ext.data.Store", + { + model: 'PartKeepr.UnitBundle.Entity.Unit', + pageSize: 99999999, + autoLoad: true + }); + + this.userStore = Ext.create("Ext.data.Store", + { + model: 'PartKeepr.AuthBundle.Entity.User', + pageSize: 99999999, + autoLoad: true + }); + + this.userPreferenceStore = Ext.create("PartKeepr.data.store.UserPreferenceStore", + { + model: 'PartKeepr.AuthBundle.Entity.UserPreference', + autoLoad: false + }); + + + }, + getSystemPreferenceStore: function () + { + return this.systemPreferenceStore; + }, + /** + * Queries for a specific system preference. Returns either the value or a default value if + * the preference was not found. + * @param key The key to query + * @param defaultValue A default value to return (optional) + * @returns the key value, or defaultValue if preference key was not found + */ + getSystemPreference: function (key, defaultValue) + { + if (this.systemPreferenceStore === undefined) { + return defaultValue; + } + var record = this.systemPreferenceStore.findRecord("preferenceKey", key); + + if (record) { + var value = record.get("preferenceValue"); + var decodedValue = Ext.decode(value, true); + + if (decodedValue === null) { + return value; + } else { + return decodedValue; + } + } else { + return (typeof defaultValue == "undefined") ? null : defaultValue; + } + }, + /** + * Sets a specific system preference. Directly commits the change to the server. + * + * @param key The key to set + * @param value The value to set + */ + setSystemPreference: function (key, value) + { + var record = this.systemPreferenceStore.findRecord("preferenceKey", key); + value = Ext.encode(value); + + if (record) { + if (record.get("preferenceValue") != value) { + record.set("preferenceValue", value); + record.save(); + } + } else { + var j = new PartKeepr.SystemPreferenceBundle.Entity.SystemPreference(); + j.set("preferenceKey", key); + j.set("preferenceValue", value); + j.save(); + this.systemPreferenceStore.add(j); + } + }, +}); + +PartKeepr.getBasePath = function () +{ + var href = document.getElementsByTagName('base')[0].href; + + + if (href.substr(-2) === '//') { + return href.substr(0, href.length - 2); + } + + if (href.substr(-1) === '/') { + return href.substr(0, href.length - 1); + } + + return href; +}; + +/** + * <p>This static method returns the instance of the application.</p> + * @return {PartKeepr} The application + */ +PartKeepr.getApplication = function () +{ + return PartKeepr.application; +};+ \ No newline at end of file diff --git a/src/PartKeepr/MobileFrontendBundle/Resources/views/index.html.twig b/src/PartKeepr/MobileFrontendBundle/Resources/views/index.html.twig @@ -0,0 +1,122 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> + <title>PartKeepr</title> + + <base href="{{ app.request.getBaseURL() }}"/> + + {% set themes = {"classic": "Classic", "crisp":"Crisp", "crisp-touch": "Crisp Touch", "gray":"Gray", "neptune": "Neptune", "neptune-touch": "Neptune Touch", "triton": "Triton", "aria": "Aria"} %} + {% set defaultTheme = "classic" %} + + {% set themeUri %}js/packages/extjs6/build/classic/theme-{{ defaultTheme }}/resources/theme-{{ defaultTheme }}-all.css{% endset %} + {% set themeUxUri %}js/packages/extjs6/build/packages/ux/classic/{{ defaultTheme }}/resources/ux-all.css{% endset %} + + <link id="theme" rel="stylesheet" href="{{ asset(themeUri) }}"/> + <link id="themeUx" rel="stylesheet" href="{{ asset(themeUxUri) }}"/> + + <!-- Include the ExtJS CSS Theme --> + {% stylesheets + filter='cssrewrite' + 'js/packages/extjs6/build/modern/theme-triton/resources/theme-triton-all.css' + 'atelierspierrot/famfamfam-silk-sprite/silk-icons-sprite.css' + 'spritesheets/fugue-16.css' + 'spritesheets/partkeepr.css' + 'bundles/partkeeprfrontend/css/PartKeepr.css' %} + <link rel="stylesheet" href="{{ asset_url }}"/> + {% endstylesheets %} + + {% image '@PartKeeprFrontendBundle/Resources/public/images/favicon.ico' %} + <link rel="icon" href="{{ asset_url }}"/> + {% endimage %} + + {% if debug %} + {% javascripts output='js/compiled/extjs.js' + 'js/packages/extjs6/build/ext-modern-all-debug.js' + %} + <script type="text/javascript" src="{{ asset_url }}"></script> + {% endjavascripts %} + {% else %} + {% javascripts output='js/compiled/extjs.js' + 'js/packages/extjs6/build/ext-modern-all.js' + %} + <script type="text/javascript" src="{{ asset_url }}"></script> + {% endjavascripts %} + + {% endif %} + {% javascripts output='js/compiled/main.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/CallActions.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/field/Array.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/HydraModel.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/HydraField.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/HydraTreeModel.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/store/ModelStore.js' + '@PartKeeprFrontendBundle/Resources/public/js/ExtJS/Bugfixes/Ext.form.field.Checkbox.EXTJS-21886.js' + '@PartKeeprFrontendBundle/Resources/public/js/ExtJS/Enhancements/Ext.view.Table-renderCell.js' + '@PartKeeprFrontendBundle/Resources/public/js/ExtJS/Enhancements/Ext.data.field.Date-ISO8601.js' %} + <script type="text/javascript" src="{{ asset_url }}"></script> + + {% endjavascripts %} + + + + + + {% javascripts output='js/compiled/models.js' + 'bundles/doctrinereflection/*' %} + <script type="text/javascript" src="{{ asset_url }}"></script> + {% endjavascripts %} + + {% javascripts output='js/compiled/main2.js' + '@PartKeeprFrontendBundle/Resources/public/js/ExtJS/Enhancements/Ext.data.Store.getFieldValue.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/i18n.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/store/CurrencyStore.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/ReflectionFieldTreeModel.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/store/OperatorStore.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Blob.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/FileSaver.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Filter.js' + '@PartKeeprFrontendBundle/Resources/public/js/Components/Auth/LoginManager.js' + '@PartKeeprFrontendBundle/Resources/public/js/Components/Widgets/PreferencePlugin.js' + '@PartKeeprFrontendBundle/Resources/public/js/Components/Auth/AuthenticationProvider.js' + '@PartKeeprFrontendBundle/Resources/public/js/Components/Auth/HTTPBasicAuthenticationProvider.js' + '@PartKeeprFrontendBundle/Resources/public/js/Components/Auth/WSSEAuthenticationProvider.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/store/UserProvidersStore.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/store/UserPreferenceStore.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Crypto/isaac.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Crypto/bcrypt.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Crypto/core.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Crypto/x64-core.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Crypto/sha512.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Crypto/sha1.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/Crypto/enc-base64.js' + '@PartKeeprFrontendBundle/Resources/public/js/ExtJS/Bugfixes/Ext.data.Model-EXTJS-15037.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/JsonWithAssociationsWriter.js' + '@PartKeeprMobileFrontendBundle/Resources/public/js/PartKeeprMobile.js' + '@PartKeeprFrontendBundle/Resources/public/js/compat.js' + '@PartKeeprFrontendBundle/Resources/public/js/Util/ServiceCall.js' + '@PartKeeprFrontendBundle/Resources/public/js/org.jerrymouse.util.locale/locale.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/HydraException.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/HydraProxy.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/HydraReader.js' + '@PartKeeprFrontendBundle/Resources/public/js/Data/HydraTreeReader.js' + '@PartKeeprFrontendBundle/Resources/public/js/Actions/BaseAction.js' + '@PartKeeprFrontendBundle/Resources/public/js/Actions/LogoutAction.js' + '@PartKeeprFrontendBundle/Resources/public/js/Models/Message.js' + '@PartKeeprFrontendBundle/Resources/public/js/php.default.min.js' %} + <script type="text/javascript" src="{{ asset_url }}"></script> + {% endjavascripts %} +</head> +<body> +<div id="loader-wrapper"> + <div id="loader-logo"></div> + <div id="loader"></div> + <div id="loader-message"></div> +</div> +<script type="text/javascript"> + window.parameters = {{ parameters|json_encode|raw }}; +</script> +</body> +</html>