forked from miguel456/rbrecruiter
RSM-6 Team features
This commit is contained in:
parent
7c0c244e21
commit
75f4404259
189
app/Http/Controllers/TeamController.php
Normal file
189
app/Http/Controllers/TeamController.php
Normal file
@ -0,0 +1,189 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\EditTeamRequest;
|
||||
use App\Http\Requests\NewTeamRequest;
|
||||
use App\Http\Requests\SendInviteRequest;
|
||||
use App\Mail\InviteToTeam;
|
||||
use App\Team;
|
||||
use App\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Mpociot\Teamwork\Facades\Teamwork;
|
||||
use Mpociot\Teamwork\TeamInvite;
|
||||
|
||||
class TeamController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('dashboard.teams.teams')
|
||||
->with('teams', Team::all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(NewTeamRequest $request)
|
||||
{
|
||||
Team::create([
|
||||
'name' => $request->teamName,
|
||||
'owner_id' => Auth::user()->id
|
||||
]);
|
||||
|
||||
$request->session()->flash('success', 'Team successfully created.');
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Team $team)
|
||||
{
|
||||
return view('dashboard.teams.edit-team')
|
||||
->with('team', $team)
|
||||
->with('users', User::all());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(EditTeamRequest $request, Team $team)
|
||||
{
|
||||
$team->description = $request->teamDescription;
|
||||
$team->openJoin = $request->joinType;
|
||||
|
||||
$team->save();
|
||||
|
||||
$request->session()->flash('success', 'Team edited successfully.');
|
||||
return redirect()->to(route('teams.index'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
public function invite(SendInviteRequest $request, Team $team)
|
||||
{
|
||||
$user = User::findOrFail($request->user);
|
||||
|
||||
if (!$team->openJoin)
|
||||
{
|
||||
|
||||
if (!Teamwork::hasPendingInvite($user->email, $team))
|
||||
{
|
||||
Teamwork::inviteToTeam($user, $team, function(TeamInvite $invite) use ($user) {
|
||||
Mail::to($user)->send(new InviteToTeam($invite));
|
||||
});
|
||||
|
||||
$request->session()->flash('success', 'Invite sent! They can now accept or deny it.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'This user has already been invited.');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'You can\'t invite users to public teams.');
|
||||
}
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function processInviteAction(Request $request, $action, $token)
|
||||
{
|
||||
|
||||
switch($action)
|
||||
{
|
||||
case 'accept':
|
||||
|
||||
$invite = Teamwork::getInviteFromAcceptToken($token);
|
||||
|
||||
if ($invite && $invite->user->is(Auth::user()))
|
||||
{
|
||||
Teamwork::acceptInvite($invite);
|
||||
$request->session()->flash('success', 'Invite accepted! You have now joined ' . $invite->team->name . '.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'Invalid or expired invite URL.');
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'deny':
|
||||
|
||||
$invite = Teamwork::getInviteFromDenyToken($token);
|
||||
|
||||
if ($invite && $invite->user->is(Auth::user()))
|
||||
{
|
||||
Teamwork::denyInvite($invite);
|
||||
$request->session()->flash('success', 'Invite denied! Ask for another invite if this isn\'t what you meant.');
|
||||
}
|
||||
else
|
||||
{
|
||||
$request->session()->flash('error', 'Invalid or expired invite URL.');
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$request->session()->flash('error', 'Sorry, but the invite URL you followed was malformed. Try asking for another invite, or submit a bug report.');
|
||||
|
||||
|
||||
}
|
||||
|
||||
// This page will show the user's current teams
|
||||
return redirect()->to(route('teams.index'));
|
||||
|
||||
}
|
||||
}
|
31
app/Http/Requests/EditTeamRequest.php
Normal file
31
app/Http/Requests/EditTeamRequest.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class EditTeamRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'teamDescription' => 'required|string|max:200',
|
||||
'joinType' => 'required|boolean'
|
||||
];
|
||||
}
|
||||
}
|
30
app/Http/Requests/NewTeamRequest.php
Normal file
30
app/Http/Requests/NewTeamRequest.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class NewTeamRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'teamName' => 'required|max:200|string'
|
||||
];
|
||||
}
|
||||
}
|
30
app/Http/Requests/SendInviteRequest.php
Normal file
30
app/Http/Requests/SendInviteRequest.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class SendInviteRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'user' => 'required|integer'
|
||||
];
|
||||
}
|
||||
}
|
55
app/Mail/InviteToTeam.php
Normal file
55
app/Mail/InviteToTeam.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Mpociot\Teamwork\TeamInvite;
|
||||
|
||||
class InviteToTeam extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
||||
public $teamName;
|
||||
|
||||
|
||||
public $name;
|
||||
|
||||
|
||||
public $inviterName;
|
||||
|
||||
|
||||
public $denyToken;
|
||||
|
||||
|
||||
public $acceptToken;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(TeamInvite $invite)
|
||||
{
|
||||
$this->teamName = $invite->team->name;
|
||||
$this->name = $invite->user->name;
|
||||
$this->inviterName = $invite->inviter->name;
|
||||
$this->acceptToken = $invite->accept_token;
|
||||
$this->denyToken = $invite->deny_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the message.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
return $this
|
||||
->subject('You have just been invited to ' . $this->teamName)
|
||||
->view('mail.invited-to-team');
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ class Team extends TeamworkTeam
|
||||
{
|
||||
public $fillable = [
|
||||
'owner_id',
|
||||
'name'
|
||||
'name',
|
||||
'description',
|
||||
'openJoin'
|
||||
];
|
||||
}
|
||||
|
@ -5,12 +5,16 @@ namespace App;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Mpociot\Teamwork\Traits\UsedByTeams;
|
||||
|
||||
|
||||
use GrahamCampbell\Markdown\Facades\Markdown;
|
||||
|
||||
|
||||
class Vacancy extends Model
|
||||
{
|
||||
use UsedByTeams;
|
||||
|
||||
public $fillable = [
|
||||
|
||||
'permissionGroupName',
|
||||
|
@ -535,6 +535,17 @@ return [
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'CheckboxValues',
|
||||
'active' => true,
|
||||
'files' => [
|
||||
[
|
||||
'type' => 'js',
|
||||
'asset' => false,
|
||||
'location' => '/js/switches.js'
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'AuthCustomisations',
|
||||
'active' => true,
|
||||
@ -545,6 +556,22 @@ return [
|
||||
'location' => '/css/authpages.css'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
[
|
||||
'name' => 'BootstrapToggleButton',
|
||||
'active' => true,
|
||||
'files' => [
|
||||
[
|
||||
'type' => 'css',
|
||||
'asset' => false,
|
||||
'location' => 'https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css'
|
||||
],
|
||||
[
|
||||
'type' => 'js',
|
||||
'asset' => false,
|
||||
'location' => 'https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js'
|
||||
]
|
||||
]
|
||||
]
|
||||
],
|
||||
];
|
||||
|
40
database/migrations/2020_10_02_112730_add_team_details.php
Normal file
40
database/migrations/2020_10_02_112730_add_team_details.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddTeamDetails extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table(config('teamwork.teams_table'), function(Blueprint $table){
|
||||
|
||||
$table->text('description')->after('name')->nullable();
|
||||
$table->enum('status', ['ACTIVE','SUSPENDED'])->after('description');
|
||||
$table->boolean('openJoin')->default(false)->after('status');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table(config('teamwork.teams_table'), function(Blueprint $table){
|
||||
|
||||
$table->dropColumn('description');
|
||||
$table->dropColumn('status');
|
||||
$table->dropColumn('openJoin');
|
||||
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddTeamIDToVacancy extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('vacancy', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('vacancy', function (Blueprint $table) {
|
||||
//
|
||||
});
|
||||
}
|
||||
}
|
3503
package-lock.json
generated
3503
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"postinstall": "npm run prod",
|
||||
"postinstall": "npm run prod",
|
||||
"dev": "npm run development",
|
||||
"development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch": "npm run development -- --watch",
|
||||
|
202
public/css/app.css
vendored
202
public/css/app.css
vendored
@ -1,9 +1,9 @@
|
||||
@import url(https://fonts.googleapis.com/css?family=Nunito);@charset "UTF-8";
|
||||
|
||||
/*!
|
||||
* Bootstrap v4.4.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2019 The Bootstrap Authors
|
||||
* Copyright 2011-2019 Twitter, Inc.
|
||||
* Bootstrap v4.5.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors
|
||||
* Copyright 2011-2020 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
@ -202,6 +202,7 @@ pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
-ms-overflow-style: scrollbar;
|
||||
}
|
||||
|
||||
figure {
|
||||
@ -269,6 +270,10 @@ select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
@ -301,13 +306,6 @@ input[type=checkbox] {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
input[type=date],
|
||||
input[type=time],
|
||||
input[type=datetime-local],
|
||||
input[type=month] {
|
||||
-webkit-appearance: listbox;
|
||||
}
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
@ -749,6 +747,7 @@ pre code {
|
||||
.col {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@ -956,6 +955,7 @@ pre code {
|
||||
.col-sm {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@ -1168,6 +1168,7 @@ pre code {
|
||||
.col-md {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@ -1380,6 +1381,7 @@ pre code {
|
||||
.col-lg {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@ -1592,6 +1594,7 @@ pre code {
|
||||
.col-xl {
|
||||
flex-basis: 0;
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
@ -2187,11 +2190,6 @@ pre code {
|
||||
box-shadow: 0 0 0 0.2rem rgba(52, 144, 220, 0.25);
|
||||
}
|
||||
|
||||
.form-control::-webkit-input-placeholder {
|
||||
color: #6c757d;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.form-control::-moz-placeholder {
|
||||
color: #6c757d;
|
||||
opacity: 1;
|
||||
@ -2218,6 +2216,15 @@ pre code {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input[type=date].form-control,
|
||||
input[type=time].form-control,
|
||||
input[type=datetime-local].form-control,
|
||||
input[type=month].form-control {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
select.form-control:focus::-ms-value {
|
||||
color: #495057;
|
||||
background-color: #fff;
|
||||
@ -2653,7 +2660,6 @@ textarea.form-control.is-invalid {
|
||||
color: #212529;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
@ -2689,6 +2695,10 @@ textarea.form-control.is-invalid {
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.btn:not(:disabled):not(.disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
a.btn.disabled,
|
||||
fieldset:disabled a.btn {
|
||||
pointer-events: none;
|
||||
@ -3324,7 +3334,6 @@ fieldset:disabled a.btn {
|
||||
.btn-link:focus,
|
||||
.btn-link.focus {
|
||||
text-decoration: underline;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.btn-link:disabled,
|
||||
@ -3789,7 +3798,8 @@ input[type=button].btn-block {
|
||||
.input-group > .custom-select,
|
||||
.input-group > .custom-file {
|
||||
position: relative;
|
||||
flex: 1 1 0%;
|
||||
flex: 1 1 auto;
|
||||
width: 1%;
|
||||
min-width: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@ -4889,7 +4899,7 @@ input[type=button].btn-block {
|
||||
}
|
||||
|
||||
.navbar-light .navbar-toggler-icon {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(0, 0, 0, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%280, 0, 0, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
.navbar-light .navbar-text {
|
||||
@ -4940,7 +4950,7 @@ input[type=button].btn-block {
|
||||
}
|
||||
|
||||
.navbar-dark .navbar-toggler-icon {
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba(255, 255, 255, 0.5)' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='30' height='30' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.5%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
|
||||
}
|
||||
|
||||
.navbar-dark .navbar-text {
|
||||
@ -4973,14 +4983,21 @@ input[type=button].btn-block {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.card > .list-group:first-child .list-group-item:first-child {
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem;
|
||||
.card > .list-group {
|
||||
border-top: inherit;
|
||||
border-bottom: inherit;
|
||||
}
|
||||
|
||||
.card > .list-group:last-child .list-group-item:last-child {
|
||||
border-bottom-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
.card > .list-group:first-child {
|
||||
border-top-width: 0;
|
||||
border-top-left-radius: calc(0.25rem - 1px);
|
||||
border-top-right-radius: calc(0.25rem - 1px);
|
||||
}
|
||||
|
||||
.card > .list-group:last-child {
|
||||
border-bottom-width: 0;
|
||||
border-bottom-right-radius: calc(0.25rem - 1px);
|
||||
border-bottom-left-radius: calc(0.25rem - 1px);
|
||||
}
|
||||
|
||||
.card-body {
|
||||
@ -5196,6 +5213,10 @@ input[type=button].btn-block {
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.breadcrumb-item {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item {
|
||||
padding-left: 0.5rem;
|
||||
}
|
||||
@ -5667,6 +5688,7 @@ a.badge-dark.focus {
|
||||
display: flex;
|
||||
height: 1rem;
|
||||
overflow: hidden;
|
||||
line-height: 0;
|
||||
font-size: 0.675rem;
|
||||
background-color: #e9ecef;
|
||||
border-radius: 0.25rem;
|
||||
@ -5721,6 +5743,7 @@ a.badge-dark.focus {
|
||||
flex-direction: column;
|
||||
padding-left: 0;
|
||||
margin-bottom: 0;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.list-group-item-action {
|
||||
@ -5751,13 +5774,13 @@ a.badge-dark.focus {
|
||||
}
|
||||
|
||||
.list-group-item:first-child {
|
||||
border-top-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0.25rem;
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
}
|
||||
|
||||
.list-group-item:last-child {
|
||||
border-bottom-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-bottom-right-radius: inherit;
|
||||
border-bottom-left-radius: inherit;
|
||||
}
|
||||
|
||||
.list-group-item.disabled,
|
||||
@ -5787,26 +5810,26 @@ a.badge-dark.focus {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.list-group-horizontal .list-group-item:first-child {
|
||||
.list-group-horizontal > .list-group-item:first-child {
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal .list-group-item:last-child {
|
||||
.list-group-horizontal > .list-group-item:last-child {
|
||||
border-top-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal .list-group-item.active {
|
||||
.list-group-horizontal > .list-group-item.active {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal .list-group-item + .list-group-item {
|
||||
.list-group-horizontal > .list-group-item + .list-group-item {
|
||||
border-top-width: 1px;
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal .list-group-item + .list-group-item.active {
|
||||
.list-group-horizontal > .list-group-item + .list-group-item.active {
|
||||
margin-left: -1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
@ -5816,26 +5839,26 @@ a.badge-dark.focus {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.list-group-horizontal-sm .list-group-item:first-child {
|
||||
.list-group-horizontal-sm > .list-group-item:first-child {
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-sm .list-group-item:last-child {
|
||||
.list-group-horizontal-sm > .list-group-item:last-child {
|
||||
border-top-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-sm .list-group-item.active {
|
||||
.list-group-horizontal-sm > .list-group-item.active {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-sm .list-group-item + .list-group-item {
|
||||
.list-group-horizontal-sm > .list-group-item + .list-group-item {
|
||||
border-top-width: 1px;
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-sm .list-group-item + .list-group-item.active {
|
||||
.list-group-horizontal-sm > .list-group-item + .list-group-item.active {
|
||||
margin-left: -1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
@ -5846,26 +5869,26 @@ a.badge-dark.focus {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.list-group-horizontal-md .list-group-item:first-child {
|
||||
.list-group-horizontal-md > .list-group-item:first-child {
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-md .list-group-item:last-child {
|
||||
.list-group-horizontal-md > .list-group-item:last-child {
|
||||
border-top-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-md .list-group-item.active {
|
||||
.list-group-horizontal-md > .list-group-item.active {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-md .list-group-item + .list-group-item {
|
||||
.list-group-horizontal-md > .list-group-item + .list-group-item {
|
||||
border-top-width: 1px;
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-md .list-group-item + .list-group-item.active {
|
||||
.list-group-horizontal-md > .list-group-item + .list-group-item.active {
|
||||
margin-left: -1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
@ -5876,26 +5899,26 @@ a.badge-dark.focus {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.list-group-horizontal-lg .list-group-item:first-child {
|
||||
.list-group-horizontal-lg > .list-group-item:first-child {
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-lg .list-group-item:last-child {
|
||||
.list-group-horizontal-lg > .list-group-item:last-child {
|
||||
border-top-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-lg .list-group-item.active {
|
||||
.list-group-horizontal-lg > .list-group-item.active {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-lg .list-group-item + .list-group-item {
|
||||
.list-group-horizontal-lg > .list-group-item + .list-group-item {
|
||||
border-top-width: 1px;
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-lg .list-group-item + .list-group-item.active {
|
||||
.list-group-horizontal-lg > .list-group-item + .list-group-item.active {
|
||||
margin-left: -1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
@ -5906,42 +5929,40 @@ a.badge-dark.focus {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.list-group-horizontal-xl .list-group-item:first-child {
|
||||
.list-group-horizontal-xl > .list-group-item:first-child {
|
||||
border-bottom-left-radius: 0.25rem;
|
||||
border-top-right-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-xl .list-group-item:last-child {
|
||||
.list-group-horizontal-xl > .list-group-item:last-child {
|
||||
border-top-right-radius: 0.25rem;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-xl .list-group-item.active {
|
||||
.list-group-horizontal-xl > .list-group-item.active {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-xl .list-group-item + .list-group-item {
|
||||
.list-group-horizontal-xl > .list-group-item + .list-group-item {
|
||||
border-top-width: 1px;
|
||||
border-left-width: 0;
|
||||
}
|
||||
|
||||
.list-group-horizontal-xl .list-group-item + .list-group-item.active {
|
||||
.list-group-horizontal-xl > .list-group-item + .list-group-item.active {
|
||||
margin-left: -1px;
|
||||
border-left-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-flush .list-group-item {
|
||||
border-right-width: 0;
|
||||
border-left-width: 0;
|
||||
.list-group-flush {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.list-group-flush .list-group-item:first-child {
|
||||
border-top-width: 0;
|
||||
.list-group-flush > .list-group-item {
|
||||
border-width: 0 0 1px;
|
||||
}
|
||||
|
||||
.list-group-flush:last-child .list-group-item:last-child {
|
||||
.list-group-flush > .list-group-item:last-child {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
|
||||
@ -6105,9 +6126,6 @@ button.close {
|
||||
padding: 0;
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
a.close.disabled {
|
||||
@ -6234,6 +6252,9 @@ a.close.disabled {
|
||||
.modal-dialog-centered::before {
|
||||
display: block;
|
||||
height: calc(100vh - 1rem);
|
||||
height: -webkit-min-content;
|
||||
height: -moz-min-content;
|
||||
height: min-content;
|
||||
content: "";
|
||||
}
|
||||
|
||||
@ -6351,6 +6372,9 @@ a.close.disabled {
|
||||
|
||||
.modal-dialog-centered::before {
|
||||
height: calc(100vh - 3.5rem);
|
||||
height: -webkit-min-content;
|
||||
height: -moz-min-content;
|
||||
height: min-content;
|
||||
}
|
||||
|
||||
.modal-sm {
|
||||
@ -6900,6 +6924,7 @@ a.close.disabled {
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -6910,6 +6935,7 @@ a.close.disabled {
|
||||
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@ -8201,6 +8227,27 @@ button.bg-dark:focus {
|
||||
}
|
||||
}
|
||||
|
||||
.user-select-all {
|
||||
-webkit-user-select: all !important;
|
||||
-moz-user-select: all !important;
|
||||
-ms-user-select: all !important;
|
||||
user-select: all !important;
|
||||
}
|
||||
|
||||
.user-select-auto {
|
||||
-webkit-user-select: auto !important;
|
||||
-moz-user-select: auto !important;
|
||||
-ms-user-select: auto !important;
|
||||
user-select: auto !important;
|
||||
}
|
||||
|
||||
.user-select-none {
|
||||
-webkit-user-select: none !important;
|
||||
-moz-user-select: none !important;
|
||||
-ms-user-select: none !important;
|
||||
user-select: none !important;
|
||||
}
|
||||
|
||||
.overflow-auto {
|
||||
overflow: auto !important;
|
||||
}
|
||||
@ -8357,18 +8404,6 @@ button.bg-dark:focus {
|
||||
height: 100vh !important;
|
||||
}
|
||||
|
||||
.stretched-link::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
pointer-events: auto;
|
||||
content: "";
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.m-0 {
|
||||
margin: 0 !important;
|
||||
}
|
||||
@ -10537,6 +10572,18 @@ button.bg-dark:focus {
|
||||
}
|
||||
}
|
||||
|
||||
.stretched-link::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
pointer-events: auto;
|
||||
content: "";
|
||||
background-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.text-monospace {
|
||||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace !important;
|
||||
}
|
||||
@ -10768,8 +10815,7 @@ a.text-dark:focus {
|
||||
}
|
||||
|
||||
.text-break {
|
||||
word-break: break-word !important;
|
||||
overflow-wrap: break-word !important;
|
||||
word-wrap: break-word !important;
|
||||
}
|
||||
|
||||
.text-reset {
|
||||
|
5
public/css/mixed.css
vendored
5
public/css/mixed.css
vendored
@ -1050,6 +1050,7 @@ Lots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css
|
||||
/* don't display any button-related controls */
|
||||
}
|
||||
}
|
||||
|
||||
/* DayGridView
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
/* day row structure */
|
||||
@ -1128,6 +1129,7 @@ Lots taken from Flatly (MIT): https://bootswatch.com/4/flatly/bootstrap.css
|
||||
display: inline-block;
|
||||
min-width: 1.25em;
|
||||
}
|
||||
|
||||
/* Scroller
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
.fc-scroller-clip {
|
||||
@ -1479,6 +1481,7 @@ TODO: figure out better styling
|
||||
.fc-rtl .fc-timeline-event.fc-not-start:before {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
@charset "UTF-8";
|
||||
/* TimeGridView all-day area
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
@ -1788,6 +1791,7 @@ be a descendant of the grid when it is being dragged.
|
||||
border-top-color: transparent;
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
/* List View
|
||||
--------------------------------------------------------------------------------------------------*/
|
||||
/* possibly reusable */
|
||||
@ -1906,6 +1910,7 @@ be a descendant of the grid when it is being dragged.
|
||||
/* theme will provide own background */
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.flatpickr-calendar{background:transparent;opacity:0;display:none;text-align:center;visibility:hidden;padding:0;-webkit-animation:none;animation:none;direction:ltr;border:0;font-size:14px;line-height:24px;border-radius:5px;position:absolute;width:307.875px;-webkit-box-sizing:border-box;box-sizing:border-box;-ms-touch-action:manipulation;touch-action:manipulation;background:#fff;-webkit-box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08);box-shadow:1px 0 0 #e6e6e6,-1px 0 0 #e6e6e6,0 1px 0 #e6e6e6,0 -1px 0 #e6e6e6,0 3px 13px rgba(0,0,0,0.08);}.flatpickr-calendar.open,.flatpickr-calendar.inline{opacity:1;max-height:640px;visibility:visible}.flatpickr-calendar.open{display:inline-block;z-index:99999}.flatpickr-calendar.animate.open{-webkit-animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1);animation:fpFadeInDown 300ms cubic-bezier(.23,1,.32,1)}.flatpickr-calendar.inline{display:block;position:relative;top:2px}.flatpickr-calendar.static{position:absolute;top:calc(100% + 2px);}.flatpickr-calendar.static.open{z-index:999;display:block}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+1) .flatpickr-day.inRange:nth-child(7n+7){-webkit-box-shadow:none !important;box-shadow:none !important}.flatpickr-calendar.multiMonth .flatpickr-days .dayContainer:nth-child(n+2) .flatpickr-day.inRange:nth-child(7n+1){-webkit-box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6;box-shadow:-2px 0 0 #e6e6e6,5px 0 0 #e6e6e6}.flatpickr-calendar .hasWeeks .dayContainer,.flatpickr-calendar .hasTime .dayContainer{border-bottom:0;border-bottom-right-radius:0;border-bottom-left-radius:0}.flatpickr-calendar .hasWeeks .dayContainer{border-left:0}.flatpickr-calendar.showTimeInput.hasTime .flatpickr-time{height:40px;border-top:1px solid #e6e6e6}.flatpickr-calendar.noCalendar.hasTime .flatpickr-time{height:auto}.flatpickr-calendar:before,.flatpickr-calendar:after{position:absolute;display:block;pointer-events:none;border:solid transparent;content:'';height:0;width:0;left:22px}.flatpickr-calendar.rightMost:before,.flatpickr-calendar.rightMost:after{left:auto;right:22px}.flatpickr-calendar:before{border-width:5px;margin:0 -5px}.flatpickr-calendar:after{border-width:4px;margin:0 -4px}.flatpickr-calendar.arrowTop:before,.flatpickr-calendar.arrowTop:after{bottom:100%}.flatpickr-calendar.arrowTop:before{border-bottom-color:#e6e6e6}.flatpickr-calendar.arrowTop:after{border-bottom-color:#fff}.flatpickr-calendar.arrowBottom:before,.flatpickr-calendar.arrowBottom:after{top:100%}.flatpickr-calendar.arrowBottom:before{border-top-color:#e6e6e6}.flatpickr-calendar.arrowBottom:after{border-top-color:#fff}.flatpickr-calendar:focus{outline:0}.flatpickr-wrapper{position:relative;display:inline-block}.flatpickr-months{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}.flatpickr-months .flatpickr-month{background:transparent;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9);height:34px;line-height:1;text-align:center;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:hidden;-webkit-box-flex:1;-webkit-flex:1;-ms-flex:1;flex:1}.flatpickr-months .flatpickr-prev-month,.flatpickr-months .flatpickr-next-month{text-decoration:none;cursor:pointer;position:absolute;top:0;height:34px;padding:10px;z-index:3;color:rgba(0,0,0,0.9);fill:rgba(0,0,0,0.9);}.flatpickr-months .flatpickr-prev-month.flatpickr-disabled,.flatpickr-months .flatpickr-next-month.flatpickr-disabled{display:none}.flatpickr-months .flatpickr-prev-month i,.flatpickr-months .flatpickr-next-month i{position:relative}.flatpickr-months .flatpickr-prev-month.flatpickr-prev-month,.flatpickr-months .flatpickr-next-month.flatpickr-prev-month{/*
|
||||
/*rtl:begin:ignore*/left:0;/*
|
||||
/*rtl:end:ignore*/}/*
|
||||
|
1
public/img/editable.svg
Normal file
1
public/img/editable.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 9.4 KiB |
41
public/img/new_team.svg
Normal file
41
public/img/new_team.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
1
public/img/team.svg
Normal file
1
public/img/team.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 11 KiB |
42871
public/js/app.js
vendored
42871
public/js/app.js
vendored
File diff suppressed because it is too large
Load Diff
94
public/js/app.js.LICENSE.txt
Normal file
94
public/js/app.js.LICENSE.txt
Normal file
@ -0,0 +1,94 @@
|
||||
/* flatpickr v4.6.3, @license MIT */
|
||||
|
||||
/*!
|
||||
* Bootstrap v4.5.0 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2020 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Chart.js v2.9.3
|
||||
* https://www.chartjs.org
|
||||
* (c) 2019 Chart.js Contributors
|
||||
* Released under the MIT License
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Sizzle CSS Selector Engine v2.3.5
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright JS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://js.foundation/
|
||||
*
|
||||
* Date: 2020-03-14
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery JavaScript Library v3.5.1
|
||||
* https://jquery.com/
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright JS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2020-05-04T22:49Z
|
||||
*/
|
||||
|
||||
/*! *****************************************************************************
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
|
||||
this file except in compliance with the License. You may obtain a copy of the
|
||||
License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
|
||||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
|
||||
MERCHANTABLITY OR NON-INFRINGEMENT.
|
||||
|
||||
See the Apache Version 2.0 License for specific language governing permissions
|
||||
and limitations under the License.
|
||||
***************************************************************************** */
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Lodash <https://lodash.com/>
|
||||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
* Released under MIT license <https://lodash.com/license>
|
||||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
*/
|
||||
|
||||
/**!
|
||||
* @fileOverview Kickass library to create and place poppers near their reference elements.
|
||||
* @version 1.16.1
|
||||
* @license
|
||||
* Copyright (c) 2016 Federico Zivolo and contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
//! moment.js
|
||||
|
||||
//! moment.js language configuration
|
||||
|
||||
//! moment.js locale configuration
|
1
public/js/globaltooltip.js
vendored
1
public/js/globaltooltip.js
vendored
@ -1,3 +1,4 @@
|
||||
$(document).ready(function() {
|
||||
$('input[rel="txtTooltip"]').tooltip();
|
||||
$('span[rel="spanTxtTooltip"]').tooltip(); // Also allow span tooltips
|
||||
});
|
||||
|
7
public/js/switches.js
vendored
Normal file
7
public/js/switches.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
$("#jointype").on('change', function() {
|
||||
if ($(this).is(':checked')) {
|
||||
$(this).attr('value', '1');
|
||||
} else {
|
||||
$(this).attr('value', '0');
|
||||
}
|
||||
});
|
2
resources/js/app.js
vendored
2
resources/js/app.js
vendored
@ -43,3 +43,5 @@ $("#comment").keyup(function(){
|
||||
$("#submitComment").on('click', function(){
|
||||
$("#newComment").submit();
|
||||
});
|
||||
|
||||
$("#jointype").bootstrapToggle();
|
||||
|
105
resources/views/dashboard/teams/edit-team.blade.php
Normal file
105
resources/views/dashboard/teams/edit-team.blade.php
Normal file
@ -0,0 +1,105 @@
|
||||
@extends('adminlte::page')
|
||||
|
||||
@section('title', config('app.name') . ' | ' . __('messages.teams.m_teams_page'))
|
||||
|
||||
@section('content_header')
|
||||
<h1>{{config('app.name')}} / {{__('messages.teams.m_teams_page')}}</h1>
|
||||
@stop
|
||||
|
||||
@section('js')
|
||||
|
||||
<x-global-errors></x-global-errors>
|
||||
|
||||
@stop
|
||||
|
||||
|
||||
@section('content')
|
||||
|
||||
@if($team->openJoin == false)
|
||||
<x-modal id="addUserModal" modal-label="addUserModalLabel" modal-title="Invite User" include-close-button="true">
|
||||
|
||||
<form id="inviteToTeam" method="POST" action="{{ route('sendInvite', ['team' => $team->id]) }}">
|
||||
@csrf
|
||||
<div class="form-group">
|
||||
<select class="custom-select" name="user">
|
||||
<option disabled selected>Choose a user to invite</option>
|
||||
@foreach ($users as $user)
|
||||
<option value="{{ $user->id }}" {{ ($user->id == Auth::user()->id) ? 'disabled' : '' }}>{{ $user->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<span class="text-sm text-muted"><i class="fas fa-info-circle"></i> This user will receive an email notification asking them to join your team.</span>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
<x-slot name="modalFooter">
|
||||
<button type="button" class="btn btn-success" onclick="$('#inviteToTeam').submit()"><i class="fas fa-paper-plane"></i> Send invite</button>
|
||||
</x-slot>
|
||||
|
||||
</x-modal>
|
||||
@endif
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col text-center">
|
||||
<img src="/img/editable.svg" alt="Edit illustration" height="220px" width="220px">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col">
|
||||
|
||||
<div class="card">
|
||||
|
||||
<div class="card-header">
|
||||
<h4 class="card-title">Edit Team</h4>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<form id="editTeam" method="POST" action="{{ route('teams.update', ['team' => $team->id]) }}">
|
||||
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
<label for="teamName">Team name</label>
|
||||
<input type="text" class="form-control" id="teamName" value="{{ $team->name }}" disabled>
|
||||
|
||||
<label for="teamDescription">Team description</label>
|
||||
<textarea class="form-control" rows="4" name="teamDescription" id="teamDescription">{{ $team->description }}</textarea>
|
||||
<span class="text-left text-muted text-sm"><a href="https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet"><i class="fab fa-markdown"></i></a> Markdown supported</span>
|
||||
|
||||
<div class="controlbuttons mt-3">
|
||||
|
||||
<span rel="spanTxtTooltip" data-toggle="tooltip" title="This setting controls whether people can join the team freely." data-placement="top">
|
||||
<input type="hidden" name="joinType" value="0"> <!-- unchecked checkbox hack (no js) -->
|
||||
<input value="0" type="checkbox" {{ ($team->openJoin == 1) ? 'checked' : '' }} name="joinType" id="jointype" data-toggle="toggle" data-on="Public Team" data-off="Private" data-onstyle="success" data-offstyle="danger" data-width="100">
|
||||
</span>
|
||||
|
||||
<button onclick="$('#addUserModal').modal('show')" type="button" id="inviteUser" name="inviteUser" class="btn btn-success" {{ ($team->openJoin) ? 'disabled' : '' }}><i class="fas fa-user-plus"></i> Invite user</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
<button type="button" class="btn btn-success" onclick="$('#editTeam').submit()"><i class="fas fa-save"></i> Save and Close</button>
|
||||
<button type="button" class="btn btn-danger" onclick="location.href='{{ route('teams.index') }}'"><i class="far fa-trash-alt"></i> Cancel</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
@stop
|
@ -6,8 +6,132 @@
|
||||
<h1>{{config('app.name')}} / {{__('messages.teams.m_teams_page')}}</h1>
|
||||
@stop
|
||||
|
||||
@section('js')
|
||||
|
||||
<x-global-errors></x-global-errors>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
|
||||
|
||||
<x-modal id="newTeamModal" modal-label="newTeamModalLabel" modal-title="New team" include-close-button="true">
|
||||
|
||||
<div class="row">
|
||||
<div class="col offset-3">
|
||||
<img src="/img/new_team.svg" height="220px" width="220px" alt="New Team illustration">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form action="{{ route('teams.store') }}" method="POST" id="newTeamForm">
|
||||
|
||||
@csrf
|
||||
|
||||
<div class="text-center">
|
||||
<input type="text" id="teamName" class="form-control" required name="teamName">
|
||||
</div>
|
||||
|
||||
<p class="text-muted text-sm">This is the name team members will see.</p>
|
||||
|
||||
</form>
|
||||
|
||||
<x-slot name="modalFooter">
|
||||
|
||||
<button type="button" class="btn btn-success" onclick="$('#newTeamForm').submit()"><i class="fas fa-check"></i> Create</button>
|
||||
|
||||
</x-slot>
|
||||
|
||||
</x-modal>
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4 offset-4 text-center">
|
||||
|
||||
<img src="/img/team.svg" height="230px" width="230px" alt="Team illustration">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
|
||||
<div class="col">
|
||||
|
||||
|
||||
<div class="card bg-gray-dark">
|
||||
|
||||
<div class="card-header bg-indigo">
|
||||
|
||||
<div class="card-title"><h4>{{ __('messages.teams.m_teams_page') }}</h4></div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
@if (!$teams->isEmpty())
|
||||
|
||||
<table class="table-borderless table-active table">
|
||||
|
||||
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Team Owner</th>
|
||||
<th>Team Name</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
@foreach ($teams as $team)
|
||||
|
||||
<tr>
|
||||
<td>{{ $team->id }}</td>
|
||||
<td>{{ $team->owner_id }}</td>
|
||||
<td>{{ $team->name }}</td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-success btn-sm ml-2" onclick="location.href='{{ route('teams.edit', ['team' => $team->id]) }}'"><i class="fas fa-cogs"></i> Settings</button>
|
||||
<button type="button" class="btn btn-warning btn-sm ml-2"><i class="fas fas fa-long-arrow-alt-right"></i> Team Dashboard</button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@endforeach
|
||||
|
||||
</tbody>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
@else
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<i class="fas fa-exclamation-triangle"></i> <b> There don't seem to be any teams here</b>
|
||||
<p>Have you tried creating or joining a team? You may also click an invite link if you've been invited.</p>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card-footer">
|
||||
|
||||
<button type="button" class="btn btn-success btn-sm ml-3" onclick="$('#newTeamModal').modal('show')"><i class="fas fa-plus-circle"></i> New team</button>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@stop
|
||||
|
167
resources/views/mail/invited-to-team.blade.php
Normal file
167
resources/views/mail/invited-to-team.blade.php
Normal file
@ -0,0 +1,167 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>You have just been invited to a team </title>
|
||||
<style>
|
||||
/* -------------------------------------
|
||||
INLINED WITH htmlemail.io/inline
|
||||
------------------------------------- */
|
||||
/* -------------------------------------
|
||||
RESPONSIVE AND MOBILE FRIENDLY STYLES
|
||||
------------------------------------- */
|
||||
@media only screen and (max-width: 620px) {
|
||||
table[class=body] h1 {
|
||||
font-size: 28px !important;
|
||||
margin-bottom: 10px !important;
|
||||
}
|
||||
table[class=body] p,
|
||||
table[class=body] ul,
|
||||
table[class=body] ol,
|
||||
table[class=body] td,
|
||||
table[class=body] span,
|
||||
table[class=body] a {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
table[class=body] .wrapper,
|
||||
table[class=body] .article {
|
||||
padding: 10px !important;
|
||||
}
|
||||
table[class=body] .content {
|
||||
padding: 0 !important;
|
||||
}
|
||||
table[class=body] .container {
|
||||
padding: 0 !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class=body] .main {
|
||||
border-left-width: 0 !important;
|
||||
border-radius: 0 !important;
|
||||
border-right-width: 0 !important;
|
||||
}
|
||||
table[class=body] .btn table {
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class=body] .btn a {
|
||||
width: 100% !important;
|
||||
}
|
||||
table[class=body] .img-responsive {
|
||||
height: auto !important;
|
||||
max-width: 100% !important;
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------
|
||||
PRESERVE THESE STYLES IN THE HEAD
|
||||
------------------------------------- */
|
||||
@media all {
|
||||
.ExternalClass {
|
||||
width: 100%;
|
||||
}
|
||||
.ExternalClass,
|
||||
.ExternalClass p,
|
||||
.ExternalClass span,
|
||||
.ExternalClass font,
|
||||
.ExternalClass td,
|
||||
.ExternalClass div {
|
||||
line-height: 100%;
|
||||
}
|
||||
.apple-link a {
|
||||
color: inherit !important;
|
||||
font-family: inherit !important;
|
||||
font-size: inherit !important;
|
||||
font-weight: inherit !important;
|
||||
line-height: inherit !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
#MessageViewBody a {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
.btn-primary table td:hover {
|
||||
background-color: #34495e !important;
|
||||
}
|
||||
.btn-primary a:hover {
|
||||
background-color: #34495e !important;
|
||||
border-color: #34495e !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="" style="background-color: #f6f6f6; font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; margin: 0; padding: 0; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%;">
|
||||
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">You have just been invited to {{ $teamName }}</span>
|
||||
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;">
|
||||
<tr>
|
||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto; max-width: 580px; padding: 10px; width: 580px;">
|
||||
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
|
||||
|
||||
<!-- START CENTERED WHITE CONTAINER -->
|
||||
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #ffffff; border-radius: 3px;">
|
||||
|
||||
<!-- START MAIN CONTENT AREA -->
|
||||
<tr>
|
||||
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
||||
<tr>
|
||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;">
|
||||
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">Hi {{ $name }},</p>
|
||||
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">{{ $inviterName }} has just invited you to join {{ $teamName }} (team).</p>
|
||||
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">Joining a team confers many benefits, such as access to the team calendar, shared files, assigned applications and much more.</p>
|
||||
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">If you accept this invite, you'll be added to the team immediately. Conversely, if you refuse it, {{ $inviterName }} won't be notified and you'll need to be invited again to join it.</p>
|
||||
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">Click one of the buttons below to make a decision.</p>
|
||||
|
||||
|
||||
<table border="0" cellpadding="0" cellspacing="0" class="btn btn-primary" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; box-sizing: border-box;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="left" style="font-family: sans-serif; font-size: 14px; vertical-align: top; padding-bottom: 15px;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: auto;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; background-color: #3498db; border-radius: 5px; text-align: center; margin-left: 5px;"> <a href="{{ route('processInvite', ['action' => 'accept', 'token' => $acceptToken]) }}" target="_blank" style="display: inline-block; color: #ffffff; background-color: #3498db; border: solid 1px #3498db; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 14px; font-weight: bold; margin: 0; padding: 12px 25px; text-transform: capitalize; border-color: #3498db;">Accept Invite</a> </td>
|
||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top; background-color: #3498db; border-radius: 5px; text-align: center; margin-left: 5px;"> <a href="{{ route('processInvite', ['action' => 'deny', 'token' => $denyToken]) }}" target="_blank" style="display: inline-block; color: #ffffff; background-color: #3498db; border: solid 1px #3498db; border-radius: 5px; box-sizing: border-box; cursor: pointer; text-decoration: none; font-size: 14px; font-weight: bold; margin: 0; padding: 12px 25px; text-transform: capitalize; border-color: #3498db;">Deny Invite</a> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">The accept and deny buttons do not expire (unless your invite is cancelled), so you can take your time to make a decision.</p>
|
||||
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">Thank you!</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- END MAIN CONTENT AREA -->
|
||||
</table>
|
||||
|
||||
<!-- START FOOTER -->
|
||||
<div class="footer" style="clear: both; Margin-top: 10px; text-align: center; width: 100%;">
|
||||
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;">
|
||||
<tr>
|
||||
<td class="content-block" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; font-size: 12px; color: #999999; text-align: center;">
|
||||
<span class="apple-link" style="color: #999999; font-size: 12px; text-align: center;">Staff Manager</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- END FOOTER -->
|
||||
|
||||
<!-- END CENTERED WHITE CONTAINER -->
|
||||
</div>
|
||||
</td>
|
||||
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
@ -40,6 +40,17 @@ Route::group(['prefix' => LaravelLocalization::setLocale(), 'middleware' => [ 'l
|
||||
Route::get('users/directory', 'ProfileController@index')
|
||||
->name('directory');
|
||||
|
||||
|
||||
Route::post('teams/{team}/invites/send', 'TeamController@invite')
|
||||
->name('sendInvite');
|
||||
|
||||
Route::get('teams/invites/{action}/{token}', 'TeamController@processInviteAction')
|
||||
->name('processInvite');
|
||||
|
||||
|
||||
Route::resource('teams', 'TeamController');
|
||||
|
||||
|
||||
Route::group(['prefix' => '/applications'], function (){
|
||||
|
||||
Route::get('/my-applications', 'ApplicationController@showUserApps')
|
||||
|
Loading…
Reference in New Issue
Block a user