From b0ca561e5bd86ebce1f4f5afa6c0839d53520160 Mon Sep 17 00:00:00 2001 From: Chidozie Ononiwu <31145988+chidozieononiwu@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:02:03 -0700 Subject: [PATCH] CSS BugFix (#9183) * CSS BugFix * Coment Resolutions * Comments for Samples * Fire api request with credentials * Add HTML to Markdown Pipe * Add MarkDown Editor --- src/dotnet/APIView/ClientSPA/angular.json | 5 +- .../APIView/ClientSPA/package-lock.json | 566 ++++++++++++++++-- src/dotnet/APIView/ClientSPA/package.json | 5 +- .../conversations.component.scss | 6 +- .../index-page/index-page.component.ts | 2 +- .../review-nav/review-nav.component.ts | 1 - .../samples-page/samples-page.component.html | 2 +- .../samples-page/samples-page.component.scss | 24 + .../samples-page/samples-page.component.ts | 66 +- .../comment-thread.component.html | 6 +- .../comment-thread.component.scss | 20 + .../shared/editor/editor.component.html | 41 +- .../shared/editor/editor.component.scss | 35 +- .../shared/editor/editor.component.spec.ts | 28 - .../shared/editor/editor.component.ts | 49 +- .../shared/review-page-layout.module.ts | 6 +- .../app/_modules/shared/shared-app.module.ts | 3 + .../app/_pipes/html-to-markdown.pipe.spec.ts | 8 + .../src/app/_pipes/html-to-markdown.pipe.ts | 27 + .../src/app/_pipes/markdown-to-html.pipe.ts | 36 +- .../_services/revisions/revisions.service.ts | 2 +- .../app/_services/samples/samples.service.ts | 2 +- .../APIView/ClientSPA/src/app/app.module.ts | 2 +- src/dotnet/APIView/ClientSPA/src/styles.less | 8 + src/dotnet/APIView/ClientSPA/src/styles.scss | 2 - 25 files changed, 775 insertions(+), 177 deletions(-) create mode 100644 src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.spec.ts create mode 100644 src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.ts create mode 100644 src/dotnet/APIView/ClientSPA/src/styles.less diff --git a/src/dotnet/APIView/ClientSPA/angular.json b/src/dotnet/APIView/ClientSPA/angular.json index 9ae8ca038..7ca8b9a7d 100644 --- a/src/dotnet/APIView/ClientSPA/angular.json +++ b/src/dotnet/APIView/ClientSPA/angular.json @@ -36,13 +36,14 @@ "src/manifest.webmanifest" ], "styles": [ - "src/styles.scss" + "src/styles.scss", + "src/styles.less" ], "scripts": [ "node_modules/jquery/dist/jquery.min.js", "node_modules/@popperjs/core/dist/umd/popper.min.js", "node_modules/bootstrap/dist/js/bootstrap.min.js", - "node_modules/quill/dist/quill.js" + "node_modules/simplemde-antd/dist/simplemde.min.js" ], "webWorkerTsConfig": "tsconfig.worker.json" }, diff --git a/src/dotnet/APIView/ClientSPA/package-lock.json b/src/dotnet/APIView/ClientSPA/package-lock.json index af47f7bd3..ba27af775 100644 --- a/src/dotnet/APIView/ClientSPA/package-lock.json +++ b/src/dotnet/APIView/ClientSPA/package-lock.json @@ -24,21 +24,23 @@ "jquery": "^3.7.1", "ngx-cookie-service": "17.1", "ngx-monaco-editor-v2": "^17.0.1", + "ngx-simplemde": "^12.0.0", "ngx-timeago": "^3.0.0", "ngx-ui-scroll": "^3.2.0", "primeicons": "^6.0.1", "primeng": "^17.1.0", - "quill": "^2.0.2", "reflect-metadata": "^0.2.2", "rehype-autolink-headings": "^7.1.0", "rehype-highlight": "^7.0.0", "rehype-raw": "^7.0.0", "rehype-slug": "^6.0.0", "rehype-stringify": "^10.0.0", + "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", + "turndown": "^7.2.0", "unified": "^11.0.4", "zone.js": "~0.14.0" }, @@ -48,6 +50,7 @@ "@angular/compiler-cli": "^17.3.10", "@fortawesome/fontawesome-free": "^6.4.2", "@types/jasmine": "~4.3.0", + "@types/turndown": "^5.0.5", "jasmine-core": "~4.6.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", @@ -2336,6 +2339,82 @@ "node": ">=6.9.0" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.18.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.18.1.tgz", + "integrity": "sha512-iWHdj/B1ethnHRTwZj+C1obmmuCzquH29EbcKr0qIjA9NfDeBDJ7vs+WOHsFeLeflE4o+dHfYndJloMKHUkWUA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.7.0.tgz", + "integrity": "sha512-+cduIZ2KbesDhbykV02K25A5xIVrquSPz4UxxYBemRlAT2aW8dhwUgLDwej7q/RJUHKk4nALYcR1puecDvbdqw==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.10.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.3.tgz", + "integrity": "sha512-kDqEU5sCP55Oabl6E7m5N+vZRoc0iWqgDVhEKifcHzPzjqCegcO4amfrYVL9PmPZpl4G0yjkpTpUO/Ui8CzO8A==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.8.2.tgz", + "integrity": "sha512-PDFG5DjHxSEjOXk9TQYYVjZDqlZTFaDBfhQixHnQOEVDDNHUbEh/hstAjcQJaA6FQdZTD1hquXTK0rVBLADR1g==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.6", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.6.tgz", + "integrity": "sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz", + "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==" + }, + "node_modules/@codemirror/view": { + "version": "6.34.1", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.34.1.tgz", + "integrity": "sha512-t1zK/l9UiRqwUNPm+pdIT0qzJlzuVckbTEMVNFhfWkGiBQClstzg+78vedCvLSX0xJEZ6lwZbPpnljL7L6iwMQ==", + "dependencies": { + "@codemirror/state": "^6.4.0", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2916,6 +2995,27 @@ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==", "dev": true }, + "node_modules/@lezer/common": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz", + "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==" + }, + "node_modules/@lezer/highlight": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz", + "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz", + "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, "node_modules/@ljharb/through": { "version": "2.3.13", "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", @@ -2940,6 +3040,11 @@ "ws": "^7.4.5" } }, + "node_modules/@mixmark-io/domino": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", + "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==" + }, "node_modules/@ngtools/webpack": { "version": "17.3.10", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-17.3.10.tgz", @@ -4030,6 +4135,12 @@ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "dev": true }, + "node_modules/@types/turndown": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.5.tgz", + "integrity": "sha512-TL2IgGgc7B5j78rIccBtlYAnkuv8nUQqhQc+DSYV5j9Be9XOcm/SKOVRuA47xAVI3680Tk9B1d8flK2GWT2+4w==", + "dev": true + }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -5521,6 +5632,28 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/codemirror": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.1.tgz", + "integrity": "sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + } + }, + "node_modules/codemirror-spell-checker": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/codemirror-spell-checker/-/codemirror-spell-checker-1.1.2.tgz", + "integrity": "sha512-2Tl6n0v+GJRsC9K3MLCdLaMOmvWL0uukajNJseorZJsslaxZyZMgENocPU8R0DyoTAiKsyqiemSOZo7kjGV0LQ==", + "dependencies": { + "typo-js": "*" + } + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -5884,6 +6017,11 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, "node_modules/critters": { "version": "0.0.22", "resolved": "https://registry.npmjs.org/critters/-/critters-0.0.22.tgz", @@ -7174,11 +7312,6 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==" - }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", @@ -9860,27 +9993,12 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, - "node_modules/lodash.clonedeep": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" - }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -9989,6 +10107,15 @@ "node": ">=8.0" } }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -10092,6 +10219,52 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-table": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", + "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/marked": { + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.3.tgz", + "integrity": "sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.1.tgz", + "integrity": "sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mdast-util-from-markdown": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.1.tgz", @@ -10115,6 +10288,114 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.0.0.tgz", + "integrity": "sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.0.0.tgz", + "integrity": "sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-hast": { "version": "13.2.0", "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", @@ -10135,6 +10416,25 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.0.tgz", + "integrity": "sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", @@ -10332,6 +10632,120 @@ "micromark-util-types": "^2.0.0" } }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.0.tgz", + "integrity": "sha512-Ub2ncQv+fwD70/l4ou27b4YzfNaCJOvyX4HxXU15m7mpYY+rjuWzsLIPZHJL253Z643RpbcP1oeIJlQ/SKW67g==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/micromark-factory-destination": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.0.tgz", @@ -11170,6 +11584,15 @@ "monaco-editor": "^0.44.0" } }, + "node_modules/ngx-simplemde": { + "version": "12.0.0", + "resolved": "https://registry.npmjs.org/ngx-simplemde/-/ngx-simplemde-12.0.0.tgz", + "integrity": "sha512-JDRl3hWcQhpMD6b9MUFnjI8RQD2FCtYYeSORZBYh9xKm4ETqXaNJp8xjo5bjs1cVd4/WN3IeHEXP1sw7zjTsnw==", + "dependencies": { + "simplemde-antd": "^1.0.0", + "tslib": "^2.1.0" + } + }, "node_modules/ngx-timeago": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ngx-timeago/-/ngx-timeago-3.0.0.tgz", @@ -11909,11 +12332,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/parchment": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parchment/-/parchment-3.0.0.tgz", - "integrity": "sha512-HUrJFQ/StvgmXRcQ1ftY6VEZUq3jA2t9ncFN4F84J/vN0/FPpQF+8FKXb3l6fLces6q0uOHj6NJn+2xvZnxO6A==" - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -12553,38 +12971,6 @@ "node": ">=8" } }, - "node_modules/quill": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/quill/-/quill-2.0.2.tgz", - "integrity": "sha512-QfazNrhMakEdRG57IoYFwffUIr04LWJxbS/ZkidRFXYCQt63c1gK6Z7IHUXMx/Vh25WgPBU42oBaNzQ0K1R/xw==", - "dependencies": { - "eventemitter3": "^5.0.1", - "lodash-es": "^4.17.21", - "parchment": "^3.0.0", - "quill-delta": "^5.1.0" - }, - "engines": { - "npm": ">=8.2.3" - } - }, - "node_modules/quill-delta": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/quill-delta/-/quill-delta-5.1.0.tgz", - "integrity": "sha512-X74oCeRI4/p0ucjb5Ma8adTXd9Scumz367kkMK5V/IatcX6A0vlgLgKbzXWy5nZmCGeNJm2oQX0d2Eqj+ZIlCA==", - "dependencies": { - "fast-diff": "^1.3.0", - "lodash.clonedeep": "^4.5.0", - "lodash.isequal": "^4.5.0" - }, - "engines": { - "node": ">= 12.0.0" - } - }, - "node_modules/quill/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -13050,6 +13436,23 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-gfm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.0.tgz", + "integrity": "sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-gfm": "^3.0.0", + "micromark-extension-gfm": "^3.0.0", + "remark-parse": "^11.0.0", + "remark-stringify": "^11.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark-parse": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", @@ -13081,6 +13484,20 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/remark-stringify": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", + "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-to-markdown": "^2.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -13812,6 +14229,16 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/simplemde-antd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/simplemde-antd/-/simplemde-antd-1.0.0.tgz", + "integrity": "sha512-bffElhQ4SPCgEatU5dzAga6ozQFvAvQkFU4a4RFESOWV4FBKXSK4Itlbdo3tl2dyy5MaGm5OGra1dLPD7ulAaw==", + "dependencies": { + "codemirror": "*", + "codemirror-spell-checker": "*", + "marked": "*" + } + }, "node_modules/slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -14333,6 +14760,11 @@ "node": ">=0.10.0" } }, + "node_modules/style-mod": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz", + "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==" + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -14762,6 +15194,14 @@ "node": "^16.14.0 || >=18.0.0" } }, + "node_modules/turndown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", + "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", + "dependencies": { + "@mixmark-io/domino": "^2.2.0" + } + }, "node_modules/type-fest": { "version": "0.21.3", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", @@ -14888,6 +15328,11 @@ "node": ">=14.17" } }, + "node_modules/typo-js": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/typo-js/-/typo-js-1.2.4.tgz", + "integrity": "sha512-Oy/k+tFle5NAA3J/yrrYGfvEnPVrDZ8s8/WCwjUE75k331QyKIsFss7byQ/PzBmXLY6h1moRnZbnaxWBe3I3CA==" + }, "node_modules/ua-parser-js": { "version": "0.7.39", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.39.tgz", @@ -15886,6 +16331,11 @@ "tslib": "^2.3.1" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/src/dotnet/APIView/ClientSPA/package.json b/src/dotnet/APIView/ClientSPA/package.json index b37c19231..9b252cf6c 100644 --- a/src/dotnet/APIView/ClientSPA/package.json +++ b/src/dotnet/APIView/ClientSPA/package.json @@ -26,21 +26,23 @@ "jquery": "^3.7.1", "ngx-cookie-service": "17.1", "ngx-monaco-editor-v2": "^17.0.1", + "ngx-simplemde": "^12.0.0", "ngx-timeago": "^3.0.0", "ngx-ui-scroll": "^3.2.0", "primeicons": "^6.0.1", "primeng": "^17.1.0", - "quill": "^2.0.2", "reflect-metadata": "^0.2.2", "rehype-autolink-headings": "^7.1.0", "rehype-highlight": "^7.0.0", "rehype-raw": "^7.0.0", "rehype-slug": "^6.0.0", "rehype-stringify": "^10.0.0", + "remark-gfm": "^4.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", + "turndown": "^7.2.0", "unified": "^11.0.4", "zone.js": "~0.14.0" }, @@ -50,6 +52,7 @@ "@angular/compiler-cli": "^17.3.10", "@fortawesome/fontawesome-free": "^6.4.2", "@types/jasmine": "~4.3.0", + "@types/turndown": "^5.0.5", "jasmine-core": "~4.6.0", "karma": "~6.4.0", "karma-chrome-launcher": "~3.2.0", diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/conversations/conversations.component.scss b/src/dotnet/APIView/ClientSPA/src/app/_components/conversations/conversations.component.scss index b910b800b..f2b6c702b 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/conversations/conversations.component.scss +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/conversations/conversations.component.scss @@ -1,6 +1,10 @@ :host ::ng-deep { .p-timeline-event-opposite { - flex: 0 0 auto !important; + display: none; + } + + .p-timeline-event-separator { + margin-left: 3%; } .p-timeline .p-timeline-event-connector { diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/index-page/index-page.component.ts b/src/dotnet/APIView/ClientSPA/src/app/_components/index-page/index-page.component.ts index a3830e0cd..c9e68e235 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/index-page/index-page.component.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/index-page/index-page.component.ts @@ -1,5 +1,5 @@ import { Component } from '@angular/core'; -import { FirstReleaseApproval, Review } from 'src/app/_models/review'; +import { Review } from 'src/app/_models/review'; @Component({ selector: 'app-index-page', diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/review-nav/review-nav.component.ts b/src/dotnet/APIView/ClientSPA/src/app/_components/review-nav/review-nav.component.ts index 15cd5c255..68b51c603 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/review-nav/review-nav.component.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/review-nav/review-nav.component.ts @@ -13,7 +13,6 @@ export class ReviewNavComponent implements OnChanges { @Output() navTreeNodeIdEmitter : EventEmitter = new EventEmitter(); - isLoading: boolean = true; assetsPath : string = environment.assetsPath; diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.html b/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.html index de6984c3e..c1b3453e4 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.html +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.html @@ -15,7 +15,7 @@
Loading...
-
+
Sample-Revision Content Load Failed...
diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.scss b/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.scss index a4f2493d9..14fb8cba0 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.scss +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.scss @@ -36,6 +36,30 @@ } } } + + blockquote { + padding: 10px 20px; + margin: 0 0 20px; + border-left: 5px solid var(--border-color); + background-color: var(base-bg-color); + font-style: italic; + color: var(--base-text-color); + } + + table { + border-collapse: collapse; + width: 100%; + } + + th, td { + border: 1px solid var(--border-color); + padding: 8px; + text-align: left; + } + } + + .CodeMirror-wrap pre { + border: none !important; } .p-splitter-panel-nested { diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.ts b/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.ts index e4bbc0817..fc96fd3b9 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/samples-page/samples-page.component.ts @@ -1,5 +1,5 @@ -import { ChangeDetectorRef, Component, ComponentFactoryResolver, ElementRef, Injector, NgZone, Renderer2, ViewContainerRef } from '@angular/core'; -import { ActivatedRoute, NavigationEnd, Params, Router } from '@angular/router'; +import { ChangeDetectorRef, Component, ElementRef, Injector, Renderer2, SimpleChange, ViewContainerRef } from '@angular/core'; +import { ActivatedRoute, Params, Router } from '@angular/router'; import { MenuItem, MessageService } from 'primeng/api'; import { FileSelectEvent } from 'primeng/fileupload'; import { Subject, take, takeUntil } from 'rxjs'; @@ -18,6 +18,7 @@ import { APIRevisionsService } from 'src/app/_services/revisions/revisions.servi import { SamplesRevisionService } from 'src/app/_services/samples/samples.service'; import { UserProfileService } from 'src/app/_services/user-profile/user-profile.service'; import { CommentThreadComponent } from '../shared/comment-thread/comment-thread.component'; +import { CommentThreadUpdateAction, CommentUpdatesDto } from 'src/app/_dtos/commentThreadUpdateDto'; @Component({ selector: 'app-samples-page', @@ -102,10 +103,12 @@ export class SamplesPageComponent { } ngAfterViewChecked(): void { - if (this.samplesContent && this.commentsLoaded && !this.commentableRegionsAdded) { - this.addCommentableRegions(); - this.commentableRegionsAdded = true; - } + setTimeout(() => { + if (this.samplesContent && this.commentsLoaded && !this.commentableRegionsAdded) { + this.addCommentableRegions(); + this.commentableRegionsAdded = true; + } + }); } createSideMenu() { @@ -115,11 +118,6 @@ export class SamplesPageComponent { tooltip: 'API', command: () => this.openLatestAPIReivisonForReview() } - //{ - // icon: 'bi bi-clock-history', - // tooltip: 'Revisions', - // command: () => this.router.navigate([`/revision/${this.reviewId}`]) - //} ]; } @@ -455,6 +453,7 @@ export class SamplesPageComponent { this.renderer.addClass(commentThreadContainer, 'py-2'); const componentRef = this.viewContainerRef.createComponent(CommentThreadComponent, { injector: this.injector }); + if (commentThread) { componentRef.instance.codePanelRowData = commentThread; } else { @@ -504,11 +503,56 @@ export class SamplesPageComponent { }); }); + componentRef.instance.commentResolutionActionEmitter.subscribe((commentUpdates: any) => { + commentUpdates.reviewId = this.reviewId!; + if (commentUpdates.commentThreadUpdateAction === CommentThreadUpdateAction.CommentResolved) { + this.commentsService.resolveComments(this.reviewId!, commentUpdates.elementId!).pipe(take(1)).subscribe({ + next: () => { + const ct = this.applyCommentResolutionUpdate(commentThread!, commentUpdates); + componentRef.instance.ngOnChanges({ + codePanelRowData: new SimpleChange(null, ct, false) + }); + } + }); + } + if (commentUpdates.commentThreadUpdateAction === CommentThreadUpdateAction.CommentUnResolved) { + this.commentsService.unresolveComments(this.reviewId!, commentUpdates.elementId!).pipe(take(1)).subscribe({ + next: () => { + const ct = this.applyCommentResolutionUpdate(commentThread!, commentUpdates); + componentRef.instance.ngOnChanges({ + codePanelRowData: new SimpleChange(null, ct, false) + }); + } + }); + } + }); + + componentRef.instance.commentUpvoteActionEmitter.subscribe((commentUpdates: any) => { + this.commentsService.toggleCommentUpVote(this.reviewId!, commentUpdates.commentId!).pipe(take(1)).subscribe({ + next: () => { + const comment = commentThread!.comments!.filter(x => x.id == commentUpdates.commentId)[0]; + if (comment) { + if (comment.upvotes.includes(this.userProfile?.userName!)) { + commentThread!.comments!.filter(x => x.id == commentUpdates.commentId)[0].upvotes.splice(comment.upvotes.indexOf(this.userProfile?.userName!), 1); + } else { + commentThread!.comments!.filter(x => x.id == commentUpdates.commentId)[0].upvotes.push(this.userProfile?.userName!); + } + } + } + }); + }); + componentRef.instance.instanceLocation = 'samples'; this.renderer.appendChild(commentThreadContainer, componentRef.location.nativeElement); return commentThreadContainer; } + private applyCommentResolutionUpdate(commentThread: CodePanelRowData, commentUpdates: CommentUpdatesDto) : CodePanelRowData { + commentThread.isResolvedCommentThread = (commentUpdates.commentThreadUpdateAction === CommentThreadUpdateAction.CommentResolved)? true : false; + commentThread.commentThreadIsResolvedBy = commentUpdates.resolvedBy!; + return commentThread; + } + private removeCommentThread(title: string): void { this.el.nativeElement.querySelector(`.user-comment-thread[title="${title}"]`).remove(); const targetCommentIcon = this.el.nativeElement.querySelectorAll(`.line-actions[title="${title}"] > .toggle-user-comments-btn`); diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.html b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.html index 9a3ceaa2a..56e437e83 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.html +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.html @@ -15,10 +15,10 @@ {{ comment.createdOn | timeago }}
-
+
- +
@@ -51,7 +51,7 @@
- +
diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.scss b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.scss index fa3d25f77..968a28803 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.scss +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/comment-thread/comment-thread.component.scss @@ -97,6 +97,7 @@ .rendered-comment-content { overflow-wrap: anywhere; + white-space: normal; pre { max-width: 100%; white-space: pre-wrap; @@ -125,5 +126,24 @@ } } } + blockquote { + padding: 10px 20px; + margin: 0 0 20px; + border-left: 5px solid var(--border-color); + background-color: var(base-bg-color); + font-style: italic; + color: var(--base-text-color); + } + + table { + border-collapse: collapse; + width: 100%; + } + + th, td { + border: 1px solid var(--border-color); + padding: 8px; + text-align: left; + } } } \ No newline at end of file diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.html b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.html index db22c76d3..eaed3e382 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.html +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.html @@ -1,40 +1 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + \ No newline at end of file diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.scss b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.scss index cf7ac9a7f..ff3be2583 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.scss +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.scss @@ -1,5 +1,38 @@ :host ::ng-deep { - .p-editor-container .p-editor-toolbar.ql-snow .ql-picker.ql-expanded .ql-picker-options { + .CodeMirror-scroll { + min-height: 100px; + } + + .CodeMirror { + min-height: 100px; + border: 1px solid var(--border-color); + background-color: var(--editor-bg-color); + color: var(--base-text-color); + } + + .CodeMirror-guttermarker { + color: var(--base-text-color); + } + + .CodeMirror-cursor { + border-left: 1px solid var(--base-text-color); + } + + .editor-toolbar { + border: 1px solid var(--border-color); + } + + .editor-toolbar a { + color: var(--base-text-color) !important; + } + + .editor-toolbar a.active, .editor-toolbar a:hover { background: var(--base-bg-color); + border-color: var(--border-color); + } + + .editor-toolbar i.separator { + border-left: 1px solid #d9d9d9; + border-right: 1px solid var(--border-color); } } \ No newline at end of file diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.spec.ts b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.spec.ts index fb6d4e4b8..e69de29bb 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.spec.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.spec.ts @@ -1,28 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { EditorComponent } from './editor.component'; -import { EditorModule } from 'primeng/editor'; -import { FormsModule, ReactiveFormsModule } from '@angular/forms'; - -describe('EditorComponent', () => { - let component: EditorComponent; - let fixture: ComponentFixture; - - beforeEach(() => { - TestBed.configureTestingModule({ - declarations: [EditorComponent], - imports: [ - EditorModule, - ReactiveFormsModule, - FormsModule - ] - }); - fixture = TestBed.createComponent(EditorComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.ts b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.ts index 0ba48a000..e315761ce 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_components/shared/editor/editor.component.ts @@ -1,5 +1,5 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { EditorTextChangeEvent } from 'primeng/editor'; +import { SimplemdeOptions } from 'ngx-simplemde'; @Component({ selector: 'app-editor', @@ -10,13 +10,50 @@ export class EditorComponent { @Input() content: string = ''; @Input() editorId: string = ''; - @Output() contentEmitter : EventEmitter = new EventEmitter(); + editorOptions : SimplemdeOptions = { + autosave: { enabled: false }, + status: false, + renderingConfig: { + codeSyntaxHighlighting: true + }, + toolbar: [ + 'bold', 'italic', 'strikethrough', 'heading', '|', + 'code', 'quote', 'link', 'table', 'horizontal-rule', '|', + 'unordered-list', 'ordered-list' + ] + }; + + ngAfterViewInit() { + setTimeout(() => { + document.querySelectorAll('.editor-toolbar a').forEach((button: any) => { + if (button.classList.contains('smdi-bold')) { + button.setAttribute('title', 'Bold (Ctrl-B)'); + } else if (button.classList.contains('smdi-italic')) { + button.setAttribute('title', 'Italic (Ctrl-I)'); + } else if (button.classList.contains('smdi-strikethrough')) { + button.setAttribute('title', 'Strikethrough'); + } else if (button.classList.contains('smdi-header')) { + button.setAttribute('title', 'Heading (Ctrl-H)'); + } else if (button.classList.contains('smdi-code')) { + button.setAttribute('title', 'Code (Ctrl-Alt-C)'); + } else if (button.classList.contains('smdi-quote-left')) { + button.setAttribute('title', 'Quote (Ctrl-\')'); + } else if (button.classList.contains('smdi-link')) { + button.setAttribute('title', 'Link (Ctrl-K)'); + } else if (button.classList.contains('smdi-table')) { + button.setAttribute('title', 'Table'); + } else if (button.classList.contains('smdi-line')) { + button.setAttribute('title', 'Horizontal Rule'); + } else if (button.classList.contains('smdi-list-ul')) { + button.setAttribute('title', 'Unordered List (Ctrl-L)'); + } else if (button.classList.contains('smdi-list-ol')) { + button.setAttribute('title', 'Ordered List (Ctrl-Alt-L)'); + } + }); + }, 0); + } getEditorContent() : string { return this.content; } - - onTextChange(event: EditorTextChangeEvent) { - this.contentEmitter.emit(event.textValue); - } } \ No newline at end of file diff --git a/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/review-page-layout.module.ts b/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/review-page-layout.module.ts index 3612e7bcf..c8bdaf51a 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/review-page-layout.module.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/review-page-layout.module.ts @@ -14,7 +14,7 @@ import { RevisionOptionsComponent } from 'src/app/_components/revision-options/r import { SharedAppModule } from './shared-app.module'; import { CommonModule } from '@angular/common'; import { PageOptionsSectionComponent } from 'src/app/_components/shared/page-options-section/page-options-section.component'; -import { NavBarComponent } from 'src/app/_components/shared/nav-bar/nav-bar.component'; +import { HtmlToMarkdownPipe } from 'src/app/_pipes/html-to-markdown.pipe'; @NgModule({ declarations: [ @@ -25,6 +25,7 @@ import { NavBarComponent } from 'src/app/_components/shared/nav-bar/nav-bar.comp RevisionOptionsComponent, PageOptionsSectionComponent, MarkdownToHtmlPipe, + HtmlToMarkdownPipe, EditorComponent, ], exports: [ @@ -35,9 +36,9 @@ import { NavBarComponent } from 'src/app/_components/shared/nav-bar/nav-bar.comp ReviewPageLayoutComponent, RevisionOptionsComponent, MarkdownToHtmlPipe, + HtmlToMarkdownPipe, EditorComponent, SharedAppModule, - EditorModule, PanelModule, MenuModule, TimelineModule, @@ -46,7 +47,6 @@ import { NavBarComponent } from 'src/app/_components/shared/nav-bar/nav-bar.comp imports: [ CommonModule, SharedAppModule, - EditorModule, PanelModule, MenuModule, TimelineModule, diff --git a/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/shared-app.module.ts b/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/shared-app.module.ts index a7686561f..d8c59d868 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/shared-app.module.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_modules/shared/shared-app.module.ts @@ -21,6 +21,7 @@ import { FileUploadModule } from 'primeng/fileupload'; import { InputTextModule } from 'primeng/inputtext'; import { MessagesModule } from 'primeng/messages'; import { BadgeModule } from 'primeng/badge'; +import { SimplemdeModule } from 'ngx-simplemde'; @NgModule({ @@ -55,6 +56,7 @@ import { BadgeModule } from 'primeng/badge'; SidebarModule, TimeagoModule, InputTextModule, + SimplemdeModule ], imports: [ CommonModule, @@ -74,6 +76,7 @@ import { BadgeModule } from 'primeng/badge'; SidebarModule, InputTextModule, TimeagoModule.forRoot(), + SimplemdeModule.forRoot() ] }) export class SharedAppModule { } diff --git a/src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.spec.ts b/src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.spec.ts new file mode 100644 index 000000000..942d67c6f --- /dev/null +++ b/src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.spec.ts @@ -0,0 +1,8 @@ +import { HtmlToMarkdownPipe } from './html-to-markdown.pipe'; + +describe('HtmlToMarkdownPipe', () => { + it('create an instance', () => { + const pipe = new HtmlToMarkdownPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.ts b/src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.ts new file mode 100644 index 000000000..bb42a46c0 --- /dev/null +++ b/src/dotnet/APIView/ClientSPA/src/app/_pipes/html-to-markdown.pipe.ts @@ -0,0 +1,27 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import TurndownService from 'turndown'; + +@Pipe({ + name: 'htmlToMarkdown', +}) +export class HtmlToMarkdownPipe implements PipeTransform { + private turndownService: TurndownService; + + constructor() { + this.turndownService = new TurndownService(); + this.turndownService.keep(['u', 's', 'mark', 'span', 'div']); + } + + transform(html: string, escapeSpacialCharacters: boolean = true): string { + if (!escapeSpacialCharacters) { + this.turndownService.escape = (text: string) => text; + } + + try { + return this.turndownService.turndown(html); + } catch (error) { + console.error('Error converting HTML to Markdown:', error); + return ''; + } + } +} diff --git a/src/dotnet/APIView/ClientSPA/src/app/_pipes/markdown-to-html.pipe.ts b/src/dotnet/APIView/ClientSPA/src/app/_pipes/markdown-to-html.pipe.ts index 9c149425c..c9c28eeec 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_pipes/markdown-to-html.pipe.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_pipes/markdown-to-html.pipe.ts @@ -1,6 +1,7 @@ import { Pipe, PipeTransform } from '@angular/core'; import { unified } from 'unified'; import { visit } from 'unist-util-visit'; +import remarkGfm from 'remark-gfm'; import remarkParse from 'remark-parse'; import remarkRehype from 'remark-rehype'; import rehypeRaw from 'rehype-raw'; @@ -13,22 +14,27 @@ const NON_SPECIAL_CHARACTERS = /^[^a-zA-Z0-9]+$/; name: 'markdownToHtml' }) export class MarkdownToHtmlPipe implements PipeTransform { - transform(markdown: string): Promise { + transform(markdown: string, addLineActions: boolean = false): Promise { return new Promise((resolve, reject) => { - unified() - .use(remarkParse) - .use(remarkRehype, { allowDangerousHtml: true }) - .use(rehypeRaw) - .use(rehypeHighlight) - .use(rehypeAddLineActions) - .use(rehypeStringify) - .process(markdown) - .then((file) => { - resolve(String(file)); - }) - .catch((err) => { - reject(err); - }); + const processor = unified() + .use(remarkParse) + .use(remarkGfm) + .use(remarkRehype, { allowDangerousHtml: true }) + .use(rehypeRaw) + .use(rehypeHighlight); + + if (addLineActions) { + processor.use(rehypeAddLineActions); + } + + processor.use(rehypeStringify) + .process(markdown) + .then((file) => { + resolve(String(file)); + }) + .catch((err) => { + reject(err); + }); }); } } diff --git a/src/dotnet/APIView/ClientSPA/src/app/_services/revisions/revisions.service.ts b/src/dotnet/APIView/ClientSPA/src/app/_services/revisions/revisions.service.ts index b87895f1f..cb8dd231e 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_services/revisions/revisions.service.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_services/revisions/revisions.service.ts @@ -18,7 +18,7 @@ export class APIRevisionsService { constructor(private http: HttpClient, private configService: ConfigService) { } getLatestAPIRevision(reviewId: string): Observable { - return this.http.get(this.baseUrl + `/${reviewId}/latest`); + return this.http.get(this.baseUrl + `/${reviewId}/latest`, { withCredentials: true }); } getAPIRevisions(noOfItemsRead: number, pageSize: number, diff --git a/src/dotnet/APIView/ClientSPA/src/app/_services/samples/samples.service.ts b/src/dotnet/APIView/ClientSPA/src/app/_services/samples/samples.service.ts index 99ec48ef8..6b751275d 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/_services/samples/samples.service.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/_services/samples/samples.service.ts @@ -16,7 +16,7 @@ export class SamplesRevisionService { constructor(private http: HttpClient, private configService: ConfigService) { } getLatestSampleRevision(reviewId: string): Observable { - return this.http.get(this.baseUrl + `/${reviewId}/latest`); + return this.http.get(this.baseUrl + `/${reviewId}/latest`, { withCredentials: true }); } getSamplesRevisions(noOfItemsRead: number, pageSize: number, diff --git a/src/dotnet/APIView/ClientSPA/src/app/app.module.ts b/src/dotnet/APIView/ClientSPA/src/app/app.module.ts index 0c7cff5a3..c9929bc6a 100644 --- a/src/dotnet/APIView/ClientSPA/src/app/app.module.ts +++ b/src/dotnet/APIView/ClientSPA/src/app/app.module.ts @@ -41,7 +41,7 @@ export function initializeApp(configService: ConfigService) { TabMenuModule, ToolbarModule, ToastModule, - HttpClientModule, + HttpClientModule ], providers: [ ConfigService, diff --git a/src/dotnet/APIView/ClientSPA/src/styles.less b/src/dotnet/APIView/ClientSPA/src/styles.less new file mode 100644 index 000000000..3c7687d2f --- /dev/null +++ b/src/dotnet/APIView/ClientSPA/src/styles.less @@ -0,0 +1,8 @@ + +@import '../node_modules/ngx-simplemde/index.less'; + +@simplemde-icon-url: '//at.alicdn.com/t/font_700857_mnodkd1cp9l766r'; +@simplemde-statusbar-lines: 'Lines:'; +@simplemde-statusbar-words: 'words:'; +@simplemde-statusbar-characters: 'Characters:'; +@simplemde-statusbar-counts: 'Total Count:'; \ No newline at end of file diff --git a/src/dotnet/APIView/ClientSPA/src/styles.scss b/src/dotnet/APIView/ClientSPA/src/styles.scss index e01eba1cc..5a0395213 100644 --- a/src/dotnet/APIView/ClientSPA/src/styles.scss +++ b/src/dotnet/APIView/ClientSPA/src/styles.scss @@ -5,8 +5,6 @@ @import "primeng/resources/themes/bootstrap4-light-blue/theme.css"; @import "primeng/resources/primeng.css"; @import "primeicons/primeicons.css"; -@import "quill/dist/quill.core.css"; -@import "quill/dist/quill.snow.css"; @import "../../../APIView/APIViewWeb/Client/css/shared/theme-colors.scss"; @import "../../../APIView/APIViewWeb/Client/css/shared/bootstraps-overrides.scss";