Skip to content

Commit

Permalink
072924.01/api revision meta data (#8720)
Browse files Browse the repository at this point in the history
* Refactor Models into Separate Files. Get Tests to all pass

* All Tests Green

* Move Projects to DotNET 8

* Switch back to net 7

* Resolve Bug in First Release Approval Button

* Remove rougue file

* Update APIRevisionsMetaData Logic

* Add Tests for AzureEngSemanticVersion
  • Loading branch information
chidozieononiwu authored Jul 31, 2024
1 parent a09e26d commit cc04af0
Show file tree
Hide file tree
Showing 11 changed files with 363 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,106 @@ describe('ApiRevisionOptionsComponent', () => {
it('should create', () => {
expect(component).toBeTruthy();
});

describe('Tag APIRevision appropriately based on date and/or status', () => {
const apiRevisions = [
{
id: '1',
isApproved: false,
version: "12.15.1",
apiRevisionType: 'manual',
},
{
id: '2',
isApproved: true,
version: "12.20.0-beta.2",
changeHistory: [
{
changeAction: 'approved',
changedOn: '2024-07-01T00:00:00Z',
}
],
isReleased: true,
releasedOn: '2024-07-02T00:00:00Z',
apiRevisionType: 'automatic',
lastUpdatedOn: '2024-07-01T00:00:00Z',
},
{
id: '3',
isApproved: true,
version: "12.20.0",
changeHistory: [
{
changeAction: 'approved',
changedOn: '2024-07-04T00:00:00Z',
}
],
isReleased: true,
releasedOn: '2024-07-05T00:00:00Z',
apiRevisionType: 'automatic',
lastUpdatedOn: '2024-07-04T00:00:00Z',
},
{
id: '4',
isApproved: true,
version: "12.21.1",
changeHistory: [
{
changeAction: 'approved',
changedOn: '2024-07-05T00:00:00Z',
}
],
isReleased: false,
apiRevisionType: 'automatic',
lastUpdatedOn: '2024-07-05T00:00:00Z',
},
{
id: '5',
isApproved: false,
version: "13.0.0",
isReleased: false,
apiRevisionType: 'automatic',
lastUpdatedOn: '2024-07-04T00:00:00Z',
},
{
id: '6',
isApproved: true,
version: "11.0.0",
changeHistory: [
{
changeAction: 'approved',
changedOn: '2021-07-04T00:00:00Z',
}
],
isReleased: true,
releasedOn: '2021-07-05T00:00:00Z',
apiRevisionType: 'automatic',
lastUpdatedOn: '2021-07-04T00:00:00Z',
},
];

it('should correctly tag the latest GA APIRevision', () => {
var result = component.tagLatestGARevision(apiRevisions);
expect(result.id).toEqual('3');
expect(result.isLatestGA).toBeTruthy();
});

it('should correctly tag the latest approved APIRevision', () => {
var result = component.tagLatestApprovedRevision(apiRevisions);
expect(result.id).toEqual('4');
expect(result.isLatestApproved).toBeTruthy();
});

it('should correctly tag the latest automatic APIRevision', () => {
var result = component.tagCurrentMainRevision(apiRevisions);
expect(result.id).toEqual('4');
expect(result.isLatestMain).toBeTruthy();
});

it('should correctly tag the latest released APIRevision', () => {
var result = component.tagLatestReleasedRevision(apiRevisions);
expect(result.id).toEqual('3');
expect(result.isLatestReleased).toBeTruthy();
});
})
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { getQueryParams } from 'src/app/_helpers/router-helpers';
import { AzureEngSemanticVersion } from 'src/app/_models/azureEngSemanticVersion';
import { APIRevision } from 'src/app/_models/revision';

@Component({
Expand Down Expand Up @@ -42,8 +43,8 @@ export class ApiRevisionOptionsComponent implements OnChanges {
ngOnChanges(changes: SimpleChanges): void {
if (changes['apiRevisions'] || changes['activeApiRevisionId'] || changes['diffApiRevisionId']) {
if (this.apiRevisions.length > 0) {
let mappedApiRevisions = this.mapRevisionToMenu(this.apiRevisions);
this.mappedApiRevisions = this.identifyAndProcessSpecialAPIRevisions(mappedApiRevisions);
this.mappedApiRevisions = this.mapRevisionToMenu(this.apiRevisions);
this.tagSpecialRevisions(this.mappedApiRevisions);

this.activeApiRevisionsMenu = this.mappedApiRevisions.filter((apiRevision: any) => apiRevision.id !== this.diffApiRevisionId);
const selectedActiveAPIRevisionindex = this.activeApiRevisionsMenu.findIndex((apiRevision: APIRevision) => apiRevision.id === this.activeApiRevisionId);
Expand Down Expand Up @@ -170,6 +171,7 @@ export class ApiRevisionOptionsComponent implements OnChanges {
return {
id : apiRevision.id,
resolvedLabel: apiRevision.resolvedLabel,
language: apiRevision.language,
label: apiRevision.label,
typeClass: typeClass,
apiRevisionType: apiRevision.apiRevisionType,
Expand All @@ -181,6 +183,7 @@ export class ApiRevisionOptionsComponent implements OnChanges {
isApproved: apiRevision.isApproved,
isReleased: apiRevision.isReleased,
releasedOn: apiRevision.releasedOn,
changeHistory: apiRevision.changeHistory,
isLatestGA : false,
isLatestApproved : false,
isLatestMain : false,
Expand All @@ -191,74 +194,92 @@ export class ApiRevisionOptionsComponent implements OnChanges {
});
}

identifyAndProcessSpecialAPIRevisions(mappedApiRevisions: any []) {
const result = [];
const semVarRegex = /(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:(?<presep>-?)(?<prelabel>[a-zA-Z]+)(?:(?<prenumsep>\.?)(?<prenumber>[0-9]{1,8})(?:(?<buildnumsep>\.?)(?<buildnumber>\d{1,3}))?)?)?/;

let latestGAApiRevision : any = null;
let latestApprovedApiRevision : any = null;
let currentMainApiRevision : any = null;
let latestReleasedApiRevision : any = null;

while (mappedApiRevisions.length > 0) {
let apiRevision = mappedApiRevisions.shift();
tagSpecialRevisions(mappedApiRevisions: any []) {
this.tagLatestGARevision(mappedApiRevisions);
this.tagLatestApprovedRevision(mappedApiRevisions);
this.tagCurrentMainRevision(mappedApiRevisions);
this.tagLatestReleasedRevision(mappedApiRevisions);
}

if (latestGAApiRevision === null) {
if (apiRevision.version) {
let versionParts = apiRevision.version.match(semVarRegex);
tagLatestGARevision(apiRevisions: any[]) {
const gaRevisions : any [] = [];

if (versionParts.groups?.prelabel === undefined && versionParts.groups?.prenumber === undefined &&
versionParts.groups?.prenumsep === undefined && versionParts.groups?.presep === undefined) {
apiRevision.isLatestGA = true;
latestGAApiRevision = apiRevision;
continue;
}
for (let apiRevision of apiRevisions) {
if (apiRevision.isReleased && apiRevision.version) {
const semVar = new AzureEngSemanticVersion(apiRevision.version, apiRevision.language);
if (semVar.versionType == "GA") {
apiRevision.semanticVersion = semVar;
gaRevisions.push(apiRevision);
}
}
}

if (latestApprovedApiRevision === null) {
if (apiRevision.isApproved) {
apiRevision.isLatestApproved = true;
latestApprovedApiRevision = apiRevision;
continue;
}
}
if (gaRevisions.length > 0) {
gaRevisions.sort((a: any, b: any) => b.semanticVersion.compareTo(a.semanticVersion));
gaRevisions[0].isLatestGA = true;
this.updateTaggedAPIRevisions(apiRevisions, gaRevisions[0]);
return gaRevisions[0];
}
}

if (currentMainApiRevision === null) {
if (apiRevision.apiRevisionType === 'Automatic') {
apiRevision.isLatestMain = true;
currentMainApiRevision = apiRevision;
continue;
}
}
tagLatestApprovedRevision(apiRevisions: any[]) {
const approvedRevisions : any [] = [];

if (latestReleasedApiRevision === null) {
if (apiRevision.isReleased) {
apiRevision.isLatestReleased = true;
latestReleasedApiRevision = apiRevision;
continue;
for (let apiRevision of apiRevisions) {
if (apiRevision.isApproved && apiRevision.changeHistory.length > 0) {
var approval = apiRevision.changeHistory.find((change: any) => change.changeAction === 'approved');
if (approval) {
apiRevision.approvedOn = approval.changedOn;
approvedRevisions.push(apiRevision);
}
}
result.push(apiRevision);
}

if (latestGAApiRevision) {
result.unshift(latestGAApiRevision);
if (approvedRevisions.length > 0) {
approvedRevisions.sort((a: any, b: any) => (new Date(b.approvedOn) as any) - (new Date(a.approvedOn) as any));
approvedRevisions[0].isLatestApproved = true;
this.updateTaggedAPIRevisions(apiRevisions, approvedRevisions[0]);
return approvedRevisions[0];
}
}

tagCurrentMainRevision(apiRevisions: any[]) {
const automaticRevisions : any [] = [];

if (latestApprovedApiRevision) {
result.unshift(latestApprovedApiRevision);
for (let apiRevision of apiRevisions) {
if (apiRevision.apiRevisionType === 'automatic') {
automaticRevisions.push(apiRevision);
}
}

if (currentMainApiRevision) {
result.unshift(currentMainApiRevision);
if (automaticRevisions.length > 0) {
automaticRevisions.sort((a: any, b: any) => (new Date(b.lastUpdatedOn) as any) - (new Date(a.lastUpdatedOn) as any));
automaticRevisions[0].isLatestMain = true;
this.updateTaggedAPIRevisions(apiRevisions, automaticRevisions[0]);
return automaticRevisions[0];
}
}

tagLatestReleasedRevision(apiRevisions: any[]) {
const releasedRevisions : any [] = [];

if (latestReleasedApiRevision) {
result.unshift(latestReleasedApiRevision);
for (let apiRevision of apiRevisions) {
if (apiRevision.isReleased) {
releasedRevisions.push(apiRevision);
}
}

if (releasedRevisions.length > 0) {
releasedRevisions.sort((a: any, b: any) => (new Date(b.releasedOn) as any) - (new Date(a.releasedOn) as any));
releasedRevisions[0].isLatestReleased = true;
this.updateTaggedAPIRevisions(apiRevisions, releasedRevisions[0]);
return releasedRevisions[0];
}
}

return result;
private updateTaggedAPIRevisions(apiRevisions: any[], taggedApiRevision: any) {
apiRevisions.splice(apiRevisions.indexOf(taggedApiRevision), 1)
apiRevisions.unshift(taggedApiRevision);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Datasource, IDatasource, SizeStrategy } from 'ngx-ui-scroll';
import { CommentsService } from 'src/app/_services/comments/comments.service';
import { getQueryParams } from 'src/app/_helpers/router-helpers';
import { ActivatedRoute, Router } from '@angular/router';
import { SCROLL_TO_NODE_QUERY_PARAM } from 'src/app/_helpers/literal-helpers';
import { SCROLL_TO_NODE_QUERY_PARAM } from 'src/app/_helpers/common-helpers';
import { CodePanelRowData, CodePanelRowDatatype } from 'src/app/_models/codePanelRowData';
import { StructuredToken } from 'src/app/_models/structuredToken';
import { CommentItemModel, CommentType } from 'src/app/_models/commentItemModel';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Component, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChange
import { ActivatedRoute, Router } from '@angular/router';
import { InputSwitchOnChangeEvent } from 'primeng/inputswitch';
import { getQueryParams } from 'src/app/_helpers/router-helpers';
import { mapLanguageAliases } from 'src/app/_helpers/service-helpers';
import { mapLanguageAliases } from 'src/app/_helpers/common-helpers';
import { Review } from 'src/app/_models/review';
import { APIRevision } from 'src/app/_models/revision';
import { ConfigService } from 'src/app/_services/config/config.service';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { MenuItem, TreeNode } from 'primeng/api';
import { Subject, take, takeUntil } from 'rxjs';
import { getLanguageCssSafeName } from 'src/app/_helpers/component-helpers';
import { getLanguageCssSafeName } from 'src/app/_helpers/common-helpers';
import { getQueryParams } from 'src/app/_helpers/router-helpers';
import { Review } from 'src/app/_models/review';
import { APIRevision, ApiTreeBuilderData, CodePanelData, ReviewPageWorkerMessageDirective } from 'src/app/_models/revision';
Expand All @@ -12,7 +12,7 @@ import { UserProfileService } from 'src/app/_services/user-profile/user-profile.
import { WorkerService } from 'src/app/_services/worker/worker.service';
import { CodePanelComponent } from '../code-panel/code-panel.component';
import { CommentsService } from 'src/app/_services/comments/comments.service';
import { ACTIVE_API_REVISION_ID_QUERY_PARAM, DIFF_API_REVISION_ID_QUERY_PARAM, DIFF_STYLE_QUERY_PARAM, REVIEW_ID_ROUTE_PARAM, SCROLL_TO_NODE_QUERY_PARAM } from 'src/app/_helpers/literal-helpers';
import { ACTIVE_API_REVISION_ID_QUERY_PARAM, DIFF_API_REVISION_ID_QUERY_PARAM, DIFF_STYLE_QUERY_PARAM, REVIEW_ID_ROUTE_PARAM, SCROLL_TO_NODE_QUERY_PARAM } from 'src/app/_helpers/common-helpers';
import { CodePanelRowData, CodePanelRowDatatype } from 'src/app/_models/codePanelRowData';
import { UserProfile } from 'src/app/_models/userProfile';

Expand Down
29 changes: 29 additions & 0 deletions src/dotnet/APIView/ClientSPA/src/app/_helpers/common-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const REVIEW_ID_ROUTE_PARAM = "reviewId";
export const ACTIVE_API_REVISION_ID_QUERY_PARAM = "activeApiRevisionId";
export const DIFF_API_REVISION_ID_QUERY_PARAM = "diffApiRevisionId";
export const DIFF_STYLE_QUERY_PARAM = "diffStyle";
export const SCROLL_TO_NODE_QUERY_PARAM = "nId";

export function getLanguageCssSafeName(language: string): string {
switch (language.toLowerCase()) {
case "c#":
return "csharp";
case "c++":
return "cplusplus";
default:
return language.toLowerCase();
}
}

export function mapLanguageAliases(languages: Iterable<string>): string[] {
const result: Set<string> = new Set<string>();

for (const language of languages) {
if (language === "TypeSpec" || language === "Cadl") {
result.add("Cadl");
result.add("TypeSpec");
}
result.add(language);
}
return Array.from(result);
}
10 changes: 0 additions & 10 deletions src/dotnet/APIView/ClientSPA/src/app/_helpers/component-helpers.ts

This file was deleted.

This file was deleted.

13 changes: 0 additions & 13 deletions src/dotnet/APIView/ClientSPA/src/app/_helpers/service-helpers.ts

This file was deleted.

Loading

0 comments on commit cc04af0

Please sign in to comment.