-
Notifications
You must be signed in to change notification settings - Fork 9
feat: add geopf sync #1178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
abulte
wants to merge
28
commits into
main
Choose a base branch
from
feat/geopf
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: add geopf sync #1178
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
e3548c3
fix: stop stuck top loading bar on admin dataset pages
abulte 0b99b6c
feat: add geopf sync
abulte 55299ee
409 -> 424
abulte a9b9672
conditionnal tab on eligible resources
abulte 77adc3b
Merge branch 'main' into feat/geopf
abulte bcc11a4
refactor around new status endpoint
abulte 30156d2
feature flag guard
abulte 4faed50
simpler polling
abulte 9e14f6a
scope 424 intercept
abulte abcf544
factorize isGeopfSynced
abulte 3fae728
catch
abulte 645cdd1
more unit tests
abulte 947e20f
geopfStatus → geopfDatasetStatus
abulte 6c4c531
nitpick
abulte 8b11cf4
renaming pull push buttons
abulte 229f3fd
add unit tests
abulte 1f9bc8a
better perm check on GeopfSyncPage
abulte a14ade8
simplify badges in components/Datasets/GeopfPushStatus.vue
abulte 199d257
disabled reason
abulte 222710e
nitpicks
abulte 48e38b5
Merge branch 'main' into feat/geopf
abulte 913fa65
add e2e tests
abulte ea40b92
debug e2e
abulte 832058a
e2e need udata geopf
abulte b2c2757
new backend version + nitpicks on urls
abulte 64396d1
Merge branch 'main' into feat/geopf
abulte b43c1be
migrate isGeopfSynced to new backend
abulte 51ea3ba
Merge branch 'main' into feat/geopf
abulte File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| <template> | ||
| <div v-if="pinnedDatastoreId"> | ||
| <p class="text-sm text-gray-medium m-0"> | ||
| {{ pinnedDatastoreName ? t('Entrepôt cartes.gouv.fr : {name} ({id})', { name: pinnedDatastoreName, id: pinnedDatastoreId }) : t('Entrepôt cartes.gouv.fr : {id}', { id: pinnedDatastoreId }) }} | ||
| </p> | ||
| </div> | ||
|
|
||
| <SelectGroup | ||
| v-else-if="connected === true" | ||
| v-model="localSelection" | ||
| :label="t('Entrepôt cartes.gouv.fr')" | ||
| :hint-text="t('Choisissez l\'entrepôt qui accueillera ce jeu de données sur cartes.gouv.fr. Ce choix ne pourra plus être modifié après le premier envoi.')" | ||
| :options="datastoreOptions" | ||
| class="max-w-sm" | ||
| /> | ||
|
|
||
| <p | ||
| v-else | ||
| class="text-sm text-gray-medium m-0" | ||
| > | ||
| {{ t("Connectez-vous à cartes.gouv.fr pour choisir l'entrepôt de ce jeu de données.") }} | ||
| </p> | ||
| </template> | ||
|
|
||
| <script setup lang="ts"> | ||
| import { SelectGroup } from '@datagouv/components-next' | ||
| import type { GeopfDatastore } from '~/utils/geopf' | ||
|
|
||
| const props = defineProps<{ | ||
| // Set on the dataset's first successful push, not editable afterwards. | ||
| pinnedDatastoreId: string | null | ||
| connected: boolean | null | ||
| }>() | ||
|
|
||
| const model = defineModel<string | null>({ default: null }) | ||
|
|
||
| const { t } = useTranslation() | ||
|
|
||
| const { data: datastores } = props.connected === true | ||
| ? await useAPI<Array<GeopfDatastore>>('/api/1/geopf/datastores/') | ||
| : { data: ref(null) } | ||
|
|
||
| const datastoreOptions = computed(() => (datastores.value ?? []).map(datastore => ({ label: datastore.name, value: datastore.datastore_id }))) | ||
| const pinnedDatastoreName = computed(() => (datastores.value ?? []).find(datastore => datastore.datastore_id === props.pinnedDatastoreId)?.name ?? null) | ||
|
|
||
| const localSelection = ref<string | null>(null) | ||
|
|
||
| watch(() => props.pinnedDatastoreId, (id) => { | ||
| if (id) model.value = id | ||
| }, { immediate: true }) | ||
|
|
||
| watch(localSelection, (id) => { | ||
| if (!props.pinnedDatastoreId) model.value = id | ||
| }) | ||
| </script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| <template> | ||
| <BannerAction | ||
| :type="bannerType" | ||
| :title="bannerTitle" | ||
| > | ||
| <template v-if="reauthRequired"> | ||
| {{ t('Votre connexion a expiré ou a été révoquée.') }} | ||
| </template> | ||
| <template v-else-if="connected === false"> | ||
| {{ t('Connectez-vous pour envoyer des fichiers et récupérer les services publiés sur cartes.gouv.fr.') }} | ||
| </template> | ||
| <template v-else-if="connected === true"> | ||
| {{ t('Vous pouvez envoyer des fichiers vers cartes.gouv.fr depuis la liste ci-dessous.') }} | ||
| </template> | ||
|
|
||
| <template #button> | ||
| <a | ||
| v-if="connected !== true || reauthRequired" | ||
| class="fr-btn fr-btn--sm" | ||
| :href="geopfLoginUrl" | ||
| > | ||
| {{ t('Se connecter') }} | ||
| </a> | ||
| <BrandedButton | ||
| v-else | ||
| color="tertiary" | ||
| size="xs" | ||
| :icon="RiLogoutBoxLine" | ||
| :loading="disconnecting" | ||
| @click="disconnect" | ||
| > | ||
| {{ t('Se déconnecter') }} | ||
| </BrandedButton> | ||
| </template> | ||
| </BannerAction> | ||
| </template> | ||
|
|
||
| <script setup lang="ts"> | ||
| import { BannerAction, BrandedButton, toast } from '@datagouv/components-next' | ||
| import { RiLogoutBoxLine } from '@remixicon/vue' | ||
|
|
||
| const props = defineProps<{ | ||
| // Id, not slug: /geopf/login/ only resolves by id. | ||
| datasetId: string | ||
| connected: boolean | null | ||
| reauthRequired?: boolean | ||
| }>() | ||
|
|
||
| const emit = defineEmits<{ | ||
| disconnected: [] | ||
| }>() | ||
|
|
||
| const { $api } = useNuxtApp() | ||
| const { t } = useTranslation() | ||
| const config = useRuntimeConfig() | ||
|
|
||
| const geopfLoginUrl = computed(() => `${config.public.apiBase}/api/1/geopf/login/?dataset_id=${encodeURIComponent(props.datasetId)}`) | ||
|
|
||
| const bannerType = computed(() => { | ||
| if (props.reauthRequired) return 'danger' | ||
| return props.connected === true ? 'primary' : 'warning' | ||
| }) | ||
| const bannerTitle = computed(() => { | ||
| if (props.reauthRequired) return t('Reconnexion à cartes.gouv.fr requise') | ||
| return props.connected === true ? t('Connecté à cartes.gouv.fr') : t('Non connecté à cartes.gouv.fr') | ||
| }) | ||
|
|
||
| const disconnecting = ref(false) | ||
|
|
||
| const disconnect = async () => { | ||
| disconnecting.value = true | ||
| try { | ||
| await $api('/api/1/geopf/token/', { method: 'DELETE' }) | ||
| toast.success(t('Vous êtes déconnecté de cartes.gouv.fr.')) | ||
| emit('disconnected') | ||
| } | ||
| catch { | ||
| // plugins/api.ts already toasted the error. | ||
| } | ||
| finally { | ||
| disconnecting.value = false | ||
| } | ||
| } | ||
| </script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| <template> | ||
| <div class="flex flex-col items-end gap-1"> | ||
| <component :is="disabledReason ? Tooltip : 'div'"> | ||
| <BrandedButton | ||
| color="secondary" | ||
| size="xs" | ||
| :icon="RiDownloadCloud2Line" | ||
| :disabled="!!disabledReason" | ||
| :loading="pulling || pull.status === 'pending'" | ||
| @click="startPull" | ||
| > | ||
| {{ t('Récupérer les services') }} | ||
| </BrandedButton> | ||
|
|
||
| <template #tooltip> | ||
| {{ disabledReason }} | ||
| </template> | ||
| </component> | ||
|
|
||
| <span | ||
| v-if="pull.status === 'done' && pull.last_synced_at" | ||
| class="text-xs text-gray-medium" | ||
| > | ||
| {{ t('Dernière synchronisation : {date}', { date: formatDate(pull.last_synced_at) }) }} | ||
| </span> | ||
| <span | ||
| v-else-if="pull.status === 'error'" | ||
| class="text-xs text-new-error" | ||
| > | ||
| {{ pull.error }} | ||
| </span> | ||
| </div> | ||
| </template> | ||
|
|
||
| <script setup lang="ts"> | ||
| import { BrandedButton, Tooltip, useFormatDate } from '@datagouv/components-next' | ||
| import { RiDownloadCloud2Line } from '@remixicon/vue' | ||
| import { isGeopfReauthRequired, type GeopfDatasetStatus } from '~/utils/geopf' | ||
|
|
||
| const props = defineProps<{ | ||
| datasetId: string | ||
| connected: boolean | null | ||
| pull: GeopfDatasetStatus['pull'] | ||
| ficheUrl: string | null | ||
| refresh: () => Promise<void> | ||
| }>() | ||
|
|
||
| const emit = defineEmits<{ | ||
| reauthRequired: [] | ||
| }>() | ||
|
|
||
| const { $api } = useNuxtApp() | ||
| const { t } = useTranslation() | ||
| const { formatDate } = useFormatDate() | ||
|
|
||
| const disabledReason = computed(() => { | ||
| if (props.connected !== true) return t('Connectez-vous à cartes.gouv.fr pour récupérer les services.') | ||
| if (!props.ficheUrl) return t('Envoyez d\'abord un fichier éligible vers cartes.gouv.fr.') | ||
| return null | ||
| }) | ||
|
|
||
| const pulling = ref(false) | ||
|
|
||
| const startPull = async () => { | ||
| pulling.value = true | ||
| try { | ||
| await $api(`/api/1/geopf/pull-offerings/${props.datasetId}/`, { method: 'POST' }) | ||
| // Awaited: udata marks the dataset `pending` before enqueueing, so this returns the new status. | ||
| await props.refresh() | ||
| } | ||
| catch (error) { | ||
| if (isGeopfReauthRequired(error)) { | ||
| emit('reauthRequired') | ||
| } | ||
| // Otherwise plugins/api.ts already toasted the error. | ||
| } | ||
| finally { | ||
| pulling.value = false | ||
| } | ||
| } | ||
| </script> |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FIXME