@jaytee
1- the migration : for example if user name is foo http: bar this will return foo bar
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\User;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('verified')->default(User::UNVERIFIED_USER);
$table->string('verified_token')->nullable();
$table->string('admin')->default(User::REGULAR_USER);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
2- Laravel version : Laravel Framework 5.8.35
3-server specifications :
PHP Version => 7.2.24-0ubuntu0.18.04.1
PDO
PDO support => enabled
PDO drivers => mysql, pgsql
pdo_mysql
PDO Driver for MySQL => enabled
Client API version => mysqlnd 5.0.12-dev - 20150407 - $Id: 3591daad22de08524295e1bd073aceeff11e6579 $
Directive => Local Value => Master Value
pdo_mysql.default_socket => /var/run/mysqld/mysqld.sock => /var/run/mysqld/mysqld.sock
pdo_pgsql
PDO Driver for PostgreSQL => enabled
PostgreSQL(libpq) Version => 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1)
Module version => 7.2.24-0ubuntu0.18.04.1
Revision => $Id: 9c5f356c77143981d2e905e276e439501fe0f419 $
pgsql
PostgreSQL Support => enabled
PostgreSQL(libpq) Version => 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1)
PostgreSQL(libpq) => PostgreSQL 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0, 64-bit
Multibyte character support => enabled
SSL support => enabled
Active Persistent Links => 0
Active Links => 0
Directive => Local Value => Master Value
pgsql.allow_persistent => On => On
pgsql.auto_reset_persistent => Off => Off
pgsql.ignore_notice => Off => Off
pgsql.log_notice => Off => Off
pgsql.max_links => Unlimited => Unlimited
pgsql.max_persistent => Unlimited => Unlimited
4- it's in test not production
5- JS code:
<template><span>
<div aria-hidden="true"
aria-labelledby="addTrainingModalLabel"
class="modal fade"
id="addTrainingModal"
ref="addNewTrainingModal"
role="dialog"
tabindex="-1">
<div role="document" v-bind:class="{'modal-lg':modalLarge, 'modal-dialog':true}">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addTrainingModalLabel">{{modalTitle}}</h5>
<button aria-label="Close" class="close" data-dismiss="modal" ref="closeAddModal" type="button">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" v-if="actionButton==='showAddTraining'">
<add-training
ref="addNewTrainingData"
:login-user-id="currentUserId"
:authrz-external-training-edit="authrzExternalTrainingEdit"
></add-training>
</div>
<div class="modal-footer">
<button class="btn btn-secondary btn-square" data-dismiss="modal" type="button">Close</button>
<button @click="createTraining()" class="btn btn-success btn-square" type="button"
v-if="actionButton==='showAddTraining'"
><i class="fa fa-plus"></i> Add
</button>
<button class="btn btn-primary btn-square" data-dismiss="modal" type="button"
v-if="actionButton==='action2'">action2
</button>
</div>
</div>
</div>
</div>
<div aria-hidden="true"
aria-labelledby="deleteTrainingModalLabel"
class="modal fade"
id="deleteTrainingModal"
ref="deleteTrainingModal"
role="dialog"
tabindex="-1">
<div role="document" v-bind:class="{'modal-lg':modalLarge, 'modal-dialog':true}">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteTrainingModalLabel">{{modalTitle |sentenceCutter(3)}}</h5>
<button aria-label="Close" class="close" data-dismiss="modal" ref="closedeleteModal"
type="button">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure to delete?
</div>
<div class="modal-footer">
<button class="btn btn-secondary btn-square" data-dismiss="modal" type="button">Close</button>
<button @click="deleteTraining()" class="btn btn-danger btn-square" data-dismiss="modal"
type="button"
v-if="actionButton==='showDeleteTraining'"><i class="fa fa-remove"></i> Delete
</button>
</div>
</div>
</div>
</div>
<div aria-hidden="true"
aria-labelledby="editTrainingModalLabel"
class="modal fade"
id="editTrainingModal"
role="dialog"
tabindex="-1">
<div role="document" v-bind:class="{'modal-lg':modalLarge, 'modal-dialog':true}">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editTrainingModalLabel">{{modalTitle}}</h5>
<button aria-label="Close" class="close" data-dismiss="modal" ref="closeEditModal"
type="button">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" v-if="actionButton==='showEditTraining'">
<edit-training :key="componentKey"
:authrz-external-training-edit="authrzExternalTrainingEdit"
:training-id-param="trainingDetailId"
:login-user-id="currentUserId"
ref="editTrainingData"></edit-training>
</div>
<div class="modal-footer">
<button class="btn btn-secondary btn-square" data-dismiss="modal" type="button">Close</button>
<button @click="editTraining()" class="btn btn-primary btn-square" type="button"
v-if="actionButton==='showEditTraining'"
><i class="fa fa-floppy-o"></i> Save
</button>
<button class="btn btn-danger btn-square" data-dismiss="modal" type="button"
v-if="actionButton==='showDeleteTraining'"><i class="fa fa-remove"></i> Delete
</button>
</div>
</div>
</div>
</div>
<ul class="nav nav-tabs" id="myTab" role="tablist">
<li class="nav-item">
<a aria-controls="Company"
aria-selected="true"
class="nav-link active"
data-toggle="tab"
href="#tab1"
id="tab1-tab"
ref="tab1"
role="tab">As participant
</a>
</li>
<li class="nav-item">
<a
aria-controls="other"
aria-selected="false"
class="nav-link"
data-toggle="tab"
href="#tab2"
id="tab2-tab"
role="tab">As trainer</a>
</li>
</ul>
<div class="tab-content" id="myTabContent">
<div aria-labelledby="tab1-tab" class="tab-pane fade show active" id="tab1" role="tabpanel">
<v-server-table :columns="columnsParticipants" :options="options" ref="trainingsTableTab1"
url="/api/trainings?meAsParticipant">
<span slot="actions" slot-scope="{row}">
<button
@click="showTrainingEdit(row.id)"
class="btn btn-primary btn-square btn-sm"
data-target="#editTrainingModal"
data-toggle="modal" v-if="authrzTrainingsEdit"
>
<i aria-hidden="true" class="fa fa-pencil"></i>
Edit</button>
<button
@click="showDeleteTraining(row)"
class="btn btn-danger btn-square btn-sm"
data-target="#deleteTrainingModal"
data-toggle="modal"
v-if="authrzTrainingsEdit"
><i aria-hidden="true"
class="fa fa-times"></i> Delete</button>
</span>
<span slot="external_urls" slot-scope="{row}">
<p v-for="link in row.external_urls">
{{ link.name }} {{link.url}}
</p>
</span>
</v-server-table>
</div>
<div aria-labelledby="tab2-tab" class="tab-pane fade" id="tab2" role="tabpanel">
<v-server-table :columns="columnsTrainers" :options="options" ref="trainingsTableTab2"
url="/api/trainings?meAsTrainer">
<span slot="actions" slot-scope="{row}">
<span slot="trainers" slot-scope="{row}">
<ul id="trainerstmp">
<li v-for="trainer in row.trainers">
{{ trainer.name }}
</li>
</ul>
</span>
<span v-if="row.intern || authrzExternalTrainingEdit" >
<button
@click="showTrainingEdit(row.id)"
class="btn btn-primary btn-square btn-sm"
data-target="#editTrainingModal"
data-toggle="modal" v-if="authrzTrainingsEdit"
>
<i aria-hidden="true" class="fa fa-pencil"></i>
Edit</button>
<button
@click="showDeleteTraining(row)"
class="btn btn-danger btn-square btn-sm"
data-target="#deleteTrainingModal"
data-toggle="modal"
v-if="authrzTrainingsEdit"
><i aria-hidden="true"
class="fa fa-times"></i> Delete</button>
</span>
</span>
<span slot="participants" slot-scope="{row}">
<ul id="participantsTab1">
<li v-for="participant in row.participants">
{{ participant.name }}
</li>
</ul>
</span>
<span slot="trainers" slot-scope="{row}">
<ul id="participantsTab2">
<li v-for="trainer in row.trainers">
{{ trainer.name }}
</li>
</ul>
</span>
<span slot="external_urls" slot-scope="{row}">
<p v-for="link in row.external_urls">
{{ link.name }} {{link.url}}
</p>
</span>
</v-server-table>
<button class="btn btn-square btn-success pull-left"
data-target="#addTrainingModal"
data-toggle="modal" type="button" v-if="authrzTrainingsEdit"
v-on:click="showAddTraining()"><i aria-hidden="true" class="fa fa-plus"></i> Add training
</button>
<p class="pb-3"></p>
</div>
</div>
</span></template>
<script>
import addTraining from "./addTraining";
import editTraining from "./editTraining";
export default {
props: ['authrzTrainingsEdit','loginUserId','authrzExternalTrainingEdit'],
name: "trainings",
components: {
'add-training': addTraining,
'edit-training': editTraining,
},
data() {
return {
componentKey: 0,
actionButton: '',
modalTitle: "modal title",
modalContent: "modal content",
modalLarge: false,
deletedTrainingId: null,
teamLeaderOfWithDescendants: null,
currentUserId: null,
columnsParticipants: ['id', 'title','begin_date', 'levelName', 'certified','certification_expired_date','certification_number','external_urls'],
columnsTrainers: ['id', 'title', 'begin_date', 'levelName', 'certified','external_urls', 'actions'],
dateColumns: ['begin_date', 'end_date'],
options: {
//https://github.com/matfish2/vue-tables-2/blob/master/lib/config/defaults.js
texts: {
filter: "",
filterPlaceholder: "Search",
limit: "",
},
initialPage: 1,
sortable: ['id'],
filterable: ['id'],
perPage: 5,
perPageValues: [5, 10, 20, 50, 100],
requestAdapter(data) {
return {
query: data.query,
limit: data.limit,
page: data.page,
sort: data.orderBy ? data.orderBy : 'id',
direction: data.ascending ? 'asc' : 'desc'
}
},
responseAdapter({data}) {
return {
data: data.data,
count: data.total,
teamLeaderOfWithDescendants: data.teamLeaderOfWithDescendants
}
},
templates: {
certified(h, row) {
return (row.certified === true) ? '✔' : '';
},
begin_date(h, row) {
return moment(row.begin_date).format('DD/MM/YYYY') + " to " + moment(row.end_date).format('DD/MM/YYYY');
},
certification_expired_date(h, row) {
if(!moment(row.certification_expired_date).isValid())return '';
let certificationExpiredDate = moment(row.certification_expired_date).format('DD/MM/YYYY') ;
return certificationExpiredDate;
},
},
headings: {
id: 'Id',
description: 'Description',
begin_date: 'Date',
title: 'Title',
levelName: 'Level',
certified: 'Certified',
participants: 'Participants',
trainers: 'Trainers',
actions: 'Actions',
certification_expired_date:'Exp date',
certification_number:'Cert number',
external_urls:'Links',
}
}
}
},
mounted() {
$("input:text:visible:first").focus();
this.getFullTeamDescendants();
},
methods: {
showTrainingEdit(trainingId) {
this.componentKey++;
this.trainingDetailId = trainingId;
this.modalLarge = true;
this.modalTitle = "Edit training";
this.actionButton = "showEditTraining";
},
deleteTraining() {
axios.delete('/api/trainings/' + this.deletedTrainingId)
.then(response => {
if (response.data === 'ok') {
this.$refs.trainingsTableTab2.refresh();
this.$refs.trainingsTableTab1.refresh();
this.trainingDeleteConfirmation()
}
});
},
showDeleteTraining(row) {
this.deletedTrainingId = row.id;
this.modalLarge = false;
this.modalTitle = "Training: " + row.title;
this.actionButton = "showDeleteTraining";
},
showAddTraining() {
this.$root.$emit('clearForm');
this.modalLarge = true;
this.modalTitle = "Add new training";
this.actionButton = "showAddTraining";
},
createTraining() {
let newTraining = this.$refs.addNewTrainingData.newTraining;
//(newTraining.defaultTrainer !== null)?newTraining.trainers.push(newTraining.defaultTrainer):''
console.log(newTraining);
axios.post('/api/trainings',
newTraining
)
.then((response) => {
this.$refs.closeAddModal.click();
this.trainingCreatedConfirmation();
this.$refs.trainingsTableTab2.refresh();
this.$refs.trainingsTableTab1.refresh();
})
.catch(error => {
if (error.response.status === 422) {
this.$refs.addNewTrainingData.errors = error.response.data.errors;
}
});
},
trainingByUser(event) {
this.options.requestAdapter = (data) => {
return {
userId: event.target.value,
query: data.query,
limit: data.limit,
page: data.page,
sort: data.orderBy ? data.orderBy : 'id',
direction: data.ascending ? 'asc' : 'desc'
}
};
this.$refs.trainingsTableTabe2.refresh();
},
getFullTeamDescendants() {
axios.get(`api/trainings?fullTeamDescendants`)
.then(response => {
this.teamLeaderOfWithDescendants = response.data.data.sort((a, b) => (a.user_full_name > b.user_full_name) ? 1 : -1);
this.currentUserId = response.data.user_id;
console.log(this.teamLeaderOfWithDescendants);
});
},
editTraining() {
let updatedTraining = this.$refs.editTrainingData.updateTraining;
axios.post('/api/trainings/' + updatedTraining.id,
updatedTraining
)
.then((response) => {
this.$refs.trainingsTableTab2.refresh();
this.$refs.trainingsTableTab1.refresh();
this.$refs.closeEditModal.click();
this.trainingUpdatedConfirmation();
//this.showTrainingEdit(0);
})
.catch(error => {
if (error.response.status === 422) {
this.$refs.editTrainingData.errors = error.response.data.errors;
}
});
}
}
,
notifications: {
trainingUpdatedConfirmation: {
title: 'Training',
message:
'Training updated with success',
type:
'success',
timeout:
2000
}
,
trainingCreatedConfirmation: {
title: 'Training',
message:
'Training added with success',
type:
'success',
timeout:
2000
}
,
trainingDeleteConfirmation: {
title: 'Training',
message:
'Training deleted with success',
type:
'success',
timeout:
2000
}
,
}
}
</script>
<style scoped>
</style>
Thanks