407b4c9c9 Nuevo calendario: la primera hora del día ahora es configurable. Tooltips.
41907bf51 WIP: BigCalendar -> Fullcalendar
5fff1f800 global.js: eliminar importaciones no utilizadas.
4a4e2086a global.js: merge/combine no funcionaba correctamente en algunos casos (ej. plugin Merlin). AttachmentsService ahora devuelve un array vacío en lugar de null si no se proporcionan adjuntos (el cliente ahora puede limpiar la lista de adjuntos después de eliminar el último adjunto).
6bf735d24 global.js: combinado mucho más corto.
407b4c9c9
Nuevo calendario: la primera hora del día ahora es configurable. Tooltips.407b4c9c917150e84635867ae2e8918629ae9636
diff --git a/projectforge-webapp/src/utilities/global.js b/projectforge-webapp/src/utilities/global.js
index aad75bcfa..bfe602d12 100644
--- a/projectforge-webapp/src/utilities/global.js
+++ b/projectforge-webapp/src/utilities/global.js
@@ -57,6 +57,13 @@ String.idify = (string) => string.replace(/[.#*, >+~/[\]=|^$:()]/g, '-');
String.truncate = (str, length) => (str?.length > length ? str.substring(0, length) : str);
+Number.as2Digits = (number) => {
+ if (number < 10) {
+ return `0${number.toString()}`;
+ }
+ return number.toString();
+};
+
Object.getResponseHeaderFilename = (contentDisposition) => {
// attachment; filename*=UTF-8''document.pdf; filename=document.pdf
const matches = /filename[^;=\n]*=(UTF-8(['"]*))?([^;=\n]*)*/.exec(contentDisposition); 41907bf51
WIP: BigCalendar -> Fullcalendar41907bf51150c1ad7299e66b8bb3ed1bb8534c0e
diff --git a/projectforge-webapp/src/utilities/global.js b/projectforge-webapp/src/utilities/global.js
index ab0ed3509..aad75bcfa 100644
--- a/projectforge-webapp/src/utilities/global.js
+++ b/projectforge-webapp/src/utilities/global.js
@@ -62,3 +62,8 @@ Object.getResponseHeaderFilename = (contentDisposition) => {
const matches = /filename[^;=\n]*=(UTF-8(['"]*))?([^;=\n]*)*/.exec(contentDisposition);
return matches && matches.length >= 3 && matches[3] ? decodeURI(matches[3].replace(/['"]/g, '')) : 'download';
};
+
+Date.toIsoDateString = (date) => {
+ const offset = date.getTimezoneOffset();
+ return new Date(date.getTime() - (offset * 60 * 1000)).toISOString().split('T')[0];
+}; 5fff1f800
global.js: eliminar importaciones no utilizadas.5fff1f8001d869654577e33ec32513b63e70bca1
diff --git a/projectforge-webapp/src/utilities/global.js b/projectforge-webapp/src/utilities/global.js
index 7cbe32c7b..ab0ed3509 100644
--- a/projectforge-webapp/src/utilities/global.js
+++ b/projectforge-webapp/src/utilities/global.js
@@ -1,6 +1,4 @@
-import { forIn, get, merge, set } from 'lodash/object';
-import { mergeWith } from 'lodash';
-import { cloneDeep, isArray } from 'lodash/lang';
+import { forIn, get, set } from 'lodash/object';
// https://stackoverflow.com/a/6491621
Object.getByString = (object, multiKey) => { 4a4e2086a
global.js: merge/combine no funcionaba correctamente en algunos casos (ej. plugin Merlin). AttachmentsService ahora devuelve un array vacío en lugar de null si no se proporcionan adjuntos (el cliente ahora puede limpiar la lista de adjuntos después de eliminar el último adjunto).4a4e2086aced8e2fa6608da4b65e087028b6138a
diff --git a/projectforge-webapp/src/utilities/global.js b/projectforge-webapp/src/utilities/global.js
index 6ddc999f8..7cbe32c7b 100644
--- a/projectforge-webapp/src/utilities/global.js
+++ b/projectforge-webapp/src/utilities/global.js
@@ -1,4 +1,6 @@
-import { forIn, get, set } from 'lodash/object';
+import { forIn, get, merge, set } from 'lodash/object';
+import { mergeWith } from 'lodash';
+import { cloneDeep, isArray } from 'lodash/lang';
// https://stackoverflow.com/a/6491621
Object.getByString = (object, multiKey) => {
@@ -15,11 +17,31 @@ Object.getByString = (object, multiKey) => {
Object.isEmpty = (object) => Object.keys(object).length === 0;
+// No eliminar propiedades de datos no proporcionadas al fusionar:
+const mergeDataProps = (src, combined) => {
+ const srcData = src.data;
+ const combinedData = combined.data;
+ if (!combinedData) {
+ return srcData;
+ }
+ forIn(srcData, (value, key) => {
+ if (Object.prototype.hasOwnProperty.call(srcData, key)) {
+ // Si la propiedad existe, se usa: el valor podría ser undefined.
+ set(combinedData, key, value);
+ }
+ });
+ return combinedData;
+};
+
// Combina dos objetos. Rutas como user.rights[2].value también son compatibles en campos o2.
-Object.combine = (o1, o2) => {
- const combined = { ...o1 };
- forIn(o2, (value, key) => {
- set(combined, key, value);
+Object.combine = (src, obj) => {
+ const combined = { ...src };
+ forIn(obj, (value, key) => {
+ if (key === 'data') {
+ set(combined, key, mergeDataProps(obj, combined));
+ } else {
+ set(combined, key, value);
+ }
});
return combined;
}; 6bf735d24
global.js: combinado mucho más corto.6bf735d24dd5a4f5ff8d89c7dfe714aa8753cdaa
diff --git a/projectforge-webapp/src/utilities/global.js b/projectforge-webapp/src/utilities/global.js
index d1608283f..6ddc999f8 100644
--- a/projectforge-webapp/src/utilities/global.js
+++ b/projectforge-webapp/src/utilities/global.js
@@ -1,5 +1,4 @@
-import { forIn, get, mergeWith, set } from 'lodash/object';
-import { isArray } from 'lodash/lang';
+import { forIn, get, set } from 'lodash/object';
// https://stackoverflow.com/a/6491621
Object.getByString = (object, multiKey) => {
@@ -16,34 +15,13 @@ Object.getByString = (object, multiKey) => {
Object.isEmpty = (object) => Object.keys(object).length === 0;
-const customizer = (objValue, srcValue) => {
- if (isArray(objValue)) {
- // No fusionar arrays: reemplazar array existente por el array src.
- return srcValue;
- }
- return undefined;
-};
-
// Combina dos objetos. Rutas como user.rights[2].value también son compatibles en campos o2.
Object.combine = (o1, o2) => {
- const newValues = {};
- const specialProperties = {};
+ const combined = { ...o1 };
forIn(o2, (value, key) => {
- if (key.includes('.') || key.match(/\[(\d)\]/) || value === undefined) {
- // keys like user.name or user.rights[2].value or undefined values
- // need special treatment after merge.
- specialProperties[key] = value;
- } else {
- newValues[key] = value;
- }
- });
- const newState = mergeWith(o1, newValues, customizer);
- forIn(specialProperties, (value, key) => {
- // Establece el valor del nuevo estado mediante una ruta de propiedad profunda (como user.name o user.rights[2].value)
- // los valores undefined también se establecerán.
- set(newState, key, value);
+ set(combined, key, value);
});
- return newState;
+ return combined;
};
Array.findByField = (array, field, value) => array.reduce((accumulator, currentValue) => {