I'm working on a project in react-admin and am trying to use an AutocompleteInputs within ReferenceInputs for Filter in a List. The list is a product that has a relationship with two different users, a consumer and provider. I'm currently able to obtain the choices for consumers and providers and filter my product list by either.
However, my issues arises with the autosuggestion. It's simply not working. Typing in the AutocompleteInput will not filter the choices to select from for either consumers or providers. I have another AutocompleteArrayInput within an ArrayReferenceInput for providers that's setup similarly and the autosuggestion is working perfectly fine.
Any thoughts?
Here's the broken AutocompleteInput:
export const ProductFilter = props => (
<Filter {...props}>
<ReferenceInput label="Consumer" reference="consumers"
source="consumer_user_id" allowEmpty>
<AutocompleteInput source="id" optionText={FullNameRenderer} />
</ReferenceInput>
<ReferenceInput label="Provider" reference="providers"
source="provider_user_id" alwaysOn allowEmpty>
<AutocompleteInput optionText={FullNameRenderer} />
</ReferenceInput>
<DateRangeInput alwaysOn />
</Filter>
)
And this is the working AutocompleteArrayInput:
export const ConsumerEdit = props => (
<Edit {...props}>
<TabbedForm redirect="show">
<FormTab label="Providers" path="provider_assignmenmts">
<ReferenceArrayInput label='Assigned Providers'
reference='providers' defaultValue={[]}
source="provider_ids" allowEmpty>
<AutocompleteArrayInput optionText={FullNameRenderer}/>
</ReferenceArrayInput>
</FormTab>
</TabbedForm>
</Edit>
)
In the component <AutocompleteInput source = "id" optionText = {FullNameRenderer} /> the attribute source = "id" is superfluous.
Well, it looks like this one is a larger issue within react-admin.
https://github.com/marmelab/react-admin/issues/3098
Related
I'm trying to extend the modx modresource object, but keep getting errors & I can't seem to figure out why. It is related to the schema (I think) but everything looks correct.
Schema:
<?xml version="1.0" encoding="UTF-8"?>
<model package="extresource" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" tablePrefix="modx_" version="1.0.0">
<object class="extResource" extends="modResource">
<composite alias="ResourceData" class="ResourceData" local="id" foreign="internalKey" cardinality="one" owner="local"/>
</object>
<object class="ResourceData" table="resource_data" extends="xPDOSimpleObject">
<field key="internalKey" dbtype="int" precision="11" phptype="integer" null="false" attributes="unsigned"/>
<field key="views" dbtype="int" precision="11" phptype="integer" null="true" />
<field key="starred" dbtype="int" precision="10" phptype="integer" null="false" />
<index alias="internalKey" name="internalKey" primary="false" unique="true" type="BTREE" >
<column key="internalKey" length="" collation="A" null="false" />
</index>
<aggregate alias="Resource" class="modResource" local="internalKey" foreign="id" cardinality="one" owner="foreign"/>
</object>
</model>
I'm testing it using:
$resource = $modx->getObject('modResource', 11112);
echo $resource->get('pagetitle'); //test I have the resource
$data = $resource->getOne('ResourceData');
The errors I get are:
Could not getOne: foreign key definition for alias ResourceData not
found. No foreign key definition for parentClass: modDocument using
relation alias: ResourceData
The table exists & has data, the package is registered in the modx extension packages. I've been over the schema many times & it looks right.
What is causing these errors?
You have to use the right object class in $modx->getObject. Otherwise you will get a modResource object, that does not know the extended object data and relationship.
$resource = $modx->getObject('extResource', 11112);
Does the resource you are loading have its class_key field set to extResource? That's needed for it to load the right resource object class.
I have a CodeFluent Entities Model such as:
<cf:project defaultNamespace="S5T" xmlns:cf="http://www.softfluent.com/codefluent/2005/1" xmlns:cfx="http://www.softfluent.com/codefluent/modeler/2008/1" xmlns:cfmy="http://www.softfluent.com/codefluent/producers.mysql/2012/1" xmlns:cfom="http://www.softfluent.com/codefluent/producers.model/2005/1" xmlns:cfasp="http://www.softfluent.com/codefluent/producers.aspnet/2011/1" xmlns:cfaz="http://www.softfluent.com/codefluent/producers.sqlazure/2011/1" xmlns:cfps="http://www.softfluent.com/codefluent/producers.sqlserver/2005/1" defaultKeyPropertyTypeName="long" maxParameterNameLength="62" defaultConcurrencyMode="None" persistencePropertyNameFormat="{1}" defaultMethodAllowDynamicSort="false" defaultProducerProductionFlags="Default, Overwrite, RemoveDates" defaultMethodDistinct="false" createDefaultMethodForms="true" createDefaultApplication="false" createDefaultHints="false" productionFlags="Default, Overwrite, RemoveDates">
<cf:import path="Default.Surface.cfp" />
<cf:producer name="SQL Server" typeName="CodeFluent.Producers.SqlServer.SqlServerProducer, CodeFluent.Producers.SqlServer">
<cf:configuration produceViews="true" targetDirectory="..\Model7Bom\Persistence" connectionString="Server=MY-MACHINE\SQLEXPRESS;Database=model7;Integrated Security=true;Application Name=S5T;Password=MyPassword;User ID=MyUser" cfx:targetProject="..\Model7Bom\Model7Bom.vbproj" cfx:targetProjectLayout="Update, DontRemove" />
</cf:producer>
<cf:entity name="User" namespace="S5T">
<cf:property name="Id" key="true" cfps:hint="CLUSTERED" />
<cf:property name="Name" />
<cf:property name="Roles" typeName="{0}.RoleCollection" relationPropertyName="Users" />
</cf:entity>
<cf:entity name="Role" namespace="S5T">
<cf:property name="Id" key="true" cfps:hint="CLUSTERED" />
<cf:property name="Name" />
<cf:property name="Users" typeName="{0}.UserCollection" relationPropertyName="Roles" />
</cf:entity>
</cf:project>
I could sucessfully decorate the cf:property name="Id" on both entities with cfps:hint="CLUSTERED". This got me Sql Server producer to correctly output
CONSTRAINT [PK_Use_Id_Use] PRIMARY KEY CLUSTERED
CONSTRAINT [PK_Rol_Id_Rol] PRIMARY KEY CLUSTERED
as opposed to default NONCLUSTERED.
How can I accomplish that with the THIRD TABLE generated by the model, to accomodate the many to many relationship?
By default, the table creation generated snippet is such as:
CREATE TABLE [dbo].[Role_Users_User_Roles] (
[Id] [bigint] NOT NULL,
[Id2] [bigint] NOT NULL,
CONSTRAINT [PK_Roe_Id_Id2_Roe] PRIMARY KEY NONCLUSTERED
(
[Id],
[Id2]
) ON [PRIMARY]
)
However, if I decorate both properties with cfps:hint="CLUSTERED" as in:
cf:property name="Roles" typeName="{0}.RoleCollection" relationPropertyName="Users" cfps:hint="CLUSTERED" /
cf:property name="Users" typeName="{0}.UserCollection" relationPropertyName="Roles" cfps:hint="CLUSTERED" /
I get a snippet generated with PRIMARY KEY CLUSTERED for the PK in TABLE [dbo].[Role_Users_User_Roles], BUT, in addition, I get an UNDESIRED effect of having an incorrect script generated for adding relations (generated filename ...relations_add.sql), such as:
ALTER TABLE [dbo].[Role_Users_User_Roles] WITH NOCHECK ADD CONSTRAINT [FK_Roe_Id_Id_Rol] FOREIGN KEY (
[Id]
) REFERENCES [dbo].[Role](
[Id]
) CLUSTERED
Along with the error from Sql Server:
Error 3 SQL80001: Incorrect syntax near 'CLUSTERED'.
And CodeFluent Producer Error:
CodeFluentRuntimeDatabaseException: CF4116: Execution of file ...path..._relations_add.sql statement at line 2
I need all three PKs CLUSTERED in the three tables generated, but not the side effect of syntax error for generating the relations.
This is not supported out-of-the-box. The hint declared on the a relation is rarely used, more meant as a Foreign Key hint than a column hint. There are several options you can use to do this.
The easiest is to use a post-generation .SQL script to add the clustered setting manually. This is described here: How to: Execute custom T-SQL scripts with the Microsoft SQL Server producer.
You could also use the Patch Producer to remove the CLUSTERED word from the file once it has been created : Patch Producer
Otherwise, here is another solution that involves an aspect I've written as a sample here. You can save the following piece of XML as a file, and reference it as an aspect in your model.
This aspect will add the CLUSTERED hint to primary keys of all Many To Many tables inferred from entities that have CLUSTERED keys. It will add the hint before the table scripts are created and ran, and will remove it after (so it won't end up in the relations_add script).
<cf:project xmlns:cf="http://www.softfluent.com/codefluent/2005/1">
<!-- assembly references -->
<?code #reference name="CodeFluent.Producers.SqlServer.dll" ?>
<?code #reference name="CodeFluent.Runtime.Database.dll" ?>
<!-- namespace includes -->
<?code #namespace name="System" ?>
<?code #namespace name="System.Collections.Generic" ?>
<?code #namespace name="CodeFluent.Model.Code" ?>
<?code #namespace name="CodeFluent.Model.Persistence" ?>
<?code #namespace name="CodeFluent.Model.Code" ?>
<!-- add global code to listen to inference steps -->
<?code
Project.StepChanging += (sender1, e1) =>
{
if (e1.Step == ImportStep.End) // hook before production begins (end of inference pipeline)
{
var modifiedTables = ProjectHandler.AddClusteredHint(Project);
// get sql server producer and hook on production events
var sqlProducer = Project.Producers.GetProducerInstance<CodeFluent.Producers.SqlServer.SqlServerProducer>();
sqlProducer.Production += (sender, e) =>
{
// determine what SQL file has been created
// we want to remove hints once the table_diffs has been created, before relations_add is created
string script = e.GetDictionaryValue("filetype", null);
if (script == "TablesDiffsScript")
{
ProjectHandler.RemoveClusteredHint(modifiedTables);
}
};
}
};
?>
<!-- add member code to handle inference modification -->
<?code #member
public class ProjectHandler
{
public static IList<Table> AddClusteredHint(Project project)
{
var list = new List<Table>();
foreach (var table in project.Database.Tables)
{
// we're only interested by tables inferred from M:M relations
if (table.Relation == null || table.Relation.RelationType != RelationType.ManyToMany)
continue;
// check this table definition is ok for us
if (table.RelationKeyColumns.Count < 1 || table.RelationRelatedKeyColumns.Count < 1)
continue;
// check clustered is declared on both sides
string keyHint = GetSqlServerProducerHint(table.RelationKeyColumns[0].Property);
string relatedKeyHint = GetSqlServerProducerHint(table.RelationKeyColumns[0].Property);
if (keyHint.IndexOf("clustered", StringComparison.OrdinalIgnoreCase) < 0 ||
relatedKeyHint.IndexOf("clustered", StringComparison.OrdinalIgnoreCase) < 0)
continue;
// force hint now, we only need to do this on one of the keys, not all
table.PrimaryKey.Elements[0].SetAttribute("hint", CodeFluent.Producers.SqlServer.Constants.SqlServerProducerNamespaceUri, "clustered");
// remember this table
list.Add(table);
}
return list;
}
public static void RemoveClusteredHint(IEnumerable<Table> list)
{
foreach (var table in list)
{
table.PrimaryKey.Elements[0].RemoveAttribute("hint", CodeFluent.Producers.SqlServer.Constants.SqlServerProducerNamespaceUri);
}
}
// helper method to read XML element's hint attribute in the SQL Server Producer namespace
private static string GetSqlServerProducerHint(Node node)
{
if (node == null)
return null;
return node.GetAttributeValue<string>("hint", CodeFluent.Producers.SqlServer.Constants.SqlServerProducerNamespaceUri, null);
}
}
?>
</cf:project>
I have created a scenario by creating a myScenario.sdl in my local config folder /atg/registry/data/scenarios/myScenario.sdl
myScenario.sdl
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE process SYSTEM "dynamosystemresource:/atg/dtds/pdl/pdl_1.0.dtd">
<process author="admin" creation-time="1413804041263" enabled="false" last-modified-by="admin" modification-time="1413804191188">
<segment migrate-subjects="true">
<segment-name>ItemAddedToOrder</segment-name>
<!--================================-->
<!--== Item added to order Quantity with fraction is defined -->
<!--================================-->
<event id="1">
<event-name>atg.commerce.order.ItemAddedToOrder</event-name>
<filter construct="event-property-filter" operator="isNotNull">
<event-property construct="event-property">
<property-name>quantityWithFraction</property-name>
</event-property>
</filter>
</event>
<!--================================-->
<!--== Log a message message: Quantity With Fraction is Defines logTriggeringEvent: true -->
<!--================================-->
<action id="2">
<action-name>Log a message</action-name>
<action-param name="message">
<constant>Quantity With Fraction is Defines</constant>
</action-param>
<action-param name="logTriggeringEvent">
<constant type="java.lang.Boolean">true</constant>
</action-param>
</action>
</segment>
</process>
And enabled the scenario:
Registry scenarioRegistry = scenarioManager.getScenarioRegistry();
byte[] data = (byte[]) scenarioRegistry.getItem(pScenarioPath);
String xml = null;
if (data != null) {
xml = new String(data, "UTF-8");
} else {
Assert.fail("No scenario is existed to enable/disable");
}
String updatedXml;
if (scenarioState && xml != null) {
updatedXml = xml.replaceAll("enabled=\"false\"", "enabled=\"true\"");
} else {
updatedXml = xml.replaceAll("enabled=\"true\"", "enabled=\"false\"");
}
scenarioRegistry.putItem(pScenarioPath, updatedXml.getBytes("UTF-8"));
Now with this above written code, I can both disable or enable the scenario by changing the state as false and true respectively. But I want to delete the scenario(please remember, my requirement is DELETE not DISABLE SCENARIO). I know using scenarioManager.updateScenario() deleted the scenario. Is my understanding right?
One more thing, I know I can delete the scenario directly from ACC. But I need to code via code not manually from ACC.
Please share your thoughts!
Did you try scenarioRegistry.removeItem(path);
I'm making my own component, and I want to have oportunity to set some properties in form builder. In all I want to reach effect similar to autocomplete control, where I can set 3 properties (URI, xpath, and relative xpath). I read, that I can do it using control-details markup, but unfortunately it does not work. This is code (I working on davinci tutorial):
<xbl:binding element="fr|tutorial-davinci" id="fr-tutorial-davinci" xxbl:mode="lhha binding value">
<metadata xmlns="http://orbeon.org/oxf/xml/form-builder" xmlns:xf="http://www.w3.org/2002/xforms">
<display-name lang="en">davinci-modified</display-name>
<templates>
<instance label=""/>
<view>
<fr:tutorial-davinci id="" appearance="minimal" labelref="#label" xmlns="" resource="" >
<xf:label ref=""/>
<xf:hint ref=""/>
<xf:help ref=""/>
<xf:alert ref=""/>
</fr:tutorial-davinci>
</view>
</templates>
<control-details>
<xf:input>
<xf:label lang="en">Some param</xf:label>
</xf:input>
</control-details>
</metadata>
<xbl:template>
<xf:model>
<xf:instance id="id1"><value/></xf:instance>
</xf:model>
<xf:input ref="instance('id1')" />
</xbl:template>
</xbl:binding>
You must have a ref attribute on<xf:input> which points to an attribute or element where the information will be stored. In autocomplete.xml, there is in particular theresource` attribute, which:
is pointed to by <xf:input>
is present on the <fr:autocomplete> template
I try to talk to a load balancer (Zeus ZXTM) with python:
a = client.factory.create('StringArrayArray')
b = client.factory.create('StringArray')
b.value = ['node01:80',]
a.value = [b,]
client.service.addDrainingNodes(['my pool'], a)
But I get the following error:
suds.WebFault: Server raised fault: 'Not an ARRAY reference at /usr/local/zeus/zxtmadmin/lib/perl/Zeus/ZXTM/SOAPBase.pm line 772.
Extract of the schema definition:
<types>
<xsd:schema targetNamespace='http://soap.zeus.com/zxtm/1.0/'
xmlns='http://www.w3.org/2001/XMLSchema'
xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'
xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'>
<xsd:complexType name="StringArray">
<xsd:complexContent>
<xsd:restriction base='SOAP-ENC:Array'>
<xsd:attribute ref='SOAP-ENC:arrayType' wsdl:arrayType='xsd:string[]'/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="StringArrayArray">
<xsd:complexContent>
<xsd:restriction base='SOAP-ENC:Array'>
<xsd:attribute ref='SOAP-ENC:arrayType' wsdl:arrayType='zeusns:StringArray[]'/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
</xsd:schema>
</types>
<message name="addDrainingNodesRequest">
<part name="names" type="zeusns:StringArray" />
<part name="values" type="zeusns:StringArrayArray" />
</message>
<message name="addDrainingNodesResponse"></message>
<portType name="PoolPort">
<operation name="addDrainingNodes">
<documentation>
Add nodes to the lists of draining nodes, for each of the named pools.
</documentation>
<input message="zeusns:addDrainingNodesRequest"/>
<output message="zeusns:addDrainingNodesResponse"/>
</operation>
</portType>
</definitions>
I also tried like this:
client.service.addDrainingNodes(['my pool'], [['node01:80']])
which worked in SOAPpy but now in suds I get:
suds.WebFault: Server raised fault: 'Value isn't an array'
Comparison between what SOAPpy and what suds sends:
SOAPpy (works):
<ns1:addDrainingNodes xmlns:ns1="http://soap.zeus.com/zxtm/1.0/Pool/" SOAP-ENC:root="1">
<v1 SOAP-ENC:arrayType="xsd:string[1]" xsi:type="SOAP-ENC:Array">
<item>my pool</item>
</v1>
<v2 SOAP-ENC:arrayType="xsd:list[1]" xsi:type="SOAP-ENC:Array">
<item SOAP-ENC:arrayType="xsd:string[1]" xsi:type="SOAP-ENC:Array">
<item>node01:80</item>
</item>
</v2>
</ns1:addDrainingNodes>
suds (doesn't work):
<ns4:addDrainingNodes>
<names xsi:type="ns0:StringArray" ns3:arrayType="ns2:string[1]">
<item xsi:type="ns2:string">my pool</item>
</names>
<values xsi:type="ns0:StringArrayArray" ns3:arrayType="ns0:StringArray[1]">
<item xsi:type="ns2:string">node01:80</item>
</values>
</ns4:addDrainingNodes>
Context:
I'm new to suds and Soap
there's only the SOAP interface to the ZXTM loadbalancer
using python2.6 and suds 0.3.9
we used to use ZSI's SOAPpy, but had issues using it under python 2.6
Edit: Added suds/SOAPpy payloads
After trying
zillions of different arguments to this function
wsdl2py from ZSI
I found out that suds 4.0 offers plugins, that solves this case by hacking, but nonetheless I think that's a suds bug:
class FixArrayPlugin(Plugin):
def sending(self, context):
command = context.envelope.getChild('Body').getChildren()[0].name
if command == 'addDrainingNodes':
context.envelope.addPrefix('xsd', 'http://www.w3.org/1999/XMLSchema')
values = context.envelope.getChild('Body').getChild('addDrainingNodes').getChild('values')
values.set('SOAP-ENC:arrayType', 'xsd:list[1]')
values.set('xsi:type', 'SOAP-ENC:Array')
item = values[0]
item.set('SOAP-ENC:arrayType', 'xsd:list[1]')
item.set('xsi:type', 'SOAP-ENC:Array')
client = Client(wsdl, location=location, plugins=[FixArrayPlugin()])
a = client.factory.create('StringArrayArray')
b = client.factory.create('StringArray')
b.item = ['node01:80']
a.item = [b,]
client.service.addDrainingNodes(['my pool'], a)
I'm looking forward for this issue to be fixed, IMO this should be a one liner
I'm leaving this open as I'm still interested in better alternatives
What looks strange to me is you have to explicitly construct types like 'StringArrayArray' and 'StringArray' - a smart enough SOAP client in a language like python should be able to figure this out via reflection, examining the arguments you pass to the service call. I'm guessing they're declared in the wsdl as something like "SOAP-ENC:Array" - if so they're not intended to be objects. That would also make sense with the error message "Not an ARRAY reference". Have you tried just;
a = [ ['node01:80',], ]
client.service.addDrainingNodes(['my pool'], a)
Or failing that perhaps...
a = client.factory.create('StringArrayArray')
b = ['node01:80',]
a.value = [ b, ]
client.service.addDrainingNodes(['my pool'], a)
Good luck.