Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Codecrew
/
Moya
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
30
Merge Requests
2
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 2b19d7ba
authored
Jul 17, 2018
by
Tuomas Riihimäki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
User preference fixes
1 parent
db4acc8b
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
334 additions
and
141 deletions
code/moya-beans-client/ejbModule/fi/codecrew/moya/beans/UserPropertyBeanLocal.java
code/moya-beans/ejbModule/fi/codecrew/moya/beans/UserBean.java
code/moya-beans/ejbModule/fi/codecrew/moya/beans/UserPropertyBean.java
code/moya-beans/ejbModule/fi/codecrew/moya/facade/EventUserFacade.java
code/moya-beans/ejbModule/fi/codecrew/moya/facade/EventUserpropertyFacade.java
code/moya-web/WebContent/resources/cditools/user/edit.xhtml
code/moya-web/src/main/java/fi/codecrew/moya/HostnameFilter.java
code/moya-web/src/main/java/fi/codecrew/moya/graphql/EntityGQLBuilder.java
code/moya-web/src/main/java/fi/codecrew/moya/graphql/GQLEntityContainer.java
code/moya-web/src/main/java/fi/codecrew/moya/graphql/GraphQLBuilder.java
code/moya-web/src/main/java/fi/codecrew/moya/graphql/MoyaGraphQLServlet.java
code/moya-web/src/main/java/fi/codecrew/moya/handler/SessionHandler.java
code/moya-web/src/main/java/fi/codecrew/moya/web/cdiview/user/UserAllergyView.java
code/moya-web/src/main/java/fi/codecrew/moya/web/cdiview/user/UserEventPropertyView.java
code/moya-web/src/main/java/fi/codecrew/moya/web/cdiview/user/UserView.java
code/moya-web/src/main/resources/fi/codecrew/moya/resources/i18n.properties
code/moya-web/src/main/resources/fi/codecrew/moya/resources/i18n_en.properties
code/moya-web/src/main/resources/fi/codecrew/moya/resources/i18n_fi.properties
code/moya-beans-client/ejbModule/fi/codecrew/moya/beans/UserPropertyBeanLocal.java
View file @
2b19d7b
...
@@ -13,4 +13,7 @@ public interface UserPropertyBeanLocal {
...
@@ -13,4 +13,7 @@ public interface UserPropertyBeanLocal {
List
<
EventUserproperty
>
getPropertiesForUser
(
EventUser
user
);
List
<
EventUserproperty
>
getPropertiesForUser
(
EventUser
user
);
List
<
UsersEventUserproperty
>
getUserPropertiesForUser
(
EventUser
user
);
List
<
UsersEventUserproperty
>
getUserPropertiesForUser
(
EventUser
user
);
UsersEventUserproperty
saveUserproperty
(
UsersEventUserproperty
object
);
}
}
code/moya-beans/ejbModule/fi/codecrew/moya/beans/UserBean.java
View file @
2b19d7b
...
@@ -29,12 +29,7 @@ import java.math.BigDecimal;
...
@@ -29,12 +29,7 @@ import java.math.BigDecimal;
import
java.security.MessageDigest
;
import
java.security.MessageDigest
;
import
java.security.NoSuchAlgorithmException
;
import
java.security.NoSuchAlgorithmException
;
import
java.text.MessageFormat
;
import
java.text.MessageFormat
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.Calendar
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Set
;
import
javax.annotation.security.DeclareRoles
;
import
javax.annotation.security.DeclareRoles
;
import
javax.annotation.security.PermitAll
;
import
javax.annotation.security.PermitAll
;
...
@@ -233,7 +228,9 @@ public class UserBean implements UserBeanLocal {
...
@@ -233,7 +228,9 @@ public class UserBean implements UserBeanLocal {
throw
new
EJBAccessException
(
"Not enough rights to find roles"
);
throw
new
EJBAccessException
(
"Not enough rights to find roles"
);
}
}
return
new
ArrayList
<
Role
>(
localFindUsersRoles
(
u
));
ArrayList
<
Role
>
ret
=
new
ArrayList
<>(
localFindUsersRoles
(
u
));
ret
.
sort
((
o1
,
o2
)
->
o1
.
getId
().
compareTo
(
o2
.
getId
()));
return
ret
;
}
}
...
...
code/moya-beans/ejbModule/fi/codecrew/moya/beans/UserPropertyBean.java
View file @
2b19d7b
...
@@ -45,14 +45,29 @@ public class UserPropertyBean implements UserPropertyBeanLocal {
...
@@ -45,14 +45,29 @@ public class UserPropertyBean implements UserPropertyBeanLocal {
}
}
@Override
@Override
public
List
<
EventUserproperty
>
getPropertiesForUser
(
EventUser
user
){
public
List
<
EventUserproperty
>
getPropertiesForUser
(
EventUser
user
)
{
return
eventPropertyFacade
.
findForUser
(
user
);
return
eventPropertyFacade
.
findForUser
(
user
);
}
}
@Override
@Override
public
List
<
UsersEventUserproperty
>
getUserPropertiesForUser
(
EventUser
user
){
public
List
<
UsersEventUserproperty
>
getUserPropertiesForUser
(
EventUser
user
)
{
return
userPropertyFacade
.
findForUser
(
user
);
return
userPropertyFacade
.
findForUser
(
user
);
}
}
@Override
public
UsersEventUserproperty
saveUserproperty
(
UsersEventUserproperty
prop
)
{
if
(
prop
==
null
)
{
return
null
;
}
if
(
prop
.
getId
()
==
null
)
{
userPropertyFacade
.
create
(
prop
);
}
else
{
prop
=
userPropertyFacade
.
merge
(
prop
);
}
return
prop
;
}
}
}
code/moya-beans/ejbModule/fi/codecrew/moya/facade/EventUserFacade.java
View file @
2b19d7b
...
@@ -199,7 +199,7 @@ public class EventUserFacade extends IntegerPkGenericFacade<EventUser> {
...
@@ -199,7 +199,7 @@ public class EventUserFacade extends IntegerPkGenericFacade<EventUser> {
listQ
.
setFirstResult
(
query
.
getPage
()
*
query
.
getPagesize
());
listQ
.
setFirstResult
(
query
.
getPage
()
*
query
.
getPagesize
());
listQ
.
setMaxResults
(
query
.
getPagesize
());
listQ
.
setMaxResults
(
query
.
getPagesize
());
}
}
return
new
SearchResult
<
EventUser
>(
listQ
.
getResultList
(),
countQ
.
getSingleResult
());
return
new
SearchResult
<>(
listQ
.
getResultList
(),
countQ
.
getSingleResult
());
}
}
...
...
code/moya-beans/ejbModule/fi/codecrew/moya/facade/EventUserpropertyFacade.java
View file @
2b19d7b
...
@@ -28,7 +28,9 @@ import javax.persistence.criteria.CriteriaBuilder;
...
@@ -28,7 +28,9 @@ import javax.persistence.criteria.CriteriaBuilder;
import
javax.persistence.criteria.CriteriaQuery
;
import
javax.persistence.criteria.CriteriaQuery
;
import
javax.persistence.criteria.Path
;
import
javax.persistence.criteria.Path
;
import
javax.persistence.criteria.Root
;
import
javax.persistence.criteria.Root
;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Set
;
@Stateless
@Stateless
@LocalBean
@LocalBean
...
@@ -45,11 +47,14 @@ public class EventUserpropertyFacade extends IntegerPkGenericFacade<EventUserpro
...
@@ -45,11 +47,14 @@ public class EventUserpropertyFacade extends IntegerPkGenericFacade<EventUserpro
CriteriaBuilder
cq
=
getEm
().
getCriteriaBuilder
();
CriteriaBuilder
cq
=
getEm
().
getCriteriaBuilder
();
CriteriaQuery
<
EventUserproperty
>
cb
=
cq
.
createQuery
(
EventUserproperty
.
class
);
CriteriaQuery
<
EventUserproperty
>
cb
=
cq
.
createQuery
(
EventUserproperty
.
class
);
Root
<
EventUserproperty
>
root
=
cb
.
from
(
EventUserproperty
.
class
);
Root
<
EventUserproperty
>
root
=
cb
.
from
(
EventUserproperty
.
class
);
Set
<
Role
>
roles
=
userbean
.
localFindUsersRoles
(
user
);
if
(
roles
==
null
||
roles
.
isEmpty
()){
return
Collections
.
emptyList
();
}
Path
<
Role
>
rolePath
=
root
.
get
(
EventUserproperty_
.
forRole
);
Path
<
Role
>
rolePath
=
root
.
get
(
EventUserproperty_
.
forRole
);
cb
.
where
(
cb
.
where
(
cq
.
equal
(
root
.
get
(
EventUserproperty_
.
event
),
user
.
getEvent
()),
cq
.
equal
(
root
.
get
(
EventUserproperty_
.
event
),
user
.
getEvent
()),
cq
.
or
(
cq
.
isNull
(
rolePath
),
rolePath
.
in
(
userbean
.
localFindUsersRoles
(
user
)
))
cq
.
or
(
cq
.
isNull
(
rolePath
),
rolePath
.
in
(
roles
))
);
);
return
getEm
().
createQuery
(
cb
).
getResultList
();
return
getEm
().
createQuery
(
cb
).
getResultList
();
...
...
code/moya-web/WebContent/resources/cditools/user/edit.xhtml
View file @
2b19d7b
...
@@ -157,18 +157,16 @@
...
@@ -157,18 +157,16 @@
</p:fieldset>
</p:fieldset>
</h:form>
</h:form>
<p:fieldset
legend=
"#{i18n['user.meta.box.title']}"
toggleable=
"true"
collapsed=
"true"
rendered=
"#{
not empty userView.meta
}"
>
<p:fieldset
legend=
"#{i18n['user.meta.box.title']}"
toggleable=
"true"
collapsed=
"true"
rendered=
"#{
userView.metaAvailable
}"
>
<div
id=
"usermetaview"
><pre><h:outputText
value=
"#{userView.prettyMeta}"
/></pre></div>
<div
id=
"usermetaview"
><pre><h:outputText
value=
"#{userView.prettyMeta}"
/></pre></div>
</p:fieldset>
</p:fieldset>
</p:panelGrid>
</p:panelGrid>
<p:fieldset
toggleable=
"true"
collapsed=
"true"
legend=
"#{i18n['user.eventproperties']}"
>
<p:fieldset
toggleable=
"true"
collapsed=
"true"
legend=
"#{i18n['user.eventproperties']}"
rendered=
"${!empty userEventPropertyView.properties}"
style=
"max-width: 800px;"
>
<h:form
id=
"eventpropertyview"
>
<h:form
id=
"eventpropertyview"
>
<p:growl
id=
"msgs"
showDetail=
"true"
/>
<p:growl
id=
"msgs"
showDetail=
"true"
/>
<p:dataTable
id=
"userpropertytable"
value=
"#{userEventPropertyView.properties}"
var=
"property"
editable=
"true
"
>
<p:dataTable
id=
"userpropertytable"
widgetVar=
"userpropertytable"
value=
"#{userEventPropertyView.properties}"
var=
"property"
editable=
"true"
rowIndexVar=
"rowIndex
"
>
<p:ajax
event=
"rowEdit"
listener=
"#{userEventPropertyView.onRowEdit}"
update=
"@form:msgs"
/>
<p:ajax
event=
"rowEdit"
listener=
"#{userEventPropertyView.onRowEdit}"
update=
"@form:msgs"
/>
<p:ajax
event=
"rowEditCancel"
listener=
"#{userEventPropertyView.onRowCancel}"
update=
"@form:msgs"
/>
<p:ajax
event=
"rowEditCancel"
listener=
"#{userEventPropertyView.onRowCancel}"
update=
"@form:msgs"
/>
...
@@ -180,11 +178,14 @@
...
@@ -180,11 +178,14 @@
</p:ajax-->
</p:ajax-->
<p:cellEditor>
<p:cellEditor>
<f:facet
name=
"output"
><h:outputText
value=
"#{property.textvalue}"
/></f:facet>
<f:facet
name=
"output"
><h:outputText
value=
"#{property.textvalue}"
/></f:facet>
<f:facet
name=
"input"
><p:inputText
value=
"#{property.textvalue}"
style=
"width:96%"
/></f:facet>
<f:facet
name=
"input"
><p:inputText
onkeydown=
"PF('userpropertytable').onKeyDown(event)"
onkeyup=
"PF('userpropertytable').onKeyUp(event, #{rowIndex})"
value=
"#{property.textvalue}"
style=
"width:96%"
/></f:facet>
</p:cellEditor>
</p:cellEditor>
</p:column>
</p:column>
<p:column
style=
"width:32px"
>
<p:column
style=
"width:32px"
>
<p:rowEditor/>
<p:rowEditor
/>
</p:column>
</p:column>
</p:dataTable>
</p:dataTable>
</h:form>
</h:form>
...
@@ -216,6 +217,40 @@
...
@@ -216,6 +217,40 @@
</h:form>
</h:form>
<script
type=
"text/javascript"
>
$
(
function
()
{
$
.
extend
(
PF
(
"userpropertytable"
),
{
onKeyDown
:
function
(
e
)
{
var
key
=
e
.
which
,
keyCode
=
$
.
ui
.
keyCode
;
if
((
key
===
keyCode
.
ENTER
||
key
===
keyCode
.
NUMPAD_ENTER
))
{
e
.
preventDefault
();
}
},
onKeyUp
:
function
(
e
,
rowIndex
)
{
var
key
=
e
.
which
,
keyCode
=
$
.
ui
.
keyCode
;
if
((
key
===
keyCode
.
ENTER
||
key
===
keyCode
.
NUMPAD_ENTER
))
{
this
.
tbody
.
find
(
'.ui-row-editor .ui-icon-check'
)
.
eq
(
rowIndex
)
.
click
();
}
if
(
key
===
keyCode
.
ESCAPE
)
{
this
.
tbody
.
find
(
'.ui-row-editor .ui-icon-close'
)
.
eq
(
rowIndex
)
.
click
();
}
}
});
});
</script>
</composite:implementation>
</composite:implementation>
</html>
</html>
code/moya-web/src/main/java/fi/codecrew/moya/HostnameFilter.java
View file @
2b19d7b
...
@@ -180,7 +180,7 @@ public class HostnameFilter implements Filter {
...
@@ -180,7 +180,7 @@ public class HostnameFilter implements Filter {
if
(
httpRequest
.
getUserPrincipal
()
==
null
)
{
if
(
httpRequest
.
getUserPrincipal
()
==
null
)
{
// Check if we are can login in with rest alternative methods ( appkey, basic auth, etc.. )
// Check if we are can login in with rest alternative methods ( appkey, basic auth, etc.. )
if
(
RestApplicationEntrypoint
.
REST_PATH
.
equals
(
httpRequest
.
getServletPath
())
if
(
RestApplicationEntrypoint
.
REST_PATH
.
equals
(
httpRequest
.
getServletPath
())
||
"/dydata"
.
equals
(
httpRequest
.
getServletPath
()))
{
||
"/dydata"
.
equals
(
httpRequest
.
getServletPath
())
||
"/graphql"
.
equals
(
httpRequest
.
getServletPath
())
)
{
authtype
=
AuthType
.
REST
;
authtype
=
AuthType
.
REST
;
...
...
code/moya-web/src/main/java/fi/codecrew/moya/graphql/EntityGQLBuilder.java
View file @
2b19d7b
...
@@ -10,16 +10,13 @@ import java.math.BigInteger;
...
@@ -10,16 +10,13 @@ import java.math.BigInteger;
import
java.time.LocalDate
;
import
java.time.LocalDate
;
import
java.time.LocalDateTime
;
import
java.time.LocalDateTime
;
import
java.time.OffsetDateTime
;
import
java.time.OffsetDateTime
;
import
java.util.ArrayList
;
import
java.util.*
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.List
;
import
static
graphql
.
Scalars
.*;
import
static
graphql
.
Scalars
.*;
import
static
graphql
.
schema
.
GraphQLFieldDefinition
.
newFieldDefinition
;
import
static
graphql
.
schema
.
GraphQLFieldDefinition
.
newFieldDefinition
;
import
static
graphql
.
schema
.
GraphQLObjectType
.
newObject
;
import
static
graphql
.
schema
.
GraphQLObjectType
.
newObject
;
public
class
EntityGQLBuilder
<
T
>
{
public
class
EntityGQLBuilder
<
T
>
implements
GQLEntityContainer
{
private
final
GraphQLObjectType
.
Builder
builder
;
private
final
GraphQLObjectType
.
Builder
builder
;
...
@@ -35,6 +32,12 @@ public class EntityGQLBuilder<T> {
...
@@ -35,6 +32,12 @@ public class EntityGQLBuilder<T> {
}
}
public
GraphQLFieldDefinition
.
Builder
addField
(
GraphQLOutputType
type
)
{
return
addField
()
.
type
(
type
)
.
name
(
type
.
getName
().
toLowerCase
());
}
public
GraphQLFieldDefinition
.
Builder
addField
()
{
public
GraphQLFieldDefinition
.
Builder
addField
()
{
if
(
builtObject
!=
null
)
{
if
(
builtObject
!=
null
)
{
throw
new
AlreadyBuiltException
(
"This method can not be called after 'build()'-function has been called"
);
throw
new
AlreadyBuiltException
(
"This method can not be called after 'build()'-function has been called"
);
...
@@ -79,9 +82,11 @@ public class EntityGQLBuilder<T> {
...
@@ -79,9 +82,11 @@ public class EntityGQLBuilder<T> {
}
}
private
GraphQLOutputType
typeForClass
(
Class
<?>
type
)
{
private
GraphQLOutputType
typeForClass
(
Class
<?>
type
)
{
if
(
Map
.
Entry
.
class
.
isAssignableFrom
(
type
))
{
return
parent
.
getMapEntryType
();
}
if
(
Boolean
.
class
.
isAssignableFrom
(
type
)
||
boolean
.
class
.
isAssignableFrom
(
type
))
{
if
(
Boolean
.
class
.
isAssignableFrom
(
type
)
||
boolean
.
class
.
isAssignableFrom
(
type
))
{
return
GraphQLBoolean
;
return
GraphQLBoolean
;
}
}
...
@@ -126,10 +131,10 @@ public class EntityGQLBuilder<T> {
...
@@ -126,10 +131,10 @@ public class EntityGQLBuilder<T> {
return
GraphQLUtils
.
GRAPHQL_DATE_TYPE
;
return
GraphQLUtils
.
GRAPHQL_DATE_TYPE
;
}
}
return
parent
.
typeFor
(
type
);
return
parent
.
typeFor
(
type
);
}
}
@Override
public
GraphQLObjectType
build
()
{
public
GraphQLObjectType
build
()
{
if
(
builtObject
==
null
)
{
if
(
builtObject
==
null
)
{
fields
.
forEach
(
f
->
builder
.
field
(
f
));
fields
.
forEach
(
f
->
builder
.
field
(
f
));
...
@@ -148,7 +153,9 @@ public class EntityGQLBuilder<T> {
...
@@ -148,7 +153,9 @@ public class EntityGQLBuilder<T> {
return
this
;
return
this
;
}
}
public
GraphQLType
getRef
()
{
public
GraphQLType
Reference
getRef
()
{
return
parent
.
typeFor
(
typeName
);
return
parent
.
typeFor
(
typeName
);
}
}
}
}
code/moya-web/src/main/java/fi/codecrew/moya/graphql/GQLEntityContainer.java
0 → 100644
View file @
2b19d7b
package
fi
.
codecrew
.
moya
.
graphql
;
import
graphql.schema.GraphQLObjectType
;
public
interface
GQLEntityContainer
{
GraphQLObjectType
build
();
}
code/moya-web/src/main/java/fi/codecrew/moya/graphql/GraphQLBuilder.java
View file @
2b19d7b
...
@@ -7,10 +7,13 @@ import org.slf4j.LoggerFactory;
...
@@ -7,10 +7,13 @@ import org.slf4j.LoggerFactory;
import
java.util.*
;
import
java.util.*
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
static
graphql
.
Scalars
.
GraphQLString
;
import
static
graphql
.
schema
.
GraphQLEnumType
.
newEnum
;
import
static
graphql
.
schema
.
GraphQLEnumType
.
newEnum
;
import
static
graphql
.
schema
.
GraphQLFieldDefinition
.
newFieldDefinition
;
import
static
graphql
.
schema
.
GraphQLObjectType
.
newObject
;
public
class
GraphQLBuilder
{
public
class
GraphQLBuilder
{
private
final
Map
<
String
,
EntityGQLBuilder
<?>
>
entities
=
new
HashMap
<>();
private
final
Map
<
String
,
GQLEntityContainer
>
entities
=
new
HashMap
<>();
private
final
Map
<
String
,
GraphQLEnumType
>
enums
=
new
HashMap
<>();
private
final
Map
<
String
,
GraphQLEnumType
>
enums
=
new
HashMap
<>();
private
final
Set
<
String
>
uncheckedTypes
=
new
HashSet
<>();
private
final
Set
<
String
>
uncheckedTypes
=
new
HashSet
<>();
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
GraphQLBuilder
.
class
);
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
GraphQLBuilder
.
class
);
...
@@ -25,6 +28,24 @@ public class GraphQLBuilder {
...
@@ -25,6 +28,24 @@ public class GraphQLBuilder {
return
ret
;
return
ret
;
}
}
public
GraphQLList
getMapEntryType
()
{
if
(!
entities
.
containsKey
(
"MapEntry"
))
{
entities
.
put
(
"MapEntry"
,
new
GQLEntityContainer
()
{
@Override
public
GraphQLObjectType
build
()
{
return
type
.
build
();
}
final
GraphQLObjectType
.
Builder
type
=
newObject
()
.
name
(
"MapEntry"
)
.
field
(
newFieldDefinition
().
name
(
"key"
).
type
(
GraphQLString
))
.
field
(
newFieldDefinition
().
name
(
"value"
).
type
(
GraphQLString
));
}
);
}
return
GraphQLList
.
list
(
typeFor
(
"MapEntry"
));
}
public
Set
<
GraphQLType
>
getTypes
()
{
public
Set
<
GraphQLType
>
getTypes
()
{
Set
<
GraphQLType
>
ret
=
new
HashSet
<>(
enums
.
values
());
Set
<
GraphQLType
>
ret
=
new
HashSet
<>(
enums
.
values
());
List
<
GraphQLObjectType
>
retEnt
=
entities
.
values
().
stream
().
map
(
v
->
v
.
build
()).
collect
(
Collectors
.
toList
());
List
<
GraphQLObjectType
>
retEnt
=
entities
.
values
().
stream
().
map
(
v
->
v
.
build
()).
collect
(
Collectors
.
toList
());
...
@@ -38,7 +59,7 @@ public class GraphQLBuilder {
...
@@ -38,7 +59,7 @@ public class GraphQLBuilder {
public
GraphQLTypeReference
typeFor
(
String
typeName
)
{
public
GraphQLTypeReference
typeFor
(
String
typeName
)
{
logger
.
warn
(
"Adding typeFor: {}"
,
typeName
);
logger
.
warn
(
"Adding typeFor: {}"
,
typeName
);
if
(!
entities
.
containsKey
(
typeName
)
&&
!
enums
.
containsKey
(
typeName
))
{
if
(!
entities
.
containsKey
(
typeName
)
&&
!
enums
.
containsKey
(
typeName
))
{
logger
.
warn
(
"Adding unknown type: this might be an error!"
+
typeName
,
new
RuntimeException
().
fillInStackTrace
());
logger
.
warn
(
"Adding unknown type: this might be an error!"
+
typeName
,
new
RuntimeException
().
fillInStackTrace
());
uncheckedTypes
.
add
(
typeName
);
uncheckedTypes
.
add
(
typeName
);
}
}
...
...
code/moya-web/src/main/java/fi/codecrew/moya/graphql/MoyaGraphQLServlet.java
View file @
2b19d7b
...
@@ -3,6 +3,7 @@ package fi.codecrew.moya.graphql;
...
@@ -3,6 +3,7 @@ package fi.codecrew.moya.graphql;
import
com.google.gson.Gson
;
import
com.google.gson.Gson
;
import
fi.codecrew.moya.beans.*
;
import
fi.codecrew.moya.beans.*
;
import
fi.codecrew.moya.entitysearch.UserSearchQuery
;
import
fi.codecrew.moya.entitysearch.UserSearchQuery
;
import
fi.codecrew.moya.enums.apps.UserPermission
;
import
fi.codecrew.moya.graphql.util.JSONPropertyDataFetcher
;
import
fi.codecrew.moya.graphql.util.JSONPropertyDataFetcher
;
import
fi.codecrew.moya.graphql.util.PropertyFetchWrapper
;
import
fi.codecrew.moya.graphql.util.PropertyFetchWrapper
;
import
fi.codecrew.moya.model.*
;
import
fi.codecrew.moya.model.*
;
...
@@ -15,6 +16,11 @@ import org.slf4j.Logger;
...
@@ -15,6 +16,11 @@ import org.slf4j.Logger;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
javax.ejb.EJB
;
import
javax.ejb.EJB
;
import
javax.json.Json
;
import
javax.json.JsonObject
;
import
javax.json.JsonWriter
;
import
javax.json.JsonWriterFactory
;
import
javax.json.stream.JsonGenerator
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletConfig
;
import
javax.servlet.ServletException
;
import
javax.servlet.ServletException
;
import
javax.servlet.annotation.WebServlet
;
import
javax.servlet.annotation.WebServlet
;
...
@@ -23,15 +29,15 @@ import javax.servlet.http.HttpServletRequest;
...
@@ -23,15 +29,15 @@ import javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.PrintWriter
;
import
java.io.PrintWriter
;
import
java.util.ArrayList
;
import
java.io.StringWriter
;
import
java.util.Collections
;
import
java.util.*
;
import
java.util.List
;
import
java.util.stream.Collector
;
import
java.util.Map
;
import
java.util.stream.Collectors
;
import
java.util.stream.Collectors
;
import
static
graphql
.
Scalars
.*;
import
static
graphql
.
Scalars
.*;
import
static
graphql
.
schema
.
GraphQLArgument
.
newArgument
;
import
static
graphql
.
schema
.
GraphQLArgument
.
newArgument
;
import
static
graphql
.
schema
.
GraphQLFieldDefinition
.
newFieldDefinition
;
import
static
graphql
.
schema
.
GraphQLFieldDefinition
.
newFieldDefinition
;
import
static
java
.
util
.
stream
.
Collectors
.
toList
;
@WebServlet
(
name
=
"MoyaGraphQLServlet"
,
urlPatterns
=
{
"/graphql/*"
})
@WebServlet
(
name
=
"MoyaGraphQLServlet"
,
urlPatterns
=
{
"/graphql/*"
})
public
class
MoyaGraphQLServlet
extends
HttpServlet
{
public
class
MoyaGraphQLServlet
extends
HttpServlet
{
...
@@ -60,6 +66,9 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -60,6 +66,9 @@ public class MoyaGraphQLServlet extends HttpServlet {
private
ProductBeanLocal
productbean
;
private
ProductBeanLocal
productbean
;
@EJB
@EJB
private
VotingBeanLocal
votebean
;
private
VotingBeanLocal
votebean
;
@EJB
private
UserPropertyBeanLocal
eventUserPropertyBean
;
private
static
final
Comparator
<?
super
GenericEntity
>
ENTITY_ID_SORTER
=
(
Comparator
<
GenericEntity
>)
(
o1
,
o2
)
->
o1
.
getId
().
compareTo
(
o2
.
getId
().
compareTo
());
@Override
@Override
public
void
init
(
ServletConfig
config
)
throws
ServletException
{
public
void
init
(
ServletConfig
config
)
throws
ServletException
{
...
@@ -78,6 +87,17 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -78,6 +87,17 @@ public class MoyaGraphQLServlet extends HttpServlet {
private
void
doQuery
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
{
private
void
doQuery
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
IOException
{
// For now, allow graphql only for VIEW_ALL users...
// After a bit more permission and error checking, allow all users to use this..
if
(!
permbean
.
hasPermission
(
UserPermission
.
VIEW_ALL
))
{
response
.
setStatus
(
HttpServletResponse
.
SC_FORBIDDEN
);
PrintWriter
writer
=
response
.
getWriter
();
writer
.
write
(
"Insufficient permissions"
);
writer
.
close
();
;
return
;
}
logger
.
warn
(
"Graphql pathinfo: {}, uri: {}, url: {}"
,
request
.
getPathInfo
(),
request
.
getRequestURI
(),
request
.
getRequestURL
());
logger
.
warn
(
"Graphql pathinfo: {}, uri: {}, url: {}"
,
request
.
getPathInfo
(),
request
.
getRequestURI
(),
request
.
getRequestURL
());
if
(
request
.
getPathInfo
()
!=
null
)
{
if
(
request
.
getPathInfo
()
!=
null
)
{
if
(
request
.
getPathInfo
().
equals
(
"/schema"
))
{
if
(
request
.
getPathInfo
().
equals
(
"/schema"
))
{
...
@@ -179,12 +199,48 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -179,12 +199,48 @@ public class MoyaGraphQLServlet extends HttpServlet {
GraphQLBuilder
builder
=
new
GraphQLBuilder
();
GraphQLBuilder
builder
=
new
GraphQLBuilder
();
{
{
EntityGQLBuilder
<
JsonObject
>
b
=
builder
.
createEntity
(
JsonObject
.
class
);
b
.
addField
().
type
(
GraphQLString
).
name
(
"asJson"
).
dataFetcher
(
environment
->
{
JsonObject
obj
=
environment
.
getSource
();
if
(
obj
==
null
)
{
return
null
;
}
StringWriter
stringWriter
=
new
StringWriter
();
Map
<
String
,
Boolean
>
config
=
new
HashMap
<
String
,
Boolean
>();
config
.
put
(
JsonGenerator
.
PRETTY_PRINTING
,
true
);
JsonWriterFactory
writerFactory
=
Json
.
createWriterFactory
(
config
);
JsonWriter
jsonWriter
=
writerFactory
.
createWriter
(
stringWriter
);
jsonWriter
.
write
(
obj
);
jsonWriter
.
close
();
return
stringWriter
.
toString
();
}).
description
(
"Returns the object as a string."
);
b
.
addField
(
Map
.
Entry
.
class
)
.
argument
(
newArgument
().
name
(
"keys"
).
defaultValue
(
Collections
.
emptyMap
()).
type
(
GraphQLList
.
list
(
GraphQLString
)))
.
name
(
"path"
)
.
description
(
"Returngs values from given keys as key, value pairs"
)
.
dataFetcher
(
environment
->
{
Map
<
String
,
String
>
ret
=
new
HashMap
<>();
final
JsonObject
jsonObj
=
environment
.
getSource
();
((
List
<
String
>)
environment
.
getArgument
(
"keys"
)).
forEach
(
key
->
{
if
(
jsonObj
.
containsKey
(
key
))
ret
.
put
(
key
,
jsonObj
.
getString
(
key
));
});
return
ret
.
entrySet
();
});
}
{
EntityGQLBuilder
<
Role
>
b
=
builder
.
createEntity
(
Role
.
class
);
EntityGQLBuilder
<
Role
>
b
=
builder
.
createEntity
(
Role
.
class
);
b
.
addField
(
Role_
.
id
);
b
.
addField
(
Role_
.
id
);
b
.
addField
(
Role_
.
name
);
b
.
addField
(
Role_
.
name
);
b
.
addField
(
Role_
.
parents
);
b
.
addField
(
Role_
.
parents
);
b
.
addField
(
Role_
.
children
);
b
.
addField
(
Role_
.
children
);
b
.
addField
(
Place_
.
meta
);
}
}
...
@@ -199,6 +255,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -199,6 +255,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
EventMap_
.
active
);
b
.
addField
(
EventMap_
.
active
);
b
.
addField
(
EventMap_
.
mimeType
);
b
.
addField
(
EventMap_
.
mimeType
);
b
.
addField
(
EventMap_
.
mapData
);
b
.
addField
(
EventMap_
.
mapData
);
b
.
addField
(
EventMap_
.
meta
);
}
}
{
{
...
@@ -217,6 +274,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -217,6 +274,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
Place_
.
providesRole
);
b
.
addField
(
Place_
.
providesRole
);
b
.
addField
(
Place_
.
product
);
b
.
addField
(
Place_
.
product
);
b
.
addField
(
Place_
.
currentUser
);
b
.
addField
(
Place_
.
currentUser
);
b
.
addField
(
Place_
.
meta
);
}
}
{
{
...
@@ -226,10 +284,33 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -226,10 +284,33 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
EventUser_
.
event
).
type
(
builder
.
typeFor
(
SIMPLE_EVENT_TYPE_NAME
));
b
.
addField
(
EventUser_
.
event
).
type
(
builder
.
typeFor
(
SIMPLE_EVENT_TYPE_NAME
));
b
.
addField
(
EventUser_
.
eventuserCreated
);
b
.
addField
(
EventUser_
.
eventuserCreated
);
b
.
addField
(
EventUser_
.
id
);
b
.
addField
(
EventUser_
.
id
);
b
.
addListField
(
Role
.
class
).
dataFetcher
(
environment
->
userbean
.
findUsersRoles
(
environment
.
getSource
()));
b
.
addListField
(
Role
.
class
).
dataFetcher
(
environment
->
{
userbean
.
findUsersRoles
(
environment
.
getSource
()));
b
.
addListField
(
UsersEventUserproperty
.
class
).
dataFetcher
(
environment
->
eventUserPropertyBean
.
getUserPropertiesForUser
(
environment
.
getSource
()).
stream
().
sorted
(
ENTITY_ID_SORTER
).
collect
(
toList
());
b
.
addField
(
EventUser_
.
currentPlaces
);
b
.
addField
(
EventUser_
.
currentPlaces
);
}
}
{
EntityGQLBuilder
<
UsersEventUserproperty
>
b
=
builder
.
createEntity
(
UsersEventUserproperty
.
class
);
b
.
addField
(
UsersEventUserproperty_
.
id
);
b
.
addField
(
UsersEventUserproperty_
.
textvalue
);
b
.
addField
(
UsersEventUserproperty_
.
decimalValue
);
b
.
addField
(
UsersEventUserproperty_
.
integerValue
);
b
.
addField
(
UsersEventUserproperty_
.
dataValue
);
b
.
addField
(
UsersEventUserproperty_
.
user
);
b
.
addField
().
name
(
"name"
).
type
(
GraphQLString
).
dataFetcher
(
environment
->
((
UsersEventUserproperty
)
environment
.
getSource
()).
getProperty
().
getName
().
getDefaultValue
()).
description
(
"Shorthand for {property { name { defaultValue }}}"
);
b
.
addField
(
UsersEventUserproperty_
.
property
);
b
.
addField
(
UsersEventUserproperty_
.
meta
);
}
{
EntityGQLBuilder
<
EventUserproperty
>
b
=
builder
.
createEntity
(
EventUserproperty
.
class
);
b
.
addField
(
EventUserproperty_
.
id
);
b
.
addField
(
EventUserproperty_
.
name
);
b
.
addField
(
EventUserproperty_
.
forRole
);
b
.
addField
(
EventUserproperty_
.
description
);
b
.
addField
(
EventUserproperty_
.
type
);
b
.
addField
(
EventUserproperty_
.
meta
);
}
{
{
EntityGQLBuilder
<
User
>
b
=
builder
.
createEntity
(
User
.
class
);
EntityGQLBuilder
<
User
>
b
=
builder
.
createEntity
(
User
.
class
);
...
@@ -246,7 +327,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -246,7 +327,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
User_
.
town
);
b
.
addField
(
User_
.
town
);
b
.
addField
(
User_
.
phone
);
b
.
addField
(
User_
.
phone
);
b
.
addField
(
User_
.
gender
);
b
.
addField
(
User_
.
gender
);
b
.
addField
().
name
(
"tshirtSize"
).
type
(
GraphQLString
).
dataFetcher
(
new
PropertyFetchWrapper
(
"user"
,
new
JSONPropertyDataFetcher
(
"meta"
,
"shirtSize"
)));
b
.
addField
(
User_
.
meta
);
b
.
addField
().
name
(
"shirtSize"
).
type
(
GraphQLString
).
dataFetcher
(
new
JSONPropertyDataFetcher
(
"meta"
,
"shirtSize"
));
b
.
addField
().
name
(
"allergiesFreetext"
).
type
(
GraphQLString
).
dataFetcher
(
new
JSONPropertyDataFetcher
(
"meta"
,
"allergies"
));
b
.
addField
().
name
(
"allergiesFreetext"
).
type
(
GraphQLString
).
dataFetcher
(
new
JSONPropertyDataFetcher
(
"meta"
,
"allergies"
));
b
.
addListField
(
UsersAllergy
.
class
)
b
.
addListField
(
UsersAllergy
.
class
)
.
name
(
"allergies"
)
.
name
(
"allergies"
)
...
@@ -260,13 +342,13 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -260,13 +342,13 @@ public class MoyaGraphQLServlet extends HttpServlet {
logger
.
warn
(
"Got allergies for user {}"
,
allergies
);
logger
.
warn
(
"Got allergies for user {}"
,
allergies
);
if
(
environment
.
getArgument
(
"onlySelected"
))
{
if
(
environment
.
getArgument
(
"onlySelected"
))
{
logger
.
warn
(
"Filtering allergies"
);
logger
.
warn
(
"Filtering allergies"
);
return
allergies
.
stream
().
filter
(
a
->
a
.
isSelected
()).
collect
(
Collectors
.
toList
());
return
allergies
.
stream
().
sorted
(
ENTITY_ID_SORTER
).
filter
(
a
->
a
.
isSelected
()).
collect
(
toList
());
}
}
return
allergies
;
return
allergies
;
});
});
b
.
addListField
(
EventUser
.
class
)
b
.
addListField
(
EventUser
.
class
)
.
dataFetcher
(
environment
->
userbean
.
findAllEventusers
(
environment
.
getSource
()))
.
dataFetcher
(
environment
->
userbean
.
findAllEventusers
(
environment
.
getSource
())
.
stream
().
sorted
(
ENTITY_ID_SORTER
).
collect
(
toList
())
)
.
description
(
"Only users themselves can fetch eventusers for other events. If another user tries to fetch this data, an exception will be thrown"
);
.
description
(
"Only users themselves can fetch eventusers for other events. If another user tries to fetch this data, an exception will be thrown"
);
}
}
...
@@ -316,6 +398,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -316,6 +398,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
PlaceSlot_
.
description
);
b
.
addField
(
PlaceSlot_
.
description
);
b
.
addField
(
PlaceSlot_
.
used
);
b
.
addField
(
PlaceSlot_
.
used
);
b
.
addField
(
PlaceSlot_
.
created
);
b
.
addField
(
PlaceSlot_
.
created
);
b
.
addField
(
PlaceSlot_
.
meta
);
}
}
...
@@ -332,6 +416,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -332,6 +416,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
Bill_
.
addr4
);
b
.
addField
(
Bill_
.
addr4
);
b
.
addField
(
Bill_
.
addr5
);
b
.
addField
(
Bill_
.
addr5
);
b
.
addField
(
Bill_
.
user
);
b
.
addField
(
Bill_
.
user
);
b
.
addField
(
Bill_
.
meta
);
}
}
{
{
...
@@ -347,6 +432,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -347,6 +432,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
Product_
.
discounts
);
b
.
addField
(
Product_
.
discounts
);
b
.
addField
(
Product_
.
unitName
);
b
.
addField
(
Product_
.
unitName
);
b
.
addField
(
Product_
.
productFlags
);
b
.
addField
(
Product_
.
productFlags
);
b
.
addField
(
Product_
.
meta
);
}
}
{
{
EntityGQLBuilder
<
Discount
>
b
=
builder
.
createEntity
(
Discount
.
class
);
EntityGQLBuilder
<
Discount
>
b
=
builder
.
createEntity
(
Discount
.
class
);
...
@@ -365,6 +452,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -365,6 +452,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
Discount_
.
validTo
);
b
.
addField
(
Discount_
.
validTo
);
b
.
addField
(
Discount_
.
products
);
b
.
addField
(
Discount_
.
products
);
b
.
addField
(
Discount_
.
shortdesc
);
b
.
addField
(
Discount_
.
shortdesc
);
b
.
addField
(
Discount_
.
meta
);
}
}
{
{
EntityGQLBuilder
<
LanEvent
>
b
=
builder
.
createEntity
(
SIMPLE_EVENT_TYPE_NAME
);
EntityGQLBuilder
<
LanEvent
>
b
=
builder
.
createEntity
(
SIMPLE_EVENT_TYPE_NAME
);
...
@@ -374,7 +463,9 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -374,7 +463,9 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
LanEvent_
.
startTime
);
b
.
addField
(
LanEvent_
.
startTime
);
b
.
addField
(
LanEvent_
.
endTime
);
b
.
addField
(
LanEvent_
.
endTime
);
b
.
addField
(
LanEvent_
.
ticketSalesBegin
);
b
.
addField
(
LanEvent_
.
ticketSalesBegin
);
b
.
addField
(
LanEvent_
.
domains
).
type
(
GraphQLList
.
list
(
GraphQLString
)).
dataFetcher
(
environment
->
((
LanEvent
)
environment
.
getSource
()).
getDomains
().
stream
().
map
(
d
->
d
.
getDomain
()).
collect
(
Collectors
.
toList
()));
b
.
addField
(
LanEvent_
.
domains
).
type
(
GraphQLList
.
list
(
GraphQLString
)).
dataFetcher
(
environment
->
((
LanEvent
)
environment
.
getSource
()).
getDomains
().
stream
().
sorted
(
ENTITY_ID_SORTER
).
map
(
d
->
d
.
getDomain
()).
collect
(
toList
()));
b
.
addField
(
LanEvent_
.
meta
);
}
}
{
{
...
@@ -393,6 +484,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -393,6 +484,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
Compo_
.
maxParticipantCount
);
b
.
addField
(
Compo_
.
maxParticipantCount
);
b
.
addField
(
Compo_
.
holdVoting
);
b
.
addField
(
Compo_
.
holdVoting
);
b
.
addField
(
Compo_
.
compoEntries
);
b
.
addField
(
Compo_
.
compoEntries
);
b
.
addField
(
Compo_
.
meta
);
}
}
{
{
...
@@ -407,6 +500,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -407,6 +500,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
CompoEntry_
.
sort
);
b
.
addField
(
CompoEntry_
.
sort
);
b
.
addField
(
CompoEntry_
.
compo
);
b
.
addField
(
CompoEntry_
.
compo
);
b
.
addField
(
CompoEntry_
.
currentFile
);
b
.
addField
(
CompoEntry_
.
currentFile
);
b
.
addField
(
CompoEntry_
.
meta
);
}
}
...
@@ -421,6 +516,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -421,6 +516,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
CompoEntryFile_
.
fileData
);
b
.
addField
(
CompoEntryFile_
.
fileData
);
b
.
addField
(
CompoEntryFile_
.
entry
);
b
.
addField
(
CompoEntryFile_
.
entry
);
b
.
addField
(
CompoEntryFile_
.
hash
).
description
(
"SHA1 hash of the file data"
);
b
.
addField
(
CompoEntryFile_
.
hash
).
description
(
"SHA1 hash of the file data"
);
b
.
addField
(
CompoEntryFile_
.
meta
);
}
}
{
{
...
@@ -430,6 +527,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -430,6 +527,8 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
LanEventDomain_
.
event
);
b
.
addField
(
LanEventDomain_
.
event
);
b
.
addField
(
LanEventDomain_
.
description
);
b
.
addField
(
LanEventDomain_
.
description
);
b
.
addField
(
LanEventDomain_
.
overridePriority
);
b
.
addField
(
LanEventDomain_
.
overridePriority
);
b
.
addField
(
LanEventDomain_
.
meta
);
}
}
/**
/**
...
@@ -447,12 +546,14 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -447,12 +546,14 @@ public class MoyaGraphQLServlet extends HttpServlet {
b
.
addField
(
LanEvent_
.
endTime
);
b
.
addField
(
LanEvent_
.
endTime
);
b
.
addField
(
LanEvent_
.
ticketSalesBegin
);
b
.
addField
(
LanEvent_
.
ticketSalesBegin
);
b
.
addField
(
LanEvent_
.
domains
);
b
.
addField
(
LanEvent_
.
domains
);
b
.
addField
(
LanEvent_
.
meta
);
b
.
addListField
(
EventMap
.
class
).
dataFetcher
(
environment
->
placebean
.
getMaps
());
b
.
addListField
(
EventMap
.
class
).
dataFetcher
(
environment
->
placebean
.
getMaps
()
.
stream
().
sorted
(
ENTITY_ID_SORTER
).
collect
(
toList
()
);
b
.
addListField
(
Role
.
class
).
dataFetcher
(
environment
->
rolebean
.
listRoles
());
b
.
addListField
(
Role
.
class
).
dataFetcher
(
environment
->
rolebean
.
listRoles
()
.
stream
().
sorted
(
ENTITY_ID_SORTER
).
collect
(
toList
()
);
b
.
addListField
(
Product
.
class
).
dataFetcher
(
environment
->
productbean
.
findProductsForEvent
());
b
.
addListField
(
Product
.
class
).
dataFetcher
(
environment
->
productbean
.
findProductsForEvent
()
.
stream
().
sorted
(
ENTITY_ID_SORTER
).
collect
(
toList
()
);
b
.
addListField
(
Compo
.
class
).
dataFetcher
(
environment
->
votebean
.
getCompoList
(
true
));
b
.
addListField
(
Compo
.
class
).
dataFetcher
(
environment
->
votebean
.
getCompoList
(
true
)
.
stream
().
sorted
(
ENTITY_ID_SORTER
).
collect
(
toList
()
);
b
.
addField
(
LanEvent_
.
id
);
b
.
addField
(
LanEvent_
.
id
);
}
}
...
@@ -529,7 +630,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
...
@@ -529,7 +630,7 @@ public class MoyaGraphQLServlet extends HttpServlet {
List
<
Integer
>
roleArgument
=
environment
.
getArgument
(
"roles"
);
List
<
Integer
>
roleArgument
=
environment
.
getArgument
(
"roles"
);
if
(
roleArgument
!=
null
&&
!
roleArgument
.
isEmpty
())
{
if
(
roleArgument
!=
null
&&
!
roleArgument
.
isEmpty
())
{
query
.
setFilterRoles
(
roleArgument
.
stream
().
map
(
id
->
rolebean
.
find
(
id
)).
collect
(
Collectors
.
toList
()));
query
.
setFilterRoles
(
roleArgument
.
stream
().
map
(
id
->
rolebean
.
find
(
id
)).
filter
(
x
->
x
!=
null
).
collect
(
toList
()));
}
}
SearchResult
<
EventUser
>
ret
=
userbean
.
getThisEventsUsers
(
query
);
SearchResult
<
EventUser
>
ret
=
userbean
.
getThisEventsUsers
(
query
);
...
...
code/moya-web/src/main/java/fi/codecrew/moya/handler/SessionHandler.java
View file @
2b19d7b
/*
/*
* Copyright Codecrew Ry
* Copyright Codecrew Ry
*
*
* All rights reserved.
* All rights reserved.
*
*
* This license applies to any software containing a notice placed by the
* This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software.
* copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software.
* This license covers modification, distribution and use of the Software.
*
*
* Any distribution and use in source and binary forms, with or without
* Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the
* modification is not permitted without explicit written permission from the
* copyright owner.
* copyright owner.
*
*
* A non-exclusive royalty-free right is granted to the copyright owner of the
* A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in
* Software to use, modify and distribute all modifications to the Software in
* future versions of the Software.
* future versions of the Software.
*
*
*/
*/
/*
/*
...
@@ -47,7 +47,6 @@ import fi.codecrew.moya.model.LanEventProperty;
...
@@ -47,7 +47,6 @@ import fi.codecrew.moya.model.LanEventProperty;
import
fi.codecrew.moya.model.LanEventPropertyKey
;
import
fi.codecrew.moya.model.LanEventPropertyKey
;
/**
/**
*
* @author tuukka
* @author tuukka
*/
*/
@Named
()
@Named
()
...
@@ -85,15 +84,15 @@ public class SessionHandler {
...
@@ -85,15 +84,15 @@ public class SessionHandler {
retStr
=
ret
.
toLanguageTag
();
retStr
=
ret
.
toLanguageTag
();
}
}
if
(
retStr
.
trim
().
equals
(
""
))
if
(
retStr
.
trim
().
equals
(
""
))
retStr
=
"fi_FI"
;
retStr
=
"fi_FI"
;
return
retStr
;
return
retStr
;
}
}
public
String
getTheme
()
{
public
String
getTheme
()
{
if
(
theme
==
null
)
{
if
(
theme
==
null
)
{
theme
=
eventbean
.
getCurrentEvent
().
getTheme
();
theme
=
eventbean
.
getCurrentEvent
().
getTheme
();
}
}
if
(
theme
==
null
||
theme
.
trim
().
isEmpty
())
{
if
(
theme
==
null
||
theme
.
trim
().
isEmpty
())
{
...
@@ -102,16 +101,16 @@ public class SessionHandler {
...
@@ -102,16 +101,16 @@ public class SessionHandler {
}
}
return
theme
;
return
theme
;
}
}
public
void
setTheme
(
String
theme
)
{
public
void
setTheme
(
String
theme
)
{
logger
.
debug
(
"Setting theme to: "
+
theme
);
logger
.
debug
(
"Setting theme to: "
+
theme
);
}
}
public
String
getFullscreen
()
{
public
String
getFullscreen
()
{
template
=
"fullprimelayout"
;
template
=
"fullprimelayout"
;
return
getTemplate
();
return
getTemplate
();
}
}
public
String
getInfoscreen
()
{
public
String
getInfoscreen
()
{
template
=
"infoview"
;
template
=
"infoview"
;
return
template
;
return
template
;
...
@@ -122,12 +121,11 @@ public class SessionHandler {
...
@@ -122,12 +121,11 @@ public class SessionHandler {
return
template
;
return
template
;
}
}
public
String
getTemplateName
()
public
String
getTemplateName
()
{
{
if
(
template
==
null
)
{
if
(
template
==
null
)
{
template
=
eventbean
.
getPropertyString
(
LanEventPropertyKey
.
EVENT_LAYOUT
);
template
=
eventbean
.
getPropertyString
(
LanEventPropertyKey
.
EVENT_LAYOUT
);
}
}
if
(
template
!=
null
)
{
if
(
template
!=
null
)
{
template
=
template
.
trim
().
toLowerCase
();
template
=
template
.
trim
().
toLowerCase
();
}
}
...
@@ -137,8 +135,7 @@ public class SessionHandler {
...
@@ -137,8 +135,7 @@ public class SessionHandler {
return
template
;
return
template
;
}
}
public
String
getTemplatePath
()
public
String
getTemplatePath
()
{
{
return
"/resources/templates/"
+
getTemplateName
();
return
"/resources/templates/"
+
getTemplateName
();
...
@@ -150,8 +147,7 @@ public class SessionHandler {
...
@@ -150,8 +147,7 @@ public class SessionHandler {
private
EnumMap
<
LanEventPropertyKey
,
Boolean
>
boolPropertyCache
=
new
EnumMap
<>(
LanEventPropertyKey
.
class
);
private
EnumMap
<
LanEventPropertyKey
,
Boolean
>
boolPropertyCache
=
new
EnumMap
<>(
LanEventPropertyKey
.
class
);
public
boolean
isEventBoolProperty
(
String
property
)
public
boolean
isEventBoolProperty
(
String
property
)
{
{
LanEventPropertyKey
prop
=
LanEventPropertyKey
.
valueOf
(
property
);
LanEventPropertyKey
prop
=
LanEventPropertyKey
.
valueOf
(
property
);
if
(!
prop
.
isBoolean
())
{
if
(!
prop
.
isBoolean
())
{
throw
new
RuntimeException
(
"Trying to fetch boolean value for non-boolean property!"
);
throw
new
RuntimeException
(
"Trying to fetch boolean value for non-boolean property!"
);
...
@@ -206,18 +202,15 @@ public class SessionHandler {
...
@@ -206,18 +202,15 @@ public class SessionHandler {
// return permbean.hasPermission(perm);
// return permbean.hasPermission(perm);
// }
// }
public
String
getDateFormat
()
public
String
getDateFormat
()
{
{
return
"dd.MM.yyyy"
;
return
"dd.MM.yyyy"
;
}
}
public
String
getDatetimeFormat
()
public
String
getDatetimeFormat
()
{
{
return
"dd.MM.yyyy HH:mm"
;
return
"dd.MM.yyyy HH:mm"
;
}
}
public
String
getShortDatetimeFormat
()
public
String
getShortDatetimeFormat
()
{
{
return
"dd.MM HH:MM:ss"
;
return
"dd.MM HH:MM:ss"
;
}
}
...
@@ -247,7 +240,8 @@ public class SessionHandler {
...
@@ -247,7 +240,8 @@ public class SessionHandler {
}
}
public
String
flushCache
()
{
public
String
flushCache
()
{
return
eventbean
.
flushCache
();
eventbean
.
flushCache
();
return
""
;
}
}
...
@@ -257,13 +251,10 @@ public class SessionHandler {
...
@@ -257,13 +251,10 @@ public class SessionHandler {
private
String
preurlString
;
private
String
preurlString
;
public
String
getRequestPreUrl
()
public
String
getRequestPreUrl
()
{
{
if
(
preurlString
==
null
)
{
if
(
preurlString
==
null
)
{
Object
ext
=
FacesContext
.
getCurrentInstance
().
getExternalContext
().
getRequest
();
Object
ext
=
FacesContext
.
getCurrentInstance
().
getExternalContext
().
getRequest
();
if
(
ext
instanceof
HttpServletRequest
)
if
(
ext
instanceof
HttpServletRequest
)
{
{
StringBuffer
url
=
((
HttpServletRequest
)
ext
).
getRequestURL
();
StringBuffer
url
=
((
HttpServletRequest
)
ext
).
getRequestURL
();
preurlString
=
url
.
substring
(
0
,
url
.
indexOf
(
"/"
,
8
));
preurlString
=
url
.
substring
(
0
,
url
.
indexOf
(
"/"
,
8
));
...
...
code/moya-web/src/main/java/fi/codecrew/moya/web/cdiview/user/UserAllergyView.java
View file @
2b19d7b
...
@@ -98,7 +98,7 @@ public class UserAllergyView extends GenericCDIView {
...
@@ -98,7 +98,7 @@ public class UserAllergyView extends GenericCDIView {
this
.
freetext
=
freetext
;
this
.
freetext
=
freetext
;
}
}
public
void
saveAllergies
()
{
public
void
saveAllergies
()
{
if
(
freetext
!=
null
&&
!
freetext
.
isEmpty
()
)
{
if
(
freetext
!=
null
)
{
EventUser
usr
=
userview
.
getSelectedUser
();
EventUser
usr
=
userview
.
getSelectedUser
();
usr
.
getUser
().
setMetaStringValue
(
ALLERGIES_METAKEY
,
freetext
);
usr
.
getUser
().
setMetaStringValue
(
ALLERGIES_METAKEY
,
freetext
);
userview
.
saveUser
();
userview
.
saveUser
();
...
...
code/moya-web/src/main/java/fi/codecrew/moya/web/cdiview/user/UserEventPropertyView.java
View file @
2b19d7b
...
@@ -52,12 +52,13 @@ public class UserEventPropertyView extends GenericCDIView {
...
@@ -52,12 +52,13 @@ public class UserEventPropertyView extends GenericCDIView {
private
List
<
UsersEventUserproperty
>
properties
;
private
List
<
UsersEventUserproperty
>
properties
;
private
UsersEventUserproperty
selectedProperty
;
private
UsersEventUserproperty
selectedProperty
;
public
void
saveProperty
(){
public
void
saveProperty
()
{
logger
.
warn
(
"Selected property {}, value: {}"
,
selectedProperty
,
selectedProperty
!=
null
?
selectedProperty
.
getTextvalue
():
"NULL"
);
logger
.
warn
(
"Selected property {}, value: {}"
,
selectedProperty
,
selectedProperty
!=
null
?
selectedProperty
.
getTextvalue
()
:
"NULL"
);
}
}
public
List
<
UsersEventUserproperty
>
getProperties
()
{
public
List
<
UsersEventUserproperty
>
getProperties
()
{
if
(
properties
==
null
)
{
if
(
properties
==
null
)
{
super
.
beginConversation
();
EventUser
selectedUser
=
userview
.
getSelectedUser
();
EventUser
selectedUser
=
userview
.
getSelectedUser
();
List
<
UsersEventUserproperty
>
userprops
=
propBean
.
getUserPropertiesForUser
(
userview
.
getSelectedUser
());
List
<
UsersEventUserproperty
>
userprops
=
propBean
.
getUserPropertiesForUser
(
userview
.
getSelectedUser
());
...
@@ -75,13 +76,18 @@ public class UserEventPropertyView extends GenericCDIView {
...
@@ -75,13 +76,18 @@ public class UserEventPropertyView extends GenericCDIView {
}
}
public
void
onRowEdit
(
RowEditEvent
event
)
{
public
void
onRowEdit
(
RowEditEvent
event
)
{
logger
.
warn
(
"onRowEdit, {} {}"
,
event
,
event
.
getObject
());
FacesMessage
msg
=
new
FacesMessage
(
"Car Edited"
);
final
UsersEventUserproperty
oldObj
=
(
UsersEventUserproperty
)
event
.
getObject
();
int
objPoint
=
properties
.
indexOf
(
oldObj
);
UsersEventUserproperty
newObj
=
propBean
.
saveUserproperty
(
oldObj
);
properties
.
set
(
objPoint
,
newObj
);
FacesMessage
msg
=
new
FacesMessage
(
"Property saved"
);
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
msg
);
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
msg
);
}
}
public
void
onRowCancel
(
RowEditEvent
event
)
{
public
void
onRowCancel
(
RowEditEvent
event
)
{
logger
.
warn
(
"Cancel Event {}, {}"
,
event
,
event
.
getObject
());
FacesMessage
msg
=
new
FacesMessage
(
"Edit Cancelled"
);
FacesMessage
msg
=
new
FacesMessage
(
"Edit Cancelled"
);
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
msg
);
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
msg
);
}
}
...
...
code/moya-web/src/main/java/fi/codecrew/moya/web/cdiview/user/UserView.java
View file @
2b19d7b
/*
/*
* Copyright Codecrew Ry
* Copyright Codecrew Ry
*
*
* All rights reserved.
* All rights reserved.
*
*
* This license applies to any software containing a notice placed by the
* This license applies to any software containing a notice placed by the
* copyright holder. Such software is herein referred to as the Software.
* copyright holder. Such software is herein referred to as the Software.
* This license covers modification, distribution and use of the Software.
* This license covers modification, distribution and use of the Software.
*
*
* Any distribution and use in source and binary forms, with or without
* Any distribution and use in source and binary forms, with or without
* modification is not permitted without explicit written permission from the
* modification is not permitted without explicit written permission from the
* copyright owner.
* copyright owner.
*
*
* A non-exclusive royalty-free right is granted to the copyright owner of the
* A non-exclusive royalty-free right is granted to the copyright owner of the
* Software to use, modify and distribute all modifications to the Software in
* Software to use, modify and distribute all modifications to the Software in
* future versions of the Software.
* future versions of the Software.
*
*
*/
*/
package
fi
.
codecrew
.
moya
.
web
.
cdiview
.
user
;
package
fi
.
codecrew
.
moya
.
web
.
cdiview
.
user
;
...
@@ -78,7 +78,7 @@ import fi.codecrew.moya.web.helper.LayoutView;
...
@@ -78,7 +78,7 @@ import fi.codecrew.moya.web.helper.LayoutView;
public
class
UserView
extends
GenericCDIView
{
public
class
UserView
extends
GenericCDIView
{
/**
/**
*
*
*/
*/
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
UserView
.
class
);
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
UserView
.
class
);
private
static
final
long
serialVersionUID
=
7724348195373468017L
;
private
static
final
long
serialVersionUID
=
7724348195373468017L
;
...
@@ -90,21 +90,21 @@ public class UserView extends GenericCDIView {
...
@@ -90,21 +90,21 @@ public class UserView extends GenericCDIView {
public
int
tabIdx
(
String
name
)
{
public
int
tabIdx
(
String
name
)
{
switch
(
name
)
{
switch
(
name
)
{
case
"edit"
:
case
"edit"
:
return
0
;
return
0
;
case
"shop"
:
case
"shop"
:
return
1
;
return
1
;
case
"accountevents"
:
case
"accountevents"
:
return
2
;
return
2
;
case
"groups"
:
case
"groups"
:
return
3
;
return
3
;
case
"picture"
:
case
"picture"
:
return
4
;
return
4
;
case
"foodwave"
:
case
"foodwave"
:
return
5
;
return
5
;
default
:
default
:
}
}
return
0
;
return
0
;
}
}
...
@@ -174,7 +174,7 @@ public class UserView extends GenericCDIView {
...
@@ -174,7 +174,7 @@ public class UserView extends GenericCDIView {
/**
/**
* This is the user that is currently logged in.
* This is the user that is currently logged in.
*
*
* @return
* @return
*/
*/
@Produces
@Produces
...
@@ -189,7 +189,7 @@ public class UserView extends GenericCDIView {
...
@@ -189,7 +189,7 @@ public class UserView extends GenericCDIView {
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
msg
);
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
msg
);
UploadedFile
f
=
event
.
getFile
();
UploadedFile
f
=
event
.
getFile
();
if
(
f
!=
null
)
if
(
f
!=
null
)
logger
.
info
(
"Received file {}, {}, {}"
,
new
Object
[]
{
f
.
getContentType
(),
f
.
getFileName
(),
f
.
getSize
()
});
logger
.
info
(
"Received file {}, {}, {}"
,
new
Object
[]
{
f
.
getContentType
(),
f
.
getFileName
(),
f
.
getSize
()
});
}
}
...
@@ -207,7 +207,7 @@ public class UserView extends GenericCDIView {
...
@@ -207,7 +207,7 @@ public class UserView extends GenericCDIView {
/**
/**
* This is the user we are currently editing, if that is not found we use
* This is the user we are currently editing, if that is not found we use
* current user
* current user
*
*
* @return
* @return
*/
*/
@Produces
@Produces
...
@@ -260,11 +260,11 @@ public class UserView extends GenericCDIView {
...
@@ -260,11 +260,11 @@ public class UserView extends GenericCDIView {
logger
.
info
(
"Cropped image {}x{}"
,
croppedImage
.
getLeft
(),
croppedImage
.
getTop
());
logger
.
info
(
"Cropped image {}x{}"
,
croppedImage
.
getLeft
(),
croppedImage
.
getTop
());
logger
.
info
(
"Cropped data bytesize {}, type {}"
,
croppedImage
.
getBytes
().
length
,
logger
.
info
(
"Cropped data bytesize {}, type {}"
,
croppedImage
.
getBytes
().
length
,
croppedImage
.
getOriginalFilename
());
croppedImage
.
getOriginalFilename
());
try
{
try
{
UserImage
newImage
=
userbean
.
saveCroppedImage
(
user
.
getUser
().
getCurrentImage
(),
croppedImage
.
getLeft
(),
UserImage
newImage
=
userbean
.
saveCroppedImage
(
user
.
getUser
().
getCurrentImage
(),
croppedImage
.
getLeft
(),
croppedImage
.
getTop
(),
croppedImage
.
getWidth
(),
croppedImage
.
getHeight
());
croppedImage
.
getTop
(),
croppedImage
.
getWidth
(),
croppedImage
.
getHeight
());
user
=
userbean
.
getEventUser
(
newImage
.
getUser
(),
false
);
user
=
userbean
.
getEventUser
(
newImage
.
getUser
(),
false
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
...
@@ -279,7 +279,7 @@ public class UserView extends GenericCDIView {
...
@@ -279,7 +279,7 @@ public class UserView extends GenericCDIView {
mpr
=
cardPrintBean
.
getUserCardAsPrintablePdf
(
getSelectedUser
().
getId
());
mpr
=
cardPrintBean
.
getUserCardAsPrintablePdf
(
getSelectedUser
().
getId
());
ByteArrayInputStream
pdfstream
=
new
ByteArrayInputStream
(
mpr
.
getPdf
());
ByteArrayInputStream
pdfstream
=
new
ByteArrayInputStream
(
mpr
.
getPdf
());
setStreamedFile
(
new
DefaultStreamedContent
(
pdfstream
,
"application/pdf"
,
setStreamedFile
(
new
DefaultStreamedContent
(
pdfstream
,
"application/pdf"
,
"user_"
+
getSelectedUser
().
getId
()
+
"_card.pdf"
));
"user_"
+
getSelectedUser
().
getId
()
+
"_card.pdf"
));
logger
.
info
(
"user_"
+
getSelectedUser
().
getId
()
+
"_card.pdf"
);
logger
.
info
(
"user_"
+
getSelectedUser
().
getId
()
+
"_card.pdf"
);
}
catch
(
Exception
e
)
{
}
catch
(
Exception
e
)
{
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
new
FacesMessage
(
e
.
getMessage
()));
FacesContext
.
getCurrentInstance
().
addMessage
(
null
,
new
FacesMessage
(
e
.
getMessage
()));
...
@@ -311,7 +311,7 @@ public class UserView extends GenericCDIView {
...
@@ -311,7 +311,7 @@ public class UserView extends GenericCDIView {
}
else
{
}
else
{
UserImage
userimage
=
userbean
.
uploadImage
(
user
,
getImage
().
getContentType
(),
getImage
().
getInputstream
(),
UserImage
userimage
=
userbean
.
uploadImage
(
user
,
getImage
().
getContentType
(),
getImage
().
getInputstream
(),
getImage
().
getFileName
(),
""
);
getImage
().
getFileName
(),
""
);
user
=
userbean
.
getEventUser
(
userimage
.
getUser
(),
false
);
user
=
userbean
.
getEventUser
(
userimage
.
getUser
(),
false
);
super
.
addFaceMessage
(
"user.imageUploaded"
);
super
.
addFaceMessage
(
"user.imageUploaded"
);
}
}
...
@@ -409,7 +409,7 @@ public class UserView extends GenericCDIView {
...
@@ -409,7 +409,7 @@ public class UserView extends GenericCDIView {
/**
/**
* attach barcode or rfid to card
* attach barcode or rfid to card
*
*
* @return
* @return
*/
*/
public
String
attachCodeToCard
()
{
public
String
attachCodeToCard
()
{
...
@@ -497,7 +497,7 @@ public class UserView extends GenericCDIView {
...
@@ -497,7 +497,7 @@ public class UserView extends GenericCDIView {
/**
/**
* This is user what is currently on "user" -variable, you should almost
* This is user what is currently on "user" -variable, you should almost
* newer use this. Use getCurrentUser() -instead.
* newer use this. Use getCurrentUser() -instead.
*
*
* @return
* @return
*/
*/
public
EventUser
getUser
()
{
public
EventUser
getUser
()
{
...
@@ -635,9 +635,14 @@ public class UserView extends GenericCDIView {
...
@@ -635,9 +635,14 @@ public class UserView extends GenericCDIView {
return
shirtEnabled
;
return
shirtEnabled
;
}
}
public
boolean
isMetaAvailable
(){
JsonObject
meta
=
getSelectedUser
().
getUser
().
getMeta
();
return
meta
!=
null
&&
!
meta
.
isEmpty
();
}
/**
/**
* Get metadata from the User (not EventUser). The data is shown in ui.
* Get metadata from the User (not EventUser). The data is shown in ui.
*
*
* @return
* @return
*/
*/
public
String
getMeta
()
{
public
String
getMeta
()
{
...
@@ -646,19 +651,17 @@ public class UserView extends GenericCDIView {
...
@@ -646,19 +651,17 @@ public class UserView extends GenericCDIView {
User
user
=
eventUser
.
getUser
();
User
user
=
eventUser
.
getUser
();
if
(
user
!=
null
)
{
if
(
user
!=
null
)
{
JsonObject
meta
=
user
.
getMeta
();
JsonObject
meta
=
user
.
getMeta
();
if
(
meta
!=
null
)
{
if
(
meta
!=
null
&&
!
meta
.
isEmpty
())
{
if
(
meta
.
keySet
().
size
()
>
0
)
{
return
meta
.
toString
();
return
meta
.
toString
();
}
}
}
}
}
}
}
return
""
;
return
""
;
}
}
public
String
getPrettyMeta
(){
public
String
getPrettyMeta
()
{
JsonObject
meta
=
getSelectedUser
().
getUser
().
getMeta
();
JsonObject
meta
=
getSelectedUser
().
getUser
().
getMeta
();
if
(
meta
==
null
)
{
if
(
meta
==
null
)
{
return
""
;
return
""
;
}
}
...
...
code/moya-web/src/main/resources/fi/codecrew/moya/resources/i18n.properties
View file @
2b19d7b
This diff could not be displayed because it is too large.
code/moya-web/src/main/resources/fi/codecrew/moya/resources/i18n_en.properties
View file @
2b19d7b
This diff could not be displayed because it is too large.
code/moya-web/src/main/resources/fi/codecrew/moya/resources/i18n_fi.properties
View file @
2b19d7b
...
@@ -1900,4 +1900,6 @@ placegroupview.count=Kpl
...
@@ -1900,4 +1900,6 @@ placegroupview.count=Kpl
user.allergies
=
Allergiat / ruokavaliot
user.allergies
=
Allergiat / ruokavaliot
allergies.save
=
Tallenna allergiat
allergies.save
=
Tallenna allergiat
\ No newline at end of file
user.eventproperties
=
Tapahtumakohtaiset tiedot
submenu.permissionDenied
=
Pääsy kielletty
\ No newline at end of file
Write
Preview
Markdown
is supported
Attach a file
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to post a comment