Skip to content

Commit d093c07

Browse files
authored
Merge dev
2 parents 00ab876 + 891d16e commit d093c07

File tree

161 files changed

+13040
-3905
lines changed

Some content is hidden

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

161 files changed

+13040
-3905
lines changed

AzureFunctions.AngularClient/src/app/apps-list/apps-list.component.html

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ <h2>{{ 'functionApps' | translate }}</h2><i *ngIf="isLoading" class="fa fa-refre
2424
</multi-drop-down>
2525

2626
<drop-down id="groupingDropDown"
27+
size="large"
2728
[options]="groupOptions"
2829
(value)="onGroupSelect($event)">
2930
</drop-down>

AzureFunctions.AngularClient/src/app/busy-state/busy-state.component.scss

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
.fxs-progress-dots > div:nth-child(4) {
9696
padding-top: 20px;
9797
width: 100%;
98-
background-color: rgba($body-bg-color, 0.30);
98+
background-color: inherit !important;
9999
}
100100

101101
:host-context(#app-root[theme=dark]){
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
<div class="click-to-edit-wrapper" (mousedown)="onMouseDown($event)">
2-
<div *ngIf="!showTextbox && !hiddenText" class="read-only-text">
3-
{{control.value || '&#8203;'}}
4-
</div>
1+
<div #container class="click-to-edit-wrapper" (mousedown)="onMouseDown($event)">
2+
<ng-container *ngIf="group.valid && !showTextbox && !this?.group?.msStayInEditMode">
3+
<div *ngIf="!hiddenText" class="read-only-text">
4+
{{control.value || '&#8203;'}}
5+
</div>
56

6-
<div *ngIf="!showTextbox && hiddenText" class="read-only-text hidden-text">
7-
{{ 'hiddenValueClickToShow' | translate }}
8-
</div>
7+
<div *ngIf="hiddenText" class="read-only-text hidden-text">
8+
{{ 'hiddenValueClickToShow' | translate }}
9+
</div>
10+
</ng-container>
911

10-
<div #target [class.hidden]="!showTextbox">
12+
<div #target [class.hidden]="group.valid && !showTextbox && !this?.group?.msStayInEditMode">
1113
<ng-content></ng-content>
1214
</div>
1315
</div>

AzureFunctions.AngularClient/src/app/controls/click-to-edit/click-to-edit.component.ts

+72-19
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@ import { Subscription } from 'rxjs/Subscription';
99
export class CustomFormGroup extends FormGroup {
1010

1111
// Tells other ClickToEdit components when we're in "edit" mode for the form group.
12-
public _msShowTextbox: Subject<boolean>;
12+
public msShowTextbox: Subject<boolean>;
1313

1414
// Tells other ClickToEdit components which control currently has focus
15-
public _msFocusedControl: string;
15+
public msFocusedControl: string;
1616

1717
// Overrides the ClickToEdit default behavior to start in edit mode for new items
18-
public _msStartInEditMode: boolean;
18+
public msStartInEditMode: boolean;
1919

20-
public _msExistenceState: 'original' | 'new' | 'deleted' = 'original';
20+
public msExistenceState: 'original' | 'new' | 'deleted' = 'original';
21+
22+
// Overrides the ClickToEdit default behavior to remain in edit mode
23+
public msStayInEditMode: boolean;
2124
}
2225

2326
export class CustomFormControl extends FormControl {
@@ -33,7 +36,10 @@ export class CustomFormControl extends FormControl {
3336
export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
3437

3538
public showTextbox = false;
36-
@Input() group: FormGroup;
39+
public group: CustomFormGroup;
40+
@Input('group') set origGroup(group: FormGroup) {
41+
this.group = group as CustomFormGroup;
42+
}
3743
@Input() name: string;
3844
@Input() placeholder: string;
3945
@Input() hiddenText: boolean;
@@ -42,6 +48,8 @@ export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
4248
// (i.e. The control's own editable/non-editable state is not affected by the extended fields in the CustomFormGroup its associated with.)
4349
@Input() alwaysShow: boolean;
4450

51+
@ViewChild('container') container: ElementRef;
52+
4553
@ViewChild('target') target: ElementRef;
4654

4755
@ContentChild(TextboxComponent) textbox: TextboxComponent;
@@ -52,7 +60,7 @@ export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
5260

5361
private _targetFocusState: 'focused' | 'blurring' | 'blurred';
5462
private _focusFunc = (e: FocusEvent) => { this._targetFocusListener(e); };
55-
private _blurFunc = (e: FocusEvent) => { this._targetBlurListener(e); };
63+
private _blurFunc = (e: FocusEvent) => { this._targetBlurListener(e); };
5664

5765
constructor() { }
5866

@@ -62,20 +70,21 @@ export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
6270
this.control = this.group.controls[this.name] as CustomFormControl;
6371

6472
const group = this.group as CustomFormGroup;
65-
if (!group._msShowTextbox) {
66-
group._msShowTextbox = new Subject<boolean>();
73+
74+
if (!group.msShowTextbox) {
75+
group.msShowTextbox = new Subject<boolean>();
6776
}
6877

69-
this._sub = group._msShowTextbox.subscribe(showTextbox => {
70-
this.showTextbox = showTextbox || this.alwaysShow || (group._msStartInEditMode && group.pristine);
71-
if (this.showTextbox && (this.group as CustomFormGroup)._msFocusedControl === this.name) {
78+
this._sub = group.msShowTextbox.subscribe(showTextbox => {
79+
this.showTextbox = showTextbox || this.alwaysShow || (group.msStartInEditMode && group.pristine);
80+
if (this.showTextbox && (this.group as CustomFormGroup).msFocusedControl === this.name) {
7281
setTimeout(() => {
7382
this._focusChild();
7483
});
7584
}
7685
});
7786

78-
if (group._msStartInEditMode || this.alwaysShow) {
87+
if (group.msStartInEditMode || this.alwaysShow) {
7988
this.showTextbox = true;
8089
}
8190
}
@@ -99,6 +108,14 @@ export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
99108
}
100109

101110
private _focusChild() {
111+
if (!this.target) {
112+
return;
113+
}
114+
115+
if ((this.target.nativeElement as HTMLElement).contains(document.activeElement)) {
116+
return;
117+
}
118+
102119
if (this.textbox) {
103120
this.textbox.focus();
104121
} else if (this.dropdown) {
@@ -111,9 +128,14 @@ export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
111128
}
112129

113130
onMouseDown(event: MouseEvent) {
114-
if (!this.showTextbox) {
131+
if (!this.showTextbox && !!this.control && !this.control.disabled) {
115132
event.preventDefault();
133+
event.stopPropagation();
116134
this._updateShowTextbox(true);
135+
136+
// Simulate 'mousedown', 'mouseup', click' event sequence on the outer-most element.
137+
// We do this because the actual clicked element will be removed from the DOM before 'mouseup' and 'click' can occur.
138+
this._simulateMouseEvents(this.container.nativeElement, ['mousedown', 'mouseup', 'click']);
117139
}
118140
}
119141

@@ -145,16 +167,24 @@ export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
145167
}
146168

147169
protected _updateShowTextbox(show: boolean) {
170+
// When an instance with alwaysShow === true gains focus:
171+
// 1. Do not make the controls in the group become visible if they
172+
// are not currently visible.
173+
// 2. If the conrols are already visible because the focus came from
174+
// another control in the group, make sure they stay visible.
175+
176+
const alwaysShowSuffix = '#ALWAYSSHOW';
148177
const group = this.group as CustomFormGroup;
178+
const name = this.name + (this.alwaysShow ? alwaysShowSuffix : '');
149179

150-
if (show) {
151-
group._msFocusedControl = this.name;
152-
} else if (group._msFocusedControl === this.name) {
153-
group._msFocusedControl = '';
180+
if (show) { //gained focus
181+
group.msFocusedControl = name;
182+
} else if (group.msFocusedControl === name) { //lost focus
183+
group.msFocusedControl = '';
154184
}
155185

156-
if (!group._msFocusedControl || group._msFocusedControl === this.name) {
157-
group._msShowTextbox.next(show);
186+
if (!group.msFocusedControl || (group.msFocusedControl === name && !this.alwaysShow)) {
187+
group.msShowTextbox.next(show);
158188
}
159189
}
160190

@@ -175,4 +205,27 @@ export class ClickToEditComponent implements OnInit, AfterViewInit, OnDestroy {
175205
this._targetFocusState = 'focused';
176206
}
177207

208+
private _simulateMouseEvents(target: HTMLElement, eventTypes: string[]) {
209+
if (!eventTypes || eventTypes.length === 0) {
210+
return;
211+
}
212+
213+
let newEvent: MouseEvent;
214+
if (typeof (Event) === 'function') {
215+
// This isn't IE, so we can use MouseEvent()
216+
newEvent = new MouseEvent(eventTypes[0], { bubbles: true, cancelable: true });
217+
} else {
218+
// This is IE, so we have to use document.createEvent() and .initEvent()
219+
newEvent = document.createEvent('MouseEvents');
220+
newEvent.initEvent(eventTypes[0], true, true);
221+
}
222+
223+
target.dispatchEvent(newEvent);
224+
225+
setTimeout(() => {
226+
eventTypes.splice(0, 1);
227+
this._simulateMouseEvents(target, eventTypes);
228+
});
229+
}
230+
178231
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
<a class="list-item clickable command" [class.disabled-command]="disabled" (click)="onClick($event)" tabindex="0" (keydown)="onKeyPress($event)">
1+
<a
2+
role="button"
3+
[attr.aria-label]="displayText"
4+
class="list-item clickable command"
5+
[class.disabled-command]="disabled"
6+
[attr.aria-disabled]="disabled"
7+
(click)="onClick($event)"
8+
tabindex="0"
9+
(keydown)="onKeyPress($event)">
210
<span [load-image]="iconUrl" class="icon-small"></span>
311
{{displayText}}
412
</a>

AzureFunctions.AngularClient/src/app/controls/info-box/info-box.component.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<div
22
class="info-box"
3+
[ngClass]="typeClass"
34
[class.clickable]="!!infoLink"
45
(click)="onClick($event)"
56
[tabIndex]="!!infoLink ? 0 : -1"
67
(keydown)="onKeyPress($event)">
78

89
<div class="info-icon-container">
9-
<div class="glyphicon glyphicon-info-sign info-icon"></div>
10+
<div [load-image]="iconPath" class="info-icon"></div>
1011
</div>
1112
<div class="info-text-container">
1213
<div>{{ infoText }}</div>

AzureFunctions.AngularClient/src/app/controls/info-box/info-box.component.scss

+36-5
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22

33
.info-box{
44
margin-bottom: 10px;
5-
background-color: $info-box-color;
65

76
.info-icon-container{
87
display: table-cell;
98
vertical-align: middle;
109

1110
.info-icon{
12-
font-size: 30px;
11+
height: 40px;
12+
width: 40px;
1313
padding: 5px;
14-
color: $primary-color;
1514
}
1615
}
1716

@@ -31,6 +30,38 @@
3130
}
3231
}
3332

34-
.info-box.clickable:hover{
35-
background-color: $info-box-color-hover;
33+
.info-box.info{
34+
background-color: $info-box-color;
35+
36+
&.clickable:hover{
37+
background-color: $info-box-color-hover;
38+
}
39+
}
40+
41+
.info-box.info /deep/ .msportalfx-svg-c15, .info-box.info /deep/ .msportalfx-svg-c16 {
42+
fill: $primary-color;
43+
}
44+
45+
.info-box.warning{
46+
background-color: $warning-box-color;
47+
48+
&.clickable:hover{
49+
background-color: $warning-box-color-hover;
50+
}
51+
}
52+
53+
.info-box.warning /deep/ .msportalfx-svg-c10 {
54+
fill: $warning-color;
55+
}
56+
57+
.info-box.error{
58+
background-color: $error-box-color;
59+
60+
&.clickable:hover{
61+
background-color: $error-box-color-hover;
62+
}
63+
}
64+
65+
.info-box.error /deep/ .msportalfx-svg-c22 {
66+
fill: $error-color;
3667
}

AzureFunctions.AngularClient/src/app/controls/info-box/info-box.component.ts

+20
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,28 @@ export class InfoBoxComponent {
1111
@Input() infoText: string = null;
1212
@Input() infoLink: string = null;
1313

14+
public typeClass = 'info';
15+
public iconPath = 'image/info.svg';
16+
1417
constructor() { }
1518

19+
@Input('typeClass') set type(value: 'info' | 'warning' | 'error') {
20+
switch (value) {
21+
case 'info':
22+
this.typeClass = 'info';
23+
this.iconPath = 'image/info.svg';
24+
break;
25+
case 'warning':
26+
this.typeClass = 'warning';
27+
this.iconPath = 'image/warning.svg';
28+
break;
29+
case 'error':
30+
this.typeClass = 'error';
31+
this.iconPath = 'image/error.svg';
32+
break;
33+
}
34+
}
35+
1636
onClick(event: any) {
1737
if (!!this.infoLink) {
1838
window.open(this.infoLink, '_blank');

0 commit comments

Comments
 (0)