Passing Enum as variable to Relay Qraphql query - relayjs

subscription userSubscription($filter: UserSubscriptionFilter!) {
User(filter: $filter) {
mutation
node {
name
addresses {
id
pincode
}
}
}}
in this subscription query i need to pass filter variable with value
const subscriptionConfig = {
subscription: updateQPListSubscription,
variables: {filter:{mutation_in: ["CREATED"]}},
However CREATED is an enum, how do i pass it as filter variable
If i hard-code in query itself then its working .... for example below query is working
subscription userSubscription {
User(filter: {mutation_in: [CREATED] node:{name_contains:"ankit"}}) {
mutation
node {
name
addresses {
id
pincode
}
}
}}
i want to pass the whole filter variable dynamically using the variables field when setting up the subscription
In graphcool playground also it does not work, however it accept the query variable i passed

Related

Mock data generation for storybook

I am trying to generate mock data using relay for storybook.
My query is
const QUERY_LIST = graphql`
query modelControllerAllUsersQuery #relay_test_operation {
allUsers {
pageInfo {
hasNextPage
}
edges {
node {
id
firstName
lastName
}
}
}
}
`
and provided RelayEnvironmentProvider as a decorator to the story. I'm trying to return some default values to my query using custom mock resolvers.
const customMockResolvers = {
...mockResolvers,
allUsers:() => ({
pageInfo:{
hasNextPage:false,
},
edges:[
{
node:{
id :'id',
firstName:'fname',
lastName :'lname',
},
},
],
}),
};
and calling it as
(operation) => MockPayloadGenerator.generate(operation, customMockResolvers)
I don't seem to be able to get the default values returned.
Currently, it is returning
{"allUsers":{"pageInfo":{"hasNextPage":false},"edges":[{"node":{"id":"<UserNode-mock-id-1>","firstName":"<mock-value-for-field-\"firstName\">","lastName":"<mock-value-for-field-\"lastName\">"}}]}}
What am I doing wrong?
When using the #relay-test-operation, the keys within your customMockResolvers object must match the type name of the fields, which can be different from the field names themselves.
For example, you could have the following in your schema:
type Foo {
id: ID!
name: String!
}
and the following query:
query FooQuery #relay_test_operation {
foo {
id
name
}
}
Then the customMockResolvers object would look like this:
const customMockResolvers = {
Foo: () => ({
id: "fooId",
name: "fooName"
})
}
Notice that I'm passing in Foo as the key instead of foo.
You can check your schema and see what the the type name of allUsers is. I suspect it would be something like AllUsers or allUsersConnection, or something similar.
Also, if you're interested in creating Storybook stories for Relay components, I created a NPM package just for that: https://www.npmjs.com/package/use-relay-mock-environment
It doesn't require adding the #relay-test-operation directive to your query, and instead relies only on resolving the String type (which is the default for all scalar properties). You can of course still add the #relay-test-operation directive and also extend the resolvers by providing customResolvers in the config.
You can also extend the the String resolver as well, by providing extendStringResolver in the config.
Feel free to review the source code here if you want to implement something similar: https://github.com/richardguerre/use-relay-mock-environment.
Note: it's still in its early days, so some things might change, but would love some feedback!

Union types support in Relay

When you have defined field as an union of two types (in example machines contains Ships and Droid) then in Relay you can do something like that:
fragment on Faction# relay(plural: true) {
name,
machines {
... on Ship {
name
}
... on Droid {
name,
primaryFunction
}
}
}
so under machines prop your objects are correctly evaluated, but if you want to do that using fragments from external components:
fragment on Faction# relay(plural: true) {
name,
machines {
${StarWarsShip.getFragment('ship')}
${StarWarsDroid.getFragment('droid')}
}
}
then you end up with fragment definitions under machines. It looks like you are trapped and can't check which object is which type in machines array so you can't decide which component should be used.
There exists a __typename field with which you should be able to introspect the type of each record:
Query
fragment on Faction #relay(plural: true) {
name,
machines {
__typename # <-- add this
${StarWarsShip.getFragment('ship')}
${StarWarsDroid.getFragment('droid')}
}
}
App code
this.props.faction.machines.map(machine =>
machine.__typename === 'Droid'
? <Droid droid={machine} />
: <Ship ship={machine} />
);

How can Grails domain object members have default names based on a computed value?

This is what I'm trying to do:
class Test {
String name
static mapping = {
name defaultValue: "test_${Test.count()}"
}
}
So when a new "test" object is created the name is test_1, test_2, test_3 etc. depending on how many test objects already exist. The above does not work because "test.count was used outside of a Grails application"
You could initialize the property instead of specifying the value via the mapping closure.
class Test {
String name = "test_${Test.count()}"
}
or
class Test {
String name = initName()
private static String initName() {
def count = Test.count()
return "test_" + count
}
}

combining criteria from params array

This example here is from the grails docs:
def emeaCriteria = {
eq "region", "EMEA"
}
def results = Airport.withCriteria {
emeaCriteria.delegate = delegate
emeaCriteria()
flights {
like "number", "BA%"
}
}
My webpage is passing back a checkbox group of ethnicities, returning the row ids. So what the server gets is:
ethnicity:[1, 4]
or if the user only picks one ethnicity:
ethnicity:4
def criteria = { params ->
//handle case where only one ethnicity is returned as just a string, not a list of strings
def list = params.ethnicty instanceof String ? [params.ethnicty] : params.ethnicity
if (list) {
inList('ethnicity', list)
}
}
I'm getting an error: java.lang.String cannot be cast to java.lang.Enum.
If I didn't have a list I think I could figure it out. The params are sending back string values, and they need to be converted to the enum class. But within the closure, how do you convert each entry into a list to the enum?
I figured it out through a combination of multiple website posts and with help from dmahapatro above.
def genderCriteria = {
if (params.gender) {
inList('gender', params.list('gender').collect { Gender.valueOf(it)} )
}
}
If a webpage passes back one or more enums (a single string or a list of strings) and you want criteria to check values from the list passed back, you have to provide a list of enum types (not strings or ints).
Here is my enum class for reference:
public enum Gender {
M('Male'),
F('Female'),
U('Unknown')
final String value
Gender(String value) {
this.value = value
}
public String toString() {
value
}
public String getKey() {
name()
}
public String getValue() {
value
}
}
And my criteria builder:
def c = MyDomain.createCriteria()
results = c.list {
genderCriteria.delegate = delegate
genderCriteria(params)
}
Even if no values are passed back for the gender field, it still works (because of the if statement in genderCriteria.
It may not be the best or cleanest solution, but it does work.

How to get enum values in activiti and what is return type of getType() of FormProperty in activiti?

I want to get the values of the enum property.
In activiti 5.13 userguide,
the enumeration values are accessible with formProperty.getType().getInformation("values")
In activiti docs,return type of getType() is FormType. But in my code getType() return type is String. So i couldn't call FormType's getInformation() method.
When i am using formProperty.getType().getInformation("values"), i got the following error.
Cannot cast object 'enum' with class 'java.lang.String' to class 'org.activiti.engine.form.FormType'.
How could i get the values of enum?
<userTask id="handleRequest" name="Handle vacation request" activiti:candidateGroups="management">
<documentation>${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).</documentation>
<extensionElements>
<activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true">
<activiti:value id="true" name="Approve"></activiti:value>
<activiti:value id="false" name="Reject"></activiti:value>
</activiti:formProperty>
<activiti:formProperty id="managerMotivation" name="Motivation" type="string"></activiti:formProperty>
</extensionElements>
</userTask>
Consider above user Task and You can do like this
//passing Task Id and Process definition Id
def getFormForTask(taskId,pdId) {
RepositoryService repositoryService =processEngine.getRepositoryService()
// getting model
BpmnModel model = repositoryService.getBpmnModel(pdId);
// getting list process from model including tasks
List<Process> processes = model.getProcesses()
List<FormProperty> taskFormPropertyList =[]
for(Process proc : processes) {
for(Object obj : proc.getFlowElements()) {
// need form Property only for User Task
if(obj instanceof UserTask) {
UserTask userTask = (UserTask)obj
if(userTask.getId() == taskId){
// getting list of Form Property from task that matches taskId
taskFormPropertyList = userTask.getFormProperties()
}
}
}
}
// loop through from Property
taskFormPropertyList.each {
// getFormValues() returns Property values for the form Property (like enum)
def fvlist = it.getFormValues()
fvlist.each {
// prints id, in this case true and false
println it.getId()
// prints name, in this case Approve and Reject
println it.getName()
}
}
}

Resources