Skip to content

Commit

Permalink
Version 4.14.2
Browse files Browse the repository at this point in the history
  • Loading branch information
acaurrinhos committed Dec 22, 2020
1 parent a8cd471 commit 0181376
Show file tree
Hide file tree
Showing 26 changed files with 198 additions and 110 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Cyclos 4 UI",
"description": "The new Cyclos 4 frontend",
"icon": "cyclos.png",
"version": "4.14.1",
"version": "4.14.2",
"license": "MIT",
"author": {
"name": "Cyclos development team",
Expand Down
5 changes: 0 additions & 5 deletions src/_definitions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ $accent: #2795c4 !default;
$primary-dark: #133f52 !default;
$accent-dark: #2795c4 !default;

// Make sure the font import URL and the font family (sans serif) are in sync
$font-import-url: "https://fonts.googleapis.com/css?family=Roboto:400,500" !default;
$font-family-sans-serif: 'Roboto', sans-serif !default;
$font-size-base: 0.875rem !default;
$font-weight-light: 300 !default;
$font-weight-normal: 400 !default;
$font-weight-bold: 500 !default;

// Toggle for enabling / disabling shadows on most parts
$enable-shadows: true !default;
Expand Down
15 changes: 8 additions & 7 deletions src/app/core/data-for-frontend-holder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HttpErrorResponse } from '@angular/common/http';
import { Injectable, Injector } from '@angular/core';
import { ApiConfiguration } from 'app/api/api-configuration';
import {
Auth, DataForFrontend, DataForUi, FrontendBanner, FrontendEnum,
FrontendIcon, FrontendPage, FrontendScreenSizeEnum, RoleEnum, User
Expand All @@ -9,7 +10,7 @@ import { FrontendService } from 'app/api/services/frontend.service';
import { ErrorStatus } from 'app/core/error-status';
import { NextRequestState } from 'app/core/next-request-state';
import { I18n } from 'app/i18n/i18n';
import { isDevServer, setReloadButton, setRootAlert } from 'app/shared/helper';
import { isDevServer, setReloadButton, setRootAlert, urlJoin } from 'app/shared/helper';
import moment from 'moment-mini-ts';
import { BehaviorSubject, Observable, of, Subscription } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
Expand All @@ -30,6 +31,7 @@ export class DataForFrontendHolder {
private authService: AuthService,
private i18n: I18n,
private injector: Injector,
private apiConfiguration: ApiConfiguration,
private nextRequestState: NextRequestState) {
}

Expand Down Expand Up @@ -66,7 +68,7 @@ export class DataForFrontendHolder {

if (dataForFrontend.frontend === FrontendEnum.CLASSIC && !isDevServer()) {
// Redirect the user to the classic frontend
this.redirectToClassicFrontend(dataForFrontend);
this.redirectToClassicFrontend();
return of(null);
}

Expand Down Expand Up @@ -206,22 +208,21 @@ export class DataForFrontendHolder {
body: { frontend: FrontendEnum.CLASSIC }
}).subscribe(() => {
// ... then redirect
this.redirectToClassicFrontend(this.dataForFrontend);
this.redirectToClassicFrontend();
});
} else {
// Just redirect
this.redirectToClassicFrontend(this.dataForFrontend);
this.redirectToClassicFrontend();
}
}

private redirectToClassicFrontend(dataForFrontend: DataForFrontend) {
private redirectToClassicFrontend() {
const url = window.location.href;
const pos = url.indexOf('/ui/');
if (pos >= 0) {
window.location.assign(`${url.substr(0, pos)}/classic`);
} else {
const dataForUi = (dataForFrontend || {}).dataForUi || {};
window.location.assign(`${dataForUi.rootUrl}/classic`);
window.location.assign(urlJoin(this.apiConfiguration.rootUrl, '..', 'classic'));
}
}

Expand Down
7 changes: 3 additions & 4 deletions src/app/core/format.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ApiConfiguration } from 'app/api/api-configuration';
import { Currency, DataForFrontend, TimeFieldEnum, TimeInterval, WeekDayEnum } from 'app/api/models';
import { I18nLoadingService } from 'app/core/i18n-loading.service';
import { I18n } from 'app/i18n/i18n';
import { empty } from 'app/shared/helper';
import { empty, urlJoin } from 'app/shared/helper';
import Big from 'big.js';
import moment from 'moment-mini-ts';
import { DataForFrontendHolder } from './data-for-frontend-holder';
Expand Down Expand Up @@ -181,9 +181,8 @@ export class FormatService {
* Returns the full URL to the configuration image (logo) with the given id
*/
getLogoUrl(id: string): string {
return this.apiConfiguration.rootUrl
+ '/../content/images/currentConfiguration/'
+ id + '?' + this._dataForFrontend.dataForUi.resourceCacheKey;
return urlJoin(this.apiConfiguration.rootUrl, '..', 'content', 'images', 'currentConfiguration', id) + '?'
+ this._dataForFrontend.dataForUi.resourceCacheKey;
}

/**
Expand Down
33 changes: 3 additions & 30 deletions src/app/core/layout.service.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { BreakpointObserver } from '@angular/cdk/layout';
import { Injectable } from '@angular/core';
import { FrontendScreenSizeEnum } from 'app/api/models';
import { DataForFrontendHolder } from 'app/core/data-for-frontend-holder';
import { blank, ElementReference, empty, htmlCollectionToArray } from 'app/shared/helper';
import { Escape, ShortcutService } from 'app/core/shortcut.service';
import { isEqual, trim } from 'lodash-es';
import { ElementReference, empty, htmlCollectionToArray } from 'app/shared/helper';
import { isEqual } from 'lodash-es';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { distinctUntilChanged, map } from 'rxjs/operators';
import { FrontendScreenSizeEnum } from 'app/api/models';

export type Theme = 'light' | 'dark';
export const Themes: Theme[] = ['light', 'dark'];
Expand Down Expand Up @@ -442,18 +442,10 @@ export class LayoutService {

private readStylesAndApplyWhenReady() {
const style = getComputedStyle(document.body);

this._fontUrl = trim(style.getPropertyValue('--font-import-url'), '" ');
if (blank(this._fontUrl)) {
// Styles are not available yet
setTimeout(() => this.readStylesAndApplyWhenReady(), 100);
return;
}
for (const name of ColorVariables) {
this._colors.set(name, style.getPropertyValue('--' + name).trim());
this._colorsDark.set(name, style.getPropertyValue('--' + name + '-dark').trim());
}
this.applyFontImport();
this.applyThemeColor();
}

Expand Down Expand Up @@ -534,23 +526,4 @@ export class LayoutService {
}
meta.content = this.themeColor;
}

private applyFontImport() {
const url = this._fontUrl;
if (empty(url)) {
return;
}

const id = 'fontImportLink';
let link: HTMLLinkElement = document.getElementById(id) as HTMLLinkElement;
if (!link) {
link = document.createElement('link');
link.id = id;
link.rel = 'stylesheet';
document.head.appendChild(link);
link.href = url;
} else if (link.href !== url) {
link.href = url;
}
}
}
7 changes: 4 additions & 3 deletions src/app/core/push-notifications.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
PushNotificationEventKind, TransactionView
} from 'app/api/models';
import { NextRequestState } from 'app/core/next-request-state';
import { empty } from 'app/shared/helper';
import { empty, urlJoin } from 'app/shared/helper';
import { EventSourcePolyfill } from 'ng-event-source';
import { Subject } from 'rxjs';

Expand Down Expand Up @@ -52,7 +52,7 @@ export class PushNotificationsService {
return;
}
const kinds = new Set<string>(Kinds);
let url = this.apiConfiguration.rootUrl + '/push/subscribe?clientId=' + ClientId;
let url = urlJoin(this.apiConfiguration.rootUrl, 'push', 'subscribe') + '?clientId=' + ClientId;
kinds.forEach(kind => url += '&kinds=' + kind);
this.eventSource = new EventSourcePolyfill(url, {
headers: this.nextRequestState.headers,
Expand All @@ -75,7 +75,8 @@ export class PushNotificationsService {
// Already opened
return;
}
const url = `${this.apiConfiguration.rootUrl}/push/subscribe?clientId=${ClientId}&kinds=`
const url = urlJoin(this.apiConfiguration.rootUrl, 'push', 'subscribe')
+ `?clientId=${ClientId}&kinds=`
+ PushNotificationEventKind.IDENTITY_PROVIDER_CALLBACK
+ `&identityProviderRequestId=${requestId}`;
this.eventSource = new EventSourcePolyfill(url, {
Expand Down
5 changes: 2 additions & 3 deletions src/app/shared/api-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,11 @@ export class ApiHelper {
* - Expired secondary password
*/
static isRestrictedAccess(dataForFrontend: DataForFrontend): boolean {
if (dataForFrontend.frontend === FrontendEnum.CLASSIC && !isDevServer()) {
if (dataForFrontend?.frontend === FrontendEnum.CLASSIC && !isDevServer()) {
// Must redirect to the new frontend
return true;
}
const dataForUi = (dataForFrontend || {}).dataForUi || {};
const auth = dataForUi.auth || {};
const auth = dataForFrontend?.dataForUi?.auth || {};
return auth.expiredPassword || auth.pendingAgreements
|| auth.pendingSecondaryPassword || auth.expiredSecondaryPassword;
}
Expand Down
15 changes: 15 additions & 0 deletions src/app/shared/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,21 @@ export function isDevServer() {
return window.location.port === '4200';
}

/**
* Joins multiple URL parts, making sure to never concatenate dulicated slashes
*/
export function urlJoin(...parts: string[]) {
return parts.map(p => {
if (p.startsWith('/')) {
p = p.substr(1);
}
if (p.endsWith('/')) {
p = p.substr(0, p.length - 1);
}
return p;
}).join('/');
}

/**
* Returns the SVG content of the root spinner
*/
Expand Down
5 changes: 3 additions & 2 deletions src/app/shared/image-upload.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { CustomField, Image, ImageKind, TempImageTargetEnum, UserImageKind } fro
import { ImagesService } from 'app/api/services/images.service';
import { NextRequestState } from 'app/core/next-request-state';
import { BaseComponent } from 'app/shared/base.component';
import { resizeImage, ResizeResult, truthyAttr } from 'app/shared/helper';
import { resizeImage, ResizeResult, truthyAttr, urlJoin } from 'app/shared/helper';
import { BehaviorSubject, forkJoin, Observable, Subscription } from 'rxjs';
import { first, switchMap } from 'rxjs/operators';

Expand Down Expand Up @@ -236,7 +236,8 @@ export class ImageUploadComponent extends BaseComponent implements OnDestroy {
data.append('image', file.content, file.name);

url = this.nextRequestState.appendAuth(url);
file.subscription = this.http.post(`${this.apiConfiguration.rootUrl}/${url}`, data, {
url = urlJoin(this.apiConfiguration.rootUrl, url);
file.subscription = this.http.post(url, data, {
observe: 'events',
reportProgress: true,
responseType: 'text',
Expand Down
3 changes: 2 additions & 1 deletion src/app/shared/password-input.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ export class PasswordInputComponent
if (this.enteredVKPassword.length < this.passwordInput.buttons.length) {
this.currentVKCombinations = chunk(this.passwordInput.buttons[this.enteredVKPassword.length], this.passwordInput.buttonsPerRow);
}
this.formControl.setValue(this.enteredVKPassword.length === 0 ? '' : this.passwordInput.id + '|' + this.enteredVKPassword.join('|'));
this.formControl.setValue(this.enteredVKPassword.length === 0 ? ''
: this.passwordInput.virtualKeyboardId + '|' + this.enteredVKPassword.join('|'));
}

onDisabledChange(isDisabled: boolean): void {
Expand Down
2 changes: 0 additions & 2 deletions src/app/shared/spinner.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
<div *ngIf="bootstrap" class="spinner-border" role="status"
[ngStyle]="{width: size, height: size}"></div>
<div *ngIf="!bootstrap" [ngStyle]="{width: size, height: size}"
[innerHTML]="svg | trust">
17 changes: 13 additions & 4 deletions src/app/shared/spinner.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, HostBinding, Input } from '@angular/core';
import { ChangeDetectionStrategy, Component, ElementRef, HostBinding, Input, OnInit } from '@angular/core';
import { getRootSpinnerSvg, truthyAttr } from 'app/shared/helper';

/**
Expand All @@ -10,9 +10,7 @@ import { getRootSpinnerSvg, truthyAttr } from 'app/shared/helper';
templateUrl: 'spinner.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SpinnerComponent {

svg = getRootSpinnerSvg();
export class SpinnerComponent implements OnInit {

@HostBinding('class.spinner') classSpinner = true;

Expand All @@ -25,4 +23,15 @@ export class SpinnerComponent {
set bootstrap(show: boolean | string) {
this._bootstrap = truthyAttr(show);
}

constructor(private element: ElementRef<HTMLElement>) { }

ngOnInit() {
if (!this.bootstrap) {
const element = this.element.nativeElement;
element.style.width = this.size;
element.style.height = this.size;
element.innerHTML = getRootSpinnerSvg();
}
}
}
4 changes: 2 additions & 2 deletions src/app/shared/temp-file-upload.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ApiConfiguration } from 'app/api/api-configuration';
import { CustomFieldDetailed, InputErrorCode, StoredFile } from 'app/api/models';
import { FilesService } from 'app/api/services/files.service';
import { BaseComponent } from 'app/shared/base.component';
import { empty } from 'app/shared/helper';
import { empty, urlJoin } from 'app/shared/helper';
import { BehaviorSubject, forkJoin, Observable, Subscription } from 'rxjs';

/**
Expand Down Expand Up @@ -151,7 +151,7 @@ export class TempFileUploadComponent extends BaseComponent {

doUpload(file: FileToUpload): Observable<StoredFile> {
return new Observable(observer => {
const url = `${this.apiConfiguration.rootUrl}/files/temp`;
const url = urlJoin(this.apiConfiguration.rootUrl, 'files', 'temp');
const data = new FormData();
data.append('file', file.file, file.name);

Expand Down
7 changes: 5 additions & 2 deletions src/app/ui/content/content-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,22 @@ export class ContentPageComponent extends BaseViewPageComponent<PageWithContent>
return `
<div id="${wrapperId}" class="iframe-content-wrapper">
<div id="${spinnerId}" class="iframe-loading-spinner">
<div class="spinner">${spinner}</div>
${spinner}
</div>
<iframe id="${iframeId}"
src="${actualUrl}"
class="iframe-content"
style="display:block;width:1px;min-width:100%;"
style="display:block;width:1px;min-width:100%;position:absolute;left:-10000px;top:0px;"
onload="
iFrameResize({
heightCalculationMethod: navigator.userAgent.indexOf('MSIE') < 0 ? 'lowestElement' : 'max',
checkOrigin: false,
warningTimeout: 0
}, '#${iframeId}');
document.getElementById('${wrapperId}').removeChild(document.getElementById('${spinnerId}'));
this.style.position = 'relative';
this.style.top = '';
this.style.left = '';
">
</iframe>
</div>
Expand Down
27 changes: 20 additions & 7 deletions src/app/ui/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@ import { DataForFrontendHolder } from 'app/core/data-for-frontend-holder';
import { I18nLoadingService } from 'app/core/i18n-loading.service';
import { IconLoadingService } from 'app/core/icon-loading.service';
import { NextRequestState } from 'app/core/next-request-state';
import { isDevServer, isSameOrigin } from 'app/shared/helper';
import { isDevServer, urlJoin } from 'app/shared/helper';
import { concat, of } from 'rxjs';
import { catchError, switchMap } from 'rxjs/operators';

declare let apiRoot: string;

// Initializes the shared services
export function initialize(
location: Location,
Expand All @@ -21,13 +19,21 @@ export function initialize(
nextRequestState: NextRequestState
): () => any {
return async () => {
// Make sure the api root doesn't end with a slash
if (apiRoot.endsWith('/')) {
apiRoot = apiRoot.substring(0, apiRoot.length - 1);
let apiRoot = 'api';
if (!isDevServer()) {
let href = window.location.href;
if (!href.endsWith('/')) {
href += '/';
}
const pos = href.indexOf('/ui/');
if (pos >= 0) {
apiRoot = href.substr(0, pos) + '/api';
}
}
console.log(`Using API root = ${apiRoot}`);

// Will split the session token if running on the same origin and not in Angular's development server
nextRequestState.useCookie = isSameOrigin(apiRoot) && !isDevServer();
nextRequestState.useCookie = !isDevServer();

// When receiving an external session token, actually assign the URL again
const path = location.path();
Expand Down Expand Up @@ -67,6 +73,13 @@ export function initialize(
switchMap(() => of(dataForFrontend)),
catchError(() => of(dataForFrontend)));
});
if (isDevServer()) {
dataForFrontendHolder.registerLoadHook(dataForFrontend => {
const link = document.getElementById('robotoLink') as HTMLLinkElement;
link.href = urlJoin(dataForFrontend.dataForUi.rootUrl, 'fonts/roboto.css');
return of(null);
});
}
const dataForFrontend$ = dataForFrontendHolder.initialize();

return await concat(i18n$, dataForFrontend$).toPromise();
Expand Down
Loading

0 comments on commit 0181376

Please sign in to comment.