diff --git a/package-lock.json b/package-lock.json index e5b8dad..e6e6078 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "html-to-text": "^8.0.0" + "react-grid-system": "^7.3.1" }, "devDependencies": { "@ant-design/icons": "^4.7.0", @@ -3379,18 +3379,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "dependencies": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, "node_modules/@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -10829,6 +10817,7 @@ "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, "license": "MIT" }, "node_modules/commondir": { @@ -11973,6 +11962,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -12290,11 +12280,6 @@ "node": ">=8" } }, - "node_modules/discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=" - }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -12322,6 +12307,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", @@ -12353,6 +12339,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, "funding": [ { "type": "github", @@ -12375,6 +12362,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.2.0" @@ -12390,6 +12378,7 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^1.0.1", @@ -12696,6 +12685,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" @@ -15454,6 +15444,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, "license": "MIT", "bin": { "he": "bin/he" @@ -15578,25 +15569,6 @@ "node": ">=8" } }, - "node_modules/html-to-text": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.0.0.tgz", - "integrity": "sha512-fEtul1OerF2aMEV+Wpy+Ue20tug134jOY1GIudtdqZi7D0uTudB2tVJBKfVhTL03dtqeJoF8gk8EPX9SyMEvLg==", - "dependencies": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.5", - "selderee": "^0.6.0" - }, - "bin": { - "html-to-text": "bin/cli.js" - }, - "engines": { - "node": ">=10.23.2" - } - }, "node_modules/html-void-elements": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", @@ -15664,6 +15636,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -17487,7 +17460,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, "license": "MIT" }, "node_modules/js-yaml": { @@ -18160,7 +18132,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -18703,6 +18674,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true, "license": "MIT" }, "node_modules/minipass": { @@ -18833,11 +18805,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, "node_modules/move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -19009,27 +18976,6 @@ "dev": true, "license": "MIT" }, - "node_modules/nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "dependencies": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - }, - "bin": { - "nearley-railroad": "bin/nearley-railroad.js", - "nearley-test": "bin/nearley-test.js", - "nearley-unparse": "bin/nearley-unparse.js", - "nearleyc": "bin/nearleyc.js" - }, - "funding": { - "type": "individual", - "url": "https://nearley.js.org/#give-to-nearley" - } - }, "node_modules/negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -19351,7 +19297,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -19946,18 +19891,6 @@ "dev": true, "license": "MIT" }, - "node_modules/parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "dependencies": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -21200,7 +21133,6 @@ "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.4.0", @@ -21212,7 +21144,6 @@ "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, "license": "MIT" }, "node_modules/property-information": { @@ -21372,11 +21303,6 @@ ], "license": "MIT" }, - "node_modules/railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=" - }, "node_modules/ramda": { "version": "0.21.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", @@ -21384,18 +21310,6 @@ "dev": true, "license": "MIT" }, - "node_modules/randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "dependencies": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - }, - "engines": { - "node": ">=0.12" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -21489,7 +21403,6 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -21878,6 +21791,17 @@ "dev": true, "license": "MIT" }, + "node_modules/react-grid-system": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/react-grid-system/-/react-grid-system-7.3.1.tgz", + "integrity": "sha512-q5dTeKURLZ2lAFLTjMKdjgubhibIu+EvdT838bcki/rQ8ftJGm+afzZHT2Da6BASWYpXo9+OSIS9M7VFp4/gbQ==", + "dependencies": { + "prop-types": "^15.7.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.x" + } + }, "node_modules/react-helmet-async": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.1.2.tgz", @@ -22802,6 +22726,7 @@ "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.12" @@ -23342,17 +23267,6 @@ "url": "https://opencollective.com/webpack" } }, - "node_modules/selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "dependencies": { - "parseley": "^0.7.0" - }, - "funding": { - "url": "https://ko-fi.com/killymxi" - } - }, "node_modules/select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", @@ -29866,15 +29780,6 @@ } } }, - "@selderee/plugin-htmlparser2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz", - "integrity": "sha512-J3jpy002TyBjd4N/p6s+s90eX42H2eRhK3SbsZuvTDv977/E8p2U3zikdiehyJja66do7FlxLomZLPlvl2/xaA==", - "requires": { - "domhandler": "^4.2.0", - "selderee": "^0.6.0" - } - }, "@sinonjs/commons": { "version": "1.8.3", "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.3.tgz", @@ -35281,7 +35186,8 @@ "commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true }, "commondir": { "version": "1.0.1", @@ -36135,7 +36041,8 @@ "deepmerge": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "dev": true }, "defaults": { "version": "1.0.3", @@ -36371,11 +36278,6 @@ "path-type": "^4.0.0" } }, - "discontinuous-range": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", - "integrity": "sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=" - }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -36398,6 +36300,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, "requires": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", @@ -36419,7 +36322,8 @@ "domelementtype": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", - "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==" + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true }, "domexception": { "version": "1.0.1", @@ -36434,6 +36338,7 @@ "version": "4.2.2", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.2.tgz", "integrity": "sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w==", + "dev": true, "requires": { "domelementtype": "^2.2.0" } @@ -36442,6 +36347,7 @@ "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "dev": true, "requires": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", @@ -36689,7 +36595,8 @@ "entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true }, "errno": { "version": "0.1.8", @@ -38732,7 +38639,8 @@ "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true }, "highcharts": { "version": "9.3.0", @@ -38830,19 +38738,6 @@ "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", "dev": true }, - "html-to-text": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-8.0.0.tgz", - "integrity": "sha512-fEtul1OerF2aMEV+Wpy+Ue20tug134jOY1GIudtdqZi7D0uTudB2tVJBKfVhTL03dtqeJoF8gk8EPX9SyMEvLg==", - "requires": { - "@selderee/plugin-htmlparser2": "^0.6.0", - "deepmerge": "^4.2.2", - "he": "^1.2.0", - "htmlparser2": "^6.1.0", - "minimist": "^1.2.5", - "selderee": "^0.6.0" - } - }, "html-void-elements": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-1.0.5.tgz", @@ -38892,6 +38787,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, "requires": { "domelementtype": "^2.0.1", "domhandler": "^4.0.0", @@ -40173,8 +40069,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.14.1", @@ -40666,7 +40561,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -41057,7 +40951,8 @@ "minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true }, "minipass": { "version": "3.1.5", @@ -41153,11 +41048,6 @@ "minimist": "^1.2.5" } }, - "moo": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.1.tgz", - "integrity": "sha512-I1mnb5xn4fO80BH9BLcF0yLypy2UKl+Cb01Fu0hJRkJjlCRtxZMWkTdAtDd5ZqCOxtCkhmRwyI57vWT+1iZ67w==" - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -41294,17 +41184,6 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, - "nearley": { - "version": "2.20.1", - "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", - "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", - "requires": { - "commander": "^2.19.0", - "moo": "^0.5.0", - "railroad-diagrams": "^1.0.0", - "randexp": "0.4.6" - } - }, "negotiator": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", @@ -41561,8 +41440,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -41967,15 +41845,6 @@ "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", "dev": true }, - "parseley": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/parseley/-/parseley-0.7.0.tgz", - "integrity": "sha512-xyOytsdDu077M3/46Am+2cGXEKM9U9QclBDv7fimY7e+BBlxh2JcBp2mgNsmkyA9uvgyTjVzDi7cP1v4hcFxbw==", - "requires": { - "moo": "^0.5.1", - "nearley": "^2.20.1" - } - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -42813,7 +42682,6 @@ "version": "15.7.2", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", - "dev": true, "requires": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", @@ -42823,8 +42691,7 @@ "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" } } }, @@ -42939,26 +42806,12 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, - "railroad-diagrams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", - "integrity": "sha1-635iZ1SN3t+4mcG5Dlc3RVnN234=" - }, "ramda": { "version": "0.21.0", "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.21.0.tgz", "integrity": "sha1-oAGr7bP/YQd9T/HVd9RN536NCjU=", "dev": true }, - "randexp": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", - "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", - "requires": { - "discontinuous-range": "1.0.0", - "ret": "~0.1.10" - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -43029,7 +42882,6 @@ "version": "17.0.2", "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", - "dev": true, "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -43315,6 +43167,14 @@ "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==", "dev": true }, + "react-grid-system": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/react-grid-system/-/react-grid-system-7.3.1.tgz", + "integrity": "sha512-q5dTeKURLZ2lAFLTjMKdjgubhibIu+EvdT838bcki/rQ8ftJGm+afzZHT2Da6BASWYpXo9+OSIS9M7VFp4/gbQ==", + "requires": { + "prop-types": "^15.7.2" + } + }, "react-helmet-async": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/react-helmet-async/-/react-helmet-async-1.1.2.tgz", @@ -44000,7 +43860,8 @@ "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==" + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true }, "reusify": { "version": "1.0.4", @@ -44379,14 +44240,6 @@ "ajv-keywords": "^3.5.2" } }, - "selderee": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/selderee/-/selderee-0.6.0.tgz", - "integrity": "sha512-ibqWGV5aChDvfVdqNYuaJP/HnVBhlRGSRrlbttmlMpHcLuTqqbMH36QkSs9GEgj5M88JDYLI8eyP94JaQ8xRlg==", - "requires": { - "parseley": "^0.7.0" - } - }, "select": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", diff --git a/package.json b/package.json index ccd2328..b022c30 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,6 @@ "typescript": "^4.4.4" }, "dependencies": { - "html-to-text": "^8.0.0" + "react-grid-system": "^7.3.1" } } diff --git a/scripts/new.sh b/scripts/new.sh index 246fb9a..59d6017 100755 --- a/scripts/new.sh +++ b/scripts/new.sh @@ -2,8 +2,8 @@ mkdir ./src/$1 -echo "" > ./src/$1/index.tsx -echo "" > ./src/$1/props.tsx +echo "import React from 'react';import { Props } from './props';export const index: React.FC = ({}) => {return
;};" > ./src/$1/index.tsx +echo "export interface Props {}" > ./src/$1/props.tsx echo "" > ./src/$1/stories.tsx -echo "" > ./src/$1/styles.tsx +echo "import { Properties } from 'csstype';export const styles = {example: {} as Properties,};" > ./src/$1/styles.tsx echo "" > ./src/$1/.test.tsx \ No newline at end of file diff --git a/src/ChatFeed/FileThumb/.test.tsx b/src/ChatFeed/FileThumb/.test.tsx new file mode 100644 index 0000000..3d9a423 --- /dev/null +++ b/src/ChatFeed/FileThumb/.test.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import * as ReactDOM from 'react-dom'; +import { Default as Thing } from './stories'; + +describe('Thing', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); + }); +}); diff --git a/src/ChatFeed/FileThumb/index.tsx b/src/ChatFeed/FileThumb/index.tsx new file mode 100644 index 0000000..3f2c070 --- /dev/null +++ b/src/ChatFeed/FileThumb/index.tsx @@ -0,0 +1,46 @@ +import React, { useState } from 'react'; + +import { getFileName } from '../../util/file'; + +import { Props } from './props'; +import { styles } from './styles'; + +export const FileThumb: React.FC = ({ + attachment, + isLoading = false, + children = 'Loading...', + style = {}, + loadingStyle = {}, +}) => { + const [hovered, setHovered] = useState(false); + + const fileStyle = { + ...styles.fileView, + ...{ + color: hovered ? '#1890ff' : '#434343', + border: hovered ? '1px solid #1890ff' : '1px solid #434343', + }, + }; + + if (isLoading || !attachment) { + return ( +
+ {children} +
+ ); + } + + return ( +
setHovered(true)} + onMouseLeave={() => setHovered(false)} + onClick={() => window.open(attachment.file)} + > + {getFileName(attachment.file)} +
+ ); +}; diff --git a/src/ChatFeed/FileThumb/props.tsx b/src/ChatFeed/FileThumb/props.tsx new file mode 100644 index 0000000..cf3e473 --- /dev/null +++ b/src/ChatFeed/FileThumb/props.tsx @@ -0,0 +1,13 @@ +import { ReactNode } from 'react'; + +import { Properties } from 'csstype'; + +import { AttachmentProps } from '../../util/interfaces'; + +export interface Props { + attachment?: AttachmentProps; + isLoading?: boolean; + children?: ReactNode; + style?: Properties; + loadingStyle?: Properties; +} diff --git a/src/ChatFeed/FileThumb/stories.tsx b/src/ChatFeed/FileThumb/stories.tsx new file mode 100644 index 0000000..2dbe38b --- /dev/null +++ b/src/ChatFeed/FileThumb/stories.tsx @@ -0,0 +1,29 @@ +import React from 'react'; + +import { Meta, Story } from '@storybook/react'; + +import { FileThumb } from '.'; + +import { Props } from './props'; + +import { fileAttachment } from '../../util/mocks'; + +const meta: Meta = { + title: 'ChatFeed/FileThumb', + component: FileThumb, + argTypes: {}, +}; + +export default meta; + +const Template: Story = (props) => ; + +export const Default = Template.bind({}); +Default.args = { + attachment: fileAttachment, +}; + +export const Loading = Template.bind({}); +Loading.args = { + isLoading: true, +}; diff --git a/src/ChatFeed/FileThumb/styles.tsx b/src/ChatFeed/FileThumb/styles.tsx new file mode 100644 index 0000000..6c083a6 --- /dev/null +++ b/src/ChatFeed/FileThumb/styles.tsx @@ -0,0 +1,28 @@ +import { Properties } from 'csstype'; + +export const styles = { + fileView: { + fontFamily: 'Avenir', + padding: '12px', + borderRadius: '14px', + display: 'inline-block', + marginBottom: '4px', + marginRight: '2px', + cursor: 'pointer', + transition: 'all .33s ease', + WebkitTransition: 'all .33s ease', + MozTransition: 'all .33s ease', + } as Properties, + loadingContainer: { + fontFamily: 'Avenir', + color: 'white', + padding: '14px', + display: 'inline-block', + borderRadius: '14px', + marginRight: '2px', + width: '136px', + marginBottom: '4px', + marginLeft: '4px', + backgroundColor: '#d9d9d9', + } as Properties, +}; diff --git a/src/ChatFeed/ImageThumb/.test.tsx b/src/ChatFeed/ImageThumb/.test.tsx new file mode 100644 index 0000000..3d9a423 --- /dev/null +++ b/src/ChatFeed/ImageThumb/.test.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import * as ReactDOM from 'react-dom'; +import { Default as Thing } from './stories'; + +describe('Thing', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); + }); +}); diff --git a/src/ChatFeed/ImageThumb/index.tsx b/src/ChatFeed/ImageThumb/index.tsx new file mode 100644 index 0000000..587c1cc --- /dev/null +++ b/src/ChatFeed/ImageThumb/index.tsx @@ -0,0 +1,41 @@ +import React, { useState } from 'react'; + +import { Props } from './props'; +import { styles } from './styles'; + +export const ImageThumb: React.FC = ({ + attachment, + isLoading = false, + children = 'Loading...', + style = {}, + loadingStyle = {}, +}) => { + const [hovered, setHovered] = useState(false); + + const thumbnailStyle = { + ...styles.thumbnail, + ...{ border: hovered ? '1px solid #1890ff' : '1px solid #fff' }, + }; + + if (isLoading || !attachment) { + return ( +
+ {children} +
+ ); + } + + return ( + setHovered(true)} + onMouseLeave={() => setHovered(false)} + src={attachment.file} + alt={'thumb-nail'} + style={{ + ...thumbnailStyle, + ...style, + }} + onClick={() => window.open(attachment.file)} + /> + ); +}; diff --git a/src/ChatFeed/ImageThumb/props.tsx b/src/ChatFeed/ImageThumb/props.tsx new file mode 100644 index 0000000..cf3e473 --- /dev/null +++ b/src/ChatFeed/ImageThumb/props.tsx @@ -0,0 +1,13 @@ +import { ReactNode } from 'react'; + +import { Properties } from 'csstype'; + +import { AttachmentProps } from '../../util/interfaces'; + +export interface Props { + attachment?: AttachmentProps; + isLoading?: boolean; + children?: ReactNode; + style?: Properties; + loadingStyle?: Properties; +} diff --git a/src/ChatFeed/ImageThumb/stories.tsx b/src/ChatFeed/ImageThumb/stories.tsx new file mode 100644 index 0000000..67bd4f7 --- /dev/null +++ b/src/ChatFeed/ImageThumb/stories.tsx @@ -0,0 +1,29 @@ +import React from 'react'; + +import { Meta, Story } from '@storybook/react'; + +import { ImageThumb } from '.'; + +import { Props } from './props'; + +import { imageAttachment } from '../../util/mocks'; + +const meta: Meta = { + title: 'ChatFeed/ImageThumb', + component: ImageThumb, + argTypes: {}, +}; + +export default meta; + +const Template: Story = (props) => ; + +export const Default = Template.bind({}); +Default.args = { + attachment: imageAttachment, +}; + +export const Loading = Template.bind({}); +Loading.args = { + isLoading: true, +}; diff --git a/src/ChatFeed/ImageThumb/styles.tsx b/src/ChatFeed/ImageThumb/styles.tsx new file mode 100644 index 0000000..eefb906 --- /dev/null +++ b/src/ChatFeed/ImageThumb/styles.tsx @@ -0,0 +1,41 @@ +import { Properties } from 'csstype'; + +export const styles = { + thumbnail: { + cursor: 'pointer', + textAlign: 'right', + display: 'inline', + objectFit: 'cover', + borderRadius: '0.3em', + padding: '2px', + // Size + height: '30vw', + width: '30vw', + maxHeight: '200px', + maxWidth: '200px', + minHeight: '100px', + minWidth: '100px', + transition: 'all .33s ease', + WebkitTransition: 'all .33s ease', + MozTransition: 'all .33s ease', + } as Properties, + loadingContainer: { + fontFamily: 'Avenir', + color: 'white', + cursor: 'pointer', + textAlign: 'right', + display: 'inline-block', + objectFit: 'cover', + borderRadius: '0.3em', + padding: '2px', + marginRight: '2px', + marginBottom: '4px', + height: '30vw', + width: '30vw', + maxHeight: '200px', + maxWidth: '200px', + minHeight: '100px', + minWidth: '100px', + backgroundColor: '#d9d9d9', + } as Properties, +}; diff --git a/src/ChatFeed/MyMessage/.test.tsx b/src/ChatFeed/MyMessage/.test.tsx new file mode 100644 index 0000000..996a446 --- /dev/null +++ b/src/ChatFeed/MyMessage/.test.tsx @@ -0,0 +1,13 @@ +import React from 'react'; +import * as ReactDOM from 'react-dom'; +import { Default as Thing } from './stories'; + +import { message } from '../../util/mocks'; + +describe('Thing', () => { + it('renders without crashing', () => { + const div = document.createElement('div'); + ReactDOM.render(, div); + ReactDOM.unmountComponentAtNode(div); + }); +}); diff --git a/src/ChatFeed/MyMessage/index.tsx b/src/ChatFeed/MyMessage/index.tsx new file mode 100644 index 0000000..77367a2 --- /dev/null +++ b/src/ChatFeed/MyMessage/index.tsx @@ -0,0 +1,175 @@ +import React, { useState } from 'react'; + +import { Props } from './props'; +import { styles } from './styles'; + +import { Dot } from '../../Dot'; + +import { FileThumb } from '../FileThumb'; +import { ImageThumb } from '../ImageThumb'; + +import { isImage, getFileName } from '../../util/file'; +import { formatTime, getDateTime } from '../../util/dateTime'; + +import { Row, Col, setConfiguration } from 'react-grid-system'; + +setConfiguration({ maxScreenClass: 'xl' }); + +export const MyMessage: React.FC = ({ + lastMessage = null, + message, + nextMessage = null, + chat = null, + isSending = false, +}) => { + const [hovered, setHovered] = useState(false); + + const topRightRadius = + !lastMessage || lastMessage.sender_username !== message.sender_username + ? '1.3em' + : '0.3em'; + const bottomRightRadius = + !nextMessage || nextMessage.sender_username !== message.sender_username + ? '1.3em' + : '0.3em'; + + const borderRadius = `1.3em ${topRightRadius} ${bottomRightRadius} 1.3em`; + const paddingBottom = + !nextMessage || nextMessage.sender_username !== message.sender_username + ? '12px' + : '2px'; + + const text: string = + message.text !== null + ? message.text.replace(/ { + const attachments = + message && message.attachments ? message.attachments : []; + + return attachments.map((attachment, index) => { + const fileName = getFileName(attachment.file); + + if (isImage(fileName)) { + return ( + + ); + } + + return
; + }); + }; + + const renderFiles = () => { + const attachments = + message && message.attachments ? message.attachments : []; + + return attachments.map((attachment, index) => { + const fileName = getFileName(attachment.file); + + if (!isImage(fileName)) { + return ( + + ); + } + + return
; + }); + }; + + const renderReads = () => { + const members = chat !== null ? chat.people : []; + return members.map((chatPerson, index) => { + return ( + + ); + }); + }; + + return ( +
+
+ {renderImages()} +
+ +
+ {renderFiles()} +
+ + + + + {formatTime(getDateTime(message.created, 0) as Date)} + + + {message.text !== null && ( +
setHovered(true)} + onMouseLeave={() => setHovered(false)} + > +
+ +
+ )} + + + + + + {renderReads()} + + +
+ ); +}; diff --git a/src/ChatFeed/MyMessage/props.tsx b/src/ChatFeed/MyMessage/props.tsx new file mode 100644 index 0000000..967f981 --- /dev/null +++ b/src/ChatFeed/MyMessage/props.tsx @@ -0,0 +1,9 @@ +import { MessageProps, ChatProps } from '../../util/interfaces'; + +export interface Props { + lastMessage?: MessageProps | null; + message: MessageProps; + nextMessage?: MessageProps | null; + chat?: ChatProps | null; + isSending?: boolean; +} diff --git a/src/ChatFeed/MyMessage/stories.tsx b/src/ChatFeed/MyMessage/stories.tsx new file mode 100644 index 0000000..022b1c3 --- /dev/null +++ b/src/ChatFeed/MyMessage/stories.tsx @@ -0,0 +1,46 @@ +import React from 'react'; + +import { Meta, Story } from '@storybook/react'; + +import { MyMessage } from '.'; +import { Props } from './props'; + +import { + message, + messagePlusAttachments, + chatReadMessage, +} from '../../util/mocks'; + +const meta: Meta = { + title: 'ChatFeed/MyMessage', + component: MyMessage, + argTypes: {}, +}; + +export default meta; + +const Template: Story = (props) => ; + +export const Default = Template.bind({}); +Default.args = { + message: messagePlusAttachments, +}; + +export const BetweenMessages = Template.bind({}); +BetweenMessages.args = { + lastMessage: message, + message: message, + nextMessage: message, +}; + +export const Sending = Template.bind({}); +Sending.args = { + isSending: true, + message: messagePlusAttachments, +}; + +export const ReadMessage = Template.bind({}); +ReadMessage.args = { + message: message, + chat: chatReadMessage, +}; diff --git a/src/ChatFeed/MyMessage/styles.tsx b/src/ChatFeed/MyMessage/styles.tsx new file mode 100644 index 0000000..9a3c6ec --- /dev/null +++ b/src/ChatFeed/MyMessage/styles.tsx @@ -0,0 +1,58 @@ +import { Properties } from 'csstype'; +export const styles = { + myMessage: { + color: 'white', + cursor: 'pointer', + float: 'right', + textAlign: 'left', + // Stay right but render text + padding: '12px', + fontSize: '15px', + fontFamily: 'Avenir', + whiteSpace: 'pre-line', + overflowWrap: 'anywhere', + maxWidth: 'calc(100% - 100px)', + // CSS Transitions + transition: 'all .33s ease', + WebkitTransition: 'all .33s ease', + MozTransition: 'all .33s ease', + } as Properties, + timeTag: { + fontFamily: 'Avenir', + position: 'relative', + top: '12px', + right: '8px', + fontSize: '14px', + color: 'rgb(24, 144, 255)', + // CSS Transitions + transition: 'all .15s ease', + WebkitTransition: 'all .15s ease', + MozTransition: 'all .15s ease', + } as Properties, + thumbnail: { + cursor: 'pointer', + textAlign: 'right', + display: 'inline', + objectFit: 'cover', + borderRadius: '0.3em', + paddingRight: '2px', + // Size + height: '30vw', + width: '30vw', + maxHeight: '200px', + maxWidth: '200px', + minHeight: '100px', + minWidth: '100px', + } as Properties, + fileView: { + fontFamily: 'Avenir', + padding: '12px', + borderRadius: '14px', + display: 'inline-block', + marginBottom: '4px', + marginRight: '2px', + cursor: 'pointer', + color: '#434343', + border: '1px solid #434343', + } as Properties, +}; diff --git a/src/ChatList/ChatLoader/stories.tsx b/src/ChatList/ChatLoader/stories.tsx index 7fdb46c..41d4235 100644 --- a/src/ChatList/ChatLoader/stories.tsx +++ b/src/ChatList/ChatLoader/stories.tsx @@ -26,10 +26,6 @@ Default.args = { export const CustomStyles = Template.bind({}); CustomStyles.args = { onVisible: () => console.log('Chat Loader is visible.'), - style: { maxWidth: '400px', padding: '0px', backgroundColor: '#4a5162' }, - children: ( - - ), + style: { maxWidth: '400px', backgroundColor: '#4a5162' }, + children: , }; diff --git a/src/ChatList/index.tsx b/src/ChatList/index.tsx index b674cd9..f803c1c 100644 --- a/src/ChatList/index.tsx +++ b/src/ChatList/index.tsx @@ -1,12 +1,13 @@ import React from 'react'; -import { Props, ChatProps } from './props'; +import { Props } from './props'; import { styles } from './styles'; import { ChatForm } from './ChatForm'; import { ChatCard } from './ChatCard'; import { ChatLoader } from './ChatLoader'; +import { ChatProps } from '../util/interfaces'; import { getDateTime } from '../util/dateTime'; export const ChatList: React.FC = ({ @@ -33,7 +34,7 @@ export const ChatList: React.FC = ({ const renderChats = (chats: Array) => { return chats.map((chat, index) => { const description = - chat.last_message?.text === '' ? 'Say hello!' : chat.last_message?.text; + chat.last_message.text !== null ? chat.last_message.text : 'Say hello!'; const timeStamp = getDateTime(chat.created).toString().substr(4, 6); const hasNotification = userName ? !readLastMessage(userName, chat) diff --git a/src/ChatList/props.tsx b/src/ChatList/props.tsx index 8f191ba..93c4b9e 100644 --- a/src/ChatList/props.tsx +++ b/src/ChatList/props.tsx @@ -2,39 +2,7 @@ import { HTMLAttributes } from 'react'; import { Properties } from 'csstype'; -export interface MessageProps { - id?: number; - text: string; - sender_username: string; - created: string; - attachments: Array; - custom_json: object | string; -} - -export interface PersonProps { - username: string; - first_name: string | null; - last_name: string | null; - avatar: string | null; - custom_json: string | object | null; - is_online: boolean; -} - -export interface ChatPersonProps { - person: PersonProps; - chat_updated: string | null; - last_read: number | null; -} -export interface ChatProps { - id: number; - title: string; - created: string; - is_direct_chat: boolean; - custom_json: object | string; - last_message: MessageProps; - attachments: Array; - people: Array; -} +import { ChatProps } from '../util/interfaces'; export interface Props extends HTMLAttributes { style?: Properties; diff --git a/src/ChatList/stories.tsx b/src/ChatList/stories.tsx index 85c1f0b..c00899a 100644 --- a/src/ChatList/stories.tsx +++ b/src/ChatList/stories.tsx @@ -5,77 +5,14 @@ import { Meta, Story } from '@storybook/react'; import { ChatList } from '.'; import { Props } from './props'; +import { chats } from '../util/mocks'; + const meta: Meta = { title: 'ChatList', component: ChatList, argTypes: {}, }; -const chats = [ - { - id: 201, - title: 'First Chat ☝️', - is_direct_chat: false, - created: '2021-01-28T02:41:48.826706Z', - custom_json: {}, - attachments: [], - people: [ - { - last_read: 1000, - person: { - username: 'Adam La Morre', - first_name: '', - last_name: '', - avatar: '', - custom_json: '', - is_online: true, - }, - chat_updated: '', - }, - ], - last_message: { - id: 1000, - created: '2021-07-14 01:18:24.567443+00:00', - attachments: [], - sender_username: 'Adam_La_Morre', - text: '

Hello there world!

', - custom_json: '{"sender_id":"1626225504264"}', - }, - }, - { - id: 202, - title: 'Chat Two ✌️ ', - is_direct_chat: false, - created: '2021-01-27T02:41:48.826706Z', - custom_json: {}, - attachments: [], - people: [], - last_message: { - created: '', - attachments: [], - sender_username: '', - text: '', - custom_json: '', - }, - }, - { - id: 203, - title: 'Direct Message w/ Adam', - is_direct_chat: true, - created: '2021-01-26T02:41:48.826706Z', - custom_json: {}, - attachments: [], - people: [], - last_message: { - created: '', - attachments: [], - sender_username: '', - text: '', - custom_json: '', - }, - }, -]; - export default meta; const Template: Story = (props) => ; @@ -110,7 +47,7 @@ UnreadMessages.args = { boxShadow: '0px 0px 3px 6px rgba(0, 0, 0, 0.1)', maxHeight: '300px', }, - userName: 'Adam La Morre', + userName: 'adam_lamorre', chats: chats, }; diff --git a/src/Dot/index.tsx b/src/Dot/index.tsx index c99a5e9..cb70c94 100644 --- a/src/Dot/index.tsx +++ b/src/Dot/index.tsx @@ -7,24 +7,23 @@ export const Dot = ({ avatarUrl = undefined, username = '', style = {}, - visible = true + visible = true, }: Props) => { - - const color = stringToColor(username) + const color = stringToColor(username); return (
- ) -} \ No newline at end of file + ); +}; diff --git a/src/Dot/props.tsx b/src/Dot/props.tsx index 8f6343b..8b920b9 100644 --- a/src/Dot/props.tsx +++ b/src/Dot/props.tsx @@ -1,8 +1,8 @@ import CSS from 'csstype'; export interface Props { - avatarUrl?: string; + avatarUrl?: string | null; username?: string; style?: CSS.Properties; visible?: boolean; -} \ No newline at end of file +} diff --git a/src/util/dateTime.ts b/src/util/dateTime.ts index 7956e01..197f3c6 100644 --- a/src/util/dateTime.ts +++ b/src/util/dateTime.ts @@ -1,17 +1,22 @@ export const getDateTime = (date: string, offset = 0) => { - if (!date) return ''; + if (!date) return ''; - date = date.replace(' ', 'T'); - offset = offset ? offset : 0; + date = date.replace(' ', 'T'); + offset = offset ? offset : 0; - const year = date.substr(0, 4); - const month = date.substr(5, 2); - const day = date.substr(8, 2); - const hour = date.substr(11, 2); - const minute = date.substr(14, 2); - const second = date.substr(17, 2); + const year = date.substr(0, 4); + const month = date.substr(5, 2); + const day = date.substr(8, 2); + const hour = date.substr(11, 2); + const minute = date.substr(14, 2); + const second = date.substr(17, 2); - var d = new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}`); - d.setHours(d.getHours() + offset); - return d; - }; \ No newline at end of file + var d = new Date(`${year}-${month}-${day}T${hour}:${minute}:${second}`); + d.setHours(d.getHours() + offset); + return d; +}; + +export function formatTime(dateTime: Date) { + var time = dateTime.toLocaleString('en-US'); + return time.split(' ')[1].slice(0, -3) + ' ' + time.slice(-2); +} diff --git a/src/util/file.tsx b/src/util/file.tsx new file mode 100644 index 0000000..205207f --- /dev/null +++ b/src/util/file.tsx @@ -0,0 +1,15 @@ +const images = ['jpg', 'jpeg', 'png', 'gif', 'tiff']; + +export const isImage = (fileName: string) => { + const dotSplit = fileName.split('.'); + return ( + dotSplit.length > 0 && + images.indexOf(dotSplit[dotSplit.length - 1].toLowerCase()) !== -1 + ); +}; + +export const getFileName = (fileUrl: string) => { + const slashSplit = fileUrl.split('/'); + const nameAndHash = slashSplit[slashSplit.length - 1]; + return nameAndHash.split('?')[0]; +}; diff --git a/src/util/interfaces.ts b/src/util/interfaces.ts new file mode 100644 index 0000000..e8877b4 --- /dev/null +++ b/src/util/interfaces.ts @@ -0,0 +1,38 @@ +export interface AttachmentProps { + id: number; + file: string; + created: string; +} +export interface MessageProps { + id?: number; + text: string | null; + sender_username: string; + created: string; + attachments: Array; + custom_json: object | string; +} + +export interface PersonProps { + username: string; + first_name: string | null; + last_name: string | null; + avatar: string | null; + custom_json: string | object | null; + is_online: boolean; +} + +export interface ChatPersonProps { + person: PersonProps; + chat_updated: string | null; + last_read: number | null; +} +export interface ChatProps { + id: number; + title: string; + created: string; + is_direct_chat: boolean; + custom_json: object | string; + last_message: MessageProps; + attachments: Array; + people: Array; +} diff --git a/src/util/mocks.tsx b/src/util/mocks.tsx new file mode 100644 index 0000000..2c838e8 --- /dev/null +++ b/src/util/mocks.tsx @@ -0,0 +1,121 @@ +export const imageAttachment = { + id: 10, + file: 'https://chat-engine-assets.s3.amazonaws.com/tutorials/my-face-min.png', + created: '2021-08-03T00:16:52.633778Z', +}; + +export const fileAttachment = { + id: 11, + file: 'https://chat-engine-assets.s3.amazonaws.com/click.mp3', + created: '2021-08-03T00:16:59.633778Z', +}; + +export const message = { + id: 1000, + created: '2021-07-14 01:18:24.567443+00:00', + attachments: [], + sender_username: 'Adam_La_Morre', + text: '

Hello there world!

', + custom_json: '', +}; + +export const messagePlusAttachments = { + id: 1000, + created: '2021-07-14 01:18:24.567443+00:00', + attachments: [imageAttachment, fileAttachment], + sender_username: 'Adam_La_Morre', + text: '

Hey check out this image and MP3 file!

', + custom_json: '', +}; + +export const adam = { + username: 'adam_lamorre', + first_name: 'Adam', + last_name: 'La Morre', + avatar: + 'https://chat-engine-assets.s3.amazonaws.com/tutorials/my-face-min.png', + custom_json: '', + is_online: true, +}; + +export const bob = { + username: 'bob_baker', + first_name: 'Bob', + last_name: 'Baker', + avatar: null, + custom_json: '', + is_online: true, +}; + +export const chatReadMessage = { + id: 201, + title: 'First Chat ☝️', + is_direct_chat: false, + created: '2021-01-28T02:41:48.826706Z', + custom_json: {}, + attachments: [], + people: [ + { + last_read: 1000, + person: adam, + chat_updated: '', + }, + { + last_read: 1000, + person: bob, + chat_updated: '', + }, + ], + last_message: message, +}; + +export const chats = [ + { + id: 201, + title: 'First Chat ☝️', + is_direct_chat: false, + created: '2021-01-28T02:41:48.826706Z', + custom_json: {}, + attachments: [], + people: [ + { + last_read: 1000, + person: adam, + chat_updated: '', + }, + ], + last_message: message, + }, + { + id: 202, + title: 'Chat Two ✌️ ', + is_direct_chat: false, + created: '2021-01-27T02:41:48.826706Z', + custom_json: {}, + attachments: [], + people: [], + last_message: { + created: '', + attachments: [], + sender_username: '', + text: '', + custom_json: '', + }, + }, + { + id: 203, + title: 'Direct Message w/ Adam', + is_direct_chat: true, + created: '2021-01-26T02:41:48.826706Z', + custom_json: {}, + attachments: [], + people: [], + last_message: { + created: '', + attachments: [], + sender_username: '', + text: '', + custom_json: '', + }, + }, +];