Virtubrick

- Mostly rebranded the website to Virtubrick, following Icseon's decision to stop paying for gtoria.net.
- Name is dynamic and can be configured via the .env file.
- Admin user search page.
- Made a page explaining what the purpose of testing sites are.
- Readded maintenance page.
- Created a batch file for (re)generating the ssl certificate.
- Reworking admin configuration page.
- Indev Roblox asset auto uploader.
- Component for user headshot/name. Toggleable status visualization.
- Virtubrick-styled tables.
This commit is contained in:
Graphictoria 2022-12-27 22:47:22 -05:00
parent de46b30b8a
commit 056d12d309
133 changed files with 1427 additions and 979 deletions

BIN
etc/art/vbrick.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 977 KiB

BIN
etc/art/virtubrick.blend Normal file

Binary file not shown.

View File

@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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
p7zJ6bVvpr9PohKjIbslj2gkrMb7gq9EH4Tv Nk9CdC6FVWP6x/I=
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@ -1,28 +1,28 @@
-----BEGIN PRIVATE KEY----- -----BEGIN PRIVATE KEY-----
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
pPVAfmA8k77J9R/XWJylkA== ZSEy8mDXVww7JCsG4avq0Fk=
-----END PRIVATE KEY----- -----END PRIVATE KEY-----

View File

@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
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
p7zJ6bVvpr9PohKjIbslj2gkrMb7gq9EH4Tv Nk9CdC6FVWP6x/I=
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@ -4,6 +4,6 @@ keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names subjectAltName = @alt_names
[alt_names] [alt_names]
DNS.1 = localhost DNS.1 = localhost
DNS.2 = gtoria.local DNS.2 = virtubrick.local
DNS.3 = *.gtoria.local DNS.3 = *.virtubrick.local
DNS.4 = *.*.gtoria.local DNS.4 = *.*.virtubrick.local

4
etc/cert/gen.bat Normal file
View File

@ -0,0 +1,4 @@
openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=US/CN=VirtuBrick-Local-CA"
openssl x509 -outform pem -in RootCA.pem -out RootCA.crt
openssl req -new -nodes -newkey rsa:2048 -keyout vbrick.key -out vbrick.csr -subj "/C=US/ST=California/L=San Mateo/O=VirtuBrick Local Test/CN=virtubrick.local"
openssl x509 -req -sha256 -days 1024 -in vbrick.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out vbrick.crt

View File

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID0TCCArmgAwIBAgIUbUj9EBw3CYxjAyrsJy1LVn6r0q0wDQYJKoZIhvcNAQEL
BQAwMzELMAkGA1UEBhMCVVMxJDAiBgNVBAMMG0dyYXBoaWN0b3JpYS1EZXZlbG9w
bWVudC1DQTAeFw0yMjA0MTUwMjM1NTNaFw0yNTAyMDIwMjM1NTNaMG4xCzAJBgNV
BAYTAlVTMRIwEAYDVQQIDAlZb3VyU3RhdGUxETAPBgNVBAcMCFlvdXJDaXR5MSEw
HwYDVQQKDBhHcmFwaGljdG9yaWEtRGV2ZWxvcG1lbnQxFTATBgNVBAMMDGd0b3Jp
YS5sb2NhbDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALYo89k+V6a9
VX2BiMEiRQbRuqxYbhcafI5Pr1eUuv99IFuHFUV/fA5QiQ3j9woTr3/VdURkr4C0
ZWjEW4yd+8p+PjM/vAx9LZp2zhYyGu9wa+fsciOXmF0zhC6nuSIhcLlHwInwJ0cv
SabXV59GmoC9zxe0xoreSAU6hggLfuEXifn0dfdJTcXwfYgrneYr7ZFS/f0lCuEh
T19/FLBChw0Hch9axPJM1N1OGmUQxPx0NJTEOp7GGTjq1VlOTpnEx+OdpWBIb0JN
fFlpDkWGD53lnf/fhio68wz9hsIv+XyNXfw7XPa1AkZWVnoTZNxwcJKC0ltVxwUG
h/uvJpi9gvUCAwEAAaOBoTCBnjAfBgNVHSMEGDAWgBTH+uxCWs1TcDYNFptpXWME
Sc+MejAJBgNVHRMEAjAAMAsGA1UdDwQEAwIE8DBEBgNVHREEPTA7gglsb2NhbGhv
c3SCDGd0b3JpYS5sb2NhbIIOKi5ndG9yaWEubG9jYWyCECouKi5ndG9yaWEubG9j
YWwwHQYDVR0OBBYEFIL06aX5T1tU7ozj1wC46e4qNW3wMA0GCSqGSIb3DQEBCwUA
A4IBAQBTZt4Pw6rzRNMPoPVOeAheLcd1JbO4Z+H3LW9MTerOp0JuaU7Q/LSbBBEp
/sP6aXzaIuepkiZk/pFlaXxDZ/XXrBy0sxGvMRI3K1hgU8evN3tiwTmLz1Vs2ffF
QEVUT3ytVxa/wP2A4uDhpZqqNjKvlxYesqXnSO7B20uO2IyYjliDwG1/dK6b6N64
XerbG+/sWjsNlpHLDu5qz7YYV78F6LO1bT24uVTWToXFFGuoJsf+3WrGp5Fg2RwN
FPBvLd+HbjWnkKN3BoMGP1fodAHTRhkiNOH3xMAOi4kxzArmxfg4gF+ABu6NO+67
iCBnuBC+ZyIkc24xsajDuU4csSho
-----END CERTIFICATE-----

View File

@ -1,17 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICszCCAZsCAQAwbjELMAkGA1UEBhMCVVMxEjAQBgNVBAgMCVlvdXJTdGF0ZTER
MA8GA1UEBwwIWW91ckNpdHkxITAfBgNVBAoMGEdyYXBoaWN0b3JpYS1EZXZlbG9w
bWVudDEVMBMGA1UEAwwMZ3RvcmlhLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAtijz2T5Xpr1VfYGIwSJFBtG6rFhuFxp8jk+vV5S6/30gW4cV
RX98DlCJDeP3ChOvf9V1RGSvgLRlaMRbjJ37yn4+Mz+8DH0tmnbOFjIa73Br5+xy
I5eYXTOELqe5IiFwuUfAifAnRy9JptdXn0aagL3PF7TGit5IBTqGCAt+4ReJ+fR1
90lNxfB9iCud5ivtkVL9/SUK4SFPX38UsEKHDQdyH1rE8kzU3U4aZRDE/HQ0lMQ6
nsYZOOrVWU5OmcTH452lYEhvQk18WWkORYYPneWd/9+GKjrzDP2Gwi/5fI1d/Dtc
9rUCRlZWehNk3HBwkoLSW1XHBQaH+68mmL2C9QIDAQABoAAwDQYJKoZIhvcNAQEL
BQADggEBAA/DMwmDDB989uhYGgpBiFENiqQBV4ApyWVSpf4p+egdVTgoa/1v1k2w
5dy2/z0x/MCzS+LTb8vwHoRXPWhLGerSXP5MgLtGWgFVrBvdfJ1QZCEc6OpihqFh
xHzKPD9Wbr3B9shUFURIsvl5qCYzwoePHPsEyrrgvF9wkmjV6ENJfIkaIi2U2ll6
H76GF3tN3ybR+NBcvRyc/xl+P8Hac4XAhvMNlDIvuFFvIMiZREnguoU0MSscSH61
3eJKZqGJx4kf81RXZw7bdAGG/OGfmF77s9EhBtxxGGKu6xcyfCzhdn0X1NsMvJXD
zIYiOCaou7k8Yu2A3VsLMsgLAV4PcH4=
-----END CERTIFICATE REQUEST-----

View File

@ -1,28 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2KPPZPlemvVV9
gYjBIkUG0bqsWG4XGnyOT69XlLr/fSBbhxVFf3wOUIkN4/cKE69/1XVEZK+AtGVo
xFuMnfvKfj4zP7wMfS2ads4WMhrvcGvn7HIjl5hdM4Qup7kiIXC5R8CJ8CdHL0mm
11efRpqAvc8XtMaK3kgFOoYIC37hF4n59HX3SU3F8H2IK53mK+2RUv39JQrhIU9f
fxSwQocNB3IfWsTyTNTdThplEMT8dDSUxDqexhk46tVZTk6ZxMfjnaVgSG9CTXxZ
aQ5Fhg+d5Z3/34YqOvMM/YbCL/l8jV38O1z2tQJGVlZ6E2TccHCSgtJbVccFBof7
ryaYvYL1AgMBAAECggEAB97gcmGG3gB47NGnpq35YjW2UB4IsQeG8YswiKM3f98t
17vlcmRIvZbt5Q4VgszznJ1iJ2YGTemoJreykPJ+ikhGyGYXlPPlADM5QleV4a9E
1PeFaFOeKgtrdFdGNjBQXjZjHlKkZSdTklmO7VCFT8y5DE2A9UfCFYpqzMwvsOqw
YA/EZdQvswnDScG8Dfu5kOGB/qAxrNGLrXcefCbYpubXBfs/duYcJ2uadTLa79sj
AK878G6Ql9LkiXx/yyq0LnUQqA0zrQeJMF9CEdNLA6O1n9BRjO9kKcR0LspKa2vp
Ygi4ISzgwJ5oR7iABcj3o/Tv2cmLdlSJp0DRuygFgQKBgQDtQl/m3Ic/7xQ/efN+
V6vPUCF/lXfw2Ep/qE5oEasCUqvcmeBOrqB8Uprl0dnLCxDz5c1jDnDaxeJpN9L7
RjHGLxqIV7F3ZfCn+neI3Ju0vbzTGkCcs6C1cbgTfrF9flgirkfR+cB0peWhEA/g
poAQW9X+jnOl3m+9JHtflpdcYQKBgQDEjGngPD7yk53c4duf7b+Im594EIHzZlv+
uczXHbP75/AwOPCsQPBycL7J0sWnsw+jyOOuCY1aj4b1VUBD1kGrgN4zziuHtMaV
wgStbAwAJOSaPcWaXXmQpTC4u9eTX7nnvnezri5E3XrnToUfK9B7+aEAZT39XHiZ
ItwOAnFPFQKBgC30i0rWMERL9KoO3wD7zkWLidGCjAbUfimX2ggCVBNRHATQsUfM
Pz2VandVXFAdxpzXSB8FrwpRBffHXlBZWk6+1O7PvYoY7rI6q2iRAn/RuH9TOGyh
xmEes77i7VIXZM7i3vpm28Y8U+wMhmbHGUsR3rM9uFzKZu5F4Le1HYBBAoGAL8lr
3IcJTvUxBokrWsD1NoOPzCNHVSRn7ZDDCvI/1llX/oF5koffbhOXb359a/6PKOUo
5iGQappG19M4YsXvBYG5hKL11nLPbY3UkU2ZxVcy9YVbS+K6Mb7YD7IsAbreekfG
1rrcqQWoYiCnISMH93yD9pKm9bjL4X+mPQm+/tkCgYEAjwdfAFSYnzUdxB8zTsXx
+p2daNJlY00YK0kf//qg4WhXkW6//jILoJFOD8lFMaVz+H30bGsHtOqAoTZ/+Ozk
Jwzlie9J2gWrInXu9zqnw2jAfIQZGZRFMNpxOoRT3yvh2fnArIXKtBdP107p2yLl
2w2vr0QHVij28jWQpsRGG0U=
-----END PRIVATE KEY-----

23
etc/cert/vbrick.crt Normal file
View File

@ -0,0 +1,23 @@
-----BEGIN CERTIFICATE-----
MIID2DCCAsCgAwIBAgIUSs0NnP/ZRmvsjJWv0ULFldiMwfowDQYJKoZIhvcNAQEL
BQAwKzELMAkGA1UEBhMCVVMxHDAaBgNVBAMME1ZpcnR1QnJpY2stTG9jYWwtQ0Ew
HhcNMjIxMjI0MDQwNzM4WhcNMjUxMDEzMDQwNzM4WjBxMQswCQYDVQQGEwJVUzET
MBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU2FuIE1hdGVvMR4wHAYDVQQK
DBVWaXJ0dUJyaWNrIExvY2FsIFRlc3QxGTAXBgNVBAMMEHZpcnR1YnJpY2subG9j
YWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCjIun15WSkYDojtmUM
TOhSvCNZiMFADx7SFtZ9BmT94aURmJkQ/OU9vEBiaPBigNaByNEjp9FyKK+oCbgC
zdZjCtHnYeOTKpK8huHYFM0PE5MmMmmEf0M6ERrSpJ0IjAjoOhBC6iz3ouDeaRaa
Ha9GuB54RF1Jo4e0nX5A8OcUuzZA1DTdlZ1wrRFymgsjYPqE9b1If9Ni9ABehlNA
+6BUtwuef1jEyKTyXSd9hK/ngo2t/wKurxsjOOZiaNDZjdY0btGVSMQS0pqxVpiz
DI7RqqkdbRhHe/3hGKvCPXs0p6RjXINKeY6lhI+Tv3qogpnHqjfrnN/mfJMt7NW2
D9VJAgMBAAGjga0wgaowHwYDVR0jBBgwFoAUujypvXOQhW0TC7XCE4MdR/gurl0w
CQYDVR0TBAIwADALBgNVHQ8EBAMCBPAwUAYDVR0RBEkwR4IJbG9jYWxob3N0ghB2
aXJ0dWJyaWNrLmxvY2FsghIqLnZpcnR1YnJpY2subG9jYWyCFCouKi52aXJ0dWJy
aWNrLmxvY2FsMB0GA1UdDgQWBBQIQHg8iyx/ED9q8mtu9VKSPxBwYzANBgkqhkiG
9w0BAQsFAAOCAQEAKmwhDHvhytS81dDOWjzYXaQXzxOn3/6NSuL0FogY2sM8Nt3L
cT9JQQqqxevG2vbnUrODC2eGMSApnoBI1mJuP2SkyZGCVbi1QLca5WII/We/HPAs
OaC6CLKs1ywpClBV0GoFO7aNWEtSbQ0haNiGoEQsk8kvPFA3kLSCUF3SN0csFOc4
vcU8GwqrbO53hpclP3SZrwjzh1VlW985EMaWGd14/e/ASYu/+FSnIjbkZmha8CXu
8dI8BPAZ6D0nVj4kBICEy3bonzdJP/MhentCrE6WH2Eg5SqA2a14sSVx5K025OmS
QLjrqRLxlwMGYC+pQ+RHPmAl/ZVrJc7vli4CsA==
-----END CERTIFICATE-----

17
etc/cert/vbrick.csr Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICtjCCAZ4CAQAwcTELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWEx
EjAQBgNVBAcMCVNhbiBNYXRlbzEeMBwGA1UECgwVVmlydHVCcmljayBMb2NhbCBU
ZXN0MRkwFwYDVQQDDBB2aXJ0dWJyaWNrLmxvY2FsMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAoyLp9eVkpGA6I7ZlDEzoUrwjWYjBQA8e0hbWfQZk/eGl
EZiZEPzlPbxAYmjwYoDWgcjRI6fRciivqAm4As3WYwrR52HjkyqSvIbh2BTNDxOT
JjJphH9DOhEa0qSdCIwI6DoQQuos96Lg3mkWmh2vRrgeeERdSaOHtJ1+QPDnFLs2
QNQ03ZWdcK0RcpoLI2D6hPW9SH/TYvQAXoZTQPugVLcLnn9YxMik8l0nfYSv54KN
rf8Crq8bIzjmYmjQ2Y3WNG7RlUjEEtKasVaYswyO0aqpHW0YR3v94Rirwj17NKek
Y1yDSnmOpYSPk796qIKZx6o365zf5nyTLezVtg/VSQIDAQABoAAwDQYJKoZIhvcN
AQELBQADggEBAH9T2qdl5mWAEkNh0mHc7io7EqKCAwGSkWudj+QqWse9cn3AELLv
VbXUcE/GkcCTYiLyY8mJxwYaGiRa/tLcl4IHgXtG/a4oAoMdB5moQorT9YiWlXrs
3bzl/vZJaSmp12k2gN0Mu8H4ED5Eg4trKIcORzRsQV6zzYhF/4oUllr3cFg30CCl
nm7Mwwk6k4yB/zNuoPm6laukeMi99TLQ8LK57odi4Wqz4mZvd5lryhGEm6dZ6Cz+
Cahdba8vzvN3RIAWMhDubMxNfaAQvV1Z0yEZ6fcmEDWzof1tD1VtA82al5YJvLy3
RZcycbaB90F0XUhb20iElnxzig2XDNcbWR0=
-----END CERTIFICATE REQUEST-----

28
etc/cert/vbrick.key Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCjIun15WSkYDoj
tmUMTOhSvCNZiMFADx7SFtZ9BmT94aURmJkQ/OU9vEBiaPBigNaByNEjp9FyKK+o
CbgCzdZjCtHnYeOTKpK8huHYFM0PE5MmMmmEf0M6ERrSpJ0IjAjoOhBC6iz3ouDe
aRaaHa9GuB54RF1Jo4e0nX5A8OcUuzZA1DTdlZ1wrRFymgsjYPqE9b1If9Ni9ABe
hlNA+6BUtwuef1jEyKTyXSd9hK/ngo2t/wKurxsjOOZiaNDZjdY0btGVSMQS0pqx
VpizDI7RqqkdbRhHe/3hGKvCPXs0p6RjXINKeY6lhI+Tv3qogpnHqjfrnN/mfJMt
7NW2D9VJAgMBAAECggEABDCrSFAUiWF/v/2sbPT0Vw+snsOaJxf17cwW+HSEfb4U
D2m9rYe5Wzngs3mVI9dbhLWqPYHoqZR6Jbt3xcaqSRzBiHGYtuWpVpZ/6lA0D70s
ErD8lqHukZxX3CCZq4460/Anc8VWoCOt8x7i4DsYwem/vc1C673IbtV7i5Wq2C4h
e9rTlYE87D7mHfCIFwlV4JOqkqPYbR6sr8cf5rdAdy5L73bU/0ff4+TwY9UxnufM
crdvhf2nWJIQHh7zCfQapFTwUIlrsyAu6t30lRkdxNje2JVxpPDaEqHnDh/Nuni5
m4t4OUXZTvLhWblIIw5iwX/M9le9MmobHWSu5odd2wKBgQDcRh/DRv57adXInweX
AVL599H1LywjQAI/2eOV9BghBHb1Ln2LTidUS59pap+RZ2NL2OnKHhDX8u1UJi2G
DGibOHQep9pE56Gq/u1WJMpKnetIGr/hMSn7Uglg01BzmopiJ5OyN3cO7KdXH71J
oySKjISI7m0D+yrp93/O74YDgwKBgQC9mGmdBKYfv3sNYwoAQFCwKKcFYxlmaY5V
u7P1ViR0V+fkh7TW844FLXtI8cI9EbE3r6huM0YMlmL6fXb1zVoQgJUtT87pTMIf
ZcAq3kzHwkIA3vwFGZ8B1MsOKDybN379a8Ev3FM+Afyr1lrv/B4L14ZWcK2QbsNi
NJ3M2HlOQwKBgDdEFNYO6uyV+kByvhnCCEqVRgVpR360oZvZlENcUe1+zEXp2y/n
dPCuZJmzWcPGl+BA1S+T6Y/08FzLk2JtnJVNTb0fSiE9qI9ZlLynUGX2R0D5DSl4
B1t6EsZLXoUSwiOsYF83kVSaRcYTPY/LMfDdHqeogoucKgE3ysZlzE73AoGAT3dr
hPmm25W5cOH7FiHe8AcKAnMH+Wny07Jp+kHR48XYl2vd+154P2lRzEAwpsIconeI
xC/Pg4UhFVazHtGkl1gdrrFNy3F1yA0w34bvbabZXV4ZCdY0VGMpfNSWmoRHQNcC
URoq9cmFa0zcLsxgl5wNXXu689fJIwdkwLBXH9sCgYB52keZwt6rRu6n1q03tFWV
hZzxpxHX1hlw3jtLvWERpF8gLp5CRwX9xoMTciS82f3W/AUBx+eIiQ1HOUJ5W1S1
3GJBqCkWD8oipPxVW9XvKCdRHiY+2Jc+dKN2KTHjZSZLWDAZYkHL3/LC+gmQhM5j
bIyBpf2Yn45e1NIxAngLCw==
-----END PRIVATE KEY-----

View File

@ -1,9 +1,11 @@
APP_NAME=Graphictoria APP_NAME=VirtuBrick
APP_ENV=local APP_ENV=local
APP_KEY= APP_KEY=
APP_DEBUG=true APP_DEBUG=true
APP_URL=http://gtoria.net APP_URL=http://virtubrick.net
MIX_APP_URL=http://gtoria.net MIX_APP_URL=http://virtubrick.net
IS_TEST_ENVIRONMENT=true
GAMESERVER_IP=127.0.0.1 GAMESERVER_IP=127.0.0.1
THUMBNAILER_IP=127.0.0.1 THUMBNAILER_IP=127.0.0.1
@ -18,7 +20,7 @@ RECAPTCHA_SECRET_KEY=ServerKeyHere
DB_CONNECTION=mysql DB_CONNECTION=mysql
DB_HOST=127.0.0.1 DB_HOST=127.0.0.1
DB_PORT=3306 DB_PORT=3306
DB_DATABASE=gtoria DB_DATABASE=virtubrick
DB_USERNAME=root DB_USERNAME=root
DB_PASSWORD= DB_PASSWORD=

View File

@ -5,7 +5,7 @@ COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
COPY --from=node /usr/local/bin/node /usr/local/bin/node COPY --from=node /usr/local/bin/node /usr/local/bin/node
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm
WORKDIR /gtoria WORKDIR /vbrick
COPY . . COPY . .

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
This file handles communications between the arbiter and the website. This file handles communications between the arbiter and the website.
*/ */

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
CDN helper. CDN helper.
*/ */

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
Domain helper. Domain helper.
*/ */

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
Grid helper Grid helper
*/ */

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
Maintenance helper Maintenance helper
*/ */
@ -14,8 +14,8 @@ class MaintenanceHelper
{ {
public static function isDown() public static function isDown()
{ {
if(GridHelper::hasAllAccess()) if(GridHelper::isIpWhitelisted())
return true; return false;
if(!file_exists(storage_path('framework/down'))) if(!file_exists(storage_path('framework/down')))
return false; return false;
@ -30,9 +30,9 @@ class MaintenanceHelper
$request = request(); $request = request();
return isset($data['secret']) && return isset($data['secret']) &&
$request->cookie('gt_constraint') && $request->cookie('vb_constraint') &&
MaintenanceModeBypassCookie::isValid( MaintenanceModeBypassCookie::isValid(
$request->cookie('gt_constraint'), $request->cookie('vb_constraint'),
$data['secret'] $data['secret']
); );
} }

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
A bit of a hacky way to implement markdown with laravel. A bit of a hacky way to implement markdown with laravel.
*/ */

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
Number helper. Number helper.
*/ */

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
Quick Administration and Management Bar helper Quick Administration and Management Bar helper
*/ */

View File

@ -1,7 +1,7 @@
<?php <?php
/* /*
Graphictoria 2022 XlXi 2022
Validation Helper Validation Helper
*/ */

View File

@ -9,230 +9,8 @@ class ApiController extends Controller
{ {
public function index() public function index()
{ {
$apiTxts = [ // TODO: XlXi: Add some checks here, such as pinging api.virtubrick.net, checking commonly used API functions, etc...
<<<EOT return response('API OK!')
+##################+
| A. Mayonnaise |
| P. On |
| I. An |
| Escalator |
+##################+
| (its goin |
| upstairs so |
| see ya later) |
+##################+
| bye bye! |
+##################+
EOT,
<<<EOT
/ This is bob. Copy and paste him so he can take over Graphictoria.
/
/\
EOT,
<<<EOT
░░░░░░░▐▀█▀▌░░░░▀█▄░░░░
░░░░░░░▐█▄█▌░░░░░░▀█▄░░
░░░░░░░░▀▄▀░░░▄▄▄▄▄▀▀░░
░░░░░░▄▄▄██▀▀▀▀░░░░░░░░
░░░░░█▀▄▄▄█░▀▀░░░░░░░░░
░░░░░▌░▄▄▄▐▌▀▀▀░░░░░░░░
░░▄░▐░░░▄▄░█░▀▀ ░░░░░░░
░░▀█▌░░░▄░▀█▀░▀ ░░░░░░░
░░░░░░░░░▄▄▐▌▄▄░░░░░░░░
░░░░░░░░░▀███▀█░▄░░░░░░
░░░░░░░░▐▌▀▄▀▄▀▐▄░░░░░░
░░░░░░░░▐▀░░░░░░▐▌░░░░░
░░░░░░░░█░░░░░░░░█░░░░░
░░░░░░░░█░░░░░░░░█░░░░░
░░░░░░░░█░░░░░░░░█░░░░░
░░░░░░ ▄██▄░░░░░ ▄██▄░░
EOT,
<<<EOT
——————————————No API?—————————————
⠀⣞⢽⢪⢣⢣⢣⢫⡺⡵⣝⡮⣗⢷⢽⢽⢽⣮⡷⡽⣜⣜⢮⢺⣜⢷⢽⢝⡽⣝
⠸⡸⠜⠕⠕⠁⢁⢇⢏⢽⢺⣪⡳⡝⣎⣏⢯⢞⡿⣟⣷⣳⢯⡷⣽⢽⢯⣳⣫⠇
⠀⠀⢀⢀⢄⢬⢪⡪⡎⣆⡈⠚⠜⠕⠇⠗⠝⢕⢯⢫⣞⣯⣿⣻⡽⣏⢗⣗⠏⠀
⠀⠪⡪⡪⣪⢪⢺⢸⢢⢓⢆⢤⢀⠀⠀⠀⠀⠈⢊⢞⡾⣿⡯⣏⢮⠷⠁⠀⠀
⠀⠀⠀⠈⠊⠆⡃⠕⢕⢇⢇⢇⢇⢇⢏⢎⢎⢆⢄⠀⢑⣽⣿⢝⠲⠉⠀⠀⠀⠀
⠀⠀⠀⠀⠀⡿⠂⠠⠀⡇⢇⠕⢈⣀⠀⠁⠡⠣⡣⡫⣂⣿⠯⢪⠰⠂⠀⠀⠀⠀
⠀⠀⠀⠀⡦⡙⡂⢀⢤⢣⠣⡈⣾⡃⠠⠄⠀⡄⢱⣌⣶⢏⢊⠂⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⢝⡲⣜⡮⡏⢎⢌⢂⠙⠢⠐⢀⢘⢵⣽⣿⡿⠁⠁⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠨⣺⡺⡕⡕⡱⡑⡆⡕⡅⡕⡜⡼⢽⡻⠏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⣼⣳⣫⣾⣵⣗⡵⡱⡡⢣⢑⢕⢜⢕⡝⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⣴⣿⣾⣿⣿⣿⡿⡽⡑⢌⠪⡢⡣⣣⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⡟⡾⣿⢿⢿⢵⣽⣾⣼⣘⢸⢸⣞⡟⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠁⠇⠡⠩⡫⢿⣝⡻⡮⣒⢽⠋⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
—————————————————————————————————
EOT,
<<<EOT
⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⢿⢯⣛⣺⣯⣿⣿⣿⣿⣿⣿⣿⢱⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⡿⣿⣿⢡⣿⣉⣿⡿⠿⠿⠿⡿⠿⠻⣿⡇⠸⣻⠾⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⡿⠛⠉⠁⠹⡰⣹⣟⣧⣤⡤⠄⠄⠠⣡⣼⣷⠄⢉⢻⣿⣿⣿⣿⣿⣿⣿⣿
⣿⠟⠄⠄⠄⡀⢸⣾⣿⣯⣯⡃⠄⠄⠄⠄⠐⠙⣿⣧⡀⠩⣧⠙⣿⣿⣿⣿⣿⣿
⣿⠄⠄⠄⠈⠈⣾⣿⣿⣿⣿⣆⡀⠄⠄⠄⠄⠄⣸⣿⣿⣿⣧⠄⣼⣿⣿⣿⣿⣿
⣿⠇⠄⠄⠄⠄⠙⠛⠛⠿⠿⢿⣿⣶⣀⣶⣾⣿⣿⣿⣿⢾⣷⣇⣤⣿⣿⣿⣿⣿
⣿⣻⠄⠄⠄⠄⠄⠄⠄⠄⠠⠤⣤⣤⣌⠉⠉⠉⠁⢈⠁⠤⠛⣼⣿⣿⣿⣿⠿⠿
⠈⠈⠄⠄⠄⠄⣀⣴⡦⠴⠠⢠⣴⣶⣶⣶⣿⣿⡶⠛⠠⠄⠄⣿⣿⡿⠟⠁⠺⠿
⣀⣤⣤⣦⣤⣼⣿⡿⣣⣿⡷⣿⣿⣿⣿⣿⣿⡿⣿⡄⠄⠄⠄⢟⡁⠚⠦⠴⠤⣤
⠿⠉⠛⠟⣻⣿⠋⢁⣿⢿⣵⣭⣞⢿⣯⣽⣿⣿⣿⣿⡆⠄⠄⠄⠉⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠈⠁⠄⢯⣷⣿⣿⣯⡿⣽⣾⣿⣿⠿⢿⣿⣧⡄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⡴⢇⠉⢹⣀⣿⣿⣿⢿⡟⣿⣧⣼⡀⡩⠻⣦⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠰⠄⠣⣸⣶⠛⠛⠻⣿⡿⠿⢱⡟⠉⠉⠻⣿⡲⠃⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠒⠄⠈⠿⠄⠄⠄⡿⠃⠄⠘⠄⠄⢀⡠⠏⠄⠄⠄⠄⠄⠄⠄⠄⠄
EOT,
<<<EOT
summoning circle, hope this works!
🕯
🕯 🕯
🕯 🕯
🕯 graphictoria client 🕯
🕯 🕯
🕯 🕯
🕯
EOT,
<<<EOT
➖➖➖➖➖➖➖➖⬛⬛⬛➖➖➖➖➖➖➖➖➖
➖➖➖➖➖➖➖⬛⬛⬛⬛⬛➖➖➖➖➖➖➖➖
➖➖➖➖➖➖⬛⬛⬜⬜⬜⬛⬛➖➖➖➖➖➖➖
➖➖➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬛➖➖➖➖➖➖
➖➖➖➖➖⬛⬜⬜⬜⬜⬜⬜⬜⬛⬛➖➖➖➖➖
➖➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛➖➖➖➖➖
➖➖➖➖⬛⬜⬜⬛⬛⬛⬜⬜⬛⬛⬛➖➖➖➖➖
➖➖➖➖⬛⬛⬛⬛⬜⬛⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖➖➖⬛⬛⬛⬜⬜⬜⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖➖⬜⬛⬛⬛⬛⬛⬜⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖⬜⬜⬜⬜⬜⬜⬜⬛⬜⬛⬛⬛⬛⬛➖➖➖➖
➖➖⬛⬛⬛⬜⬜⬜⬛⬜⬜⬛⬛⬛⬛⬛⬛➖➖➖
➖➖⬜⬛⬛⬜⬜⬛⬜⬜⬛⬛⬛⬛⬛⬛⬛➖➖➖
➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬜⬛⬛➖➖➖
➖➖➖➖⬜⬜⬜⬛⬛⬛⬛⬛⬜⬜⬜⬛⬛➖➖➖
➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛➖➖
➖➖➖➖⬜⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛➖
➖➖➖⬛⬛⬜⬜⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛➖
➖➖⬛⬛⬛⬛⬜⬜⬜⬜⬜⬜⬛⬛⬛⬛⬛⬛⬛➖
EOT,
<<<EOT
⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏⠄⠄⠄⠄⠄⠄⠄⠄⠙⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⠄⠄⢀⣀⣀⣀⡀⠄⢀⣠⡔⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣰⢿⣿⣿⣿⣿⣿⣿⣷⡆⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⡏⣻⣟⣿⣿⡿⣟⣛⣿⡃⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣧⣿⣾⣿⣷⣿⣷⣿⣿⣿⣷⣽⣹⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⡟⣟⣿⣿⠺⣟⣻⣿⣿⣿⡏⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⡝⠻⠵⠿⠿⢿⣿⣿⢳⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣧⠈⣛⣛⣿⣿⡿⣡⣞⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡧⠄⠙⠛⠛⢁⣴⣿⣿⣷⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⡿⠟⠉⠄⠄⢠⠄⣀⣠⣾⣿⣿⡿⠟⠁⠄⠈⠛⢿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⡟⠉⠄⠄⢀⠠⠐⠒⠐⠾⠿⢟⠋⠁⠄⢀⣀⠠⠐⠄⠂⠈⠻⢿⣿⣿
⣿⣿⣿⠋⠁⠄⢀⡈⠄⠄⠄⠄⠄⠄⠄⠄⠁⠒⠉⠄⢠⣶⠄⠄⠄⠄⠄⠈⠫⢿
⣿⣿⡟⠄⢔⠆⡀⠄⠈⢀⠄⠄⠄⠄⠄⠄⠄⢄⡀⠄⠈⡐⢠⠒⠄⠄⠄⠄⢀⣂
⣿⣿⠁⡀⠄⠄⢇⠄⠄⢈⠆⠄⠄⢀⠔⠉⠁⠉⠉⠣⣖⠉⡂⡔⠂⠄⢀⠔⠁⠄
⣿⡿⠄⠄⠄⠄⢰⠹⣗⣺⠤⠄⠰⡎⠄⠄⠄⠄⠄⠄⠘⢯⡶⢟⡠⠰⠄⠄⠄⠄
EOT,
<<<EOT
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢀⣶⣿⣿⣿⣿⣿⣿⣶⣆⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣸⣿⣿⠉⠉⠉⠄⠉⢹⣿⣦⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢿⣿⣿⣁⠄⠄⠤⠤⡀⠻⣿⠃⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠘⣿⣿⣿⡗⠖⡶⢾⣶⠊⡏⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢻⣿⣿⣅⣈⠂⠐⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠘⢿⣾⣇⣂⣠⠄⠄⠄⠁⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢘⣿⣗⠒⠄⢨⠶⢁⣄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠨⣿⣿⡿⠋⠁⣴⣿⣿⣷⣦⣄⡀⠄⠄⠄⠄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⠄⠄⢀⣠⣄⣶⣎⢱⢄⢀⣾⣿⣿⣿⣿⣿⣿⣿⣶⣦⣤⣄⠄⠄⠄⠄
⠄⠄⠄⠄⠄⠄⠄⢠⣾⣿⣿⡞⢝⡟⠃⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣇⠄⠄⠄
⠄⠄⠄⠄⠆⢄⠄⢛⡫⠝⢿⡥⠟⡃⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣼⣭⣻⣿⣿⡀⠄⠄
⠄⠄⠄⣴⣆⠄⢋⠄⠐⣡⣿⣆⣴⣼⣿⣿⣿⣿⣿⣿⣿⣿⠏⢈⣿⣿⣿⣿⣿⣿⣷⡄⠄
⠄⠄⣼⣿⣷⠄⠉⠒⣪⣹⣟⣹⣿⣿⣿⣿⣿⣟⣿⣿⣿⡇⢀⣸⣿⣿⣿⢟⣽⣿⣿⣇⠄
EOT,
<<<EOT
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣶⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⠿⠟⠛⠻⣿⠆⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣆⣀⣀⠀⣿⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⠻⣿⣿⣿⠅⠛⠋⠈⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠘⢼⣿⣿⣿⣃⠠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣟⡿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣛⣛⣫⡄⠀⢸⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣠⣴⣾⡆⠸⣿⣿⣿⡷⠂⠨⣿⣿⣿⣿⣶⣦⣤⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣤⣾⣿⣿⣿⣿⡇⢀⣿⡿⠋⠁⢀⡶⠪⣉⢸⣿⣿⣿⣿⣿⣇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣿⣿⣿⣿⣿⣿⣿⣿⡏⢸⣿⣷⣿⣿⣷⣦⡙⣿⣿⣿⣿⣿⡏⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⣿⣿⣿⣿⣿⣿⣿⣿⣇⢸⣿⣿⣿⣿⣿⣷⣦⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃⠀⠀⠀⠀⠀⠀⠀⠀⠀
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢹⣿⣵⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣯⡁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀
EOT,
<<<EOT
⣿⣿⣿⣿⣿⣿⡿⠛⠋⠉⠄⠄⠄⠄⠄⠄⠄⠄⠄⠈⠉⠛⠿⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⡿⠋⠁⠄⠄⢠⣴⣶⣿⣿⣶⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠈⠿⣿⣿⣿⣿
⣿⣿⡟⠁⠄⠄⠄⠄⣿⣿⣿⣿⣿⣿⣇⡀⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢹⣿⣿⣿
⣿⣿⣧⠄⠄⠄⠄⢰⣿⣿⣿⣿⣿⣿⣿⡆⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⣸⣿⣿⣿
⣿⣿⣿⣧⡀⠄⠄⢸⣿⣿⣿⣿⣿⣿⣿⣷⣆⠄⠄⠄⠄⠄⠄⠄⠄⣰⣿⣿⣿⣿
⣿⣿⣿⣿⡿⣦⣀⣾⣿⣟⣉⠉⠙⢛⡏⠁⠄⠄⠄⠄⠄⠄⠄⠄⠚⢿⣿⣿⣿⣿
⣿⣿⣿⣿⣯⣗⣻⣿⣯⣥⣦⠄⣀⣾⡇⠄⠄⠂⠄⠄⠄⠄⠄⠄⠄⣼⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡇⠄⠄⠂⠄⠄⠄⠄⠄⠄⠄⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣟⣻⠋⠄⠄⠄⠄⠄⠄⠄⢀⠄⣸⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡁⡀⠄⠄⠄⠄⠄⠄⢸⣾⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣥⣾⣷⠶⠆⠄⠄⠄⢀⠄⠄⠄⠸⣿⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣶⣄⡀⠄⠄⠄⠄⠄⢀⠄⠸⣿⣿⣿⣿⣿⣿
⣿⣿⣿⣿⣿⣿⠟⠚⣿⣿⡻⠿⠿⠛⠙⠁⠄⠄⠄⠄⠠⠂⠄⠄⠘⠿⣿⣿⣿⣿
⠿⠛⠉⠁⠁⠄⠄⠄⣻⣿⣿⣧⣠⣀⠄⠄⠄⠄⡀⠂⠄⠄⠄⠄⠄⠄⠈⠉⠿⢿
⠄⠄⠄⠄⠄⠄⠄⠄⠄⠘⠿⣿⡿⠃⢀⡠⠄⠃⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
EOT,
<<<EOT
⠀⠀⠀⠀⣠⣦⣤⣀
⠀⠀⠀⠀⢡⣤⣿⣿
⠀⠀⠀⠀⠠⠜⢾⡟
⠀⠀⠀⠀⠀⠹⠿⠃⠄
⠀⠀⠈⠀⠉⠉⠑⠀⠀⠠⢈⣆
⠀⠀⣄⠀⠀⠀⠀⠀⢶⣷⠃⢵
⠐⠰⣷⠀⠀⠀⠀⢀⢟⣽⣆⠀⢃
⠰⣾⣶⣤⡼⢳⣦⣤⣴⣾⣿⣿⠞
⠀⠈⠉⠉⠛⠛⠉⠉⠉⠙⠁
⠀⠀⡐⠘⣿⣿⣯⠿⠛⣿⡄
⠀⠀⠁⢀⣄⣄⣠⡥⠔⣻⡇
⠀⠀⠀⠘⣛⣿⣟⣖⢭⣿⡇
⠀⠀⢀⣿⣿⣿⣿⣷⣿⣽⡇
⠀⠀⢸⣿⣿⣿⡇⣿⣿⣿⣇
⠀⠀⠀⢹⣿⣿⡀⠸⣿⣿⡏
⠀⠀⠀⢸⣿⣿⠇⠀⣿⣿⣿
⠀⠀⠀⠈⣿⣿⠀⠀⢸⣿⡿
⠀⠀⠀⠀⣿⣿⠀⠀⢀⣿⡇
⠀⣠⣴⣿⡿⠟⠀⠀⢸⣿⣷
⠀⠉⠉⠁⠀⠀⠀⠀⢸⣿⣿⠁
⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈
EOT,
<<<EOT
this is nsg
🤠
  🍺🍺🍺
🍺🍺🍺🍺🍺🍺
👇🏽  🍺🍺 👇🏽
  🍺 🍺
  🍺 🍺
  👢 👢
say hi to nsg
EOT,
<<<EOT
If you're wondering why all all of these random responses keep showing up, that is the magic of computer programming. A bored programmer(that's me!) decided they wanted to grab a bunch of ascii images off the internet and modify them to fit the theme of this site instead of doing code. Basically doing sweet F.A. on the job.
This is why the client took 2 years... THIS IS WHY. (graphictoria sunday btw)
Anyways, I applaud you for wasting probably minutes of your life to find this message, maybe skipped over it a few times while spamming CTRL + R, but still reached it eventually.
If this is your first time going to "api.gtoria.net", well; hm... Oh, I know! Erase everything you've seen here from your mind, and move on to doing something more productive. There's nothing at all to see on this here "api.gtoria.net" index page. Nothing at all!
EOT
];
// TODO: XlXi: Add some checks here, such as pinging api.gtoria.net, checking commonly used API functions, etc...
return response($apiTxts[array_rand($apiTxts)])
->header('Content-Type', 'text/plain'); ->header('Content-Type', 'text/plain');
} }
} }

View File

@ -49,7 +49,7 @@ class CommentsController extends Controller
// TODO: XlXi: user profile link // TODO: XlXi: user profile link
$poster = [ $poster = [
'name' => $comment->user->username, 'name' => $comment->user->username,
'thumbnail' => 'https://www.gtoria.local/images/testing/headshot.png', 'thumbnail' => 'https://www.virtubrick.local/images/testing/headshot.png',
'url' => $comment->user->getProfileUrl() 'url' => $comment->user->getProfileUrl()
]; ];

View File

@ -41,7 +41,7 @@ class FeedController extends Controller
$poster = [ $poster = [
'type' => 'User', 'type' => 'User',
'name' => $user->username, 'name' => $user->username,
'thumbnail' => 'https://www.gtoria.local/images/testing/headshot.png', 'thumbnail' => 'https://www.virtubrick.local/images/testing/headshot.png',
'url' => $user->getProfileUrl() 'url' => $user->getProfileUrl()
]; ];
} }

View File

@ -0,0 +1,67 @@
<?php
namespace App\Http\Controllers\Api;
use Carbon\Carbon;
use Symfony\Component\HttpFoundation\Cookie;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\Models\DynamicWebConfiguration;
use App\Helpers\ValidationHelper;
use App\Http\Controllers\Controller;
class MaintenanceController extends Controller
{
public function bypass(Request $request)
{
$validator = Validator::make($request->all(), [
'password' => ['required'],
'buttons' => ['required']
]);
if($validator->fails())
return ValidationHelper::generateValidatorError($validator);
$valid = $validator->valid();
$password = $valid['password'];
$buttons = $valid['buttons'];
$mtconf = json_decode(DynamicWebConfiguration::whereName('MaintenancePassword')->first()->value);
if(file_exists(storage_path('framework/down')) && $password == $mtconf->password)
{
$btns = array_slice($buttons, -count($mtconf->combination));
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
if(isset($data['secret']) && $btns === $mtconf->combination)
{
$trustedHosts = explode(',', env('TRUSTED_HOSTS'));
$origin = join('.', array_slice(explode('.', explode('//', $request->headers->get('origin'))[1]), -2));
$passCheck = false;
foreach($trustedHosts as &$host)
{
if(str_ends_with($origin, $host))
$passCheck = true;
}
$expiresAt = Carbon::now()->addHours(24);
$bypassCookie = new Cookie('vb_constraint', base64_encode(json_encode([
'expires_at' => $expiresAt->getTimestamp(),
'mac' => hash_hmac('SHA256', $expiresAt->getTimestamp(), $data['secret']),
])), $expiresAt);
$bypassCookie = $bypassCookie->withSameSite('none');
if($passCheck)
$bypassCookie = $bypassCookie->withDomain('.' . $origin);
return response('')
->withCookie($bypassCookie);
}
}
$validator->errors()->add('password', 'Bad Request.');
return ValidationHelper::generateValidatorError($validator);
}
}

View File

@ -6,6 +6,8 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Models\DynamicWebConfiguration; use App\Models\DynamicWebConfiguration;
use App\Models\User;
use App\Models\UserIp;
class AdminController extends Controller class AdminController extends Controller
{ {
@ -20,11 +22,60 @@ class AdminController extends Controller
} }
// Moderator+ // Moderator+
// GET admin.dashboard
function dashboard() function dashboard()
{ {
return view('web.admin.dashboard'); return view('web.admin.dashboard');
} }
// GET admin.usersearch
function userSearch()
{
return view('web.admin.usersearch');
}
// POST admin.usersearch
function userSearchQuery(Request $request)
{
if($request->has('userid-button'))
{
$request->validate([
'userid-search' => ['required', 'int']
]);
return view('web.admin.usersearch')->with('users', User::where('id', $request->get('userid-search'))->get());
}
if($request->has('username-button'))
{
$request->validate([
'username-search' => ['required', 'string']
]);
return view('web.admin.usersearch')->with('users', User::where('username', 'like', '%' . $request->get('username-search') . '%')->get());
}
if($request->has('ipaddress-button'))
{
$request->validate([
'ipaddress-search' => ['required', 'ip']
]);
$result = UserIp::where('ipAddress', $request->get('ipaddress-search'))
->join('users', 'users.id', '=', 'user_ips.userId')
->orderBy('users.id', 'desc');
return view('web.admin.usersearch')->with('users', $result->get())->with('isIpSearch', true);
}
return view('web.admin.usersearch')->with('error', 'Input validation failed.');
}
// GET admin.autoupload
function autoUpload()
{
return view('web.admin.autoupload');
}
// Admin+ // Admin+
function metricsVisualization() function metricsVisualization()
{ {

View File

@ -0,0 +1,16 @@
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class MaintenanceController extends Controller
{
public function index()
{
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
return view('web.maintenance', ['hideLogin' => !isset($data['secret'])]);
}
}

View File

@ -19,7 +19,7 @@ class TestController extends Controller
// mrgrey = https://www.roblox.com/asset/?id=1785197 // mrgrey = https://www.roblox.com/asset/?id=1785197
$test = new SoapService('Thumbnail'); $test = new SoapService('Thumbnail');
$result = $test->OpenJob(GridHelper::JobTemplate('test', 10, 0, 0, 'test render', 'place', ['http://www.roblox.com/asset/?id=444204653', 'PNG', 1920, 1080, 'https://www.gtoria.local/', 169618721])); $result = $test->OpenJob(GridHelper::JobTemplate('test', 10, 0, 0, 'test render', 'place', ['http://www.roblox.com/asset/?id=444204653', 'PNG', 1920, 1080, 'https://www.virtubrick.local/', 169618721]));
return response(base64_decode($result->OpenJobExResult->LuaValue[0]->value)) return response(base64_decode($result->OpenJobExResult->LuaValue[0]->value))
->header('Content-Type', 'image/png'); ->header('Content-Type', 'image/png');

View File

@ -0,0 +1,14 @@
<?php
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
class TestSiteController extends Controller
{
public function info()
{
return view('web.testing.info');
}
}

View File

@ -23,7 +23,6 @@ class Kernel extends HttpKernel
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class, \Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class, \App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
@ -39,6 +38,8 @@ class Kernel extends HttpKernel
'csrf', 'csrf',
\Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Routing\Middleware\SubstituteBindings::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
// XlXi: Yeah no, the double session protector was stupid. // XlXi: Yeah no, the double session protector was stupid.
//\App\Http\Middleware\DoubleSessionProtector::class, // Prevents DDoS attacks. //\App\Http\Middleware\DoubleSessionProtector::class, // Prevents DDoS attacks.
\App\Http\Middleware\DailyReward::class, \App\Http\Middleware\DailyReward::class,
@ -46,6 +47,8 @@ class Kernel extends HttpKernel
], ],
'api' => [ 'api' => [
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, // \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class, \Illuminate\Routing\Middleware\SubstituteBindings::class,
], ],

View File

@ -7,6 +7,8 @@ use Closure;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use App\Models\UserIp;
class LastSeenMiddleware class LastSeenMiddleware
{ {
/** /**
@ -23,6 +25,8 @@ class LastSeenMiddleware
$user->last_seen = Carbon::now(); $user->last_seen = Carbon::now();
$user->timestamps = false; $user->timestamps = false;
$user->save(); $user->save();
$user->saveIp($request->ip());
} }
return $next($request); return $next($request);

View File

@ -2,16 +2,48 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance as Middleware; use App\Helpers\MaintenanceHelper;
class PreventRequestsDuringMaintenance extends Middleware use Closure;
use Illuminate\Support\Facades\Route;
use Illuminate\Http\Request;
class PreventRequestsDuringMaintenance
{ {
/** public function handle(Request $request, Closure $next)
* The URIs that should be reachable while maintenance mode is enabled. {
* if(MaintenanceHelper::isDown($request))
* @var array<int, string> {
*/ if(str_starts_with($request->route()->getName(), 'maintenance.'))
protected $except = [ return $next($request);
//
]; if(in_array('api', $request->route()->middleware()))
{
if($request->route()->getName() == 'content') // cdn.virtubrick.net
return $next($request);
return response(['errors' => [['code' => 503, 'message' => 'ServiceUnavailable']]], 503)
->header('Cache-Control', 'private')
->header('Content-Type', 'application/json; charset=utf-8');
}
// Not an API route.
if($request->route()->uri() != 'maintenance')
return redirect('/maintenance?ReturnUrl=' . urlencode(url()->full()));
}
else
{
if(str_starts_with($request->route()->getName(), 'maintenance.'))
{
$returnUrl = $request->input('ReturnUrl');
if(!$returnUrl)
$returnUrl = '/';
return redirect($returnUrl);
}
}
return $next($request);
}
} }

View File

@ -55,15 +55,15 @@ class AppDeployment implements ShouldQueue
switch($this->deployment->app) switch($this->deployment->app)
{ {
case 'client': case 'client':
$appArchive = 'Graphictoria.zip'; $appArchive = 'VirtuBrick.zip';
$appName = 'GraphictoriaPlayer.exe'; $appName = 'VirtuBrickPlayer.exe';
$bootstrapperName = 'GraphictoriaPlayerLauncher.exe'; $bootstrapperName = 'VirtuBrickPlayerLauncher.exe';
$bootstrapperVersionName = 'BootstrapperVersion.txt'; $bootstrapperVersionName = 'BootstrapperVersion.txt';
break; break;
case 'studio': case 'studio':
$appArchive = 'GraphictoriaStudio.zip'; $appArchive = 'VirtuBrickStudio.zip';
$appName = 'GraphictoriaStudio.exe'; $appName = 'VirtuBrickStudio.exe';
$bootstrapperName = 'GraphictoriaStudioLauncherBeta.exe'; $bootstrapperName = 'VirtuBrickStudioLauncherBeta.exe';
$bootstrapperVersionName = 'BootstrapperQTStudioVersion.txt'; $bootstrapperVersionName = 'BootstrapperQTStudioVersion.txt';
break; break;
} }

View File

@ -2,6 +2,7 @@
namespace App\Jobs; namespace App\Jobs;
use claviska\SimpleImage;
use Illuminate\Bus\Queueable; use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -83,10 +84,10 @@ class ArbiterRender implements ShouldQueue
{ {
// TODO: XlXi: User avatar/closeup render support. // TODO: XlXi: User avatar/closeup render support.
$arguments = [ $arguments = [
url(sprintf('/asset?id=%d', $this->assetId)), // TODO: XlXi: Move url() to route() once the route actually exists. route('client.asset', ['id' => $this->assetId]),
($this->is3D ? 'OBJ' : 'PNG'), ($this->is3D ? 'OBJ' : 'PNG'),
840, // Width 420*4, // Width // XlXi: These get scaled down by 4.
840, // Height 420*4, // Height // XlXi: These get scaled down by 4.
url('/') . '/' url('/') . '/'
]; ];
switch($this->type) { switch($this->type) {
@ -177,7 +178,13 @@ class ArbiterRender implements ShouldQueue
$this->tracker->targetObj->set3DHash(CdnHelper::SaveContent(json_encode($result), 'text/plain')); $this->tracker->targetObj->set3DHash(CdnHelper::SaveContent(json_encode($result), 'text/plain'));
} else { } else {
$this->tracker->targetObj->set2DHash(CdnHelper::SaveContentB64($result, 'image/png')); $image = new SimpleImage();
$image = $image
->fromString(base64_decode($result))
->resize($arguments[2]/4, $arguments[3]/4)
->toString();
$this->tracker->targetObj->set2DHash(CdnHelper::SaveContentB64(base64_encode($image), 'image/png'));
} }
$this->tracker->delete(); $this->tracker->delete();

View File

@ -48,6 +48,7 @@ class User extends Authenticatable implements MustVerifyEmail
protected $casts = [ protected $casts = [
'email_verified_at' => 'datetime', 'email_verified_at' => 'datetime',
'next_reward' => 'datetime', 'next_reward' => 'datetime',
'created_at' => 'datetime',
'last_seen' => 'datetime', 'last_seen' => 'datetime',
]; ];
@ -91,6 +92,17 @@ class User extends Authenticatable implements MustVerifyEmail
return $this->created_at->isoFormat('ll'); return $this->created_at->isoFormat('ll');
} }
public function getCensoredEmail()
{
$email = $this->email;
$bits = explode('@', $email);
$name = implode('@', array_slice($bits, 0, count($bits) - 1));
$length = floor(strlen($name) / 2);
return substr($name, 0, $length) . str_repeat('*', $length) . "@" . end($bits);
}
// XlXi: TODO: Replace this with detailed presence // XlXi: TODO: Replace this with detailed presence
// like what game the user is in or // like what game the user is in or
// what place they're editing. // what place they're editing.
@ -99,6 +111,27 @@ class User extends Authenticatable implements MustVerifyEmail
return ($this->last_seen >= Carbon::now()->subMinutes(2)); return ($this->last_seen >= Carbon::now()->subMinutes(2));
} }
public function getRolesets()
{
return UserRoleset::where('User_id', $this->id);
}
public function saveIp($ip)
{
$ipExists = UserIp::where('userId', $this->id)
->where('ipAddress', $ip)
->exists();
if(!$ipExists)
{
return UserIp::create([
'userId' => $this->id,
'ipAddress' => $ip
]);
}
return false;
}
public function _hasRolesetInternal($roleName) public function _hasRolesetInternal($roleName)
{ {
$roleset = Roleset::where('Name', $roleName)->first(); $roleset = Roleset::where('Name', $roleName)->first();

26
web/app/Models/UserIp.php Normal file
View File

@ -0,0 +1,26 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class UserIp extends Model
{
use HasFactory;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'userId',
'ipAddress'
];
public function user()
{
return $this->belongsTo(User::class, 'userId');
}
}

View File

@ -128,7 +128,7 @@ class Asset extends Model
$thumbnail = Http::get(route('thumbnails.v1.asset', ['id' => $renderId, 'type' => '2d'])); $thumbnail = Http::get(route('thumbnails.v1.asset', ['id' => $renderId, 'type' => '2d']));
if($thumbnail->json('status') == 'loading') if($thumbnail->json('status') == 'loading')
return ($this->assetTypeId == 9 ? 'https://gtoria.local/images/busy/game.png' : 'https://gtoria.local/images/busy/asset.png'); return ($this->assetTypeId == 9 ? 'https://virtubrick.local/images/busy/game.png' : 'https://virtubrick.local/images/busy/asset.png');
return $thumbnail->json('data'); return $thumbnail->json('data');
} }

View File

@ -44,7 +44,7 @@ class ResetPasswordNotification extends Notification
*/ */
public function toMail($notifiable) public function toMail($notifiable)
{ {
$title = 'Graphictoria Password Reset'; $title = config('app.name') . ' Password Reset';
return (new MailMessage) return (new MailMessage)
->subject($title) ->subject($title)

View File

@ -37,6 +37,14 @@ class AppServiceProvider extends ServiceProvider
return get_class($validator) != UriValidator::class; return get_class($validator) != UriValidator::class;
}); });
Blade::directive('nonav', function() {
return '<?php $noNav=true; ?>';
});
Blade::directive('nofooter', function() {
return '<?php $noFooter=true; ?>';
});
Blade::directive('owner', function() { Blade::directive('owner', function() {
return '<?php if(Auth::check() && Auth::user()->hasRoleset(\'Owner\')): ?>'; return '<?php if(Auth::check() && Auth::user()->hasRoleset(\'Owner\')): ?>';
}); });

View File

@ -32,7 +32,7 @@ class RouteServiceProvider extends ServiceProvider
$this->routes(function () { $this->routes(function () {
// //
// Domain: gtoria.net // Domain: virtubrick.net
// //
Route::domain(DomainHelper::TopLevelDomain()) Route::domain(DomainHelper::TopLevelDomain())
->middleware('web') ->middleware('web')
@ -40,7 +40,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/web.php')); ->group(base_path('routes/web.php'));
// //
// Domain: www.gtoria.net // Domain: www.virtubrick.net
// //
Route::domain('www.' . DomainHelper::TopLevelDomain()) Route::domain('www.' . DomainHelper::TopLevelDomain())
->middleware('web') ->middleware('web')
@ -48,7 +48,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/web.php')); ->group(base_path('routes/web.php'));
// //
// Domain: www.gtoria.net // Domain: www.virtubrick.net
// //
Route::domain('blog.' . DomainHelper::TopLevelDomain()) Route::domain('blog.' . DomainHelper::TopLevelDomain())
->middleware('web') ->middleware('web')
@ -57,7 +57,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/blog.php')); ->group(base_path('routes/blog.php'));
// //
// Domain: api.gtoria.net // Domain: api.virtubrick.net
// //
Route::domain('api.' . DomainHelper::TopLevelDomain()) Route::domain('api.' . DomainHelper::TopLevelDomain())
->middleware('api') ->middleware('api')
@ -65,7 +65,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/api.php')); ->group(base_path('routes/api.php'));
// //
// Domain: cdn.gtoria.net // Domain: cdn.virtubrick.net
// //
Route::domain('cdn.' . DomainHelper::TopLevelDomain()) Route::domain('cdn.' . DomainHelper::TopLevelDomain())
->middleware('api') ->middleware('api')
@ -73,7 +73,7 @@ class RouteServiceProvider extends ServiceProvider
->group(base_path('routes/cdn.php')); ->group(base_path('routes/cdn.php'));
// //
// Domain: setup.gtoria.net // Domain: setup.virtubrick.net
// //
Route::domain('setup.' . DomainHelper::TopLevelDomain()) Route::domain('setup.' . DomainHelper::TopLevelDomain())
->middleware('api') ->middleware('api')

View File

@ -50,8 +50,8 @@ class AppDeploymentFilenameRule implements Rule
{ {
array_push($files, ...[ array_push($files, ...[
'playerpdb.zip', 'playerpdb.zip',
'graphictoria.zip', 'virtubrick.zip',
'graphictoriaplayerlauncher.exe' 'virtubrickplayerlauncher.exe'
]); ]);
} }
elseif($this->appType == 'studio') elseif($this->appType == 'studio')
@ -61,8 +61,8 @@ class AppDeploymentFilenameRule implements Rule
'imageformats.zip', 'imageformats.zip',
'content-scripts.zip', 'content-scripts.zip',
'studiopdb.zip', 'studiopdb.zip',
'graphictoriastudio.zip', 'virtubrickstudio.zip',
'graphictoriastudiolauncherbeta.exe' 'virtubrickstudiolauncherbeta.exe'
]); ]);
} }

View File

@ -0,0 +1,28 @@
<?php
namespace App\View\Components\Admin;
use Illuminate\View\Component;
class UserSearchInput extends Component
{
/**
* Create a new component instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.admin.user-search-input');
}
}

View File

@ -0,0 +1,28 @@
<?php
namespace App\View\Components;
use Illuminate\View\Component;
class UserCircle extends Component
{
/**
* Create a new component instance.
*
* @return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* @return \Illuminate\Contracts\View\View|\Closure|string
*/
public function render()
{
return view('components.user-circle');
}
}

View File

@ -6,6 +6,7 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.0.2", "php": "^8.0.2",
"claviska/simpleimage": "^3.7",
"elhebert/laravel-sri": "^3.1", "elhebert/laravel-sri": "^3.1",
"guzzlehttp/guzzle": "^7.2", "guzzlehttp/guzzle": "^7.2",
"laravel/framework": "^9.2", "laravel/framework": "^9.2",

109
web/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "01ebc87de69ddff55214f2b48dae78c1", "content-hash": "add8af8f80cfe2dbb0306929490c1386",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@ -66,6 +66,55 @@
], ],
"time": "2021-08-15T20:50:18+00:00" "time": "2021-08-15T20:50:18+00:00"
}, },
{
"name": "claviska/simpleimage",
"version": "3.7.2",
"source": {
"type": "git",
"url": "https://github.com/claviska/SimpleImage.git",
"reference": "82dbef988e356baa5d73993a1351bcb6c0959269"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/claviska/SimpleImage/zipball/82dbef988e356baa5d73993a1351bcb6c0959269",
"reference": "82dbef988e356baa5d73993a1351bcb6c0959269",
"shasum": ""
},
"require": {
"ext-gd": "*",
"league/color-extractor": "0.3.*",
"php": ">=5.6.0"
},
"type": "library",
"autoload": {
"psr-0": {
"claviska": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Cory LaViska",
"homepage": "http://www.abeautifulsite.net/",
"role": "Developer"
}
],
"description": "A PHP class that makes working with images as simple as possible.",
"support": {
"issues": "https://github.com/claviska/SimpleImage/issues",
"source": "https://github.com/claviska/SimpleImage/tree/3.7.2"
},
"funding": [
{
"url": "https://github.com/claviska",
"type": "github"
}
],
"time": "2022-12-12T14:31:53+00:00"
},
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
"version": "v3.0.1", "version": "v3.0.1",
@ -1324,6 +1373,64 @@
}, },
"time": "2022-03-23T12:38:24+00:00" "time": "2022-03-23T12:38:24+00:00"
}, },
{
"name": "league/color-extractor",
"version": "0.3.2",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/color-extractor.git",
"reference": "837086ec60f50c84c611c613963e4ad2e2aec806"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/color-extractor/zipball/837086ec60f50c84c611c613963e4ad2e2aec806",
"reference": "837086ec60f50c84c611c613963e4ad2e2aec806",
"shasum": ""
},
"require": {
"ext-gd": "*",
"php": ">=5.4.0"
},
"replace": {
"matthecat/colorextractor": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "~2",
"phpunit/phpunit": "~5"
},
"type": "library",
"autoload": {
"psr-4": {
"": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mathieu Lechat",
"email": "math.lechat@gmail.com",
"homepage": "http://matthecat.com",
"role": "Developer"
}
],
"description": "Extract colors from an image as a human would do.",
"homepage": "https://github.com/thephpleague/color-extractor",
"keywords": [
"color",
"extract",
"human",
"image",
"palette"
],
"support": {
"issues": "https://github.com/thephpleague/color-extractor/issues",
"source": "https://github.com/thephpleague/color-extractor/tree/master"
},
"time": "2016-12-15T09:30:02+00:00"
},
{ {
"name": "league/commonmark", "name": "league/commonmark",
"version": "2.3.0", "version": "2.3.0",

View File

@ -15,7 +15,7 @@ return [
| |
*/ */
'name' => env('APP_NAME', 'Graphictoria'), 'name' => env('APP_NAME', 'VirtuBrick'),
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
@ -54,7 +54,7 @@ return [
| |
*/ */
'url' => env('APP_URL', 'http://gtoria.net'), 'url' => env('APP_URL', 'http://virtubrick.net'),
'asset_url' => env('ASSET_URL'), 'asset_url' => env('ASSET_URL'),
@ -213,4 +213,15 @@ return [
// 'ExampleClass' => App\Example\ExampleClass::class, // 'ExampleClass' => App\Example\ExampleClass::class,
])->toArray(), ])->toArray(),
/*
|--------------------------------------------------------------------------
| Testing Environment Mode
|--------------------------------------------------------------------------
|
| When test environment mode is enabled, the site will display a
| banner explaining that it's not the real site.
|
*/
'testenv' => (bool) env('IS_TEST_ENVIRONMENT', true),
]; ];

View File

@ -4,7 +4,7 @@ return [
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Graphictoria Arbiter Configuration | VirtuBrick Arbiter Configuration
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| |
| This file holds various IP configurations for the games relay/thumbnail | This file holds various IP configurations for the games relay/thumbnail

View File

@ -19,7 +19,7 @@ return [
'allowed_methods' => ['*'], 'allowed_methods' => ['*'],
'allowed_origins' => ['*.gtoria.net','*.gtoria.local'], 'allowed_origins' => ['*.virtubrick.net','*.virtubrick.local'],
'allowed_origins_patterns' => [], 'allowed_origins_patterns' => [],

View File

@ -128,7 +128,7 @@ return [
'cookie' => env( 'cookie' => env(
'SESSION_COOKIE', 'SESSION_COOKIE',
'GTSession' 'VBSession'
), ),
/* /*

View File

@ -18,6 +18,7 @@ return new class extends Migration
$table->string('ticket'); $table->string('ticket');
$table->unsignedBigInteger('userId'); $table->unsignedBigInteger('userId');
$table->boolean('used')->default(false); $table->boolean('used')->default(false);
$table->boolean('maintenanceBypass')->default(false);
$table->timestamps(); $table->timestamps();
}); });
} }

View File

@ -18,7 +18,7 @@ return new class extends Migration
$table->string('version'); $table->string('version');
$table->string('app'); $table->string('app');
$table->string('type'); $table->string('type');
$table->int('step')->default(0); $table->integer('step')->default(0);
$table->string('error')->nullable(); $table->string('error')->nullable();
$table->timestamps(); $table->timestamps();
}); });

View File

@ -0,0 +1,35 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('user_ips', function (Blueprint $table) {
$table->id();
$table->string('ipAddress');
$table->unsignedBigInteger('userId');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('user_ips');
}
};

View File

@ -10,7 +10,7 @@ services:
environment: environment:
MYSQL_ROOT_PASSWORD: 'test' MYSQL_ROOT_PASSWORD: 'test'
volumes: volumes:
- database-data:/graphictoria - database-data:/virtubrick
volumes: volumes:
database-data: database-data:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -114,7 +113,7 @@ class Comments extends Component {
{ {
this.state.error != '' this.state.error != ''
? ?
<div className="alert alert-danger graphictoria-alert graphictoria-error-popup m-2 mb-0">{ this.state.error }</div> <div className="alert alert-danger virtubrick-alert virtubrick-error-popup m-2 mb-0">{ this.state.error }</div>
: :
null null
} }
@ -140,7 +139,7 @@ class Comments extends Component {
<div className="d-flex p-2" onMouseEnter={ () => this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }> <div className="d-flex p-2" onMouseEnter={ () => this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }>
<div className="me-2"> <div className="me-2">
<a href={ poster.url }> <a href={ poster.url }>
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border graphictora-feed-user-circle" /> <img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border virtubrick-feed-user-circle" />
</a> </a>
</div> </div>
<div className="flex-fill"> <div className="flex-fill">

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -175,7 +174,7 @@ class RevertDeploymentCard extends Component {
<DeploymentCard name={ this.props.name } index={ this.props.index } removeDeployment={ this.props.removeDeployment }> <DeploymentCard name={ this.props.name } index={ this.props.index } removeDeployment={ this.props.removeDeployment }>
<h5 className="mb-0">Revert Deployment</h5> <h5 className="mb-0">Revert Deployment</h5>
<p className="text-muted">Select a previous deployment below to roll back the { this.props.index } version.</p> <p className="text-muted">Select a previous deployment below to roll back the { this.props.index } version.</p>
<select className="form-select mt-2" id="gt-revert-deployment" disabled={ this.state.loading }> <select className="form-select mt-2" id="vb-revert-deployment" disabled={ this.state.loading }>
<option selected>{ this.state.loading ? 'Loading...' : 'None Selected' }</option> <option selected>{ this.state.loading ? 'Loading...' : 'None Selected' }</option>
{ {
this.state.deployments.map((deployment, index) => ( this.state.deployments.map((deployment, index) => (
@ -232,8 +231,8 @@ class PushDeploymentCard extends Component {
case 'client': case 'client':
this.neededFiles = this.neededFiles.concat([ this.neededFiles = this.neededFiles.concat([
'PlayerPdb.zip', 'PlayerPdb.zip',
'Graphictoria.zip', 'VirtuBrick.zip',
'GraphictoriaPlayerLauncher.exe' 'VirtuBrickPlayerLauncher.exe'
]); ]);
break; break;
case 'studio': case 'studio':
@ -242,8 +241,8 @@ class PushDeploymentCard extends Component {
'imageformats.zip', 'imageformats.zip',
'content-scripts.zip', 'content-scripts.zip',
'StudioPdb.zip', 'StudioPdb.zip',
'GraphictoriaStudio.zip', 'VirtuBrickStudio.zip',
'GraphictoriaStudioLauncherBeta.exe' 'VirtuBrickStudioLauncherBeta.exe'
]); ]);
break; break;
} }
@ -377,7 +376,7 @@ class PushDeploymentCard extends Component {
} }
return ( return (
<div className="graphictoria-item-card graphictoria-game-card"> <div className="virtubrick-item-card virtubrick-game-card">
<div className="card m-2" data-bs-toggle="tooltip" data-bs-placement="top" title={ file.name }> <div className="card m-2" data-bs-toggle="tooltip" data-bs-placement="top" title={ file.name }>
<div className="bg-light d-flex p-3"> <div className="bg-light d-flex p-3">
<i className={classNames(fileIconClasses)}></i> <i className={classNames(fileIconClasses)}></i>
@ -424,13 +423,13 @@ class PushDeploymentCard extends Component {
<h5 className="mb-0 mt-3">Optional Configuration</h5> <h5 className="mb-0 mt-3">Optional Configuration</h5>
<p className="text-muted mb-3">Only change if you've updated the security settings on the client/rcc. Shutting down game servers will delay deployment by 10 minutes.</p> <p className="text-muted mb-3">Only change if you've updated the security settings on the client/rcc. Shutting down game servers will delay deployment by 10 minutes.</p>
<div className="form-check form-switch"> <div className="form-check form-switch">
<input className="form-check-input" type="checkbox" role="switch" id="gt-shut-down-servers" /> <input className="form-check-input" type="checkbox" role="switch" id="vb-shut-down-servers" />
<label className="form-check-label" htmlFor="gt-shut-down-servers">Shut down game servers.</label> <label className="form-check-label" htmlFor="vb-shut-down-servers">Shut down game servers.</label>
</div> </div>
<label htmlFor="gt-rcc-security-key" className="form-label mt-2">Update RCC Security Key</label> <label htmlFor="vb-rcc-security-key" className="form-label mt-2">Update RCC Security Key</label>
<input type="text" id="gt-rcc-security-key" className="form-control" placeholder="New RCC Security Key" onChange={ changeEvent => this.setOptions('rccAccessKey', changeEvent.target.value) } /> <input type="text" id="vb-rcc-security-key" className="form-control" placeholder="New RCC Security Key" onChange={ changeEvent => this.setOptions('rccAccessKey', changeEvent.target.value) } />
<label htmlFor="gt-rcc-security-key" className="form-label mt-2">Update Version Compatibility Salt</label> <label htmlFor="vb-rcc-security-key" className="form-label mt-2">Update Version Compatibility Salt</label>
<input type="text" id="gt-rcc-security-key" className="form-control" placeholder="New Version Compatibility Salt" onChange={ changeEvent => this.setOptions('versionCompatiblityFuzzyKey', changeEvent.target.value) } /> <input type="text" id="vb-rcc-security-key" className="form-control" placeholder="New Version Compatibility Salt" onChange={ changeEvent => this.setOptions('versionCompatiblityFuzzyKey', changeEvent.target.value) } />
</> </>
: :
null null
@ -592,10 +591,10 @@ class Deployer extends Component {
<h5>Deployment Options</h5> <h5>Deployment Options</h5>
<div className="d-block"> <div className="d-block">
<div className="btn-group mb-1"> <div className="btn-group mb-1">
<input type="radio" className="btn-check" name="gt-deployment-type" id="gt-deployment-deploy" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'deploy') } checked={ this.state.deployType == 'deploy' } /> <input type="radio" className="btn-check" name="vb-deployment-type" id="vb-deployment-deploy" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'deploy') } checked={ this.state.deployType == 'deploy' } />
<label className="btn btn-sm btn-outline-primary" htmlFor="gt-deployment-deploy">Deploy</label> <label className="btn btn-sm btn-outline-primary" htmlFor="vb-deployment-deploy">Deploy</label>
<input type="radio" className="btn-check" name="gt-deployment-type" id="gt-deployment-revert" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'revert') } checked={ this.state.deployType == 'revert' } /> <input type="radio" className="btn-check" name="vb-deployment-type" id="vb-deployment-revert" autoComplete="off" onChange={ (e)=>this.trySetDeployType(e, 'revert') } checked={ this.state.deployType == 'revert' } />
<label className="btn btn-sm btn-outline-primary" htmlFor="gt-deployment-revert">Revert</label> <label className="btn btn-sm btn-outline-primary" htmlFor="vb-deployment-revert">Revert</label>
</div> </div>
<br /> <br />
<button className="btn btn-sm btn-success" onClick={ ()=>this.createDeployment('client') } disabled={ this.deploymentExists('client') }>Deploy Client</button> <button className="btn btn-sm btn-success" onClick={ ()=>this.createDeployment('client') } disabled={ this.deploymentExists('client') }>Deploy Client</button>
@ -604,7 +603,7 @@ class Deployer extends Component {
<hr /> <hr />
{ {
this.state.showTypeSwitchError ? this.state.showTypeSwitchError ?
<div className="alert alert-danger graphictoria-alert graphictoria-error-popup">Remove your { this.state.deployType == 'deploy' ? 'deployments' : 'reversions' } to change the uploader type.</div> <div className="alert alert-danger virtubrick-alert virtubrick-error-popup">Remove your { this.state.deployType == 'deploy' ? 'deployments' : 'reversions' } to change the uploader type.</div>
: :
null null
} }

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -104,7 +103,7 @@ class Feed extends Component {
{ {
this.state.error != '' this.state.error != ''
? ?
<div className="alert alert-danger graphictoria-alert graphictoria-error-popup m-2 mb-0">{ this.state.error }</div> <div className="alert alert-danger virtubrick-alert virtubrick-error-popup m-2 mb-0">{ this.state.error }</div>
: :
null null
} }
@ -126,7 +125,7 @@ class Feed extends Component {
<div className="me-2"> <div className="me-2">
<a href={ poster.url }> <a href={ poster.url }>
{ poster.type == 'User' ? { poster.type == 'User' ?
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border graphictora-feed-user-circle" /> : <img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border virtubrick-feed-user-circle" /> :
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="img-fluid" /> <img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="img-fluid" />
} }
</a> </a>

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -34,7 +33,7 @@ class GameItemCard extends Component {
render() { render() {
return ( return (
<a <a
className="graphictoria-item-card graphictoria-game-card" className="virtubrick-item-card virtubrick-game-card"
href={ this.props.item.Url } href={ this.props.item.Url }
onMouseEnter={() => this.setState({hovered: true})} onMouseEnter={() => this.setState({hovered: true})}
onMouseLeave={() => this.setState({hovered: false})} onMouseLeave={() => this.setState({hovered: false})}
@ -47,7 +46,7 @@ class GameItemCard extends Component {
className='img-fluid' className='img-fluid'
/> />
<div className="p-2"> <div className="p-2">
<p>{ this.props.item.Name }</p> <p className="text-truncate">{ this.props.item.Name }</p>
<p className="text-muted small">{commaSeparate(this.props.item.Playing)} Playing</p> <p className="text-muted small">{commaSeparate(this.props.item.Playing)} Playing</p>
<div className="d-flex mt-1"> <div className="d-flex mt-1">
<i className={classNames({ <i className={classNames({
@ -58,7 +57,7 @@ class GameItemCard extends Component {
<div className={classNames({ <div className={classNames({
'my-auto': true, 'my-auto': true,
'mx-1': true, 'mx-1': true,
'graphictoria-vote-bar': true, 'virtubrick-vote-bar': true,
'rounded-1': true, 'rounded-1': true,
'border': true, 'border': true,
'border-light': true, 'border-light': true,
@ -85,7 +84,7 @@ class GameItemCard extends Component {
</span> </span>
{ {
this.state.hovered ? this.state.hovered ?
<span className="graphictoria-item-details"> <span className="virtubrick-item-details">
<div className="card px-2"> <div className="card px-2">
<hr className="m-0" /> <hr className="m-0" />
<p className="text-truncate my-1"> <p className="text-truncate my-1">
@ -157,7 +156,7 @@ class Games extends Component {
} }
{ {
!this.state.pageLoaded ? !this.state.pageLoaded ?
<div className="graphictoria-shop-overlay"> <div className="virtubrick-shop-overlay">
<Loader /> <Loader />
</div> </div>
: :
@ -181,7 +180,7 @@ class Games extends Component {
<li className="list-inline-item"> <li className="list-inline-item">
<button className="btn btn-secondary" disabled={(this.state.pageNumber <= 1) ? true : null}><i className="fa-solid fa-angle-left"></i></button> <button className="btn btn-secondary" disabled={(this.state.pageNumber <= 1) ? true : null}><i className="fa-solid fa-angle-left"></i></button>
</li> </li>
<li className="list-inline-item graphictoria-paginator"> <li className="list-inline-item virtubrick-paginator">
<span>Page&nbsp;</span> <span>Page&nbsp;</span>
<input type="text" value={ this.state.pageNumber || '' } className="form-control" disabled={this.state.pageLoaded ? null : true} /> <input type="text" value={ this.state.pageNumber || '' } className="form-control" disabled={this.state.pageLoaded ? null : true} />
<span>&nbsp;of { this.state.pageCount || '???' }</span> <span>&nbsp;of { this.state.pageCount || '???' }</span>

View File

@ -1,11 +1,10 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
const Loader = () => { const Loader = () => {
return ( return (
<div className="gtoria-loader"><div></div><div></div><div></div><div></div></div> <div className="vbrick-loader"><div></div><div></div><div></div><div></div></div>
); );
}; };

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -15,7 +14,7 @@ import SearchBar from './SearchBar';
axios.defaults.withCredentials = true; axios.defaults.withCredentials = true;
const searchBarId = 'graphictoria-nav-searchbar'; const searchBarId = 'virtubrick-nav-searchbar';
$(document).ready(function() { $(document).ready(function() {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]')); var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -14,7 +13,7 @@ import Loader from './Loader';
axios.defaults.withCredentials = true; axios.defaults.withCredentials = true;
const playerProtocol = 'graphictoria-player'; const playerProtocol = 'virtubrick-player';
class PlaceLoadingModal extends Component { class PlaceLoadingModal extends Component {
constructor(props) { constructor(props) {
@ -70,14 +69,14 @@ class PlaceLoadingModal extends Component {
{ {
this.state.showDownloadScreen ? this.state.showDownloadScreen ?
<> <>
<h5>Download Graphictoria</h5> <h5>Download VirtuBrick</h5>
<p>Download Graphictoria to get access to thousands of community-driven games.</p> <p>Download VirtuBrick to get access to thousands of community-driven games.</p>
<a href={ buildGenericApiUrl('setup', 'GraphictoriaPlayerLauncher.exe') } target="_blank" className="btn btn-success mt-3">Download</a> <a href={ buildGenericApiUrl('setup', 'VirtuBrickPlayerLauncher.exe') } target="_blank" className="btn btn-success mt-3">Download</a>
</> </>
: :
<> <>
<Loader /> <Loader />
<p>Starting Graphictoria</p> <p>Starting VirtuBrick</p>
</> </>
} }
</div> </div>
@ -118,7 +117,7 @@ class PlaceLoadingErrorModal extends Component {
<div className="modal-content text-center"> <div className="modal-content text-center">
<div className="modal-body d-flex flex-column pb-4"> <div className="modal-body d-flex flex-column pb-4">
<button type="button" className="ms-auto btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" className="ms-auto btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<h5>An error occurred while starting Graphictoria.</h5> <h5>An error occurred while starting VirtuBrick.</h5>
<p>Error Detail: { this.props.message }</p> <p>Error Detail: { this.props.message }</p>
</div> </div>
</div> </div>
@ -167,7 +166,7 @@ class PlaceButtons extends Component {
let protocol = playerProtocol; let protocol = playerProtocol;
let domainSplit = getCurrentDomain().split('.'); let domainSplit = getCurrentDomain().split('.');
if(getCurrentDomain() == 'gtoria.local') if(getCurrentDomain() == 'virtubrick.local')
{ {
protocol += '-dev'; protocol += '-dev';
} }
@ -187,7 +186,7 @@ class PlaceButtons extends Component {
.catch(function(error) { .catch(function(error) {
this.setModal(<PlaceLoadingErrorModal setModal={ this.setModal } message={ error.message } />); this.setModal(<PlaceLoadingErrorModal setModal={ this.setModal } message={ error.message } />);
//alert('Error while starting Graphictoria: ' + error.message); //alert('Error while starting VirtuBrick: ' + error.message);
}.bind(this)); }.bind(this));
} }

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -7,7 +6,7 @@ import { createRef, Component } from 'react';
import classNames from 'classnames/bind'; import classNames from 'classnames/bind';
const itemId = 'gt-item'; const itemId = 'vb-item';
class PurchaseConfirmationModal extends Component { class PurchaseConfirmationModal extends Component {
constructor(props) { constructor(props) {
@ -54,7 +53,7 @@ class PurchaseConfirmationModal extends Component {
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div className="modal-body d-flex flex-column"> <div className="modal-body d-flex flex-column">
<p>Would you like to purchase the { this.state.assetType } <strong>{ this.state.assetName }</strong> from { this.state.assetCreator } for <span className="graphictoria-tokens">{ this.state.assetPrice }</span>?</p> <p>Would you like to purchase the { this.state.assetType } <strong>{ this.state.assetName }</strong> from { this.state.assetCreator } for <span className="virtubrick-tokens">{ this.state.assetPrice }</span>?</p>
<img src="/images/testing/hat.png" width="240" height="240" alt={ this.state.assetName } className="mx-auto my-2 img-fluid" /> <img src="/images/testing/hat.png" width="240" height="240" alt={ this.state.assetName } className="mx-auto my-2 img-fluid" />
</div> </div>
<div className="modal-footer flex-column"> <div className="modal-footer flex-column">
@ -63,7 +62,7 @@ class PurchaseConfirmationModal extends Component {
&nbsp; &nbsp;
<button className="btn btn-secondary" data-bs-dismiss="modal">Cancel</button> <button className="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
</div> </div>
<p className="text-muted pt-1">You will have <span className="graphictoria-tokens">{ Math.max(0, (this.state.userTokens - this.state.assetPrice)) }</span> after this purchase.</p> <p className="text-muted pt-1">You will have <span className="virtubrick-tokens">{ Math.max(0, (this.state.userTokens - this.state.assetPrice)) }</span> after this purchase.</p>
</div> </div>
</div> </div>
</div> </div>
@ -114,7 +113,7 @@ class NotEnoughTokensModal extends Component {
<button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button> <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div className="modal-body"> <div className="modal-body">
<p>You need <span className="graphictoria-tokens">{ this.state.assetPrice - this.state.userTokens }</span> more to purchase this item.</p> <p>You need <span className="virtubrick-tokens">{ this.state.assetPrice - this.state.userTokens }</span> more to purchase this item.</p>
</div> </div>
<div className="modal-footer"> <div className="modal-footer">
<button className="btn btn-secondary" data-bs-dismiss="modal">Ok</button> <button className="btn btn-secondary" data-bs-dismiss="modal">Ok</button>

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -69,16 +68,16 @@ const SearchBar = () => {
return ( return (
<> <>
<input type="text" ref={inputRef} className="form-control d-lg-flex" placeholder="Search" aria-label="Search" aria-describedby="graphictoria-nav-search-button" onChange={ changeEvent => setSearchQuery(changeEvent.target.value) } value={ searchQuery }/> <input type="text" ref={inputRef} className="form-control d-lg-flex" placeholder="Search" aria-label="Search" aria-describedby="virtubrick-nav-search-button" onChange={ changeEvent => setSearchQuery(changeEvent.target.value) } value={ searchQuery }/>
{ {
searchQuery.length !== 0 ? searchQuery.length !== 0 ?
<div ref={dropdownRef} id="graphictoria-search-dropdown"> <div ref={dropdownRef} id="virtubrick-search-dropdown">
<ul className="dropdown-menu show" area-labelledby="graphictoria-search-dropdown"> <ul className="dropdown-menu show" area-labelledby="virtubrick-search-dropdown">
{ {
dropdownLinks.map(({ area, urlbase }, index) => dropdownLinks.map(({ area, urlbase }, index) =>
<li key={index}> <li key={index}>
<a className="dropdown-item py-2" onClick={ () => setSearchQuery('') } href={ urlbase + encodeURIComponent(searchQuery) }>Search <b className="text-truncate graphictoria-search-dropdown-truncate">{searchQuery}</b> in {area}</a> <a className="dropdown-item py-2" onClick={ () => setSearchQuery('') } href={ urlbase + encodeURIComponent(searchQuery) }>Search <b className="text-truncate virtubrick-search-dropdown-truncate">{searchQuery}</b> in {area}</a>
</li> </li>
) )
} }

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -176,14 +175,14 @@ class ShopCategories extends Component {
render() { render() {
return ( return (
<div className="graphictoria-shop-categories"> <div className="virtubrick-shop-categories">
<h5>Category</h5> <h5>Category</h5>
<ShopCategoryButton id="all" label="All Items" getCategoryAssetTypeByLabel={this.props.getCategoryAssetTypeByLabel} getCategoryAssetTypeIds={this.props.getCategoryAssetTypeIds} navigateCategory={this.props.navigateCategory} shopState={this.props.shopState} /> <ShopCategoryButton id="all" label="All Items" getCategoryAssetTypeByLabel={this.props.getCategoryAssetTypeByLabel} getCategoryAssetTypeIds={this.props.getCategoryAssetTypeIds} navigateCategory={this.props.navigateCategory} shopState={this.props.shopState} />
<ul className="list-unstyled ps-0"> <ul className="list-unstyled ps-0">
{ {
Object.keys(shopCategories).map((categoryName, index) => Object.keys(shopCategories).map((categoryName, index) =>
<li className="mb-1"> <li className="mb-1">
<a className="text-decoration-none fw-normal align-items-center graphictoria-list-dropdown" data-bs-toggle="collapse" data-bs-target={`#${makeCategoryId(categoryName, 'collapse')}`} aria-expanded={(index === 0 ? 'true' : 'false')} href="#">{ categoryName }</a> <a className="text-decoration-none fw-normal align-items-center virtubrick-list-dropdown" data-bs-toggle="collapse" data-bs-target={`#${makeCategoryId(categoryName, 'collapse')}`} aria-expanded={(index === 0 ? 'true' : 'false')} href="#">{ categoryName }</a>
<div className={classNames({'collapse': true, 'show': (index === 0)})} id={makeCategoryId(categoryName, 'collapse')}> <div className={classNames({'collapse': true, 'show': (index === 0)})} id={makeCategoryId(categoryName, 'collapse')}>
<ul className="btn-toggle-nav list-unstyled fw-normal small"> <ul className="btn-toggle-nav list-unstyled fw-normal small">
<li><ShopCategoryButton id={makeCategoryId(`all-${categoryName}`, 'type')} label={`All ${categoryName}`} categoryName={categoryName} getCategoryAssetTypeByLabel={this.props.getCategoryAssetTypeByLabel} getCategoryAssetTypeIds={this.props.getCategoryAssetTypeIds} navigateCategory={this.props.navigateCategory} shopState={this.props.shopState} /></li> <li><ShopCategoryButton id={makeCategoryId(`all-${categoryName}`, 'type')} label={`All ${categoryName}`} categoryName={categoryName} getCategoryAssetTypeByLabel={this.props.getCategoryAssetTypeByLabel} getCategoryAssetTypeIds={this.props.getCategoryAssetTypeIds} navigateCategory={this.props.navigateCategory} shopState={this.props.shopState} /></li>
@ -216,7 +215,7 @@ class ShopItemCard extends Component {
return ( return (
<a <a
className="graphictoria-item-card" className="virtubrick-item-card"
href={ item.Url } href={ item.Url }
onMouseEnter={() => this.setState({hovered: true})} onMouseEnter={() => this.setState({hovered: true})}
onMouseLeave={() => this.setState({hovered: false})} onMouseLeave={() => this.setState({hovered: false})}
@ -231,14 +230,14 @@ class ShopItemCard extends Component {
<div className="p-2"> <div className="p-2">
<p>{ item.Name }</p> <p>{ item.Name }</p>
{ item.OnSale ? { item.OnSale ?
<p className="graphictoria-tokens text-truncate">{commaSeparate(item.Price)}</p> <p className="virtubrick-tokens text-truncate">{commaSeparate(item.Price)}</p>
: <p className="text-muted">Offsale</p> : <p className="text-muted">Offsale</p>
} }
</div> </div>
</span> </span>
{ {
this.state.hovered ? this.state.hovered ?
<span className="graphictoria-item-details"> <span className="virtubrick-item-details">
<div className="card px-2"> <div className="card px-2">
<p className="text-truncate"> <p className="text-truncate">
<span className="text-muted">Creator: </span><a href={ item.Creator.Url } className="text-decoration-none fw-normal">{ item.Creator.Name }</a> <span className="text-muted">Creator: </span><a href={ item.Creator.Url } className="text-decoration-none fw-normal">{ item.Creator.Name }</a>
@ -364,7 +363,7 @@ class Shop extends Component {
} }
{ {
!this.state.pageLoaded ? !this.state.pageLoaded ?
<div className="graphictoria-shop-overlay"> <div className="virtubrick-shop-overlay">
<Loader /> <Loader />
</div> </div>
: :
@ -389,7 +388,7 @@ class Shop extends Component {
<li className="list-inline-item"> <li className="list-inline-item">
<button className="btn btn-secondary" disabled={(this.state.pageNumber <= 1) ? true : null}><i className="fa-solid fa-angle-left"></i></button> <button className="btn btn-secondary" disabled={(this.state.pageNumber <= 1) ? true : null}><i className="fa-solid fa-angle-left"></i></button>
</li> </li>
<li className="list-inline-item graphictoria-paginator"> <li className="list-inline-item virtubrick-paginator">
<span>Page&nbsp;</span> <span>Page&nbsp;</span>
<input type="text" value={ this.state.pageNumber || '' } className="form-control" disabled={this.state.pageLoaded ? null : true} /> <input type="text" value={ this.state.pageNumber || '' } className="form-control" disabled={this.state.pageLoaded ? null : true} />
<span>&nbsp;of { this.state.pageCount || '???' }</span> <span>&nbsp;of { this.state.pageCount || '???' }</span>

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -51,6 +50,7 @@ const Scene = ({json}) => {
camera.position.set(thumbnailCameraPosition.x, thumbnailCameraPosition.y, thumbnailCameraPosition.z); camera.position.set(thumbnailCameraPosition.x, thumbnailCameraPosition.y, thumbnailCameraPosition.z);
camera.lookAt(pointToLookat); camera.lookAt(pointToLookat);
camera.translateZ(0.5);
// lighting // lighting
// FIXME: XlXi: if you toggle 3d on and off it'll create these twice // FIXME: XlXi: if you toggle 3d on and off it'll create these twice
@ -119,7 +119,7 @@ class ThumbnailTool extends Component {
this.setState({ initialLoading: false }); this.setState({ initialLoading: false });
if(this.renderable3d && localStorage.getItem('gt-use-3d-thumbnails') === 'true') if(this.renderable3d && localStorage.getItem('vb-use-3d-thumbnails') === 'true')
this.toggle3D(); this.toggle3D();
} }
} }
@ -169,7 +169,7 @@ class ThumbnailTool extends Component {
let is3d = !this.state.is3d; let is3d = !this.state.is3d;
this.setState({ loading: true, is3d: is3d, seed3d: Math.random() }); this.setState({ loading: true, is3d: is3d, seed3d: Math.random() });
localStorage.setItem('gt-use-3d-thumbnails', is3d); localStorage.setItem('vb-use-3d-thumbnails', is3d);
if(is3d) { if(is3d) {
this.loadThumbnail(`thumbnails/v1/asset?id=${this.assetId}&type=3D`, true); this.loadThumbnail(`thumbnails/v1/asset?id=${this.assetId}&type=3D`, true);

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Deployer from '../components/Deployer'; import Deployer from '../components/Deployer';
const deployerId = 'gt-deployer'; const deployerId = 'vb-deployer';
$(document).ready(function() { $(document).ready(function() {
if (document.getElementById(deployerId)) { if (document.getElementById(deployerId)) {

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -7,8 +6,8 @@ import $ from 'jquery';
import * as Bootstrap from 'bootstrap'; import * as Bootstrap from 'bootstrap';
import React from 'react'; import React from 'react';
const navId = 'gt-blog-nav'; const navId = 'vb-blog-nav';
const hideClass = 'graphictoria-blognav-hide'; const hideClass = 'virtubrick-blognav-hide';
function scrollChanged() { function scrollChanged() {
const nav = document.getElementById(navId); const nav = document.getElementById(navId);

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Feed from '../components/Feed'; import Feed from '../components/Feed';
const feedId = 'gt-dash-feed'; const feedId = 'vb-dash-feed';
$(document).ready(function() { $(document).ready(function() {
if (document.getElementById(feedId)) { if (document.getElementById(feedId)) {

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Games from '../components/Games'; import Games from '../components/Games';
const gamesId = 'gt-games-main'; const gamesId = 'vb-games-main';
$(document).ready(function() { $(document).ready(function() {
if (document.getElementById(gamesId)) { if (document.getElementById(gamesId)) {

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -12,9 +11,9 @@ import Comments from '../components/Comments';
import PurchaseButton from '../components/PurchaseButton'; import PurchaseButton from '../components/PurchaseButton';
import ThumbnailTool from '../components/ThumbnailTool'; import ThumbnailTool from '../components/ThumbnailTool';
const purchaseId = 'gt-purchase-button'; const purchaseId = 'vb-purchase-button';
const commentsId = 'gt-comments'; const commentsId = 'vb-comments';
const thumbnailId = 'gt-thumbnail'; const thumbnailId = 'vb-thumbnail';
$(document).ready(function() { $(document).ready(function() {
if (document.getElementById(commentsId)) { if (document.getElementById(commentsId)) {

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -22,7 +21,7 @@ const randomEuler = () => [Math.random() * Math.PI, Math.random() * Math.PI, Mat
const randomData = Array.from({ length: 2000 }, (r = 200) => ({ random: Math.random(), position: randomVector(r), rotation: randomEuler() })); const randomData = Array.from({ length: 2000 }, (r = 200) => ({ random: Math.random(), position: randomVector(r), rotation: randomEuler() }));
function Scene() { function Scene() {
const { nodes, materials } = useGLTF('/models/graphictoriapart.glb'); const { nodes, materials } = useGLTF('/models/virtubrickpart.glb');
return ( return (
<> <>
@ -71,8 +70,8 @@ function Camera({ ...props }){
let ButtonHistory = [] let ButtonHistory = []
function attemptBypass() { function attemptBypass() {
axios.post(buildGenericApiUrl('apis', 'v1/maintenance/bypass'), { axios.post(buildGenericApiUrl('api', 'maintenance/v1/bypass'), {
'password': $('#gt_mt_buttons > input').val(), 'password': $('#vbrick_mt_buttons > input').val(),
'buttons': ButtonHistory.slice(-40) 'buttons': ButtonHistory.slice(-40)
}) })
.then((response) => { .then((response) => {
@ -87,11 +86,11 @@ $(document).ready(function() {
<Scene /> <Scene />
</Suspense> </Suspense>
</Canvas>), </Canvas>),
document.getElementsByClassName('gtoria-maintenance-background')[0] document.getElementsByClassName('vbrick-maintenance-background')[0]
); );
$('#gt_mt_buttons').on('click', 'button', function() { $('#vbrick_mt_buttons').on('click', 'button', function() {
let ButtonId = parseInt(this.getAttribute('name').substr(8)); //gt_mtbtnX let ButtonId = parseInt(this.getAttribute('name').substr(8)); //vb_mtbtnX
ButtonHistory.push(ButtonId); ButtonHistory.push(ButtonId);
attemptBypass(); attemptBypass();

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -12,9 +11,9 @@ import Comments from '../components/Comments';
import ThumbnailTool from '../components/ThumbnailTool'; import ThumbnailTool from '../components/ThumbnailTool';
import PlaceButtons from '../components/PlaceButtons'; import PlaceButtons from '../components/PlaceButtons';
const thumbnailId = 'gt-thumbnail'; const thumbnailId = 'vb-thumbnail';
const buttonsId = 'gt-place-buttons'; const buttonsId = 'vb-place-buttons';
const commentsId = 'gt-comments'; const commentsId = 'vb-comments';
$(document).ready(function() { $(document).ready(function() {
if (document.getElementById(thumbnailId)) { if (document.getElementById(thumbnailId)) {

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
@ -10,7 +9,7 @@ import { render } from 'react-dom';
import Shop from '../components/Shop'; import Shop from '../components/Shop';
const shopId = 'gt-shop-main'; const shopId = 'vb-shop-main';
$(document).ready(function() { $(document).ready(function() {
if (document.getElementById(shopId)) { if (document.getElementById(shopId)) {

View File

@ -1,11 +1,10 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */
import $ from 'jquery'; import $ from 'jquery';
const configId = 'gt-config-values'; const configId = 'vb-config-values';
$(document).ready(function() { $(document).ready(function() {
if (document.getElementById(configId)) { if (document.getElementById(configId)) {

View File

@ -1,5 +1,4 @@
/* /*
Graphictoria 5 (https://gtoria.net)
Copyright © XlXi 2022 Copyright © XlXi 2022
*/ */

View File

@ -0,0 +1,45 @@
// XlXi: Loads bootstrap without utilities/api.
// scss-docs-start import-stack
// Configuration
@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/mixins";
@import "~bootstrap/scss/utilities";
// Layout & components
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
@import "~bootstrap/scss/containers";
@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";
@import "~bootstrap/scss/transitions";
@import "~bootstrap/scss/dropdown";
@import "~bootstrap/scss/button-group";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
@import "~bootstrap/scss/card";
@import "~bootstrap/scss/accordion";
@import "~bootstrap/scss/breadcrumb";
@import "~bootstrap/scss/pagination";
@import "~bootstrap/scss/badge";
@import "~bootstrap/scss/alert";
@import "~bootstrap/scss/progress";
@import "~bootstrap/scss/list-group";
@import "~bootstrap/scss/close";
@import "~bootstrap/scss/toasts";
@import "~bootstrap/scss/modal";
@import "~bootstrap/scss/tooltip";
@import "~bootstrap/scss/popover";
@import "~bootstrap/scss/carousel";
@import "~bootstrap/scss/spinners";
@import "~bootstrap/scss/offcanvas";
@import "~bootstrap/scss/placeholders";
// Helpers
@import "~bootstrap/scss/helpers";
// scss-docs-end import-stack

View File

@ -1,5 +1,4 @@
// © XlXi 2021 // © XlXi 2021
// Graphictoria 5
@function tint-color($color, $percent){ @function tint-color($color, $percent){
@return mix(white, $color, $percent); @return mix(white, $color, $percent);
@ -12,7 +11,7 @@
// Lumen 5.0.1 // Lumen 5.0.1
// Bootswatch // Bootswatch
$theme: "graphictoria" !default; $theme: "virtubrick" !default;
// //
// Color system // Color system
@ -30,19 +29,20 @@ $gray-800: #333 !default;
$gray-900: #222 !default; $gray-900: #222 !default;
$black: #000 !default; $black: #000 !default;
$gtblue: #348aff !default; $gtblue: #348aff !default;
$blue: #158cba !default; $blue: #158cba !default;
$indigo: #6610f2 !default; $indigo: #6610f2 !default;
$purple: #6f42c1 !default; $purple: #6f42c1 !default;
$pink: #e83e8c !default; $pink: #e83e8c !default;
$red: #ff4136 !default; $red: #ff4136 !default;
$orange: #fd7e14 !default; $orange: #fd7e14 !default;
$yellow: #ff851b !default; $yellow: #ff851b !default;
$green: #28b62c !default; $realyellow: #ffde1b !default;
$teal: #20c997 !default; $green: #28b62c !default;
$cyan: #75caeb !default; $teal: #20c997 !default;
$cyan: #75caeb !default;
$graphictoria: $gtblue !default; $virtubrick: $gtblue !default;
$primary: $blue !default; $primary: $blue !default;
$secondary: $gray-200 !default; $secondary: $gray-200 !default;
$success: $green !default; $success: $green !default;

View File

@ -1,13 +1,10 @@
// © XlXi 2021 // © XlXi 2021
// Graphictoria 5
@use "sass:math"; @use "sass:math";
// Lumen 5.0.1 // Lumen 5.0.1
// Bootswatch // Bootswatch
@import "Variables";
@import "~bootstrap/scss/bootstrap";
@import "./scss/fontawesome.scss"; @import "./scss/fontawesome.scss";
@import "./scss/brands.scss"; @import "./scss/brands.scss";
@import "./scss/duotone.scss"; @import "./scss/duotone.scss";
@ -16,6 +13,14 @@
@import "./scss/solid.scss"; @import "./scss/solid.scss";
@import "./scss/thin.scss"; @import "./scss/thin.scss";
@import "Variables";
@import "Bootstrap";
// XlXi: Edit utilities API.
// Border is removed because of how stupidly it's handled by Bootstrap. It completely breaks our dark theme.
$utilities: map-remove($utilities, "border", "border-top", "border-end", "border-bottom", "border-start");
@import "~bootstrap/scss/utilities/api";
// Variables // Variables
$web-font-path: "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,300;0,400;0,700;1,400&display=swap" !default; $web-font-path: "https://fonts.googleapis.com/css2?family=Source+Sans+Pro:ital,wght@0,300;0,400;0,700;1,400&display=swap" !default;
@ -40,7 +45,7 @@ img.twemoji {
// Shop // Shop
.graphictoria-tokens { .virtubrick-tokens {
background: 0 1px/contain no-repeat url("/images/symbols/token.svg"); background: 0 1px/contain no-repeat url("/images/symbols/token.svg");
color: #e59800!important; color: #e59800!important;
font-weight: bold; font-weight: bold;
@ -72,22 +77,22 @@ img.twemoji {
} }
} }
.graphictoria-asset-thumbnail { .virtubrick-asset-thumbnail {
width: 420px; width: 420px;
height: 420px; height: 420px;
} }
.graphictoria-game-thumbnail { .virtubrick-game-thumbnail {
width: 640px; width: 640px;
height: 360px; height: 360px;
} }
.graphictoria-smaller-page { .virtubrick-smaller-page {
max-width: 1096px; max-width: 1096px;
margin: 0 auto 0 auto; margin: 0 auto 0 auto;
} }
.graphictoria-list-dropdown::after { .virtubrick-list-dropdown::after {
@include caret-down(); @include caret-down();
content: ""; content: "";
@ -96,7 +101,7 @@ img.twemoji {
vertical-align: 0.255em; vertical-align: 0.255em;
} }
.graphictoria-item-card { .virtubrick-item-card {
text-decoration: none!important; text-decoration: none!important;
font-weight: 400!important; font-weight: 400!important;
display: inline-block; display: inline-block;
@ -124,7 +129,7 @@ img.twemoji {
color: inherit!important; color: inherit!important;
} }
.graphictoria-item-details { .virtubrick-item-details {
position: relative; position: relative;
display: flex; display: flex;
@ -144,12 +149,12 @@ img.twemoji {
} }
} }
.graphictoria-item-card > span > img { .virtubrick-item-card > span > img {
background: url("/Images/Item-Image-Vignette.png"); background: url("/Images/Item-Image-Vignette.png");
background-size: cover; background-size: cover;
} }
.graphictoria-game-card { .virtubrick-game-card {
@media (max-width: 576px) { @media (max-width: 576px) {
width: math.div(100%, 2) width: math.div(100%, 2)
} }
@ -171,7 +176,7 @@ img.twemoji {
} }
} }
.graphictoria-shop-overlay { .virtubrick-shop-overlay {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -182,19 +187,19 @@ img.twemoji {
z-index: 10; z-index: 10;
} }
.graphictoria-shop-overlay > .gtoria-loader { .virtubrick-shop-overlay > .vbrick-loader {
margin: auto; margin: auto;
} }
.graphictoria-shop-categories { .virtubrick-shop-categories {
border: 0; border: 0;
@media (min-width: 768px) { @media (min-width: 768px) {
html.gtoria-light & { html.vbrick-light & {
border-right: 2px solid #dee2e6!important; border-right: 2px solid #dee2e6!important;
} }
html.gtoria-dark & { html.vbrick-dark & {
border-right: 2px solid #333!important; border-right: 2px solid #333!important;
} }
@ -206,19 +211,19 @@ img.twemoji {
// Maintenance // Maintenance
.gtoria-maintenance-background { .vbrick-maintenance-background {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
z-index: -9999; z-index: -9999;
} }
.gtoria-maintenance-form { .vbrick-maintenance-form {
html.gtoria-light & { html.vbrick-light & {
background: radial-gradient($gray-100 5%, transparent 65%); background: radial-gradient($gray-100 5%, transparent 65%);
} }
html.gtoria-dark & { html.vbrick-dark & {
background: radial-gradient(shade-color($gray-900, 30%) 5%, transparent 65%); background: radial-gradient(shade-color($gray-900, 30%) 5%, transparent 65%);
} }
@ -242,7 +247,7 @@ img.twemoji {
} }
.modal-content { .modal-content {
html.gtoria-dark & { html.vbrick-dark & {
background-color: #222 !important; background-color: #222 !important;
} }
} }
@ -257,11 +262,11 @@ img.twemoji {
// Loader // Loader
.gtoria-loader-center { .vbrick-loader-center {
margin: auto; margin: auto;
} }
.gtoria-loader { .vbrick-loader {
display: inline-block; display: inline-block;
position: relative; position: relative;
margin: auto auto 0 auto; margin: auto auto 0 auto;
@ -269,43 +274,43 @@ img.twemoji {
height: 80px; height: 80px;
} }
.gtoria-loader div { .vbrick-loader div {
position: absolute; position: absolute;
top: 33px; top: 33px;
width: 13px; width: 13px;
height: 13px; height: 13px;
border-radius: 50%; border-radius: 50%;
html.gtoria-light & { html.vbrick-light & {
background-color: $dark; background-color: $dark;
} }
html.gtoria-dark & { html.vbrick-dark & {
background-color: $light; background-color: $light;
} }
} }
.gtoria-loader div:nth-child(1) { .vbrick-loader div:nth-child(1) {
left: 8px; left: 8px;
animation: gtoria-ld-p1 0.5s infinite; animation: vbrick-ld-p1 0.5s infinite;
} }
.gtoria-loader div:nth-child(2) { .vbrick-loader div:nth-child(2) {
left: 8px; left: 8px;
animation: gtoria-ld-p2 0.5s infinite; animation: vbrick-ld-p2 0.5s infinite;
} }
.gtoria-loader div:nth-child(3) { .vbrick-loader div:nth-child(3) {
left: 32px; left: 32px;
animation: gtoria-ld-p2 0.5s infinite; animation: vbrick-ld-p2 0.5s infinite;
} }
.gtoria-loader div:nth-child(4) { .vbrick-loader div:nth-child(4) {
left: 56px; left: 56px;
animation: gtoria-ld-p3 0.5s infinite; animation: vbrick-ld-p3 0.5s infinite;
} }
@keyframes gtoria-ld-p1 { @keyframes vbrick-ld-p1 {
0% { 0% {
transform: scale(0); transform: scale(0);
} }
@ -314,7 +319,7 @@ img.twemoji {
} }
} }
@keyframes gtoria-ld-p3 { @keyframes vbrick-ld-p3 {
0% { 0% {
transform: scale(1); transform: scale(1);
} }
@ -323,7 +328,7 @@ img.twemoji {
} }
} }
@keyframes gtoria-ld-p2 { @keyframes vbrick-ld-p2 {
0% { 0% {
transform: translate(0, 0); transform: translate(0, 0);
} }
@ -334,31 +339,31 @@ img.twemoji {
// Background // Background
html, body, #gtoria-root { html, body, #vbrick-root {
height: 100%; height: 100%;
background: transparent; background: transparent;
color: inherit; color: inherit;
} }
html { html {
&.gtoria-light { &.vbrick-light {
background-color: $gray-100; background-color: $gray-100;
color: $gray-900; color: $gray-900;
} }
&.gtoria-dark { &.vbrick-dark {
background-color: shade-color($gray-900, 30%); background-color: shade-color($gray-900, 30%);
color: $gray-100; color: $gray-100;
} }
} }
#gtoria-root { #vbrick-root {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
} }
.graphictoria-home { .virtubrick-home {
background-image: url("/Images/Backgrounds/Home.png"); background-image: url("/Images/Backgrounds/Home.png");
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -367,7 +372,7 @@ html {
display: flex; display: flex;
} }
.graphictoria-home-about { .virtubrick-home-about {
background-image: url("/Images/Backgrounds/About.png"); background-image: url("/Images/Backgrounds/About.png");
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
@ -375,7 +380,7 @@ html {
min-height: 500px; min-height: 500px;
} }
.graphictoria-home-about-card { .virtubrick-home-about-card {
color: #fff; color: #fff;
background: #000000ad; background: #000000ad;
border-radius: 5px; border-radius: 5px;
@ -385,21 +390,21 @@ html {
border-width: 0 0 2px; border-width: 0 0 2px;
} }
.graphictoria-nojs { .virtubrick-nojs {
background-image: url("/Images/Backgrounds/NoJs.png"); background-image: url("/Images/Backgrounds/NoJs.png");
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
} }
.graphictoria-admin { .virtubrick-admin {
background-image: url("/Images/Backgrounds/stars.jpg"); background-image: url("/Images/Backgrounds/stars.jpg");
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center; background-position: center;
} }
.graphictoria-blog { .virtubrick-blog {
/* XlXi: I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS */ /* XlXi: I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS */
background-image: url("/Images/Backgrounds/Blog.png")!important; background-image: url("/Images/Backgrounds/Blog.png")!important;
background-size: cover!important; background-size: cover!important;
@ -411,27 +416,27 @@ html {
// Home Page // Home Page
.graphictoria-homepage-header { .virtubrick-homepage-header {
font-size: 4rem; font-size: 4rem;
font-weight: bold; font-weight: bold;
} }
.graphictoria-homepage-fine-print { .virtubrick-homepage-fine-print {
font-size: .6rem; font-size: .6rem;
opacity: 70%; opacity: 70%;
} }
.graphictoria-small-aligned-text { .virtubrick-small-aligned-text {
font-size: .6rem; font-size: .6rem;
vertical-align: middle; vertical-align: middle;
} }
.graphictoria-home-shadow { .virtubrick-home-shadow {
text-shadow: 0 0 4px $gray-700; text-shadow: 0 0 4px $gray-700;
} }
// Character // Character
.gt-charimg { .vb-charimg {
max-height: 300px; max-height: 300px;
max-width: 300px; max-width: 300px;
@media (max-width: 768px) { @media (max-width: 768px) {
@ -440,13 +445,13 @@ html {
} }
} }
.graphictora-user-circle { .virtubrick-user-circle {
border-radius: 50%; border-radius: 50%;
background: url("/Images/User-Image-Vignette.png"); background: url("/Images/User-Image-Vignette.png");
background-size: cover; background-size: cover;
} }
.graphictora-feed-user-circle { .virtubrick-feed-user-circle {
border-radius: 50%; border-radius: 50%;
background: url("/Images/User-Image-Vignette.png"); background: url("/Images/User-Image-Vignette.png");
background-size: cover; background-size: cover;
@ -457,11 +462,75 @@ html {
// Border // Border
.border { .border {
html.gtoria-dark & { html.vbrick-dark & {
border-color: $gray-700!important; border: 1px solid $gray-700;
} }
html.gtoria-light & { html.vbrick-light & {
border-color: $border-color!important; border: 1px solid $border-color;
}
&-top {
html.vbrick-dark & {
border-top: $gray-700;
}
html.vbrick-light & {
border-top: $border-color;
}
}
&-end {
html.vbrick-dark & {
border-right: $gray-700;
}
html.vbrick-light & {
border-right: $border-color;
}
}
&-bottom {
html.vbrick-dark & {
border-bottom: $gray-700;
}
html.vbrick-light & {
border-bottom: $border-color;
}
}
&-start {
html.vbrick-dark & {
border-left: $gray-700;
}
html.vbrick-light & {
border-left: $border-color;
}
}
&-top-0 {
border-top: 0!important;
}
&-end-0 {
border-end: 0!important;
}
&-bottom-0 {
border-bottom: 0!important;
}
&-start-0 {
border-start: 0!important;
}
&-vb-online-website {
border-color: #22acff!important;
}
&-vb-in-game {
border-color: #00d926!important;
}
&-vb-in-studio {
border-color: #ff8f00!important;
} }
} }
@ -477,11 +546,11 @@ html {
} }
} }
.bg-graphictoria { .bg-virtubrick {
background-color: $graphictoria; background-color: $virtubrick;
} }
.graphictoria-navbar { .virtubrick-navbar {
background-color: $white; background-color: $white;
border-color: shade-color($white, 10%); border-color: shade-color($white, 10%);
border-style: solid; border-style: solid;
@ -490,7 +559,7 @@ html {
padding-top: 4px; padding-top: 4px;
padding-bottom: 4px; padding-bottom: 4px;
html.gtoria-light & { html.vbrick-light & {
background-color: $white; background-color: $white;
border-color: shade-color($white, 10%); border-color: shade-color($white, 10%);
@ -543,7 +612,7 @@ html {
} }
} }
html.gtoria-dark & { html.vbrick-dark & {
background-color: $gray-900; background-color: $gray-900;
border-color: tint-color($gray-900, 10%); border-color: tint-color($gray-900, 10%);
@ -596,32 +665,32 @@ html {
} }
} }
.graphictoria-blognav { .virtubrick-blognav {
transition: background 100ms, border-color 100ms; transition: background 100ms, border-color 100ms;
transition-timing-function: ease-out; transition-timing-function: ease-out;
} }
.graphictoria-blognav-hide { .virtubrick-blognav-hide {
background: #ffffff00!important; background: #ffffff00!important;
border-color: #ffffff00!important; border-color: #ffffff00!important;
} }
.graphictoria-nav-margin { .virtubrick-nav-margin {
margin-top: 63px; margin-top: 63px;
} }
.graphictoria-nav-splitter { .virtubrick-nav-splitter {
margin-top: 16px; margin-top: 16px;
margin-bottom: 16px !important; margin-bottom: 16px !important;
} }
.graphictoria-user-dropdown::after { .virtubrick-user-dropdown::after {
position: absolute; position: absolute;
top: 50%; top: 50%;
right: 0; right: 0;
} }
.graphictoria-search, #graphictoria-search-dropdown { .virtubrick-search, #virtubrick-search-dropdown {
position: absolute; position: absolute;
@media (max-width: 992px) { @media (max-width: 992px) {
display: none; display: none;
@ -636,11 +705,11 @@ html {
} }
} }
.graphictoria-search { .virtubrick-search {
font-family: "FontAwesome", $font-family-sans-serif; font-family: "FontAwesome", $font-family-sans-serif;
} }
.graphictoria-search-dropdown-truncate { .virtubrick-search-dropdown-truncate {
@media (min-width: 992px) { @media (min-width: 992px) {
max-width: 5.375rem; max-width: 5.375rem;
} }
@ -651,21 +720,21 @@ html {
margin-bottom: -0.35rem; margin-bottom: -0.35rem;
} }
#graphictoria-search-dropdown > .dropdown-menu { #virtubrick-search-dropdown > .dropdown-menu {
width: 100%; width: 100%;
left: 0; left: 0;
} }
// Cards // Cards
.graphictoria-small-card { .virtubrick-small-card {
@media (min-width: 992px) { @media (min-width: 992px) {
max-width: 50%; max-width: 50%;
margin: auto; margin: auto;
} }
} }
.graphictoria-moderation-card { .virtubrick-moderation-card {
@media (min-width: 992px) { @media (min-width: 992px) {
max-width: 70%; max-width: 70%;
margin: auto; margin: auto;
@ -674,7 +743,7 @@ html {
.card { .card {
@include shadow(); @include shadow();
html.gtoria-dark & { html.vbrick-dark & {
background-color: #222; background-color: #222;
} }
} }
@ -686,7 +755,7 @@ html {
overflow-y: auto !important; overflow-y: auto !important;
} }
.graphictoria-center-vh { .virtubrick-center-vh {
margin-top: auto; margin-top: auto;
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
@ -731,7 +800,7 @@ html {
&-secondary { &-secondary {
border-color: shade-color($secondary, 10%); border-color: shade-color($secondary, 10%);
html.gtoria-dark & { html.vbrick-dark & {
color: $white; color: $white;
background-color: $dark; background-color: $dark;
border-color: shade-color($dark, 10%); border-color: shade-color($dark, 10%);
@ -787,11 +856,11 @@ html {
background: transparent; background: transparent;
border: 0; border: 0;
html.gtoria-light & { html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity)); color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
} }
html.gtoria-dark & { html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity)); color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
} }
@ -810,11 +879,11 @@ html {
background: transparent; background: transparent;
border: 0; border: 0;
html.gtoria-light & { html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity)); color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
} }
html.gtoria-dark & { html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity)); color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
} }
@ -833,11 +902,11 @@ html {
background: transparent; background: transparent;
border: 0; border: 0;
html.gtoria-light & { html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity)); color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
} }
html.gtoria-dark & { html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity)); color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
} }
@ -876,7 +945,7 @@ html {
} }
input { input {
html.gtoria-dark & { html.vbrick-dark & {
background-color: $gray-800; background-color: $gray-800;
color: $gray-100; color: $gray-100;
border-color: $gray-700; border-color: $gray-700;
@ -948,13 +1017,13 @@ input {
border-top-width: 1px; border-top-width: 1px;
@include box-shadow(none); @include box-shadow(none);
html.gtoria-dark & { html.vbrick-dark & {
color: $gray-100; color: $gray-100;
background-color: $gray-800; background-color: $gray-800;
border-color: $gray-700; border-color: $gray-700;
} }
html.gtoria-light & { html.vbrick-light & {
color: $gray-500; color: $gray-500;
background-color: $white; background-color: $white;
border-color: $gray-400; border-color: $gray-400;
@ -962,7 +1031,7 @@ input {
} }
.dropdown-item { .dropdown-item {
html.gtoria-dark & { html.vbrick-dark & {
color: $gray-100; color: $gray-100;
&:not(.disabled):hover { &:not(.disabled):hover {
@ -971,7 +1040,7 @@ input {
} }
} }
.graphictoria-nav-dropdown { .virtubrick-nav-dropdown {
margin-top: 11px !important; margin-top: 11px !important;
border-top: 0; border-top: 0;
border-radius: 0 0 0.25rem 0.25rem; border-radius: 0 0 0.25rem 0.25rem;
@ -1041,11 +1110,11 @@ input {
} }
} }
.graphictoria-paginator * { .virtubrick-paginator * {
display: inline-block; display: inline-block;
} }
.graphictoria-paginator > input { .virtubrick-paginator > input {
width: 35px; width: 35px;
text-align: center; text-align: center;
padding: 0; padding: 0;
@ -1099,6 +1168,11 @@ input {
border-color: shade-color($warning, 10%); border-color: shade-color($warning, 10%);
} }
&-yellow {
background-color: $realyellow;
border-color: shade-color($realyellow, 10%);
}
&-dark { &-dark {
background-color: $dark; background-color: $dark;
border-color: shade-color($dark, 10%); border-color: shade-color($dark, 10%);
@ -1125,7 +1199,7 @@ input {
} }
} }
.graphictoria-alert { .virtubrick-alert {
border-radius: 0; border-radius: 0;
text-align: center; text-align: center;
margin-bottom: 0; margin-bottom: 0;
@ -1133,7 +1207,7 @@ input {
padding-bottom: 0.35rem; padding-bottom: 0.35rem;
} }
.graphictoria-alert > .btn-close { .virtubrick-alert > .btn-close {
padding-top: 0.75rem; padding-top: 0.75rem;
padding-bottom: 0.75rem; padding-bottom: 0.75rem;
} }
@ -1222,10 +1296,10 @@ a.list-group-item {
// Footer // Footer
.footer { .footer {
html.gtoria-dark & { html.vbrick-dark & {
background-color: $gray-900 !important; background-color: $gray-900 !important;
} }
html.gtoria-light & { html.vbrick-light & {
background-color: $white !important; background-color: $white !important;
} }
} }
@ -1433,7 +1507,7 @@ p {
align-items: center !important; align-items: center !important;
} }
.graphictoria-error-popup { .virtubrick-error-popup {
margin-bottom: 10px; margin-bottom: 10px;
border-radius: 10px; border-radius: 10px;
@ -1447,12 +1521,12 @@ p {
} }
// Voting // Voting
.graphictoria-vote-bar { .virtubrick-vote-bar {
// border // border
html.gtoria-dark & { html.vbrick-dark & {
border-color: $gray-700; border-color: $gray-700;
} }
html.gtoria-light & { html.vbrick-light & {
border-color: $border-color; border-color: $border-color;
} }
@ -1471,3 +1545,44 @@ p {
position: relative; position: relative;
height: 10px; height: 10px;
} }
// Tables
table {
html.vbrick-light & {
color: rgba(var(--bs-black-rgb),var(--bs-text-opacity));
}
html.vbrick-dark & {
color: rgba(var(--bs-light-rgb),var(--bs-text-opacity));
}
}
.table>:not(:first-child) {
html.vbrick-dark & {
border-top: 1px solid $gray-700;
}
html.vbrick-light & {
border-top: 1px solid $border-color;
}
}
table > tbody > tr > th {
font-weight: normal;
}
.virtubrick-table {
margin-bottom: 0;
}
.virtubrick-table > tbody > tr:last-child > th {
border: unset;
}
.virtubrick-table > thead {
html.vbrick-dark & {
background-color: #ffffff0f;
}
html.vbrick-light & {
background-color: #0000000f;
}
}

View File

@ -5,7 +5,7 @@
]) ])
@if(Auth::check() && Auth::user()->hasRoleset($roleset)) @if(Auth::check() && Auth::user()->hasRoleset($roleset))
<div class="card gt-admin-card"> <div class="card vb-admin-card">
<div class="card-header bg-{{ $color }} text-light"> <div class="card-header bg-{{ $color }} text-light">
{{ $name }} {{ $name }}
</div> </div>

View File

@ -2,7 +2,7 @@
'name' 'name'
]) ])
<span class="gt-admin-navtitle">{{ $name }}</span> <span class="vb-admin-navtitle">{{ $name }}</span>
<ul class="gt-admin-nav nav flex-column"> <ul class="vb-admin-nav nav flex-column">
{{ $slot }} {{ $slot }}
</ul> </ul>

View File

@ -2,7 +2,7 @@
'stat' 'stat'
]) ])
<div class="my-auto rounded-1 bg-secondary border border-light right-0 me-1 position-relative graphictoria-admin-usagebar"> <div class="my-auto rounded-1 bg-secondary border border-light right-0 me-1 position-relative virtubrick-admin-usagebar">
@php @php
$usage_bar_color = 'bg-primary'; $usage_bar_color = 'bg-primary';
$usage_bar_usage = $stat * 100; $usage_bar_usage = $stat * 100;
@ -15,7 +15,7 @@
$usage_bar_color = 'bg-danger'; // Red $usage_bar_color = 'bg-danger'; // Red
@endphp @endphp
<div <div
class="{{ $usage_bar_color }} rounded-1 position-absolute graphictoria-admin-usagebar" class="{{ $usage_bar_color }} rounded-1 position-absolute virtubrick-admin-usagebar"
style="width:{{ $usage_bar_usage }}%!important;height:8px!important;" style="width:{{ $usage_bar_usage }}%!important;height:8px!important;"
></div> ></div>
</div> </div>

View File

@ -0,0 +1,15 @@
@props([
'id',
'definition'
])
<div class="col-6">
<label for="vb-{{ $id }}-search" class="form-label">{{ $definition }}</label>
<form method="POST" action="{{ route('admin.usersearch') }}" enctype="multipart/form-data">
@csrf
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="{{ $definition }} Here" aria-label="{{ $definition }} Here" name="{{ $id }}-search" id="vb-{{ $id }}-search" aria-describedby="vb-{{ $id }}-search-btn">
<button type="submit" class="btn btn-primary" type="button" name="{{ $id }}-button" id="vb-{{ $id }}-search-btn">Search</button>
</div>
</form>
</div>

View File

@ -1,5 +1,5 @@
@php @php
$classes = ['card', 'graphictoria-small-card', 'shadow-sm']; $classes = ['card', 'virtubrick-small-card', 'shadow-sm'];
if(isset($attributes['class'])) if(isset($attributes['class']))
$classes = array_merge($classes, explode(' ', $attributes['class'])); $classes = array_merge($classes, explode(' ', $attributes['class']));

View File

@ -1 +1 @@
<div class="gtoria-loader"><div></div><div></div><div></div><div></div></div> <div class="vbrick-loader"><div></div><div></div><div></div><div></div></div>

View File

@ -0,0 +1,35 @@
@props([
'user',
'statusIndicator',
'size'
])
@php
// 37x37 Default
$size = isset($size) ? $size : 37;
$showStatus = (!isset($statusIndicator) || $statusIndicator);
$classes = [
'img-fluid',
'border',
'me-1',
'virtubrick-user-circle'
];
if($showStatus)
{
// TODO: XlXi: Advanced user presence. (in games, in studio, etc)
if($user->isOnline())
$classes = array_merge($classes, ['border-vb-online-website', 'border-2']);
}
@endphp
<span class="d-flex align-items-center">
{{-- TODO: XlXi: User headshots --}}
<img
src="{{ asset('images/testing/headshot.png') }}"
@class($classes)
width="{{ $size }}"
height="{{ $size }}"
>
<p>{{ $user->username }}</p>
</span>

View File

@ -1,6 +1,6 @@
@extends('layouts.email') @extends('layouts.email')
@section('title', 'Graphictoria Password Reset') @section('title', config('app.name') . ' Password Reset')
@section('content') @section('content')
<h4>Hello, <b>{{ $user }}</b>!</h4> <h4>Hello, <b>{{ $user }}</b>!</h4>

View File

@ -3,10 +3,10 @@
@section('title', 'Bad Request') @section('title', 'Bad Request')
@section('content') @section('content')
<div class="container graphictoria-center-vh"> <div class="container virtubrick-center-vh">
<x-card title="BAD REQUEST"> <x-card title="BAD REQUEST">
<x-slot name="body"> <x-slot name="body">
There was a problem with your request. If you believe this is an error on our part, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>! There was a problem with your request. If you believe this is an error on our part, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
</x-slot> </x-slot>
<x-slot name="footer"> <x-slot name="footer">
<div class="mt-2"> <div class="mt-2">

View File

@ -3,11 +3,11 @@
@section('title', 'Unauthorized') @section('title', 'Unauthorized')
@section('content') @section('content')
<div class="container graphictoria-center-vh"> <div class="container virtubrick-center-vh">
<x-card title="UNAUTHORIZED"> <x-card title="UNAUTHORIZED">
<x-slot name="body"> <x-slot name="body">
You're missing the proper authentication to view this page. If you believe this is an error, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>!
</x-slot> </x-slot>
You're missing the proper authentication to view this page. If you believe this is an error, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
<x-slot name="footer"> <x-slot name="footer">
<div class="mt-2"> <div class="mt-2">
<a class="btn btn-primary px-4 me-2" href="{{ url('/') }}">Home</a> <a class="btn btn-primary px-4 me-2" href="{{ url('/') }}">Home</a>

View File

@ -3,10 +3,10 @@
@section('title', 'Forbidden') @section('title', 'Forbidden')
@section('content') @section('content')
<div class="container graphictoria-center-vh"> <div class="container virtubrick-center-vh">
<x-card title="FORBIDDEN"> <x-card title="FORBIDDEN">
<x-slot name="body"> <x-slot name="body">
You don't have permission to view this page. If you believe this is an error, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>! You don't have permission to view this page. If you believe this is an error, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
</x-slot> </x-slot>
<x-slot name="footer"> <x-slot name="footer">
<div class="mt-2"> <div class="mt-2">

View File

@ -7,10 +7,10 @@ $errorTitles = ['OH NOES!!!', 'BZZT', 'ERROR', 'UH OH.'];
@section('title', 'Not Found') @section('title', 'Not Found')
@section('content') @section('content')
<div class="container graphictoria-center-vh"> <div class="container virtubrick-center-vh">
<x-card title="{{ $errorTitles[array_rand($errorTitles)] }}"> <x-card title="{{ $errorTitles[array_rand($errorTitles)] }}">
<x-slot name="body"> <x-slot name="body">
We've looked far and wide and weren't able to find the page you were looking for. If you believe this is an error, contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>! We've looked far and wide and weren't able to find the page you were looking for. If you believe this is an error, contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>!
</x-slot> </x-slot>
<x-slot name="footer"> <x-slot name="footer">
<div class="mt-2"> <div class="mt-2">

View File

@ -3,10 +3,10 @@
@section('title', 'Internal Server Error') @section('title', 'Internal Server Error')
@section('content') @section('content')
<div class="container graphictoria-center-vh"> <div class="container virtubrick-center-vh">
<x-card title="INTERNAL SERVER ERROR"> <x-card title="INTERNAL SERVER ERROR">
<x-slot name="body"> <x-slot name="body">
Oops, we ran into an issue while trying to process your request, please try again later in a few minutes. If the issue persists after a few minutes, please contact us at <a href="mailto:support@gtoria.net" class="fw-bold text-decoration-none">support@gtoria.net</a>. Oops, we ran into an issue while trying to process your request, please try again later in a few minutes. If the issue persists after a few minutes, please contact us at <a href="mailto:support@virtubrick.net" class="fw-bold text-decoration-none">support@virtubrick.net</a>.
</x-slot> </x-slot>
<x-slot name="footer"> <x-slot name="footer">
<div class="mt-2"> <div class="mt-2">

View File

@ -3,7 +3,7 @@
@section('title', 'Not Implemented') @section('title', 'Not Implemented')
@section('content') @section('content')
<div class="container graphictoria-center-vh"> <div class="container virtubrick-center-vh">
<x-card title="NOT IMPLEMENTED"> <x-card title="NOT IMPLEMENTED">
<x-slot name="body"> <x-slot name="body">
todo todo

Some files were not shown because too many files have changed in this diff Show More