diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..849f9d151 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +dist/ +.vscode/ +node_modules/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..ebc14d509 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM node:13.10.1-buster + +COPY . /app/src +WORKDIR /app/src +RUN npm i && \ + npm run build +CMD ["npm", "run", "start"] \ No newline at end of file diff --git a/manifest.json b/manifest.json index 5e30b54cb..442f4e920 100644 --- a/manifest.json +++ b/manifest.json @@ -1,37 +1,37 @@ { - "name": "Vue Hackernews 2.0", - "short_name": "Vue HN", + "name": "HN Time-Machine", + "short_name": "HN ⏳", "icons": [{ - "src": "/public/logo-120.png", - "sizes": "120x120", - "type": "image/png" - }, { - "src": "/public/logo-144.png", - "sizes": "144x144", - "type": "image/png" - }, { - "src": "/public/logo-152.png", - "sizes": "152x152", - "type": "image/png" - }, { - "src": "/public/logo-192.png", - "sizes": "192x192", - "type": "image/png" - }, { - "src": "/public/logo-256.png", - "sizes": "256x256", - "type": "image/png" - }, { - "src": "/public/logo-384.png", - "sizes": "384x384", - "type": "image/png" - }, { + "src": "/public/logo-120.png", + "sizes": "120x120", + "type": "image/png" + }, { + "src": "/public/logo-144.png", + "sizes": "144x144", + "type": "image/png" + }, { + "src": "/public/logo-152.png", + "sizes": "152x152", + "type": "image/png" + }, { + "src": "/public/logo-192.png", + "sizes": "192x192", + "type": "image/png" + }, { + "src": "/public/logo-256.png", + "sizes": "256x256", + "type": "image/png" + }, { + "src": "/public/logo-384.png", + "sizes": "384x384", + "type": "image/png" + }, { "src": "/public/logo-512.png", "sizes": "512x512", "type": "image/png" - }], + }], "start_url": "/", "background_color": "#f2f3f5", "display": "standalone", "theme_color": "#f60" -} +} \ No newline at end of file diff --git a/package.json b/package.json index b8c7a74c8..e82c3d9bc 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "vue-hackernews-2.0", + "name": "nostalgia-hn", "description": "A Vue.js project", "author": "Evan You ", "private": true, @@ -23,11 +23,15 @@ "extract-text-webpack-plugin": "^3.0.2", "firebase": "4.6.2", "lru-cache": "^4.1.1", + "node-fetch": "^2.6.0", "route-cache": "0.4.3", "serve-favicon": "^2.4.5", "vue": "^2.5.22", + "vue-client-only": "^2.0.0", + "vue-collapsible": "^2.0.0", "vue-router": "^3.0.1", "vue-server-renderer": "^2.5.22", + "vue-star-rating": "^1.6.1", "vuex": "^3.0.1", "vuex-router-sync": "^5.0.0" }, diff --git a/public/logo-120.png b/public/logo-120.png index f5a580ff6..c850b6a8c 100644 Binary files a/public/logo-120.png and b/public/logo-120.png differ diff --git a/public/logo-144.png b/public/logo-144.png index 622ee81ce..625883367 100644 Binary files a/public/logo-144.png and b/public/logo-144.png differ diff --git a/public/logo-152.png b/public/logo-152.png index 197ed282e..1838e1c32 100644 Binary files a/public/logo-152.png and b/public/logo-152.png differ diff --git a/public/logo-192.png b/public/logo-192.png index 11fc88229..fc2bec6f6 100644 Binary files a/public/logo-192.png and b/public/logo-192.png differ diff --git a/public/logo-256.png b/public/logo-256.png index 10e8600f3..a8019540f 100644 Binary files a/public/logo-256.png and b/public/logo-256.png differ diff --git a/public/logo-384.png b/public/logo-384.png index 916192665..c2bfdb51b 100644 Binary files a/public/logo-384.png and b/public/logo-384.png differ diff --git a/public/logo-48.png b/public/logo-48.png index a6c29b4a2..46ee85fa6 100644 Binary files a/public/logo-48.png and b/public/logo-48.png differ diff --git a/public/logo-512.png b/public/logo-512.png index ac8f68624..cfbbe125a 100644 Binary files a/public/logo-512.png and b/public/logo-512.png differ diff --git a/server.js b/server.js index f7b7330b5..8d68a49ca 100644 --- a/server.js +++ b/server.js @@ -16,7 +16,7 @@ const serverInfo = const app = express() -function createRenderer (bundle, options) { +function createRenderer(bundle, options) { // https://github.com/vuejs/vue/blob/dev/packages/vue-server-renderer/README.md#why-use-bundlerenderer return createBundleRenderer(bundle, Object.assign(options, { // for component caching @@ -78,7 +78,7 @@ app.use('/service-worker.js', serve('./dist/service-worker.js')) // https://www.nginx.com/blog/benefits-of-microcaching-nginx/ app.use(microcache.cacheSeconds(1, req => useMicroCache && req.originalUrl)) -function render (req, res) { +function render(req, res) { const s = Date.now() res.setHeader("Content-Type", "text/html") @@ -87,7 +87,7 @@ function render (req, res) { const handleError = err => { if (err.url) { res.redirect(err.url) - } else if(err.code === 404) { + } else if (err.code === 404) { res.status(404).send('404 | Page Not Found') } else { // Render Error Page or Redirect @@ -98,7 +98,7 @@ function render (req, res) { } const context = { - title: 'Vue HN 2.0', // default title + title: 'HN Time-Machine', // default title url: req.url } renderer.renderToString(context, (err, html) => { diff --git a/src/App.vue b/src/App.vue index ff8643cab..bd03f89ed 100644 --- a/src/App.vue +++ b/src/App.vue @@ -2,17 +2,14 @@
@@ -22,81 +19,114 @@ diff --git a/src/api/create-api-client.js b/src/api/create-api-client.js index 1a92e7415..e823dc9a3 100644 --- a/src/api/create-api-client.js +++ b/src/api/create-api-client.js @@ -5,3 +5,7 @@ export function createAPI ({ config, version }) { Firebase.initializeApp(config) return Firebase.database().ref(version) } + +export function fetchData(...params) { + return window.fetch(...params); +} diff --git a/src/api/create-api-server.js b/src/api/create-api-server.js index f7bb7d1fc..18745226a 100644 --- a/src/api/create-api-server.js +++ b/src/api/create-api-server.js @@ -1,5 +1,6 @@ import Firebase from 'firebase' import LRU from 'lru-cache' +import fetch from 'node-fetch'; export function createAPI ({ config, version }) { let api @@ -29,3 +30,7 @@ export function createAPI ({ config, version }) { } return api } + +export function fetchData(...params) { + return fetch(...params); +} diff --git a/src/api/index.js b/src/api/index.js index 46ccc77fc..bcdbcc2a9 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -1,5 +1,5 @@ // this is aliased in webpack config based on server/client build -import { createAPI } from 'create-api' +import { createAPI, fetchData } from 'create-api' const logRequests = !!process.env.DEBUG_API @@ -16,12 +16,12 @@ if (api.onServer) { warmCache() } -function warmCache () { +function warmCache() { fetchItems((api.cachedIds.top || []).slice(0, 30)) setTimeout(warmCache, 1000 * 60 * 15) } -function fetch (child) { +function fetch(child) { logRequests && console.log(`fetching ${child}...`) const cache = api.cachedItems if (cache && cache.has(child)) { @@ -41,25 +41,25 @@ function fetch (child) { } } -export function fetchIdsByType (type) { +export function fetchIdsByType(type) { return api.cachedIds && api.cachedIds[type] ? Promise.resolve(api.cachedIds[type]) : fetch(`${type}stories`) } -export function fetchItem (id) { +export function fetchItem(id) { return fetch(`item/${id}`) } -export function fetchItems (ids) { +export function fetchItems(ids) { return Promise.all(ids.map(id => fetchItem(id))) } -export function fetchUser (id) { +export function fetchUser(id) { return fetch(`user/${id}`) } -export function watchList (type, cb) { +export function watchList(type, cb) { let first = true const ref = api.child(`${type}stories`) const handler = snapshot => { @@ -74,3 +74,39 @@ export function watchList (type, cb) { ref.off('value', handler) } } + +export function fetchSimilar(queries) { + return fetchData('https://textsimilarity.research.peltarion.com/query/batch', { + method: 'POST', + body: JSON.stringify({ + queries, + dataset: 'hn-sbert', + top_n: 3 + }) + }) + .then(resp => resp.json()) + .then(json => json.rankings.map(i => i.entries)); +} + +function uuidv4() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} + +export default function sendFeedBack(query, result, rating) { + if (document.sessionId === undefined) { + document.sessionId = uuidv4() + } + return fetchData('https://textsimilarity.research.peltarion.com/feedback', { + method: 'POST', + body: JSON.stringify({ + query: query, + result: result, + rating: rating, + dataset: 'hn-sbert', + sessionId: document.sessionId + }) + }) +} diff --git a/src/components/Accordion.vue b/src/components/Accordion.vue new file mode 100644 index 000000000..f759818e1 --- /dev/null +++ b/src/components/Accordion.vue @@ -0,0 +1,42 @@ +> + + + + + + + diff --git a/src/components/Comment.vue b/src/components/Comment.vue index 1503ed40d..4b5fc4c36 100644 --- a/src/components/Comment.vue +++ b/src/components/Comment.vue @@ -6,11 +6,13 @@
- {{ + + {{ open - ? '[-]' - : '[+] ' + pluralize(comment.kids.length) + ' collapsed' - }} + ? '[-]' + : '[+] ' + pluralize(comment.kids.length) + ' collapsed' + }} +