Skip to content
Snippets Groups Projects
Commit e57a18b0 authored by OZGCloud's avatar OZGCloud
Browse files

Merge pull request 'ozg-6300-accordion-zusammenarbeit' (#716) from...

Merge pull request 'ozg-6300-accordion-zusammenarbeit' (#716) from ozg-6300-accordion-zusammenarbeit into master

Reviewed-on: https://git.ozg-sh.de/ozgcloud-app/alfa/pulls/716


Reviewed-by: default avatarOZGCloud <ozgcloud@mgm-tp.com>
parents 4281bb2c 60fe4cd2
Branches
Tags
No related merge requests found
Showing
with 955 additions and 222 deletions
......@@ -21,6 +21,7 @@
* Die sprachspezifischen Genehmigungen und Beschränkungen
* unter der Lizenz sind dem Lizenztext zu entnehmen.
*/
import { CollaborationInVorgangContainerComponent } from '@alfa-client/collaboration';
import { VorgangForwardingContainerComponent } from '@alfa-client/forwarding';
import { KommentarListInVorgangContainerComponent } from '@alfa-client/kommentar';
import { PostfachMailListContainerComponent } from '@alfa-client/postfach';
......@@ -30,6 +31,7 @@ import {
createEmptyStateResource,
createStateResource,
} from '@alfa-client/tech-shared';
import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils';
import {
ExpansionPanelComponent,
OzgcloudStrokedButtonWithSpinnerComponent,
......@@ -57,6 +59,7 @@ describe('VorgangDetailAreaComponent', () => {
let component: VorgangDetailAreaComponent;
let fixture: ComponentFixture<VorgangDetailAreaComponent>;
const collaborationContainer: string = getDataTestIdOf('collaboration-in-voragng-container');
const wiedervorlagenContainer: string = getDataTestIdOf('wiedervorlagen-container-in-vorgang');
const kommentarContainer: string = getDataTestIdOf('kommentar-container-in-vorgang');
const postfachNachrichtenContainer: string = getDataTestIdOf(
......@@ -86,6 +89,7 @@ describe('VorgangDetailAreaComponent', () => {
MockComponent(VorgangForwardingContainerComponent),
MockComponent(BescheidListInVorgangContainerComponent),
MockComponent(ExpansionPanelComponent),
MockComponent(CollaborationInVorgangContainerComponent),
],
}).compileComponents();
});
......@@ -101,6 +105,26 @@ describe('VorgangDetailAreaComponent', () => {
expect(component).toBeTruthy();
});
describe('Collaboration', () => {
it('should be visibile if link is present', () => {
component.vorgangStateResource = createStateResource(
createVorgangWithEingangResource([VorgangWithEingangLinkRel.CREATE_COLLABORATION_REQUEST]),
);
fixture.detectChanges();
existsAsHtmlElement(fixture, collaborationContainer);
});
it('should be hidden if link is missing', () => {
component.vorgangStateResource = createStateResource(vorgang);
fixture.detectChanges();
notExistsAsHtmlElement(fixture, collaborationContainer);
});
});
describe('wiedervorlagen', () => {
it('should be visible', () => {
component.vorgangStateResource = createStateResource(
......
......@@ -23,6 +23,7 @@
*/
import { BescheidModule } from '@alfa-client/bescheid';
import { BinaryFileModule } from '@alfa-client/binary-file';
import { CollaborationModule } from '@alfa-client/collaboration';
import { ForwardingModule } from '@alfa-client/forwarding';
import { HistorieModule } from '@alfa-client/historie';
import { KommentarModule } from '@alfa-client/kommentar';
......@@ -161,6 +162,7 @@ const routes: Routes = [
TextareaEditorComponent,
BescheidStatusTextComponent,
ErrorMessageComponent,
CollaborationModule,
],
declarations: [
VorgangDetailPageComponent,
......
......@@ -64,6 +64,8 @@ export enum VorgangWithEingangLinkRel {
BESCHEIDE = 'bescheide',
UEBERSPRINGEN_UND_ABSCHLIESSEN = 'ueberspringen_und_abschliessen',
DOWNLOAD_ATTACHMENTS = 'downloadAttachments',
CREATE_COLLABORATION_REQUEST = 'createCollaborationRequest',
}
export enum LoeschAnforderungLinkRel {
......
This diff is collapsed.
......@@ -12,7 +12,7 @@
"build": "nx run alfa:build",
"test": "nx affected --target=test --parallel 8 -- --runInBand",
"test:cov": "jest --coverage",
"test:lib": "nx test ${npm_config_lib} --watchAll",
"test:lib": "nx test ${npm_config_lib}",
"test:debug:lib": "nx test ${npm_config_lib} --detectOpenHandles --watchAll",
"ci-build": "nx run alfa:build --outputHashing=all",
"ci-build-admin": "nx container admin && cp -r dist/ apps/admin/",
......
......@@ -23,6 +23,7 @@
"@alfa-client/bescheid-shared": ["libs/bescheid-shared/src/index.ts"],
"@alfa-client/binary-file": ["libs/binary-file/src/index.ts"],
"@alfa-client/binary-file-shared": ["libs/binary-file-shared/src/index.ts"],
"@alfa-client/collaboration": ["libs/collaboration/src/index.ts"],
"@alfa-client/command-shared": ["libs/command-shared/src/index.ts"],
"@alfa-client/environment-shared": ["libs/environment-shared/src/index.ts"],
"@alfa-client/forwarding": ["libs/forwarding/src/index.ts"],
......@@ -55,7 +56,8 @@
"@alfa-client/wiedervorlage-shared": ["libs/wiedervorlage-shared/src/index.ts"],
"@ods/component": ["libs/design-component/src/index.ts"],
"@ods/system": ["libs/design-system/src/index.ts"],
"authentication": ["libs/authentication/src/index.ts"]
"authentication": ["libs/authentication/src/index.ts"],
"test": ["libs/test/src/index.ts"]
}
},
"exclude": ["node_modules", "tmp"]
......
......@@ -10,6 +10,7 @@ server:
ozgcloud:
feature:
reply-always-allowed: true
collaboration-enabled: true
production: false
stage:
production: false
......
......@@ -9,6 +9,7 @@ keycloak:
ozgcloud:
feature:
reply-always-allowed: true
collaboration-enabled: true
forwarding:
lninfo:
url: classpath:files/LandesnetzInfo.html
......
......@@ -18,6 +18,7 @@ grpc:
ozgcloud:
feature:
reply-always-allowed: true
collaboration-enabled: true
production: false
user-assistance:
documentation:
......
package de.ozgcloud.alfa.collaboration;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
import java.util.Objects;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.LinkRelation;
import org.springframework.hateoas.server.RepresentationModelProcessor;
import org.springframework.stereotype.Component;
import de.ozgcloud.alfa.common.ModelBuilder;
import de.ozgcloud.alfa.common.command.CommandController;
import de.ozgcloud.alfa.common.user.CurrentUserService;
import de.ozgcloud.alfa.common.user.UserRole;
import de.ozgcloud.alfa.vorgang.VorgangWithEingang;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Component
@ConditionalOnProperty("ozgcloud.feature.collaboration-enabled")
class CollaborationVorgangProcessor implements RepresentationModelProcessor<EntityModel<VorgangWithEingang>> {
static final LinkRelation REL_CREATE_COLLABORATION_REQUEST = LinkRelation.of("createCollaborationRequest");
private final CurrentUserService currentUserService;
@Override
public EntityModel<VorgangWithEingang> process(EntityModel<VorgangWithEingang> model) {
var vorgang = model.getContent();
if (Objects.isNull(vorgang)) {
return model;
}
return ModelBuilder.fromModel(model)
.ifMatch(() -> currentUserService.hasRole(UserRole.VERWALTUNG_USER))
.addLink(linkTo(methodOn(CommandController.CommandByRelationController.class).createCommand(vorgang.getId(), vorgang.getId(),
vorgang.getVersion(), null)).withRel(REL_CREATE_COLLABORATION_REQUEST))
.buildModel();
}
}
......@@ -16,4 +16,9 @@ public class FeatureToggleProperties {
* Enable mail reply option regardless of other configuration.
*/
private boolean replyAlwaysAllowed = false;
/**
* Enable collaboration-feature in Vorgang
*/
private boolean collaborationEnabled = false;
}
......@@ -29,7 +29,6 @@ import java.util.List;
import java.util.Objects;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.jwt.Jwt;
......@@ -37,7 +36,9 @@ import org.springframework.stereotype.Service;
import de.ozgcloud.alfa.common.binaryfile.AlfaUserWithFileId;
import de.ozgcloud.common.errorhandling.TechnicalException;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Service
public class CurrentUserService {
......@@ -51,10 +52,9 @@ public class CurrentUserService {
static final String KEYCLOAK_USER_GIVEN_NAME = "given_name";
static final String KEYCLOAK_USER_FAMILY_NAME = "family_name";
@Autowired
private UserService userService;
@Autowired
private RoleHierarchy roleHierarchy;
private final UserService userService;
private final RoleHierarchy roleHierarchy;
public boolean hasRole(String role) {
return CurrentUserHelper.hasRole(role) || hasRoleReachable(role);
......
package de.ozgcloud.alfa.collaboration;
import static org.assertj.core.api.Assertions.*;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
class CollaborationVorgangProcessorITCase {
@SpringBootTest(properties = {"ozgcloud.feature.collaboration-enabled=true"})
@Nested
class OnFeatureEnabled {
@Test
void shouldExistInApplicationContext(ApplicationContext context) {
assertThat(context.getBean(CollaborationVorgangProcessor.class)).isNotNull();
}
}
@SpringBootTest
@Nested
class OnFeatureDisabled {
@Test
void shouldNotExistInApplicationContext(ApplicationContext context) {
assertThatThrownBy(() -> context.getBean(CollaborationVorgangProcessor.class)).isInstanceOf(NoSuchBeanDefinitionException.class);
}
}
}
package de.ozgcloud.alfa.collaboration;
import static de.ozgcloud.alfa.common.UserProfileUrlProviderTestFactory.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Spy;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.UriTemplate;
import de.ozgcloud.alfa.common.UserProfileUrlProvider;
import de.ozgcloud.alfa.common.command.CommandController;
import de.ozgcloud.alfa.common.user.CurrentUserService;
import de.ozgcloud.alfa.common.user.UserRole;
import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory;
import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory;
class CollaborationVorgangProcessorTest {
@Spy
@InjectMocks
private CollaborationVorgangProcessor processor;
@Mock
private CurrentUserService currentUserService;
private final UserProfileUrlProvider urlProvider = new UserProfileUrlProvider();
@Nested
class TestProcess {
@Nested
class OnNullVorgang {
@Test
void shouldNotAddLinksIfVorgangIsNull() {
var model = processor.process(new EntityModel<>() {
});
assertThat(model.hasLinks()).isFalse();
}
}
@Nested
class OnNonNullVorgang {
@BeforeEach
void prepareBuilder() {
initUserProfileUrlProvider(urlProvider);
}
@Test
void shouldAddCreateCollaborationRequestRelation() {
when(currentUserService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(true);
var model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create()));
assertThat(model.getLink(CollaborationVorgangProcessor.REL_CREATE_COLLABORATION_REQUEST)).isPresent().get()
.extracting(Link::getHref)
.isEqualTo(UriTemplate.of(CommandController.CommandByRelationController.COMMAND_BY_RELATION_PATH)
.expand(VorgangHeaderTestFactory.ID, VorgangHeaderTestFactory.ID, VorgangHeaderTestFactory.VERSION).toString());
}
@Test
void shouldNotAddCreateCollaborationRequestRelation() {
when(currentUserService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(false);
var model = processor.process(EntityModel.of(VorgangWithEingangTestFactory.create()));
assertThat(model.getLink(CollaborationVorgangProcessor.REL_CREATE_COLLABORATION_REQUEST)).isEmpty();
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment