{"version":3,"sources":["components/common/Link.js","components/common/Slogan.js","utils.js","components/common/Header.js","components/common/SponsorPyramid.js","components/common/Footer.js","components/common/Background.js","components/common/FadeImage.js","components/common/ImageGallery/Person.js","components/common/ImageGallery/index.js","components/calendar/Program.js","components/calendar/Calendar.js","components/common/Countdown.js","components/common/VideoPlayer.js","components/pages/frontpage/Frontpage.js","components/pages/sponsors/Companies.js","i18n.js","components/common/PropositionPicker/CalendarWidget.js","components/common/Icons.js","components/common/PropositionPicker/DatePicker.js","components/common/PropositionPicker/TimePicker.js","components/common/PropositionPicker/Proposition.js","components/common/PropositionPicker/index.js","components/pages/registration/RegistrationForm.js","components/calendar/SignUpCalendar.js","components/pages/registration/Registration.js","components/pages/library/Library.js","components/pages/admin/Login.js","components/pages/guide/FAQ.js","components/pages/guide/Programme.js","components/pages/guide/Checklist.js","components/pages/guide/Guide.js","components/pages/calendar-callback/CalendarCallback.js","components/pages/registration/Success.js","components/pages/registration/Error.js","components/admin/LogoutButton.js","components/admin/AdminNavbar.js","components/admin/Styles.js","components/admin/Registration.js","components/admin/RegistrationPanel.js","components/pages/admin/AdminRegistrationsPage.js","components/admin/Message.js","components/admin/MessagePanel.js","components/pages/admin/AdminShoutboxPage.js","components/admin/BanPanel.js","components/admin/Ban.js","components/pages/admin/AdminBansPage.js","components/admin/ReservedName.js","components/admin/ReservedNamePanel.js","components/pages/admin/AdminReservedPage.js","components/admin/Recruitment.js","components/admin/RecruitmentPanel.js","components/pages/admin/AdminRecruitmentPage.js","components/common/SocketProvider.js","components/common/ChatProvider.js","components/common/Shoutbox.js","components/calendar/InfoScreenProgram.js","components/calendar/InfoScreenCalendar.js","components/pages/infoscreen/InfoScreen.js","components/pages/recruitment/Recruitment.js","components/pages/recruitment/Success.js","components/pages/recruitment/Error.js","components/routes/Routes.js","theme.js","components/App.js","index.js","svg/check-mark.svg"],"names":["Link","to","localize","newTab","props","i18n","useTranslation","langRoute","language","target","undefined","Phrase","styled","div","p","theme","color","boldText","Slogan","t","numberOfPhrases","Number","index","useMemo","Math","floor","random","dotenv","config","cookie","Cookie","environment","process","window","buildEnv","BACKEND_URL","REACT_APP_BACKEND_HTTP_URL","AuthError","unauthorized","Error","composeRequest","endpoint","id_token","method","body","token","get","headers","Headers","append","req","Request","isJSON","resp","includes","checkJWTAuth","a","fetch","console","log","ok","removeMessage","id","status","json","text","data","error","statusText","banUserForMessage","liftBan","ip","parseSearch","search","slice","split","map","reduce","obj","key","value","linkToTelegramChat","chatName","logoURL","REACT_APP_STATIC_URL","HeaderContainer","header","HeaderNavContainer","Logo","img","SocialMediaButton","i","SocialMediaLink","headerLinkColor","headerLinkColorHover","SocialMediaContainer","span","ReactLink","blue","blueDark","MobileLink","DesktopLink","Row","Menu","BurgerButton","button","active","redMedium","Freq","Social","rel","title","float","href","className","Nav","nav","expand","HeaderLogo","src","width","height","Header","useState","mobileMenuExpanded","setMobileMenuExpanded","location","useLocation","switchRouteLanguage","pathname","replace","onClick","tek","nitor","fonum","wibax","fatLizart","ABB","oikia","SponsorContainer","medium","semilarge","large","xl","SponsorImg","invert","whiteBG","Sponsor","alt","loading","SponsorPyramid","FooterContainer","footer","Footer","BackgroundGraphics","Background","Component","FadeImage","loaded","Image","state","onLoad","bind","this","setState","Guy","PersonHeader","PersonRole","bodyText","Img","css","Desc","Person","name","role","desc","Gallery","section","IMG_URL","people","mail","ImageGallery","person","ProgramBlock","maintainance","containerBg","oneDayPreview","Column","flex","Title","h4","Genre","small","Author","Paragraph","ShowMore","PlaceholderImage","ProgramImage","Description","expanded","setExpanded","toggleExpand","useCallback","exp","expandLink","length","maxLength","substring","join","shortenText","Program","image","trim","startDate","dateFormat","start","endDate","end","team","description","genre","REACT_APP_CALENDAR_ID","REACT_APP_START_DATE","REACT_APP_END_DATE","Date","Button","Controls","CalendarLink","groupBy","xs","rv","x","v","Function","push","preloadImages","images","forEach","document","createElement","startOfDay","date","setHours","Calendar","all","setAll","today","setToday","useEffect","parse","Array","isArray","program","test","removeHtml","innerHTML","textContent","r","sort","y","grouped","min","max","fetchProgrammes","bottomControlUsed","useRef","topControls","incrementDay","e","current","currentTarget","dataset","bottom","decrementDay","scrollIntoView","locales","toLocaleDateString","weekday","year","month","day","currentProgram","find","now","content","ref","data-bottom","h1","CountdownContainer","DigitContainer","DigitBlock","DigitSubtitle","DigitWrapper","countdownBg","Digit","Countdown","infoScreen","setNow","timer","lastTick","setTimeout","tick","nextTick","clearInterval","totalMs","sec","hour","renderDigit","digit","TransitionGroup","CSSTransition","classNames","timeout","renderDigits","number","subtitle","Container","white10","FrameContainer","VideoPlayer","frameBorder","allow","allowFullScreen","seasonStart","Trivia","ul","Frontpage","showCountdown","style","paddingTop","paddingBottom","i18nKey","components","Main","main","ColumnContainer","h2","AudioPlayerContainer","AudioPlayer","AudioPlayerLabel","label","Companies","controls","type","use","Backend","initReactI18next","init","lng","fallbackLng","react","transKeepBasicHtmlNodesFor","DateContainer","table","DateCell","td","DateHeader","FillerDate","radioStartDate","setUTCFullYear","getFullYear","getMonth","getDate","CalendarWidget","show","onDateSelect","rows","afterEndDate","setUTCDate","getUTCDate","col","getUTCDay","fill","_","aria-label","dateDay","row","i18next","PlusIcon","viewBox","d","CrossIcon","CalendarIcon","Widget","DatePicker","select","options","times","keys","n","time","leftPad","generateOptions","TimePicker","onChange","PropositionContainer","PropositionRow","Label","RemoveButton","Proposition","onUpdateValue","startTime","endTime","onDelete","showCalendar","setShowCalendar","event","AddButton","PropositionPicker","setPropositionValue","newValue","fieldState","setValue","fieldApi","prev","deleteProposition","splice","renderPropositions","onAddProposition","filter","renderAddButton","asField","Form","InformedForm","Fieldset","fieldset","CustomNumberField","setTouched","onBlur","initialValue","forwardedRef","rest","step","NumberField","StyledText","InformedText","StyledTextArea","InformedTextArea","Text","validate","notEmptyString","formatRegCode","code","toUpperCase","RegCode","format","TextArea","optional","RadioGroup","Submit","white100","galleryHoverBg","Info","errorRed","Tag","validatePropositions","propositions","RegistrationForm","preRegCodeOk","setFormApi","formApi","handlePreRegistration","getState","axios","post","values","preRegCode","setError","rerender","handleSubmit","history","prerecord","email","getErrors","errors","getValues","renderErrors","Object","handleSubmitFailure","setPropositionValues","getPropositionValues","getValue","isClosed","signupCloses","isOpen","signupOpens","getApi","onSubmit","onSubmitFailure","initialValues","field","placeholder","responsible","participants","duration","info","producer","onValueChange","setValues","textAlign","margin","withRouter","ProgramContainer","finlandTime","toLocaleString","timeZone","getTime","SmallProgram","SignUpCalendar","dayStart","dayEnd","endOfDay","previousDayPrograms","freeSlots","programs","lastPreviousProgram","adjustedDayStart","sortedPrograms","b","nextProgram","getFreeSlots","postSignupOpens","postSignupCloses","Registration","Results","Result","contrast","white30","SearchBar","input","SearchContainer","SearchButton","TypePickerContainer","Tab","TypePicker","setType","checked","htmlFor","Search","onInput","forwardRef","onKeyPress","keyCode","which","PaginationContainer","Pagination","setIndex","amountOfRows","isPreviousDisabled","isNextDisabled","disabled","fetcher","queryString","then","res","createQueryString","query","pageIndex","encodeURIComponent","swrConfig","dedupingInterval","revalidateOnFocus","revalidateOnReconnect","errorRetryCount","Prefetch","useSWR","Library","setPageIndex","setQuery","inputRef","behavior","results","result","artistData","artist","even","white","album","renderResult","renderResults","amount","CLIENT_ID","REACT_APP_OAUTH_CLIENT_ID","Login","GoogleLogin","pink100","turquoise100","LoginPage","responseGoogle","remove","params","next","tokenId","set","jwt","clientId","buttonText","onSuccess","onFailure","hostedDomain","responseType","signedIn","Question","Answer","faqComponents","children","frontpage","library","m3u","download","flac","mp3","aac","fb2k","vlc","qas","question","answer","FAQ","qa","DurationInput","InputLabel","Subtitle","AmountContainer","Programme","onInputChange","evt","calculateAmounts","hours","calc","perc","num","wholes","decimals","mins","hourPart","count","minutePart","ads","speech","music","jingles","amounts","abs","TranslationWithStrong","Checklist","Guide","match","url","path","component","CalendarCallback","queryParams","h3","RegistrationSuccess","withTranslation","RegistrationError","paths","logout","errorStatusCodes","hidden","Log","Count","LogRow","LogRowContrast","onSelect","timestamp","Panel","_id","accept","photoshoot","AdminRegistrationsPage","fetchRegistrations","Authorization","registrations","response","isSelected","msg","other","selected","componentDidUpdate","logScrolled","logRef","scrollTop","scrollHeight","renderRegistrationRows","m","React","createRef","RegistrationPanel","refresh","Message","Buttons","Actions","Modal","ReactModal","grey100","ModalContent","ModalButtons","ModalButton","showRemoveModal","showBanModal","ban","renderModal","contentLabel","BannedWordsPanel","wordRows","words","handleChange","handleDelete","word","idx","AdminShoutboxPage","messages","filters","wordField","showBannedMessages","setShowBannedMessages","fetchWords","fetchFilters","fetchMessages","toggleFilter","nextState","slug","updatedFilter","f","handleWordDelete","delete","w","wordFieldHandleChange","wordFieldHandleSubmit","preventDefault","renderContent","filterRows","messageRows","MessagePanel","timeOfBan","timeOfMessage","Ban","AdminBansPage","bans","fetchBans","banRows","BanPanel","ReservedName","AdminReservedPage","reservedNames","fetchReservedUsers","reserved","reservedNameRows","ReservedNamePanel","Recruitment","roles","message","item","AdminRecruitmentPage","recruitments","fetchRecruitment","recruitment","recruitmentRows","RecruitmentPanel","WS_URL","REACT_APP_BACKEND_WS_URL","SocketContext","createContext","SocketProvider","WebSocket","connection","setConnection","reconnect","onopen","onerror","onclose","close","Provider","ChatContext","ChatProvider","chatLog","setChatLog","setLog","InputContainer","SendButton","Username","InputRow","Prompt","Verified","Timestamp","RowText","RowUser","Block","Shoutbox","useContext","logContext","cookieRef","chatLogRef","usernameRef","msgRef","showError","handleData","currentLog","JSON","initial","newLog","concat","erase","filtered","sendMessage","username","authorization","alert","send","stringify","addEventListener","removeEventListener","verified","Time","InfoScreenProgram","InfoScreenCalendar","setInterval","sorted","upcoming","CountdownTitle","countdownTo","InfoScreen","setShowCountdown","reload","clearTimeout","RecruitmentSuccess","RecruitmentError","LanguageSwitcher","lang","useParams","changeLanguage","exact","from","bgBlue","bgDark","white70","bgLight","blueLight","highlightCol","linkColor","headingColor","galleryHoverText","orange100","orangedark100","darkpink100","bgGreen","lightOrange","realOrange","darkOrange","white2","font","heading","GlobalStyle","createGlobalStyle","App","fallback","Routes","rootElement","getElementById","hasChildNodes","hydrate","render","module","exports"],"mappings":"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","file":"static/js/main.ea7e46bf.chunk.js","sourcesContent":["import React from 'react';\nimport { Link as ReactLink } from 'react-router-dom';\nimport { useTranslation } from 'react-i18next';\n\nconst Link = ({ to, localize = true, newTab = false, ...props }) => {\n const { i18n } = useTranslation();\n \n let langRoute = '';\n if (localize) {\n langRoute = i18n.language === 'fi' ? '' : `/${i18n.language}`;\n }\n\n return (\n \n );\n};\n\nexport default Link;","import React, { useMemo } from 'react';\nimport styled from 'styled-components';\nimport { useTranslation } from 'react-i18next';\n\n/* const phrases = [\n \"Korkea taajuus, matala laatu\",\n \"Matala taajuus, korkea laatu\",\n \"Etelän halvinta puheaikaa\",\n \"Suomen nopein kuulotelevisio\",\n \"Ovi kiinni, Radio auki\",\n \"Oispa konteilla\",\n \"Mitäs tyhmää vois vielä keksiä...\",\n \"Ei mitään kakkaa vaan semi-laatua\",\n \"Buy high, sell low\",\n \"Älykkäät ihmiset, tyhmät järjestelmät\",\n \"Ai onks tää päällä huppista\",\n \"Se on rock!\",\n \"Testattu tuotannossa! :D\",\n \"Testataan tuotannossa! :P\",\n \"Sirkus pyörii, pellet vaihtuu\",\n \"Maistuu hyvältä kumpaankin suuntaan\"\n //<>Tee ite paremmin:{' '}rekry@radiodiodi.fi >\n]; */\n\nconst Phrase = styled.div`\n min-height: 2.5em;\n margin: 0 0.3em 0;\n\n font-size: 1.3rem;\n line-height: 1em;\n color: ${(p) => p.theme.color.boldText};\n\n text-align: center;\n\n @media screen and (min-width: 499px) {\n max-width: 40%;\n }\n`;\n\nconst Slogan = () => {\n const { t } = useTranslation();\n\n const numberOfPhrases = Number(t('navbar.numPhrases'));\n const index = useMemo(\n () => Math.floor(numberOfPhrases * Math.random()),\n [numberOfPhrases]\n );\n\n return {t(`navbar.phrases.${index}`)} ;\n};\n\nexport default Slogan;\n","import 'whatwg-fetch';\nimport Cookie from 'universal-cookie';\nimport { setTimeout } from 'timers';\nimport dotenv from 'dotenv';\ndotenv.config();\n\nconst cookie = new Cookie();\n\nexport const environment = {\n ...process.env,\n ...(window.buildEnv || {})\n};\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\n\nclass AuthError extends Error {\n constructor() {\n super('Unauthorized');\n this.unauthorized = true;\n }\n}\n\n/**\n * Create Request object\n * @param {String} endpoint\n * @param {String} id_token\n * @param {String} method\n * @param {Object} body\n */\nconst composeRequest = (endpoint, id_token, method = 'GET', body = null) => {\n const token = id_token || cookie.get('jwt');\n\n const headers = new Headers();\n headers.append('Authorization', token);\n const req = new Request(endpoint, {\n headers,\n method,\n body,\n });\n\n return req;\n}\n\nconst isJSON = resp => {\n return resp && resp.headers && resp.headers.get('Content-Type').includes('application/json');\n}\n\nconst checkJWTAuth = async token => {\n const req = composeRequest(`${BACKEND_URL}/auth`, token);\n\n try {\n const resp = await fetch(req);\n\n console.log('Backend auth response:');\n console.log(resp);\n\n return resp.ok;\n } catch (err) {\n console.log(err);\n return false;\n }\n}\n\nconst removeMessage = async id => {\n const req = composeRequest(`${BACKEND_URL}/admin/messages/remove/${id}`, null, 'DELETE');\n\n try {\n const resp = await fetch(req);\n\n if (resp.status === 401) {\n throw new AuthError();\n }\n\n const data = isJSON(resp)\n ? await resp.json()\n : await resp.text();\n\n if (!resp.ok) {\n if (data.error) {\n throw new Error(data.error);\n } else {\n throw new Error(resp.statusText);\n }\n }\n\n console.log('Backend messages response:');\n console.log(data);\n } catch (err) {\n console.log(err);\n throw err;\n }\n}\n\nconst banUserForMessage = async id => {\n const req = composeRequest(`${BACKEND_URL}/admin/users/ban/${id}`, null, 'DELETE');\n\n try {\n const resp = await fetch(req);\n\n if (resp.status === 401) {\n throw new AuthError();\n }\n\n const data = isJSON(resp)\n ? await resp.json()\n : await resp.text();\n\n if (!resp.ok) {\n if (data.error) {\n throw new Error(data.error);\n } else {\n throw new Error(resp.statusText);\n }\n }\n\n console.log('Backend messages response:');\n console.log(data);\n } catch (err) {\n console.log(err);\n throw err;\n }\n}\n\nconst liftBan = async ip => {\n const req = composeRequest(`${BACKEND_URL}/admin/users/unban/${ip}`, null, 'DELETE');\n\n try {\n const resp = await fetch(req);\n\n if (resp.status === 401) {\n throw new AuthError();\n }\n\n const data = isJSON(resp)\n ? await resp.json()\n : await resp.text();\n\n if (!resp.ok) {\n if (data.error) {\n throw new Error(data.error);\n } else {\n throw new Error(resp.statusText);\n }\n }\n\n console.log('Backend messages response:');\n console.log(data);\n } catch (err) {\n console.log(err);\n throw err;\n }\n}\n\nconst wait = time => new Promise((resolve, reject) => {\n setTimeout(resolve, time);\n});\n\nconst fetchSongsByField = async (field, title) => {\n const req = composeRequest(`${BACKEND_URL}/${field}/${title}`, null, 'GET');\n try {\n const resp = await fetch(req);\n\n if (resp.status === 429) { // too many requests\n await wait(1000); // ms\n return fetchSongsByField(field, title);\n }\n\n const data = isJSON(resp)\n ? await resp.json()\n : await resp.text();\n\n if (!resp.ok) {\n if (data.error) {\n throw new Error(data.error);\n } else {\n throw new Error(resp.statusText);\n }\n }\n\n console.log('Backend messages response:');\n console.log(data);\n\n return data.results;\n } catch (err) {\n console.log(err);\n throw err;\n }\n}\n\nconst fetchSongs = async () => {\n const req = composeRequest(`${BACKEND_URL}`, null, 'GET');\n try {\n const resp = await fetch(req);\n\n if (resp.status === 429) { // too many requests\n await wait(1000); // ms\n return fetchSongs();\n }\n\n const data = isJSON(resp)\n ? await resp.json()\n : await resp.text();\n\n if (!resp.ok) {\n if (data.error) {\n throw new Error(data.error);\n } else {\n throw new Error(resp.statusText);\n }\n }\n\n console.log('Backend messages response:');\n console.log(data);\n\n return data.results || [];\n } catch (err) {\n console.log(err);\n throw err;\n }\n}\n\nconst fetchNowPlayingProgramme = async () => {\n const req = composeRequest(`${BACKEND_URL}/now_playing`, null, 'GET');\n\n try {\n const resp = await fetch(req);\n\n if (resp.status === 401) {\n throw new AuthError();\n }\n\n const data = isJSON(resp)\n ? await resp.json()\n : await resp.text();\n\n if (!resp.ok) {\n if (data.error) {\n throw new Error(data.error);\n } else {\n throw new Error(resp.statusText);\n }\n }\n\n return data;\n } catch (err) {\n console.log(err);\n throw err;\n }\n}\n\n/* DEPRECATED: fetchCurrentSong\n * Current implementation in Player uses WebSockets.\n * The helper function still remains here.\n */\n\nconst fetchCurrentSong = async () => {\n const req = composeRequest(`${BACKEND_URL}/api/current_song`, null, 'GET');\n\n try {\n const resp = await fetch(req);\n\n if (resp.status === 401) {\n throw new AuthError();\n }\n\n const data = isJSON(resp)\n ? await resp.json()\n : await resp.text();\n\n if (!resp.ok) {\n if (data.error) {\n throw new Error(data.error);\n } else {\n throw new Error(resp.statusText);\n }\n }\n\n return data;\n } catch (err) {\n console.log(err);\n throw err;\n }\n}\n\nconst registerProgramme = async data => {\n const body = JSON.stringify(data);\n const req = composeRequest(`${BACKEND_URL}/api/register`, null, 'POST', body);\n\n try {\n const resp = await fetch(req);\n return resp.ok;\n } catch (err) {\n console.log(err);\n return false;\n }\n}\n\n/* Take N first whole words, where N is the amount of words below 100 characters total */\nconst shortenText = (text, maxLength = 100) =>\n text.length < maxLength\n ? text\n : `${text.split(' ').slice(0, text.substring(0, maxLength).split(' ').length - 1).join(' ')}...`;\n\nconst parseSearch = search => search\n .slice(1)\n .split('&')\n .map(p => p.split('='))\n .reduce((obj, [key, value]) => ({ ...obj, [key]: value }), {});\n\nexport const linkToTelegramChat = chatName => `https://t.me/${chatName}`;\n\nexport {\n checkJWTAuth,\n removeMessage,\n banUserForMessage,\n liftBan,\n AuthError,\n fetchSongsByField,\n fetchSongs,\n registerProgramme,\n shortenText,\n fetchNowPlayingProgramme,\n fetchCurrentSong,\n parseSearch,\n}\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport { useLocation } from 'react-router-dom';\nimport ReactLink from './Link';\nimport Slogan from './Slogan';\nimport { linkToTelegramChat } from '../../utils';\nimport { environment } from '../../utils';\nimport { useTranslation } from 'react-i18next';\n\nconst logoURL = `${environment.REACT_APP_STATIC_URL}/img/2025/2025_header.svg`;\n\nconst HeaderContainer = styled.header`\n margin-bottom: 2rem;\n`;\n\nconst HeaderNavContainer = styled.div`\n display: flex;\n justify-content: space-between;\n width: 100%;\n margin-top: 0.3rem;\n`;\n\nconst Logo = styled.img`\n max-width: 100%;\n height: auto;\n margin-bottom: -5%;\n\n @media screen and (max-width: 499px) {\n margin-bottom: 20px;\n }\n`;\n\nconst SocialMediaButton = styled.i`\n font-size: 2rem;\n`;\n\nconst SocialMediaLink = styled.a`\n color: ${(p) => p.theme.color.headerLinkColor};\n transition: color 0.2s ease;\n\n &:hover,\n &:focus {\n color: ${(p) => p.theme.color.headerLinkColorHover};\n }\n\n margin: 0 0.5rem 0;\n`;\n\nconst SocialMediaContainer = styled.span`\n display: flex;\n flex-flow: row nowrap;\n margin-right: auto;\n align-items: flex-end;\n`;\n\nconst Link = styled(ReactLink)`\n font-size: 1.1rem;\n color: ${(p) =>\n p.color ||\n (p.blue && p.theme.color.blueDark) ||\n p.theme.color.headerLinkColor};\n margin-left: 0.8rem;\n transition: color 0.3s ease;\n font-weight: 500;\n\n &:hover {\n color: ${(p) => p.theme.color.blueDark};\n text-decoration: none;\n }\n`;\n\nconst MobileLink = styled(Link)`\n @media screen and (min-width: 1000px) {\n display: none;\n }\n`;\n\nconst DesktopLink = styled(Link)`\n @media screen and (max-width: 999px) {\n display: none;\n }\n`;\n\nconst Row = styled.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n`;\n\nconst Menu = styled.div`\n width: 100%;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n\n @media screen and (min-width: 1000px) {\n flex-direction: row;\n }\n`;\n\nconst BurgerButton = styled.button`\n background: transparent;\n border: none;\n cursor: pointer;\n font-size: 1.8rem;\n padding: 0.5rem;\n margin-right: -0.5rem;\n margin-left: 1rem;\n color: ${(p) => (p.active ? p.theme.color.boldText : p.theme.color.boldText)};\n\n &:hover {\n color: ${(p) => p.theme.color.redMedium};\n }\n\n @media screen and (min-width: 1000px) {\n display: none;\n }\n`;\n\nconst Freq = styled.div`\n min-height: 2.5em;\n margin: 0 0.3em 0\n font-weight: bold;\n font-size: 1.5rem;\n line-height: 1em;\n color: ${(p) => p.theme.color.boldText};\n\n @media screen and (max-width: 499px) {\n font-size: 1.3rem;\n }\n`;\n\nconst Social = () => {\n const { t } = useTranslation();\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n};\n\nconst Nav = styled.nav`\n display: ${(p) => (p.expand ? 'flex' : 'none')};\n flex-direction: column;\n align-items: flex-end;\n line-height: 1.8;\n\n @media screen and (min-width: 1000px) {\n display: flex;\n flex-direction: row;\n }\n`;\n\nexport const HeaderLogo = () => (\n \n);\n\nconst Header = () => {\n const [mobileMenuExpanded, setMobileMenuExpanded] = useState(false);\n const { t, i18n } = useTranslation();\n\n const toggleMobileMenuExpanded = () => {\n setMobileMenuExpanded(!mobileMenuExpanded);\n };\n\n const location = useLocation();\n\n const switchRouteLanguage = () => {\n if (i18n.language === 'en') {\n return location.pathname.replace('/en', '');\n } else {\n return `/en${location.pathname}`;\n }\n };\n\n const renderNavigation = (expand) => {\n return (\n \n {t('navbar.frontpage')}\n {t('navbar.signup')}\n {/* {t('navbar.recruitment')} */}\n {t('navbar.library')}\n {t('navbar.forCompanies')}\n {/* Yhteistyökumppaniksi? */}\n {t('navbar.forProgrammeMakers')}\n \n {i18n.language === 'en' ? 'Suomeksi' : 'In English'}\n \n \n );\n };\n\n return (\n \n \n \n \n \n \n 102,0 MHz \n
\n \n \n \n \n \n {i18n.language === 'en' ? 'Suomeksi' : 'In English'}\n \n \n \n \n
\n {renderNavigation(mobileMenuExpanded)}\n \n \n \n );\n};\n\nexport default Header;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { environment } from '../../utils';\n\nconst tek = `${environment.REACT_APP_STATIC_URL}/img/2022/sponsors/tek.png`;\n// const siili = `${environment.REACT_APP_STATIC_URL}/img/2022/sponsors/Siili_white.png`;\n// const knowit = `${environment.REACT_APP_STATIC_URL}/img/2022/sponsors/knowit.png`;\n// const granlund = `${environment.REACT_APP_STATIC_URL}/img/2023/sponsors/granlund_white.png`;\nconst nitor = `${environment.REACT_APP_STATIC_URL}/img/2023/sponsors/nitor_white.svg`;\nconst fonum = `${environment.REACT_APP_STATIC_URL}/img/2024/sponsors/fonum_white.png`;\n// const tter = `${environment.REACT_APP_STATIC_URL}/img/2019/TTER.png`;\nconst wibax = `${environment.REACT_APP_STATIC_URL}/img/2024/sponsors/wibax-logo-white-cmyk.svg`;\nconst fatLizart = `${environment.REACT_APP_STATIC_URL}/img/2025/sponsors/FL_logo-black_web.png`;\nconst ABB = `${environment.REACT_APP_STATIC_URL}/img/2025/sponsors/2000px-ABB_logo_red.svg.png`;\nconst oikia = `${environment.REACT_APP_STATIC_URL}/img/2025/sponsors/Oikiasipsi_Logo_musta_RGB.png`;\n// const avp = `${environment.REACT_APP_STATIC_URL}/img/2024/sponsors/AVP_Black kopio.svg`;\n\nconst SponsorContainer = styled.div`\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-around;\n align-content: flex-start;\n align-items: center;\n margin: 1rem 0 0 -2rem;\n\n & > * {\n margin: 0 0 2rem 2rem;\n height: 80px;\n width: 160px;\n\n ${(props) =>\n props.medium &&\n `\n height: 150px;\n width: 300px;\n `}\n\n ${(props) =>\n props.semilarge &&\n `\n height: 200px;\n width: 400px;\n `}\n\n ${(props) =>\n props.large &&\n `\n height: 250px;\n width: 500px;\n `}\n\n ${(props) =>\n props.xl &&\n `\n height: 400px;\n width: 750px;\n `}\n\n img {\n width: 100%;\n height: 100%;\n object-fit: contain;\n }\n }\n`;\n\nconst SponsorImg = styled.img`\n ${(p) =>\n p.invert &&\n `\n filter: invert(100%);\n `}\n\n ${(p) =>\n p.whiteBG &&\n `\n background-color: white;\n border: 67px solid white\n width: unset !important;\n `}\n`;\n\nconst Sponsor = ({ src, alt, invert, whiteBG }) => (\n
\n \n
\n);\n\nexport const SponsorPyramid = () => {\n return (\n \n {/* \n \n */}\n \n \n \n \n\n \n {/* */}\n {/* */}\n \n \n {/* */}\n \n \n \n {/* */}\n \n
\n );\n};\n\nexport default SponsorPyramid;\n","import React from 'react';\nimport styled from 'styled-components';\nimport SponsorPyramid from './SponsorPyramid';\n\nconst FooterContainer = styled.footer`\n text-align: center;\n padding: 1rem;\n border-top: solid;\n border-width: 4px;\n border-color: ${(p) => p.theme.color.boldText};\n`;\n\nfunction Footer() {\n return (\n \n \n © Radiodiodi 2025\n \n );\n}\n\nexport default Footer;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\nimport { environment } from '../../utils';\n\nconst BackgroundGraphics = styled.div`\n background: url(${environment.REACT_APP_STATIC_URL}/img/2024/tausta.svg);\n background-size: cover;\n background-position: center bottom;\n position: fixed;\n z-index: -1;\n height: 120vh;\n width: 120vw;\n bottom: 3vh;\n right: 0;\n opacity: 0.2;\n`;\n\nclass Background extends Component {\n render() {\n return ;\n }\n}\n\nexport default Background;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\n\nconst FadeImage = styled.img`\n opacity: ${p => p.loaded ? 1 : 0};\n transition: opacity 0.5s;\n`;\n\nclass Image extends Component {\n constructor(props) {\n super(props);\n\n this.state = {\n loaded: false,\n };\n\n this.onLoad = this.onLoad.bind(this);\n }\n\n onLoad() {\n this.setState({\n loaded: true \n });\n }\n\n render() {\n return ;\n }\n}\n\nexport default Image;","import React from 'react';\nimport styled from 'styled-components';\nimport PropTypes from 'prop-types';\nimport FadeImage from '../FadeImage';\nimport { useTranslation } from 'react-i18next';\n\nconst Guy = styled.div`\n text-align: center;\n --spacing: 2rem;\n margin: 1rem var(--spacing) var(--spacing);\n width: 100%;\n\n @media screen and (min-width: 701px) {\n width: calc((100% - var(--spacing) * 4) / 2);\n }\n\n @media screen and (min-width: 1001px) {\n width: calc((100% - var(--spacing) * 6) / 3);\n margin-top: -3rem;\n\n &:nth-child(1),\n &:nth-child(2),\n &:nth-child(3) {\n margin-top: 1rem;\n }\n &:nth-child(4),\n &:nth-child(9) {\n margin-left: calc(\n (100% - var(--spacing) * 6) / 3 / 2 + var(--spacing) * 2\n );\n }\n }\n`;\n\nconst PersonHeader = styled.div`\n color: ${(p) => p.theme.color.boldText};\n font-size: 1.2rem;\n font-weight: 700;\n`;\n\nconst PersonRole = styled.div`\n color: ${(p) => p.theme.color.bodyText};\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 1.5px;\n`;\n\nconst Img = styled(FadeImage)`\n margin-top: 1rem;\n max-width: 100%;\n ${(p) => p.css};\n border-radius: 100%;\n aspect-ratio: 1 / 1;\n object-fit: cover;\n`;\n\nconst Desc = styled.p`\n text-align: right;\n font-style: italic;\n`;\n\nconst Person = ({ name, role, img, desc }) => {\n const { t } = useTranslation();\n return (\n \n \n {name} \n {t(role)} \n {desc && {desc} }\n \n );\n};\n\nPerson.propTypes = {\n name: PropTypes.string,\n img: PropTypes.any,\n role: PropTypes.string,\n desc: PropTypes.string,\n mail: PropTypes.string,\n};\n\nexport default Person;\n","import React from 'react';\nimport styled from 'styled-components';\n\nimport Person from './Person';\nimport { environment } from '../../../utils';\n\nconst Gallery = styled.section`\n display: flex;\n flex-flow: row wrap;\n justify-content: flex-start;\n`;\n\nconst IMG_URL = `${environment.REACT_APP_STATIC_URL}/img/2025/toimitus/`;\n\nconst people = [\n {\n name: 'Ilkka',\n role: 'frontpage.editorialTeam.editor',\n img: `${IMG_URL}ilkka.jpg`,\n mail: 'paatoimittaja@radiodiodi.fi',\n },\n {\n name: 'Samuli',\n role: 'frontpage.editorialTeam.oltermanni',\n img: `${IMG_URL}samuli.jpg`,\n mail: 'leo@radiodiodi.fi',\n },\n {\n name: 'Aaron',\n role: 'frontpage.editorialTeam.promoRep',\n img: `${IMG_URL}aaron.jpg`,\n mail: '@radiodiodi.fi',\n },\n {\n name: 'Risto',\n role: 'frontpage.editorialTeam.studio',\n img: `${IMG_URL}risto.jpg`,\n mail: 'studio@radiodiodi.fi',\n },\n {\n name: 'Santeri',\n role: 'frontpage.editorialTeam.corporate',\n img: `${IMG_URL}santeri.jpg`,\n mail: 'yrityssuhteet@radiodiodi.fi',\n },\n {\n name: 'Elli',\n role: 'frontpage.editorialTeam.communications',\n img: `${IMG_URL}elli.jpg`,\n mail: 'viestinta@radiodiodi.fi',\n },\n {\n name: 'Anna',\n role: 'frontpage.editorialTeam.graphics',\n img: `${IMG_URL}anna.jpg`,\n // mail: 'anni@radiodiodi.fi',\n },\n {\n name: 'Teemu',\n role: 'frontpage.editorialTeam.construction',\n img: `${IMG_URL}teemu.jpg`,\n // mail: 'vili@radiodiodi.fi',\n },\n {\n name: 'Eemeli',\n role: 'frontpage.editorialTeam.tech',\n img: `${IMG_URL}eemeli.jpg`,\n mail: 'tekniikka@radiodiodi.fi',\n },\n {\n name: 'Akseli',\n role: 'frontpage.editorialTeam.tech',\n img: `${IMG_URL}akseli.jpg`,\n mail: 'tekniikka@radiodiodi.fi',\n },\n];\n\nconst ImageGallery = () => {\n return (\n \n {people.map((person, index) => (\n \n ))}\n \n );\n};\n\nexport default ImageGallery;\n","import React, { useCallback, useState } from 'react';\nimport styled from 'styled-components';\nimport { shortenText } from '../../utils';\n//import placeholderImg from '../../images/placeholder_dark.svg'\nimport dateFormat from 'dateformat';\nimport { environment } from '../../utils';\n\nconst ProgramBlock = styled.div`\n padding: 1.5rem;\n min-height: ${(p) => (p.maintainance ? 'none' : '150px')};\n\n &::after {\n content: '';\n clear: both;\n display: table;\n }\n\n background-color: ${(p) => p.theme.color.containerBg};\n margin-bottom: 0.5rem;\n display: flex;\n flex-direction: row;\n\n @media screen and (max-width: 500px) {\n flex-direction: column;\n }\n\n justify-content: space-between;\n\n @media screen and (max-width: 700px) {\n display: ${(p) => (p.oneDayPreview ? 'none' : 'flex')};\n }\n`;\n\nconst Column = styled.div`\n flex: ${(p) => p.flex};\n /* display: flex; */\n flex-direction: column;\n`;\n\nconst Image = styled.img`\n width: 150px;\n max-height: 150px;\n background-size: cover;\n margin-right: 1.5rem;\n\n @media screen and (max-width: 500px) {\n margin: 0 1rem 1rem 0;\n align-self: flex-start;\n }\n`;\n\nconst Title = styled.h4`\n margin: 0.5rem 0;\n font-size: 18px;\n border-bottom: 1px solid ${(p) => p.theme.color.boldText};\n word-wrap: break-word;\n\n @media (max-width: 600px) {\n margin-right: 0;\n }\n`;\n\nconst Genre = styled.small`\n margin-top: -4px;\n color: ${(p) => p.theme.color.boldText};\n letter-spacing: 0.5px;\n`;\n\nconst Author = styled.span`\n display: inline-block;\n margin: 0.5rem 0;\n font-weight: 500;\n font-size: 1rem;\n`;\n\nconst Paragraph = styled.p`\n font-size: 14px;\n line-height: 1.3;\n margin: 0.5em 0;\n @media screen and (max-width: 500px) {\n font-size: 16px;\n }\n`;\n\nconst ShowMore = styled.span`\n cursor: pointer;\n font-size: 12px;\n padding: 0;\n color: ${(p) => p.theme.color.boldText};\n\n @media screen and (max-width: 800px - 1px) {\n font-size: 16px;\n }\n`;\n\nconst PlaceholderImage = ({ alt }) => (\n \n);\n\nconst ProgramImage = ({ src, alt }) => {\n // const originalHref = src.replace('/ohjelmat', '/ohjelmat/original');\n\n return (\n // \n \n // \n );\n};\n\nconst DESCRIPTION_MAX_LENGTH = 250;\n\nconst Description = ({ desc }) => {\n const [expanded, setExpanded] = useState(false);\n const toggleExpand = useCallback(() => setExpanded((exp) => !exp), []);\n\n const expandLink =\n desc.length > DESCRIPTION_MAX_LENGTH ? (\n \n {expanded ? ' Vähemmän' : ' Lisää'}\n \n ) : null;\n\n return (\n \n {expanded ? desc : shortenText(desc, DESCRIPTION_MAX_LENGTH)}\n {expandLink}\n \n );\n};\n\nconst Program = ({ p, oneDayPreview }) => {\n const maintainance = p.title === 'HUOLTOTAUKO';\n const img =\n p.image && p.image.trim() ? (\n \n ) : (\n \n );\n\n const startDate = dateFormat(p.start, 'HH:MM');\n const endDate = dateFormat(p.end, 'HH:MM');\n\n return (\n \n {img} \n \n {`${startDate} - ${endDate}`} \n \n {p.title} - {p.team} \n \n {p.description && }\n {p.genre} \n \n \n );\n};\n\nexport default Program;\n","import React, { useState, useEffect, useRef, useCallback } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport styled from 'styled-components';\nimport Program from './Program';\nimport { environment } from '../../utils';\n\nconst {\n REACT_APP_BACKEND_HTTP_URL,\n REACT_APP_CALENDAR_ID,\n REACT_APP_START_DATE,\n REACT_APP_END_DATE,\n} = environment;\n\nconst startDate = new Date(REACT_APP_START_DATE);\nconst endDate = new Date(REACT_APP_END_DATE);\n\nconst Button = styled.button`\n background-color: ${(p) => p.theme.color.boldText};\n color: white;\n padding: 0.5rem 0;\n font-size: 14px;\n border: none;\n min-width: 100px;\n cursor: pointer;\n\n &:hover {\n background-color: ${(p) => p.theme.color.redMedium};\n }\n\n @media screen and (max-width: 450px) {\n margin: 0.5rem 0;\n }\n`;\n\nconst Controls = styled.div`\n margin: 1rem 0;\n padding: 0.5rem 0;\n text-align: center;\n display: flex;\n justify-content: space-between;\n flex-wrap: wrap;\n flex-direction: row;\n align-items: center;\n\n @media screen and (max-width: 450px) {\n flex-direction: column;\n }\n`;\n\nconst CalendarLink = styled.div`\n text-align: center;\n margin-bottom: 2rem;\n`;\n\nconst groupBy = (xs, key) =>\n xs.reduce((rv, x) => {\n var v = key instanceof Function ? key(x) : x[key];\n (rv[v] = rv[v] || []).push(x);\n return rv;\n }, {});\n\nconst preloadImages = (images) => {\n images.forEach((src) => {\n const img = document.createElement('img');\n img.src = src; // Assigning the img src immediately requests the image\n });\n};\n\nconst currentDateWithinBounds = () =>\n startOfDay(Math.min(endDate, Math.max(new Date(), startDate)));\n\nconst startOfDay = (date) => new Date(date).setHours(0, 0, 0, 0);\n\nconst Calendar = ({ oneDayPreview }) => {\n const { t } = useTranslation();\n const [all, setAll] = useState();\n const [today, setToday] = useState();\n\n useEffect(() => {\n if (Date.parse(REACT_APP_START_DATE) && Date.parse(REACT_APP_END_DATE)) {\n const fetchProgrammes = async () => {\n try {\n const resp = await fetch(`${REACT_APP_BACKEND_HTTP_URL}/programmes`);\n const data = await resp.json();\n if (!data || !Array.isArray(data)) {\n console.error('Programme data invalid. Data: ', data);\n return;\n }\n\n data.forEach((program) => {\n program.start = new Date(program.start);\n program.end = new Date(program.end);\n\n // Hotfix for removing html from descriptions\n if (\n / |/.test(\n `${program.image}${program.description}${program.team}${program.genre}`\n )\n ) {\n function removeHtml(text) {\n const div = document.createElement('div');\n div.innerHTML = text;\n return div.textContent.trim();\n }\n if (program.image) program.image = removeHtml(program.image);\n if (program.description)\n program.description = removeHtml(program.description);\n if (program.team) program.team = removeHtml(program.team);\n if (program.genre) program.genre = removeHtml(program.genre);\n }\n });\n\n const images = data.map((p) => p.image || '');\n preloadImages(images);\n\n const r = data.sort((x, y) => +x.start - y.start);\n const grouped = groupBy(r, (x) => startOfDay(x.start));\n\n setToday(currentDateWithinBounds());\n setAll(grouped);\n } catch (error) {\n console.error(error);\n }\n };\n fetchProgrammes();\n }\n }, []);\n\n // We only want to scroll after a manual day change, and then only after rerendering.\n // The ways to do this:\n // - flushSync in event handler (no idea how this works in React from 2017)\n // - store change source in useState (probably doesn't batch in React from 2017)\n // - store change source in useRef\n const bottomControlUsed = useRef(false);\n const topControls = useRef();\n\n const incrementDay = useCallback(\n (e) => {\n bottomControlUsed.current = e.currentTarget.dataset.bottom;\n setToday(startOfDay(Math.min(today + 86400000, endDate)));\n },\n [today]\n );\n const decrementDay = useCallback(\n (e) => {\n bottomControlUsed.current = e.currentTarget.dataset.bottom;\n setToday(startOfDay(Math.max(today - 86400000, startDate)));\n },\n [today]\n );\n\n useEffect(() => {\n // Forced scrolling is annoying but better than the bottom button jumping around when days change\n if (bottomControlUsed.current && topControls.current)\n topControls.current.scrollIntoView();\n }, [today]);\n\n if (!all || !today) return null;\n\n const locales = [t('frontpage.calendar.dateLocale'), 'fi-FI', 'fi'];\n const dateOptions = {\n weekday: 'long',\n year: 'numeric',\n month: 'numeric',\n day: 'numeric',\n };\n const date = new Date(today).toLocaleDateString(locales, dateOptions);\n\n if (oneDayPreview) {\n if (all[today]) {\n const currentProgram = all[today].find((program) => {\n const now = new Date();\n const start = program.start;\n const end = program.end;\n const hasNotEnded = end > now;\n const hasStarted = start < now;\n return hasStarted && hasNotEnded;\n });\n\n if (!currentProgram) {\n return null;\n }\n return ;\n } else {\n return null;\n }\n }\n\n const content = all[today]\n ? all[today].map((p) => )\n : [];\n\n return (\n \n
{t('frontpage.calendar.title')} \n
\n {t('frontpage.calendar.prev')} \n {date} \n {t('frontpage.calendar.next')} \n \n {content}\n
\n \n {t('frontpage.calendar.prev')}\n \n {date} \n \n {t('frontpage.calendar.next')}\n \n \n
\n {t('frontpage.calendar.viewFull')}\n \n \n Google Calendar\n \n \n
\n );\n};\n\nexport default Calendar;\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\nimport { TransitionGroup, CSSTransition } from 'react-transition-group';\nimport { useTranslation } from 'react-i18next';\n\nconst Title = styled.h1`\n display: block;\n color: ${(p) => p.theme.color.boldText};\n font-size: 2.5rem;\n text-align: center;\n padding-top: 0;\n margin-bottom: 1.5rem;\n\n @media (max-width: 799px) {\n font-size: 2.2rem;\n margin-bottom: 1rem;\n }\n @media (max-width: 639px) {\n font-size: 1.8rem;\n margin-bottom: 0.85rem;\n }\n @media (max-width: 479px) {\n font-size: 1.6rem;\n margin-bottom: 0.7rem;\n }\n @media (max-width: 399px) {\n font-size: 1.4rem;\n margin-bottom: 0.5rem;\n }\n`;\n\nconst CountdownContainer = styled.div`\n margin-bottom: 1rem;\n\n &.infoscreen {\n margin-left: -2rem;\n margin-right: -2rem;\n }\n`;\n\nconst DigitContainer = styled.div`\n display: flex;\n justify-content: space-evenly;\n\n .infoscreen & {\n justify-content: space-between;\n }\n`;\n\nconst DigitBlock = styled.div`\n display: grid;\n grid-template-columns: auto auto;\n grid-template-rows: auto auto;\n column-gap: 0.8rem;\n row-gap: 0.5rem;\n justify-items: center;\n\n @media (max-width: 799px) {\n column-gap: 0.6rem;\n row-gap: 0.4rem;\n }\n @media (max-width: 639px) {\n column-gap: 0.5rem;\n row-gap: 0.3rem;\n }\n @media (max-width: 479px) {\n column-gap: 0.4rem;\n row-gap: 0.25rem;\n }\n @media (max-width: 399px) {\n column-gap: 0.3rem;\n row-gap: 0.2rem;\n }\n\n .infoscreen & {\n column-gap: 1rem;\n row-gap: 1rem;\n }\n`;\n\nconst DigitSubtitle = styled.div`\n grid-column: span 2;\n font-size: 1.6rem;\n font-weight: 600;\n\n @media (max-width: 999px) {\n font-size: 1.5rem;\n }\n @media (max-width: 799px) {\n font-size: 1.2rem;\n }\n @media (max-width: 639px) {\n font-size: 1rem;\n }\n @media (max-width: 479px) {\n font-size: 0.9rem;\n }\n @media (max-width: 399px) {\n font-size: 0.8rem;\n }\n\n .infoscreen & {\n font-size: 1.8rem;\n }\n`;\n\nconst DigitWrapper = styled.div`\n background-color: ${(p) => p.theme.color.countdownBg};\n font-size: 6rem;\n height: 1.2em;\n width: 1.5ch;\n line-height: 1.2em;\n position: relative;\n overflow: hidden;\n\n @media (max-width: 999px) {\n font-size: 5rem;\n }\n @media (max-width: 799px) {\n font-size: 4rem;\n }\n @media (max-width: 639px) {\n font-size: 3rem;\n }\n @media (max-width: 479px) {\n font-size: 2.4rem;\n }\n @media (max-width: 399px) {\n font-size: 2.1rem;\n }\n\n .infoscreen & {\n font-size: 10rem;\n width: 1.2ch;\n }\n`;\n\nconst Digit = styled.div`\n position: absolute;\n left: 0;\n top: 0;\n width: 100%;\n height: 100%;\n text-align: center;\n\n &.countdown-enter {\n opacity: 0;\n top: -100%;\n }\n &.countdown-enter-active {\n opacity: 1;\n top: 0;\n transition: opacity 300ms, top 300ms;\n }\n &.countdown-exit {\n opacity: 1;\n top: 0;\n }\n &.countdown-exit-active {\n opacity: 0;\n top: 100%;\n transition: opacity 300ms, top 300ms;\n }\n`;\n\nconst Countdown = ({ title, to, infoScreen }) => {\n const { t } = useTranslation();\n const [now, setNow] = useState(Date.now());\n\n useEffect(() => {\n let lastTick = Date.now();\n let timer;\n const tick = () => {\n setNow(Date.now());\n // Tick semi-consistently every second\n const nextTick = lastTick + 1000;\n timer = setTimeout(tick, Math.max(0, nextTick - Date.now()));\n lastTick = nextTick;\n };\n timer = setTimeout(tick, 1000);\n return () => clearInterval(timer);\n }, []);\n\n const totalMs = Math.max(to - now, 0);\n const sec = Math.floor((totalMs / 1e3) % 60);\n const min = Math.floor((totalMs / 60e3) % 60);\n const hour = Math.floor((totalMs / 3600e3) % 24);\n const day = Math.floor(totalMs / 86400e3);\n\n const renderDigit = (digit) => (\n \n \n \n {digit} \n \n \n \n );\n\n const renderDigits = (number, subtitle) => (\n \n {renderDigit(Math.floor(number / 10))}\n {renderDigit(number % 10)}\n {subtitle} \n \n );\n\n return (\n \n {title && {title} }\n \n {renderDigits(day, t('countdown.days'))}\n {renderDigits(hour, t('countdown.hours'))}\n {renderDigits(min, t('countdown.minutes'))}\n {renderDigits(sec, t('countdown.seconds'))}\n \n \n );\n};\n\nexport default Countdown;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\n\nconst Container = styled.div`\n padding: 1rem;\n background-color: ${p => p.theme.color.white10};\n margin-bottom: 1rem;\n`;\n\nconst FrameContainer = styled.div`\n position: relative;\n padding-bottom: 56.25%;\n padding-top: 30px;\n height: 0;\n overflow: hidden;\n\n iframe {\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n }\n`;\n\nclass VideoPlayer extends Component {\n render() {\n const { src } = this.props;\n return (\n \n \n \n \n \n )\n }\n}\n\nexport default VideoPlayer;\n","import React, { useState } from 'react';\n// import ReactLink from '../../common/Link';\nimport styled from 'styled-components';\n// import RegistrationCounter from '../registration/Counter';\n\nimport ImageGallery from '../../common/ImageGallery';\n// import Instagram from '../../common/Instagram';\nimport Calendar from '../../calendar/Calendar';\n// import Shoutbox from '../../common/Shoutbox';\nimport { linkToTelegramChat } from '../../../utils';\nimport Countdown from '../../common/Countdown';\nimport VideoPlayer from '../../common/VideoPlayer';\n// import {\n// signupCloses,\n// signupOpens,\n// postSignupCloses,\n// postSignupOpens,\n// } from '../registration/Registration';\nimport { useTranslation, Trans } from 'react-i18next';\n// import { signupOpens } from '../registration/Registration';\n\nconst seasonStart = new Date('2025-04-12T12:00:00+02:00');\n\nconst Container = styled.div`\n display: flex;\n gap: 1rem;\n margin-bottom: 2rem;\n background-color: ${(p) => p.theme.color.containerBg};\n padding: 1rem;\n margin-top: 1rem;\n padding-top: 0;\n\n @media screen and (max-width: 800px) {\n flex-direction: column-reverse;\n flex-direction: column;\n }\n\n & > * {\n /*flex: 0 1 50%;*/\n }\n`;\n\nconst Title = styled.h1`\n margin: 0 0 1rem;\n`;\n\nconst Paragraph = styled.div`\n margin-bottom: 1rem;\n`;\n\nconst Trivia = styled.ul`\n li {\n margin-top: 1rem;\n }\n\n li::marker {\n color: ${(p) => p.theme.color.boldText};\n font-size: 1.3em;\n }\n\n strong {\n color: ${(p) => p.theme.color.boldText};\n }\n`;\n\n// const Announcement = styled.div`\n// padding: 2rem;\n// background-color: ${(p) => p.theme.color.firstBoxBg};\n// color: ${(p) => p.theme.color.firstBoxText};\n// font-size: 1.6rem;\n// line-height: 1.1em;\n// font-weight: bold;\n// text-align: center;\n\n// a {\n// color: ${(p) => p.theme.color.boldText};\n// }\n\n// hr {\n// width: 10%;\n// border-style: dashed;\n// }\n\n// @media screen and (max-width: 360px) {\n// font-size: 1.2rem;\n// padding: 1rem;\n// }\n// `;\n\n/* const Recruitment = styled.div`\n padding: 2rem;\n background-color: ${p => p.theme.color.firstBoxBg};\n color: ${p => p.theme.color.firstBoxText};\n font-size: 0.8rem;\n line-height: 0.5rem;\n font-weight: bold;\n text-align: center;\n font-style: italic;\n\n hr {\n width: 10%;\n border-style: dashed;\n }\n`; */\n\n// const Link = styled(ReactLink)`\n// color: ${(p) => p.color || p.theme.color.linkColor};\n// transition: color 0.2s ease;\n\n// &:hover,\n// &:focus {\n// color: ${(p) => p.theme.color.linkColorHover};\n// text-decoration: none;\n// }\n// `;\n\n// const CenteredParagraph = styled.section`\n// margin: 0 auto 3rem;\n// font-size: 1.2rem;\n// max-width: 80ch;\n// text-align: justify;\n// `;\n\nconst Frontpage = () => {\n const { t } = useTranslation();\n // don't disappear countdown suddenly\n const [showCountdown] = useState(new Date() < seasonStart);\n return (\n <>\n {showCountdown && (\n \n \n
\n )}\n {/* \n {new Date() >= postSignupCloses ? (\n Signup link]}\n />\n ) : new Date() >= postSignupOpens ? (\n ]}\n />\n ) : new Date() >= signupCloses ? (\n <>{t('frontpage.announcement.postregistration')}>\n ) : new Date() >= signupOpens ? (\n ]}\n />\n ) : (\n <>{t('frontpage.announcement.preregistration')}>\n )}\n */}\n {/* */}\n {/* \n Mukaan toimittamaan Radiodiodia?\n */}\n\n \n \n
\n {t('frontpage.title')} \n \n \n \n \n
{t('frontpage.didYouKnow.title')} \n
\n \n \n {' '}\n ,\n ]}\n />\n \n \n 141]}\n />\n \n \n 61]}\n />\n \n \n \n \n \n
{t('frontpage.contactUs.title')} \n
{t('frontpage.contactUs.editorialTeam')}: \n
toimitus@radiodiodi.fi \n
\n
{t('frontpage.contactUs.corporatePartnerships')}: \n
\n yrityssuhteet@radiodiodi.fi\n \n
\n \n {/* */}\n \n {/* {t('frontpage.editorialTeam.title')} */}\n \n {/* */}\n \n >\n );\n};\n\nexport default Frontpage;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { environment } from '../../../utils';\nimport { useTranslation } from 'react-i18next';\n\nconst Main = styled.main`\n background-color: ${p => p.theme.color.containerBg};\n padding: 1rem;\n`;\n\nconst Paragraph = styled.p`\n text-align: left;\n max-width: 70ch;\n`;\n\nconst ColumnContainer = styled.div`\n display: flex;\n flex-direction: row;\n\n @media screen and (max-width: 1000px) {\n flex-direction: column;\n }\n\n justify-content: space-between;\n`;\n\nconst Column = styled.span`\n margin-bottom: 1rem;\n`;\n\nconst Title = styled.h2`\n text-align: left;\n`;\n\nconst AudioPlayerContainer = styled.div`\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-between;\n margin: 0 -0.5rem;\n`;\n\nconst AudioPlayer = styled.span`\n display: flex;\n flex-direction: column;\n margin: 0 0.5rem 1rem;\n\n @supports (-moz-appearance: none) {\n width: 30%; /* fixes firefox width bug */\n }\n\n @media screen and (max-width: 700px) {\n width: 100%;\n flex-direction: row;\n justify-content: space-between;\n }\n\n @media screen and (max-width: 500px) {\n width: 100%;\n flex-direction: column;\n align-items: center;\n }\n`;\n\nconst AudioPlayerLabel = styled.label`\n margin-bottom: 0.5rem;\n\n @media screen and (max-width: 700px) {\n margin-bottom: 0;\n align-self: center;\n }\n\n @media screen and (max-width: 500px) {\n margin-bottom: 0.5rem;\n }\n`;\n\nconst Companies = () => {\n const { t } = useTranslation();\n return (\n \n \n {t('companies.contact')}:{' '}\n \n yrityssuhteet@radiodiodi.fi\n \n \n\n {t('companies.title')} \n {t('companies.paragraph1')} \n {t('companies.paragraph2')} \n {t('companies.paragraph3')} \n\n \n \n {t('companies.ads.title')} \n \n {t('companies.ads.1')} \n {t('companies.ads.2')} \n {t('companies.ads.3')} \n \n \n \n {t('companies.visibility.title')} \n \n {t('companies.visibility.1')} \n {t('companies.visibility.2')} \n {t('companies.visibility.3')} \n \n \n \n\n {t('companies.interested')} \n \n \n yrityssuhteet@radiodiodi.fi\n \n \n {t('companies.previousAds')} \n\n \n \n \n Vincit – ATK-ohjelmoitsija\n \n \n \n \n \n\n \n SRV – Diego & Alberto \n \n \n \n \n\n \n Futurice – Chilicorn.org \n \n \n \n \n \n \n );\n}\n\nexport default Companies;\n","import i18n from 'i18next';\nimport { initReactI18next } from 'react-i18next';\nimport Backend from 'i18next-http-backend';\n\ni18n.use(Backend).use(initReactI18next).init({\n lng: 'fi',\n fallbackLng: 'fi',\n react: {\n transKeepBasicHtmlNodesFor: ['br', 'strong', 'em', 'i', 'p', 'ul', 'li'],\n }\n});\n\nexport default i18n;\n","import React, { useMemo } from 'react';\nimport styled from 'styled-components';\nimport i18next from '../../../i18n';\nimport { environment } from '../../../utils';\n\nconst { REACT_APP_START_DATE, REACT_APP_END_DATE } = environment;\n\nconst Container = styled.div`\n text-align: center;\n padding: 0.5rem 1rem;\n background-color: ${(p) => p.theme.color.white10};\n margin-right: 0.5rem;\n\n @media screen and (min-width: 700px) {\n flex: 1 0 350px;\n }\n`;\n\nconst Title = styled.h4`\n margin: 0;\n`;\n\nconst DateContainer = styled.table`\n width: 100%;\n border-collapse: separate;\n border-spacing: 0 0.5rem;\n font-family: monospace;\n font-size: 1rem;\n`;\n\nconst DateCell = styled.td`\n cursor: pointer;\n position: relative;\n\n &:hover:after {\n content: '';\n z-index: -1;\n position: absolute;\n\n height: 1.6em;\n width: 1.6em;\n border-radius: 100%;\n\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n\n background-color: ${(p) => p.theme.color.redMedium};\n }\n`;\n\nconst DateHeader = styled.td`\n user-select: none;\n border-bottom: 1px solid;\n`;\n\nconst FillerDate = styled.td``;\n\nconst radioStartDate = new Date(`${REACT_APP_START_DATE}T00:00:00Z`);\nconst endDate = new Date(`${REACT_APP_END_DATE}T00:00:00Z`); // exclusive, usually 30.4. - marked with emoji\n\n// don't show days earlier than today\nconst today = new Date(0);\n// (and hope the user is in the correct timezone)\nconst now = new Date();\n// use UTC for calendar generation though so timezones etc. don't matter\ntoday.setUTCFullYear(now.getFullYear(), now.getMonth(), now.getDate());\nconst startDate = today > radioStartDate ? today : radioStartDate;\n\nconst CalendarWidget = ({ show, onDateSelect }) => {\n // Generate the rows of the calendar.\n const rows = useMemo(() => {\n const rows = [];\n // Fill also the day after end of broadcast with an emoji\n const afterEndDate = new Date(endDate);\n afterEndDate.setUTCDate(endDate.getUTCDate() + 1);\n for (\n let date = new Date(startDate);\n date <= afterEndDate;\n date.setUTCDate(date.getUTCDate() + 1)\n ) {\n // compute column from weekday\n const col = (date.getUTCDay() + 6) % 7;\n // add new row if necessary\n if (!rows.length || col === 0) {\n rows.push(\n Array(7)\n .fill()\n .map((_, index) => )\n );\n }\n if (date >= afterEndDate) {\n // last day, unselectable and has emoji\n rows[rows.length - 1][col] = (\n \n \n 🥳\n \n \n );\n } else {\n // normal selectable day\n const dateDay = date.getUTCDate();\n rows[rows.length - 1][col] = (\n onDateSelect(dateDay)}>\n {dateDay}\n \n );\n }\n }\n\n return rows.map((row, index) => {row} );\n }, [onDateSelect]);\n\n const t = i18next.t;\n\n if (!show) return null;\n\n return (\n \n {t('signup.propositions.april')} \n \n \n \n {t('signup.weekdays.mon')} \n {t('signup.weekdays.tue')} \n {t('signup.weekdays.wed')} \n {t('signup.weekdays.thu')} \n {t('signup.weekdays.fri')} \n {t('signup.weekdays.sat')} \n {t('signup.weekdays.sun')} \n \n \n {rows} \n \n \n );\n};\n\nexport default CalendarWidget;\n","import React from 'react';\n\nconst PlusIcon = () => (\n \n \n \n);\n\nconst CrossIcon = () => (\n \n \n \n);\n\nconst CalendarIcon = () => (\n \n \n \n)\n\nconst InfoIcon = () => (\n \n)\n\nexport { PlusIcon, CrossIcon, CalendarIcon, InfoIcon };\n","import React from 'react';\nimport styled from 'styled-components';\nimport { CalendarIcon } from '../Icons';\nimport { useTranslation } from 'react-i18next';\n\nconst Widget = styled.span`\n display: flex;\n align-items: center;\n\n margin: 0.5rem 0;\n user-select: none;\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n\n & > * {\n margin-right: 1em;\n }\n\n &:hover {\n color: ${(p) => p.theme.color.boldText};\n }\n\n svg {\n color: ${(p) => p.theme.color.boldText};\n width: 1em;\n height: 1em;\n }\n`;\n\nconst DatePicker = ({ date, onClick, show }) => {\n const { t } = useTranslation();\n return (\n \n \n {date || t('signup.propositions.date')} \n {show && (\n \n \n
\n )}\n {!show && (\n \n \n
\n )}\n \n );\n};\n\nexport default DatePicker;\n","import React from 'react';\nimport styled from 'styled-components';\n\nconst Widget = styled.select`\n padding: 0.5rem 1rem;\n margin-right: 0.5rem;\n user-select: none;\n font-variant-numeric: tabular-nums;\n font-size: 1rem;\n line-height: 1.3rem;\n border-radius: 0;\n appearance: none;\n`;\n\nconst leftPad = n => n >= 10 ? `${n}` : `0${n}`;\n\nconst generateOptions = () => {\n // Alkuperäiset arvot Array 24 leftPad(n)\n const times = [...Array(24).keys()].map((n, i) => {\n const hours = n;\n const minutes = '00';\n const time = `${leftPad(hours)}:${minutes}`;\n return {time} ;\n });\n return [\n --:-- ,\n ...times,\n ];\n}\n\nconst options = generateOptions();\n\nconst TimePicker = ({ time, onChange }) => {\n return (\n \n {options}\n \n );\n}\n\nexport default TimePicker;\n","import React, { useState } from 'react';\nimport styled from 'styled-components';\nimport CalendarWidget from './CalendarWidget';\nimport DatePicker from './DatePicker';\nimport TimePicker from './TimePicker';\nimport { CrossIcon } from '../Icons';\nimport { useTranslation } from 'react-i18next';\n\nconst PropositionContainer = styled.div`\n padding: 0.5rem 0 0.5rem 1rem;\n margin-bottom: 1rem;\n border-left: 4px solid ${(p) => p.theme.color.boldText};\n`;\n\nconst PropositionRow = styled.div`\n display: flex;\n justify-content: space-between;\n flex-direction: column;\n gap: 1rem;\n\n @media screen and (min-width: 700px) {\n flex-direction: row;\n align-items: flex-start;\n }\n`;\n\nconst Row = styled.div`\n display: flex;\n justify-content: space-between;\n flex-wrap: wrap;\n gap: 1rem;\n`;\n\nconst Column = styled.div`\n display: flex;\n flex-grow: 1;\n flex-direction: column;\n justify-content: flex-start;\n`;\n\nconst Label = styled.label`\n font-size: 0.9rem;\n`;\n\nconst RemoveButton = styled.span`\n display: flex;\n max-width: 30px;\n margin: 0.5rem;\n align-self: flex-end;\n cursor: pointer;\n\n &:hover svg path {\n fill: ${(p) => p.theme.color.boldText};\n }\n\n svg {\n width: 25px;\n height: 25px;\n\n path {\n fill: ${(p) => p.theme.color.boldText};\n }\n }\n`;\n\nconst Proposition = ({ onUpdateValue, startTime, endTime, date, onDelete }) => {\n const [showCalendar, setShowCalendar] = useState(true);\n const { t } = useTranslation();\n\n const onDatePickerClick = () => {\n setShowCalendar(!showCalendar);\n };\n\n const onDateSelect = (dateDay) => {\n const date = `${dateDay}.04.2025`;\n setShowCalendar(false);\n\n onUpdateValue({ date, startTime, endTime });\n };\n\n const onStartTimeChange = (event) => {\n const startTime = event.target.value;\n onUpdateValue({ date, startTime, endTime });\n };\n\n const onEndTimeChange = (event) => {\n const endTime = event.target.value;\n onUpdateValue({ date, startTime, endTime });\n };\n\n const remove = () => {\n onDelete();\n };\n\n return (\n <>\n \n \n \n \n \n \n
\n \n \n \n \n {t('signup.propositions.startTime')} \n \n \n \n {t('signup.propositions.endTime')} \n \n \n
\n \n \n >\n );\n};\n\nexport default Proposition;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\nimport { asField } from 'informed';\nimport Proposition from './Proposition';\nimport { PlusIcon } from '../Icons';\nimport i18next from '../../../i18n';\n\nconst Container = styled.div`\n margin: 10px 0;\n`;\n\nconst AddButton = styled.div`\n display: flex;\n align-content: end;\n cursor: pointer;\n\n svg {\n height: 20px;\n width: 20px;\n margin: auto 1rem;\n path {\n fill: ${(p) => p.theme.color.boldText};\n }\n }\n\n &:hover {\n color: ${(p) => p.theme.color.boldText};\n }\n`;\n\nclass PropositionPicker extends Component {\n setPropositionValue = (index) => (newValue) => {\n const { fieldState, fieldApi } = this.props;\n const { setValue } = fieldApi;\n const prev = [...fieldState.value];\n prev[index] = newValue;\n setValue(prev);\n };\n\n deleteProposition = (index) => (newValue) => {\n const { fieldState, fieldApi } = this.props;\n const { setValue } = fieldApi;\n const prev = [...fieldState.value];\n prev.splice(index, 1);\n setValue(prev);\n };\n\n renderPropositions = () => {\n const { fieldState } = this.props;\n const value = fieldState.value || [];\n\n const rows = value.map((p, i) => (\n \n ));\n\n return {rows}
;\n };\n\n onAddProposition = () => {\n const { fieldState, fieldApi } = this.props;\n const { setValue } = fieldApi;\n const oldValue = fieldState.value || [];\n\n // remove nulls\n const value = oldValue.filter((p) => !!p.date);\n\n setValue([...value, { date: null, startTime: null, endTime: null }]);\n };\n\n renderAddButton() {\n return (\n \n \n {i18next.t('signup.propositions.add')} \n \n );\n }\n\n render() {\n return (\n \n {this.renderPropositions()}\n {this.renderAddButton()}\n \n );\n }\n}\n\nexport default asField(PropositionPicker);\n","import React, { Component } from 'react';\nimport { withRouter } from 'react-router';\nimport axios from 'axios';\nimport {\n Form as InformedForm,\n Text as InformedText,\n TextArea as InformedTextArea,\n RadioGroup as InformedRadioGroup,\n Radio,\n asField,\n} from 'informed';\nimport Link from '../../common/Link';\nimport styled from 'styled-components';\nimport PropositionPicker from '../../common/PropositionPicker';\nimport { environment } from '../../../utils';\nimport i18next from '../../../i18n';\nimport { Trans } from 'react-i18next';\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\n\nconst Form = styled(InformedForm)`\n margin: 3rem 0;\n\n input,\n text,\n textarea {\n font-family: inherit;\n font-size: 1rem;\n border: 2px solid ${(p) => p.theme.color.boldText};\n }\n\n p {\n max-width: 70ch;\n }\n\n fieldset {\n border: none;\n border-top: 0.2rem solid ${(p) => p.theme.color.boldText};\n margin-top: 2rem;\n }\n\n legend {\n font-size: 1.2rem;\n padding: 0 0.5em;\n }\n\n strong {\n color: ${(p) => p.theme.color.boldText};\n }\n`;\n\nconst Fieldset = styled.fieldset`\n @media screen and (min-width: 800px) {\n label {\n display: flex;\n justify-content: space-between;\n }\n }\n`;\n\nconst CustomNumberField = asField(({ fieldState, fieldApi, ...props }) => {\n const { value } = fieldState;\n const { setValue, setTouched } = fieldApi;\n const { onChange, onBlur, initialValue, forwardedRef, ...rest } = props;\n return (\n {\n setValue(e.target.value);\n if (onChange) {\n onChange(e);\n }\n }}\n onBlur={(e) => {\n setTouched(true);\n if (onBlur) {\n onBlur(e);\n }\n }}\n />\n );\n});\n\nconst NumberField = styled(CustomNumberField)`\n padding: 0.5rem;\n max-width: 500px;\n width: 100%;\n`;\n\nconst StyledText = styled(InformedText)`\n padding: 0.5rem;\n max-width: 500px;\n width: 100%;\n`;\n\nconst StyledTextArea = styled(InformedTextArea)`\n padding: 0.5rem;\n max-width: 500px;\n width: 100%;\n`;\n\nconst Text = (props) => ;\n\nconst formatRegCode = (code) => {\n return code ? code.toUpperCase().replace(/[^A-Z0-9-]/g, '') : '';\n};\n\nconst RegCode = (props) => (\n \n);\n\nconst TextArea = (props) => (\n \n);\n\nconst RadioGroup = (props) => (\n \n);\n\nconst Label = styled.label`\n display: block;\n margin: 1em 0;\n font-weight: 600;\n\n input:not([type='checkbox']):not([type='radio']),\n textarea {\n display: block;\n }\n\n input[type='radio'],\n input[type='checkbox'] {\n margin: 0 1rem;\n }\n`;\n\nconst Submit = styled.button`\n display: block;\n width: 7em;\n padding: 1em 1.5em;\n margin: 2em auto;\n background-color: ${(p) => p.theme.color.boldText};\n font-size: 1.1rem;\n color: ${(p) => p.theme.color.white100};\n\n border: none;\n outline: none;\n cursor: pointer;\n\n &:hover,\n &:focus {\n background-color: ${(p) => p.theme.color.galleryHoverBg};\n }\n`;\n\nconst Info = styled.p`\n margin-left: 2em;\n color: ${(p) => p.theme.color.boldText};\n\n a {\n color: ${(p) => p.theme.color.bodyText};\n }\n`;\n\nconst Error = styled.div`\n color: ${(p) => p.theme.color.errorRed};\n`;\n\nconst Tag = styled.span`\n color: ${(p) => p.theme.color.blueDark};\n font-weight: 600;\n`;\n\nconst notEmptyString = (value) =>\n !value ? i18next.t('signup.empty') : undefined;\nconst validatePropositions = (propositions) => {\n if (!propositions || propositions.length === 0) {\n return 'Ehdota vähintään yhtä aikaväliä';\n }\n\n for (const p of propositions) {\n if (!p.date) {\n return i18next.t('signup.propositions.dateMissing');\n }\n if (!p.startTime) {\n return i18next.t('signup.propositions.startMissing');\n }\n if (!p.endTime) {\n return i18next.t('signup.propositions.endMissing');\n }\n }\n\n return undefined;\n};\n\nclass RegistrationForm extends Component {\n state = { preRegCodeOk: false };\n\n setFormApi = (formApi) => {\n this.formApi = formApi;\n };\n\n handlePreRegistration = async () => {\n const state = this.formApi.getState();\n try {\n const resp = await axios.post(\n `${BACKEND_URL}/api/register_code`,\n state.values\n );\n console.log(resp);\n if (resp.data.ok) {\n this.setState({\n preRegCode: state.values.preRegCode,\n preRegCodeOk: true,\n });\n } else {\n this.formApi.setError('preRegCode', resp.data.error);\n }\n } catch (err) {\n console.error(err);\n this.formApi.setError('preRegCode', 'Koodin tarkistus epäonnistui');\n }\n this.rerender();\n };\n\n handleSubmit = async () => {\n const { history } = this.props;\n const state = this.formApi.getState();\n console.log(state);\n\n try {\n if (state.values.prerecord === 'live') {\n // remove null propositions\n state.values.propositions = state.values.propositions.filter(\n (p) => p.date\n );\n }\n if (this.state.preRegCode)\n state.values.preRegCode = this.state.preRegCode;\n const resp = await axios.post(\n `${BACKEND_URL}/api/register`,\n state.values,\n {\n headers: {\n 'Accept-Language': i18next.language,\n },\n }\n );\n console.log(resp);\n const email = state.values.email;\n history.push(`/ilmo/success?email=${email}`);\n } catch (err) {\n console.error(err);\n history.push('/ilmo/error');\n }\n };\n\n getErrors = () => (this.formApi ? this.formApi.getState().errors || {} : {});\n\n getValues = () => (this.formApi ? this.formApi.getState().values || {} : {});\n\n renderErrors = () => {\n const errors = this.getErrors();\n const hasErrors = !!Object.keys(errors).length;\n if (!hasErrors) return null;\n\n return {i18next.t('signup.errors')} ;\n };\n\n rerender = () => {\n // force rerender\n this.setState({});\n };\n\n handleSubmitFailure = (data) => {\n this.rerender();\n return true;\n };\n\n setPropositionValues = (value) => {\n const formApi = this.formApi;\n if (formApi) formApi.setValue('propositions', value);\n };\n\n getPropositionValues = () => {\n const formApi = this.formApi;\n const val = formApi ? formApi.getValue('propositions') : [];\n return val || [];\n };\n\n render() {\n const errors = this.getErrors();\n const values = this.getValues();\n const t = i18next.t;\n\n const isClosed = new Date() > this.props.signupCloses;\n const isOpen = new Date() > this.props.signupOpens && !isClosed;\n\n if (!this.state.preRegCodeOk && !isOpen) {\n return (\n \n );\n }\n\n return (\n \n );\n }\n}\n\nexport default withRouter(RegistrationForm);\n","import React, { useState, useEffect, useRef, useCallback } from 'react';\r\nimport { useTranslation } from 'react-i18next';\r\nimport styled from 'styled-components';\r\nimport Program from './Program';\r\nimport { environment } from '../../utils';\r\nimport dateFormat from 'dateformat';\r\n\r\nconst {\r\n REACT_APP_BACKEND_HTTP_URL,\r\n // REACT_APP_CALENDAR_ID,\r\n REACT_APP_START_DATE,\r\n REACT_APP_END_DATE,\r\n} = environment;\r\n\r\nconst startDate = new Date(REACT_APP_START_DATE);\r\nconst endDate = new Date(REACT_APP_END_DATE);\r\n\r\nconst Button = styled.button`\r\n background-color: ${(p) => p.theme.color.boldText};\r\n color: white;\r\n padding: 0.5rem 0;\r\n font-size: 14px;\r\n border: none;\r\n min-width: 100px;\r\n cursor: pointer;\r\n\r\n &:hover {\r\n background-color: ${(p) => p.theme.color.redMedium};\r\n }\r\n\r\n @media screen and (max-width: 450px) {\r\n margin: 0.5rem 0;\r\n }\r\n`;\r\n\r\nconst Controls = styled.div`\r\n margin: 1rem 0;\r\n padding: 0.5rem 0;\r\n text-align: center;\r\n display: flex;\r\n justify-content: space-between;\r\n flex-wrap: wrap;\r\n flex-direction: row;\r\n align-items: center;\r\n\r\n @media screen and (max-width: 450px) {\r\n flex-direction: column;\r\n }\r\n`;\r\n\r\nconst groupBy = (xs, key) =>\r\n xs.reduce((rv, x) => {\r\n var v = key instanceof Function ? key(x) : x[key];\r\n (rv[v] = rv[v] || []).push(x);\r\n return rv;\r\n }, {});\r\n\r\nconst preloadImages = (images) => {\r\n images.forEach((src) => {\r\n const img = document.createElement('img');\r\n img.src = src; // Assigning the img src immediately requests the image\r\n });\r\n};\r\n\r\nconst ProgramContainer = styled.div`\r\n display: flex;\r\n align-items: center;\r\n justify-content: start;\r\n flex-direction: row;\r\n gap: 1rem;\r\n`;\r\n\r\nconst startOfDay = (date) => {\r\n // Convert the date to Finland time (Europe/Helsinki) and set to 00:00\r\n const finlandTime = new Date(\r\n new Date(date).toLocaleString('en-US', { timeZone: 'Europe/Helsinki' })\r\n );\r\n finlandTime.setHours(0, 0, 0, 0); // Set to 00:00\r\n return finlandTime.getTime();\r\n};\r\n\r\nconst endOfDay = (date) => {\r\n // Convert the date to Finland time (Europe/Helsinki) and set to 23:59\r\n const finlandTime = new Date(\r\n new Date(date).toLocaleString('en-US', { timeZone: 'Europe/Helsinki' })\r\n );\r\n finlandTime.setHours(23, 59, 59, 999); // Set to 23:59:59.999\r\n return finlandTime.getTime();\r\n};\r\n\r\nconst currentDateWithinBounds = () =>\r\n startOfDay(Math.min(endDate, Math.max(new Date(), startDate)));\r\n\r\nconst getFreeSlots = (programs, dayStart, dayEnd, previousDayPrograms = []) => {\r\n const freeSlots = [];\r\n\r\n // Include the last program from the previous day if it overlaps\r\n const lastPreviousProgram =\r\n previousDayPrograms.length > 0\r\n ? previousDayPrograms[previousDayPrograms.length - 1]\r\n : null;\r\n\r\n let adjustedDayStart = dayStart;\r\n if (lastPreviousProgram && lastPreviousProgram.end > dayStart) {\r\n adjustedDayStart = lastPreviousProgram.end; // Start after the last program from the previous day\r\n }\r\n\r\n // Sort programs by start time\r\n const sortedPrograms = programs.sort((a, b) => a.start - b.start);\r\n\r\n // Check for free time before the first program\r\n if (sortedPrograms.length > 0 && sortedPrograms[0].start > adjustedDayStart) {\r\n freeSlots.push({\r\n start: new Date(adjustedDayStart),\r\n end: new Date(sortedPrograms[0].start),\r\n });\r\n }\r\n\r\n // Find gaps between programs\r\n for (let i = 0; i < sortedPrograms.length - 1; i++) {\r\n const currentProgram = sortedPrograms[i];\r\n const nextProgram = sortedPrograms[i + 1];\r\n\r\n if (currentProgram.end < nextProgram.start) {\r\n freeSlots.push({\r\n start: new Date(currentProgram.end),\r\n end: new Date(nextProgram.start),\r\n });\r\n }\r\n }\r\n\r\n // Check for free time after the last program\r\n if (\r\n sortedPrograms.length > 0 &&\r\n sortedPrograms[sortedPrograms.length - 1].end < dayEnd\r\n ) {\r\n freeSlots.push({\r\n start: new Date(sortedPrograms[sortedPrograms.length - 1].end),\r\n end: new Date(dayEnd),\r\n });\r\n }\r\n\r\n // If no programs exist, the entire day is free\r\n if (sortedPrograms.length === 0) {\r\n freeSlots.push({\r\n start: new Date(adjustedDayStart),\r\n end: new Date(dayEnd),\r\n });\r\n }\r\n\r\n return freeSlots;\r\n};\r\n\r\nconst SmallProgram = ({ p }) => {\r\n const { t } = useTranslation();\r\n const start = dateFormat(p.start, 'HH:MM');\r\n const end = dateFormat(p.end, 'HH:MM');\r\n return (\r\n \r\n {`${start} - ${end}`} \r\n {p.title ? (\r\n {p.title}
\r\n ) : (\r\n \r\n {t('frontpage.calendar.freeSlot')} \r\n
\r\n )}\r\n \r\n );\r\n};\r\n\r\nconst SignUpCalendar = ({ oneDayPreview }) => {\r\n const { t } = useTranslation();\r\n const [all, setAll] = useState();\r\n const [today, setToday] = useState();\r\n\r\n useEffect(() => {\r\n if (Date.parse(REACT_APP_START_DATE) && Date.parse(REACT_APP_END_DATE)) {\r\n const fetchProgrammes = async () => {\r\n try {\r\n const resp = await fetch(`${REACT_APP_BACKEND_HTTP_URL}/programmes`);\r\n const data = await resp.json();\r\n if (!data || !Array.isArray(data)) {\r\n console.error('Programme data invalid. Data: ', data);\r\n return;\r\n }\r\n\r\n data.forEach((program) => {\r\n program.start = new Date(program.start);\r\n program.end = new Date(program.end);\r\n\r\n // Hotfix for removing html from descriptions\r\n if (\r\n / |/.test(\r\n `${program.image}${program.description}${program.team}${program.genre}`\r\n )\r\n ) {\r\n function removeHtml(text) {\r\n const div = document.createElement('div');\r\n div.innerHTML = text;\r\n return div.textContent.trim();\r\n }\r\n if (program.image) program.image = removeHtml(program.image);\r\n if (program.description)\r\n program.description = removeHtml(program.description);\r\n if (program.team) program.team = removeHtml(program.team);\r\n if (program.genre) program.genre = removeHtml(program.genre);\r\n }\r\n });\r\n\r\n const images = data.map((p) => p.image || '');\r\n preloadImages(images);\r\n\r\n const r = data.sort((x, y) => +x.start - y.start);\r\n const grouped = groupBy(r, (x) => startOfDay(x.start));\r\n\r\n setToday(currentDateWithinBounds());\r\n setAll(grouped);\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n };\r\n fetchProgrammes();\r\n }\r\n }, []);\r\n\r\n const bottomControlUsed = useRef(false);\r\n const topControls = useRef();\r\n\r\n const incrementDay = useCallback(\r\n (e) => {\r\n bottomControlUsed.current = e.currentTarget.dataset.bottom;\r\n setToday(startOfDay(Math.min(today + 86400000, endDate)));\r\n },\r\n [today]\r\n );\r\n const decrementDay = useCallback(\r\n (e) => {\r\n bottomControlUsed.current = e.currentTarget.dataset.bottom;\r\n setToday(startOfDay(Math.max(today - 86400000, startDate)));\r\n },\r\n [today]\r\n );\r\n\r\n useEffect(() => {\r\n // Forced scrolling is annoying but better than the bottom button jumping around when days change\r\n if (bottomControlUsed.current && topControls.current)\r\n topControls.current.scrollIntoView();\r\n }, [today]);\r\n\r\n if (!all || !today) return null;\r\n\r\n const locales = [t('frontpage.calendar.dateLocale'), 'fi-FI', 'fi'];\r\n const dateOptions = {\r\n weekday: 'long',\r\n year: 'numeric',\r\n month: 'numeric',\r\n day: 'numeric',\r\n };\r\n const date = new Date(today).toLocaleDateString(locales, dateOptions);\r\n\r\n if (oneDayPreview) {\r\n if (all[today]) {\r\n const currentProgram = all[today].find((program) => {\r\n const now = new Date();\r\n const start = program.start;\r\n const end = program.end;\r\n const hasNotEnded = end > now;\r\n const hasStarted = start < now;\r\n return hasStarted && hasNotEnded;\r\n });\r\n\r\n if (!currentProgram) {\r\n return null;\r\n }\r\n return ;\r\n } else {\r\n return null;\r\n }\r\n }\r\n\r\n const isFirstDay = today === startOfDay(startDate);\r\n const dayStart = isFirstDay\r\n ? startOfDay(today) + 12 * 60 * 60 * 1000 // skip first 12 hours of first day\r\n : startOfDay(today);\r\n const dayEnd = endOfDay(today);\r\n\r\n const previousDay = startOfDay(today - 86400000);\r\n const previousDayPrograms = all[previousDay] || [];\r\n const currentDayPrograms = all[today] || [];\r\n\r\n const freeSlots = getFreeSlots(\r\n currentDayPrograms,\r\n dayStart,\r\n dayEnd,\r\n previousDayPrograms\r\n );\r\n\r\n const content = all[today]\r\n ? [...all[today], ...freeSlots]\r\n .sort((a, b) => a.start - b.start)\r\n .map((p) => )\r\n : [];\r\n\r\n return (\r\n \r\n
{t('frontpage.calendar.title')} \r\n \r\n {t('frontpage.calendar.prev')} \r\n {date} \r\n {t('frontpage.calendar.next')} \r\n \r\n\r\n {content}\r\n \r\n );\r\n};\r\n\r\nexport default SignUpCalendar;\r\n","import React from 'react';\nimport styled from 'styled-components';\nimport Link from '../../common/Link';\nimport { useState } from 'react';\n\nimport RegistrationForm from './RegistrationForm';\nimport Countdown from '../../common/Countdown';\nimport { linkToTelegramChat } from '../../../utils';\nimport { useTranslation, Trans } from 'react-i18next';\nimport SignUpCalendar from '../../calendar/SignUpCalendar.js';\n\nconst Main = styled.main`\n background-color: ${(p) => p.theme.color.containerBg};\n padding: 1rem;\n\n p {\n max-width: 800px;\n }\n`;\nexport const signupOpens = new Date('2025-03-04T12:00:00+03:00'); // new Date('2025-03-04T12:00:00+02:00'); // initial signup\nexport const signupCloses = new Date('2025-05-1T23:59:59+02:00');\nexport const postSignupOpens = new Date('2025-03-27T21:00:00+02:00'); // signup for remaining spots\nexport const postSignupCloses = new Date('2025-05-30T01:00:00+02:00');\n\nconst Registration = () => {\n const { t } = useTranslation();\n const [showCountdown] = useState(new Date() < signupOpens);\n\n if (new Date() >= postSignupCloses) {\n return (\n \n {t('signup.closed.title')} \n \n ]}\n />\n
\n \n );\n }\n\n return (\n <>\n {showCountdown && (\n \n \n
\n )}\n \n {/* {new Date() >= postSignupOpens ? (\n {t('signup.postregistration.open')} \n ) : new Date() >= signupCloses ? (\n {t('signup.postregistration.soon')} \n ) : new Date() >= signupOpens ? (\n {t('signup.signup.title')} \n ) : (\n {t('signup.preRegistration.pageTitle')} \n )} */}\n\n {/* {new Date() >= postSignupOpens && (\n \n {t('signup.notice')} \n \n )} */}\n {t('signup.title')} \n\n {t('signup.paragraph1')}
\n \n \n {' '}\n ,\n \n {' '}\n ,\n ]}\n />\n
\n \n ,\n ,\n ,\n ]}\n />\n
\n \n {t('signup.paragraph4')}{' '}\n toimitus@radiodiodi.fi \n
\n \n\n \n \n >\n );\n};\n\nexport default Registration;\n","import React, { useState, useRef, useEffect } from 'react';\nimport axios from 'axios';\nimport useSWR from 'swr';\nimport styled from 'styled-components';\nimport { environment } from '../../../utils';\nimport { useTranslation } from 'react-i18next';\n\nconst Container = styled.div`\n p {\n max-width: 700px;\n }\n`;\n\nconst Results = styled.div``;\n\nconst Result = styled.div`\n color: ${(p) => (p.header ? p.theme.color.boldText : p.theme.color.bodyText)};\n font-weight: ${(p) => (p.header ? 'bold' : 'inherit')};\n background-color: ${(p) =>\n p.contrast ? p.theme.color.white10 : p.theme.color.white30};\n padding: 0.5rem 0.3rem;\n margin: 0.2rem 0;\n display: flex;\n flex-direction: row;\n\n @media screen and (max-width: 500px) {\n flex-direction: column;\n\n div:not(:first-child) {\n margin-top: 0.5rem;\n }\n }\n`;\n\nconst Error = styled.h2`\n text-align: center;\n margin: 1rem auto;\n font-weight: 400;\n color: ${(p) => p.theme.color.boldText};\n`;\n\nconst Column = styled.div`\n flex: 1;\n margin-left: 0.5rem;\n line-height: 1.2;\n`;\n\nconst SearchBar = styled.input`\n padding: 0.5rem;\n flex: 1;\n`;\n\nconst SearchContainer = styled.div`\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n margin-bottom: 2rem;\n`;\n\nconst Button = styled.button`\n background: none;\n background-color: ${(p) => p.theme.color.boldText};\n border: none;\n cursor: pointer;\n font-weight: 700;\n color: white;\n padding: 1em 2em;\n letter-spacing: 0.05rem;\n\n &:hover,\n &:active {\n background-color: ${(p) => p.theme.color.redMedium};\n }\n\n &:disabled {\n background-color: ${(p) => p.theme.color.bodyText};\n cursor: default;\n color: #dbdbdb;\n border: none;\n }\n`;\n\nconst SearchButton = styled(Button)`\n padding: 0.5rem;\n min-width: 5rem;\n text-align: center;\n cursor: pointer;\n`;\n\nconst TypePickerContainer = styled.div`\n display: flex;\n flex-wrap: wrap;\n justify-content: flex-start;\n margin-top: 1rem;\n gap: 0.2rem;\n`;\n\nconst Tab = styled.label`\n display: flex;\n flex-direction: row;\n align-items: center;\n\n input {\n display: none;\n }\n\n label {\n padding: 0.5rem 1rem;\n background-color: ${(p) => p.theme.color.white10};\n cursor: pointer;\n }\n\n label:hover {\n background-color: ${(p) => p.theme.color.redMedium};\n }\n\n input:checked + label {\n background-color: ${(p) => p.theme.color.boldText};\n color: ${(p) => p.theme.color.white100};\n }\n`;\n\nconst TypePicker = ({ type, setType }) => {\n const { t } = useTranslation();\n return (\n \n \n setType('title')}\n checked={type === 'title'}\n />\n {t('library.song')} \n \n \n setType('artist')}\n checked={type === 'artist'}\n />\n {t('library.artist')} \n \n \n setType('album')}\n checked={type === 'album'}\n />\n {t('library.album')} \n \n \n );\n};\n\nconst Search = ({ onInput, forwardRef }) => {\n const { t } = useTranslation();\n const onPromptKeyPress = (event) => {\n const ENTER_KEY = 13;\n\n if ([event.keyCode, event.which].includes(ENTER_KEY)) {\n onInput();\n }\n };\n\n return (\n \n \n {t('library.search')} \n \n );\n};\n\nconst PaginationContainer = styled.div`\n display: flex;\n justify-content: center;\n align-items: center;\n margin: 2rem 0;\n\n @media screen and (max-width: 500px) {\n flex-direction: column;\n }\n\n span {\n margin: 1rem 4rem;\n }\n`;\n\nconst Pagination = ({ index, setIndex, amountOfRows }) => {\n const { t } = useTranslation();\n const ROWS_PER_PAGE = 50;\n\n const isPreviousDisabled = index <= 1;\n const isNextDisabled = index * ROWS_PER_PAGE >= amountOfRows;\n if (isPreviousDisabled && isNextDisabled) {\n return null;\n }\n return (\n \n setIndex(index - 1)}>\n {t('library.previous')}\n \n \n {t('library.page')}: {index}\n \n setIndex(index + 1)}>\n {t('library.next')}\n \n \n );\n};\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\nconst fetcher = (queryString) =>\n axios\n .get(`${BACKEND_URL}/library/search?${queryString}`)\n .then((res) => res.data);\n\nconst createQueryString = (type, query, pageIndex) =>\n `type=${type}&search=${encodeURIComponent(query)}&page=${pageIndex}`;\n\nconst swrConfig = {\n dedupingInterval: 864000,\n revalidateOnFocus: false,\n revalidateOnReconnect: false,\n errorRetryCount: 3,\n};\n\n// component used to only prefetch the data on\n// the next page so that it's already loaded when\n// the user decides to go there\nconst Prefetch = ({ type, query, pageIndex }) => {\n const queryString = createQueryString(type, query, pageIndex + 1);\n useSWR(queryString, fetcher, swrConfig);\n\n return null;\n};\n\nconst Library = () => {\n const [pageIndex, setPageIndex] = useState(1);\n const [type, setType] = useState('title');\n const [query, setQuery] = useState('');\n const inputRef = useRef();\n\n const queryString = createQueryString(type, query, pageIndex);\n const { data, error } = useSWR(queryString, fetcher, swrConfig);\n\n const { t } = useTranslation();\n\n // scroll to top when the data is updated i.e.\n // the user has navigated to other page\n useEffect(() => {\n inputRef.current.scrollIntoView({ behavior: 'smooth' });\n }, [inputRef, data]);\n\n const renderResult = (result, index) => {\n if (!result || !result.title) return null;\n\n const artistData = Array.isArray(result.artist)\n ? result.artist.join(', ')\n : result.artist;\n\n const even = index % 2 === 0;\n\n return (\n \n {result.title} \n {artistData} \n {result.album} \n \n );\n };\n\n const renderResults = (results) => {\n if (!results || !Array.isArray(results)) {\n return null;\n }\n\n if (results.length === 0) {\n return {t('library.noResults')} ;\n }\n\n const rows = results.map((r, i) => renderResult(r, i));\n return (\n \n \n {t('library.song')} \n {t('library.artist')} \n {t('library.album')} \n \n {rows}\n \n );\n };\n\n const onInput = () => {\n setPageIndex(1);\n const query = inputRef.current.value;\n setQuery(query);\n };\n\n const onTypeSelect = (type) => {\n setType(type);\n onInput();\n };\n\n return (\n \n {t('library.musicLibrary')} \n {t('library.info')}
\n\n \n \n\n {!error && !data && {t('library.fetching')} }\n {error && {t('library.error')} }\n {data && renderResults(data.result)}\n \n\n \n \n );\n};\n\nexport default Library;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\nimport GoogleLogin from 'react-google-login';\nimport { checkJWTAuth } from '../../../utils';\nimport Cookie from 'universal-cookie';\nimport { parseSearch, environment } from '../../../utils';\n\nconst cookie = new Cookie();\n\nconst CLIENT_ID = environment.REACT_APP_OAUTH_CLIENT_ID;\n\nconst Container = styled.div`\n display: block;\n\n i,\n button {\n display: block;\n }\n`;\n\nconst Login = styled(GoogleLogin)`\n padding: 1rem 1.5rem;\n margin: 1rem 0;\n font-size: 1rem;\n background-color: ${p => p.theme.color.pink100};\n color: ${p => p.theme.color.white100};\n outline: none;\n border: none;\n cursor: pointer;\n`;\n\nconst Error = styled.i`\n color: ${p => p.theme.color.turquoise100};\n margin: 1rem 0;\n`;\n\nclass LoginPage extends Component {\n constructor(props) {\n super(props);\n this.state = {\n error: '',\n }\n const jwt = cookie.get('jwt');\n if (jwt) {\n this.responseGoogle({\n tokenId: jwt\n });\n }\n }\n\n responseGoogle = async resp => {\n console.log(resp);\n if (resp.error) {\n console.log('Login error.')\n cookie.remove('jwt');\n this.setState({\n error: resp.error,\n });\n return;\n }\n\n const { location, history } = this.props;\n const { search } = location;\n const params = parseSearch(search);\n const next = params.next || '/admin';\n\n const id_token = resp.tokenId;\n const ok = await checkJWTAuth(id_token);\n if (ok) {\n cookie.set('jwt', id_token);\n history.push(next);\n } else {\n cookie.remove('jwt');\n console.log('Backend auth verification failed.');\n this.setState({\n error: 'Backend auth verification failed.',\n });\n }\n }\n\n render() {\n const { error } = this.state;\n return (\n \n Log in to Radiodiodi admin \n Use your Radiodiodi.fi domain email. \n \n {error && Error: {error} }\n \n );\n }\n}\n\nexport default LoginPage;\n","import React, { Fragment } from 'react';\nimport { Trans, useTranslation } from 'react-i18next';\nimport styled from 'styled-components';\nimport Link from '../../common/Link';\n\nconst Container = styled.div`\n`;\n\nconst Question = styled.i`\n &::before {\n content: 'Q: ';\n }\n\n display: block;\n margin: 1rem 0 0.5rem;\n`;\n\nconst Answer = styled.div`\n margin: 1rem 0 3rem 1.4rem;\n`;\n\nconst EmailLink = ({ children }) => {children} ;\n\n// Stuff that can be interpolated into translation strings\nconst faqComponents = {\n email: ,\n frontpage: ,\n library: ,\n\n m3u: radiodiodi.m3u ,\n flac: https://virta.radiodiodi.fi/flac ,\n mp3: https://virta.radiodiodi.fi/mp3 ,\n aac: https://virta.radiodiodi.fi/aac ,\n fb2k: Foobar2000 ,\n vlc: VLC ,\n};\n\nconst qas = [\n {\n question: 'faq.what.q',\n answer: 'faq.what.a',\n },\n {\n question: 'faq.frequency.q',\n answer: 'faq.frequency.a',\n },\n {\n question: 'faq.streams.q',\n answer: 'faq.streams.a',\n },\n {\n question: 'faq.when.q',\n answer: 'faq.when.a',\n },\n {\n question: 'faq.where.q',\n answer: 'faq.where.a',\n },\n {\n question: 'faq.who.q',\n answer: 'faq.who.a',\n },\n {\n question: 'faq.idea.q',\n answer: 'faq.idea.a',\n },\n // , jotta toimitus voi valmistella studion erikoisempaa ohjelmaa varten. Autamme mielellämme typerienkin ideoidesi toteuttamisessa\n {\n question: 'faq.howMany.q',\n answer: 'faq.howMany.a',\n },\n {\n question: 'faq.music.q',\n answer: 'faq.music.a',\n },\n {\n question: 'faq.notAllowed.q',\n answer: 'faq.notAllowed.a',\n },\n {\n question: 'faq.tech.q',\n answer: 'faq.tech.a',\n },\n // {\n // question: 'Saako studiossa syödä/juoda? Entä alkoholi?',\n // answer: 'Vältä syömistä studiotiloissa. Alkoholi on kielletty sillä lähetys tapahtuu koulun tiloista.'\n // // answer: 'Kunhan laitteet pysyvät ehjänä ja kunnossa, mikään ei estä studiossa syömistä tai juomista.'\n // },\n {\n question: 'faq.ads.q',\n answer: 'faq.ads.a',\n },\n {\n question: 'faq.jingle.q',\n answer: 'faq.jingle.a',\n },\n {\n question: 'faq.ownJingle.q',\n answer: 'faq.ownJingle.a',\n },\n {\n question: 'faq.record.q',\n answer: 'faq.record.a',\n },\n {\n question: 'faq.prerecord.q',\n answer: 'faq.prerecord.a',\n },\n {\n question: 'faq.remote.q',\n answer: 'faq.remote.a',\n },\n {\n question: 'faq.producer.q',\n answer: 'faq.producer.a',\n },\n {\n question: 'faq.producing.q',\n answer: 'faq.producing.a',\n // answer: 'Laita sähköpostia studio@radiodiodi.fi ja liity Radiodiodin Telegram-kanaville. Tuottajakoulutuksia järjestetään kiinnostuneille studion rakennusviikolla ja ensimmäisen lähetysviikon aikana.'\n },\n {\n question: 'faq.needProducer.q',\n answer: 'faq.needProducer.a',\n },\n {\n question: 'faq.rekry.q',\n answer: 'faq.rekry.a',\n }\n];\n\nconst FAQ = () => {\n const { t } = useTranslation();\n\n return (\n \n {t('faq.title')} \n {t('faq.facts.title')} \n \n {t('faq.facts.laws')} \n {t('faq.facts.editor')} \n {t('faq.facts.finance')} \n {/* Radio-ohjelman tuottaa Radiodiodin tuottaja tai koulutettu ohjelmantekijä. */}\n {t('faq.facts.fun')} \n {t('faq.facts.experience')} \n \n \n {qas.map((qa, index) => (\n \n \n \n \n \n \n \n \n ))}\n \n );\n}\n\nexport default FAQ;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\nimport i18next from '../../../i18n';\n\nconst Container = styled.div`\n`;\n\nconst DurationInput = styled.input`\n padding: 0.5rem;\n margin-left: 1rem;\n`;\n\nconst InputLabel = styled.label`\n display: flex;\n justify-content: flex-start;\n align-items: center;\n`;\n\nconst Subtitle = styled.h4`\n`;\n\nconst AmountContainer = styled.div`\n padding: 1rem 2rem;\n`;\n\nconst Row = styled.div`\n line-height: 1.5rem;\n`;\n\nclass Programme extends Component {\n state = {\n duration: 1,\n }\n\n onInputChange = evt => {\n this.setState({\n duration: evt.target.value,\n });\n }\n\n calculateAmounts = hours => {\n const t = i18next.t;\n const calc = perc => {\n const num = perc * hours;\n const wholes = Math.floor(num);\n const decimals = num - wholes;\n const mins = Math.floor(decimals * 60);\n\n const hourPart = wholes > 0 ? t('calculator.hour', { count: wholes }) : '';\n const minutePart = mins > 0 ? t('calculator.minute', { count: mins }) : '';\n return `${hourPart} ${minutePart}`;\n };\n\n return {\n ads: calc(0.05),\n speech: calc(0.50),\n music: calc(0.35),\n jingles: calc(0.10),\n }\n }\n\n render() {\n const { duration } = this.state;\n const amounts = this.calculateAmounts(Math.abs(duration));\n const t = i18next.t;\n return (\n \n {t('calculator.title')} \n {t('calculator.description')}
\n \n {t('calculator.input')}\n \n \n\n {t('calculator.structure')} \n \n {t('calculator.talk')}: {amounts.speech}
\n {t('calculator.music')}: {amounts.music}
\n {t('calculator.jingles')}: {amounts.jingles}
\n {t('calculator.ads')}: {amounts.ads}
\n \n \n );\n }\n}\n\nexport default Programme;\n","import React from 'react';\nimport styled from 'styled-components';\nimport Link from '../../common/Link';\nimport Programme from './Programme';\nimport { useTranslation, Trans } from 'react-i18next';\n\nconst Container = styled.div`\n strong {\n color: ${(p) => p.theme.color.boldText};\n }\n`;\n\nconst TranslationWithStrong = (key) => {\n return ]} />;\n};\n\nconst Checklist = () => {\n const { t } = useTranslation();\n return (\n <>\n \n {t('checklist.title')} \n \n {t('checklist.1')} \n {t('checklist.2')} \n {t('checklist.3')} \n \n {t('checklist.4')}\n \n \n {t('checklist.5')}:{' '}\n toimitus@radiodiodi.fi \n \n \n ]}\n />\n \n {t('checklist.7')} \n {t('checklist.8')} \n {t('checklist.9')} \n {/*Osallistu kaatoon! */}\n \n\n {t('checklist.planning.title')} \n {TranslationWithStrong('checklist.planning.name')}
\n {TranslationWithStrong('checklist.planning.description')}
\n {TranslationWithStrong('checklist.planning.goal')}
\n {TranslationWithStrong('checklist.planning.theme')}
\n {/* Aikataulu. Aamuyön ohjelma voi olla hyvinkin erilaista kuin keskipäivän ohjelma.
*/}\n {TranslationWithStrong('checklist.planning.audience')}
\n {TranslationWithStrong('checklist.planning.elements')}
\n {TranslationWithStrong('checklist.planning.ads')}
\n \n \n >\n );\n};\n\nexport default Checklist;\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Route, Redirect, Switch, Link as ReactLink } from 'react-router-dom';\nimport FAQ from './FAQ';\nimport Checklist from './Checklist';\nimport { useTranslation } from 'react-i18next';\n\nconst Link = styled(ReactLink)`\n margin-right: 1rem;\n`;\n\nconst Main = styled.main`\n background-color: ${p => p.theme.color.containerBg};\n padding: 1rem;\n`;\n\nconst Guide = ({ match }) => {\n const { t } = useTranslation();\n return (\n \n {t('guide')} \n \n {t('checklist.title')}\n {t('faq.title')}\n \n \n \n \n \n \n \n );\n}\n\nexport default Guide;\n","import React from 'react';\nimport { parseSearch } from '../../../utils';\n\nconst CalendarCallback = ({ location }) => {\n const { search } = location;\n const queryParams = parseSearch(search);\n return (\n \n
Google calendar authorization \n
Copy and paste this to your terminal:
\n
\n { queryParams.code || 'No code in query params. Something went wrong!' }\n \n
There might be no prompt for the code but paste it anyway. Restart your backend afterwards!
\n
\n )\n};\n\nexport default CalendarCallback;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\n\nimport { parseSearch } from '../../../utils';\nimport i18next from '../../../i18n';\nimport { withTranslation } from 'react-i18next';\n\nconst Container = styled.div`\n margin-bottom: 2rem;\n`;\n\nconst Paragraph = styled.div`\n max-width: 700px;\n margin-bottom: 1rem;\n flex-grow: 1;\n\n hr {\n width: 50%;\n text-align: left;\n }\n`;\n\nconst Title = styled.h3`\n margin: 0;\n height: 4rem;\n`;\n\nclass RegistrationSuccess extends Component {\n render() {\n const { location } = this.props;\n const { search } = location;\n const queryParams = parseSearch(search);\n const { email } = queryParams;\n const t = i18next.t;\n\n return (\n \n \n {t('signup.success.title')} \n \n {t('signup.success.thanks')}\n \n { email && (\n \n {t('signup.success.email')} { email }.\n \n )}\n {/* \n Ohjelmantekijät kuvataan 3.4. ja 4.4. myöhemmin ilmoitettavassa paikassa. Jos jäi kysymyksiä, vastauksia löytyy postilokerosta toimitus@radiodiodi.fi. \n */}\n \n \n );\n }\n}\n\nexport default withTranslation()(RegistrationSuccess);\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\nimport i18next from '../../../i18n';\nimport { Trans, withTranslation } from 'react-i18next';\n\nconst Container = styled.div`\n margin-bottom: 2rem;\n`;\n\nconst Paragraph = styled.div`\n max-width: 700px;\n flex-grow: 1;\n\n hr {\n width: 50%;\n text-align: left;\n }\n`;\n\nconst Title = styled.h3`\n margin: 0;\n height: 4rem;\n`;\n\nclass RegistrationError extends Component {\n render() {\n const t = i18next.t;\n return (\n \n \n {t('signup.error.title')} \n \n ]} />\n \n \n \n );\n }\n}\n\nexport default withTranslation()(RegistrationError);\n","import React from 'react';\nimport Cookie from 'universal-cookie';\nimport styled from 'styled-components';\nimport { withRouter } from 'react-router';\n\nconst cookie = new Cookie();\n\nconst Button = styled.button`\n outline: none;\n border: none;\n padding: 0.5rem 1rem;\n color: ${(p) => p.theme.color.white100};\n background-color: ${(p) => p.theme.color.boldText};\n font-size: 16px;\n cursor: pointer;\n`;\n\nconst paths = ['/', '/admin'];\n\nconst logout = (history) => () => {\n paths.forEach((path) => {\n cookie.remove('jwt', { path });\n });\n\n history.push('/login');\n};\n\nconst LogoutButton = ({ history }) => {\n return Log out ;\n};\n\nexport default withRouter(LogoutButton);\n","import React from 'react';\nimport styled from 'styled-components';\nimport { Link } from 'react-router-dom';\nimport { withRouter } from 'react-router';\nimport LogoutButton from './LogoutButton';\n\nexport const errorStatusCodes = [401, 500];\n\nconst Row = styled.div`\n display: flex;\n flex-flow: row nowrap;\n align-items: center;\n\n a {\n margin-right: 0.5rem;\n }\n\n @media screen and (max-width: 600px) {\n flex-flow: column nowrap;\n align-items: flex-end;\n\n a,\n button {\n margin-bottom: 0.5rem;\n }\n }\n`;\n\nconst AdminNavbar = () => {\n return (\n \n Shoutbox\n Bans\n Reserved users\n Registrations\n Recruitment\n \n
\n );\n};\n\nexport default withRouter(AdminNavbar);\n","import styled from 'styled-components';\n\nexport const Container = styled.div`\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n flex-wrap: nowrap;\n`;\n\nexport const Column = styled.div`\n ${(p) => p.hidden && 'display: none'};\n margin: 0.5rem 0;\n flex: 1 0 auto;\n\n @media screen and (min-width: 500px) {\n min-width: 400px;\n }\n\n max-width: 100%;\n`;\n\nexport const Log = styled.div`\n max-height: 20rem;\n overflow-y: auto;\n overflow-x: hidden;\n margin-bottom: 2rem;\n`;\n\nexport const Count = styled.div`\n margin: 0.5rem 0;\n`;\n\nexport const LogRow = styled.div`\n margin: 0.5rem 0;\n cursor: pointer;\n\n &:hover {\n padding-left: 8px;\n border-left: 4px solid ${(p) => p.theme.color.boldText};\n }\n\n transition: 0.5s padding-left;\n transition: 0.1s border-left;\n min-width: 0;\n`;\n\nexport const LogRowContrast = styled.span`\n color: ${(p) => p.theme.color.boldText};\n`;\n","import React, { Component } from 'react';\nimport { LogRow, LogRowContrast } from './Styles';\n\nclass Registration extends Component {\n render() {\n const { data, onSelect } = this.props;\n return (\n onSelect(data)}>\n {data.timestamp}, {data.name} \n \n );\n }\n}\n\nexport default Registration;\n","import React from 'react';\nimport styled from 'styled-components';\n\nconst Container = styled.div`\n padding: 0.5rem;\n margin-bottom: 2rem;\n background-color: ${p => p.theme.color.white10};\n`;\n\nconst Row = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n\n @media screen and (max-width: 600px) {\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 0.5rem;\n\n .propositions {\n width: 100%;\n }\n }\n\n justify-content: space-between;\n padding: 0.2rem 0.5rem;\n border-bottom: 1px dotted ${p => p.theme.color.white100};\n\n div:last-of-type {\n text-align: right;\n }\n`;\n\nconst renderPropositions = (propositions) => {\n if (!propositions) return null;\n return propositions.map((p, index) => (\n \n {p.date}: {p.startTime}–{p.endTime}\n
\n ))\n}\n\nconst Panel = ({ data }) => {\n if (!data) return null;\n console.log(data)\n return (\n \n \n ID
\n { data._id }
\n
\n \n Registered at
\n { data.timestamp }
\n
\n \n Accept
\n { data.accept }
\n
\n \n Name
\n { data.name }
\n
\n \n Description
\n { data.description }
\n
\n \n Team
\n { data.team }
\n
\n \n Responsible
\n { data.responsible }
\n
\n \n Email
\n { data.email }
\n
\n \n Genre/type
\n { data.genre }
\n
\n \n Participants
\n { data.participants }
\n
\n \n Duration
\n { data.duration }
\n
\n \n Info
\n { data.info }
\n
\n \n Producer
\n { data.producer }
\n
\n \n Photoshoot date
\n { data.photoshoot }
\n
\n \n Time propositions
\n { renderPropositions(data.propositions) }
\n
\n \n )\n}\n\nexport default Panel;\n","import React, { Component } from 'react';\nimport axios from 'axios';\nimport Cookie from 'universal-cookie';\nimport AdminNavbar from '../../admin/AdminNavbar';\nimport Registration from '../../admin/Registration';\nimport RegistrationPanel from '../../admin/RegistrationPanel';\nimport { Count, Column, Container, Log } from '../../admin/Styles';\nimport { environment } from '../../../utils';\nimport { errorStatusCodes } from '../../admin/AdminNavbar';\n\nconst cookie = new Cookie();\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\n\nclass AdminRegistrationsPage extends Component {\n constructor(props) {\n super(props);\n this.state = {\n registrations: [],\n loading: true,\n error: null,\n selected: null,\n logScrolled: false\n };\n this.logRef = React.createRef();\n this.fetchRegistrations();\n }\n\n fetchRegistrations = async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n\n try {\n const resp = await axios.get(`${BACKEND_URL}/admin/registrations`, {\n headers: {\n Authorization: token\n }\n });\n const registrations = resp.data;\n this.setState({\n registrations,\n loading: false\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/registrations');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error, check console'\n });\n }\n };\n\n isSelected = (msg, other) => {\n return msg && other && msg._id === other._id;\n };\n\n onSelect = data => {\n console.log(data);\n this.setState({\n selected: data\n });\n };\n\n componentDidUpdate = () => {\n const { logScrolled } = this.state;\n // Scroll to bottom of chat log\n if (this.logRef.current && !logScrolled) {\n this.logRef.current.scrollTop = this.logRef.current.scrollHeight;\n this.setState({\n logScrolled: true\n });\n }\n };\n\n renderRegistrationRows = () => {\n const { registrations, loading, error, selected } = this.state;\n\n if (error) {\n return error;\n }\n\n if (loading) {\n return { rows: 'Loading...' };\n }\n\n if (registrations.length === 0) {\n return { rows: 'No registrations yet.' };\n }\n\n const rows = registrations.map((m, index) => (\n \n ));\n\n return { rows, count: rows.length };\n };\n\n render() {\n const { selected } = this.state;\n const { history } = this.props;\n const { rows, count } = this.renderRegistrationRows();\n return (\n \n \n Registrations \n {count && Total: {count} registration(s) }\n \n {rows} \n \n \n \n \n \n );\n }\n}\n\nexport default AdminRegistrationsPage;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\nimport { LogRow, LogRowContrast } from './Styles';\n\nconst Text = styled.span`\n text-overflow: ellipsis;\n overflow: hidden;\n min-width: 0;\n`;\n\nclass Message extends Component {\n select = () => {\n const { data, onSelect } = this.props;\n onSelect(data, 'message');\n }\n\n render() {\n const { data, selected } = this.props;\n return (\n \n { data.timestamp } \n { data.name }: \n { data.text } \n \n )\n }\n}\n\nexport default Message;","import React, { Component, Fragment } from 'react';\nimport styled from 'styled-components';\nimport ReactModal from 'react-modal';\nimport { removeMessage, banUserForMessage } from '../../utils';\n\nconst Container = styled.div`\n padding: 0.5rem;\n margin-bottom: 2rem;\n min-width: 0;\n background-color: ${(p) => p.theme.color.white10};\n`;\n\nconst Row = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n\n @media screen and (max-width: 400px) {\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 0.5rem;\n }\n\n justify-content: space-between;\n padding: 0.5rem;\n min-width: 0;\n`;\n\nconst Buttons = styled.div`\n @media screen and (max-width: 400px) {\n width: 100%;\n }\n\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n`;\n\nconst Button = styled.button`\n margin: 0 0.5rem;\n\n @media screen and (max-width: 400px) {\n margin: 0 0;\n }\n\n padding: 1rem;\n border: 0;\n font-size: 1rem;\n`;\n\nconst Actions = styled.div`\n flex: 1;\n`;\n\nconst Modal = styled(ReactModal)`\n width: 500px;\n\n @media screen and (max-width: 600px) {\n width: 90vw;\n }\n\n background-color: ${(p) => p.theme.color.white100};\n\n &,\n * {\n color: ${(p) => p.theme.color.grey100};\n }\n\n margin: auto;\n padding: 1rem;\n margin-top: calc(50vh - 0.5 * 400px);\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n`;\n\nconst ModalContent = styled.div`\n flex: 1;\n margin-bottom: 2rem;\n text-align: center;\n`;\n\nconst ModalButtons = styled.div`\n display: flex;\n flex-direction: row;\n\n button {\n background-color: ${(p) => p.theme.color.boldText};\n }\n`;\n\nconst ModalButton = styled(Button)`\n flex: 1;\n\n @media screen and (max-width: 400px) {\n margin: 0 0.5rem;\n }\n`;\n\nconst Text = styled.span`\n text-overflow: ellipsis;\n overflow: hidden;\n margin-left: 1rem;\n min-width: 0;\n`;\n\nclass Panel extends Component {\n state = {\n showRemoveModal: false,\n showBanModal: false,\n };\n\n ban = async () => {\n const { data, history, refresh } = this.props;\n this.setState({ showBanModal: false });\n try {\n await banUserForMessage(data._id);\n refresh();\n } catch (err) {\n console.log(err);\n if (err.unauthorized) {\n history.push('/login?next=/admin');\n }\n }\n };\n\n remove = async () => {\n const { data, history, refresh } = this.props;\n this.setState({ showRemoveModal: false });\n try {\n await removeMessage(data._id);\n refresh();\n } catch (err) {\n console.log(err);\n if (err.unauthorized) {\n history.push('/login?next=/admin');\n }\n }\n };\n\n renderModal = () => {\n const { data } = this.props;\n const { showRemoveModal, showBanModal } = this.state;\n return (\n \n \n \n Remove message? \n Username: {data.name}\n \n Message: {data.text}\n \n \n Yes \n this.setState({ showRemoveModal: false })}\n >\n No\n \n \n \n \n \n Ban user by IP? \n IP: {data.ip}\n \n \n Yes \n this.setState({ showBanModal: false })}>\n No\n \n \n \n \n );\n };\n\n render() {\n const { data } = this.props;\n\n return data ? (\n \n {this.renderModal()}\n \n Timestamp
\n {data.timestamp}
\n
\n \n ID
\n {data._id}
\n
\n \n Username
\n {data.name}
\n
\n \n Message
\n {data.text} \n
\n \n IP Address
\n {data.ip}
\n
\n \n Actions \n \n this.setState({ showRemoveModal: true })}>\n Remove\n \n this.setState({ showBanModal: true })}>\n Ban by IP\n \n \n
\n \n ) : null;\n }\n}\n\nexport default Panel;\n","import React, { Component, Fragment } from 'react';\nimport axios from 'axios';\nimport Message from '../../admin/Message';\nimport MessagePanel from '../../admin/MessagePanel';\nimport Cookie from 'universal-cookie';\nimport AdminNavbar from '../../admin/AdminNavbar';\nimport { Count, Column, Container, Log } from '../../admin/Styles';\nimport { environment } from '../../../utils';\nimport { errorStatusCodes } from '../../admin/AdminNavbar';\n\nconst cookie = new Cookie();\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\n\nconst BannedWordsPanel = ({\n words,\n field,\n handleChange,\n handleSubmit,\n handleDelete,\n}) => {\n let wordRows;\n if (words.length === 0) {\n wordRows = [No banned words
];\n } else {\n wordRows = words.map((word, idx) => {\n return (\n \n {word.word} Delete \n \n );\n });\n }\n\n return (\n \n \n \n \n Ban word:\n \n \n \n \n \n );\n};\n\nclass AdminShoutboxPage extends Component {\n state = {\n messages: [],\n selected: null,\n loading: true,\n logScrolled: false,\n filters: [],\n words: [],\n wordField: '',\n };\n logRef = React.createRef();\n state = {\n ...this.state,\n showBannedMessages: false,\n };\n\n setShowBannedMessages = (value) => {\n this.setState({ showBannedMessages: value });\n };\n\n fetchWords = async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n try {\n const res = await axios.get(`${BACKEND_URL}/admin/words`, {\n headers: {\n Authorization: token,\n },\n });\n const words = res.data.words;\n this.setState({\n words,\n loading: false,\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/shoutbox');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error loading words, check console',\n });\n }\n };\n\n fetchFilters = async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n try {\n const res = await axios.get(`${BACKEND_URL}/admin/filters`, {\n headers: {\n Authorization: token,\n },\n });\n const filters = res.data.filters;\n this.setState({\n filters,\n loading: false,\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/shoutbox');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error loading filters, check console',\n });\n }\n };\n\n fetchMessages = async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n\n try {\n const resp = await axios.get(`${BACKEND_URL}/admin/messages`, {\n headers: {\n Authorization: token,\n },\n });\n const messages = resp.data.messages;\n this.setState({\n messages,\n loading: false,\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/shoutbox');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error loading messages, check console',\n });\n }\n };\n\n componentDidMount() {\n this.refresh();\n }\n\n componentDidUpdate = () => {\n const { logScrolled } = this.state;\n // Scroll to bottom of chat log\n if (this.logRef.current && !logScrolled) {\n this.logRef.current.scrollTop = this.logRef.current.scrollHeight;\n this.setState({\n logScrolled: true,\n });\n }\n };\n\n onSelect = (data, type) => {\n console.log(data);\n this.setState({\n selected: data,\n });\n };\n\n toggleFilter = (filter) => async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n const nextState = filter.state ? 'off' : 'on';\n const slug = filter.slug;\n try {\n const res = await axios.post(\n `${BACKEND_URL}/admin/filters/${slug}/${nextState}`,\n null,\n {\n headers: {\n Authorization: token,\n },\n }\n );\n const updatedFilter = res.data;\n this.setState({\n filters: this.state.filters.map((f) =>\n f.slug === updatedFilter.slug ? updatedFilter : f\n ),\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/shoutbox');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error while togling filter, check console',\n });\n }\n };\n\n handleWordDelete = (word) => async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n const id = word._id;\n try {\n // eslint-disable-next-line no-unused-vars\n const res = await axios.delete(\n `${BACKEND_URL}/admin/words/remove/${id}`,\n {\n headers: {\n Authorization: token,\n },\n }\n );\n this.setState({\n words: this.state.words.filter((w) => w._id !== id),\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/shoutbox');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error while deleting banned word, check console',\n });\n }\n };\n\n isSelected = (msg, other) => {\n return msg && other && msg._id === other._id;\n };\n\n refresh = () => {\n this.fetchMessages();\n this.fetchFilters();\n this.fetchWords();\n };\n\n wordFieldHandleChange = (event) => {\n this.setState({ wordField: event.target.value });\n };\n\n wordFieldHandleSubmit = async (event) => {\n event.preventDefault();\n const { history } = this.props;\n const token = cookie.get('jwt');\n const word = this.state.wordField;\n try {\n await axios.post(`${BACKEND_URL}/admin/words/${word}`, null, {\n headers: {\n Authorization: token,\n },\n });\n this.fetchWords();\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/shoutbox');\n return;\n }\n }\n this.setState({ wordField: '' });\n };\n\n renderContent = () => {\n const { messages, filters, selected, loading, words, wordField } =\n this.state;\n const { history } = this.props;\n if (loading) {\n return Loading... ;\n }\n\n let filterRows;\n if (filters.length === 0) {\n filterRows = [No filters available.
];\n } else {\n filterRows = (\n \n {filters.map((filter) => {\n const state = filter.state ? 'ON' : 'OFF';\n const nextState = filter.state ? 'OFF' : 'ON';\n\n return (\n \n {filter.slug} {filter.description}, state:{' '}\n {state} \n \n Turn {nextState}!\n \n \n );\n })}\n \n );\n }\n\n let messageRows, count;\n if (messages.length === 0) {\n messageRows = No shoutbox messages.
;\n } else {\n messageRows = messages.map((m, index) => (\n \n ));\n count = messageRows.length;\n }\n\n return (\n \n Shoutbox filters \n {filterRows} \n Banned words \n \n this.setShowBannedMessages(!this.state.showBannedMessages)\n }\n >\n {this.state.showBannedMessages ? 'Hide' : 'Expand'}\n \n {this.state.showBannedMessages && (\n \n \n \n )}\n Shoutbox messages \n {count && Total: {count} shoutbox messages(s) }\n \n {messageRows} \n \n \n \n \n \n );\n };\n\n render() {\n return (\n \n \n {this.renderContent()}\n \n );\n }\n}\n\nexport default AdminShoutboxPage;\n","import React, { Component, Fragment } from 'react';\nimport styled from 'styled-components';\nimport ReactModal from 'react-modal';\nimport { liftBan } from '../../utils';\n\nconst Container = styled.div`\n padding: 0.5rem;\n margin-bottom: 2rem;\n background-color: ${(p) => p.theme.color.white10};\n`;\n\nconst Row = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n\n @media screen and (max-width: 400px) {\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 0.5rem;\n }\n\n justify-content: space-between;\n padding: 0.5rem;\n`;\n\nconst Button = styled.button`\n @media screen and (max-width: 400px) {\n margin: 0 0;\n }\n\n background-color: ${(p) => p.theme.color.boldText};\n color: ${(p) => p.theme.color.white100};\n padding: 1rem;\n border: none;\n outline: none;\n font-size: 1rem;\n cursor: pointer;\n`;\n\nconst Actions = styled.div`\n flex: 1;\n`;\n\nconst Modal = styled(ReactModal)`\n width: 500px;\n\n @media screen and (max-width: 600px) {\n width: 90vw;\n }\n\n background-color: ${(p) => p.theme.color.white100};\n\n &,\n * {\n color: ${(p) => p.theme.color.grey100};\n }\n\n margin: auto;\n padding: 1rem;\n margin-top: calc(50vh - 0.5 * 400px);\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n`;\n\nconst ModalContent = styled.div`\n flex: 1;\n margin-bottom: 2rem;\n text-align: center;\n`;\n\nconst ModalButtons = styled.div`\n display: flex;\n flex-direction: row;\n\n button {\n margin: 1rem;\n background-color: ${(p) => p.theme.color.boldText};\n }\n`;\n\nconst ModalButton = styled(Button)`\n flex: 1;\n\n @media screen and (max-width: 400px) {\n margin: 0 0.5rem;\n }\n`;\n\nclass Panel extends Component {\n state = {\n showRemoveModal: false,\n };\n\n remove = async () => {\n const { data, history, refresh } = this.props;\n this.setState({ showRemoveModal: false });\n try {\n await liftBan(data.ip);\n refresh();\n } catch (err) {\n console.log(err);\n if (err.unauthorized) {\n history.push('/login?next=/admin');\n }\n }\n };\n\n renderModal = () => {\n const { data } = this.props;\n const { showRemoveModal } = this.state;\n return (\n \n \n \n Lift ban? \n {data.name}, IP: {data.ip}\n \n \n Yes \n this.setState({ showRemoveModal: false })}\n >\n No\n \n \n \n \n );\n };\n\n render() {\n const { data } = this.props;\n\n return data ? (\n \n {this.renderModal()}\n \n Time of ban
\n {data.timeOfBan}
\n
\n \n Time of last message
\n {data.timeOfMessage}
\n
\n \n ID
\n {data._id}
\n
\n \n Username
\n {data.name}
\n
\n \n Last message
\n {data.text}
\n
\n \n IP Address
\n {data.ip}
\n
\n \n Actions \n this.setState({ showRemoveModal: true })}>\n Lift ban\n \n
\n \n ) : null;\n }\n}\n\nexport default Panel;\n","import React, { Component } from 'react';\nimport { LogRow } from './Styles';\n\nclass Ban extends Component {\n render() {\n const { data, onSelect } = this.props;\n return (\n onSelect(data, 'ban')}>\n { data.name }, IP: { data.ip }\n \n );\n }\n}\n\nexport default Ban;","import React, { Component, Fragment } from 'react';\nimport axios from 'axios';\nimport BanPanel from '../../admin/BanPanel';\nimport Ban from '../../admin/Ban';\nimport Cookie from 'universal-cookie';\nimport AdminNavbar from '../../admin/AdminNavbar';\nimport { Count, Column, Container, Log } from '../../admin/Styles';\nimport { environment } from '../../../utils';\nimport { errorStatusCodes } from '../../admin/AdminNavbar';\n\nconst cookie = new Cookie();\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\n\nclass AdminBansPage extends Component {\n state = {\n bans: [],\n selected: null,\n loading: true,\n logScrolled: false\n };\n logRef = React.createRef();\n\n fetchBans = async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n\n try {\n const resp = await axios.get(`${BACKEND_URL}/admin/users/banned`, {\n headers: {\n Authorization: token\n }\n });\n const bans = resp.data.bans;\n this.setState({\n bans,\n loading: false\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/bans');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error, check console'\n });\n }\n };\n\n componentDidMount() {\n this.refresh();\n }\n\n componentDidUpdate = () => {\n const { logScrolled } = this.state;\n // Scroll to bottom of chat log\n if (this.logRef.current && !logScrolled) {\n this.logRef.current.scrollTop = this.logRef.current.scrollHeight;\n this.setState({\n logScrolled: true\n });\n }\n };\n\n onSelect = (data, type) => {\n console.log(data);\n this.setState({\n selected: data\n });\n };\n\n isSelected = (msg, other) => {\n return msg && other && msg._id === other._id;\n };\n\n refresh = () => {\n this.fetchBans();\n };\n\n renderContent = () => {\n const { bans, selected, loading } = this.state;\n const { history } = this.props;\n if (loading) {\n return Loading... ;\n }\n\n let banRows, count;\n if (bans.length === 0) {\n banRows = No bans.
;\n } else {\n banRows = bans.map((m, index) => (\n \n ));\n count = banRows.length;\n }\n\n return (\n \n {count && Total: {count} ban(s) }\n \n {banRows} \n \n \n \n \n \n );\n };\n\n render() {\n return (\n \n \n Bans \n {this.renderContent()}\n \n );\n }\n}\n\nexport default AdminBansPage;\n","import React, { Component } from 'react';\nimport { LogRow } from './Styles';\n\nclass ReservedName extends Component {\n render() {\n const { data, onSelect } = this.props;\n return (\n onSelect(data, 'reserved')}>\n { data.name }, IP: { data.ip }\n \n );\n }\n}\n\nexport default ReservedName;","import React, { Component } from 'react';\nimport styled from 'styled-components';\n\nconst Container = styled.div`\n padding: 0.5rem;\n margin-bottom: 2rem;\n background-color: ${p => p.theme.color.white10};\n`;\n\nconst Row = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n\n @media screen and (max-width: 400px) {\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 0.5rem;\n }\n\n justify-content: space-between;\n padding: 0.5rem;\n`;\n\nclass Panel extends Component {\n\n render() {\n const { data } = this.props;\n\n return data ? (\n \n \n ID
\n { data._id }
\n
\n \n Username
\n { data.name }
\n
\n \n IP Address
\n { data.ip }
\n
\n \n ) : null;\n }\n}\n\nexport default Panel;","import React, { Component, Fragment } from 'react';\nimport axios from 'axios';\nimport ReservedName from '../../admin/ReservedName';\nimport ReservedNamePanel from '../../admin/ReservedNamePanel';\nimport Cookie from 'universal-cookie';\nimport AdminNavbar from '../../admin/AdminNavbar';\nimport { Count, Column, Container, Log } from '../../admin/Styles';\nimport { environment } from '../../../utils';\nimport { errorStatusCodes } from '../../admin/AdminNavbar';\n\nconst cookie = new Cookie();\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\n\nclass AdminReservedPage extends Component {\n state = {\n reservedNames: [],\n selected: null,\n loading: true,\n logScrolled: false\n };\n logRef = React.createRef();\n\n fetchReservedUsers = async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n\n try {\n const resp = await axios.get(`${BACKEND_URL}/admin/users/reserved`, {\n headers: {\n Authorization: token\n }\n });\n const reservedNames = resp.data.reserved;\n this.setState({\n reservedNames,\n loading: false\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/reserved_users');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error, check console'\n });\n }\n };\n\n componentDidMount() {\n this.refresh();\n }\n\n componentDidUpdate = () => {\n const { logScrolled } = this.state;\n // Scroll to bottom of chat log\n if (this.logRef.current && !logScrolled) {\n this.logRef.current.scrollTop = this.logRef.current.scrollHeight;\n this.setState({\n logScrolled: true\n });\n }\n };\n\n onSelect = (data, type) => {\n console.log(data);\n this.setState({\n selected: data\n });\n };\n\n isSelected = (msg, other) => {\n return msg && other && msg._id === other._id;\n };\n\n refresh = () => {\n this.fetchReservedUsers();\n };\n\n renderContent = () => {\n const { reservedNames, selected, loading } = this.state;\n const { history } = this.props;\n\n if (loading) {\n return Loading... ;\n }\n\n let reservedNameRows, count;\n if (reservedNames.length === 0) {\n reservedNameRows = No reserved names.
;\n } else {\n reservedNameRows = reservedNames.map((m, index) => (\n \n ));\n count = reservedNameRows.length;\n }\n\n return (\n \n {count && Total: {count} reserved name(s) }\n \n {reservedNameRows} \n \n \n \n \n \n );\n };\n\n render() {\n return (\n \n \n Reserved users \n {this.renderContent()}\n \n );\n }\n}\n\nexport default AdminReservedPage;\n","import React, { Component } from 'react';\nimport { LogRow } from './Styles';\n\nclass Recruitment extends Component {\n render() {\n const { data, onSelect } = this.props;\n return (\n onSelect(data, 'recruitment')}>\n { data.name }\n \n );\n }\n}\n\nexport default Recruitment;","import React, { Component } from 'react';\nimport styled from 'styled-components';\n\nconst Container = styled.div`\n padding: 0.5rem;\n margin-bottom: 2rem;\n background-color: ${p => p.theme.color.white10};\n`;\n\nconst Row = styled.div`\n display: flex;\n flex-direction: row;\n align-items: center;\n\n @media screen and (max-width: 400px) {\n flex-direction: column;\n align-items: flex-start;\n margin-bottom: 0.5rem;\n }\n\n justify-content: space-between;\n padding: 0.5rem;\n`;\n\nclass Panel extends Component {\n\n render() {\n const { data } = this.props;\n\n return data ? (\n \n \n ID
\n { data._id }
\n
\n \n Timestamp
\n { data.timestamp }
\n
\n \n Name
\n { data.name }
\n
\n \n Email
\n { data.email }
\n
\n \n Roles
\n {data.roles && data.roles.join(', ')}
\n
\n \n Application:
\n
\n \n {data.message.split('\\n').map((item, key) => {\n return {item} \n })}
\n
\n\n \n ) : null;\n }\n}\n\nexport default Panel;","import React, { Component, Fragment } from 'react';\nimport axios from 'axios';\nimport Recruitment from '../../admin/Recruitment';\nimport RecruitmentPanel from '../../admin/RecruitmentPanel';\nimport Cookie from 'universal-cookie';\nimport AdminNavbar from '../../admin/AdminNavbar';\nimport { Count, Column, Container, Log } from '../../admin/Styles';\nimport { environment } from '../../../utils';\nimport { errorStatusCodes } from '../../admin/AdminNavbar';\n\nconst cookie = new Cookie();\n\nconst BACKEND_URL = environment.REACT_APP_BACKEND_HTTP_URL;\n\nclass AdminRecruitmentPage extends Component {\n state = {\n recruitments: [],\n selected: null,\n loading: true,\n logScrolled: false\n };\n logRef = React.createRef();\n\n fetchRecruitment = async () => {\n const { history } = this.props;\n const token = cookie.get('jwt');\n\n try {\n const resp = await axios.get(`${BACKEND_URL}/admin/recruitment`, {\n headers: {\n Authorization: token\n }\n });\n const recruitment = resp.data;\n this.setState({\n recruitments: recruitment,\n loading: false\n });\n } catch (err) {\n console.error(err);\n if (err.response && errorStatusCodes.includes(err.response.status)) {\n cookie.remove('jwt');\n history.push('/login?next=/admin/recruitment');\n return;\n }\n\n this.setState({\n loading: false,\n error: 'Error, check console'\n });\n }\n };\n\n componentDidMount() {\n this.refresh();\n }\n\n componentDidUpdate = () => {\n const { logScrolled } = this.state;\n // Scroll to bottom of chat log\n if (this.logRef.current && !logScrolled) {\n this.logRef.current.scrollTop = this.logRef.current.scrollHeight;\n this.setState({\n logScrolled: true\n });\n }\n };\n\n onSelect = (data, type) => {\n console.log(data);\n this.setState({\n selected: data\n });\n };\n\n isSelected = (msg, other) => {\n return msg && other && msg._id === other._id;\n };\n\n refresh = () => {\n this.fetchRecruitment();\n };\n\n renderContent = () => {\n const { recruitments, selected, loading } = this.state;\n const { history } = this.props;\n\n if (loading) {\n return Loading... ;\n }\n\n let recruitmentRows, count;\n if (recruitments.length === 0) {\n recruitmentRows = No applications.
;\n } else {\n recruitmentRows = recruitments.map((m, index) => (\n \n ));\n count = recruitmentRows.length;\n }\n\n return (\n \n {count && Total: {count} application(s) }\n \n {recruitmentRows} \n \n \n \n \n \n );\n };\n\n render() {\n return (\n \n \n Recruitment \n {this.renderContent()}\n \n );\n }\n}\n\nexport default AdminRecruitmentPage;\n","import React, { useState, useEffect, createContext } from 'react';\nimport { environment } from '../../utils';\n\nconst WS_URL = environment.REACT_APP_BACKEND_WS_URL;\n\nexport const SocketContext = createContext(null);\n\nconst SocketProvider = ({ children }) => {\n const [connection, setConnection] = useState(() => new WebSocket(WS_URL));\n\n const reconnect = () => {\n console.log(\"Reconnecting WebSocket...\");\n setConnection(new WebSocket(WS_URL));\n };\n\n useEffect(() => {\n connection.onopen = () => {\n console.log('WebSocket connection established');\n }\n connection.onerror = (evt) => {\n console.log(`WebSocket error. Data: ${evt.data}`);\n }\n connection.onclose = () => setTimeout(reconnect, 1000);\n return () => { connection.close(); };\n }, [connection]);\n\n return (\n \n {children}\n \n );\n};\n\nexport default SocketProvider;\n","import React, { useState, createContext } from 'react';\n\nexport const ChatContext = createContext(null);\n\nconst ChatProvider = ({ children }) => {\n const [chatLog, setChatLog] = useState([]);\n\n return (\n \n {children}\n \n );\n};\n\nexport default ChatProvider;\n","import React, { useRef, useEffect, useCallback, useContext } from 'react';\nimport styled from 'styled-components';\nimport Cookie from 'universal-cookie';\nimport dateFormat from 'dateformat';\nimport { SocketContext } from './SocketProvider';\nimport { ChatContext } from './ChatProvider';\n\nimport verified from '../../svg/check-mark.svg';\n\nconst MAX_MESSAGES = 100;\nconst MESSAGE_MAX_LENGTH = 500;\nconst USERNAME_MAX_LENGTH = 16;\n\nconst cookie = new Cookie();\n\nconst Container = styled.div`\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n padding: 1rem;\n max-height: calc(100vh - 2rem);\n background-color: ${(p) => p.theme.color.white10};\n`;\n\nconst Log = styled.div`\n width: 100%;\n flex: 1;\n overflow: auto;\n font-size: 0.8rem;\n line-height: 1.1rem;\n\n scrollbar-color: #aaa #0000;\n scrollbar-width: thin;\n\n &::-webkit-scrollbar {\n width: 0.5rem;\n }\n\n &::-webkit-scrollbar-track {\n opacity: 0;\n }\n\n &::-webkit-scrollbar-thumb {\n background: #888;\n }\n\n &::-webkit-scrollbar-thumb:hover {\n background: #aaa;\n }\n`;\n\nconst Row = styled.div`\n padding: 0.3rem;\n font-size: 1rem;\n ${(p) => p.error && `color: ${(p) => p.theme.color.turquoise100}`};\n display: flex;\n align-items: flex-start;\n`;\n\nconst InputContainer = styled.div`\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n`;\n\nconst SendButton = styled.a`\n padding: 0.5rem;\n margin: 0.5rem;\n cursor: pointer;\n background-color: ${(p) => p.theme.color.white100};\n color: ${(p) => p.theme.color.grey100};\n\n &:hover {\n text-decoration: none;\n background-color: ${(p) => p.theme.color.boldText};\n color: ${(p) => p.theme.color.white100};\n }\n`;\n\nconst Username = styled.input`\n padding: 0.5rem;\n margin: 0.5rem;\n flex: 1;\n`;\n\nconst InputRow = styled.div`\n flex: 4;\n display: flex;\n`;\n\nconst Prompt = styled.input`\n flex: 1;\n padding: 0.5rem;\n margin: 0.5rem;\n`;\n\nconst Verified = styled.img`\n width: 16px;\n margin: 0 0.3rem 0 0;\n filter: invert(1);\n`;\n\nconst Timestamp = styled.div`\n white-space: nowrap;\n margin-right: 0.3rem;\n display: flex;\n justify-content: space-between;\n font-size: 0.8rem;\n font-weight: bold;\n opacity: 0.8;\n`;\n\nconst RowText = styled.span`\n word-break: break-word;\n`;\n\nconst RowUser = styled.span`\n white-space: pre;\n font-weight: bold;\n color: ${(p) => p.theme.color.boldText};\n\n &::after {\n content: ': ';\n color: ${(p) => p.theme.color.white100};\n }\n`;\n\nconst Block = styled.span`\n display: block;\n word-break: break-all;\n`;\n\nconst Shoutbox = () => {\n const connection = useContext(SocketContext);\n const logContext = useContext(ChatContext);\n const cookieRef = useRef(null);\n const chatLogRef = useRef(null);\n const usernameRef = useRef(null);\n const msgRef = useRef(null);\n\n const showError = useCallback(\n (evt) => {\n logContext.setLog([\n {\n error: true,\n name: 'SERVER',\n text: 'Huutislaatikko ei saa yhteyttä! :(',\n timestamp: new Date(),\n },\n ]);\n },\n [logContext]\n );\n\n const handleData = useCallback(\n (evt) => {\n const data = JSON.parse(evt.data);\n\n // Hack to get the current state of the log with the setter function\n let currentLog;\n logContext.setLog((current) => {\n currentLog = current;\n return current;\n });\n\n if (data.initial) {\n logContext.setLog(data.initial);\n } else if (data.message) {\n const newLog = currentLog.concat([data.message]);\n if (newLog.length > MAX_MESSAGES) {\n newLog.splice(0, 1);\n }\n logContext.setLog(newLog);\n } else if (data.erase) {\n const id = data.erase;\n const filtered = currentLog.filter((m) => m._id !== id);\n logContext.setLog(filtered);\n }\n },\n [logContext]\n );\n\n const sendMessage = () => {\n const text = msgRef.current.value,\n username = usernameRef.current.value;\n\n const authorization = cookie.get('jwt');\n if (!username || username.length === 0) {\n alert('A username is required!');\n return;\n }\n\n if (!text || text.length === 0) {\n alert('A message is required!');\n return;\n }\n\n if (text.length > MESSAGE_MAX_LENGTH) {\n alert(`Message too long! Max: ${MESSAGE_MAX_LENGTH} characters.`);\n return;\n }\n\n if (username.length > USERNAME_MAX_LENGTH) {\n alert(`Username too long! Max: ${USERNAME_MAX_LENGTH} characters.`);\n return;\n }\n\n console.log(`Send message: ${text}, username: ${username}`);\n connection.send(\n JSON.stringify({\n name: username,\n text,\n authorization,\n })\n );\n\n msgRef.current.value = '';\n };\n\n const setUsername = () => {\n const username = usernameRef.current.value;\n cookieRef.current.set('username', username);\n };\n\n const renderRows = (rows) => {\n // Filter out messages from before 2025\n rows = rows.filter(\n (row) =>\n new Date(Date.parse(row.timestamp)) >= new Date('2025-04-01T00:00:00Z')\n );\n return rows.map((row, index) => (\n \n \n \n {dateFormat(new Date(Date.parse(row.timestamp)), 'dd.mm HH:MM')}\n \n \n \n {row.reserved && }\n {row.name} \n {row.text} \n \n
\n ));\n };\n\n useEffect(() => {\n connection.addEventListener('message', handleData);\n connection.addEventListener('error', showError);\n\n return () => {\n connection.removeEventListener('message', handleData);\n connection.removeEventListener('error', showError);\n };\n }, [connection, handleData, showError]);\n\n useEffect(() => {\n cookieRef.current = new Cookie();\n const username = cookieRef.current.get('username') || '';\n usernameRef.current.value = username;\n }, []);\n\n useEffect(() => {\n chatLogRef.current.scrollTop = chatLogRef.current.scrollHeight;\n });\n\n const onPromptKeyPress = (event) => {\n const ENTER_KEY = 13;\n\n if ([event.keyCode, event.which].includes(ENTER_KEY)) {\n sendMessage();\n }\n };\n\n console.log(logContext.log);\n\n return (\n \n {renderRows(logContext.log)} \n\n \n \n \n \n {'>'} \n \n \n \n );\n};\n\nexport default Shoutbox;\n","import React from 'react';\nimport styled from 'styled-components';\n//import placeholderImg from '../../images/placeholder_dark.svg'\nimport dateFormat from 'dateformat';\nimport { environment } from '../../utils';\n\nconst ProgramBlock = styled.div`\n font-size: 24px;\n\n padding: 1.5rem;\n min-height: ${(p) => (p.maintainance ? 'none' : '150px')};\n\n &::after {\n content: '';\n clear: both;\n display: table;\n }\n\n background-color: ${(p) => p.theme.color.containerBg};\n margin-bottom: 1em;\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n`;\n\nconst Column = styled.div`\n flex: ${(p) => p.flex};\n /* display: flex; */\n flex-direction: column;\n`;\n\nconst Image = styled.img`\n height: 220px;\n width: 220px;\n background-size: cover;\n margin-right: 1.5rem;\n`;\n\nconst Time = styled.span`\n font-size: 1em;\n`;\n\nconst Title = styled.h4`\n margin: 0.5em 0;\n font-size: 1.3em;\n border-bottom: 1px solid ${(p) => p.theme.color.boldText};\n word-wrap: break-word;\n`;\n\nconst Genre = styled.span`\n margin-top: -4px;\n color: ${(p) => p.theme.color.boldText};\n letter-spacing: 0.04em;\n font-size: 0.9em;\n`;\n\nconst Author = styled.span`\n display: inline-block;\n margin: 0.5rem 0;\n font-weight: 500;\n font-size: 0.8em;\n`;\n\nconst Paragraph = styled.p`\n font-size: 1em;\n line-height: 1.4;\n margin: 0.5em 0;\n`;\n\nconst PlaceholderImage = ({ alt }) => (\n \n);\n\nconst ProgramImage = ({ src, alt }) => {\n // const originalHref = src.replace('/ohjelmat', '/ohjelmat/original');\n\n return (\n // \n \n // \n );\n};\n\nconst InfoScreenProgram = ({ p, oneDayPreview }) => {\n const maintainance = p.title === 'HUOLTOTAUKO';\n const img =\n p.image && p.image.trim() ? (\n \n ) : (\n \n );\n\n const startDate = dateFormat(p.start, 'HH:MM');\n const endDate = dateFormat(p.end, 'HH:MM');\n\n return (\n \n {img} \n \n {`${startDate} - ${endDate}`} \n \n {p.title} - {p.team} \n \n {p.description && {p.description} }\n {p.genre} \n \n \n );\n};\n\nexport default InfoScreenProgram;\n","import React, { useEffect, useMemo, useState } from 'react';\nimport styled from 'styled-components';\nimport { environment } from '../../utils';\nimport InfoScreenProgram from './InfoScreenProgram';\n\nconst { \n REACT_APP_BACKEND_HTTP_URL,\n REACT_APP_START_DATE,\n REACT_APP_END_DATE\n} = environment;\n\n\nconst Title = styled.h1`\n display: flex;\n justify-content: space-between;\n font-size: 2rem;\n margin: 0 0 2rem;\n`;\n\nconst startDate = new Date(REACT_APP_START_DATE)\nconst endDate = new Date(REACT_APP_END_DATE)\n\nconst preloadImages = (images) => {\n images.forEach((src) => {\n const img = document.createElement('img');\n img.src = src; // Assigning the img src immediately requests the image\n });\n}\n\nconst InfoScreenCalendar = ({ count = 5 }) => {\n const [all, setAll] = useState();\n const [now, setNow] = useState(Date.now());\n\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 60000);\n return () => clearInterval(timer);\n }, []);\n\n useEffect((() => {\n if (Date.parse(REACT_APP_START_DATE) && Date.parse(REACT_APP_END_DATE)) {\n const fetchProgrammes = async () => {\n try {\n const resp = await fetch(`${REACT_APP_BACKEND_HTTP_URL}/programmes`)\n const data = await resp.json();\n if (!data || !Array.isArray(data)) {\n console.error('Programme data invalid. Data: ', data);\n return;\n }\n\n data.forEach(program => {\n program.start = new Date(program.start);\n program.end = new Date(program.end);\n\n // Hotfix for removing html from descriptions\n if (/ |/.test(`${program.image}${program.description}${program.team}${program.genre}`)) {\n function removeHtml(text) {\n const div = document.createElement(\"div\");\n div.innerHTML = text;\n return div.textContent.trim();\n }\n if (program.image) program.image = removeHtml(program.image);\n if (program.description) program.description = removeHtml(program.description);\n if (program.team) program.team = removeHtml(program.team);\n if (program.genre) program.genre = removeHtml(program.genre);\n }\n })\n\n const images = data.map(p => p.image || '');\n preloadImages(images);\n\n const filtered = data.filter(p => p.start >= startDate && p.end <= endDate)\n const sorted = filtered.sort((x, y) => + x.start - y.start);\n setAll(sorted);\n } catch (error) {\n console.error(error);\n }\n }\n fetchProgrammes();\n }\n }), []);\n\n const upcoming = useMemo(\n () => all && all.filter(p => p.end > now).slice(0, count),\n [all, now, count],\n );\n\n if (!all) return null;\n\n const content = upcoming && upcoming.map(p => );\n\n return (\n \n
\n Tulevia radio-ohjelmia
\n Upcoming programmes
\n \n {content}\n
\n )\n}\n\nexport default InfoScreenCalendar\n","import React, { useEffect, useState } from 'react';\nimport styled from 'styled-components';\n\nimport InfoScreenCalendar from '../../calendar/InfoScreenCalendar';\nimport { HeaderLogo } from '../../common/Header';\nimport Countdown from '../../common/Countdown';\n\nconst CountdownContainer = styled.div`\n margin-bottom: 4rem;\n`;\n\nconst CountdownTitle = styled.h1`\n display: flex;\n justify-content: space-between;\n font-size: 2rem;\n margin: 0 0 2rem;\n`;\n\nconst countdownTo = new Date('2025-04-12T12:00:00+03:00');\n\nconst InfoScreen = () => {\n const [showCountdown, setShowCountdown] = useState(Date.now() < countdownTo);\n\n useEffect(() => {\n const timer = setInterval(() => setShowCountdown(Date.now() < countdownTo), 5000);\n return () => clearInterval(timer);\n }, []);\n\n useEffect(() => {\n const timer = setTimeout(() => window.location.reload(), 300e3);\n return () => clearTimeout(timer);\n }, []);\n\n return (\n <>\n \n {showCountdown && (\n \n \n Lähetyskauden alkuun:
\n Broadcast will start in:
\n \n \n \n )}\n \n >\n );\n}\n\nexport default InfoScreen;\n","import React from 'react';\nimport styled from 'styled-components';\n\n// import RecruitmentForm from './RecruitmentForm';\n// import { useTranslation, Trans } from 'react-i18next';\nimport { useTranslation } from 'react-i18next';\n\nconst Main = styled.main`\n background-color: ${p => p.theme.color.containerBg};\n padding: 1rem;\n\n p {\n max-width: 700px;\n }\n`;\n\nconst Recruitment = () => {\n const { t } = useTranslation();\n return (\n \n {/* {t('rekry.title')} \n {t('rekry.paragraph1')}
\n {t('rekry.paragraph2')}
\n \n , ]} />\n
*/}\n\n {/* Hae tuottajaksi Radiodiodiin! \n \n Lorem ipsum dolor sit amet joo salee tarvitaan tuottajia\n
\n \n Tähän lörinää siitä mitä tuottaja tekee\n
*/}\n \n {t('rekry.closed')} \n {/* */}\n \n );\n}\n\nexport default Recruitment;\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\n\nimport { parseSearch } from '../../../utils';\nimport i18next from '../../../i18n';\nimport { withTranslation } from 'react-i18next';\n\nconst Container = styled.div`\n margin-bottom: 2rem;\n`;\n\nconst Paragraph = styled.div`\n max-width: 700px;\n margin-bottom: 1rem;\n flex-grow: 1;\n\n hr {\n width: 50%;\n text-align: left;\n }\n`;\n\nconst Title = styled.h3`\n margin: 0;\n height: 4rem;\n`;\n\nclass RecruitmentSuccess extends Component {\n render() {\n const { location } = this.props;\n const { search } = location;\n const queryParams = parseSearch(search);\n const { email } = queryParams;\n const t = i18next.t;\n\n return (\n \n \n {t('signup.success.title')} \n \n {t('rekry.success.description')}\n \n { email && (\n \n {t('rekry.success.email')} { email }.\n \n )}\n \n \n );\n }\n}\n\nexport default withTranslation()(RecruitmentSuccess);\n","import React, { Component } from 'react';\nimport styled from 'styled-components';\nimport i18next from '../../../i18n';\nimport { Trans, withTranslation } from 'react-i18next';\n\nconst Container = styled.div`\n margin-bottom: 2rem;\n`;\n\nconst Paragraph = styled.div`\n max-width: 700px;\n flex-grow: 1;\n\n hr {\n width: 50%;\n text-align: left;\n }\n`;\n\nconst Title = styled.h3`\n margin: 0;\n height: 4rem;\n`;\n\nclass RecruitmentError extends Component {\n render() {\n const t = i18next.t;\n return (\n \n \n {t('rekry.error.title')} \n \n ]} />\n \n \n \n );\n }\n}\n\nexport default withTranslation()(RecruitmentError);\n","import React, { useEffect } from 'react';\nimport {\n BrowserRouter as Router,\n Route,\n Switch,\n Redirect,\n useParams,\n useLocation,\n} from 'react-router-dom';\nimport Header from '../common/Header';\nimport Footer from '../common/Footer';\nimport Background from '../common/Background';\nimport Frontpage from '../pages/frontpage/Frontpage';\nimport Companies from '../pages/sponsors/Companies';\nimport Registration from '../pages/registration/Registration';\nimport Library from '../pages/library/Library';\nimport Login from '../pages/admin/Login';\nimport Guide from '../pages/guide/Guide';\n// import English from '../pages/english/English';\nimport CalendarCallback from '../pages/calendar-callback/CalendarCallback';\nimport RegistrationSuccess from '../pages/registration/Success';\nimport RegistrationError from '../pages/registration/Error';\nimport AdminRegistrationsPage from '../pages/admin/AdminRegistrationsPage';\nimport AdminShoutboxPage from '../pages/admin/AdminShoutboxPage';\nimport AdminBansPage from '../pages/admin/AdminBansPage';\nimport AdminReservedPage from '../pages/admin/AdminReservedPage';\nimport AdminRecruitmentPage from '../pages/admin/AdminRecruitmentPage';\n// import Player from '../common/Player';\nimport Shoutbox from '../common/Shoutbox';\nimport ChatProvider from '../common/ChatProvider';\nimport InfoScreen from '../pages/infoscreen/InfoScreen';\nimport Recruitment from '../pages/recruitment/Recruitment';\nimport RecruitmentSuccess from '../pages/recruitment/Success';\nimport RecruitmentError from '../pages/recruitment/Error';\nimport { useTranslation } from 'react-i18next';\n\nconst LanguageSwitcher = () => {\n const { i18n } = useTranslation();\n const { lang } = useParams();\n const location = useLocation();\n const defaultLanguage = 'fi';\n\n useEffect(() => {\n if (location.pathname === '/register') {\n i18n.changeLanguage('en');\n } else if (lang === undefined || !['fi', 'en'].includes(lang)) {\n i18n.changeLanguage(defaultLanguage);\n } else {\n i18n.changeLanguage(lang);\n }\n }, [lang, i18n, defaultLanguage]);\n\n return null;\n};\n\nexport default () => {\n return (\n \n \n \n \n \n \n \n \n \n {/* */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n {/* */}\n \n {/* */}\n 404 } />\n \n \n \n \n \n \n );\n};\n","import { createGlobalStyle } from 'styled-components';\n\nexport const theme = {\n color: {\n bgBlue: '#1A1830',\n bgDark: 'rgba(33, 33, 33, 1)',\n grey100: 'rgba(30, 29, 50, 1)',\n white100: 'rgba(255, 255, 255, 1.0)',\n white70: 'rgba(255, 255, 255, 0.7)',\n white30: 'rgba(255, 255, 255, 0.3)',\n white10: 'rgba(255, 255, 255, 0.10)',\n\n // 2025 colors\n bgLight: '#DCF6DC', // Changed\n containerBg: '#FEFFEE', // Changed\n blueDark: '#720078', // Changed\n blueLight: '#ff00ff',\n boldText: '#275328', // Changed\n redMedium: '#258a27', // Changed\n errorRed: '#ff0000',\n highlightCol: 'rgba(220, 246, 220, 1)', // Changed\n bodyText: '#275328', // Changed\n // firstBoxBg: 'rgba(131, 165, 242, .31)',\n // firstBoxText: '#ff00ff',\n countdownBg: '#bbf2bb',\n linkColor: '#008E04', // Changed\n // linkColorHover: '#FF9C94',\n headingColor: '#275328', // Changed\n headerLinkColor: '#275328', // Changed\n // englishLinkColor: '#275328', //Changed\n galleryHoverBg: '#720078',\n galleryHoverText: 'white',\n\n // make sure we can see unused colors\n orange100: 'lime',\n orangedark100: 'lime',\n turquoise100: 'lime',\n pink100: 'lime',\n darkpink100: 'lime',\n bgGreen: 'lime',\n lightOrange: 'lime',\n realOrange: 'lime',\n darkOrange: 'lime',\n white2: 'lime',\n },\n font: {\n heading: 'Montserrat, sans-serif', // Similar to Avenir, serif headings.\n body: 'Montserrat, sans-serif', // Similar to Avenir, body text.\n },\n};\n\nexport const GlobalStyle = createGlobalStyle`\n body {\n font-family: ${theme.font.body};\n font-weight: 500;\n letter-spacing: 0.5px;\n max-width: 1000px;\n margin: 0 auto 0;\n padding: 1rem;\n line-height: 1.5rem;\n overflow-x: hidden;\n position: relative;\n }\n\n html {\n box-sizing: border-box;\n background-color: ${theme.color.bgLight};\n color: ${theme.color.bodyText};\n }\n\n *,\n *::before,\n *::after {\n box-sizing: inherit;\n }\n\n h1,\n h2 {\n line-height: 2rem;\n font-size: 1.5rem;\n font-family: ${theme.font.heading};\n font-weight: bolder;\n color: ${theme.color.headingColor};\n display: flex;\n margin: 0;\n padding: 1.5rem 0 0;\n }\n\n h3 {\n font-size: 1.5rem;\n color: ${theme.color.headingColor};\n }\n\n a {\n color: ${theme.color.linkColor};\n text-decoration: none;\n cursor: pointer;\n\n &:hover {\n text-decoration: underline;\n }\n }\n\n strong {\n font-weight: 700;\n }\n`;\n\nexport default GlobalStyle;\n","import React, { Component, Suspense } from 'react';\n\nimport Routes from './routes/Routes';\nimport SocketProvider from './common/SocketProvider';\nimport { ThemeProvider } from 'styled-components';\nimport { GlobalStyle, theme } from '../theme';\n// import { environment } from '../utils';\n\n// console.log('environment:', environment);\n\nclass App extends Component {\n render() {\n return (\n }>\n \n \n \n \n \n \n \n );\n }\n}\n\nexport default App;\n","import React from 'react';\nimport { hydrate, render } from 'react-dom';\nimport App from './components/App';\nimport './i18n';\n\nconst rootElement = document.getElementById('root');\nif (rootElement.hasChildNodes()) {\n hydrate( , rootElement);\n} else {\n render( , rootElement);\n}\n","module.exports = __webpack_public_path__ + \"static/media/check-mark.1b1d3d0a.svg\";"],"sourceRoot":""}