mirror of
https://github.com/opf/openproject.git
synced 2026-06-13 19:20:00 +00:00
[OP-19543] Replace lodash null/empty helpers
Null/empty/type predicates move from the global `_` to native checks: `isNil` -> `== null`, `isNaN` -> `Number.isNaN`, `defaultTo` -> `??`, `compact` -> `filter(Boolean)`. `isEmpty`, `castArray`, `isObject` and `reject` are replaced per call site with the equivalent native form for the concrete collection type. The global `_` stays until the remaining buckets land. `compact` sites whose result feeds a non-nullable type use a narrowing `(x): x is NonNullable<typeof x>` predicate, since `filter(Boolean)` does not narrow in TypeScript. https://community.openproject.org/wp/OP-19543
This commit is contained in:
@@ -186,7 +186,7 @@ export class ApiV3Service {
|
||||
* @param projectIdentifier
|
||||
*/
|
||||
public withOptionalProject(projectIdentifier:string|number|null|undefined):ApiV3ProjectPaths|this {
|
||||
if (_.isNil(projectIdentifier)) {
|
||||
if (projectIdentifier == null) {
|
||||
return this;
|
||||
}
|
||||
return this.projects.id(projectIdentifier);
|
||||
|
||||
@@ -100,7 +100,7 @@ export class ApiV3ResourceCollection<V, T extends ApiV3GettableResource<V>> exte
|
||||
}
|
||||
|
||||
public withOptionalId(id?:string|number|null):this|T {
|
||||
if (_.isNil(id)) {
|
||||
if (id == null) {
|
||||
return this;
|
||||
}
|
||||
return this.id(id);
|
||||
|
||||
@@ -26,7 +26,7 @@ export class SimpleResourceCollection<T = SimpleResource> {
|
||||
* @param id
|
||||
*/
|
||||
public withOptionalId(id?:string|number):this|T {
|
||||
if (_.isNil(id)) {
|
||||
if (id == null) {
|
||||
return this;
|
||||
}
|
||||
return this.id(id);
|
||||
|
||||
@@ -80,7 +80,7 @@ export class CurrentUserService {
|
||||
.principalFilter$()
|
||||
.pipe(
|
||||
map((userFilter) => {
|
||||
const filters:ApiV3ListFilter[] = _.compact([userFilter]);
|
||||
const filters:ApiV3ListFilter[] = [userFilter].filter((x):x is NonNullable<typeof x> => Boolean(x));
|
||||
|
||||
if (projectContext) {
|
||||
filters.push(['context', '=', [projectContext === 'global' || projectContext === 'projects' ? 'g' : `w${projectContext}`]]);
|
||||
@@ -101,7 +101,7 @@ export class CurrentUserService {
|
||||
* in the provided context.
|
||||
*/
|
||||
public hasCapabilities$(action:string|string[], projectContext:string|null):Observable<boolean> {
|
||||
const actions = _.castArray(action);
|
||||
const actions = Array.isArray(action) ? action : [action];
|
||||
return this
|
||||
.capabilities$(actions, projectContext)
|
||||
.pipe(
|
||||
@@ -118,7 +118,7 @@ export class CurrentUserService {
|
||||
* has any of the required capabilities in the provided context.
|
||||
*/
|
||||
public hasAnyCapabilityOf$(actions:string|string[], projectContext:string|null):Observable<boolean> {
|
||||
const actionsToFilter = _.castArray(actions);
|
||||
const actionsToFilter = Array.isArray(actions) ? actions : [actions];
|
||||
return this
|
||||
.capabilities$(actionsToFilter, projectContext)
|
||||
.pipe(
|
||||
|
||||
@@ -6,14 +6,14 @@ import { OpenprojectHalModuleHelpers } from 'core-app/features/hal/helpers/lazy-
|
||||
import { HalSource } from 'core-app/features/hal/interfaces';
|
||||
|
||||
export function cloneHalResourceCollection<T extends HalResource>(values:T[]|undefined):T[] {
|
||||
if (_.isNil(values)) {
|
||||
if (values == null) {
|
||||
return [];
|
||||
}
|
||||
return values.map((v) => v.$copy<T>());
|
||||
}
|
||||
|
||||
export function cloneHalResource<T extends HalResource>(value:T|undefined):T|undefined {
|
||||
if (_.isNil(value)) {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
return value.$copy<T>();
|
||||
@@ -38,7 +38,7 @@ export function initializeHalProperties<T extends HalResource>(halResourceServic
|
||||
}
|
||||
|
||||
function asHalResource(value?:HalSource, loaded = true):HalResource|HalSource|undefined|null {
|
||||
if (_.isNil(value)) {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ export function initializeHalProperties<T extends HalResource>(halResourceServic
|
||||
const sourceName = `_${name}`;
|
||||
const sourceObj:any = halResource.$source[sourceName];
|
||||
|
||||
if (_.isObject(sourceObj)) {
|
||||
if (typeof sourceObj === 'object' && sourceObj !== null) {
|
||||
Object.keys(sourceObj).forEach((propName) => {
|
||||
OpenprojectHalModuleHelpers.lazy((halResource)[instanceName],
|
||||
propName,
|
||||
@@ -147,7 +147,7 @@ export function initializeHalProperties<T extends HalResource>(halResourceServic
|
||||
return element.map((source) => asHalResource(source, true));
|
||||
}
|
||||
|
||||
if (_.isObject(element)) {
|
||||
if (typeof element === 'object' && element !== null) {
|
||||
_.each(element, (child:any, name:string) => {
|
||||
if (child && (child._embedded || child._links)) {
|
||||
OpenprojectHalModuleHelpers.lazy(element as any,
|
||||
|
||||
@@ -33,7 +33,7 @@ export namespace OpenprojectHalModuleHelpers {
|
||||
property:string,
|
||||
getter:() => any,
|
||||
setter?:(value:any) => void):void {
|
||||
if (_.isObject(obj)) {
|
||||
if (typeof obj === 'object' && obj !== null) {
|
||||
let done = false;
|
||||
let value:any;
|
||||
const config:any = {
|
||||
|
||||
@@ -216,9 +216,7 @@ export class HalResourceService {
|
||||
* @returns {HalResource}
|
||||
*/
|
||||
public createHalResource<T extends HalResource = HalResource>(source:any, loaded = true):T {
|
||||
if (_.isNil(source)) {
|
||||
source = HalResource.getEmptyResource();
|
||||
}
|
||||
source ??= HalResource.getEmptyResource();
|
||||
|
||||
const type = source._type || 'HalResource';
|
||||
return this.createHalResourceOfType<T>(type, source, loaded);
|
||||
|
||||
@@ -325,7 +325,7 @@ export class IanCenterService extends UntilDestroyedMixin {
|
||||
const promise = this
|
||||
.apiV3Service
|
||||
.work_packages
|
||||
.requireAll(_.compact(wpIds));
|
||||
.requireAll(wpIds.filter(Boolean));
|
||||
|
||||
wpIds.forEach((id) => {
|
||||
cache.clearAndLoad(
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ export class FilterToggledMultiselectValueComponent implements OnInit, AfterView
|
||||
}
|
||||
|
||||
public setValues(val:HalResource[]|string[]|string|HalResource):void {
|
||||
this.filter.values = _.castArray(val) as HalResource[]|string[];
|
||||
this.filter.values = (Array.isArray(val) ? val : [val]) as HalResource[]|string[];
|
||||
this.filterChanged.emit(this.filter);
|
||||
this.cdRef.detectChanges();
|
||||
}
|
||||
|
||||
+1
-1
@@ -140,7 +140,7 @@ export class WorkPackageFilterValues {
|
||||
*/
|
||||
private filterAlreadyApplied(change:WorkPackageChangeset|Record<string, unknown>, filter:{ id:string, values:unknown[] }):boolean {
|
||||
const value:unknown = change instanceof WorkPackageChangeset ? change.projectedResource[filter.id] : change[filter.id];
|
||||
const current = _.castArray(value);
|
||||
const current = Array.isArray(value) ? value : [value];
|
||||
|
||||
for (let i = 0; i < filter.values.length; i++) {
|
||||
for (let j = 0; j < current.length; j++) {
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ export class GroupedRowsBuilder extends RowsBuilder {
|
||||
* The hierarchy builder is only applicable if the hierarchy mode is active
|
||||
*/
|
||||
public isApplicable(table:WorkPackageTable) {
|
||||
return !_.isEmpty(this.groups);
|
||||
return this.groups.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -229,7 +229,7 @@ export class UrlParamsHelperService {
|
||||
if (query.timelineVisible) {
|
||||
paramsData.tv = query.timelineVisible;
|
||||
|
||||
if (!_.isEmpty(query.timelineLabels)) {
|
||||
if (Object.keys(query.timelineLabels ?? {}).length > 0) {
|
||||
paramsData.tll = JSON.stringify(query.timelineLabels);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ export class WpRelationInlineAddExistingComponent {
|
||||
};
|
||||
|
||||
public addExisting() {
|
||||
if (_.isNil(this.selectedWpId)) {
|
||||
if (this.selectedWpId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ export class WorkPackageRelationQueryComponent extends WorkPackageRelationQueryB
|
||||
// When relations have changed, refresh this table
|
||||
this.wpRelations.observe(this.workPackage.id!)
|
||||
.pipe(
|
||||
filter((val) => !_.isEmpty(val)),
|
||||
filter((val) => !(val == null || (Array.isArray(val) ? val.length === 0 : Object.keys(val).length === 0))),
|
||||
this.untilDestroyed(),
|
||||
)
|
||||
.subscribe(() => this.refreshTable());
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ export class WpTableConfigurationSortByTabComponent implements TabComponent, OnI
|
||||
}
|
||||
|
||||
sortElements = sortElements.map((object) => this.getMatchingSort(object.column.href!, object.direction));
|
||||
this.wpTableSortBy.update(_.compact(sortElements));
|
||||
this.wpTableSortBy.update(sortElements.filter((x):x is NonNullable<typeof x> => Boolean(x)));
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
+1
-1
@@ -32,6 +32,6 @@ export class OpTableActionsService {
|
||||
*/
|
||||
public render(workPackage:WorkPackageResource):HTMLElement[] {
|
||||
const built = this.actions.map((factory) => factory(this.injector, workPackage).buildElement());
|
||||
return _.compact(built);
|
||||
return built.filter((x):x is NonNullable<typeof x> => Boolean(x));
|
||||
}
|
||||
}
|
||||
|
||||
+8
-8
@@ -85,7 +85,7 @@ export class TimelineCellRenderer {
|
||||
public isEmpty(wp:WorkPackageResource) {
|
||||
const start = moment(wp.startDate);
|
||||
const due = moment(wp.dueDate);
|
||||
const noStartAndDueValues = _.isNaN(start.valueOf()) && _.isNaN(due.valueOf());
|
||||
const noStartAndDueValues = Number.isNaN(start.valueOf()) && Number.isNaN(due.valueOf());
|
||||
return noStartAndDueValues;
|
||||
}
|
||||
|
||||
@@ -246,21 +246,21 @@ export class TimelineCellRenderer {
|
||||
let start = moment(change.projectedResource.startDate);
|
||||
let due = moment(change.projectedResource.dueDate);
|
||||
|
||||
if (_.isNaN(start.valueOf()) && _.isNaN(due.valueOf())) {
|
||||
if (Number.isNaN(start.valueOf()) && Number.isNaN(due.valueOf())) {
|
||||
element.style.visibility = 'hidden';
|
||||
} else {
|
||||
element.style.visibility = 'visible';
|
||||
}
|
||||
|
||||
// only start date, fade out bar to the right
|
||||
if (_.isNaN(due.valueOf()) && !_.isNaN(start.valueOf())) {
|
||||
if (Number.isNaN(due.valueOf()) && !Number.isNaN(start.valueOf())) {
|
||||
// Set due date to today
|
||||
due = moment();
|
||||
bar.setAttribute('style', 'background-image: linear-gradient(90deg, rgba(255,255,255,0) 0%, #F1F1F1 100%) !important');
|
||||
}
|
||||
|
||||
// only finish date, fade out bar to the left
|
||||
if (_.isNaN(start.valueOf()) && !_.isNaN(due.valueOf())) {
|
||||
if (Number.isNaN(start.valueOf()) && !Number.isNaN(due.valueOf())) {
|
||||
start = due.clone();
|
||||
bar.setAttribute('style', 'background-image: linear-gradient(90deg, #F1F1F1 0%, rgba(255,255,255,0) 80%) !important');
|
||||
}
|
||||
@@ -336,7 +336,7 @@ export class TimelineCellRenderer {
|
||||
|
||||
let start = moment(projection.startDate);
|
||||
const due = moment(projection.dueDate);
|
||||
start = _.isNaN(start.valueOf()) ? due.clone() : start;
|
||||
start = Number.isNaN(start.valueOf()) ? due.clone() : start;
|
||||
|
||||
const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');
|
||||
|
||||
@@ -349,8 +349,8 @@ export class TimelineCellRenderer {
|
||||
let start = moment(projection.startDate);
|
||||
let due = moment(projection.dueDate);
|
||||
|
||||
start = _.isNaN(start.valueOf()) ? due.clone() : start;
|
||||
due = _.isNaN(due.valueOf()) ? start.clone() : due;
|
||||
start = Number.isNaN(start.valueOf()) ? due.clone() : start;
|
||||
due = Number.isNaN(due.valueOf()) ? start.clone() : due;
|
||||
|
||||
const offsetStart = start.diff(renderInfo.viewParams.dateDisplayStart, 'days');
|
||||
const duration = due.diff(start, 'days') + 1;
|
||||
@@ -461,7 +461,7 @@ export class TimelineCellRenderer {
|
||||
element.style.width = calculatePositionValueForDayCount(viewParams, duration);
|
||||
|
||||
// ensure minimum width
|
||||
if (!_.isNaN(start.valueOf()) || !_.isNaN(due.valueOf())) {
|
||||
if (!Number.isNaN(start.valueOf()) || !Number.isNaN(due.valueOf())) {
|
||||
const minWidth = _.max([renderInfo.viewParams.pixelPerDay, 2]);
|
||||
element.style.minWidth = `${minWidth}px`;
|
||||
}
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ export class TimelineMilestoneCellRenderer extends TimelineCellRenderer {
|
||||
|
||||
public isEmpty(wp:WorkPackageResource) {
|
||||
const date = moment(wp.date);
|
||||
return _.isNaN(date.valueOf());
|
||||
return Number.isNaN(date.valueOf());
|
||||
}
|
||||
|
||||
public canMoveDates(wp:WorkPackageResource) {
|
||||
@@ -120,7 +120,7 @@ export class TimelineMilestoneCellRenderer extends TimelineCellRenderer {
|
||||
const date = moment(renderInfo.change.projectedResource.date);
|
||||
|
||||
// abort if no date
|
||||
if (_.isNaN(date.valueOf())) {
|
||||
if (Number.isNaN(date.valueOf())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -92,10 +92,10 @@ export class WorkPackageTimelineCell {
|
||||
canConnectRelations():boolean {
|
||||
const wp = this.latestRenderInfo.workPackage;
|
||||
if (this.schemaCache.of(wp).isMilestone) {
|
||||
return !_.isNil(wp.date);
|
||||
return wp.date != null;
|
||||
}
|
||||
|
||||
return !_.isNil(wp.startDate) || !_.isNil(wp.dueDate);
|
||||
return wp.startDate != null || wp.dueDate != null;
|
||||
}
|
||||
|
||||
public clear() {
|
||||
|
||||
+2
-2
@@ -130,7 +130,7 @@ export class WorkPackageTableTimelineRelations extends UntilDestroyedMixin imple
|
||||
)
|
||||
.subscribe((list) => {
|
||||
// ... make sure that the corresponding relations are loaded ...
|
||||
const wps = _.compact(list.map((row) => row.workPackageId));
|
||||
const wps = list.map((row) => row.workPackageId).filter((x):x is NonNullable<typeof x> => Boolean(x));
|
||||
void this.wpRelations.requireAll(wps);
|
||||
});
|
||||
|
||||
@@ -161,7 +161,7 @@ export class WorkPackageTableTimelineRelations extends UntilDestroyedMixin imple
|
||||
private renderWorkPackagesRelations(workPackageIds:string[]) {
|
||||
workPackageIds.forEach((workPackageId) => {
|
||||
const workPackageWithRelation = this.workPackagesWithRelations[workPackageId];
|
||||
if (_.isNil(workPackageWithRelation)) {
|
||||
if (workPackageWithRelation == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,9 +164,9 @@ export function getTimeSlicesForHeader(vp:TimelineViewParameters,
|
||||
const firstRest:[Moment, Moment] = rest.splice(0, 1)[0];
|
||||
const lastRest:[Moment, Moment] = rest.pop()!;
|
||||
const inViewportAndBoundaries = _.concat(
|
||||
[firstRest].filter((e) => !_.isNil(e)),
|
||||
[firstRest].filter((e) => e != null),
|
||||
inViewport,
|
||||
[lastRest].filter((e) => !_.isNil(e)),
|
||||
[lastRest].filter((e) => e != null),
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+1
-1
@@ -175,7 +175,7 @@ export class WorkPackageViewColumnsService extends WorkPackageQueryStateService<
|
||||
|
||||
public setColumnsById(columnIds:string[]) {
|
||||
const mapped = columnIds.map((id) => _.find(this.all, (c) => c.id === id));
|
||||
this.setColumns(_.compact(mapped));
|
||||
this.setColumns(mapped.filter((x):x is NonNullable<typeof x> => Boolean(x)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -283,7 +283,7 @@ export class WorkPackageViewFiltersService extends WorkPackageQueryStateService<
|
||||
const invisibleFilters = new Set(this.hidden);
|
||||
invisibleFilters.delete('search');
|
||||
|
||||
return _.reject(this.current, (filter) => invisibleFilters.has(filter.id));
|
||||
return this.current.filter((filter) => !invisibleFilters.has(filter.id));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ export class WorkPackageViewHighlightingService extends WorkPackageQueryStateSer
|
||||
}
|
||||
|
||||
private filteredValue(value:WorkPackageViewHighlight):WorkPackageViewHighlight {
|
||||
if (_.isEmpty(value.selectedAttributes)) {
|
||||
if (!value.selectedAttributes?.length) {
|
||||
value.selectedAttributes = undefined;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -166,7 +166,7 @@ export class WorkPackageViewOrderService extends WorkPackageQueryStateService<Qu
|
||||
const { value } = this.positions;
|
||||
|
||||
// Remove empty or stale values given we can reload them
|
||||
if ((_.isEmpty(value) || this.positions.isValueOlderThan(60000))) {
|
||||
if (((value == null || Object.keys(value).length === 0) || this.positions.isValueOlderThan(60000))) {
|
||||
this.positions.clear('Clearing old positions value');
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -75,7 +75,7 @@ workPackage:WorkPackageResource,
|
||||
}
|
||||
|
||||
// Only if any relations exist for this work package
|
||||
if (_.isNil(relations)) {
|
||||
if (relations == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ this.relationsForColumn(workPackage, relations, column),
|
||||
* @return The filtered relations
|
||||
*/
|
||||
public relationsForColumn(workPackage:WorkPackageResource, relations:RelationsStateValue|undefined, column:QueryColumn) {
|
||||
if (_.isNil(relations)) {
|
||||
if (relations == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@ export class WorkPackageViewTimelineService extends WorkPackageQueryStateService
|
||||
...this.defaultState,
|
||||
visible: query.timelineVisible,
|
||||
zoomLevel: query.timelineZoomLevel,
|
||||
labels: query.timelineLabels,
|
||||
labels: query.timelineLabels ?? this.defaultLabels,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ export class WorkPackageViewTimelineService extends WorkPackageQueryStateService
|
||||
}
|
||||
|
||||
public get labels() {
|
||||
if (_.isEmpty(this.current.labels)) {
|
||||
if (Object.keys(this.current.labels).length === 0) {
|
||||
return this.defaultLabels;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -354,7 +354,7 @@ export class OpAutocompleterComponent<T extends IAutocompleteItem = IAutocomplet
|
||||
if (!this.model) {
|
||||
return '';
|
||||
} else if (Array.isArray(this.model)) {
|
||||
const mappedValues = this.model.map((el) => (_.isObject(el) ? el[this.inputBindValue as 'id'] : el) as string);
|
||||
const mappedValues = this.model.map((el) => ((typeof el === 'object' && el !== null) ? el[this.inputBindValue as 'id'] : el) as string);
|
||||
return mappedValues.length > 0 ? mappedValues : [''];
|
||||
} else {
|
||||
return this.model[this.inputBindValue as 'id'] as string || '';
|
||||
@@ -562,7 +562,7 @@ export class OpAutocompleterComponent<T extends IAutocompleteItem = IAutocomplet
|
||||
|
||||
protected defaultCompareWithFunction():null|((a:unknown, b:unknown) => boolean) {
|
||||
return (a, b) => {
|
||||
if (this.bindValue && !_.isObject(b)) {
|
||||
if (this.bindValue && !(typeof b === 'object' && b !== null)) {
|
||||
return (a as Record<string, unknown>)[this.bindValue] === b;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ export function comparableDate(date?:DateOption):number|null {
|
||||
export function setDates(dates:DateOption|DateOption[], datePicker:DatePicker, enforceDate?:Date):void {
|
||||
const { currentMonth, currentYear, selectedDates } = datePicker.datepickerInstance;
|
||||
|
||||
const [newStart, newEnd] = _.castArray(dates);
|
||||
const [newStart, newEnd] = Array.isArray(dates) ? dates : [dates];
|
||||
const [selectedStart, selectedEnd] = selectedDates;
|
||||
|
||||
// In case the new times match the current times, do not try to update
|
||||
|
||||
+2
-2
@@ -206,7 +206,7 @@ export class OpWpDatePickerInstanceComponent extends UntilDestroyedMixin impleme
|
||||
}
|
||||
|
||||
private currentDates():string[] {
|
||||
const compactedDates = _.compact([this.startDateValue, this.dueDateValue]);
|
||||
const compactedDates = [this.startDateValue, this.dueDateValue].filter((x):x is NonNullable<typeof x> => Boolean(x));
|
||||
return this.timezoneService.utcDatesToISODateStrings(compactedDates);
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ export class OpWpDatePickerInstanceComponent extends UntilDestroyedMixin impleme
|
||||
minDate: this.minDate,
|
||||
} as flatpickr.Options.Options;
|
||||
|
||||
return _.omitBy(options, (v) => _.isNil(v));
|
||||
return _.omitBy(options, (v) => v == null);
|
||||
}
|
||||
|
||||
private onFlatpickrChange(dates:Date[], _datestr:string, _instance:flatpickr.Instance) {
|
||||
|
||||
@@ -459,7 +459,7 @@ export class ResourceChangeset<T extends HalResource = HalResource> {
|
||||
protected getLinkedValue(val:any, fieldSchema:IFieldSchema) {
|
||||
// Links should always be nullified as { href: null }, but
|
||||
// this wasn't always the case, so ensure null values are returned as such.
|
||||
if (_.isNil(val)) {
|
||||
if (val == null) {
|
||||
return { href: null };
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ import { cssClassCustomOption, DisplayField } from 'core-app/shared/components/f
|
||||
|
||||
export class ResourcesDisplayField extends DisplayField {
|
||||
public isEmpty():boolean {
|
||||
return _.isEmpty(this.value);
|
||||
return this.value == null || (Array.isArray(this.value) ? this.value.length === 0 : Object.keys(this.value as Record<string, unknown>).length === 0);
|
||||
}
|
||||
|
||||
public get stringValue():string[] {
|
||||
|
||||
@@ -101,7 +101,7 @@ export abstract class EditForm<T extends HalResource = HalResource> {
|
||||
* Return whether this form has any active fields
|
||||
*/
|
||||
public hasActiveFields():boolean {
|
||||
return !_.isEmpty(this.activeFields);
|
||||
return Object.keys(this.activeFields).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-2
@@ -110,7 +110,7 @@ export class MultiSelectEditFieldComponent extends EditFieldComponent implements
|
||||
*/
|
||||
public buildSelectedOption() {
|
||||
const value:HalResource[] = this.resource[this.name];
|
||||
return value ? _.castArray(value).map((val) => this.findValueOption(val)) : [];
|
||||
return value ? (Array.isArray(value) ? value : [value]).map((val) => this.findValueOption(val)) : [];
|
||||
}
|
||||
|
||||
public get selectedOption() {
|
||||
@@ -135,7 +135,7 @@ export class MultiSelectEditFieldComponent extends EditFieldComponent implements
|
||||
return option;
|
||||
};
|
||||
|
||||
this.resource[this.name] = _.castArray(val).map((el) => mapper(el));
|
||||
(this.resource as Record<string, ValueOption[]>)[this.name] = (Array.isArray(val) ? val : [val]).map((el) => mapper(el) as ValueOption);
|
||||
}
|
||||
|
||||
public onOpen() {
|
||||
|
||||
@@ -100,14 +100,14 @@ export class ConfirmDialogModalComponent extends OpModalComponent {
|
||||
|
||||
this.options = (this.locals.options ?? {}) as ConfirmDialogOptions;
|
||||
|
||||
this.dangerHighlighting = _.defaultTo(this.options.dangerHighlighting, false);
|
||||
this.showListData = _.defaultTo(this.options.showListData, false);
|
||||
this.refreshOnCancel = _.defaultTo(this.options.refreshOnCancel, false);
|
||||
this.listTitle = _.defaultTo(this.options.listTitle, '');
|
||||
this.warningText = _.defaultTo(this.options.warningText, '');
|
||||
this.passedData = _.defaultTo(this.options.passedData, []);
|
||||
this.showClose = _.defaultTo(this.options.showClose, true);
|
||||
this.divideContent = _.defaultTo(this.options.divideContent, false);
|
||||
this.dangerHighlighting = (this.options.dangerHighlighting ?? false);
|
||||
this.showListData = (this.options.showListData ?? false);
|
||||
this.refreshOnCancel = (this.options.refreshOnCancel ?? false);
|
||||
this.listTitle = (this.options.listTitle ?? '');
|
||||
this.warningText = (this.options.warningText ?? '');
|
||||
this.passedData = (this.options.passedData ?? []);
|
||||
this.showClose = (this.options.showClose ?? true);
|
||||
this.divideContent = (this.options.divideContent ?? false);
|
||||
// override default texts and icons if any
|
||||
this.text = _.defaults(this.options.text, this.text);
|
||||
this.icon = _.defaults(this.options.icon, this.icon);
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ export default class ProjectLifeCycleFormController extends FormPreviewControlle
|
||||
}
|
||||
|
||||
private updateFlatpickrCalendar() {
|
||||
const dates:Date[] = _.compact(this.dateInputFields.map((field) => this.toDate(field.value)));
|
||||
const dates:Date[] = this.dateInputFields.map((field) => this.toDate(field.value)).filter((x):x is NonNullable<typeof x> => Boolean(x));
|
||||
const ignoreNonWorkingDays = false;
|
||||
const mode = 'range';
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
*/
|
||||
|
||||
import { Controller } from '@hotwired/stimulus';
|
||||
import { compact } from 'lodash';
|
||||
|
||||
export default class SortByConfigController extends Controller {
|
||||
static targets = [
|
||||
@@ -74,7 +73,7 @@ export default class SortByConfigController extends Controller {
|
||||
return null;
|
||||
});
|
||||
|
||||
return JSON.stringify(compact(filters));
|
||||
return JSON.stringify(filters.filter(Boolean));
|
||||
}
|
||||
|
||||
// Tries to find the parent form in the DOM. If present and the form contains a `page` field marked
|
||||
@@ -270,12 +269,12 @@ export default class SortByConfigController extends Controller {
|
||||
}
|
||||
|
||||
getAllSelectedFields(...excludedRows:HTMLElement[]):string[] {
|
||||
return compact(this.inputRowTargets.map((row) => {
|
||||
return this.inputRowTargets.map((row) => {
|
||||
if (!excludedRows.includes(row)) {
|
||||
return this.getSelectedField(row);
|
||||
}
|
||||
return null;
|
||||
}));
|
||||
}).filter((x):x is NonNullable<typeof x> => Boolean(x));
|
||||
}
|
||||
|
||||
moveRowToBottom(row:HTMLElement):void {
|
||||
|
||||
+2
-2
@@ -250,7 +250,7 @@ export default class PreviewController extends DialogPreviewController {
|
||||
}
|
||||
|
||||
private updateFlatpickrCalendar() {
|
||||
const dates:Date[] = _.compact([this.currentStartDate, this.currentDueDate]);
|
||||
const dates:Date[] = [this.currentStartDate, this.currentDueDate].filter((x):x is NonNullable<typeof x> => Boolean(x));
|
||||
const ignoreNonWorkingDays = this.currentIgnoreNonWorkingDays;
|
||||
const mode = this.mode();
|
||||
|
||||
@@ -271,7 +271,7 @@ export default class PreviewController extends DialogPreviewController {
|
||||
return this.toDate(flatPickrDates[0]);
|
||||
}
|
||||
|
||||
const fieldDates = _.compact([this.currentStartDate, this.currentDueDate])
|
||||
const fieldDates = [this.currentStartDate, this.currentDueDate].filter((x):x is NonNullable<typeof x> => Boolean(x))
|
||||
.map((date) => this.timezoneService.utcDateToISODateString(date));
|
||||
const diff = _.difference(flatPickrDates, fieldDates);
|
||||
return this.toDate(diff[0]);
|
||||
|
||||
Reference in New Issue
Block a user