Skip to content

Commit

Permalink
v1.193.0-rc1
Browse files Browse the repository at this point in the history
  • Loading branch information
varovaro committed Dec 2, 2024
2 parents c2546c4 + 433e2d2 commit 0cd79ad
Show file tree
Hide file tree
Showing 67 changed files with 2,128 additions and 1,729 deletions.
20 changes: 20 additions & 0 deletions .github/ISSUE_TEMPLATE/dependency-update.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
name: "Dependency update"
about: 'Update a dependency to a newer version that requires code changes'
title: 'Update from to'
labels: ['dependencies', 'Tech Debt :hammer_and_wrench:']
assignees: ''
---

**Dependency update**

`dependency-name` from `current-version` to `newer-version`

**Additional context**

Steps broken in the pipeline or any identified issues.

**Update checklist:**
- [ ] Dependency removed in all ignore lists of `.github/dependabot.yml`.
- [ ] Check any reference to the dependency in the resolutions section of `package.json`.
- [ ] The dependency is no longer needed.
55 changes: 28 additions & 27 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ updates:
interval: daily
ignore:
- dependency-name: "@types/*"
- dependency-name: "@sentry/node"
- dependency-name: "@sentry/node" #6880
versions: [">= 7.114.0"]
- dependency-name: flowbite #Flowbite & flowbite-datepicker upgrade #6993
versions: [">= 2.3.1"]
Expand All @@ -16,37 +16,28 @@ updates:
versions: [">= 0.10.1"]
- dependency-name: Mongoose #Mongoose upgrade #7017
versions: [">= 8.4.3"]
- dependency-name: cookie
- dependency-name: "@socket.io*"
- dependency-name: bootstrap
- dependency-name: express-prom-bundle
- dependency-name: immutable
- dependency-name: otplib
- dependency-name: redux
- dependency-name: redux-thunk
- dependency-name: "@typescript-eslint/eslint-plugin"
- dependency-name: "@typescript-eslint/parser"
- dependency-name: eslint #6784
- dependency-name: fetch-mock
- dependency-name: react-router-dom
- dependency-name: react-datepicker
- dependency-name: recharts
- dependency-name: "@headlessui/react"
- dependency-name: react-player
open-pull-requests-limit: 5
labels:
- dependencies
rebase-strategy: disabled
groups:
dev-minor-dependencies:
applies-to: version-updates
update-types: [minor, patch]
patterns:
- "*"
exclude-patterns:
- "@babel*"
- "@storybook*"
- "@sentry*"
- "@dnd-kit"
- socket.io
- recharts
- eslint
- flowbite*
- Mongoose
- react-datepicker
- "@headlessui/react"
- react-player
- express*
dev-major-dependencies:
applies-to: version-updates
update-types: [major]
patterns:
- "*"
exclude-patterns:
- cookie
babel:
applies-to: version-updates
patterns:
Expand Down Expand Up @@ -75,3 +66,13 @@ updates:
applies-to: version-updates
patterns:
- express*
dev-minor-dependencies:
applies-to: version-updates
update-types: [minor, patch]
patterns:
- "*"
dev-major-dependencies:
applies-to: version-updates
update-types: [major]
patterns:
- "*"
71 changes: 32 additions & 39 deletions app/api/settings/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,10 @@ import { settingsModel } from './settingsModel';

const DEFAULT_MAP_STARTING_POINT: LatLonSchema[] = [{ lon: 6, lat: 46 }];

type FilterOrLink = SettingsFilterSchema | SettingsLinkSchema;
type FilterOrLink = SettingsFilterSchema | SettingsLinkSchema | SettingsSublinkSchema;

const isLink = (item: any): item is SettingsLinkSchema => item.type && item.title;

type SubLinkKeyType = keyof SettingsSublinkSchema;

const subLinkProperties: SubLinkKeyType[] = ['title' as 'title', 'url' as 'url'];

const isSubLinkKey = (key: string | number | symbol): key is SubLinkKeyType =>
subLinkProperties.includes(key as any);

const getUpdatesAndDeletes = <T extends FilterOrLink>(
matchProperty: keyof T,
propertyName: keyof T,
Expand All @@ -36,45 +29,45 @@ const getUpdatesAndDeletes = <T extends FilterOrLink>(
) => {
const updatedValues: { [k: string]: any } = {};
const deletedValues: string[] = [];
const values: { [k: string]: string } = {};

currentValues.forEach(value => {
const matchValue = newValues.find(
v => v[matchProperty] && v[matchProperty]?.toString() === value[matchProperty]?.toString()
);
//flatten values
const flattenedCurrentValues = currentValues.reduce((result, value) => {
if (isLink(value) && value.sublinks) {
return [...result, ...(value.sublinks as T[]), value];
}
return [...result, value];
}, [] as T[]);

if (value[propertyName] && matchValue && matchValue[propertyName] !== value[propertyName]) {
if (isLink(value) && value.sublinks && isSubLinkKey(propertyName)) {
value.sublinks.forEach(sublink => {
updatedValues[ensure<string>(sublink[propertyName])] = sublink[propertyName];
});
}
updatedValues[ensure<string>(value[propertyName])] = matchValue[propertyName];
const flattenedNewValues = newValues.reduce<T[]>((result, value) => {
if (isLink(value) && value.sublinks) {
return [...result, ...(value.sublinks as T[]), value];
}
return [...result, value];
}, [] as T[]);

flattenedCurrentValues.forEach(value => {
const matchValue = flattenedNewValues.find(
(v): v is T =>
v[matchProperty] && v[matchProperty]?.toString() === value[matchProperty]?.toString()
);

if (!matchValue) {
if (isLink(value) && value.sublinks && isSubLinkKey(propertyName)) {
value.sublinks.forEach(sublink => {
if (sublink[propertyName]) {
deletedValues.push(ensure<string>(sublink[propertyName] as string));
}
});
}
deletedValues.push(ensure<string>(value[propertyName]));
return;
}
});

const values = newValues.reduce<{ [k: string]: string }>((result, value) => {
const sublinkResults: { [key: string]: string | unknown } = {};
if (isLink(value) && value.sublinks && isSubLinkKey(propertyName)) {
value.sublinks.forEach(sublink => {
sublinkResults[ensure<string>(sublink[propertyName])] = sublink[propertyName];
});
const nameHasChanged = value[propertyName] !== matchValue[propertyName];
if (nameHasChanged) {
updatedValues[ensure<string>(value[propertyName])] = matchValue[propertyName];
}
return {
...result,
[ensure<string>(value[propertyName])]: value[propertyName],
...sublinkResults,
} as { [k: string]: string };
}, {});
});

//latest values
flattenedNewValues.forEach(value => {
values[ensure<string>(value[propertyName])] = ensure<string>(value[propertyName]);
});

return { updatedValues, deletedValues, values };
};

Expand Down
50 changes: 50 additions & 0 deletions app/api/settings/specs/settings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,56 @@ describe('settings', () => {
{ 'Page 1': 'Page 1', 'Page three': 'Page three' }
);
});

it('should update the translation for links moving to groups', async () => {
const config = {
...baseConfig,
links: [
...baseConfig.links,
{ title: 'Page two', type: 'link' as 'link', url: 'url2' },
{
title: 'Group one',
type: 'group' as 'group',
sublinks: [],
},
],
};
const savedConfig = await settings.save(config);
const finalConfig = {
...baseConfig,
links: [
{
title: 'Page one',
type: 'link' as 'link',
url: 'url',
_id: savedConfig.links?.[0]._id,
},
{
title: 'Group one',
type: 'group' as 'group',
sublinks: [
{
title: 'Page 2',
type: 'link' as 'link',
url: 'url2',
_id: savedConfig.links?.[1]._id,
},
],
_id: savedConfig.links?.[2]._id,
},
],
};

jest.clearAllMocks();
await settings.save(finalConfig);

expect(translations.updateContext).toHaveBeenCalledWith(
{ id: 'Menu', label: 'Menu', type: 'Uwazi UI' },
{ 'Page two': 'Page 2' },
[],
{ 'Page one': 'Page one', 'Group one': 'Group one', 'Page 2': 'Page 2' }
);
});
});
});

Expand Down
12 changes: 9 additions & 3 deletions app/react/Documents/components/SnippetList.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,19 @@ const DocumentContentSnippets = ({
</li>
{documentSnippets.map((snippet, index) => {
const selected = snippet.get('text') === selectedSnippet.get('text') ? 'selected' : '';
const filename = snippet.get('filename');
console.log('filename', filename);
const page = snippet.get('page');
console.log(
`${documentViewUrl}?page=${page}&searchTerm=${searchTerm || ''}${filename ? `&file=${filename}` : ''}`
);
return (
<li key={index} className={`snippet-list-item fulltext-snippet ${selected}`}>
<I18NLink
onClick={() => selectSnippet(snippet.get('page'), snippet)}
to={`${documentViewUrl}?page=${snippet.get('page')}&searchTerm=${searchTerm || ''}`}
onClick={() => selectSnippet(page, snippet)}
to={`${documentViewUrl}?page=${page}&searchTerm=${searchTerm || ''}${filename ? `&file=${filename}` : ''}`}
>
<span className="page-number">{snippet.get('page')}</span>
<span className="page-number">{page}</span>
<span className="snippet-text">
<SafeHTML>{snippet.get('text')}</SafeHTML>
</span>
Expand Down
4 changes: 0 additions & 4 deletions app/react/Layout/ItemSnippet.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,6 @@ ItemSnippet.propTypes = {
}).isRequired,
};

ItemSnippet.defaultProps = {
onSnippetClick: undefined,
};

export const mapStateToProps = (state, ownProps) => ({
template: state.templates.find(tmpl => tmpl.get('_id') === ownProps.doc.template),
});
Expand Down
25 changes: 14 additions & 11 deletions app/react/Layout/TableRows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,20 @@ const TableRowsComponent = ({
const [multipleSelection, setMultipleSelection] = useState(selectionLength > 1);
return (
<>
{documents.get('rows').map((entity: any) => (
<TableRow
entity={entity}
columns={columns}
clickOnDocument={clickOnDocument}
storeKey={storeKey}
key={entity.get('_id')}
setMultipleSelection={setMultipleSelection}
multipleSelection={multipleSelection}
/>
))}
{documents
.get('rows')
.map((entity: any) => (
<TableRow
entity={entity}
columns={columns}
clickOnDocument={clickOnDocument}
storeKey={storeKey}
key={entity.get('_id')}
setMultipleSelection={setMultipleSelection}
multipleSelection={multipleSelection}
/>
))
.toArray()}
</>
);
};
Expand Down
42 changes: 29 additions & 13 deletions app/react/Library/actions/libraryActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -329,27 +329,43 @@ function multipleUpdate(entities, values) {
function saveEntity(entity, formModel) {
// eslint-disable-next-line max-statements
return async dispatch => {
const { entity: updatedDoc, errors } = await saveEntityWithFiles(entity, dispatch);
let updatedDoc;
let errors = [];
let message = '';

dispatch(formActions.reset(formModel));
await dispatch(unselectAllDocuments());
if (entity._id) {
message = 'Entity updated';
dispatch(updateEntity(updatedDoc));
dispatch(actions.updateIn('library.markers', ['rows'], updatedDoc));
} else {
message = 'Entity created';
dispatch(elementCreated(updatedDoc));
let submitFailed = false;
try {
({ entity: updatedDoc, errors } = await saveEntityWithFiles(entity, dispatch));

dispatch(formActions.reset(formModel));
await dispatch(unselectAllDocuments());
if (entity._id) {
message = 'Entity updated';
dispatch(updateEntity(updatedDoc));
dispatch(actions.updateIn('library.markers', ['rows'], updatedDoc));
} else {
message = 'Entity created';
dispatch(elementCreated(updatedDoc));
}
} catch (ex) {
submitFailed = true;
message = t('System', 'Unable to save, failed response', null, false);
errors.push(ex.message);
}

if (errors.length) {
message = `${message} with the following errors: ${JSON.stringify(errors, null, 2)}`;
}
if (submitFailed) {
dispatch(formActions.setSubmitFailed(formModel));
}
const notificationMessage = t('System', message, null, false);
const notificationType = errors.length ? 'warning' : 'success';
await dispatch(
notificationActions.notify(notificationMessage, errors.length ? 'warning' : 'success')
notificationActions.notify(notificationMessage, !submitFailed ? notificationType : 'danger')
);
await dispatch(selectSingleDocument(updatedDoc));
if (!errors.length) {
await dispatch(selectSingleDocument(updatedDoc));
}
};
}

Expand Down
12 changes: 11 additions & 1 deletion app/react/Library/actions/saveEntityWithFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,17 @@ const saveEntityWithFiles = async (entity: ClientEntitySchema, dispatch?: Dispat
});

request.end((err, res) => {
if (err) return reject(err);
if (!res.ok && (res.body.prettyMessage !== undefined || res.body.error !== undefined)) {
if (err) {
reject(
new Error(
`${res.body.prettyMessage || res.body.error}. Request Id: ${res.body.requestId}`
)
);
}
} else if (err) {
reject(err);
}

if (dispatch && addedDocuments.length) {
dispatch({
Expand Down
Loading

0 comments on commit 0cd79ad

Please sign in to comment.