├── .gitignore ├── .prettierrc.json ├── shared ├── tsconfig.json ├── missing-types.d.ts └── state.ts ├── server ├── tsconfig.json ├── render.tsx ├── components │ └── pages │ │ ├── big-screen │ │ ├── styles.css │ │ └── index.tsx │ │ ├── header │ │ └── index.tsx │ │ ├── logged-out │ │ └── index.tsx │ │ ├── admin │ │ ├── topics │ │ │ └── index.tsx │ │ ├── index.tsx │ │ ├── simple-login │ │ │ └── index.tsx │ │ └── styles.css │ │ ├── logged-in │ │ └── index.tsx │ │ ├── big-screen-iframe │ │ └── index.tsx │ │ └── user-page │ │ ├── index.tsx │ │ └── styles.css ├── missing-types.d.ts ├── utils.ts ├── config.ts ├── index.ts ├── big-screen │ └── index.tsx ├── auth │ └── index.tsx ├── user │ └── index.tsx ├── admin │ └── index.tsx └── state.ts ├── client ├── tsconfig.json ├── missing-types.d.ts ├── big-screen-iframe │ └── index.tsx ├── admin │ └── index.tsx ├── admin-topics │ └── index.tsx ├── user │ └── index.tsx ├── components │ ├── select │ │ └── index.tsx │ ├── big-screen │ │ ├── vs.tsx │ │ ├── champion-scores.tsx │ │ ├── iframe.tsx │ │ ├── audio.tsx │ │ └── index.tsx │ ├── color-select │ │ └── index.tsx │ ├── vote │ │ ├── vote-buttons.tsx │ │ └── index.tsx │ ├── transition │ │ └── index.tsx │ └── admin │ │ ├── presentation-view │ │ └── index.tsx │ │ ├── index.tsx │ │ ├── bracket │ │ └── index.tsx │ │ ├── iframe │ │ └── index.tsx │ │ ├── selected-bracket │ │ └── index.tsx │ │ ├── champions │ │ └── index.tsx │ │ └── vote │ │ └── index.tsx ├── big-screen │ └── index.ts ├── ws │ └── index.ts └── utils.ts ├── generic-tsconfig.json ├── lib ├── node-external-plugin.js ├── resolve-dirs-plugin.js ├── consts-plugin.js ├── compress-plugin.js ├── asset-plugin.js ├── simple-ts.js ├── css-plugin.js └── client-bundle-plugin.js ├── missing-types.d.ts ├── config.js ├── CONTRIBUTING.md ├── package.json ├── rollup.config.js ├── start.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .DS_Store 3 | node_modules 4 | .data 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } 5 | -------------------------------------------------------------------------------- /shared/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../generic-tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["esnext", "dom", "dom.iterable"], 5 | "types": [] 6 | }, 7 | "include": ["./**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../generic-tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["esnext", "dom"], 5 | "types": ["node"] 6 | }, 7 | "references": [{ "path": "../client" }, { "path": "../shared" }] 8 | } 9 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../generic-tsconfig.json", 3 | "compilerOptions": { 4 | "lib": ["esnext", "dom", "dom.iterable"], 5 | "types": [] 6 | }, 7 | "references": [{ "path": "../shared" }], 8 | "include": ["./**/*"] 9 | } 10 | -------------------------------------------------------------------------------- /generic-tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "experimentalDecorators": true, 4 | "target": "ES2020", 5 | "downlevelIteration": true, 6 | "module": "esnext", 7 | "jsx": "react", 8 | "jsxFactory": "h", 9 | "strict": true, 10 | "moduleResolution": "node", 11 | "outDir": ".data/ts-tmp", 12 | "composite": true, 13 | "declarationMap": true, 14 | "baseUrl": "./", 15 | "rootDir": "./", 16 | "allowSyntheticDefaultImports": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /client/missing-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | /// 14 | -------------------------------------------------------------------------------- /shared/missing-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | /// 14 | -------------------------------------------------------------------------------- /client/big-screen-iframe/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, render } from 'preact'; 14 | import BigScreen from 'client/components/big-screen'; 15 | 16 | render(, document.querySelector('.big-screen-container')!); 17 | -------------------------------------------------------------------------------- /server/render.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import render from 'preact-render-to-string'; 14 | import { h, VNode } from 'preact'; 15 | 16 | export function renderPage(vnode: VNode) { 17 | return '' + render(vnode); 18 | } 19 | -------------------------------------------------------------------------------- /client/admin/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, render } from 'preact'; 14 | import Admin from 'client/components/admin'; 15 | import { keepServerAlive } from 'client/utils'; 16 | 17 | keepServerAlive(); 18 | render(, document.querySelector('.admin-container')!); 19 | -------------------------------------------------------------------------------- /client/admin-topics/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, render } from 'preact'; 14 | import AdminTopics from 'client/components/admin-topics'; 15 | import { keepServerAlive } from 'client/utils'; 16 | 17 | keepServerAlive(); 18 | render(, document.querySelector('.topics-container')!); 19 | -------------------------------------------------------------------------------- /lib/node-external-plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | // Check that a node module exists, but treat it as external. 14 | export default function() { 15 | return { 16 | name: 'node-external', 17 | resolveId(id) { 18 | try { 19 | require.resolve(id); 20 | return { id, external: true }; 21 | } catch (err) {} 22 | }, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /client/user/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, render } from 'preact'; 14 | import Vote from 'client/components/vote'; 15 | 16 | declare global { 17 | interface Window { 18 | initialState: Vote['props']['initialState']; 19 | } 20 | } 21 | 22 | render( 23 | , 24 | document.querySelector('.vote-container')!, 25 | ); 26 | -------------------------------------------------------------------------------- /lib/resolve-dirs-plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { resolve } from 'path'; 14 | 15 | export default function resolveDirs(paths) { 16 | return { 17 | name: 'resolve-dirs', 18 | async resolveId(id) { 19 | const foundMatch = paths.some( 20 | path => id === path || id.startsWith(path + '/'), 21 | ); 22 | if (!foundMatch) return; 23 | return resolve(await this.resolveId('./' + id, './')); 24 | }, 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /missing-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | declare module 'asset-url:*' { 14 | const value: string; 15 | export default value; 16 | } 17 | 18 | declare module 'consts:title' { 19 | const value: string; 20 | export default value; 21 | } 22 | 23 | declare module 'consts:subTitle' { 24 | const value: string; 25 | export default value; 26 | } 27 | 28 | declare module 'consts:webSocketOrigin' { 29 | const value: string; 30 | export default value; 31 | } 32 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | 14 | /** Displayed to the user, and on the big screen, and the */ 15 | export const title = 'Big Web Quiz'; 16 | /** Displayed to the user, and on the big screen */ 17 | export const subTitle = 'The over-engineered way to vote on stuff'; 18 | /** 19 | * Set WEB_SOCKET_ORIGIN if you want to use a different origin for the web socket. 20 | * You probably don't. 21 | */ 22 | export const webSocketOrigin = process.env.WEB_SOCKET_ORIGIN || ''; 23 | -------------------------------------------------------------------------------- /server/components/pages/big-screen/styles.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | html, 14 | body { 15 | background: #000; 16 | margin: 0; 17 | padding: 0; 18 | overflow: hidden; 19 | height: 100%; 20 | } 21 | 22 | html:fullscreen { 23 | cursor: none; 24 | 25 | iframe { 26 | pointer-events: none; 27 | } 28 | } 29 | 30 | iframe { 31 | position: absolute; 32 | top: 50%; 33 | left: 50%; 34 | width: 1920px; 35 | height: 1080px; 36 | border: none; 37 | transform: translate(-50%, -50%); 38 | } 39 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution, 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to <https://cla.developers.google.com/> to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google.com/conduct/). 29 | -------------------------------------------------------------------------------- /lib/consts-plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | const moduleStart = 'consts:'; 14 | 15 | export default function constsPlugin(consts) { 16 | return { 17 | name: 'consts-plugin', 18 | resolveId(id) { 19 | if (!id.startsWith(moduleStart)) return; 20 | return id; 21 | }, 22 | load(id) { 23 | if (!id.startsWith(moduleStart)) return; 24 | const key = id.slice(moduleStart.length); 25 | 26 | if (!(key in consts)) { 27 | this.error(`Cannot find const: ${key}`); 28 | return; 29 | } 30 | 31 | return `export default ${JSON.stringify(consts[key])}`; 32 | }, 33 | }; 34 | } 35 | -------------------------------------------------------------------------------- /client/components/select/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, FunctionalComponent, JSX } from 'preact'; 14 | 15 | const Select: FunctionalComponent<JSX.HTMLAttributes> = props => { 16 | const { class: className, ...selectProps } = props; 17 | 18 | return ( 19 | <div class={'select' + (className ? ' ' + className : '')}> 20 | <select {...selectProps}></select> 21 | <div class="select-icon"> 22 | <svg class="fill-current h-4 w-4" viewBox="0 0 20 20"> 23 | <path d="M9.3 13l.7.7L15.7 8l-1.5-1.4-4.2 4.2-4.2-4.2L4.3 8z" /> 24 | </svg> 25 | </div> 26 | </div> 27 | ); 28 | }; 29 | 30 | export default Select; 31 | -------------------------------------------------------------------------------- /client/big-screen/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | const iframe = document.querySelector('iframe') as HTMLIFrameElement; 14 | const { width, height } = iframe.getBoundingClientRect(); 15 | 16 | function resizeIframe() { 17 | const xScale = document.documentElement.offsetWidth / width; 18 | const yScale = document.documentElement.offsetHeight / height; 19 | const scale = Math.min(xScale, yScale); 20 | iframe.style.transform = `translate(-50%, -50%) scale(${scale})`; 21 | } 22 | 23 | window.onresize = resizeIframe; 24 | resizeIframe(); 25 | 26 | window.onkeydown = (event: KeyboardEvent) => { 27 | if (event.key === 'f') { 28 | document.documentElement.requestFullscreen(); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /server/missing-types.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | /// <reference path="../missing-types.d.ts" /> 14 | 15 | declare module 'client-bundle:*' { 16 | const value: string; 17 | export default value; 18 | export const imports: string[]; 19 | } 20 | 21 | declare module 'css:*' { 22 | const value: string; 23 | export default value; 24 | export const inline: string; 25 | } 26 | 27 | // Types for our session 28 | declare namespace Express { 29 | interface Session extends SessionData { 30 | user?: UserSession; 31 | voterId: string; 32 | simpleAdminPassword?: string; 33 | } 34 | } 35 | 36 | interface UserSession { 37 | email: string; 38 | emailVerified: boolean; 39 | name: string; 40 | picture?: string; 41 | id: string; 42 | } 43 | -------------------------------------------------------------------------------- /server/components/pages/header/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, FunctionalComponent } from 'preact'; 14 | 15 | interface Props { 16 | user?: UserSession; 17 | } 18 | 19 | const Header: FunctionalComponent<Props> = ({ user }) => { 20 | if (!user) return <header />; 21 | 22 | return ( 23 | <header class="main-header"> 24 | <img 25 | width="40" 26 | height="40" 27 | alt={user.name} 28 | src={`${user.picture}=s${40}-c`} 29 | srcset={`${user.picture}=s${80}-c 2x`} 30 | tabIndex={0} 31 | class="user-image" 32 | /> 33 | <form method="post" action="/auth/logout"> 34 | <button class="unbutton log-out-button">Logout</button> 35 | </form> 36 | </header> 37 | ); 38 | }; 39 | 40 | export default Header; 41 | -------------------------------------------------------------------------------- /client/components/big-screen/vs.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, FunctionalComponent, RenderableProps } from 'preact'; 14 | 15 | interface Props { 16 | colorFrom?: string; 17 | colorTo?: string; 18 | } 19 | 20 | const VS: FunctionalComponent<Props> = ({ 21 | colorFrom, 22 | colorTo, 23 | children, 24 | }: RenderableProps<Props>) => ( 25 | <div 26 | class="vs-circle" 27 | style={{ 28 | '--color-from': colorFrom || '', 29 | '--color-to': colorTo || '', 30 | }} 31 | > 32 | <div class="vs-outer vs-outer-1"></div> 33 | <div class="vs-outer vs-outer-2"></div> 34 | <div class="vs-outer vs-outer-3"></div> 35 | <div class="vs-outer vs-outer-4"></div> 36 | <div class="vs-innermost-circle">{children || 'VS'}</div> 37 | </div> 38 | ); 39 | 40 | export default VS; 41 | -------------------------------------------------------------------------------- /lib/compress-plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { brotliCompress } from 'zlib'; 14 | import { promisify } from 'util'; 15 | 16 | const compress = promisify(brotliCompress); 17 | 18 | export default function() { 19 | return { 20 | name: 'compress-plugin', 21 | async generateBundle(options, bundle) { 22 | const compressRe = /\.(js|css|svg|html)$/; 23 | 24 | await Promise.all( 25 | Object.values(bundle).map(async entry => { 26 | if (entry.type !== 'asset') return; 27 | if (!compressRe.test(entry.fileName)) return; 28 | const output = await compress(entry.source); 29 | this.emitFile({ 30 | type: 'asset', 31 | source: output, 32 | fileName: entry.fileName + '.br', 33 | }); 34 | }), 35 | ); 36 | }, 37 | }; 38 | } 39 | -------------------------------------------------------------------------------- /server/components/pages/logged-out/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, FunctionalComponent } from 'preact'; 14 | import UserPage from '../user-page'; 15 | import { palette } from 'shared/state'; 16 | import { getHexColor } from 'client/utils'; 17 | 18 | const LoggedOut: FunctionalComponent = () => { 19 | return ( 20 | <UserPage> 21 | <div class="log-in-container"> 22 | <form method="post" action="/auth/login"> 23 | <button 24 | class="unbutton vote-button" 25 | style={{ 26 | '--color-from': getHexColor(palette[5][0]), 27 | '--color-to': getHexColor(palette[5][1]), 28 | }} 29 | > 30 | Log in 31 | </button> 32 | </form> 33 | </div> 34 | </UserPage> 35 | ); 36 | }; 37 | 38 | export default LoggedOut; 39 | -------------------------------------------------------------------------------- /server/components/pages/admin/topics/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, FunctionalComponent } from 'preact'; 14 | 15 | import cssPath from 'css:../styles.css'; 16 | import bundleURL from 'client-bundle:client/admin-topics'; 17 | import title from 'consts:title'; 18 | 19 | const TopicsAdminPage: FunctionalComponent = () => { 20 | return ( 21 | <html> 22 | <head> 23 | <title>Topics - Admin - {title} 24 | 25 | 26 | 36 |
37 | 38 | ); 39 | }; 40 | 41 | export default LoggedIn; 42 | -------------------------------------------------------------------------------- /server/components/pages/big-screen-iframe/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2019 Google Inc. All Rights Reserved. 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * Unless required by applicable law or agreed to in writing, software 8 | * distributed under the License is distributed on an "AS IS" BASIS, 9 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | * See the License for the specific language governing permissions and 11 | * limitations under the License. 12 | */ 13 | import { h, FunctionalComponent } from 'preact'; 14 | 15 | import cssPath from 'css:./styles.css'; 16 | import bundleURL, { imports } from 'client-bundle:client/big-screen-iframe'; 17 | import title from 'consts:title'; 18 | 19 | const BigScreenIframePage: FunctionalComponent<{}> = () => { 20 | return ( 21 | 22 | 23 | {title} 24 | 25 | 29 | 30 |