profile finished; improved layout a bit

This commit is contained in:
Christine Slotty 2020-07-16 18:39:00 +02:00
parent 163bf8129b
commit c988b65817
15 changed files with 258 additions and 101 deletions

View File

@ -205,7 +205,7 @@ class AppController extends Controller
$stateUser->email != $json['user']['email']) {
$stateUser->first_name = $json['user']['first_name'];
$stateUser->last_name = $json['user']['last_name'];
$stateUser->username = $json['user']['username'];
//$stateUser->username = $json['user']['username'];
$stateUser->email = $json['user']['email'];
if (!$stateUserTable->save($stateUser)) {
$this->Flash->error(__('error updating state user ' . json_encode($stateUser->errors())));
@ -222,7 +222,7 @@ class AppController extends Controller
$newStateUser->public_key = $public_key_bin;
$newStateUser->first_name = $json['user']['first_name'];
$newStateUser->last_name = $json['user']['last_name'];
$newStateUser->username = $json['user']['username'];
//$newStateUser->username = $json['user']['username'];
$newStateUser->email = $json['user']['email'];
if (!$stateUserTable->save($newStateUser)) {
$this->Flash->error(__('error saving state user ' . json_encode($newStateUser->errors())));

View File

@ -2,7 +2,6 @@
namespace App\Controller;
use App\Controller\AppController;
use App\Controller\CommunityProfilesController;
use Model\Navigation\NaviHierarchy;
use Model\Navigation\NaviHierarchyEntry;
@ -29,6 +28,93 @@ class ProfileController extends AppController
add(new NaviHierarchyEntry(__('Mein Profil'), 'Profile', 'index', true))
);
}
/**
* Get binary file data from request data
*
* @return binary data
*/
protected function getFileData($requestData)
{
$binaryFileData = null;
// Get a list of UploadedFile objects
$file = $requestData['profile_img'];
// Read the file data.
$type = $file['type'];
$error = $file['error'];
if ($error === 0 && strpos($type, 'image/') === 0) {
$path = new File($file['tmp_name']);
$binaryFileData = $path->read(true, 'r');
$this->log("binaryFileData: ".$binaryFileData, 'debug');
}
return $binaryFileData;
}
/**
* Update Profile Data
*
* ...which is spread over two tables.
*
* @throws Exception
*/
protected function updateProfileData($requestData, $userId, $communityProfile)
{
// Update Profile with Form Data!
$usersTable = TableRegistry::getTableLocator()->get('StateUsers');
$stateUserQuery = $usersTable
->find('all')
->select(['id', 'first_name', 'last_name'])
->where(['id' => $userId]);
if ($stateUserQuery->count() == 1) {
$stateUser = $stateUserQuery->first();
$stateUser = $usersTable->patchEntity($stateUser, $requestData);
$profilesTable = TableRegistry::getTableLocator()->get('CommunityProfiles');
// Save old binary data, because the file input is always empty, in HTML!
$oldBinaryData = $communityProfile['profile_img'];
$communityProfile = $profilesTable->patchEntity($communityProfile, $requestData);
$communityProfile['state_user_id'] = $userId;
$binaryFileData = $this->getFileData($requestData);
if ($binaryFileData !== null) {
$this->log("CommunityProfile: Writing binary img data.", 'debug');
$communityProfile['profile_img'] = $binaryFileData;
} else {
$this->log("CommunityProfile: Nothing uploaded!", 'debug');
$communityProfile['profile_img'] = $oldBinaryData;
}
if ($profilesTable->save($communityProfile) &&
$usersTable->save($stateUser)
) {
$this->Flash->success(__('Dein Profil wurde aktualisiert!'));
}
} else {
$this->Flash->error(__("Non-recoverable database problem - state_user doesn't exist or not unique!"));
}
return [$stateUser, $communityProfile];
}
/**
* Get or create CommunityProfile
*
* @return \Cake\ORM\CommunityProfile
*/
protected function getCommunityProfile($userId)
{
$profilesTable = TableRegistry::getTableLocator()->get('CommunityProfiles');
$communityProfileQuery = $profilesTable
->find('all')
->select(['id', 'profile_img', 'profile_desc'])
->where(['state_user_id' => $userId]);
if ($communityProfileQuery->count() != 1) {
$communityProfile = $profilesTable->newEntity();
if ($profilesTable->save($communityProfile)) {
$this->log("CommunityProfile created.", 'debug');
}
} else {
$communityProfile = $communityProfileQuery->first();
}
return $communityProfile;
}
/**
* Index method
*
@ -45,23 +131,10 @@ class ProfileController extends AppController
}
$user = $session->read('StateUser');
$communityProfile = $session->read('CommunityProfile');
if (!isset($communityProfile)) {
$profilesTable = TableRegistry::getTableLocator()->get('CommunityProfiles');
$communityProfileQuery = $profilesTable
->find('all')
->select(['id', 'profile_img', 'profile_desc'])
->where(['state_user_id' => $user['id']]);
if ($communityProfileQuery->count() != 1) {
$communityProfile = $profilesTable->newEntity();
if ($profilesTable->save($communityProfile)) {
$this->Flash->success(__('Neues Profil erstellt.'));
}
} else {
$communityProfile = $communityProfileQuery->first();
}
$session->write('CommunityProfile', $communityProfile);
if (!$communityProfile) {
$this->log("CommunityProfile not found in session! Loading or creating new one.", 'debug');
$session->write('CommunityProfile', $this->getCommunityProfile($user['id']));
}
$this->set('user', $user);
$this->set('communityProfile', $communityProfile);
$this->set('timeUsed', microtime(true) - $startTime);
@ -76,6 +149,7 @@ class ProfileController extends AppController
$startTime = microtime(true);
$this->viewBuilder()->setLayout('frontend');
$session = $this->getRequest()->getSession();
$user = $session->read('StateUser');
$communityProfile = $session->read('CommunityProfile');
if (!$user) {
@ -85,50 +159,21 @@ class ProfileController extends AppController
}
$user = $session->read('StateUser');
}
if (!$communityProfile) {
$this->log("CommunityProfile not found in session! Loading or creating new one.", 'debug');
$session->write('CommunityProfile', $this->getCommunityProfile($user['id']));
}
$profileForm = new ProfileForm();
if ($this->request->is('post')) {
$requestData = $this->request->getData();
if ($profileForm->validate($requestData)) {
// Get a list of UploadedFile objects
$file = $requestData['profile_img'];
var_dump($file);
$binaryFileData = null;
// Read the file data.
$type = $file['type'];
$error = $file['error'];
if ($error === 0 && strpos($type, 'image/') === 0) {
$path = new File($file['tmp_name']);
$binaryFileData = $path->read(true, 'r');
}
// Update Profile with Form Data!
$usersTable = TableRegistry::getTableLocator()->get('StateUsers');
$stateUserQuery = $usersTable
->find('all')
->select(['id', 'first_name', 'last_name'])
->where(['id' => $user['id']]);
if ($stateUserQuery->count() == 1) {
$stateUser = $stateUserQuery->first();
$stateUser = $usersTable->patchEntity($stateUser, $requestData);
$profilesTable = TableRegistry::getTableLocator()->get('CommunityProfiles');
$communityProfile = $profilesTable->patchEntity($communityProfile, $requestData);
$communityProfile['state_user_id'] = $user['id'];
if ($binaryFileData !== null) {
echo "schreibe neue daten";
$communityProfile['profile_img'] = $binaryFileData;
}
if ($profilesTable->save($communityProfile) &&
$usersTable->save($stateUser)
) {
$user['first_name'] = $stateUser['first_name'];
$user['last_name'] = $stateUser['last_name'];
$session->write('StateUser.first_name', $stateUser['first_name']);
$session->write('StateUser.last_name', $stateUser['last_name']);
$session->write('CommunityProfile', $communityProfile);
$this->Flash->success(__('Dein Profil wurde aktualisiert!'));
}
} else {
$this->Flash->error(__("Non-recoverable database problem - state_user doesn't exist or not unique!"));
}
[$stateUser, $communityProfile] = $this->updateProfileData($requestData, $user['id'], $communityProfile);
$user['first_name'] = $stateUser['first_name'];
$user['last_name'] = $stateUser['last_name'];
$session->write('StateUser.first_name', $stateUser['first_name']);
$session->write('StateUser.last_name', $stateUser['last_name']);
$session->write('CommunityProfile', $communityProfile);
} else {
$this->Flash->error(__('Something was invalid, please try again!'));
}

View File

@ -145,7 +145,7 @@ class StateUsersController extends AppController
$communityUsers->where(['OR' => [
'first_name LIKE' => $globalSearch,
'last_name LIKE' => $globalSearch,
'username LIKE' => $globalSearch,
//'username LIKE' => $globalSearch,
'email LIKE' => $globalSearch
]]);
@ -183,7 +183,7 @@ class StateUsersController extends AppController
$finalUser['name'] = $c_user->first_name . ' ' . $c_user->last_name;
$finalUser['first_name'] = $c_user->first_name;
$finalUser['last_name'] = $c_user->last_name;
$finalUser['username'] = $c_user->username;
//$finalUser['username'] = $c_user->username;
$finalUser['email'] = $c_user->email;
}
} elseif (count($user['login']) == 1) {
@ -205,7 +205,7 @@ class StateUsersController extends AppController
$finalUser['name'] = $l_user['first_name'] . ' ' . $l_user['last_name'];
$finalUser['first_name'] = $l_user['first_name'];
$finalUser['last_name'] = $l_user['last_name'];
$finalUser['username'] = $l_user['username'];
//$finalUser['username'] = $l_user['username'];
$finalUser['email'] = $l_user['email'];
$finalUser['created'] = new FrozenTime($l_user['created']);
} else {
@ -232,7 +232,7 @@ class StateUsersController extends AppController
$finalUser['name'] = $user['first_name'] . ' ' . $user['last_name'];
$finalUser['first_name'] = $user['first_name'];
$finalUser['last_name'] = $user['last_name'];
$finalUser['username'] = $user['username'];
//$finalUser['username'] = $user['username'];
$finalUser['email'] = $user['email'];
$finalUser['created'] = new FrozenTime($user['created']);
$finalUser['indicator'] = ['name' => $state, 'color' => $color];

View File

@ -63,7 +63,7 @@ $this->assign(
</div>
</div>
<div class="content-region">
<legend>Statistik</legend>
<h3>Statistik</h3>
<div class="content-collection">
<div class="content-item info-item">
<i class="material-icons-outlined">cached</i>

View File

@ -22,10 +22,10 @@ if(intval($transactionPendings) > 0) {
array_push($navi, new NaviEntryAbsoluteLink(__('Abmelden'), 'exit_to_app', 'account/logout'));
}
?>
<span class="user-name">
<?=$user['first_name'].' '.$user['last_name']?>
</span>
<i class="material-icons-outlined user-icon" onclick="toggleUserMenu()">account_circle</i>
<div class="user-menu-container">
<span class="user-name"><?=$user['first_name'].' '.$user['last_name']?></span>
<i class="material-icons-outlined user-icon" onclick="toggleUserMenu()">account_circle</i>
</div>
<div class="nav-vertical user-menu">
<ul>
<?php foreach($navi as $n) echo $n; ?>

View File

@ -18,6 +18,10 @@ $this->loadHelper('Form', [
<?= $this->Form->control('first_name', ['label' => __('Vorname'), 'placeholder' => 'Vorname', 'value' => $user['first_name']]) ?>
<?= $this->Form->control('last_name', ['label' => __('Nachname'), 'placeholder' => 'Nachname', 'value' => $user['last_name']]) ?>
<?= $this->Form->control('profile_img', ['type' => 'file', 'accept' => 'image/*', 'label' => __('Profilbild')]) ?>
<?php if ($communityProfile['profile_img']) : ?>
<label class="form-label">&nbsp;</label>
<div><img class="edit-profile-img" src="data:image/*;base64,<?=base64_encode($communityProfile['profile_img'])?>"/></div>
<?php endif; ?>
<?= $this->Form->control('profile_desc', ['label' => __('Beschreibung'), 'rows' => 4, 'placeholder' => 'Beschreibung', 'value' => $communityProfile['profile_desc']]) ?>
<?= $this->Form->button(__('Daten speichern'), ['name' => 'submit', 'class' => 'form-button']) ?>
<?= $this->Form->end() ?>

View File

@ -5,11 +5,19 @@ use Cake\Routing\Router;
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
$header = '<div>';
$header .= '<h1 class="inline-header">'.$user['first_name'] . '&nbsp;' . $user['last_name'] . '</h1>';
if (!empty($communityProfile['profile_desc'])) {
$header .= "<p>".$communityProfile['profile_desc']."</p>";
}
$header .= '</div>';
if ($communityProfile && $communityProfile['profile_img']) {
$header .= "<div><img
class='show-profile-img'
src='data:image/*;base64,".base64_encode($communityProfile['profile_img'])."'/></div>";
}
$this->assign('title', __('Mein Profil'));
$this->assign(
'header',
'<h1>'.__('Profil') . ' von: ' . $user['first_name'] . '&nbsp;' . $user['last_name'] . '</h1>'
);
$this->assign('header', $header);
?>
<?php if(isset($requestTime)) : ?>
<span><?= round($requestTime * 1000.0) ?> ms</span>
@ -33,10 +41,6 @@ $this->assign(
<span class="fact label">Nachname:</span>
<span class="fact"><?=$user['last_name']?></span>
</li>
<li class="fact">
<span class="fact label">Beschreibung:</span>
<span class="fact"><?=$communityProfile['profile_desc']?></span>
</li>
<li class="fact">
<span class="fact label"></span>
<span class="fact">

View File

@ -62,7 +62,8 @@ use Cake\I18n\FrozenTime;
}
</style>
<div class="grd_container_small grd_margin-bottom_120">
<div class="action-form">
<p class="form-header">Schöpfen</p>
<button type="button" onclick="checkAll()" >Alle auswählen</button>
<button type="button" onclick="uncheckAll()">Alle abwählen</button>
<div style="margin-bottom:5px"></div>
@ -211,8 +212,6 @@ use Cake\I18n\FrozenTime;
}
function checkTransactionExecuting() {
getJson('<?= $this->Url->build(["controller" => "JsonRequestHandler"]);?>', 'getRunningUserTasks',
// success
function(json) {

View File

@ -0,0 +1,76 @@
<?php
namespace App\Test\TestCase\Controller;
use App\Controller\ProfilesController;
use Cake\TestSuite\IntegrationTestTrait;
use Cake\TestSuite\TestCase;
/**
* App\Controller\ProfilesController Test Case
*
* @uses \App\Controller\ProfilesController
*/
class ProfilesControllerTest extends TestCase
{
use IntegrationTestTrait;
/**
* Fixtures
*
* @var array
*/
public $fixtures = [
'app.StateUsers',
'app.CommunityProfiles',
];
/**
* Test index method
*
* @return void
*/
public function testIndex()
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test view method
*
* @return void
*/
public function testView()
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test add method
*
* @return void
*/
public function testAdd()
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test edit method
*
* @return void
*/
public function testEdit()
{
$this->markTestIncomplete('Not implemented yet.');
}
/**
* Test delete method
*
* @return void
*/
public function testDelete()
{
$this->markTestIncomplete('Not implemented yet.');
}
}

BIN
tests/data/smallest.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 B

1
tests/data/verysmall.jpg Normal file
View File

@ -0,0 +1 @@
FF D8 FF E0 00 10 4A 46 49 46 00 01 01 01 00 48 00 48 00 00 FF DB 00 43 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF C2 00 0B 08 00 01 00 01 01 01 11 00 FF C4 00 14 10 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF DA 00 08 01 01 00 01 3F 10

View File

@ -23,7 +23,7 @@
/* GRID */
.layout {
display: grid;
grid-template-rows: [top] 6vh [line2] 86vh [footer1] 3vh [footer2] 5vh [end];
grid-template-rows: [top] 8vh [line2] 86vh [footer1] 3vh [footer2] 5vh [end];
grid-template-columns: [left1] auto [left2] 1fr [left3] 12fr [right3] 1fr [right2] auto [right1];
grid-template-areas: "header header header header header"
"left . center . ."

View File

@ -11,42 +11,40 @@
@media screen {
.header-user {
display: flex;
justify-content: flex-end;
align-items: center;
align-content: center;
flex-direction: column;
justify-content: flex-start;
align-items: flex-end;
align-content: flex-end;
width: 100%;
min-width: 12em;
background-color: @container-background;
border: 1px solid @menu-border-color;
padding: .75em;
border-radius: 0 0 0 18px;
z-index: 2;
}
.user-name {
display: block;
.user-menu-container {
font-size: .8em;
font-weight: 300;
line-height: 1em;
text-align: right;
padding-right: .25em;
margin: auto;
padding: .25em 1em;
z-index: 20;
}
.user-icon {
display: block;
display: inline-block;
vertical-align: center;
cursor: pointer;
}
.nav-vertical.user-menu {
position: fixed;
display: none;
top: 25px;
right: 0;
background-color: @container-background;
border-left: 1px solid @menu-border-color;
border-bottom: 1px solid @menu-border-color;
border-radius: 0 0 16px 16px;
z-index: -1;
margin-top: 1em;
z-index: 15;
font-size: .9em;
margin-top: 0 !important;
}
.nav-vertical.user-menu.visible {
@ -73,17 +71,25 @@
.material-icons-outlined.user-info {
color: @unobtrusive;
}
.material-icons-outlined.user-info.success {
color: @success;
}
@media @tablet-down {
.header-user {
align-items: flex-start;
align-content: flex-start;
position: relative;
min-width: 3em;
background-color: transparent;
padding: .75em;
z-index: 15;
justify-content: center;
margin-top: -4px;
margin-left: -16px;
color: @action-button-background1;
}
.user-menu-container {
margin: 0;
padding: 0;
}
.user-name {
@ -95,7 +101,9 @@
}
.nav-vertical.user-menu {
position: fixed;
top: 1px;
right: 0;
margin-top: 0;
}

View File

@ -88,8 +88,11 @@
/* Top Info Above Main */
.info-container {
display: flex;
justify-content: space-around;
align-items: center;
max-width: 70%;
padding: .5em 25px;
padding: 1em 25px;
}
@media @tablet-down {
@ -148,6 +151,7 @@
.content-region h3 {
color: @container-header;
}
.content-region {
border-bottom: 1px dashed @light;
padding: 0 25px;
@ -175,6 +179,18 @@
border-left: 2px solid @info-item-border;
}
.inline-header {
display: inline;
}
.show-profile-img {
display: block;
height: 100px;
vertical-align: middle;
border-radius: 10px;
border: 2px dotted @info-background;
}
@media @tablet-down {
.content-region {
padding-left: 5px;

View File

@ -154,6 +154,10 @@ and open the template in the editor.
padding: .5em 1em;
}
.edit-profile-img {
width: 100px;
}
/* CENTER FORM SPECIFICS */
.form-body form {
display: grid;