feat(CodePlayground): ✨ Visualization of component code in real time
This commit is contained in:
parent
36757bd163
commit
10e935d2e7
36
.vscode/settings.json
vendored
36
.vscode/settings.json
vendored
@ -11,25 +11,25 @@
|
|||||||
"source.fixAll.eslint": "explicit"
|
"source.fixAll.eslint": "explicit"
|
||||||
},
|
},
|
||||||
"workbench.colorCustomizations": {
|
"workbench.colorCustomizations": {
|
||||||
"activityBar.activeBackground": "#0894ba",
|
"activityBar.activeBackground": "#fac8fb",
|
||||||
"activityBar.background": "#0894ba",
|
"activityBar.background": "#fac8fb",
|
||||||
"activityBar.foreground": "#e7e7e7",
|
"activityBar.foreground": "#15202b",
|
||||||
"activityBar.inactiveForeground": "#e7e7e799",
|
"activityBar.inactiveForeground": "#15202b99",
|
||||||
"activityBarBadge.background": "#99077a",
|
"activityBarBadge.background": "#95920b",
|
||||||
"activityBarBadge.foreground": "#e7e7e7",
|
"activityBarBadge.foreground": "#15202b",
|
||||||
"commandCenter.border": "#e7e7e799",
|
"commandCenter.border": "#15202b99",
|
||||||
"sash.hoverBorder": "#0894ba",
|
"sash.hoverBorder": "#fac8fb",
|
||||||
"statusBar.background": "#066d89",
|
"statusBar.background": "#f598f8",
|
||||||
"statusBar.foreground": "#e7e7e7",
|
"statusBar.foreground": "#15202b",
|
||||||
"statusBarItem.hoverBackground": "#0894ba",
|
"statusBarItem.hoverBackground": "#f068f5",
|
||||||
"statusBarItem.remoteBackground": "#066d89",
|
"statusBarItem.remoteBackground": "#f598f8",
|
||||||
"statusBarItem.remoteForeground": "#e7e7e7",
|
"statusBarItem.remoteForeground": "#15202b",
|
||||||
"titleBar.activeBackground": "#066d89",
|
"titleBar.activeBackground": "#f598f8",
|
||||||
"titleBar.activeForeground": "#e7e7e7",
|
"titleBar.activeForeground": "#15202b",
|
||||||
"titleBar.inactiveBackground": "#066d8999",
|
"titleBar.inactiveBackground": "#f598f899",
|
||||||
"titleBar.inactiveForeground": "#e7e7e799"
|
"titleBar.inactiveForeground": "#15202b99"
|
||||||
},
|
},
|
||||||
"peacock.color": "#066d89",
|
"peacock.color": "#f598f8",
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"orbis",
|
"orbis",
|
||||||
"Orbis"
|
"Orbis"
|
||||||
|
39
Dockerfile
Normal file
39
Dockerfile
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
## Build image and name it 'custom-next'
|
||||||
|
# docker build -t custom-next .
|
||||||
|
|
||||||
|
## Run container and name it 'OrbisPlayground'. Webpage is localhost:3000
|
||||||
|
# docker run -it --rm -dp 3000:3000 --name OrbisPlayground custom-next
|
||||||
|
|
||||||
|
## Connect to container
|
||||||
|
# docker exec -it OrbisPlayground sh
|
||||||
|
|
||||||
|
## Stop docker container
|
||||||
|
# docker stop OrbisPlayground
|
||||||
|
|
||||||
|
## All together
|
||||||
|
# docker stop OrbisPlayground & docker image rm -f custom-next & docker build -t custom-next . && docker run -it --rm -dp 3000:3000 --name OrbisPlayground custom-next && docker exec -it OrbisPlayground sh
|
||||||
|
|
||||||
|
# Start Dockerfile
|
||||||
|
ARG VERSION=18.16.0-alpine3.17
|
||||||
|
ARG DIR=OrbisPlayground
|
||||||
|
|
||||||
|
FROM node:${VERSION} as builder
|
||||||
|
# redeclare ARG because ARG not in build environment
|
||||||
|
ARG DIR
|
||||||
|
WORKDIR /${DIR}
|
||||||
|
COPY . .
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add git
|
||||||
|
RUN yarn
|
||||||
|
RUN NODE_ENV=production yarn build
|
||||||
|
|
||||||
|
FROM node:${VERSION} as runner
|
||||||
|
# redeclare ARG because ARG not in build environment
|
||||||
|
ARG DIR
|
||||||
|
WORKDIR /${DIR}
|
||||||
|
COPY --from=builder /${DIR}/public ./public
|
||||||
|
COPY --from=builder /${DIR}/.next/standalone .
|
||||||
|
COPY --from=builder /${DIR}/.next/static ./.next/static
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
ENTRYPOINT ["node", "server.js"]
|
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"constants": {
|
"constants": {
|
||||||
"plataforma": "web",
|
"plataforma": "web",
|
||||||
"publicPath": "/orbistemplate",
|
"publicPath": "/orbisPlayground",
|
||||||
"urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
"urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
||||||
"urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
"urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
||||||
"urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
"urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/operation?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTso",
|
||||||
"appTitle": "OrbisTemplate",
|
"appTitle": "orbisPlayground",
|
||||||
"idApp": "orbistemplate",
|
"idApp": "orbisPlayground",
|
||||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||||
"maxMbUpload": 4,
|
"maxMbUpload": 4,
|
||||||
"defaultLocale": "es"
|
"defaultLocale": "es"
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"constants": {
|
"constants": {
|
||||||
"plataforma": "web",
|
"plataforma": "web",
|
||||||
"publicPath": "/orbistemplate",
|
"publicPath": "/orbisPlayground",
|
||||||
"urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
"urlServerImages" : "https://gt.via-asesores.com/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||||
"urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
"urlWebApi": "https://gt.via-asesores.com/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||||
"urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
"urlUploadApi": "https://gt.via-asesores.com/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||||
"appTitle": "OrbisTemplate",
|
"appTitle": "orbisPlayground",
|
||||||
"idApp": "orbistemplate",
|
"idApp": "orbisPlayground",
|
||||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||||
"maxMbUpload": 4,
|
"maxMbUpload": 4,
|
||||||
"defaultLocale": "es"
|
"defaultLocale": "es"
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"constants": {
|
"constants": {
|
||||||
"plataforma": "web",
|
"plataforma": "web",
|
||||||
"publicPath": "/orbistemplate",
|
"publicPath": "/orbisPlayground",
|
||||||
"urlServerImages" : "https://localhost:3000/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
"urlServerImages" : "https://localhost:3000/smartoperation/orbisapi/dtsrv/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||||
"urlWebApi": "https://localhost:3000/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
"urlWebApi": "https://localhost:3000/smartoperation/orbisapi/api/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||||
"urlUploadApi": "https://localhost:3000/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
"urlUploadApi": "https://localhost:3000/smartoperation/orbisapi/upload/dev/orbis?apikey=NTAzYzZlOTItMDcwZC00Zjg4LTljODMtNzBkNGQ5YjZhZTMw",
|
||||||
"appTitle": "OrbisTemplate",
|
"appTitle": "orbisPlayground",
|
||||||
"idApp": "orbistemplate",
|
"idApp": "orbisPlayground",
|
||||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||||
"maxMbUpload": 4,
|
"maxMbUpload": 4,
|
||||||
"defaultLocale": "es"
|
"defaultLocale": "es"
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"constants": {
|
"constants": {
|
||||||
"plataforma": "web",
|
"plataforma": "web",
|
||||||
"publicPath": "/orbistemplate",
|
"publicPath": "/orbisPlayground",
|
||||||
"urlServerImages" : "https://www.via-asesores.com/smartoperation/orbisapi/dtsrv/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
"urlServerImages" : "https://www.via-asesores.com/smartoperation/orbisapi/dtsrv/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
||||||
"urlWebApi": "https://www.via-asesores.com/smartoperation/orbisapi/api/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
"urlWebApi": "https://www.via-asesores.com/smartoperation/orbisapi/api/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
||||||
"urlUploadApi": "https://www.via-asesores.com/smartoperation/orbisapi/upload/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
"urlUploadApi": "https://www.via-asesores.com/smartoperation/orbisapi/upload/prod/orbis?apikey=MDJmNTEwOWUtNWY2ZC00OGJlLThjZGQtNWM4NmEyNmZmN2U5",
|
||||||
"appTitle": "OrbisTemplate",
|
"appTitle": "orbisPlayground",
|
||||||
"idApp": "orbistemplate",
|
"idApp": "orbisPlayground",
|
||||||
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
"publicKey":"-----BEGIN PUBLIC KEY----- MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA205Ag8sXnqc0XsPa4NiS tZSca+3afzgkMdpotsIOphZxketyBLs4QOKYsAHGw51R68fbx5oLmDCn7a4n4ZtT u39ksIQg1lwQ3y7pqfb9BbYZKhtYigL8URUVrsQ5EuZxk9BOHHez59gizNzM+Vp0 zlnOuJVZdVdp3d+d1z+oE3ejsdXLGFEjAblo8GNQxTgxOXJk2VQ+4yQX5QN+mEYS FQpJqP9z5Y+/SVXlD3e943XjuNOFZwSG2uVkW3tuKsvGBOA38xLKydY9hb5y0WdM E0/hnOvB6gfIOovSmdTonDF3224iGQJa8RXss3SN+6NeLnhJQYGBri6U4sa0lNR/ 5vip/VCzaHliYERTztT2NgW6WUZAEW05gjN6Qid2eB7lKs/ND3BQkDHUKqouNDO1 xookeBqSg7fT/l3D6D7QzJE5Jc+bdZUDrr2MeYXehzbGg8sUBXJZbOu6GUkDSM5Y C8r/SnZhhA0ancQZZW/t4TmFNiLiGrqNS4uJf4UHKKsmXHCKDKB/bdlp60lTl6YF ocGzW6tBPdDFD7S5UTPqg//ob6mvuPFJ0E6t8Le60P+UiZIdmINe9dX9darS0VNH +eCVLj1J7iQNyXrelD5sE7xhAvQ3+jp3Q4mXWVgOZi1Uh/+/iNXDxrAtzKipYAOg zuyH0DDtO3E4JSiv4qr8o+UCAwEAAQ== -----END PUBLIC KEY-----",
|
||||||
"maxMbUpload": 4,
|
"maxMbUpload": 4,
|
||||||
"defaultLocale": "es"
|
"defaultLocale": "es"
|
||||||
|
10
jsconfig.json
Normal file
10
jsconfig.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"],
|
||||||
|
"vComponents/*": ["./node_modules/vComponents/dist/components/*"],
|
||||||
|
"via-ui/*": ["./node_modules/via-ui/dist/components/*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
package.json
17
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "next-template",
|
"name": "orbis-playground",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "My Next.js project",
|
"description": "Orbis Playground",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.via-asesores.com/jmaritar/next-template"
|
"url": "https://git.via-asesores.com/jmaritar/next-template"
|
||||||
@ -25,7 +25,13 @@
|
|||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/standalone": "^7.23.7",
|
||||||
|
"@codemirror/lang-javascript": "^6.2.1",
|
||||||
|
"@codemirror/theme-one-dark": "^6.1.2",
|
||||||
|
"@codesandbox/sandpack-react": "^2.10.0",
|
||||||
"@headlessui/react": "^1.7.17",
|
"@headlessui/react": "^1.7.17",
|
||||||
|
"@uiw/codemirror-theme-monokai": "^4.21.21",
|
||||||
|
"@uiw/react-codemirror": "^4.21.21",
|
||||||
"config": "^3.3.9",
|
"config": "^3.3.9",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
"js-md5": "^0.8.3",
|
"js-md5": "^0.8.3",
|
||||||
@ -36,10 +42,15 @@
|
|||||||
"react-dom": "^18",
|
"react-dom": "^18",
|
||||||
"react-dropzone-component": "^3.2.0",
|
"react-dropzone-component": "^3.2.0",
|
||||||
"react-icons": "^4.12.0",
|
"react-icons": "^4.12.0",
|
||||||
|
"react-live": "^4.1.5",
|
||||||
|
"react-live-runner": "^1.0.5",
|
||||||
|
"react-runner": "^1.0.3",
|
||||||
"react-simple-hook-store": "^0.0.6",
|
"react-simple-hook-store": "^0.0.6",
|
||||||
"react-toastify": "^9.1.3",
|
"react-toastify": "^9.1.3",
|
||||||
"rosetta": "^1.1.0",
|
"rosetta": "^1.1.0",
|
||||||
"vComponents": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/v-components.git"
|
"v-functions": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/v-functions.git",
|
||||||
|
"vComponents": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/v-components.git#dev_ja",
|
||||||
|
"via-ui": "git+https://2bdcc0300e0ed5ac01f9dcd51368f7ac74fdb85a@git.via-asesores.com/libraries/via-ui.git#dev_ja"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
tailwindcss: {},
|
tailwindcss: {},
|
||||||
autoprefixer: {},
|
autoprefixer: {}
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
|
BIN
public/images/backgrounds.webp
Normal file
BIN
public/images/backgrounds.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
32
src/components/CodeEditor/index.jsx
Normal file
32
src/components/CodeEditor/index.jsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import CodeMirror from '@uiw/react-codemirror'
|
||||||
|
import { javascript } from '@codemirror/lang-javascript'
|
||||||
|
import { monokai } from '@uiw/codemirror-theme-monokai'
|
||||||
|
import { useStore } from '@/hooks/useStore'
|
||||||
|
// import { oneDark } from '@codemirror/theme-one-dark'
|
||||||
|
|
||||||
|
const CodeEditor = ({ code, onChange }) => {
|
||||||
|
const [currentCode, setCurrentCode] = useState(code)
|
||||||
|
|
||||||
|
const [theme] = useStore(s => s.theme, a => a.setTheme)
|
||||||
|
|
||||||
|
const onCodeChange = (value, viewUpdate) => {
|
||||||
|
onChange(value)
|
||||||
|
setCurrentCode(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<CodeMirror
|
||||||
|
value={currentCode}
|
||||||
|
extensions={[javascript({ jsx: true })]}
|
||||||
|
theme={theme === 'dark' ? monokai : undefined}
|
||||||
|
className='shadow-neon max-h-[50vh] overflow-auto rounded-lg border'
|
||||||
|
// readOnly={true}
|
||||||
|
onChange={onCodeChange}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CodeEditor
|
88
src/components/CodePlayground/index.jsx
Normal file
88
src/components/CodePlayground/index.jsx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { Icons } from '../Icons'
|
||||||
|
import { LiveProvider, LiveError, LivePreview } from 'react-live'
|
||||||
|
import CodeEditor from '../CodeEditor'
|
||||||
|
import useKeyPress from '@/hooks/useKeyPress'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import presets from '@/utils/globalPresets'
|
||||||
|
|
||||||
|
const CodePlayground = ({ code, onChange, scope }) => {
|
||||||
|
const [view, setView] = useState('preview')
|
||||||
|
const [currentCode, setCurrentCode] = useState(code)
|
||||||
|
|
||||||
|
const toggleView = () => {
|
||||||
|
setView(view === 'preview' ? 'code' : 'preview')
|
||||||
|
}
|
||||||
|
|
||||||
|
useKeyPress('Tab', toggleView, true)
|
||||||
|
|
||||||
|
const copyToClipboard = () => {
|
||||||
|
navigator.clipboard.writeText(code).then(() => {
|
||||||
|
toast.success('Código copiado al portapapeles', presets.toaster)
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('Algo salió mal al copiar el código: ', err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCodeChange = (editor, data, value) => {
|
||||||
|
setCurrentCode(editor)
|
||||||
|
onChange(editor)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setCurrentCode(code)
|
||||||
|
}, [code])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='flex-row'>
|
||||||
|
<div className='mb-3 flex justify-end'>
|
||||||
|
<div className="shadow-neon shadow-neon-sky flex space-x-1 rounded-lg bg-slate-200 dark:!bg-slate-900">
|
||||||
|
<button
|
||||||
|
onClick={() => setView('preview')}
|
||||||
|
className={`flex items-center rounded-md px-2 py-[0.4375rem] pr-3 text-sm font-semibold ${view === 'preview' ? 'bg-white shadow dark:!bg-[#333333]' : 'bg-slate-200 dark:!bg-transparent'}`}
|
||||||
|
>
|
||||||
|
<Icons.Eye className={`h-5 w-5 flex-none ${view === 'preview' ? 'stroke-sky-500 dark:stroke-sky-300' : 'stroke-slate-600 dark:stroke-slate-400'}`}/>
|
||||||
|
<span className={`ml-2 ${view === 'preview' ? 'text-sky-500 dark:text-sky-300' : 'text-slate-600 dark:text-slate-400'}`}>
|
||||||
|
Preview
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setView('code')}
|
||||||
|
className={`flex items-center rounded-md px-2 py-[0.4375rem] pr-3 text-sm font-semibold ${view === 'code' ? 'bg-white shadow dark:!bg-[#333333]' : 'bg-slate-200 dark:!bg-transparent'}`}
|
||||||
|
>
|
||||||
|
<Icons.Code className={`h-5 w-5 flex-none ${view === 'code' ? 'stroke-sky-500 dark:stroke-sky-300' : 'stroke-slate-600 dark:stroke-slate-400'}`}/>
|
||||||
|
<span className={`ml-2 ${view === 'code' ? 'text-sky-500 dark:text-sky-300' : 'text-slate-600 dark:text-slate-400'}`}>
|
||||||
|
Code
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='my-1 ml-6 mr-3 h-auto w-[2px] bg-slate-900/10 dark:bg-slate-900/20' />
|
||||||
|
|
||||||
|
<button
|
||||||
|
onClick={copyToClipboard}
|
||||||
|
className="shadow-neon shadow-neon-sky group relative flex h-9 w-9 items-center justify-center rounded-md bg-white text-slate-600 hover:text-slate-900 dark:!bg-[#333333] dark:!stroke-sky-300 dark:hover:!text-sky-100"
|
||||||
|
>
|
||||||
|
<Icons.Copy className="h-5 w-5 stroke-slate-400 transition group-hover:rotate-[-4deg] group-hover:stroke-slate-600 group-active:group-hover:stroke-sky-500 dark:group-hover:stroke-sky-300" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<LiveProvider code={currentCode} scope={scope} noInline={true}>
|
||||||
|
{ view === 'preview' &&
|
||||||
|
<div className={`${view === 'preview' ? '' : 'hidden'}`}>
|
||||||
|
<LivePreview className='shadow-neon rounded-lg border p-2' />
|
||||||
|
<LiveError className="mt-2 rounded bg-red-500 text-white" />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<div className={`${view === 'code' ? '' : 'hidden'}`}>
|
||||||
|
<CodeEditor code={currentCode} onChange={handleCodeChange} />
|
||||||
|
</div>
|
||||||
|
</LiveProvider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CodePlayground
|
25
src/components/Icons/index.jsx
Normal file
25
src/components/Icons/index.jsx
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { BsSearch } from 'react-icons/bs'
|
||||||
|
import { IoEllipsisVertical, IoFilter } from 'react-icons/io5'
|
||||||
|
import { DocumentPlusIcon, EyeIcon, PencilSquareIcon } from '@heroicons/react/24/solid'
|
||||||
|
import { FaChevronLeft, FaChevronRight, FaPaperclip, FaUser } from 'react-icons/fa'
|
||||||
|
import { RiEyeLine } from 'react-icons/ri'
|
||||||
|
import { LuEye, LuCode2, LuClipboardList } from 'react-icons/lu'
|
||||||
|
|
||||||
|
export const Icons = {
|
||||||
|
// Common Icons
|
||||||
|
Search: BsSearch,
|
||||||
|
New: DocumentPlusIcon,
|
||||||
|
Edit: PencilSquareIcon,
|
||||||
|
View: IoFilter,
|
||||||
|
Pre: FaChevronLeft,
|
||||||
|
Next: FaChevronRight,
|
||||||
|
User: FaUser,
|
||||||
|
Details: EyeIcon,
|
||||||
|
Attachments: FaPaperclip,
|
||||||
|
Options: IoEllipsisVertical,
|
||||||
|
|
||||||
|
Eye: LuEye,
|
||||||
|
Code: LuCode2,
|
||||||
|
Copy: LuClipboardList
|
||||||
|
|
||||||
|
}
|
41
src/components/LivePreview/index.jsx
Normal file
41
src/components/LivePreview/index.jsx
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
import { transform } from '@babel/standalone'
|
||||||
|
|
||||||
|
const LivePreview = ({ code }) => {
|
||||||
|
const iframeRef = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!iframeRef.current) return
|
||||||
|
|
||||||
|
// Aquí, asegúrate de que 'code' contenga solo el JSX, no una declaración de componente.
|
||||||
|
// Por ejemplo, debería verse así: "<div>Hello from JSX!</div>;"
|
||||||
|
const transformedCode = transform(`<>${code}</>`, {
|
||||||
|
presets: ['react']
|
||||||
|
}).code
|
||||||
|
|
||||||
|
const iframe = iframeRef.current
|
||||||
|
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document
|
||||||
|
iframeDoc.open()
|
||||||
|
iframeDoc.write(`
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head><title>Preview</title></head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script src="https://unpkg.com/react/umd/react.development.js"></script>
|
||||||
|
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
${transformedCode}
|
||||||
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||||
|
root.render(React.createElement(React.Fragment, null, ...React.Children.toArray(React.createElement(() => (${code}), {}))));
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`)
|
||||||
|
iframeDoc.close()
|
||||||
|
}, [code])
|
||||||
|
|
||||||
|
return <iframe ref={iframeRef} style={{ width: '100%', height: '300px', border: 'none' }} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LivePreview
|
@ -90,7 +90,7 @@ const FormLogin = ({ onLogin }) => {
|
|||||||
onChange={(e) => { validate(e) }}
|
onChange={(e) => { validate(e) }}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className={'via-append-input'}
|
className={'via-append-input shadow-neon'}
|
||||||
onClick={(e) => { e.stopPropagation() }}
|
onClick={(e) => { e.stopPropagation() }}
|
||||||
disabled
|
disabled
|
||||||
>
|
>
|
||||||
@ -115,7 +115,7 @@ const FormLogin = ({ onLogin }) => {
|
|||||||
onChange={(e) => { validate(e) }}
|
onChange={(e) => { validate(e) }}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className={'via-append-input'}
|
className={'via-append-input shadow-neon'}
|
||||||
onClick={(e) => { e.stopPropagation(); e.preventDefault(); setViewPassword(!viewPassword) }}
|
onClick={(e) => { e.stopPropagation(); e.preventDefault(); setViewPassword(!viewPassword) }}
|
||||||
>
|
>
|
||||||
{ viewPassword === false && <EyeIcon className="h-5 w-5" /> }
|
{ viewPassword === false && <EyeIcon className="h-5 w-5" /> }
|
||||||
@ -127,7 +127,11 @@ const FormLogin = ({ onLogin }) => {
|
|||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={!isInputValid}
|
disabled={!isInputValid}
|
||||||
className={`${'via-button'} ${(isInputValid ? 'bg-cyan-900' : 'bg-red-400')} mx-0 w-full justify-center`}
|
className={`via-button shadow-neon
|
||||||
|
${(isInputValid
|
||||||
|
? '!bg-theme-app-500'
|
||||||
|
: '!bg-danger')}
|
||||||
|
mx-0 w-full justify-center`}
|
||||||
>
|
>
|
||||||
<KeyIcon className="h-5 w-5 pr-2" />
|
<KeyIcon className="h-5 w-5 pr-2" />
|
||||||
{ i18n.t('login.connect') }
|
{ i18n.t('login.connect') }
|
||||||
|
118
src/components/ResizableDiv/index.jsx
Normal file
118
src/components/ResizableDiv/index.jsx
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
import React, { useState, useEffect, useRef } from 'react'
|
||||||
|
|
||||||
|
export default function ResizableDiv ({ children, id, element = {}, disable = false, direction = 'col', min = 20, grow = false, onChange = () => {}, onResize = () => {}, className = '', style = {} }) {
|
||||||
|
const [isMounted, setIsMounted] = useState(false)
|
||||||
|
const [modelo, setModelo] = useState({ ...element })
|
||||||
|
// const [eventUpdate, setEventUpdate] = useState(0)
|
||||||
|
const [initialPosX, setInitialPosX] = useState(null)
|
||||||
|
const [initialSizeX, setInitialSizeX] = useState(null)
|
||||||
|
const [initialPosY, setInitialPosY] = useState(null)
|
||||||
|
const [initialSizeY, setInitialSizeY] = useState(null)
|
||||||
|
|
||||||
|
const divRef = useRef(null)
|
||||||
|
|
||||||
|
const initialX = (e) => {
|
||||||
|
if (divRef != null && divRef.current != null) {
|
||||||
|
const resizable = divRef.current // document.getElementById('Resizable');
|
||||||
|
setInitialPosX(e.clientX)
|
||||||
|
setInitialSizeX(resizable.offsetWidth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeX = (e) => {
|
||||||
|
// if (divRef != null && divRef.current != null) {
|
||||||
|
// let resizable = divRef.current // document.getElementById('Resizable');
|
||||||
|
// resizable.style.width = `${parseInt(initialSizeX) + parseInt(e.clientX - initialPosX)}px`
|
||||||
|
// }
|
||||||
|
const newWidth = parseInt(initialSizeX) + parseInt(e.clientX - initialPosX)
|
||||||
|
onChange('width', newWidth, modelo)
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialY = (e) => {
|
||||||
|
if (divRef != null && divRef.current != null) {
|
||||||
|
const resizable = divRef.current // document.getElementById('Resizable');
|
||||||
|
setInitialPosY(e.clientY)
|
||||||
|
setInitialSizeY(resizable.offsetHeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeY = (e) => {
|
||||||
|
// if (divRef != null && divRef.current != null) {
|
||||||
|
// let resizable = divRef.current // document.getElementById('Resizable');
|
||||||
|
// resizable.style.height = `${parseInt(initialSizeY) + parseInt(e.clientY - initialPosY)}px`
|
||||||
|
// }
|
||||||
|
const newHeight = parseInt(initialSizeY) + parseInt(e.clientY - initialPosY)
|
||||||
|
onChange('height', newHeight, modelo)
|
||||||
|
}
|
||||||
|
|
||||||
|
const applyResize = () => {
|
||||||
|
// console.log(' applyResize ')
|
||||||
|
if (divRef != null && divRef.current != null) {
|
||||||
|
const resizable = divRef.current // document.getElementById('Resizable');
|
||||||
|
if (!grow || grow === false) {
|
||||||
|
if (direction === 'col') {
|
||||||
|
resizable.style.height = `${modelo.height}px`
|
||||||
|
resizable.style.width = '100%'
|
||||||
|
}
|
||||||
|
if (direction === 'row') {
|
||||||
|
resizable.style.height = '100%'
|
||||||
|
resizable.style.width = `${modelo.width}px`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (direction === 'col') {
|
||||||
|
resizable.style.height = '5rem'
|
||||||
|
resizable.style.width = '100%'
|
||||||
|
}
|
||||||
|
if (direction === 'row') {
|
||||||
|
resizable.style.height = '100%'
|
||||||
|
resizable.style.width = '5rem'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
onResize()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isMounted) {
|
||||||
|
applyResize()
|
||||||
|
}
|
||||||
|
}, [modelo, isMounted])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (isMounted) {
|
||||||
|
if (JSON.stringify({ ...element, _dz_background_image: null }) !== JSON.stringify({ ...modelo, _dz_background_image: null })) {
|
||||||
|
setModelo({ ...element })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [element])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setIsMounted(true)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={divRef}
|
||||||
|
id={id}
|
||||||
|
className={` relative flex items-center justify-center ${direction === 'col' ? 'w-full' : (grow ? ' w-4 ' : '')} ${direction === 'row' ? 'h-full' : (grow ? ' h-4 ' : '')} ${className}`}
|
||||||
|
style={grow ? { flexGrow: 1, ...style } : { ...style }}>
|
||||||
|
{children}
|
||||||
|
{ disable !== true && direction === 'col' &&
|
||||||
|
<div
|
||||||
|
className=' drag-resize-div-x bg-sky-300 '
|
||||||
|
draggable='true'
|
||||||
|
onDragStart={initialY}
|
||||||
|
onDragEnd={resizeY} />
|
||||||
|
}
|
||||||
|
{ disable !== true && direction === 'row' &&
|
||||||
|
<div
|
||||||
|
className=' drag-resize-div-y bg-sky-300 '
|
||||||
|
draggable='true'
|
||||||
|
onDragStart={initialX}
|
||||||
|
onDragEnd={resizeX} />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
468
src/components/vComponents/Sidebar/index.jsx
Normal file
468
src/components/vComponents/Sidebar/index.jsx
Normal file
@ -0,0 +1,468 @@
|
|||||||
|
import React, { useEffect, useRef, useState } from 'react'
|
||||||
|
import { ChevronDownIcon, ArrowLeftOnRectangleIcon, MagnifyingGlassIcon, XMarkIcon, Bars3Icon } from '@heroicons/react/20/solid'
|
||||||
|
import * as iconsFc from 'react-icons/fc'
|
||||||
|
import * as iconsMd from 'react-icons/md'
|
||||||
|
import * as HeroIcons from '@heroicons/react/24/solid'
|
||||||
|
import mq from 'js-mq'
|
||||||
|
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
Sidebar.propTypes = {
|
||||||
|
sidebarOpen: PropTypes.bool,
|
||||||
|
setSidebarOpen: PropTypes.func,
|
||||||
|
menu: PropTypes.array,
|
||||||
|
sidebarStyles: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
||||||
|
optionStyles: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
||||||
|
iconOptionStyles: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
||||||
|
suboptionStyles: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
||||||
|
iconSuboptionStyles: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
||||||
|
onClickLogout: PropTypes.func,
|
||||||
|
companyObj: PropTypes.object,
|
||||||
|
userObj: PropTypes.object,
|
||||||
|
setTitle: PropTypes.func,
|
||||||
|
i18n: PropTypes.object,
|
||||||
|
router: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||||
|
environment: PropTypes.object,
|
||||||
|
presets: PropTypes.object,
|
||||||
|
appTitleStyles: PropTypes.string,
|
||||||
|
userInfoStyles: PropTypes.string
|
||||||
|
}
|
||||||
|
|
||||||
|
// funcion que agrupa un vector de objetos por un campo y lo convierte en arbol
|
||||||
|
const nest = (items, idMenu = null, link = 'id_menu_padre') =>
|
||||||
|
items
|
||||||
|
.filter(item => item[link] === idMenu)
|
||||||
|
.map(item => ({
|
||||||
|
...item,
|
||||||
|
children:
|
||||||
|
nest(items, item.id_menu).length <= 0
|
||||||
|
? undefined
|
||||||
|
: nest(items, item.id_menu)
|
||||||
|
}))
|
||||||
|
|
||||||
|
const fontSizeClass = ' xs:text-md sm:text-md md:text-md lg:text-base xl:text-base '
|
||||||
|
|
||||||
|
// From https://reactjs.org/docs/hooks-state.html
|
||||||
|
export default function Sidebar ({ sidebarOpen, setSidebarOpen = () => {}, menu, sidebarStyles, optionStyles = fontSizeClass, iconOptionStyles, suboptionStyles = fontSizeClass, iconSuboptionStyles, onClickLogout, companyObj, userObj, setTitle, i18n = { t: () => { return 'txtNone' } }, router = [], environment = {}, presets, appTitleStyles = '', userInfoStyles = fontSizeClass, hideInputSearch = false }) {
|
||||||
|
const trigger = useRef(null)
|
||||||
|
const sidebar = useRef(null)
|
||||||
|
const [options, setOptions] = useState([])
|
||||||
|
const [isMobile, setIsMobile] = useState(false)
|
||||||
|
const [searchText, setSearchText] = useState('')
|
||||||
|
|
||||||
|
const getFontSize = (base) => {
|
||||||
|
if (base != null &&
|
||||||
|
(base.includes('text-xs') || base.includes('text-sm') || base.includes('text-base') || base.includes('text-md') || base.includes('text-lg') || base.includes('text-xl'))) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return fontSizeClass
|
||||||
|
}
|
||||||
|
|
||||||
|
// close on click outside
|
||||||
|
useEffect(() => {
|
||||||
|
const clickHandler = ({ target }) => {
|
||||||
|
if (!sidebar.current || !trigger.current) return
|
||||||
|
if (!sidebarOpen || sidebar.current.contains(target) || trigger.current.contains(target)) return
|
||||||
|
setSidebarOpen(false)
|
||||||
|
}
|
||||||
|
document.addEventListener('click', clickHandler)
|
||||||
|
return () => document.removeEventListener('click', clickHandler)
|
||||||
|
})
|
||||||
|
|
||||||
|
// close if the esc key is pressed
|
||||||
|
useEffect(() => {
|
||||||
|
const keyHandler = ({ keyCode }) => {
|
||||||
|
if (!sidebarOpen || keyCode !== 27) return
|
||||||
|
setSidebarOpen(false)
|
||||||
|
}
|
||||||
|
document.addEventListener('keydown', keyHandler)
|
||||||
|
return () => document.removeEventListener('keydown', keyHandler)
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const menus = nest(menu)
|
||||||
|
// console.log('menu', menus)
|
||||||
|
setOptions(menus)
|
||||||
|
}, [menu])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
registrarBreckpoint()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
const registrarBreckpoint = () => {
|
||||||
|
if (typeof document !== undefined) {
|
||||||
|
try {
|
||||||
|
mq.register([
|
||||||
|
/* eslint-enable */
|
||||||
|
{ name: 'mobile', query: '(max-width: 767px)' },
|
||||||
|
{ name: 'desktop', query: '(min-width: 768px)' }
|
||||||
|
])
|
||||||
|
mq.on('mobile', (e) => {
|
||||||
|
setIsMobile(true)
|
||||||
|
})
|
||||||
|
mq.on('desktop', (e) => {
|
||||||
|
setIsMobile(false)
|
||||||
|
})
|
||||||
|
const arrayEstadoMq = mq.getState()
|
||||||
|
if (arrayEstadoMq.length && (arrayEstadoMq[0] === 'not-mobile' || arrayEstadoMq[0] === 'desktop')) {
|
||||||
|
setIsMobile(false)
|
||||||
|
} else {
|
||||||
|
setIsMobile(true)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`Error al registrar mq breackpoints - ${e.message}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSidebarClass = () => {
|
||||||
|
let resultCss = ''
|
||||||
|
if (isMobile === true) {
|
||||||
|
resultCss = `flex flex-col z-60 top-1/3 h-4/6 overflow-y-auto w-full shrink-0 p-4 rounded-md duration-[400ms] ease-in-out
|
||||||
|
${sidebarOpen ? 'translate-y-0 fixed' : ' transform translate-y-[100vh] fixed'} `
|
||||||
|
} else {
|
||||||
|
resultCss = `flex flex-col z-40 left-0 top-0 h-screen overflow-y-auto w-64 shrink-0 p-4 transition-all duration-200 ease-in-out
|
||||||
|
${sidebarOpen ? 'translate-x-0 relative' : '-translate-x-64 absolute'} `
|
||||||
|
}
|
||||||
|
return resultCss
|
||||||
|
}
|
||||||
|
|
||||||
|
const setSelected = (option) => {
|
||||||
|
const menus = options.slice()
|
||||||
|
const idx = menus.indexOf(option)
|
||||||
|
option.isSelected = option.isSelected ? !option.isSelected : true
|
||||||
|
menus.splice(idx, 1, option)
|
||||||
|
setOptions(menus)
|
||||||
|
if (option.path && option.path !== null) {
|
||||||
|
setTitle(option.title)
|
||||||
|
setSidebarOpen(false)
|
||||||
|
router.push(`${option.path}/${environment.getTime()}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const setSelectedSubOption = (option, suboption) => {
|
||||||
|
const menus = options.slice()
|
||||||
|
const idxOption = menus.indexOf(option)
|
||||||
|
const idxSubOption = option.children.indexOf(suboption)
|
||||||
|
suboption.isSelected = suboption.isSelected ? !suboption.isSelected : true
|
||||||
|
option.children.splice(idxSubOption, 1, suboption)
|
||||||
|
setTitle(suboption.title)
|
||||||
|
menus.splice(idxOption, 1, option)
|
||||||
|
setOptions(menus)
|
||||||
|
setSidebarOpen(false)
|
||||||
|
router.push(`${suboption.path}/${environment.getTime()}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* eslint-disable */
|
||||||
|
const SubMenuOption = ({ option }) => {
|
||||||
|
|
||||||
|
if (option.children && option.children.length > 0 && option.isSelected === true) {
|
||||||
|
return (
|
||||||
|
<ul id='dropdown-example' className='ml-1 py-1 space-y-1'>
|
||||||
|
{option.children.map((suboption) => {
|
||||||
|
if (suboption.type === 'divisor') {
|
||||||
|
return (<li key={suboption.id_menu}><hr /></li>)
|
||||||
|
}
|
||||||
|
//Iconos subMenu
|
||||||
|
const getIcono = (item) => {
|
||||||
|
try {
|
||||||
|
const IconComponent = HeroIcons[item.icon]
|
||||||
|
if (IconComponent != null) {
|
||||||
|
return IconComponent
|
||||||
|
}
|
||||||
|
const IconComponentMd = iconsMd[item.icon]
|
||||||
|
if (IconComponentMd != null) {
|
||||||
|
return IconComponentMd
|
||||||
|
}
|
||||||
|
const IconComponentFC = iconsFc[item.icon]
|
||||||
|
if (IconComponentFC != null) {
|
||||||
|
return IconComponentFC
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
} catch (e) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let Icono = null
|
||||||
|
if (suboption.icon) {
|
||||||
|
Icono = getIcono(suboption)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<li key={suboption.id_menu} onClick={() => setSelectedSubOption(option, suboption)} title={suboption.title} className='cursor-pointer'>
|
||||||
|
<div
|
||||||
|
className={`flex items-center p-2 pl-3 w-full truncate overflow-hidden rounded-lg transition duration-75 group cursor-pointer ${Array.isArray(suboptionStyles) ? suboptionStyles.join(' ') : suboptionStyles} ${getFontSize(suboptionStyles)}`}
|
||||||
|
title={suboption.title}
|
||||||
|
>
|
||||||
|
|
||||||
|
{Icono && <Icono className={`h-7 w-7 text-white fill-current ${Array.isArray(iconSuboptionStyles) ? iconSuboptionStyles.join(' ') : iconSuboptionStyles}`} />}
|
||||||
|
|
||||||
|
<div className='inline-flex truncate text-ellipsis'>
|
||||||
|
{/* {suboption.title} */}
|
||||||
|
{suboption.i18n ? i18n.t(suboption.i18n) : suboption.title}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{suboption.badge && (
|
||||||
|
<span className='ml-1 inline-flex items-center justify-center rounded-full bg-red-600 px-2 py-1 text-xs font-bold leading-none text-red-100'>{suboption.badge}</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
/* eslint-enable */
|
||||||
|
|
||||||
|
const MenuOption = ({ option }) => {
|
||||||
|
// Iconos Menu
|
||||||
|
const getIcono = (item) => {
|
||||||
|
try {
|
||||||
|
const IconComponent = HeroIcons[item.icon]
|
||||||
|
if (IconComponent != null) {
|
||||||
|
return IconComponent
|
||||||
|
}
|
||||||
|
const IconComponentMd = iconsMd[item.icon]
|
||||||
|
if (IconComponentMd != null) {
|
||||||
|
return IconComponentMd
|
||||||
|
}
|
||||||
|
const IconComponentFC = iconsFc[item.icon]
|
||||||
|
if (IconComponentFC != null) {
|
||||||
|
return IconComponentFC
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
} catch (e) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let Icono = null
|
||||||
|
if (option.icon) {
|
||||||
|
Icono = getIcono(option)
|
||||||
|
}
|
||||||
|
if (option.type === 'titulo') {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className={`group flex w-full items-center rounded-lg p-2 transition duration-75 ${Array.isArray(optionStyles) ? optionStyles.join(' ') : optionStyles} ${getFontSize(optionStyles)}`}
|
||||||
|
aria-controls='dropdown-example' data-collapse-toggle='dropdown-example'
|
||||||
|
title={option.title}
|
||||||
|
>
|
||||||
|
<div className='ml-3 flex-1 truncate whitespace-nowrap text-left'>
|
||||||
|
{/* {option.title} */}
|
||||||
|
{option.i18n ? i18n.t(option.i18n) : option.title}
|
||||||
|
</div>
|
||||||
|
{option.badge && (
|
||||||
|
<span className='ml-1 inline-flex items-center justify-center rounded-full bg-red-600 px-2 py-1 text-xs font-bold leading-none text-red-100'>{option.badge}</span>
|
||||||
|
) }
|
||||||
|
{Icono && <Icono className={`h-7 w-7 fill-current text-white ${Array.isArray(iconOptionStyles) ? iconOptionStyles.join(' ') : iconOptionStyles}`} />}
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className={`group flex w-full items-center rounded-lg p-2 transition duration-75 ${Array.isArray(optionStyles) ? optionStyles.join(' ') : optionStyles} ${getFontSize(optionStyles)}`}
|
||||||
|
aria-controls='dropdown-example' data-collapse-toggle='dropdown-example'
|
||||||
|
title={option.title}
|
||||||
|
onClick={() => setSelected(option)}
|
||||||
|
>
|
||||||
|
|
||||||
|
{Icono && <Icono className={`h-7 w-7 fill-current text-white ${Array.isArray(iconOptionStyles) ? iconOptionStyles.join(' ') : iconOptionStyles}`} />}
|
||||||
|
|
||||||
|
<div className='ml-3 flex-1 truncate whitespace-nowrap text-left'>
|
||||||
|
{/* {option.title} */}
|
||||||
|
{option.i18n ? i18n.t(option.i18n) : option.title}
|
||||||
|
</div>
|
||||||
|
{option.badge && (
|
||||||
|
<span className='ml-1 inline-flex items-center justify-center rounded-full bg-red-600 px-2 py-1 text-xs font-bold leading-none text-red-100'>{option.badge}</span>
|
||||||
|
) }
|
||||||
|
{option.children && option.children.length > 0 && <ChevronDownIcon className='h-6 w-6' />}
|
||||||
|
</button>
|
||||||
|
<SubMenuOption option={option} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
MenuOption.propTypes = {
|
||||||
|
option: PropTypes.object
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFilteredOptions = (options, searchText, originalMenu) => {
|
||||||
|
const searchLower = searchText.toLowerCase()
|
||||||
|
|
||||||
|
const cloneWithIsSelected = (items, selectedItems) => {
|
||||||
|
return items.map(item => {
|
||||||
|
const selectedItem = selectedItems.find(si => si.id_menu === item.id_menu)
|
||||||
|
const isSelected = selectedItem ? selectedItem.isSelected : false
|
||||||
|
const children = item.children ? cloneWithIsSelected(item.children, selectedItems) : []
|
||||||
|
return { ...item, isSelected, children }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchAndMergeItems = (items, isChildMatch = false) => {
|
||||||
|
return items.reduce((acc, item) => {
|
||||||
|
const matchSelf = item.title.toLowerCase().includes(searchLower)
|
||||||
|
const children = item.children ? searchAndMergeItems(item.children, matchSelf || isChildMatch) : []
|
||||||
|
const newItem = { ...item, children }
|
||||||
|
|
||||||
|
if (matchSelf || children.length > 0 || isChildMatch) {
|
||||||
|
const existingIndex = acc.findIndex(e => e.id_menu === item.id_menu)
|
||||||
|
if (existingIndex > -1) {
|
||||||
|
acc[existingIndex] = { ...acc[existingIndex], isSelected: newItem.isSelected || acc[existingIndex].isSelected }
|
||||||
|
} else {
|
||||||
|
acc.push(newItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc
|
||||||
|
}, [])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (searchText) {
|
||||||
|
return searchAndMergeItems(options)
|
||||||
|
} else {
|
||||||
|
const selectedItems = options.filter(item => item.isSelected)
|
||||||
|
return cloneWithIsSelected(originalMenu, selectedItems)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const originalMenu = nest(menu)
|
||||||
|
|
||||||
|
const filteredOptions = getFilteredOptions(options, searchText, originalMenu)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Sidebar backdrop (mobile only) bg-slate-900 */}
|
||||||
|
<div
|
||||||
|
className={`fixed inset-0 bg-opacity-30 z-40 md:hidden md:z-auto transition-opacity duration-200
|
||||||
|
${sidebarOpen ? 'opacity-100' : 'pointer-events-none opacity-0'} ${Array.isArray(sidebarStyles) ? sidebarStyles.join(' ') : sidebarStyles}`}
|
||||||
|
aria-hidden='true'
|
||||||
|
onClick={() => { setSidebarOpen(!sidebarOpen) }}
|
||||||
|
/>
|
||||||
|
{/* Sidebar */}
|
||||||
|
{/* lg:translate-x-0 lg:w-20 lg:static lg:left-auto lg:top-auto lg:overflow-y-auto lg:sidebar-expanded:!w-64 2xl:!w-64 */}
|
||||||
|
<div
|
||||||
|
id='sidebar'
|
||||||
|
ref={sidebar}
|
||||||
|
className={` ${getSidebarClass()} ${Array.isArray(sidebarStyles) ? sidebarStyles.join(' ') : sidebarStyles}`}
|
||||||
|
>
|
||||||
|
{/* Expand / collapse button */}
|
||||||
|
<div className='fixed right-6 top-4 justify-end pt-0 md:hidden '>
|
||||||
|
<div className='px-3 py-2'>
|
||||||
|
<button onClick={() => setSidebarOpen(!sidebarOpen)}>
|
||||||
|
<div className='sr-only'>Expand / collapse sidebar</div>
|
||||||
|
<XMarkIcon className={`text-${presets.theme}-600 h-6 w-6 rounded-md bg-white/50`} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Sidebar header */}
|
||||||
|
<div className='mb-10 flex justify-between pr-3 sm:px-2'>
|
||||||
|
{/* Close button */}
|
||||||
|
{/* <button
|
||||||
|
ref={trigger}
|
||||||
|
className={`absolute cursor-pointer -right-3 top-9 w-7 border-dark-purple z-50
|
||||||
|
border-2 rounded-full ${!sidebarOpen && 'rotate-180'}`}
|
||||||
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
||||||
|
aria-controls='sidebar'
|
||||||
|
aria-expanded={sidebarOpen}
|
||||||
|
>
|
||||||
|
<div className='sr-only'>Close sidebar</div>
|
||||||
|
{sidebarOpen
|
||||||
|
? <ArrowLeftIcon className='w-6 h-6 fill-current text-white' />
|
||||||
|
: <ArrowRightIcon className='w-6 h-6 fill-current text-white' />
|
||||||
|
}
|
||||||
|
</button> */}
|
||||||
|
{/* Logo */}
|
||||||
|
<div className='flex items-center gap-x-2' title='Versión 3.0.10'>
|
||||||
|
<img
|
||||||
|
src={presets.images.icon}
|
||||||
|
className={`h-12 w-12 cursor-pointer duration-500 ${
|
||||||
|
sidebarOpen && 'rotate-[360deg]'
|
||||||
|
}`}
|
||||||
|
alt={presets.appTitle}
|
||||||
|
width={100}
|
||||||
|
height={100}
|
||||||
|
/>
|
||||||
|
<h1 className={`origin-left text-xl font-medium text-white duration-200 ${!sidebarOpen && 'scale-0'} ${appTitleStyles} `}>
|
||||||
|
{presets.appTitle}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* user Info */}
|
||||||
|
<div className={` flex w-full flex-col space-y-0 border-b-2 border-gray-300 text-gray-50 ${userInfoStyles} ${getFontSize(userInfoStyles)}`}>
|
||||||
|
<div className='px-2 font-medium '> {userObj ? userObj.compania : ''} </div>
|
||||||
|
<div className='px-2'>{userObj ? userObj.nombre_usuario : ''}</div>
|
||||||
|
<div className='break-all px-2 '>{userObj ? userObj.email : ''}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Links */}
|
||||||
|
<div className={`my-0 overflow-y-auto rounded px-2 py-4 ${Array.isArray(sidebarStyles) ? sidebarStyles.join(' ') : sidebarStyles}`}>
|
||||||
|
|
||||||
|
{/* Search */}
|
||||||
|
{ hideInputSearch !== true &&
|
||||||
|
<div className='relative -mt-2 mb-1 flex h-9 justify-between'>
|
||||||
|
<input
|
||||||
|
id='searchText'
|
||||||
|
name='searchText'
|
||||||
|
value={searchText}
|
||||||
|
type='search'
|
||||||
|
className='via-input-search-sidebar focus:!outline-none focus:!ring-0'
|
||||||
|
onInput={(e) => { setSearchText(e.target.value) }}
|
||||||
|
onChange={(e) => { setSearchText(e.target.value) }}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
className='via-button-search-sidebar'
|
||||||
|
onClick={(e) => { e.stopPropagation() }}
|
||||||
|
disabled
|
||||||
|
>
|
||||||
|
<MagnifyingGlassIcon className='h-5 w-5' />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
<ul className='space-y-2'>
|
||||||
|
{filteredOptions.map((option) => {
|
||||||
|
/* eslint-disable */
|
||||||
|
return (
|
||||||
|
<li key={option.id_menu + '_li'}>
|
||||||
|
{option.type === 'divisor' && <hr key={option.id_menu} />}
|
||||||
|
{option.type !== 'divisor' && <MenuOption option={option} key={option.id_menu} />}
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
/* eslint-enable */
|
||||||
|
})}
|
||||||
|
<hr />
|
||||||
|
<li>
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className={`group flex w-full items-center rounded-lg p-2 transition duration-75 ${Array.isArray(optionStyles) ? optionStyles.join(' ') : optionStyles} ${getFontSize(optionStyles)}`}
|
||||||
|
aria-controls='dropdown-example' data-collapse-toggle='dropdown-example'
|
||||||
|
onClick={() => onClickLogout()}
|
||||||
|
>
|
||||||
|
<ArrowLeftOnRectangleIcon className='h-6 w-6 pr-2' />
|
||||||
|
<div className='ml-3 flex-1 whitespace-nowrap text-left'>{i18n.t('common.logout')}</div>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{ isMobile === true &&
|
||||||
|
<div className="fixed bottom-3 right-3 z-60" v-if="isMobile" >
|
||||||
|
<button
|
||||||
|
id="vtDrawerButton"
|
||||||
|
className={`bg-${presets.theme}-600 hover:bg-${presets.theme}-700 focus:shadow-outline-purple flex items-center justify-between rounded-lg border border-transparent p-2 font-normal leading-5 text-white transition-colors duration-150 focus:outline-none active:bg-purple-600`}
|
||||||
|
aria-label="Like"
|
||||||
|
onClick={() => { setSidebarOpen(!sidebarOpen) }}
|
||||||
|
>
|
||||||
|
<Bars3Icon className='h-6 w-6' />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
@ -6,17 +6,17 @@ import { TbColorPicker, TbLanguage } from 'react-icons/tb'
|
|||||||
const UserOptionsMenu = ({ setPreferences, theme, i18n }) => {
|
const UserOptionsMenu = ({ setPreferences, theme, i18n }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex items-center justify-center text-gray-900">
|
<div className="flex items-center justify-center text-gray-900 dark:text-white">
|
||||||
<TbColorPicker className="mr-2 h-5 w-5" aria-hidden="true" />
|
<TbColorPicker className="mr-2 h-5 w-5" aria-hidden="true" />
|
||||||
Tema
|
Tema
|
||||||
</div>
|
</div>
|
||||||
<div className="mb-4 grid grid-cols-2 gap-2 p-1">
|
<div className="mb-2 grid grid-cols-2 gap-2 p-1">
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
<button
|
<button
|
||||||
className={`${
|
className={`${
|
||||||
theme === 'light'
|
theme === 'light'
|
||||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
? 'bg-theme-app-500 text-white dark:bg-theme-app-500'
|
||||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
: 'bg-theme-app-50 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-theme-app-100'
|
||||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setPreferences('light')
|
setPreferences('light')
|
||||||
@ -30,8 +30,8 @@ const UserOptionsMenu = ({ setPreferences, theme, i18n }) => {
|
|||||||
<button
|
<button
|
||||||
className={`${
|
className={`${
|
||||||
theme === 'dark'
|
theme === 'dark'
|
||||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
? 'bg-theme-app-500 text-white dark:bg-theme-app-500'
|
||||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
: 'bg-theme-app-50 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-theme-app-100'
|
||||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPreferences('dark')
|
setPreferences('dark')
|
||||||
@ -43,18 +43,18 @@ const UserOptionsMenu = ({ setPreferences, theme, i18n }) => {
|
|||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex items-center justify-center text-gray-900">
|
<div className="flex items-center justify-center text-gray-900 dark:text-white">
|
||||||
<TbLanguage className="mr-2 h-5 w-5" aria-hidden="true" />
|
<TbLanguage className="mr-2 h-5 w-5" aria-hidden="true" />
|
||||||
Idioma
|
Idioma
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-2 gap-2 p-1">
|
<div className="mb-2 grid grid-cols-2 gap-2 p-1">
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
<button
|
<button
|
||||||
className={`${
|
className={`${
|
||||||
i18n.activeLocale === 'es'
|
i18n.activeLocale === 'es'
|
||||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
? 'bg-theme-app-500 text-white dark:bg-theme-app-500'
|
||||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
: 'bg-theme-app-50 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-theme-app-100'
|
||||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
setPreferences('es')
|
setPreferences('es')
|
||||||
@ -82,8 +82,8 @@ const UserOptionsMenu = ({ setPreferences, theme, i18n }) => {
|
|||||||
<button
|
<button
|
||||||
className={`${
|
className={`${
|
||||||
i18n.activeLocale === 'en'
|
i18n.activeLocale === 'en'
|
||||||
? 'bg-slate-700 text-white dark:bg-slate-800'
|
? 'bg-theme-app-500 text-white dark:bg-theme-app-500'
|
||||||
: 'bg-gray-200 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-gray-300'
|
: 'bg-theme-app-50 text-gray-900 transition-colors duration-[350ms] ease-in-out hover:bg-theme-app-100'
|
||||||
} group flex w-full items-center rounded-md p-2 text-sm`}
|
} group flex w-full items-center rounded-md p-2 text-sm`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setPreferences('en')
|
setPreferences('en')
|
||||||
|
72
src/data/menu.json
Normal file
72
src/data/menu.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id_menu": "v-components",
|
||||||
|
"title": "v-components",
|
||||||
|
"descripcion": null,
|
||||||
|
"icon": "FcDeployment",
|
||||||
|
"path": null,
|
||||||
|
"orden": 1,
|
||||||
|
"id_menu_padre": null,
|
||||||
|
"badge": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id_menu": "data-table",
|
||||||
|
"title": "DataTable",
|
||||||
|
"descripcion": null,
|
||||||
|
"icon": "FcDataSheet",
|
||||||
|
"path": "/seguridad/compania",
|
||||||
|
"orden": 1.1,
|
||||||
|
"id_menu_padre": "v-components",
|
||||||
|
"badge": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id_menu": "data-form",
|
||||||
|
"title": "DataFrom",
|
||||||
|
"descripcion": null,
|
||||||
|
"icon": "FcKindle",
|
||||||
|
"path": "/seguridad/departamento",
|
||||||
|
"orden": 1.2,
|
||||||
|
"id_menu_padre": "v-components",
|
||||||
|
"badge": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id_menu": "via-ui",
|
||||||
|
"title": "via-ui",
|
||||||
|
"descripcion": null,
|
||||||
|
"icon": "FcCloseUpMode",
|
||||||
|
"path": "",
|
||||||
|
"orden": 2,
|
||||||
|
"id_menu_padre": null,
|
||||||
|
"badge": "New"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id_menu": "tooltip",
|
||||||
|
"title": "Tooltip",
|
||||||
|
"descripcion": null,
|
||||||
|
"icon": "FcMms",
|
||||||
|
"path": "/via-ui/tooltip",
|
||||||
|
"orden": 2.1,
|
||||||
|
"id_menu_padre": "via-ui",
|
||||||
|
"badge": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id_menu": "tab",
|
||||||
|
"title": "Tab",
|
||||||
|
"descripcion": null,
|
||||||
|
"icon": "FcTemplate",
|
||||||
|
"path": "/via-ui/tab",
|
||||||
|
"orden": 2.1,
|
||||||
|
"id_menu_padre": "via-ui",
|
||||||
|
"badge": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id_menu": "test",
|
||||||
|
"title": "Test",
|
||||||
|
"descripcion": null,
|
||||||
|
"icon": "FcIdea",
|
||||||
|
"path": "/via-ui/test",
|
||||||
|
"orden": 2.1,
|
||||||
|
"id_menu_padre": "via-ui",
|
||||||
|
"badge": null
|
||||||
|
}
|
||||||
|
]
|
29
src/hooks/useKeyPress.js
Normal file
29
src/hooks/useKeyPress.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { useEffect } from 'react'
|
||||||
|
|
||||||
|
const useKeyPress = (targetKeys, onKeyPress, preventDefault = false) => {
|
||||||
|
useEffect(() => {
|
||||||
|
const handleKeyPress = (event) => {
|
||||||
|
const keys = Array.isArray(targetKeys) ? targetKeys : [targetKeys]
|
||||||
|
|
||||||
|
if (keys.every(key => {
|
||||||
|
if (key === 'Meta' || key === 'Control' || key === 'Alt' || key === 'Shift') {
|
||||||
|
return event.getModifierState(key)
|
||||||
|
} else {
|
||||||
|
return event.key === key
|
||||||
|
}
|
||||||
|
})) {
|
||||||
|
if (preventDefault) {
|
||||||
|
event.preventDefault()
|
||||||
|
}
|
||||||
|
onKeyPress()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('keydown', handleKeyPress)
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener('keydown', handleKeyPress)
|
||||||
|
}
|
||||||
|
}, [targetKeys, onKeyPress, preventDefault])
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useKeyPress
|
@ -2,12 +2,14 @@ import { createStore } from 'react-simple-hook-store'
|
|||||||
|
|
||||||
interface IState {
|
interface IState {
|
||||||
title: string;
|
title: string;
|
||||||
|
theme: string;
|
||||||
usuarioPermisos: object | null;
|
usuarioPermisos: object | null;
|
||||||
valueEasyMDE: string;
|
valueEasyMDE: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IActions {
|
interface IActions {
|
||||||
setTitle: (newState: string) => void;
|
setTitle: (newState: string) => void;
|
||||||
|
setTheme: (newState: string) => void;
|
||||||
setUsuarioPermisos: (newState: object | null) => void;
|
setUsuarioPermisos: (newState: object | null) => void;
|
||||||
setValueForEasyMDE: (newState: string) => void;
|
setValueForEasyMDE: (newState: string) => void;
|
||||||
}
|
}
|
||||||
@ -15,6 +17,7 @@ interface IActions {
|
|||||||
export const { useStore, store } = createStore<IState, IActions>(
|
export const { useStore, store } = createStore<IState, IActions>(
|
||||||
{
|
{
|
||||||
title: '',
|
title: '',
|
||||||
|
theme: 'light',
|
||||||
usuarioPermisos: null,
|
usuarioPermisos: null,
|
||||||
valueEasyMDE: ''
|
valueEasyMDE: ''
|
||||||
},
|
},
|
||||||
@ -24,6 +27,11 @@ export const { useStore, store } = createStore<IState, IActions>(
|
|||||||
title: newState
|
title: newState
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
setTheme: (store, newState) => {
|
||||||
|
store.setState({
|
||||||
|
theme: newState
|
||||||
|
})
|
||||||
|
},
|
||||||
setUsuarioPermisos: (store, newState) => {
|
setUsuarioPermisos: (store, newState) => {
|
||||||
store.setState({
|
store.setState({
|
||||||
usuarioPermisos: newState
|
usuarioPermisos: newState
|
||||||
|
@ -12,10 +12,12 @@ import SessionTimeout from '@/components/SessionTimeout'
|
|||||||
import UserOptionsMenu from '@/components/widgets/UserOptionsMenu'
|
import UserOptionsMenu from '@/components/widgets/UserOptionsMenu'
|
||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
|
|
||||||
|
import menuData from '@/data/menu.json'
|
||||||
|
|
||||||
export const LayoutContext = createContext()
|
export const LayoutContext = createContext()
|
||||||
|
|
||||||
const Footer = dynamic(() => { return import('vComponents/Footer') }, { ssr: false })
|
const Footer = dynamic(() => { return import('vComponents/Footer') }, { ssr: false })
|
||||||
const Sidebar = dynamic(() => { return import('vComponents/Sidebar') }, { ssr: false })
|
const Sidebar = dynamic(() => { return import('@/components/vComponents/Sidebar') }, { ssr: false })
|
||||||
const Navbar = dynamic(() => { return import('vComponents/Navbar') }, { ssr: false })
|
const Navbar = dynamic(() => { return import('vComponents/Navbar') }, { ssr: false })
|
||||||
|
|
||||||
const ResponsiveContainer = ({ children }) => {
|
const ResponsiveContainer = ({ children }) => {
|
||||||
@ -26,13 +28,14 @@ const ResponsiveContainer = ({ children }) => {
|
|||||||
|
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(true)
|
const [sidebarOpen, setSidebarOpen] = useState(true)
|
||||||
const [menu, setMenu] = useState([])
|
const [menu, setMenu] = useState([])
|
||||||
const [title, setTitle] = useStore(s => s.title, a => a.setTitle)
|
|
||||||
const [userObj, setUserObj] = useState()
|
const [userObj, setUserObj] = useState()
|
||||||
const [token, setToken] = useState('')
|
const [token, setToken] = useState('')
|
||||||
const [theme, setTheme] = useState('light')
|
|
||||||
const [constanteObj, setConstanteObj] = useState('')
|
const [constanteObj, setConstanteObj] = useState('')
|
||||||
const [appVersion, setAppVersion] = useState('1.0.0')
|
const [appVersion, setAppVersion] = useState('1.0.0')
|
||||||
|
|
||||||
|
const [title, setTitle] = useStore(s => s.title, a => a.setTitle)
|
||||||
|
const [theme, setTheme] = useStore(s => s.theme, a => a.setTheme)
|
||||||
|
|
||||||
const doLogout = async () => {
|
const doLogout = async () => {
|
||||||
const redirectPath = await environment.logout()
|
const redirectPath = await environment.logout()
|
||||||
await i18n.locale('es')
|
await i18n.locale('es')
|
||||||
@ -107,7 +110,8 @@ const ResponsiveContainer = ({ children }) => {
|
|||||||
loading.start()
|
loading.start()
|
||||||
setMenu([])
|
setMenu([])
|
||||||
if (token && token !== null) {
|
if (token && token !== null) {
|
||||||
const options = await execute('SPR_MENU_S', [token, 'BO', null])
|
// const options = await execute('SPR_MENU_S', [token, 'BO', null])
|
||||||
|
const options = menuData
|
||||||
setMenu(options)
|
setMenu(options)
|
||||||
}
|
}
|
||||||
loading.stop()
|
loading.stop()
|
||||||
@ -232,6 +236,7 @@ const ResponsiveContainer = ({ children }) => {
|
|||||||
userMenuButtonStyles="via-user-menu-btn-navbar"
|
userMenuButtonStyles="via-user-menu-btn-navbar"
|
||||||
userOptionStyles="via-user-options-navbar"
|
userOptionStyles="via-user-options-navbar"
|
||||||
userOptionSelectedStyles="via-user-options-selected-navbar"
|
userOptionSelectedStyles="via-user-options-selected-navbar"
|
||||||
|
menuStyles="via-menu-navbar"
|
||||||
onClickLogout={() => doLogout()}
|
onClickLogout={() => doLogout()}
|
||||||
onClickProfile={() => router.push(`${presets.locations.profile}/${environment.getTime()}`)}
|
onClickProfile={() => router.push(`${presets.locations.profile}/${environment.getTime()}`)}
|
||||||
MenuOptions={() => <UserOptionsMenu setPreferences={setPreferences} theme={theme} i18n={i18n} />}
|
MenuOptions={() => <UserOptionsMenu setPreferences={setPreferences} theme={theme} i18n={i18n} />}
|
||||||
@ -243,7 +248,7 @@ const ResponsiveContainer = ({ children }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div className={userObj && userObj.nombre_usuario ? 'responsive-container' : 'hidden'}>
|
<div className={userObj && userObj.nombre_usuario ? 'responsive-container' : ''}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
@ -252,7 +257,7 @@ const ResponsiveContainer = ({ children }) => {
|
|||||||
<SessionTimeout i18n={i18n} user={userObj} onTimeout={() => onTimeout()} onCancelTimeout={() => onCancelTimeout()} />
|
<SessionTimeout i18n={i18n} user={userObj} onTimeout={() => onTimeout()} onCancelTimeout={() => onCancelTimeout()} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<Footer version={appVersion} label={i18n.t('common.version') || 'version'} />
|
<Footer footerStyle='via-footer' version={appVersion} label={i18n.t('common.version') || 'version'} />
|
||||||
</div>
|
</div>
|
||||||
</LayoutContext.Provider>
|
</LayoutContext.Provider>
|
||||||
)
|
)
|
||||||
|
@ -1,27 +1,34 @@
|
|||||||
import { RouteProvider } from '@/hooks/useRoute'
|
import { RouteProvider } from '@/hooks/useRoute'
|
||||||
|
import { useStore } from '@/hooks/useStore'
|
||||||
import ResponsiveContainer from '@/layout/ResponsiveContainer'
|
import ResponsiveContainer from '@/layout/ResponsiveContainer'
|
||||||
import LoadingProvider from '@/plugins/LoadingContext'
|
import LoadingProvider from '@/plugins/LoadingContext'
|
||||||
import I18nProvider from '@/plugins/i18nContext'
|
import I18nProvider from '@/plugins/i18nContext'
|
||||||
import '@/styles/globals.css'
|
|
||||||
import type { AppProps } from 'next/app'
|
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import 'vComponents/styles/generated/output.css'
|
|
||||||
import 'vComponents/styles/generated/bgColors.min.css'
|
|
||||||
|
|
||||||
import { ToastContainer } from 'react-toastify'
|
import { ToastContainer } from 'react-toastify'
|
||||||
|
|
||||||
export default function App ({ Component, pageProps }: AppProps) {
|
import '@/styles/globals.css'
|
||||||
|
import 'vComponents/styles/generated/bgColors.min.css'
|
||||||
|
import 'vComponents/styles/generated/output.css'
|
||||||
|
|
||||||
|
export default function App ({ Component, pageProps }) {
|
||||||
|
const [theme] = useStore(s => s.theme, a => a.setTheme)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<link rel="icon" href="https://wiki.via-asesores.com/logo-orbis_min.png" type="image/x-icon" />
|
<link rel="icon" href="https://wiki.via-asesores.com/logo-orbis_min.png" type="image/x-icon" />
|
||||||
<title>Orbis Template</title>
|
<title>Orbis Playground</title>
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<I18nProvider locale={'es'} dict={''}>
|
<I18nProvider locale={'es'} dict={''}>
|
||||||
<LoadingProvider>
|
<LoadingProvider>
|
||||||
<ToastContainer />
|
|
||||||
<ResponsiveContainer>
|
<ResponsiveContainer>
|
||||||
|
<ToastContainer
|
||||||
|
theme={theme === 'dark' ? 'dark' : 'light'}
|
||||||
|
toastClassName={theme === 'dark'
|
||||||
|
? 'bg-black shadow-neon text-white rounded-lg'
|
||||||
|
: 'bg-white text-black drop-shadow-lg rounded-lg shadow-lg'}
|
||||||
|
/>
|
||||||
<RouteProvider>
|
<RouteProvider>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</RouteProvider>
|
</RouteProvider>
|
40
src/pages/dashboard/index.jsx
Normal file
40
src/pages/dashboard/index.jsx
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import presets from '@/utils/globalPresets'
|
||||||
|
import React from 'react'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
|
||||||
|
const DashboardPage = () => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="grid grid-cols-4 gap-4 text-white">
|
||||||
|
<div className='bg-theme-app-50' >01</div>
|
||||||
|
<div className='bg-theme-app-100' >02</div>
|
||||||
|
<div className='bg-theme-app-200' >03</div>
|
||||||
|
<div className='bg-theme-app-300' >04</div>
|
||||||
|
<div className='bg-theme-app-400' >05</div>
|
||||||
|
<div className="col-span-3 grid grid-cols-subgrid gap-4 bg-theme-app-500">
|
||||||
|
<div className="col-start-2">06</div>
|
||||||
|
</div>
|
||||||
|
<div className='bg-theme-app-600' >07</div>
|
||||||
|
<div className='bg-theme-app-700' >08</div>
|
||||||
|
<div className='bg-theme-app-800' >09</div>
|
||||||
|
<div className='bg-theme-app-900' >10</div>
|
||||||
|
<div className='bg-theme-app-950' >11</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="via-button shadow-neon bg-theme-app-500 backdrop:bg-gray-50"
|
||||||
|
onClick={() => toast.success('Hola mundo', presets.toaster)}
|
||||||
|
>
|
||||||
|
Mostrar toast
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button className="shadow-neon shadow-neon-sky h-8 w-44 rounded-full bg-red-600 text-center text-purple-200" >
|
||||||
|
Button Neon
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DashboardPage
|
@ -56,12 +56,12 @@ const LoginPage = () => {
|
|||||||
max_mb_upload: process.env.maxMbUpload
|
max_mb_upload: process.env.maxMbUpload
|
||||||
}
|
}
|
||||||
await environment.login(user.token, user, constante)
|
await environment.login(user.token, user, constante)
|
||||||
toast.success(`Bienvenido ${user.nombre_usuario}`, presets.toaster)
|
await global.setTheme(user.theme)
|
||||||
await global.setUserObj(user)
|
await global.setUserObj(user)
|
||||||
await global.setConstanteObj(constante)
|
await global.setConstanteObj(constante)
|
||||||
await global.setToken(resultado[0].token)
|
await global.setToken(resultado[0].token)
|
||||||
await global.setTheme(user.theme)
|
|
||||||
await i18n.locale(user.i18n)
|
await i18n.locale(user.i18n)
|
||||||
|
toast.success(`Bienvenido ${user.nombre_usuario}`, presets.toaster)
|
||||||
router.push(homePath)
|
router.push(homePath)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
9
src/pages/via-ui/[...index].jsx
Normal file
9
src/pages/via-ui/[...index].jsx
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
const viaUIPage = () => {
|
||||||
|
return (
|
||||||
|
<div>viaUIPage</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default viaUIPage
|
29
src/pages/via-ui/tab/[...index].jsx
Normal file
29
src/pages/via-ui/tab/[...index].jsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from 'via-ui/tab'
|
||||||
|
|
||||||
|
const TabPage = () => {
|
||||||
|
const [tab, setTab] = React.useState('data')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tabs activeValue={tab}>
|
||||||
|
<TabsList>
|
||||||
|
<TabsTrigger value="data" onClick={() => setTab('data')}>
|
||||||
|
Datos del Evento
|
||||||
|
</TabsTrigger>
|
||||||
|
<TabsTrigger value="docs" onClick={() => setTab('docs')}>
|
||||||
|
Documentos del Evento
|
||||||
|
</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="data">
|
||||||
|
tabs data
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="docs">
|
||||||
|
tabs docs
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TabPage
|
56
src/pages/via-ui/test/[...index].jsx
Normal file
56
src/pages/via-ui/test/[...index].jsx
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import CodePlayground from '@/components/CodePlayground'
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from 'via-ui/tab'
|
||||||
|
|
||||||
|
const initialCode =
|
||||||
|
`// import { Tabs, TabsContent, TabsList, TabsTrigger } from 'via-ui/tab'
|
||||||
|
|
||||||
|
const TabsExample = () => {
|
||||||
|
const [tab, setTab] = React.useState('data');
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Tabs activeValue={tab} onChange={setTab}>
|
||||||
|
<TabsList>
|
||||||
|
<TabsTrigger value="data">Datos del Evento</TabsTrigger>
|
||||||
|
<TabsTrigger value="docs">Documentos del Evento</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
|
||||||
|
<TabsContent value="data">
|
||||||
|
tabs data
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value="docs">
|
||||||
|
tabs docs
|
||||||
|
</TabsContent>
|
||||||
|
</Tabs>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render(<TabsExample />);
|
||||||
|
`
|
||||||
|
|
||||||
|
const ExampleComponentPage = () => {
|
||||||
|
const [code, setCode] = useState(initialCode)
|
||||||
|
|
||||||
|
// El objeto scope debería incluir todos los componentes y funciones que el código JSX necesita
|
||||||
|
const scope = {
|
||||||
|
React,
|
||||||
|
useState,
|
||||||
|
Tabs,
|
||||||
|
TabsContent,
|
||||||
|
TabsList,
|
||||||
|
TabsTrigger
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className='rounded-lg bg-white p-4 shadow-lg dark:!bg-[#222222]'>
|
||||||
|
<CodePlayground code={code} onChange={(newCode) => { setCode(newCode) }} scope={scope} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ExampleComponentPage
|
@ -1,9 +1,9 @@
|
|||||||
.via-navbar {
|
.via-navbar {
|
||||||
@apply bg-white dark:bg-[#222222] border-slate-200 text-theme-app-500 dark:text-theme-app-50 font-semibold !important;
|
@apply bg-white dark:bg-[#222222] border-slate-200 text-theme-app-500 dark:text-theme-app-50 font-semibold transition-colors duration-[350ms] ease-in-out !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.via-menu-btn-navbar {
|
.via-menu-btn-navbar {
|
||||||
@apply text-slate-600 hover:text-slate-900 !important;
|
@apply text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-200 transition-colors duration-[350ms] ease-in-out shadow-neon rounded-md !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.via-user-menu-btn-navbar {
|
.via-user-menu-btn-navbar {
|
||||||
@ -11,9 +11,17 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.via-user-options-navbar {
|
.via-user-options-navbar {
|
||||||
@apply text-gray-900 bg-transparent transition-colors duration-[350ms] ease-in-out !important;
|
@apply bg-transparent border border-transparent dark:border-theme-app-400 text-gray-900 dark:text-white transition-colors duration-[350ms] ease-in-out !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.via-user-options-selected-navbar {
|
.via-user-options-selected-navbar {
|
||||||
@apply bg-slate-700 dark:bg-slate-800 text-white transition-colors duration-[350ms] ease-in-out !important;
|
@apply bg-theme-app-50 border border-transparent dark:bg-theme-app-500 transition-colors duration-[350ms] ease-in-out !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.via-menu-navbar {
|
||||||
|
@apply bg-white dark:bg-[#222222] border-slate-200 text-black dark:text-white transition-colors duration-[350ms] ease-in-out !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.via-footer {
|
||||||
|
@apply bg-white dark:bg-[#222222] border-slate-200 text-black dark:text-white transition-colors duration-[350ms] ease-in-out text-xs !h-8 !important;
|
||||||
}
|
}
|
@ -3,11 +3,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.via-options-sidebar {
|
.via-options-sidebar {
|
||||||
@apply text-theme-app-50 bg-transparent transition-colors duration-150 font-semibold hover:bg-theme-app-50 hover:text-gray-800 dark:text-theme-app-50 dark:hover:bg-theme-app-700 first-letter:uppercase !important;
|
@apply text-theme-app-50 bg-transparent transition-colors duration-150 font-semibold hover:bg-theme-app-50 hover:text-gray-800 dark:text-theme-app-50 dark:hover:bg-theme-app-200 first-letter:uppercase !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.via-sub-options-sidebar {
|
.via-sub-options-sidebar {
|
||||||
@apply text-white hover:bg-theme-app-100 transition-colors duration-150 font-semibold gap-x-1 hover:text-gray-800 dark:text-theme-app-50 dark:hover:bg-theme-app-800 !important;
|
@apply text-white hover:bg-theme-app-100 transition-colors duration-150 font-semibold gap-x-1 hover:text-gray-800 dark:text-theme-app-50 dark:hover:bg-theme-app-300 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.via-drawer-count {
|
.via-drawer-count {
|
||||||
@ -29,3 +29,12 @@
|
|||||||
.via-icons-sub-sidebar {
|
.via-icons-sub-sidebar {
|
||||||
@apply !text-theme-app-950 bg-cyan-50 rounded-md h-6 w-6 p-[1px] drop-shadow-md !important;
|
@apply !text-theme-app-950 bg-cyan-50 rounded-md h-6 w-6 p-[1px] drop-shadow-md !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.via-input-search-sidebar {
|
||||||
|
@apply w-full rounded-l-lg shadow-lg !border-l-2 !border-y-2 border-r-0 border-[#7b1fa2] focus:border-blue-500 !important;
|
||||||
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.5) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.via-button-search-sidebar {
|
||||||
|
@apply bg-theme-app-500 hover:bg-theme-app-600 text-white flex justify-center items-center p-2 rounded-r-lg cursor-pointer shadow-neon dark:!border-l-0 !important;
|
||||||
|
}
|
@ -26,6 +26,58 @@
|
|||||||
@apply bg-theme-app-700 border-theme-app-700 dark:bg-theme-app-900 dark:border-theme-app-900;
|
@apply bg-theme-app-700 border-theme-app-700 dark:bg-theme-app-900 dark:border-theme-app-900;
|
||||||
transition: 0s;
|
transition: 0s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-neon {
|
||||||
|
0%, 100% {
|
||||||
|
box-shadow:
|
||||||
|
0 0 4px var(--tw-shadow-color),
|
||||||
|
0 0 8px var(--tw-shadow-color);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
box-shadow:
|
||||||
|
0 0 8px var(--tw-shadow-color),
|
||||||
|
0 0 10px var(--tw-shadow-color);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
box-shadow:
|
||||||
|
0 0 6px var(--tw-shadow-color),
|
||||||
|
0 0 12px var(--tw-shadow-color);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
box-shadow:
|
||||||
|
0 0 8px var(--tw-shadow-color),
|
||||||
|
0 0 14px var(--tw-shadow-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer components {
|
||||||
|
.shadow-neon {
|
||||||
|
@apply shadow-lg;
|
||||||
|
border: 2px solid var(--tw-border-color);
|
||||||
|
--tw-shadow-color: rgba(0, 0, 0, 0.25);
|
||||||
|
--tw-border-color: transparent;
|
||||||
|
box-shadow: 0 2px 15px var(--tw-shadow-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .shadow-neon {
|
||||||
|
--tw-shadow-color: #9c27b0;
|
||||||
|
--tw-border-color: #7b1fa2;
|
||||||
|
box-shadow: 0 2px 15px var(--tw-shadow-color);
|
||||||
|
}
|
||||||
|
.dark .shadow-neon:hover {
|
||||||
|
animation: pulse-neon 2s infinite ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .shadow-neon.shadow-neon-purple {
|
||||||
|
--tw-shadow-color: #9c27b0;
|
||||||
|
--tw-border-color: #7b1fa2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .shadow-neon.shadow-neon-sky {
|
||||||
|
--tw-shadow-color: #00c4e2;
|
||||||
|
--tw-border-color: #00a2ba;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Additional Styles */
|
/* Additional Styles */
|
||||||
|
@ -110,7 +110,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.responsive-container {
|
.responsive-container {
|
||||||
@apply w-full h-auto min-h-[calc(100vh-60px)] mx-auto bg-[#ECEFF8] dark:bg-[#0f0f0f] items-center pb-10 p-2;
|
@apply w-full h-auto min-h-[calc(100vh-60px)] mx-auto bg-[#ECEFF8] dark:bg-[#0f0f0f] items-center pb-10 p-2 transition-colors duration-[350ms] ease-in-out text-[#0F0F0F] dark:text-[#F1F1F1] !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.via-title {
|
.via-title {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.via-login-logo {
|
.via-login-logo {
|
||||||
@apply w-64 h-64 bg-center bg-auto bg-no-repeat object-cover;
|
@apply w-64 h-64 bg-center bg-auto bg-no-repeat object-contain !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.via-login-background {
|
.via-login-background {
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
const theme = 'blue'
|
const theme = 'blue'
|
||||||
|
|
||||||
const presets = {
|
const presets = {
|
||||||
appTitle: 'Orbis Template',
|
appTitle: 'Orbis Playground',
|
||||||
theme: `${theme}`,
|
theme: `${theme}`,
|
||||||
svgIconUrl: 'https://www.via-asesores.com/svgicons/smartoperation/',
|
svgIconUrl: 'https://www.via-asesores.com/svgicons/smartoperation/',
|
||||||
images: {
|
images: {
|
||||||
loginFondo: 'https://www.via-asesores.com/backgrounds/smartoperation/SmartOperation_background.png',
|
loginFondo: `${process.env.publicPath}/images/backgrounds.webp`,
|
||||||
welcomeFondo: 'https://www.via-asesores.com/backgrounds/smartoperation/SmartOperation_background.png',
|
welcomeFondo: 'https://www.via-asesores.com/backgrounds/smartoperation/SmartOperation_background.png',
|
||||||
icon: 'https://www.via-asesores.com/logos/logo_icons/smarterp_icon.svg',
|
icon: 'https://www.via-asesores.com/logos/logo_icons/smartdeveloper_icon.svg',
|
||||||
logo: 'https://www.via-asesores.com/logos/smartOperations.png',
|
logo: 'https://www.via-asesores.com/logos/logo_vertical/smartdeveloper_vertical_logo.svg',
|
||||||
imageLoader: 'https://www.via-asesores.com/logos/logo_via.png',
|
imageLoader: 'https://www.via-asesores.com/logos/logo_via.png',
|
||||||
noImageFound: 'https://www.via-asesores.com/smartsalesnprofit/images/LogoViasaClaroTransparente_600x.png',
|
noImageFound: 'https://www.via-asesores.com/smartsalesnprofit/images/LogoViasaClaroTransparente_600x.png',
|
||||||
onError: 'https://www.via-asesores.com/smartsalesnprofit/images/LogoViasaClaroTransparente_600x.png',
|
onError: 'https://www.via-asesores.com/smartsalesnprofit/images/LogoViasaClaroTransparente_600x.png',
|
||||||
@ -25,8 +25,7 @@ const presets = {
|
|||||||
hideProgressBar: false,
|
hideProgressBar: false,
|
||||||
closeOnClick: true,
|
closeOnClick: true,
|
||||||
pauseOnHover: true,
|
pauseOnHover: true,
|
||||||
draggable: true,
|
draggable: true
|
||||||
theme: 'light'
|
|
||||||
},
|
},
|
||||||
pristine: {
|
pristine: {
|
||||||
// class of the parent element where the error/success class is added
|
// class of the parent element where the error/success class is added
|
||||||
|
@ -54,6 +54,8 @@ const config: Config = {
|
|||||||
md: '0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -1px rgba(0, 0, 0, 0.02)',
|
md: '0 4px 6px -1px rgba(0, 0, 0, 0.08), 0 2px 4px -1px rgba(0, 0, 0, 0.02)',
|
||||||
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.01)',
|
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -2px rgba(0, 0, 0, 0.01)',
|
||||||
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 10px 10px -5px rgba(0, 0, 0, 0.01)'
|
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 10px 10px -5px rgba(0, 0, 0, 0.01)'
|
||||||
|
// neon: '0 0 3px #7f11e0, 0 0 6px #7f11e0, 0 0 9px #7f11e0',
|
||||||
|
// 'neon-hover': '0 0 6px #7f11e0, 0 0 12px #7f11e0, 0 0 18px #7f11e0'
|
||||||
},
|
},
|
||||||
outline: {
|
outline: {
|
||||||
blue: '2px solid rgba(0, 112, 244, 0.5)'
|
blue: '2px solid rgba(0, 112, 244, 0.5)'
|
||||||
@ -64,17 +66,17 @@ const config: Config = {
|
|||||||
disabled: '#cbd5e1'
|
disabled: '#cbd5e1'
|
||||||
},
|
},
|
||||||
'theme-app': {
|
'theme-app': {
|
||||||
50: '#DDE3EB',
|
50: '#e1ddeb',
|
||||||
100: '#B0C4D6',
|
100: '#bab0d6',
|
||||||
200: '#83A5C1',
|
200: '#9383c1',
|
||||||
300: '#5686AC',
|
300: '#6c56ac',
|
||||||
400: '#296897',
|
400: '#462997',
|
||||||
500: '#1E507B',
|
500: '#361e7b',
|
||||||
600: '#1B4870',
|
600: '#311b70',
|
||||||
700: '#183F64',
|
700: '#2c1864',
|
||||||
800: '#153758',
|
800: '#261558',
|
||||||
900: '#112F4D',
|
900: '#21114d',
|
||||||
950: '#0E2741'
|
950: '#1b0e41'
|
||||||
},
|
},
|
||||||
warning: '#3B82F6',
|
warning: '#3B82F6',
|
||||||
'warning-dark': '#1E40AF',
|
'warning-dark': '#1E40AF',
|
||||||
|
Loading…
Reference in New Issue
Block a user