diff --git a/src/assets/img/404/404.svg b/src/assets/img/404/404.svg new file mode 100644 index 0000000000..aaad7f8396 --- /dev/null +++ b/src/assets/img/404/404.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/img/globalping/404.svg b/src/assets/img/globalping/404.svg new file mode 100644 index 0000000000..aaad7f8396 --- /dev/null +++ b/src/assets/img/globalping/404.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/src/assets/js/app-globalping.js b/src/assets/js/app-globalping.js index e425af75e5..b5e03cd362 100644 --- a/src/assets/js/app-globalping.js +++ b/src/assets/js/app-globalping.js @@ -11,6 +11,7 @@ const cGlobalpingIntegrations = require('../../views/pages/globalping/integratio const cGlobalpingAbout = require('../../views/pages/globalping/about-us.html'); const cGlobalpingSponsors = require('../../views/pages/globalping/sponsors.html'); const cGlobalpingCredits = require('../../views/pages/globalping/credits.html'); +const cGlobalpingError = require('../../views/pages/globalping/_404.html'); const { getGlobalpingUser } = require('./utils/http'); Ractive.DEBUG = location.hostname === 'localhost'; @@ -37,6 +38,7 @@ app.router.addRoute('/integrations', cGlobalpingIntegrations); app.router.addRoute('/about-us', cGlobalpingAbout); app.router.addRoute('/sponsors', cGlobalpingSponsors); app.router.addRoute('/credits', cGlobalpingCredits); +app.router.addRoute('/(.*)', cGlobalpingError); app.router.replaceQueryParam = function (name, newValue) { history.replaceState(history.state, null, location.href.replace(new RegExp(`${name}=[^&]+|$`), `${name}=${encodeURIComponent(newValue)}`)); diff --git a/src/assets/js/app.js b/src/assets/js/app.js index 373c8eb90b..90e3a1230d 100644 --- a/src/assets/js/app.js +++ b/src/assets/js/app.js @@ -28,6 +28,7 @@ const cEsmsh = require('../../views/pages/esmsh.html'); const cCustomCdnOss = require('../../views/pages/oss-cdn.html'); const cCustomCdnOssProject = require('../../views/pages/_oss-cdn-project.html'); const cDocumentation = require('../../views/pages/documentation.html'); +const cError = require('../../views/pages/_404.html'); Ractive.DEBUG = location.hostname === 'localhost'; @@ -82,6 +83,7 @@ app.router.addRoute('/esmsh', cEsmsh); app.router.addRoute('/oss-cdn', cCustomCdnOss); app.router.addRoute('/oss-cdn/:name', cCustomCdnOssProject); app.router.addRoute('/documentation', cDocumentation); +app.router.addRoute('/(.*)', cError); _.onDocumentReady(() => { let state = {}; diff --git a/src/assets/less/app-globalping.less b/src/assets/less/app-globalping.less index 0489a5f0c2..e4bc81eaed 100644 --- a/src/assets/less/app-globalping.less +++ b/src/assets/less/app-globalping.less @@ -27,3 +27,4 @@ @import "pages/globalping/about-us.less"; @import "pages/globalping/sponsors.less"; @import "pages/globalping/credits.less"; +@import "pages/globalping/404.less"; diff --git a/src/assets/less/app.less b/src/assets/less/app.less index 031a5babce..dbb62b5d82 100644 --- a/src/assets/less/app.less +++ b/src/assets/less/app.less @@ -64,6 +64,7 @@ @import "pages/gsap.less"; @import "pages/proxy.less"; @import "pages/proxy-project.less"; +@import "pages/404.less"; @import "pages/tools/purge.less"; // This should go after rawgit. diff --git a/src/assets/less/btn.less b/src/assets/less/btn.less index 2b593686e2..39601bff7f 100644 --- a/src/assets/less/btn.less +++ b/src/assets/less/btn.less @@ -221,3 +221,37 @@ color: #8228f6; } } + +.btn-404 { + display: inline-flex; + align-items: center; + justify-content: center; + font-size: 14px; + line-height: 20px; + color: #fff; + background: #d92a28; + border-radius: 6px; + padding: 10px 20px; + transition: color 200ms, background 200ms; + border: none; + user-select: none; + + &:hover { + background: #e13509; + } + + &:active { + background: #b02907; + } + + &:focus { + background: #f65128; + box-shadow: 0 0 0 1px #fff, 0 0 0 4px rgba(31, 150, 255, .48); + } + + &:active, &:hover, &:focus { + color: #fff; + outline: none; + text-decoration: none; + } +} diff --git a/src/assets/less/components/header.less b/src/assets/less/components/header.less index 50b0f5497a..c1ee63f689 100644 --- a/src/assets/less/components/header.less +++ b/src/assets/less/components/header.less @@ -21,6 +21,22 @@ } } + &.page-404-header { + position: absolute; + width: 100%; + background: transparent; + + .navbar { + background: transparent; + border: none; + box-shadow: none; + + ul.nav > li > a { + color: #fff; + } + } + } + &.header-with-globalping-bg, &.header-with-gp-translucent-bg { --link-highlight-color: @gp-green; @@ -65,7 +81,7 @@ } } - &.gp-about-us-header { + &.gp-about-us-header, &.gp-404-header { position: absolute; width: 100%; diff --git a/src/assets/less/pages/404.less b/src/assets/less/pages/404.less new file mode 100644 index 0000000000..256b214fcc --- /dev/null +++ b/src/assets/less/pages/404.less @@ -0,0 +1,61 @@ +.p-404 { + font-family: Lexend, sans-serif; + font-style: normal; + font-weight: 400; + -webkit-font-smoothing: antialiased; + width: 100%; + height: 1080px; + background: linear-gradient(180deg, #e64e3d 7.5%, #fff 100%); + + .page-404 { + display: flex; + width: 100%; + max-width: 1248px; + margin: 0 auto; + flex-direction: row; + align-items: center; + padding: 190px 24px 338px; + + &_text-block { + display: flex; + flex-direction: column; + row-gap: 24px; + width: 412px; + height: 228px; + + &_title { + font-size: 32px; + font-weight: 600; + line-height: 50px; + letter-spacing: .2; + color: #fff; + } + + &_descr { + font-size: 16px; + font-weight: 400; + line-height: 20px; + color: #fff; + } + + &_btn { + font-size: 14px; + font-weight: 400; + line-height: 20px; + width: 172px; + padding: 10px 20px; + } + } + + &_img-block { + width: 552px; + height: 552px; + mix-blend-mode: overlay;/* stylelint-disable */ + margin-left: auto; + + @media (max-width: @screen-sm-max) { + display: none; + } + } + } +} diff --git a/src/assets/less/pages/globalping/404.less b/src/assets/less/pages/globalping/404.less new file mode 100644 index 0000000000..66a0dd7a61 --- /dev/null +++ b/src/assets/less/pages/globalping/404.less @@ -0,0 +1,61 @@ +.p-globalping-404 { + font-family: Lexend, sans-serif; + font-style: normal; + font-weight: 400; + -webkit-font-smoothing: antialiased; + width: 100%; + height: 1080px; + background: linear-gradient(180deg, #00b88c 8%, #fff 100%); + + .gp-404 { + display: flex; + width: 100%; + max-width: 1248px; + margin: 0 auto; + flex-direction: row; + align-items: center; + padding: 190px 24px 338px; + + &_text-block { + display: flex; + flex-direction: column; + row-gap: 24px; + width: 412px; + height: 228px; + + &_title { + font-size: 32px; + font-weight: 600; + line-height: 50px; + letter-spacing: .2; + color: #fff; + } + + &_descr { + font-size: 16px; + font-weight: 400; + line-height: 20px; + color: #fff; + } + + &_btn { + font-size: 14px; + font-weight: 400; + line-height: 20px; + width: 172px; + padding: 10px 20px; + } + } + + &_img-block { + width: 552px; + height: 552px; + mix-blend-mode: overlay;/* stylelint-disable */ + margin-left: auto; + + @media (max-width: @screen-sm-max) { + display: none; + } + } + } +} diff --git a/src/index.js b/src/index.js index 848f81aca4..b1425c73f8 100644 --- a/src/index.js +++ b/src/index.js @@ -252,6 +252,7 @@ if (site === 'globalping') { koaElasticUtils.addRoutes(router, [ [ '/(.*)', '/(.*)' ], ], async (ctx) => { + let path = ctx.path.startsWith('/_') ? '/_404' : ctx.path; let root = site === 'globalping' ? 'globalping/' : ''; let data = { ..._.pick(ctx.query, [ 'docs', 'limit', 'page', 'query', 'type', 'style', 'measurement' ]), @@ -259,15 +260,15 @@ koaElasticUtils.addRoutes(router, [ }; try { - ctx.body = await ctx.render(`pages/${root}` + (ctx.path === '/' ? '_index' : ctx.path) + '.html', data); + ctx.body = await ctx.render(`pages/${root}` + (path === '/' ? '_index' : path) + '.html', data); ctx.maxAge = 5 * 60; } catch (e) { if (app.env === 'development') { console.error(e); } - ctx.status = 301; - return ctx.redirect('/'); + ctx.status = 404; + ctx.body = await ctx.render(`pages/${root}_404.html`, { actualPath: ctx.path }); } }); diff --git a/src/views/components/header.html b/src/views/components/header.html index ff3c9c895a..ddca74d955 100644 --- a/src/views/components/header.html +++ b/src/views/components/header.html @@ -1,5 +1,5 @@
-