add: CompanyDocument
Add class * Add CompanyDocument class, associated repo and twig files
This commit is contained in:
parent
e13dc0bf66
commit
82ee30a724
125
src/Entity/CompanyDocument.php
Normal file
125
src/Entity/CompanyDocument.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Enums\DocumentExtras;
|
||||
use App\Repository\CompanyDocumentRepository;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Bridge\Doctrine\Types\UuidType;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
#[ORM\Entity(repositoryClass: CompanyDocumentRepository::class)]
|
||||
class CompanyDocument
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\Column(type: UuidType::NAME, unique: true)]
|
||||
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
|
||||
#[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
|
||||
private ?Uuid $id = null;
|
||||
|
||||
#[ORM\ManyToOne]
|
||||
#[ORM\JoinColumn(nullable: false)]
|
||||
private ?Company $company = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $title = null;
|
||||
|
||||
#[ORM\Column(type: Types::TEXT, nullable: true)]
|
||||
private ?string $text = null;
|
||||
|
||||
#[ORM\Column(type: Types::DATETIME_MUTABLE)]
|
||||
private ?\DateTimeInterface $updated = null;
|
||||
|
||||
#[ORM\Column(type: Types::JSON, enumType: DocumentExtras::class, nullable: true)]
|
||||
private array $extras = [];
|
||||
|
||||
public function getId(): ?Uuid
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getCompany(): ?Company
|
||||
{
|
||||
return $this->company;
|
||||
}
|
||||
|
||||
public function setCompany(?Company $company): static
|
||||
{
|
||||
$this->company = $company;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTitle(): ?string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setTitle(string $title): static
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getText(): ?string
|
||||
{
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
public function setText(?string $text): static
|
||||
{
|
||||
$this->text = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUpdated(): ?\DateTimeInterface
|
||||
{
|
||||
return $this->updated;
|
||||
}
|
||||
|
||||
public function setUpdated(\DateTimeInterface $updated): static
|
||||
{
|
||||
$this->updated = $updated;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getExtras(): array
|
||||
{
|
||||
return $this->extras;
|
||||
}
|
||||
|
||||
public function setExtras(array $extras): static
|
||||
{
|
||||
$this->extras = $extras;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function inExtras(DocumentExtras $field): bool
|
||||
{
|
||||
return in_array($field, $this->extras);
|
||||
}
|
||||
|
||||
public function renderHtml(): string
|
||||
{
|
||||
$text = $this->text;
|
||||
if ($this->inExtras(DocumentExtras::EMAIL)) {
|
||||
$text = str_replace('{{ email }}', "<input type='email' name='email' id='email' value='{{ doc.client.email }}'/>", $text);
|
||||
$text = str_replace('{{ checkbox|email }}', "<input type='checkbox' name='emailClient' id='emailClient' value='1'/>", $text);
|
||||
}
|
||||
|
||||
if ($this->inExtras(DocumentExtras::PHONE)) {
|
||||
$text = str_replace('{{ phone }}', "<input type='tel' name='phone' id='phone' value='{{ doc.client.phone }}'/>", $text);
|
||||
$text = str_replace('{{ checkbox|phone }}', "<input type='checkbox' name='callClient' id='callClient' value='1'/>", $text);
|
||||
$text = str_replace('{{ checkbox|text }}', "<input type='checkbox' name='textClient' id='textClient' value='1'/>", $text);
|
||||
}
|
||||
|
||||
return <<<HTML
|
||||
$text
|
||||
HTML;
|
||||
}
|
||||
}
|
43
src/Repository/CompanyDocumentRepository.php
Normal file
43
src/Repository/CompanyDocumentRepository.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\CompanyDocument;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<CompanyDocument>
|
||||
*/
|
||||
class CompanyDocumentRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, CompanyDocument::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return CompanyDocument[] Returns an array of CompanyDocument objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('c')
|
||||
// ->andWhere('c.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('c.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?CompanyDocument
|
||||
// {
|
||||
// return $this->createQueryBuilder('c')
|
||||
// ->andWhere('c.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
103
templates/internal/admin/company/docs/add-document.html.twig
Normal file
103
templates/internal/admin/company/docs/add-document.html.twig
Normal file
@ -0,0 +1,103 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
{{ block('nav', 'internal/libs/nav.html.twig') }}
|
||||
|
||||
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
|
||||
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
|
||||
|
||||
<section>
|
||||
|
||||
<div class="card card-plain">
|
||||
<div class="card-header">
|
||||
<h4 class="font-weight-bolder">Add New Document</h4>
|
||||
<p class="mb-0"></p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="container">
|
||||
{{ form_errors(form) }}
|
||||
|
||||
{{ form_start(form) }}
|
||||
<div class="row">
|
||||
<div class='col'>
|
||||
<div class='input-group input-group-outline mb-3'>
|
||||
<label for='doc_form_title' class='form-label'>Title</label>
|
||||
<input type='text' name='{{ field_name(form.title) }}' id='doc_form_title' class='form-control' required='required'/>
|
||||
</div>
|
||||
|
||||
<div class='input-group input-group-outline mb-3'>
|
||||
{#{{ form_row(form.extras) }}#}
|
||||
{% for e in enum('App\\Enums\\DocumentExtras').cases() %}
|
||||
<input type='checkbox' name='{{ field_name(form.extras) }}[]' id='{{ e.name }}' value='{{ e.value }}'/>
|
||||
<label for='{{ e.name }}' class='extras'>{{ e.name|lower|replace({'_': ' '})|capitalize }}</label>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
<div class='input-group input-group-outline mb-3 is-filled'>
|
||||
<textarea name='{{ field_name(form.text) }}' id='doc-text' placeholder='Document Text'></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-lg bg-gradient-dark btn-lg w-100 mt-4 mb-0">Save Document</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_js %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/tinymce@7.6.0/tinymce.min.js"></script>
|
||||
<script type='module'>
|
||||
window.onload = function () {
|
||||
tinymce.init({
|
||||
selector: '#doc-text',
|
||||
height: 500,
|
||||
width: 1200,
|
||||
plugins: ['advlist',
|
||||
'autolink',
|
||||
'lists',
|
||||
'link',
|
||||
'image',
|
||||
'charmap',
|
||||
'preview',
|
||||
'anchor',
|
||||
'searchreplace',
|
||||
'visualblocks',
|
||||
'code',
|
||||
'fullscreen',
|
||||
'insertdatetime',
|
||||
'media',
|
||||
'table',
|
||||
'help',
|
||||
'wordcount'/**/
|
||||
],
|
||||
toolbar: 'undo redo | ' +
|
||||
'blocks | ' +
|
||||
'bold italic underline forecolor | ' +
|
||||
'alignleft aligncenter alignright | ' +
|
||||
'bullist numlist outdent indent | ' +
|
||||
'removeformat | help',
|
||||
content_style: '' // 'body { font-family:Helvetica,Arial,sans-serif; font-size:16px }'
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_css %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.5/skins/lightgray/content.min.css">
|
||||
<style type='text/css'>
|
||||
.extras {
|
||||
margin: 0 5px !important;
|
||||
}
|
||||
#doc-text {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
@ -0,0 +1,50 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<style type='text/css' rel='stylesheet'>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
.sheet-outer {
|
||||
margin: 0;
|
||||
}
|
||||
.sheet {
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
page-break-after: always;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
body {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
|
||||
.sheet {
|
||||
background: #ffffff;
|
||||
box-shadow: 0 .5mm 2mm rgba(0,0,0,.3);
|
||||
margin: 5mm auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media print {
|
||||
}
|
||||
|
||||
@page {
|
||||
size: letter;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header id="header" style='height:100px;'>
|
||||
<img id="companyLogo" src='{{ company_image_path }}/{{ company.companyLogo }}' style='height:100px;width:100px;'/>
|
||||
</header>
|
||||
<main id="body">
|
||||
<section id='doc-content'></section>
|
||||
</main>
|
||||
<footer id='footer'>
|
||||
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
109
templates/internal/admin/company/docs/edit-document.html.twig
Normal file
109
templates/internal/admin/company/docs/edit-document.html.twig
Normal file
@ -0,0 +1,109 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
{{ block('nav', 'internal/libs/nav.html.twig') }}
|
||||
|
||||
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
|
||||
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
|
||||
|
||||
<section>
|
||||
|
||||
<div class="card card-plain">
|
||||
<div class="card-header">
|
||||
<h4 class="font-weight-bolder">Edit Document</h4>
|
||||
<p class="mb-0"></p>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="container">
|
||||
{{ form_errors(form) }}
|
||||
|
||||
{{ form_start(form) }}
|
||||
<div class="row">
|
||||
<div class='col'>
|
||||
<div class='input-group input-group-outline mb-3 is-filled'>
|
||||
<label for='doc_form_title' class='form-label'>Title</label>
|
||||
<input type='text' name='{{ field_name(form.title) }}' value='{{ doc.title }}' id='doc_form_title' class='form-control' required='required'/>
|
||||
</div>
|
||||
|
||||
<div class='input-group input-group-outline mb-3'>
|
||||
{{ form_row(form.extras) }}
|
||||
{# for e in enum('App\\Enums\\DocumentExtras').cases %}
|
||||
<input type='checkbox' name='{{ field_name(form.extras) }}[]' id='{{ e.name }}' value='{{ e.value }}'/>
|
||||
<label for='{{ e.name }}' class='extras'>{{ e.name|lower|replace({'_': ' '})|capitalize }}</label>
|
||||
{% endfor #}
|
||||
</div>
|
||||
|
||||
<div class='input-group input-group-outline mb-3 is-filled'>
|
||||
<textarea name='{{ field_name(form.text) }}' id='doc-text' placeholder='Document Text'></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='row'>
|
||||
<div class="text-center">
|
||||
<button type="submit" class="btn btn-lg bg-gradient-dark btn-lg w-100 mt-4 mb-0">Save Document</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_js %}
|
||||
<script src="https://cdn.jsdelivr.net/npm/tinymce@7.6.0/tinymce.min.js"></script>
|
||||
<script type='module'>
|
||||
window.onload = function () {
|
||||
tinymce.init({
|
||||
license_key: 'gpl',
|
||||
selector: '#doc-text',
|
||||
height: 500,
|
||||
width: 1200,
|
||||
plugins: ['advlist',
|
||||
'autolink',
|
||||
'lists',
|
||||
'link',
|
||||
'image',
|
||||
'charmap',
|
||||
'preview',
|
||||
'anchor',
|
||||
'searchreplace',
|
||||
'visualblocks',
|
||||
'code',
|
||||
'fullscreen',
|
||||
'insertdatetime',
|
||||
'media',
|
||||
'table',
|
||||
'help',
|
||||
'wordcount'/**/
|
||||
],
|
||||
toolbar: 'undo redo | ' +
|
||||
'blocks | ' +
|
||||
'bold italic underline forecolor | ' +
|
||||
'alignleft aligncenter alignright | ' +
|
||||
'bullist numlist outdent indent | ' +
|
||||
'removeformat | help',
|
||||
content_style: '',
|
||||
setup: function(editor) {
|
||||
editor.on('init', function(e) {
|
||||
editor.setContent("{{ docText|raw }}");
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block page_css %}
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.5/skins/lightgray/content.min.css">
|
||||
<style type='text/css'>
|
||||
.extras {
|
||||
margin: 0 5px !important;
|
||||
}
|
||||
#doc-text {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
@ -0,0 +1,66 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
{{ block('nav', 'internal/libs/nav.html.twig') }}
|
||||
|
||||
<main class="main-content position-relative max-height-vh-100 h-100 border-radius-lg ">
|
||||
{{ block('topnav', 'internal/libs/top-nav.html.twig') }}
|
||||
|
||||
<div class="container-fluid py-2">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card my-4">
|
||||
<div class="card-header p-0 position-relative mt-n4 mx-3 z-index-2">
|
||||
<div class="d-flex justify-content-between bg-gradient-dark shadow-dark border-radius-lg pt-4 pb-3 ps-3 p-2">
|
||||
<div>
|
||||
<h6 class="text-white text-capitalize ps-3">Document List</h6>
|
||||
</div>
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<div>
|
||||
<button type="button" class="btn btn-block btn-light mb-3" onclick="window.open('{{ path('app_add_doc') }}', '_self')">Add Document</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body px-0 pb-2">
|
||||
<div class="table-responsive p-0">
|
||||
<table class="table align-items-center mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">Title</th>
|
||||
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7 ps-2">Last Update</th>
|
||||
<th class="text-secondary opacity-7"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id='doc-list'>
|
||||
{% for d in docs %}
|
||||
<tr>
|
||||
<td>
|
||||
<div class='d-flex px-2 py-1'>
|
||||
<div class='d-flex flex-column justify-content-center'>
|
||||
<h6 class='mb-0 text-small'>{{ d.title }}</h6>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<p class='text-xs font-weight-bold mb-0'>{{ d.updated|date('F j, Y', company_timezone) }}</p>
|
||||
</td>
|
||||
<td class='align-right'>
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<a href='{{ path('app_edit_doc', {docId: d.id}) }}' class='' title='Edit Document' data-toggle='tooltip'>
|
||||
<i class="material-symbols-rounded opacity-5">edit</i>
|
||||
</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user