#cofacts

2020-05-01
Nacs 10:36:15
@nacs13 has joined the channel
lucien 14:55:49
好猛
github 15:22:31
From comments in <https://github.com/cofacts/rumors-line-bot/pull/169|#169>: • `Query.context` is a little bit confusing with apollo context • `UserContext.state` &amp; `UserContext.data` should be non-nullable
github 15:34:11
*<https://github.com/cofacts/rumors-line-bot/compare/a28f1b6b5ba2...8a390abf8dac|8 new commits> pushed to <https://github.com/cofacts/rumors-line-bot/tree/dev|`dev`>* <https://github.com/cofacts/rumors-line-bot/commit/080040ad2857b3c1d410465f4ccb5a755f48caf7|`080040ad`> - GraphQL authentication &amp; context population <https://github.com/cofacts/rumors-line-bot/commit/30c8a3e52d0715a56eb6eace1484d834eb29cfe4|`30c8a3e5`> - Implement authentication, @auth directive and context field <https://github.com/cofacts/rumors-line-bot/commit/da8ccf6e33848f919e4459fbe91d3b7391052851|`da8ccf6e`> - Redundent jest.mock() as manual mocks for node modules will always load. <https://github.com/cofacts/rumors-line-bot/commit/f24191c880cf28a4fb879d64a1f440ea76071f14|`f24191c8`> - Add "manual" (auto) mock for redisClient so that all redisClient deps are mocked (such as in graphql/__tests__/insights) <https://github.com/cofacts/rumors-line-bot/commit/8dfa0c12afe6b0f6c8b49b798e4474c955450a89|`8dfa0c12`> - Prettier fix <https://github.com/cofacts/rumors-line-bot/commit/5295edb20990e761d51773539fab7903d37fc657|`5295edb2`> - Avoid calling the real redisClient in unit tests <https://github.com/cofacts/rumors-line-bot/commit/97b491de65d9a67c9c92bbdb4ac4118ff8f8359f|`97b491de`> - Add userId in GraphQL context after authentication <https://github.com/cofacts/rumors-line-bot/commit/8a390abf8dac39ad4701a9870628cbb1f06dad0c|`8a390abf`> - Merge pull request #169 from cofacts/auth-api
github 15:37:06
*<https://github.com/cofacts/rumors-line-bot/compare/8a390abf8dac...c5b684609691|9 new commits> pushed to <https://github.com/cofacts/rumors-line-bot/tree/dev|`dev`>* <https://github.com/cofacts/rumors-line-bot/commit/d36d76e47d90f391580d4ca5866aab14aa1efcf5|`d36d76e4`> - Implements mutation GraphQL endpoints for LIFF <https://github.com/cofacts/rumors-line-bot/commit/deb8bdd8075e5107db100ca2062caff5d5dccaba|`deb8bdd8`> - Remove submitReplyRequest because it is no longer needed <https://github.com/cofacts/rumors-line-bot/commit/ea856c552b8e8612936609b8fec6773c7a53d31d|`ea856c55`> - Remove submitArticle mutation because it's not needed <https://github.com/cofacts/rumors-line-bot/commit/b853bed252645822f9a81eccd79a9b72160efb64|`b853bed2`> - Prettier fix <https://github.com/cofacts/rumors-line-bot/commit/7860ec7dcc8c773ee25755d1563e26a3a4d16ac1|`7860ec7d`> - Add unit test for gql <https://github.com/cofacts/rumors-line-bot/commit/8ec314510a5e31c4de95248b3e6b09caa690a9b6|`8ec31451`> - Lint fix <https://github.com/cofacts/rumors-line-bot/commit/cc864507472181a1d2d713d18e5ecb675ac41824|`cc864507`> - gql error handling test. For test coverage... <https://github.com/cofacts/rumors-line-bot/commit/f86275a983ddd303333466dea15de103e17159ca|`f86275a9`> - Prettier fix <https://github.com/cofacts/rumors-line-bot/commit/c5b684609691bad8ec9ed6bd83df397dae310f40|`c5b68460`> - Merge pull request #170 from cofacts/mutation-api
github 15:37:22
Successfully deployed <https://github.com/cofacts/rumors-line-bot/commit/8a390abf8dac39ad4701a9870628cbb1f06dad0c|`8a390ab`> to <https://dashboard.heroku.com/apps/rumors-line-bot-staging/activity/builds/d14cc973-eef1-4425-9095-7c854349ac09|rumors-line-bot-staging>
github 15:38:01
*<https://github.com/cofacts/rumors-line-bot/compare/c5b684609691...8cc7ede5ddaf|8 new commits> pushed to <https://github.com/cofacts/rumors-line-bot/tree/dev|`dev`>* <https://github.com/cofacts/rumors-line-bot/commit/9d7f9b991f55c65a5f282ef0e11f1e0307099b1a|`9d7f9b99`> - Setup svelte liff and server build <https://github.com/cofacts/rumors-line-bot/commit/0bb6c769cdefba3d5d1589579d3fc3096c2779b7|`0bb6c769`> - audit fix <https://github.com/cofacts/rumors-line-bot/commit/51673df03e493ef42ddc49abbd3cfee1789d1396|`51673df0`> - Add liff proxy in dev mode <https://github.com/cofacts/rumors-line-bot/commit/eb8d1a7859035ff2b936544b29521d590465fbc6|`eb8d1a78`> - Add basic svelte setup <https://github.com/cofacts/rumors-line-bot/commit/0c2d09f027979d223b13077a61796da77fdc49ef|`0c2d09f0`> - Svelte i18n and corejs polyfill <https://github.com/cofacts/rumors-line-bot/commit/711fe7f2fb924332b0d94991777211c2fe3a1bfb|`711fe7f2`> - Imports polyfills that supports Safari10 and Android 52 <https://github.com/cofacts/rumors-line-bot/commit/10bb13afcf58cda3e5a09a68f61b13df3aeecd28|`10bb13af`> - Eslint ignore built liff/* <https://github.com/cofacts/rumors-line-bot/commit/8cc7ede5ddaf463e80977208ae97a93c81fa68f5|`8cc7ede5`> - Merge pull request #171 from cofacts/svelte-liff
mrorz 19:34:45
/github unsubscribe cofacts commits,statuses,deployments,releases
github 19:34:45
This channel will get notifications from <https://github.com/cofacts|cofacts> for: `issues`, `pulls`, `public`
mrorz 19:35:18
/github subscribe cofacts reviews,comments
github 19:35:18
This channel will get notifications from <https://github.com/cofacts|cofacts> for: `issues`, `pulls`, `public`, `comments`, `reviews`
mrorz 19:37:50
@ggm PR review 囉,請過目
https://github.com/cofacts/rumors-line-bot/pull/182

mongoClient 的實作我覺得有些太複雜了,abstraction 也有點怪 QQ
To see <https://github.com/cofacts/rumors-line-bot/issues/162|#162>
噢其實我覺得好像繼承 mongoClient 比較好
然後為什麼不要用 es6 class 呀
其他我晚點繼續看噢
React 寫久就會不喜歡 class (欸

其實主要是看到底想做的是 generalized client 還是 specialized singleton

我不反對做成 generalized client,就是包成 class、new 時進行連線,constructor 裡面設定 URL 等等

我也不反對另外做個 factory function 來吐一個前述的 class 的 singleton instance

但現在這個 class 實在太詭異,輸出的 constructor 可以改 URL 卻不能改 dbName,又有 singleton 的 static method、也會自動 connect 等等
我們對 `mongoClient` 還有下面的需求,會讓我覺得要滿足這些需求時,做成 class 反而是比較多餘的封裝

1. 我們會希望整個 app 共用一個 MongoDB 連線,而不是每個 request 來就重新連 MongoDB
2. 我們會連的資料庫就是 env vars 裡面指定的那些,不會有別的資料庫
這應該也是為什麼你會設計 `getInstance` 這個 static method 來回傳 singleton,因為 singleton 才是能滿足我們需求的 pattern

但如果我們想要的是 singleton 的話,那在 Javascript 的世界裡,我們大可以直接使用 object literal 就能辦到,不需要大費周章地包成 class 然後 instantiate 自己之類的
我是覺得自動連線的地方比較怪異沒錯,但其實你改成的 `getClient()` 的方式也是做了一樣的事情?「可以改 URI 卻不能改 dbName」為什麼不合理呀?我們不會用到別的 db 所以 `dbName` 不能改,但是會根據 `production` 和 `staging` 來有不同的 URI,所以 MONGODB_URI 會透過環境變數修改
主要的差別在 expose 出整個 class,跟只吐一個 factory method 的差別唷
應該是說我在裡面寫的那份 code 就是
「可以達成一樣的事情,但不會 leak 其他邏輯(規定要某種 call 法)的 abstraction」
嗯懂
但還是有隱含已連線的問題,要真的解決這個怪異,可能改成 getConnectedClient 之類的吧
然後我不覺得這是大費周章的包成 class 耶,不過就是定義一個 class 寫個 singleton ,用 object literal 的寫法不就也是模擬成 class 的樣子嗎?(吐出一個 object,然後他有一些 function 可以呼叫)那為什麼不直接用 class 來定義勒?
`getConnectedClient` 比較像是吐 object 的 factory (function) 的感覺
還是你是想說的是,既然我們都可以用 object literal 來做了,何須用 class
恩也可以這麼說
試想我們今天如果要加一上另外一個 function,你要做的事情是在 setupClient 的回傳值裡面加入一個 function
而 class 方法要做的事情,是在 class 裡面加入一個 function
我覺得 class 的做法不是比較直覺比較合理嗎?
我去找到這個 class 定義在哪裡,替他加上一個 function
我的直覺會是
我找到那個物件在哪裡,然後加上一個 method
而且 object literal 的做法,就會讓回傳值包得長長的
因為我要一包物件
他出生就是個 instance
factory 只是因為我想把連線之類的事情,從 import file 的時機點,延後到呼叫 `getClient`時做
不然其實我覺得 import 時就 connect 其實也挺好的
這樣就真的只要 `export default obj` 然後那個 `obj` 就是整個 module 的內容惹
啊其實不太行,最後至少還是要回傳個 promise
要等 connect (async) 之後才能讓使用者操作
嗯一定要回 promise
不然就是在某個地方先 await 過之類的(感覺很奇怪)
那就是 promise of 那個可以 db 呀 collection 呀 close 呀的 API (一個物件)
畢竟 JS 的 module.exports 本身就是個大 singleton
那我好奇噢,如果之後轉 typescript 的話,class 的做法可以明確的知道定義長怎樣,不管是每個 function 的或是自己,那這樣的話 object literal 的做法會長怎樣?
我需要另外定義一個 Type/Interface 來描述他是嗎?
轉 Typescript 的話
我會訂個 type 描述 `CofactsMongoClient`

然後定 getClient 會回傳 `Promise<CofactsMongoClient>`
那些 function 的 type 都指定好之後,讓 typescript 的 structural typing 確認我的 implementation 是不是確實會生出這個形狀的東西
嗯但 class 的做法不用另外再描述
對外面來說他就是吐 `Promise<CofactsMongoClient>` 的 function~
如果要 class 的話,那我覺得我們就在 constructor 裡面回傳那個 singleton instance 吧

像是這份答案的 ES7 version (Update 2019) https://stackoverflow.com/a/6733919/1582110

把 class expose 出去的時候,外面的人只能做一件事情,就是 new 它
然後 new 它,就只會回傳那個 singleton,然後連線啥的都會自動做好這樣

這樣一來外面的使用者只有一種使用方法,會是比較合適的封裝
就是 constructor 裡面會處理 getInstance or getClient 的概念
(我發現另一篇類似發問文的 best answer 就是 instance XD 但那是在 class 出現之前寫的)

https://stackoverflow.com/questions/1479319/simplest-cleanest-way-to-implement-singleton-in-javascript
好我來看看,然後把 connected 寫在註解好了,我覺得拿到一個已連線的 client 真的怪怪的 XDD 但每次呼叫 .connect() 也不是辦法
對啊沒有 class 一定是會這樣寫呀 還是 var 耶
我覺得比較棘手的部分是,我們的東西是 async 的,所以 class constructor 要怎麼處理那個 async 的部分其實滿討厭
`Downvote for the accepted answer not being a singleton at all. It's just a global variable. – mlibby Feb 25 '13 at 12:53`
對沒有原生 class 的 JS 來說
真的就是 global variable 呀 XD
對啊他好嚴格
大概是四人幫的粉絲、喜歡 Java 不喜歡 Javascript 的人 (?
> class constructor 要怎麼處理那個 async 的部分其實滿討厭
我現在想到的東西超怪的耶,就是 constructor 會回傳一個 promise,然後 promise 會 resolve to singleton instance when connected to database

所以會有一個超詭異的狀況:

我 new 一個 class ,但拿到的不是該 class 的 instance 而是 promise of that instance

超反直覺的
除非我們 extend Promise (更鬧了)
要不然就是保留現在的 getInstance

未來 Typescript 的時候直接用 private constructor 把 new 那條路堵起來,這樣只能呼叫 `getInstance` 抓 instance

https://khalilstemmler.com/blogs/typescript/when-to-use-a-private-constructor/
extend Promise 很帥耶⋯
我不太能接受 extend Promise

我覺得 private constructor 是最接近你原本想做的東西了
現在沒有 typescript
就放個註解說「不要 new!」吧
嗯 typescript 的話就可以 private constructor
啊然後其實 dbName 也可以拿掉,用預設的,也就是 MONGODB_URI 的
喔喔那個 mongodb connection uri `/` 後面帶的 db name 是 auth 用 db,不一定等於資料存放的 db 的說
`/` 後面是 dbname 沒錯, `authsource` 可以指定另外的 auth
欸不是
所以就算有帶 `/dbName` 我們還是要 `db(dbName)` 一次
我要說的是可以這樣 `/cofacts?authsource=admin`
嗯但這樣連線完,你似乎還是得要 `.db('cofacts')` ?
可以試試看
我的印象是還是要 `db` 指定 db name
不用噢
The name of the database we want to use. If not provided, use database name from connection string.
真的耶
學到了
ggm 19:51:11
好啊我看看
ggm 20:30:03
噢其實我覺得好像繼承 mongoClient 比較好
ggm 20:31:12
然後為什麼不要用 es6 class 呀
ggm 20:32:10
其他我晚點繼續看噢
mrorz 22:38:24
React 寫久就會不喜歡 class (欸

其實主要是看到底想做的是 generalized client 還是 specialized singleton

我不反對做成 generalized client,就是包成 class、new 時進行連線,constructor 裡面設定 URL 等等

我也不反對另外做個 factory function 來吐一個前述的 class 的 singleton instance

但現在這個 class 實在太詭異,輸出的 constructor 可以改 URL 卻不能改 dbName,又有 singleton 的 static method、也會自動 connect 等等
mrorz 22:45:42
我們對 `mongoClient` 還有下面的需求,會讓我覺得要滿足這些需求時,做成 class 反而是比較多餘的封裝

1. 我們會希望整個 app 共用一個 MongoDB 連線,而不是每個 request 來就重新連 MongoDB
2. 我們會連的資料庫就是 env vars 裡面指定的那些,不會有別的資料庫
這應該也是為什麼你會設計 `getInstance` 這個 static method 來回傳 singleton,因為 singleton 才是能滿足我們需求的 pattern

但如果我們想要的是 singleton 的話,那在 Javascript 的世界裡,我們大可以直接使用 object literal 就能辦到,不需要大費周章地包成 class 然後 instantiate 自己之類的
ggm 23:07:12
我是覺得自動連線的地方比較怪異沒錯,但其實你改成的 `getClient()` 的方式也是做了一樣的事情?「可以改 URI 卻不能改 dbName」為什麼不合理呀?我們不會用到別的 db 所以 `dbName` 不能改,但是會根據 `production` 和 `staging` 來有不同的 URI,所以 MONGODB_URI 會透過環境變數修改
  • 👍1
mrorz 23:21:54
主要的差別在 expose 出整個 class,跟只吐一個 factory method 的差別唷
mrorz 23:24:49
應該是說我在裡面寫的那份 code 就是
「可以達成一樣的事情,但不會 leak 其他邏輯(規定要某種 call 法)的 abstraction」
ggm 23:25:32
嗯懂
ggm 23:28:34
但還是有隱含已連線的問題,要真的解決這個怪異,可能改成 getConnectedClient 之類的吧
ggm 23:30:00
然後我不覺得這是大費周章的包成 class 耶,不過就是定義一個 class 寫個 singleton ,用 object literal 的寫法不就也是模擬成 class 的樣子嗎?(吐出一個 object,然後他有一些 function 可以呼叫)那為什麼不直接用 class 來定義勒?
mrorz 23:30:46
`getConnectedClient` 比較像是吐 object 的 factory (function) 的感覺
ggm 23:30:50
還是你是想說的是,既然我們都可以用 object literal 來做了,何須用 class
mrorz 23:31:08
恩也可以這麼說
ggm 23:31:23
試想我們今天如果要加一上另外一個 function,你要做的事情是在 setupClient 的回傳值裡面加入一個 function
ggm 23:31:42
而 class 方法要做的事情,是在 class 裡面加入一個 function
ggm 23:32:00
我覺得 class 的做法不是比較直覺比較合理嗎?
ggm 23:32:23
我去找到這個 class 定義在哪裡,替他加上一個 function
mrorz 23:33:07
我的直覺會是
我找到那個物件在哪裡,然後加上一個 method
ggm 23:33:12
而且 object literal 的做法,就會讓回傳值包得長長的
mrorz 23:33:34
因為我要一包物件
他出生就是個 instance
mrorz 23:34:32
factory 只是因為我想把連線之類的事情,從 import file 的時機點,延後到呼叫 `getClient`時做
不然其實我覺得 import 時就 connect 其實也挺好的
mrorz 23:35:04
這樣就真的只要 `export default obj` 然後那個 `obj` 就是整個 module 的內容惹
mrorz 23:36:58
啊其實不太行,最後至少還是要回傳個 promise
要等 connect (async) 之後才能讓使用者操作
ggm 23:37:57
嗯一定要回 promise
ggm 23:38:15
不然就是在某個地方先 await 過之類的(感覺很奇怪)
mrorz 23:38:37
那就是 promise of 那個可以 db 呀 collection 呀 close 呀的 API (一個物件)
mrorz 23:42:44
畢竟 JS 的 module.exports 本身就是個大 singleton
ggm 23:43:11
那我好奇噢,如果之後轉 typescript 的話,class 的做法可以明確的知道定義長怎樣,不管是每個 function 的或是自己,那這樣的話 object literal 的做法會長怎樣?
ggm 23:44:30
我需要另外定義一個 Type/Interface 來描述他是嗎?
mrorz 23:45:32
轉 Typescript 的話
我會訂個 type 描述 `CofactsMongoClient`

然後定 getClient 會回傳 `Promise<CofactsMongoClient>`
mrorz 23:46:17
那些 function 的 type 都指定好之後,讓 typescript 的 structural typing 確認我的 implementation 是不是確實會生出這個形狀的東西
ggm 23:46:24
嗯但 class 的做法不用另外再描述
  • 1
  • 1
mrorz 23:46:43
對外面來說他就是吐 `Promise<CofactsMongoClient>` 的 function~
mrorz 23:50:50
如果要 class 的話,那我覺得我們就在 constructor 裡面回傳那個 singleton instance 吧

像是這份答案的 ES7 version (Update 2019) https://stackoverflow.com/a/6733919/1582110

把 class expose 出去的時候,外面的人只能做一件事情,就是 new 它
然後 new 它,就只會回傳那個 singleton,然後連線啥的都會自動做好這樣

這樣一來外面的使用者只有一種使用方法,會是比較合適的封裝
Stack Overflow
Possible Duplicate: Simplest/Cleanest way to implement singleton in JavaScript? I'm using this pattern for singletons, in the example the singleton is PlanetEarth: var NAMESPACE = function ()...
mrorz 23:51:14
就是 constructor 裡面會處理 getInstance or getClient 的概念
mrorz 23:54:24
(我發現另一篇類似發問文的 best answer 就是 instance XD 但那是在 class 出現之前寫的)

https://stackoverflow.com/questions/1479319/simplest-cleanest-way-to-implement-singleton-in-javascript
Stack Overflow
What is the simplest/cleanest way to implement singleton pattern in JavaScript?
ggm 23:54:36
好我來看看,然後把 connected 寫在註解好了,我覺得拿到一個已連線的 client 真的怪怪的 XDD 但每次呼叫 .connect() 也不是辦法
ggm 23:55:41
對啊沒有 class 一定是會這樣寫呀 還是 var 耶
mrorz 23:56:21
我覺得比較棘手的部分是,我們的東西是 async 的,所以 class constructor 要怎麼處理那個 async 的部分其實滿討厭
  • 👍1
ggm 23:56:30
`Downvote for the accepted answer not being a singleton at all. It's just a global variable. – mlibby Feb 25 '13 at 12:53`
ggm 23:56:31
XDD
mrorz 23:57:21
對沒有原生 class 的 JS 來說
真的就是 global variable 呀 XD
ggm 23:57:39
對啊他好嚴格
mrorz 23:58:15
大概是四人幫的粉絲、喜歡 Java 不喜歡 Javascript 的人 (?
2020-05-02
mrorz 00:01:31
> class constructor 要怎麼處理那個 async 的部分其實滿討厭
我現在想到的東西超怪的耶,就是 constructor 會回傳一個 promise,然後 promise 會 resolve to singleton instance when connected to database

所以會有一個超詭異的狀況:

我 new 一個 class ,但拿到的不是該 class 的 instance 而是 promise of that instance

超反直覺的
mrorz 00:02:11
除非我們 extend Promise (更鬧了)
mrorz 00:11:59
要不然就是保留現在的 getInstance

未來 Typescript 的時候直接用 private constructor 把 new 那條路堵起來,這樣只能呼叫 `getInstance` 抓 instance

https://khalilstemmler.com/blogs/typescript/when-to-use-a-private-constructor/
khalilstemmler.com
In this blog post, I explain how using a private constructor helps to force a single way to create an object, and why it's most commonly used with the Factory Pattern.
ggm 00:14:15
extend Promise 很帥耶⋯
mrorz 00:14:40
我不太能接受 extend Promise

我覺得 private constructor 是最接近你原本想做的東西了
mrorz 00:14:45
現在沒有 typescript
mrorz 00:14:56
就放個註解說「不要 new!」吧
  • 1
ggm 00:15:41
嗯 typescript 的話就可以 private constructor
ggm 00:15:45
ggm 00:22:50
啊然後其實 dbName 也可以拿掉,用預設的,也就是 MONGODB_URI 的
github 00:25:15
Update: as <https://g0v-slack-archive.g0v.ronny.tw/index/channel/C2PPMRQGP/2020-05|discussed in Slack> we decided to add a comment to constructor to indicate that the users of `CofactsMongoClient` should never call `new` by themselves. When we adopt Typescript in the future, we will make the constructor private to make sure that users of `CofactsMongoClient` can only retrieve its singleton instance via `getInstance()` static method. `CofactsMongoClient` is dedicated to connecting to Cofacts LINE bot mongodb, not something that is generalized. ES6 class is used so that it's easier to define method and update the client type in the same time, also ensures a smoother updater when we rewrite in Typescript.
mrorz 00:25:53
喔喔那個 mongodb connection uri `/` 後面帶的 db name 是 auth 用 db,不一定等於資料存放的 db 的說
ggm 00:26:48
`/` 後面是 dbname 沒錯, `authsource` 可以指定另外的 auth
ggm 00:27:36
欸不是
mrorz 00:27:38
所以就算有帶 `/dbName` 我們還是要 `db(dbName)` 一次
ggm 00:27:41
我要說的是可以這樣 `/cofacts?authsource=admin`
mrorz 00:28:09
嗯但這樣連線完,你似乎還是得要 `.db('cofacts')` ?
mrorz 00:28:44
可以試試看
我的印象是還是要 `db` 指定 db name
ggm 00:29:15
不用噢
ggm 00:29:25
The name of the database we want to use. If not provided, use database name from connection string.
mrorz 00:31:07
真的耶
mrorz 00:31:08
學到了
mrorz 00:31:09
  • 🙌1
mrorz 01:11:54
Replied to a thread: 2020-04-22 22:43:20
這份在 review 中的 UI,目前放上 staging 囉
https://cofacts.hacktabl.org/

其中 reply list 會遇到之前 user 是 null 的問題
cofacts.hacktabl.org
Cofacts is a collaborative system connecting instant messages and fact-check reports or different opinions together. It’s a grass-root effort fighting mis/disinformation in Taiwan.
mrorz 01:14:21
但那應該是因為有 user 的 app id 是 `DEVELOPMENT_BACKEND` 的關係。因此,其實 reply 或任何東西的 user 都有可能是 null,程式邏輯上不能有任何地方沒有先檢查 user 不是 null 就直接存取 user 唷。
cc/ @yanglin5689446
mrorz 02:25:35
Staging 上某 reply 的 user 是 null
image.png
mrorz 02:26:07
localhost 上則不是 null
image.png
mrorz 02:30:34
這其實是當時為了讓 localhost 開發方便,
訂有讓 localhost 可以看到 app_id = `DEVEOPMENT_BACKEND` 的使用者的緣故
https://github.com/cofacts/rumors-api/blob/master/src/graphql/models/User.js#L113-L115

其實只要是 localhost:3000 接上 API server 之後,就能打 mutation,這其實不太安全,所以才做了這種 `DEVELOPMENT_BACKEND` 機制,特別允許這種 localhost:3000 的 request,只是安上不同 appId https://github.com/cofacts/rumors-api/blob/master/src/checkHeaders.js#L37-L42
mrorz 02:33:53
而 staging 上那個造成 exception 的 reply,app_id 確實是 `DEVELOPMENT_BACKEND` @@
```{
"_index" : "replies_v1_0_2",
"_type" : "doc",
"_id" : "jD2sy3EBrIRcahlYXQri",
"_version" : 2,
"found" : true,
"_source" : {
"userId" : "hD1qunEBrIRcahlYYQoi",
"appId" : "DEVELOPMENT_FRONTEND",
"type" : "NOT_ARTICLE",
"text" : "fasdfasdfadsfasdfadsfasdfadsfadsfadsfadsfadsfadsfadsfasdffasdfasdfadsfasdfadsfasdfadsfadsfadsfadsfadsfadsfadsfasdffasdfasdfadsfasdfadsfasdfadsfadsfadsfadsfadsfadsfadsfasdf",
"reference" : "fasdfasdfadsfasdfadsfasdfadsfadsfadsfadsfadsfadsfadsfasdf",
"createdAt" : "2020-04-30T15:20:03.289Z",
"hyperlinks" : [ ]
}
}```
mrorz 02:38:52
還是其實我應該做的是在 staging 開放 localhost 但 production 不開放

把 `DEVELOPMENT_BACKEND` 機制整個淘汰掉
以及把資料庫內所有 appId = `DEVELOPMENT_BACKEND` 的東西都砍掉?
mrorz 02:39:24
但這樣就無法模擬有不同 appId 的狀況就是了 QQ
github 12:29:52
Merge base temporarily changed to new page UI for correct diff. Will change back to dev benefits merge.
2020-05-03
github 04:26:48
Seems that in staging site, `user` being `null` would break `Avatar` and throw exception. I think the implementation of `&lt;Avatar&gt;` should guard against `null`.
github 04:26:48
Mobile menu has the same z-index with result dropdown but comes later in DOM, thus it is coming through: <https://user-images.githubusercontent.com/108608/80872659-d78d9100-8ce5-11ea-87e3-61657e99221d.gif|z-index> May need to increase z-index here, or form a stacking context with `z-index: 0` for mobile menu to contain the badge?
github 04:26:48
As discussed <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1587274861203800|in Slack>, please don't use `withData` in non-page components. Just use them on components under `pages/` directory.
github 04:26:48
Seems that the padding is too large in mobile version, names and avatar do not align in center. <https://user-images.githubusercontent.com/108608/80833043-5ddf9f80-8c20-11ea-83e7-e8e3722f4d24.png|image> You can use object / array notation on `py` for setting this responsively <https://material-ui.com/system/basics/#object|https://material-ui.com/system/basics/#object>
github 04:26:48
Inconsistent size of thumb-up/down button and the reason button in mobile view. <https://user-images.githubusercontent.com/108608/80891170-f5aebd80-8cf4-11ea-8163-818ee6de925a.png|image> Corresponding mockup: <https://user-images.githubusercontent.com/108608/80891197-1f67e480-8cf5-11ea-851f-39bc14f9c875.png|image>
github 04:26:48
I think we can open another ticket for implementing the real "for you" count listed in spec: <https://g0v.hackmd.io/iJm9_nZaTA2GyInn7ycxoA|https://g0v.hackmd.io/iJm9_nZaTA2GyInn7ycxoA> The "自己沒有送過任何 normal articleReply" part has no API yet, while "article.replyRequestCount &gt;= N (default N = 2)" and "沒有任何 normal articleReply 符合「正feedback&gt;負feedback &amp;&amp; status == "NORMAL"」" are currently available in `ListArticle` filter.
github 04:26:49
Search result for replies is different from mockup. It should be listing replies that has the query text, rather than articles that has the query text. Mockup: <https://user-images.githubusercontent.com/108608/80891388-3a872400-8cf6-11ea-9ecc-dfd781fd27fc.png|image> Current: <https://user-images.githubusercontent.com/108608/80891392-4377f580-8cf6-11ea-99c0-fae928ed5f47.png|image> This may be huge so can include in future PRs.
github 04:26:49
You also need `vote` under each feedbacks, because the you are using `vote` to move feedbacks in the right tab. Currently both tabs are empty because no feedback has `vote` field...... <https://user-images.githubusercontent.com/108608/80891094-61445b00-8cf4-11ea-82a2-eda5e2b83054.png|image>
mrorz 14:10:48
https://github.com/cofacts/rumors-site/pull/248/files
@yanglin5689446 是說這個是不是還沒 ready 呀

我看用到 `ExpandableText` 的地方傳了 `lineClamp` 進去,但 `ExpandableText` 內部並沒有處理它
mrorz 16:22:45
Replied to a thread: 2020-04-16 16:26:26
關於「我查核過」的 filter
他跟 navbar 「等你來答」的數字的 query
定義剛好相反
(有我的 articleReply 與沒有我的 articleReply)
g0v.hackmd.io
mrorz 16:24:58
我在想要不要比照 `hasPositiveFeedbackArticleReply` ,在 `ListArticle` filter做一個 `hasMyArticleReply`

`true` 就是有,`false`就是沒有

不過之後 profile page 如果要列出某使用者的 `articleReply`,不知道是要改 `ListArticle` filter 還是要在 User 底下加 field 就是了⋯⋯

cc/ @lucien @yanglin5689446
yanglin 16:28:01
如果有座在 `ListArticle` 在 profile 就繼續用就可以了吧?
反正 query 會被 group 在一起發送?
mrorz 16:28:03
如果「某使用者的 `articleReply`」只會在 profile 之類的頁面使用,那確實是做在 User 底下比較合理,這樣 `ListArticle` filter 只要實作「有/沒有我的 articleReply」filter 即可
github 16:39:13
<https://github.com/orgs/cofacts/projects/5#card-37456782|https://github.com/orgs/cofacts/projects/5#card-37456782> added here
github 16:40:31
card added here: <https://github.com/orgs/cofacts/projects/5#card-34990256|https://github.com/orgs/cofacts/projects/5#card-34990256>
github 19:24:37
You may reset `MockDate` here
2020-05-04
github 00:49:29
*PR has been edited* :construction_worker: This PR has received other commits, so Renovate will stop updating it to avoid conflicts or other problems. If you wish to abandon your changes and have Renovate start over you may click the "rebase" checkbox in the PR body/description.
github 00:59:54
<https://coveralls.io/builds/30522585|Coverage Status> Coverage decreased (-5.1%) to 85.901% when pulling *<https://github.com/cofacts/rumors-api/commit/a64cc97a8f82f0c4bcd3b9f5946f4b55feb91ea9|a64cc97> on renovate/all* into *<https://github.com/cofacts/rumors-api/commit/4e8354b1aed320fc76cdeb09a4c1468822e09956|4e8354b> on master*.
github 01:13:01
The Elasticsearch js library we are <https://www.npmjs.com/package/elasticsearch|currently using> is deprecated, thus we are migrating to the <https://www.elastic.co/blog/new-elasticsearch-javascript-client-released|new client>. 95% of the changes in this PR is to mitigate this <https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/6.x/breaking-changes.html|breaking change>: &gt; The returned value of an API call will no longer be the body, statusCode, and headers for callbacks and just the body for promises. The new returned value will be a unique object containing the body, statusCode, headers, warnings, and meta, for both callback and promises. Therefore a majority of the code change is destructuring `body` from the all the values the elasticsearch client returns. We remove elasticsearch log related setup, since the new client does not have an integrated logger anymore. We add unit test to `auth.js`, in which some of its logic binding to passport cannot be tested, thus the coverage goes down a bit. Lastly, the version of submodule rumors-db is also updated. In latest changes, `.env` file is removed from rumors-db codebase, thus we need to provide ELASTICSEARCH_URL manually in package.json of rumors-api, otherwise it will break environments like Travis CI.
因為原本的 elasticsearch js client deprecate 了,我更新了一下 elasticsearch js client。

他有個大 breaking change,更正了 client 回傳的所有結構,所以導致 rumors-api 裡面每一個有呼叫到 elasticsearch client 的地方幾乎都要跟著改。總之這個 PR 之所以巨大就是大在這囧
這個變更太多了,為了找出有沒有問題
我先把它放到 staging 上跑跑看囉

如果大家最近打 staging API 出問題請提出,說不定是這個 PR 的問題
@darkbtf 留意個
mrorz 01:18:23
因為原本的 elasticsearch js client deprecate 了,我更新了一下 elasticsearch js client。

他有個大 breaking change,更正了 client 回傳的所有結構,所以導致 rumors-api 裡面每一個有呼叫到 elasticsearch client 的地方幾乎都要跟著改。總之這個 PR 之所以巨大就是大在這囧
  • 😱1
mrorz 01:20:19
@yanglin5689446
其實主要是考量 `ListArticle` 這裡如果計算 `articleReply` 還要考慮是「哪個使用者發的 `articleReply`」那 API 就不能只是 boolean
而必須是個 boolean + user ID string,所以會從
```hasMyArticleReply: Boolean```
變成
```articleReplyFrom: { userId: String, appId: String, exists: Boolean }```
(想不到更好的取名 囧)
  • 👍1
github 01:32:56
其實我是指左邊兩顆 vote 按鈕,與右邊灰底的顯示部分不一樣高 <https://user-images.githubusercontent.com/108608/80921136-0ddf1500-8da7-11ea-9607-e723cb5b942d.png|image> Mockup 裡,雖然 mobile / desktop 下的 button 高度不同,但左右兩塊都是等高的。
github 02:03:01
mobile 下, avatar 應該要跟右側文字置中。目前這樣好像有點太低了 <https://user-images.githubusercontent.com/108608/80921817-3ff27600-8dab-11ea-959e-14a0224b806d.png|image>
github 03:41:26
Actually, replies page has different filter from article page. Mockup: <https://user-images.githubusercontent.com/108608/80923827-88646080-8db8-11ea-8dea-faf365456f67.png|image> Spec: <https://g0v.hackmd.io/ZZWHWi2BTuyhkSWzAvKLAw#%E9%81%8E%E6%BF%BE%E9%81%B8%E9%A0%85%EF%BC%9A|https://g0v.hackmd.io/ZZWHWi2BTuyhkSWzAvKLAw#%E9%81%8E%E6%BF%BE%E9%81%B8%E9%A0%85%EF%BC%9A> The API for "我查核過" and reply type filtering is still on the way, but "還未有有效查核", "熱門回報" and "熱門討論" are legit `ListArticle` filters already (`hasPositiveFeedbackArticleReply`, `replyRequestCount` and `replyCount` respectively). Considering the size of this change, I think we can handle this in future PRs, may need a ticket for this.
github 10:22:18
card added here: <https://github.com/orgs/cofacts/projects/5#card-37494391|https://github.com/orgs/cofacts/projects/5#card-37494391>
github 14:03:41
LGTM! Let's ship it to staging <https://github.githubassets.com/images/icons/emoji/shipit.png|:shipit:>
  • 1
  • ❤️1
Deployed to staging 🚀
mrorz 16:25:49
Replied to a thread: 2020-05-04 14:03:41
Deployed to staging 🚀
yanglin 19:09:54
是說現在的 category 是透過一個環境變數決定要不要顯示
不過現在 category 功能應該已經測試過了?
可以打開了嗎?
mrorz 19:54:45
被藏起來的是 add category 的功能
我覺得應該要藏到有訊息被 category 分好類為止(也就是資料庫裡會有一些訊息是分好類的),這樣使用者就能用這些當成例子,判斷手頭上還沒有被分類的某訊息是屬於哪一類。

分類的進度要問 @ggm

我覺得新寫介面的話就不用考慮那個 env var 了
2020-05-05
github 02:12:43
Current implementation (puppeteer) eats up too much resource and the its throughput cannot keep up with the usage of rumors-api. We should consider other solutions as well. *Resources* Previous research: <https://github.com/cofacts/rumors-api/issues/41|cofacts/rumors-api#41> Web archiving tools by IIPC (behind wayback machine) <https://github.com/iipc/awesome-web-archiving|https://github.com/iipc/awesome-web-archiving> *Archiver* • Python + headless chrome <https://github.com/internetarchive/brozzler|https://github.com/internetarchive/brozzler> • Headless chrome <https://github.com/N0taN3rd/Squidwarc|https://github.com/N0taN3rd/Squidwarc> • Headless chrome with queue <https://github.com/yujiosaka/headless-chrome-crawler|https://github.com/yujiosaka/headless-chrome-crawler> • Save all in one html file <https://github.com/Y2Z/monolith|https://github.com/Y2Z/monolith> *Text summarization (w/ Chinese upport)* • request + newspaper3k (Python3) <https://newspaper.readthedocs.io/en/latest/|https://newspaper.readthedocs.io/en/latest/> *Misc* • Readability + readability-readarable <https://github.com/mozilla/readability#whats-readability-readerable|https://github.com/mozilla/readability#whats-readability-readerable>
yanglin 10:53:44
@mrorz 我昨天又重新用上面討論的方式實作了
之前那個算是丟上來討論而已
  • 1
yanglin 10:54:11
再麻煩你幫我 review 了🙏
chihao 14:54:53
有個關於 cofacts collected messages 的問題,如果想知道含有特定關鍵字的 collected message,推薦在這裡搜尋嗎? https://cofacts.g0v.tw/articles?filter=all 在這裡搜尋可以按照時間排序嗎?
1. 可以在搜尋框搜尋無誤唷!不過如果文字長一點,會有不一樣的效果。
2. 現在 UI 沒有,但之後搜尋介面下可以按照其他方式排序,也可以指定要哪個時間送進來的資料。
mrorz++
這個部分是 @yanglin5689446 實作的 ~~
感謝 🙌 有其他搜尋的管道嗎?我記得好像有 API 但還沒用過 😅
Chatbot 就是搜尋管道之一
只是 Chatbot 比對比較嚴格,差太多就會說找不到
網站上的搜尋功能,設定寬鬆很多,擦邊都算相似
GraphQL API 是 ListArticles ,filter.moreLikeThis
ggm 15:05:25
30k 篇的分類都分好了,隨時可以打回去 production
ggm 15:13:01
我其實忘記現在 category mutation API 是不是上 production 了,上了的話 @darkbtf 就可以把我們現在標的好的資料含若水標記的資料全部打回去哩
應該是有在 production 上
我覺得可以先把資料放進 Staging 測測
恩恩我們是預計這禮拜會打到 staging
但是 staging 和 production 的文章好像長得不一樣
就能打就打(?
嗯嗯
就是 staging 不存在的文章就跳過~
mrorz 15:21:02
1. 可以在搜尋框搜尋無誤唷!不過如果文字長一點,會有不一樣的效果。
2. 現在 UI 沒有,但之後搜尋介面下可以按照其他方式排序,也可以指定要哪個時間送進來的資料。
chihao 15:21:36
mrorz++
mrorz 15:22:04
這個部分是 @yanglin5689446 實作的 ~~
mrorz 15:22:33
chihao 15:22:36
感謝 🙌 有其他搜尋的管道嗎?我記得好像有 API 但還沒用過 😅
mrorz 15:23:24
Chatbot 就是搜尋管道之一
只是 Chatbot 比對比較嚴格,差太多就會說找不到
mrorz 15:23:45
網站上的搜尋功能,設定寬鬆很多,擦邊都算相似
mrorz 15:24:18
GraphQL API 是 ListArticles ,filter.moreLikeThis
mrorz 15:27:30
應該是有在 production 上
我覺得可以先把資料放進 Staging 測測
ggm 15:28:09
恩恩我們是預計這禮拜會打到 staging
ggm 15:28:26
但是 staging 和 production 的文章好像長得不一樣
ggm 15:28:43
就能打就打(?
yanglin 15:59:41
不知道為什麼 `GetArticle` 只要 query `requestedForReply` 就會變得很慢欸 0.0
會不會是因為你 get 的那篇 article 的 reply request 太多呀
咦不對呀
他用 userId + articleId 下去搜的話,應該只會找到 0 個或 1 個 @@
requestedForReply 應該只是一個布林?
他是即時去搜 replyrequest
了解
我只要加這個 field 就會一直轉圈圈 XD
他是「這個使用者有沒有按過我也想知道」
所以每個人不一樣~
但不應該要轉很久才對
啊除非
你是在文章列表裡面下 `requestedForReply`
我是在 `GetArticle` 下

應該不會慢很多才對,就是多一個到 elasticsearch 撈資料的動作而已 @@
今天稍微調查了一下發現
只要加了 `requestedForReply`
Hyperlink 的 polling 就會沒有 response
導致 app 一直轉圈圈
怪了,為什麼會跟 hyperlink 有關 QQ
我也不太確定 我之後再試試看
我現在是在 Article details 的頁面的 GetArticle query 新增 就會
我發現 5/4 更新 staging API 成 https://github.com/cofacts/rumors-api/pull/153 的版本之後,5/5 @yanglin5689446 就回報問題

朝 API 裡面 elasticsearch result 沒接好的方向調查 ing
結果不是 elasticsearch result 沒接好
而是
1. 一般來說,跟使用者相關的 object field 如 `ownVote` 等等,在沒有指定 userId (如:SSR) 時,會直接回傳 null。然而, `requestedForReply` 錯誤地使用了只有 mutation API 該用的 `assertUser({...})` ,所以只要有 requestedForReply 就會產生 error。
2. 我們用的 apollo-link-error 如果有 exception 的話,他就會無聲無息地悶不吭聲,讓後面的 apollo-client resolve 一整個卡住。我是在 `BatchHttpLink` 與 `onError` 中間插了一個印 console 的 link 才能抓到那個 error。

目前我們的 `onError` 裡頭用了 `alert()`,在 NodeJS 環境下並無此 function,所以他其實應該在 runtime 時遇到了 Reference error,但卻無聲無息。
至於 apollo-link-error 把 runtime error 吃掉這件事情,我在 codesandbox 上卻無法重現

https://codesandbox.io/s/awesome-shamir-vpf2d?file=/index.js
看起來 error 有好好地被抓出來 @@
mrorz 16:45:30
嗯嗯
就是 staging 不存在的文章就跳過~
mrorz 16:46:42
會不會是因為你 get 的那篇 article 的 reply request 太多呀
mrorz 16:47:56
咦不對呀
他用 userId + articleId 下去搜的話,應該只會找到 0 個或 1 個 @@
yanglin 16:49:29
requestedForReply 應該只是一個布林?
mrorz 16:49:52
他是即時去搜 replyrequest
mrorz 16:50:13
``` requestedForReply: { type: GraphQLBoolean, description: 'If the current user has requested for reply for this article', resolve: async ({ id }, args, { userId, appId, loaders }) =&gt; { assertUser({ userId, appId }); const userReplyRequests = await loaders.searchResultLoader.load({ index: 'replyrequests', body: { query: { bool: { must: [{ term: { userId } }, { term: { articleId: id } }], }, }, }, }); return userReplyRequests &amp;&amp; userReplyRequests.length &gt; 0; }, }, ```
yanglin 16:50:23
了解
yanglin 16:50:39
我只要加這個 field 就會一直轉圈圈 XD
mrorz 16:50:41
他是「這個使用者有沒有按過我也想知道」
所以每個人不一樣~
mrorz 16:50:54
但不應該要轉很久才對
mrorz 16:51:17
啊除非
你是在文章列表裡面下 `requestedForReply`
yanglin 16:51:42
我是在 `GetArticle` 下
mrorz 16:52:07

應該不會慢很多才對,就是多一個到 elasticsearch 撈資料的動作而已 @@
stbb1025 17:11:03
@lucien @mrorz發佈查核闢謠的時候,資料來源是一定要附上的嗎?還是可以空白?或是不硬性規定但平台這邊會希望使用者附上資料來源?
只有「不在查證範圍」可以不用附來源,否則原則上是一定要附。

但過去也有些人亂打哎哎
我覺得我們可以實驗看看改成一定要附上
就算是他自己打電話去確認,他也要附註他自己去電話查核的時間跟紀錄,所以應該會有文字記錄
這樣我mobile比較好設計
不在查證範圍 是一定沒有來源欄位的
比較有爭議是個人意見,到底要不要給來源
個人意見找反例有時候會非常困難
我覺得個人意見還是要有欄位讓他填「不同意見」

就算只是佐證自己在回應裡講的材料也好

只是這就不是嚴格的「不同意見出處」
mrorz 17:12:15
只有「不在查證範圍」可以不用附來源,否則原則上是一定要附。

但過去也有些人亂打哎哎
lucien 17:24:29
我覺得我們可以實驗看看改成一定要附上
lucien 17:25:51
就算是他自己打電話去確認,他也要附註他自己去電話查核的時間跟紀錄,所以應該會有文字記錄
  • 👍1
stbb1025 17:28:54
stbb1025 17:29:14
這樣我mobile比較好設計
lucien 17:29:35
不在查證範圍 是一定沒有來源欄位的
lucien 17:29:56
比較有爭議是個人意見,到底要不要給來源
lucien 17:30:14
個人意見找反例有時候會非常困難
mrorz 17:32:07
我覺得個人意見還是要有欄位讓他填「不同意見」

就算只是佐證自己在回應裡講的材料也好

只是這就不是嚴格的「不同意見出處」
github 22:11:51
We can use this so that the translators don't need to handle the triangles: ``` ({expanded ? t`Show Less` + ' ▲' : t`Show More` + ' ▼'}) ``` or ``` ({expanded ? `${t`Show Less`} ▲` : `${t`Show More`} ▼`}) ```
github 22:38:00
Not sure why, but there are some weird cases that need to trace code to figure out why <https://user-images.githubusercontent.com/108608/81078431-cf6d6580-8f20-11ea-9f84-6179c4ba4342.png|image> The article content is `555`. Can be found by searching `555` in page. Other similar scenario are: <https://user-images.githubusercontent.com/108608/81078509-ec099d80-8f20-11ea-8040-4ee1f7cccce0.png|image> <https://user-images.githubusercontent.com/108608/81078549-fd52aa00-8f20-11ea-94b4-6f2fef72861e.png|image>
github 23:02:05
Blocked by <https://github.com/storybookjs/storybook/issues/10631|storybookjs/storybook#10631>
github 23:12:40
I suggest adding the component to storybook so that we can get visual documentation &amp; snapshot testing
2020-05-06
mrorz 00:16:01
請問 @yanglin5689446 今天晚上有空線上會議嗎~

今天晚上 @stbb1025 會與 @lucien 討論 UI (detail page mobile 版),也想問問你有沒有什麼想當面問的

時間大概會是 @lucien 到場的時間(8pm~11pm 之間的不知道什麼時間)
可以喔
今天我可以線上會議嗎?
我大概九點
開始叫我唷
我正在使用 tico
毫無反應
@lucien 你不見了
github 01:16:18
Update: 1. abort LIFF on desktop <https://camo.githubusercontent.com/425d8a29fc7b947ffbbc9ca790a714c00c0ee8eb/68747470733a2f2f73332d61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f6730762d6861636b6d642d696d616765732f75706c6f6164732f75706c6f61645f32353230343736353734383931643233303762643131343533326165323237372e676966|https://camo.githubusercontent.com/425d8a29fc7b947ffbbc9ca790a714c00c0ee8eb/68747470733a2f2f73332d61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f6730762d6861636b6d642d696d616765732f75706c6f6164732f75706c6f61645f32353230343736353734383931643233303762643131343533326165323237372e676966> 2. explicitly tell user that we have recorded their feedback (regardless of them inputting the reason or not) in LIFF <https://camo.githubusercontent.com/59a3074d175f7d205d2e1eafaacb6c92f2a04171/68747470733a2f2f73332d61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f6730762d6861636b6d642d696d616765732f75706c6f6164732f75706c6f61645f62313061303365653566333061623433323163323437386161316634663735342e706e67|https://camo.githubusercontent.com/59a3074d175f7d205d2e1eafaacb6c92f2a04171/68747470733a2f2f73332d61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f6730762d6861636b6d642d696d616765732f75706c6f6164732f75706c6f61645f62313061303365653566333061623433323163323437386161316634663735342e706e67>
github 01:57:25
As discussed in <https://g0v.hackmd.io/@mrorz/BksBf58KI#%E9%80%81%E5%87%BA-source-%E8%88%87-reason-%E5%BE%8C%E7%9A%84%E8%A8%8A%E6%81%AF%E9%87%8D%E8%A4%87%E5%95%8F%E9%A1%8C|https://g0v.hackmd.io/@mrorz/BksBf58KI#%E9%80%81%E5%87%BA-source-%E8%88%87-reason-%E5%BE%8C%E7%9A%84%E8%A8%8A%E6%81%AF%E9%87%8D%E8%A4%87%E5%95%8F%E9%A1%8C> This PR turns the 2 bubbles after LIFF response into carousel to make it more compact, hopefully the message will not overwhelm the user. <https://user-images.githubusercontent.com/108608/81098815-790e2000-8f3c-11ea-8c1d-d2917421ab65.png|image> Note that • In response to source (first carousel), both bubble are all call-to-actions (we want user to both provide more info and share) • In response to reason (2nd carousel), not many people updates their own reason, thus use gray color instead; also, the update bubble is moved to the right (2nd bubble).
github 01:59:45
*Pull Request Test Coverage Report for <https://coveralls.io/builds/30576473|Build 771>* • *2* of *2* *(100.0%)* changed or added relevant lines in *2* files are covered. • No unchanged relevant lines lost coverage. • Overall coverage increased (+*0.02%*) to *98.652%* * * * * * * *:yellow_heart: - <https://coveralls.io|Coveralls>*
github 09:23:09
Draft 也會抓出來啊 😦
ready to review 會再一次 XDD
nonumpa 09:33:34
Draft 也會抓出來啊 😦
github 11:11:40
this seems like the old behavior of original commit, but I rebase the commit, it should look like these now: <https://user-images.githubusercontent.com/12843409/81135340-5276d600-8f8a-11ea-806c-b92fbfde2c68.png|截圖 2020-05-06 上午11 10 29> <https://user-images.githubusercontent.com/12843409/81135343-560a5d00-8f8a-11ea-873a-99dba391476d.png|截圖 2020-05-06 上午11 10 14>
mrorz 11:16:54
ready to review 會再一次 XDD
github 11:20:18
It seems that it only happens on specific articles that has only 1 line, and the line is super short, on desktop. You can search for `555` on <https://cofacts.hacktabl.org/replies|staging> to see the following sample <https://user-images.githubusercontent.com/108608/81135607-72f36000-8f8b-11ea-975b-7a81433e250a.png|image>
@mrorz 因為我有 rebase 然後改掉原本的 commit
所以可能跟之前 deploy 到 staging 得不太一樣
可能要再 deploy 一次試試
目前我這看起來是好的(如 comment 的附圖)
感謝,確認正常
yanglin 11:52:28
@mrorz 因為我有 rebase 然後改掉原本的 commit
所以可能跟之前 deploy 到 staging 得不太一樣
可能要再 deploy 一次試試
目前我這看起來是好的(如 comment 的附圖)
mrorz 12:22:22
Replied to a thread: 2020-05-06 00:16:01
請問 @yanglin5689446 今天晚上有空線上會議嗎~

今天晚上 @stbb1025 會與 @lucien 討論 UI (detail page mobile 版),也想問問你有沒有什麼想當面問的

時間大概會是 @lucien 到場的時間(8pm~11pm 之間的不知道什麼時間)
yanglin 12:35:28
可以喔
  • 1
  • 👍1
mrorz 12:36:40
感謝,確認正常
github 12:37:27
Confirmed that its' fixed after rebase.
mrorz 12:59:25
Replied to a thread: 2020-05-04 01:13:01
這個變更太多了,為了找出有沒有問題
我先把它放到 staging 上跑跑看囉

如果大家最近打 staging API 出問題請提出,說不定是這個 PR 的問題
  • 👍2
github 14:14:23
New article details page UI <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=681%3A0|mockup>
github 16:25:12
Change pagination to infinity load
ggm 17:33:34
@darkbtf 留意個
lucien 19:00:55
今天我可以線上會議嗎?
github 19:21:33
But `null` and `undefined` are different in mongodb. For example ``` db.collection('inventory').find({ item: null }); ``` ``` db.collection('inventory').find({ item: { $exists: false } }); ``` I'm not sure there is any effect in the future, so I choose the precise defines.
mrorz 19:33:57
lucien 19:55:52
我大概九點
stbb1025 21:13:41
開始叫我唷
lucien 21:13:57
我正在使用 tico
lucien 21:14:03
毫無反應
mrorz 21:15:16
@lucien @stbb1025 我們是不是換個 Jitsi 才有聲音呀
這裡都白白看不到你們
stbb1025 21:15:35
我跟@lucien 可以通話
lucien 21:16:24
我跟 nick 一國
stbb1025 21:16:33
yeah
mrorz 21:18:51
@yanglin5689446 我們在這裡開會
https://tico.chat/powercall?room=cofactshack&type=timeFirst
tico.chat
The considerate messenger. Chat with whom you care about always at the best moments and times
stbb1025 21:19:37
@lucien 你不見了
lucien 21:19:53
我聽得到各位
lucien 21:20:03
你們聽不到我
mrorz 21:21:24
@yanglin5689446 @lucien @stbb1025 https://meet.jit.si/cofactshack
meet.jit.si
Join a WebRTC video conference powered by the Jitsi Videobridge
mrorz 21:53:36
Stack Overflow
I can only find questions where people have the opposite problem. I want my fixed content to go above the iOS keyboard. Image of the problem: I want iOS to behave like Android. Is there a simpl...
mrorz 21:54:45
Pixel 2: Top 與 Bottom 在鍵盤出現時都會出現
iPhone X: 整個螢幕往上推,top 會被推不見,bottom 仍然黏著
lucien 21:55:34
Screenshot_20200506-215518.png
mrorz 22:02:08
@yanglin5689446 FYI: 從我們的 analytics 做的手機上的 browser version 統計
https://g0v.hackmd.io/@mrorz/rksKX45D8#LIFF-compatibility
HackMD
20200408 會議紀錄 ===== &gt; Workis: MrOrz, bil, lucien &gt; 線上:志超 &gt; 線上開會:<https://tico.chat/powercall?room=>
github 22:11:06
Hi all, I really enjoy your works with cofacts chatbot. I can easily distinguish the truth of messages from my parents, that is reeeally good. However, there is a feature that I need is not in the current version. The feature I need is `sharing the results to other chat rooms`, such as my parent's private message or family channel etc. Thanks for your effort. You are the best.
mrorz 22:17:43
material-ui.com
Tabs make it easy to explore and switch between different views.
mrorz 22:45:02
Material design: dialog with options
image.png
mrorz 22:45:28
Option with description
image.png
mrorz 22:56:42
開新視窗的 icon
image.png
mrorz 23:13:01
material-ui.com
Menus display a list of choices on temporary surfaces.
2020-05-07
mrorz 00:06:59
LINE bot 的新流程在 staging 囉
大家可以打開手機到 staging 玩玩看
staging 這邊請:https://lin.ee/1QUzEX4nI

跟上週不太一樣的地方有:
1. 阻擋桌面版點出 LIFF
2. 修改理由與分享 flex message 的排列
3. 按下「有用」/「沒用」後的 LIFF 告知使用者已經紀錄 voting
PR 堆得很高 :books: 我想如果 PR 放一個月都沒人看的話,就要包裹通過囉 .__.
https://github.com/cofacts/rumors-line-bot/pulls
github 00:10:31
Yeah I know about the `$exists`. But if you declare a field to be any type that is not null, say, a string, can you still assign `null` to that field?
github 00:54:16
Hi <https://github.com/shrimp509|@shrimp509> it's glad to see the chatbot helps :) If you feel like sharing the results from Cofacts to other chatrooms, you may either 1. long-press the reply and choose "share". After that you can select multiple messages to share (usually the reason and the references provided by the editor) and then choose the target chatrooms. 2. When the chatbot asks if the reply is useful, reply "yes". The chatbot will then encourage you to share this reply with friends. Option 2 works like this: <https://user-images.githubusercontent.com/108608/81205116-d23d8880-8ffc-11ea-9a15-fb2cd86e87b8.png|Screenshot_20200507-004353_2> <https://user-images.githubusercontent.com/108608/81205127-d5387900-8ffc-11ea-819c-a0b28bb97ef4.png|Screenshot_20200507-004411> We designed this flow because we really needs the user's feedback on usefulness of a reply, and we don't want to ask user to share a reply if they think it's not useful in the first place.
github 09:06:56
delightfullychaotic 2020-05-07 09:11:40
這是昨天台南小松的熱情朋友,哈哈,我自己都不知道分享給朋友可以純文字。
github 09:06:57
Got it!! I didn't notice the share button after choosing one of the results. Thanks for your detail explanation of why you design like this. I understand your consideration. Thank you again.
delightfullychaotic 09:11:40
這是昨天台南小松的熱情朋友,哈哈,我自己都不知道分享給朋友可以純文字。
  • 👍1
github 11:54:33
If `process.env.IMAGE_MESSAGE_ENABLED` is not true, image messages will not be tracked. Maybe we can extract this along with <https://github.com/cofacts/rumors-line-bot/blob/7a93a085e75e9d3ac1bcd8018b4a1625e4353bdf/src/webhook/index.js#L168|index.js L168>, <https://github.com/cofacts/rumors-line-bot/blob/7a93a085e75e9d3ac1bcd8018b4a1625e4353bdf/src/webhook/index.js#L179|index.js L179> to the beginning of <https://github.com/cofacts/rumors-line-bot/blob/7a93a085e75e9d3ac1bcd8018b4a1625e4353bdf/src/webhook/index.js#L83|process message>.
mrorz 12:22:22
@ggm 關於這個呀 https://github.com/cofacts/rumors-line-bot/pull/182/files/d03bb7533c63264eb241b4cee08548df6fa050df#discussion_r418464972

我有看到你後來把 _id 拿掉,_不過我當時想討論的其實是為什麼要放 `_id`, `userId`, `articleId` 等等欄位進 model,但沒看到有 code 在存取這些欄位。
我已經滿久沒有在用類似這樣的 ORM / Active record pattern 的介面了,通常就是 get 一個物件,呼叫 update 或 insert 也都是直接呼叫 client 傳一個物件進去,沒有在 `obj.save()` 這樣。
_id 是 mongodb 預設會有的欄位,在top level schema我記得是拿不掉的
我在說的是像這個檔案
src/database/models/userArticleLink.js

我可以理解用 static method 來把此種 model 相關的 DB operation 收納在一個 class 裡面,但我不知道為什麼會有 L70 開始的下面那些 field,因為目前好像沒有人會去存取這些 field。

他看起來像是預留給 ORM 機制,
也就是之後會有人從資料庫讀出來之後灌進 `UserArticleLink` instance 用的,或有人未來會 `new UserArticleLink` 然後填資料進去。
還是 GGM 寫下面那些 field,其實是為了 typing? 像這樣
噢我原本要解釋打到一半睡著 XD
拿掉 `_id` 是因為整個過程中我們都不會需要 `_id` ,所以不需要對 `_id` 做 verify
然後另外那些變數是 class public field declarations,現階段了作用是為了給開發者看說這個 class 會有這個欄位,以及要給 jsdoc 看有這個定義
跟 ORM 其實比較無關,是為了 typing,當我呼叫 `findOrInsertByUserId` 取得實體之後我會有這個 `newReplyNotifyToken` property
了解,所以是 for type definition
不透過 class 做的話,另外寫 jsdoc 要另外
```@typedef {Object} UserSettings```
然後再寫一些
```@property```
這樣
對對
但這邊只是給 jsdoc 對吧
我自己之前接觸過的 repo 其實也大多是以另外寫 type 為主,API function 呼叫時,再去使用那些 type。

利用 class field type definition 來把 typing 與 API 結構放在一起是第一次看到
然後存取的部分應該會發生在後面,譬如拿 `newReplyNotifyToken` 出來用,或判斷時間要送推播的時候
用 typescript 當然就可以把 type 抽出來呀
但「把 type 抽出來」這種 pattern,在 JSDoc 裡相對應的語法,就是你不想用的 `@typedef`
我以為你用 class 是想說之後如果轉 typescript 也直接用 typescript class 無痛(?)轉
對啊這也是
雖然 typescript 其實會抱怨說這些 field 沒有 initializer,不過那也是之後轉 typescript 再來研究就好的事 (茶
我覺得這樣寫法蠻奇怪的
看起來應該要有 factory 去產你要的結構
我覺得 class field type definition 會比寫 jsdoc 還具體還好用,在 typescript 也用得到,到時候就把 `@type {boolean}` 這個換掉就好
現在兩個放在一起,就會有這樣的問題
為什麼會像是要用 factory 生成呀?
GGM 484 覺得這些寫 JS 的人都很喜歡 factory pattern
像這個討論串:https://g0v-tw.slack.com/archives/C2PPMRQGP/p1588333070310900
我覺得沒那麼複雜啦 XD
像這個簡單的例子,就是一個 Rectangle 裡面有 height 和 width 這樣而已
我覺得有點像是習慣差異耶

從 C++ / Java 來的人很直覺會想說 type definition 放在 class 很清楚

但大家 Javascript 導入 Typescript 的過程與 mind model,開發者心裡想的其實是,typing 是一種幫我檢查資料形狀的「外掛」
所以 JS developer 會直覺的使用 JS 常用的手段,例如 export object literal 出去當 API、用 thunk 解決呼叫時間問題等等,然後再用 type 去 “annotate” 這些 expose 出去的 API
最主要的目的就是想要透過 class 來描述我從 database (mongo) 拿出來有哪些欄位
另外一個比較意識形態的問題是,Javascript 社群有拒C文化 (這裏的 C 是 class),比較擁抱 fp⋯⋯ XD
es6 出了 class,越來越 js 專案轉 ts,typescript 也有完整的 class,我覺得抗拒 C 文化倒是很難說⋯
其實不用 class 也是寫一堆
```Object.defineProperty```
```A.prototype.oooxxx```
之類的東西呀其實
Typescript 我覺得很 class
真怪怎麼沒有變色 XD
尤其開始用reflect metadata之後
嗯嗯
我只是想解釋為什麼我跟 Lucien 會針對 code 裡用到 class 的不同的地方,都下意識地提出說可以用 factory 解的原因

因為學校裡有教的確實是比較偏 OOP 的習慣,所以我也很好奇我什麼時候 pickup 了這種 JS 的思維
把工廠跟產出物放在同一個class會導致你沒辦法在 constructor init 產出物的property
你進typescript之後會很難處理
Mongo orm 會用 model 跟 document 分別描述這兩個東西
工廠其實是 static function (method) 為什麼會影響 constructor init ?
怎麼描述的做法我覺得都有,像是 `loopback 3` 是用分開描述有點像我現在寫的這樣,有一個 .json 另一個 .js,`loopback 4` 則是寫在一個檔案描述,不過他就導入 typescript 了
然後 `sailsjs` 就是把工廠和產出物寫在一起,譬如 `People.create()` 和 `people.save()` 之類的,透過 static function 切開
其實我覺得 `UserArticleLink` 這個 class 好像並不是設計給人 `new` 的,之後有 private constructor 的時候可能一樣要擋起來,跟 `CofactsMongoClient` 一樣
mrorz 12:23:42
我已經滿久沒有在用類似這樣的 ORM / Active record pattern 的介面了,通常就是 get 一個物件,呼叫 update 或 insert 也都是直接呼叫 client 傳一個物件進去,沒有在 `obj.save()` 這樣。
lucien 12:30:46
_id 是 mongodb 預設會有的欄位,在top level schema我記得是拿不掉的
mrorz 12:36:08
我在說的是像這個檔案
src/database/models/userArticleLink.js

我可以理解用 static method 來把此種 model 相關的 DB operation 收納在一個 class 裡面,但我不知道為什麼會有 L70 開始的下面那些 field,因為目前好像沒有人會去存取這些 field。

他看起來像是預留給 ORM 機制,
也就是之後會有人從資料庫讀出來之後灌進 `UserArticleLink` instance 用的,或有人未來會 `new UserArticleLink` 然後填資料進去。
mrorz 12:46:59
還是 GGM 寫下面那些 field,其實是為了 typing? 像這樣
image.png
ggm 12:47:00
噢我原本要解釋打到一半睡著 XD
ggm 12:47:57
拿掉 `_id` 是因為整個過程中我們都不會需要 `_id` ,所以不需要對 `_id` 做 verify
  • 👍1
ggm 12:49:55
然後另外那些變數是 class public field declarations,現階段了作用是為了給開發者看說這個 class 會有這個欄位,以及要給 jsdoc 看有這個定義
  • 👌1
ggm 12:51:55
跟 ORM 其實比較無關,是為了 typing,當我呼叫 `findOrInsertByUserId` 取得實體之後我會有這個 `newReplyNotifyToken` property
mrorz 12:52:53
了解,所以是 for type definition
ggm 12:52:58
不透過 class 做的話,另外寫 jsdoc 要另外
```@typedef {Object} UserSettings```
ggm 12:53:32
然後再寫一些
```@property```
這樣
mrorz 12:53:38
對對
lucien 12:56:09
但這邊只是給 jsdoc 對吧
mrorz 12:59:45
我自己之前接觸過的 repo 其實也大多是以另外寫 type 為主,API function 呼叫時,再去使用那些 type。

利用 class field type definition 來把 typing 與 API 結構放在一起是第一次看到
ggm 13:00:52
然後存取的部分應該會發生在後面,譬如拿 `newReplyNotifyToken` 出來用,或判斷時間要送推播的時候
ggm 13:02:06
用 typescript 當然就可以把 type 抽出來呀
mrorz 13:04:05
但「把 type 抽出來」這種 pattern,在 JSDoc 裡相對應的語法,就是你不想用的 `@typedef`
mrorz 13:06:51
我以為你用 class 是想說之後如果轉 typescript 也直接用 typescript class 無痛(?)轉
ggm 13:06:58
對啊這也是
mrorz 13:08:02
雖然 typescript 其實會抱怨說這些 field 沒有 initializer,不過那也是之後轉 typescript 再來研究就好的事 (茶
lucien 13:10:06
我覺得這樣寫法蠻奇怪的
lucien 13:10:37
看起來應該要有 factory 去產你要的結構
ggm 13:10:53
我覺得 class field type definition 會比寫 jsdoc 還具體還好用,在 typescript 也用得到,到時候就把 `@type {boolean}` 這個換掉就好
lucien 13:10:57
現在兩個放在一起,就會有這樣的問題
ggm 13:11:39
為什麼會像是要用 factory 生成呀?
mrorz 13:12:09
GGM 484 覺得這些寫 JS 的人都很喜歡 factory pattern
像這個討論串:https://g0v-tw.slack.com/archives/C2PPMRQGP/p1588333070310900
Johnson Liang
@ggm PR review 囉,請過目
https://github.com/cofacts/rumors-line-bot/pull/182

mongoClient 的實作我覺得有些太複雜了,abstraction 也有點怪 QQ
ggm 13:12:43
我覺得沒那麼複雜啦 XD
ggm 13:13:08
MDN Web Docs
JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.
ggm 13:14:04
像這個簡單的例子,就是一個 Rectangle 裡面有 height 和 width 這樣而已
mrorz 13:15:05
我覺得有點像是習慣差異耶

從 C++ / Java 來的人很直覺會想說 type definition 放在 class 很清楚

但大家 Javascript 導入 Typescript 的過程與 mind model,開發者心裡想的其實是,typing 是一種幫我檢查資料形狀的「外掛」
mrorz 13:16:38
所以 JS developer 會直覺的使用 JS 常用的手段,例如 export object literal 出去當 API、用 thunk 解決呼叫時間問題等等,然後再用 type 去 “annotate” 這些 expose 出去的 API
ggm 13:17:15
最主要的目的就是想要透過 class 來描述我從 database (mongo) 拿出來有哪些欄位
mrorz 13:18:27
另外一個比較意識形態的問題是,Javascript 社群有拒C文化 (這裏的 C 是 class),比較擁抱 fp⋯⋯ XD
ggm 13:21:21
es6 出了 class,越來越 js 專案轉 ts,typescript 也有完整的 class,我覺得抗拒 C 文化倒是很難說⋯
ggm 13:23:35
其實不用 class 也是寫一堆
```Object.defineProperty```
```A.prototype.oooxxx```
之類的東西呀其實
lucien 13:23:36
Typescript 我覺得很 class
ggm 13:23:53
真怪怎麼沒有變色 XD
lucien 13:23:58
尤其開始用reflect metadata之後
mrorz 13:32:13
嗯嗯
我只是想解釋為什麼我跟 Lucien 會針對 code 裡用到 class 的不同的地方,都下意識地提出說可以用 factory 解的原因

因為學校裡有教的確實是比較偏 OOP 的習慣,所以我也很好奇我什麼時候 pickup 了這種 JS 的思維
  • 👍1
lucien 13:56:08
把工廠跟產出物放在同一個class會導致你沒辦法在 constructor init 產出物的property
lucien 13:56:35
你進typescript之後會很難處理
lucien 13:57:10
Mongo orm 會用 model 跟 document 分別描述這兩個東西
ggm 14:16:17
工廠其實是 static function (method) 為什麼會影響 constructor init ?
ggm 14:21:31
怎麼描述的做法我覺得都有,像是 `loopback 3` 是用分開描述有點像我現在寫的這樣,有一個 .json 另一個 .js,`loopback 4` 則是寫在一個檔案描述,不過他就導入 typescript 了
ggm 14:22:58
然後 `sailsjs` 就是把工廠和產出物寫在一起,譬如 `People.create()` 和 `people.save()` 之類的,透過 static function 切開
mrorz 14:23:43
其實我覺得 `UserArticleLink` 這個 class 好像並不是設計給人 `new` 的,之後有 private constructor 的時候可能一樣要擋起來,跟 `CofactsMongoClient` 一樣
  • 👍1
github 14:57:47
Yes, if using mongodb ``` $&gt; db.ppl.insert({phoneNumber: null}) WriteResult({ "nInserted" : 1 }) $&gt; db.ppl.insert({phoneNumber: '0912'}) WriteResult({ "nInserted" : 1 }) $&gt; db.ppl.find() { "_id" : ObjectId("5eb3ad6a9a5e1f8e59885998"), "phoneNumber" : null } { "_id" : ObjectId("5eb3ad739a5e1f8e59885999"), "phoneNumber" : "0912" } ``` There are 2 options: 1. [require=true] Should be exist, then string or null 2. [require=false] It would be string or undefined (not exists) But I think yours is better to be less verbose first, and then update if need.
github 15:02:23
btw, If we follow option 1, then we can query easily ``` db.collection('inventory').find({ itemA: null, itemB: 'book' }); ``` Not sure if it's important for now
github 15:10:55
Hmm if I want to find a document that has one field that does not exist, the first idea that comes to my mind would be `{itemA: {$exists: false}}`, did not think of testing `null` in the first place. The syntax also mixes well with other conditions in place (i.e. `{itemA: {$exists: false}, itemB: 'book'}`). Slightly longer than the `null` version, but I think its occurrence in codebase should be less than field definitions.
github 15:15:29
Seems that json schema we are currently using _does_ block non-required fields from being set to `null`. <https://user-images.githubusercontent.com/108608/81265339-824ed800-9075-11ea-8365-a52860f545f6.png|image>
github 15:21:44
On the other hand, one draw back (?) of using non-required fields would be that it's a bit counterintuitive when we want to set a field conditionally, for instance, ``` const person = { name: 'foo', ...(revealGender ? {gender: input} : {}) } ``` Setting everything to required + allow null for some fields forces us to specify all fields, but is easier (?) to set conditional content: ``` const person = { name: 'foo', gender: revealGender ? input : null, bloodType: null, weight: null, height: null, birthday: null } ```
github 15:31:17
&gt; Seems that json schema we are currently using _does_ block non-required fields from being set to `null`. You are not using the current one ? Should be use `oneOf` in your demo case ?
github 15:44:37
&gt; Hmm if I want to find a document that has one field that does not exist, the first idea that comes to my mind would be `{itemA: {$exists: false}}`, did not think of testing `null` in the first place. I'm not sure that is the first idea. There are different usages in different situations. Let's talk about `newReplyNotifyToken` if it's expired or not working or something. I want to set to be `null`, not `undefined`, and find those documents by using `null` not `{$exists: false}`
github 15:45:55
In the demo case I am testing if jsonschema can block `null` when it's assigned to non-required fields. Personally I think we should either stick to (a) field not-required + can't be null, or (b) all-field-required + can be null, not a mixture of (a) and (b). While the current code is in (b), in the demonstration I was trying to show that (a) also works as exptected.
github 19:11:55
Interesting aspect of `newReplyNotifyToken`, didn't think of that. When `newReplyNotifyToken` is expired, I would ask the user if they want to delete the token. If they say yes, we invoke `db.collection('userArticleLinks').update({$unset: {newReplyNotifyToken: ''}})`. That's indeed longer than setting `newReplyNotifyToken` to `null`.
2020-05-08
mrorz 00:59:19
因為最近會跟其他有興趣實作 Cofacts 的組織接觸,所以更新了一下 developer homepage:
https://hackmd.io/@mrorz/r1nfwTrgM

裡面有
• 更新的系統架構圖
• 更新的 DB index 圖 https://g0v.hackmd.io/@mrorz/S1caurZq8
• 新畫的 ER Model 圖https://g0v.hackmd.io/@mrorz/S1caurZq8
希望這樣對新開發者有助益~
HackMD
【Cofacts 真的假的】Homepage for Developers ====== ## Source codes Cofacts is comprised of several com
HackMD
Updated at 2020/5/7
  • 👍1
mrorz 01:29:22
另外,因為今天 @darkbtf 問到關於 userId / appId 的問題,我覺得應該要把 Cofacts 系統的 userId / appId 機制給寫下來:

https://g0v.hackmd.io/ZcoUOX_-RQSkJyl5xz4_Zg

文件還沒寫完,之後會需要討論說,未來要擴充的話要怎麼處理的細節。
  • 👍1
yanglin 12:29:21
@mrorz 視覺化搜尋趨勢那邊可能需要資料 api
mrorz 12:29:39
對對那個要補
  • 👌1
szeming 13:35:45
@szeming has joined the channel
yanglin 18:03:25
今天稍微調查了一下發現
只要加了 `requestedForReply`
Hyperlink 的 polling 就會沒有 response
導致 app 一直轉圈圈
yu_tainan 18:20:20
@ytyubox has joined the channel
mrorz 18:38:49
怪了,為什麼會跟 hyperlink 有關 QQ
yanglin 18:40:36
我也不太確定 我之後再試試看
我現在是在 Article details 的頁面的 GetArticle query 新增 就會
2020-05-09
nonumpa 00:15:01
https://g0v.hackmd.io/eIeU2g86Tfu5VnLazNfUvQ#資料表:UserSettings
問個問題,我們會讓使用者同時使用 Line Notify 和 Push Api 嗎
還是會直接從 server 端就決定要用哪種?
兩個都開好像沒什麼意義,功能一樣(雖然 Line notify 可以選擇傳到別的聊天室,但通知訊息主要是針對使用者查過的訊息,預期使用者不會這樣用。)
Hmm 做成 server 端(用 env vars)決定好像比較簡單齁
我們可能英文版與 staging 用 LINE notify (畢竟也沒付費帳號)
localhost 與 production 用 Push API
nonumpa 00:35:24
第二個問題,Line notify 我想要做成打開通知就 link,關掉通知就 revoke token,這樣做比較簡單
不然我們除了開關通知可能還要另外做一個 link/revoke 的功能
但其實點了 revoke 就等於關閉通知,點了開啟通知就等於要 link
(關閉通知可以不用 revoke,link 可以不用開啟通知)
好呀就這樣辦~
mrorz 03:43:01
Hmm 做成 server 端(用 env vars)決定好像比較簡單齁
mrorz 03:43:47
我們可能英文版與 staging 用 LINE notify (畢竟也沒付費帳號)
localhost 與 production 用 Push API
  • 1
  • 1
mrorz 03:53:00
好呀就這樣辦~
hoyang 08:42:01
@hoyangtsai has joined the channel
github 14:03:11
*Pull Request Test Coverage Report for <https://coveralls.io/builds/30669027|Build 787>* • *59* of *62* *(95.16%)* changed or added relevant lines in *5* files are covered. • No unchanged relevant lines lost coverage. • Overall coverage decreased (*-0.5%*) to *96.177%* * * * * * * *:yellow_heart: - <https://coveralls.io|Coveralls>*
ggm 15:04:16
我 rebase dev 之後,跑 test 會噴這個
``` PASS src/lib/__tests__/gql.js
● Console

console.error src/lib/gql.js:53
GraphQL operation contains error: [ { message: 'Runtime error' } ]```
Pass 的話不用理~
那個是在測 error handling 嗎?
ggm 15:04:22
要理他嗎?
github 16:14:09
The vertical spacing is imbalanced <https://user-images.githubusercontent.com/108608/81465180-95d77b80-91fa-11ea-8dd5-63061579f71f.png|image> I suggest adding negative bottom margin to `ul.articleList` to undo the bottom margin of `ArticleItem`. Of course other solutions also apply (such as removing the bottom margin for last `ArticleItem` using `:last-child`), but we should still manage the margin of `ul.articleList`; it is still having the default margin defined by the browser. <https://user-images.githubusercontent.com/108608/81465177-87895f80-91fa-11ea-8af7-664d4a0d4b08.png|image>
github 16:14:09
Instead of using `refetch` that cleans up `listArticlesData`, please consider leveraging `fetchMore` which allows us to describe how new data is appended to `listArticlesData` using `updateQuery()`. In this way we don't need to maintain a separate state `articleEdges`. Reference: <https://www.apollographql.com/docs/react/data/pagination/|https://www.apollographql.com/docs/react/data/pagination/> Introductory post: <https://www.apollographql.com/blog/pagination-and-infinite-scrolling-in-apollo-client-59ff064aac61|https://www.apollographql.com/blog/pagination-and-infinite-scrolling-in-apollo-client-59ff064aac61> Also, we don't need to store `nextCursor` in separate state; we can just get the cursor from the last edge in the data. Lastly, the current implementation does not preserve the page if the user enters a detail page from the list and hit back to return. We hope that using `fetchMore` could solve the current issue, since apollo-cache should reserve the items loaded so far and next-router should manage the scroll position.
github 16:14:09
If we leverage `loadMore` and get cursor from last edge directly in `ArticlePageLayout`, we can leave the pagination logic entirely in where pagination happens, reduce the props passed to `LoadMore`. Personally I think `onClick` and `loading` should be enough; we can even detect if we reached the last page outside of `&lt;LoadMore&gt;`.
github 16:14:09
It's a good try of changing the pagination into infinite load. I think we can • leverage `loadMore` instead of `refetch` and see if it helps with preserving pages when user navigates from detail page back to list page. • reduce the props passed to `LoadMore` as we encapsulate pagination logic in the component that uses `LoadMore`.
github 23:29:50
LGTM! Thanks for your patience and the explanation, very inspiring. It seems that it is possible to further simplify the logic of `MongoClient.getInstance()`, see the comment below.
@ggm 有 conflict 唷

也可以參考一下我的 Comment ~
真怪我之前有 rebase 了說,我又 rebase 然後 push 囉
github 23:29:50
Seems that this is equivalent to: ``` // It returns promise anyway, no need for async in this function. // If we want to hint that this returns a promise, just use JSDoc `@returns {Promise&lt;CofactsMongoClient&gt;}` static getInstance() { // combines set-by-default and default setting return this._instance = this._instance || (async () =&gt; { const client = new CofactsMongoClient(MONGODB_URI); await client.mongoClient.connect(); return client; })(); } ``` Giving the async arrow function a good name can further improve its readability: ``` // Somewhere outside the class: // async function instantiateClientAndConnect() { const client = new CofactsMongoClient(MONGODB_URI); await client.mongoClient.connect(); return client; } // Then, back to inside the class, the code is super easy to understand now: // static getInstance() { return this._instance = this._instance || instantiateClientAndConnect(); } ```
@ggm 有 conflict 唷

也可以參考一下我的 Comment ~
真怪我之前有 rebase 了說,我又 rebase 然後 push 囉
2020-05-10
github 01:32:17
Fix this error: old version of articleCategories is null, instead of being initialized to empty list. ``` { "errors": [ { "message": "illegal_argument_exception", "locations": [ { "line": 2, "column": 3 } ], "path": [ "CreateArticleCategory" ], "extensions": { "code": "INTERNAL_SERVER_ERROR", "exception": { "name": "ResponseError", "meta": { "body": { "error": { "root_cause": [ { "type": "remote_transport_exception", "reason": "[VxKgRte][127.0.0.1:9300][indices:data/write/update[s]]" } ], "type": "illegal_argument_exception", "reason": "failed to execute script", "caused_by": { "type": "script_exception", "reason": "runtime error", "script_stack": [ "found = ctx._source.articleCategories.stream()\n .filter(", " ^---- HERE" ], "script": "\n def found = ctx._source.articleCategories.stream()\n .filter(ar -&gt; ar.get('categoryId').equals(params.articleCategory.get('categoryId')))\n .findFirst();\n\n if (found.isPresent()) {\n HashMap ar = found.get();\n if (ar.get('status').equals('DELETED')) {\n ar.put('status', 'NORMAL');\n ar.put('userId', 'model_test');\n ar.put('appId', 'DEVELOPMENT_BACKEND');\n ar.put('updatedAt', '2020-05-07T11:56:48.759Z');\n } else {\n ctx.op = 'none';\n }\n } else {\n ctx._source.articleCategories.add(params.articleCategory);\n ctx._source.normalArticleCategoryCount = ctx._source.articleCategories.stream().filter(\n ar -&gt; ar.get('status').equals('NORMAL')\n ).count();\n }\n ", "lang": "painless", "caused_by": { "type": "null_pointer_exception", "reason": null } } }, "status": 400 }, "statusCode": 400, "headers": { "content-type": "application/json; charset=UTF-8", "content-length": "1401" }, "warnings": null, "meta": { "context": null, "request": { "params": { "method": "POST", "path": "/articles/doc/zzyt710qo56u/_update", "body": "{\"script\":{\"source\":\"\\n def found = ctx._source.articleCategories.stream()\\n .filter(ar -&gt; ar.get('categoryId').equals(params.articleCategory.get('categoryId')))\\n .findFirst();\\n\\n if (found.isPresent()) {\\n HashMap ar = found.get();\\n if (ar.get('status').equals('DELETED')) {\\n ar.put('status', 'NORMAL');\\n ar.put('userId', 'model_test');\\n ar.put('appId', 'DEVELOPMENT_BACKEND');\\n ar.put('updatedAt', '2020-05-07T11:56:48.759Z');\\n } else {\\n ctx.op = 'none';\\n }\\n } else {\\n ctx._source.articleCategories.add(params.articleCategory);\\n ctx._source.normalArticleCategoryCount = ctx._source.articleCategories.stream().filter(\\n ar -&gt; ar.get('status').equals('NORMAL')\\n ).count();\\n }\\n \",\"lang\":\"painless\",\"params\":{\"articleCategory\":{\"userId\":\"model_test\",\"appId\":\"DEVELOPMENT_BACKEND\",\"aiModel\":\"bert\",\"aiConfidence\":1,\"positiveFeedbackCount\":0,\"negativeFeedbackCount\":0,\"categoryId\":\"mD2n7nEBrIRcahlYLAr7\",\"status\":\"NORMAL\",\"createdAt\":\"2020-05-07T11:56:48.759Z\",\"updatedAt\":\"2020-05-07T11:56:48.759Z\"}}},\"_source\":[\"articleCategories.*\"]}", "querystring": "", "headers": { "User-Agent": "elasticsearch-js/6.8.6 (linux 4.4.0-137-generic-x64; Node.js v12.14.1)", "Content-Type": "application/json", "Content-Length": "1269" }, "timeout": 30000 }, "options": { "warnings": null }, "id": 89085 }, "name": "elasticsearch-js", "connection": { "url": "<http://cofacts-db-staging:9200/>", "id": "<http://cofacts-db-staging:9200/>", "headers": {}, "deadCount": 0, "resurrectTimeout": 0, "_openRequests": 0, "status": "alive", "roles": { "master": true, "data": true, "ingest": true, "ml": false } }, "attempts": 0, "aborted": false } } } }, "authError": false } ], "data": { "CreateArticleCategory": null } } which can be reproduced by this mutation: ``` mutation { CreateArticleCategory( articleId: "zzyt710qo56u" categoryId: "mD2n7nEBrIRcahlYLAr7" aiModel: "bert" aiConfidence: 1.0 ) { articleId categoryId } }
liao.jason2 11:11:36
@liao.jason2 has joined the channel
liao.jason2 11:11:36
@liao.jason2 has joined the channel
github 15:47:07
LGTM! It works on staging, I think we can <https://github.githubassets.com/images/icons/emoji/shipit.png|:shipit:>
github 16:37:11
Please `npm run lint:fix` first. <https://travis-ci.org/github/cofacts/rumors-site/builds/684561774|https://travis-ci.org/github/cofacts/rumors-site/builds/684561774>
github 16:38:13
Suggest adding `copyBtnRef.current`, `content` and `onClick` to dependency array • Adding `copyBtnRef.current` is for the case when DOM of the the button is reconstructed, the `ClipboardJS` instance should be bound to the new DOM element instead. • Adding `content` and `onClick` is to prevent the case when these props are updated, ClipboardJS is still connecting to old callbacks that access an old JS closure.
github 16:55:57
Deploying to production • Backup: `gcs/2020-05-10-before-migration` • Migrated at: TBD *1st round* ``` 16:59 ≎ ~/workspace/rumors-db ➠ npx babel-node db/migrations/202005-add-article-categories.js ResponseError: Response Error at IncomingMessage.&lt;anonymous&gt; (/Users/mrorz/workspace/rumors-db/node_modules/@elastic/elasticsearch/lib/Transport.js:296:25) at IncomingMessage.emit (events.js:205:15) at IncomingMessage.EventEmitter.emit (domain.js:471:20) at endReadableNT (_stream_readable.js:1137:12) at processTicksAndRejections (internal/process/task_queues.js:84:9) { name: 'ResponseError', meta: { body: { took: 4641, timed_out: false, total: 36068, updated: 3577, deleted: 0, batches: 4, version_conflicts: 423, noops: 0, retries: [Object], throttled_millis: 0, requests_per_second: -1, throttled_until_millis: 0, failures: [Array] }, statusCode: 409, headers: { 'content-type': 'application/json; charset=UTF-8', 'content-length': '133674' }, warnings: null, meta: { context: null, request: [Object], name: 'elasticsearch-js', connection: [Object], attempts: 1, aborted: false } } } ```
github 17:35:55
This PR: • tells elasticsearch to do nothing when `articleCategories` exists • log everything when error occurs • log response when success
@darkbtf 麻煩看一下
我小改了一下 migration
改完之後想說在 production 再重跑一次
沒有指定 op = ‘noop’ 的話是不是會無差別寫入呀
第一次完全沒 `noop` ,但最新的 Articles 應該都要有 articleCategories
mrorz 17:37:27
@darkbtf 麻煩看一下
我小改了一下 migration
改完之後想說在 production 再重跑一次
mrorz 18:22:51
Deploying to production • Backup: `gcs/2020-05-10-before-migration` • Migrated at: TBD *1st round* ``` 16:59 ≎ ~/workspace/rumors-db ➠ npx babel-node db/migrations/202005-add-article-categories.js ResponseError: Response Error at IncomingMessage.&lt;anonymous&gt; (/Users/mrorz/workspace/rumors-db/node_modules/@elastic/elasticsearch/lib/Transport.js:296:25) at IncomingMessage.emit (events.js:205:15) at IncomingMessage.EventEmitter.emit (domain.js:471:20) at endReadableNT (_stream_readable.js:1137:12) at processTicksAndRejections (internal/process/task_queues.js:84:9) { name: 'ResponseError', meta: { body: { took: 4641, timed_out: false, total: 36068, updated: 3577, deleted: 0, batches: 4, version_conflicts: 423, noops: 0, retries: [Object], throttled_millis: 0, requests_per_second: -1, throttled_until_millis: 0, failures: [Array] }, statusCode: 409, headers: { 'content-type': 'application/json; charset=UTF-8', 'content-length': '133674' }, warnings: null, meta: { context: null, request: [Object], name: 'elasticsearch-js', connection: [Object], attempts: 1, aborted: false } } } ``` *2nd round* ``` 18:20 ≎ ~/workspace/rumors-db ➠ npx babel-node db/migrations/202005-add-article-categories.js { body: { took: 3650, timed_out: false, total: 36068, updated: 0, deleted: 0, batches: 37, version_conflicts: 0, noops: 36068, retries: { bulk: 0, search: 0 }, throttled_millis: 0, requests_per_second: -1, throttled_until_millis: 0, failures: [] }, statusCode: 200, headers: { 'content-type': 'application/json; charset=UTF-8', 'content-length': '239' }, warnings: null, meta: { context: null, request: { params: [Object], options: [Object], id: 1 }, name: 'elasticsearch-js', connection: { url: '<http://localhost:62222/>', id: '<http://localhost:62222/>', headers: {}, deadCount: 0, resurrectTimeout: 0, _openRequests: 0, status: 'alive', roles: [Object] }, attempts: 0, aborted: false } } ```
mrorz 18:23:52
沒有指定 op = ‘noop’ 的話是不是會無差別寫入呀
mrorz 18:24:44
第一次完全沒 `noop` ,但最新的 Articles 應該都要有 articleCategories
mrorz 18:28:53
關於「過去查過的訊息列表」的細節實作,規劃寫在這裡,請大家過目 @acerxp511 @lucien
https://g0v.hackmd.io/eIeU2g86Tfu5VnLazNfUvQ?both#Implementation-detail-2020510

主要要討論的東西有:
• 會新增一種 LIFF <> Chatbot GraphQL 的認證方式
• 如何用 google analytics utm_source 追蹤後續動作是來自「過去查過的訊息列表」的操作、並且記錄「過去查過的訊息列表」是「從 rich menu 點開」的還是「從 push message 點開」的
  • 👌1
2020-05-11
Sam Ho 09:54:55
@rongson has joined the channel
mrorz 13:13:41
Google search console 說下面這兩個頁面的點擊次數與上個月相比增加最多(+7.37K)
https://cofacts.g0v.tw/article/ui2q0uicd96a
https://cofacts.g0v.tw/article/u4qohr84huax

看來網友對把草莓插在樹上的影片很有興趣
mrorz 13:33:38
不過說到 Google,上週 Cofacts 配合 Youtube API Services Team 的 audit 調查,對方表示 Cofacts 在下面兩點不合格:

1. 沒有在 Privacy 與 ToS 中提及 Youtube ToS - Policy #: III.A.1,2
2. 沒有每 30 天就重新更新爬到的 non-authorized 資料 - Policy #: III.E.4.a-g
1 的部分我們可能會需要針對 Terms of use (LINE網站) 進行修正(加上 Youtube 相關敘述)之後,正式把它加到 Cofacts 官網上
2 的部分就就滿討厭的,不只技術上很煩,也會影響 Cofacts 的使用——一但原始謠言影片被下架,30 天內資料庫被強制更新,那個影片的 title 與 description 就會被洗掉。

我在 audit 時給的例子就很明顯,謠言本體剛好是個被下架的影片,拿另一個被重新上架的影片去查,還能查到對應的訊息:https://docs.google.com/document/d/1hlFszsLV9uUJl17L40o6AGZVtyAEoTcLA76wSz969QI/edit
(註: 步驟裡的那個 query 影片之前還活著,大概最近幾天也下架了⋯⋯)

Cofacts 之所以製作 URL preview,其中一個目的就是為了保存訊息被回報的當下,連結裡面的內容,以供未來查詢比對。如果要求我們每 30 天要更新,效果會大打折扣,以上面這個 COVID-19 陰謀論的例子來說,甚至會影響到 COVID-19 的防疫。

不知道大家有沒有什麼想法呢?
mrorz 13:35:11
1 的部分我們可能會需要針對 Terms of use (LINE網站) 進行修正(加上 Youtube 相關敘述)之後,正式把它加到 Cofacts 官網上
mrorz 13:42:06
Replied to a thread: 2020-05-11 13:33:38
2 的部分就就滿討厭的,不只技術上很煩,也會影響 Cofacts 的使用——一但原始謠言影片被下架,30 天內資料庫被強制更新,那個影片的 title 與 description 就會被洗掉。

我在 audit 時給的例子就很明顯,謠言本體剛好是個被下架的影片,拿另一個被重新上架的影片去查,還能查到對應的訊息:https://docs.google.com/document/d/1hlFszsLV9uUJl17L40o6AGZVtyAEoTcLA76wSz969QI/edit
(註: 步驟裡的那個 query 影片之前還活著,大概最近幾天也下架了⋯⋯)

Cofacts 之所以製作 URL preview,其中一個目的就是為了保存訊息被回報的當下,連結裡面的內容,以供未來查詢比對。如果要求我們每 30 天要更新,效果會大打折扣,以上面這個 COVID-19 陰謀論的例子來說,甚至會影響到 COVID-19 的防疫。

不知道大家有沒有什麼想法呢?
github 13:56:45
Replaced by `ListArticle`, no longer needs root-level article-reply list
github 14:10:34
As discussed in <https://g0v-slack-archive.g0v.ronny.tw/index/channel/C2PPMRQGP/2020-05#ts-1588494165.332500|Slack>, we are adding this to `ListArticleFilter`: ``` articleReplyFrom: { userId: String, appId: String, exists: Boolean } ``` In order to filter out articles that • contains my reply (for "我查核過" filter in reply (actually replied _article_) list) • does not contain my reply (for <https://g0v.hackmd.io/iJm9_nZaTA2GyInn7ycxoA|navbar "for you" numbering>) • contains a certain user's reply • contains no certain user's reply Relates to • <https://github.com/cofacts/rumors-api/issues/60|#60> • <https://github.com/cofacts/rumors-api/issues/35|#35> • <https://github.com/cofacts/rumors-site/pull/247#discussion_r419149777|cofacts/rumors-site#247 (comment)>
mrorz 14:14:00
Pass 的話不用理~
那個是在測 error handling 嗎?
github 14:15:34
Article should provide a field that returns analytics data for trend charts using <https://developers.google.com/analytics/devguides/reporting/core/v4|Google Analytics Reporting API> • Chatbot visit per day • Chatbot user count per day • Chatbot total visit in 30 days • Chatbot total user in 30 days • All above stats, but using Cofacts production site as target Related: • <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO?node-id=889:306#25950845|https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO?node-id=889:306#25950845>
mrorz 14:15:40
Article should provide a field that returns analytics data for trend charts using <https://developers.google.com/analytics/devguides/reporting/core/v4|Google Analytics Reporting API> Related: • <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO?node-id=889:306#25950845|https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO?node-id=889:306#25950845>
github 18:03:12
I eventually remove the LoadMore component and leverage the whole component to `AarticlePageLayout`, because with only `onClick` &amp; `loading` the LoadMore component seems similar to regular button, the actual logics are mostly move to `ArticlePageLayout`, it's a bit strange to have a Component call `LoadMore` while the actual load-more logics are written in upper component.
2020-05-12
github 02:21:21
Sorry, I forgot to consider the case when there is no "next" button: <https://user-images.githubusercontent.com/108608/81596572-e4ea0000-93f6-11ea-9841-4d63cce39514.png|image> (It's fine in mobile, though; it's just that floating action buttons are covering the last item)
github 02:21:21
Thanks for the modification! When clicking into detail pages &amp; back out, the scroll position and previously loaded pages all worked like a charm. Spotted some minor styling issue, not a blocker though.
mrorz 10:49:05
@ggm 有 conflict 唷

也可以參考一下我的 Comment ~
mrorz 10:59:05
Now on staging:
• API: https://github.com/cofacts/rumors-api/pull/153
• Website: dev branch (infinte scroll pending,稍晚 deploy)
• Chatbot: https://github.com/cofacts/rumors-line-bot/pull/184 (連環 7 PR 的最後一個,還有 4 個沒人 review)
我週三想要把這些都推上 production 來收 user feedback,比較能知道目前為止的這些大變動,有哪些需要改進的地方。推上去之後可能會有一兩週的 error 爆炸期。

網站、chatbot 的 error quota 還有滿多的,我覺得可以接得住 error。
• Staging site: https://cofacts.hacktabl.org/articles
• Staging line bot: https://lin.ee/1QUzEX4nI
大家覺得如何呢?有什麼 release blocker 嗎?
我是覺得 staging 的東西放一陣子了,都沒有人有啥意見,就算去 Facebook 社團請人到 staging 點一點,也應該不會有什麼人試。

早晚都要上 production,不如就直接放上去,才能收到真實的 feedback 或抱怨~
我想有一種做法是

production 放上 staging 的版本、保留原本 production 的 image,如果有很嚴重的問題的話就隨時 revert back 到原本的 production
如果沒問題的話就 merge 這些 PR、build 正式的 docker image label (其實 staging 跟 production 的 docker image 根本是同一份 code,只是 label 不同,並沒有 build-time config⋯⋯)
全民公測可能也不錯
我今天會把 chatbot 與網站英文翻中文
不過還是注意到一些網站的 release blocker:

• ~Article detail 裡的 upvote / downvote 已經被更新為新樣式,但是他是壞的(component prop breaking change?)~ PR249 中已修正
• 文章列表至少應該要有「熱門回報」filter,亦即現在 production 上的「僅顯示兩個回報以上」的功能
• 「等你來答」目前 filter 跟 spec 不符,功能跟 article list 預設目前一致
我覺得至少以上三點要修正,release 比較有意義 @@

Spec 與 mockup 放在:
https://g0v.hackmd.io/0xqZVqKiSYaIeSYFtT5NRg?view#Versions--release-scope
@lucien 針對 chatbot 的連環 PR,現況是
• 我的 PR 會與 GGM database 的部分有 conflict,先 merge 一個進去會比較好處理
• 尚未 review 的 PR 就算有東西要改,在過長的連環 PR 底下要改也很麻煩
我建議我的 chatbot PR 先全部 merge,有問題之後另外開 PR,這樣比較能 unblock 之後的開發與 deploy?
cc/ @ggm @acerxp511
我投先 merge 一票
conflict 我修掉哩
先 merge ok
全民公測也 ok
@acerxp511 @ggm dev merge 完囉,請把你們的 branch rebase 到最新的 dev
感謝感謝
mrorz 11:13:06
我是覺得 staging 的東西放一陣子了,都沒有人有啥意見,就算去 Facebook 社團請人到 staging 點一點,也應該不會有什麼人試。

早晚都要上 production,不如就直接放上去,才能收到真實的 feedback 或抱怨~
mrorz 11:19:23
我想有一種做法是

production 放上 staging 的版本、保留原本 production 的 image,如果有很嚴重的問題的話就隨時 revert back 到原本的 production
mrorz 11:20:36
如果沒問題的話就 merge 這些 PR、build 正式的 docker image label (其實 staging 跟 production 的 docker image 根本是同一份 code,只是 label 不同,並沒有 build-time config⋯⋯)
lucien 14:05:07
全民公測可能也不錯
2020-05-13
mrorz 11:16:24
Coscup我們能報哪一個議程呀
@lucien 已經截止囉。有個 open source chatbot track,但我變不出跟去年不同的內容,所以沒投。
mrorz 13:16:38
Replied to a thread: 2020-05-12 10:59:05
我今天會把 chatbot 與網站英文翻中文
不過還是注意到一些網站的 release blocker:

• ~Article detail 裡的 upvote / downvote 已經被更新為新樣式,但是他是壞的(component prop breaking change?)~ PR249 中已修正
• 文章列表至少應該要有「熱門回報」filter,亦即現在 production 上的「僅顯示兩個回報以上」的功能
• 「等你來答」目前 filter 跟 spec 不符,功能跟 article list 預設目前一致
我覺得至少以上三點要修正,release 比較有意義 @@

Spec 與 mockup 放在:
https://g0v.hackmd.io/0xqZVqKiSYaIeSYFtT5NRg?view#Versions--release-scope
lucien 14:32:10
Coscup我們能報哪一個議程呀
mrorz 15:18:41
@lucien 已經截止囉。有個 open source chatbot track,但我變不出跟去年不同的內容,所以沒投。
mrorz 15:30:54
現在 staging site 上的是 @yanglin5689446PR-249 的內容唷

有新的 article detail:https://cofacts.hacktabl.org/article/1fiten3qki74s
直連 article detail 會 time-out,看起來是遇到了之前 yanglin 回報的 `requestedForReply` 欄位很慢的問題
https://g0v-tw.slack.com/archives/C2PPMRQGP/p1588665581350300
@lucien @stbb1025 實際用起來才發現,現在「寫新回應」區塊放在「現有回應」上面,可能會讓使用者以為沒有新回應,就自己寫了一個 XD

那個區塊是可以收合的嗎? wireframe 與 mockup 好像沒有標記。而且如果可以收合,也不知道如何把該區塊「合起來」。

cc/ @yanglin5689446
咦?不是點查核闢謠才會展開嗎
可能因為沒標所以 https://cofacts.hacktabl.org/articles 目前實作是開開的 XD

另外點開之後要怎麼關起來呢?再點一次「查核闢謠」按鈕?
好XD我再補一下
點了之後不用關起來吧?如果照你說的情境,目前的設計他們一定是有看到下面回應才點開的
是點擊才出現
Hmm 那先讓他預設收合後再看看好了
我也是實際在網站上看了之後才發現,使用者有可能看完訊息就想回這件事情

希望預設收合之後,「現有回應」的可見度就會變高。
所以寫新回應的區塊
手機版跟 PC 版一致都是點了 `查核闢謠` 按鈕之後才打開嗎?
手機版會切換到新頁面唷
PC 與手機都是點了按鈕之後才會有查核闢謠的區塊或全版 modal

手機要不要換 URL 可以討論
換網址的話就能按手機的 back
不換網址的話可能還是要處理一下手機的 back 避免誤按(或保留現在的自動儲存功能)
我私心覺得兩個都可以換網址一下
這樣我在做的時候可以固定網址 hot relaod 不用一直點開 XD
啊 不過 next router 我不熟 QQ
我非常懷疑 next-router 是否能做到這種 full-screen modal 換 URL 但原頁面後面的資料全數保留的事情
可以 google 一下有沒有人做過
說不定其實可以這樣

```// pages/article/[id].js

export default DefaultArticlePage() {
// ...
return <ArticlePage showCreate={false} />
}

// pages/article/[id]/create.js

export default ArticlePageWithCreate() {
// ...
return <ArticlePage showCreate={true} />
}```
然後直接用 next-router `Link` 換頁之類的

因為是兩個相同的 component 所以或許 react reconcile 時會發現是同一個 component 所以不會重新 mount

但可能要測一下
雖然這樣做要小心頁面裡的所有 URL 絕對不能用相對路徑,不然 `/article/xxx` 到 `/article/xxx/create` 會導致相對路徑對歪 XD
mrorz 15:34:39
直連 article detail 會 time-out,看起來是遇到了之前 yanglin 回報的 `requestedForReply` 欄位很慢的問題
https://g0v-tw.slack.com/archives/C2PPMRQGP/p1588665581350300
yanglin
不知道為什麼 `GetArticle` 只要 query `requestedForReply` 就會變得很慢欸 0.0
github 15:40:52
Deployed to <https://cofacts.hacktabl.org/articles|https://cofacts.hacktabl.org/articles> so that everyone can inspect. <https://hub.docker.com/r/cofacts/rumors-site/tags|Docker image tags>: `pr249-en` and `pr249-tw`
mrorz 15:49:37
@lucien 針對 chatbot 的連環 PR,現況是
• 我的 PR 會與 GGM database 的部分有 conflict,先 merge 一個進去會比較好處理
• 尚未 review 的 PR 就算有東西要改,在過長的連環 PR 底下要改也很麻煩
我建議我的 chatbot PR 先全部 merge,有問題之後另外開 PR,這樣比較能 unblock 之後的開發與 deploy?
cc/ @ggm @acerxp511
mrorz 16:03:50
@lucien @stbb1025 實際用起來才發現,現在「寫新回應」區塊放在「現有回應」上面,可能會讓使用者以為沒有新回應,就自己寫了一個 XD

那個區塊是可以收合的嗎? wireframe 與 mockup 好像沒有標記。而且如果可以收合,也不知道如何把該區塊「合起來」。

cc/ @yanglin5689446
stbb1025 16:05:53
咦?不是點查核闢謠才會展開嗎
  • 😮1
mrorz 16:07:20
可能因為沒標所以 https://cofacts.hacktabl.org/articles 目前實作是開開的 XD

另外點開之後要怎麼關起來呢?再點一次「查核闢謠」按鈕?
stbb1025 16:09:03
好XD我再補一下
點了之後不用關起來吧?如果照你說的情境,目前的設計他們一定是有看到下面回應才點開的
lucien 16:10:42
是點擊才出現
mrorz 16:11:00
Hmm 那先讓他預設收合後再看看好了
mrorz 16:11:39
我也是實際在網站上看了之後才發現,使用者有可能看完訊息就想回這件事情

希望預設收合之後,「現有回應」的可見度就會變高。
nonumpa 16:12:40
我投先 merge 一票
  • 1
stbb1025 17:55:04
今天想討論一下這樣的landing page走向o不ok?
ok的話我就繼續把後面內容做完
(這版的寬是1024)
landing_page_20200513.png
  • ❤️4
  • 🐳1
  • 🦒1
@bil @mrorz @lucien
(努力想像首圖英文版怎麼處理)
我覺得很有趣~~
「大家都想知道」是最近新謠言嗎
可以幫我翻譯一下嗎我就直接排XD
是熱門謠言,但我想跟大家討論一下要揭露哪些訊息
Got a hoax in messaging app?
Was it a FAKE NEWS?
Got something suspicious in messaging apps?
You may:
Copy & paste the suspicious content here
[Look it UP]
Was it a FAKE NEWS? ->我喜歡這個 ❤️
f-word XD

媒體是好朋友,用 f-word 感覺會讓媒體有戒心
原來有這層考量 XD
stbb1025 17:59:25
@bil @mrorz @lucien
mrorz 17:59:42
(努力想像首圖英文版怎麼處理)
mrorz 17:59:57
我覺得很有趣~~
mrorz 18:00:06
「大家都想知道」是最近新謠言嗎
stbb1025 18:00:07
可以幫我翻譯一下嗎我就直接排XD
stbb1025 18:01:46
是熱門謠言,但我想跟大家討論一下要揭露哪些訊息
mrorz 18:02:57
Got a hoax in messaging app?
  • ❤️1
bil 18:03:14
Was it a FAKE NEWS?
  • ❤️1
mrorz 18:04:31
Got something suspicious in messaging apps?
  • ❤️1
ggm 18:06:05
真怪我之前有 rebase 了說,我又 rebase 然後 push 囉
bil 18:06:07
You may:
Copy & paste the suspicious content here
[Look it UP]
  • ❤️1
ggm 18:06:40
conflict 我修掉哩
ggm 18:07:18
先 merge ok
  • 1
ggm 18:08:01
全民公測也 ok
stbb1025 18:09:16
Was it a FAKE NEWS? ->我喜歡這個 ❤️
mrorz 18:25:04
我剛才在整理現在 staging 與 spec 不一樣的地方,然後發現 spec 有個地方我也不太清楚。

想問 @lucien spec 的 article list(可疑訊息)reply list(最新查核)的 default filter 分別是什麼呢?會有「什麼 filter 都沒有」的狀況嗎?如果「什麼 filter 都沒有」,那 article list 與 reply list 的差別會是什麼呢?
@lucien 可以說明一下 article list(可疑訊息) 與 reply list(最新查核)的 default filter 分別是什麼呢?
Default 沒有filter 但有 sort
@lucien 所以「最新查核」會顯示「尚未被回應」的文章嗎~?

https://g0v.hackmd.io/@NFi0czulSemxCM8RNSlz8Q/HJ8xT3QVU/%2FZZWHWi2BTuyhkSWzAvKLAw spec 沒說不行唷。
所以目前也實作成了這樣,尚無回應的文章也可能會列在「最新查核」
最新查核只會出現有查核過的文章
一定是至少有一篇回應的
現在最新查核也是從 article 下去 filter 而不是 reply 對嗎
已更新
不過這是不會出現在選項上的 filter
感謝更新,這可能要開一張新票來處理

目前 @yanglin5689446 實作的 `defaultFilter` 機制可能要稍微改一下,才能支援這種「不會出現在選項上、關不掉的 filter」
(現在的 `defaultFilter` 可以被新設的 filter 覆蓋)
mrorz 20:07:49
@acerxp511 @ggm dev merge 完囉,請把你們的 branch rebase 到最新的 dev
感謝感謝
  • 💪1
delightfullychaotic 21:42:15
請問開會是開完了嗎?我一直找不到連結QQ
delightfullychaotic 2020-05-13 22:00:22
結果有剛剛按個mute 就默默又沒有了== Howie真的不用負責嗎
但我也不知道怎麼重現 XD 他只能通靈
或許我們的 powercall room 很有靈氣
比較容易重現 bug
你可以跟他約在那個 room
說不定就能重現
nonumpa 21:46:03
tico.chat
The considerate messenger. Chat with whom you care about always at the best moments and times
delightfullychaotic 22:00:22
結果有剛剛按個mute 就默默又沒有了== Howie真的不用負責嗎
Further 23:27:27
@i.further.54 has joined the channel
mrorz 23:52:26
但我也不知道怎麼重現 XD 他只能通靈
mrorz 23:53:31
或許我們的 powercall room 很有靈氣
比較容易重現 bug
你可以跟他約在那個 room
說不定就能重現
mrorz 23:54:17
f-word XD

媒體是好朋友,用 f-word 感覺會讓媒體有戒心
2020-05-14
mrorz 02:38:48
Figma
Created with Figma
https://cofacts.kktix.cc/events/cofacteditor20 請看看有沒有 misinformation (?)
頭到砲管的很迷因耶,不用嗎
那張是直的 超難排
這樣嗎
是說怎麼看得出來那是砲管 w
哈哈哈哈
所以要放哪張 wwwww
Model 決定@bil
@delightfullychaotic 麻煩你在在地社團散佈惹 m(_ _)m https://cofacts.kktix.cc/events/cofacteditor20
delightfullychaotic 2020-05-16 15:40:47
我覺得有model正面更好!
yanglin 08:24:38
所以寫新回應的區塊
手機版跟 PC 版一致都是點了 `查核闢謠` 按鈕之後才打開嗎?
stbb1025 09:17:52
手機版會切換到新頁面唷
bil 11:15:04
CC
  • 2
mrorz 11:17:13
PC 與手機都是點了按鈕之後才會有查核闢謠的區塊或全版 modal

手機要不要換 URL 可以討論
換網址的話就能按手機的 back
不換網址的話可能還是要處理一下手機的 back 避免誤按(或保留現在的自動儲存功能)
mrorz 11:34:13
https://cofacts.kktix.cc/events/cofacteditor20 請看看有沒有 misinformation (?)
cofacts.kktix.cc
2 個月一次,用一個下午與 Cofacts 一起工作闢謠解惑,讓不同意見突破同溫層。 來編輯小聚就送限量 Cofacts 貼紙。回應超過200篇,送委外設計LINE貼圖!感謝好想工作室 提供場地。
github 11:55:52
Staging DB provisioned on Heroku, let's give it a shot <https://user-images.githubusercontent.com/108608/81890969-d740a000-95d9-11ea-91ac-8a389767eb25.png|螢幕快照 2020-05-14 上午11 52 59>
stbb1025 12:03:57
原來有這層考量 XD
mrorz 12:13:55
Replied to a thread: 2020-05-05 15:59:41
我發現 5/4 更新 staging API 成 https://github.com/cofacts/rumors-api/pull/153 的版本之後,5/5 @yanglin5689446 就回報問題

朝 API 裡面 elasticsearch result 沒接好的方向調查 ing
  • 👌1
mrorz 14:19:44
結果不是 elasticsearch result 沒接好
而是
1. 一般來說,跟使用者相關的 object field 如 `ownVote` 等等,在沒有指定 userId (如:SSR) 時,會直接回傳 null。然而, `requestedForReply` 錯誤地使用了只有 mutation API 該用的 `assertUser({...})` ,所以只要有 requestedForReply 就會產生 error。
mrorz 14:20:21
image.png
mrorz 14:21:02
image.png
mrorz 14:22:16
2. 我們用的 apollo-link-error 如果有 exception 的話,他就會無聲無息地悶不吭聲,讓後面的 apollo-client resolve 一整個卡住。我是在 `BatchHttpLink` 與 `onError` 中間插了一個印 console 的 link 才能抓到那個 error。

目前我們的 `onError` 裡頭用了 `alert()`,在 NodeJS 環境下並無此 function,所以他其實應該在 runtime 時遇到了 Reference error,但卻無聲無息。
lucien 14:49:42
頭到砲管的很迷因耶,不用嗎
github 14:57:26
During SSR, an GraphQL Error can halt the processing of Apollo-link middlewares, causing the server-side render to return nothing. This PR 1. Always print the error to console 2. Fix SSR by detecting if `alert` exists in the global namespace (it's `undefined` during NodeJS SSR) From discussion: <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589437262448200?thread_ts=1588665581.350300&amp;cid=C2PPMRQGP|https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589437262448200?thread_ts=1588665581.350300&amp;cid=C2PPMRQGP> &gt; 2. 我們用的 apollo-link-error 如果有 exception 的話,他就會無聲無息地悶不吭聲,讓後面的 apollo-client resolve 一整個卡住。我是在 BatchHttpLink 與 onError 中間插了一個印 console 的 link 才能抓到那個 error。 &gt; 目前我們的 onError 裡頭用了 alert(),在 NodeJS 環境下並無此 function,所以他其實應該在 runtime 時遇到了 Reference error,但卻無聲無息。
yanglin 15:13:49
我私心覺得兩個都可以換網址一下
這樣我在做的時候可以固定網址 hot relaod 不用一直點開 XD
yanglin 15:38:12
啊 不過 next router 我不熟 QQ
mrorz 15:48:31
至於 apollo-link-error 把 runtime error 吃掉這件事情,我在 codesandbox 上卻無法重現

https://codesandbox.io/s/awesome-shamir-vpf2d?file=/index.js
mrorz 15:50:01
看起來 error 有好好地被抓出來 @@
image.png
github 16:52:46
Currently, `requestedForReply` of `Article` object type would throw error if the user is not logged-in. However, other fields that requires authentication (such as <https://github.com/cofacts/rumors-api/blob/master/src/graphql/models/ArticleReply.js#L68-L89|`ownVote`>, <https://github.com/cofacts/rumors-api/blob/master/src/graphql/models/ArticleReply.js#L42-L51|`canUpdateStatus`>) just returns `null` if the user is not logged in. `assertUser()` is meant for mutation resolvers and ordinary object type resolvers should avoid using `assertUser()`. Related discussion: • <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1588665581350300|https://g0v-tw.slack.com/archives/C2PPMRQGP/p1588665581350300> • <https://g0v-slack-archive.g0v.ronny.tw/index/channel/C2PPMRQGP#ts-1588665581.350300|https://g0v-slack-archive.g0v.ronny.tw/index/channel/C2PPMRQGP#ts-1588665581.350300>
mrorz 16:55:08
我非常懷疑 next-router 是否能做到這種 full-screen modal 換 URL 但原頁面後面的資料全數保留的事情
可以 google 一下有沒有人做過
  • 😢1
mrorz 16:56:47
說不定其實可以這樣

```// pages/article/[id].js

export default DefaultArticlePage() {
// ...
return <ArticlePage showCreate={false} />
}

// pages/article/[id]/create.js

export default ArticlePageWithCreate() {
// ...
return <ArticlePage showCreate={true} />
}```
然後直接用 next-router `Link` 換頁之類的

因為是兩個相同的 component 所以或許 react reconcile 時會發現是同一個 component 所以不會重新 mount

但可能要測一下
mrorz 16:59:44
雖然這樣做要小心頁面裡的所有 URL 絕對不能用相對路徑,不然 `/article/xxx` 到 `/article/xxx/create` 會導致相對路徑對歪 XD
mrorz 17:00:47
那張是直的 超難排
mrorz 17:13:35
這樣嗎
image.png
mrorz 17:15:15
是說怎麼看得出來那是砲管 w
lucien 17:30:46
哈哈哈哈
github 18:25:51
No idea why pr keeps failing no matter how many times I rebuild. `CreateReply` test cleanup always fails. On my local machine, I can reproduce the error for the first time I merge the code, but cannot reproduce at all after the first run. Soooo weird.
mrorz 21:48:13
所以要放哪張 wwwww
lucien 22:15:22
Model 決定@bil
mrorz 22:59:31
cofacts.kktix.cc
2 個月一次,用一個下午與 Cofacts 一起工作闢謠解惑,讓不同意見突破同溫層。 來編輯小聚就送限量 Cofacts 貼紙。回應超過200篇,送委外設計LINE貼圖!感謝好想工作室 提供場地。
2020-05-15
yanglin 11:30:59
想問一下上面的那個篩選
我原本以為他只能單選(舊的邏輯也是單選)
不過從新的邏輯上來看這幾個選項是沒有重疊的
所以他們是可以多選的嗎?
image.png
lucien 11:35:27
是設計成可以多選的
  • 👌2
github 14:23:28
Currently if we click "Share" on desktop with a narrow browser screen, the share button does nothing. Let's combine `openMenu` and `handleShare`: • If `navigator.share` exists, use then invoke `navigator.share` • Otherwise, perform logic in `openMenu` We would only need one button this way
github 14:23:28
Looks like something worth joining <http://cofacts.hacktabl.org/storybook/index.html|http://cofacts.hacktabl.org/storybook/index.html> Otherwise we may forget about this component :P
github 14:23:28
`px` incorrect; you may also need to adjust `py` taking its content into consideration *as-is* <https://user-images.githubusercontent.com/108608/81927501-50f67f00-9616-11ea-9497-a4f8c51f00c1.png|image> *to-be* Spec: <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=889%3A306|https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=889%3A306> <https://user-images.githubusercontent.com/108608/81927523-5eac0480-9616-11ea-9321-bd2d0385e6eb.png|image>
github 14:23:28
This default assignment breaks `if (!article) {` early-return condition in L172 below. Therefore, if user mistyped the article ID, they are greeted with internal server error: <https://user-images.githubusercontent.com/108608/81925904-b8f79600-9613-11ea-80d7-c51ce8ebaa9f.png|image> I suggest 1. Move all hooks invocation forward to enable early-return 2. Use early return to guard unexpected condition 3. Push all destructuring assignments as late as possible, or at least after the early return blocks
github 14:23:28
I did not went through all the files, here are the first batch of the comments. Some of them are regarding functionalities, which we can discuss. For comments on paddings / margins / borders, we can leave that to the future PRs (when mobile design is implemented)
github 14:23:28
Please re-adjust the padding so that it matches <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=889%3A306|mockup>. • padding between content and separator should be 16px • last item should not have bottom separator
github 14:23:28
1. Seems that this line does not appear? Currently there is no separation between replies, which is a bit hard to read. <https://user-images.githubusercontent.com/108608/82017417-b0f03280-96b5-11ea-9b82-f19ee8656924.png|image> 2. According to <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=681%3A0|mockup> the horizontal line between replies should be solid lines.
github 14:23:28
Let's follow the mockup and limit the number of line of such message to 5 and mind its line breaks. <https://cofacts.hacktabl.org/article/16aoyuv6t0cwz|https://cofacts.hacktabl.org/article/16aoyuv6t0cwz> <https://user-images.githubusercontent.com/108608/81927029-8babe780-9615-11ea-98d8-f21a5d295fc8.png|image> Mockup: <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=889%3A306|https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=889%3A306>
github 14:23:29
Copy 請改成 &gt; Inserting blank lines between reference items can improve readability in LINE. cc/ <https://github.com/LucienLee|@LucienLee>
github 14:23:29
margin top too big for this and the following cards *as-is* <https://user-images.githubusercontent.com/108608/81927953-1214f900-9617-11ea-8b44-02ec0ada917a.png|image> *to-be* <https://user-images.githubusercontent.com/108608/81928000-25c05f80-9617-11ea-8c51-0d10ef61904f.png|image>
github 14:23:29
This class does not seem to have any effect
github 14:23:29
The line on the top of Reference should be `dashed` not `dotted`
github 14:23:29
"I second that" button toggles the form that submits `replyRequest`, thus I think the state `requestedForReply` should link to that button. ( <https://github.com/LucienLee|@LucienLee> , do we have different state for "I second that" button if the user has requested reply? ) I don't see "I also wanna know" button in mockup now
github 14:23:29
As <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589357030428400?thread_ts=1589355054.427400&amp;cid=C2PPMRQGP|discussed in slack> the new form should be collapsed (hidden) by default. <https://user-images.githubusercontent.com/108608/82015571-a16eea80-96b1-11ea-9bcb-626c1c4e43fa.png|image> Also there are <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589440429449700?thread_ts=1589355054.427400&amp;cid=C2PPMRQGP|discussions> around having new URL for the state that has form expanded. I am OK with both URL or no URL solution.
yanglin 18:17:07
現在 `ListArticles` 有 `replied by me` 的 filter 嗎?
只看到用 appId + userId 做 filter 的
mrorz 18:19:59
As discussed in <https://g0v-slack-archive.g0v.ronny.tw/index/channel/C2PPMRQGP/2020-05#ts-1588494165.332500|Slack>, we are adding this to `ListArticleFilter`: ``` articleReplyFrom: { userId: String, appId: String, exists: Boolean } ``` In order to filter out articles that • contains my reply (for "我查核過" filter in reply (actually replied _article_) list) • does not contain my reply (for <https://g0v.hackmd.io/iJm9_nZaTA2GyInn7ycxoA|navbar "for you" numbering>) • contains a certain user's reply • contains no certain user's reply Relates to • <https://github.com/cofacts/rumors-api/issues/60|#60> • <https://github.com/cofacts/rumors-api/issues/35|#35> • <https://github.com/cofacts/rumors-site/pull/247#discussion_r419149777|cofacts/rumors-site#247 (comment)>
  • 👌1
2020-05-16
github 03:03:23
fix some bugs and add some missing features mentioned <https://g0v.hackmd.io/8qj-pd_XTN-nOYMi-5ZBnw|here>
mrorz 13:00:00
Replied to a thread: 2020-05-13 18:25:04
@lucien 可以說明一下 article list(可疑訊息) 與 reply list(最新查核)的 default filter 分別是什麼呢?
mrorz 13:47:45
@acerxp511 發現 cofacts 的 url-resolver 好像掛了,現在傳含有 URL 進 chatbot 或 Cofacts 網站都不會有回應
一個月內好像也有發生一次,我也是手動進去重開 url-resolver

這裡有 survey 一些不用 puppeteer (headless browser) 的方式,但還沒有結果

https://github.com/cofacts/url-resolver/issues/69
mem 吃完 2G, CPU 400%
某種同步率嗎⋯⋯
重開了
平常時候是這樣
機器是 16G RAM
elasticsearch 吃掉了 9G (JVM 選項開 8G)
我覺得開 2G 給 url-resolver 合理,還是我應該開 4G?
url-resovler logs:
https://drive.google.com/drive/folders/1f2poUvF6M315inwV4BWHy2tBWah2Yu-f?usp=sharing
• 看起來我們很常要爬 youtube 網址,常爬到超過 quota
• 系統過載之後就是一直 network error,看不出來到底是發生什麼事情
• 還沒找到原爆點。說不定在那個地方可以看到是某些特定 URL 或在一段時間內被要求 resolve 很多 URL 之後就會進入這種 CPU 400%, mem 100% 的狀態?
目前對要怎麼 monitor 與自動 recover 還沒想法 >“<
mrorz 13:48:30
一個月內好像也有發生一次,我也是手動進去重開 url-resolver

這裡有 survey 一些不用 puppeteer (headless browser) 的方式,但還沒有結果

https://github.com/cofacts/url-resolver/issues/69
Current implementation (puppeteer) eats up too much resource and the its throughput cannot keep up with the usage of rumors-api. We should consider other solutions as well. *Resources* Previous research: <https://github.com/cofacts/rumors-api/issues/41|cofacts/rumors-api#41> Web archiving tools by IIPC (behind wayback machine) <https://github.com/iipc/awesome-web-archiving|https://github.com/iipc/awesome-web-archiving> *Archiver* • Python + headless chrome <https://github.com/internetarchive/brozzler|https://github.com/internetarchive/brozzler> • Headless chrome <https://github.com/N0taN3rd/Squidwarc|https://github.com/N0taN3rd/Squidwarc> • Headless chrome with queue <https://github.com/yujiosaka/headless-chrome-crawler|https://github.com/yujiosaka/headless-chrome-crawler> • Save all in one html file <https://github.com/Y2Z/monolith|https://github.com/Y2Z/monolith> *Text summarization (w/ Chinese upport)* • request + newspaper3k (Python3) <https://newspaper.readthedocs.io/en/latest/|https://newspaper.readthedocs.io/en/latest/> *Misc* • Readability + readability-readarable <https://github.com/mozilla/readability#whats-readability-readerable|https://github.com/mozilla/readability#whats-readability-readerable>
lucien 13:48:45
Default 沒有filter 但有 sort
mrorz 13:51:42
mem 吃完 2G, CPU 400%
某種同步率嗎⋯⋯
image.png
  • 😮1
mrorz 14:02:17
重開了
mrorz 14:10:00
平常時候是這樣
memory.gif
mrorz 14:10:55
機器是 16G RAM
elasticsearch 吃掉了 9G (JVM 選項開 8G)
我覺得開 2G 給 url-resolver 合理,還是我應該開 4G?
mrorz 14:24:02
url-resovler logs:
https://drive.google.com/drive/folders/1f2poUvF6M315inwV4BWHy2tBWah2Yu-f?usp=sharing
• 看起來我們很常要爬 youtube 網址,常爬到超過 quota
• 系統過載之後就是一直 network error,看不出來到底是發生什麼事情
• 還沒找到原爆點。說不定在那個地方可以看到是某些特定 URL 或在一段時間內被要求 resolve 很多 URL 之後就會進入這種 CPU 400%, mem 100% 的狀態?
mrorz 14:25:36
目前對要怎麼 monitor 與自動 recover 還沒想法 >“<
mrorz 15:09:00
@lucien 所以「最新查核」會顯示「尚未被回應」的文章嗎~?

https://g0v.hackmd.io/@NFi0czulSemxCM8RNSlz8Q/HJ8xT3QVU/%2FZZWHWi2BTuyhkSWzAvKLAw spec 沒說不行唷。
mrorz 15:21:52
所以目前也實作成了這樣,尚無回應的文章也可能會列在「最新查核」
image.png
mrorz 15:33:05
Replied to a thread: 2020-05-14 02:38:48
@delightfullychaotic 麻煩你在在地社團散佈惹 m(_ _)m https://cofacts.kktix.cc/events/cofacteditor20
cofacts.kktix.cc
2 個月一次,用一個下午與 Cofacts 一起工作闢謠解惑,讓不同意見突破同溫層。 來編輯小聚就送限量 Cofacts 貼紙。回應超過200篇,送委外設計LINE貼圖!感謝好想工作室 提供場地。
  • ❤️1
  • 1
  • 2
delightfullychaotic 15:40:47
我覺得有model正面更好!
github 16:52:06
Seems that Material-UI's `TextField` applies a `flex-direction: column` to the root component of `TextField`, causing the control height not following the height of its container. Overriding the default `flex-direction` may allow `TextField` height in-sync with its container: <https://user-images.githubusercontent.com/108608/82112973-bf594f80-9784-11ea-8b97-6e3c4e397338.png|image>
github 16:52:06
1. `overflow: scroll` will cause non-Mac browsers always display a scrollbar like this: <https://user-images.githubusercontent.com/108608/82112770-dac35b00-9782-11ea-8d7c-a8bff5ecf171.png|image> 2. In this case we should never need a scrollbar, thus I don't think we ever need `overflow` property. I suggest we remove `alignItems="center"` together, using the default value of `align-items`, which is `stretch` and should make flex items stretch to have equal height. Next thing is removing excessive wrapping `div`s surrounding the flex items, so that the dropdown components can be the direct child (flex item) of the flexbox. Under the power of `align-item: stretch`, they should then have the same height, achieving the style we want.
github 16:52:06
Sometimes we would use `{start: undefined, end: &lt;some-time&gt;}` to find messages from the beginning of the project to a specific date. Therefore, I think we should also support the case with only `end` as well. ``` if (start) { filterObj[timeRangeKey] = {...filterObj[timeRangeKey], GTE: start}; } if (end) { filterObj[timeRangeKey] = {...filterObj[timeRangeKey], LTE: end}; } ```
github 16:52:06
Thank you for the timely fix! It's so glad to see the outdated `status` being replaced by the brand new `filter` mechanism :rocket: Please find below my suggestions regarding styles and filters applied. Also, regarding reply list (`pages/replies.js`), I am confirming with <https://github.com/LucienLee|@LucienLee> to see if we should apply a always-on filter on `replyCount` in this <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589365504440400|slack thread>. Let's follow up the discussion in slack.
github 16:52:06
Articles with reply (`replyCount` &gt; 0) but has no positive feedbacks should also be included, so we can drop `replyCount = 0` constraint
github 16:52:06
Articles with reply `(replyCount &gt; 0)` but has no positive feedbacks should also be included, so we can drop `replyCount = 0` constraint. Ref: <https://g0v.hackmd.io/@NFi0czulSemxCM8RNSlz8Q/HJ8xT3QVU/%2FahtI6xsFRQyxktrIlc1VcQ|spec>
github 16:52:07
Need to check why `classes` is undefined in mobile <https://user-images.githubusercontent.com/108608/82113048-5cb48380-9785-11ea-8b7a-aca8653ebfdc.gif|filter-error>
github 18:56:26
Actually this collides with reply's localstorage cache. This is a bug that can be perceived in current production as well. Changing `text` to some other key should fix the bug; we can also open a separate issue, since this is not in the scope of this PR actually. <https://user-images.githubusercontent.com/108608/82118015-e88ad780-97a6-11ea-8541-057b3cb7ed06.png|螢幕快照 2020-05-16 下午6 53 59>
github 19:49:48
This `flex` is not needed. Instead, I think we can add `-webkit-line-clamp` (and other properties to make it work) <https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp|https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp> so that it displays `...` when text is truncated.
github 19:50:28
When there is no image on the right, we don't need `marginRight`. Therefore I suggest we should set `margin-left` on image instead.
github 19:52:27
font-size should be 14 according to <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=889%3A306|mockup>. Currently it's slightly larger than 14px due to Google chrome's user agent stylesheet <https://user-images.githubusercontent.com/108608/82119147-bd0beb00-97ae-11ea-955e-a002fa2b86c8.png|image>
github 19:59:51
<https://user-images.githubusercontent.com/12843409/82119267-913d3500-97af-11ea-917e-db1faae0bc0d.png|截圖 2020-05-16 下午7 56 13> the `overflow: hidden` is because that when selecting custom time range, the total length would be too long that breaks the layout
delightfullychaotic 22:19:37
感謝感謝
台南人的紅血球很有趣
delightfullychaotic 22:19:49
等到發完文會請台南社群協助
github 22:52:41
I think that instead of customizing a button from browser style into primary button, we should use <https://material-ui.com/components/buttons/#contained-buttons|Material UI Contained Buttons with `disableElevation`>. It has better handle over hover &amp; active states as well. The same goes to the button and the <https://material-ui.com/components/button-group/#disabled-elevation|buttonGroup> in `CreateReplyRequestForm`.
github 23:39:23
Hmm I didn't think of that. I think we can have a wrapping flexbox here, allowing the sort control go to second line.
mrorz 23:41:09
感謝感謝
mrorz 23:41:20
台南人的紅血球很有趣
github 23:51:25
It is in a good shape now, I think are just a few steps away before pushing to production. • fix conflict • handling the case when date selector &amp; sort dropdown break the screen • maybe showing only articles with replies in `/pages/replies` (discussion: <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589365504440400|https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589365504440400> )
2020-05-17
yanglin 00:13:54
@lucien @stbb1025 @mrorz
想問一下 search result 頁面現在的狀況
https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=432%3A2019
之前提到的問題應該是目前沒辦法用 `ListReplies` 去關聯到原始訊息
所以沒辦法套用到如熱門查核、含有個人意見等 articles 相關的 filter
應該也沒有辦法套用主題 filter
Figma
Created with Figma
從 reply 的角度應該也沒辦法列出回應的原始的 article
因為一個 reply 可能會關聯到多個 articles
你說的沒錯,搜尋頁面的「查核回應」是無法用熱門查核、含有個人意見等 article 相關的 filter

spec 裡面也確實針對「查核回應」訂有與 article 不同的 filter:
https://g0v.hackmd.io/oWSar1t0SzWo150Dsbepxw#%E6%9F%A5%E6%A0%B8%E5%9B%9E%E6%87%89

• 自己回應的 (對應到 `ListReplyFilter.selfOnly`)
• 「reply type」以及時間(對應到 `ListReplyFilter.type`)
Wireframe 與 Mockup 裡面會顯示跟 article filter 一樣,我猜是複製貼上忘記改~
我覺得就按照 spec 裡說的,使用「自己回應的」與 reply type 即可~

有需要 mockup 排的話可以請 @stbb1025
還有一個問題是 reply 可能會對應到多個 article
所以應該沒辦法做到這樣?
請直接拿第一個 article 唷,因為第一個應該是回應原作者連結的,理論上那個回應應該與第一個文章最吻合
會對第一個原始文章,下面顯示的更多被用於哪些文章,點擊後會以 modal 形式出現其他的文章列表
yanglin 00:16:19
從 reply 的角度應該也沒辦法列出回應的原始的 article
因為一個 reply 可能會關聯到多個 articles
yanglin 00:26:23
@lucien @stbb1025 @mrorz
然後想討論一下手機版 reply editor 的一些問題
因為我上次會只開一半拍謝 QQ
https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=1307%3A131
手機版的 editor 會根據回應的種類而改變上面的分頁
但有幾個問題:
1. 分頁的邏輯 PC 跟手機版不同,PC 版是編輯器跟查回應,手機版則是坐在上方的 select,對使用者來說會不會有點怪?
2. 現有的 ReplyForm component 是一個 form 包含回應內容跟資料來源的輸入,現在手機版的設計會變成內容跟資料來源是不同分頁,可能會變成整個 component 架構的大改,複雜度會提高滿多的,想討論看看有沒有折衷辦法
3. 我在想有可不可以讓手機版編輯器像 drawer https://material-ui.com/zh/components/drawers/ 一樣下滑,就可以邊看到原文回應編編輯了,就可以少做一個分頁
Figma
Created with Figma
material-ui.com
导航抽屉提供了一个访问您应用中的目标地址的途径。侧边栏被固定在屏幕的左侧或右侧,而它包含了一些补充内容。
1. 「撰寫新回應 / 使用現有回應」之所以從 tab 變 select 是因為有兩層 tab 很怪,所以前者換成 select 放在最上面。我是覺得這對手機使用者滿自然的~
2. 我覺得手機螢幕實在太受限,必須要重排整個使用者體驗,導致行為桌機版的 `NewReplySection` 整個都不一樣,建議要直接手機版跟電腦版分開做 QQ (如 `DesktopNewReplySection`/`MobileNewReplySection`之類)。不過,視覺上很類似的一些子 component 就可以重用,外觀功能差太多的部分就直接分不同的版本ㄅ。
3. 我覺得他比較像是 full-screen dialog (`<Dialog fullScreen>`)。編輯器的「原始文章/撰寫回應/資料來源」則是 swipable full-width tab (`<Tabs variant="fullWidth">`搭配 `SwipeableViews`)。關於 Drawer,寫回應的時候只看那些 Drawer 露出的小部分原文恐怕沒有太大幫助,而寫回應本身也是需要整個螢幕來專心的作業,權衡之下我覺得 Drawer 可能沒有比 full-screen dialog 好唷。
關於 3 我是想編輯器還是全螢幕
只是可能可以往下拉露出上半部
就可以跟原文作對照?
或著說我現在不太確定「原始文章」那個分頁會怎麼呈現
分頁我明天補上唷,不好意思~
但基本上就是很簡單的筆記本呈現形式,不會有圓角外框
> 只是可能可以往下拉露出上半部
> 就可以跟原文作對照?
我們在討論的時候,原本確實有想過上下 split screen。但後來想到一件事情:
「如果 soft keyboard 一顯示,整個螢幕還剩下多少空間?」

然後我就打消上下分開這個想法了。
抽屜當天我有提出來討論過,不過因為除了輸入空間考慮,當天還有討論理由與來源的流程擺放問題,如果理由跟來源已經是一組 tab 了,那原文還是要找一個地方放一個按鈕要滑出 drawer ,不如用一致的分頁處理起來比較簡單。
@yanglin5689446 已補上原始文章的分頁囉,感謝!
github 00:45:44
LGTM! Let's leave the <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1589365504440400|reply list discussion> for future PRs to keep the scope small. Thanks for your patience!
github 00:51:19
I found a weird case that my feedback is visible in API but not in UI. <https://user-images.githubusercontent.com/108608/82125422-6fa47380-97d8-11ea-8f9c-c034e02abcd6.png|螢幕快照 2020-05-17 上午12 48 24>
mrorz 01:22:08
你說的沒錯,搜尋頁面的「查核回應」是無法用熱門查核、含有個人意見等 article 相關的 filter

spec 裡面也確實針對「查核回應」訂有與 article 不同的 filter:
https://g0v.hackmd.io/oWSar1t0SzWo150Dsbepxw#%E6%9F%A5%E6%A0%B8%E5%9B%9E%E6%87%89

• 自己回應的 (對應到 `ListReplyFilter.selfOnly`)
• 「reply type」以及時間(對應到 `ListReplyFilter.type`)
Wireframe 與 Mockup 裡面會顯示跟 article filter 一樣,我猜是複製貼上忘記改~
mrorz 01:23:01
我覺得就按照 spec 裡說的,使用「自己回應的」與 reply type 即可~

有需要 mockup 排的話可以請 @stbb1025
mrorz 01:32:33
1. 「撰寫新回應 / 使用現有回應」之所以從 tab 變 select 是因為有兩層 tab 很怪,所以前者換成 select 放在最上面。我是覺得這對手機使用者滿自然的~
2. 我覺得手機螢幕實在太受限,必須要重排整個使用者體驗,導致行為桌機版的 `NewReplySection` 整個都不一樣,建議要直接手機版跟電腦版分開做 QQ (如 `DesktopNewReplySection`/`MobileNewReplySection`之類)。不過,視覺上很類似的一些子 component 就可以重用,外觀功能差太多的部分就直接分不同的版本ㄅ。
3. 我覺得他比較像是 full-screen dialog (`<Dialog fullScreen>`)。編輯器的「原始文章/撰寫回應/資料來源」則是 swipable full-width tab (`<Tabs variant="fullWidth">`搭配 `SwipeableViews`)。關於 Drawer,寫回應的時候只看那些 Drawer 露出的小部分原文恐怕沒有太大幫助,而寫回應本身也是需要整個螢幕來專心的作業,權衡之下我覺得 Drawer 可能沒有比 full-screen dialog 好唷。
mrorz 01:56:46
我在 deploy 英文版 Cofacts LINE bot 遇到怪現象:跳 LIFF 一定會 400 bad request
https://drive.google.com/file/d/1p0-J2k8J_NiQE2brIuLQT2-8B2Vckm5d/view?usp=sharing

大家可以幫我試試看嗎?加加看英文版 Cofacts: https://line.me/R/ti/p/%40439txwho
它的資料庫是接 production(畢竟是英文版正式站),所以不能亂塞東西進去測 XD

可以複製貼上下面的文字查詢
> 瀾滄人民醫院: 昨天凌晨二點二十三分, 十三名男女生感染 SK5 病毒死亡, 最大的 32 歲, 最小的 5 歲, 參與搶救的醫生已被隔離, 中央 1 台電視新聞己播出, 暫時別吃豬肉, 特別是乳源的豬肉, 目前廣西貴港已有 13,167 個已感染. 收到馬上發給你關心的人, 最好是群發. 為了您的健康, 請轉發吧, 少買豬肉吃. 看了快轉, 幫別人等於幫自己
這個 LIFF 靈異現象在 LINE 官方社團提了超多次,但都沒人解決的樣子

https://www.facebook.com/groups/linebot/permalink/2405070733156832/
https://www.facebook.com/groups/linebot/permalink/2298376747159565/
https://www.facebook.com/groups/linebot/permalink/2265639553766618/
https://www.facebook.com/groups/linebot/permalink/2213035389027035/
我覺得 LINE 在 LIFF (尤其是 LIFF V2)的 developer experience 非常不優,根本沒有 experience 只有 frustration⋯⋯
我可以 reproduce
不過在授權我有出現另一個不能選的選項
> 我可以 reproduce
Hmm 那可能是我設定有問題 @@
網路上回報的狀況很妙,是說只有一兩台
感謝測試
修好了,是因為 LIFF 裡的 LIFF_ID 是在 build time 決定的,如果 build 完了才改 LIFF_URL env var,會導致 LIFF ID 與 LIFF_URL 對不上,因此在 `liff.init` 時會觸發 400 bad request。

Troubleshooting note added to README
https://github.com/cofacts/rumors-line-bot/commit/b7ce8ea95184faee06104defe279a7ebcafc88a8
mrorz 01:57:04
它的資料庫是接 production(畢竟是英文版正式站),所以不能亂塞東西進去測 XD

可以複製貼上下面的文字查詢
mrorz 01:57:40
> 瀾滄人民醫院: 昨天凌晨二點二十三分, 十三名男女生感染 SK5 病毒死亡, 最大的 32 歲, 最小的 5 歲, 參與搶救的醫生已被隔離, 中央 1 台電視新聞己播出, 暫時別吃豬肉, 特別是乳源的豬肉, 目前廣西貴港已有 13,167 個已感染. 收到馬上發給你關心的人, 最好是群發. 為了您的健康, 請轉發吧, 少買豬肉吃. 看了快轉, 幫別人等於幫自己
mrorz 01:59:06
這個 LIFF 靈異現象在 LINE 官方社團提了超多次,但都沒人解決的樣子

https://www.facebook.com/groups/linebot/permalink/2405070733156832/
https://www.facebook.com/groups/linebot/permalink/2298376747159565/
https://www.facebook.com/groups/linebot/permalink/2265639553766618/
https://www.facebook.com/groups/linebot/permalink/2213035389027035/
我覺得 LINE 在 LIFF (尤其是 LIFF V2)的 developer experience 非常不優,根本沒有 experience 只有 frustration⋯⋯
yanglin 10:18:57
關於 3 我是想編輯器還是全螢幕
只是可能可以往下拉露出上半部
就可以跟原文作對照?
yanglin 10:36:54
或著說我現在不太確定「原始文章」那個分頁會怎麼呈現
stbb1025 10:54:50
分頁我明天補上唷,不好意思~
stbb1025 10:55:27
但基本上就是很簡單的筆記本呈現形式,不會有圓角外框
yanglin 11:17:39
還有一個問題是 reply 可能會對應到多個 article
所以應該沒辦法做到這樣?
截圖 2020-05-17 上午11.16.17.png
mrorz 15:42:09
請直接拿第一個 article 唷,因為第一個應該是回應原作者連結的,理論上那個回應應該與第一個文章最吻合
  • 👌1
mrorz 15:44:53
> 只是可能可以往下拉露出上半部
> 就可以跟原文作對照?
我們在討論的時候,原本確實有想過上下 split screen。但後來想到一件事情:
「如果 soft keyboard 一顯示,整個螢幕還剩下多少空間?」

然後我就打消上下分開這個想法了。
github 15:59:42
This is on the roadmap of deploying current staging chatbot to production. <https://user-images.githubusercontent.com/108608/82138971-36f7af00-9857-11ea-8e41-b6e14856cde1.png|image> <https://user-images.githubusercontent.com/108608/82138973-3ced9000-9857-11ea-87f2-61146b5216b6.png|image> <https://user-images.githubusercontent.com/108608/82138986-57276e00-9857-11ea-8019-d30d0626552c.png|image> <https://user-images.githubusercontent.com/108608/82138977-41b24400-9857-11ea-8739-ad32644c0562.png|image>
github 16:21:03
*Pull Request Test Coverage Report for <https://coveralls.io/builds/30840342|Build 823>* • *0* of *0* changed or added relevant lines in *0* files are covered. • No unchanged relevant lines lost coverage. • Overall coverage remained the same at *98.438%* * * * * * * *:yellow_heart: - <https://coveralls.io|Coveralls>*
lucien 16:31:30
抽屜當天我有提出來討論過,不過因為除了輸入空間考慮,當天還有討論理由與來源的流程擺放問題,如果理由跟來源已經是一組 tab 了,那原文還是要找一個地方放一個按鈕要滑出 drawer ,不如用一致的分頁處理起來比較簡單。
  • 👌1
  • 👍1
lucien 16:32:43
最新查核只會出現有查核過的文章
lucien 16:33:33
一定是至少有一篇回應的
lucien 16:36:27
現在最新查核也是從 article 下去 filter 而不是 reply 對嗎
lucien 16:38:07
會對第一個原始文章,下面顯示的更多被用於哪些文章,點擊後會以 modal 形式出現其他的文章列表
  • 👍1
lucien 16:42:05
我可以 reproduce
lucien 16:42:34
不過在授權我有出現另一個不能選的選項
lucien 16:49:54
已更新
lucien 16:50:29
不過這是不會出現在選項上的 filter
mrorz 20:56:34
> 我可以 reproduce
Hmm 那可能是我設定有問題 @@
網路上回報的狀況很妙,是說只有一兩台
mrorz 20:57:09
感謝測試
mrorz 21:00:38
感謝更新,這可能要開一張新票來處理

目前 @yanglin5689446 實作的 `defaultFilter` 機制可能要稍微改一下,才能支援這種「不會出現在選項上、關不掉的 filter」
  • 👌1
mrorz 21:04:41
(現在的 `defaultFilter` 可以被新設的 filter 覆蓋)
github 23:46:03
Translate to zh_TW of list pages, before pushing to production. Translations referring to the <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=0%3A1|mockup>. <https://user-images.githubusercontent.com/108608/82153073-dfc5fe80-9897-11ea-957b-b8def2b0a26e.png|image> <https://user-images.githubusercontent.com/108608/82153111-13088d80-9898-11ea-8059-a1b3970e2fb3.png|image> <https://user-images.githubusercontent.com/108608/82153118-1f8ce600-9898-11ea-9099-147f708a590e.png|image> <https://user-images.githubusercontent.com/108608/82153177-86aa9a80-9898-11ea-8976-f1b4c2a1e11e.png|image> <https://user-images.githubusercontent.com/108608/82153181-8d391200-9898-11ea-8312-286fab636dbe.png|image>
github 23:59:07
These are temporary components that is going to be replaced, so I don't translate these.
2020-05-18
stbb1025 11:38:37
@yanglin5689446 已補上原始文章的分頁囉,感謝!
github 14:06:48
A Google Tag Manager custom variable setup like below will be able to track the React component name (if it's static `displayName` is set) of the clicked element (or clicked element's ancestor): ``` function() { var currentNode = {{Click Element}}; var reactInstanceKey = Object.keys(currentNode).find(function(key){ return key.startsWith('__reactInternalInstance$'); }); if(!reactInstanceKey) return; var currentInst = currentNode[reactInstanceKey]; while(currentInst) { if(currentInst.elementType &amp;&amp; currentInst.elementType.displayName &amp;&amp; // Ignore names like "WithStyles(ForwardRef(ButtonGroup))" currentInst.elementType.displayName.indexOf('(') === -1) { return currentInst.elementType.displayName; } currentInst = currentInst.return; } } ``` However, most components in Cofacts code base do not have `displayName` -- some buttons we want to track isn't even an isolated component. I am switching to `data-ga` method property instead of `displayName`.
github 14:53:20
*Google Tag Manager setup* *User defined variable `Clicked Element Path`* ``` function() { var currentNode = {{Click Element}}; var reactInstanceKey = Object.keys(currentNode).find(function(key){ return key.startsWith('__reactInternalInstance$'); }); if(!reactInstanceKey) return; var currentInst = currentNode[reactInstanceKey]; var path = []; while(currentInst) { if(currentInst.memoizedProps &amp;&amp; currentInst.memoizedProps['data-ga']) { path.unshift(currentInst.memoizedProps['data-ga']); } else if(currentInst.elementType &amp;&amp; currentInst.elementType.displayName &amp;&amp; // Ignore names like "WithStyles(ForwardRef(ButtonGroup))" currentInst.elementType.displayName.indexOf('(') === -1) { path.unshift(currentInst.elementType.displayName); } currentInst = currentInst.return; } return path.join(' &gt; '); } ```
mrorz 15:07:39
請問 @lucien https://g0v.hackmd.io/ahtI6xsFRQyxktrIlc1VcQ#%E6%88%90%E6%95%88%E8%BF%BD%E8%B9%A4 裡的「多少瀏覽量比例 UV / All UV」是什麼意思呢

是指「可疑轉傳訊息」(不分 filter / sort)的 unique visitor 數 / 全站 unique visitor 數嗎
現在一些上了 `displayName` 與 `data-ga` prop 的元素,點擊後會出現在 Google analytics。只要 event hit 有送去 GA,這樣應該就能算 unique visitor~

Review PR here: https://github.com/cofacts/rumors-site/pull/254
是喔
github 19:17:40
等你來答//交給你了//請你查證
mrorz 19:23:04
Replied to a thread: 2020-05-18 15:07:39
現在一些上了 `displayName` 與 `data-ga` prop 的元素,點擊後會出現在 Google analytics。只要 event hit 有送去 GA,這樣應該就能算 unique visitor~

Review PR here: https://github.com/cofacts/rumors-site/pull/254
This PR sends the `data-ga` property or `displayName` of the clicked component to Google Analytics, so that we can track click of component of interest. See the `eventCategory` (in non-bold text) on the right side of the screen recording: <https://user-images.githubusercontent.com/108608/82204954-5dd9e200-9938-11ea-95d4-f65308839c15.gif|onclick-path>. The innerText of the clicked element is sent as `eventLabel`. Collected events in Google analytics: <https://user-images.githubusercontent.com/108608/82203326-beb3eb00-9935-11ea-8b6b-f0bb9b6c4847.png|image> This fixes <https://github.com/cofacts/rumors-site/issues/237|#237> . *Related Spec* This PR implements "成效追蹤" part of the following spec: • <https://g0v.hackmd.io/ahtI6xsFRQyxktrIlc1VcQ#%E6%88%90%E6%95%88%E8%BF%BD%E8%B9%A4|Dubious messages> • <https://g0v.hackmd.io/ZZWHWi2BTuyhkSWzAvKLAw#%E6%88%90%E6%95%88%E8%BF%BD%E8%B9%A4|Latest replies> • <https://g0v.hackmd.io/@NFi0czulSemxCM8RNSlz8Q/HJ8xT3QVU/%2FN8I2-zkJTaS35BP8VH8ZQA|Hoax for you> (subset of Latest replies) *Google Tag Manager setup* <https://user-images.githubusercontent.com/108608/82202606-bd35f300-9934-11ea-9556-ceaee3ab223a.png|image> *User defined variable `Clicked Element Path`* This shows the the clicked item's component name (`&lt;ComponentName&gt;`) or `data-ga` property (`[ga propety]`) when their descendent is clicked. ``` function() { var currentNode = {{Click Element}}; if(!currentNode) return ''; var reactInstanceKey = Object.keys(currentNode).find(function(key){ return key.startsWith('__reactInternalInstance$'); }); if(!reactInstanceKey) return ''; var currentInst = currentNode[reactInstanceKey]; var path = []; while(currentInst) { if(currentInst.memoizedProps &amp;&amp; currentInst.memoizedProps['data-ga'] &amp;&amp; // data-ga may be passed down to multiple levels of child components. // we don't want to record duplicated 'data-ga'. path[0] !== '[' + currentInst.memoizedProps['data-ga'] + ']') { path.unshift('[' + currentInst.memoizedProps['data-ga'] + ']'); } else if(currentInst.elementType &amp;&amp; currentInst.elementType.displayName &amp;&amp; // Ignore names like "WithStyles(ForwardRef(ButtonGroup))" currentInst.elementType.displayName.indexOf('(') === -1) { path.unshift('&lt;' + currentInst.elementType.displayName + '&gt;'); } currentInst = currentInst.return; } return path.join(' ▸ '); } ``` *Trigger `Clicked element with path`* <https://user-images.githubusercontent.com/108608/82203039-5238ec00-9935-11ea-9d32-dbc87e68dbb2.png|image> *Tag `Click event to GA`* <https://user-images.githubusercontent.com/108608/82203158-814f5d80-9935-11ea-8eed-90328a0c2b71.png|image>
lucien 19:23:37
是喔
  • 1
github 19:28:22
We use both `data-ga` and `displayName` in the end. `data-ga` provides greater flexibility because we can set different names for different occurrences, while `displayName` makes sure all clicks under a component will be recorded no matter where it is rendered.
mrorz 19:59:25
Replied to a thread: 2020-05-17 01:56:46
修好了,是因為 LIFF 裡的 LIFF_ID 是在 build time 決定的,如果 build 完了才改 LIFF_URL env var,會導致 LIFF ID 與 LIFF_URL 對不上,因此在 `liff.init` 時會觸發 400 bad request。

Troubleshooting note added to README
https://github.com/cofacts/rumors-line-bot/commit/b7ce8ea95184faee06104defe279a7ebcafc88a8
  • 👍1
mrorz 20:30:05
週末大松前希望可以把新網站上 production (deploy 計畫見此),不過有兩件事情希望大家幫忙 ><
1. Review 一下 google analytics tracking 特定元件的 PR
2. 前者 merge to dev 之後,rebase https://github.com/cofacts/rumors-site/pull/249 到最新的 dev
然後我就能 PR249 的內容放上 staging 與 production~
我剛才把 tracking 的 PR merge 進 dev 了,麻煩 @yanglin5689446 把 PR249 (`new-article-detail-page-ui`) rebase 到 dev 唷
大松之前我想要推一個版本上 staging & production

現在的 dev 的 article page,reply upvote / downvote 是壞掉的,所以希望能至少有現在 `b3ef1a1e` (commit message: “Add copy button ref”) 的 UI 讓大家 try try
PR 還沒有改完也沒關係,因為該 commit 版本下, 功能上應該跟現在 production 差不多,或許可以先來收個 early feedback~
我有先 rebase & push 了
如果有什麼要壞掉要先修再跟我說
@yanglin5689446 好像有漏檔案唷
已修正
我發現 https://cofacts.hacktabl.org/hoax-for-you 在 Android Chrome 好像會炸掉
但 iOS safari 沒事
超怪 ._.
2020-05-19
mrorz 01:08:23
Replied to a thread: 2020-03-04 20:05:11
Hi @poesiapeng, 剛才 deploy 了最新版的 chatbot。現在看完一篇回應之後應該可以接另一篇囉!

不過,如果傳了新的訊息進來,前一則訊息的所有按鈕仍然會失效。

因為整個 chatbot 剛完成大改寫,所以最近可能會發現沒測到的 bug,還請大家多多幫忙回報 m(_ _)m

cc/ @delightfullychaotic 原討論串
mrorz 01:14:53
月黑風高 沒使用者 佈版好時機
  • ❤️2
  • 😆3
github 10:38:41
View details in Rollbar: <https://rollbar.com/mrorz/rumors-line-bot/items/208/|https://rollbar.com/mrorz/rumors-line-bot/items/208/> ``` BadRequestError: request aborted File "/app/node_modules/raw-body/index.js", line 231, in IncomingMessage.onAborted done(createError(400, 'request aborted', { File "events.js", line 310, in IncomingMessage.emit File "_http_server.js", line 532, in abortIncoming File "_http_server.js", line 525, in socketOnClose File "events.js", line 322, in Socket.emit File "net.js", line 672, in TCP.&lt;anonymous&gt; ```
github 10:39:53
Should if this is due to normal usage (e.g. pressed an outdated button). If it is, we should configure rollbar to ignore such error.
github 13:07:47
Welcome to <https://togithub.com/renovatebot/renovate|Renovate>! This is an onboarding PR to help you understand and configure settings before regular Pull Requests begin. :vertical_traffic_light: To activate Renovate, merge this Pull Request. To disable Renovate, simply close this Pull Request unmerged. * * * *Detected Package Files* • `package.json` (npm) *Configuration Summary* Based on the default config's presets, Renovate will: • Start dependency updates only once this onboarding PR is merged • Separate major versions of dependencies into individual branches/PRs • Do not separate patch and minor upgrades into separate PRs for the same dependency • Upgrade to unstable versions only if the existing version is unstable • Raise PRs immediately (after branch is created) • If semantic commits detected, use semantic commit type `fix` for dependencies and `chore` for all others • Keep existing branches updated even when not scheduled • Disable automerging feature - wait for humans to merge all PRs • Ignore `node_modules`, `bower_components`, `vendor` and various test/tests directories • Autodetect whether to pin dependencies or maintain ranges • Rate limit PR creation to a maximum of two per hour • Limit to maximum 20 open PRs at any time • Group known monorepo packages together • Use curated list of recommended non-monorepo package groupings :abcd: Would you like to change the way Renovate is upgrading your dependencies? Simply edit the `renovate.json` in this branch with your custom config and the list of Pull Requests in the "What to Expect" section below will be updated the next time Renovate runs. * * * You have configured Renovate to use branch `master` as base branch. *What to Expect* With your current configuration, Renovate will create 6 Pull Requests: Pin dependencies • Schedule: ["at any time"] • Branch name: `renovate/pin-dependencies` • Merge into: `master` • Pin <https://togithub.com/testing-library/jest-dom|@testing-library/jest-dom> to `4.2.4` • Pin <https://togithub.com/testing-library/react-testing-library|@testing-library/react> to `9.5.0` • Pin <https://togithub.com/testing-library/user-event|@testing-library/user-event> to `7.2.1` • Pin <https://togithub.com/DefinitelyTyped/DefinitelyTyped|@types/jest> to `24.9.1` • Pin <https://togithub.com/DefinitelyTyped/DefinitelyTyped|@types/node> to `12.12.39` • Pin <https://togithub.com/DefinitelyTyped/DefinitelyTyped|@types/react> to `16.9.35` • Pin <https://togithub.com/DefinitelyTyped/DefinitelyTyped|@types/react-dom> to `16.9.8` • Pin <https://togithub.com/facebook/react|react> to `16.13.1` • Pin <https://togithub.com/facebook/react|react-dom> to `16.13.1` • Pin <https://togithub.com/Microsoft/TypeScript|typescript> to `3.7.5` Update dependency typescript to v3.9.2 • Schedule: ["at any time"] • Branch name: `renovate/typescript-3.x` • Merge into: `master` • Upgrade <https://togithub.com/Microsoft/TypeScript|typescript> to `3.9.2` Update dependency @testing-library/jest-dom to v5 • Schedule: ["at any time"] • Branch name: `renovate/testing-library-jest-dom-5.x` • Merge into: `master` • Upgrade <https://togithub.com/testing-library/jest-dom|@testing-library/jest-dom> to `5.7.0` Update dependency @testing-library/react to v10 • Schedule: ["at any time"] • Branch name: `renovate/testing-library-react-10.x` • Merge into: `master` • Upgrade <https://togithub.com/testing-library/react-testing-library|@testing-library/react> to `10.0.4` Update dependency @testing-library/user-event to v10 • Schedule: ["at any time"] • Branch name: `renovate/testing-library-user-event-10.x` • Merge into: `master` • Upgrade <https://togithub.com/testing-library/user-event|@testing-library/user-event> to `10.3.1` Update dependency @​types/jest to v25 • Schedule: ["at any time"] • Branch name: `renovate/jest-25.x` • Merge into: `master` • Upgrade <https://togithub.com/DefinitelyTyped/DefinitelyTyped|@types/jest> to `25.2.3` :children_crossing: Branch creation will be limited to maximum 2 per hour, so it doesn't swamp any CI resources or spam the project. See docs for `prhourlylimit` for details. * * * :question: Got questions? Check out Renovate's <https://docs.renovatebot.com/|Docs>, particularly the Getting Started section. If you need any further assistance then you can also <https://togithub.com/renovatebot/config-help/issues|request help here>. * * * This PR has been generated by <https://renovate.whitesourcesoftware.com|WhiteSource Renovate>. View repository job log <https://app.renovatebot.com/dashboard#cofacts/community-builder|here>.
lucien 14:10:12
@mrorz 回報的 sort / filter 我有問題,能請你看看嗎?以及我之後想要收集,一個人的所有查核回應被搜尋到幾次的資料
https://g0v.hackmd.io/bbreV0ZqRDarHl4Zt5UpEw?both
  • 1
卡片很有趣~~
針對你的問題,我寫在 hackmd 的 comment 裡囉
我想法也有寫在 md 裡
mrorz 14:37:35
卡片很有趣~~
mrorz 14:52:41
針對你的問題,我寫在 hackmd 的 comment 裡囉
lucien 17:00:10
我想法也有寫在 md 裡
Swim 19:43:06
@mrorz 剛剛測試了,確認可以點擊其他回應!辛苦了👍
不過剛剛我要點擊「是」回應是否有幫助的問題,卻跳出這個畫面,可是我是使用手機😅⋯⋯
Image from iOS
bil 20:15:41
Image from iOS
bil 20:16:54
重新在手機中複製貼上也操作不能唷
開了喔,doesn’t work
喔喔應該是要關起來 QQ
關著的時候不 work 嗎
兩個都不work喔
GG
今天晚上直接連到我電腦的機器上來 debug 吧
這應該是 LIFF 的 bug,研究出來之後要回報
mrorz 21:38:53
LINE TODAY
我們常會在LINE裡點開連結網址,然後LINE會用內部瀏覽器打開這個連結,不過若想再分享到LINE之外的地方(如FB、IG、訊息…等),就得再換成用Safari開啟,多了一道步驟,有點麻煩。 現在iOS版的LINE Labs裡,新增「一律用Safari開啟」的選項,讓你在LINE裡點擊連結時,會直接用Safari開啟網頁,包括LINE購物的頁面也是。 這樣一來就可以使用Safari的延伸工具,做外部分享或更多應用了,比方Safari有擋廣告的外掛,這樣點開看新聞連結,就不用受彈出廣告干擾了[愛心]。 其他如分享到備忘錄、翻譯、列印、做備註、加入書籤或稍後閱讀…等,也會因為直接用Safari瀏覽
mrorz 21:49:22
Hmm 我是 Android 使用者,沒有遇到這件事情呢。

@poesiapeng 請問您是不是有開啟「在 Safari 開啟連結」功能呢

https://today.line.me/tw/article/%E6%96%B0%E5%A2%9E%EF%BC%8F+iOS%E7%89%88LINE+%E6%8F%90%E4%BE%9B%E7%94%A8Safari%E9%96%8B%E5%95%9F%E9%80%A3%E7%B5%90%E7%9A%84%E5%AF%A6%E9%A9%97%E5%8A%9F%E8%83%BD-nm9m0D
2020-05-20
yanglin 01:26:47
@mrorz 想問一下現在搜尋現有文章的部分
有一部分是從 article 傳下來的 relatedReplies
還有從 ReplySearch 搜尋的部分也會有 RelatedReplies
為什麼會分成兩邊啊
```<ReplySearch
existingReplyIds={existingReplyIds}
onConnect={handleConnect}
disabled={connectingReply}
/>
<RelatedReplies
relatedArticleReplies={relatedArticleReplies}
onConnect={handleConnect}
disabled={connectingReply}
/>```
在原版 rumors-site (現 production) 的邏輯裡

`<RelatedReplies>` 這個 component 就是 given article reply 畫出「相關訊息原文 + 回應 + 『將這份回應加進此文章的回應』」的功能型 component

而搜尋時,無論是「跟此 article 很像的 article 的 articleReply」
還是「編輯另外打關鍵字後,找出的 article 或 reply 的 articleReply」
最後都會用上面 `<RelatedReplies>`那種方式呈現,所以重用 `<RelatedReplies> compoennt`
這樣應該會是該文章相關的回應不管在哪個 tab 都會顯示?
現在的相關訊息/回應的 filter 邏輯是有分全部訊息、我的訊息、全部回應、我的回應
我在改這段 所以想確認一下之前的邏輯~
補個脈絡來確認一下你指稱的部分,也讓其他人可以參與~

你現在想確認的是,按下圖中 dropdown 裡的「全部訊息」「全部回應」「我的訊息」「我的回應」之後再搜尋,會顯示的結果列表
跟下面這個「使用現有回應」分頁裡,搜尋框的搜尋結果
的差別在哪裡嗎
關於「之前的邏輯」(也就是現在的 production)v.s. mockup:

1. 其實 mockup「使用現有回應」tab,是 _production 上「使用現有回應」與「搜尋」2 個 tab 的集合體_——mockup 裡,搜尋框沒東西的時候,就是呈現此 article 的relatedArticle 的回應;搜尋框裡打字之後,就是按照使用者選的「全部訊息」「全部回應」「我的訊息」「我的回應」進行搜尋後,呈現搜尋結果。最後的 action button 是「直接用此回應」,按下去就會直接送一個新回應。 Production 的搜尋功能只有「全部訊息」「全部回應」,這次 mockup 裡面新增「我的訊息」「我的回應」。
2. mockup 「撰寫新回應」tab 裡的搜尋框,就是_現在 production 完全沒有_的功能了,最後的 action button 是把單則搜尋結果,複製貼上到現在正在撰寫的回應與出處中,讓編輯可以改一改之後才(以自己的名義)送出。
btw 我不確定 mockup 裡的「我的訊息」是什麼意思,這個之前並沒有討論過呢。
@lucien 可以解釋一下那些 filter 嗎?
搜尋關鍵字於 <全站的所有可疑訊息>, <全站的所有查核回應>, <我回報過的可疑訊息>, <我查核過的回應>
@lucien
`ListArticle` 目前無法過濾出「我回報的可疑訊息」,但 `ListReply` 有 `selfOnly` 可以用,所以「我查核過的回應」可以做。我建議在 API 不支援的現在,暫時先拿掉「我回報的可疑訊息」這個選項。

cc/ @yanglin5689446
mrorz 02:17:51
在原版 rumors-site (現 production) 的邏輯裡

`<RelatedReplies>` 這個 component 就是 given article reply 畫出「相關訊息原文 + 回應 + 『將這份回應加進此文章的回應』」的功能型 component

而搜尋時,無論是「跟此 article 很像的 article 的 articleReply」
還是「編輯另外打關鍵字後,找出的 article 或 reply 的 articleReply」
最後都會用上面 `<RelatedReplies>`那種方式呈現,所以重用 `<RelatedReplies> compoennt`
mrorz 02:43:10
本週會議記錄
專心準備大松吧,我真的很想 deploy 網站 list page⋯⋯
https://g0v.hackmd.io/TfMlpKYhS3-boaLTgiriYg?view
  • 🙌1
powercall 像是個無聲的黑洞
mrorz 11:03:13
今天發現有個 https://www.npmjs.com/package/truncate-utf8-bytes 好像比我們使用https://www.npmjs.com/package/grapheme-splitter 更適合確保 LINE bot 的回應不超過大小。

不過前者用 WTFPL,好像有人想要改掉,但作者沒理他 XD
讀完相關討論也不確定為啥大家想換掉它就是了。
It would be really great to replace WTFPL license from published npm artifacts
github 12:30:13
*Renovate is disabled* Renovate is disabled due to lack of config. If you wish to reenable it, you can either (a) commit a config file to your base branch, or (b) rename this closed PR to trigger a replacement onboarding PR.
ggm 13:57:16
category 現在應該都打回去 production 和 staging 了(現在也會自動撈自動打回去了,目前只支援一個 model 常態跑著,另個我們會一天醒來一次開 gpu 機器,然後再關機器),我現在正在準備 data scientist 的 release 文件,想說來得及的話,在大松花個 5 分鐘講一下(或是給大家看文件),如果有人想要貢獻 model 的話要怎麼做
  • 👍2
  • 💯1
你想要短講還是成果報告呢
都可以報唷
> category 現在應該都打回去 production 和 staging 了
今天晚上處理完 rumors-site 的 tracking 之後,會來試試看~
感謝感謝
@ggm production 的 article 的確有 `articleCategory` 了,感謝感謝

不過沒有上 category 本體(資料庫`categories` index 是空的),所以 UI 會因為對不到 category 而壞掉 ><
mrorz 14:15:12
你想要短講還是成果報告呢
都可以報唷
yanglin 14:27:12
這樣應該會是該文章相關的回應不管在哪個 tab 都會顯示?
現在的相關訊息/回應的 filter 邏輯是有分全部訊息、我的訊息、全部回應、我的回應
我在改這段 所以想確認一下之前的邏輯~
mrorz 15:06:47
乍讀之下,好像可以用來幫 editor monetize?
1. 讀者每個月付 5 塊給 Web Monetization provider
2. 若讀者造訪一個支援 web monetization 的網頁,那他的閱讀就會變成一小筆金額,轉給網頁裡寫的那個 payment pointer

https://dev.to/hacksultan/web-monetization-like-i-m-5-1418
https://hacks.mozilla.org/2020/03/web-monetization-coil-and-firefox-reality/
Irvinfly
Mozilla, CC 跟 Coil 成立的一個新的獎助金,贊助「Web Monetization」標準相關的開發與設計專案,申請時間到 6/12
https://www.grantfortheweb.org/apply
DEV Community
A guide to getting started with web monetization
mrorz 15:41:16
補個脈絡來確認一下你指稱的部分,也讓其他人可以參與~

你現在想確認的是,按下圖中 dropdown 裡的「全部訊息」「全部回應」「我的訊息」「我的回應」之後再搜尋,會顯示的結果列表
image.png
mrorz 15:41:53
跟下面這個「使用現有回應」分頁裡,搜尋框的搜尋結果
的差別在哪裡嗎
image.png
mrorz 15:50:31
關於「之前的邏輯」(也就是現在的 production)v.s. mockup:

1. 其實 mockup「使用現有回應」tab,是 _production 上「使用現有回應」與「搜尋」2 個 tab 的集合體_——mockup 裡,搜尋框沒東西的時候,就是呈現此 article 的relatedArticle 的回應;搜尋框裡打字之後,就是按照使用者選的「全部訊息」「全部回應」「我的訊息」「我的回應」進行搜尋後,呈現搜尋結果。最後的 action button 是「直接用此回應」,按下去就會直接送一個新回應。 Production 的搜尋功能只有「全部訊息」「全部回應」,這次 mockup 裡面新增「我的訊息」「我的回應」。
mrorz 15:53:53
2. mockup 「撰寫新回應」tab 裡的搜尋框,就是_現在 production 完全沒有_的功能了,最後的 action button 是把單則搜尋結果,複製貼上到現在正在撰寫的回應與出處中,讓編輯可以改一改之後才(以自己的名義)送出。
mrorz 15:57:56
btw 我不確定 mockup 裡的「我的訊息」是什麼意思,這個之前並沒有討論過呢。
mrorz 15:59:59
> category 現在應該都打回去 production 和 staging 了
今天晚上處理完 rumors-site 的 tracking 之後,會來試試看~
感謝感謝
bil 16:36:03
開了喔,doesn’t work
bil 16:43:03
不行呢
Image from iOS
mrorz 17:57:15
喔喔應該是要關起來 QQ
關著的時候不 work 嗎
mrorz 17:59:26
如果有的話,請把它關閉再試試看唷
  • 1
bil 17:59:33
兩個都不work喔
mrorz 18:06:44
GG
今天晚上直接連到我電腦的機器上來 debug 吧
這應該是 LIFF 的 bug,研究出來之後要回報
yanglin 19:00:51
Replied to a thread: 2020-05-20 01:26:47
@lucien 可以解釋一下那些 filter 嗎?
lucien 19:04:55
搜尋關鍵字於 <全站的所有可疑訊息>, <全站的所有查核回應>, <我回報過的可疑訊息>, <我查核過的回應>
github 20:34:45
Currently, iOS will show this when opening LIFF <https://user-images.githubusercontent.com/108608/82446442-3cfcc280-9ad9-11ea-9b97-a217cdcddca6.png|image> Related discussion: <https://g0v-tw.slack.com/archives/C2PPMRQGP/p1583323511054400|https://g0v-tw.slack.com/archives/C2PPMRQGP/p1583323511054400> This PR avoids this condition by moving `isInClient` API call to after `liff.init()`.
github 20:37:11
*Pull Request Test Coverage Report for <https://coveralls.io/builds/30916892|Build 828>* • *0* of *0* changed or added relevant lines in *0* files are covered. • No unchanged relevant lines lost coverage. • Overall coverage remained the same at *98.438%* * * * * * * *:yellow_heart: - <https://coveralls.io|Coveralls>*
github 20:41:21
Response is now incorrect. According to <https://github.com/cofacts/rumors-line-bot/blob/dev/src/webhook/handlers/askingArticleSubmissionConsent.js#L35-L41|source code>, it should block article submission and shows hint to other fact checkers (see <https://github.com/cofacts/rumors-line-bot/blob/dev/src/webhook/handlers/__tests__/askingArticleSubmissionConsent.test.js#L57-L84|unit test>) Instead, it shows: <https://user-images.githubusercontent.com/108608/82446786-e2179b00-9ad9-11ea-8986-4c361d0c86e1.png|Screenshot_20200520-203235>
github 20:46:55
Or maybe the user aborted the loading LIFF due to long waiting time?
github 21:07:15
Close because landing page is in the scope of Cofacts Next project
Swim 21:56:19
確認可以打開囉!辛苦了
lucien 21:59:47
powercall 像是個無聲的黑洞
stbb1025 22:06:02
聽不到orz你們的聲音~~~~
mrorz 22:06:50
GG
mrorz 22:06:55
換 jitsi 吧
mrorz 22:07:43
meet.jit.si
Join a WebRTC video conference powered by the Jitsi Videobridge
mrorz 22:25:38
感謝您的測試,我們晚上 9:45 時剛上新版,應該是修好了~~
mrorz 22:32:47
我剛才把 tracking 的 PR merge 進 dev 了,麻煩 @yanglin5689446 把 PR249 (`new-article-detail-page-ui`) rebase 到 dev 唷
mrorz 22:34:17
大松之前我想要推一個版本上 staging & production

現在的 dev 的 article page,reply upvote / downvote 是壞掉的,所以希望能至少有現在 `b3ef1a1e` (commit message: “Add copy button ref”) 的 UI 讓大家 try try
mrorz 22:44:06
PR 還沒有改完也沒關係,因為該 commit 版本下, 功能上應該跟現在 production 差不多,或許可以先來收個 early feedback~
  • 👌1
mrorz 22:58:36
Nick Chang
今天想討論一下這樣的landing page走向o不ok?
ok的話我就繼續把後面內容做完
(這版的寬是1024)
stbb1025 23:52:07
https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=912%3A384
@bil @lucien @mrorz 我新增了卡牌頁的設計,把Lucien想放的資訊都放進卡牌裡,另外把優秀回答者變成像是陷阱卡的概念XD,用卡牌堆疊的方式呈現,應該更有卡牌感。歡迎討論~
Figma
Created with Figma
  • ❤️1
對我來說
我對左右兩個方向的喜好程度的差距
其實小到可能每天都會喜歡不一樣的選項 XD

目前的我覺得左邊深色與淺色底區塊一刀切比較俐落、視覺上比較舒服。

如果哪天覺得比較想要有挑戰性的話就會選右邊吧 ._.

雖然有聽今晚針對 cover photo 使用時機的討論、也有聽到 gamification 可以取其理念而不用在介面上完全靠攏的聲音,但最後同時比較左右兩邊的時候,不知怎的就會選擇比較令人感到習慣的安全牌設計 ._.
或許這反映了我最近我欠 code 債欠太多,缺乏安全感 (?)
那我也是屬於沒安全感的一個(?)XDD
卡牌設計很可愛❤️其實如果是卡片設計的話,那可以在基礎的版面選擇安全設計,然後把其他的資訊都卡片化一張一張的收起來
卡牌設計跟卡片設計還是不一樣的,卡牌式運用桌遊延續下來把一個操作主題變成一張可以拿在手上,讓你有掌握收藏感的形式;卡片設計是把內容區塊用卡片區隔分組呈現。
卡牌我覺得可以嘗試的地方在於:
1. 從一致化的 profile 設計樣板跳脫
2. 壓縮重要資訊在比較小的卡牌上,可以集中內容。
我覺得如果是為了開發時程考量,我們可以先用卡片,之後再考慮回來嘗試卡牌。
2020-05-21
mrorz 01:41:38
對我來說
我對左右兩個方向的喜好程度的差距
其實小到可能每天都會喜歡不一樣的選項 XD

目前的我覺得左邊深色與淺色底區塊一刀切比較俐落、視覺上比較舒服。

如果哪天覺得比較想要有挑戰性的話就會選右邊吧 ._.

雖然有聽今晚針對 cover photo 使用時機的討論、也有聽到 gamification 可以取其理念而不用在介面上完全靠攏的聲音,但最後同時比較左右兩邊的時候,不知怎的就會選擇比較令人感到習慣的安全牌設計 ._.
mrorz 01:42:43
或許這反映了我最近我欠 code 債欠太多,缺乏安全感 (?)
stbb1025 01:54:10
那我也是屬於沒安全感的一個(?)XDD
bil 11:51:47
卡牌設計很可愛❤️其實如果是卡片設計的話,那可以在基礎的版面選擇安全設計,然後把其他的資訊都卡片化一張一張的收起來
yanglin 14:45:00
我有先 rebase & push 了
如果有什麼要壞掉要先修再跟我說
  • 1
mrorz 15:32:04
Cofacts Next 的 user profile 頁與「顯示某人送出過的文章」等功能,讓我們需要更新現在 rumors-api 如何處理 user 的機制。

在「Representation of backend app users」這個段落,我整理了 LINE bot user ID (backend app user id) 的一些特性,以及系統的需求,然後提出了兩種實作方向:
https://g0v.hackmd.io/ZcoUOX_-RQSkJyl5xz4_Zg?view#Representation-of-backend-app-users

方向 1 比較接近上週三討論的做法,對系統的改動較少;但我在考量 Cofacts Next 的各種「指涉特定 backend user」的需求之後,現在覺得方向 2 的架構比較乾淨且符合直覺,只是會需要大改現在的 rumors-api code。

希望大家針對兩種方向不吝指教,這攸關 profile page 與跟「人」有關的 article filter 做不做得出來呢。
mrorz 17:29:19
@yanglin5689446 好像有漏檔案唷
image.png
yanglin 17:42:03
已修正
  • 🙏1
github 18:16:19
這個在 ReplySearch 的部分已經在修了
可以的話先不要上 Editor 的部分等 ReplySearch 一起 🙏
喔喔好唷感謝告知

那我上到上次 review 的 add copy button (`2be2131`)~
github 18:16:19
Nested `form` is introduced here, it's not valid DOM structure. Please remove one of the nesting form. <https://user-images.githubusercontent.com/108608/82548180-80b10400-9b8d-11ea-8586-e688044708a9.png|image>
這個在 ReplySearch 的部分已經在修了
可以的話先不要上 Editor 的部分等 ReplySearch 一起 🙏
喔喔好唷感謝告知

那我上到上次 review 的 add copy button (`2be2131`)~
github 18:16:19
If what we want is a horizontal scroll when there is not enough space, please use `overflowX: auto`. `overflow: scroll`: • introduces always-on scrolls, it's there even if no scroll is needed • scrolls both directions, which is pretty rare in design <https://user-images.githubusercontent.com/108608/82548608-28c6cd00-9b8e-11ea-8d28-c12bcd4ee7a6.png|image> I suggest web developers on Mac should turn on "always show scroll bars" at all times so that we can empathize Windows users more. It may be not obvious for Mac users with hidden scrollbars, the <https://www.filamentgroup.com/lab/scrollbars/|Windows users will always get ugly scroll bars for every `overflow: scroll` we write.>
這個在 ReplySearch 的部分已經在修了
可以的話先不要上 Editor 的部分等 ReplySearch 一起 🙏
喔喔好唷感謝告知

那我上到上次 review 的 add copy button (`2be2131`)~
github 18:16:19
Why overflow scroll here? It's introducing always-on horizontal &amp; vertical scrolls. What can we get from `overflow: scroll`? <https://user-images.githubusercontent.com/108608/82547760-d33df080-9b8c-11ea-8849-65ffd3a13367.png|image>
這個在 ReplySearch 的部分已經在修了
可以的話先不要上 Editor 的部分等 ReplySearch 一起 🙏
喔喔好唷感謝告知

那我上到上次 review 的 add copy button (`2be2131`)~
github 18:21:51
seems that we are missing `flex: 1` here <https://user-images.githubusercontent.com/108608/82549705-ebfbd580-9b8f-11ea-8a54-c14b53537f7f.png|image>
yanglin 18:24:39
這個在 ReplySearch 的部分已經在修了
可以的話先不要上 Editor 的部分等 ReplySearch 一起 🙏
github 18:25:37
`.aside`'s padding and `.similarMessageContainer`'s horizonal padding are stacked together on desktop. <https://user-images.githubusercontent.com/108608/82549939-53198a00-9b90-11ea-9a94-57d867a9bb50.png|image> Mockup: <https://user-images.githubusercontent.com/108608/82549998-72b0b280-9b90-11ea-8fb8-ec3f216da72b.png|image>
mrorz 18:26:51
Replied to a thread: 2020-05-21 18:16:19
喔喔好唷感謝告知

那我上到上次 review 的 add copy button (`2be2131`)~
  • 👍1
mrorz 19:00:15
HackMD
g0v 線上百人黑客松用線上揪松(jothon online) + g0v 協作工具,讓您在家也能參加黑客松!
mrorz 19:57:40
我發現 https://cofacts.hacktabl.org/hoax-for-you 在 Android Chrome 好像會炸掉
但 iOS safari 沒事
超怪 ._.
Screenshot_20200521-195512.png
  • 😱1
mrorz 20:20:52
@ggm production 的 article 的確有 `articleCategory` 了,感謝感謝

不過沒有上 category 本體(資料庫`categories` index 是空的),所以 UI 會因為對不到 category 而壞掉 ><
image.png
yanglin 22:06:33
想問一下
現在的 ReplySearch 在點擊 `將此文章加入回應` 之後會直接 submit
我看現在 production 上的行為也是如此
這個行為是預期中的嗎?
嗯嗯是的~

這個行為對應到 mockup 上,會是「使用現有回應」分頁下「直接用此回應」的按鈕的行為
而 wireframe 上「撰寫新回應」的搜尋框的按鈕「延伸此回應來查核」,會把東西加進正在撰寫的、還沒送出的新回應文字框內。

這與「使用現有回應」的「直接用此回應」行為不同,也是 production 上沒有,這次改版新增的功能。
也就是說如果兩個分頁裡的搜尋結果都想要 reuse `ReplySearch` component,那按鈕的 onClick 會需要由使用 `ReplySearch` 的人來決定,不能在 `ReplySearch` 或甚至是那顆按鈕裡自顧自地呼叫 `createArticleReplyConnection` mutation
mrorz 22:37:16
嗯嗯是的~

這個行為對應到 mockup 上,會是「使用現有回應」分頁下「直接用此回應」的按鈕的行為
image.png
mrorz 22:40:17
而 wireframe 上「撰寫新回應」的搜尋框的按鈕「延伸此回應來查核」,會把東西加進正在撰寫的、還沒送出的新回應文字框內。

這與「使用現有回應」的「直接用此回應」行為不同,也是 production 上沒有,這次改版新增的功能。
image.png
  • 👌1
mrorz 22:42:22
也就是說如果兩個分頁裡的搜尋結果都想要 reuse `ReplySearch` component,那按鈕的 onClick 會需要由使用 `ReplySearch` 的人來決定,不能在 `ReplySearch` 或甚至是那顆按鈕裡自顧自地呼叫 `createArticleReplyConnection` mutation
yanglin 23:40:38
https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=1291%3A300
@mrorz @stbb1025 按下搜尋欄會變色的功能我目前想到的解法是用 `:focus-within` 這個 selector 會比較好做
不過他的支援性有點差 (IE 不支援)
https://caniuse.com/#search=focus%20within
你們覺得呢?
Figma
Created with Figma
我覺得支援度不差呀~mobile 也都有
直接用吧~
mrorz 23:44:33
我覺得支援度不差呀~mobile 也都有
直接用吧~
  • 👌1
2020-05-22
github 01:25:36
<https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=1307%3A285|https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=1307%3A285> the mobile version is horizontal scrolls
github 01:30:28
I'll change it to `overflow: auto` though, to hide scrollbar when user using windows
github 02:42:36
Also, here is a tool that can send to multiple archivers: <https://github.com/oduwsdl/archivenow|https://github.com/oduwsdl/archivenow> There is a server mode available, thus it seems that we can directly dockerize the server so that rumors-api can invoke it whenever it got a url to archive.
mrorz 13:47:47
整理了一下 Youtube API audit 之後我們該怎麼做
https://g0v.hackmd.io/@mrorz/H1T2PIQoU

裡面列出了我們自己的需求,以及各種 mitigation 的 Z 與 B。目前還沒有結論,所以有任何想法歡迎提出
HackMD
Youtube scrapping alternatives ===== :::info 相關討論 - [20200511 Slack](<https://g0v-tw.slack.com/arc>
  • 🦒1
不知道0archive會不會遇到類似的情況@@
我更新了一些東東上去
oembed 很讚!!!感謝分享
bil 18:18:40
不知道0archive會不會遇到類似的情況@@
2020-05-23
lucien 03:50:11
我更新了一些東東上去
  • 2
lucien 03:51:59
卡牌設計跟卡片設計還是不一樣的,卡牌式運用桌遊延續下來把一個操作主題變成一張可以拿在手上,讓你有掌握收藏感的形式;卡片設計是把內容區塊用卡片區隔分組呈現。
  • ❤️1
lucien 03:56:23
卡牌我覺得可以嘗試的地方在於:
1. 從一致化的 profile 設計樣板跳脫
2. 壓縮重要資訊在比較小的卡牌上,可以集中內容。
我覺得如果是為了開發時程考量,我們可以先用卡片,之後再考慮回來嘗試卡牌。
  • ❤️1
mrorz 09:14:24
oembed 很讚!!!感謝分享
Che Chia Chang 10:02:50
@davidchang has joined the channel
bil 10:18:43
原來預錄提案的話就不用很早起stand by嗎!!!!!!
而且還有翻譯謝謝orz超前部署
睡到自然醒待在workis的鄰鄰很感恩🙏
  • 1
bil 10:19:38
早上提到的案例是:
電腦專家建議「不要投票」才能破解電腦程式作票的設計「65%× 總投票數= 罷韓票數」,簡而言之,不去投票所得到的總票數較難達到罷韓電腦作票的門檻,如果去投不同意票,反而總票數增加,會墮入事先設計好的電腦作票程式門檻。

總票數越多×65%= 罷韓票數越多

結論: 請想一想2020年總統大選時,韓國瑜得票數真的會輸那麼多嗎? 電腦專家提示的情況清楚了嗎? 簡單一句話: 不要去投票
bil 10:19:55
Aray
hahababee 10:22:40
@hahababee has joined the channel
mglee 10:43:37
cofacts 資料庫改版了 🎉
  • 🙌3
  • ❤️2
ronnywang 10:50:54
假如線上揪松有人聽不到其他人的聲音的話,麻煩跟我說一聲喔,上一版的線上揪松有這樣的 bug
我我我 (還是大家沒說話?)
試試看從這邊進來
mglee 10:57:23
我我我 (還是大家沒說話?)
ronnywang 11:00:49
jitsi.jothon.online
Join a WebRTC video conference powered by the Jitsi Videobridge
ronnywang 11:00:53
試試看從這邊進來
nonumpa 11:03:54
剛剛去新網站點大拇指,有點小困惑要點左邊的還是右邊的
螢幕快照 2020-05-23 上午10.59.42.png
比鄰今天也遇到一樣的問題

其實我已經忘記當時討論為什麼要把按鈕跟顯示分開了

總之實際用起來幾乎都會按到顯示那塊
筆記一下,那時候應該是參考臉書把操作跟看結果分開的設計,那我覺得統計的形式要改成底線文字比較不會混淆
目前把收到的 feedback 放在最下面協作區
https://g0v.hackmd.io/@mrorz/B1oRgyNjL
nonumpa 11:04:49
於是去看了一下 Youtube 的長怎樣
螢幕快照 2020-05-23 上午11.04.03.png
Sofia 11:57:32
@sofia has joined the channel
mrorz 12:06:22
Replied to a thread: 2020-05-23 11:03:54
比鄰今天也遇到一樣的問題

其實我已經忘記當時討論為什麼要把按鈕跟顯示分開了

總之實際用起來幾乎都會按到顯示那塊
lucien 12:31:10
筆記一下,那時候應該是參考臉書把操作跟看結果分開的設計,那我覺得統計的形式要改成底線文字比較不會混淆
mrorz 12:41:06
目前把收到的 feedback 放在最下面協作區
https://g0v.hackmd.io/@mrorz/B1oRgyNjL
HackMD
Cofacts Hackath39n 協作頁面 ===== :::info - g0v slack channel:`#cofacts` - :handshake: 實體地點:[Workis 工作是](https
github 12:51:58
View details in Rollbar: <https://rollbar.com/mrorz/rumors-line-bot/items/216/|https://rollbar.com/mrorz/rumors-line-bot/items/216/> ``` Error: user doesn't grant required permissions yet File "<https://static.line-scdn.net/liff/edge/2.1/sdk.js>", line 2, in t File "<https://static.line-scdn.net/liff/edge/2.1/sdk.js>", line 2, in z File "<https://static.line-scdn.net/liff/edge/2.1/sdk.js>", line 2, in [anonymous] File "<https://static.line-scdn.net/liff/edge/2.1/sdk.js>", line 2, in [anonymous] File "<https://static.line-scdn.net/liff/edge/2.1/sdk.js>", line 2, in s File "[native code]", line unknown, in promiseReactionJob ```
github 12:54:07
I suspect this is because the user removed "send message to chatroom" function. Need help reproducing this bug. If this is confirmed, we should come up with a way to aid user enable the permission.
mrorz 13:21:45
我發現整個網站有 4 個地方定了 Noto Sans 甚至還有訂全站的 font-size 與 line-height,但只有在首頁有引入 link tag。

理論上應該只要留 theme 的設定就好才對。調這個可能會影響整個網站就是惹 QQ
image.png
  • 😮1
2020-05-24
github 13:51:04
card added here <https://github.com/orgs/cofacts/projects/5#card-38799010|https://github.com/orgs/cofacts/projects/5#card-38799010>
github 13:52:48
card added here <https://github.com/orgs/cofacts/projects/5#card-38799032|https://github.com/orgs/cofacts/projects/5#card-38799032>
github 14:25:36
I think it's because that the logic here is to display feebacks with user present: ``` {feedbacks .filter(({ vote, user }) =&gt; vote === 'UPVOTE' &amp;&amp; user) .map(feedback =&gt; ( &lt;Feedback key={feedback.id} {...feedback} /&gt; ))} ```
2020-05-25
github 00:38:54
Previously, every arithmetic input (with `{LT, GT, ...}`) has its own type, but they are almost the same -- there are only 2 types of such input throughout `rumors-api`, one is for integers, another for date strings. This PR replaces these `getArithmeticExpressionType` calls with 2 input object type instance to simplify the schema. Behavior of rumors-api should not be affected at all.
yanglin 01:00:08
@mrorz @lucien @stbb1025 確認一下 search page 的現狀跟需要釐清的點:
https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=432%3A2019
1. 從 mockup 看起來是要可以從 reference 的標題及文字做搜尋,不過目前 `ListReplies` 好像沒有這樣的 filter?
2. 排序以及 Filter 的 `篩選` `主題` 部分在 `ListReplies` 基本上應該是做不到的
3. 最新查核頁面雖然以使用者而言是以 reply 作為主體,但實際上為了滿足 spec 中的 filter (https://g0v.hackmd.io/ZZWHWi2BTuyhkSWzAvKLAw) 是打 `ListArticles` 的 API 並關聯 replies,但是在 search replies 看起來無可避免的是要用 `ListReplies` 才能滿足 spec 了,所以這兩個頁面可能會變成 UI 長很像但實際上是打不同的 API,這樣 OK 嗎?
Figma
Created with Figma
關於 2 請見
3. 我覺得本來搜尋回應就是要打 ListReply,UI 有類似的外觀沒有什麼不妥。

不過如上圖引述 spec 所述,搜尋回應的 filter 應該會與搜尋文章的 filter 不同。
1. 根據 source code,用 `moreLikeThis` filter 時,搜尋時也會參考 `reference` 欄位。
我是覺得 mockup 裡的 highlight 可以先不做,因為其實 elasticsearch 支援 highlighting,可以先等 API 做完 https://github.com/cofacts/rumors-api/issues/51 再來支援
github 09:37:34
Got it, make sense. I am going to <https://g0v.hackmd.io/ZcoUOX_-RQSkJyl5xz4_Zg|revamp user handling>, giving users from `localhost` a dedicated browser app ID on staging site, and show browser app users to all apps. Hopefully this will solve these weird issue during development.
mrorz 09:42:22
@lucien 接下來台南小聚前我想開一個顯示某個時間後的 article reply feedback 的 API (`ListArticleReplyFeedback`) ,他會可以
• filter by `articlereplyfeedback` 的 `createdAt`, `updatedAt`
• filter by `userId`
• filter by `appId` (如小聚期間顯示來自 `RUMORS_SITE` 的 feedback count,不應計入來自 LINE bot 的 feedback)
• filter by `comment` (`more_like_this` 或 `simple_query_string` 等文字檢索)
• filter by `score`
• sort by `createdAt` or `updatedAt` or `score` (雖然 `score` 目前只有 1, -1,但因為 sort 可以一次下多個,所以可以先 sort by `score` 再 sort by `createdAt` 之類)
如果這個 API 只拿來做 community builder 有點可惜。我想請問這些用來做 profile page 足夠ㄇ
我評價過的回應,主體還是回應,如果評價想放進去可以調整設計
可以用 `ListArticleReplyFeedback` 撈出 `articleReplyFeedback` 列表,然後取用其對應的 `reply` 繪製「我評價過的回應」的 UI
但 filter 與 sorting 只能使用 articereplyfeedback 的欄位
而且技術上也不可能從 `ListReply` 中使用評價做 filter/sort,現在 schema 裡面 `ArticleReplyFeedback` 跟 `Reply` 是完全分開的 index,linking table `articleReply` 更是做在 `articles` 的 nested object
https://g0v.hackmd.io/F1K20uFNSzivBPXsKdg30Q
mrorz 09:47:43
關於 2 請見
image.png
mrorz 09:49:10
3. 我覺得本來搜尋回應就是要打 ListReply,UI 有類似的外觀沒有什麼不妥。

不過如上圖引述 spec 所述,搜尋回應的 filter 應該會與搜尋文章的 filter 不同。
mrorz 09:50:39
1. 根據 source code,用 `moreLikeThis` filter 時,搜尋時也會參考 `reference` 欄位。
``` fields: ['text', 'reference'], ```
  • 😀1
mrorz 09:52:51
我是覺得 mockup 裡的 highlight 可以先不做,因為其實 elasticsearch 支援 highlighting,可以先等 API 做完 https://github.com/cofacts/rumors-api/issues/51 再來支援
*Scenario* 1. LINE users seems not happy with the current "similarity" and tends to create new articles all the time. By showing the exact match of sentences may help them choose the identical articles. 2. Snippets / highlights can help Editors find interesting articles in the "related replies / articles" section. *Proposed solutions* API server should return matched paragraphs in each search result. LINE bot &amp; website should display the search result in a manner similar to the <https://support.google.com/webmasters/answer/35624?hl=en|snippets in Google Search>. This is achievable via elastic search "highlighting" function. <https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-highlighting.html|https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-highlighting.html>
lucien 12:56:15
我評價過的回應,主體還是回應,如果評價想放進去可以調整設計
mrorz 13:33:57
可以用 `ListArticleReplyFeedback` 撈出 `articleReplyFeedback` 列表,然後取用其對應的 `reply` 繪製「我評價過的回應」的 UI
mrorz 13:34:17
但 filter 與 sorting 只能使用 articereplyfeedback 的欄位
mrorz 13:35:50
而且技術上也不可能從 `ListReply` 中使用評價做 filter/sort,現在 schema 裡面 `ArticleReplyFeedback` 跟 `Reply` 是完全分開的 index,linking table `articleReply` 更是做在 `articles` 的 nested object
https://g0v.hackmd.io/F1K20uFNSzivBPXsKdg30Q
mrorz 13:42:08
抱歉現在發現 production & staging 上面,reply list 顯示的作者與時間並不正確 >“<
reply list 裡顯示的作者與時間,應該是 `articleReply.user` 與 `articleReply.createdAt` ,而不該是 `articleReply.reply.user` 與 `articleReply.reply.createdAt` 唷。
原因是,把一則舊回應 connect 到 article 上的是 `articleReply.user` 。一則現有 `reply` 被用在其他 `article` 時,`reply.user` 其實並不知情,完全是 `articleReply.user` 的意思。

整個列表「最近被回應」的排序,也是使用 `articleReply.createdAt` 的時間,而不是 `reply.createdAt`

(下圖橘字 `articleReply.updatedAt` 是誤植,應該是 `articleReply.createdAt` )
螢幕快照 2020-05-25 下午1.30.30.png
github 14:00:25
Thanks for the update! I found some points not considered previously and has added as comments.
github 14:00:25
According to mockup, in the first line, we now always show `articleReply`'s author all the time. <https://user-images.githubusercontent.com/108608/82780423-b0ac2000-9e89-11ea-9b94-7f1354574c08.png|image> When `articleReply`'s author differs from the `reply` author, we show "originally written by XXX | original reply referenced N times" as extra info.
github 14:00:25
Although in the mockup, “Follow” function is actually excluded from current plan. Please remove the button for now.
github 14:00:25
Actually this button opens a form that submits reply request, thus `requestedForReply` flag should somehow affect this button. Currently mockup and spec did not consider the state of this button when the user has submitted a reply request (i.e. `requestedForReply` is `true`). I suggest changing the wording of the button to `Update comment` when `requestedForReply === true`. What do you think? <https://github.com/yanglin5689446|@yanglin5689446> <https://github.com/LucienLee|@LucienLee>
github 14:00:25
The time display here should not be `reply`'s `createdAt`. It should be the corresponding `articleReply`'s `createdAt` instead. <https://user-images.githubusercontent.com/108608/82780291-47c4a800-9e89-11ea-8227-9a791474f328.png|螢幕快照 2020-05-25 下午1 08 44> When A is using B's old reply, A is `articleReply.user` and B is `articleReply.reply.user`. B previously created the reply for another article; it's A that connects the reply to this article, thus we use A instead of B.
github 14:00:25
Consider using <https://material-ui.com/customization/default-theme/?expand-path=$.zIndex|`theme.zIndex.appBar`>, which takes modals, tooltips, snackbars into consideration as well.
mrorz 14:38:47
@lucien
`ListArticle` 目前無法過濾出「我回報的可疑訊息」,但 `ListReply` 有 `selfOnly` 可以用,所以「我查核過的回應」可以做。我建議在 API 不支援的現在,暫時先拿掉「我回報的可疑訊息」這個選項。

cc/ @yanglin5689446
github 14:52:41
Let's add `target="_blank"` here since the button says "in new tab"
github 14:52:41
[Trivial] Since all its child have `flex-grow`, we don't need `justifyContent` here
github 14:52:41
The new search UI looks really nice! The use of context is good is also inspiring. Thank you for the implementation. Please find my trivial suggestions below.
github 14:57:30
The desktop now looks good in line clamp :) However, given the limited lines to display in this section, I think we don't need to add `nl2br`, so that we can reveal more text to the user. <https://user-images.githubusercontent.com/108608/82786769-c294bf80-9e97-11ea-8ad1-f492d20bb394.png|image>
github 15:02:03
&gt; The desktop now looks good in line clamp :) &gt; &gt; However, given the limited lines to display in this section, I think we don't need to add `nl2br`, so that we can reveal more text to the user. &gt; &gt; <https://user-images.githubusercontent.com/108608/82786769-c294bf80-9e97-11ea-8ad1-f492d20bb394.png|image>
github 15:15:10
Clicking each similar-article item should go to article page. Forgot to add `&lt;Link&gt;` :P
github 15:25:33
Unit test on travis is totally broken......
2020-05-26
github 00:24:45
Previously, `client.deleteByQuery` may delete nothing when `urls` index is not refreshed. This causes unit tests to fail if `CreateReply` unit test is executed before other unit tests that reads `urls` index. This manual refresh should make sure unit tests gets consistent results.
github 00:53:01
We have come a long way to bring the article detail page to the current level. Good work! I believe we can deliver an upgrade to the current production site for a function complete editing experience very soon -- we are just few fixes away :muscle:
github 00:53:01
Next.js <https://nextjs.org/docs/api-reference/next/link|suggests> using `&lt;a&gt;` tag for `&lt;Link&gt;`'s children. I think we can directly change `.similarMessageContainer` to use `a` tag instead of `div`. Currently it do navigates user if they click the link, but if `&lt;Link&gt;` is combined with `&lt;a&gt;`, it allows user to cmd-click to open the link in new tab. We won't need `cursor: pointer` on the element as well, since `&lt;a&gt;` already turns cursor into pointer. (But we may need `text-decoration: none` to cancel out `&lt;a&gt;`'s default style, though.)
github 00:53:01
On desktop browser with a narrow screen, we get an inactive button: <https://user-images.githubusercontent.com/108608/82830907-9013b280-9ee9-11ea-89ac-1b8fb1744319.gif|share-no-use> Root cause is as described <https://github.com/cofacts/rumors-site/pull/249#discussion_r425051205|above> -- we only need one button that invokes `navigator.share` if it's available and shows dropdown otherwise.
mrorz 10:59:16
這張 API 的小小 refactor 求 review:
• 把重複的 argument 定義為重複使用的 input object type
• 修好 unit test 常常 fail 的問題
https://github.com/cofacts/rumors-api/pull/168
Previously, every arithmetic input (with `{LT, GT, ...}`) has its own input object type, but they are almost the same -- there are only 2 types of such input throughout `rumors-api`, one is for integers, another for date strings. This PR replaces these `getArithmeticExpressionType` calls with 2 input object type instance to simplify the schema. Behavior of rumors-api should not be affected at all.
今天晚點看
lucien 12:49:57
今天晚點看
  • 1
github 14:42:55
I've observed that we won't get the issue if you comment out the `&lt;Trendline /&gt;` component which is aligned with <https://github.com/cofacts/rumors-site/issues/211#issuecomment-586492770|iframe issue> that <https://github.com/normanlinnet|@normanlinnet> mentioned. I'll continue to dig into the problem and see if I can find a way to solve it.
github 14:58:07
Thank you <https://github.com/jihchi|@jihchi> for locating the component that caused this issue! We recently have <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=681%3A0|plans> to replace the iframe with line charts (data from Google Analytics reporting API). Let's hope the problem can go away soon. Removing "good first issue" because the root cause is identified as something we are going to deprecate soon.
2020-05-27
annc 12:08:23
@annhhchen has joined the channel
mrorz 12:25:00
今天請假一次
收到~下次要早點說唷
lucien 14:34:55
ok
lucien 15:37:21
已更新文件
github 16:02:00
This PR implements `ListArticleReplyFeedback` API. *Use case* • As Cofacts team, I want to <https://cofacts.github.io/community-builder/#/bignum?start=2020-05-24T15%3A57&amp;panels=useful|show number of new feedbacks generated> on website on the projector screen during editor meetups, so that I can encourage the participants. • As Cofacts team, I want to see new feedbacks generated this week and use them as insights when posting updates to editor's Facebook group, so that I can encourage editors in the community • As Cofacts editor, I want to see a list of new feedbacks on my article reply feedbacks in <https://g0v.hackmd.io/@NFi0czulSemxCM8RNSlz8Q/HJ8xT3QVU/%2FbbreV0ZqRDarHl4Zt5UpEw|my profile page>, so that I can acknowledge my contribution and understand what I can improve on. *Capability* • List article reply feedback in the database that can: • filter by`userId`, `appId`, `articleId`, `replyId` • filter by a range of `createdAt` or `updatedAt` • filter by feedback vote `1` or `-1` • filter by `comments` matching some keyword • sort by feedback vote, `createdAt` or `updatedAt` • Add necessary fields on `ArticleReplyFeedback` object type
這隻 API 本週末小聚的 BigNum display 會用到,麻煩大家看一下唷
感謝感謝
github 16:04:43
<https://coveralls.io/builds/31055976|Coverage Status> Coverage increased (+0.5%) to 86.506% when pulling *<https://github.com/cofacts/rumors-api/commit/a2881651da8fc1df653aec4aac47a3d0ec9f4ba1|a288165> on list-article-reply-feedback* into *<https://github.com/cofacts/rumors-api/commit/e7daf069d889f04cd2f20961eb2f2a5f2e8f7e48|e7daf06> on master*.
github 16:49:58
Trivial: `replyAuthor` seems not needed here
手癢所以不小心修掉了,請 @yanglin5689446 改 code fu06
github 16:50:39
LGTM! Let's ship it <https://github.githubassets.com/images/icons/emoji/shipit.png|:shipit:>
github 17:17:23
This flash message is never shown because `onClose()` unmounts `Snackbar`. Suggest moving snackbar to in `article/[id].js`.
github 17:17:23
1 blocking issue discovered: `AppHeader` is covering `NewReplySection` on mobile. Seems that we should either use <https://material-ui.com/components/dialogs/#full-screen-dialogs|Material-ui Full screen dialog>, or at least applying <https://material-ui.com/customization/z-index/|`theme.zIndex.modal`>. <https://user-images.githubusercontent.com/108608/83000384-ddecff80-a03c-11ea-9ec7-6f3f343c4b34.png|image>
mrorz 17:19:01
手癢所以不小心修掉了,請 @yanglin5689446 改 code fu06
github 17:41:06
I think it's rare to see parent components passing a state setter function down to its children. • I suggest making `NewReplySection`'s only responsibility would be invoking event handlers like `onSubmissionComplete`. `article/[id].js` should invoke `setFlashMessage` when handling `onSubmissionComplete` . • It's OK for `createReply` and `connectReply` to show the same flash message "The reply has been submitted.". We can add `onError` prop as error handler to `NewReplySection`, invoking the callback on error. However, I think it's also OK if we directly invoke `alert()` on error, or process errors within `NewReplySection`.
針對 commit 的 comment 在 github 上好像能見度不高 QQ
我有看到歐也修囉
我順手修一修然後上 merge 唷
mrorz 18:02:47
針對 commit 的 comment 在 github 上好像能見度不高 QQ
yanglin 18:17:14
我有看到歐也修囉
yanglin 18:20:31
在改全站搜索時遇到一個問題:
目前相關回覆會先全部 replies,再從 articleReplies 找第一個 article 當作該 reply 第一次回覆的 article,所以 query 大概長這樣:
```ListReplies(){
...
articleReplies(status: NORMAL) {
article {}
}
}```
但如果這個 reply 已經被刪除 ,`articleReplies(status: NORMAL)` 就可能會是空的
這樣要怎麼處理呢?
這種 reply 我覺得要略過耶

若一個回應完全沒有任何 normal articleReply,那他很可能是有打錯字或者是不夠好的回應

我自己也會回應的時候改兩三次,然後刪掉覺得不夠好的 articleReply。所以我在搜尋的時候,不會希望這些沒 articleReply 的 reply 出現。
mrorz 18:52:56
這種 reply 我覺得要略過耶

若一個回應完全沒有任何 normal articleReply,那他很可能是有打錯字或者是不夠好的回應

我自己也會回應的時候改兩三次,然後刪掉覺得不夠好的 articleReply。所以我在搜尋的時候,不會希望這些沒 articleReply 的 reply 出現。
lucien 19:29:09
今天請假一次
bil 20:38:45
收到~下次要早點說唷
2020-05-28
mrorz 02:03:34
我順手修一修然後上 merge 唷
github 10:36:43
View details in Rollbar: <https://rollbar.com/mrorz/rumors-line-bot/items/220/|https://rollbar.com/mrorz/rumors-line-bot/items/220/> ``` TypeError: Cannot read property 'sessionId' of undefined File "/app/build/webhook/index.js", line 89, in singleUserHandler if (data.sessionId !== context.data.sessionId) { File "&lt;anonymous&gt;", line unknown, in runMicrotasks File "internal/process/task_queues.js", line 97, in processTicksAndRejections ```
github 10:37:55
Should figure out how to reproduce. Which one is undefined, `data` or `context.data`?
bil 12:09:05
https://cofacts.g0v.tw/article/2unpagfl6e9hn
url 很長的頁會排版長得很長很長
  • 1
github 13:11:43
Ref: <https://github.com/storybookjs/storybook/issues/10477#issuecomment-635075061|storybookjs/storybook#10477 (comment)> Reproduce: 1. `docker pull node:12` 2. `IMAGE_NAME=rumors-site-test hooks/build` 3. See build error like this one: <https://user-images.githubusercontent.com/108608/83101336-b2bdeb00-a0e4-11ea-84e5-bfb14cdc796e.png|image> This PR follows suggestions in <https://github.com/storybookjs/storybook/issues/10477|storybookjs/storybook#10477> to fix the build error.
mrorz 13:42:06
Replied to a thread: 2020-05-27 16:02:00
這隻 API 本週末小聚的 BigNum display 會用到,麻煩大家看一下唷
感謝感謝
yanglin 22:30:40
剛剛發現 `ListReplies` API 的 filter 現在只能一次套用一種 type
但是 mockup 裡 replies type filter 會改成多選的
所以後端應該需要改一下
截圖 2020-05-28 下午10.29.50.png
2020-05-29
github 00:32:54
Update search page, make replies search works. mockup: <https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=432%3A2727|https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=432%3A2727>
mrorz 00:40:24
看來 `flex: 1` 不足以讓右邊欄乖乖變小,還需要 `min-width: 0` 來取消掉 flexbox 的 min-sizing behavior 才行
https://cofacts.hacktabl.org/article/x1265bzf4voa
Stack Overflow
I have 4 flexbox columns and everything works fine, but when I add some text to a column and set it to a big font size, it is making the column wider than it should be due to the flex property. I ...
  • 👌1
mrorz 12:53:46
新版上架 🚀
https://github.com/cofacts/rumors-site/releases/tag/release%2F20200529
(雖然其實大松前就透過改 image 的方式上了,但今天是正式走 merge + build + release 流程唷)
  • 🚀1
github 14:57:40
<https://www.figma.com/file/zpD45j8nqDB2XfA6m2QskO/Cofacts-website?node-id=299%3A403|Reply page mockup> requires a multi-select reply type filter for `ListReplies`. This PR: • implements `ListReplies`'s `types` filter. • add snapshot name to test cases that has multiple snapshot files so that it's easier to do code review.
github 15:00:11
<https://coveralls.io/builds/31110287|Coverage Status> Coverage increased (+0.07%) to 86.578% when pulling *<https://github.com/cofacts/rumors-api/commit/970a0b46c2308c41197337f10a5412e6c8e5dbd1|970a0b4> on listreply-multiple-type* into *<https://github.com/cofacts/rumors-api/commit/a2b89f7014dfa4c901ffab6d10c78b833278f297|a2b89f7> on master*.
github 15:49:34
Currently if we specify multiple filters to `ArticleReplyFeedback`, the search result will be the union of all filters: • Filter: `{createdAt: {GT: "2020-05-29T00:00:00Z"}}` • Result `totalCount`: 26 • Filter: `{createdAt: {GT: "2020-05-29T00:00:00Z"}, vote: UPVOTE}` • Result`totalCount`: 145358 This PR changes the behavior to intersection so that the filter is more useful. *Root cause* Originally the filters are attached to `shouldQueries`. However, we allow elasticsearch to include items that matches only 1 should cause. `shouldQueries` should be only used in queries that involves relevance scoring, such as `more_like_this`.
github 15:52:07
<https://coveralls.io/builds/31111158|Coverage Status> Coverage remained the same at 86.578% when pulling *<https://github.com/cofacts/rumors-api/commit/2d1471faf2a5bd61a0f25badc424c2b352ba45d7|2d1471f> on fix-arf-multi-filter* into *<https://github.com/cofacts/rumors-api/commit/1ef3790da93aec2ee26426d5561766ff1708ae13|1ef3790> on master*.
github 17:44:09
Fixes <https://github.com/cofacts/rumors-api/issues/165|#165> • Implements `articleRepliesFrom` in <https://github.com/cofacts/rumors-api/issues/165|#165> • Drops `appId` because `userId` should be sufficient according to <https://g0v.hackmd.io/ZcoUOX_-RQSkJyl5xz4_Zg#%E6%96%B9%E5%90%91-2-%E9%87%9D%E5%B0%8D%E6%AF%8F%E5%80%8B-backend-user-%E9%83%BD%E7%94%A2%E7%94%9F%E4%B8%80%E5%80%8B-user-document|`userId` / `appId` management proposal> • I cannot think of any useful use case filtering article-reply's `appId` yet • Fixes `categoryIds` and `hasArticleReplyWithMorePositiveFeedback`, which unions its results when used with other filters and is incorrect • Similar to <https://github.com/cofacts/rumors-api/pull/171|#171>, please see <https://github.com/cofacts/rumors-api/pull/171|#171> for explanation.
github 17:46:51
<https://coveralls.io/builds/31113234|Coverage Status> Coverage increased (+0.4%) to 86.933% when pulling *<https://github.com/cofacts/rumors-api/commit/315b7a48dec52eb6ce99ad214622d713e0d25bd3|315b7a4> on user-filter* into *<https://github.com/cofacts/rumors-api/commit/1ef3790da93aec2ee26426d5561766ff1708ae13|1ef3790> on master*.
mrorz 17:57:35
\APIの日/
github 18:36:16
Ref: <https://www.facebook.com/groups/cofacts/permalink/2702689166629562/|https://www.facebook.com/groups/cofacts/permalink/2702689166629562/> *Impact* All reply submission. No one can submit new replies to Cofacts now. *Root cause* In `NewReplySection/index`, `handleSubmit` is picking up old `fields` variable, which is always empty. *Proposed fix* • Add `fields` to `useCallback` deps • TODO: Make eslint emit error on omitted dependency
mrorz 20:31:16
現在橢圓形黃色送出按鈕 for reply, feedback, reply request 按下去之後看起來好像沒反應,等一下之後突然送出了。在網路連線比較差的地方,這件事情特別明顯。

我覺得在按下去之後應該要有一個 loading state,可能是顯示 material ui 的 loading 然後 disable 他之類的?

請問 @stbb1025 有什麼想法嗎~
material-ui.com
Progress indicators commonly known as spinners, express an unspecified wait time or display the length of a process. The animation works with CSS, not JavaScript.
我覺得加個loading圈圈吧
github 22:01:57
This PR enables react-hooks eslint rules and fixes all errors. All violation of `react-hooks/exhausive-deps` now triggers build failure and requires explicitly disabling it using line comments (also need to include a good reason in comment!). Current violations are fixed using the following rules: • `useCallback`: 1. curried callbacks (`item =&gt; () =&gt; {}`) should not put in `useCallback` because when it's used in event handlers, curry function is invoked and a new copy of handler is always returned. There is no use putting `useCallback` over curried callbacks. 2. event handlers depending on other function that is not memoized: its dependency will change every render. I remove its `useCallback` in this case. 3. otherwise, add dependency to array. • `useEffect`: 1. If it's meant to be a `componentDidMount`, I disable the rule for that line. 2. If it's meant to be invoked on dependency change, I add the remaining dependencies. *Each code change in this PR may introduce hard-to-find bugs. Please inspect carefully.*
lucien 22:42:27
我覺得加個loading圈圈吧
2020-05-30
jihchi 10:22:47
Hello,不知道先前有沒有討論過?有考慮幫 website 加上 E2E test 嗎?
lbrett558 15:58:56
@lbrett558 has joined the channel
2020-05-31
mrorz 15:46:54
小聚參與者傑哥發現破版
https://cofacts.g0v.tw/article/33y6c0kmucpjq
不知道是誰撐的 orz
被預覽畫面給撐爆了 XD
tmonk 16:11:20
被預覽畫面給撐爆了 XD
tmonk 18:07:55
請問現在右上角的「我的主頁」跟「關於 Cofacts」是可以使用的嗎?點了沒反應 😛
lucien 18:42:36
設計好了,但還沒實作呢
  • 2