diff --git a/package-lock.json b/package-lock.json index c1b6a9e6..f8b8ecb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "@types/jest": "^30.0.0", "@types/node": "^25.0.3", "@vitejs/plugin-vue": "^6.0.3", + "@vitejs/plugin-vue-jsx": "^5.1.3", "@vueuse/core": "^14.1.0", "animate.css": "^4.1.1", "babel-runtime": "^6.26.0", @@ -151,6 +152,19 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", @@ -178,6 +192,38 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -188,6 +234,20 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", @@ -220,6 +280,19 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-plugin-utils": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", @@ -230,6 +303,38 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -543,6 +648,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", + "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/runtime": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", @@ -6156,6 +6281,87 @@ "vue": "^3.2.25" } }, + "node_modules/@vitejs/plugin-vue-jsx": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-5.1.3.tgz", + "integrity": "sha512-I6Zr8cYVr5WHMW5gNOP09DNqW9rgO8RX73Wa6Czgq/0ndpTfJM4vfDChfOT1+3KtdrNqilNBtNlFwVeB02ZzGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.5", + "@babel/plugin-syntax-typescript": "^7.27.1", + "@babel/plugin-transform-typescript": "^7.28.5", + "@rolldown/pluginutils": "^1.0.0-beta.56", + "@vue/babel-plugin-jsx": "^2.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0", + "vue": "^3.0.0" + } + }, + "node_modules/@vitejs/plugin-vue-jsx/node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.58", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.58.tgz", + "integrity": "sha512-qWhDs6yFGR5xDfdrwiSa3CWGIHxD597uGE/A9xGqytBjANvh4rLCTTkq7szhMV4+Ygh+PMS90KVJ8xWG/TkX4w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-2.0.1.tgz", + "integrity": "sha512-uZ66EaFbnnZSYqYEyplWvn46GhZ1KuYSThdT68p+am7MgBNbQ3hphTL9L+xSIsWkdktwhPYLwPgVWqo96jDdRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-2.0.1.tgz", + "integrity": "sha512-a8CaLQjD/s4PVdhrLD/zT574ZNPnZBOY+IhdtKWRB4HRZ0I2tXBi5ne7d9eCfaYwp5gU5+4KIyFTV1W1YL9xZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@vue/babel-helper-vue-transform-on": "2.0.1", + "@vue/babel-plugin-resolve-type": "2.0.1", + "@vue/shared": "^3.5.22" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-2.0.1.tgz", + "integrity": "sha512-ybwgIuRGRRBhOU37GImDoWQoz+TlSqap65qVI6iwg/J7FfLTLmMf97TS7xQH9I7Qtr/gp161kYVdhr1ZMraSYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.4", + "@vue/compiler-sfc": "^3.5.22" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@vue/compiler-core": { "version": "3.5.26", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.26.tgz", diff --git a/package.json b/package.json index a775cbf2..9ad99b79 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "@types/jest": "^30.0.0", "@types/node": "^25.0.3", "@vitejs/plugin-vue": "^6.0.3", + "@vitejs/plugin-vue-jsx": "^5.1.3", "@vueuse/core": "^14.1.0", "animate.css": "^4.1.1", "babel-runtime": "^6.26.0", diff --git a/src/views/Feed/columns.js b/src/views/Feed/columns.js deleted file mode 100644 index 7fc4a7a2..00000000 --- a/src/views/Feed/columns.js +++ /dev/null @@ -1,137 +0,0 @@ -import { ElTag, ElTooltip } from 'element-plus'; -import { h, resolveComponent } from 'vue'; - -import { formatDateFilter, statusClass } from '../../shared/utils'; -import { i18n } from '../../plugin'; -import { useUserStore } from '../../stores'; - -const { t } = i18n.global; - -export const columns = [ - { - accessorKey: 'created_at', - header: () => t('table.feed.date'), - cell: ({ row }) => { - const createdAt = row.getValue('created_at'); - return h( - ElTooltip, - { placement: 'right' }, - { - content: () => - h('span', formatDateFilter(createdAt, 'long')), - default: () => - h('span', formatDateFilter(createdAt, 'short')) - } - ); - } - }, - { - accessorKey: 'type', - header: () => t('table.feed.type'), - cell: ({ row }) => { - const type = row.getValue('type'); - return h( - ElTag, - { type: 'info', effect: 'plain', size: 'small' }, - () => t(`view.feed.filters.${type}`) - ); - } - }, - { - accessorKey: 'displayName', - header: () => t('table.feed.user'), - cell: ({ row }) => { - const { showUserDialog } = useUserStore(); - const original = row.original; - return h( - 'span', - { - class: 'x-link table-user', - style: 'padding-right: 10px', - onClick: () => showUserDialog(original.userId) - }, - original.displayName - ); - } - }, - { - id: 'detail', - header: () => t('table.feed.detail'), - cell: ({ row }) => { - const original = row.original; - const type = original.type; - const Location = resolveComponent('Location'); - const AvatarInfo = resolveComponent('AvatarInfo'); - - if (type === 'GPS') { - return original.location - ? h(Location, { - location: original.location, - hint: original.worldName, - grouphint: original.groupName - }) - : null; - } - - if (type === 'Offline' || type === 'Online') { - return original.location - ? h(Location, { - location: original.location, - hint: original.worldName, - grouphint: original.groupName - }) - : null; - } - - if (type === 'Status') { - if ( - original.statusDescription === - original.previousStatusDescription - ) { - return h('span', [ - h('i', { - class: [ - 'x-user-status', - statusClass(original.previousStatus) - ] - }), - h('span', { class: 'mx-2' }, ' → '), - h('i', { - class: [ - 'x-user-status', - statusClass(original.status) - ] - }) - ]); - } - - return h('span', [ - h('i', { - class: [ - 'x-user-status', - 'mr-2', - statusClass(original.status) - ] - }), - h('span', original.statusDescription) - ]); - } - - if (type === 'Avatar') { - return h(AvatarInfo, { - imageurl: original.currentAvatarImageUrl, - userid: original.userId, - hintownerid: original.ownerId, - hintavatarname: original.avatarName, - avatartags: original.currentAvatarTags - }); - } - - if (type === 'Bio') { - return h('span', original.bio); - } - - return null; - } - } -]; diff --git a/src/views/Feed/columns.jsx b/src/views/Feed/columns.jsx new file mode 100644 index 00000000..bd291ac8 --- /dev/null +++ b/src/views/Feed/columns.jsx @@ -0,0 +1,154 @@ +import { ElTag } from 'element-plus'; +import { resolveComponent } from 'vue'; + +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger +} from '../../components/ui/tooltip'; +import { formatDateFilter, statusClass } from '../../shared/utils'; +import { i18n } from '../../plugin'; +import { useUserStore } from '../../stores'; + +const { t } = i18n.global; + +export const columns = [ + { + accessorKey: 'created_at', + header: () => t('table.feed.date'), + cell: ({ row }) => { + const createdAt = row.getValue('created_at'); + const shortText = formatDateFilter(createdAt, 'short'); + const longText = formatDateFilter(createdAt, 'long'); + + return ( + + + + {shortText} + + + {longText} + + + + ); + } + }, + { + accessorKey: 'type', + header: () => t('table.feed.type'), + cell: ({ row }) => { + const type = row.getValue('type'); + return ( + + {t(`view.feed.filters.${type}`)} + + ); + } + }, + { + accessorKey: 'displayName', + header: () => t('table.feed.user'), + cell: ({ row }) => { + const { showUserDialog } = useUserStore(); + const original = row.original; + return ( + showUserDialog(original.userId)} + > + {original.displayName} + + ); + } + }, + { + id: 'detail', + header: () => t('table.feed.detail'), + cell: ({ row }) => { + const original = row.original; + const type = original.type; + const Location = resolveComponent('Location'); + const AvatarInfo = resolveComponent('AvatarInfo'); + + if (type === 'GPS') { + return original.location ? ( + + ) : null; + } + + if (type === 'Offline' || type === 'Online') { + return original.location ? ( + + ) : null; + } + + if (type === 'Status') { + if ( + original.statusDescription === + original.previousStatusDescription + ) { + return ( + + + Ўъ + + + ); + } + + return ( + + + {original.statusDescription} + + ); + } + + if (type === 'Avatar') { + return ( + + ); + } + + if (type === 'Bio') { + return {original.bio}; + } + + return null; + } + } +]; diff --git a/src/vite.config.js b/src/vite.config.js index 99609f9d..1237a936 100644 --- a/src/vite.config.js +++ b/src/vite.config.js @@ -6,6 +6,7 @@ import { defineConfig, loadEnv } from 'vite'; import tailwindcss from '@tailwindcss/vite'; import vue from '@vitejs/plugin-vue'; +import vueJsx from '@vitejs/plugin-vue-jsx'; import { languageCodes } from './localization/locales'; @@ -66,6 +67,9 @@ export default defineConfig(({ mode }) => { base: '', plugins: [ vue(), + vueJsx({ + tsTransform: 'built-in' + }), tailwindcss(), buildAndUploadSourceMaps && import('@sentry/vite-plugin').then(({ sentryVitePlugin }) =>