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:
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>