harbor/src/portal/src/app/shared/units/shared.utils.ts

227 lines
7.0 KiB
TypeScript
Raw Normal View History

2017-05-11 08:59:12 +02:00
// Copyright (c) 2017 VMware, Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { NgForm } from '@angular/forms';
import { MessageService } from '../components/global-message/message.service';
import {
AlertType,
Add date/time format setting in portal (#16796) * Add date/time format setting in portal Currently, the format used for rendering dates and times is derived from the language/locale selected by the user. The formats used in the en-US locale ("English" in Harbor's GUI) are ambiguous and hard to understand for many users. For example, is 10/11/21 the 10th of November, 2021, the 11th of October, 2021, or even something else like the 21nd of November, 2010? Even if one does know how to interpret it in theory, such dates are essentially enciphered and must be mentally deciphered by the user every time, incurring unnecessary cognitive load. Similarly, many users are used to the 24-hour clock rather than the 12-hour clock (AM/PM), and so on. This PR adds a dropdown next to the existing language selector that lets the user choose between the default format for the current locale and the internationally standardized, unambiguous ISO 8601 format. For example, when viewing a list of resources, the ISO 8601 option makes points in time display as > 2021-10-11, 13:37 instead of > 10/11/21, 1:37 PM thereby improving the user experience considerably for users not familiar with the US date/time format (or, in general, the default format for the locale they have selected). The localized versions of the "Default" label are copied from `SCANNER.DEFAULT` in each locale. Signed-off-by: Simon Alling <alling.simon@gmail.com> * Fix indentation Signed-off-by: Simon Alling <alling.simon@gmail.com> * Remove redundant localStorage existence check Signed-off-by: Simon Alling <alling.simon@gmail.com> * Run 'npm run lint -- --fix'
2022-05-24 11:45:34 +02:00
DatetimeRendering,
DATETIME_RENDERINGS,
DEFAULT_DATETIME_RENDERING_LOCALSTORAGE_KEY,
DefaultDatetimeRendering,
httpStatusCode,
SupportedLanguage,
LANGUAGES,
} from '../entities/shared.const';
/**
* To check if form is empty
*/
export const isEmptyForm = function (ngForm: NgForm): boolean {
if (ngForm && ngForm.form) {
let values = ngForm.form.value;
if (values) {
for (let key in values) {
if (values[key]) {
return false;
}
}
}
}
return true;
};
/**
* A type guard that checks if the given value is a supported language.
*/
export function isSupportedLanguage(x: unknown): x is SupportedLanguage {
return Object.keys(LANGUAGES).some(lang => x === lang);
}
/**
* Hanlde the 401 and 403 code
*
* If handled the 401 or 403, then return true otherwise false
*/
export const accessErrorHandler = function (
error: any,
msgService: MessageService
): boolean {
if (error && error.status && msgService) {
if (error.status === httpStatusCode.Unauthorized) {
msgService.announceAppLevelMessage(
error.status,
'UNAUTHORIZED_ERROR',
AlertType.DANGER
);
return true;
}
}
return false;
};
// Provide capability of reconstructing the query paramter
export const maintainUrlQueryParmas = function (
uri: string,
key: string,
value: string
): string {
let re: RegExp = new RegExp('([?&])' + key + '=.*?(&|#|$)', 'i');
if (value === undefined) {
if (uri.match(re)) {
return uri.replace(re, '$1$2');
} else {
return uri;
}
} else {
if (uri.match(re)) {
return uri.replace(re, '$1' + key + '=' + value + '$2');
} else {
let hash = '';
if (uri.indexOf('#') !== -1) {
hash = uri.replace(/.*#/, '#');
uri = uri.replace(/#.*/, '');
}
let separator = uri.indexOf('?') !== -1 ? '&' : '?';
return uri + separator + key + '=' + value + hash;
}
}
};
/**
* handle docker client response error
* {"code":412,"message":"{\"errors\":[{\"code\":\"DENIED\",\"message\":\"Failed to process request,
* due to 'golang1:test1' is a immutable tag.\",\"detail\":\"Failed to process request,
* due to 'golang1:test1' is a immutable tag.\"}]}\n"}
* @param errorString string
*/
const errorHandlerForDockerClient = function (errorString: string): string {
try {
const errorMsgBody = JSON.parse(errorString);
if (
errorMsgBody.errors &&
errorMsgBody.errors[0] &&
errorMsgBody.errors[0].message
) {
return errorMsgBody.errors[0].message;
}
} catch (err) {}
return errorString;
};
2017-05-11 08:59:12 +02:00
/**
* To handle the error message body
* Standard error return format {code : number, message: string} / {error: {code: number, message: string},...}
**
* returns {string}
2017-05-11 08:59:12 +02:00
*/
2017-05-11 08:59:12 +02:00
export const errorHandler = function (error: any): string {
if (!error) {
return 'UNKNOWN_ERROR';
2017-05-11 08:59:12 +02:00
}
// oci standard
if (error.errors && error.errors instanceof Array && error.errors.length) {
return error.errors.reduce((preError, currentError, index) => {
return preError
? `${preError},${currentError.message}`
: currentError.message;
}, '');
}
// Not a standard error return Basically not used cover unknown error
try {
const jsonError = JSON.parse(error.error);
if (jsonError.errors && jsonError.errors instanceof Array) {
return (
jsonError.errors?.map(error => error.message) ?? [
'UNKNOWN_ERROR',
]
).join(',');
} else {
return JSON.parse(error.error).message;
}
} catch (err) {}
// Not a standard error return Basically not used cover unknown error
if (typeof error.error === 'string') {
return error.error;
}
// oci standard
if (
error.error &&
error.error.errors &&
error.error.errors instanceof Array &&
error.error.errors.length
) {
return error.error.errors.reduce((preError, currentError, index) => {
return preError
? `${preError},${currentError.message}`
: currentError.message;
}, '');
}
if (error.error && error.error.message) {
if (typeof error.error.message === 'string') {
// handle docker client response error
return errorHandlerForDockerClient(error.error.message);
}
}
if (error.message) {
// handle docker client response error
if (typeof error.message === 'string') {
return errorHandlerForDockerClient(error.message);
}
}
// Not a standard error return Basically not used cover unknown error
2017-05-11 08:59:12 +02:00
if (!(error.statusCode || error.status)) {
2018-03-19 08:25:55 +01:00
// treat as string message
2017-05-11 08:59:12 +02:00
return '' + error;
} else {
switch (error.statusCode || error.status) {
case 400:
return 'BAD_REQUEST_ERROR';
2017-05-11 08:59:12 +02:00
case 401:
return 'UNAUTHORIZED_ERROR';
2017-05-11 08:59:12 +02:00
case 403:
return 'FORBIDDEN_ERROR';
2017-05-11 08:59:12 +02:00
case 404:
return 'NOT_FOUND_ERROR';
2017-05-11 08:59:12 +02:00
case 412:
return 'PRECONDITION_FAILED';
2017-05-11 08:59:12 +02:00
case 409:
return 'CONFLICT_ERROR';
2017-05-11 08:59:12 +02:00
case 500:
return 'SERVER_ERROR';
2017-05-11 08:59:12 +02:00
default:
return 'UNKNOWN_ERROR';
2017-05-11 08:59:12 +02:00
}
}
};
Add date/time format setting in portal (#16796) * Add date/time format setting in portal Currently, the format used for rendering dates and times is derived from the language/locale selected by the user. The formats used in the en-US locale ("English" in Harbor's GUI) are ambiguous and hard to understand for many users. For example, is 10/11/21 the 10th of November, 2021, the 11th of October, 2021, or even something else like the 21nd of November, 2010? Even if one does know how to interpret it in theory, such dates are essentially enciphered and must be mentally deciphered by the user every time, incurring unnecessary cognitive load. Similarly, many users are used to the 24-hour clock rather than the 12-hour clock (AM/PM), and so on. This PR adds a dropdown next to the existing language selector that lets the user choose between the default format for the current locale and the internationally standardized, unambiguous ISO 8601 format. For example, when viewing a list of resources, the ISO 8601 option makes points in time display as > 2021-10-11, 13:37 instead of > 10/11/21, 1:37 PM thereby improving the user experience considerably for users not familiar with the US date/time format (or, in general, the default format for the locale they have selected). The localized versions of the "Default" label are copied from `SCANNER.DEFAULT` in each locale. Signed-off-by: Simon Alling <alling.simon@gmail.com> * Fix indentation Signed-off-by: Simon Alling <alling.simon@gmail.com> * Remove redundant localStorage existence check Signed-off-by: Simon Alling <alling.simon@gmail.com> * Run 'npm run lint -- --fix'
2022-05-24 11:45:34 +02:00
/**
* Gets the datetime rendering setting saved by the user, or the default setting if no valid saved value is found.
*/
export function getDatetimeRendering(): DatetimeRendering {
const savedDatetimeRendering = localStorage.getItem(
DEFAULT_DATETIME_RENDERING_LOCALSTORAGE_KEY
);
if (savedDatetimeRendering && isDatetimeRendering(savedDatetimeRendering)) {
Add date/time format setting in portal (#16796) * Add date/time format setting in portal Currently, the format used for rendering dates and times is derived from the language/locale selected by the user. The formats used in the en-US locale ("English" in Harbor's GUI) are ambiguous and hard to understand for many users. For example, is 10/11/21 the 10th of November, 2021, the 11th of October, 2021, or even something else like the 21nd of November, 2010? Even if one does know how to interpret it in theory, such dates are essentially enciphered and must be mentally deciphered by the user every time, incurring unnecessary cognitive load. Similarly, many users are used to the 24-hour clock rather than the 12-hour clock (AM/PM), and so on. This PR adds a dropdown next to the existing language selector that lets the user choose between the default format for the current locale and the internationally standardized, unambiguous ISO 8601 format. For example, when viewing a list of resources, the ISO 8601 option makes points in time display as > 2021-10-11, 13:37 instead of > 10/11/21, 1:37 PM thereby improving the user experience considerably for users not familiar with the US date/time format (or, in general, the default format for the locale they have selected). The localized versions of the "Default" label are copied from `SCANNER.DEFAULT` in each locale. Signed-off-by: Simon Alling <alling.simon@gmail.com> * Fix indentation Signed-off-by: Simon Alling <alling.simon@gmail.com> * Remove redundant localStorage existence check Signed-off-by: Simon Alling <alling.simon@gmail.com> * Run 'npm run lint -- --fix'
2022-05-24 11:45:34 +02:00
return savedDatetimeRendering;
}
return DefaultDatetimeRendering;
Add date/time format setting in portal (#16796) * Add date/time format setting in portal Currently, the format used for rendering dates and times is derived from the language/locale selected by the user. The formats used in the en-US locale ("English" in Harbor's GUI) are ambiguous and hard to understand for many users. For example, is 10/11/21 the 10th of November, 2021, the 11th of October, 2021, or even something else like the 21nd of November, 2010? Even if one does know how to interpret it in theory, such dates are essentially enciphered and must be mentally deciphered by the user every time, incurring unnecessary cognitive load. Similarly, many users are used to the 24-hour clock rather than the 12-hour clock (AM/PM), and so on. This PR adds a dropdown next to the existing language selector that lets the user choose between the default format for the current locale and the internationally standardized, unambiguous ISO 8601 format. For example, when viewing a list of resources, the ISO 8601 option makes points in time display as > 2021-10-11, 13:37 instead of > 10/11/21, 1:37 PM thereby improving the user experience considerably for users not familiar with the US date/time format (or, in general, the default format for the locale they have selected). The localized versions of the "Default" label are copied from `SCANNER.DEFAULT` in each locale. Signed-off-by: Simon Alling <alling.simon@gmail.com> * Fix indentation Signed-off-by: Simon Alling <alling.simon@gmail.com> * Remove redundant localStorage existence check Signed-off-by: Simon Alling <alling.simon@gmail.com> * Run 'npm run lint -- --fix'
2022-05-24 11:45:34 +02:00
}
function isDatetimeRendering(x: unknown): x is DatetimeRendering {
return Object.keys(DATETIME_RENDERINGS).some(k => k === x);
}