Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
APIRevisions Search and Filter
  • Loading branch information
chidozieononiwu committed Mar 5, 2024
commit 8d2d7a00c999220d3f3995e3aab2855eaebea8f1
15 changes: 10 additions & 5 deletions src/dotnet/APIView/APIViewWeb/Client/css/pages/review.scss
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#review-left {
max-width: none;
min-width: 10px;
height: calc(100vh - 155px);
height: calc(100vh - 130px);
overflow: auto;
max-height: 100vh;
padding: 5px 0px 5px 10px;
Expand All @@ -32,7 +32,7 @@
#review-right {
max-width: 100%;
min-width: 100px;
height: calc(100vh - 155px);
height: calc(100vh - 130px);
padding: 0px;
overflow: auto;
background-color: var(--base-fg-color);
Expand Down Expand Up @@ -64,15 +64,20 @@
}
}

#apiRevisions-context, #conversiations-context {
width: 40dvw;
#apiRevisions-context, #conversiations-context, #add-apirevision-context {
width: 50dvw;
background-color: var(--base-bg-color);
}
#add-apirevision-context {
width: 30dvw;
background-color: var(--base-bg-color);
}

#apiRevisions-context {
.card {
flex-direction: row;
overflow: hidden;
background-color: var(--base-fg-color);

img {
width: 105px;
Expand All @@ -87,7 +92,7 @@

.apiRevisions-list-container {
overflow: auto;
height: 83dvh;
height: 80dvh;

.btn-group-vertical {
align-self: center;
Expand Down
6 changes: 4 additions & 2 deletions src/dotnet/APIView/APIViewWeb/Client/css/shared/layout.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -144,6 +144,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;
Expand Down
6 changes: 3 additions & 3 deletions src/dotnet/APIView/APIViewWeb/Client/css/shared/mixins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
}

@mixin review-offcanvas-menu-content {
min-height: calc(100vh - 135px);
max-height: calc(100vh - 135px);
min-height: calc(100vh - 110px);
max-height: calc(100vh - 110px);
overflow-y: auto;
margin-top: 95px;
margin-top: 80px;
}

@mixin review-approval-border {
Expand Down
148 changes: 148 additions & 0 deletions src/dotnet/APIView/APIViewWeb/Client/src/pages/revisions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import * as hp from "../shared/helpers";

$(() => {
const apiRevisionsSearchBox = $("#apiRevisions-search");
const apiRevisionsSearchContext = $(".apiRevisions-list-container .card-body");
const apiRevisionTypeFilter = ["#manual-apirevisions-check", "#automatic-apirevisions-check", "#pullrequest-apirevisions-check"];

$(document).on("click", ".revision-rename-icon", e => {
toggleNameField($(e.target));
});
Expand All @@ -16,4 +22,146 @@ $(() => {
renameIcon.toggle();
renameIcon.siblings(".revision-name-input").toggle();
}

function makeActiveAPIRevisionEventHandler(event) {
const trigger = $(event.target);
const activeCard = $(".apiRevisions-list-container .bi.bi-clock-history").closest(".card");
activeCard.find(".bi.bi-clock-history").remove();
activeCard.find(".btn-group-vertical").append(`<button type="button" class="btn btn-sm btn-outline-primary make-active">Make Active</button>`);
activeCard.find(".btn-group-vertical").append(`<button type="button" class="btn btn-sm btn-outline-primary make-diff">Make Diff</button>`);

activeCard.find(".btn-group-vertical .make-active").on("click", makeActiveAPIRevisionEventHandler);
activeCard.find(".btn-group-vertical .make-diff").on("click", makeDiffAPIRevisionEventHandler);

trigger.closest(".card").children(".apirevision-indicator-checks").append(`<i class="bi bi-clock-history mr-1"></i>`);
trigger.siblings(".make-diff").remove();
trigger.remove();
}

function makeDiffAPIRevisionEventHandler(event) {
const trigger = $(event.target);
const diffCard = $(".apiRevisions-list-container .bi.bi-file-diff").closest(".card");
diffCard.find(".bi.bi-file-diff").remove();
diffCard.find(".btn-group-vertical").append(`<button type="button" class="btn btn-sm btn-outline-primary make-active">Make Active</button>`);
diffCard.find(".btn-group-vertical").append(`<button type="button" class="btn btn-sm btn-outline-primary make-diff">Make Diff</button>`);

diffCard.find(".btn-group-vertical .make-active").on("click", makeActiveAPIRevisionEventHandler);
diffCard.find(".btn-group-vertical .make-diff").on("click", makeDiffAPIRevisionEventHandler);

trigger.closest(".card").children(".apirevision-indicator-checks").append(`<i class="bi bi-file-diff mr-1"></i>`);
trigger.siblings(".make-active").remove();
trigger.remove();
}
function clearDiffAPIRevisionEventHandler(event) {
const trigger = $(event.target);
const diffCard = $(".apiRevisions-list-container .bi.bi-file-diff").closest(".card");
diffCard.find(".bi.bi-file-diff").remove();
trigger.closest(".btn-group-vertical").append(`<button type="button" class="btn btn-sm btn-outline-primary make-active">Make Active</button>`);
trigger.closest(".btn-group-vertical").append(`<button type="button" class="btn btn-sm btn-outline-primary make-diff">Make Diff</button>`);

diffCard.find(".btn-group-vertical .make-active").on("click", makeActiveAPIRevisionEventHandler);
diffCard.find(".btn-group-vertical .make-diff").on("click", makeDiffAPIRevisionEventHandler);

trigger.remove();
}


/* MANAGE APIREVISIONS IN CONTEXT OF REVIEW PAGE
--------------------------------------------------------------------------------------------------------------------------------------------------------*/

// Toggle active class for left side offcanvas buttons
["#apiRevisions-context", "#add-apirevision-context"].forEach(function (value, index) {
$(value).on("shown.bs.offcanvas", function () {
$("#left-review-offcanvas-menu-content").find('[data-bs-original-title="API"]').removeClass("active");
$("#left-review-offcanvas-menu-content").find('[data-bs-target="#apiRevisions-context"]').addClass("active");
})

$(value).on("hidden.bs.offcanvas", function (event) {
$("#left-review-offcanvas-menu-content").find('[data-bs-original-title="API"]').addClass("active");
$("#left-review-offcanvas-menu-content").find('[data-bs-target="#apiRevisions-context"]').removeClass("active");
event.stopPropagation();
})

if (value == "#apiRevisions-context") {
$(value).on("hide.bs.offcanvas", function (event) {
const activeRevisionId = $(".apiRevisions-list-container .bi.bi-clock-history").closest(".card").attr("data-id");
let diffRevisionId = "";
const diffIcon = $(".apiRevisions-list-container .bi.bi-file-diff");
if (diffIcon.length > 0) {
diffRevisionId = diffIcon.closest(".card").attr("data-id")!;
}

const url = new URL(window.location.href);
url.searchParams.set("revisionId", activeRevisionId!);
if (diffRevisionId) {
url.searchParams.set("diffRevisionId", diffRevisionId!);
}
else {
url.searchParams.delete("diffRevisionId");
}
if (window.location.href != url.href) {
window.location.href = url.href;
}
});
}
});

$("#conversiations-context").on("hidden.bs.offcanvas", function () {
$("#left-review-offcanvas-menu-content").find('[data-bs-original-title="API"]').addClass("active");
$("#left-review-offcanvas-menu-content").find('[data-bs-target="#conversiations-context"]').removeClass("active");
});

$("#conversiations-context").on("shown.bs.offcanvas", function () {
$("#left-review-offcanvas-menu-content").find('[data-bs-original-title="API"]').removeClass("active");
$("#left-review-offcanvas-menu-content").find('[data-bs-target="#conversiations-context"]').addClass("active");
});

// Search / Filter APIRevisions
apiRevisionsSearchBox.on("input", function () {
apiRevisionTypeFilter.forEach(function (value, index) {
$(value).removeAttr('checked');
});
const searchText = (apiRevisionsSearchBox.val() as string).toUpperCase();
(<any>apiRevisionsSearchContext.closest(".card").show()).unmark();

if (searchText) {
(<any>apiRevisionsSearchContext).mark(searchText, {
done: function () {
apiRevisionsSearchContext.not(":has(mark)").closest(".card").hide();
}
})
}
});

// 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)) {
$(".apiRevisions-list-container .card").show();
}
else {
$(".apiRevisions-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
$(".apiRevisions-list-container .card .btn.make-active").on("click", makeActiveAPIRevisionEventHandler);
$(".apiRevisions-list-container .card .btn.make-diff").on("click", makeDiffAPIRevisionEventHandler);
$(".apiRevisions-list-container .card .btn.clear-diff").on("click", clearDiffAPIRevisionEventHandler);
});
63 changes: 56 additions & 7 deletions src/dotnet/APIView/APIViewWeb/Pages/Assemblies/Review.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -597,7 +597,7 @@
<div class="row g-4">
<div class="col mx-3">
<div class="d-grid gap-2">
<button type="button" class="btn btn-primary">Add Revision</button>
<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>
Expand All @@ -610,13 +610,13 @@
</div>
<div class="input-group mb-3">
<span class="input-group-text"><i class="fa-solid fa-magnifying-glass"></i></span>
<input type="text" class="form-control" id="apiRevisions-search" aria-label="apirevision search">
<input type="search" placeholder="Search.." class="form-control" id="apiRevisions-search" aria-label="apirevision search">
</div>
</div>
<div class="apiRevisions-list-container pe-2">
@foreach (var apiRevision in Model.ReviewContent.APIRevisions)
{
<div class="card @apiRevision.IsApproved my-2">
<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>
Expand All @@ -626,16 +626,19 @@
<div class="btn-group-vertical animate__animated animate__fadeIn" role="group" aria-label="apiRevision action buttons">
@if (apiRevision.Id != Model.ReviewContent.ActiveAPIRevision.Id && (Model.ReviewContent.DiffAPIRevision == null || Model.ReviewContent.DiffAPIRevision.Id != apiRevision.Id))
{
<button type="button" class="btn btn-sm btn-outline-primary">Make Active</button>
<button type="button" class="btn btn-sm btn-outline-primary make-active">Make Active</button>
}

@if ((Model.ReviewContent.DiffAPIRevision == null || Model.ReviewContent.DiffAPIRevision.Id != apiRevision.Id) && Model.ReviewContent.ActiveAPIRevision.Id != apiRevision.Id)
{
<button type="button" class="btn btn-sm btn-outline-primary">Make Diff</button>
<button type="button" class="btn btn-sm btn-outline-primary make-diff">Make Diff</button>
}
@if (Model.ReviewContent.DiffAPIRevision != null && apiRevision.Id == Model.ReviewContent.DiffAPIRevision.Id)
{
<button type="button" class="btn btn-sm btn-outline-primary clear-diff">Clear Diff</button>
}
@if (User.GetGitHubLogin() == apiRevision.CreatedBy)
{
<button type="button" class="btn btn-sm btn-outline-danger">Delete</button>
<button type="button" class="btn btn-sm btn-outline-danger delete">Delete</button>
}
</div>
<div class="apirevision-indicator-checks animate__animated animate__slideInLeft">
Expand Down Expand Up @@ -668,4 +671,50 @@
<div class="offcanvas-body">
Content for the offcanvas goes here. You can place just about any Bootstrap component or custom elements here.
</div>
</div>

<div class="offcanvas offcanvas-end" 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.ReviewContent.Review.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 asp-for="AddAPIRevisionFilePath" 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="AddAPIRevisionLabel" 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;"><i class="fas fa-cloud-upload-alt"></i> Upload</button>
</div>
</form>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public ReviewPageModel(
public bool ShowDiffOnly { get; set; }
[BindProperty(Name = "notificationMessage", SupportsGet = true)]
public string NotificationMessage { get; set; }
[FromForm]
public string AddAPIRevisionFilePath { get; set; }
[FromForm]
public string AddAPIRevisionLabel { get; set; }

/// <summary>
/// Handler for loading page
Expand Down