mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-20 14:43:49 +00:00
Merge remote-tracking branch 'origin/issue466_file_upload' into workflow/fixes-2022-02
This commit is contained in:
@@ -70,9 +70,10 @@ class AccompanyingPeriodWorkEvaluation implements TrackCreationInterface, TrackU
|
||||
* @ORM\OneToMany(
|
||||
* targetEntity=AccompanyingPeriodWorkEvaluationDocument::class,
|
||||
* mappedBy="accompanyingPeriodWorkEvaluation",
|
||||
* cascade={"remove"}
|
||||
* cascade={"remove", "persist"}
|
||||
* )
|
||||
* @Serializer\Groups({"read"})
|
||||
* @Serializer\Groups({"read", "write"})
|
||||
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
|
||||
*/
|
||||
private Collection $documents;
|
||||
|
||||
|
@@ -61,7 +61,7 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
|
||||
* @ORM\SequenceGenerator(sequenceName="chill_person_social_work_eval_doc_id_seq", allocationSize=1, initialValue=1000)
|
||||
* @Serializer\Groups({"read"})
|
||||
*/
|
||||
private ?int $id;
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(
|
||||
@@ -69,6 +69,8 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
|
||||
* cascade={"remove"},
|
||||
* )
|
||||
* @Serializer\Groups({"read"})
|
||||
* @Serializer\Groups({"write"})
|
||||
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
|
||||
*/
|
||||
private ?StoredObject $storedObject = null;
|
||||
|
||||
@@ -80,6 +82,14 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
|
||||
*/
|
||||
private ?DocGeneratorTemplate $template = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", nullable=true)
|
||||
* @Serializer\Groups({"read"})
|
||||
* @Serializer\Groups({"write"})
|
||||
* @Serializer\Groups({"accompanying_period_work_evaluation:create"})
|
||||
*/
|
||||
private ?string $title = null;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="date_immutable", nullable=true, options={"default": null})
|
||||
* @Serializer\Groups({"read"})
|
||||
@@ -127,6 +137,11 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
public function getTitle(): ?string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DateTimeImmutable|null
|
||||
*/
|
||||
@@ -185,6 +200,13 @@ class AccompanyingPeriodWorkEvaluationDocument implements \Chill\MainBundle\Doct
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setTitle(?string $title): AccompanyingPeriodWorkEvaluationDocument
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setUpdatedAt(DateTimeInterface $datetime): TrackUpdateInterface
|
||||
{
|
||||
$this->updatedAt = $datetime;
|
||||
|
@@ -65,14 +65,31 @@
|
||||
<h5>{{ $t('Documents') }} :</h5>
|
||||
|
||||
<div class="flex-table">
|
||||
<div class="item-bloc" v-for="d in evaluation.documents">
|
||||
<div class="item-bloc" v-for="(d, i) in evaluation.documents" :key="i">
|
||||
<div class="item-row">
|
||||
<div class="item-col"><h6>{{ d.template.name.fr }}</h6></div>
|
||||
<div class="item-col">
|
||||
<p>Créé par {{ d.createdBy.text }}<br/>
|
||||
Le {{ $d(ISOToDatetime(d.createdAt.datetime), 'long') }}</p>
|
||||
|
||||
</div>
|
||||
<div class="item-col" style="margin-right: 6px;">
|
||||
<label class="col-form-label">
|
||||
{{ $t('document_title') }}
|
||||
</label>
|
||||
<div>
|
||||
<input
|
||||
class="form-control form-control-sm"
|
||||
type="string"
|
||||
:value=d.title
|
||||
:id=d.id
|
||||
@input="onInputDocumentTitle"/>
|
||||
</div>
|
||||
<div v-if="d.template">
|
||||
<label class="col-form-label">
|
||||
{{ $t('template_title') }}
|
||||
</label>
|
||||
<div>{{ d.template.name.fr }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-col">
|
||||
<p v-if="d.createdBy">Créé par {{ d.createdBy.text }}<br/>
|
||||
Le {{ $d(ISOToDatetime(d.createdAt.datetime), 'long') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-row">
|
||||
<ul class="record_actions" >
|
||||
@@ -81,6 +98,10 @@
|
||||
<i class="fa fa-edit"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a class="btn btn-sm btn-delete" @click="removeDocument(d)">
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,6 +109,7 @@
|
||||
</div>
|
||||
|
||||
<div class="row mb-3">
|
||||
<h6>{{ $t('document_add') }} :</h6>
|
||||
<pick-template
|
||||
entityClass="Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation"
|
||||
:id="evaluation.id"
|
||||
@@ -99,6 +121,20 @@
|
||||
<label class="col-sm-4 col-form-label">{{ $t('evaluation_generate_a_document') }}</label>
|
||||
</template>
|
||||
</pick-template>
|
||||
<div>
|
||||
<label class="col-sm-4 col-form-label">{{ $t('document_upload') }}</label>
|
||||
<ul class="record_actions">
|
||||
<li>
|
||||
<add-async-upload
|
||||
:buttonTitle="$t('browse')"
|
||||
:options="asyncUploadOptions"
|
||||
@addDocument="addDocument"
|
||||
>
|
||||
</add-async-upload>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,6 +147,7 @@ import ClassicEditor from 'ChillMainAssets/module/ckeditor5/index.js';
|
||||
import { mapGetters, mapState } from 'vuex';
|
||||
import PickTemplate from 'ChillDocGeneratorAssets/vuejs/_components/PickTemplate.vue';
|
||||
import {buildLink} from 'ChillDocGeneratorAssets/lib/document-generator';
|
||||
import AddAsyncUpload from 'ChillDocStoreAssets/vuejs/_components/AddAsyncUpload.vue';
|
||||
|
||||
const i18n = {
|
||||
messages: {
|
||||
@@ -129,6 +166,11 @@ const i18n = {
|
||||
evaluation_add_a_document: "Ajouter un document",
|
||||
evaluation_add: "Ajouter une évaluation",
|
||||
Documents: "Documents",
|
||||
document_add: "Générer ou téléverser un document",
|
||||
document_upload: "Téléverser un document",
|
||||
document_title: "Titre du document",
|
||||
template_title: "Nom du template",
|
||||
browse: "Ajouter un document"
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -139,14 +181,23 @@ export default {
|
||||
components: {
|
||||
ckeditor: CKEditor.component,
|
||||
PickTemplate,
|
||||
AddAsyncUpload
|
||||
},
|
||||
i18n,
|
||||
data() {
|
||||
return {
|
||||
editor: ClassicEditor,
|
||||
template: null,
|
||||
asyncUploadOptions: {
|
||||
maxFiles: 1,
|
||||
maxPostSize: 15000000,
|
||||
required: false,
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.evaluation)
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
'isPosting'
|
||||
@@ -162,7 +213,6 @@ export default {
|
||||
return dateToISO(this.evaluation.startDate);
|
||||
},
|
||||
set(v) {
|
||||
console.log(v);
|
||||
this.$store.commit('setEvaluationStartDate', { key: this.evaluation.key, date: ISOToDate(v) });
|
||||
}
|
||||
},
|
||||
@@ -205,11 +255,11 @@ export default {
|
||||
})
|
||||
;
|
||||
},
|
||||
buildEditLink(storedObject) {
|
||||
return `/wopi/edit/${storedObject.uuid}?returnPath=` + encodeURIComponent(
|
||||
buildEditLink(storedObject) {
|
||||
return `/wopi/edit/${storedObject.uuid}?returnPath=` + encodeURIComponent(
|
||||
window.location.pathname + window.location.search + window.location.hash);
|
||||
},
|
||||
submitBeforeGenerate({template}) {
|
||||
},
|
||||
submitBeforeGenerate({template}) {
|
||||
const callback = (data) => {
|
||||
let evaluationId = data.accompanyingPeriodWorkEvaluations.find(e => e.key === this.evaluation.key).id;
|
||||
|
||||
@@ -217,6 +267,21 @@ export default {
|
||||
};
|
||||
|
||||
return this.$store.dispatch('submit', callback).catch(e => { console.log(e); throw e; });
|
||||
},
|
||||
onInputDocumentTitle(event) {
|
||||
const id = Number(event.target.id);
|
||||
const title = event.target.value;
|
||||
this.$store.commit('updateDocumentTitle', {id: id, evaluationKey: this.evaluation.key, title: title});
|
||||
},
|
||||
addDocument(storedObject) {
|
||||
let document = {
|
||||
type: 'accompanying_period_work_evaluation_document',
|
||||
storedObject: storedObject
|
||||
};
|
||||
this.$store.commit('addDocument', {key: this.evaluation.key, document: document});
|
||||
},
|
||||
removeDocument(document) {
|
||||
this.$store.commit('removeDocument', {key: this.evaluation.key, document: document});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@@ -110,6 +110,7 @@ const store = createStore({
|
||||
maxDate: e.maxDate !== null ? { datetime: datetimeToISO(e.maxDate) } : null,
|
||||
warningInterval: intervalDaysToISO(e.warningInterval),
|
||||
comment: e.comment,
|
||||
documents: e.documents
|
||||
};
|
||||
if (e.id !== undefined) {
|
||||
o.id = e.id;
|
||||
@@ -197,6 +198,18 @@ const store = createStore({
|
||||
|
||||
found.results = found.results.filter(r => r.id !== result.id);
|
||||
},
|
||||
addDocument(state, payload) {
|
||||
state.evaluationsPicked.find(e => e.key === payload.key).documents.push(payload.document);
|
||||
},
|
||||
removeDocument(state, payload) {
|
||||
let evaluations = state.evaluationsPicked.find(e => e.key === payload.key);
|
||||
|
||||
if (evaluations === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
evaluations.documents = evaluations.documents.filter(d => d.id !== payload.document.id);
|
||||
},
|
||||
addEvaluation(state, evaluation) {
|
||||
let e = {
|
||||
type: "accompanying_period_work_evaluation",
|
||||
@@ -284,6 +297,10 @@ const store = createStore({
|
||||
setIsPosting(state, st) {
|
||||
state.isPosting = st;
|
||||
},
|
||||
updateDocumentTitle(state, payload) {
|
||||
state.evaluationsPicked.find(e => e.key === payload.evaluationKey)
|
||||
.documents.find(d => d.id === payload.id).title = payload.title;
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
updateThirdParty({ commit }, payload) {
|
||||
@@ -374,13 +391,18 @@ const store = createStore({
|
||||
});
|
||||
}
|
||||
},
|
||||
addDocument({commit}, payload) {
|
||||
commit('addDocument', payload);
|
||||
},
|
||||
removeDocument({commit}, payload) {
|
||||
commit('removeDocument', payload);
|
||||
},
|
||||
submit({ getters, state, commit }, callback) {
|
||||
let
|
||||
payload = getters.buildPayload,
|
||||
url = `/api/1.0/person/accompanying-course/work/${state.work.id}.json`,
|
||||
errors = []
|
||||
;
|
||||
|
||||
commit('setIsPosting', true);
|
||||
|
||||
return makeFetch('PUT', url, payload)
|
||||
@@ -397,6 +419,9 @@ const store = createStore({
|
||||
commit('setErrors', error.violations);
|
||||
});
|
||||
},
|
||||
updateDocumentTitle({commit}, payload) {
|
||||
commit('updateDocumentTitle', payload)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\PersonBundle\Serializer\Normalizer;
|
||||
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
|
||||
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||
use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\DenormalizerAwareTrait;
|
||||
use Symfony\Component\Serializer\Normalizer\ObjectToPopulateTrait;
|
||||
|
||||
use function array_key_exists;
|
||||
use function array_merge;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
|
||||
/**
|
||||
* This denormalizer rely on AbstractNormalizer for most of the job, and
|
||||
* add some logic for synchronizing collection.
|
||||
*/
|
||||
class AccompanyingPeriodWorkEvaluationDenormalizer implements ContextAwareDenormalizerInterface, DenormalizerAwareInterface
|
||||
{
|
||||
use DenormalizerAwareTrait;
|
||||
use ObjectToPopulateTrait;
|
||||
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private AccompanyingPeriodWorkRepository $workRepository;
|
||||
|
||||
public function __construct(
|
||||
AccompanyingPeriodWorkRepository $workRepository,
|
||||
EntityManagerInterface $em
|
||||
) {
|
||||
$this->workRepository = $workRepository;
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
public function denormalize($data, $type, $format = null, array $context = [])
|
||||
{
|
||||
$evaluation = $this->denormalizer->denormalize($data, $type, $format, array_merge(
|
||||
$context,
|
||||
['skip' => self::class]
|
||||
));
|
||||
|
||||
//if (in_array('accompanying_period_work:edit', $context['groups'] ?? [], true)) {
|
||||
$this->handleEvaluationCollection($data, $evaluation, $format, $context);
|
||||
//}
|
||||
|
||||
return $evaluation;
|
||||
}
|
||||
|
||||
public function supportsDenormalization($data, $type, $format = null, array $context = []): bool
|
||||
{
|
||||
return AccompanyingPeriodWorkEvaluation::class === $type
|
||||
&& self::class !== ($context['skip'] ?? null)
|
||||
&& is_array($data)
|
||||
&& array_key_exists('type', $data)
|
||||
&& 'accompanying_period_work_evaluation' === $data['type'];
|
||||
}
|
||||
|
||||
private function handleEvaluationCollection(array $data, AccompanyingPeriodWorkEvaluation $evaluation, string $format, array $context)
|
||||
{
|
||||
$dataById = [];
|
||||
$dataWithoutId = [];
|
||||
|
||||
foreach ($data['documents'] as $e) {
|
||||
if (array_key_exists('id', $e)) {
|
||||
$dataById[$e['id']] = $e;
|
||||
} else {
|
||||
$dataWithoutId[] = $e;
|
||||
}
|
||||
}
|
||||
dump($dataById);
|
||||
dump($dataWithoutId);
|
||||
|
||||
dump($evaluation);
|
||||
//partition the separate kept documents and removed one
|
||||
[$kept, $removed] = $evaluation->getDocuments()
|
||||
->partition(
|
||||
static fn (int $key, AccompanyingPeriodWorkEvaluationDocument $a) => array_key_exists($a->getId(), $dataById)
|
||||
);
|
||||
//$kept = $evaluation->getDocuments();
|
||||
dump($kept);
|
||||
dump($removed);
|
||||
// remove the document from evaluation
|
||||
foreach ($removed as $r) {
|
||||
dump($r);
|
||||
$evaluation->removeDocument($r);
|
||||
}
|
||||
// handle the documents kept
|
||||
foreach ($kept as $k) {
|
||||
dump($k); // Cannot iterate over $kept which is a PersistentCollection
|
||||
$evaluation->removeDocument($k);
|
||||
dump($evaluation);
|
||||
$document = $this->denormalizer->denormalize(
|
||||
$dataById[$k->getId()],
|
||||
AccompanyingPeriodWorkEvaluationDocument::class,
|
||||
$format,
|
||||
array_merge(
|
||||
$context,
|
||||
[
|
||||
'groups' => ['write'],
|
||||
AbstractNormalizer::OBJECT_TO_POPULATE => $k,
|
||||
]
|
||||
)
|
||||
);
|
||||
|
||||
$evaluation->addDocument($document);
|
||||
}
|
||||
// create new document
|
||||
foreach ($dataWithoutId as $newData) {
|
||||
dump($newData);
|
||||
$document = $this->denormalizer->denormalize(
|
||||
$newData,
|
||||
AccompanyingPeriodWorkEvaluationDocument::class,
|
||||
$format,
|
||||
array_merge(
|
||||
$context,
|
||||
['groups' => ['accompanying_period_work_evaluation:create']]
|
||||
)
|
||||
);
|
||||
$evaluation->addDocument($document);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\Migrations\Person;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
/**
|
||||
* Add title to AccompanyingPeriodWorkEvaluationDocument.
|
||||
*/
|
||||
final class Version20220224145951 extends AbstractMigration
|
||||
{
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document DROP title');
|
||||
}
|
||||
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Add title to AccompanyingPeriodWorkEvaluationDocument';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('ALTER TABLE chill_person_accompanying_period_work_evaluation_document ADD title TEXT DEFAULT NULL');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user