Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release/v1.7.0 #689

Merged
merged 36 commits into from Mar 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
494252c
[SIG-2286] Main menu z-index fix
janjaap Mar 5, 2020
f0b916f
(Chore) Remove connect from departments overview
janjaap Mar 5, 2020
4e3cd73
Merge pull request #663 from Amsterdam/SIG-2286_main-menu-zindex-fix
janjaap Mar 5, 2020
f6f9426
Merge branch 'develop' into chore-remove-connect-from-departments-ove…
janjaap Mar 6, 2020
b6690fd
Merge pull request #665 from Amsterdam/chore-remove-connect-from-depa…
janjaap Mar 9, 2020
60cc90d
(Chore) Remove connect from users overview
jpoppe Mar 9, 2020
c993edd
removed userCan left overs
jpoppe Mar 9, 2020
042acff
added object-curly-spacing rule to the ESLint configuration
jpoppe Mar 9, 2020
fea8543
applied review feedback changes
jpoppe Mar 10, 2020
33b56e8
fixed test import
jpoppe Mar 10, 2020
22e84a8
Merge pull request #667 from Amsterdam/chore-remove-connect-from-cont…
jpoppe Mar 10, 2020
51169a9
[SIG-2358] User overview page infinite loop on navigation
janjaap Mar 11, 2020
f2cb25e
Merge remote-tracking branch 'origin/develop' into SIG-2286_main-menu…
janjaap Mar 11, 2020
7cd7c8a
Adds ADR
janjaap Mar 11, 2020
77d9c74
Adds date
janjaap Mar 11, 2020
4422c99
Changed ADR status
janjaap Mar 11, 2020
fe1ca4f
Merge pull request #671 from Amsterdam/SIG-2286_main-menu-notificatio…
janjaap Mar 11, 2020
58b394f
(Chore) Remove isAuthenticated props
janjaap Mar 11, 2020
ea1bf41
[SIG-2333] v0 => v1 replace
janjaap Mar 11, 2020
868815e
Merge pull request #672 from Amsterdam/chore-remove-isauthenticated-p…
janjaap Mar 12, 2020
013e467
Adds tests for IncidentContainer saga
janjaap Mar 12, 2020
827a799
Merge remote-tracking branch 'origin/develop' into SIG-2333_v0-v1-rep…
janjaap Mar 12, 2020
b06f3e6
Merge pull request #673 from Amsterdam/SIG-2333_v0-v1-replace
janjaap Mar 12, 2020
8710f2b
[SIG-2280] Incident types definition
janjaap Mar 12, 2020
6ce1bc1
Merge pull request #674 from Amsterdam/SIG-2280_types-definition
janjaap Mar 13, 2020
d3b70bd
[SIG-2281] Form configuration for incident type
janjaap Mar 13, 2020
a5d4363
Merge remote-tracking branch 'origin/develop' into SIG-2281_form-conf…
janjaap Mar 13, 2020
4097a0c
[SIG-2307] Incident type patch
janjaap Mar 13, 2020
c12d8f6
Adds tests
janjaap Mar 13, 2020
d9adc60
Merge pull request #675 from Amsterdam/SIG-2281_form-config-incident-…
janjaap Mar 13, 2020
d592b80
Merge remote-tracking branch 'origin/develop' into SIG-2307_incident-…
janjaap Mar 13, 2020
94bd940
Merge pull request #676 from Amsterdam/SIG-2307_incident-type-patch
janjaap Mar 13, 2020
59e347f
[SIG-1025] header tekst verkeerd gestyled
jpoppe Mar 16, 2020
ce5f1ff
found one more font-weight target
jpoppe Mar 16, 2020
158975f
Merge pull request #680 from Amsterdam/SIG-1025_header_tekst_verkeerd…
jpoppe Mar 18, 2020
e53740f
Merge branch 'master' into release/v1.7.0
janjaap Mar 18, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc.js
Expand Up @@ -69,6 +69,7 @@ module.exports = {
'no-console': 1,
'no-unused-vars': 2,
'no-use-before-define': 0,
'object-curly-spacing': [1, 'always'],
'prefer-template': 2,
'react/destructuring-assignment': 0,
'react-hooks/exhaustive-deps': 'warn',
Expand Down
2 changes: 1 addition & 1 deletion .prettierrc
Expand Up @@ -5,5 +5,5 @@
"singleQuote": true,
"parser": "babel",
"htmlWhitespaceSensitivity": "strict",
"printWidth": 80
"printWidth": 120
}
13 changes: 7 additions & 6 deletions docs/adr/0001-fetching-incidents.md
@@ -1,7 +1,8 @@
# Architectural decision records
# Fetching incidents

## Fetching incidents
date: 2020-01-15

## Context
In the Signals frontend application, two different endpoints provide data that can be used to render an overview of incidents.

The first one is the [private signals endpoint](https://api.data.amsterdam.nl/api/swagger/?url=/signals/swagger/openapi.yaml#/default/get_signals_v1_private_signals_), the second is the private search endpoint. Both return the same data structure, but expect/require different parameters.
Expand All @@ -27,29 +28,29 @@ In a number of occasions, a request is made to one of the private endpoints to r
Every time the input for the `SearchBar` is submitted, the `SearchBar` container dispatches an action that trigger another fetch. The `submit` event triggers a redirect to the `IncidentManagement` module. See 1. for details.

Component: `signals/containers/SearchBar`

Action: `setSearchQuery`

4. **When a pagination item is clicked**

If the incidents overview page renders a `Pagination` component, every click on a pagination item results in an action being dispatched. This action, in turn, triggers a fetch of results from either the `search` endpoint or the `signals` endpoint, depending on the presence of a search query.

Component: `signals/IncidentManagement/containers/IncidentOverviewPage`

Action: `pageChanged`

5. **When a column's order is changed**

The incidents overview page shows a table with sortable columns. Clicking on a column header will dispatch an action. This action, similar to `pageChanged` will trigger a fetch of results from either the `search` endpoint or the `signals` endpoint.

Component: `signals/IncidentManagement/containers/IncidentOverviewPage`

Action: `orderingChanged`

6. **When an incident has been successfully patched**

Individual incidents can be patched in the `IncidentDetail` container. Navigating back from the detail page to the overview page should show the changes that have been applied to the incident. Therefore, after the `patchIncidentSuccess` action has been dispatched, a new set of (updated) incidents is retrieved.

Component: `signals/IncidentManagement/containers/IncidentDetail`

Action: `patchIncident`
21 changes: 21 additions & 0 deletions docs/adr/0002-using-local-state-in-settings-module.md
@@ -0,0 +1,21 @@
# Using local state in settings module

Date: 2020-03-11

## Status

Accepted

## Context

Some of the data that is required by the application is only needed in specific modules. Till now, `redux` has been relied on heavily and most of times for good reason. Some data, however, is only needed in specific parts of the application, but is still stored in the global store or is kept in a reducer on a per-component basis.

Different parts of the application have their own saga, reducer, actions and selectors which makes the application more difficult to understand, error prone and maintenance harder to keep up.

Storing all data in the global store requires a lot of (duplicate) boilerplate code, tests and mocking.

## Decision

The structure of the application's state needs to reflect the data that is globally required. If specific data is only needed in specific parts of the application, that application's part should provide the data through a reducer and a context provider and not make use of the global (`redux`) store.

Essentially, the entire application's state can be provided by a context provider, but for now we'll take the bottom-up approach and gradually refactor and introduce the reducer/context approach in favour of `redux` complexity.
48 changes: 36 additions & 12 deletions src/components/SiteHeader/__tests__/SiteHeader.test.js
@@ -1,7 +1,7 @@
import React from 'react';
import { render, fireEvent, cleanup } from '@testing-library/react';
import { render, fireEvent, cleanup, act } from '@testing-library/react';
import MatchMediaMock from 'match-media-mock';
import { act } from 'react-dom/test-utils';
import 'jest-styled-components';

import * as auth from 'shared/services/auth/auth';
import { history, withAppContext } from 'test/utils';
Expand All @@ -25,7 +25,9 @@ describe('components/SiteHeader', () => {
it('should render correctly when not authenticated', () => {
jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => false);

history.push('/');
act(() => {
history.push('/');
});

const { container, rerender, queryByText } = render(
withAppContext(<SiteHeader />)
Expand All @@ -50,17 +52,23 @@ describe('components/SiteHeader', () => {
value: mmm,
});

history.push('/manage');
act(() => {
history.push('/manage');
});

rerender(withAppContext(<SiteHeader />));

expect(queryByText('Melden')).toBeNull();

expect(container.querySelector('#header')).toHaveStyleRule('z-index: 2');
});

it('should render correctly when authenticated', () => {
jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => true);

history.push('/');
act(() => {
history.push('/');
});

const { container, queryByText } = render(withAppContext(<SiteHeader showItems={{ settings: true, users: true, groups: true }} />));

Expand All @@ -73,12 +81,16 @@ describe('components/SiteHeader', () => {
1
);

expect(container.querySelector('#header')).toHaveStyleRule('z-index: 2');

cleanup();

// narrow window toggle
mmm.setConfig({ type: 'screen', width: breakpoint - 1 });

history.push('/manage');
act(() => {
history.push('/manage');
});

render(withAppContext(<SiteHeader showItems={{ settings: true, users: true, groups: true }} />));

Expand Down Expand Up @@ -119,7 +131,9 @@ describe('components/SiteHeader', () => {
it('should render a title', () => {
jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => false);

history.push('/');
act(() => {
history.push('/');
});

const { queryByText } = render(withAppContext(<SiteHeader />));

Expand All @@ -132,7 +146,9 @@ describe('components/SiteHeader', () => {

jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => true);

history.push('/');
act(() => {
history.push('/');
});

render(withAppContext(<SiteHeader />));

Expand All @@ -143,7 +159,9 @@ describe('components/SiteHeader', () => {

jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => false);

history.push('/manage');
act(() => {
history.push('/manage');
});

render(withAppContext(<SiteHeader />));

Expand All @@ -163,7 +181,9 @@ describe('components/SiteHeader', () => {
it('should render a tall header', () => {
jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => false);

history.push('/');
act(() => {
history.push('/');
});

const { container, rerender } = render(
withAppContext(<SiteHeader location={{ pathname: '/' }} />)
Expand All @@ -185,7 +205,9 @@ describe('components/SiteHeader', () => {

cleanup();

history.push('/manage');
act(() => {
history.push('/manage');
});

jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => false);

Expand Down Expand Up @@ -237,7 +259,9 @@ describe('components/SiteHeader', () => {
});

it('should handle logout callback', () => {
history.push('/');
act(() => {
history.push('/');
});

jest.spyOn(auth, 'isAuthenticated').mockImplementation(() => true);

Expand Down
18 changes: 11 additions & 7 deletions src/components/SiteHeader/index.js
Expand Up @@ -26,26 +26,28 @@ const StyledHeader = styled(HeaderComponent)`
a:link {
text-decoration: none;
}
${({ isFrontOffice, tall }) =>
isFrontOffice &&
tall &&
css`

${({ isFrontOffice, tall }) => isFrontOffice && tall && css`
& {
max-width: 960px;
h1 {
margin-left: ${themeSpacing(-5)};
font-weight: 400;
}

h1 a {
&,
span {
width: 153px;
}
}

h1 a span {
background-image: url(${svg.LogoShort}) !important;
}
}
`}
`}

nav {
width: 100%;
ul {
Expand Down Expand Up @@ -86,9 +88,12 @@ const StyledSearchBar = styled(SearchBar)`
`;

const HeaderWrapper = styled.div`
z-index: 1;
position: relative;

#header {
z-index: 2;
}

${({ tall }) =>
!tall &&
css`
Expand All @@ -104,7 +109,6 @@ const HeaderWrapper = styled.div`
css`
#header {
position: relative;
z-index: 2;

header {
height: 160px;
Expand Down
4 changes: 2 additions & 2 deletions src/models/incident/reducer.js
@@ -1,7 +1,6 @@
import { fromJS } from 'immutable';

import stadsdeelList from 'signals/incident-management/definitions/stadsdeelList';
import priorityList from 'signals/incident-management/definitions/priorityList';
import { stadsdeelList, priorityList, typesList } from 'signals/incident-management/definitions';
import statusList, {
changeStatusOptionList,
defaultTextsOptionList,
Expand Down Expand Up @@ -54,6 +53,7 @@ export const initialState = fromJS({
[PATCH_TYPE_LOCATION]: false,
},
split: false,
typesList,
});

function incidentModelReducer(state = initialState, action) {
Expand Down
8 changes: 6 additions & 2 deletions src/shared/services/configuration/configuration.js
Expand Up @@ -108,8 +108,12 @@ export class Configuration {
return `${this.API_ROOT}signals/category/prediction`;
}

get INCIDENT_ENDPOINT() {
return `${this.API_ROOT}signals/signal/`;
get INCIDENT_PUBLIC_ENDPOINT() {
return `${this.API_ROOT}signals/v1/public/signals/`;
}

get INCIDENT_PRIVATE_ENDPOINT() {
return `${this.API_ROOT}signals/v1/private/signals/`;
}

get INCIDENTS_ENDPOINT() {
Expand Down
15 changes: 4 additions & 11 deletions src/shared/services/file-upload-channel/index.js
@@ -1,11 +1,7 @@
import {
buffers,
eventChannel,
END,
} from 'redux-saga';

function fileUploadChannel(endpoint, file, id) {
return eventChannel(emitter => {
import { buffers, eventChannel, END } from 'redux-saga';

export default (endpoint, file, id) =>
eventChannel(emitter => {
const formData = new window.FormData();
formData.append('signal_id', id);
formData.append('image', file);
Expand Down Expand Up @@ -52,6 +48,3 @@ function fileUploadChannel(endpoint, file, id) {
xhr.abort();
};
}, buffers.sliding(2));
}

export default fileUploadChannel;
Expand Up @@ -22,10 +22,11 @@ function getId(item) {

const MetaList = ({
incident,
subcategories,
priorityList,
onPatchIncident,
onEditStatus,
onPatchIncident,
priorityList,
subcategories,
typesList,
}) => {
const children = get(incident, '_links.sia:children');
const parent = get(incident, '_links.sia:parent');
Expand Down Expand Up @@ -86,6 +87,24 @@ const MetaList = ({
</Highlight>
)}

{incident.type && (
<Highlight
subscribeTo={incident.type.code}
>
<ChangeValue
component={RadioInput}
definitionClass="meta-list__definition"
display="Type"
incident={incident}
list={typesList}
onPatchIncident={onPatchIncident}
path="type.code"
type="type"
valueClass="meta-list__value"
/>
</Highlight>
)}

<Highlight subscribeTo={incident.category.sub_slug}>
<ChangeValue
display="Subcategorie"
Expand Down Expand Up @@ -217,11 +236,11 @@ const MetaList = ({

MetaList.propTypes = {
incident: incidentType.isRequired,
onEditStatus: PropTypes.func.isRequired,
onPatchIncident: PropTypes.func.isRequired,
priorityList: dataListType.isRequired,
subcategories: PropTypes.array.isRequired,

onPatchIncident: PropTypes.func.isRequired,
onEditStatus: PropTypes.func.isRequired,
typesList: dataListType.isRequired,
};

export default MetaList;