Skip to content
Projects
Groups
Snippets
Help
Sign in / Register
Toggle navigation
Minds Frontend
Project overview
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Locked Files
Issues
805
Merge Requests
52
CI / CD
Security & Compliance
Packages
Wiki
Snippets
Members
Collapse sidebar
Close sidebar
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Minds
Minds Frontend
Compare Revisions
1e5ca2324e0362d1dcb1e9c9c1e4a21627e6fb59...a135d23e3e555a14a85d8caa98d3aa03aedb47bb
Source
a135d23e3e555a14a85d8caa98d3aa03aedb47bb
...
Target
1e5ca2324e0362d1dcb1e9c9c1e4a21627e6fb59
Compare
Commits (3)
(refactor): split tabs into individual forms
· 78b06555
Olivia Madrid
authored
1 day ago
78b06555
(refactor): more pro settings validation and ui
· a3c569e9
Olivia Madrid
authored
15 minutes ago
a3c569e9
Merge branch 'pro-settings-2163' of gitlab.com:minds/front into pro-settings-2163
· a135d23e
Olivia Madrid
authored
11 minutes ago
a135d23e
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
984 additions
and
598 deletions
+984
-598
src/app/common/common.module.ts
View file @
a135d23e
...
...
@@ -123,6 +123,7 @@ import { ShadowboxLayoutComponent } from './components/shadowbox-layout/shadowbo
import
{
ShadowboxHeaderComponent
}
from
'
./components/shadowbox-header/shadowbox-header.component
'
;
import
{
FormDescriptorComponent
}
from
'
./components/form-descriptor/form-descriptor.component
'
;
import
{
FormToastComponent
}
from
'
./components/form-toast/form-toast.component
'
;
import
{
ShadowboxSubmitButtonComponent
}
from
'
./components/shadowbox-submit-button/shadowbox-submit-button.component
'
;
PlotlyModule
.
plotlyjs
=
PlotlyJS
;
...
...
@@ -236,6 +237,7 @@ PlotlyModule.plotlyjs = PlotlyJS;
ShadowboxHeaderComponent
,
FormDescriptorComponent
,
FormToastComponent
,
ShadowboxSubmitButtonComponent
,
],
exports
:
[
MINDS_PIPES
,
...
...
@@ -333,6 +335,7 @@ PlotlyModule.plotlyjs = PlotlyJS;
ShadowboxLayoutComponent
,
FormDescriptorComponent
,
FormToastComponent
,
ShadowboxSubmitButtonComponent
,
],
providers
:
[
SiteService
,
...
...
This diff is collapsed.
src/app/common/components/form-toast/form-toast.component.html
View file @
a135d23e
<div
class=
"m-formToast__toastsContainer"
>
<ng-container
*ngFor=
"let toast of toasts; let i = index"
>
<div
class=
"m-formToast__wrapper"
*ngIf=
"toast.visible
"
>
<div
class=
"m-formToast__wrapper"
[ngClass]=
"{ active: toast.visible }
"
>
<i
class=
"material-icons m-formToast__icon--success"
*ngIf=
"toast.type === 'success'"
...
...
@@ -16,9 +16,15 @@
*ngIf=
"toast.type === 'warning'"
>
warning
</i
>
<i
class=
"material-icons m-formToast__icon--info"
*ngIf=
"toast.type === 'info'"
></i>
<p
i18n
>
{{ toast.message }}
</p>
<div
class=
"m-formToast__iconWrapper"
>
<i
class=
"material-icons m-formToast__icon--close"
(click)=
"dismiss(i)"
<i
class=
"material-icons m-formToast__icon--close"
(click)=
"toast.visible = false"
>
clear
</i
>
</div>
...
...
This diff is collapsed.
src/app/common/components/form-toast/form-toast.component.scss
View file @
a135d23e
...
...
@@ -2,12 +2,13 @@ m-formToast {
margin
:
37px
70px
0
70px
;
display
:
flex
;
flex-flow
:
column
nowrap
;
min-width
:
300px
;
max-width
:
522px
;
position
:
fixed
;
bottom
:
24
px
;
bottom
:
24
;
}
.m-formToast
s
__toastsContainer
{
min-width
:
300px
;
.m-formToast__toastsContainer
{
height
:
auto
;
transition
:
all
0
.3s
ease
;
}
.m-formToast__wrapper
{
...
...
@@ -17,11 +18,16 @@ m-formToast {
padding
:
13px
;
margin-bottom
:
16px
;
display
:
flex
;
opacity
:
0
;
transition
:
opacity
0
.4s
cubic-bezier
(
0
.23
,
1
,
0
.32
,
1
);
@include
m-theme
()
{
color
:
themed
(
$m-grey-600
);
background-color
:
themed
(
$m-white
);
box-shadow
:
0
0
15px
0
rgba
(
themed
(
$m-black
)
,
0
.2
);
}
&
.active
{
opacity
:
1
;
}
p
{
flex-grow
:
1
;
margin
:
0
;
...
...
@@ -46,37 +52,33 @@ m-formToast {
color
:
themed
(
$m-amber-dark
);
}
}
.m-formToast__icon--info
{
margin-right
:
14px
;
}
.m-formToast__icon--close
{
cursor
:
pointer
;
transition
:
all
0
.2s
ease-out
;
@include
m-theme
()
{
color
:
themed
(
$m-grey-
4
00
);
color
:
themed
(
$m-grey-
3
00
);
}
&
:hover
{
transform
:
scale
(
1
.2
);
@include
m-theme
()
{
color
:
themed
(
$m-grey-
2
00
);
color
:
themed
(
$m-grey-
1
00
);
}
}
&
:active
{
@include
m-theme
()
{
color
:
themed
(
$m-grey-
6
00
);
color
:
themed
(
$m-grey-
4
00
);
}
}
}
@media
screen
and
(
max-width
:
$min-tablet
)
{
m-formToast
{
// margin: 37px 24px 0 24px;
margin
:
0px
24px
;
margin
:
0
auto
;
max-width
:
85%
;
position
:
absolute
;
bottom
:
48px
;
}
}
// TODOOJM
// @media screen and (max-width: $max-mobile) {
// m-formToast {
// position: fixed;
// }
// }
This diff is collapsed.
src/app/common/components/form-toast/form-toast.component.ts
View file @
a135d23e
import
{
Component
,
OnInit
,
OnDestroy
}
from
'
@angular/core
'
;
import
{
Component
,
OnInit
,
OnDestroy
,
ChangeDetectionStrategy
,
ChangeDetectorRef
,
}
from
'
@angular/core
'
;
import
{
FormToast
,
FormToastService
}
from
'
../../services/form-toast.service
'
;
import
{
Subscription
}
from
'
rxjs
'
;
@
Component
({
selector
:
'
m-formToast
'
,
templateUrl
:
'
./form-toast.component.html
'
,
changeDetection
:
ChangeDetectionStrategy
.
OnPush
,
})
export
class
FormToastComponent
implements
OnInit
,
OnDestroy
{
toasts
:
FormToast
[]
=
[];
timeoutIds
:
number
[]
=
[];
subscription
:
Subscription
;
constructor
(
private
service
:
FormToastService
)
{}
constructor
(
private
service
:
FormToastService
,
protected
cd
:
ChangeDetectorRef
)
{}
ngOnInit
()
{
this
.
subscription
=
this
.
service
.
onToast
().
subscribe
(
toast
=>
{
// clear toasts when an empty toast is received
if
(
!
toast
.
message
)
{
// clear toasts when an empty toast is received
this
.
toasts
=
[];
return
;
}
toast
[
'
visible
'
]
=
true
;
const
toastIndex
=
this
.
toasts
.
push
(
toast
)
-
1
;
console
.
log
(
'
***tolll
'
,
toast
);
console
.
log
(
toastIndex
);
this
.
detectChanges
();
// TODOOJM something is wrong here
const
toastTimeout
=
setTimeout
(()
=>
{
this
.
toasts
[
toastIndex
].
visible
=
false
;
console
.
log
(
'
***to
'
,
this
.
toasts
[
toastIndex
]
);
},
10
000
);
this
.
detectChanges
(
);
},
3
000
);
this
.
timeoutIds
.
push
(
setTimeout
(()
=>
toastTimeout
));
});
}
dismiss
(
index
)
{
console
.
log
(
this
.
toasts
[
index
]);
this
.
toasts
[
index
].
visible
=
false
;
this
.
detectChanges
();
}
detectChanges
()
{
this
.
cd
.
markForCheck
();
this
.
cd
.
detectChanges
();
}
ngOnDestroy
()
{
...
...
This diff is collapsed.
src/app/common/components/page-layout/page-layout.component.scss
View file @
a135d23e
...
...
@@ -2,6 +2,8 @@ m-pageLayout {
display
:
block
;
position
:
relative
;
width
:
100%
;
max-width
:
1200px
;
margin
:
auto
;
min-height
:
100%
;
padding
:
56px
0
48px
0
;
@include
m-theme
()
{
...
...
@@ -9,7 +11,7 @@ m-pageLayout {
color
:
themed
(
$m-grey-800
);
}
&
.isForm
{
min-height
:
none
;
min-height
:
0px
;
}
.m-tooltip
{
...
...
@@ -33,14 +35,14 @@ m-pageLayout {
m-sidebarMenu
{
display
:
block
;
box-sizing
:
border-box
;
padding-left
:
105px
;
width
:
245px
;
padding-left
:
20px
;
@include
m-theme
()
{
background-color
:
themed
(
$m-white
);
}
}
.m-pageLayout__main
{
margin-left
:
350px
;
margin-left
:
25%
;
margin-right
:
24px
;
@include
m-theme
()
{
...
...
@@ -50,6 +52,12 @@ m-sidebarMenu {
}
@media
screen
and
(
max-width
:
$min-tablet
)
{
m-pageLayout
{
&
.isForm
{
padding-bottom
:
0px
;
}
}
.m-pageLayout__main
{
display
:
block
;
margin
:
0
;
...
...
This diff is collapsed.
src/app/common/components/shadowbox-header/shadowbox-header.component.scss
View file @
a135d23e
...
...
@@ -16,8 +16,6 @@ m-shadowboxHeader {
.m-shadowboxHeader__container
{
overflow-x
:
hidden
;
overflow-y
:
hidden
;
// display: flex;
// flex-wrap: nowrap;
transition
:
all
0
.5s
cubic-bezier
(
0
.23
,
1
,
0
.32
,
1
);
&
.disable-scrollbars
{
...
...
This diff is collapsed.
src/app/common/components/shadowbox-layout/shadowbox-layout.component.html
View file @
a135d23e
...
...
@@ -17,7 +17,18 @@
</ng-container>
>
</m-shadowboxHeader
>
<div
class=
"m-shadowboxLayout__bottom"
>
<div
*ngIf=
"!isForm"
class=
"m-shadowboxLayout__bottom"
>
<ng-content
select=
".m-shadowboxLayout__body"
></ng-content>
<ng-content
select=
".m-shadowboxLayout__footer"
></ng-content>
</div>
<ng-container
*ngIf=
"isForm"
>
<ng-content
class=
"m-shadowboxLayout__bottom"
select=
".m-shadowboxLayout__bottom"
>
<!-- <ng-content select=".m-shadowboxLayout__body"></ng-content>
<ng-content select=".m-shadowboxLayout__footer"></ng-content> -->
</ng-content>
</ng-container>
This diff is collapsed.
src/app/common/components/shadowbox-layout/shadowbox-layout.component.scss
View file @
a135d23e
...
...
@@ -31,10 +31,8 @@ m-shadowboxHeader.isScrollable {
.m-shadowboxLayout__button
{
cursor
:
pointer
;
padding
:
10px
20px
;
font-size
:
17px
;
font-weight
:
300
;
background-color
:
#4fc3a9
;
height
:
43px
;
min-
height
:
43px
;
border
:
0
;
transition
:
all
0
.2s
ease
;
border-radius
:
2px
;
...
...
@@ -44,9 +42,6 @@ m-shadowboxHeader.isScrollable {
}
&
:hover
{
transform
:
scale
(
1
.02
);
// background-color: #4cb9a0;
}
&
:active
{
background-color
:
#55ccb2
;
@include
m-theme
()
{
box-shadow
:
0
3px
3px
-2px
rgba
(
themed
(
$m-black
)
,
0
.2
)
,
...
...
@@ -54,17 +49,67 @@ m-shadowboxHeader.isScrollable {
0
1px
7px
0
rgba
(
themed
(
$m-black
)
,
0
.12
);
}
}
&
:active
{
transform
:
scale
(
0
.999
);
@include
m-theme
()
{
box-shadow
:
0
3px
2px
-2px
rgba
(
themed
(
$m-black
)
,
0
.2
)
,
0
2px
3px
0
rgba
(
themed
(
$m-black
)
,
0
.14
)
,
0
1px
5px
0
rgba
(
themed
(
$m-black
)
,
0
.12
);
}
}
&
:disabled
,
&
[
disabled
]
{
cursor
:
default
;
@include
m-theme
()
{
background-color
:
themed
(
$m-grey-200
);
background-color
:
themed
(
$m-grey-100
);
}
}
p
{
margin
:
0
;
font-size
:
17px
;
font-weight
:
300
;
span
{
font-size
:
72px
;
}
}
}
button
{
outline
:
0
;
}
@keyframes
blink
{
0
%
{
opacity
:
0
.2
;
transform
:
scale
(
2
.1
);
font-size
:
77px
;
}
20
%
{
opacity
:
1
;
transform
:
scale
(
1
.2
);
font-size
:
90px
;
}
100
%
{
opacity
:
0
.2
;
transform
:
scale
(
1
.3
);
}
}
p
.m-shadowboxLayout__buttonStatus--saving
{
// line-height:70px
span
{
animation-name
:
blink
;
animation-duration
:
1
.4s
;
animation-iteration-count
:
infinite
;
animation-fill-mode
:
both
;
&
:nth-child
(
2
)
{
animation-delay
:
0
.2s
;
}
&
:nth-child
(
3
)
{
animation-delay
:
0
.4s
;
}
}
}
// ---------------------------------------
m-shadowboxLayout
.isForm
{
margin-top
:
69px
;
...
...
@@ -108,7 +153,7 @@ m-shadowboxLayout.isForm {
}
.m-shadowboxLayout__footer
{
justify-content
:
center
;
padding
:
24px
;
padding
:
24px
24px
48px
24px
;
}
}
}
...
...
This diff is collapsed.
src/app/common/components/shadowbox-submit-button/shadowbox-submit-button.component.html
0 → 100644
View file @
a135d23e
<div
class=
"m-shadowboxLayout__footer"
>
<button
class=
"m-shadowboxSubmitButton"
type=
"submit"
[disabled]=
"disabled"
>
<div
[hidden]=
"saveStatus !== 'unsaved'"
class=
"m-shadowboxSubmitButton__status--unsaved"
>
<ng-content
select=
"[m-shadowboxSubmitButton__status--unsaved]"
></ng-content>
</div>
<div
[hidden]=
"saveStatus !== 'saving'"
class=
"m-shadowboxSubmitButton__status--saving"
>
<span></span>
<span></span>
<span></span>
</div>
<div
[hidden]=
"saveStatus !== 'saved'"
class=
"m-shadowboxSubmitButton__status--saved"
>
<ng-content
select=
"[m-shadowboxSubmitButton__status--saved]"
></ng-content>
</div>
</button>
</div>
<!-- [ngClass]="{ transparent: saveStatus !== 'saving' }" -->
This diff is collapsed.
src/app/common/components/shadowbox-submit-button/shadowbox-submit-button.component.scss
0 → 100644
View file @
a135d23e
.m-shadowboxSubmitButton
{
// display: grid;
min-width
:
220px
;
position
:
relative
;
cursor
:
pointer
;
padding
:
10px
20px
;
background-color
:
#4fc3a9
;
min-height
:
43px
;
border
:
0
;
transition
:
all
0
.2s
ease
;
border-radius
:
2px
;
outline
:
0
;
@include
m-theme
()
{
color
:
themed
(
$m-white
);
}
&
:hover
{
&
:not
(
:disabled
)
{
transform
:
scale
(
1
.02
);
background-color
:
#55ccb2
;
@include
m-theme
()
{
box-shadow
:
0
3px
3px
-2px
rgba
(
themed
(
$m-black
)
,
0
.2
)
,
0
2px
5px
0
rgba
(
themed
(
$m-black
)
,
0
.14
)
,
0
1px
7px
0
rgba
(
themed
(
$m-black
)
,
0
.12
);
}
}
}
&
:active
{
&
:not
(
:disabled
)
{
transform
:
scale
(
0
.999
);
background-color
:
#4fc3a9
;
@include
m-theme
()
{
box-shadow
:
0
3px
2px
-2px
rgba
(
themed
(
$m-black
)
,
0
.2
)
,
0
2px
3px
0
rgba
(
themed
(
$m-black
)
,
0
.14
)
,
0
1px
5px
0
rgba
(
themed
(
$m-black
)
,
0
.12
);
}
}
}
&
:disabled
,
&
[
disabled
]
{
cursor
:
default
;
@include
m-theme
()
{
background-color
:
themed
(
$m-grey-100
);
}
}
}
button
{
outline
:
0
;
}
[
class
*=
'm-shadowboxSubmitButton__status'
]
{
// visibility: visible;
font-size
:
17px
;
font-weight
:
300
;
// &.transparent {
// visibility: hidden;
// }
}
@keyframes
blink
{
0
%
{
opacity
:
0
.2
;
}
20
%
{
opacity
:
1
;
transform
:
scale
(
1
.05
);
}
100
%
{
opacity
:
0
.2
;
transform
:
scale
(
0
.9
);
}
}
.m-shadowboxSubmitButton__status--saving
{
span
{
display
:
inline-block
;
height
:
8px
;
width
:
8px
;
margin
:
0
6px
;
border-radius
:
50%
;
animation-name
:
blink
;
animation-duration
:
1
.4s
;
animation-iteration-count
:
infinite
;
animation-fill-mode
:
both
;
@include
m-theme
()
{
background-color
:
themed
(
$m-white
);
}
&
:nth-child
(
2
)
{
animation-delay
:
0
.2s
;
}
&
:nth-child
(
3
)
{
animation-delay
:
0
.4s
;
}
}
}
@media
screen
and
(
max-width
:
$max-mobile
)
{
m-shadowboxSubmitButton
{
min-width
:
50%
;
}
}
This diff is collapsed.
src/app/common/components/shadowbox-submit-button/shadowbox-submit-button.component.spec.ts
0 → 100644
View file @
a135d23e
import
{
async
,
ComponentFixture
,
TestBed
}
from
'
@angular/core/testing
'
;
import
{
ShadowboxSubmitButtonComponent
}
from
'
./shadowbox-submit-button.component
'
;
describe
(
'
ShadowboxSubmitButtonComponent
'
,
()
=>
{
let
component
:
ShadowboxSubmitButtonComponent
;
let
fixture
:
ComponentFixture
<
ShadowboxSubmitButtonComponent
>
;
beforeEach
(
async
(()
=>
{
TestBed
.
configureTestingModule
({
declarations
:
[
ShadowboxSubmitButtonComponent
],
}).
compileComponents
();
}));
beforeEach
(()
=>
{
fixture
=
TestBed
.
createComponent
(
ShadowboxSubmitButtonComponent
);
component
=
fixture
.
componentInstance
;
fixture
.
detectChanges
();
});
it
(
'
should create
'
,
()
=>
{
expect
(
component
).
toBeTruthy
();
});
});
This diff is collapsed.
src/app/common/components/shadowbox-submit-button/shadowbox-submit-button.component.ts
0 → 100644
View file @
a135d23e
import
{
Component
,
OnInit
,
Input
}
from
'
@angular/core
'
;
@
Component
({
selector
:
'
m-shadowboxSubmitButton
'
,
templateUrl
:
'
./shadowbox-submit-button.component.html
'
,
})
export
class
ShadowboxSubmitButtonComponent
implements
OnInit
{
@
Input
()
saveStatus
:
string
=
'
unsaved
'
;
@
Input
()
disabled
:
boolean
=
false
;
constructor
()
{}
ngOnInit
()
{}
}
This diff is collapsed.
src/app/common/components/sidebar-menu/sidebar-menu.component.html
View file @
a135d23e
...
...
@@ -29,43 +29,38 @@
</div> -->
</div>
</a>
<!-- <ng-container *ngFor="let menu of menus"> -->
<div
class=
"m-sidebarMenu__menuContainer expanded"
*ngIf=
"menu.header.permissionGranted"
>
<!-- [ngClass]="{ expanded: menu.header.expanded }" -->
<div
class=
"m-sidebarMenu__header"
>
<h3>
{{ menu.header.label }}
</h3>
<!-- <i
class="material-icons"
*ngIf="menu.header.expanded && menu.links"
(click)="menu.header.expanded = false"
>keyboard_arrow_up</i
> -->
<!-- <i class="material-icons" *ngIf="!menu.header.expanded && menu.links"
>keyboard_arrow_down</i
> -->
<!-- (click)="menu.header.expanded = true" -->
</div>
<nav
class=
"m-sidebarMenu__linksContainer"
*ngIf=
"menu.links"
>
<div
class=
"m-sidebarMenu__link"
*ngFor=
"let link of menu.links"
>
<!-- OJMTODO: fix target _blank -->
<a
*ngIf=
"link.permissionGranted"
(click)=
"mobileMenuExpanded = false"
[routerLink]=
"link.path ? '/' + link.path : '../' + link.id"
routerLinkActive=
"selected"
[routerLinkActiveOptions]=
"{ exact: true }"
[target]=
"link.newWindow ? '_blank' : '_self'"
[ngClass]=
"{ newWindow: link.newWindow }"
><i
class=
"material-icons"
*ngIf=
"link.newWindow"
>
launch
</i>
<span>
{{ link.label }}
</span></a
<ng-container
*ngIf=
"link.permissionGranted"
>
<ng-container
*ngIf=
"!link.newWindow"
>
<a
(click)=
"mobileMenuExpanded = false"
[routerLink]=
"link.path ? '/' + link.path : '../' + link.id"
routerLinkActive=
"selected"
[routerLinkActiveOptions]=
"{ exact: true }"
>
<span>
{{ link.label }}
</span></a
>
</ng-container>
<ng-container
*ngIf=
"link.newWindow"
><a
[routerLink]=
"link.path ? ['/' + link.path] : ['../' + link.id]"
target=
"_blank"
class=
"newWindow"
><i
class=
"material-icons"
>
launch
</i>
<span>
{{ link.label }}
</span></a
></ng-container
></ng-container
>
</div>
</nav>
</div>
<!-- </ng-container> -->
</div>
This diff is collapsed.
src/app/common/components/sidebar-menu/sidebar-menu.component.ts
View file @
a135d23e
...
...
@@ -26,6 +26,7 @@ export { MenuLink };
})
export
class
SidebarMenuComponent
implements
OnInit
{
@
Input
()
menuId
:
string
;
@
Input
()
menuObj
:
Menu
;
menu
:
Menu
;
mobileMenuExpanded
=
false
;
...
...
@@ -38,7 +39,9 @@ export class SidebarMenuComponent implements OnInit {
ngOnInit
()
{
this
.
minds
=
window
.
Minds
;
this
.
user
=
this
.
session
.
getLoggedInUser
();
this
.
menu
=
sidebarMenus
.
find
(
menu
=>
menu
.
header
.
id
===
this
.
menuId
);
this
.
menu
=
this
.
menuObj
?
this
.
menuObj
:
sidebarMenus
.
find
(
menu
=>
menu
.
header
.
id
===
this
.
menuId
);
this
.
getUserRoles
();
this
.
grantPermissionsAndFindActiveMenu
();
}
...
...
@@ -53,7 +56,6 @@ export class SidebarMenuComponent implements OnInit {
}
grantPermissionsAndFindActiveMenu
()
{
// this.menu.forEach(this.menu => {
this
.
menu
.
header
[
'
permissionGranted
'
]
=
this
.
menu
.
header
.
permissions
?
this
.
checkForRoleMatch
(
this
.
menu
.
header
.
permissions
)
:
true
;
...
...
@@ -72,14 +74,6 @@ export class SidebarMenuComponent implements OnInit {
}
});
}
// if (location.pathname.indexOf(this.menus.header.path) !== -1) {
// this.menus.header['expanded'] = true;
// this.activeMenu = this.menu;
// } else {
// this.menu.header['expanded'] = false;
// }
// });
}
checkForRoleMatch
(
permissionsArray
)
{
...
...
This diff is collapsed.
src/app/common/services/form-toast.service.ts
View file @
a135d23e
import
{
Injectable
}
from
'
@angular/core
'
;
import
{
Observable
,
Subject
}
from
'
rxjs
'
;
// import { filter } from 'rxjs/operators';
export
interface
FormToast
{
type
?:
'
success
'
|
'
error
'
|
'
warning
'
|
'
info
'
|
null
;
...
...
@@ -13,11 +12,8 @@ export class FormToastService {
private
subject
=
new
Subject
<
FormToast
>
();
constructor
()
{}
// enable subscribing to toasts observable
onToast
():
Observable
<
FormToast
>
{
return
this
.
subject
.
asObservable
();
// .pipe(filter(x => x);
// .pipe(filter(x => x && x.toastId === toastId));
}
success
(
message
:
string
)
{
...
...
@@ -47,14 +43,16 @@ export class FormToastService {
inform
(
message
:
string
)
{
const
toast
:
FormToast
=
{
message
:
message
,
type
:
'
error
'
,
type
:
'
info
'
,
};
this
.
trigger
(
toast
);
}
trigger
(
toast
:
FormToast
)
{
toast
[
'
visible
'
]
=
true
;
if
(
!
toast
.
type
)
toast
.
type
=
'
info
'
;
if
(
!
toast
.
type
)
{
toast
.
type
=
'
info
'
;
}
this
.
subject
.
next
(
toast
);
}
}
This diff is collapsed.
src/app/modules/pro/settings/settings.component.html
View file @
a135d23e
This diff is collapsed.
Click to expand it.
src/app/modules/pro/settings/settings.component.scss
View file @
a135d23e
m-proSettings
{
display
:
block
;
@include
m-theme
()
{
background-color
:
themed
(
$m-white
);
}
form
{
margin
:
0
;
padding
:
0
;
...
...
@@ -17,23 +21,28 @@ m-proSettings {
[
class
*=
'm-proSettings__field'
]
{
position
:
relative
;
margin-
top
:
28px
;
margin-
bottom
:
28px
;
font-size
:
15px
;
line-height
:
20px
;
font-weight
:
300
;
@include
m-theme
()
{
color
:
themed
(
$m-grey-800
);
}
&
:first-child
{
margin-top
:
0
;
&
:last-child
{
margin-bottom
:
42px
;
}
&
.hasValidationRow
{
&
:not
(
:last-child
)
{
margin-bottom
:
6px
;
}
}
&
[
class
$
=
'--checkbox'
]
,
&
[
class
$
=
'--radio'
]
{
&
.m-proSettings__field--checkbox
,
&
.m-proSettings__field--radio
{
align-items
:
center
;
flex-flow
:
row
wrap
;
}
&
[
class
$
=
'--radio'
]
{
&
.m-proSettings__field--radio
{
.m-proSettings__row--label
{
margin-bottom
:
21px
;
}
...
...
@@ -50,17 +59,30 @@ m-proSettings {
flex-flow
:
row
nowrap
;
position
:
relative
;
}
&
[
class
$
=
'--validation'
]
{
margin-top
:
3px
;
min-height
:
22px
;
p
{
font-size
:
14px
;
line-height
:
19px
;
margin
:
0
8px
0
0
;
font-weight
:
300
;
@include
m-theme
()
{
color
:
themed
(
$m-red-dark
);
}
}
}
}
.stretchedField
{
.m-proSettings__row--label
m-tooltip
{
margin-left
:
-12px
;
.m-tooltip--bubble
{
right
:
12px
;
}
}
.m-proSettings__row--input
{
flex-flow
:
row
nowrap
;
}
.m-proSettings__row--validation
{
justify-content
:
flex-end
;
}
label
,
input
,
textarea
{
...
...
@@ -70,9 +92,11 @@ m-proSettings {
}
.m-proSettings__field--color
{
.m-proSettings__row--input
input
{
width
:
120px
;
box-sizing
:
border-box
;
.m-proSettings__row--input
{
input
{
width
:
120px
;
box-sizing
:
border-box
;
}
}
}
...
...
@@ -122,8 +146,24 @@ m-proSettings {
border
:
1px
solid
themed
(
$m-grey-50
);
}
&
:focus
{
&
:not
(
:read-only
)
{
@include
m-theme
()
{
border-color
:
themed
(
$m-blue
);
}
}
}
}
}
input
,
textarea
{
&
:not
(
:read-only
)
:not
(
:-moz-read-only
)
{
cursor
:
default
;
}
&
:not
(
.m-draggableList__cell
)
{
&
.ng-invalid.form-control
{
@include
m-theme
()
{
border-color
:
themed
(
$m-
blue
);
border-color
:
themed
(
$m-
red-dark
);
}
}
}
...
...
@@ -162,17 +202,22 @@ m-proSettings {
background-color
:
themed
(
$m-white
);
}
&
:hover
{
transform
:
scale
(
1
.04
);
@include
m-theme
()
{
border-color
:
rgba
(
themed
(
$m-grey-200
)
,
0
.7
);
box-shadow
:
0
3px
2px
-5px
rgba
(
themed
(
$m-black
)
,
0
.1
)
,
0
2px
2px
0
rgba
(
themed
(
$m-black
)
,
0
.04
)
,
0
1px
4px
0
rgba
(
themed
(
$m-black
)
,
0
.05
);
}
}
&
:active
{
transform
:
scale
(
0
.98
);
@include
m-theme
()
{
box-shadow
:
0
1px
1px
-4px
rgba
(
themed
(
$m-black
)
,
0
.
2
)
,
0
2px
2px
0
rgba
(
themed
(
$m-black
)
,
0
.14
)
,
0
1px
2px
0
rgba
(
themed
(
$m-black
)
,
0
.
12
);
box-shadow
:
0
3px
1px
-6px
rgba
(
themed
(
$m-black
)
,
0
.1
2
)
,
0
0px
1px
0
rgba
(
themed
(
$m-black
)
,
0
.07
)
,
0
1px
2px
0
rgba
(
themed
(
$m-black
)
,
0
.
08
);
}
}
&
:disabled
,
&
[
disabled
]
{
cursor
:
default
;
...
...
@@ -233,7 +278,7 @@ m-proSettings {
object-fit
:
cover
;
}
}
&
[
class
$
=
'
__o
verlay'
]
{
&
[
class
$
=
'
O
verlay'
]
{
opacity
:
0
;
position
:
absolute
;
top
:
0
;
...
...
@@ -249,12 +294,12 @@ m-proSettings {
background
:
rgba
(
themed
(
$m-black-always
)
,
0
.4
);
}
&
:hover
{
.m-proSettings__filePreviewOverlay
{
opacity
:
1
;
// display: flex;
// align-items: center;
// justify-content: center;
}
//
.m-proSettings__filePreviewOverlay {
opacity
:
1
;
// display: flex;
// align-items: center;
// justify-content: center;
//
}
}
}
...
...
@@ -290,25 +335,11 @@ m-proSettings {
&
.m-proSettingsDomain__validIcon--false
i
.material-icons
{
@include
m-theme
()
{
color
:
themed
(
$m-red
);
color
:
themed
(
$m-red
-dark
);
}
}
}
.m-proSettings__error
{
margin
:
0
0
16px
0
;
padding
:
8px
;
border-radius
:
8px
;
border
:
1px
solid
;
font-size
:
14px
;
line-height
:
1
;
@include
m-theme
()
{
color
:
themed
(
$m-red
);
border-color
:
themed
(
$m-red
);
}
}
m-formDescriptor
{
box-sizing
:
border-box
;
flex
:
1
0
160px
;
...
...
@@ -331,6 +362,11 @@ m-proSettings {
-ms-user-select
:
none
;
user-select
:
none
;
&
[
class
$
=
'--radio'
]
{
margin
:
0
24px
12px
0
;
padding-left
:
30px
;
}
input
{
position
:
absolute
;
opacity
:
0
;
...
...
@@ -338,8 +374,10 @@ m-proSettings {
height
:
0
;
width
:
0
;
&
:checked
~
[
class
*=
'm-proSettings__customInput'
]
{
@include
m-theme
()
{
background-color
:
themed
(
$m-blue
);
&
[
class
$
=
'--checkbox'
]
{
@include
m-theme
()
{
background-color
:
themed
(
$m-blue
);
}
}
&
:after
{
display
:
block
;
...
...
@@ -380,12 +418,12 @@ m-proSettings {
}
&
:after
{
border-radius
:
50%
;
left
:
8
px
;
top
:
8
px
;
width
:
7
px
;
height
:
7
px
;
left
:
3
px
;
top
:
3
px
;
width
:
0
px
;
height
:
0
px
;
@include
m-theme
()
{
border
:
2
px
solid
themed
(
$m-blue
);
border
:
7
px
solid
themed
(
$m-blue
);
}
}
}
...
...
@@ -406,6 +444,12 @@ m-proSettings {
@media
screen
and
(
max-width
:
1000px
)
{
m-proSettings
{
.stretchedField
{
// .m-proSettings__row--label m-tooltip {
// .m-tooltip--bubble {
// right: 12px;
// }
// }
[
class
*=
'm-proSettings__row'
]
{
flex-flow
:
row
wrap
;
label
,
...
...
@@ -427,3 +471,14 @@ m-proSettings {
}
}
}
@media
screen
and
(
max-width
:
$min-tablet
)
{
m-proSettings
{
.stretchedField
{
.m-proSettings__row--label
m-tooltip
{
.m-tooltip--bubble
{
right
:
12px
;
}
}
}
}
}
This diff is collapsed.
src/app/modules/pro/settings/settings.component.ts
View file @
a135d23e
...
...
@@ -5,6 +5,7 @@ import {
ElementRef
,
OnDestroy
,
OnInit
,
AfterViewInit
,
ViewChild
,
}
from
'
@angular/core
'
;
import
{
Subject
,
Subscription
}
from
'
rxjs
'
;
...
...
@@ -16,17 +17,15 @@ import { SiteService } from '../../../common/services/site.service';
import
{
debounceTime
}
from
'
rxjs/operators
'
;
import
{
DomSanitizer
,
SafeUrl
}
from
'
@angular/platform-browser
'
;
import
{
FormToastService
}
from
'
../../../common/services/form-toast.service
'
;
import
{
NgForm
}
from
'
@angular/forms
'
;
@
Component
({
selector
:
'
m-proSettings
'
,
changeDetection
:
ChangeDetectionStrategy
.
OnPush
,
templateUrl
:
'
settings.component.html
'
,
})
export
class
ProSettingsComponent
implements
OnInit
,
OnDestroy
{
//OJMTODO remove this
toastIndex
:
number
=
0
;
toastMessages
=
[
'
rye
'
,
'
wheat
'
,
'
7-grain
'
,
'
bagel
'
,
'
pumpernickel
'
];
export
class
ProSettingsComponent
implements
OnInit
,
AfterViewInit
,
OnDestroy
{
activeForm
:
NgForm
;
activeTab
:
any
;
tabs
=
[
{
...
...
@@ -63,6 +62,8 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
settings
:
any
;
init
:
boolean
=
false
;
inProgress
:
boolean
;
saved
:
boolean
=
false
;
...
...
@@ -73,7 +74,7 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
error
:
string
;
saveSuccessful
:
boolean
;
hexPattern
=
'
^#?([0-9A-Fa-f]{3}){1,2}$
'
;
// accepts both 3- and 6-digit codes, hash is optional
domainValidationSubject
:
Subject
<
any
>
=
new
Subject
<
any
>
();
...
...
@@ -89,6 +90,9 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
@
ViewChild
(
'
backgroundField
'
,
{
static
:
false
})
protected
backgroundField
:
ElementRef
<
HTMLInputElement
>
;
// TODO: make one of these for each form
@
ViewChild
(
'
themeForm
'
,
{
static
:
false
})
themeForm
:
NgForm
;
constructor
(
protected
service
:
ProService
,
protected
session
:
Session
,
...
...
@@ -105,6 +109,11 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
this
.
paramMap$
=
this
.
route
.
paramMap
.
subscribe
((
params
:
ParamMap
)
=>
{
const
activeTabParam
=
params
.
get
(
'
tab
'
);
this
.
activeTab
=
this
.
tabs
.
find
(
tab
=>
tab
.
id
===
activeTabParam
);
this
.
activeTab
[
'
saveStatus
'
]
=
'
unsaved
'
;
if
(
this
.
init
)
{
this
.
getActiveForm
();
this
.
detectChanges
();
}
});
this
.
param$
=
this
.
route
.
params
.
subscribe
(
params
=>
{
...
...
@@ -120,22 +129,23 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
.
subscribe
(()
=>
this
.
validateDomain
());
}
ngAfterViewInit
()
{
this
.
init
=
true
;
this
.
getActiveForm
();
this
.
detectChanges
();
}
getActiveForm
()
{
const
tempFormStr
=
this
.
activeTab
.
id
+
'
Form
'
;
this
.
activeForm
=
this
[
tempFormStr
];
console
.
log
(
this
.
activeForm
);
}
ngOnDestroy
()
{
this
.
paramMap$
.
unsubscribe
();
this
.
param$
.
unsubscribe
();
this
.
domainValidation$
.
unsubscribe
();
}
// OJMTODO remove this after testing
tempToast
()
{
this
.
formToastService
.
warn
(
this
.
toastMessages
[
this
.
toastIndex
]);
if
(
this
.
toastIndex
<
6
)
{
this
.
toastIndex
++
;
}
else
{
this
.
toastIndex
=
0
;
}
}
async
load
()
{
this
.
inProgress
=
true
;
this
.
detectChanges
();
...
...
@@ -169,6 +179,7 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
}
catch
(
e
)
{
this
.
isDomainValid
=
null
;
this
.
error
=
(
e
&&
e
.
message
)
||
'
Error checking domain
'
;
this
.
formToastService
.
error
(
this
.
error
);
}
this
.
detectChanges
();
...
...
@@ -217,6 +228,16 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
return
this
.
settings
[
`
${
type
}
_image`
];
}
onSubmit
(
form
)
{
console
.
log
(
form
);
console
.
log
(
form
.
value
);
this
.
error
=
null
;
this
.
activeTab
.
saveStatus
=
'
saving
'
;
this
.
detectChanges
();
// TODO: add '#' to colors without them
}
async
save
()
{
this
.
error
=
null
;
this
.
inProgress
=
true
;
...
...
@@ -243,10 +264,14 @@ export class ProSettingsComponent implements OnInit, OnDestroy {
this
.
settings
=
settings
;
await
this
.
service
.
set
(
this
.
settings
,
this
.
user
);
this
.
saveSuccessful
=
true
;
this
.
formToastService
.
success
(
'
Pro settings have been successfully updated
'
);
this
.
activeTab
.
saveStatus
=
'
saved
'
;
}
catch
(
e
)
{
this
.
error
=
e
.
message
;
this
.
saveSuccessful
=
false
;
this
.
formToastService
.
error
(
'
Error:
'
+
this
.
error
);
this
.
activeTab
.
saveStatus
=
'
unsaved
'
;
}
this
.
saved
=
true
;
...
...
This diff is collapsed.