Add collection and new vocab + mess with repository
This commit is contained in:
parent
f8e470b096
commit
0a41ff4a7b
@ -44,10 +44,12 @@ if (location.pathname.includes('login')) {
|
||||
|
||||
if (! location.pathname.includes('login')) {
|
||||
const vocabs = document.querySelector('#vocabs');
|
||||
const records = document.querySelector('#records');
|
||||
const userMenu = document.querySelector('.dropdown-trigger');
|
||||
const userCaret = document.querySelector('#user-caret');
|
||||
|
||||
const forVocabs = document.querySelector('#for-vocabs')
|
||||
const forRecords = document.querySelector('#for-records')
|
||||
|
||||
if (forVocabs) {
|
||||
forVocabs.addEventListener('click', function () {
|
||||
@ -63,6 +65,20 @@ if (! location.pathname.includes('login')) {
|
||||
});
|
||||
}
|
||||
|
||||
if (forRecords) {
|
||||
forRecords.addEventListener('click', function () {
|
||||
records.classList.toggle('is-hidden');
|
||||
|
||||
if (this.firstElementChild.classList.contains('fa-angle-right')) {
|
||||
this.firstElementChild.classList.remove('fa-angle-right');
|
||||
this.firstElementChild.classList.add('fa-angle-down');
|
||||
} else {
|
||||
this.firstElementChild.classList.remove('fa-angle-down');
|
||||
this.firstElementChild.classList.add('fa-angle-right');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
userMenu.addEventListener('click', function () {
|
||||
document.querySelector('.dropdown').classList.toggle('is-active');
|
||||
if (userCaret.classList.contains('fa-caret-down')) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
@import url('../vendor/bulma/css/bulma.min.css');
|
||||
@import url('../fonts/stylesheet.css');
|
||||
@import url('../fontawesome-free-6.6.0-web/css/all.min.css');
|
||||
@import url('../vendor/bulma/css/bulma.min.css');
|
||||
|
||||
:root {
|
||||
--arcoa-blue: rgba(66,135,199,0.98);
|
||||
@ -15,13 +15,11 @@ body {
|
||||
min-height: 100vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
#vocabs a {
|
||||
|
||||
#vocabs a,
|
||||
#records a {
|
||||
color: #fff;
|
||||
}
|
||||
/* For dev only*/
|
||||
.sf-toolbar-clearer {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.table.record td,
|
||||
.table.record th {
|
||||
@ -29,5 +27,13 @@ body {
|
||||
}
|
||||
|
||||
.table.record th {
|
||||
min-width: 220px;
|
||||
min-width: 240px;
|
||||
}
|
||||
|
||||
.table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.results tr > th {
|
||||
text-align: center !important;
|
||||
}
|
@ -7,10 +7,13 @@
|
||||
"php": ">=8.2",
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"api-platform/doctrine-orm": "^4.0",
|
||||
"api-platform/symfony": "^4.0",
|
||||
"doctrine/dbal": "^3",
|
||||
"doctrine/doctrine-bundle": "^2.13",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.3",
|
||||
"doctrine/orm": "^3.3",
|
||||
"nelmio/cors-bundle": "^2.5",
|
||||
"phpdocumentor/reflection-docblock": "^5.4",
|
||||
"phpstan/phpdoc-parser": "^1.33",
|
||||
"symfony/asset": "7.1.*",
|
||||
|
1480
composer.lock
generated
1480
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -13,4 +13,6 @@ return [
|
||||
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
|
||||
ApiPlatform\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
|
||||
];
|
||||
|
7
config/packages/api_platform.yaml
Normal file
7
config/packages/api_platform.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
api_platform:
|
||||
title: Hello API Platform
|
||||
version: 1.0.0
|
||||
defaults:
|
||||
stateless: true
|
||||
cache_headers:
|
||||
vary: ['Content-Type', 'Authorization', 'Origin']
|
@ -4,7 +4,9 @@ framework:
|
||||
csrf_protection: true
|
||||
|
||||
# Note that the session will be started ONLY if you read or write from it.
|
||||
session: true
|
||||
session:
|
||||
enabled: true
|
||||
cookie_lifetime: 3600
|
||||
|
||||
#esi: true
|
||||
#fragments: true
|
||||
|
10
config/packages/nelmio_cors.yaml
Normal file
10
config/packages/nelmio_cors.yaml
Normal file
@ -0,0 +1,10 @@
|
||||
nelmio_cors:
|
||||
defaults:
|
||||
origin_regex: true
|
||||
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
|
||||
allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
|
||||
allow_headers: ['Content-Type', 'Authorization']
|
||||
expose_headers: ['Link']
|
||||
max_age: 3600
|
||||
paths:
|
||||
'^/': null
|
@ -38,6 +38,9 @@ security:
|
||||
- { path: ^/admin, roles: ROLE_ADMIN }
|
||||
- { path: ^/profile, roles: ROLE_USER }
|
||||
- { path: ^/bibliography, roles: ROLE_USER }
|
||||
- { path: ^/collection, roles: ROLE_USER }
|
||||
- { path: ^/object, roles: ROLE_USER }
|
||||
- { path: ^/site, roles: ROLE_USER }
|
||||
|
||||
when@test:
|
||||
security:
|
||||
|
4
config/routes/api_platform.yaml
Normal file
4
config/routes/api_platform.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
api_platform:
|
||||
resource: .
|
||||
type: api_platform
|
||||
prefix: /api
|
@ -3,6 +3,7 @@
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Bibliography;
|
||||
use App\Form\BibliographyType;
|
||||
//use App\Security\Voter\VocabVoter;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
@ -23,10 +24,18 @@ class BibliographyController extends AbstractController
|
||||
}
|
||||
|
||||
#[Route('/bibliography', name: 'app_bibliography_landing')]
|
||||
public function landing(): Response
|
||||
public function landing(EntityManagerInterface $em): Response
|
||||
{
|
||||
$repo = $em->getRepository(Bibliography::class);
|
||||
$records = $repo->findBy([], ['modifiedAt' => 'DESC']);
|
||||
$count = count($records);
|
||||
|
||||
$records = array_slice($records, 0, 15);
|
||||
|
||||
return $this->render('bibliography/landing.html.twig', [
|
||||
'controller_name' => 'BibliographyController',
|
||||
'records' => $records,
|
||||
'count' => $count,
|
||||
]);
|
||||
}
|
||||
|
||||
@ -38,11 +47,30 @@ class BibliographyController extends AbstractController
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/bibliography/add', name: 'app_bibliography_add')]
|
||||
/**
|
||||
* @todo Permissions with voter
|
||||
*/
|
||||
#[Route('/bibliography/add', name: 'app_bibliography_create')]
|
||||
public function add(): Response
|
||||
{
|
||||
return $this->render('bibliography/add.html.twig', [
|
||||
$form = $this->createForm(BibliographyType::class);
|
||||
|
||||
return $this->render('bibliography/create.html.twig', [
|
||||
'controller_name' => 'BibliographyController',
|
||||
'form' => $form,
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* @todo Permissions!
|
||||
*/
|
||||
#[Route('/bibliography/delete/{id<\d+>}', name: 'app_bibliography_del')]
|
||||
public function delete(Bibliography $bibliography, EntityManagerInterface $em): Response
|
||||
{
|
||||
$em->remove($bibliography);
|
||||
$em->flush();
|
||||
|
||||
$this->addFlash('notice', 'Term deleted successfully');
|
||||
|
||||
return $this->redirectToRoute('app_bibliography_landing');
|
||||
}
|
||||
}
|
||||
|
26
src/Controller/CollectionController.php
Normal file
26
src/Controller/CollectionController.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Collection;
|
||||
use App\Entity\Bibliography;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class CollectionController extends AbstractController
|
||||
{
|
||||
#[Route('/collection/{id<\d+>}', name: 'app_collection')]
|
||||
public function index(Collection $collection, EntityManagerInterface $em): Response
|
||||
{
|
||||
$bibliographies = $em->getRepository(Bibliography::class)->findAllCollection($collection->getId());
|
||||
|
||||
$collection->setBibliographies($bibliographies);
|
||||
|
||||
return $this->render('collection/index.html.twig', [
|
||||
'controller_name' => 'CollectionController',
|
||||
'record' => $collection,
|
||||
]);
|
||||
}
|
||||
}
|
34
src/Controller/VocabObjectTypeController.php
Normal file
34
src/Controller/VocabObjectTypeController.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use App\Entity\VocabObjectType;
|
||||
|
||||
/**
|
||||
* @todo Pagination
|
||||
*/
|
||||
class VocabObjectTypeController extends AbstractController
|
||||
{
|
||||
#[Route('/vocabs/object_type', name: 'app_vocab_object_type')]
|
||||
public function index(EntityManagerInterface $em): Response
|
||||
{
|
||||
$roles = $this->getUser()->getRoles();
|
||||
|
||||
if (in_array('ROLE_READER', $roles)) {
|
||||
$this->addFlash('warning', 'Only editors, revisors and administrators can view vocabularies');
|
||||
return $this->redirectToRoute('app_home');
|
||||
}
|
||||
|
||||
$terms = $em->getRepository(VocabObjectType::class)
|
||||
->findBy([], ['term' => 'ASC']);
|
||||
|
||||
return $this->render('vocab_object_type/index.html.twig', [
|
||||
'controller_name' => 'VocabObjectTypeController',
|
||||
'terms' => $terms
|
||||
]);
|
||||
}
|
||||
}
|
@ -2,14 +2,14 @@
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
//use App\Repository\UserRepository;
|
||||
|
||||
use App\Repository\BibliographyRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use App\RecordStatus;
|
||||
use Doctrine\Common\Collections\Collection as DoctrineCollection;
|
||||
|
||||
#[ORM\Entity()]
|
||||
#[ORM\Entity(repositoryClass: BibliographyRepository::class)]
|
||||
#[ORM\Table(name: 'bibliography')]
|
||||
class Bibliography
|
||||
{
|
||||
@ -42,6 +42,20 @@ class Bibliography
|
||||
#[ORM\Column(length: 100, name: 'creator')]
|
||||
private ?string $creator = null;
|
||||
|
||||
#[ORM\JoinTable(name: 'rel_riferimento_collezione')]
|
||||
#[ORM\JoinColumn(name: 'Bibliografia_id_bib', referencedColumnName: 'id')]
|
||||
#[ORM\InverseJoinColumn(name: 'Collezione_id_coll', referencedColumnName: 'id')]
|
||||
#[ORM\ManyToMany(targetEntity: Collection::class)]
|
||||
private DoctrineCollection $collections;
|
||||
|
||||
private DoctrineCollection $documents;
|
||||
|
||||
private DoctrineCollection $objects;
|
||||
|
||||
private DoctrineCollection $persons;
|
||||
|
||||
private DoctrineCollection $sites;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
@ -143,4 +157,16 @@ class Bibliography
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCollections(): ?DoctrineCollection
|
||||
{
|
||||
return $this->collections;
|
||||
}
|
||||
|
||||
public function setCollections(DoctrineCollection $collections): static
|
||||
{
|
||||
$this->collections = $collections;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
295
src/Entity/Collection.php
Normal file
295
src/Entity/Collection.php
Normal file
@ -0,0 +1,295 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
//use App\Repository\UserRepository;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use App\RecordStatus;
|
||||
use Doctrine\Common\Collections\Collection as DoctrineCollection;
|
||||
|
||||
#[ORM\Entity()]
|
||||
#[ORM\Table(name: 'collection')]
|
||||
class Collection
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(name: 'id')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(name: 'stato')]
|
||||
private ?int $status = null;
|
||||
|
||||
#[ORM\Column(name: 'modif')]
|
||||
private ?DateTimeImmutable $modifiedAt = null;
|
||||
|
||||
#[ORM\Column(name: 'tit_coll', type: Types::TEXT)]
|
||||
private ?string $title = null;
|
||||
|
||||
#[ORM\Column(name: 'data_coll', type: Types::TEXT)]
|
||||
private ?string $chronology = null;
|
||||
|
||||
#[ORM\Column(name: 'inizio_coll', type: Types::SMALLINT)]
|
||||
private ?int $startDate = null;
|
||||
|
||||
#[ORM\Column(name: 'fine_coll', type: Types::SMALLINT)]
|
||||
private ?int $endDate = null;
|
||||
|
||||
#[ORM\Column(name: 'desc_coll', type: Types::TEXT)]
|
||||
private ?string $description = null;
|
||||
|
||||
#[ORM\Column(name: 'desc_br_coll', type: Types::TEXT)]
|
||||
private ?string $shortDescription = null;
|
||||
|
||||
#[ORM\Column(name: 'id_est_coll', type: Types::TEXT)]
|
||||
private ?string $externalIdentifier = null;
|
||||
|
||||
#[ORM\Column(name: 'link_coll', type: Types::TEXT)]
|
||||
private ?string $link = null;
|
||||
|
||||
#[ORM\Column(name: 'sogg_coll', type: Types::TEXT)]
|
||||
private ?string $subjectHeadings = null;
|
||||
|
||||
#[ORM\Column(name: 'uri_coll', type: Types::TEXT)]
|
||||
private ?string $uri = null;
|
||||
|
||||
#[ORM\Column(name: 'resp', length: 100)]
|
||||
private ?string $owner = null;
|
||||
|
||||
#[ORM\Column(name: 'note_coll', type: Types::TEXT)]
|
||||
private ?string $notes = null;
|
||||
|
||||
#[ORM\Column(length: 100, name: 'editor')]
|
||||
private ?string $editor = null;
|
||||
|
||||
#[ORM\Column(length: 100, name: 'creator')]
|
||||
private ?string $creator = null;
|
||||
|
||||
// TODO: These are references to vocabs
|
||||
#[ORM\Column(name: 'dir_aut_coll')]
|
||||
private ?int $authorRights = null;
|
||||
|
||||
#[ORM\Column(name: 'dir_acc_coll')]
|
||||
private ?int $accessRights = null;
|
||||
|
||||
#[ORM\Column(name: 'lic_coll')]
|
||||
private ?int $license = null;
|
||||
|
||||
#[ORM\JoinTable(name: 'rel_riferimento_collezione')]
|
||||
#[ORM\JoinColumn(name: 'Collezione_id_coll', referencedColumnName: 'id')]
|
||||
#[ORM\InverseJoinColumn(name: 'Bibliografia_id_bib', referencedColumnName: 'id')]
|
||||
#[ORM\ManyToMany(targetEntity: Bibliography::class)]
|
||||
private DoctrineCollection $bibliographies;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getStatus(): ?string
|
||||
{
|
||||
$status = RecordStatus::tryFrom($this->status);
|
||||
return $status->toString();
|
||||
}
|
||||
|
||||
public function setStatus(int $status): static
|
||||
{
|
||||
$this->status = $status;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getModifiedAt(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->modifiedAt;
|
||||
}
|
||||
|
||||
public function setModifiedAt(DateTimeImmutable $modifiedAt): static
|
||||
{
|
||||
$this->modifiedAt = $modifiedAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOwner(): ?string
|
||||
{
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
public function setOwner(string $owner): static
|
||||
{
|
||||
$this->owner = $owner;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEditor(): ?string
|
||||
{
|
||||
return $this->editor;
|
||||
}
|
||||
|
||||
public function setEditor(string $editor): static
|
||||
{
|
||||
$this->editor = $editor;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreator(): ?string
|
||||
{
|
||||
return $this->creator;
|
||||
}
|
||||
|
||||
public function setCreator(string $creator): static
|
||||
{
|
||||
$this->creator = $creator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getTitle(): ?string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setTitle(string $title): static
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getChronology(): ?string
|
||||
{
|
||||
return $this->chronology;
|
||||
}
|
||||
|
||||
public function setChronology(string $chronology): static
|
||||
{
|
||||
$this->chronology = $chronology;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStartDate(): ?int
|
||||
{
|
||||
return $this->startDate;
|
||||
}
|
||||
|
||||
public function setStartDate(int $startDate): static
|
||||
{
|
||||
$this->startDate = $startDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getEndDate(): ?int
|
||||
{
|
||||
return $this->endDate;
|
||||
}
|
||||
|
||||
public function setEndDate(int $endDate): static
|
||||
{
|
||||
$this->endDate = $endDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(string $description): static
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getShortDescription(): ?string
|
||||
{
|
||||
return $this->shortDescription;
|
||||
}
|
||||
|
||||
public function setShortDescription(string $shortDescription): static
|
||||
{
|
||||
$this->shortDescription = $shortDescription;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getExternalIdentifier(): ?string
|
||||
{
|
||||
return $this->externalIdentifier;
|
||||
}
|
||||
|
||||
public function setExternalIdentifier(string $externalIdentifier): static
|
||||
{
|
||||
$this->externalIdentifier = $externalIdentifier;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLink(): ?string
|
||||
{
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
public function setLink(string $link): static
|
||||
{
|
||||
$this->link = $link;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSubjectHeadings(): ?string
|
||||
{
|
||||
return $this->link;
|
||||
}
|
||||
|
||||
public function setSubjectHeadings(string $subjectHeadings): static
|
||||
{
|
||||
$this->subjectHeadings = $subjectHeadings;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUri(): ?string
|
||||
{
|
||||
return $this->uri;
|
||||
}
|
||||
|
||||
public function setUri(string $uri): static
|
||||
{
|
||||
$this->uri = $uri;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNotes(): ?string
|
||||
{
|
||||
return $this->notes;
|
||||
}
|
||||
|
||||
public function setNotes(string $notes): static
|
||||
{
|
||||
$this->notes = $notes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getBibliographies(): ?DoctrineCollection
|
||||
{
|
||||
return $this->bibliographies;
|
||||
}
|
||||
|
||||
public function setBibliographies(DoctrineCollection $bibliographies): static
|
||||
{
|
||||
$this->bibliographies = $bibliographies;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
37
src/Entity/VocabObjectType.php
Normal file
37
src/Entity/VocabObjectType.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
//use App\Repository\UserRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity()]
|
||||
#[ORM\Table(name: 'lis_tipologia_oggetto')]
|
||||
class VocabObjectType implements \App\VocabInterface
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column(name: 'id_lis_tip_ogg')]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 80, name: 'lis_tip_ogg')]
|
||||
private ?string $term = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getTerm(): ?string
|
||||
{
|
||||
return $this->term;
|
||||
}
|
||||
|
||||
public function setTerm(string $term): static
|
||||
{
|
||||
$this->term = $term;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
51
src/Form/BibliographyType.php
Normal file
51
src/Form/BibliographyType.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Bibliography;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class BibliographyType extends AbstractType
|
||||
{
|
||||
/**
|
||||
* @todo Create status choices from enum
|
||||
*/
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('status', ChoiceType::class, [
|
||||
'choices' => [
|
||||
'-- Select status --' => '',
|
||||
'Draft' => 1,
|
||||
'Complete' => 2,
|
||||
'Unindexed' => 3,
|
||||
'Published' => 4,
|
||||
],
|
||||
'label' => 'Status (*)'
|
||||
])
|
||||
->add(
|
||||
'editor',
|
||||
TextType::class,
|
||||
[
|
||||
'label' => 'Editor(s) (*)'
|
||||
]
|
||||
)
|
||||
->add('citation', TextType::class, ['label' => 'Citation (*)'])
|
||||
->add('reference', TextareaType::class, ['label' => 'Reference (*)'])
|
||||
->add('notes', TextareaType::class, ['label' => 'Editorial notes', 'required' => false])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Bibliography::class,
|
||||
]);
|
||||
}
|
||||
}
|
@ -5,6 +5,8 @@ namespace App\Repository;
|
||||
use App\Entity\Bibliography;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Query\ResultSetMappingBuilder;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Bibliography>
|
||||
@ -15,5 +17,24 @@ class BibliographyRepository extends ServiceEntityRepository
|
||||
{
|
||||
parent::__construct($registry, Bibliography::class);
|
||||
}
|
||||
|
||||
public function findAllCollection(int $collectionId): ?ArrayCollection
|
||||
{
|
||||
$rsm = new ResultSetMappingBuilder($this->getEntityManager());
|
||||
$rsm->addRootEntityFromClassMetadata('App\Entity\Bibliography', 'b');
|
||||
|
||||
$query = $this->getEntityManager()->createNativeQuery(
|
||||
"SELECT id, stato, editor, cit_bib, rif_bib FROM bibliography b
|
||||
JOIN rel_riferimento_collezione
|
||||
ON Bibliografia_id_bib = id
|
||||
WHERE Collezione_id_coll = :collId",
|
||||
$rsm
|
||||
);
|
||||
$query->setParameter('collId', $collectionId);
|
||||
|
||||
$bibliographies = new ArrayCollection($query->getResult());
|
||||
|
||||
return $bibliographies;
|
||||
}
|
||||
}
|
||||
|
||||
|
20
src/Repository/CollectionRepository.php
Normal file
20
src/Repository/CollectionRepository.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Collection;
|
||||
use App\Repository\BibliographyRepository;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<Collection>
|
||||
*/
|
||||
class CollectionRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Collection::class);
|
||||
}
|
||||
}
|
||||
|
18
src/Repository/VocabObjectTypeRepository.php
Normal file
18
src/Repository/VocabObjectTypeRepository.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\VocabObjectType;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<VocabFuncContext>
|
||||
*/
|
||||
class VocabObjectTypeRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, VocabObjectType::class);
|
||||
}
|
||||
}
|
35
symfony.lock
35
symfony.lock
@ -1,4 +1,18 @@
|
||||
{
|
||||
"api-platform/symfony": {
|
||||
"version": "4.0",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "4.0",
|
||||
"ref": "e9952e9f393c2d048f10a78f272cd35e807d972b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/api_platform.yaml",
|
||||
"config/routes/api_platform.yaml",
|
||||
"src/ApiResource/.gitignore"
|
||||
]
|
||||
},
|
||||
"doctrine/doctrine-bundle": {
|
||||
"version": "2.13",
|
||||
"recipe": {
|
||||
@ -26,6 +40,18 @@
|
||||
"migrations/.gitignore"
|
||||
]
|
||||
},
|
||||
"nelmio/cors-bundle": {
|
||||
"version": "2.5",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "1.5",
|
||||
"ref": "6bea22e6c564fba3a1391615cada1437d0bde39c"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/nelmio_cors.yaml"
|
||||
]
|
||||
},
|
||||
"phpunit/phpunit": {
|
||||
"version": "9.6",
|
||||
"recipe": {
|
||||
@ -248,6 +274,15 @@
|
||||
"templates/base.html.twig"
|
||||
]
|
||||
},
|
||||
"symfony/uid": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "7.0",
|
||||
"ref": "0df5844274d871b37fc3816c57a768ffc60a43a5"
|
||||
}
|
||||
},
|
||||
"symfony/ux-turbo": {
|
||||
"version": "v2.21.0"
|
||||
},
|
||||
|
72
templates/bibliography/create.html.twig
Normal file
72
templates/bibliography/create.html.twig
Normal file
@ -0,0 +1,72 @@
|
||||
{% extends 'data_entry.html.twig' %}
|
||||
|
||||
{% block title %}Bibliography - Add new | ArCOA{% endblock %}
|
||||
|
||||
{% block rightpanel %}
|
||||
<div class="container" style="max-width: 60vw">
|
||||
<h1 class="is-size-1 mt-0 has-text-centered">Bibliography</h1>
|
||||
<h2 class="is-size-3 mt-3 has-text-centered">Add new record</h2>
|
||||
|
||||
<p class="pt-4 pb-4 has-text-link has-text-weight-bold">Fields marked with (*) are mandatory</p>
|
||||
<div class="card p-5 has-background-light">
|
||||
{{ form_start(form) }}
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{{ form_label(form.status) }}
|
||||
</label>
|
||||
<div class="select">
|
||||
{{ form_widget(form.status) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{{ form_label(form.editor) }}
|
||||
</label>
|
||||
<div class="control">
|
||||
{{
|
||||
form_widget(
|
||||
form.editor,
|
||||
{'attr': {'class': 'input', 'placeholder': 'Name of the editor (mandatory)'}}
|
||||
)
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{{ form_label(form.citation) }}
|
||||
</label>
|
||||
<div class="control">
|
||||
{{ form_widget(form.citation, {'attr': {'class': 'input'}}) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{{ form_label(form.reference) }}
|
||||
</label>
|
||||
<div class="control">
|
||||
{{ form_widget(form.reference, {'attr': {'class': 'textarea'}}) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">
|
||||
{{ form_label(form.notes) }}
|
||||
</label>
|
||||
<div class="control">
|
||||
{{ form_widget(form.notes, {'attr': {'class': 'textarea'}}) }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="field is-grouped is-grouped-right mt-5">
|
||||
<div class="control">
|
||||
<button type="submit" class="button is-link">
|
||||
Save
|
||||
<span class="icon ml-3">
|
||||
<i class="fa fa-save"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" defer></script>
|
||||
{% endblock %}
|
@ -1,6 +1,6 @@
|
||||
{% extends 'data_entry.html.twig' %}
|
||||
|
||||
{% block title %}Bibliography | ArCOA{% endblock %}
|
||||
{% block title %}Bibliography - {{ record.citation }} | ArCOA{% endblock %}
|
||||
|
||||
{% block rightpanel %}
|
||||
<div class="container" style="max-width: 60vw">
|
||||
@ -16,6 +16,7 @@
|
||||
<p><strong>Editor:</strong> {{ record.editor }}</p>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div class="card p-5">
|
||||
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}
|
||||
<div class="columns">
|
||||
@ -27,12 +28,18 @@
|
||||
<i class="fa fa-edit"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button class="button is-danger ml-2">
|
||||
<button class="button is-link">
|
||||
Copy
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-copy"></i>
|
||||
</span>
|
||||
</button>
|
||||
<a href="{{ path('app_bibliography_del', {'id' : record.id}) }}" class="button is-danger" id="del-record">
|
||||
Delete
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-trash"></i>
|
||||
</span>
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@ -57,5 +64,54 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" defer></script>
|
||||
|
||||
<div class="modal">
|
||||
<div class="modal-background"></div>
|
||||
<div class="modal-card">
|
||||
<header class="modal-card-head">
|
||||
<span class="icon is-large has-text-warning">
|
||||
<i class="fa fa-warning fa-2x"></i>
|
||||
</span>
|
||||
<p class="modal-card-title has-text-danger pl-2"><strong>Delete record?</strong></p>
|
||||
<button class="delete" aria-label="close"></button>
|
||||
</header>
|
||||
<section class="modal-card-body">
|
||||
<p class="is-size-5">This record will be permanently deleted. Proceed?</p>
|
||||
</section>
|
||||
<footer class="modal-card-foot">
|
||||
<div class="buttons is-right">
|
||||
<button class="button is-link" id="confirm-del">Confirm</button>
|
||||
<button class="button is-light" id="cancel">Cancel</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" defer>
|
||||
const del = document.querySelector('#del-record');
|
||||
const delPath = del.href;
|
||||
|
||||
del.addEventListener('click', event => {
|
||||
event.preventDefault();
|
||||
|
||||
const modal = document.querySelector('.modal');
|
||||
modal.classList.add('is-active');
|
||||
|
||||
modal.querySelector('.delete').addEventListener('click', () => {
|
||||
modal.classList.remove('is-active');
|
||||
});
|
||||
modal.querySelector('.modal-background').addEventListener('click', () => {
|
||||
modal.classList.remove('is-active');
|
||||
});
|
||||
modal.querySelector('#cancel').addEventListener('click', () => {
|
||||
modal.classList.remove('is-active');
|
||||
});
|
||||
|
||||
// Proceed with deletion...
|
||||
modal.querySelector('#confirm-del').addEventListener('click', () => {
|
||||
location.href = delPath;
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
@ -7,19 +7,25 @@
|
||||
<h1 class="is-size-1 mt-0 has-text-centered">Bibliography</h1>
|
||||
<h2 class="is-size-3 mt-3 has-text-centered">Choose action</h2>
|
||||
|
||||
{% for message in app.flashes('notice') %}
|
||||
<div class=" mt-4 notification is-success">
|
||||
<button class="delete"></button>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="card p-5 mt-6 pt-6 pb-6">
|
||||
<div class="columns">
|
||||
<div class="column is-half has-text-centered">
|
||||
<a href="{{ path('app_bibliography_search') }}" class="button is-large">
|
||||
<button class="button is-medium">
|
||||
Search
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-search"></i>
|
||||
</span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') or is_granted('ROLE_EDITOR') %}
|
||||
<div class="column has-text-centered">
|
||||
<a href="{{ path('app_bibliography_add') }}" class="button is-link is-large">
|
||||
<a href="{{ path('app_bibliography_create') }}" class="button is-link is-medium">
|
||||
Add new
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-plus"></i>
|
||||
@ -29,6 +35,54 @@
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="has-text-centered is-size-4 mt-6">Records</h3>
|
||||
<p class="pt-4 pb-4"><strong>{{ count }} result(s) found</strong></p>
|
||||
<table class="table is-hoverable is-fullwidth mt-5 has-text-centered results">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Citation</th>
|
||||
<th>Status</th>
|
||||
<th>Editor</th>
|
||||
<th>Reference</th>
|
||||
<th>Last modified</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
{% for record in records %}
|
||||
<tr>
|
||||
<td><a href="{{ path('app_bibliography', {'id' : record.id}) }}">{{ record.id }}</a></td>
|
||||
<td><a href="{{ path('app_bibliography', {'id' : record.id}) }}">{{ record.citation }}</a></td>
|
||||
<td>{{ record.status }}</td>
|
||||
<td>{{ record.owner }}</td>
|
||||
<td style="max-width: 350px;">{{ record.reference }}</td>
|
||||
<td>
|
||||
{{ record.modifiedAt.format('Y-m-d') }}<br>
|
||||
{{ record.editor }} at {{ record.modifiedAt.format('H:i:s') }}
|
||||
</td>
|
||||
<td style="min-width: 120px;">
|
||||
<div class="buttons">
|
||||
<button class="button is-small is-link" title="Edit record">
|
||||
<span class="icon">
|
||||
<i class="fa fa-edit"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button class="button is-small is-danger" title="Delete record">
|
||||
<span class="icon">
|
||||
<i class="fa fa-trash"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
<script type="text/javascript" defer></script>
|
||||
<script type="text/javascript" defer>
|
||||
const delBtns = document.querySelectorAll('.delete');
|
||||
for (let btn of delBtns) {
|
||||
btn.addEventListener('click', function () {
|
||||
this.parentElement.classList.add('is-hidden');
|
||||
})
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
89
templates/collection/index.html.twig
Normal file
89
templates/collection/index.html.twig
Normal file
@ -0,0 +1,89 @@
|
||||
{% extends 'data_entry.html.twig' %}
|
||||
|
||||
{% block title %}Collection - {{ record.title }} | ArCOA{% endblock %}
|
||||
|
||||
{% block rightpanel %}
|
||||
<div class="container" style="max-width: 60vw">
|
||||
<h1 class="is-size-1 mt-0 has-text-centered">Collection</h1>
|
||||
<h2 class="is-size-3 mt-3 has-text-centered">{{ record.title }}</h2>
|
||||
|
||||
<article class="message is-info mt-3">
|
||||
<div class="message-body">
|
||||
<p>
|
||||
<strong>Last modified:</strong> {{ record.modifiedAt.format('Y-m-d') }}
|
||||
at {{ record.modifiedAt.format('H:i:s') }}
|
||||
</p>
|
||||
<p><strong>Editor:</strong> {{ record.editor }}</p>
|
||||
</div>
|
||||
</article>
|
||||
<div class="card p-5">
|
||||
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}
|
||||
<div class="columns">
|
||||
<div class="column is-half"></div>
|
||||
<div class="column has-text-right">
|
||||
<button class="button is-link">
|
||||
Edit
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-edit"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button class="button is-link">
|
||||
Copy
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-copy"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button class="button is-danger">
|
||||
Delete
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-trash"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="tabs is-boxed is-fullwidth">
|
||||
<ul>
|
||||
<li class="is-active">Record</li>
|
||||
<li>Relations</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="data-tabs" id="record">
|
||||
<table class="table is-fullwidth pt-4 record">
|
||||
<tr><th>Record ID</th><td>{{ record.id }}</td></tr>
|
||||
<tr><th>Status</th><td>{{ record.getStatus() }}</td></tr>
|
||||
<tr><th>Editor(s)</th><td>{{ record.editor }}</td></tr>
|
||||
<tr><th>Collection name</th><td>{{ record.title }}</td></tr>
|
||||
<tr><th>Chronology</th><td>{{ record.chronology }}</td></tr>
|
||||
<tr><th>Start date</th><td>{{ record.startDate }}</td></tr>
|
||||
<tr><th>End date</th><td>{{ record.endDate }}</td></tr>
|
||||
<tr><th>Description</th><td>{{ record.description }}</td></tr>
|
||||
<tr><th>Short description</th><td>{{ record.shortDescription }}</td></tr>
|
||||
<tr><th>External identifier(s)</th><td>{{ record.externalIdentifier }}</td></tr>
|
||||
<tr><th>External link(s)</th><td>{{ record.link }}</td></tr>
|
||||
<tr><th>Subject headings</th><td>{{ record.subjectHeadings }}</td></tr>
|
||||
<tr><th>ArCOA URI</th><td>{{ record.uri }}</td></tr>
|
||||
<tr><th>Editorial notes</th><td>{{ record.notes }}</td></tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="data-tabs is-hidden" id="relations">
|
||||
{% if record.bibliographies %}
|
||||
<p class="p-4 has-text-bold">Bibliographies</p>
|
||||
<table class="table is-fullwidth is-hoverable has-text-centered">
|
||||
<tr><th>ID</th><th>Status</th><th>Citation</th><th>Editor</th><th>Reference</th></tr>
|
||||
{% for biblio in record.bibliographies %}
|
||||
<tr>
|
||||
<td><a href="{{ path('app_bibliography', {'id' : biblio.id}) }}">{{ biblio.id }}</a></td>
|
||||
<td><a href="{{ path('app_bibliography', {'id' : biblio.id}) }}">{{ biblio.citation }}</a></td>
|
||||
<td>{{ biblio.status }}</td>
|
||||
<td>{{ biblio.editor }}</td>
|
||||
<td>{{ biblio.reference }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" defer></script>
|
||||
{% endblock %}
|
@ -3,9 +3,12 @@
|
||||
{% block body %}
|
||||
|
||||
<nav class="navbar has-background-light">
|
||||
<div class="navbar-start">
|
||||
<div class="navbar-start ml-4">
|
||||
<a href="/" class="navbar-item">
|
||||
<strong>ArCOA Data Entry</strong>
|
||||
<span class="icon is-clickable">
|
||||
<i class="fa fa-home"></i>
|
||||
</span>
|
||||
<strong>ArCOA Digital Archive</strong>
|
||||
</a>
|
||||
</div>
|
||||
{% if app.user %}
|
||||
@ -56,7 +59,7 @@
|
||||
</nav>
|
||||
<div class="columns mb-0">
|
||||
<div class="column is-one-fifth arcoa-menu mb-0">
|
||||
<aside class="menu pl-4">
|
||||
<aside class="menu">
|
||||
{% if 'ROLE_READER' not in app.user.roles %}
|
||||
<p class="menu-label has-text-white mt-3 pt-5 pl-5 is-size-6">
|
||||
Vocabularies
|
||||
@ -146,7 +149,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a>
|
||||
<a href="{{ path('app_vocab_object_type') }}">
|
||||
<span class="icon pr-3">
|
||||
<i class="fa fa-plus"></i>
|
||||
</span>
|
||||
@ -209,6 +212,18 @@
|
||||
<i class="fa fa-angle-right"></i>
|
||||
</span>
|
||||
</p>
|
||||
<ul class="pl-6 is-hidden has-text-white" id="records">
|
||||
<li>
|
||||
<a href="{{ path('app_bibliography_landing') }}">
|
||||
Bibliography
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="">
|
||||
Collection
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
<div class="column mt-6 mb-6">
|
||||
|
@ -87,7 +87,7 @@
|
||||
terms.addEventListener('click', async (event) => {
|
||||
const clicked = event.target;
|
||||
|
||||
if (clicked.classList.contains('is-danger')) {
|
||||
if (clicked.getAttribute('data-id-delete')) {
|
||||
const termId = clicked.getAttribute('data-id-delete');
|
||||
|
||||
const data = new FormData;
|
||||
@ -103,7 +103,7 @@
|
||||
if (res.status === 200) {
|
||||
notice.innerHTML = `
|
||||
<button class="delete"></button>
|
||||
Term updated successfully
|
||||
Term deleted successfully
|
||||
`;
|
||||
notice.classList.remove('is-hidden');
|
||||
notice.querySelector('.delete').addEventListener('click', () => {
|
||||
|
167
templates/vocab_object_type/index.html.twig
Normal file
167
templates/vocab_object_type/index.html.twig
Normal file
@ -0,0 +1,167 @@
|
||||
{% extends 'data_entry.html.twig' %}
|
||||
|
||||
{% block title %}Vocab - Functional context | ArCOA{% endblock %}
|
||||
|
||||
{% block rightpanel %}
|
||||
<div class="container" style="max-width: 50vw">
|
||||
<h1 class="is-size-1 mt-0 has-text-centered">Vocabulary</h1>
|
||||
<h2 class="is-size-3 mt-4 has-text-centered">Object type</h2>
|
||||
|
||||
<div class="container mt-6">
|
||||
<!-- For AJAX calls... TODO: not working from controller? -->
|
||||
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}
|
||||
<form method="post" action="{{ path('app_vocab_func_context_add') }}">
|
||||
<label class="label">Add new term</label>
|
||||
<div class="field has-addons">
|
||||
<div class="control">
|
||||
<input class="input" name="_term" type="text" placeholder="Add new term">
|
||||
</div>
|
||||
<div class="control">
|
||||
<button type="submit" class="button is-link">
|
||||
Add
|
||||
<span class="icon ml-3">
|
||||
<i class="fa fa-plus"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
<div class="notification is-success is-hidden mt-5" id="ajax-success">
|
||||
</div>
|
||||
{% for message in app.flashes('notice') %}
|
||||
<div class="notification is-success mt-5" id="server-success">
|
||||
<button class="delete"></button>
|
||||
{{ message }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<h3 class="mt-6 mb-5 is-size-5"><strong>Terms in vocabulary</strong></h3>
|
||||
<table class="table is-fullwidth" id="terms">
|
||||
<tr><th>Term</th>{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}<th>Actions</th>{% endif %}</tr>
|
||||
{% for term in terms %}
|
||||
<tr data-row-id="{{ term.id }}">
|
||||
<td>
|
||||
<input class="input" type="text" value="{{ term.term }}" disabled data-term-id="{{ term.id }}" />
|
||||
</td>
|
||||
{% if is_granted('ROLE_ADMIN') or is_granted('ROLE_REVISOR') %}
|
||||
<td>
|
||||
<div class="buttons">
|
||||
<button class="button is-primary is-hidden" data-id-save="{{ term.id }}">
|
||||
Save
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-save"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button class="button is-link" data-id-edit="{{ term.id }}">
|
||||
Edit
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-edit"></i>
|
||||
</span>
|
||||
</button>
|
||||
<button class="button is-danger" data-id-delete="{{ term.id }}">
|
||||
Delete
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-trash"></i>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" defer>
|
||||
const terms = document.querySelector('#terms');
|
||||
const serverNotice = document.querySelector('#server-success');
|
||||
|
||||
if (serverNotice) {
|
||||
serverNotice.querySelector('.delete').addEventListener('click', () => {
|
||||
serverNotice.remove();
|
||||
});
|
||||
}
|
||||
|
||||
terms.addEventListener('click', async (event) => {
|
||||
const clicked = event.target;
|
||||
|
||||
if (clicked.getAttribute('data-id-delete')) {
|
||||
const termId = clicked.getAttribute('data-id-delete');
|
||||
|
||||
const data = new FormData;
|
||||
data.append("_id", termId);
|
||||
|
||||
const res = await fetch("{{ path('app_vocab_func_context_del') }}", {
|
||||
method: "POST",
|
||||
body: data,
|
||||
});
|
||||
|
||||
const notice = document.querySelector('#ajax-success');
|
||||
|
||||
if (res.status === 200) {
|
||||
notice.innerHTML = `
|
||||
<button class="delete"></button>
|
||||
Term deleted successfully
|
||||
`;
|
||||
notice.classList.remove('is-hidden');
|
||||
notice.querySelector('.delete').addEventListener('click', () => {
|
||||
notice.classList.add('is-hidden');
|
||||
});
|
||||
const row = document.querySelector(`tr[data-row-id="${termId}"]`);
|
||||
row.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (clicked.getAttribute('data-id-edit')) {
|
||||
const termId = clicked.getAttribute('data-id-edit');
|
||||
const saveBtn = document.querySelector(`button[data-id-save="${termId}"]`);
|
||||
const input = document.querySelector(`input[data-term-id="${termId}"]`);
|
||||
input.disabled = input.disabled ? false : true;
|
||||
saveBtn.classList.toggle('is-hidden');
|
||||
|
||||
clicked.classList.toggle('is-link');
|
||||
|
||||
if (!clicked.classList.contains('is-link')) {
|
||||
clicked.innerHTML = `
|
||||
Cancel
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-times"></i>
|
||||
</span>
|
||||
`;
|
||||
} else {
|
||||
clicked.innerHTML = `
|
||||
Edit
|
||||
<span class="icon ml-2">
|
||||
<i class="fa fa-edit"></i>
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
|
||||
const data = new FormData;
|
||||
data.append("_id", termId);
|
||||
saveBtn.addEventListener('click', async () => {
|
||||
data.append("_new_term", input.value);
|
||||
const res = await fetch("{{ path('app_vocab_func_context_upd') }}", {
|
||||
method: "POST",
|
||||
body: data,
|
||||
});
|
||||
|
||||
const notice = document.querySelector('#ajax-success');
|
||||
|
||||
if (res.status === 200) {
|
||||
notice.innerHTML = `
|
||||
<button class="delete"></button>
|
||||
Term updated successfully
|
||||
`;
|
||||
notice.classList.remove('is-hidden');
|
||||
notice.querySelector('.delete').addEventListener('click', () => {
|
||||
notice.classList.add('is-hidden');
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
Loading…
Reference in New Issue
Block a user