relaunch
This commit is contained in:
parent
abaa95f71d
commit
6309faa898
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
Binary file not shown.
Before Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
Binary file not shown.
After Width: | Height: | Size: 416 KiB |
|
@ -5,5 +5,25 @@ require('bootstrap');
|
|||
|
||||
import '../styles/app.scss';
|
||||
|
||||
// CKEditor
|
||||
//require '@'
|
||||
import '../styles/ckeditor.css';
|
||||
|
||||
|
||||
require('@fortawesome/fontawesome-free/css/all.min.css');
|
||||
require('@fortawesome/fontawesome-free/js/all.js');
|
||||
|
||||
|
||||
|
||||
|
||||
window.Dropzone = require('@symfony/ux-dropzone/dist/controller');
|
||||
Dropzone.autodiscover = false;
|
||||
|
||||
/*
|
||||
initializeDropzone();
|
||||
|
||||
function initializeDropzone()
|
||||
{
|
||||
let formElement = document.querySelector('js-dropzone');
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,106 @@
|
|||
:root {
|
||||
/* Overrides the border radius setting in the theme. */
|
||||
--ck-border-radius: 4px;
|
||||
|
||||
/* Overrides the default font size in the theme. */
|
||||
--ck-font-size-base: 14px;
|
||||
|
||||
/* Helper variables to avoid duplication in the colors. */
|
||||
--ck-custom-background: hsl(270, 1%, 29%);
|
||||
--ck-custom-foreground: hsl(255, 3%, 18%);
|
||||
--ck-custom-border: hsl(300, 1%, 22%);
|
||||
--ck-custom-white: hsl(0, 0%, 100%);
|
||||
|
||||
/* -- Overrides generic colors. ------------------------------------------------------------- */
|
||||
|
||||
--ck-color-base-foreground: var(--ck-custom-background);
|
||||
--ck-color-focus-border: hsl(208, 90%, 62%);
|
||||
--ck-color-text: hsl(0, 0%, 98%);
|
||||
--ck-color-shadow-drop: hsla(0, 0%, 0%, 0.2);
|
||||
--ck-color-shadow-inner: hsla(0, 0%, 0%, 0.1);
|
||||
|
||||
/* -- Overrides the default .ck-button class colors. ---------------------------------------- */
|
||||
|
||||
--ck-color-button-default-background: var(--ck-custom-background);
|
||||
--ck-color-button-default-hover-background: hsl(270, 1%, 22%);
|
||||
--ck-color-button-default-active-background: hsl(270, 2%, 20%);
|
||||
--ck-color-button-default-active-shadow: hsl(270, 2%, 23%);
|
||||
--ck-color-button-default-disabled-background: var(--ck-custom-background);
|
||||
|
||||
--ck-color-button-on-background: var(--ck-custom-foreground);
|
||||
--ck-color-button-on-hover-background: hsl(255, 4%, 16%);
|
||||
--ck-color-button-on-active-background: hsl(255, 4%, 14%);
|
||||
--ck-color-button-on-active-shadow: hsl(240, 3%, 19%);
|
||||
--ck-color-button-on-disabled-background: var(--ck-custom-foreground);
|
||||
|
||||
--ck-color-button-action-background: hsl(168, 76%, 42%);
|
||||
--ck-color-button-action-hover-background: hsl(168, 76%, 38%);
|
||||
--ck-color-button-action-active-background: hsl(168, 76%, 36%);
|
||||
--ck-color-button-action-active-shadow: hsl(168, 75%, 34%);
|
||||
--ck-color-button-action-disabled-background: hsl(168, 76%, 42%);
|
||||
--ck-color-button-action-text: var(--ck-custom-white);
|
||||
|
||||
--ck-color-button-save: hsl(120, 100%, 46%);
|
||||
--ck-color-button-cancel: hsl(15, 100%, 56%);
|
||||
|
||||
/* -- Overrides the default .ck-dropdown class colors. -------------------------------------- */
|
||||
|
||||
--ck-color-dropdown-panel-background: var(--ck-custom-background);
|
||||
--ck-color-dropdown-panel-border: var(--ck-custom-foreground);
|
||||
|
||||
/* -- Overrides the default .ck-splitbutton class colors. ----------------------------------- */
|
||||
|
||||
--ck-color-split-button-hover-background: var(--ck-color-button-default-hover-background);
|
||||
--ck-color-split-button-hover-border: var(--ck-custom-foreground);
|
||||
|
||||
/* -- Overrides the default .ck-input class colors. ----------------------------------------- */
|
||||
|
||||
--ck-color-input-background: var(--ck-custom-background);
|
||||
--ck-color-input-border: hsl(257, 3%, 43%);
|
||||
--ck-color-input-text: hsl(0, 0%, 98%);
|
||||
--ck-color-input-disabled-background: hsl(255, 4%, 21%);
|
||||
--ck-color-input-disabled-border: hsl(250, 3%, 38%);
|
||||
--ck-color-input-disabled-text: hsl(0, 0%, 78%);
|
||||
|
||||
/* -- Overrides the default .ck-labeled-field-view class colors. ---------------------------- */
|
||||
|
||||
--ck-color-labeled-field-label-background: var(--ck-custom-background);
|
||||
|
||||
/* -- Overrides the default .ck-list class colors. ------------------------------------------ */
|
||||
|
||||
--ck-color-list-background: var(--ck-custom-background);
|
||||
--ck-color-list-button-hover-background: var(--ck-color-base-foreground);
|
||||
--ck-color-list-button-on-background: var(--ck-color-base-active);
|
||||
--ck-color-list-button-on-background-focus: var(--ck-color-base-active-focus);
|
||||
--ck-color-list-button-on-text: var(--ck-color-base-background);
|
||||
|
||||
/* -- Overrides the default .ck-balloon-panel class colors. --------------------------------- */
|
||||
|
||||
--ck-color-panel-background: var(--ck-custom-background);
|
||||
--ck-color-panel-border: var(--ck-custom-border);
|
||||
|
||||
/* -- Overrides the default .ck-toolbar class colors. --------------------------------------- */
|
||||
|
||||
--ck-color-toolbar-background: var(--ck-custom-background);
|
||||
--ck-color-toolbar-border: var(--ck-custom-border);
|
||||
|
||||
/* -- Overrides the default .ck-tooltip class colors. --------------------------------------- */
|
||||
|
||||
--ck-color-tooltip-background: hsl(252, 7%, 14%);
|
||||
--ck-color-tooltip-text: hsl(0, 0%, 93%);
|
||||
|
||||
/* -- Overrides the default colors used by the ckeditor5-image package. --------------------- */
|
||||
|
||||
--ck-color-image-caption-background: hsl(0, 0%, 97%);
|
||||
--ck-color-image-caption-text: hsl(0, 0%, 20%);
|
||||
|
||||
/* -- Overrides the default colors used by the ckeditor5-widget package. -------------------- */
|
||||
|
||||
--ck-color-widget-blurred-border: hsl(0, 0%, 87%);
|
||||
--ck-color-widget-hover-border: hsl(43, 100%, 68%);
|
||||
--ck-color-widget-editable-focus-background: var(--ck-custom-white);
|
||||
|
||||
/* -- Overrides the default colors used by the ckeditor5-link package. ---------------------- */
|
||||
|
||||
--ck-color-link-default: hsl(190, 100%, 75%);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import { startStimulusApp } from '@symfony/stimulus-bridge';
|
||||
|
||||
// Registers Stimulus controllers from controllers.json and in the controllers/ directory
|
||||
export const app = startStimulusApp(require.context(
|
||||
'@symfony/stimulus-bridge/lazy-controller-loader!./controllers',
|
||||
true,
|
||||
/\.(j|t)sx?$/
|
||||
));
|
||||
|
||||
// register any custom, 3rd party controllers here
|
||||
// app.register('some_controller_name', SomeImportedController);
|
|
@ -0,0 +1,5 @@
|
|||
when@dev:
|
||||
debug:
|
||||
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
|
||||
# See the "server:dump" command to start a new server.
|
||||
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
|
|
@ -0,0 +1,24 @@
|
|||
framework:
|
||||
messenger:
|
||||
failure_transport: failed
|
||||
|
||||
transports:
|
||||
# https://symfony.com/doc/current/messenger.html#transport-configuration
|
||||
async:
|
||||
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
|
||||
options:
|
||||
use_notify: true
|
||||
check_delayed_interval: 60000
|
||||
retry_strategy:
|
||||
max_retries: 3
|
||||
multiplier: 2
|
||||
failed: 'doctrine://default?queue_name=failed'
|
||||
# sync: 'sync://'
|
||||
|
||||
routing:
|
||||
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
|
||||
Symfony\Component\Notifier\Message\ChatMessage: async
|
||||
Symfony\Component\Notifier\Message\SmsMessage: async
|
||||
|
||||
# Route your messages to the transports
|
||||
# 'App\Message\YourMessage': async
|
|
@ -0,0 +1,61 @@
|
|||
monolog:
|
||||
channels:
|
||||
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
|
||||
|
||||
when@dev:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
channels: ["!event"]
|
||||
# uncomment to get logging in your browser
|
||||
# you may have to allow bigger header sizes in your Web server configuration
|
||||
#firephp:
|
||||
# type: firephp
|
||||
# level: info
|
||||
#chromephp:
|
||||
# type: chromephp
|
||||
# level: info
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine", "!console"]
|
||||
|
||||
when@test:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
channels: ["!event"]
|
||||
nested:
|
||||
type: stream
|
||||
path: "%kernel.logs_dir%/%kernel.environment%.log"
|
||||
level: debug
|
||||
|
||||
when@prod:
|
||||
monolog:
|
||||
handlers:
|
||||
main:
|
||||
type: fingers_crossed
|
||||
action_level: error
|
||||
handler: nested
|
||||
excluded_http_codes: [404, 405]
|
||||
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
|
||||
nested:
|
||||
type: stream
|
||||
path: php://stderr
|
||||
level: debug
|
||||
formatter: monolog.formatter.json
|
||||
console:
|
||||
type: console
|
||||
process_psr_3_messages: false
|
||||
channels: ["!event", "!doctrine"]
|
||||
deprecation:
|
||||
type: stream
|
||||
channels: [deprecation]
|
||||
path: php://stderr
|
|
@ -0,0 +1,16 @@
|
|||
framework:
|
||||
notifier:
|
||||
#chatter_transports:
|
||||
# slack: '%env(SLACK_DSN)%'
|
||||
# telegram: '%env(TELEGRAM_DSN)%'
|
||||
#texter_transports:
|
||||
# twilio: '%env(TWILIO_DSN)%'
|
||||
# nexmo: '%env(NEXMO_DSN)%'
|
||||
channel_policy:
|
||||
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
|
||||
urgent: ['email']
|
||||
high: ['email']
|
||||
medium: ['email']
|
||||
low: ['email']
|
||||
admin_recipients:
|
||||
- { email: admin@example.com }
|
|
@ -0,0 +1,3 @@
|
|||
sensio_framework_extra:
|
||||
router:
|
||||
annotations: false
|
|
@ -0,0 +1,15 @@
|
|||
when@dev:
|
||||
web_profiler:
|
||||
toolbar: true
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { only_exceptions: false }
|
||||
|
||||
when@test:
|
||||
web_profiler:
|
||||
toolbar: false
|
||||
intercept_redirects: false
|
||||
|
||||
framework:
|
||||
profiler: { collect: false }
|
|
@ -0,0 +1,4 @@
|
|||
when@dev:
|
||||
_errors:
|
||||
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
|
||||
prefix: /_error
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"controllers": {
|
||||
"@symfony/ux-dropzone": {
|
||||
"dropzone": {
|
||||
"enabled": true,
|
||||
"fetch": "eager",
|
||||
"autoimport": {
|
||||
"@symfony/ux-dropzone/src/style.css": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entrypoints": []
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database:
|
||||
ports:
|
||||
- "5432"
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
mailer:
|
||||
image: schickling/mailcatcher
|
||||
ports: [1025, 1080]
|
||||
###< symfony/mailer ###
|
|
@ -0,0 +1,21 @@
|
|||
version: '3'
|
||||
|
||||
services:
|
||||
###> doctrine/doctrine-bundle ###
|
||||
database:
|
||||
image: postgres:${POSTGRES_VERSION:-13}-alpine
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB:-app}
|
||||
# You should definitely change the password in production
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ChangeMe}
|
||||
POSTGRES_USER: ${POSTGRES_USER:-symfony}
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data:rw
|
||||
# You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
|
||||
# - ./docker/db/data:/var/lib/postgresql/data:rw
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
volumes:
|
||||
###> doctrine/doctrine-bundle ###
|
||||
db-data:
|
||||
###< doctrine/doctrine-bundle ###
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20220409135404 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE user ADD first_name VARCHAR(255) DEFAULT NULL, ADD last_name VARCHAR(255) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('ALTER TABLE `user` DROP first_name, DROP last_name');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20220409150258 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE quotes (id INT AUTO_INCREMENT NOT NULL, quote LONGTEXT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE quotes');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20220410123550 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE projects (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255) NOT NULL, url VARCHAR(255) NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
$this->addSql('ALTER TABLE user CHANGE first_name first_name VARCHAR(255) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE projects');
|
||||
$this->addSql('ALTER TABLE `user` CHANGE first_name first_name VARCHAR(255) DEFAULT \'\'');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
final class Version20220410131552 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE TABLE projects_user (projects_id INT NOT NULL, user_id INT NOT NULL, INDEX IDX_B38D6A811EDE0F55 (projects_id), INDEX IDX_B38D6A81A76ED395 (user_id), PRIMARY KEY(projects_id, user_id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||
$this->addSql('ALTER TABLE projects_user ADD CONSTRAINT FK_B38D6A811EDE0F55 FOREIGN KEY (projects_id) REFERENCES projects (id) ON DELETE CASCADE');
|
||||
$this->addSql('ALTER TABLE projects_user ADD CONSTRAINT FK_B38D6A81A76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id) ON DELETE CASCADE');
|
||||
$this->addSql('ALTER TABLE projects ADD teaser_image VARCHAR(255) DEFAULT NULL');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('DROP TABLE projects_user');
|
||||
$this->addSql('ALTER TABLE projects DROP teaser_image');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Projects;
|
||||
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class ProjectsCrudController extends AbstractCrudController
|
||||
{
|
||||
public static function getEntityFqcn(): string
|
||||
{
|
||||
return Projects::class;
|
||||
}
|
||||
|
||||
/*
|
||||
public function configureFields(string $pageName): iterable
|
||||
{
|
||||
return [
|
||||
IdField::new('id'),
|
||||
TextField::new('title'),
|
||||
TextEditorField::new('description'),
|
||||
];
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller\Admin;
|
||||
|
||||
use App\Entity\Quotes;
|
||||
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
|
||||
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
|
||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
|
||||
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class QuotesCrudController extends AbstractCrudController
|
||||
{
|
||||
public static function getEntityFqcn(): string
|
||||
{
|
||||
return Quotes::class;
|
||||
}
|
||||
|
||||
public function configureFields(string $pageName): iterable
|
||||
{
|
||||
return [
|
||||
IdField::new(propertyName: 'id'),
|
||||
TextField::new(propertyName: 'quote'),
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Repository\ProjectsRepository;use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class ProjectsController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/projects/{name}', name: 'app_projects')]
|
||||
public function index(ProjectsRepository $projectsRepository, string $name = ''): Response
|
||||
{
|
||||
if ($name == '') {
|
||||
return $this->render(view: 'projects/index.html.twig', parameters: [
|
||||
'projects' => $projectsRepository->findAll()
|
||||
]);
|
||||
} else {
|
||||
if ($project = $projectsRepository->findOneByName(value: $name)) {
|
||||
$readMe = file_get_contents(filename: $project->getURL() . '/raw/branch/master/README.md');
|
||||
|
||||
//$parsedReadMe = $markdownParser->transformMarkdown(text: $readMe);
|
||||
|
||||
return $this->render(view: 'projects/show.html.twig', parameters: [
|
||||
'project' => $project,
|
||||
'readme' => $readMe
|
||||
]);
|
||||
} else {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -2,17 +2,74 @@
|
|||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\User;
|
||||
use App\Repository\UserRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
|
||||
/**
|
||||
* Class UserController
|
||||
* @package App\Controller
|
||||
*/
|
||||
class UserController extends AbstractController
|
||||
{
|
||||
#[Route('/user', name: 'user')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('user/index.html.twig', [
|
||||
'controller_name' => 'UserController',
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* @param \App\Repository\UserRepository $userRepository
|
||||
* @param string $userName
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
#[Route(path: '/profile/edit/{username}', name: 'app_profile_edit')]
|
||||
public function editProfile(UserRepository $userRepository, string $username = ''): Response
|
||||
{
|
||||
/** var User $user */
|
||||
if ($username === '') {
|
||||
if ($this->isGranted(attribute: 'ROLE_USER')) {
|
||||
$user = $this->getUser();
|
||||
} else {
|
||||
throw new AccessDeniedException('You need to be logged in.');
|
||||
}
|
||||
} else {
|
||||
if ($this->isGranted(attribute: 'ROLE_ADMIN')) {
|
||||
$user = $userRepository->findOneBy([
|
||||
"username" => $username
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($user)) {
|
||||
return $this->render(view: 'user/edit_profile.html.twig', parameters: [
|
||||
'user' => $user,
|
||||
]);
|
||||
} else {
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \App\Repository\UserRepository $userRepository
|
||||
* @param string $username
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*/
|
||||
#[Route(path: '/profile/{username}', name: 'app_profile')]
|
||||
public function showProfile(UserRepository $userRepository, string $username = ''): Response
|
||||
{
|
||||
/** var User $user */
|
||||
if ($username === '') {
|
||||
$user = $this->getUser();
|
||||
} else {
|
||||
$user = $userRepository->findOneBy([
|
||||
"username" => $username
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->render(view: 'user/show_profile.html.twig', parameters: [
|
||||
'user' => $user,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\ProjectsRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
#[ORM\Entity(repositoryClass: ProjectsRepository::class)]
|
||||
class Projects
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private ?int $id;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255)]
|
||||
private ?string $name;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255)]
|
||||
private ?string $description;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255)]
|
||||
private ?string $url;
|
||||
|
||||
#[ORM\Column(type: 'datetime_immutable')]
|
||||
private ?\DateTimeImmutable $createdAt;
|
||||
|
||||
#[ORM\Column(type: 'string', length: 255, nullable: true)]
|
||||
private ?string $teaserImage;
|
||||
|
||||
#[ORM\ManyToMany(targetEntity: User::class, inversedBy: 'projects')]
|
||||
private $developer;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->developer = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null|string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $Name): self
|
||||
{
|
||||
$this->name = $Name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(string $Description): self
|
||||
{
|
||||
$this->description = $Description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getURL(): ?string
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function setURL(string $url): self
|
||||
{
|
||||
$this->url = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt(\DateTimeImmutable $createdAt): self
|
||||
{
|
||||
$this->createdAt = $createdAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTeaserImage(): ?string
|
||||
{
|
||||
return $this->teaserImage;
|
||||
}
|
||||
|
||||
public function setTeaserImage(?string $teaserImage): self
|
||||
{
|
||||
$this->teaserImage = $teaserImage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, User>
|
||||
*/
|
||||
public function getDeveloper(): Collection
|
||||
{
|
||||
return $this->developer;
|
||||
}
|
||||
|
||||
public function addDeveloper(User $developer): self
|
||||
{
|
||||
if (!$this->developer->contains($developer)) {
|
||||
$this->developer[] = $developer;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeDeveloper(User $developer): self
|
||||
{
|
||||
$this->developer->removeElement($developer);
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\QuotesRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: QuotesRepository::class)]
|
||||
class Quotes
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(type: 'integer')]
|
||||
private $id;
|
||||
|
||||
#[ORM\Column(type: 'text')]
|
||||
private $quote;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getQuote(): ?string
|
||||
{
|
||||
return $this->quote;
|
||||
}
|
||||
|
||||
public function setQuote(string $quote): self
|
||||
{
|
||||
$this->quote = $quote;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Projects;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\NonUniqueResultException;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Projects|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Projects|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Projects[] findAll()
|
||||
* @method Projects[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ProjectsRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct(registry: $registry, entityClass: Projects::class);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function add(Projects $entity, bool $flush = true): void
|
||||
{
|
||||
$this->_em->persist($entity);
|
||||
if ($flush) {
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function remove(Projects $entity, bool $flush = true): void
|
||||
{
|
||||
$this->_em->remove($entity);
|
||||
if ($flush) {
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Projects[] Returns an array of Projects objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('p')
|
||||
->andWhere('p.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('p.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
public function findOneByName($value): ?Projects
|
||||
{
|
||||
|
||||
try {
|
||||
return $this->createQueryBuilder(alias: 'q')
|
||||
->andWhere('q.name = :val')
|
||||
->setParameter(key: 'val', value: $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
} catch(NonUniqueResultException $e) {
|
||||
dd($e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Quotes;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\ORM\OptimisticLockException;
|
||||
use Doctrine\ORM\ORMException;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Quotes|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Quotes|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Quotes[] findAll()
|
||||
* @method Quotes[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class QuotesRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct(registry: $registry, entityClass: Quotes::class);
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function add(Quotes $entity, bool $flush = true): void
|
||||
{
|
||||
$this->_em->persist($entity);
|
||||
if ($flush) {
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function remove(Quotes $entity, bool $flush = true): void
|
||||
{
|
||||
$this->_em->remove($entity);
|
||||
if ($flush) {
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return null|float|int|mixed|string
|
||||
* @throws \Doctrine\ORM\NonUniqueResultException
|
||||
*/
|
||||
public function findOneRandom(): mixed
|
||||
{
|
||||
$idLimits = $this->createQueryBuilder(alias: 'q')
|
||||
->select('MIN(q.id)', 'MAX(q.id)')
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
$randomPossibleId = rand(min: $idLimits[1], max: $idLimits[2]);
|
||||
|
||||
return $this->createQueryBuilder(alias: 'q')
|
||||
->where(predicates: 'q.id >= :random_id')
|
||||
->setParameter(key: 'random_id', value: $randomPossibleId)
|
||||
->setMaxResults(maxResults: 1)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
|
||||
// /**
|
||||
// * @return Quotes[] Returns an array of Quotes objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('q')
|
||||
->andWhere('q.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('q.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Quotes
|
||||
{
|
||||
return $this->createQueryBuilder('q')
|
||||
->andWhere('q.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
|
||||
namespace App\Security;
|
||||
|
||||
use App\Entity\User;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
||||
use Symfony\Component\Security\Core\Exception\UserNotFoundException;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\CustomCredentials;
|
||||
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
|
||||
use App\Repository\UserRepository;
|
||||
use Symfony\Component\Security\Http\Util\TargetPathTrait;
|
||||
use function mysql_xdevapi\getSession;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
|
||||
{
|
||||
use TargetPathTrait;
|
||||
/**
|
||||
* @var \App\Repository\UserRepository
|
||||
*/
|
||||
private UserRepository $userRepository;
|
||||
/**
|
||||
* @var \Symfony\Component\Routing\RouterInterface
|
||||
*/
|
||||
private RouterInterface $router;
|
||||
|
||||
public function __construct(UserRepository $userRepository, RouterInterface $router)
|
||||
{
|
||||
$this->userRepository = $userRepository;
|
||||
$this->router = $router;
|
||||
}
|
||||
|
||||
|
||||
public function authenticate(Request $request): Passport
|
||||
{
|
||||
$username = $request->request->get(key: 'username');
|
||||
$password = $request->request->get(key: 'password');
|
||||
$csrfToken = $request->request->get(key: '_csrf_token');
|
||||
|
||||
$request->getSession()->set(name: Security::LAST_USERNAME, value: $username);
|
||||
|
||||
return new Passport(
|
||||
userBadge: new UserBadge(userIdentifier: $username, userLoader: function ($userIdentifier) {
|
||||
$user = $this->userRepository->findOneBy(['username' => $userIdentifier]);
|
||||
|
||||
if (!$user) {
|
||||
$user = $this->userRepository->findOneBy(['email' => $userIdentifier]);
|
||||
}
|
||||
|
||||
if (!$user) {
|
||||
throw new UserNotFoundException();
|
||||
}
|
||||
|
||||
return $user;
|
||||
}),
|
||||
credentials: new CustomCredentials(customCredentialsChecker: function ($credentials, User $user) {
|
||||
return $credentials === 'test';
|
||||
|
||||
}, credentials : $password),
|
||||
|
||||
// new PasswordCredentials($password),
|
||||
badges: [
|
||||
new CsrfTokenBadge(csrfTokenId: 'authenticate', csrfToken: $csrfToken),
|
||||
new RememberMeBadge()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
|
||||
{
|
||||
if ($target = $this->getTargetPath(session: $request->getSession(), firewallName: $firewallName)) {
|
||||
return new RedirectResponse(url: $target);
|
||||
}
|
||||
|
||||
return new RedirectResponse(
|
||||
url: $this->router->generate(name: 'app_main')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
protected function getLoginUrl(Request $request): string
|
||||
{
|
||||
return $this->router->generate(name: 'app_login');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
{# templates/admin/index.html.twig #}
|
||||
|
||||
{% extends '@EasyAdmin/page/content.html.twig' %}
|
|
@ -0,0 +1,70 @@
|
|||
{# templates/projects/index.html.twig #}
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %} Projects {% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="container-fluid box">
|
||||
<div class="row">
|
||||
<h2>This is an overview of my current public (and open source) projects.</h2>
|
||||
|
||||
<!-- projects List -->
|
||||
<div class="col-sm-12">
|
||||
{% for project in projects %}
|
||||
<div class="project-container bg-dark my-4">
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<a href="{{ path('app_projects', { name: project.name }) }}">
|
||||
{% if project.teaserImage %}
|
||||
<img
|
||||
class="blog-img"
|
||||
src=" {# uploaded_asset(blogpost.teaserImage)|imagine_filter('squared_thumbnail_small') #}"
|
||||
alt="Teaser">
|
||||
{% else %}
|
||||
<img
|
||||
class="blog-img"
|
||||
src="{{ asset('build/images/24unix/24_logo_bg_96x96.png') }}"
|
||||
alt="Teaser">
|
||||
{% endif %}
|
||||
</a>
|
||||
<br>
|
||||
<div>
|
||||
{% for developer in project.developer %}
|
||||
<a class="align-left blog-details"
|
||||
href="{{ path('app_profile', { 'username':developer.username }) }}">
|
||||
<img class="article-author-img rounded-circle"
|
||||
src="{{ asset('build/images/tracer_schmolle.png') }}"
|
||||
alt="profile"></a>
|
||||
<a href="{{ path('app_profile', { 'username':developer.username }) }}">{{ developer.username }}</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-8 mt-2">
|
||||
<a href="{{ path('app_projects', { name: project.name }) }}">
|
||||
<div class="article-title d-inline-block pl-3 align-middle">
|
||||
<h2>{{ project.name }}</h2>
|
||||
</div>
|
||||
</a>
|
||||
<br>
|
||||
<div class="blog-teaser mb-2 pb-2 text-xl-start">
|
||||
{{ project.description }}
|
||||
<br>
|
||||
<br>
|
||||
started: {{ project.createdAt | ago }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<div class="text-xl-start">
|
||||
<a href="{{ path('app_main') }}"><i class="fa fa-plus-circle"></i></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
|
@ -0,0 +1,38 @@
|
|||
{# templates/blog/blog_show.html.twig #}
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %} Blogpost {% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<div class="d-flex justify-content-end">
|
||||
<a href="{{ path('app_main', { id : project.id }) }}"><i class="fa fa-3x fa-fw fa-edit"></i></a>
|
||||
<a href="{{ path('app_main', { id : project.id }) }}"><i class="fa fa-3x fa-fw fa-trash"></i></a>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="show-article-container p-3 mt-4">
|
||||
<div class="show-article-title-container d-inline-block pl-3 align-middle">
|
||||
<h2>{{ project.name }}</h2>
|
||||
</div>
|
||||
<div>
|
||||
Source: <a href="{{ project.url }}" target="_blank">{{ project.url }}</a> <i
|
||||
class="fa fa-external-link" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<div class="article-text">
|
||||
{{ readme | markdown_to_html }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,53 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
Profile of {{ user.username }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="container box rounded bg-dark mt-5 mb-5">
|
||||
<div class="row">
|
||||
<div class="col-md-3 border-right">
|
||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
||||
<img class="rounded-circle mt-5"
|
||||
width="150px"
|
||||
src=" {{ asset('build/images/tracer_schmolle.png') }}" alt="profile image">
|
||||
<span class="font-weight-bold">{{ user.username }}</span>
|
||||
<span class="text-white-50"><i class="fa fa-lg fa-envelope me-1"></i>{{ user.email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 border-right">
|
||||
<div class="p-3 py-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4 class="text-right">User Profile</h4>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="first-name">First Name</label>
|
||||
<input type="text" id="first-name" class="form-control" placeholder="First Name" value="{{ user.firstName }}">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="last-name">Last Name</label>
|
||||
<input type="text" id="last-name" class="form-control" value="{{ user.lastName }}" placeholder="Last Name">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="username">Username</label>
|
||||
<input type="text" class="form-control" id="username" placeholder="eMail address" value="{{ user.email }}">
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="mt-5 text-center">
|
||||
<button class="btn btn-primary profile-button" type="button">Save Profile</button>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,53 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}
|
||||
Profile of {{ user.username }}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
|
||||
<div class="container box rounded bg-dark mt-5 mb-5">
|
||||
<div class="row">
|
||||
<div class="col-md-3 border-right">
|
||||
<div class="d-flex flex-column align-items-center text-center p-3 py-5">
|
||||
<img class="rounded-circle mt-5"
|
||||
width="150px"
|
||||
src=" {{ asset('build/images/tracer_schmolle.png') }}" alt="profile image">
|
||||
<span class="font-weight-bold">{{ user.username }}</span>
|
||||
<span class="text-white-50"><i class="fa fa-lg fa-envelope me-1"></i>{{ user.email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-5 border-right">
|
||||
<div class="p-3 py-5">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4 class="text-right">User Profile</h4>
|
||||
</div>
|
||||
<div class="row mt-2">
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="first-name">First Name</label>
|
||||
<input type="text" disabled id="first-name" class="form-control" placeholder="First Name" value="{{ user.firstName }}">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="last-name">Last Name</label>
|
||||
<input type="text" disabled id="last-name" class="form-control" value="{{ user.lastName }}" placeholder="Last Name">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<label class="labels" for="username">Username</label>
|
||||
<input type="text" disabled class="form-control" id="username" placeholder="eMail address" value="{{ user.email }}">
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="mt-5 text-center">
|
||||
<button class="btn btn-primary profile-button" type="button">Save Profile</button>
|
||||
</div>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
|
@ -0,0 +1,2 @@
|
|||
"Invalid credentials.": "Invalid password entered!"
|
||||
"Username could not be found.": "Neither user or eMail address is valid!"
|
Loading…
Reference in New Issue