From cc3bc45a2c12c68dfbec3a98bd9f0eb6243e5e58 Mon Sep 17 00:00:00 2001 From: taro Date: Sat, 22 Mar 2025 12:01:11 -0300 Subject: [PATCH 01/25] . --- src/utils/onUserId.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/utils/onUserId.js diff --git a/src/utils/onUserId.js b/src/utils/onUserId.js new file mode 100644 index 00000000..28c1fcae --- /dev/null +++ b/src/utils/onUserId.js @@ -0,0 +1,19 @@ +import { watch } from 'vue'; + +import { useUserStore } from 'stores/user'; + +const userStore = useUserStore(); + +export const onUserId = (cb) => watch( + () => userStore?.user?.id, + async userId => { + if (userId) { + try { + await cb(userId); + } catch (error) { + console.error(error); + } + } + }, + { immediate: true } +); From 6cb8267a0b4ae396f69fdeba2d74bd0323d0591f Mon Sep 17 00:00:00 2001 From: wbuezas Date: Tue, 25 Mar 2025 10:53:52 +0100 Subject: [PATCH 02/25] News view refactor --- src/components/common/FormModel.vue | 14 +++++--- src/pages/Admin/NewsDetails.vue | 52 ++++++++++++++--------------- src/pages/Admin/NewsView.vue | 24 +++++-------- src/stores/user.js | 5 ++- 4 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/components/common/FormModel.vue b/src/components/common/FormModel.vue index fc5d1217..99ab9da1 100644 --- a/src/components/common/FormModel.vue +++ b/src/components/common/FormModel.vue @@ -69,6 +69,10 @@ const props = defineProps({ filter: { type: Object, default: null + }, + dataRequired: { + type: Object, + default: () => {} } }); @@ -122,9 +126,10 @@ onMounted(async () => { async function fetch() { try { - let { data } = await api.get(props.url, { - params: { filter: JSON.stringify(props.filter) } - }); + const params = props.filter + ? { filter: JSON.stringify(props.filter) } + : {}; + let { data } = await api.get(props.url, { params }); if (Array.isArray(data)) data = data[0] ?? {}; formData.value = { ...data }; emit('onDataFetched', formData.value); @@ -144,9 +149,10 @@ async function save() { isLoading.value = true; try { - const body = props.mapper + let body = props.mapper ? props.mapper(formData.value, originalData.value) : formData.value; + body = { ...body, ...props.dataRequired }; const method = props.urlCreate ? 'post' : 'patch'; const url = props.urlCreate || props.urlUpdate || props.url; diff --git a/src/pages/Admin/NewsDetails.vue b/src/pages/Admin/NewsDetails.vue index 92c3f797..15adb2a6 100644 --- a/src/pages/Admin/NewsDetails.vue +++ b/src/pages/Admin/NewsDetails.vue @@ -7,19 +7,21 @@ import VnImg from 'src/components/ui/VnImg.vue'; import VnForm from 'src/components/common/VnForm.vue'; import VnSelect from 'src/components/common/VnSelect.vue'; import VnInput from 'src/components/common/VnInput.vue'; +import FormModel from 'src/components/common/FormModel.vue'; import { useAppStore } from 'stores/app'; +import { useUserStore } from 'stores/user'; import { storeToRefs } from 'pinia'; -const jApi = inject('jApi'); +const api = inject('api'); const { t } = useI18n(); const route = useRoute(); const router = useRouter(); const appStore = useAppStore(); +const userStore = useUserStore(); const { isHeaderMounted } = storeToRefs(appStore); const newsTags = ref([]); -const pks = computed(() => ({ id: route.params.id })); const isEditMode = !!route.params.id; const formData = ref( !route.params.id @@ -32,22 +34,25 @@ const formData = ref( : undefined ); -const fetchNewDataSql = computed(() => { +const initialFetchUrl = computed(() => { if (!route.params.id) return undefined; - return { - query: ` - SELECT id, title, text, tag, priority, image - FROM news WHERE id = #id`, - params: { id: route.params.id } - }; + return `news/${route.params.id}`; +}); + +const urlUpdate = computed(() => { + if (!route.params.id) return undefined; + return `news/${route.params.id}`; +}); + +const urlCreate = computed(() => { + if (route.params.id) return undefined; + return 'news'; }); const getNewsTag = async () => { try { - newsTags.value = await jApi.query( - `SELECT name, description FROM newsTag - ORDER BY description` - ); + const { data } = await api.get('newsTags'); + newsTags.value = data; } catch (error) { console.error('Error getting newsTag:', error); } @@ -73,19 +78,14 @@ onMounted(async () => { {{ t('back') }} - - + diff --git a/src/pages/Admin/NewsView.vue b/src/pages/Admin/NewsView.vue index 27bef4db..f071adaf 100644 --- a/src/pages/Admin/NewsView.vue +++ b/src/pages/Admin/NewsView.vue @@ -5,13 +5,14 @@ import { useI18n } from 'vue-i18n'; import CardList from 'src/components/ui/CardList.vue'; import VnImg from 'src/components/ui/VnImg.vue'; import VnList from 'src/components/ui/VnList.vue'; +import FormModel from 'src/components/common/FormModel.vue'; import { useAppStore } from 'stores/app'; import { storeToRefs } from 'pinia'; import { useVnConfirm } from 'src/composables/useVnConfirm.js'; import useNotify from 'src/composables/useNotify.js'; -const jApi = inject('jApi'); +const api = inject('api'); const { t } = useI18n(); const appStore = useAppStore(); const { openConfirmationModal } = useVnConfirm(); @@ -24,28 +25,19 @@ const news = ref([]); const getNews = async () => { try { loading.value = true; - news.value = await jApi.query( - `SELECT n.id, u.nickname, n.priority, n.image, n.title - FROM news n - JOIN account.user u ON u.id = n.userFk - ORDER BY priority, n.created DESC` - ); - loading.value = false; + + const { data } = await api.get('news'); + news.value = data; } catch (error) { console.error('Error getting news:', error); + } finally { + loading.value = false; } }; const deleteNew = async (id, index) => { try { - await jApi.execQuery( - `START TRANSACTION; - DELETE FROM hedera.news WHERE ((id = #id)); - COMMIT`, - { - id - } - ); + await api.delete(`news/${id}`); news.value.splice(index, 1); notify(t('dataSaved'), 'positive'); } catch (error) { diff --git a/src/stores/user.js b/src/stores/user.js index 8f170752..8b75f124 100644 --- a/src/stores/user.js +++ b/src/stores/user.js @@ -296,6 +296,8 @@ export const useUserStore = defineStore('user', () => { tokenConfig.value = null; }; + const userId = computed(() => user.value?.id); + watch( [mainUser, supplantedUser], () => (user.value = supplantedUser.value || mainUser.value), @@ -336,6 +338,7 @@ export const useUserStore = defineStore('user', () => { updateUserLang, init, $reset, - onLogin + onLogin, + userId }; }); From a7264fe1fc9e306a3b3a8dbcd5a97ba84a394b3b Mon Sep 17 00:00:00 2001 From: wbuezas Date: Tue, 25 Mar 2025 11:42:53 +0100 Subject: [PATCH 03/25] Migrate image collections --- src/pages/Admin/PhotosView.vue | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/pages/Admin/PhotosView.vue b/src/pages/Admin/PhotosView.vue index b1e32f94..2802e1ce 100644 --- a/src/pages/Admin/PhotosView.vue +++ b/src/pages/Admin/PhotosView.vue @@ -7,7 +7,6 @@ import VnForm from 'src/components/common/VnForm.vue'; import VnInput from 'src/components/common/VnInput.vue'; import useNotify from 'src/composables/useNotify.js'; -const jApi = inject('jApi'); const api = inject('api'); const { t } = useI18n(); const { notify } = useNotify(); @@ -45,9 +44,8 @@ const isSubmitable = computed(() => const getImageCollections = async () => { try { - imageCollections.value = await jApi.query( - 'SELECT name, `desc` FROM imageCollection ORDER BY `desc`' - ); + const { data } = await api.get('imageCollections'); + imageCollections.value = data; } catch (error) { console.error('Error getting image collections:', error); } From f7030d1213e736a161f375250f7da5ec11ee3b36 Mon Sep 17 00:00:00 2001 From: wbuezas Date: Tue, 25 Mar 2025 15:11:42 +0100 Subject: [PATCH 04/25] WIP --- src/pages/Admin/PhotosView.vue | 46 +++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/pages/Admin/PhotosView.vue b/src/pages/Admin/PhotosView.vue index 2802e1ce..d80c61ee 100644 --- a/src/pages/Admin/PhotosView.vue +++ b/src/pages/Admin/PhotosView.vue @@ -32,7 +32,7 @@ const statusIcons = { } }; const formInitialData = reactive({ - schema: 'catalog', + collectionFk: 'catalog', updateMatching: true }); const imageCollections = ref([]); @@ -51,6 +51,10 @@ const getImageCollections = async () => { } }; +const buildUploadUrl = (id, collection) => { + return `images/upload?id=${encodeURIComponent(id)}&collection=${encodeURIComponent(collection)}`; +}; + const onSubmit = async data => { if (!addedFiles.value.length) { notify(t('noFilesToUpload'), 'warning'); @@ -59,20 +63,37 @@ const onSubmit = async data => { const filteredFiles = addedFiles.value.filter( file => file.uploadStatus === 'pending' ); - const promises = filteredFiles.map((file, index) => { + const promises = filteredFiles.map(async (file, index) => { const fileIndex = filteredFiles[index].index; addedFiles.value[fileIndex].uploadStatus = 'uploading'; + // const formData = new FormData(); + // formData.append('file', file.file); + + // const entityId = imageCollections.value.find( + // collection => collection.name === data.collectionFk + // ).model; + + // const url = buildUploadUrl(entityId, data.collectionFk); + // console.log('url', url); + // return api({ + // method: 'post', + // url: url, + // data: formData, + // headers: { + // 'Content-Type': 'multipart/form-data' + // } + // }); + const formData = new FormData(); - formData.append('updateMatching', data.updateMatching); - formData.append('image', file.file); - formData.append('name', file.name); - formData.append('schema', data.schema); - formData.append('srv', 'json:image/upload'); - return api({ - method: 'post', - url: location.origin, - data: formData, + const now = Date.vnNew(); + const timestamp = now.getTime(); + console.log('file', file); + const fileName = `${file.file?.name}_${timestamp}`; + formData.append('blob', file.file, fileName); + + await axios.post('Images/upload', formData, { + params: newPhoto, headers: { 'Content-Type': 'multipart/form-data' } @@ -102,6 +123,7 @@ const onSubmit = async data => { }; const onFilesAdded = files => { + console.log('files', files); const initialFilesLength = addedFiles.value.length; files.forEach((file, index) => { const [name] = file.name.split('.'); @@ -146,7 +168,7 @@ onMounted(async () => getImageCollections()); >