TSK-177 Add authentication and login page for taskana spring rest example
This commit is contained in:
parent
66bdaab7cf
commit
99b882f867
29
rest/pom.xml
29
rest/pom.xml
|
|
@ -1,19 +1,20 @@
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>pro.taskana</groupId>
|
<groupId>pro.taskana</groupId>
|
||||||
<artifactId>taskana-rest-parent</artifactId>
|
<artifactId>taskana-rest-parent</artifactId>
|
||||||
<version>0.1.4-SNAPSHOT</version>
|
<version>0.1.4-SNAPSHOT</version>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<description>This pom is parent to all taskana rest modules and serves the common build.</description>
|
<description>This pom is parent to all taskana rest modules and serves the common build.</description>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<module>taskana-rest-spring</module>
|
<module>taskana-rest-spring</module>
|
||||||
<module>taskana-rest-spring-example</module>
|
<module>../web</module>
|
||||||
</modules>
|
<module>taskana-rest-spring-example</module>
|
||||||
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,16 @@
|
||||||
<artifactId>h2</artifactId>
|
<artifactId>h2</artifactId>
|
||||||
<version>1.4.197</version>
|
<version>1.4.197</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!--
|
||||||
|
Since taskana-web packs its content in /static, we do not have to unpack it again.
|
||||||
|
However, when any local change has to be done to that folder you have to copy
|
||||||
|
target/classes/static manually from taskana-web.
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>pro.taskana</groupId>
|
||||||
|
<artifactId>taskana-web</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<!-- Tests -->
|
<!-- Tests -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|
@ -60,7 +69,6 @@
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
|
|
@ -69,4 +77,5 @@
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package pro.taskana.rest.controllers;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
public class ViewController {
|
||||||
|
@RequestMapping({ "/administration*/**", "/workplace*/**", "/monitor*/**" })
|
||||||
|
public String index() {
|
||||||
|
return "forward:/index.html";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
package pro.taskana.rest.models;
|
||||||
|
|
||||||
|
public class User {
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -10,13 +10,14 @@ import javax.security.auth.callback.PasswordCallback;
|
||||||
import javax.security.auth.login.LoginException;
|
import javax.security.auth.login.LoginException;
|
||||||
import javax.security.auth.spi.LoginModule;
|
import javax.security.auth.spi.LoginModule;
|
||||||
|
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import pro.taskana.security.GroupPrincipal;
|
import pro.taskana.security.GroupPrincipal;
|
||||||
import pro.taskana.security.UserPrincipal;
|
import pro.taskana.security.UserPrincipal;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO.
|
* TODO.
|
||||||
*/
|
*/
|
||||||
public class SampleLoginModule implements LoginModule {
|
public class SampleLoginModule extends UsernamePasswordAuthenticationFilter implements LoginModule {
|
||||||
|
|
||||||
private NameCallback nameCallback;
|
private NameCallback nameCallback;
|
||||||
|
|
||||||
|
|
@ -24,6 +25,7 @@ public class SampleLoginModule implements LoginModule {
|
||||||
|
|
||||||
private Subject subject;
|
private Subject subject;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean abort() throws LoginException {
|
public boolean abort() throws LoginException {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package pro.taskana.rest.security;
|
package pro.taskana.rest.security;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
@ -11,13 +12,16 @@ import org.springframework.security.authentication.jaas.JaasAuthenticationProvid
|
||||||
import org.springframework.security.authentication.jaas.JaasNameCallbackHandler;
|
import org.springframework.security.authentication.jaas.JaasNameCallbackHandler;
|
||||||
import org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler;
|
import org.springframework.security.authentication.jaas.JaasPasswordCallbackHandler;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
|
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||||
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
import org.springframework.security.web.jaasapi.JaasApiIntegrationFilter;
|
||||||
import org.springframework.web.cors.CorsConfiguration;
|
import org.springframework.web.cors.CorsConfiguration;
|
||||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||||
import org.springframework.web.filter.CorsFilter;
|
import org.springframework.web.filter.CorsFilter;
|
||||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||||
|
|
||||||
|
|
@ -28,26 +32,43 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
|
||||||
|
@Value("${devMode}")
|
||||||
|
private boolean devMode;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
|
||||||
http.csrf()
|
http.csrf()
|
||||||
.disable()
|
.disable()
|
||||||
.authenticationProvider(jaasAuthProvider())
|
.authenticationProvider(jaasAuthProvider())
|
||||||
.authorizeRequests()
|
.authorizeRequests()
|
||||||
.antMatchers(HttpMethod.GET, "/**")
|
.antMatchers(HttpMethod.GET, "/**")
|
||||||
.authenticated()
|
.authenticated()
|
||||||
.and()
|
.and()
|
||||||
.httpBasic()
|
.httpBasic()
|
||||||
.and()
|
.and()
|
||||||
.addFilter(new JaasApiIntegrationFilter());
|
.addFilter(new JaasApiIntegrationFilter());
|
||||||
|
|
||||||
|
if (devMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
http
|
||||||
|
.authorizeRequests()
|
||||||
|
.anyRequest().authenticated()
|
||||||
|
.and()
|
||||||
|
.formLogin()
|
||||||
|
.permitAll()
|
||||||
|
.and()
|
||||||
|
.logout()
|
||||||
|
.permitAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public JaasAuthenticationProvider jaasAuthProvider() {
|
public JaasAuthenticationProvider jaasAuthProvider() {
|
||||||
JaasAuthenticationProvider authenticationProvider = new JaasAuthenticationProvider();
|
JaasAuthenticationProvider authenticationProvider = new JaasAuthenticationProvider();
|
||||||
authenticationProvider.setAuthorityGranters(new AuthorityGranter[] {new SampleRoleGranter()});
|
authenticationProvider.setAuthorityGranters(new AuthorityGranter[]{new SampleRoleGranter()});
|
||||||
authenticationProvider.setCallbackHandlers(new JaasAuthenticationCallbackHandler[] {
|
authenticationProvider.setCallbackHandlers(new JaasAuthenticationCallbackHandler[]{
|
||||||
new JaasNameCallbackHandler(), new JaasPasswordCallbackHandler()});
|
new JaasNameCallbackHandler(), new JaasPasswordCallbackHandler()});
|
||||||
authenticationProvider.setLoginContextName("taskana");
|
authenticationProvider.setLoginContextName("taskana");
|
||||||
authenticationProvider.setLoginConfig(new ClassPathResource("pss_jaas.config"));
|
authenticationProvider.setLoginConfig(new ClassPathResource("pss_jaas.config"));
|
||||||
return authenticationProvider;
|
return authenticationProvider;
|
||||||
|
|
@ -72,6 +93,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||||
config.addAllowedOrigin("*");
|
config.addAllowedOrigin("*");
|
||||||
config.addAllowedHeader("*");
|
config.addAllowedHeader("*");
|
||||||
config.addAllowedMethod("*");
|
config.addAllowedMethod("*");
|
||||||
|
config.addAllowedMethod("POST");
|
||||||
source.registerCorsConfiguration("/**", config);
|
source.registerCorsConfiguration("/**", config);
|
||||||
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
|
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
|
||||||
bean.setOrder(0);
|
bean.setOrder(0);
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ datasource.url=jdbc:h2:mem:taskana;IGNORECASE=TRUE;LOCK_MODE=0;INIT=CREATE SCHEM
|
||||||
datasource.driverClassName=org.h2.Driver
|
datasource.driverClassName=org.h2.Driver
|
||||||
datasource.username=sa
|
datasource.username=sa
|
||||||
datasource.password=sa
|
datasource.password=sa
|
||||||
|
devMode=false
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Custom Login Page</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<form name="f" th:action="@{/login}" method="post">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Please Login</legend>
|
||||||
|
<div th:if="${param.error}" class="alert alert-error">
|
||||||
|
Invalid username and password.
|
||||||
|
</div>
|
||||||
|
<div th:if="${param.logout}" class="alert alert-success">
|
||||||
|
You have been logged out.
|
||||||
|
</div>
|
||||||
|
<label for="username">Username</label>
|
||||||
|
<input type="text" id="username" name="username"/>
|
||||||
|
<label for="password">Password</label>
|
||||||
|
<input type="password" id="password" name="password"/>
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="submit" class="btn">Log in</button>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -39,7 +39,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import pro.taskana.rest.resource.ClassificationSummaryResource;
|
import pro.taskana.rest.resource.ClassificationSummaryResource;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"devMode=true"})
|
||||||
@Import(RestConfiguration.class)
|
@Import(RestConfiguration.class)
|
||||||
public class ClassificationControllerIntTest {
|
public class ClassificationControllerIntTest {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import pro.taskana.rest.resource.TaskSummaryResource;
|
import pro.taskana.rest.resource.TaskSummaryResource;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"devMode=true"})
|
||||||
@Import(RestConfiguration.class)
|
@Import(RestConfiguration.class)
|
||||||
public class TaskControllerIntTest {
|
public class TaskControllerIntTest {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import pro.taskana.TaskanaRole;
|
||||||
import pro.taskana.rest.resource.TaskanaUserInfoResource;
|
import pro.taskana.rest.resource.TaskanaUserInfoResource;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"devMode=true"})
|
||||||
@Import(RestConfiguration.class)
|
@Import(RestConfiguration.class)
|
||||||
public class TaskanaEngineControllerIntTest {
|
public class TaskanaEngineControllerIntTest {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import pro.taskana.rest.resource.DistributionTargetResource;
|
||||||
import pro.taskana.rest.resource.WorkbasketSummaryResource;
|
import pro.taskana.rest.resource.WorkbasketSummaryResource;
|
||||||
|
|
||||||
@RunWith(SpringRunner.class)
|
@RunWith(SpringRunner.class)
|
||||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = {"devMode=true"})
|
||||||
@Import(RestConfiguration.class)
|
@Import(RestConfiguration.class)
|
||||||
public class WorkbasketControllerIntTest {
|
public class WorkbasketControllerIntTest {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1221,7 +1221,17 @@
|
||||||
"boom": {
|
"boom": {
|
||||||
"version": "2.10.1",
|
"version": "2.10.1",
|
||||||
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
|
"resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz",
|
||||||
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8="
|
"integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "2.16.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"hoek": {
|
||||||
|
"version": "2.16.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||||
|
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"bootstrap": {
|
"bootstrap": {
|
||||||
"version": "3.3.7",
|
"version": "3.3.7",
|
||||||
|
|
@ -5168,7 +5178,15 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"boom": "2.10.1",
|
"boom": "2.10.1",
|
||||||
"cryptiles": "2.0.5",
|
"cryptiles": "2.0.5",
|
||||||
|
"hoek": "2.16.3",
|
||||||
"sntp": "1.0.9"
|
"sntp": "1.0.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"hoek": {
|
||||||
|
"version": "2.16.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||||
|
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"he": {
|
"he": {
|
||||||
|
|
@ -10004,7 +10022,17 @@
|
||||||
"sntp": {
|
"sntp": {
|
||||||
"version": "1.0.9",
|
"version": "1.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
|
"resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz",
|
||||||
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg="
|
"integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=",
|
||||||
|
"requires": {
|
||||||
|
"hoek": "2.16.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"hoek": {
|
||||||
|
"version": "2.16.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
|
||||||
|
"integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"socket.io": {
|
"socket.io": {
|
||||||
"version": "2.0.4",
|
"version": "2.0.4",
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'classifications',
|
path: 'classifications',
|
||||||
component: MasterAndDetailComponent,
|
component: MasterAndDetailComponent,
|
||||||
canActivate: [DomainGuard],
|
canActivate: [DomainGuard],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { Ng2AutoCompleteModule } from 'ng2-auto-complete';
|
import { Ng2AutoCompleteModule } from 'ng2-auto-complete';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
|
||||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||||
import { AlertModule } from 'ngx-bootstrap';
|
import { AlertModule } from 'ngx-bootstrap';
|
||||||
import { SharedModule } from 'app/shared/shared.module';
|
import { SharedModule } from 'app/shared/shared.module';
|
||||||
|
|
@ -45,11 +44,10 @@ const MODULES = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
Ng2AutoCompleteModule,
|
Ng2AutoCompleteModule,
|
||||||
HttpClientModule,
|
|
||||||
AngularSvgIconModule,
|
AngularSvgIconModule,
|
||||||
AlertModule,
|
AlertModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
AdministrationRoutingModule,
|
AdministrationRoutingModule
|
||||||
];
|
];
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
|
|
|
||||||
|
|
@ -4,23 +4,19 @@ import { Injectable } from '@angular/core';
|
||||||
import { environment } from 'environments/environment';
|
import { environment } from 'environments/environment';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { ReplaySubject } from 'rxjs/ReplaySubject';
|
import { ReplaySubject } from 'rxjs/ReplaySubject';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ClassificationCategoriesService {
|
export class ClassificationCategoriesService {
|
||||||
|
|
||||||
private url = environment.taskanaRestUrl + '/v1/classification-categories';
|
private url = environment.taskanaRestUrl + '/v1/classification-categories';
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
private dataObs$ = new ReplaySubject<Array<string>>(1);
|
private dataObs$ = new ReplaySubject<Array<string>>(1);
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient) { }
|
constructor(
|
||||||
|
private httpClient: HttpClient) { }
|
||||||
|
|
||||||
getCategories(forceRefresh = false): Observable<Array<string>> {
|
getCategories(forceRefresh = false): Observable<Array<string>> {
|
||||||
if (!this.dataObs$.observers.length || forceRefresh) {
|
if (!this.dataObs$.observers.length || forceRefresh) {
|
||||||
this.httpClient.get<Array<string>>(this.url, this.httpOptions).subscribe(
|
this.httpClient.get<Array<string>>(this.url).subscribe(
|
||||||
data => this.dataObs$.next(data),
|
data => this.dataObs$.next(data),
|
||||||
error => {
|
error => {
|
||||||
this.dataObs$.error(error);
|
this.dataObs$.error(error);
|
||||||
|
|
|
||||||
|
|
@ -11,21 +11,16 @@ import { TaskanaDate } from 'app/shared/util/taskana.date';
|
||||||
export class ClassificationDefinitionService {
|
export class ClassificationDefinitionService {
|
||||||
|
|
||||||
url = environment.taskanaRestUrl + '/v1/classificationdefinitions';
|
url = environment.taskanaRestUrl + '/v1/classificationdefinitions';
|
||||||
|
constructor(
|
||||||
httpOptions = {
|
private httpClient: HttpClient,
|
||||||
headers: new HttpHeaders({
|
private alertService: AlertService
|
||||||
'Content-Type': 'application/json',
|
) {
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient, private alertService: AlertService) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET
|
// GET
|
||||||
exportClassifications(domain: string) {
|
exportClassifications(domain: string) {
|
||||||
domain = (domain === '' ? '' : '?domain=' + domain);
|
domain = (domain === '' ? '' : '?domain=' + domain);
|
||||||
this.httpClient.get<ClassificationDefinition[]>(this.url + domain, this.httpOptions)
|
this.httpClient.get<ClassificationDefinition[]>(this.url + domain)
|
||||||
.subscribe(
|
.subscribe(
|
||||||
response => saveAs(new Blob([JSON.stringify(response)], { type: 'text/plain;charset=utf-8' }),
|
response => saveAs(new Blob([JSON.stringify(response)], { type: 'text/plain;charset=utf-8' }),
|
||||||
'Classifications_' + TaskanaDate.getDate() + '.json')
|
'Classifications_' + TaskanaDate.getDate() + '.json')
|
||||||
|
|
@ -36,7 +31,7 @@ export class ClassificationDefinitionService {
|
||||||
// TODO handle error
|
// TODO handle error
|
||||||
importClassifications(classifications: any) {
|
importClassifications(classifications: any) {
|
||||||
this.httpClient.post(this.url + '/import',
|
this.httpClient.post(this.url + '/import',
|
||||||
JSON.parse(classifications), this.httpOptions).subscribe(
|
JSON.parse(classifications)).subscribe(
|
||||||
classificationsUpdated => this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, 'Import was successful')),
|
classificationsUpdated => this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, 'Import was successful')),
|
||||||
error => this.alertService.triggerAlert(new AlertModel(AlertType.DANGER, 'Import was not successful'))
|
error => this.alertService.triggerAlert(new AlertModel(AlertType.DANGER, 'Import was not successful'))
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -9,22 +9,17 @@ import { ReplaySubject } from 'rxjs/ReplaySubject';
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ClassificationTypesService {
|
export class ClassificationTypesService {
|
||||||
private url = environment.taskanaRestUrl + '/v1/classification-types';
|
private url = environment.taskanaRestUrl + '/v1/classification-types';
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
private classificationTypeSelectedValue = 'TASK';
|
private classificationTypeSelectedValue = 'TASK';
|
||||||
private classificationTypeSelected = new BehaviorSubject<string>(this.classificationTypeSelectedValue);
|
private classificationTypeSelected = new BehaviorSubject<string>(this.classificationTypeSelectedValue);
|
||||||
private dataObs$ = new ReplaySubject<Array<string>>(1);
|
private dataObs$ = new ReplaySubject<Array<string>>(1);
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient) { }
|
constructor(private httpClient: HttpClient
|
||||||
|
) { }
|
||||||
|
|
||||||
getClassificationTypes(forceRefresh = false): Observable<Array<string>> {
|
getClassificationTypes(forceRefresh = false): Observable<Array<string>> {
|
||||||
|
|
||||||
if (!this.dataObs$.observers.length || forceRefresh) {
|
if (!this.dataObs$.observers.length || forceRefresh) {
|
||||||
this.httpClient.get<Array<string>>(this.url, this.httpOptions).subscribe(
|
this.httpClient.get<Array<string>>(this.url).subscribe(
|
||||||
data => this.dataObs$.next(data),
|
data => this.dataObs$.next(data),
|
||||||
error => {
|
error => {
|
||||||
this.dataObs$.error(error);
|
this.dataObs$.error(error);
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,6 @@ export class ClassificationsService {
|
||||||
private classificationSelected = new Subject<string>();
|
private classificationSelected = new Subject<string>();
|
||||||
private classificationSaved = new Subject<number>();
|
private classificationSaved = new Subject<number>();
|
||||||
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
private classificationTypes: Array<string>;
|
private classificationTypes: Array<string>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
|
@ -42,8 +35,7 @@ export class ClassificationsService {
|
||||||
return this.domainService.getSelectedDomain().mergeMap(domain => {
|
return this.domainService.getSelectedDomain().mergeMap(domain => {
|
||||||
const classificationTypes = this.classificationTypeService.getSelectedClassificationType();
|
const classificationTypes = this.classificationTypeService.getSelectedClassificationType();
|
||||||
return this.getClassificationObservable(this.httpClient.get<ClassificationResource>(
|
return this.getClassificationObservable(this.httpClient.get<ClassificationResource>(
|
||||||
`${environment.taskanaRestUrl}/v1/classifications/?domain=${domain}`,
|
`${environment.taskanaRestUrl}/v1/classifications/?domain=${domain}`));
|
||||||
this.httpOptions));
|
|
||||||
|
|
||||||
}).do(() => {
|
}).do(() => {
|
||||||
this.domainService.domainChangedComplete();
|
this.domainService.domainChangedComplete();
|
||||||
|
|
@ -52,7 +44,7 @@ export class ClassificationsService {
|
||||||
|
|
||||||
// GET
|
// GET
|
||||||
getClassification(id: string): Observable<ClassificationDefinition> {
|
getClassification(id: string): Observable<ClassificationDefinition> {
|
||||||
return this.httpClient.get<ClassificationDefinition>(`${environment.taskanaRestUrl}/v1/classifications/${id}`, this.httpOptions)
|
return this.httpClient.get<ClassificationDefinition>(`${environment.taskanaRestUrl}/v1/classifications/${id}`)
|
||||||
.do((classification: ClassificationDefinition) => {
|
.do((classification: ClassificationDefinition) => {
|
||||||
if (classification) {
|
if (classification) {
|
||||||
this.classificationTypeService.selectClassificationType(classification.type);
|
this.classificationTypeService.selectClassificationType(classification.type);
|
||||||
|
|
@ -63,18 +55,17 @@ export class ClassificationsService {
|
||||||
|
|
||||||
// POST
|
// POST
|
||||||
postClassification(classification: Classification): Observable<Classification> {
|
postClassification(classification: Classification): Observable<Classification> {
|
||||||
return this.httpClient.post<Classification>(`${environment.taskanaRestUrl}/v1/classifications`, classification,
|
return this.httpClient.post<Classification>(`${environment.taskanaRestUrl}/v1/classifications`, classification);
|
||||||
this.httpOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT
|
// PUT
|
||||||
putClassification(url: string, classification: Classification): Observable<Classification> {
|
putClassification(url: string, classification: Classification): Observable<Classification> {
|
||||||
return this.httpClient.put<Classification>(url, classification, this.httpOptions);
|
return this.httpClient.put<Classification>(url, classification);
|
||||||
}
|
}
|
||||||
|
|
||||||
// DELETE
|
// DELETE
|
||||||
deleteClassification(url: string): Observable<string> {
|
deleteClassification(url: string): Observable<string> {
|
||||||
return this.httpClient.delete<string>(url, this.httpOptions);
|
return this.httpClient.delete<string>(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// #region "Service extras"
|
// #region "Service extras"
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,29 @@
|
||||||
import {Injectable} from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import {environment} from 'app/../environments/environment';
|
import { environment } from 'app/../environments/environment';
|
||||||
import {saveAs} from 'file-saver/FileSaver';
|
import { saveAs } from 'file-saver/FileSaver';
|
||||||
import {AlertService} from 'app/services/alert/alert.service';
|
import { AlertService } from 'app/services/alert/alert.service';
|
||||||
import {WorkbasketDefinition} from 'app/models/workbasket-definition';
|
import { WorkbasketDefinition } from 'app/models/workbasket-definition';
|
||||||
import {AlertModel, AlertType} from 'app/models/alert';
|
import { AlertModel, AlertType } from 'app/models/alert';
|
||||||
import {TaskanaDate} from 'app/shared/util/taskana.date';
|
import { TaskanaDate } from 'app/shared/util/taskana.date';
|
||||||
import {ErrorModel} from 'app/models/modal-error';
|
import { ErrorModel } from 'app/models/modal-error';
|
||||||
import {ErrorModalService} from 'app/services/errorModal/error-modal.service';
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkbasketDefinitionService {
|
export class WorkbasketDefinitionService {
|
||||||
url: string = environment.taskanaRestUrl + '/v1/workbasketdefinitions';
|
url: string = environment.taskanaRestUrl + '/v1/workbasketdefinitions';
|
||||||
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient, private alertService: AlertService,
|
constructor(private httpClient: HttpClient, private alertService: AlertService,
|
||||||
private errorModalService: ErrorModalService) {
|
private errorModalService: ErrorModalService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET
|
// GET
|
||||||
exportWorkbaskets(domain: string) {
|
exportWorkbaskets(domain: string) {
|
||||||
domain = (domain === '' ? '' : '?domain=' + domain);
|
domain = (domain === '' ? '' : '?domain=' + domain);
|
||||||
this.httpClient.get<WorkbasketDefinition[]>(this.url + domain, this.httpOptions).subscribe(
|
this.httpClient.get<WorkbasketDefinition[]>(this.url + domain).subscribe(
|
||||||
response => {
|
response => {
|
||||||
saveAs(new Blob([JSON.stringify(response)], {type: 'text/plain;charset=utf-8'}),
|
saveAs(new Blob([JSON.stringify(response)], { type: 'text/plain;charset=utf-8' }),
|
||||||
'Workbaskets_' + TaskanaDate.getDate() + '.json');
|
'Workbaskets_' + TaskanaDate.getDate() + '.json');
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
@ -40,10 +32,10 @@ export class WorkbasketDefinitionService {
|
||||||
// POST
|
// POST
|
||||||
importWorkbasketDefinitions(workbasketDefinitions: any) {
|
importWorkbasketDefinitions(workbasketDefinitions: any) {
|
||||||
this.httpClient.post(environment.taskanaRestUrl + '/v1/workbasketdefinitions/import',
|
this.httpClient.post(environment.taskanaRestUrl + '/v1/workbasketdefinitions/import',
|
||||||
JSON.parse(workbasketDefinitions), this.httpOptions).subscribe(
|
JSON.parse(workbasketDefinitions)).subscribe(
|
||||||
workbasketsUpdated => this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, 'Import was successful')),
|
workbasketsUpdated => this.alertService.triggerAlert(new AlertModel(AlertType.SUCCESS, 'Import was successful')),
|
||||||
error => this.errorModalService.triggerError(new ErrorModel(
|
error => this.errorModalService.triggerError(new ErrorModel(
|
||||||
`There was an error importing workbaskets`, error.message))
|
`There was an error importing workbaskets`, error.message))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import { Subject } from 'rxjs/Subject';
|
import { Subject } from 'rxjs/Subject';
|
||||||
import { environment } from 'app/../environments/environment';
|
import { environment } from 'app/../environments/environment';
|
||||||
|
|
@ -43,12 +43,6 @@ export class WorkbasketService {
|
||||||
// Domain
|
// Domain
|
||||||
readonly DOMAIN = 'domain';
|
readonly DOMAIN = 'domain';
|
||||||
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
page = 1;
|
page = 1;
|
||||||
pageSize = 9;
|
pageSize = 9;
|
||||||
|
|
@ -86,7 +80,7 @@ export class WorkbasketService {
|
||||||
`${environment.taskanaRestUrl}/v1/workbaskets/${this.getWorkbasketSummaryQueryParameters(
|
`${environment.taskanaRestUrl}/v1/workbaskets/${this.getWorkbasketSummaryQueryParameters(
|
||||||
sortBy, order, name,
|
sortBy, order, name,
|
||||||
nameLike, descLike, owner, ownerLike, type, key, keyLike, requiredPermission,
|
nameLike, descLike, owner, ownerLike, type, key, keyLike, requiredPermission,
|
||||||
!allPages ? this.page : undefined, !allPages ? this.pageSize : undefined, domain)}`, this.httpOptions)
|
!allPages ? this.page : undefined, !allPages ? this.pageSize : undefined, domain)}`)
|
||||||
.do(workbaskets => {
|
.do(workbaskets => {
|
||||||
return workbaskets;
|
return workbaskets;
|
||||||
});
|
});
|
||||||
|
|
@ -96,51 +90,50 @@ export class WorkbasketService {
|
||||||
}
|
}
|
||||||
// GET
|
// GET
|
||||||
getWorkBasket(id: string): Observable<Workbasket> {
|
getWorkBasket(id: string): Observable<Workbasket> {
|
||||||
return this.httpClient.get<Workbasket>(`${environment.taskanaRestUrl}/v1/workbaskets/${id}`, this.httpOptions);
|
return this.httpClient.get<Workbasket>(`${environment.taskanaRestUrl}/v1/workbaskets/${id}`);
|
||||||
}
|
}
|
||||||
// POST
|
// POST
|
||||||
createWorkbasket(workbasket: Workbasket): Observable<Workbasket> {
|
createWorkbasket(workbasket: Workbasket): Observable<Workbasket> {
|
||||||
return this.httpClient
|
return this.httpClient
|
||||||
.post<Workbasket>(`${environment.taskanaRestUrl}/v1/workbaskets`, workbasket, this.httpOptions);
|
.post<Workbasket>(`${environment.taskanaRestUrl}/v1/workbaskets`, workbasket);
|
||||||
|
|
||||||
}
|
}
|
||||||
// PUT
|
// PUT
|
||||||
updateWorkbasket(url: string, workbasket: Workbasket): Observable<Workbasket> {
|
updateWorkbasket(url: string, workbasket: Workbasket): Observable<Workbasket> {
|
||||||
return this.httpClient
|
return this.httpClient
|
||||||
.put<Workbasket>(url, workbasket, this.httpOptions)
|
.put<Workbasket>(url, workbasket)
|
||||||
.catch(this.handleError);
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
// DELETE
|
// DELETE
|
||||||
deleteWorkbasket(url: string) {
|
deleteWorkbasket(url: string) {
|
||||||
return this.httpClient.delete(url, this.httpOptions);
|
return this.httpClient.delete(url);
|
||||||
}
|
}
|
||||||
// GET
|
// GET
|
||||||
getWorkBasketAccessItems(url: string): Observable<WorkbasketAccessItemsResource> {
|
getWorkBasketAccessItems(url: string): Observable<WorkbasketAccessItemsResource> {
|
||||||
return this.httpClient.get<WorkbasketAccessItemsResource>(url, this.httpOptions);
|
return this.httpClient.get<WorkbasketAccessItemsResource>(url);
|
||||||
}
|
}
|
||||||
// POST
|
// POST
|
||||||
createWorkBasketAccessItem(url: string, workbasketAccessItem: WorkbasketAccessItems): Observable<WorkbasketAccessItems> {
|
createWorkBasketAccessItem(url: string, workbasketAccessItem: WorkbasketAccessItems): Observable<WorkbasketAccessItems> {
|
||||||
return this.httpClient.post<WorkbasketAccessItems>(url, workbasketAccessItem, this.httpOptions);
|
return this.httpClient.post<WorkbasketAccessItems>(url, workbasketAccessItem);
|
||||||
}
|
}
|
||||||
// PUT
|
// PUT
|
||||||
updateWorkBasketAccessItem(url: string, workbasketAccessItem: Array<WorkbasketAccessItems>): Observable<string> {
|
updateWorkBasketAccessItem(url: string, workbasketAccessItem: Array<WorkbasketAccessItems>): Observable<string> {
|
||||||
return this.httpClient.put<string>(url,
|
return this.httpClient.put<string>(url,
|
||||||
workbasketAccessItem,
|
workbasketAccessItem);
|
||||||
this.httpOptions);
|
|
||||||
}
|
}
|
||||||
// GET
|
// GET
|
||||||
getWorkBasketsDistributionTargets(url: string): Observable<WorkbasketDistributionTargetsResource> {
|
getWorkBasketsDistributionTargets(url: string): Observable<WorkbasketDistributionTargetsResource> {
|
||||||
return this.httpClient.get<WorkbasketDistributionTargetsResource>(url, this.httpOptions);
|
return this.httpClient.get<WorkbasketDistributionTargetsResource>(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PUT
|
// PUT
|
||||||
updateWorkBasketsDistributionTargets(url: string, distributionTargetsIds: Array<string>):
|
updateWorkBasketsDistributionTargets(url: string, distributionTargetsIds: Array<string>):
|
||||||
Observable<WorkbasketDistributionTargetsResource> {
|
Observable<WorkbasketDistributionTargetsResource> {
|
||||||
return this.httpClient.put<WorkbasketDistributionTargetsResource>(url, distributionTargetsIds, this.httpOptions);
|
return this.httpClient.put<WorkbasketDistributionTargetsResource>(url, distributionTargetsIds);
|
||||||
}
|
}
|
||||||
// DELETE
|
// DELETE
|
||||||
removeDistributionTarget(url: string) {
|
removeDistributionTarget(url: string) {
|
||||||
return this.httpClient.delete<string>(url, this.httpOptions);
|
return this.httpClient.delete<string>(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -214,5 +207,6 @@ export class WorkbasketService {
|
||||||
return Observable.throw(errMsg);
|
return Observable.throw(errMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #endregion
|
// #endregion
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="container-scrollable">
|
<div class="container-scrollable">
|
||||||
<taskana-spinner [isRunning]="requestInProgress" ></taskana-spinner>
|
<taskana-spinner [isRunning]="requestInProgress" ></taskana-spinner>
|
||||||
<taskana-no-access *ngIf="!requestInProgress && (!hasPermission && !workbasket || !workbasket && selectedId)"></taskana-no-access>
|
<taskana-no-access *ngIf="!requestInProgress && (!workbasket || !workbasket && selectedId)"></taskana-no-access>
|
||||||
<div id="workbasket-details" *ngIf="workbasket && !requestInProgress">
|
<div id="workbasket-details" *ngIf="workbasket && !requestInProgress">
|
||||||
<ul class="nav nav-tabs" role="tablist">
|
<ul class="nav nav-tabs" role="tablist">
|
||||||
<li *ngIf="showDetail" class="visible-xs visible-sm hidden">
|
<li *ngIf="showDetail" class="visible-xs visible-sm hidden">
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ import { LinksWorkbasketSummary } from 'app/models/links-workbasket-summary';
|
||||||
|
|
||||||
import { WorkbasketService } from 'app/administration/services/workbasket/workbasket.service';
|
import { WorkbasketService } from 'app/administration/services/workbasket/workbasket.service';
|
||||||
import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-detail.service';
|
import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-detail.service';
|
||||||
import { PermissionService } from 'app/services/permission/permission.service';
|
|
||||||
import { AlertService } from 'app/services/alert/alert.service';
|
import { AlertService } from 'app/services/alert/alert.service';
|
||||||
import { SavingWorkbasketService } from 'app/administration/services/saving-workbaskets/saving-workbaskets.service';
|
import { SavingWorkbasketService } from 'app/administration/services/saving-workbaskets/saving-workbaskets.service';
|
||||||
|
|
||||||
|
|
@ -79,7 +78,7 @@ describe('WorkbasketDetailsComponent', () => {
|
||||||
declarations: [WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent,
|
declarations: [WorkbasketDetailsComponent, NoAccessComponent, WorkbasketInformationComponent, SpinnerComponent,
|
||||||
IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe, AlertComponent, GeneralMessageModalComponent, AccessItemsComponent,
|
IconTypeComponent, MapValuesPipe, RemoveNoneTypePipe, AlertComponent, GeneralMessageModalComponent, AccessItemsComponent,
|
||||||
DistributionTargetsComponent, FilterComponent, DualListComponent, DummyDetailComponent, SelectWorkBasketPipe],
|
DistributionTargetsComponent, FilterComponent, DualListComponent, DummyDetailComponent, SelectWorkBasketPipe],
|
||||||
providers: [WorkbasketService, MasterAndDetailService, PermissionService, ErrorModalService, RequestInProgressService,
|
providers: [WorkbasketService, MasterAndDetailService, ErrorModalService, RequestInProgressService,
|
||||||
AlertService, SavingWorkbasketService, {
|
AlertService, SavingWorkbasketService, {
|
||||||
provide: DomainService,
|
provide: DomainService,
|
||||||
useClass: DomainServiceMock
|
useClass: DomainServiceMock
|
||||||
|
|
@ -92,7 +91,6 @@ describe('WorkbasketDetailsComponent', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(WorkbasketDetailsComponent);
|
fixture = TestBed.createComponent(WorkbasketDetailsComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
component.hasPermission = false;
|
|
||||||
debugElement = fixture.debugElement.nativeElement;
|
debugElement = fixture.debugElement.nativeElement;
|
||||||
router = TestBed.get(Router)
|
router = TestBed.get(Router)
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
@ -129,16 +127,10 @@ describe('WorkbasketDetailsComponent', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should has created taskana-no-access if workbasket is not defined and hasPermission is false', () => {
|
|
||||||
expect(component.workbasket).toBeUndefined();
|
|
||||||
component.hasPermission = false;
|
|
||||||
fixture.detectChanges();
|
|
||||||
expect(debugElement.querySelector('taskana-no-access')).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should has created taskana-workbasket-details if workbasket is defined and taskana-no-access should dissapear', () => {
|
it('should has created taskana-workbasket-details if workbasket is defined and taskana-no-access should dissapear', () => {
|
||||||
expect(component.workbasket).toBeUndefined();
|
expect(component.workbasket).toBeUndefined();
|
||||||
component.hasPermission = false;
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(debugElement.querySelector('taskana-no-access')).toBeTruthy();
|
expect(debugElement.querySelector('taskana-no-access')).toBeTruthy();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import { ACTION } from 'app/models/action';
|
||||||
|
|
||||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
import { WorkbasketService } from 'app/administration/services/workbasket/workbasket.service'
|
import { WorkbasketService } from 'app/administration/services/workbasket/workbasket.service'
|
||||||
import { PermissionService } from 'app/services/permission/permission.service';
|
|
||||||
import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-detail.service'
|
import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-detail.service'
|
||||||
import { DomainService } from 'app/services/domain/domain.service';
|
import { DomainService } from 'app/services/domain/domain.service';
|
||||||
|
|
||||||
|
|
@ -28,7 +27,6 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
||||||
workbasketCopy: Workbasket;
|
workbasketCopy: Workbasket;
|
||||||
selectedId: string = undefined;
|
selectedId: string = undefined;
|
||||||
showDetail = false;
|
showDetail = false;
|
||||||
hasPermission = true;
|
|
||||||
requestInProgress = false;
|
requestInProgress = false;
|
||||||
action: string;
|
action: string;
|
||||||
|
|
||||||
|
|
@ -43,7 +41,6 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private masterAndDetailService: MasterAndDetailService,
|
private masterAndDetailService: MasterAndDetailService,
|
||||||
private permissionService: PermissionService,
|
|
||||||
private domainService: DomainService) { }
|
private domainService: DomainService) { }
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -80,14 +77,6 @@ export class WorkbasketDetailsComponent implements OnInit, OnDestroy {
|
||||||
this.masterAndDetailSubscription = this.masterAndDetailService.getShowDetail().subscribe(showDetail => {
|
this.masterAndDetailSubscription = this.masterAndDetailService.getShowDetail().subscribe(showDetail => {
|
||||||
this.showDetail = showDetail;
|
this.showDetail = showDetail;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.permissionSubscription = this.permissionService.hasPermission().subscribe(permission => {
|
|
||||||
this.hasPermission = permission;
|
|
||||||
if (!this.hasPermission) {
|
|
||||||
this.requestInProgress = false;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backClicked(): void {
|
backClicked(): void {
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,17 @@ import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
import { BusinessAdminGuard } from 'app/guards/business-admin-guard';
|
||||||
|
import { MonitorGuard } from 'app/guards/monitor-guard';
|
||||||
|
|
||||||
const appRoutes: Routes = [
|
const appRoutes: Routes = [
|
||||||
{
|
{
|
||||||
|
canActivate: [BusinessAdminGuard],
|
||||||
path: 'administration',
|
path: 'administration',
|
||||||
loadChildren: './administration/administration.module#AdministrationModule',
|
loadChildren: './administration/administration.module#AdministrationModule',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
canActivate: [MonitorGuard],
|
||||||
path: 'monitor',
|
path: 'monitor',
|
||||||
loadChildren: './monitor/monitor.module#MonitorModule',
|
loadChildren: './monitor/monitor.module#MonitorModule',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@ import { SharedModule } from 'app/shared/shared.module';
|
||||||
* Services
|
* Services
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { HttpClientInterceptor } from 'app/services/httpClientInterceptor/http-client-interceptor.service';
|
|
||||||
import { PermissionService } from 'app/services/permission/permission.service';
|
|
||||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
||||||
import { OrientationService } from 'app/services/orientation/orientation.service';
|
import { OrientationService } from 'app/services/orientation/orientation.service';
|
||||||
|
|
@ -32,19 +30,22 @@ import { MasterAndDetailService } from 'app/services/masterAndDetail/master-and-
|
||||||
import { TreeService } from 'app/services/tree/tree.service';
|
import { TreeService } from 'app/services/tree/tree.service';
|
||||||
import { TitlesService } from 'app/services/titles/titles.service';
|
import { TitlesService } from 'app/services/titles/titles.service';
|
||||||
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
|
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
|
||||||
|
import { WindowRefService } from 'app/services/window/window.service';
|
||||||
|
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Components
|
* Components
|
||||||
*/
|
*/
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { NavBarComponent } from 'app/components/nav-bar/nav-bar.component';
|
import { NavBarComponent } from 'app/components/nav-bar/nav-bar.component';
|
||||||
|
import { UserInformationComponent } from 'app/components/user-information/user-information.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Guards
|
* Guards
|
||||||
*/
|
*/
|
||||||
import { DomainGuard } from './guards/domain-guard';
|
import { DomainGuard } from './guards/domain-guard';
|
||||||
|
import { BusinessAdminGuard } from './guards/business-admin-guard';
|
||||||
|
import { MonitorGuard } from './guards/monitor-guard';
|
||||||
import { APP_BASE_HREF } from '@angular/common';
|
import { APP_BASE_HREF } from '@angular/common';
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -64,29 +65,31 @@ const MODULES = [
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
NavBarComponent
|
NavBarComponent,
|
||||||
|
UserInformationComponent
|
||||||
];
|
];
|
||||||
|
|
||||||
export function startupServiceFactory(startupService: StartupService): Function {
|
export function startupServiceFactory(startupService: StartupService): () => Promise<any> {
|
||||||
return () => startupService.load();
|
return (): Promise<any> => {
|
||||||
|
return startupService.load();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: DECLARATIONS,
|
declarations: DECLARATIONS,
|
||||||
imports: MODULES,
|
imports: MODULES,
|
||||||
providers: [
|
providers: [
|
||||||
|
WindowRefService,
|
||||||
{ provide: APP_BASE_HREF, useValue: '/' },
|
{ provide: APP_BASE_HREF, useValue: '/' },
|
||||||
DomainService,
|
DomainService,
|
||||||
{
|
|
||||||
provide: HTTP_INTERCEPTORS,
|
|
||||||
useClass: HttpClientInterceptor,
|
|
||||||
multi: true
|
|
||||||
},
|
|
||||||
ErrorModalService,
|
ErrorModalService,
|
||||||
RequestInProgressService,
|
RequestInProgressService,
|
||||||
OrientationService,
|
OrientationService,
|
||||||
SelectedRouteService,
|
SelectedRouteService,
|
||||||
DomainGuard,
|
DomainGuard,
|
||||||
|
BusinessAdminGuard,
|
||||||
|
MonitorGuard,
|
||||||
StartupService,
|
StartupService,
|
||||||
{
|
{
|
||||||
provide: APP_INITIALIZER,
|
provide: APP_INITIALIZER,
|
||||||
|
|
@ -95,11 +98,11 @@ export function startupServiceFactory(startupService: StartupService): Function
|
||||||
multi: true
|
multi: true
|
||||||
},
|
},
|
||||||
AlertService,
|
AlertService,
|
||||||
PermissionService,
|
|
||||||
MasterAndDetailService,
|
MasterAndDetailService,
|
||||||
TreeService,
|
TreeService,
|
||||||
TitlesService,
|
TitlesService,
|
||||||
CustomFieldsService
|
CustomFieldsService,
|
||||||
|
TaskanaEngineService
|
||||||
],
|
],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="pull-left col-sm-3 col-md-4">
|
<div class="pull-left col-sm-3 col-md-4">
|
||||||
<button type="button" *ngIf="!showNavbar" class="btn btn-default navbar-toggle show pull-left" (click)="toogleNavBar();"
|
<button type="button" *ngIf="!showNavbar" class="btn btn-default navbar-toggle show pull-left" (click)="toogleNavBar();"
|
||||||
aria-expanded="true" aria-controls="navbar">
|
aria-expanded="true" aria-controls="navbar">
|
||||||
<span class="glyphicon glyphicon-arrow-right white"></span>
|
<span class="glyphicon glyphicon glyphicon-th-list white"></span>
|
||||||
</button>
|
</button>
|
||||||
<span> </span>
|
<span> </span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<h2 class="navbar-brand no-margin"> {{title}}</h2>
|
<h2 class="navbar-brand no-margin"> {{title}}</h2>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="selectedRoute.indexOf('workbaskets') !== -1 || selectedRoute.indexOf('classifications') !== -1"class="pull-right domain-form">
|
<div *ngIf="selectedRoute.indexOf('workbaskets') !== -1 || selectedRoute.indexOf('classifications') !== -1" class="pull-right domain-form">
|
||||||
<div class="dropdown clearfix btn-group">
|
<div class="dropdown clearfix btn-group">
|
||||||
<label class="control-label hidden-xs">Working on </label>
|
<label class="control-label hidden-xs">Working on </label>
|
||||||
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||||
|
|
@ -36,23 +36,25 @@
|
||||||
<ul class="nav">
|
<ul class="nav">
|
||||||
<svg-icon class="logo white visible-xs" src="./assets/icons/logo.svg"></svg-icon>
|
<svg-icon class="logo white visible-xs" src="./assets/icons/logo.svg"></svg-icon>
|
||||||
<h2 class="navbar-brand no-margin logo visible-xs"> {{title}}</h2>
|
<h2 class="navbar-brand no-margin logo visible-xs"> {{title}}</h2>
|
||||||
<button type="button" *ngIf="showNavbar" class="btn btn-default navbar-toggle show pull-right" (click)="toogleNavBar();"
|
<button type="button" class="btn btn-default logout navbar-toggle show pull-right" data-toggle="tooltip" title="logout" (click)="logout()" aria-expanded="true"
|
||||||
aria-expanded="true" aria-controls="navbar">
|
aria-controls="logout">
|
||||||
<span class="glyphicon glyphicon-arrow-left white"></span>
|
<span class="glyphicon glyphicon-share white"></span>
|
||||||
</button>
|
</button>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-content">
|
<div class="nav-content">
|
||||||
<div class="row menu">
|
<taskana-user-information></taskana-user-information>
|
||||||
|
<div *ngIf="administrationAccess" class="row menu">
|
||||||
<span (click)="toogleNavBar()" routerLink="administration/workbaskets" aria-controls="administration" routerLinkActive="active">Administration</span>
|
<span (click)="toogleNavBar()" routerLink="administration/workbaskets" aria-controls="administration" routerLinkActive="active">Administration</span>
|
||||||
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('workbaskets') !== -1 }">
|
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('workbaskets') !== -1 }">
|
||||||
<span (click)="toogleNavBar()" class="col-xs-6" routerLink="administration/workbaskets" aria-controls="Workbaskets" routerLinkActive="active">Workbaskets</span>
|
<span (click)="toogleNavBar()" class="col-xs-6" routerLink="administration/workbaskets" aria-controls="Workbaskets" routerLinkActive="active">Workbaskets</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('classifications') !== -1}">
|
<div class="row submenu" [ngClass]="{'selected': selectedRoute.indexOf('classifications') !== -1}">
|
||||||
<span (click)="toogleNavBar()" class="col-xs-6" routerLink="administration/classifications" aria-controls="Classifications" routerLinkActive="active">Classifications</span>
|
<span (click)="toogleNavBar()" class="col-xs-6" routerLink="administration/classifications" aria-controls="Classifications"
|
||||||
|
routerLinkActive="active">Classifications</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('monitor') !== -1}">
|
<div *ngIf="monitorAccess" class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('monitor') !== -1}">
|
||||||
<span (click)="toogleNavBar()" routerLink="{{monitorUrl}}" aria-controls="Monitor" routerLinkActive="active">Monitor</span>
|
<span (click)="toogleNavBar()" routerLink="{{monitorUrl}}" aria-controls="Monitor" routerLinkActive="active">Monitor</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('workplace') !== -1 || selectedRoute === ''}">
|
<div class="row menu" [ngClass]="{'selected': selectedRoute.indexOf('workplace') !== -1 || selectedRoute === ''}">
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ $selected-border-color: #22a39f;
|
||||||
|
|
||||||
.navbar-toggle{
|
.navbar-toggle{
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
|
|
||||||
|
}
|
||||||
|
button.navbar-toggle:hover > span{
|
||||||
|
color:$selected-border-color;
|
||||||
}
|
}
|
||||||
ul.nav > p {
|
ul.nav > p {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
@ -29,7 +33,6 @@ svg-icon.logo {
|
||||||
padding: 6px 5px 5px 5px;
|
padding: 6px 5px 5px 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
h2.navbar-brand{
|
h2.navbar-brand{
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
@ -67,8 +70,7 @@ h2.navbar-brand{
|
||||||
|
|
||||||
|
|
||||||
.nav-content{
|
.nav-content{
|
||||||
margin-top: 25px;
|
margin-top: 5px;
|
||||||
margin-left: 8px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,28 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { SharedModule } from 'app/shared/shared.module';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
import { NavBarComponent } from './nav-bar.component';
|
import { NavBarComponent } from './nav-bar.component';
|
||||||
|
import { UserInformationComponent } from 'app/components/user-information/user-information.component';
|
||||||
|
|
||||||
import { SelectedRouteService } from 'app/services/selected-route/selected-route';
|
import { SelectedRouteService } from 'app/services/selected-route/selected-route';
|
||||||
import { DomainService } from 'app/services/domain/domain.service';
|
import { DomainService } from 'app/services/domain/domain.service';
|
||||||
import { DomainServiceMock } from 'app/services/domain/domain.service.mock';
|
import { DomainServiceMock } from 'app/services/domain/domain.service.mock';
|
||||||
|
import { BusinessAdminGuard } from 'app/guards/business-admin-guard';
|
||||||
|
import { MonitorGuard } from 'app/guards/monitor-guard';
|
||||||
|
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
|
||||||
|
import { WindowRefService } from 'app/services/window/window.service';
|
||||||
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
|
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
||||||
|
|
||||||
|
import { UserInfoModel } from 'app/models/user-info';
|
||||||
|
|
||||||
describe('NavBarComponent', () => {
|
describe('NavBarComponent', () => {
|
||||||
let component: NavBarComponent;
|
let component: NavBarComponent;
|
||||||
let fixture: ComponentFixture<NavBarComponent>;
|
let fixture: ComponentFixture<NavBarComponent>;
|
||||||
let debugElement, navBar;
|
let debugElement, navBar, taskanaEngineService;
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: 'classifications', component: NavBarComponent }
|
{ path: 'classifications', component: NavBarComponent }
|
||||||
|
|
@ -20,16 +32,23 @@ describe('NavBarComponent', () => {
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [NavBarComponent],
|
declarations: [NavBarComponent, UserInformationComponent],
|
||||||
imports: [
|
imports: [
|
||||||
AngularSvgIconModule,
|
AngularSvgIconModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
RouterTestingModule.withRoutes(routes),
|
RouterTestingModule.withRoutes(routes),
|
||||||
|
SharedModule
|
||||||
],
|
],
|
||||||
providers: [SelectedRouteService, {
|
providers: [SelectedRouteService, {
|
||||||
provide: DomainService,
|
provide: DomainService,
|
||||||
useClass: DomainServiceMock
|
useClass: DomainServiceMock
|
||||||
}]
|
},
|
||||||
|
BusinessAdminGuard,
|
||||||
|
MonitorGuard,
|
||||||
|
TaskanaEngineService,
|
||||||
|
WindowRefService,
|
||||||
|
ErrorModalService,
|
||||||
|
RequestInProgressService]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
@ -39,6 +58,8 @@ describe('NavBarComponent', () => {
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
debugElement = fixture.debugElement.nativeElement;
|
debugElement = fixture.debugElement.nativeElement;
|
||||||
navBar = fixture.debugElement.componentInstance;
|
navBar = fixture.debugElement.componentInstance;
|
||||||
|
taskanaEngineService = TestBed.get(TaskanaEngineService);
|
||||||
|
spyOn(taskanaEngineService, 'getUserInformation').and.returnValue(Observable.of(new UserInfoModel));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ import { SelectedRouteService } from 'app/services/selected-route/selected-route
|
||||||
import { Subscription } from 'rxjs/Subscription';
|
import { Subscription } from 'rxjs/Subscription';
|
||||||
import { trigger, state, style, transition, keyframes, animate } from '@angular/animations';
|
import { trigger, state, style, transition, keyframes, animate } from '@angular/animations';
|
||||||
import { DomainService } from 'app/services/domain/domain.service';
|
import { DomainService } from 'app/services/domain/domain.service';
|
||||||
|
import { BusinessAdminGuard } from 'app/guards/business-admin-guard';
|
||||||
|
import { MonitorGuard } from 'app/guards/monitor-guard';
|
||||||
|
import { WindowRefService } from 'app/services/window/window.service';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'taskana-nav-bar',
|
selector: 'taskana-nav-bar',
|
||||||
templateUrl: './nav-bar.component.html',
|
templateUrl: './nav-bar.component.html',
|
||||||
|
|
@ -38,11 +40,17 @@ export class NavBarComponent implements OnInit, OnDestroy {
|
||||||
monitorUrl = './monitor';
|
monitorUrl = './monitor';
|
||||||
workplaceUrl = './workplace';
|
workplaceUrl = './workplace';
|
||||||
|
|
||||||
|
administrationAccess = false;
|
||||||
|
monitorAccess = false;
|
||||||
|
|
||||||
selectedRouteSubscription: Subscription;
|
selectedRouteSubscription: Subscription;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private selectedRouteService: SelectedRouteService,
|
private selectedRouteService: SelectedRouteService,
|
||||||
private domainService: DomainService) { }
|
private domainService: DomainService,
|
||||||
|
private businessAdminGuard: BusinessAdminGuard,
|
||||||
|
private monitorGuard: MonitorGuard,
|
||||||
|
private window: WindowRefService) { }
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.selectedRouteSubscription = this.selectedRouteService.getSelectedRoute().subscribe((value: string) => {
|
this.selectedRouteSubscription = this.selectedRouteService.getSelectedRoute().subscribe((value: string) => {
|
||||||
|
|
@ -56,6 +64,13 @@ export class NavBarComponent implements OnInit, OnDestroy {
|
||||||
this.domainService.getSelectedDomain().subscribe(domain => {
|
this.domainService.getSelectedDomain().subscribe(domain => {
|
||||||
this.selectedDomain = domain;
|
this.selectedDomain = domain;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.businessAdminGuard.canActivate().subscribe(hasAccess => {
|
||||||
|
this.administrationAccess = hasAccess
|
||||||
|
});
|
||||||
|
this.monitorGuard.canActivate().subscribe(hasAccess => {
|
||||||
|
this.monitorAccess = hasAccess
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
switchDomain(domain) {
|
switchDomain(domain) {
|
||||||
|
|
@ -65,6 +80,12 @@ export class NavBarComponent implements OnInit, OnDestroy {
|
||||||
toogleNavBar() {
|
toogleNavBar() {
|
||||||
this.showNavbar = !this.showNavbar;
|
this.showNavbar = !this.showNavbar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
logout() {
|
||||||
|
this.window.nativeWindow.location.href = environment.taskanaRestUrl + '/login?logout';
|
||||||
|
}
|
||||||
|
|
||||||
private setTitle(value: string = 'workbaskets') {
|
private setTitle(value: string = 'workbaskets') {
|
||||||
if (value.indexOf('workbaskets') === 0 || value.indexOf('classifications') === 0) {
|
if (value.indexOf('workbaskets') === 0 || value.indexOf('classifications') === 0) {
|
||||||
this.title = this.titleAdministration;
|
this.title = this.titleAdministration;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="icon">
|
||||||
|
<div class="icon-wrap col-xs-offset-5">
|
||||||
|
<svg-icon class="blue big" src="./assets/icons/user.svg"></svg-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="user-info white">
|
||||||
|
<span>Logged as: {{userInformation.userId}}</span>
|
||||||
|
<button type="button" class="btn btn-default white pull-right transparent" (click)="toogleRoles();" aria-expanded="true" aria-controls="roles">
|
||||||
|
<span>Roles</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="white pull-right roles col-xs-12" [@toggle]="showRoles" *ngIf="showRoles">
|
||||||
|
<span><i>{{roles}}</i></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
.big {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.user-info {
|
||||||
|
margin-top:85px;
|
||||||
|
> span {
|
||||||
|
margin: 0 15px 0 15px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon, {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
& > .icon-wrap {
|
||||||
|
border-radius: 50%;
|
||||||
|
border: solid 3px #22a39f;
|
||||||
|
width: 74px;
|
||||||
|
height: 74px;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #175263;
|
||||||
|
position: absolute;
|
||||||
|
-webkit-box-shadow: 0px 3px 3px #416b6a;
|
||||||
|
-moz-box-shadow: 0px 3px 3px #416b6a;
|
||||||
|
box-shadow: 0px 3px 3px #416b6a;
|
||||||
|
|
||||||
|
&> svg-icon {
|
||||||
|
border-radius: 50%;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: white;
|
||||||
|
position: absolute;
|
||||||
|
margin:2px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon:before { content: '';
|
||||||
|
position: absolute;
|
||||||
|
border-bottom: solid 3px #22a39f;
|
||||||
|
width: 100%;
|
||||||
|
height: 60px;
|
||||||
|
transform: translateY(-33%);
|
||||||
|
-webkit-box-shadow: 0px 3px 3px #416b6a;
|
||||||
|
-moz-box-shadow: 0px 3px 3px #416b6a;
|
||||||
|
box-shadow: 0px 3px 3px #416b6a;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.transparent, {
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
&:hover{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
color:#22a39f
|
||||||
|
}
|
||||||
|
&:focus{
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
outline: none;
|
||||||
|
color:white
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { HttpModule } from '@angular/http';
|
||||||
|
|
||||||
|
import { UserInformationComponent } from './user-information.component';
|
||||||
|
|
||||||
|
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
|
||||||
|
import { UserInfoModel } from 'app/models/user-info';
|
||||||
|
|
||||||
|
describe('UserInformationComponent', () => {
|
||||||
|
let component: UserInformationComponent;
|
||||||
|
let fixture: ComponentFixture<UserInformationComponent>;
|
||||||
|
let taskanaEngineService;
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [AngularSvgIconModule,
|
||||||
|
HttpClientModule, HttpModule],
|
||||||
|
declarations: [UserInformationComponent],
|
||||||
|
providers: [TaskanaEngineService]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(UserInformationComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
taskanaEngineService = TestBed.get(TaskanaEngineService);
|
||||||
|
spyOn(taskanaEngineService, 'getUserInformation').and.returnValue(Observable.of(new UserInfoModel));
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
|
||||||
|
import { UserInfoModel } from 'app/models/user-info';
|
||||||
|
import { trigger, transition, animate, keyframes, style } from '@angular/animations';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'taskana-user-information',
|
||||||
|
templateUrl: './user-information.component.html',
|
||||||
|
styleUrls: ['./user-information.component.scss'],
|
||||||
|
animations: [
|
||||||
|
trigger('toggle', [
|
||||||
|
transition('void => *', animate('300ms ease-in', keyframes([
|
||||||
|
style({ opacity: 0, height: '0px' }),
|
||||||
|
style({ opacity: 1, height: '10px' }),
|
||||||
|
style({ opacity: 1, height: '*' })]))),
|
||||||
|
transition('* => void', animate('300ms ease-out', keyframes([
|
||||||
|
style({ opacity: 1, height: '*' }),
|
||||||
|
style({ opacity: 0, height: '10px' }),
|
||||||
|
style({ opacity: 0, height: '0px' })])))
|
||||||
|
]
|
||||||
|
)],
|
||||||
|
})
|
||||||
|
export class UserInformationComponent implements OnInit {
|
||||||
|
|
||||||
|
userInformation: UserInfoModel;
|
||||||
|
roles = '';
|
||||||
|
showRoles = false;
|
||||||
|
constructor(private taskanaEngineService: TaskanaEngineService) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.taskanaEngineService.getUserInformation().subscribe(userInfo => {
|
||||||
|
this.userInformation = userInfo;
|
||||||
|
this.roles = '[' + userInfo.roles.join(',') + ']';
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
toogleRoles() {
|
||||||
|
this.showRoles = !this.showRoles;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DomainService } from 'app/services/domain/domain.service';
|
||||||
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
|
import { ErrorModel } from 'app/models/modal-error';
|
||||||
|
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AdminGuard implements CanActivate {
|
||||||
|
constructor(private taskanaEngineService: TaskanaEngineService, public router: Router) { }
|
||||||
|
|
||||||
|
canActivate() {
|
||||||
|
return this.taskanaEngineService.getUserInformation().map(userInfo => {
|
||||||
|
if (userInfo.roles.length === 0) {
|
||||||
|
return this.navigateToWorplace();
|
||||||
|
}
|
||||||
|
const adminRole = userInfo.roles.find(role => {
|
||||||
|
if (role === 'ADMIN') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (adminRole) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.navigateToWorplace();
|
||||||
|
}).catch(() => {
|
||||||
|
return Observable.of(this.navigateToWorplace())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToWorplace(): boolean {
|
||||||
|
this.router.navigate(['workplace']);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DomainService } from 'app/services/domain/domain.service';
|
||||||
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
|
import { ErrorModel } from 'app/models/modal-error';
|
||||||
|
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class BusinessAdminGuard implements CanActivate {
|
||||||
|
constructor(private taskanaEngineService: TaskanaEngineService, public router: Router) { }
|
||||||
|
|
||||||
|
canActivate() {
|
||||||
|
return this.taskanaEngineService.getUserInformation().map(userInfo => {
|
||||||
|
if (userInfo.roles.length === 0) {
|
||||||
|
return this.navigateToWorplace();
|
||||||
|
}
|
||||||
|
const adminRole = userInfo.roles.find(role => {
|
||||||
|
if (role === 'BUSINESS_ADMIN' || role === 'ADMIN' ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (adminRole) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.navigateToWorplace();
|
||||||
|
}).catch(() => {
|
||||||
|
|
||||||
|
return Observable.of(this.navigateToWorplace())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToWorplace(): boolean {
|
||||||
|
this.router.navigate(['workplace']);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { CanActivate, Router } from '@angular/router';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { DomainService } from 'app/services/domain/domain.service';
|
||||||
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
|
import { ErrorModel } from 'app/models/modal-error';
|
||||||
|
import { TaskanaEngineService } from 'app/services/taskana-engine/taskana-engine.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class MonitorGuard implements CanActivate {
|
||||||
|
constructor(private taskanaEngineService: TaskanaEngineService, public router: Router) { }
|
||||||
|
|
||||||
|
canActivate() {
|
||||||
|
return this.taskanaEngineService.getUserInformation().map(userInfo => {
|
||||||
|
if (userInfo.roles.length === 0) {
|
||||||
|
return this.navigateToWorplace();
|
||||||
|
}
|
||||||
|
const adminRole = userInfo.roles.find(role => {
|
||||||
|
if (role === 'MONITOR' || role === 'ADMIN' ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (adminRole) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.navigateToWorplace();
|
||||||
|
}).catch(() => {
|
||||||
|
|
||||||
|
return Observable.of(this.navigateToWorplace())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToWorplace(): boolean {
|
||||||
|
this.router.navigate(['workplace']);
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
export class UserInfoModel {
|
||||||
|
constructor(
|
||||||
|
public userId: string = undefined,
|
||||||
|
public groupIds: Array<string> = [],
|
||||||
|
public roles: Array<string> = []) { };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -7,29 +7,22 @@ import { WorkbasketCounter } from 'app/monitor/models/workbasket-counter';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RestConnectorService {
|
export class RestConnectorService {
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/hal+json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
constructor(private httpClient: HttpClient) {
|
constructor(private httpClient: HttpClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
getTaskStatistics(): Observable<State[]> {
|
getTaskStatistics(): Observable<State[]> {
|
||||||
return this.httpClient.get<Array<State>>(environment.taskanaRestUrl + '/v1/monitor/countByState?states=READY,CLAIMED,COMPLETED',
|
return this.httpClient.get<Array<State>>(environment.taskanaRestUrl + '/v1/monitor/countByState?states=READY,CLAIMED,COMPLETED')
|
||||||
this.httpOptions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
getWorkbasketStatistics(): Observable<WorkbasketCounter> {
|
getWorkbasketStatistics(): Observable<WorkbasketCounter> {
|
||||||
return this.httpClient.get<WorkbasketCounter>(environment.taskanaRestUrl
|
return this.httpClient.get<WorkbasketCounter>(environment.taskanaRestUrl
|
||||||
+ '/v1/monitor/taskcountByWorkbasketDaysAndState?daysInPast=5&states=READY,CLAIMED,COMPLETED',
|
+ '/v1/monitor/taskcountByWorkbasketDaysAndState?daysInPast=5&states=READY,CLAIMED,COMPLETED')
|
||||||
this.httpOptions)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getTaskStatusReport(): Observable<Object> {
|
getTaskStatusReport(): Observable<Object> {
|
||||||
return this.httpClient.get(environment.taskanaRestUrl + '/v1/monitor/taskStatusReport', this.httpOptions)
|
return this.httpClient.get(environment.taskanaRestUrl + '/v1/monitor/taskStatusReport')
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,6 @@ export class DomainService {
|
||||||
|
|
||||||
url = environment.taskanaRestUrl + '/v1/domains';
|
url = environment.taskanaRestUrl + '/v1/domains';
|
||||||
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
private domainSelectedValue;
|
private domainSelectedValue;
|
||||||
private domainSelected = new BehaviorSubject<string>('');
|
private domainSelected = new BehaviorSubject<string>('');
|
||||||
private domainSwitched = new Subject<string>();
|
private domainSwitched = new Subject<string>();
|
||||||
|
|
@ -33,7 +27,7 @@ export class DomainService {
|
||||||
// GET
|
// GET
|
||||||
getDomains(forceRefresh = false): Observable<string[]> {
|
getDomains(forceRefresh = false): Observable<string[]> {
|
||||||
if (!this.dataObs$.observers.length || forceRefresh) {
|
if (!this.dataObs$.observers.length || forceRefresh) {
|
||||||
this.httpClient.get<string[]>(this.url, this.httpOptions).subscribe(
|
this.httpClient.get<string[]>(this.url).subscribe(
|
||||||
domains => {
|
domains => {
|
||||||
this.dataObs$.next(domains);
|
this.dataObs$.next(domains);
|
||||||
if (!this.domainSelectedValue && domains && domains.length > 0) {
|
if (!this.domainSelectedValue && domains && domains.length > 0) {
|
||||||
|
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
import { TestBed, inject } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { PermissionService } from './permission.service';
|
|
||||||
|
|
||||||
describe('PermissionService', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
TestBed.configureTestingModule({
|
|
||||||
providers: [PermissionService]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should be created', inject([PermissionService], (service: PermissionService) => {
|
|
||||||
expect(service).toBeTruthy();
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
import { Injectable } from '@angular/core';
|
|
||||||
import { Observable } from 'rxjs/Observable';
|
|
||||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
|
||||||
|
|
||||||
@Injectable()
|
|
||||||
export class PermissionService {
|
|
||||||
|
|
||||||
private permission = new BehaviorSubject<boolean>(true);
|
|
||||||
|
|
||||||
|
|
||||||
setPermission(permission: boolean) {
|
|
||||||
this.permission.next(permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
hasPermission(): Observable<boolean> {
|
|
||||||
return this.permission.asObservable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,20 +2,23 @@ import { Observable } from 'rxjs/Observable';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { CanActivate } from '@angular/router';
|
import { CanActivate } from '@angular/router';
|
||||||
import { environment } from 'app/../environments/environment';
|
import { environment } from 'app/../environments/environment';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable, Inject } from '@angular/core';
|
||||||
import { TitlesService } from 'app/services/titles/titles.service';
|
import { TitlesService } from 'app/services/titles/titles.service';
|
||||||
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
|
import { CustomFieldsService } from 'app/services/custom-fields/custom-fields.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class StartupService {
|
export class StartupService {
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private httpClient: HttpClient,
|
private httpClient: HttpClient,
|
||||||
private titlesService: TitlesService,
|
private titlesService: TitlesService,
|
||||||
private customFieldsService: CustomFieldsService) { }
|
private customFieldsService: CustomFieldsService) { }
|
||||||
|
|
||||||
load(): Promise<any> {
|
load(): Promise<any> {
|
||||||
return this.loadEnvironment();
|
return this.loadEnvironment();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private loadEnvironment() {
|
private loadEnvironment() {
|
||||||
return this.httpClient.get<any>('environments/data-sources/environment-information.json').map(jsonFile => {
|
return this.httpClient.get<any>('environments/data-sources/environment-information.json').map(jsonFile => {
|
||||||
if (jsonFile) {
|
if (jsonFile) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
import { environment } from 'environments/environment';
|
||||||
|
import { UserInfoModel } from 'app/models/user-info';
|
||||||
|
import { ReplaySubject } from 'rxjs/ReplaySubject';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class TaskanaEngineService {
|
||||||
|
|
||||||
|
private dataObs$ = new ReplaySubject<UserInfoModel>(1);
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private httpClient: HttpClient
|
||||||
|
) { }
|
||||||
|
|
||||||
|
// GET
|
||||||
|
getUserInformation(forceRefresh = false): Observable<UserInfoModel> {
|
||||||
|
if (!this.dataObs$.observers.length || forceRefresh) {
|
||||||
|
this.httpClient.get<UserInfoModel>(`${environment.taskanaRestUrl}/v1/current-user-info`).subscribe(
|
||||||
|
data => this.dataObs$.next(data),
|
||||||
|
error => {
|
||||||
|
this.dataObs$.error(error);
|
||||||
|
this.dataObs$ = new ReplaySubject(1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.dataObs$;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
// This interface is optional, showing how you can add strong typings for custom globals.
|
||||||
|
// Just use "Window" as the type if you don't have custom global stuff
|
||||||
|
export interface IWindowService extends Window {
|
||||||
|
__custom_global_stuff: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWindow (): any {
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class WindowRefService {
|
||||||
|
get nativeWindow (): IWindowService {
|
||||||
|
return getWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,6 @@ import { HttpClientModule } from '@angular/common/http';
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpModule } from '@angular/http';
|
||||||
|
|
||||||
import { HttpClientInterceptor } from './http-client-interceptor.service';
|
import { HttpClientInterceptor } from './http-client-interceptor.service';
|
||||||
import { PermissionService } from 'app/services/permission/permission.service';
|
|
||||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
||||||
|
|
||||||
|
|
@ -11,7 +10,7 @@ describe('HttpExtensionService', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [HttpClientModule, HttpModule],
|
imports: [HttpClientModule, HttpModule],
|
||||||
providers: [HttpClientInterceptor, PermissionService, ErrorModalService, RequestInProgressService]
|
providers: [HttpClientInterceptor, ErrorModalService, RequestInProgressService]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse } from '@angular/common/http';
|
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import 'rxjs/add/operator/catch';
|
import 'rxjs/add/operator/catch';
|
||||||
import 'rxjs/add/observable/throw';
|
import 'rxjs/add/observable/throw';
|
||||||
|
|
@ -7,28 +7,31 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||||
|
|
||||||
import { ErrorModel } from 'app/models/modal-error';
|
import { ErrorModel } from 'app/models/modal-error';
|
||||||
|
|
||||||
import { PermissionService } from 'app/services/permission/permission.service';
|
|
||||||
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
import { ErrorModalService } from 'app/services/errorModal/error-modal.service';
|
||||||
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
import { RequestInProgressService } from 'app/services/requestInProgress/request-in-progress.service';
|
||||||
|
import { environment } from 'environments/environment';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class HttpClientInterceptor implements HttpInterceptor {
|
export class HttpClientInterceptor implements HttpInterceptor {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private permissionService: PermissionService,
|
|
||||||
private errorModalService: ErrorModalService,
|
private errorModalService: ErrorModalService,
|
||||||
private requestInProgressService: RequestInProgressService) {
|
private requestInProgressService: RequestInProgressService) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
req = req.clone({ headers: req.headers.set('Content-Type', 'application/hal+json') });
|
||||||
|
if (!environment.production) {
|
||||||
|
req = req.clone({ headers: req.headers.set('Authorization', 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x') });
|
||||||
|
}
|
||||||
return next.handle(req).do(event => {
|
return next.handle(req).do(event => {
|
||||||
this.permissionService.setPermission(true);
|
|
||||||
|
|
||||||
}, err => {
|
}, err => {
|
||||||
this.requestInProgressService.setRequestInProgress(false);
|
this.requestInProgressService.setRequestInProgress(false);
|
||||||
if (err instanceof HttpErrorResponse && (err.status === 401 || err.status === 403)) {
|
if (err instanceof HttpErrorResponse && (err.status === 401 || err.status === 403)) {
|
||||||
this.permissionService.setPermission(false)
|
this.errorModalService.triggerError(
|
||||||
|
new ErrorModel('You have no access to this resource ', err));
|
||||||
} else if (err instanceof HttpErrorResponse && (err.status === 404) && err.url.indexOf('environment-information.json')) {
|
} else if (err instanceof HttpErrorResponse && (err.status === 404) && err.url.indexOf('environment-information.json')) {
|
||||||
// ignore this error message
|
// ignore this error message
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||||
import { AlertModule } from 'ngx-bootstrap';
|
import { AlertModule } from 'ngx-bootstrap';
|
||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
|
|
@ -22,6 +22,7 @@ import { SelectWorkBasketPipe } from './pipes/selectedWorkbasket/seleted-workbas
|
||||||
import { SpreadNumberPipe } from './pipes/spreadNumber/spread-number';
|
import { SpreadNumberPipe } from './pipes/spreadNumber/spread-number';
|
||||||
import { OrderBy } from './pipes/orderBy/orderBy';
|
import { OrderBy } from './pipes/orderBy/orderBy';
|
||||||
import { MapToIterable } from './pipes/mapToIterable/mapToIterable';
|
import { MapToIterable } from './pipes/mapToIterable/mapToIterable';
|
||||||
|
import { HttpClientInterceptor } from './services/httpClientInterceptor/http-client-interceptor.service';
|
||||||
|
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
|
|
@ -51,7 +52,14 @@ const DECLARATIONS = [
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: DECLARATIONS,
|
declarations: DECLARATIONS,
|
||||||
imports: MODULES,
|
imports: MODULES,
|
||||||
exports: DECLARATIONS
|
exports: DECLARATIONS,
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: HttpClientInterceptor,
|
||||||
|
multi: true
|
||||||
|
}
|
||||||
|
]
|
||||||
})
|
})
|
||||||
export class SharedModule {
|
export class SharedModule {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpHeaders } from '@angular/common/http';
|
||||||
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
import { environment } from 'environments/environment';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CustomHttpClientInterceptor implements HttpInterceptor {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
|
||||||
|
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
if (!environment.production) {
|
||||||
|
req = req.clone({ headers: req.headers.set('Authorization', 'Basic YWRtaW46YWRtaW4=') });
|
||||||
|
}
|
||||||
|
return next.handle(req);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,35 +8,27 @@ import { environment } from 'app/../environments/environment';
|
||||||
export class TaskService {
|
export class TaskService {
|
||||||
url = environment.taskanaRestUrl + '/v1/tasks';
|
url = environment.taskanaRestUrl + '/v1/tasks';
|
||||||
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/hal+json',
|
|
||||||
'Authorization': 'Basic YWRtaW46YWRtaW4=',
|
|
||||||
'user': 'user_1_1'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient) {
|
constructor(private httpClient: HttpClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
findTaskWithWorkbaskets(basketKey: string): Observable<Task[]> {
|
findTaskWithWorkbaskets(basketKey: string): Observable<Task[]> {
|
||||||
return this.httpClient.get<Task[]>(this.url + '?workbasketId=' + basketKey, this.httpOptions);
|
return this.httpClient.get<Task[]>(this.url + '?workbasketId=' + basketKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTask(id: string): Observable<Task> {
|
getTask(id: string): Observable<Task> {
|
||||||
return this.httpClient.get<Task>(this.url + '/' + id, this.httpOptions);
|
return this.httpClient.get<Task>(this.url + '/' + id);
|
||||||
}
|
}
|
||||||
|
|
||||||
completeTask(id: string): Observable<Task> {
|
completeTask(id: string): Observable<Task> {
|
||||||
return this.httpClient.post<Task>(this.url + '/' + id + '/complete', '', this.httpOptions);
|
return this.httpClient.post<Task>(this.url + '/' + id + '/complete', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
claimTask(id: string): Observable<Task> {
|
claimTask(id: string): Observable<Task> {
|
||||||
return this.httpClient.post<Task>(this.url + '/' + id + '/claim', 'test', this.httpOptions);
|
return this.httpClient.post<Task>(this.url + '/' + id + '/claim', 'test');
|
||||||
}
|
}
|
||||||
|
|
||||||
transferTask(taskId: string, workbasketKey: string): Observable<Task> {
|
transferTask(taskId: string, workbasketKey: string): Observable<Task> {
|
||||||
return this.httpClient.post<Task>(this.url + '/' + taskId
|
return this.httpClient.post<Task>(this.url + '/' + taskId
|
||||||
+ '/transfer/' + workbasketKey, '', this.httpOptions);
|
+ '/transfer/' + workbasketKey, '');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,17 @@
|
||||||
import {Injectable} from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import {Workbasket} from 'app/models/workbasket';
|
import { Workbasket } from 'app/models/workbasket';
|
||||||
import {environment} from 'app/../environments/environment';
|
import { environment } from 'app/../environments/environment';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
import {HttpClient, HttpHeaders} from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkbasketService {
|
export class WorkbasketService {
|
||||||
url = environment.taskanaRestUrl + '/v1/workbaskets';
|
url = environment.taskanaRestUrl + '/v1/workbaskets';
|
||||||
|
|
||||||
httpOptions = {
|
|
||||||
headers: new HttpHeaders({
|
|
||||||
'Content-Type': 'application/hal+json',
|
|
||||||
'Authorization': 'Basic VEVBTUxFQURfMTpURUFNTEVBRF8x'
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(private httpClient: HttpClient) {
|
constructor(private httpClient: HttpClient) {
|
||||||
}
|
}
|
||||||
|
|
||||||
getAllWorkBaskets(): Observable<Workbasket[]> {
|
getAllWorkBaskets(): Observable<Workbasket[]> {
|
||||||
return this.httpClient.get<Workbasket[]>(this.url + '?required-permission=OPEN', this.httpOptions);
|
return this.httpClient.get<Workbasket[]>(this.url + '?required-permission=OPEN');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ import { CommonModule } from '@angular/common';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { Ng2AutoCompleteModule } from 'ng2-auto-complete';
|
import { Ng2AutoCompleteModule } from 'ng2-auto-complete';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||||
import { AngularSvgIconModule } from 'angular-svg-icon';
|
import { AngularSvgIconModule } from 'angular-svg-icon';
|
||||||
import { WorkplaceRoutingModule } from './workplace-routing.module';
|
import { WorkplaceRoutingModule } from './workplace-routing.module';
|
||||||
import { AlertModule } from 'ngx-bootstrap';
|
import { AlertModule } from 'ngx-bootstrap';
|
||||||
|
import { SharedModule } from 'app/shared/shared.module';
|
||||||
|
|
||||||
import { WorkplaceComponent } from './workplace.component';
|
import { WorkplaceComponent } from './workplace.component';
|
||||||
import { SelectorComponent } from './workbasket-selector/workbasket-selector.component';
|
import { SelectorComponent } from './workbasket-selector/workbasket-selector.component';
|
||||||
|
|
@ -19,6 +20,8 @@ import { OrderTasksByPipe } from './util/orderTasksBy.pipe';
|
||||||
import { DataService } from './services/data.service';
|
import { DataService } from './services/data.service';
|
||||||
import { TaskService } from './services/task.service';
|
import { TaskService } from './services/task.service';
|
||||||
import { WorkbasketService } from './services/workbasket.service';
|
import { WorkbasketService } from './services/workbasket.service';
|
||||||
|
import { CustomHttpClientInterceptor } from './services/custom-http-interceptor/custom-http-interceptor.service';
|
||||||
|
|
||||||
|
|
||||||
const MODULES = [
|
const MODULES = [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|
@ -27,7 +30,8 @@ const MODULES = [
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
AngularSvgIconModule,
|
AngularSvgIconModule,
|
||||||
WorkplaceRoutingModule,
|
WorkplaceRoutingModule,
|
||||||
AlertModule
|
AlertModule,
|
||||||
|
SharedModule
|
||||||
];
|
];
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
|
|
@ -46,7 +50,12 @@ const DECLARATIONS = [
|
||||||
providers: [
|
providers: [
|
||||||
DataService,
|
DataService,
|
||||||
TaskService,
|
TaskService,
|
||||||
WorkbasketService
|
WorkbasketService,
|
||||||
|
{
|
||||||
|
provide: HTTP_INTERCEPTORS,
|
||||||
|
useClass: CustomHttpClientInterceptor,
|
||||||
|
multi: true
|
||||||
|
},
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class WorkplaceModule {
|
export class WorkplaceModule {
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ $green: #246972;
|
||||||
$grey: grey;
|
$grey: grey;
|
||||||
$brown: #f0ad4e;
|
$brown: #f0ad4e;
|
||||||
$invalid: #a94442;
|
$invalid: #a94442;
|
||||||
|
$aquamarine: #22a39f;
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blue-green{
|
||||||
|
color: $blue-green;
|
||||||
|
& svg {
|
||||||
|
fill: $blue-green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.green {
|
.green {
|
||||||
color: $green;
|
color: $green;
|
||||||
& svg {
|
& svg {
|
||||||
|
|
@ -112,6 +119,13 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.aquamarine {
|
||||||
|
color: $aquamarine;
|
||||||
|
& svg {
|
||||||
|
fill: $aquamarine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
svg-icon.fa-fw > svg {
|
svg-icon.fa-fw > svg {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
width: 1.25em;
|
width: 1.25em;
|
||||||
|
|
@ -283,3 +297,4 @@ li.list-group-item:hover, {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue