aboutsummaryrefslogtreecommitdiffhomepage
path: root/main/app/sprinkles/extend-user
diff options
context:
space:
mode:
Diffstat (limited to 'main/app/sprinkles/extend-user')
-rwxr-xr-xmain/app/sprinkles/extend-user/.gitignore3
-rwxr-xr-xmain/app/sprinkles/extend-user/README.md29
-rwxr-xr-xmain/app/sprinkles/extend-user/composer.json22
-rwxr-xr-xmain/app/sprinkles/extend-user/routes/member.php7
-rwxr-xr-xmain/app/sprinkles/extend-user/schema/requests/user/create.yaml86
-rwxr-xr-xmain/app/sprinkles/extend-user/schema/requests/user/edit-info.yaml50
-rwxr-xr-xmain/app/sprinkles/extend-user/src/Controller/MemberController.php123
-rwxr-xr-xmain/app/sprinkles/extend-user/src/Database/Migrations/v400/MembersTable.php34
-rwxr-xr-xmain/app/sprinkles/extend-user/src/Database/Models/Member.php124
-rwxr-xr-xmain/app/sprinkles/extend-user/src/Database/Models/MemberAux.php20
-rwxr-xr-xmain/app/sprinkles/extend-user/src/Database/Scopes/MemberAuxScope.php36
-rwxr-xr-xmain/app/sprinkles/extend-user/src/ServicesProvider/ServicesProvider.php26
-rwxr-xr-xmain/app/sprinkles/extend-user/templates/forms/user.html.twig145
-rwxr-xr-xmain/app/sprinkles/extend-user/templates/pages/user.html.twig11
14 files changed, 716 insertions, 0 deletions
diff --git a/main/app/sprinkles/extend-user/.gitignore b/main/app/sprinkles/extend-user/.gitignore
new file mode 100755
index 0000000..5a664d4
--- /dev/null
+++ b/main/app/sprinkles/extend-user/.gitignore
@@ -0,0 +1,3 @@
+.DS_Store
+.idea
+*.komodoproject
diff --git a/main/app/sprinkles/extend-user/README.md b/main/app/sprinkles/extend-user/README.md
new file mode 100755
index 0000000..60a4bcd
--- /dev/null
+++ b/main/app/sprinkles/extend-user/README.md
@@ -0,0 +1,29 @@
+# User Extension Sprinkle (UserFrosting 4.1)
+
+Example sprinkle for extending the User class to contain additional fields.
+
+# Installation
+
+Edit UserFrosting `app/sprinkles.json` and add the following to the `require` list : `"userfrosting/extend-user": "~4.1.1"`. Also add `extend-user` to the `base` list. For example:
+
+```
+{
+ "require": {
+ "userfrosting/extend-user": "~4.1.1"
+ },
+ "base": [
+ "core",
+ "account",
+ "admin",
+ "extend-user"
+ ]
+}
+```
+
+### Update Composer
+
+- Run `composer update` from the root project directory.
+
+### Run migration
+
+- Run `php bakery bake` from the root project directory.
diff --git a/main/app/sprinkles/extend-user/composer.json b/main/app/sprinkles/extend-user/composer.json
new file mode 100755
index 0000000..4c8a0fa
--- /dev/null
+++ b/main/app/sprinkles/extend-user/composer.json
@@ -0,0 +1,22 @@
+{
+ "name": "userfrosting/extend-user",
+ "type": "userfrosting-sprinkle",
+ "description": "An example Sprinkle for extending the User model and table with additional fields or relationships.",
+ "homepage": "https://github.com/userfrosting/extend-user",
+ "license" : "MIT",
+ "authors" : [
+ {
+ "name": "Alexander Weissman",
+ "homepage": "https://alexanderweissman.com"
+ }
+ ],
+ "autoload": {
+ "psr-4": {
+ "UserFrosting\\Sprinkle\\ExtendUser\\": "src/"
+ }
+ },
+ "extra": {
+ "installer-name": "extend-user"
+ }
+}
+
diff --git a/main/app/sprinkles/extend-user/routes/member.php b/main/app/sprinkles/extend-user/routes/member.php
new file mode 100755
index 0000000..19028ac
--- /dev/null
+++ b/main/app/sprinkles/extend-user/routes/member.php
@@ -0,0 +1,7 @@
+<?php
+/**
+ * Routes for administrative user management. Overrides routes defined in routes://admin/users.php
+ */
+$app->group('/admin/users', function () {
+ $this->get('/u/{user_name}', 'UserFrosting\Sprinkle\ExtendUser\Controller\MemberController:pageInfo');
+})->add('authGuard'); \ No newline at end of file
diff --git a/main/app/sprinkles/extend-user/schema/requests/user/create.yaml b/main/app/sprinkles/extend-user/schema/requests/user/create.yaml
new file mode 100755
index 0000000..2df2955
--- /dev/null
+++ b/main/app/sprinkles/extend-user/schema/requests/user/create.yaml
@@ -0,0 +1,86 @@
+---
+user_name:
+ validators:
+ length:
+ label: "&USERNAME"
+ min: 1
+ max: 50
+ message: VALIDATE.LENGTH_RANGE
+ no_leading_whitespace:
+ label: "&USERNAME"
+ message: VALIDATE.NO_LEAD_WS
+ no_trailing_whitespace:
+ label: "&USERNAME"
+ message: VALIDATE.NO_TRAIL_WS
+ required:
+ label: "&USERNAME"
+ message: VALIDATE.REQUIRED
+ username:
+ label: "&USERNAME"
+ message: VALIDATE.USERNAME
+first_name:
+ validators:
+ length:
+ label: "&FIRST_NAME"
+ min: 1
+ max: 20
+ message: VALIDATE.LENGTH_RANGE
+ required:
+ label: "&FIRST_NAME"
+ message: VALIDATE.REQUIRED
+ transformations:
+ - trim
+last_name:
+ validators:
+ length:
+ label: "&LAST_NAME"
+ min: 1
+ max: 30
+ message: VALIDATE.LENGTH_RANGE
+ transformations:
+ - trim
+email:
+ validators:
+ required:
+ label: "&EMAIL"
+ message: VALIDATE.REQUIRED
+ length:
+ label: "&EMAIL"
+ min: 1
+ max: 150
+ message: VALIDATE.LENGTH_RANGE
+ email:
+ message: VALIDATE.INVALID_EMAIL
+locale:
+ default: en_US
+ validators:
+ required:
+ label: "&LOCALE"
+ domain: server
+ message: VALIDATE.REQUIRED
+ length:
+ label: "&LOCALE"
+ min: 1
+ max: 10
+ domain: server
+ message: VALIDATE.LENGTH_RANGE
+group_id:
+ validators:
+ integer:
+ label: "&GROUP"
+ domain: server
+ message: VALIDATE.INTEGER
+city:
+ validators:
+ length:
+ label: City
+ min: 1
+ max: 255
+ message: VALIDATE.LENGTH_RANGE
+country:
+ validators:
+ length:
+ label: Country
+ min: 1
+ max: 255
+ message: VALIDATE.LENGTH_RANGE
diff --git a/main/app/sprinkles/extend-user/schema/requests/user/edit-info.yaml b/main/app/sprinkles/extend-user/schema/requests/user/edit-info.yaml
new file mode 100755
index 0000000..edfae6e
--- /dev/null
+++ b/main/app/sprinkles/extend-user/schema/requests/user/edit-info.yaml
@@ -0,0 +1,50 @@
+---
+first_name:
+ validators:
+ length:
+ label: "&FIRST_NAME"
+ min: 1
+ max: 20
+ message: VALIDATE.LENGTH_RANGE
+last_name:
+ validators:
+ length:
+ label: "&LAST_NAME"
+ min: 1
+ max: 30
+ message: VALIDATE.LENGTH_RANGE
+email:
+ validators:
+ length:
+ label: "&EMAIL"
+ min: 1
+ max: 150
+ message: VALIDATE.LENGTH_RANGE
+ email:
+ message: VALIDATE.INVALID_EMAIL
+locale:
+ validators:
+ length:
+ label: "&LOCALE"
+ min: 1
+ max: 10
+ message: VALIDATE.LENGTH_RANGE
+group_id:
+ validators:
+ integer:
+ label: "&GROUP"
+ message: VALIDATE.INTEGER
+city:
+ validators:
+ length:
+ label: City
+ min: 1
+ max: 255
+ message: VALIDATE.LENGTH_RANGE
+country:
+ validators:
+ length:
+ label: Country
+ min: 1
+ max: 255
+ message: VALIDATE.LENGTH_RANGE \ No newline at end of file
diff --git a/main/app/sprinkles/extend-user/src/Controller/MemberController.php b/main/app/sprinkles/extend-user/src/Controller/MemberController.php
new file mode 100755
index 0000000..c584286
--- /dev/null
+++ b/main/app/sprinkles/extend-user/src/Controller/MemberController.php
@@ -0,0 +1,123 @@
+<?php
+namespace UserFrosting\Sprinkle\ExtendUser\Controller;
+
+use Illuminate\Database\Capsule\Manager as Capsule;
+use Psr\Http\Message\ResponseInterface as Response;
+use Psr\Http\Message\ServerRequestInterface as Request;
+use UserFrosting\Sprinkle\Admin\Controller\UserController;
+use UserFrosting\Sprinkle\Core\Facades\Debug;
+use UserFrosting\Support\Exception\ForbiddenException;
+
+class MemberController extends UserController
+{
+ /**
+ * Renders a page displaying a user's information, in read-only mode.
+ *
+ * This checks that the currently logged-in user has permission to view the requested user's info.
+ * It checks each field individually, showing only those that you have permission to view.
+ * This will also try to show buttons for activating, disabling/enabling, deleting, and editing the user.
+ * This page requires authentication.
+ * Request type: GET
+ */
+ public function pageInfo($request, $response, $args)
+ {
+ $user = $this->getUserFromParams($args);
+
+ // If the user no longer exists, forward to main user listing page
+ if (!$user) {
+ $usersPage = $this->ci->router->pathFor('uri_users');
+ return $response->withRedirect($usersPage, 404);
+ }
+
+ /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */
+ $authorizer = $this->ci->authorizer;
+
+ /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */
+ $currentUser = $this->ci->currentUser;
+
+ // Access-controlled page
+ if (!$authorizer->checkAccess($currentUser, 'uri_user', [
+ 'user' => $user
+ ])) {
+ throw new ForbiddenException();
+ }
+
+ /** @var UserFrosting\Config\Config $config */
+ $config = $this->ci->config;
+
+ // Get a list of all locales
+ $locales = $config->getDefined('site.locales.available');
+
+ // Determine fields that currentUser is authorized to view
+ $fieldNames = ['user_name', 'name', 'email', 'locale', 'group', 'roles', 'address'];
+
+ // Generate form
+ $fields = [
+ // Always hide these
+ 'hidden' => ['theme']
+ ];
+
+ // Determine which fields should be hidden
+ foreach ($fieldNames as $field) {
+ if (!$authorizer->checkAccess($currentUser, 'view_user_field', [
+ 'user' => $user,
+ 'property' => $field
+ ])) {
+ $fields['hidden'][] = $field;
+ }
+ }
+
+ // Determine buttons to display
+ $editButtons = [
+ 'hidden' => []
+ ];
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['name', 'email', 'locale']
+ ])) {
+ $editButtons['hidden'][] = 'edit';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['flag_enabled']
+ ])) {
+ $editButtons['hidden'][] = 'enable';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['flag_verified']
+ ])) {
+ $editButtons['hidden'][] = 'activate';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['password']
+ ])) {
+ $editButtons['hidden'][] = 'password';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'update_user_field', [
+ 'user' => $user,
+ 'fields' => ['roles']
+ ])) {
+ $editButtons['hidden'][] = 'roles';
+ }
+
+ if (!$authorizer->checkAccess($currentUser, 'delete_user', [
+ 'user' => $user
+ ])) {
+ $editButtons['hidden'][] = 'delete';
+ }
+
+ return $this->ci->view->render($response, 'pages/user.html.twig', [
+ 'user' => $user,
+ 'locales' => $locales,
+ 'fields' => $fields,
+ 'tools' => $editButtons
+ ]);
+ }
+}
diff --git a/main/app/sprinkles/extend-user/src/Database/Migrations/v400/MembersTable.php b/main/app/sprinkles/extend-user/src/Database/Migrations/v400/MembersTable.php
new file mode 100755
index 0000000..a27d485
--- /dev/null
+++ b/main/app/sprinkles/extend-user/src/Database/Migrations/v400/MembersTable.php
@@ -0,0 +1,34 @@
+<?php
+namespace UserFrosting\Sprinkle\ExtendUser\Database\Migrations\v400;
+
+use UserFrosting\System\Bakery\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Database\Schema\Builder;
+
+class MembersTable extends Migration
+{
+ public $dependencies = [
+ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\UsersTable'
+ ];
+
+ public function up()
+ {
+ if (!$this->schema->hasTable('members')) {
+ $this->schema->create('members', function (Blueprint $table) {
+ $table->increments('id');
+ $table->string('city', 255)->nullable();
+ $table->string('country', 255)->nullable();
+
+ $table->engine = 'InnoDB';
+ $table->collation = 'utf8_unicode_ci';
+ $table->charset = 'utf8';
+ $table->foreign('id')->references('id')->on('users');
+ });
+ }
+ }
+
+ public function down()
+ {
+ $this->schema->drop('members');
+ }
+}
diff --git a/main/app/sprinkles/extend-user/src/Database/Models/Member.php b/main/app/sprinkles/extend-user/src/Database/Models/Member.php
new file mode 100755
index 0000000..98d9d70
--- /dev/null
+++ b/main/app/sprinkles/extend-user/src/Database/Models/Member.php
@@ -0,0 +1,124 @@
+<?php
+namespace UserFrosting\Sprinkle\ExtendUser\Database\Models;
+
+use UserFrosting\Sprinkle\Account\Database\Models\User;
+use UserFrosting\Sprinkle\ExtendUser\Database\Models\MemberAux;
+use UserFrosting\Sprinkle\ExtendUser\Database\Scopes\MemberAuxScope;
+
+trait LinkMemberAux
+{
+ /**
+ * The "booting" method of the trait.
+ *
+ * @return void
+ */
+ protected static function bootLinkMemberAux()
+ {
+ /**
+ * Create a new MemberAux if necessary, and save the associated member data every time.
+ */
+ static::saved(function ($member) {
+ $member->createAuxIfNotExists();
+
+ if ($member->auxType) {
+ // Set the aux PK, if it hasn't been set yet
+ if (!$member->aux->id) {
+ $member->aux->id = $member->id;
+ }
+
+ $member->aux->save();
+ }
+ });
+ }
+}
+
+class Member extends User
+{
+ use LinkMemberAux;
+
+ protected $fillable = [
+ 'user_name',
+ 'first_name',
+ 'last_name',
+ 'email',
+ 'locale',
+ 'theme',
+ 'group_id',
+ 'flag_verified',
+ 'flag_enabled',
+ 'last_activity_id',
+ 'password',
+ 'deleted_at',
+ 'city',
+ 'country'
+ ];
+
+ protected $auxType = 'UserFrosting\Sprinkle\ExtendUser\Database\Models\MemberAux';
+
+ /**
+ * Required to be able to access the `aux` relationship in Twig without needing to do eager loading.
+ * @see http://stackoverflow.com/questions/29514081/cannot-access-eloquent-attributes-on-twig/35908957#35908957
+ */
+ public function __isset($name)
+ {
+ if (in_array($name, [
+ 'aux'
+ ])) {
+ return true;
+ } else {
+ return parent::__isset($name);
+ }
+ }
+
+ /**
+ * Globally joins the `members` table to access additional properties.
+ */
+ protected static function boot()
+ {
+ parent::boot();
+
+ static::addGlobalScope(new MemberAuxScope);
+ }
+
+ /**
+ * Custom mutator for Member property
+ */
+ public function setCityAttribute($value)
+ {
+ $this->createAuxIfNotExists();
+
+ $this->aux->city = $value;
+ }
+
+ /**
+ * Custom mutator for Member property
+ */
+ public function setCountryAttribute($value)
+ {
+ $this->createAuxIfNotExists();
+
+ $this->aux->country = $value;
+ }
+
+ /**
+ * Relationship for interacting with aux model (`members` table).
+ */
+ public function aux()
+ {
+ return $this->hasOne($this->auxType, 'id');
+ }
+
+ /**
+ * If this instance doesn't already have a related aux model (either in the db on in the current object), then create one
+ */
+ protected function createAuxIfNotExists()
+ {
+ if ($this->auxType && !count($this->aux)) {
+ // Create aux model and set primary key to be the same as the main user's
+ $aux = new $this->auxType;
+
+ // Needed to immediately hydrate the relation. It will actually get saved in the bootLinkMemberAux method.
+ $this->setRelation('aux', $aux);
+ }
+ }
+}
diff --git a/main/app/sprinkles/extend-user/src/Database/Models/MemberAux.php b/main/app/sprinkles/extend-user/src/Database/Models/MemberAux.php
new file mode 100755
index 0000000..c826409
--- /dev/null
+++ b/main/app/sprinkles/extend-user/src/Database/Models/MemberAux.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace UserFrosting\Sprinkle\ExtendUser\Database\Models;
+
+use UserFrosting\Sprinkle\Core\Database\Models\Model;
+
+class MemberAux extends Model
+{
+ public $timestamps = false;
+
+ /**
+ * @var string The name of the table for the current model.
+ */
+ protected $table = 'members';
+
+ protected $fillable = [
+ 'city',
+ 'country'
+ ];
+}
diff --git a/main/app/sprinkles/extend-user/src/Database/Scopes/MemberAuxScope.php b/main/app/sprinkles/extend-user/src/Database/Scopes/MemberAuxScope.php
new file mode 100755
index 0000000..c732147
--- /dev/null
+++ b/main/app/sprinkles/extend-user/src/Database/Scopes/MemberAuxScope.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace UserFrosting\Sprinkle\ExtendUser\Database\Scopes;
+
+use Illuminate\Database\Eloquent\Scope;
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Builder;
+
+class MemberAuxScope implements Scope
+{
+ /**
+ * Apply the scope to a given Eloquent query builder.
+ *
+ * @param \Illuminate\Database\Eloquent\Builder $builder
+ * @param \Illuminate\Database\Eloquent\Model $model
+ * @return void
+ */
+ public function apply(Builder $builder, Model $model)
+ {
+ $baseTable = $model->getTable();
+ // Hardcode the table name here, or you can access it using the classMapper and `getTable`
+ $auxTable = 'members';
+
+ // Specify columns to load from base table and aux table
+ $builder->addSelect(
+ "$baseTable.*",
+ "$auxTable.city as city",
+ "$auxTable.country as country"
+ );
+
+ // Join on matching `member` records
+ $builder->leftJoin($auxTable, function ($join) use ($baseTable, $auxTable) {
+ $join->on("$auxTable.id", '=', "$baseTable.id");
+ });
+ }
+}
diff --git a/main/app/sprinkles/extend-user/src/ServicesProvider/ServicesProvider.php b/main/app/sprinkles/extend-user/src/ServicesProvider/ServicesProvider.php
new file mode 100755
index 0000000..8ea3860
--- /dev/null
+++ b/main/app/sprinkles/extend-user/src/ServicesProvider/ServicesProvider.php
@@ -0,0 +1,26 @@
+<?php
+
+// In /app/sprinkles/site/src/ServicesProvider/ServicesProvider.php
+
+namespace UserFrosting\Sprinkle\ExtendUser\ServicesProvider;
+
+class ServicesProvider
+{
+ /**
+ * Register extended user fields services.
+ *
+ * @param Container $container A DI container implementing ArrayAccess and container-interop.
+ */
+ public function register($container)
+ {
+ /**
+ * Extend the 'classMapper' service to register model classes.
+ *
+ * Mappings added: Member
+ */
+ $container->extend('classMapper', function ($classMapper, $c) {
+ $classMapper->setClassMapping('user', 'UserFrosting\Sprinkle\ExtendUser\Database\Models\Member');
+ return $classMapper;
+ });
+ }
+}
diff --git a/main/app/sprinkles/extend-user/templates/forms/user.html.twig b/main/app/sprinkles/extend-user/templates/forms/user.html.twig
new file mode 100755
index 0000000..b7c98a9
--- /dev/null
+++ b/main/app/sprinkles/extend-user/templates/forms/user.html.twig
@@ -0,0 +1,145 @@
+<form class="js-form" method="{{form.method | default('POST')}}" action="{{site.uri.public}}/{{form.action}}">
+ {% include "forms/csrf.html.twig" %}
+ <div class="js-form-alerts">
+ </div>
+ <div class="row">
+ {% block user_form %}
+ {% if 'user_name' not in form.fields.hidden %}
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label>{{translate('USERNAME')}}</label>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="fa fa-edit fa-fw"></i></span>
+ <input type="text" class="form-control" name="user_name" autocomplete="off" value="{{user.user_name}}" placeholder="{{translate('USERNAME')}}" {% if 'user_name' in form.fields.disabled %}disabled{% endif %}>
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% if 'group' not in form.fields.hidden %}
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label for="input-group">{{translate('GROUP')}}</label>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="fa fa-users fa-fw"></i></span>
+ {% if 'group' in form.fields.disabled %}
+ <input type="text" class="form-control" name="theme" value="{{user.group.name}}" disabled>
+ {% else %}
+ <select id="input-group" class="form-control js-select2" name="group_id">
+ {% for group in groups %}
+ <option value="{{group.id}}" {% if (group.id == user.group_id) %}selected{% endif %}>{{group.name}}</option>
+ {% endfor %}
+ </select>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% if 'name' not in form.fields.hidden %}
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label>{{translate('FIRST_NAME')}}</label>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="fa fa-edit fa-fw"></i></span>
+ <input type="text" class="form-control" name="first_name" autocomplete="off" value="{{user.first_name}}" placeholder="{{translate('FIRST_NAME')}}" {% if 'name' in form.fields.disabled %}disabled{% endif %}>
+ </div>
+ </div>
+ </div>
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label>{{translate('LAST_NAME')}}</label>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="fa fa-edit fa-fw"></i></span>
+ <input type="text" class="form-control" name="last_name" autocomplete="off" value="{{user.last_name}}" placeholder="{{translate('LAST_NAME')}}" {% if 'name' in form.fields.disabled %}disabled{% endif %}>
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% if 'email' not in form.fields.hidden %}
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label>{{translate('EMAIL')}}</label>
+ <div class="input-group js-copy-container">
+ <span class="input-group-addon"><i class="fa fa-envelope fa-fw"></i></span>
+ <input type="text" class="form-control js-copy-target" name="email" autocomplete="off" value="{{user.email}}" placeholder="{{translate('EMAIL')}}" {% if 'email' in form.fields.disabled %}disabled{% endif %}>
+ {% if 'email' in form.fields.disabled %}
+ <span class="input-group-btn">
+ <button class="btn btn-default js-copy-trigger" type="button"><i class="fa fa-clipboard"></i></button>
+ </span>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% if 'theme' not in form.fields.hidden %}
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label for="input-theme">{{translate('THEME')}}</label>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="fa fa-puzzle-piece fa-fw"></i></span>
+ {% if 'theme' in form.fields.disabled %}
+ <input type="text" class="form-control" name="theme" value="{{themes[user.theme]}}" disabled>
+ {% else %}
+ <select id="input-theme" class="form-control js-select2" name="theme">
+ {% for option, label in theme %}
+ <option value="{{option}}" {% if (option == user.theme) %}selected{% endif %}>{{label}}</option>
+ {% endfor %}
+ </select>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% if 'locale' not in form.fields.hidden %}
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label for="input-locale">{{translate('LOCALE')}}</label>
+ <div class="input-group">
+ <span class="input-group-addon"><i class="fa fa-language fa-fw"></i></span>
+ {% if 'locale' in form.fields.disabled %}
+ <input type="text" class="form-control" name="theme" value="{{locales[user.locale]}}" disabled>
+ {% else %}
+ <select id="input-locale" class="form-control js-select2" name="locale">
+ {% for option, label in locales %}
+ <option value="{{option}}" {% if (option == user.locale) %}selected{% endif %}>{{label}}</option>
+ {% endfor %}
+ </select>
+ {% endif %}
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% if 'address' not in form.fields.hidden %}
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label>City</label>
+ <div class="input-group js-copy-container">
+ <span class="input-group-addon"><i class="fa fa-map-pin"></i></span>
+ <input type="text" class="form-control" name="city" autocomplete="off" value="{{user.city}}" placeholder="City" {% if 'address' in form.fields.disabled %}disabled{% endif %}>
+ </div>
+ </div>
+ </div>
+ <div class="col-sm-6">
+ <div class="form-group">
+ <label>Country</label>
+ <div class="input-group js-copy-container">
+ <span class="input-group-addon"><i class="fa fa-map-pin"></i></span>
+ <input type="text" class="form-control" name="country" autocomplete="off" value="{{user.country}}" placeholder="Country" {% if 'address' in form.fields.disabled %}disabled{% endif %}>
+ </div>
+ </div>
+ </div>
+ {% endif %}
+ {% endblock %}
+ </div><br>
+ <div class="row">
+ <div class="col-xs-8 col-sm-4">
+ <button type="submit" class="btn btn-block btn-lg btn-success">{{form.submit_text}}</button>
+ </div>
+ <div class="col-xs-4 col-sm-3 pull-right">
+ <button type="button" class="btn btn-block btn-lg btn-link" data-dismiss="modal">{{translate('CANCEL')}}</button>
+ </div>
+ </div>
+</form>
+<!-- Include validation rules -->
+<script>
+ {% include "pages/partials/page.js.twig" %}
+</script>
diff --git a/main/app/sprinkles/extend-user/templates/pages/user.html.twig b/main/app/sprinkles/extend-user/templates/pages/user.html.twig
new file mode 100755
index 0000000..46e79aa
--- /dev/null
+++ b/main/app/sprinkles/extend-user/templates/pages/user.html.twig
@@ -0,0 +1,11 @@
+{% extends "@admin/pages/user.html.twig" %}
+
+{% block user_profile %}
+ {% if 'locale' not in fields.hidden %}
+ <hr>
+ <strong><i class="fa fa-map-marker margin-r-5"></i> Location</strong>
+ <p class="text-muted box-profile-property">
+ {{user.city}}, {{user.country}}
+ </p>
+ {% endif %}
+{% endblock %}