Skip to content

Commit b626bd6

Browse files
ehamaihartra344
authored andcommitted
[SpecPicker] First part of implementing spec picker - Handles existing plans within Functions UI (#2497)
* [SpecPicker] First part of implementing spec picker - Handles existing plans within Functions UI * Updated with PR feedback
1 parent 910ec7b commit b626bd6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+2470
-51
lines changed

AzureFunctions.AngularClient/src/app/feature-group/feature-item.ts

+18
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,21 @@ export class TabFeature extends FeatureItem {
149149
this._broadcastService.broadcastEvent(BroadcastEvent.OpenTab, this.featureId);
150150
}
151151
}
152+
153+
export class DisableableTabFeature extends DisableableFeature {
154+
constructor(
155+
title: string,
156+
keywords: string,
157+
info: string,
158+
imageUrl: string,
159+
public featureId: string,
160+
private _broadcastService: BroadcastService,
161+
disableInfoStream?: Subject<DisableInfo>,
162+
overrideDisableInfo?: ScenarioResult) {
163+
super(title, keywords, info, imageUrl, disableInfoStream, overrideDisableInfo);
164+
}
165+
166+
click() {
167+
this._broadcastService.broadcastEvent(BroadcastEvent.OpenTab, this.featureId);
168+
}
169+
}

AzureFunctions.AngularClient/src/app/shared/components/function-app-context-component.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { ReplaySubject } from 'rxjs/ReplaySubject';
1414

1515

1616
export abstract class FunctionAppContextComponent extends ErrorableComponent implements OnDestroy {
17-
public viewInfo: TreeViewInfo<any>;
17+
private _viewInfo: TreeViewInfo<any>;
1818
public context: FunctionAppContext;
1919

2020
protected viewInfoEvents: Observable<TreeViewInfo<any> & {
@@ -30,10 +30,14 @@ export abstract class FunctionAppContextComponent extends ErrorableComponent imp
3030
private timeout: number;
3131

3232
@Input('viewInfo')
33-
private set viewInfoComponent_viewInfo(viewInfo: TreeViewInfo<any>) {
33+
public set viewInfo(viewInfo: TreeViewInfo<any>) {
3434
this.viewInfoSubject.next(viewInfo);
3535
}
3636

37+
public get viewInfo() {
38+
return this._viewInfo;
39+
}
40+
3741
constructor(componentName: string, functionAppService: FunctionAppService, broadcastService: BroadcastService, setBusy?: Function, private clearBusy?: Function) {
3842
super(componentName, broadcastService);
3943

AzureFunctions.AngularClient/src/app/shared/conditional-http-client.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ArmError, HttpError } from './models/http-result';
1+
import { ArmError, HttpError, ArmPollError } from './models/http-result';
22
import { Preconditions as p } from './preconditions';
33
import { Observable } from 'rxjs/Observable';
44
import { HttpResult, HttpErrorResponse } from 'app/shared/models/http-result';
@@ -132,6 +132,11 @@ export class ConditionalHttpClient {
132132
}
133133
}
134134

135+
const armPollError = <ArmPollError><any>body;
136+
if (!mesg && armPollError && armPollError.Message) {
137+
mesg = armPollError.Message;
138+
}
139+
135140
if (!mesg && response.statusText && response.url) {
136141
mesg = `${response.statusText} - ${response.url}`;
137142
}

AzureFunctions.AngularClient/src/app/shared/directives/monaco-editor.directive.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import { UserService } from './../services/user.service';
22
import { Directive, EventEmitter, ElementRef, Input, Output, HostBinding } from '@angular/core';
3-
import 'rxjs/add/operator/distinctUntilChanged';
4-
53
import { GlobalStateService } from '../services/global-state.service';
64
import { CacheService } from 'app/shared/services/cache.service';
75
import { Subject } from 'rxjs/Subject';
@@ -258,8 +256,8 @@ export class MonacoEditorDirective {
258256

259257
setMonacoSchema(schemaName: string) {
260258
this._cacheService.get('assets/schemas/' + schemaName)
261-
.subscribe((schema) => {
262-
schema.additionalProperties = false;
259+
.subscribe((schema: any) => {
260+
schema.additionalProperties = false; // This is weird. Seems like it's setting a property on HTTP response object
263261
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
264262
validate: true,
265263
schemas: [{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export interface ArmProviderInfo {
2+
resourceTypes: ResourceType[];
3+
}
4+
5+
export interface ResourceType {
6+
resourceType: string;
7+
locations: string[];
8+
}

AzureFunctions.AngularClient/src/app/shared/models/arm/arm-obj.ts

+14-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export interface ArmObj<T> {
88
location: string;
99
properties: T;
1010
identity?: Identity;
11+
sku?: Sku;
1112
}
1213

1314
export interface ArmArrayResult<T> {
@@ -19,4 +20,16 @@ export interface Identity {
1920
principalId: string;
2021
tenantId: string;
2122
type: string;
22-
}
23+
}
24+
25+
export interface Sku {
26+
name: string;
27+
tier?: string;
28+
size?: string;
29+
family?: string;
30+
capacity?: number;
31+
}
32+
33+
export interface AvailableSku {
34+
sku: Sku;
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export interface BillingMeter {
2+
meterId: string;
3+
billingLocation: string;
4+
shortName: string;
5+
friendlyName: string;
6+
resourceType: string;
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface GeoRegion {
2+
name: string;
3+
displayName: string;
4+
sortOrder: number;
5+
}

AzureFunctions.AngularClient/src/app/shared/models/broadcast-event.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ export interface DirtyStateEvent {
2828
reason: string | null;
2929
}
3030

31-
export interface BusyStateEvent{
31+
export interface BusyStateEvent {
3232
busyComponentName: string;
3333
action: 'setBusyState' | 'clearBusyState' | 'clearOverallBusyState';
3434
busyStateKey: string;
3535
}
3636

37-
export interface TreeUpdateEvent{
37+
export interface TreeUpdateEvent {
3838
operation: 'add' | 'remove' | 'removeChild' | 'update' | 'navigate';
3939
resourceId: string;
4040
data?: any;

AzureFunctions.AngularClient/src/app/shared/models/constants.ts

+12
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export class SiteTabIds {
7272
public static readonly deploymentSlotsConfig = 'deploymentSlotsConfig';
7373
public static readonly deploymentSlotsSwap = 'deploymentSlotsSwap';
7474
public static readonly deploymentSlotsCreate = 'deploymentSlotsCreate';
75+
public static readonly scaleUp = 'scaleUp';
7576
}
7677

7778
export class Arm {
@@ -112,6 +113,11 @@ export class Links {
112113
public static clientAffinityLearnMore = 'https://go.microsoft.com/fwlink/?linkid=798249';
113114
}
114115

116+
export class Kinds {
117+
public static readonly linux = 'linux';
118+
public static readonly aseV2 = 'ASEV2';
119+
}
120+
115121
export class LocalStorageKeys {
116122
public static readonly siteTabs = '/site/tabs';
117123
public static readonly savedSubsKey = '/subscriptions/selectedIds';
@@ -180,6 +186,7 @@ export class ScenarioIds {
180186
public static readonly enableProcessExplorer = 'EnableProcessExplorer';
181187
public static readonly enableBackups = 'EnableBackups';
182188
public static readonly enableTinfoil = 'EnableTinfoil';
189+
public static readonly addScaleUp = 'AddScaleUp';
183190
public static readonly addSiteFileStorage = 'ShowSiteFileStorage';
184191
public static readonly showSitePin = 'ShowSitePin';
185192
public static readonly showCreateRefreshSub = 'ShowCreateRefreshSub';
@@ -248,12 +255,17 @@ export class LogCategories {
248255
public static readonly functionNew = 'FunctionNew';
249256
public static readonly cicd = 'CICD';
250257
public static readonly telemetry = 'Telemetry';
258+
public static readonly specPicker = 'SpecPicker';
251259
public static readonly featureComponent = 'FeatureComponent';
252260
public static readonly deploymentSlots = 'DeploymentSlots';
253261
public static readonly swapSlots = 'SwapSlots';
254262
public static readonly addSlot = 'AddSlot';
255263
}
256264

265+
export class SubscriptionQuotaIds {
266+
public static dreamSparkQuotaId: string = 'DreamSpark_2015-02-01';
267+
}
268+
257269
export class KeyCodes {
258270
public static readonly tab = 9;
259271
public static readonly enter = 13;

AzureFunctions.AngularClient/src/app/shared/models/http-result.ts

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ export interface ArmError {
1717
}
1818
}
1919

20+
export interface ArmPollError {
21+
Code: string;
22+
Message: string;
23+
}
24+
2025
export interface HttpErrorResponse<T> {
2126
message: string;
2227
error: any | null;

AzureFunctions.AngularClient/src/app/shared/models/portal.ts

+10-4
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ export interface CrmInfo {
3535
namespaceId: string;
3636
}
3737

38-
export interface DataMessage<T>{
38+
export interface DataMessage<T> {
3939
operationId: string;
4040
data: T;
4141
}
4242

43-
export interface BladeResult{
43+
export interface DataMessageResult<T> {
4444
status: 'success' | 'failed' | 'cancelled';
45-
result: any;
45+
result: T;
4646
}
4747

4848
export interface Action {
@@ -79,6 +79,8 @@ export class Verbs {
7979
public static setupOAuth = 'setup-oauth';
8080
public static pinPart = 'pin-part';
8181
public static setNotification = 'set-notification';
82+
public static getSubscriptionInfo = 'get-subscription-info';
83+
public static getSpecCosts = 'get-spec-costs';
8284

8385
// Requests from Ibiza
8486
public static sendStartupInfo = 'send-startup-info';
@@ -138,11 +140,15 @@ export interface NotificationStartedInfo {
138140
id: string
139141
}
140142

141-
export interface DirtyStateInfo{
143+
export interface DirtyStateInfo {
142144
dirty: boolean;
143145
message?: string;
144146
}
145147

148+
export interface SubscriptionRequest {
149+
subscriptionId: string;
150+
}
151+
146152
export enum PartSize {
147153
/**
148154
* A tile that is 1 column x 1 row.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
export interface ServerFarm {
1+
import { HostingEnvironmentProfile } from './arm/hosting-environment';
2+
export interface ServerFarm {
23
serverFarmName: string;
34
armId: string;
45
subscriptionId: string;
56
resoruceGroupName: string;
67
geoRegion: string;
7-
}
8+
hostingEnvironmentProfile?: HostingEnvironmentProfile;
9+
}

AzureFunctions.AngularClient/src/app/shared/models/subscription.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,9 @@ export interface Subscription {
22
subscriptionId: string;
33
displayName: string;
44
state: string;
5-
}
5+
subscriptionPolicies: SubscriptionPolicies;
6+
}
7+
8+
export interface SubscriptionPolicies {
9+
quotaId: string;
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// import { ArmService } from './arm.service';
2+
import { Injectable, Injector } from '@angular/core';
3+
import { ConditionalHttpClient } from '../conditional-http-client';
4+
import { UserService } from './user.service';
5+
import { CacheService } from './cache.service';
6+
import { ResourceId, ArmObj } from '../models/arm/arm-obj';
7+
import { Observable } from 'rxjs/Observable';
8+
import { HttpResult } from '../models/http-result';
9+
import { HostingEnvironment } from '../models/arm/hosting-environment';
10+
11+
type Result<T> = Observable<HttpResult<T>>;
12+
13+
@Injectable()
14+
export class AseService {
15+
private readonly _client: ConditionalHttpClient;
16+
17+
constructor(
18+
userService: UserService,
19+
injector: Injector,
20+
private _cacheService: CacheService) {
21+
this._client = new ConditionalHttpClient(injector, _ => userService.getStartupInfo().map(i => i.token));
22+
}
23+
24+
getAse(resourceId: ResourceId): Result<ArmObj<HostingEnvironment>> {
25+
const getPlan = this._cacheService.getArm(resourceId).map(r => r.json());
26+
return this._client.execute({ resourceId: resourceId }, t => getPlan);
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Observable } from 'rxjs/Observable';
2+
import { Injectable, Injector } from '@angular/core';
3+
import { UserService } from './user.service';
4+
import { PortalService } from './portal.service';
5+
@Injectable()
6+
export class BillingService {
7+
8+
constructor(
9+
userService: UserService,
10+
injector: Injector,
11+
private _portalService: PortalService) {
12+
}
13+
14+
checkIfSubscriptionHasQuotaId(subscriptionId: string, quotaId: string) {
15+
return this._portalService.getSubscription(subscriptionId)
16+
.map(s => {
17+
return s && s.subscriptionPolicies && s.subscriptionPolicies.quotaId.toLowerCase() === quotaId.toLowerCase();
18+
})
19+
.catch(e => Observable.of(false));
20+
}
21+
}

AzureFunctions.AngularClient/src/app/shared/services/cache.service.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export class CacheService {
7373
return this._armService.send('PATCH', url, content);
7474
}
7575

76-
get(url: string, force?: boolean, headers?: Headers, invokeApi?: boolean) {
76+
get(url: string, force?: boolean, headers?: Headers, invokeApi?: boolean): Observable<Response> {
7777
return this.send(url, 'GET', force, headers, null, invokeApi);
7878
}
7979

0 commit comments

Comments
 (0)