Redesign Revision Select (#7687)
* Refactor Review Badge * Refactor Review Page UI * Adjust APIRevisions Page * APIRevisions Search and Filter * Updated to Revisions Context Blade * Add APIRevision Functioning * Add RequestVerificationToken for APIRevisionDelete * Refinde APIRevision Context * Refine APIRevision Context * Improvements to Revisions Page * Update to APIREvisions Page * Update to Samples Page * Rename and Delete Samples * Add conversiation info badge
This commit is contained in:
Родитель
77b852436b
Коммит
3c08b3d0ec
|
@ -1,13 +1,11 @@
|
|||
@import "../shared/mixins.scss";
|
||||
|
||||
#conversation-main-container {
|
||||
@include fixed-page-heights;
|
||||
color: var(--base-text-color);
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
@include main-content-container;
|
||||
}
|
||||
|
||||
.conversiation-center {
|
||||
overflow: auto;
|
||||
color: var(--base-text-color);
|
||||
height: calc(100vh - 145px);
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@
|
|||
|
||||
#index-offcanvas-menu-content {
|
||||
padding: 130px 60px 10px 20px;
|
||||
min-height: calc(100vh - 40px);
|
||||
max-height: calc(100vh - 40px);
|
||||
min-height: calc(100vh - 30px);
|
||||
max-height: calc(100vh - 30px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,35 +1,19 @@
|
|||
@import "../shared/mixins.scss";
|
||||
|
||||
#review-info-bar > .SumoSelect:nth-of-type(even) {
|
||||
width: 20%;
|
||||
#review-info-bar {
|
||||
font-size: small;
|
||||
background-color: var(--base-fg-color);
|
||||
}
|
||||
|
||||
#review-info-bar > .SumoSelect:nth-of-type(odd) {
|
||||
width: 10%;
|
||||
}
|
||||
|
||||
#revision-select ~ .optWrapper {
|
||||
width: auto;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
#diff-select ~ .optWrapper {
|
||||
width: auto;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
#revision-select {
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
#diff-select {
|
||||
width: 20%;
|
||||
.breadcrumb .icon-language {
|
||||
min-height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
#review-left {
|
||||
max-width: none;
|
||||
min-width: 10px;
|
||||
height: calc(100vh - 220px);
|
||||
height: calc(100vh - 120px);
|
||||
overflow: auto;
|
||||
max-height: 100vh;
|
||||
padding: 5px 0px 5px 10px;
|
||||
|
@ -43,7 +27,7 @@
|
|||
#review-right {
|
||||
max-width: 100%;
|
||||
min-width: 100px;
|
||||
height: calc(100vh - 220px);
|
||||
height: calc(100vh - 120px);
|
||||
padding: 0px;
|
||||
overflow: auto;
|
||||
background-color: var(--base-fg-color);
|
||||
|
@ -51,17 +35,8 @@
|
|||
contain: size layout paint;
|
||||
}
|
||||
|
||||
#review-offcanvas-menu-content {
|
||||
padding: 10px 20px 10px 20px;
|
||||
min-height: calc(100vh - 190px);
|
||||
max-height: calc(100vh - 190px);
|
||||
overflow-y: auto;
|
||||
margin-top: 150px;
|
||||
}
|
||||
|
||||
.review-approved {
|
||||
border: solid 2px var(--success-color);
|
||||
box-shadow: var(--box-shadow-success);
|
||||
@include review-approval-border;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,61 @@
|
|||
@import "../shared/mixins.scss";
|
||||
|
||||
#add-revision-button {
|
||||
@include bottom-right-floating;
|
||||
@include btn-circle;
|
||||
@include btn-circle-xl;
|
||||
#revisions-main-container {
|
||||
@include main-content-container;
|
||||
|
||||
.revisions-list-container {
|
||||
.card {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
box-shadow: var(--box-shadow-link) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#revisions-main-container {
|
||||
@include fixed-page-heights;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
.revisions-list-container {
|
||||
overflow: auto;
|
||||
height: 78dvh;
|
||||
|
||||
.revision-actions {
|
||||
align-self: center;
|
||||
margin-right: 15px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.revision-indicator-checks, .revision-actions {
|
||||
align-self: center;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
flex-direction: row;
|
||||
overflow: hidden;
|
||||
background-color: var(--base-fg-color);
|
||||
|
||||
.card-body {
|
||||
padding: 0.5rem 0.75rem;
|
||||
font-size: small;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.edit-revision-label {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
|
||||
.card.True {
|
||||
@include review-approval-border;
|
||||
}
|
||||
}
|
||||
|
||||
.revisions-list-container > .card:hover {
|
||||
.revision-actions {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
|
@ -1,19 +1,20 @@
|
|||
@import "../shared/mixins.scss";
|
||||
|
||||
#add-sample-button {
|
||||
@include bottom-right-floating;
|
||||
@include btn-circle;
|
||||
@include btn-circle-xl;
|
||||
#samples-main-container {
|
||||
@include main-content-container;
|
||||
}
|
||||
|
||||
#samples-main-container {
|
||||
@include fixed-page-heights;
|
||||
padding-right: 0px;
|
||||
padding-left: 0px;
|
||||
#edit-samples-context, #upload-samples-context {
|
||||
@include offcanvas-context-large
|
||||
}
|
||||
|
||||
.samples-center {
|
||||
overflow: auto;
|
||||
height: calc(100vh - 120px);
|
||||
padding: 0px;
|
||||
background-color: var(--base-fg-color);
|
||||
scroll-behavior: smooth;
|
||||
contain: size layout paint;
|
||||
}
|
||||
|
||||
.usage-sample + .border + .rounded {
|
||||
|
@ -33,4 +34,10 @@
|
|||
|
||||
.usage-sample .internal {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-samples-content {
|
||||
textarea {
|
||||
height: 60dvh;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@
|
|||
.btn-check:focus + .btn-outline-primary, .btn-outline-primary:focus {
|
||||
box-shadow: var(--box-shadow-link);
|
||||
}
|
||||
.btn-check:focus + .btn, .btn:focus {
|
||||
box-shadow: var(--box-shadow-link);
|
||||
}
|
||||
|
||||
.page-link {
|
||||
background-color: var(--base-fg-color);
|
||||
|
@ -91,6 +94,14 @@
|
|||
border: 1px solid var(--border-color) !important;
|
||||
}
|
||||
|
||||
.border-start {
|
||||
border-left: 1px solid var(--border-color) !important;
|
||||
}
|
||||
|
||||
.border-end {
|
||||
border-right: 1px solid var(--border-color) !important;
|
||||
}
|
||||
|
||||
.border-top {
|
||||
border-top: 1px solid var(--border-color) !important;
|
||||
}
|
||||
|
@ -99,6 +110,21 @@
|
|||
border-bottom: 1px solid var(--border-color) !important;
|
||||
}
|
||||
|
||||
.breadcrumb {
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
.breadcrumb-item + .breadcrumb-item::before {
|
||||
margin-top: 0rem;
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item::before {
|
||||
padding-right: 0.25rem;
|
||||
}
|
||||
|
||||
.breadcrumb-item + .breadcrumb-item {
|
||||
padding-left: 0.25rem;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
color: var(--base-text-color);
|
||||
background-color: var(--base-fg-color);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.icon-language {
|
||||
min-height: 34px;
|
||||
width: 34px;
|
||||
min-height: 31px;
|
||||
width: 31px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
@ -165,67 +165,67 @@
|
|||
|
||||
.icon-csharp {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/csharp-original.svg) center center no-repeat;
|
||||
background: url(/icons/csharp-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-javascript {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/javascript-original.svg) center center no-repeat;
|
||||
background: url(/icons/javascript-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-python {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/python-original.svg) center center no-repeat;
|
||||
background: url(/icons/python-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-c {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/c-original.svg) center center no-repeat;
|
||||
background: url(/icons/c-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-cplusplus {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/cplusplus-original.svg) center center no-repeat;
|
||||
background: url(/icons/cplusplus-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-go {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/go-original.svg) center center no-repeat;
|
||||
background: url(/icons/go-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-java {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/java-original.svg) center center no-repeat;
|
||||
background: url(/icons/java-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-java-spring {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/java-spring-original.svg) center center no-repeat;
|
||||
background: url(/icons/java-spring-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-java-android {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/java-android-original.svg) center center no-repeat;
|
||||
background: url(/icons/java-android-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-swift {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/swift-original.svg) center center no-repeat;
|
||||
background: url(/icons/swift-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-kotlin {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/kotlin-original.svg) center center no-repeat;
|
||||
background: url(/icons/kotlin-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-json {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/json-original.svg) center center no-repeat;
|
||||
background: url(/icons/json-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-swagger {
|
||||
@extend .icon-language;
|
||||
background: url(/icons/swagger-original.svg) center center no-repeat;
|
||||
background: url(/icons/swagger-original.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-comments {
|
||||
|
@ -236,9 +236,9 @@
|
|||
}
|
||||
|
||||
.icon-chevron-right {
|
||||
background: url(/icons/chevron-right.svg) center center no-repeat;
|
||||
background: url(/icons/chevron-right.svg) center/contain no-repeat;
|
||||
}
|
||||
|
||||
.icon-chevron-up {
|
||||
background: url(/icons/chevron-up.svg) center center no-repeat;
|
||||
background: url(/icons/chevron-up.svg) center/contain no-repeat;
|
||||
}
|
|
@ -77,8 +77,8 @@ html {
|
|||
bottom: 0;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
z-index: 3;
|
||||
background: var(--base-bg-color);
|
||||
}
|
||||
|
@ -93,6 +93,11 @@ html {
|
|||
color: var(--link-active);
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding-top: 0rem;
|
||||
padding-bottom: 0rem;
|
||||
}
|
||||
|
||||
.rounded-1 {
|
||||
border-radius: 3px !important;
|
||||
}
|
||||
|
@ -144,6 +149,8 @@ input[type="search"]::-webkit-search-cancel-button {
|
|||
.main-nav-cst-theme {
|
||||
background-color: var(--navbar-bg);
|
||||
color: var(--navbar-text);
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
|
||||
a:hover {
|
||||
text-decoration: none;
|
||||
|
@ -193,11 +200,11 @@ input[type="search"]::-webkit-search-cancel-button {
|
|||
color: var(--primary-btn-color);
|
||||
}
|
||||
|
||||
.tooltip.bs-tooltip-right .tooltip-arrow::before {
|
||||
.tooltip.bs-tooltip-end .tooltip-arrow::before {
|
||||
border-right-color: var(--primary-color) !important;
|
||||
}
|
||||
|
||||
.tooltip.bs-tooltip-left .tooltip-arrow::before {
|
||||
.tooltip.bs-tooltip-start .tooltip-arrow::before {
|
||||
border-left-color: var(--primary-color) !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,16 +22,33 @@
|
|||
box-shadow: var(--box-shadow-sm);
|
||||
}
|
||||
|
||||
@mixin fixed-page-heights {
|
||||
height: calc(100vh - 190px);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@mixin main-content-container {
|
||||
transition: margin-right .5s;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
@mixin review-offcanvas-menu-content {
|
||||
min-height: calc(100vh - 100px);
|
||||
max-height: calc(100vh - 100px);
|
||||
overflow-y: auto;
|
||||
margin-top: 70px;
|
||||
}
|
||||
|
||||
@mixin review-approval-border {
|
||||
border: solid 2px var(--success-color);
|
||||
box-shadow: var(--box-shadow-success);
|
||||
}
|
||||
|
||||
@mixin offcanvas-context-large {
|
||||
width: 50dvw;
|
||||
background-color: var(--base-bg-color);
|
||||
}
|
||||
|
||||
@mixin offcanvas-context-small {
|
||||
width: 30dvw;
|
||||
background-color: var(--base-bg-color);
|
||||
}
|
||||
|
||||
@mixin placeholder {
|
||||
::-webkit-input-placeholder {
|
||||
@content;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import "../shared/mixins.scss";
|
||||
|
||||
.offcanvas-menu {
|
||||
height: 100vh;
|
||||
width: 0;
|
||||
|
@ -16,15 +18,76 @@
|
|||
right: 0;
|
||||
}
|
||||
|
||||
.offcanvas-menu-content {
|
||||
.left-offcanvas {
|
||||
@extend .offcanvas-menu;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.right-offcanvas-menu-content {
|
||||
border-left: 1px solid var(--border-color) !important;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
|
||||
.left-offcanvas-menu-content {
|
||||
border-right: 1px solid var(--border-color) !important;
|
||||
transform: translate3d(0, 0, 0);
|
||||
|
||||
.badge {
|
||||
font-size: 0.55em;
|
||||
top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
#right-offcanvas-menu-content {
|
||||
padding: 10px 20px 10px 20px;
|
||||
@include review-offcanvas-menu-content;
|
||||
}
|
||||
|
||||
#left-offcanvas-menu-content {
|
||||
padding: 10px 0px 10px 5px;
|
||||
@include review-offcanvas-menu-content;
|
||||
|
||||
.btn-check:focus + .btn, .btn:focus {
|
||||
box-shadow: var(--box-shadow-left);
|
||||
}
|
||||
|
||||
.btn {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
.btn.active {
|
||||
box-shadow: var(--box-shadow-left);
|
||||
}
|
||||
}
|
||||
|
||||
#review-right-offcanvas-toggle, #samples-right-offcanvas-toggle, #revisions-right-offcanvas-toggle {
|
||||
+ .btn-sm {
|
||||
padding: 0.05rem 0.4rem;
|
||||
font-size: 0.775rem;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
#apiRevisions-context, #samplesRevisions-context {
|
||||
@include offcanvas-context-large
|
||||
}
|
||||
|
||||
#add-apirevision-context {
|
||||
@include offcanvas-context-small
|
||||
}
|
||||
|
||||
.move-main-content-container-left {
|
||||
margin-right: 340px;
|
||||
}
|
||||
|
||||
.show-offcanvas {
|
||||
.move-main-content-container-right {
|
||||
margin-left: 60px;
|
||||
}
|
||||
|
||||
.show-right-offcanvas {
|
||||
width: 340px;
|
||||
}
|
||||
|
||||
.show-left-offcanvas {
|
||||
width: 60px;
|
||||
}
|
|
@ -30,6 +30,7 @@
|
|||
--box-shadow-inset: inset 0 1px 2px #{rgba($black, .075)};
|
||||
--box-shadow-success: 0 0 0 0.1rem #{rgba($success, 10%)};
|
||||
--box-shadow-link: 0 0 0 0.2rem #{rgba($primary, 50%)};
|
||||
--box-shadow-left: -5px 0px 0px 0rem #{rgba($primary, 100%)};
|
||||
/*----Nav--------------------------------------------------------*/
|
||||
--navbar-bg: #{tint-color($base-bg-color, 100%)};
|
||||
--navbar-text: #{$base-text-color};
|
||||
|
@ -84,6 +85,7 @@
|
|||
--box-shadow-inset: inset 0 1px 2px #{rgba($white, .075)};
|
||||
--box-shadow-success: 0 0 0 0.1rem #{rgba($success, 10%)};
|
||||
--box-shadow-link: 0 0 0 0.2rem #{rgba($primary-color, 50%)};
|
||||
--box-shadow-left: -5px 0px 0px 0rem #{rgba($primary-color, 100%)};
|
||||
/*----Nav--------------------------------------------------------*/
|
||||
--navbar-bg: #{tint-color($base-bg-color, 20%)};
|
||||
--navbar-text: #{tint-color($base-text-color, 40%)};
|
||||
|
@ -140,6 +142,7 @@
|
|||
--box-shadow-inset: inset 0 1px 2px #{rgba($gray-100, .075)};
|
||||
--box-shadow-success: 0 0 0 0.1rem #{rgba($success, 10%)};
|
||||
--box-shadow-link: 0 0 0 0.2rem #{rgba($primary-color, 50%)};
|
||||
--box-shadow-left: -5px 0px 0px 0rem #{rgba($primary-color, 100%)};
|
||||
/*----Nav--------------------------------------------------------*/
|
||||
--navbar-bg: #{tint-color($base-bg-color, 20%)};
|
||||
--navbar-text: #{tint-color($base-text-color, 40%)};
|
||||
|
|
|
@ -6,5 +6,6 @@ import "./pages/index.ts";
|
|||
import "./pages/review.ts";
|
||||
import "./pages/revisions.ts";
|
||||
import "./pages/user-profile.ts";
|
||||
import "./pages/samples.ts";
|
||||
|
||||
|
||||
|
|
|
@ -490,20 +490,6 @@ export function addClickEventToClassesInSections() {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Select Event Handlers to API Revision Select
|
||||
*/
|
||||
export function addSelectEventToAPIRevisionSelect() {
|
||||
$('#revision-select, #diff-select').each(function (index, value) {
|
||||
$(this).on('change', function () {
|
||||
var url = $(this).find(":selected").val();
|
||||
if (url) {
|
||||
window.location.href = url as string;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if targetAnchor is present, if its not present, expand the section and scroll to the targetAnchor
|
||||
* @param { String } uriHash the hash/id of the anchor we are looking for
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import { rightOffCanvasNavToggle } from "../shared/off-canvas";
|
||||
|
||||
import * as rvM from "./review.module"
|
||||
|
@ -18,12 +17,6 @@ $(() => {
|
|||
|
||||
// Run when document is ready
|
||||
$(function() {
|
||||
// Enable SumoSelect
|
||||
(<any>$("#revision-select")).SumoSelect({ search: true, searchText: 'Search Revisions...' });
|
||||
(<any>$("#diff-select")).SumoSelect({ search: true, searchText: 'Search Revisons for Diff...' });
|
||||
(<any>$("#revision-type-select")).SumoSelect();
|
||||
(<any>$("#diff-revision-type-select")).SumoSelect();
|
||||
|
||||
// Update codeLine Section state after page refresh
|
||||
const shownSectionHeadingLineNumbers = sessionStorage.getItem("shownSectionHeadingLineNumbers");
|
||||
|
||||
|
@ -34,7 +27,6 @@ $(() => {
|
|||
|
||||
// Scroll ids into view for Ids hidden in collapsed sections
|
||||
const uriHash = location.hash;
|
||||
console.log(`Initial uriHash: ${uriHash}`);
|
||||
if (uriHash) {
|
||||
let targetAnchorId = uriHash.replace('#', '');
|
||||
targetAnchorId = decodeURIComponent(targetAnchorId);
|
||||
|
@ -165,45 +157,6 @@ $(() => {
|
|||
$(this).get(0).scrollIntoView({ block: "center"});
|
||||
});
|
||||
|
||||
/* DROPDOWN FILTER FOR REVIEW, REVISIONS AND DIFF (UPDATES REVIEW PAGE ON CHANGE)
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
rvM.addSelectEventToAPIRevisionSelect();
|
||||
|
||||
$('#revision-type-select, #diff-revision-type-select').each(function(index, value) {
|
||||
$(this).on('change', function () {
|
||||
const pageIds = hp.getReviewAndRevisionIdFromUrl(window.location.href);
|
||||
const reviewId = pageIds["reviewId"];
|
||||
const apiRevisionId = pageIds["revisionId"];
|
||||
|
||||
const select = (index == 0) ? $('#revision-select') : $('#diff-select');
|
||||
const text = (index == 0) ? 'Revisions' : 'Revisions for Diff';
|
||||
|
||||
let uri = (index == 0) ? '?handler=APIRevisionsPartial' : '?handler=APIDiffRevisionsPartial';
|
||||
uri = uri + `&reviewId=${reviewId}`;
|
||||
uri = uri + `&apiRevisionId=${apiRevisionId}`;
|
||||
uri = uri + '&apiRevisionType=' + $(this).find(":selected").val();
|
||||
|
||||
$.ajax({
|
||||
url: uri
|
||||
}).done(function (partialViewResult) {
|
||||
console.log(partialViewResult);
|
||||
const id = select.attr('id');
|
||||
const selectUpdate = $(`<select placeholder="Select ${text}..." id="${id}" aria-label="${text} Select"></select>`);
|
||||
selectUpdate.html(partialViewResult);
|
||||
select.parent().replaceWith(selectUpdate);
|
||||
(<any>$(`#${id}`)).SumoSelect({ placeholder: `Select ${text}...`, search: true, searchText: `Search ${text}...` })
|
||||
|
||||
// Disable Diff Revision Select until a revision is selected
|
||||
if (index == 0)
|
||||
{
|
||||
(<any>$('#diff-revision-type-select')[0]).sumo.disable();
|
||||
(<any>$('#diff-select')[0]).sumo.disable();
|
||||
}
|
||||
rvM.addSelectEventToAPIRevisionSelect();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/* BUTTON FOR REQUEST REVIEW (CHANGES BETWEEN REQUEST ALL AND REQUEST SELECTED IN THE REQUEST APPROVAL SECTION)
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
$('.selectReviewerForRequest').on("click", function () {
|
||||
|
|
|
@ -1,19 +1,336 @@
|
|||
import * as hp from "../shared/helpers";
|
||||
import { rightOffCanvasNavToggle } from "../shared/off-canvas";
|
||||
|
||||
|
||||
$(() => {
|
||||
$(document).on("click", ".revision-rename-icon", e => {
|
||||
toggleNameField($(e.target));
|
||||
});
|
||||
|
||||
$(document).on("click", ".cancel-revision-rename", e => {
|
||||
var icon = $(e.target).parent().siblings(".revision-rename-icon");
|
||||
toggleNameField(icon);
|
||||
});
|
||||
|
||||
$(document).on("click", ".submit-revision-rename", e => {
|
||||
$(e.target).parents(".revision-rename-form").submit();
|
||||
});
|
||||
const apiRevisionsSearchBox = $("#apiRevisions-search");
|
||||
const samplesRevisionsSearchBox = $("#samplesRevisions-search");
|
||||
const apiRevisionsSearchContext = $(".api-revisions.revisions-list-container .card-body");
|
||||
const samplesRevisionsSearchContext = $(".samples-revisions.revisions-list-container .card-body");
|
||||
const apiRevisionTypeFilter = ["#manual-apirevisions-check", "#automatic-apirevisions-check", "#pullrequest-apirevisions-check"];
|
||||
|
||||
function toggleNameField(renameIcon: JQuery) {
|
||||
renameIcon.toggle();
|
||||
renameIcon.siblings(".revision-name-input").toggle();
|
||||
}
|
||||
|
||||
function makeActiveAPIRevisionEventHandler(event) {
|
||||
const trigger = $(event.currentTarget);
|
||||
let context = "api"; // Can be API or Sample
|
||||
let classSelect = ".bi.bi-clock-history";
|
||||
let classTxt = "bi bi-clock-history";
|
||||
if (trigger.find(".bi.bi-puzzle").length > 0) {
|
||||
context = "sample";
|
||||
classSelect = ".bi.bi-puzzle";
|
||||
classTxt = "bi bi-puzzle";
|
||||
}
|
||||
|
||||
const activeCard = $(`.revisions-list-container ${classSelect}.active-rev`).closest(".card");
|
||||
activeCard.find(`${classSelect}.active-rev`).remove();
|
||||
if (context == "api") {
|
||||
activeCard.find(".btn-group").prepend(`<button type="button" class="btn btn-sm btn-outline-primary make-diff" data-bs-toggle="tooltip" title="Make Diff"><i class="bi bi-file-diff mr-1"></i></button>`);
|
||||
}
|
||||
activeCard.find(".btn-group").prepend(`<button type="button" class="btn btn-sm btn-outline-primary make-active" data-bs-toggle="tooltip" title="Make Active"><i class="${classTxt} mr-1"></i></button>`);
|
||||
|
||||
activeCard.find(".btn-group .make-active").on("click", makeActiveAPIRevisionEventHandler);
|
||||
if (context == "api") {
|
||||
activeCard.find(".btn-group .make-diff").on("click", makeDiffAPIRevisionEventHandler);
|
||||
}
|
||||
|
||||
trigger.closest(".card").children(".revision-indicator-checks").append(`<i class="${classTxt} active-rev mr-1"></i>`);
|
||||
trigger.siblings(".make-diff").remove();
|
||||
trigger.remove();
|
||||
$(".revisions-list-container").addClass("revisions-changed");
|
||||
$(".tooltip").remove();
|
||||
}
|
||||
|
||||
function makeDiffAPIRevisionEventHandler(event) {
|
||||
const trigger = $(event.currentTarget);
|
||||
const diffCard = $(".revisions-list-container .bi.bi-file-diff.diff-rev").closest(".card");
|
||||
diffCard.find(".bi.bi-file-diff.diff-rev").remove();
|
||||
diffCard.find(".btn-group").prepend(`<button type="button" class="btn btn-sm btn-outline-primary make-diff" data-bs-toggle="tooltip" title="Make Diff"><i class="bi bi-file-diff mr-1"></i></button>`);
|
||||
diffCard.find(".btn-group").prepend(`<button type="button" class="btn btn-sm btn-outline-primary make-active" data-bs-toggle="tooltip" title="Make Active"><i class="bi bi-clock-history mr-1"></i></button>`);
|
||||
|
||||
diffCard.find(".btn-group .make-active").on("click", makeActiveAPIRevisionEventHandler);
|
||||
diffCard.find(".btn-group .make-diff").on("click", makeDiffAPIRevisionEventHandler);
|
||||
|
||||
trigger.closest(".card").children(".revision-indicator-checks").append(`<i class="bi bi-file-diff diff-rev mr-1"></i>`);
|
||||
trigger.siblings(".make-active").remove();
|
||||
trigger.remove();
|
||||
$(".revisions-list-container").addClass("revisions-changed");
|
||||
$(".tooltip").remove();
|
||||
}
|
||||
|
||||
function clearDiffAPIRevisionEventHandler(event) {
|
||||
const trigger = $(event.currentTarget);
|
||||
const diffCard = $(".revisions-list-container .bi.bi-file-diff.diff-rev").closest(".card");
|
||||
diffCard.find(".bi.bi-file-diff.diff-rev").remove();
|
||||
trigger.closest(".btn-group").prepend(`<button type="button" class="btn btn-sm btn-outline-primary make-diff" data-bs-toggle="tooltip" title="Make Diff"><i class="bi bi-file-diff mr-1"></i></button>`);
|
||||
trigger.closest(".btn-group").prepend(`<button type="button" class="btn btn-sm btn-outline-primary make-active" data-bs-toggle="tooltip" title="Make Active"><i class="bi bi-clock-history mr-1"></i></button>`);
|
||||
|
||||
diffCard.find(".btn-group .make-active").on("click", makeActiveAPIRevisionEventHandler);
|
||||
diffCard.find(".btn-group .make-diff").on("click", makeDiffAPIRevisionEventHandler);
|
||||
trigger.remove();
|
||||
$(".revisions-list-container").addClass("revisions-changed");
|
||||
$(".tooltip").remove();
|
||||
}
|
||||
|
||||
function exitAPIRevisionRename(apiRevisionCard) {
|
||||
apiRevisionCard.find(".card-title").removeClass("d-none");
|
||||
apiRevisionCard.find(".card-subtitle").removeClass("d-none");
|
||||
apiRevisionCard.find(".edit-revision-label").addClass("d-none");
|
||||
}
|
||||
|
||||
function handleShownRevisionContext(context) {
|
||||
$("#left-offcanvas-menu-content").find('[data-bs-original-title="API"]').removeClass("active");
|
||||
$("#left-offcanvas-menu-content").find('[data-bs-original-title="Samples"]').removeClass("active");
|
||||
$("#left-offcanvas-menu-content").find(`[data-bs-target="${context}"]`).addClass("active");
|
||||
if (context == "#apiRevisions-context" || context == "#samplesRevisions-context") {
|
||||
$(".revisions-list-container").removeClass("revisions-changed");
|
||||
}
|
||||
}
|
||||
|
||||
function handleHiddenRevisionContext(context) {
|
||||
if (context == "#apiRevisions-context" || context == "#add-apirevision-context") {
|
||||
$("#left-offcanvas-menu-content").find('[data-bs-original-title="API"]').addClass("active");
|
||||
}
|
||||
|
||||
if (context == "#samplesRevisions-context") {
|
||||
$("#left-offcanvas-menu-content").find('[data-bs-original-title="Samples"]').addClass("active");
|
||||
}
|
||||
$("#left-offcanvas-menu-content").find(`[data-bs-target="${context}"]`).removeClass("active");
|
||||
}
|
||||
|
||||
function handleHideRevisionContext(context) {
|
||||
let classSelect = ".bi.bi-clock-history";
|
||||
if (context == "#samplesRevisions-context") {
|
||||
classSelect = ".bi.bi-puzzle";
|
||||
}
|
||||
$(context).on("hide.bs.offcanvas", function (event) {
|
||||
const activeRevisionId = $(`.revisions-list-container ${classSelect}.active-rev`).closest(".card").attr("data-id");
|
||||
let diffRevisionId = "";
|
||||
const diffIcon = $(".revisions-list-container .bi.bi-file-diff.diff-rev");
|
||||
if (diffIcon.length > 0) {
|
||||
diffRevisionId = diffIcon.closest(".card").attr("data-id")!;
|
||||
}
|
||||
|
||||
const url = new URL(window.location.href);
|
||||
const currRevisionId = hp.getReviewAndRevisionIdFromUrl(url.href)["revisionId"];
|
||||
|
||||
if (!currRevisionId || url.searchParams.has("revisionId")) {
|
||||
url.searchParams.set("revisionId", activeRevisionId!);
|
||||
}
|
||||
else {
|
||||
url.pathname = url.pathname.replace(currRevisionId, activeRevisionId!);
|
||||
}
|
||||
|
||||
if (diffRevisionId) {
|
||||
url.searchParams.set("diffRevisionId", diffRevisionId!);
|
||||
}
|
||||
else {
|
||||
url.searchParams.delete("diffRevisionId");
|
||||
}
|
||||
|
||||
if ($(".revisions-list-container").hasClass("revisions-changed")) {
|
||||
if (window.location.href != url.href) {
|
||||
window.location.href = url.href;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function searchRevisions(searchBox, searchContext) {
|
||||
const searchText = (searchBox.val() as string).toUpperCase();
|
||||
(<any>searchContext.closest(".card").show()).unmark();
|
||||
|
||||
if (searchText) {
|
||||
(<any>searchContext).mark(searchText, {
|
||||
done: function () {
|
||||
searchContext.not(":has(mark)").closest(".card").hide();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
function deleteRevisions(target) {
|
||||
const id = hp.getReviewAndRevisionIdFromUrl(window.location.href)["reviewId"];
|
||||
const revisionCard = $(target).closest(".card");
|
||||
const revisionsId = revisionCard.attr("data-id");
|
||||
var antiForgeryToken = $("input[name=__RequestVerificationToken]").val();
|
||||
let url = `/Assemblies/Revisions/${id}/${revisionsId}`;
|
||||
|
||||
let ajax = {
|
||||
type: "DELETE",
|
||||
headers: {
|
||||
"RequestVerificationToken": antiForgeryToken as string
|
||||
},
|
||||
success: function () {
|
||||
revisionCard.remove();
|
||||
}
|
||||
};
|
||||
|
||||
if ($(target).closest(".revisions-list-container").hasClass("samples-revisions")) {
|
||||
url = `/Assemblies/Samples/${id}/${revisionsId}?handler=Upload`;
|
||||
const data = {
|
||||
Deleting: true,
|
||||
ReviewId: id,
|
||||
SampleId: revisionsId
|
||||
};
|
||||
ajax["data"] = data;
|
||||
ajax["type"] = "POST";
|
||||
}
|
||||
ajax["url"] = url;
|
||||
$.ajax(ajax);
|
||||
}
|
||||
|
||||
function renameRevision(target) {
|
||||
const id = hp.getReviewAndRevisionIdFromUrl(window.location.href)["reviewId"];
|
||||
const revisionCard = $(target).closest(".card");
|
||||
const updatedLabel = revisionCard.find(".edit-revision-label > input").val();
|
||||
const revisionsId = revisionCard.attr("data-id");
|
||||
var antiForgeryToken = $("input[name=__RequestVerificationToken]").val();
|
||||
let url = `/Assemblies/Revisions/${id}/${revisionsId}?handler=Rename&newLabel=${updatedLabel}`;
|
||||
|
||||
let ajax = {
|
||||
type: "POST",
|
||||
headers: {
|
||||
"RequestVerificationToken": antiForgeryToken as string
|
||||
},
|
||||
success: function (data) {
|
||||
revisionCard.find(".card-title").text(data);
|
||||
exitAPIRevisionRename(revisionCard);
|
||||
}
|
||||
};
|
||||
|
||||
if ($(target).closest(".revisions-list-container").hasClass("samples-revisions")) {
|
||||
url = `/Assemblies/Samples/${id}/${revisionsId}?handler=Upload`;
|
||||
const data = {
|
||||
Renaming: true,
|
||||
RevisionTitle: updatedLabel,
|
||||
ReviewId: id,
|
||||
SampleId: revisionsId
|
||||
};
|
||||
ajax["data"] = data;
|
||||
}
|
||||
ajax["url"] = url;
|
||||
$.ajax(ajax);
|
||||
}
|
||||
|
||||
/* RIGHT OFFCANVAS OPERATIONS
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
// Open / Close right Offcanvas Menu
|
||||
$("#revisions-right-offcanvas-toggle").on('click', function () {
|
||||
hp.updatePageSettings(function () {
|
||||
rightOffCanvasNavToggle("revisions-main-container");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/* MANAGE APIREVISIONS IN CONTEXT OF REVIEW PAGE
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
|
||||
// Toggle active class for left side offcanvas buttons
|
||||
["#apiRevisions-context", "#add-apirevision-context", "#samplesRevisions-context"].forEach(function (value, index) {
|
||||
$(value).on("shown.bs.offcanvas", function () {
|
||||
handleShownRevisionContext(value);
|
||||
});
|
||||
|
||||
$(value).on("hidden.bs.offcanvas", function (event) {
|
||||
handleHiddenRevisionContext(value);
|
||||
event.stopPropagation();
|
||||
});
|
||||
|
||||
if (value == "#apiRevisions-context" || value == "#samplesRevisions-context") {
|
||||
handleHideRevisionContext(value);
|
||||
}
|
||||
});
|
||||
|
||||
// Search / Filter APIRevisions
|
||||
apiRevisionsSearchBox.on("input", function () {
|
||||
apiRevisionTypeFilter.forEach(function (value, index) {
|
||||
$(value).removeAttr('checked');
|
||||
});
|
||||
searchRevisions(apiRevisionsSearchBox, apiRevisionsSearchContext);
|
||||
});
|
||||
|
||||
samplesRevisionsSearchBox.on("input", function () {
|
||||
searchRevisions(samplesRevisionsSearchBox, samplesRevisionsSearchContext);
|
||||
});
|
||||
|
||||
// Filter by APIRevision Type
|
||||
apiRevisionTypeFilter.forEach(function (value, index) {
|
||||
$(value).on("change", function (event) {
|
||||
apiRevisionsSearchBox.val('');
|
||||
const manualChecked = $(apiRevisionTypeFilter[0]).is(":checked");
|
||||
const autoChecked = $(apiRevisionTypeFilter[1]).is(":checked");
|
||||
const prChecked = $(apiRevisionTypeFilter[2]).is(":checked");
|
||||
|
||||
if ((manualChecked && autoChecked && prChecked) || (!manualChecked && !autoChecked && !prChecked)) {
|
||||
$(".api-revisions.revisions-list-container .card").show();
|
||||
}
|
||||
else {
|
||||
$(".api-revisions.revisions-list-container .card-subtitle").each(function (index, element) {
|
||||
if ((manualChecked && element.innerText.includes("Type: Manual")) ||
|
||||
(autoChecked && element.innerText.includes("Type: Automatic")) ||
|
||||
(prChecked && element.innerText.includes("Type: PullRequest ")) ||
|
||||
(manualChecked && autoChecked && prChecked)) {
|
||||
$(element).closest(".card").show();
|
||||
}
|
||||
else {
|
||||
$(element).closest(".card").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Set Active or Diff APIRevision
|
||||
$(".revisions-list-container .card .btn.make-active").on("click", makeActiveAPIRevisionEventHandler);
|
||||
$(".revisions-list-container .card .btn.make-diff").on("click", makeDiffAPIRevisionEventHandler);
|
||||
$(".revisions-list-container .card .btn.clear-diff").on("click", clearDiffAPIRevisionEventHandler);
|
||||
|
||||
// Delete API Revision
|
||||
$(".revisions-list-container .delete").on("click", function (e) {
|
||||
e.stopPropagation();
|
||||
deleteRevisions(this);
|
||||
});
|
||||
|
||||
// Rename API Revision Label
|
||||
$(".revisions-list-container .rename").on("click", function (e) {
|
||||
e.stopPropagation();
|
||||
const apiRevisionCard = $(this).closest(".card");
|
||||
apiRevisionCard.find(".card-title").addClass("d-none");
|
||||
apiRevisionCard.find(".card-subtitle").addClass("d-none");
|
||||
apiRevisionCard.find(".edit-revision-label").removeClass("d-none");
|
||||
});
|
||||
|
||||
$(".revisions-list-container .cancel-rename").on("click", function (e) {
|
||||
e.stopPropagation();
|
||||
const apiRevisionCard = $(this).closest(".card");
|
||||
exitAPIRevisionRename(apiRevisionCard);
|
||||
});
|
||||
|
||||
$(".revisions-list-container .enter-rename").on("click", function (e) {
|
||||
e.stopPropagation();
|
||||
renameRevision(this);
|
||||
});
|
||||
|
||||
$(".edit-revision-label").on("click", function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
// Open API Revision in new tab
|
||||
$("#revisions-main-container .revisions-list-container .card").on("click", function () {
|
||||
const apiRevisionsId = $(this).attr("data-id");
|
||||
const revisionContainer = $(this).closest(".revisions-list-container");
|
||||
|
||||
if (revisionContainer.hasClass("api-revisions")) {
|
||||
const uri = (window.location.href).replace("/Revisions/", "/Review/") + `?revisionId=${apiRevisionsId}`;
|
||||
window.open(uri, "_blank");
|
||||
}
|
||||
|
||||
if (revisionContainer.hasClass("samples-revisions")) {
|
||||
const uri = (window.location.href).replace("/Revisions/", "/Samples/") + `?revisionId=${apiRevisionsId}`;
|
||||
window.open(uri, "_blank");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
import * as hp from "../shared/helpers";
|
||||
import { rightOffCanvasNavToggle } from "../shared/off-canvas";
|
||||
|
||||
$(() => {
|
||||
/* RIGHT OFFCANVAS OPERATIONS
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
// Open / Close right Offcanvas Menu
|
||||
$("#samples-right-offcanvas-toggle").on('click', function () {
|
||||
hp.updatePageSettings(function () {
|
||||
rightOffCanvasNavToggle("samples-main-container");
|
||||
});
|
||||
});
|
||||
});
|
|
@ -390,10 +390,12 @@ $(() => {
|
|||
highlightCurrentRow(inlineRow, true);
|
||||
});
|
||||
|
||||
$("#jump-to-first-comment").on("click", function () {
|
||||
$("#jump-to-first-comment").on("click", function (e) {
|
||||
e.preventDefault();
|
||||
var commentRows = $('.comment-row');
|
||||
var displayedCommentRows = hp.getDisplayedCommentRows(commentRows, false, true);
|
||||
$(displayedCommentRows[0])[0].scrollIntoView();
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
function highlightCurrentRow(rowElement: JQuery<HTMLElement> = $(), isInlineRow: boolean = false) {
|
||||
|
|
|
@ -244,14 +244,17 @@ export function getDisplayedCommentRows(commentRows: JQuery<HTMLElement>, clearC
|
|||
* @returns result dictionary of "reviewId" and "revisionId", if they exist; undefined otherwise
|
||||
*/
|
||||
export function getReviewAndRevisionIdFromUrl(uri) {
|
||||
const regex = /.+(Review|Conversation|Revisions|Samples)\/([a-zA-Z0-9]+)(\?revisionId=([a-zA-Z0-9]+))?/;
|
||||
const regex = /.+(Review|Conversation|Revisions|Samples)\/([a-zA-Z0-9]+)(\/([a-zA-Z0-9]+)|\?revisionId=([a-zA-Z0-9]+))?/;
|
||||
|
||||
const match = uri.match(regex);
|
||||
const result = {}
|
||||
|
||||
if (match) {
|
||||
result["reviewId"] = match[2];
|
||||
result["revisionId"] = match[4]; // undefined if latest revision
|
||||
result["revisionId"] = match[4]; // undefined if latest revision, or searchParam used
|
||||
if (!result["revisionId"]) {
|
||||
result["revisionId"] = match[5];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -2,10 +2,21 @@
|
|||
export function rightOffCanvasNavToggle(mainContainser: String) {
|
||||
if ($(".right-offcanvas").css("width") == '0px') {
|
||||
$(`#${mainContainser}`).addClass("move-main-content-container-left");
|
||||
$("#right-offcanvas-menu").addClass("show-offcanvas");
|
||||
$("#right-offcanvas-menu").addClass("show-right-offcanvas");
|
||||
}
|
||||
else {
|
||||
$("#right-offcanvas-menu").removeClass("show-offcanvas");
|
||||
$("#right-offcanvas-menu").removeClass("show-right-offcanvas");
|
||||
$(`#${mainContainser}`).removeClass("move-main-content-container-left");
|
||||
}
|
||||
}
|
||||
export function leftOffCanvasNavToggle(mainContainser: String) {
|
||||
if ($(".left-offcanvas").css("width") == '0px') {
|
||||
$(`#${mainContainser}`).addClass("move-main-content-container-right");
|
||||
$("#left-offcanvas-menu").addClass("show-left-offcanvas");
|
||||
}
|
||||
else {
|
||||
$("#left-offcanvas-menu").removeClass("show-left-offcanvas");
|
||||
$(`#${mainContainser}`).removeClass("move-main-content-container-right");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace APIViewWeb.Helpers
|
|||
.ForMember(dest => dest.ShowHiddenApis, opt => opt.MapFrom((src, dest) => src._showHiddenApis != null ? src._showHiddenApis : dest._showHiddenApis))
|
||||
.ForMember(dest => dest.HideReviewPageOptions, opt => opt.MapFrom((src, dest) => src._hideReviewPageOptions != null ? src._hideReviewPageOptions : dest._hideReviewPageOptions))
|
||||
.ForMember(dest => dest.HideIndexPageOptions, opt => opt.MapFrom((src, dest) => src._hideIndexPageOptions != null ? src._hideIndexPageOptions : dest._hideIndexPageOptions))
|
||||
.ForMember(dest => dest.HideSamplesPageOptions, opt => opt.MapFrom((src, dest) => src._hideSamplesPageOptions != null ? src._hideSamplesPageOptions : dest._hideSamplesPageOptions))
|
||||
.ForMember(dest => dest.HideRevisionsPageOptions, opt => opt.MapFrom((src, dest) => src._hideRevisionsPageOptions != null ? src._hideRevisionsPageOptions : dest._hideRevisionsPageOptions))
|
||||
.ForMember(dest => dest.ShowComments, opt => opt.MapFrom((src, dest) => src._showComments != null ? src._showComments : dest._showComments))
|
||||
.ForMember(dest => dest.ShowSystemComments, opt => opt.MapFrom((src, dest) => src._showSystemComments != null ? src._showSystemComments : dest._showSystemComments));
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ using APIViewWeb.Managers.Interfaces;
|
|||
using APIViewWeb.Hubs;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
||||
namespace APIViewWeb.Helpers
|
||||
|
@ -368,7 +370,7 @@ namespace APIViewWeb.Helpers
|
|||
reviewPageContent.Review = review;
|
||||
reviewPageContent.Navigation = activeRevisionRenderableCodeFile.CodeFile.Navigation;
|
||||
reviewPageContent.codeLines = codeLines;
|
||||
reviewPageContent.APIRevisionsGrouped = apiRevisions.OrderByDescending(c => c.CreatedOn).GroupBy(r => r.APIRevisionType).ToDictionary(r => r.Key.ToString(), r => r.ToList());
|
||||
reviewPageContent.APIRevisions = apiRevisions.OrderByDescending(c => c.CreatedOn);
|
||||
reviewPageContent.ActiveAPIRevision = activeRevision;
|
||||
reviewPageContent.DiffAPIRevision = diffRevision;
|
||||
reviewPageContent.TotalActiveConversiations = comments.Threads.Count(t => !t.IsResolved);
|
||||
|
@ -499,6 +501,29 @@ namespace APIViewWeb.Helpers
|
|||
return label;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload API Revision
|
||||
/// </summary>
|
||||
/// <param name="apiRevisionsManager"></param>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="upload"></param>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public static async Task<APIRevisionListItemModel> UploadAPIRevisionAsync(IAPIRevisionsManager apiRevisionsManager, ClaimsPrincipal user, string id, [FromForm] IFormFile upload, [FromForm] string label, [FromForm] string filePath)
|
||||
{
|
||||
if (upload != null)
|
||||
{
|
||||
var openReadStream = upload.OpenReadStream();
|
||||
return await apiRevisionsManager.AddAPIRevisionAsync(user, id, APIRevisionType.Manual, upload.FileName, label, openReadStream, language: null);
|
||||
}
|
||||
else
|
||||
{
|
||||
return await apiRevisionsManager.AddAPIRevisionAsync(user, id, APIRevisionType.Manual, filePath, label, null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create DiffOnly Lines
|
||||
/// </summary>
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace APIViewWeb.LeanModels
|
|||
public ReviewListItemModel Review { get; set; }
|
||||
public NavigationItem[] Navigation { get; set; }
|
||||
public CodeLineModel[] codeLines { get; set; }
|
||||
public Dictionary<string, List<APIRevisionListItemModel>> APIRevisionsGrouped { get; set; }
|
||||
public IEnumerable<APIRevisionListItemModel> APIRevisions { get; set; }
|
||||
public APIRevisionListItemModel ActiveAPIRevision { get; set; }
|
||||
public APIRevisionListItemModel DiffAPIRevision { get; set; }
|
||||
public int TotalActiveConversiations { get; set; }
|
||||
|
|
|
@ -251,7 +251,7 @@ namespace APIViewWeb.Managers
|
|||
/// <param name="language"></param>
|
||||
/// <param name="awaitComputeDiff"></param>
|
||||
/// <returns></returns>
|
||||
public async Task AddAPIRevisionAsync(
|
||||
public async Task<APIRevisionListItemModel> AddAPIRevisionAsync(
|
||||
ClaimsPrincipal user,
|
||||
string reviewId,
|
||||
APIRevisionType apiRevisionType,
|
||||
|
@ -262,7 +262,7 @@ namespace APIViewWeb.Managers
|
|||
bool awaitComputeDiff = false)
|
||||
{
|
||||
var review = await _reviewsRepository.GetReviewAsync(reviewId);
|
||||
await AddAPIRevisionAsync(user, review, apiRevisionType, name, label, fileStream, language, awaitComputeDiff);
|
||||
return await AddAPIRevisionAsync(user, review, apiRevisionType, name, label, fileStream, language, awaitComputeDiff);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace APIViewWeb.Managers.Interfaces
|
|||
public APIRevisionListItemModel GetNewAPIRevisionAsync(APIRevisionType apiRevisionType, string reviewId = null, string packageName = null, string language = null,
|
||||
string label = null, int? prNumber = null, string createdBy = "azure-sdk");
|
||||
public Task<bool> ToggleAPIRevisionApprovalAsync(ClaimsPrincipal user, string id, string revisionId = null, APIRevisionListItemModel apiRevision = null, string notes = "", string approver = "");
|
||||
public Task AddAPIRevisionAsync(ClaimsPrincipal user, string reviewId, APIRevisionType apiRevisionType, string name, string label, Stream fileStream, string language = "", bool awaitComputeDiff = false);
|
||||
public Task<APIRevisionListItemModel> AddAPIRevisionAsync(ClaimsPrincipal user, string reviewId, APIRevisionType apiRevisionType, string name, string label, Stream fileStream, string language = "", bool awaitComputeDiff = false);
|
||||
public Task<APIRevisionListItemModel> AddAPIRevisionAsync(ClaimsPrincipal user, ReviewListItemModel review, APIRevisionType apiRevisionType, string name, string label, Stream fileStream, string language, bool awaitComputeDiff = false);
|
||||
public Task RunAPIRevisionGenerationPipeline(List<APIRevisionGenerationPipelineParamModel> reviewGenParams, string language);
|
||||
public Task SoftDeleteAPIRevisionAsync(ClaimsPrincipal user, string reviewId, string revisionId);
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace APIViewWeb.Managers
|
|||
public Task<string> GetSamplesRevisionContentAsync(string fileId);
|
||||
public Task<SamplesRevisionModel> UpsertSamplesRevisionsAsync(ClaimsPrincipal user, string reviewId, string sample, string revisionTitle, string FileName = null);
|
||||
public Task<SamplesRevisionModel> UpsertSamplesRevisionsAsync(ClaimsPrincipal user, string reviewId, Stream fileStream, string revisionTitle, string FileName);
|
||||
public Task UpdateSamplesRevisionTitle(string reviewId, string sampleId, string newTitle);
|
||||
public Task DeleteSamplesRevisionAsync(ClaimsPrincipal user, string reviewId, string sampleId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,6 +87,13 @@ namespace APIViewWeb.Managers
|
|||
return await UpsertSamplesRevisionsAsync(user, reviewId, sample, revisionTitle, FileName);
|
||||
}
|
||||
|
||||
public async Task UpdateSamplesRevisionTitle(string reviewId, string sampleId, string newTitle)
|
||||
{
|
||||
var samplesRevision = await _samplesRevisionsRepository.GetSamplesRevisionAsync(reviewId, sampleId);
|
||||
samplesRevision.Title = newTitle;
|
||||
await _samplesRevisionsRepository.UpsertSamplesRevisionAsync(samplesRevision);
|
||||
}
|
||||
|
||||
public async Task DeleteSamplesRevisionAsync(ClaimsPrincipal user, string reviewId, string sampleId)
|
||||
{
|
||||
var samplesRevision = await _samplesRevisionsRepository.GetSamplesRevisionAsync(reviewId, sampleId);
|
||||
|
|
|
@ -9,10 +9,10 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
public class SamplesRevisionUploadModel
|
||||
{
|
||||
[BindProperty]
|
||||
public string sampleString { get; set; }
|
||||
public string SampleString { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string updateString { get; set; }
|
||||
public string UpdateString { get; set; }
|
||||
|
||||
[BindProperty]
|
||||
public string ReviewId { get; set; }
|
||||
|
@ -23,9 +23,15 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
[BindProperty]
|
||||
public bool Deleting { get; set; } = false;
|
||||
|
||||
[BindProperty]
|
||||
public bool DeletingAndRedirect { get; set; } = false;
|
||||
|
||||
[BindProperty]
|
||||
public bool Updating { get; set; } = false;
|
||||
|
||||
[BindProperty]
|
||||
public bool Renaming { get; set; } = false;
|
||||
|
||||
[BindProperty]
|
||||
public string SampleId { get; set; }
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
using System.Collections.Generic;
|
||||
using APIViewWeb.LeanModels;
|
||||
using CsvHelper.Configuration.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace APIViewWeb.Models
|
||||
{
|
||||
|
@ -19,6 +18,8 @@ namespace APIViewWeb.Models
|
|||
internal bool? _showHiddenApis;
|
||||
internal bool? _hideReviewPageOptions;
|
||||
internal bool? _hideIndexPageOptions;
|
||||
internal bool? _hideSamplesPageOptions;
|
||||
internal bool? _hideRevisionsPageOptions;
|
||||
internal bool? _showComments;
|
||||
internal bool? _showSystemComments;
|
||||
internal string _theme;
|
||||
|
@ -94,6 +95,20 @@ namespace APIViewWeb.Models
|
|||
set => _hideIndexPageOptions = value;
|
||||
}
|
||||
|
||||
[Name("HideSamplesPageOptions")]
|
||||
public bool? HideSamplesPageOptions
|
||||
{
|
||||
get => _hideSamplesPageOptions ?? false;
|
||||
set => _hideSamplesPageOptions = value;
|
||||
}
|
||||
|
||||
[Name("HideRevisionsPageOptions")]
|
||||
public bool? HideRevisionsPageOptions
|
||||
{
|
||||
get => _hideRevisionsPageOptions ?? false;
|
||||
set => _hideRevisionsPageOptions = value;
|
||||
}
|
||||
|
||||
[Name("ShowComments")]
|
||||
public bool? ShowComments
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
@page "{id?}"
|
||||
@model APIViewWeb.Pages.Assemblies.ConversationModel
|
||||
@using APIViewWeb.Helpers
|
||||
@using APIViewWeb.LeanModels
|
||||
@using APIViewWeb.Models
|
||||
@{
|
||||
Layout = "Shared/_Layout";
|
||||
|
@ -8,60 +9,72 @@
|
|||
TempData["UserPreference"] = PageModelHelpers.GetUserPreference(Model._preferenceCache, User);
|
||||
}
|
||||
<div class="container-fluid mx-0 px-0 sub-header-content">
|
||||
<div class="row mx-1 px-0 py-2">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group-sm input-group">
|
||||
<partial name="Shared/_ReviewBadge" model="(Model.Review, Model.LatestAPIRevision)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="row px-3 py-2 border-bottom" id="review-info-bar">
|
||||
<partial name="Shared/_ReviewBadge" model="(Model.Review, default(APIRevisionListItemModel), default(APIRevisionListItemModel), default(UserPreferenceModel))" />
|
||||
</div>
|
||||
</div>
|
||||
@{
|
||||
var leftOffCanvasClass = " show-left-offcanvas";
|
||||
var mainContainerClass = " move-main-content-container-right";
|
||||
}
|
||||
|
||||
<div id="left-offcanvas-menu" class="left-offcanvas@(leftOffCanvasClass)">
|
||||
<div class="left-offcanvas-menu-content" id="left-offcanvas-menu-content">
|
||||
<div class="btn-group-vertical" role="group" aria-label="Vertical button group">
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Review" asp-route-id="@Model.Review.Id"><i class="bi bi-braces" data-bs-toggle="tooltip" data-bs-placement="right" title="API"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Revisions" asp-route-id="@Model.Review.Id"><i class="bi bi-clock-history" data-bs-toggle="tooltip" data-bs-placement="right" title="Revisons"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" data-bs-toggle="tooltip" data-bs-placement="right" title="API" active-if="@TempData["page"].Equals("conversation")"><i class="bi bi-chat-left-dots"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Samples" asp-route-id="@Model.Review.Id"><i class="bi bi-puzzle" data-bs-toggle="tooltip" data-bs-placement="right" title="Samples"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<partial name="Shared/_ReviewNavBar" />
|
||||
</div>
|
||||
<div class="container" id="conversation-main-container">
|
||||
<div class="row mx-0 px-0 py-2">
|
||||
<div class="col-lg-12 px-0" data-review-id=@Model.Review.Id>
|
||||
@if (!Model.Threads.Any() && !Model.UsageSampleThreads.Any())
|
||||
{
|
||||
<div class="text-muted">There are no comments in the review.</div>
|
||||
<div class="container-fluid pt-2@(mainContainerClass)" id="conversation-main-container">
|
||||
<div class="row g-2" data-review-id="@Model.Review.Id">
|
||||
@if (!Model.Threads.Any() && !Model.UsageSampleThreads.Any())
|
||||
{
|
||||
<div class="text-muted">There are no comments in the review.</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (Model.Threads.Any())
|
||||
{
|
||||
<div class="col mx-3">
|
||||
<h6 class="ms-3">APIRevisions Comments</h6>
|
||||
@if (Model.Threads.Any())
|
||||
{
|
||||
<div class="border rounded conversiation-center">
|
||||
@foreach (var revision in Model.Threads)
|
||||
{
|
||||
var divId = $"rev-{revision.Key.Id}";
|
||||
|
||||
<div class="card-header p-2 clickable" id="header-@revision.Key.Id" data-toggle="collapse" data-target="#@divId">
|
||||
@PageModelHelpers.ResolveRevisionLabel(revision.Key)
|
||||
</div>
|
||||
<div id=@divId class="collapse show" data-revision-id=@revision.Key.Id aria-labelledby="header-@revision.Key.Id">
|
||||
<table class="code-window">
|
||||
@foreach (var thread in revision.Value)
|
||||
{
|
||||
var elementId = thread.LineId;
|
||||
<tr class="code-line"><td class="code p-2" style="word-break: break-all;"><a class="comment-url" asp-page="Review"
|
||||
asp-route-id=@Model.Review.Id
|
||||
asp-route-revisionId=@revision.Key.Id
|
||||
asp-fragment=@Uri.EscapeDataString(elementId)>@elementId</a>
|
||||
</td>
|
||||
</tr>
|
||||
<partial name="_CommentThreadPartial" model="@thread" />
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (Model.Threads.Any())
|
||||
{
|
||||
<div class="border rounded conversiation-center">
|
||||
@foreach (var revision in Model.Threads)
|
||||
{
|
||||
var divId = $"rev-{revision.Key.Id}";
|
||||
|
||||
<div class="card-header p-2 clickable" id="header-@revision.Key.Id" data-toggle="collapse" data-target="#@divId">
|
||||
PageModelHelpers.ResolveRevisionLabel(@revision.Key.Label)
|
||||
</div>
|
||||
<div id=@divId class="collapse show" data-revision-id=@revision.Key.Id aria-labelledby="header-@revision.Key.Id">
|
||||
<table class="code-window">
|
||||
@foreach (var thread in revision.Value)
|
||||
{
|
||||
var elementId = thread.LineId;
|
||||
<tr class="code-line"><td class="code p-2" style="word-break: break-all;"><a class="comment-url" asp-page="Review"
|
||||
asp-route-id=@Model.Review.Id
|
||||
asp-route-revisionId=@revision.Key.Id
|
||||
asp-fragment=@Uri.EscapeDataString(elementId)>@elementId</a>
|
||||
</td>
|
||||
</tr>
|
||||
<partial name="_CommentThreadPartial" model="@thread" />
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (Model.UsageSampleThreads.Count > 0)
|
||||
{
|
||||
var skipped = 1;
|
||||
<br />
|
||||
@if (Model.UsageSampleThreads.Any())
|
||||
{
|
||||
var skipped = 1;
|
||||
<div class="col mx-3">
|
||||
<h6 class="ms-3">Sample Revisions Comments</h6>
|
||||
<div class="border rounded conversiation-center">
|
||||
@foreach (var revision in Model.UsageSampleThreads.Reverse())
|
||||
{
|
||||
|
@ -76,14 +89,14 @@
|
|||
{
|
||||
displayName += " - " + revision.Key.sampleRevision.OriginalFileName;
|
||||
}
|
||||
<div class="card-header p-2 text-black-50 clickable" id="header-@revision.Key.sampleRevisionNumber" data-toggle="collapse" data-target="#@divId">
|
||||
<div class="card-header p-2 clickable" id="header-@revision.Key.sampleRevisionNumber" data-toggle="collapse" data-target="#@divId">
|
||||
@displayName
|
||||
</div>
|
||||
<div id=@divId class="collapse show" data-revision-id=@revision.Key.sampleRevisionNumber aria-labelledby="header-@revision.Key.sampleRevisionNumber">
|
||||
<table class="code-window">
|
||||
@foreach (var thread in revision.Value.OrderBy(e => int.Parse(e.LineId.Split("-").Last())).GroupBy(x => x.LineId).Select(g => g.First()))
|
||||
{
|
||||
int indexA = Model.SampleLines.Count() - (revision.Key.sampleRevisionNumber - skipped);
|
||||
int indexA = Model.SampleLines.Count() - Math.Abs(revision.Key.sampleRevisionNumber - skipped);
|
||||
int indexB = int.Parse(thread.Comments.First().ElementId.Split("-").Last()) - 1;
|
||||
@if (thread.Comments.Any())
|
||||
{
|
||||
|
@ -106,10 +119,9 @@
|
|||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
}
|
||||
<partial name="_CommentFormPartial" model="@Model.TaggableUsers" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,8 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using ApiView;
|
||||
using APIView;
|
||||
using APIViewWeb.LeanModels;
|
||||
using APIViewWeb.Managers;
|
||||
using APIViewWeb.Managers.Interfaces;
|
||||
|
|
|
@ -33,12 +33,16 @@
|
|||
</div>
|
||||
|
||||
@{
|
||||
var offCanvasClass = " show-offcanvas";
|
||||
var offCanvasClass = " show-right-offcanvas";
|
||||
var mainContainerClass = " move-main-content-container-left";
|
||||
if (userPreference.HideIndexPageOptions.HasValue && userPreference.HideIndexPageOptions == true)
|
||||
{
|
||||
offCanvasClass = String.Empty;
|
||||
mainContainerClass = string.Empty;
|
||||
}
|
||||
}
|
||||
<div id="right-offcanvas-menu" class="right-offcanvas@(offCanvasClass)">
|
||||
<div class="offcanvas-menu-content" id="index-offcanvas-menu-content">
|
||||
<div class="right-offcanvas-menu-content" id="index-offcanvas-menu-content">
|
||||
<p class="h6">Filters</p>
|
||||
<div class="input-group input-group-sm mb-2">
|
||||
<span class="input-group-text">Languages</span>
|
||||
|
@ -66,11 +70,6 @@
|
|||
<hr class="border">
|
||||
</div>
|
||||
</div>
|
||||
@{
|
||||
var mainContainerClass = " move-main-content-container-left";
|
||||
if (userPreference.HideIndexPageOptions.HasValue && userPreference.HideIndexPageOptions == true)
|
||||
mainContainerClass = String.Empty;
|
||||
}
|
||||
|
||||
<div class="container-fluid mb-5@(mainContainerClass)" id="index-main-container">
|
||||
<div class="modal fade" id="uploadModel" tabindex="-1" role="dialog">
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -10,6 +10,7 @@ using APIViewWeb.Managers.Interfaces;
|
|||
using APIViewWeb.Models;
|
||||
using APIViewWeb.Repositories;
|
||||
using Microsoft.ApplicationInsights.AspNetCore.Extensions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
|
@ -17,7 +18,6 @@ using Microsoft.CodeAnalysis;
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.TeamFoundation.Common;
|
||||
|
||||
|
||||
namespace APIViewWeb.Pages.Assemblies
|
||||
{
|
||||
public class ReviewPageModel : PageModel
|
||||
|
@ -130,7 +130,7 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
return RedirectToPage("Index", new { notificationMessage = ReviewContent.NotificationMessage });
|
||||
}
|
||||
|
||||
if (ReviewContent.APIRevisionsGrouped == null || !ReviewContent.APIRevisionsGrouped.Any())
|
||||
if (ReviewContent.APIRevisions == null || !ReviewContent.APIRevisions.Any())
|
||||
{
|
||||
return RedirectToPage("LegacyReview", new { id = id });
|
||||
}
|
||||
|
@ -302,6 +302,28 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
await _notificationManager.NotifyApproversOfReview(User, apiRevisionId, reviewers);
|
||||
return RedirectToPage(new { id = id, revisionId = apiRevisionId });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload APIRevisions
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="upload"></param>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IActionResult> OnPostUploadAsync(string id, [FromForm] IFormFile upload, [FromForm] string label, [FromForm] string filePath)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
var apiRevision = await PageModelHelpers.UploadAPIRevisionAsync(_apiRevisionsManager, User, id, upload, label, filePath);
|
||||
|
||||
return RedirectToPage(new { id = id, revisionId = apiRevision.Id });
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get Routing Data for a Review
|
||||
/// </summary>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
@page "{id?}"
|
||||
@page "{id?}/{revisionId?}"
|
||||
@model APIViewWeb.Pages.Assemblies.RevisionsPageModel
|
||||
@using APIViewWeb.Helpers
|
||||
@using APIViewWeb.LeanModels;
|
||||
|
@ -6,183 +6,81 @@
|
|||
@{
|
||||
Layout = "Shared/_Layout";
|
||||
ViewData["Title"] = "Revisions";
|
||||
TempData["UserPreference"] = PageModelHelpers.GetUserPreference(Model._preferenceCache, User);
|
||||
var userPreference = PageModelHelpers.GetUserPreference(Model._preferenceCache, User);
|
||||
TempData["UserPreference"] = userPreference;
|
||||
}
|
||||
<div class="container-fluid mx-0 px-0 sub-header-content">
|
||||
<div class="row mx-1 px-0 py-2">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group-sm input-group">
|
||||
<partial name="Shared/_ReviewBadge" model="(Model.Review, Model.LatestAPIRevision)" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
</div>
|
||||
<div class="row px-3 py-2 border-bottom" id="review-info-bar">
|
||||
<partial name="Shared/_ReviewBadge" model="(Model.Review, default(APIRevisionListItemModel), default(APIRevisionListItemModel), default(UserPreferenceModel))" />
|
||||
</div>
|
||||
<partial name="Shared/_ReviewNavBar" />
|
||||
</div>
|
||||
|
||||
<div class="container" id="revisions-main-container">
|
||||
<div class="row">
|
||||
<div id="add-revision-button">
|
||||
<button type="button" class="btn btn-primary" id="add-revision-button" data-bs-toggle="modal" data-bs-target="#uploadModel"><small>ADD</small><br><i class="fas fa-sm fa-plus"></i><br><small>REVISION</small></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@{
|
||||
var rightOffCanvasClass = " show-right-offcanvas";
|
||||
var leftOffCanvasClass = " show-left-offcanvas";
|
||||
var mainContainerLeftClass = " move-main-content-container-left";
|
||||
var mainContainerRightClass = " move-main-content-container-right";
|
||||
if (userPreference.HideRevisionsPageOptions.HasValue && userPreference.HideRevisionsPageOptions == true)
|
||||
{
|
||||
rightOffCanvasClass = String.Empty;
|
||||
mainContainerRightClass = String.Empty;
|
||||
}
|
||||
var mainContainerClass = mainContainerLeftClass + mainContainerRightClass;
|
||||
}
|
||||
|
||||
<div class="modal fade" id="uploadModel" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<form asp-page-handler="Upload" method="post" enctype="multipart/form-data">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Upload file</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
@if (!(LanguageServiceHelpers.MapLanguageAliases(new List<string> { "TypeSpec" })).Contains(Model.Review.Language))
|
||||
{
|
||||
<div class="input-group mb-3 custom-file-label">
|
||||
<label class="input-group-text small" for="uploadRevisionFile">Select file to add</label>
|
||||
<input name="upload" for="upload" type="file" class="form-control" id="uploadRevisionFile">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-pills nav-fill mb-3" id="typespec-pills-tab" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="typespec-pills-tsp-tab" data-bs-toggle="pill" data-bs-target="#typespec-pills-tsp" type="button" role="tab" aria-controls="typespec-pills-tsp" aria-selected="true">TypeSpec</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="typespec-pills-json-tab" data-bs-toggle="pill" data-bs-target="#typespec-pills-json" type="button" role="tab" aria-controls="typespec-pills-json" aria-selected="false">Json</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content mb-3" id="typespec-pills-tabcontent">
|
||||
<div class="tab-pane fade show active" id="typespec-pills-tsp" role="tabpanel" aria-labelledby="typespec-pills-tsp-tab" tabindex="0">
|
||||
<div class="input-group custom-file-label">
|
||||
<label class="input-group-text small" for="uploadRevisionFile">Select file to add</label>
|
||||
<input name="upload" for="upload" type="file" class="form-control" id="uploadRevisionFile">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="typespec-pills-json" role="tabpanel" aria-labelledby="typespec-pills-json-tab" tabindex="0">
|
||||
<input asp-for="FilePath" class="form-control" type="text" placeholder="Package root e.g https://github.com/Azure/azure-rest-api-specs/specification/cognitiveservices/AnomalyDetector/">
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<input asp-for="Label" class="form-control" type="text" placeholder="Enter an optional revision label">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;"><i class="fas fa-cloud-upload-alt"></i> Upload</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mx-0 px-0 py-2">
|
||||
<div class="col-lg-12 mx-0 px-0">
|
||||
@if (Model.APIRevisions.ContainsKey("Automatic"))
|
||||
{
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item list-group-item-heading fw-bold">Automatic APIRevisions</li>
|
||||
@foreach (var revision in Model.APIRevisions["Automatic"])
|
||||
{
|
||||
<li class="list-group-item">
|
||||
<form class="form-inline revision-rename-form float-left" asp-page-handler="Rename" method="post">
|
||||
<span asp-resource="@revision" asp-requirement="@RevisionOwnerRequirement.Instance">
|
||||
<a href="#" class="text-decoration-none revision-rename-icon pr-2">✎</a>
|
||||
<input type="hidden" name="revisionId" value="@revision.Id" />
|
||||
<span class="revision-name-input form-group-lg pr-2" style="display:none">
|
||||
<input type="text" class="form-control" name="newLabel" value="@revision.Label" placeholder="Enter a revision label" />
|
||||
<a href="#" class="text-decoration-none submit-revision-rename">✔️</a>
|
||||
<a href="#" class="text-decoration-none cancel-revision-rename">❌</a>
|
||||
</span>
|
||||
</span>
|
||||
<span class="revision-name-label">@revision.Label</span>
|
||||
<span class="font-italic pl-3">
|
||||
<span>@revision.APIRevisionType.ToString(), Created: </span>
|
||||
<span date="@revision.CreatedOn"></span>
|
||||
<span>By: @revision.CreatedBy</span>
|
||||
</span>
|
||||
</form>
|
||||
<form asp-resource="@revision" asp-requirement="@RevisionOwnerRequirement.Instance"
|
||||
class="form-inline float-right" asp-page-handler="Delete" method="post">
|
||||
<input type="hidden" name="revisionId" value="@revision.Id" />
|
||||
<input type="submit" class="btn btn-danger btn-sm" value="Delete" />
|
||||
</form>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
@if (Model.APIRevisions.ContainsKey("PullRequest"))
|
||||
{
|
||||
<ul class="list-group mt-2">
|
||||
<li class="list-group-item list-group-item-heading fw-bold">PullRequest APIRevisions</li>
|
||||
@foreach (var revision in Model.APIRevisions["PullRequest"])
|
||||
{
|
||||
<li class="list-group-item">
|
||||
<form class="form-inline revision-rename-form float-left" asp-page-handler="Rename" method="post">
|
||||
<span asp-resource="@revision" asp-requirement="@RevisionOwnerRequirement.Instance">
|
||||
<a href="#" class="text-decoration-none revision-rename-icon pr-2">✎</a>
|
||||
<input type="hidden" name="revisionId" value="@revision.Id" />
|
||||
<span class="revision-name-input form-group-lg pr-2" style="display:none">
|
||||
<input type="text" class="form-control" name="newLabel" value="@revision.Label" placeholder="Enter a revision label" />
|
||||
<a href="#" class="text-decoration-none submit-revision-rename">✔️</a>
|
||||
<a href="#" class="text-decoration-none cancel-revision-rename">❌</a>
|
||||
</span>
|
||||
</span>
|
||||
<span class="revision-name-label">@revision.Label</span>
|
||||
<span class="font-italic pl-3">
|
||||
<span>@revision.APIRevisionType.ToString(), Created: </span>
|
||||
<span date="@revision.CreatedOn"></span>
|
||||
<span>By: @revision.CreatedBy</span>
|
||||
</span>
|
||||
</form>
|
||||
<form asp-resource="@revision" asp-requirement="@RevisionOwnerRequirement.Instance"
|
||||
class="form-inline float-right" asp-page-handler="Delete" method="post">
|
||||
<input type="hidden" name="revisionId" value="@revision.Id" />
|
||||
<input type="submit" class="btn btn-danger btn-sm" value="Delete" />
|
||||
</form>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
@if (Model.APIRevisions.ContainsKey("Manual"))
|
||||
{
|
||||
<ul class="list-group mt-2">
|
||||
<li class="list-group-item list-group-item-heading fw-bold">Manual APIRevisions</li>
|
||||
@foreach (var revision in Model.APIRevisions["Manual"])
|
||||
{
|
||||
<li class="list-group-item">
|
||||
<form class="form-inline revision-rename-form float-left" asp-page-handler="Rename" method="post">
|
||||
<span asp-resource="@revision" asp-requirement="@RevisionOwnerRequirement.Instance">
|
||||
<a href="#" class="text-decoration-none revision-rename-icon pr-2">✎</a>
|
||||
<input type="hidden" name="revisionId" value="@revision.Id" />
|
||||
<span class="revision-name-input form-group-lg pr-2" style="display:none">
|
||||
<input type="text" class="form-control" name="newLabel" value="@revision.Label" placeholder="Enter a revision label" />
|
||||
<a href="#" class="text-decoration-none submit-revision-rename">✔️</a>
|
||||
<a href="#" class="text-decoration-none cancel-revision-rename">❌</a>
|
||||
</span>
|
||||
</span>
|
||||
<span class="revision-name-label">@revision.Label</span>
|
||||
<span class="font-italic pl-3">
|
||||
<span>@revision.APIRevisionType.ToString(), Created: </span>
|
||||
<span date="@revision.CreatedOn"></span>
|
||||
<span>By: @revision.CreatedBy</span>
|
||||
</span>
|
||||
</form>
|
||||
<form asp-resource="@revision" asp-requirement="@RevisionOwnerRequirement.Instance"
|
||||
class="form-inline float-right" asp-page-handler="Delete" method="post">
|
||||
<input type="hidden" name="revisionId" value="@revision.Id" />
|
||||
<input type="submit" class="btn btn-danger btn-sm" value="Delete" />
|
||||
</form>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
<div id="left-offcanvas-menu" class="left-offcanvas@(leftOffCanvasClass)">
|
||||
<div class="left-offcanvas-menu-content" id="left-offcanvas-menu-content">
|
||||
<div class="btn-group-vertical" role="group" aria-label="Vertical button group">
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Review" asp-route-id="@Model.Review.Id"><i class="bi bi-braces" data-bs-toggle="tooltip" data-bs-placement="right" title="API"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" active-if="@TempData["page"].Equals("revisions")"><i class="bi bi-clock-history" data-bs-toggle="tooltip" data-bs-placement="right" title="Revisons"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Conversation" asp-route-id="@Model.Review.Id"><i class="bi bi-chat-left-dots" data-bs-toggle="tooltip" data-bs-placement="right" title="Conversiations"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Samples" asp-route-id="@Model.Review.Id"><i class="bi bi-puzzle" data-bs-toggle="tooltip" data-bs-placement="right" title="Samples"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="right-offcanvas-menu" class="right-offcanvas@(rightOffCanvasClass)">
|
||||
<div class="right-offcanvas-menu-content" id="right-offcanvas-menu-content">
|
||||
<p class="h6">
|
||||
<a data-bs-toggle="collapse" href="#revisionsUpdateCollapse" aria-expanded="true" aria-controls="revisionsUpdateCollapse">Update <i class="fa-solid fa-ellipsis"></i></a>
|
||||
</p>
|
||||
@{
|
||||
var revisionsUpdateCollapseState = " show";
|
||||
if (Request.Cookies.ContainsKey("revisionsUpdateCollapse"))
|
||||
{
|
||||
if (!Request.Cookies["revisionsUpdateCollapse"].Equals("shown"))
|
||||
revisionsUpdateCollapseState = String.Empty;
|
||||
}
|
||||
}
|
||||
<ul class="list-group collapse mb-3@(revisionsUpdateCollapseState)" id="samplesInfoCollapse">
|
||||
<li class="list-group-item text-center">
|
||||
<div class="d-grid gap-2 my-2">
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="offcanvas" data-bs-target="#add-apirevision-context" aria-controls="add-apirevision-context">Add APIRevisions</button>
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="offcanvas" data-bs-target="#upload-samples-context" aria-controls="upload-samples-context">Add Samples Revisions</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid pt-2@(mainContainerClass)" id="revisions-main-container">
|
||||
<div class="row g-2">
|
||||
<div class="col">
|
||||
<h6 class="ms-3">APIRevisions</h6>
|
||||
<partial name="Shared/_APIRevisionsPartial" model="(Model.Review, Model.APIRevisions, default(APIRevisionListItemModel), default(APIRevisionListItemModel))" />
|
||||
</div>
|
||||
@if (Model.SamplesRevisions.Any())
|
||||
{
|
||||
<div class="col">
|
||||
<h6 class="ms-3">Sample Revisions</h6>
|
||||
<partial name="Shared/_SamplesRevisionsPartial" model="(Model.Review, Model.SamplesRevisions, default(SamplesRevisionModel))" />
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<partial name="Shared/_AddSamplesRevisionsPartial" model="Model.Review" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using APIViewWeb.Helpers;
|
||||
using APIViewWeb.LeanModels;
|
||||
using APIViewWeb.Managers;
|
||||
using APIViewWeb.Managers.Interfaces;
|
||||
using APIViewWeb.Models;
|
||||
using APIViewWeb.Repositories;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
@ -16,66 +16,52 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
{
|
||||
private readonly IReviewManager _reviewManager;
|
||||
private readonly IAPIRevisionsManager _apiRevisionsManager;
|
||||
private readonly ISamplesRevisionsManager _samplesRevisionsManager;
|
||||
public readonly UserPreferenceCache _preferenceCache;
|
||||
|
||||
public RevisionsPageModel(
|
||||
IReviewManager manager,
|
||||
IAPIRevisionsManager reviewRevisionsManager,
|
||||
ISamplesRevisionsManager samplesRevisionsManager,
|
||||
UserPreferenceCache preferenceCache)
|
||||
{
|
||||
_reviewManager = manager;
|
||||
_apiRevisionsManager = reviewRevisionsManager;
|
||||
_samplesRevisionsManager = samplesRevisionsManager;
|
||||
_preferenceCache = preferenceCache;
|
||||
}
|
||||
|
||||
public ReviewListItemModel Review { get; set; }
|
||||
public APIRevisionListItemModel LatestAPIRevision { get; set; }
|
||||
public Dictionary<string, List<APIRevisionListItemModel>> APIRevisions { get; set; }
|
||||
|
||||
[FromForm]
|
||||
public string Label { get; set; }
|
||||
|
||||
[FromForm]
|
||||
public string FilePath { get; set; }
|
||||
|
||||
[FromForm]
|
||||
public string Language { get; set; }
|
||||
public IEnumerable<SamplesRevisionModel> SamplesRevisions { get; set; }
|
||||
public IEnumerable<APIRevisionListItemModel> APIRevisions { get; set; }
|
||||
|
||||
public async Task<IActionResult> OnGetAsync(string id)
|
||||
{
|
||||
TempData["Page"] = "revisions";
|
||||
|
||||
Review = await _reviewManager.GetReviewAsync(User, id);
|
||||
LatestAPIRevision = await _apiRevisionsManager.GetLatestAPIRevisionsAsync(Review.Id);
|
||||
var revisions = await _apiRevisionsManager.GetAPIRevisionsAsync(Review.Id);
|
||||
APIRevisions = revisions.GroupBy(r => r.APIRevisionType).ToDictionary(r => r.Key.ToString(), r => r.ToList());
|
||||
APIRevisions = (await _apiRevisionsManager.GetAPIRevisionsAsync(Review.Id)).OrderByDescending(c => c.CreatedOn);
|
||||
SamplesRevisions = (await _samplesRevisionsManager.GetSamplesRevisionsAsync(Review.Id)).OrderByDescending(c => c.CreatedOn);
|
||||
|
||||
return Page();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostUploadAsync(string id, [FromForm] IFormFile upload)
|
||||
/// <summary>
|
||||
/// Upload APIRevisions
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="upload"></param>
|
||||
/// <param name="label"></param>
|
||||
/// <param name="filePath"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IActionResult> OnPostUploadAsync(string id, [FromForm] IFormFile upload, [FromForm] string label, [FromForm] string filePath)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
if (upload != null)
|
||||
{
|
||||
var openReadStream = upload.OpenReadStream();
|
||||
await _apiRevisionsManager.AddAPIRevisionAsync(User, id, APIRevisionType.Manual, upload.FileName, Label, openReadStream, language: Language);
|
||||
}
|
||||
else
|
||||
{
|
||||
await _apiRevisionsManager.AddAPIRevisionAsync(User, id, APIRevisionType.Manual, FilePath, Label, null);
|
||||
}
|
||||
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> OnPostDeleteAsync(string id, string revisionId)
|
||||
{
|
||||
await _apiRevisionsManager.SoftDeleteAPIRevisionAsync(User, id, revisionId);
|
||||
await PageModelHelpers.UploadAPIRevisionAsync(_apiRevisionsManager, User, id, upload, label, filePath);
|
||||
|
||||
return RedirectToPage();
|
||||
}
|
||||
|
@ -83,8 +69,19 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
public async Task<IActionResult> OnPostRenameAsync(string id, string revisionId, string newLabel)
|
||||
{
|
||||
await _apiRevisionsManager.UpdateAPIRevisionLabelAsync(User, revisionId, newLabel);
|
||||
return Content(newLabel);
|
||||
}
|
||||
|
||||
return RedirectToPage();
|
||||
/// <summary>
|
||||
/// Delete API Revision
|
||||
/// </summary>
|
||||
/// <param name="id"></param>
|
||||
/// <param name="revisionId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<IActionResult> OnDeleteAsync(string id, string revisionId)
|
||||
{
|
||||
await _apiRevisionsManager.SoftDeleteAPIRevisionAsync(User, id, revisionId);
|
||||
return new NoContentResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,89 +10,86 @@
|
|||
TempData["UserPreference"] = userPreference;
|
||||
}
|
||||
|
||||
@{
|
||||
var rightOffCanvasClass = " show-right-offcanvas";
|
||||
var leftOffCanvasClass = " show-left-offcanvas";
|
||||
var mainContainerLeftClass = " move-main-content-container-left";
|
||||
var mainContainerRightClass = " move-main-content-container-right";
|
||||
if (userPreference.HideSamplesPageOptions.HasValue && userPreference.HideSamplesPageOptions == true)
|
||||
{
|
||||
rightOffCanvasClass = String.Empty;
|
||||
mainContainerRightClass = String.Empty;
|
||||
}
|
||||
var mainContainerClass = mainContainerLeftClass + mainContainerRightClass;
|
||||
}
|
||||
|
||||
<div class="container-fluid mx-0 px-0 sub-header-content">
|
||||
<div class="row px-3 py-2 border-bottom" id="review-info-bar">
|
||||
<partial name="Shared/_ReviewBadge" model="(Model.Review, default(APIRevisionListItemModel), default(APIRevisionListItemModel), default(UserPreferenceModel))" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="left-offcanvas-menu" class="left-offcanvas@(leftOffCanvasClass)">
|
||||
<div class="left-offcanvas-menu-content" id="left-offcanvas-menu-content">
|
||||
<div class="btn-group-vertical" role="group" aria-label="Vertical button group">
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Review" asp-route-id="@Model.Review.Id"><i class="bi bi-braces" data-bs-toggle="tooltip" data-bs-placement="right" title="API"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" data-bs-toggle="offcanvas" data-bs-target="#samplesRevisions-context" aria-controls="samplesRevisions-context"><i class="bi bi-clock-history" data-bs-toggle="tooltip" data-bs-placement="right" title="Revisons"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" asp-page="Conversation" asp-route-id="@Model.Review.Id"><i class="bi bi-chat-left-dots" data-bs-toggle="tooltip" data-bs-placement="right" title="Conversiations"></i></a>
|
||||
<a type="button" class="btn btn-lg btn-link mb-2" data-bs-toggle="tooltip" data-bs-placement="right" title="Samples" active-if="@TempData["page"].Equals("samples")"><i class="bi bi-puzzle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="right-offcanvas-menu" class="right-offcanvas@(rightOffCanvasClass)">
|
||||
<div class="right-offcanvas-menu-content" id="right-offcanvas-menu-content">
|
||||
<p class="h6">
|
||||
<a data-bs-toggle="collapse" href="#samplesUpdateCollapse" aria-expanded="true" aria-controls="samplesUpdateCollapse">Update <i class="fa-solid fa-ellipsis"></i></a>
|
||||
</p>
|
||||
@{
|
||||
var samplesUpdateCollapseState = " show";
|
||||
if (Request.Cookies.ContainsKey("samplesUpdateCollapse"))
|
||||
{
|
||||
if (!Request.Cookies["samplesUpdateCollapse"].Equals("shown"))
|
||||
samplesUpdateCollapseState = String.Empty;
|
||||
}
|
||||
}
|
||||
<ul class="list-group collapse mb-3@(samplesUpdateCollapseState)" id="samplesInfoCollapse">
|
||||
<li class="list-group-item text-center">
|
||||
<span class="small text-muted"><i>Uploaded by <strong> <a username="@Model.ActiveSampleRevision.CreatedBy"> @Model.ActiveSampleRevision.CreatedBy </a></strong></i></span>
|
||||
<div class="d-grid gap-2 my-2">
|
||||
@if (Model.SampleContent != null && Model.SampleContent.Any())
|
||||
{
|
||||
<button type="button" class="btn btn-outline-primary" data-bs-toggle="offcanvas" data-bs-target="#edit-samples-context" aria-controls="edit-samples-context">Edit</button>
|
||||
@if (Model.ActiveSampleRevision.CreatedBy == User.GetGitHubLogin())
|
||||
{
|
||||
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#deleteModel">Delete</button>
|
||||
}
|
||||
}
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="offcanvas" data-bs-target="#upload-samples-context" aria-controls="upload-samples-context">Add Sample</button>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (Model.ActiveSampleRevision != null && (Model.ActiveSampleRevision.FileId == "Bad Deployment" || Model.ActiveSampleRevision.FileId == "File Content Missing")) // If the samples container does not exist
|
||||
{
|
||||
<div class="container-fluid mx-0 px-0 sub-header-content">
|
||||
<div class="row mx-1 px-0 py-2">
|
||||
<div class="col-md-6">
|
||||
<div class="input-group-sm input-group">
|
||||
<partial name="Shared/_ReviewBadge" model="(Model.Review, default(APIRevisionListItemModel))" />
|
||||
<div class="container-fluid pt-2@(mainContainerClass)" id="samples-main-container">
|
||||
<div class="row mx-0 px-0">
|
||||
<div class="col-lg-12 mx-0 px-0">
|
||||
<div class="text-muted">
|
||||
<p> <strong> Usage Samples are not available for this APIView deployment. </strong></p>
|
||||
<p> Please check <a href="https://github.com/Azure/azure-sdk-tools/blob/main/src/dotnet/APIView/APIViewWeb/CONTRIBUTING.md">CONTRIBUTING.md</a> to see how to enable them. </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
</div>
|
||||
</div>
|
||||
<partial name="Shared/_ReviewNavBar" />
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row mx-1 px-0 py-3">
|
||||
<div class="text-muted">
|
||||
<p> <strong> Usage Samples are not available for this APIView deployment. </strong></p>
|
||||
<p> Please check <a href="https://github.com/Azure/azure-sdk-tools/blob/main/src/dotnet/APIView/APIViewWeb/CONTRIBUTING.md">CONTRIBUTING.md</a> to see how to enable them. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="container-fluid mx-0 px-0 sub-header-content">
|
||||
<div class="row mx-1 px-0 py-2">
|
||||
<div class="col-md-8">
|
||||
<div class="input-group-sm input-group" id="review-info-bar">
|
||||
<partial name="Shared/_ReviewBadge" model="(Model.Review, default(APIRevisionListItemModel))"/>
|
||||
@if (Model.SampleRevisions.Any())
|
||||
{
|
||||
@if (Model.SampleContent.Length > 0)
|
||||
{
|
||||
<span class="input-group-text">Revision:</span>
|
||||
<select id="revision-select" aria-label="Revision Select">
|
||||
@foreach (var revision in Model.SampleRevisions)
|
||||
{
|
||||
var urlValue = @Url.ActionLink("Samples", "Assemblies", new
|
||||
{
|
||||
id = @Model.Review.Id,
|
||||
revisionId = @revision.FileId,
|
||||
});
|
||||
|
||||
string revTitle = revision.Title == null ? $"Created On {revision.CreatedOn}" : $"Created On: {revision.Title}";
|
||||
|
||||
if (revision.FileId == Model.ActiveSampleRevision.FileId)
|
||||
{
|
||||
<option selected value="@urlValue">@revTitle</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@urlValue">@revTitle</option>
|
||||
}
|
||||
}
|
||||
</select>
|
||||
}
|
||||
@if (Model.SampleContent.Length > 0)
|
||||
{
|
||||
<button type="button" class="btn btn-sm border shadow-sm btn-light" data-bs-toggle="modal" data-bs-target="#updateModel"><i class="fa-solid fa-pen-to-square"></i> Edit</button>
|
||||
@if (Model.ActiveSampleRevision.CreatedBy == User.GetGitHubLogin())
|
||||
{
|
||||
<button type="button" class="btn btn-sm shadow-sm btn-outline-danger" data-bs-toggle="modal" data-bs-target="#deleteModel"><i class="fas fa-times-circle"></i> Delete</button>
|
||||
}
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
</div>
|
||||
</div>
|
||||
<partial name="Shared/_ReviewNavBar" />
|
||||
</div>
|
||||
<div class="container-fluid" id="samples-main-container">
|
||||
<div class="row mx-0 px-0 py-2">
|
||||
<div class="col-lg-12 mx-0" data-review-id=@Model.Review.Id>
|
||||
<div id="add-sample-button">
|
||||
<button type="button" class="btn btn-primary" id="add-sample-button" data-bs-toggle="modal" data-bs-target="#uploadModel"><small>ADD</small><br><i class="fas fa-sm fa-plus"></i><br><small>SAMPLE</small></button>
|
||||
</div>
|
||||
<div class="container-fluid pt-2@(mainContainerClass)" id="samples-main-container">
|
||||
<div class="row mx-0 px-0">
|
||||
<div class="col-lg-12 mx-0 px-0" data-review-id=@Model.Review.Id>
|
||||
@if (Model.SampleRevisions.Any())
|
||||
{
|
||||
@if (Model.SampleContent.Length == 0)
|
||||
|
@ -113,7 +110,6 @@ else
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<i> Sample uploaded by <strong> <a username="@Model.ActiveSampleRevision.CreatedBy"> @Model.ActiveSampleRevision.CreatedBy </a></strong></i>
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -126,138 +122,73 @@ else
|
|||
<partial name="_SampleCommentFormPartial" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<partial name="Shared/_AddSamplesRevisionsPartial" model="Model.Review" />
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="modal fade" id="uploadModel" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Add Usage Sample</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Pick an upload method:</label>
|
||||
|
||||
<ul class="nav nav-pills nav-fill mb-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="home-tab" data-bs-toggle="tab" href="#md-text">Markdown Text</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="profile-tab" data-bs-toggle="tab" href="#md-file">Markdown File</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content border rounded px-3">
|
||||
<div class="tab-pane active pt-2" id="md-text">
|
||||
<form asp-page-handler="Upload" method="post">
|
||||
<div class="form-group ">
|
||||
<label asp-for="Upload.RevisionTitle"> Enter a sample title (Optional) </label>
|
||||
<input asp-for="Upload.RevisionTitle" class="form-control" type="text" /> <br />
|
||||
<textarea asp-for="Upload.sampleString" class="new-thread-comment-text form-control" rows="25" placeholder="Enter your markdown formatted usage sample here"></textarea>
|
||||
<input asp-for="Upload.ReviewId" hidden value="@Model.Review.Id" />
|
||||
<div class="d-flex flex-row-reverse pt-3 mb-3">
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;"><i class="fa-solid fa-floppy-disk"></i> Save</button>
|
||||
<button type="button" class="btn btn-outline-secondary me-1" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane pt-2" id="md-file">
|
||||
<form asp-page-handler="Upload" method="post" enctype="multipart/form-data">
|
||||
<label asp-for="Upload.RevisionTitle"> Enter a sample title (Optional) </label>
|
||||
<input asp-for="Upload.RevisionTitle" class="form-control" type="text" /> <br />
|
||||
<input asp-for="Upload.ReviewId" hidden value="@Model.Review.Id" />
|
||||
<div class="input-group mb-3 custom-file-label">
|
||||
<label for="uploadMarkdownSample" class="input-group-text small mb-0">Select usage sample for this review</label>
|
||||
<input asp-for="Upload.File" type="file" class="form-control" id="uploadMarkdownSample">
|
||||
</div>
|
||||
<div class="d-flex flex-row-reverse pt-3 mb-3">
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;"><i class="fas fa-cloud-upload-alt"></i> Upload</button>
|
||||
<button type="button" class="btn btn-outline-secondary me-1" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="offcanvas offcanvas-end border-start" tabindex="-1" id="edit-samples-context" aria-labelledby="edit-samples-context-label">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="offcanvasLabel">Update Usage Samples</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<form asp-page-handler="Upload" method="post">
|
||||
<div class="form-group">
|
||||
<div class="border rounded p-3">
|
||||
<label asp-for="Upload.RevisionTitle"> Enter a sample title (Optional) </label>
|
||||
<input asp-for="Upload.RevisionTitle" class="form-control" type="text" /> <br />
|
||||
<div class="edit-samples-content">
|
||||
<textarea asp-for="Upload.UpdateString" class="form-control" rows="25"></textarea>
|
||||
</div>
|
||||
<input asp-for="Upload.ReviewId" hidden value="@Model.Review.Id" />
|
||||
<input asp-for="Upload.Updating" hidden type="text" value="@true" />
|
||||
<p class="text-muted"> This will create a new revision of the sample. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-grid gap-2 my-2">
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="modal fade" id="deleteModel" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Delete Usage Sample</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="tab-content">
|
||||
<p class="text-center"> This action can not be undone. </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="form-group">
|
||||
<form asp-page-handler="Upload" method="post">
|
||||
<input asp-for="Upload.sampleString" hidden value="@null" />
|
||||
<input asp-for="Upload.ReviewId" hidden value="@Model.Review.Id" />
|
||||
<input asp-for="Upload.Deleting" hidden type="text" value="@true" />
|
||||
<input asp-for="Upload.SampleId" hidden type="text" value="@Model.ActiveSampleRevision.Id" />
|
||||
<input asp-for="Upload.FileId" hidden type="text" value="@Model.ActiveSampleRevision.FileId" />
|
||||
<button type="button" class="btn btn-outline-dark" data-dismiss="modal">Close</button>
|
||||
<button type="submit" name="submit" value="Submit" class="btn btn-outline-danger"><i class="fas fa-times-circle"></i> Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" id="deleteModel" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-sm" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Delete Usage Sample</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="tab-content">
|
||||
<p class="text-center"> This action can not be undone. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="modal fade" id="updateModel" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-footer">
|
||||
<div class="form-group">
|
||||
<form asp-page-handler="Upload" method="post">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Update Usage Sample</h5>
|
||||
<button type="button" class="close" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<div class="tab-content border rounded p-3">
|
||||
<div class="tab-pane active" id="md-text">
|
||||
<label asp-for="Upload.RevisionTitle"> Enter a sample title (Optional) </label>
|
||||
<input asp-for="Upload.RevisionTitle" class="form-control" type="text" /> <br />
|
||||
<div class="form-group">
|
||||
<div class="new-sample-content">
|
||||
<textarea asp-for="Upload.updateString" class="new-thread-comment-text form-control" rows="25"></textarea>
|
||||
</div>
|
||||
<input asp-for="Upload.ReviewId" hidden value="@Model.Review.Id" />
|
||||
<input asp-for="Upload.Updating" hidden type="text" value="@true" />
|
||||
</div>
|
||||
<p class="text-muted"> This will create a new revision of the sample. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-outline-dark" data-dismiss="modal">Close</button>
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;"><i class="fa-solid fa-pen-to-square"></i> Save</button>
|
||||
</div>
|
||||
<input asp-for="Upload.SampleString" hidden value="@null" />
|
||||
<input asp-for="Upload.ReviewId" hidden value="@Model.Review.Id" />
|
||||
<input asp-for="Upload.DeletingAndRedirect" hidden type="text" value="@true" />
|
||||
<input asp-for="Upload.SampleId" hidden type="text" value="@Model.ActiveSampleRevision.Id" />
|
||||
<input asp-for="Upload.FileId" hidden type="text" value="@Model.ActiveSampleRevision.FileId" />
|
||||
<button type="button" class="btn btn-outline-primary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="submit" name="submit" value="Submit" class="btn btn-outline-danger">Delete</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="offcanvas offcanvas-end border-start" tabindex="-1" id="samplesRevisions-context" aria-labelledby="samplesRevisions-contex-label">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="samplesRevisions-contex-label"><a asp-page="Revisions" asp-route-id="@Model.Review.Id">Revisions</a></h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<partial name="Shared/_SamplesRevisionsPartial" model="(Model.Review, Model.SampleRevisions, Model.ActiveSampleRevision)" />
|
||||
</div>
|
||||
</div>
|
|
@ -7,12 +7,14 @@ using ApiView;
|
|||
using APIView;
|
||||
using APIViewWeb.LeanModels;
|
||||
using APIViewWeb.Managers;
|
||||
using APIViewWeb.Managers.Interfaces;
|
||||
using APIViewWeb.Models;
|
||||
using APIViewWeb.Repositories;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Octokit;
|
||||
|
||||
namespace APIViewWeb.Pages.Assemblies
|
||||
{
|
||||
|
@ -58,13 +60,13 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
// This try-catch is for the case that the deployment is set up incorrectly for usage samples
|
||||
try
|
||||
{
|
||||
SampleRevisions = await _samplesRevisionsManager.GetSamplesRevisionsAsync(Review.Id);
|
||||
SampleRevisions = (await _samplesRevisionsManager.GetSamplesRevisionsAsync(Review.Id)).OrderBy(s => s.CreatedOn);
|
||||
|
||||
if (SampleRevisions != null && SampleRevisions.Any())
|
||||
{
|
||||
if (revisionId != null)
|
||||
{
|
||||
ActiveSampleRevision = SampleRevisions.Where(s => s.FileId == revisionId).First();
|
||||
ActiveSampleRevision = SampleRevisions.Where(s => s.Id == revisionId).First();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -74,7 +76,7 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
Comments = await _commentsManager.GetUsageSampleCommentsAsync(Review.Id);
|
||||
SampleContent = ParseLines(ActiveSampleRevision.FileId, Comments).Result;
|
||||
SampleOriginal = await _samplesRevisionsManager.GetSamplesRevisionContentAsync(ActiveSampleRevision.OriginalFileId);
|
||||
Upload.updateString = SampleOriginal;
|
||||
Upload.UpdateString = SampleOriginal;
|
||||
if (SampleContent == null)
|
||||
{
|
||||
// Potentially bad blob setup, potentially erroneous file fetch
|
||||
|
@ -115,32 +117,45 @@ namespace APIViewWeb.Pages.Assemblies
|
|||
|
||||
await AssertAccess(User);
|
||||
|
||||
var file = Upload.File;
|
||||
string sampleString = Upload.sampleString;
|
||||
string reviewId = Upload.ReviewId;
|
||||
string revisionTitle = Upload.RevisionTitle;
|
||||
SamplesRevisionModel sampleRevision = null;
|
||||
|
||||
if (file != null)
|
||||
if (Upload.File != null)
|
||||
{
|
||||
using (var openReadStream = file.OpenReadStream())
|
||||
using (var openReadStream = Upload.File.OpenReadStream())
|
||||
{
|
||||
await _samplesRevisionsManager.UpsertSamplesRevisionsAsync(User, reviewId, openReadStream, revisionTitle, file.FileName);
|
||||
sampleRevision = await _samplesRevisionsManager.UpsertSamplesRevisionsAsync(User, Upload.ReviewId, openReadStream, Upload.RevisionTitle, Upload.File.FileName);
|
||||
}
|
||||
}
|
||||
else if (sampleString != null)
|
||||
else if (Upload.SampleString != null)
|
||||
{
|
||||
await _samplesRevisionsManager.UpsertSamplesRevisionsAsync(User, reviewId, sampleString, revisionTitle);
|
||||
sampleRevision = await _samplesRevisionsManager.UpsertSamplesRevisionsAsync(User, Upload.ReviewId, Upload.SampleString, Upload.RevisionTitle);
|
||||
}
|
||||
else if (Upload.Updating)
|
||||
{
|
||||
await _samplesRevisionsManager.UpsertSamplesRevisionsAsync(User, reviewId, Upload.updateString, revisionTitle);
|
||||
sampleRevision = await _samplesRevisionsManager.UpsertSamplesRevisionsAsync(User, Upload.ReviewId, Upload.UpdateString, Upload.RevisionTitle);
|
||||
}
|
||||
else if (Upload.Deleting)
|
||||
else if (Upload.Deleting || Upload.DeletingAndRedirect)
|
||||
{
|
||||
await _samplesRevisionsManager.DeleteSamplesRevisionAsync(User, reviewId, Upload.SampleId);
|
||||
await _samplesRevisionsManager.DeleteSamplesRevisionAsync(User, Upload.ReviewId, Upload.SampleId);
|
||||
|
||||
if (Upload.Deleting)
|
||||
{
|
||||
return new NoContentResult();
|
||||
}
|
||||
return RedirectToPage();
|
||||
}
|
||||
else if (Upload.Renaming)
|
||||
{
|
||||
await _samplesRevisionsManager.UpdateSamplesRevisionTitle(Upload.ReviewId, Upload.SampleId, Upload.RevisionTitle);
|
||||
return Content(Upload.RevisionTitle);
|
||||
}
|
||||
|
||||
return RedirectToPage();
|
||||
if (sampleRevision != null)
|
||||
{
|
||||
return RedirectToPage(new { id = sampleRevision.ReviewId, revisionId = sampleRevision.Id });
|
||||
}
|
||||
return StatusCode(500);
|
||||
|
||||
}
|
||||
|
||||
private async Task<CodeLineModel[]> ParseLines(string fileId, ReviewCommentsModel comments)
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
@using APIViewWeb.Helpers
|
||||
@using APIViewWeb.LeanModels;
|
||||
@model (ReviewListItemModel review, IEnumerable<APIRevisionListItemModel> APIRevisions, APIRevisionListItemModel activeAPIRevision, APIRevisionListItemModel diffAPIRevision)
|
||||
<div class="row g-4">
|
||||
<div class="col mx-3">
|
||||
<form>
|
||||
<div class="d-grid gap-2">
|
||||
@if (Model.activeAPIRevision != null)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="offcanvas" data-bs-target="#add-apirevision-context" aria-controls="add-apirevision-context">Add APIRevision</button>
|
||||
}
|
||||
<div class="btn-group" role="group" aria-label="APIRevisions Select">
|
||||
<input type="checkbox" class="btn-check" id="manual-apirevisions-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="manual-apirevisions-check">Manual</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" id="automatic-apirevisions-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="automatic-apirevisions-check">Automatic</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" id="pullrequest-apirevisions-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="pullrequest-apirevisions-check">Pull Request</label>
|
||||
</div>
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text"><i class="fa-solid fa-magnifying-glass"></i></span>
|
||||
<input type="search" placeholder="Search.." class="form-control" id="apiRevisions-search" aria-label="apirevision search">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="api-revisions revisions-list-container p-2">
|
||||
@foreach (var apiRevision in Model.APIRevisions)
|
||||
{
|
||||
<div class="card @apiRevision.IsApproved my-2" data-id="@apiRevision.Id">
|
||||
<img username="@apiRevision.CreatedBy" size="105" aria-label="GitHub User Avatar" />
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">@apiRevision.Label</h6>
|
||||
@if (User.GetGitHubLogin() == apiRevision.CreatedBy)
|
||||
{
|
||||
<div class="input-group input-group-sm mb-1 edit-revision-label d-none">
|
||||
<input type="text" class="form-control" value="@apiRevision.Label" aria-label="Edit APIRevison Label">
|
||||
<button class="input-group-text enter-rename"><i class="bi bi-check"></i></button>
|
||||
<button class="input-group-text cancel-rename"><i class="bi bi-x"></i></button>
|
||||
</div>
|
||||
}
|
||||
<p class="card-subtitle mb-1 text-body-secondary"><b>Created: </b><span date="@apiRevision.CreatedOn"></span> , <b>By: </b>@apiRevision.CreatedBy</p>
|
||||
<p class="card-subtitle mb-0 text-body-secondary"><b>Last Updated: </b><span date="@apiRevision.LastUpdatedOn"></span> , <b>Type: </b>@apiRevision.APIRevisionType , <b>Version: </b>@apiRevision.Files[0].PackageVersion</p>
|
||||
</div>
|
||||
<div class="revision-actions">
|
||||
<div class="btn-group animate__animated animate__fadeIn" role="group" aria-label="apiRevision action buttons">
|
||||
@if (Model.activeAPIRevision != null)
|
||||
{
|
||||
@if (apiRevision.Id != Model.activeAPIRevision.Id && (Model.diffAPIRevision == null || Model.diffAPIRevision.Id != apiRevision.Id))
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-primary make-active" data-bs-toggle="tooltip" title="Make Active"><i class="bi bi-clock-history mr-1"></i></button>
|
||||
}
|
||||
@if ((Model.diffAPIRevision == null || Model.diffAPIRevision.Id != apiRevision.Id) && Model.activeAPIRevision.Id != apiRevision.Id)
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-primary make-diff" data-bs-toggle="tooltip" title="Make Diff"><i class="bi bi-file-diff mr-1"></i></button>
|
||||
}
|
||||
@if (Model.diffAPIRevision != null && apiRevision.Id == Model.diffAPIRevision.Id)
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-primary clear-diff" data-bs-toggle="tooltip" title="Clear Diff"><i class="bi bi-file-earmark-minus"></i></button>
|
||||
}
|
||||
|
||||
}
|
||||
@if (User.GetGitHubLogin() == apiRevision.CreatedBy)
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-primary rename" data-bs-toggle="tooltip" title="Rename"><i class="bi bi-pencil-square"></i></button>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary delete" data-bs-toggle="tooltip" title="Delete"><i class="bi bi-x-circle text-danger"></i></button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="revision-indicator-checks animate__animated animate__slideInLeft">
|
||||
@if (apiRevision.IsApproved)
|
||||
{
|
||||
<i class="fas fa-check-circle text-success mr-1"></i>
|
||||
}
|
||||
@if (Model.activeAPIRevision != null)
|
||||
{
|
||||
@if (apiRevision.Id == Model.activeAPIRevision.Id)
|
||||
{
|
||||
<i class="bi bi-clock-history active-rev mr-1"></i>
|
||||
}
|
||||
@if (Model.diffAPIRevision != null && Model.diffAPIRevision.Id == apiRevision.Id)
|
||||
{
|
||||
<i class="bi bi-file-diff diff-rev mr-1"></i>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="_AddAPIRevisionsPartial" model="Model.review" />
|
|
@ -0,0 +1,49 @@
|
|||
@using APIViewWeb.Helpers
|
||||
@using APIViewWeb.LeanModels;
|
||||
@model ReviewListItemModel
|
||||
|
||||
<div class="offcanvas offcanvas-end border-start" tabindex="-1" id="add-apirevision-context" aria-labelledby="add-apirevision-context-label">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="add-apirevision-context-label">Add APIRevision</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<form asp-page-handler="Upload" method="post" enctype="multipart/form-data">
|
||||
<div class="d-grid gap-2">
|
||||
@if (!(LanguageServiceHelpers.MapLanguageAliases(new List<string> { "TypeSpec" })).Contains(Model.Language))
|
||||
{
|
||||
<div class="input-group custom-file-label">
|
||||
<label class="input-group-text small" for="uploadRevisionFile">Select file to add</label>
|
||||
<input name="upload" for="upload" type="file" class="form-control" id="uploadRevisionFile">
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<ul class="nav nav-pills nav-fill" id="typespec-pills-tab" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link active" id="typespec-pills-tsp-tab" data-bs-toggle="pill" data-bs-target="#typespec-pills-tsp" type="button" role="tab" aria-controls="typespec-pills-tsp" aria-selected="true">TypeSpec</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" id="typespec-pills-json-tab" data-bs-toggle="pill" data-bs-target="#typespec-pills-json" type="button" role="tab" aria-controls="typespec-pills-json" aria-selected="false">Json</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content" id="typespec-pills-tabcontent">
|
||||
<div class="tab-pane fade show active" id="typespec-pills-tsp" role="tabpanel" aria-labelledby="typespec-pills-tsp-tab" tabindex="0">
|
||||
<div class="input-group custom-file-label">
|
||||
<label class="input-group-text small" for="uploadRevisionFile">Select file to add</label>
|
||||
<input name="upload" for="upload" type="file" class="form-control" id="uploadRevisionFile">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="typespec-pills-json" role="tabpanel" aria-labelledby="typespec-pills-json-tab" tabindex="0">
|
||||
<input name="filePath" for="filePath" class="form-control" type="text" placeholder="Package root e.g https://github.com/Azure/azure-rest-api-specs/specification/cognitiveservices/AnomalyDetector/">
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
<div>
|
||||
<input name="label" for="label" class="form-control" type="text" placeholder="Enter an optional revision label">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;">Upload</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,58 @@
|
|||
@using APIViewWeb.Helpers;
|
||||
@using APIViewWeb.LeanModels;
|
||||
@using APIViewWeb.Pages.Assemblies;
|
||||
@model ReviewListItemModel
|
||||
|
||||
<div class="offcanvas offcanvas-end border-start" tabindex="-1" id="upload-samples-context" aria-labelledby="upload-samples-contextt-label">
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="offcanvasLabel">Add Usage Samples</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<div class="form-group">
|
||||
<label>Pick an upload method:</label>
|
||||
|
||||
<ul class="nav nav-pills nav-fill mb-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="home-tab" data-bs-toggle="tab" href="#md-text">Markdown Text</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="profile-tab" data-bs-toggle="tab" href="#md-file">Markdown File</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content border rounded px-3">
|
||||
<div class="tab-pane active pt-2" id="md-text">
|
||||
<form asp-page="Samples" asp-page-handler="Upload" method="post">
|
||||
<div class="form-group ">
|
||||
<label for="uploadSamplesRevisionTitleA">Enter a sample title (Optional) </label>
|
||||
<input name="RevisionTitle" id="uploadSamplesRevisionTitleA" class="form-control" type="text" /> <br />
|
||||
<div class="edit-samples-content">
|
||||
<textarea name="SampleString" class="form-control" rows="25" placeholder="Enter your markdown formatted usage sample here"></textarea>
|
||||
</div>
|
||||
<input name="ReviewId" hidden value="@Model.Id" />
|
||||
<div class="d-grid gap-2 my-2">
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="tab-pane pt-2" id="md-file">
|
||||
<form asp-page-handler="Upload" method="post" enctype="multipart/form-data">
|
||||
<label for="uploadSamplesRevisionTitleB"> Enter a sample title (Optional) </label>
|
||||
<input name="RevisionTitle" id="uploadSamplesRevisionTitleB" class="form-control" type="text" /> <br />
|
||||
<input name="ReviewId" hidden value="@Model.Id" />
|
||||
<div class="input-group mb-3 custom-file-label">
|
||||
<label for="uploadMarkdownSample" class="input-group-text small mb-0">Select usage sample for this review</label>
|
||||
<input name="File" type="file" class="form-control" id="uploadMarkdownSample">
|
||||
</div>
|
||||
<div class="d-grid gap-2 my-2">
|
||||
<button type="submit" class="btn btn-primary" onclick="this.form.submit(); this.disabled = true;">Upload</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -17,6 +17,7 @@
|
|||
crossorigin="anonymous"
|
||||
integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" />
|
||||
</environment>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" />
|
||||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css"/>
|
||||
<!-- Soma Select -->
|
||||
|
@ -46,9 +47,6 @@
|
|||
<div class="navbar-collapse collapse">
|
||||
<ul class="navbar-nav me-auto">
|
||||
@if (User.Identity.IsAuthenticated) {
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" asp-area="" asp-page="/Assemblies/Index">Reviews</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<span asp-resource="@Model" asp-requirement="@ApproverRequirement.Instance">
|
||||
<a class="nav-link" asp-area="" asp-page="/Assemblies/RequestedReviews">Requested Reviews</a>
|
||||
|
|
|
@ -3,39 +3,83 @@
|
|||
@using System.Text.RegularExpressions;
|
||||
@using APIViewWeb.Helpers;
|
||||
@using APIViewWeb.LeanModels;
|
||||
@model (ReviewListItemModel review, APIRevisionListItemModel activeRevision);
|
||||
@{
|
||||
var packageName = Model.review.PackageName;
|
||||
}
|
||||
@if (Model.review.Language != null)
|
||||
{
|
||||
string iconClassName = "icon-" + PageModelHelpers.GetLanguageCssSafeName(Model.review.Language);
|
||||
string langVariant = String.Empty;
|
||||
@if (Model.activeRevision != default(APIRevisionListItemModel) && !string.IsNullOrEmpty(Model.activeRevision.Files.First().LanguageVariant) && Model.activeRevision.Files.First().LanguageVariant.ToLower() != "default")
|
||||
@using APIViewWeb.Models
|
||||
@model (ReviewListItemModel review, APIRevisionListItemModel activeAPIRevision, APIRevisionListItemModel diffAPIRevision, UserPreferenceModel userPreference);
|
||||
|
||||
<div class="col-md-11">
|
||||
<nav style="--bs-breadcrumb-divider: '-';" aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
@{
|
||||
string iconClassName = "icon-" + PageModelHelpers.GetLanguageCssSafeName(Model.review.Language);
|
||||
string langVariant = String.Empty;
|
||||
}
|
||||
@if (Model.activeAPIRevision != null && !string.IsNullOrEmpty(Model.activeAPIRevision.Files.First().LanguageVariant) && Model.activeAPIRevision.Files.First().LanguageVariant.ToLower() != "default")
|
||||
{
|
||||
langVariant = @Model.activeAPIRevision.Files.First().LanguageVariant.ToLower();
|
||||
iconClassName += "-" + @Model.activeAPIRevision.Files.First().LanguageVariant.ToLower();
|
||||
}
|
||||
<li class="breadcrumb-item"><span role="img" class="icon-language @iconClassName" aria-label="@Model.review.Language @langVariant"></span> @Model.review.PackageName</li>
|
||||
@if (Model.review.IsApproved)
|
||||
{
|
||||
<li class="breadcrumb-item" data-bs-toggle="tooltip" title="Approved for First Release"><i class="fa-regular fa-circle-check text-success"></i></li>
|
||||
}
|
||||
@if (Model.activeAPIRevision != null)
|
||||
{
|
||||
<li class="breadcrumb-item"><i class="bi bi-clock-history"></i> @PageModelHelpers.ResolveRevisionLabel(Model.activeAPIRevision, false)</li>
|
||||
@if (Model.activeAPIRevision.IsApproved)
|
||||
{
|
||||
<li class="breadcrumb-item" data-bs-toggle="tooltip" title="APIRevision is Approved"><i class="fa-regular fa-circle-check text-success"></i></li>
|
||||
}
|
||||
}
|
||||
@if (Model.diffAPIRevision != null)
|
||||
{
|
||||
<li class="breadcrumb-item"><i class="bi bi-file-diff"></i> @PageModelHelpers.ResolveRevisionLabel(Model.diffAPIRevision, false)</li>
|
||||
@if (Model.diffAPIRevision.IsApproved)
|
||||
{
|
||||
<li class="breadcrumb-item" data-bs-toggle="tooltip" title="Diff APIRevision is Approved"><i class="fa-regular fa-circle-check text-success"></i></li>
|
||||
}
|
||||
}
|
||||
</ol>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="col-1">
|
||||
@if (TempData["page"].Equals("api"))
|
||||
{
|
||||
langVariant = @Model.activeRevision.Files.First().LanguageVariant.ToLower();
|
||||
iconClassName += "-" + @Model.activeRevision.Files.First().LanguageVariant.ToLower();
|
||||
if (Model.userPreference != null && Model.userPreference.HideReviewPageOptions.HasValue && Model.userPreference.HideReviewPageOptions == true)
|
||||
{
|
||||
<input type="checkbox" class="btn-check" id="review-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="checkbox" checked class="btn-check" id="review-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
<label class="btn btn-sm btn-outline-primary float-end" accesskey="m" for="review-right-offcanvas-toggle"><i class="fa fa-bars"></i></label>
|
||||
}
|
||||
<span role="img" class="input-group-text icon-language @iconClassName" aria-label="@Model.review.Language @langVariant"></span>
|
||||
}
|
||||
@{
|
||||
var packageFieldWidth = 3;
|
||||
if (packageName != null)
|
||||
@if (TempData["page"].Equals("revisions"))
|
||||
{
|
||||
packageFieldWidth += packageName.Length;
|
||||
if (Model.userPreference != null && Model.userPreference.HideRevisionsPageOptions.HasValue && Model.userPreference.HideRevisionsPageOptions == true)
|
||||
{
|
||||
<input type="checkbox" class="btn-check" id="revisions-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="checkbox" checked class="btn-check" id="revisions-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
<label class="btn btn-sm btn-outline-primary float-end" accesskey="m" for="revisions-right-offcanvas-toggle"><i class="fa fa-bars"></i></label>
|
||||
}
|
||||
}
|
||||
<input type="text" class="form-control fw-bold" style="max-width: @(packageFieldWidth)ch; font-family: monospace;" value="@(packageName ?? "")" aria-label="Package Name of Review" readonly>
|
||||
@if (packageName != null)
|
||||
{
|
||||
@if (Model.review.IsApproved)
|
||||
@if (TempData["page"].Equals("samples"))
|
||||
{
|
||||
<span class="input-group-text" data-bs-toggle="tooltip" title="Approved for First Release">
|
||||
<i class="fa-regular fa-circle-check text-success"></i>
|
||||
</span>
|
||||
if (Model.userPreference != null && Model.userPreference.HideSamplesPageOptions.HasValue && Model.userPreference.HideSamplesPageOptions == true)
|
||||
{
|
||||
<input type="checkbox" class="btn-check" id="samples-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="checkbox" checked class="btn-check" id="samples-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
<label class="btn btn-sm btn-outline-primary float-end" accesskey="m" for="samples-right-offcanvas-toggle"><i class="fa fa-bars"></i></label>
|
||||
}
|
||||
}
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
@using APIViewWeb.Models
|
||||
@{
|
||||
var id = ViewContext.RouteData.Values["id"];
|
||||
var userPreference = TempData["UserPreference"] as UserPreferenceModel;
|
||||
}
|
||||
|
||||
<div class="row mx-1 p-0 mt-0 border-bottom">
|
||||
<nav class="navbar pt-0">
|
||||
<ul class="nav nav-pills">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" active-if="@TempData["page"].Equals("api")" asp-page="Review" asp-route-id="@id">API</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" active-if="@TempData["page"].Equals("conversation")" asp-page="Conversation" asp-route-id="@id">Conversations</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" active-if="@TempData["page"].Equals("revisions")" asp-page="Revisions" asp-route-id="@id">Revisions</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" active-if="@TempData["page"].Equals("samples")" asp-page="Samples" asp-route-id="@id">Usage Samples</a>
|
||||
</li>
|
||||
</ul>
|
||||
@if (TempData["page"].Equals("api"))
|
||||
{
|
||||
if (userPreference.HideReviewPageOptions.HasValue && userPreference.HideReviewPageOptions == true)
|
||||
{
|
||||
<input type="checkbox" class="btn-check" id="review-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
else
|
||||
{
|
||||
<input type="checkbox" checked class="btn-check" id="review-right-offcanvas-toggle" autocomplete="off">
|
||||
}
|
||||
<label class="btn btn-sm btn-outline-primary float-end" accesskey="m" for="review-right-offcanvas-toggle"><i class="fa fa-bars"></i> Options</label>
|
||||
}
|
||||
</nav>
|
||||
</div>
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
@using APIViewWeb.Helpers;
|
||||
@using APIViewWeb.LeanModels;
|
||||
@using APIViewWeb.Models
|
||||
|
@ -27,16 +26,16 @@
|
|||
@if (review.Language != null)
|
||||
{
|
||||
string iconClassName = "icon-" + PageModelHelpers.GetLanguageCssSafeName(@review.Language);
|
||||
<span role="img" class="mx-1 icon icon-language @iconClassName" aria-label="@review.Language"></span>
|
||||
<span role="img" class="m-1 icon icon-language @iconClassName" aria-label="@review.Language"></span>
|
||||
}
|
||||
<a class="review-name align-middle" asp-page="./Review" asp-route-id="@review.Id">@review.PackageName.Substring(0, @truncationIndex)</a>
|
||||
@*
|
||||
Disabling approval (first release / Package name approval) for now as it is of no benefit to users
|
||||
@if (review.IsApproved == true)
|
||||
{
|
||||
<i class="fas fa-check-circle text-success ml-2"></i>
|
||||
}
|
||||
*@
|
||||
Disabling approval (first release / Package name approval) for now as it is of no benefit to users
|
||||
@if (review.IsApproved == true)
|
||||
{
|
||||
<i class="fas fa-check-circle text-success ml-2"></i>
|
||||
}
|
||||
*@
|
||||
</td>
|
||||
<td class="align-middle cst-bdr-left ps-3">
|
||||
<a username="@review.CreatedBy">@review.CreatedBy</a>
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
|
||||
@using APIViewWeb.Helpers
|
||||
@using APIViewWeb.LeanModels
|
||||
@using APIViewWeb.Models
|
||||
@model (IEnumerable<APIRevisionListItemModel> revisions, APIRevisionListItemModel activeRevision, APIRevisionListItemModel diffRevision, bool forDiff, bool showDocumentation, bool showDiffOnly)
|
||||
|
||||
@if (@Model.revisions.Any())
|
||||
{
|
||||
var selectedRevisionLabel = String.Empty;
|
||||
if (!@Model.forDiff && @Model.activeRevision != default(APIRevisionListItemModel))
|
||||
{
|
||||
selectedRevisionLabel = PageModelHelpers.ResolveRevisionLabel(@Model.activeRevision, false);
|
||||
}
|
||||
else if (@Model.diffRevision != default(APIRevisionListItemModel))
|
||||
{
|
||||
selectedRevisionLabel = PageModelHelpers.ResolveRevisionLabel(@Model.diffRevision, false);
|
||||
}
|
||||
|
||||
if (String.IsNullOrEmpty(selectedRevisionLabel))
|
||||
{
|
||||
<option selected value=""></option>
|
||||
}
|
||||
|
||||
@foreach (var revision in @Model.revisions)
|
||||
{
|
||||
var optionClass = (revision.IsApproved) ? "option-approved" : "option-pending";
|
||||
|
||||
var urlValue = @Url.ActionLink("Review", "Assemblies", new
|
||||
{
|
||||
id = revision.ReviewId,
|
||||
revisionId = @revision.Id,
|
||||
doc = @Model.showDocumentation
|
||||
});
|
||||
|
||||
if (Model.forDiff)
|
||||
{
|
||||
urlValue = @Url.ActionLink("Review", "Assemblies", new
|
||||
{
|
||||
id = revision.ReviewId,
|
||||
revisionId = @Model.activeRevision.Id,
|
||||
diffOnly = Model.showDiffOnly,
|
||||
doc = @Model.showDocumentation,
|
||||
diffRevisionId = @revision.Id
|
||||
});
|
||||
}
|
||||
|
||||
var revisionLabel = PageModelHelpers.ResolveRevisionLabel(@revision, false);
|
||||
|
||||
if (!String.IsNullOrEmpty(selectedRevisionLabel) && revisionLabel == selectedRevisionLabel)
|
||||
{
|
||||
<option selected value="@urlValue" class="@optionClass">@revisionLabel</option>
|
||||
}
|
||||
else
|
||||
{
|
||||
<option value="@urlValue" class="@optionClass">@revisionLabel</option>
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
<div id="js-comment-form-template" class="d-none">
|
||||
<div id="js-comment-form-template" class="d-none">
|
||||
<div class="comment-form border-top new-thread-comment">
|
||||
<form data-post-update="comments" class="new-thread-comment-form comment" method="post" asp-controller="Comments" asp-action="Add">
|
||||
<div class="new-comment-content">
|
||||
<textarea class="new-thread-comment-text form-control" name="commentText" rows="3" placeholder="Click Add Comment or press Ctrl+Enter to add your comment."></textarea>
|
||||
</div>
|
||||
<input name="usageSampleComment" value="true" hidden type="text" />
|
||||
<button type="submit" name="submit" value="Submit" class="comment-submit-button btn btn-outline-dark">Add Comment</button>
|
||||
<button type="button" name="cancel" value="Cancel" class="comment-cancel-button btn btn-outline-dark">Cancel</button>
|
||||
<input type="checkbox" name="resolutionLock" checked class="custom-checkbox btn-outline-dark" />
|
||||
<button type="submit" name="submit" value="Submit" class="comment-submit-button btn btn-outline-secondary">Add Comment</button>
|
||||
<button type="button" name="cancel" value="Cancel" class="comment-cancel-button btn btn-outline-secondary">Cancel</button>
|
||||
<input type="checkbox" name="resolutionLock" checked class="custom-checkbox btn-outline-secondary" />
|
||||
<label for="resolutionLock" class="text-muted small"> Allow anyone to resolve conversation </label>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -20,8 +20,8 @@
|
|||
</div>
|
||||
<input type="hidden" class="js-comment-id" name="commentId" />
|
||||
<input name="usageSampleComment" value="@true" hidden type="text" />
|
||||
<button type="submit" name="submit" value="Submit" class="comment-submit-button btn btn-outline-dark">Save</button>
|
||||
<button type="button" name="cancel" value="Cancel" class="comment-cancel-button btn btn-outline-dark">Cancel</button>
|
||||
<button type="submit" name="submit" value="Submit" class="comment-submit-button btn btn-outline-secondary">Save</button>
|
||||
<button type="button" name="cancel" value="Cancel" class="comment-cancel-button btn btn-outline-secondary">Cancel</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,84 @@
|
|||
@using APIViewWeb.Helpers
|
||||
@using APIViewWeb.LeanModels;
|
||||
@using APIViewWeb.Pages.Assemblies
|
||||
@model (ReviewListItemModel review, IEnumerable<SamplesRevisionModel> samplesRevisions, SamplesRevisionModel activeSamplesRevision)
|
||||
<div class="row g-4">
|
||||
<div class="col mx-3">
|
||||
<form>
|
||||
<div class="d-grid gap-2">
|
||||
@if (Model.activeSamplesRevision != null)
|
||||
{
|
||||
<button type="button" class="btn btn-primary" data-bs-toggle="offcanvas" data-bs-target="#upload-samples-context" aria-controls="upload-samples-context">Add Samples Revision</button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="btn-group invisible" role="group" aria-label="Samples Revisions Select"> @*Added for asthetics*@
|
||||
<input type="checkbox" class="btn-check" id="manual-apirevisions-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="manual-apirevisions-check">Manual</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" id="automatic-apirevisions-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="automatic-apirevisions-check">Automatic</label>
|
||||
|
||||
<input type="checkbox" class="btn-check" id="pullrequest-apirevisions-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="pullrequest-apirevisions-check">Pull Request</label>
|
||||
</div>
|
||||
}
|
||||
@if (Model.samplesRevisions.Any())
|
||||
{
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text"><i class="fa-solid fa-magnifying-glass"></i></span>
|
||||
<input type="search" placeholder="Search.." class="form-control" id="samplesRevisions-search" aria-label="samplesrevision search">
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="samples-revisions revisions-list-container p-2">
|
||||
@foreach (var samplesRevision in Model.samplesRevisions)
|
||||
{
|
||||
<div class="card my-2" data-id="@samplesRevision.Id">
|
||||
<img username="@samplesRevision.CreatedBy" size="105" aria-label="GitHub User Avatar" />
|
||||
<div class="card-body">
|
||||
<h6 class="card-title">@samplesRevision.Title</h6>
|
||||
@if (User.GetGitHubLogin() == samplesRevision.CreatedBy)
|
||||
{
|
||||
<div class="input-group input-group-sm mb-1 edit-revision-label d-none">
|
||||
<input type="text" class="form-control" value="@samplesRevision.Title" aria-label="Edit Samples Revision Label">
|
||||
<button class="input-group-text enter-rename"><i class="bi bi-check"></i></button>
|
||||
<button class="input-group-text cancel-rename"><i class="bi bi-x"></i></button>
|
||||
</div>
|
||||
}
|
||||
<p class="card-subtitle mb-1 text-body-secondary"><b>Created: </b><span date="@samplesRevision.CreatedOn"></span> , <b>By: </b>@samplesRevision.CreatedBy</p>
|
||||
</div>
|
||||
<div class="revision-actions">
|
||||
<div class="btn-group animate__animated animate__fadeIn" role="group" aria-label="Samples Revision action buttons">
|
||||
@if (Model.activeSamplesRevision != null)
|
||||
{
|
||||
@if (samplesRevision.Id != Model.activeSamplesRevision.Id)
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-primary make-active" data-bs-toggle="tooltip" title="Make Active"><i class="bi bi-puzzle"></i></button>
|
||||
}
|
||||
}
|
||||
@if (User.GetGitHubLogin() == samplesRevision.CreatedBy)
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-outline-primary rename" data-bs-toggle="tooltip" title="Rename"><i class="bi bi-pencil-square"></i></button>
|
||||
<button type="button" class="btn btn-sm btn-outline-primary delete" data-bs-toggle="tooltip" title="Delete"><i class="bi bi-x-circle text-danger"></i></button>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="revision-indicator-checks animate__animated animate__slideInLeft">
|
||||
@if (Model.activeSamplesRevision != null)
|
||||
{
|
||||
@if (samplesRevision.Id == Model.activeSamplesRevision.Id)
|
||||
{
|
||||
<i class="bi bi-puzzle active-rev mr-1"></i>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<partial name="Shared/_AddSamplesRevisionsPartial" model="@Model.review" />
|
|
@ -27,17 +27,12 @@ using APIView.Identity;
|
|||
using APIViewWeb.Managers;
|
||||
using APIViewWeb.Hubs;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.AspNetCore.Mvc.ApplicationParts;
|
||||
using APIViewWeb.LeanControllers;
|
||||
using APIViewWeb.MiddleWare;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using System.IO;
|
||||
using Microsoft.Azure.Cosmos;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
using APIViewWeb.Helpers;
|
||||
using APIViewWeb.Managers.Interfaces;
|
||||
using WebMarkupMin.AspNetCore7;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче