Commit b9e724ef authored by ZeMKI's avatar ZeMKI

Newsletter and code optimization

* now users require a profile.
* new column on profile: newsletter.
* using config.enums for newsletter status.
* now you can define 0 pre-defined tokens for a study.
* css optimization.
parent 6ecca000
This diff is collapsed.
......@@ -7,15 +7,14 @@ use Illuminate\Http\Request;
/**
* App\Answer
*
* @property int $id
* @property int|null $question_id
* @property array $answer
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property int $id
* @property int|null $question_id
* @property array $answer
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Interview[] $interviews
* @property-read int|null $interviews_count
* @property-read \App\Question|null $question
* @property-read int|null $interviews_count
* @property-read \App\Question|null $question
* @method static \Illuminate\Database\Eloquent\Builder|\App\Answer newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Answer newQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\Answer query()
......@@ -45,17 +44,22 @@ class Answer extends Model
*/
public static function saveResultQuestions(Request $request, Interview $interview): void
{
foreach ($request->input('results_questions') as $key => $value) {
if (is_numeric($key)) {
foreach ($request->input('results_questions') as $key => $value)
{
if (is_numeric($key))
{
$answer = Answer::where('id', '=', $key)->first();
$question = Question::where('id', '=', $answer->question_id)->first();
$answertype = $answer->answer['type'];
if ($answertype === 'open' || $answertype === 'scale') {
if ($answertype === 'open' || $answertype === 'scale')
{
$interview->answers()->attach($key, ['result' => $value, 'question_id' => $question->id]);
}
}
if ($key === 'multi' || $key === 'onechoice') {
foreach ($value as $answer) {
if ($key === 'multi' || $key === 'onechoice')
{
foreach ($value as $answer)
{
$answer = Answer::where('id', '=', $answer['id'])->first();
$question = Question::where('id', '=', $answer->question_id)->first();
$interview->answers()->attach($answer['id'], ['question_id' => $question->id]);
......@@ -70,7 +74,8 @@ class Answer extends Model
*/
public static function assignAnswersToQuestion(Interview $interview, $data): void
{
foreach ($data['questions'] as $question) {
foreach ($data['questions'] as $question)
{
$question['available_answers'] = $question->availableAnswers();
$question['answers'] = $question->answers()->having('pivot_interview_id', '=', $interview->id)->get();
}
......
......@@ -103,6 +103,7 @@ class Helper
$array = array_values($temp_array);
return $array;
}
/**
* @param $string
* @param $start
......@@ -113,12 +114,11 @@ class Helper
{
$string = ' ' . $string;
$ini = strpos($string, $start);
if ($ini === 0 || $ini === false) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
if (strpos($string, $end, $ini) === false) {
if (strpos($string, $end, $ini) === false)
{
$len = strlen($string) - 1;
}
return substr($string, $ini, $len);
......
......@@ -8,6 +8,7 @@ use App\Role;
use App\User;
use Helper;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Validator;
use Spatie\WebhookServer\WebhookCall;
......@@ -65,6 +66,7 @@ class RegisterController extends Controller
*/
protected function create($data)
{
$userexist = User::where('email', '=', $data['email'])->first();
$role = Role::where('name', 'supervisor')->first();
......@@ -78,17 +80,25 @@ class RegisterController extends Controller
$user->password_token = Helper::random_str(30);
$user->save();
$profile = $user->addProfile($user);
$profile->newsletter = array_key_exists('newsletter',$data) ? config('enums.newsletter_status.SUBSCRIBED') : config('enums.newsletter_status.NOT SUBSCRIBED');
$profile->save();
$createStudyPermission = Permission::where('name', 'create-studies')
->first();
$user->supervised_by = $user->id;
$user->attachPermissions([$createStudyPermission]);
$user->attachRole($role);
WebhookCall::create()
->url('https://chat.zemki.uni-bremen.de/hooks/Jj3dDY2KzSFDS2kxZ/SvbmjdswXTASAXxC2GfgfTpFooK5Eo4kFBGPyDRrtsWmgED3')
->payload(['text' => 'User '.$data['email'].' has registered on Mesort. We have a total of '.User::all()->count().' users!'])
->useSecret('Jj3dDY2KzSFDS2kxZ/SvbmjdswXTASAXxC2GfgfTpFooK5Eo4kFBGPyDRrtsWmgED3')
->dispatch();
if (!App::environment('local')) {
WebhookCall::create()
->url('https://chat.zemki.uni-bremen.de/hooks/Jj3dDY2KzSFDS2kxZ/SvbmjdswXTASAXxC2GfgfTpFooK5Eo4kFBGPyDRrtsWmgED3')
->payload(['text' => 'User '.$data['email'].' has registered on Mesort. We have a total of '.User::all()->count().' users!'])
->useSecret('Jj3dDY2KzSFDS2kxZ/SvbmjdswXTASAXxC2GfgfTpFooK5Eo4kFBGPyDRrtsWmgED3')
->dispatch();
}
$user->save();
......
......@@ -2,8 +2,12 @@
namespace App\Http\Controllers;
use App\Helpers\NewsletterStatus;
use Auth;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\Response;
use Illuminate\View\View;
use Session;
class HomeController extends Controller
......@@ -19,11 +23,12 @@ class HomeController extends Controller
/**
* Show the application dashboard.
* @return Response
* @return Application|Factory|View
*/
public function index()
{
$data['studies'] = Auth::user()->studies;
$data['newsletter'] = Auth::user()->profile->newsletter === config('enums.newsletter_status.NOT DECIDED');
return view('home', $data);
}
......
......@@ -6,6 +6,9 @@ use App\Notifications\NotificationFromStaff;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Notification;
use mysql_xdevapi\Exception;
use phpDocumentor\Reflection\Types\Boolean;
use PhpParser\Node\Expr\Cast\Bool_;
class NotificationController extends Controller
{
......@@ -38,5 +41,31 @@ class NotificationController extends Controller
$user->notify(new NotificationFromStaff(['title' => $request->input('title'), 'message' => $request->input('message')]));
return view('admin.notifications', ['message' => 'Notification sent to ' . $request->input('email')]);
}
public function addToNewsletter(Request $request)
{
$subscribe = $request->input('subscribed') ? config('enums.newsletter_status.SUBSCRIBED') : config('enums.newsletter_status.NOT SUBSCRIBED');
try
{
if(auth()->user()->profile()->exists())
{
auth()->user()->profile->newsletter = $subscribe;
auth()->user()->profile->save();
}else{
$profile = auth()->user()->addProfile(auth()->user());
$profile->newsletter = $subscribe;
$profile->save();
}
return response()->json(['message' => 'Your preference was saved!','r' => $subscribe], 200);
}catch (Exception $exception)
{
return response()->json(['message' => 'A problem occurred, contact the administrator.'], 500);
}
}
}
......@@ -22,15 +22,14 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\View\View;
use Image;
use Storage;
class StudyController extends Controller
{
public function create(Request $request)
{
if (Auth::user()->hasReachMaxNumberOfStudies()) {
if (Auth::user()->hasReachMaxNumberOfStudies())
{
auth()->user()->addAction('trying to create a study', $request->url(), 'Max numbers of studies reached for user ' . auth()->user()->email);
abort(403, 'You reached the max number of studies');
}
......@@ -46,14 +45,18 @@ class StudyController extends Controller
$copy = $study->replicate();
$copy->save();
$study->load('questions', 'sortings', 'tokens');
foreach ($study->getRelations() as $relationName => $values) {
if ($relationName === "sortings") {
foreach ($study->getRelations() as $relationName => $values)
{
if ($relationName === "sortings")
{
$request = new Request();
$request->replace(['details' => $study->sortings[0]->pivot->details, 'sortingid' => $study->sortings[0]->id]);
Sorting::store($request, $copy);
} else if ($relationName === "questions") {
} else if ($relationName === "questions")
{
$this->CopyQuestionsRemoveInterviews($study, $copy);
} else if ($relationName === "tokens") {
} else if ($relationName === "tokens")
{
$this->RemoveTokensCreatedDuringInterview($values);
$copy->{$relationName}()->attach($values);
}
......@@ -69,20 +72,21 @@ class StudyController extends Controller
*/
private function CopyQuestionsRemoveInterviews(Study $study, Study $copy): void
{
foreach ($study->questions as $question) {
foreach ($study->questions as $question)
{
$copiedQuestion = $copy->questions()->create($question->toArray());
$answers = Answer::where('question_id', $question->id)->get();
foreach ($answers as $answer) {
foreach ($answers as $answer)
{
$answer->question_id = $copiedQuestion->id;
$copiedQuestion->answers()->create($answer->toArray());
}
// remove interviews
foreach ($copiedQuestion->answers as $answer) {
foreach ($copiedQuestion->answers as $answer)
{
$answer->interviews()->detach();
$answer->interviews()->delete();
}
}
}
......@@ -93,8 +97,10 @@ class StudyController extends Controller
private function RemoveTokensCreatedDuringInterview(&$values): void
{
// remove tokens created during interview
foreach ($values as $index => $token) {
if ($token->author == 0) {
foreach ($values as $index => $token)
{
if ($token->author == 0)
{
unset($values[$index]);
}
}
......@@ -117,11 +123,13 @@ class StudyController extends Controller
public function store(Request $request, $dummy = false)
{
if ($dummy != false) {
if ($dummy != false)
{
$userForStudy = User::where('id', $dummy)->first();
$request = new Request(config('utilities.dummyStudy1'));
} else $userForStudy = Auth::user();
if (!$request->has('name') || !$request->has('description')) {
if (!$request->has('name') || !$request->has('description'))
{
return response()->json('Data are not valid', 422);
}
$newStudy = new Study();
......@@ -143,32 +151,43 @@ class StudyController extends Controller
}
/**
* Save the tokens to the database, if any.
* @param Study $study
* @param Request $request
* @param $token
*/
public function saveTokens(Study $study, Request $request, &$token): void
{
foreach ($request->get('sorting')['tokens'] as $tokenToSave) {
if($request->get('sorting')['tokens']){
foreach ($request->get('sorting')['tokens'] as $tokenToSave)
{
Token::store($tokenToSave, $study);
}
}
}
/**
* Save the questions to database, if any.
* @param $questions
* @param $study
* @param bool $edit
*/
public function saveQuestionsAnswers($questions, $study, $edit = false)
{
if ($edit) {
foreach ($study->questions as $questionToReset) {
if ($edit)
{
foreach ($study->questions as $questionToReset)
{
Answer::where('question_id', '=', $questionToReset['id'])->delete();
Question::destroy($questionToReset['id']);
}
}
if (array_key_exists('question', $questions[0])) {
foreach ($questions as $questionToSave) {
$atLeastOneQuestion = array_key_exists('question', $questions[0]);
if ($atLeastOneQuestion)
{
foreach ($questions as $questionToSave)
{
$question = new Question();
$question->question = $questionToSave['question'];
$question->detail = $questions[0]['type'];
......@@ -180,13 +199,16 @@ class StudyController extends Controller
}
/**
* Save the answers for a given question.
* @param $questionToSave
* @param Question $question
*/
private function saveAnswers($questionToSave, Question $question): void
{
if ($questionToSave['ismultiple']) {
foreach ($questionToSave['answers'] as $answerToSave) {
if ($questionToSave['ismultiple'])
{
foreach ($questionToSave['answers'] as $answerToSave)
{
$answer = new Answer();
$answer->question_id = $question->id;
$answerJson = ['type' => 'multi', 'answer' => $answerToSave];
......@@ -194,8 +216,10 @@ class StudyController extends Controller
$answer->save();
}
}
if ($questionToSave['isonechoice']) {
foreach ($questionToSave['answers'] as $answerToSave) {
if ($questionToSave['isonechoice'])
{
foreach ($questionToSave['answers'] as $answerToSave)
{
$answer = new Answer();
$answer->question_id = $question->id;
$answerJson = ['type' => 'onechoice', 'answer' => $answerToSave];
......@@ -203,14 +227,16 @@ class StudyController extends Controller
$answer->save();
}
}
if ($questionToSave['isopen']) {
if ($questionToSave['isopen'])
{
$answer = new Answer();
$answerJson = ['type' => 'open', 'answer' => ''];
$answer->question_id = $question->id;
$answer->answer = $answerJson;
$answer->save();
}
if ($questionToSave['isscale']) {
if ($questionToSave['isscale'])
{
$answer = new Answer();
$answerJson = ['type' => 'scale', 'answer' => ['min' => $questionToSave['scalemin'], 'max' => $questionToSave['scalemax'], 'minlabel' => $questionToSave['minlabel'], 'maxlabel' => $questionToSave['maxlabel']]];
$answer->question_id = $question->id;
......@@ -247,11 +273,13 @@ class StudyController extends Controller
public function update(Study $study, Request $request)
{
$this->authorize($study);
if (!$request->has('name')) {
if (!$request->has('name'))
{
return response()->json('Data are not valid', 422);
}
$study = Study::where('id', '=', $request->input('id'))->with('questions')->first();
if (!$study->isEditable()) {
if (!$study->isEditable())
{
return back()->withInput();
}
// sorting
......@@ -280,7 +308,8 @@ class StudyController extends Controller
public function removeTokensFromStudy(Study $study): void
{
$available_tokens = $study->available_tokens()->pluck('tokens.id')->toArray();
foreach ($available_tokens as $tokensToDelete) {
foreach ($available_tokens as $tokensToDelete)
{
$to = Token::where('id', '=', $tokensToDelete)->first();
$study->tokens()->detach($to->id);
$to->delete();
......@@ -295,11 +324,13 @@ class StudyController extends Controller
public function destroy(Study $study, Request $request)
{
if (!auth()->user()->hasRole(['admin', 'supervisor'])) {
if (!auth()->user()->hasRole(['admin', 'supervisor']))
{
abort(403, 'You are not allowed to edit this study');
}
if (!auth()->user()->can('delete-studies', $study->id)) return response('You are not authorized to delete this study.', 403);
foreach ($study->interviews as $interview) {
foreach ($study->interviews as $interview)
{
File::delete($interview->sorting_screenshot);
$interview->answers()->detach();
$interview->answers()->delete();
......@@ -333,11 +364,11 @@ class StudyController extends Controller
public function deleteallbyuser(User $user, Request $request)
{
$studies = Study::where('user_id', $user->id)->get();
foreach ($studies as $study) {
foreach ($studies as $study)
{
$study->delete();
}
auth()->user()->addAction('delete all studies by user', $request->url(), 'user deleted studies for the user ' . $user->email);
return response()->json(['message' => 'Studies Deleted!'], 200);
}
}
......@@ -41,7 +41,7 @@ class Profile extends Model
* @var array
*/
protected $fillable = [
'name', 'address', 'workaddress', 'phonenumber1', 'phonenumber2',
'name', 'address', 'workaddress', 'phonenumber1', 'phonenumber2','newsletter',
];
public function user()
......
......@@ -2,8 +2,6 @@
namespace App;
use Auth;
use DB;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\User as Authenticatable;
......@@ -12,30 +10,29 @@ use Laratrust\Traits\LaratrustUserTrait;
/**
* App\User
*
* @property int $id
* @property string $email
* @property string $password
* @property string|null $remember_token
* @property string|null $last_login_date
* @property int|null $supervised_by
* @property string|null $password_token
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property string|null $email_verified_at
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Interview[] $interviews
* @property-read int|null $interviews_count
* @property int $id
* @property string $email
* @property string $password
* @property string|null $remember_token
* @property string|null $last_login_date
* @property int|null $supervised_by
* @property string|null $password_token
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon|null $deleted_at
* @property string|null $email_verified_at
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Interview[] $interviews
* @property-read int|null $interviews_count
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[] $notifications
* @property-read int|null $notifications_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Permission[] $permissions
* @property-read int|null $permissions_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Role[] $roles
* @property-read int|null $roles_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Study[] $rolesTeams
* @property-read int|null $roles_teams_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Study[] $studies
* @property-read int|null $studies_count
* @property-read int|null $notifications_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Permission[] $permissions
* @property-read int|null $permissions_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Role[] $roles
* @property-read int|null $roles_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Study[] $rolesTeams
* @property-read int|null $roles_teams_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Study[] $studies
* @property-read int|null $studies_count
* @method static \Illuminate\Database\Eloquent\Builder|\App\User newModelQuery()
* @method static \Illuminate\Database\Eloquent\Builder|\App\User newQuery()
* @method static \Illuminate\Database\Query\Builder|\App\User onlyTrashed()
......@@ -64,6 +61,7 @@ class User extends Authenticatable implements MustVerifyEmail
use LaratrustUserTrait;
use Notifiable;
use SoftDeletes;
/**
* The attributes that are mass assignable.
* @var array
......@@ -108,6 +106,22 @@ class User extends Authenticatable implements MustVerifyEmail
return in_array(13, $this->permissions()->pluck('id')->toArray());
}
public function profile()
{
return $this->hasOne(Profile::class);
}
/**
*
*/
public function addProfile($user)
{
$profile = new Profile();
$profile->user_id = $user->id;
$profile->save();
return $profile;
}
/**
* @param $name
* @param $url
......
<?php
return [
'newsletter_status' => [
'SUBSCRIBED' => 2,
'NOT SUBSCRIBED' => 1,
'NOT DECIDED' => 0,
]
];
......@@ -16,14 +16,13 @@ class CreateUsersProfilesTable extends Migration
Schema::create('users_profiles', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->references('id')->on('users')->onDelete('cascade');
$table->string('name', 255);
$table->string('address', 255);
$table->date('birthday');
$table->string('phonenumber1', 190);
$table->string('phonenumber2', 190);
$table->string('workaddress', 255);
$table->string('name', 255)->nullable();
$table->string('address', 255)->nullable();
$table->date('birthday')->nullable();
$table->string('phonenumber1', 190)->nullable();
$table->string('phonenumber2', 190)->nullable();
$table->string('workaddress', 255)->nullable();
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
......
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddNewsletterToUserProfiles extends Migration
{
public function up()
{
Schema::table('users_profiles', function (Blueprint $table)
{
$table->tinyInteger('newsletter')->default(0)->nullable();
});
}
public function down()
{
Schema::table('users_profiles', function (Blueprint $table)
{
//
});
}
}
This diff is collapsed.
......@@ -179,7 +179,7 @@
<b-field :label="trans('Number of tokens to be sorted')">
<b-numberinput controls-position="compact" type="is-light"
v-model="sorting.tokennumber"
id="numberoftokens" min="1" max="50" :editable="editable"
id="numberoftokens" min="0" max="40" :editable="editable"
steps="1"></b-numberinput>
</b-field>
</div>
......@@ -505,7 +505,7 @@
<input v-if="!isedit" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 focus:outline-none"
:class="{'is-loading' : loading}"
type="submit"
@click.prevent="createstudy()" :value="trans('Create new study')">
@click.prevent="savestudy()" :value="trans('Create new study')">
<input v-if="isedit" class="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 focus:outline-none"
:class="{'is-loading' : loading}"
type="submit"
......@@ -570,17 +570,12 @@
maxvalue: 1,
centerLabel: '',