|
|
@@ -558,7 +558,7 @@ Est-ce qu'on peut espérer quelque chose de ce genre ?
|
|
|
|
|
|
##### 4- Formulaire de création / édition d'une entité
|
|
|
|
|
|
-Exemple de pages/organization/contact_points/_id.vue :
|
|
|
+Exemple de `pages/organization/contact_points/_id.vue` :
|
|
|
|
|
|
<script>
|
|
|
setup () {
|
|
|
@@ -667,9 +667,101 @@ Dans components/Ui/Form.vue :
|
|
|
</template>
|
|
|
|
|
|
|
|
|
-Alternative :
|
|
|
+Ce qui pourrait peut-être donner quelque chose comme :
|
|
|
+
|
|
|
+pages/organization/contact_points/_id.vue :
|
|
|
+
|
|
|
+ <script>
|
|
|
+ setup () {
|
|
|
+ const id = parseInt(route.value.params.id)
|
|
|
+
|
|
|
+ return {
|
|
|
+ id
|
|
|
+ }
|
|
|
+ </script>
|
|
|
+
|
|
|
+ <template>
|
|
|
+ <FormOrganizationContactPoint :id="id"></FormOrganizationContactPoint>
|
|
|
+ </template>
|
|
|
+
|
|
|
+components/Form/Organization/ContactPoint.vue :
|
|
|
+
|
|
|
+ <script>
|
|
|
+ setup () {
|
|
|
+ const { em } = useEntityManager()
|
|
|
+
|
|
|
+ const { fetchState, contactPoint } = props.id ? em.fetch(ContactPoint, props.id) : em.new(ContactPoint)
|
|
|
+
|
|
|
+ (...)
|
|
|
+
|
|
|
+ return {
|
|
|
+ contactPoint,
|
|
|
+ fetchState,
|
|
|
+ (...)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ </script>
|
|
|
+
|
|
|
+ <template>
|
|
|
+ <UiForm
|
|
|
+ v-if="!fetchState.pending"
|
|
|
+ :id="id"
|
|
|
+ :model="model"
|
|
|
+ :submitActions="submitActions">
|
|
|
+ >
|
|
|
+ <template #form.input="{contactPoint}">
|
|
|
+ (...)
|
|
|
+ </template>
|
|
|
+ </UiForm>
|
|
|
+ </template>
|
|
|
+
|
|
|
+
|
|
|
+Dans components/Ui/Form.vue :
|
|
|
+
|
|
|
+ <script>
|
|
|
+ setup () {
|
|
|
+ const { em } = useEntityManager()
|
|
|
+ const { id }: ToRefs = toRefs(props)
|
|
|
+
|
|
|
+ (...)
|
|
|
+
|
|
|
+ const submit = async (next: string|null = null) => {
|
|
|
+ if(await validate()){
|
|
|
+ markAsNotDirty()
|
|
|
+
|
|
|
+ em.persist(contactPoint)
|
|
|
+
|
|
|
+ (...)
|
|
|
+ }
|
|
|
+
|
|
|
+ const quitForm = () => {
|
|
|
+ // reset entity
|
|
|
+ em.reset(contactPoint)
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ submit,
|
|
|
+ contactPoint,
|
|
|
+ quitForm,
|
|
|
+ }
|
|
|
+ </script>
|
|
|
+
|
|
|
+ <template>
|
|
|
+ <v-form
|
|
|
+ ref="form"
|
|
|
+ lazy-validation
|
|
|
+ :readonly="readonly"
|
|
|
+ >
|
|
|
+ (...)
|
|
|
+ <UiButtonSubmit
|
|
|
+ v-if="!readonly"
|
|
|
+ @submit="submit"
|
|
|
+ :actions="actions"
|
|
|
+ ></UiButtonSubmit>
|
|
|
+ </v-form>
|
|
|
+ </template>
|
|
|
+
|
|
|
|
|
|
- (...)
|
|
|
|
|
|
##### 5- Population d'un input par un enum
|
|
|
|
|
|
@@ -703,10 +795,20 @@ Dans components/Ui/Input/Enum.vue :
|
|
|
}
|
|
|
|
|
|
|
|
|
-Alternative :
|
|
|
+Ce qui pourrait peut-être donner quelque chose comme :
|
|
|
|
|
|
+components/Ui/Input/Enum.vue :
|
|
|
+
|
|
|
+ const { enumType } = props
|
|
|
+ const { enumManager } = useEnumManager()
|
|
|
(...)
|
|
|
|
|
|
+ const items: Ref<Array<EnumChoices>> = enumManager.fetchByType(enumType)
|
|
|
+
|
|
|
+ return {
|
|
|
+ items,
|
|
|
+ (...)
|
|
|
+ }
|
|
|
|
|
|
##### 6- Population d'un input par des entités (ex: liste des pays)
|
|
|
|
|
|
@@ -770,9 +872,23 @@ Dans services/store/repository.ts :
|
|
|
}
|
|
|
|
|
|
|
|
|
-Alternative :
|
|
|
+Ce qui pourrait peut-être donner quelque chose comme :
|
|
|
|
|
|
- (...)
|
|
|
+page components/Form/Organization/Address.vue :
|
|
|
+
|
|
|
+ <script>
|
|
|
+
|
|
|
+ const { em } = useEntityManager()
|
|
|
+
|
|
|
+ const { countriesFetchingState, countries } = em.fetchAll(Country)
|
|
|
+
|
|
|
+ return {
|
|
|
+ (...)
|
|
|
+ countries,
|
|
|
+ countriesFetchingState,
|
|
|
+ (...)
|
|
|
+ }
|
|
|
+ </script>
|
|
|
|
|
|
|
|
|
##### 7- Population d'un input depuis une source externe (ex : adresses)
|
|
|
@@ -868,7 +984,20 @@ Dans composables/data/useAddressPostalUtils.ts :
|
|
|
|
|
|
Alternative :
|
|
|
|
|
|
- (...)
|
|
|
+composables/data/useAddressPostalUtils.ts
|
|
|
+
|
|
|
+ async function searchFunction(research: string, field: string): Promise<Array<AnyJson>> {
|
|
|
+ if (research) {
|
|
|
+ const response = await Connection.get({
|
|
|
+ url: `https://api-adresse.data.gouv.fr/search/?q=${research}&type=municipality&autocomplete=1&limit=20`,
|
|
|
+ params: {
|
|
|
+ noXaccessId: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const apiResponse = response.features.map((data: AnyJson) => data.properties)
|
|
|
+
|
|
|
+ (...)
|
|
|
+ }
|
|
|
|
|
|
|
|
|
##### 8- Affichage / upload d'une image
|
|
|
@@ -1014,8 +1143,103 @@ Dans composables/data/useImageProvider.ts :
|
|
|
|
|
|
Alternative :
|
|
|
|
|
|
+pages/organization/index.vue :
|
|
|
+
|
|
|
+ <UiImage
|
|
|
+ :id="getIdFromUri(organization['logo'])"
|
|
|
+ :upload="true"
|
|
|
+ :width="200"
|
|
|
+ field="logo"
|
|
|
+ :ownerId="id"
|
|
|
+ ></UiImage>
|
|
|
+
|
|
|
+components/Ui/Image.vue :
|
|
|
+
|
|
|
+ <script>
|
|
|
+ const { imageManager } = useImageManager()
|
|
|
+
|
|
|
+ const { imageLoaded, image } = imageManager.fetch(props.id, props.height, props.width)
|
|
|
+ </script>
|
|
|
+
|
|
|
+
|
|
|
+components/Ui/Input/Image.vue :
|
|
|
+
|
|
|
+ const { em } = useEntityManager()
|
|
|
+ const { imageManager } = useImageManager()
|
|
|
+
|
|
|
+ const cropper:Ref<any> = ref(null)
|
|
|
+ const image: Ref<AnyJson> = ref({
|
|
|
+ id: null,
|
|
|
+ src: null,
|
|
|
+ file: null,
|
|
|
+ name: null
|
|
|
+ })
|
|
|
+
|
|
|
(...)
|
|
|
|
|
|
+ if(props.existingImageId){
|
|
|
+ useFetch(async () => {
|
|
|
+ const result: ApiResponse = await $dataProvider.invoke({
|
|
|
+ type: QUERY_TYPE.DEFAULT,
|
|
|
+ url: 'api/files',
|
|
|
+ id: props.existingImageId
|
|
|
+ })
|
|
|
+
|
|
|
+ const { fetchState, imageLoaded } = imageManager.fetch(props.existingImageId)
|
|
|
+
|
|
|
+ const config = JSON.parse(imageLoaded.data.config)
|
|
|
+ (...)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // je suis pas sûr de comprendre la différence entre l'appel précédent (dans le if) et celui ci?
|
|
|
+ const { fetchState, imageLoaded } = getOne(props.existingImageId)
|
|
|
+
|
|
|
+ (...)
|
|
|
+
|
|
|
+ const save = async () => {
|
|
|
+ fileToSave.config = JSON.stringify({
|
|
|
+ x: coordinates.value.left,
|
|
|
+ y: coordinates.value.top,
|
|
|
+ height: coordinates.value.height,
|
|
|
+ width: coordinates.value.width
|
|
|
+ })
|
|
|
+
|
|
|
+ //Cas d'un PUT : l'image existe déjà on bouge simplement le cropper
|
|
|
+ if (image.value.id) {
|
|
|
+ em.persist(image.value)
|
|
|
+
|
|
|
+ //On émet un évent afin de mettre à jour le formulaire de départ
|
|
|
+ emit('reload')
|
|
|
+ }
|
|
|
+
|
|
|
+ //Post : on créer une nouvelle image donc on passe par l'api legacy...
|
|
|
+ else{
|
|
|
+ if (image.value.file) {
|
|
|
+ //On créer l'objet File à sauvegarder
|
|
|
+ const file = em.new(File)
|
|
|
+
|
|
|
+ file.name = image.value.name
|
|
|
+ file.imgFieldName = props.field
|
|
|
+ file.visibility = 'EVERYBODY'
|
|
|
+ file.folder = 'IMAGES'
|
|
|
+
|
|
|
+ if (props.ownerId)
|
|
|
+ file.ownerId = props.ownerId
|
|
|
+
|
|
|
+ //Appel au datapersister
|
|
|
+ em.persist(file)
|
|
|
+
|
|
|
+ //On émet un évent afin de mettre à jour le formulaire de départ
|
|
|
+ emit('update', response.data['@id'])
|
|
|
+
|
|
|
+ } else {
|
|
|
+ //On reset l'image : on a appuyer sur "poubelle" puis on enregistre
|
|
|
+ emit('reset')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
##### 9. Téléchargement / upload de fichier
|
|
|
|
|
|
@@ -1072,8 +1296,27 @@ Dans components/Layout/Header/Notification.vue :
|
|
|
|
|
|
Alternative :
|
|
|
|
|
|
+components/Layout/Header/Notification.vue :
|
|
|
+
|
|
|
+
|
|
|
+ const { em } = useEntityManager()
|
|
|
+ const notifications: Ref = em.fetchAll(Notification)
|
|
|
+
|
|
|
(...)
|
|
|
|
|
|
+ const markNotificationsAsRead = () => {
|
|
|
+ unreadNotification.value.map((notification: Notification) => {
|
|
|
+ notification.notificationUsers = ['read']
|
|
|
+
|
|
|
+ const notificationUser = em.new(NotificationUsers)
|
|
|
+ notificationUser.access = `/api/accesses/${currentAccessId}`
|
|
|
+ notificationUser.notification = `/api/notifications/${notification.id}`
|
|
|
+ notificationUser.isRead = true
|
|
|
+ em.persist(notificationUser)
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
##### 11- Validation de données
|
|
|
|
|
|
Sur la page pages/organization/index.vue :
|
|
|
@@ -1113,8 +1356,31 @@ Dans composables/form/useValidator.ts :
|
|
|
|
|
|
Alternative :
|
|
|
|
|
|
- (...)
|
|
|
+composables/form/useValidator.ts
|
|
|
|
|
|
+ function useHandleSiret() {
|
|
|
+ const siretError: Ref<boolean> = ref(false)
|
|
|
+ const siretErrorMessage: Ref<string> = ref('')
|
|
|
+
|
|
|
+ const checkSiret = async (siret: string) => {
|
|
|
+ const response = await Connection.get({
|
|
|
+ url: '/api/siret-checking/' + siret,
|
|
|
+ })
|
|
|
+
|
|
|
+ if (typeof response !== 'undefined') {
|
|
|
+ siretError.value = !response.isCorrect
|
|
|
+ siretErrorMessage.value = response.isCorrect ? '' : i18n.t('siret_error') as string
|
|
|
+ } else {
|
|
|
+ siretError.value = false
|
|
|
+ siretErrorMessage.value = ''
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return {
|
|
|
+ siretError,
|
|
|
+ siretErrorMessage,
|
|
|
+ checkSiret
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
##### 12- Affichage de données issues d'une api externe ou de routes custom
|
|
|
|