Merge pull request #9 from GRA0007/dev
Timezones and better url generation
This commit is contained in:
commit
8aed37c413
|
|
@ -18,6 +18,7 @@
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dayjs": "^1.10.4",
|
"dayjs": "^1.10.4",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"express": "^4.17.1"
|
"express": "^4.17.1",
|
||||||
|
"punycode": "^2.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,49 @@
|
||||||
const dayjs = require('dayjs');
|
const dayjs = require('dayjs');
|
||||||
|
const punycode = require('punycode/');
|
||||||
|
|
||||||
const adjectives = require('../res/adjectives.json');
|
const adjectives = require('../res/adjectives.json');
|
||||||
const crabs = require('../res/crabs.json');
|
const crabs = require('../res/crabs.json');
|
||||||
|
|
||||||
const capitalize = (string) => string.charAt(0).toUpperCase() + string.slice(1);
|
const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1);
|
||||||
|
|
||||||
const generateId = (name) => {
|
|
||||||
const id = name.trim().toLowerCase().replace(/[^A-Za-z0-9 ]/g, '').replace(/\s+/g, '-');
|
|
||||||
const number = Math.floor(100000 + Math.random() * 900000);
|
|
||||||
return `${id}-${number}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Generate a random name based on an adjective and a crab species
|
||||||
const generateName = () => {
|
const generateName = () => {
|
||||||
return `${capitalize(adjectives[Math.floor(Math.random() * adjectives.length)])} ${crabs[Math.floor(Math.random() * crabs.length)]} Crab`;
|
return `${capitalize(adjectives[Math.floor(Math.random() * adjectives.length)])} ${crabs[Math.floor(Math.random() * crabs.length)]} Crab`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Generate a slug for the crab fit
|
||||||
|
const generateId = name => {
|
||||||
|
let id = punycode.encode(name.trim().toLowerCase()).trim().replace(/[^A-Za-z0-9 ]/g, '').replace(/\s+/g, '-');
|
||||||
|
if (id.replace(/-/g, '') === '') {
|
||||||
|
id = generateName().trim().toLowerCase().replace(/[^A-Za-z0-9 ]/g, '').replace(/\s+/g, '-');
|
||||||
|
}
|
||||||
|
const number = Math.floor(100000 + Math.random() * 900000);
|
||||||
|
return `${id}-${number}`;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = async (req, res) => {
|
module.exports = async (req, res) => {
|
||||||
const { event } = req.body;
|
const { event } = req.body;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const name = event.name.trim() === '' ? generateName() : event.name.trim();
|
const name = event.name.trim() === '' ? generateName() : event.name.trim();
|
||||||
const eventId = generateId(name);
|
let eventId = generateId(name);
|
||||||
const currentTime = dayjs().unix();
|
const currentTime = dayjs().unix();
|
||||||
|
|
||||||
const entity = {
|
// Check if the event ID already exists, and if so generate a new one
|
||||||
|
let eventResult;
|
||||||
|
do {
|
||||||
|
const query = req.datastore.createQuery(req.types.event)
|
||||||
|
.select('__key__')
|
||||||
|
.filter('__key__', req.datastore.key([req.types.event, eventId]));
|
||||||
|
|
||||||
|
eventResult = (await req.datastore.runQuery(query))[0][0];
|
||||||
|
|
||||||
|
if (eventResult !== undefined) {
|
||||||
|
eventId = generateId(name);
|
||||||
|
}
|
||||||
|
} while (eventResult !== undefined);
|
||||||
|
|
||||||
|
const entity = {
|
||||||
key: req.datastore.key([req.types.event, eventId]),
|
key: req.datastore.key([req.types.event, eventId]),
|
||||||
data: {
|
data: {
|
||||||
name: name,
|
name: name,
|
||||||
|
|
|
||||||
|
|
@ -942,6 +942,11 @@ pumpify@^2.0.1:
|
||||||
inherits "^2.0.3"
|
inherits "^2.0.3"
|
||||||
pump "^3.0.0"
|
pump "^3.0.0"
|
||||||
|
|
||||||
|
punycode@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||||
|
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||||
|
|
||||||
qs@6.7.0:
|
qs@6.7.0:
|
||||||
version "6.7.0"
|
version "6.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import dayjs from 'dayjs';
|
||||||
import utc from 'dayjs/plugin/utc';
|
import utc from 'dayjs/plugin/utc';
|
||||||
import timezone from 'dayjs/plugin/timezone';
|
import timezone from 'dayjs/plugin/timezone';
|
||||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||||
|
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Center,
|
Center,
|
||||||
|
|
@ -23,6 +24,7 @@ import {
|
||||||
Logo,
|
Logo,
|
||||||
Title,
|
Title,
|
||||||
EventName,
|
EventName,
|
||||||
|
EventDate,
|
||||||
LoginForm,
|
LoginForm,
|
||||||
LoginSection,
|
LoginSection,
|
||||||
Info,
|
Info,
|
||||||
|
|
@ -40,6 +42,7 @@ import timezones from 'res/timezones.json';
|
||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
dayjs.extend(timezone);
|
dayjs.extend(timezone);
|
||||||
dayjs.extend(customParseFormat);
|
dayjs.extend(customParseFormat);
|
||||||
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
const Event = (props) => {
|
const Event = (props) => {
|
||||||
const timeFormat = useSettingsStore(state => state.timeFormat);
|
const timeFormat = useSettingsStore(state => state.timeFormat);
|
||||||
|
|
@ -283,6 +286,7 @@ const Event = (props) => {
|
||||||
{(!!event || isLoading) ? (
|
{(!!event || isLoading) ? (
|
||||||
<>
|
<>
|
||||||
<EventName isLoading={isLoading}>{event?.name}</EventName>
|
<EventName isLoading={isLoading}>{event?.name}</EventName>
|
||||||
|
<EventDate isLoading={isLoading} title={event?.created && dayjs.unix(event?.created).format('h:mma D MMMM, YYYY')}>{event?.created && `Created ${dayjs.unix(event?.created).fromNow()}`}</EventDate>
|
||||||
<ShareInfo
|
<ShareInfo
|
||||||
onClick={() => navigator.clipboard?.writeText(`https://crab.fit/${id}`)
|
onClick={() => navigator.clipboard?.writeText(`https://crab.fit/${id}`)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
@ -366,6 +370,22 @@ const Event = (props) => {
|
||||||
onChange={event => setTimezone(event.currentTarget.value)}
|
onChange={event => setTimezone(event.currentTarget.value)}
|
||||||
options={timezones}
|
options={timezones}
|
||||||
/>
|
/>
|
||||||
|
{event?.timezone && event.timezone !== timezone && <p>This event was created in the timezone <strong>{event.timezone}</strong>. <a href="#" onClick={e => {
|
||||||
|
e.preventDefault();
|
||||||
|
setTimezone(event.timezone);
|
||||||
|
}}>Click here</a> to use it.</p>}
|
||||||
|
{((
|
||||||
|
Intl.DateTimeFormat().resolvedOptions().timeZone !== timezone
|
||||||
|
&& (event?.timezone && event.timezone !== Intl.DateTimeFormat().resolvedOptions().timeZone)
|
||||||
|
) || (
|
||||||
|
event?.timezone === undefined
|
||||||
|
&& Intl.DateTimeFormat().resolvedOptions().timeZone !== timezone
|
||||||
|
)) && (
|
||||||
|
<p>Your local timezone is detected to be <strong>{Intl.DateTimeFormat().resolvedOptions().timeZone}</strong>. <a href="#" onClick={e => {
|
||||||
|
e.preventDefault();
|
||||||
|
setTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
|
||||||
|
}}>Click here</a> to use it.</p>
|
||||||
|
)}
|
||||||
</StyledMain>
|
</StyledMain>
|
||||||
</LoginSection>
|
</LoginSection>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ export const Title = styled.span`
|
||||||
export const EventName = styled.h1`
|
export const EventName = styled.h1`
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
margin: 20px 0 14px;
|
margin: 20px 0 5px;
|
||||||
|
|
||||||
${props => props.isLoading && `
|
${props => props.isLoading && `
|
||||||
&:after {
|
&:after {
|
||||||
|
|
@ -39,6 +39,28 @@ export const EventName = styled.h1`
|
||||||
`}
|
`}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const EventDate = styled.span`
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
opacity: .8;
|
||||||
|
margin: 0 0 10px;
|
||||||
|
font-weight: 500;
|
||||||
|
letter-spacing: .01em;
|
||||||
|
|
||||||
|
${props => props.isLoading && `
|
||||||
|
&:after {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
height: 1em;
|
||||||
|
width: 200px;
|
||||||
|
max-width: 100%;
|
||||||
|
background-color: ${props.theme.loading};
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
export const LoginForm = styled.form`
|
export const LoginForm = styled.form`
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr 100px;
|
grid-template-columns: 1fr 1fr 100px;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue