MOBILE-3631 core: Add splitview placeholder page
parent
18cb43aa5e
commit
001048fc9a
|
@ -1,5 +1,7 @@
|
||||||
<ion-content class="menu">
|
<ion-content class="menu">
|
||||||
<ng-content></ng-content>
|
<ng-content></ng-content>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
<ion-router-outlet class="content"></ion-router-outlet>
|
<ion-router-outlet class="content-outlet"></ion-router-outlet>
|
||||||
<!-- @todo placeholder -->
|
<core-empty-box class="content-placeholder" icon="fas-arrow-circle-left" [message]="placeholderText | translate"
|
||||||
|
[flipIconRtl]="true">
|
||||||
|
</core-empty-box>
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
// @todo RTL layout
|
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
--menu-min-width: 270px;
|
--menu-min-width: 270px;
|
||||||
--menu-max-width: 28%;
|
--menu-max-width: 28%;
|
||||||
|
--menu-box-shadow: var(--core-menu-box-shadow-end);
|
||||||
|
--menu-z: 2;
|
||||||
|
--menu-border-width: 1;
|
||||||
--menu-display: flex;
|
--menu-display: flex;
|
||||||
--content-display: block;
|
--content-display: block;
|
||||||
--border-width: 1;
|
--content-outlet-display: none;
|
||||||
|
--content-placeholder-display: var(--content-display);
|
||||||
|
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
@ -17,54 +19,33 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
|
||||||
|
|
||||||
:host(.menu-only) {
|
|
||||||
--menu-min-width: 0;
|
|
||||||
--menu-max-width: 100%;
|
|
||||||
--content-display: none;
|
|
||||||
--border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host(.content-only) {
|
|
||||||
--menu-display: none;
|
|
||||||
--border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
:host-context(ion-app.md) {
|
|
||||||
--border: calc(var(--border-width) * 1px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, .13))));
|
|
||||||
}
|
|
||||||
|
|
||||||
:host-context(ion-app.ios) {
|
|
||||||
--border: calc(var(--border-width) * .55px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-250, #c8c7cc)));
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu,
|
.menu,
|
||||||
.content {
|
.content-outlet {
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
box-shadow: none !important;
|
box-shadow: none;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
|
box-shadow: var(--menu-box-shadow);
|
||||||
|
z-index: var(--menu-z);
|
||||||
display: var(--menu-display);
|
display: var(--menu-display);
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
order: -1;
|
order: -1;
|
||||||
border-left: unset;
|
width: 100%;
|
||||||
border-right: unset;
|
|
||||||
border-inline-start: 0;
|
border-inline-start: 0;
|
||||||
border-inline-end: var(--border);
|
border-inline-end: var(--border);
|
||||||
min-width: var(--menu-min-width);
|
min-width: var(--menu-min-width);
|
||||||
max-width: var(--menu-max-width);
|
max-width: var(--menu-max-width);
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content-outlet {
|
||||||
display: var(--content-display);
|
display: var(--content-outlet-display);
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
||||||
::ng-deep ion-header {
|
::ng-deep ion-header {
|
||||||
|
@ -72,3 +53,40 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.content-placeholder {
|
||||||
|
display: var(--content-placeholder-display);
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
background-color: var(--ion-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.menu-only) {
|
||||||
|
--menu-min-width: 0;
|
||||||
|
--menu-max-width: 100%;
|
||||||
|
--content-display: none;
|
||||||
|
--menu-border-width: 0;
|
||||||
|
--menu-box-shadow: none;
|
||||||
|
--menu-z: 0;
|
||||||
|
--selected-item-border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.content-only) {
|
||||||
|
--menu-display: none;
|
||||||
|
--menu-border-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
:host(.outlet-activated) {
|
||||||
|
--content-placeholder-display: none;
|
||||||
|
--content-outlet-display: var(--content-display);
|
||||||
|
}
|
||||||
|
|
||||||
|
:host-context(ion-app.md) {
|
||||||
|
--border: calc(var(--menu-border-width) * 1px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-150, rgba(0, 0, 0, .13))));
|
||||||
|
}
|
||||||
|
|
||||||
|
:host-context(ion-app.ios) {
|
||||||
|
--border: calc(var(--menu-border-width) * .55px) solid var(--ion-item-border-color, var(--ion-border-color, var(--ion-color-step-250, #c8c7cc)));
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { AfterViewInit, Component, ElementRef, HostBinding, OnDestroy, ViewChild } from '@angular/core';
|
import { AfterViewInit, Component, ElementRef, HostBinding, Input, OnDestroy, ViewChild } from '@angular/core';
|
||||||
import { IonRouterOutlet } from '@ionic/angular';
|
import { IonRouterOutlet } from '@ionic/angular';
|
||||||
import { CoreScreen } from '@services/screen';
|
import { CoreScreen } from '@services/screen';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
@ -32,6 +32,7 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
|
||||||
|
|
||||||
@ViewChild(IonRouterOutlet) outlet!: IonRouterOutlet;
|
@ViewChild(IonRouterOutlet) outlet!: IonRouterOutlet;
|
||||||
@HostBinding('class') classes = '';
|
@HostBinding('class') classes = '';
|
||||||
|
@Input() placeholderText = 'core.emptysplit';
|
||||||
isNested = false;
|
isNested = false;
|
||||||
|
|
||||||
private subscriptions?: Subscription[];
|
private subscriptions?: Subscription[];
|
||||||
|
@ -65,6 +66,10 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
|
||||||
private updateClasses(): void {
|
private updateClasses(): void {
|
||||||
const classes: string[] = [this.getCurrentMode()];
|
const classes: string[] = [this.getCurrentMode()];
|
||||||
|
|
||||||
|
if (this.outlet.isActivated) {
|
||||||
|
classes.push('outlet-activated');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isNested) {
|
if (this.isNested) {
|
||||||
classes.push('nested');
|
classes.push('nested');
|
||||||
}
|
}
|
||||||
|
@ -92,4 +97,13 @@ export class CoreSplitViewComponent implements AfterViewInit, OnDestroy {
|
||||||
return CoreSplitViewMode.MenuAndContent;
|
return CoreSplitViewMode.MenuAndContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if both panels are shown. It depends on screen width.
|
||||||
|
*
|
||||||
|
* @return If split view is enabled.
|
||||||
|
*/
|
||||||
|
isOn(): boolean {
|
||||||
|
return this.outlet.isActivated;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
:host {
|
:host {
|
||||||
|
--side-blocks-box-shadow: var(--core-menu-box-shadow-start);
|
||||||
|
|
||||||
&.core-no-blocks .core-course-blocks-content {
|
&.core-no-blocks .core-course-blocks-content {
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +22,7 @@
|
||||||
div.core-course-blocks-side {
|
div.core-course-blocks-side {
|
||||||
max-width: var(--side-blocks-max-width);
|
max-width: var(--side-blocks-max-width);
|
||||||
min-width: var(--side-blocks-min-width);
|
min-width: var(--side-blocks-min-width);
|
||||||
box-shadow: -4px 0px 16px rgba(0, 0, 0, 0.18);
|
box-shadow: var(--side-blocks-box-shadow);
|
||||||
z-index: 2;
|
z-index: 2;
|
||||||
// @todo @include core-split-area-end();
|
// @todo @include core-split-area-end();
|
||||||
}
|
}
|
||||||
|
@ -53,7 +55,7 @@
|
||||||
:host-context([dir="rtl"]).core-has-blocks {
|
:host-context([dir="rtl"]).core-has-blocks {
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
div.core-course-blocks-side {
|
div.core-course-blocks-side {
|
||||||
box-shadow: 4px 0px 16px rgba(0, 0, 0, 0.18);
|
box-shadow: var(--side-blocks-box-shadow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,6 +91,21 @@ export class CoreNavigatorService {
|
||||||
return matches?.[1] ?? null;
|
return matches?.[1] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if a section is loaded on the split view (tablet mode).
|
||||||
|
*
|
||||||
|
* @param path Path, can be a glob pattern.
|
||||||
|
* @return Whether the active route is using the given path.
|
||||||
|
*/
|
||||||
|
isCurrentPathInTablet(path: string): boolean {
|
||||||
|
if (CoreScreen.instance.isMobile) {
|
||||||
|
// Split view is off.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.isCurrent(path);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigate to a new path.
|
* Navigate to a new path.
|
||||||
*
|
*
|
||||||
|
@ -213,6 +228,8 @@ export class CoreNavigatorService {
|
||||||
* @return Previous path.
|
* @return Previous path.
|
||||||
*/
|
*/
|
||||||
getPreviousPath(): string {
|
getPreviousPath(): string {
|
||||||
|
// @todo: Remove this method and the used attributes.
|
||||||
|
// This is a quick workarround to avoid loops. Ie, in messages we can navigate to user profile and there to messages.
|
||||||
return CoreUrlUtils.instance.removeUrlParams(this.previousPath || '');
|
return CoreUrlUtils.instance.removeUrlParams(this.previousPath || '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,10 @@ ion-icon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[dir=rtl] ion-icon.icon-flip-rtl {
|
||||||
|
transform: scaleX(-1);
|
||||||
|
}
|
||||||
|
|
||||||
// Ionic alert.
|
// Ionic alert.
|
||||||
ion-alert.core-alert-network-error .alert-head {
|
ion-alert.core-alert-network-error .alert-head {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
|
@ -106,6 +106,7 @@
|
||||||
--color: var(--custom-bottom-tabs-color, var(--white));
|
--color: var(--custom-bottom-tabs-color, var(--white));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--core-toolbar-button-image-width: var(--custom-toolbar-button-image-width, 32px);
|
||||||
--ion-statusbar-background: var(--custom-toolbar-background, var(--ion-color-primary));
|
--ion-statusbar-background: var(--custom-toolbar-background, var(--ion-color-primary));
|
||||||
ion-toolbar {
|
ion-toolbar {
|
||||||
--color: var(--custom-toolbar-color, var(--ion-color-primary-contrast));
|
--color: var(--custom-toolbar-color, var(--ion-color-primary-contrast));
|
||||||
|
@ -170,8 +171,6 @@
|
||||||
--selected-item-color: var(--custom-selected-item-color, var(--core-color));
|
--selected-item-color: var(--custom-selected-item-color, var(--core-color));
|
||||||
--selected-item-border-width: var(--custom-selected-item-border-width, 5px);
|
--selected-item-border-width: var(--custom-selected-item-border-width, 5px);
|
||||||
|
|
||||||
--drop-shadow: var(--custom-drop-shadow, 0, 0, 0, 0.2);
|
|
||||||
|
|
||||||
--core-login-background: var(--custom-login-background, var(--white));
|
--core-login-background: var(--custom-login-background, var(--white));
|
||||||
--core-login-text-color: var(--custom-login-text-color, var(--black));
|
--core-login-text-color: var(--custom-login-text-color, var(--black));
|
||||||
|
|
||||||
|
@ -188,11 +187,8 @@
|
||||||
--core-star-color: var(--custom-star-color, var(--core-color));
|
--core-star-color: var(--custom-star-color, var(--core-color));
|
||||||
|
|
||||||
--core-large-avatar-size: var(--custom-large-avatar-size, 90px);
|
--core-large-avatar-size: var(--custom-large-avatar-size, 90px);
|
||||||
|
|
||||||
--core-avatar-size: var(--custom-avatar-size, 40px);
|
--core-avatar-size: var(--custom-avatar-size, 40px);
|
||||||
|
|
||||||
--core-toolbar-button-image-width: var(--custom-toolbar-button-image-width, 32px);
|
|
||||||
|
|
||||||
--core-send-message-input-background: var(--custom-send-message-input-background, var(--gray));
|
--core-send-message-input-background: var(--custom-send-message-input-background, var(--gray));
|
||||||
--core-send-message-input-color: var(--custom-send-message-input-color, var(--black));
|
--core-send-message-input-color: var(--custom-send-message-input-color, var(--black));
|
||||||
|
|
||||||
|
@ -214,6 +210,11 @@
|
||||||
--addon-messages-avatar-size: var(--custom-messages-avatar-size, 30px);
|
--addon-messages-avatar-size: var(--custom-messages-avatar-size, 30px);
|
||||||
--addon-messages-discussion-badge: var(--custom-messages-discussion-badge, var(--core-color));
|
--addon-messages-discussion-badge: var(--custom-messages-discussion-badge, var(--core-color));
|
||||||
--addon-messages-discussion-badge-text: var(--custom-messages-discussion-badge-text, var(--white));
|
--addon-messages-discussion-badge-text: var(--custom-messages-discussion-badge-text, var(--white));
|
||||||
|
|
||||||
|
--drop-shadow: var(--custom-drop-shadow, 0, 0, 0, 0.2);
|
||||||
|
|
||||||
|
--core-menu-box-shadow-end: var(--custom-menu-box-shadow-end, -4px 0px 16px rgba(0, 0, 0, 0.18));
|
||||||
|
--core-menu-box-shadow-start: var(--custom-menu-box-shadow-start, 4px 0px 16px rgba(0, 0, 0, 0.18));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue