This forum is in READ-ONLY mode.
You can look around, but if you want to ask a new question, please use the new forum.
Home » support » General discussion » Building Own Generator  (4) 7 Vote(s)
Re: Building Own Generator [message #55300 is a reply to message #55298 ] Tue, 01 July 2008 16:43 Go to previous messageGo to next message
KRavEN  is currently offline KRavEN
Messages: 213
Registered: May 2007
Faithful Member
Clear the cookie for your site. There have been some recent changes to the generator that are probably causing that problem because of a leftover cookie. Once it's cleared you should be fine.
Re: Building Own Generator [message #55327 is a reply to message #55300 ] Tue, 01 July 2008 23:19 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Some bug fixes have been committed by KRavEN and me.

I was working on getting a grid in an edit-page, and get it linked as well, which now is working Surprised

for a demo:
http://tejohnston.dynora.eu/backend_dev.php/voyage/edit/voya ge_id/2
after login (admin:admin) reload the entire page...


Leon
Re: Building Own Generator [message #55388 is a reply to message #24107 ] Thu, 03 July 2008 03:25 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
I've committed a major reimplementation for the generator, especially regarding hacks and bugs around PhpNames

I also reimplemented a part of the getI18NString-method.

The generator is now also capable of handling multipleForeignKeys to a same Table.


Leon
Re: Building Own Generator [message #55420 is a reply to message #55388 ] Thu, 03 July 2008 14:14 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
found a problem with the update form yesterday. drop down combos won't get their data from json anymore (json autocomplete is broken) working on that right now...


Leon
Re: Building Own Generator [message #55421 is a reply to message #55420 ] Thu, 03 July 2008 14:21 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
json-autocomplete problem fixed.

It might be possible that there are some invalid combo-names I'll come back to that. Please provide more bugs if you find them.


Leon
Re: Building Own Generator [message #55425 is a reply to message #55421 ] Thu, 03 July 2008 15:03 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
some extra fixes have been committed, next thing todo is take a good look at action.class.php

These problems are caused by $column->getName() which returns the relative name from now on (same as key), maybe rethink this as well


Leon
Re: Building Own Generator [message #55437 is a reply to message #24107 ] Thu, 03 July 2008 19:25 Go to previous messageGo to next message
saganxis  is currently offline saganxis
Messages: 24
Registered: February 2008
Location: Argentina
Junior Member
Hi to all. This post maybe is more realted with the Extjs2Plugin than Extjs2ThemePlugin, but i know you know about how to use this plugin.
I'm using sF 1.1 so i installed the Extjs2Plugin(i don't know how to make Extjs2ThemePlugin to work in 1.1). I did some chages to
the code in this post: http://www.symfony-project.org/forum/index.php/t/12399/.
I wanted to add the TreePanel control, so i modified the /plugins/sfExtjs2Plugin/config/config.php file and add some lines in the
"mapping plugin method against class" section.

I added this lines:
    'KeyMap'            => 'Ext.KeyMap',
    'TreePanel'         => 'Ext.tree.TreePanel',
    'Observable'        => 'Ext.util.Observable',
    'TreeLoader'        => 'Ext.tree.TreeLoader',
    'Node'				=> 'Ext.data.Node',
    'TreeNode'			=> 'Ext.tree.TreeNode',
    'AsyncTreeNode'     => 'Ext.tree.AsyncTreeNode'


and then the "sfConfig::set" for each class.


Well, in the layout.php i added this Panel:

    $sfExtjs2Plugin->Panel(array
    (
      'id'=>'tonyWp',
      'region'=>'west',
      'title'=>'Menú Principal',
      'margins'=>'0 0 0 5',
      'cmargins'=>'0 0 0 0',
      'width'=>'200',
      'minSize'=>'100',
      'maxSize'=>'300',
      'split'=>'true',
      'collapsible'=>'true',
      'items' => array(
         $sfExtjs2Plugin->TreePanel(array(
           'id'=> 'tree-panel',
    	   'title'=> 'Sample Layouts',
           'region'=>'north',
           'split'=> true,
           'height'=> 300,
           'root'=> $sfExtjs2Plugin->TreeNode(array(
	           'draggable'=>false, 
	           'text'=>'the root',
         	   'expanded'=> true,
	             
           ))
        ))
   
      )
    ))


So the root element appear. But i don't know how to build the tree childrens...

I probed adding:

           'loader' => $sfExtjs2Plugin->TreeLoader(array(
   				'dataUrl'=> 'tree-data.json', //this is the url that will return the JSON string
   				'requestMethod'=> 'GET' //you can configure POST as well, depends on your script that is waiting on the above url
			))



to the previous TreePanel and i put the tree-data.json file in the web dir.

I want something sinilar to this:

http://extjs.com/deploy/dev/examples/layout-browser/layout-b rowser.html

i tryed this too:
http://cappelleh-java.blogspot.com/2008/06/exttreetreepanel- examples-explained.html

Do you know how can i make this work??????
Re: Building Own Generator [message #55441 is a reply to message #55437 ] Thu, 03 July 2008 19:43 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Hi saganxis,

I've added the config-mappings to the sfExtjs2Plugin.

hard to say how to make it work if I don't know what goes wrong at the moment... I haven't got experience with this ext.tree-object myself but comparing your php-extjs2 code with the example I can't see a real difference at first sight.

Do you get to see an error in firebug? or can you see the json being loaded?

About Sf1.1; Upgrading the ThemePlugin to 1.1 hasn't got a high priority yet. First it needs to be somewhat more stable, maybe skipping 1.1 and jump right to 1.2, Can't tell yet.

We can make a 1.1 branch if someone wants to make it work for 1.1 though, although I would advice to wait till the actions.class.php file has been improved.


Leon
Re: Building Own Generator [message #55443 is a reply to message #24107 ] Thu, 03 July 2008 21:03 Go to previous messageGo to next message
saganxis  is currently offline saganxis
Messages: 24
Registered: February 2008
Location: Argentina
Junior Member
Thanks for the response!!

I tested again but with some changes. the final code in the layout is:

 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

<?php include_http_metas() ?>
<?php include_metas() ?>

<?php include_title() ?>

<link rel="shortcut icon" href="/favicon.ico" />


</head>
<body>
<?php
$tab1info = "test";
$help = "Alguna ayuda";

$sfExtjs2Plugin = new sfExtjs2Plugin(array('theme'=>'aero'));
$sfExtjs2Plugin->load();
$sfExtjs2Plugin->begin();

// **************************************
// Application
// **************************************
/*'loader' => $sfExtjs2Plugin->TreeLoader(array(
              'dataUrl'=>'http://uvqapp11.dev/js/tree-data.json',
              'requestMethod' => 'GET'
           ))*/
$sfExtjs2Plugin_App_viewport = $sfExtjs2Plugin->Viewport(array
(
  'layout' => 'border',  'items'  => array
  (
    $sfExtjs2Plugin->Panel(array
    (
      'id'=>'tonyNp',
      'region'=>'north',
      'height'=>'auto',
      'title'=>' ',
      'html'=> image_tag('logouvq'),
      'split'=>'true',
      'collapsible'=>'true'
    )),
   
    $sfExtjs2Plugin->Panel(array
    (
      'id'=>'tonyWp',
      'region'=>'west',
      'title'=>'Menú Principal',
      'margins'=>'0 0 0 5',
      'cmargins'=>'0 0 0 0',
      'width'=>'200',
      'minSize'=>'100',
      'maxSize'=>'300',
      'split'=>'true',
      'collapsible'=>'true',
      'items' => array(
         $sfExtjs2Plugin->TreePanel(array(
           'id'=> 'tree-panel',
    	   'title'=> 'Sample Layouts',
           'region'=>'north',
           'split'=> true,
           'height'=> 300,
           'rootVisible'=> false,
           'loader' => $sfExtjs2Plugin->TreeLoader(array(
   				'dataUrl'=> 'http://uvqapp11.dev/tree-data.json', //this is the url that will return the JSON string
   				'requestMethod'=> 'GET' //you can configure POST as well, depends on your script that is waiting on the above url
			)),
           
           'root'=> $sfExtjs2Plugin->AsyncTreeNode(array())
			
           
        ))
   
      )
    )),
    $sfExtjs2Plugin->TabPanel(array
    (
      'id'=>'tonyCp',
      'region'=>'center',
      'margins'=>'0 5 0 0',
      'items'=>array(
        $sfExtjs2Plugin->Panel(array(
          'title'=>'Página Principal',
          'contentEl' => 'center'
          
        )),
        $sfExtjs2Plugin->Panel(array(
          'title'=>'Ayuda',
          'html'=>$help
        ))
      )
    ))
  )
));

$sfExtjs2Plugin->beginApplication(array
(
  'name'   => 'App',
  'public' => array(
    'init' => $sfExtjs2Plugin->asMethod("$sfExtjs2Plugin_App_viewport;"
  )
)
));

$sfExtjs2Plugin->endApplication();
$sfExtjs2Plugin->end('Ext.onReady(App.init, App);');

?>

<div id="center" style="padding-left: 20px; padding-top: 20px;">
<?php echo $sf_content ?>
</div>
</body>
</html>



I have to fix the dataUrl param, but this is just a test.
Here is an screenshot of what i wanted to do. Is is simple by now.

  • Attachment: symfony.png
    (Size: 203.06KB, Downloaded 173 time(s))

Re: Building Own Generator [message #55447 is a reply to message #55443 ] Fri, 04 July 2008 00:53 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Sorry think I misunderstood your problem. The problem isn't the sfExtjs2Plugin, but the construction of the json-data isn't it?

As said I haven't used the tree-panel myself yet, but the example you gave shows your should construct something like this:
    [{
        id: 1,
        text: 'A leaf Node',
        leaf: true
    },{
        id: 2,
        text: 'A folder Node',
        children: [{
            id: 3,
            text: 'A child Node',
            leaf: true
        }]
   }]


I assume you know what you want to construct, but not how to create a json itself.

It probably is the easiest to create an array, and export this as json.

You can see how I do it manually in my actions.class.php for my menu here:
  public function executeGetOverview()
  {
    $filter = $this->getRequestParameter('filter');

    $c = new Criteria();
    $c->addDescendingOrderByColumn(VoyagePeer::CREATED_AT);
    $c->addAscendingOrderByColumn(AssignmentPeer::SUBJECT);
    $c->addAscendingOrderByColumn(AssignmentParcelPeer::SUBJECT);


    $words = explode(' ', $filter);

    //filter on words from search-field
    foreach($words as $word)
    {
      if (strlen($word) > 2)
      {
        $c1 = $c->getNewCriterion(AssignmentPeer::SUBJECT, '%'.$word.'%', Criteria::LIKE);
        $c2 = $c->getNewCriterion(AssignmentParcelPeer::SUBJECT, '%'.$word.'%', Criteria::LIKE);
        $c3 = $c->getNewCriterion(ClientCompanyPeer::NAME, '%'.$word.'%', Criteria::LIKE);
        $c4 = $c->getNewCriterion(BerthPeer::NAME, '%'.$word.'%', Criteria::LIKE);
        $c5 = $c->getNewCriterion(VesselPeer::NAME, '%'.$word.'%', Criteria::LIKE);
        $c6 = $c->getNewCriterion(CityPeer::NAME, '%'.$word.'%', Criteria::LIKE);

        $c1->addOr($c2);
        $c1->addOr($c3);
        $c1->addOr($c4);
        $c1->addOr($c5);
        $c1->addOr($c6);

        $c->add($c1);
      }
    }


    $this->overview = AssignmentParcelPeer::doSelectLeftJoinAssignment($c);

    $results = array();
    foreach ($this->overview as $result)
    {
      $assignment = $result->getAssignment();
      $voyage     = $assignment->getVoyage();

      $results[] = array(
        'voyage_id'                 => $voyage->getVoyageId(),
        'voyage_title'              => $voyage->getTitle(),

        'assignment_id'             => $assignment->getAssignmentId(),
        'assignment_subject'        => $assignment->getSubject(),

        'assignment_parcel_id'      => $result->getAssignmentParcelId(),
        'assignment_parcel_subject' => $result->getSubject(),
      );
    }

//    $this->getResponse()->setHttpHeader('X-JSON');
    sfConfig::set('sf_web_debug', false);
    return $this->renderText(json_encode($results));


  }

I fill an array called $results, and transform this into json with json_encode.

Hope this can help.


Leon
Re: Building Own Generator [message #55456 is a reply to message #24107 ] Fri, 04 July 2008 05:04 Go to previous messageGo to next message
saganxis  is currently offline saganxis
Messages: 24
Registered: February 2008
Location: Argentina
Junior Member
Thanks lvanderree, yes tou were right. I tested with a php file and it worked.
here is the code(it's just an example).
When i do this in a right way i 'll post on how to do it.

<?php

$var = array(array(
	'text' => 'Basic Ext Layouts',
	'expanded' => true,
	'children' => array(
		array(
			'text' => 'Basic Ext Layouts',
			'leaf' => true
		)


	)

	)
);
echo json_encode($var);

?>
Re: Building Own Generator [message #55484 is a reply to message #24107 ] Fri, 04 July 2008 12:54 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
People I have moved the definition of peer_method!

moved definition of peer_method and peer_count_method directly under generator.class.param (not under list anymore)

I will update the wiki about this change


Leon
Re: Building Own Generator [message #55589 is a reply to message #55484 ] Mon, 07 July 2008 01:23 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
two of my next-todo's will be
1. checkboxes don't seem to be there for booleans
2. fieldsets in edit-tabpages


Leon
Re: Building Own Generator [message #55609 is a reply to message #55589 ] Mon, 07 July 2008 12:49 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Is there anyone who is using (field/display) partials at the moment? I don't think they are really usable is it?

I am thinking about reimplementing these like this:

partials will be used for fields (grideditor-columneditor or form-field) but without adding fields for the json results. you fill the json-results with values from custom-methods and with a + as prefix you can make this column invisible in the forms/grids.

so syntax will be:
[_partial, +json_field]

This way you can have partials which won't require data, like fieldlabels, and can tabbpages which contain only actions.

Anyone who's got any ideas/comments about this?


Leon
Re: Building Own Generator [message #55671 is a reply to message #55609 ] Tue, 08 July 2008 02:23 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
json files are now being generated with the help of the json_encode method. Templates have been removed, since everything is now defined in the action.class, which should be even faster.


Leon
Re: Building Own Generator [message #55704 is a reply to message #24107 ] Tue, 08 July 2008 10:14 Go to previous messageGo to next message
snk00sj  is currently offline snk00sj
Messages: 71
Registered: July 2006
Member
thx for the tip about clearing cookies for sorting columns, i'll make sure to add that to the wiki 'troubleshooting' part.

I am looking for the best way to integrate the extjs grid in my application. I don't want the grid to show 100% (taking up the entire page) but i'd like it fit in in my current layout.php

What would be the best approach to reach this goal ?


Digital Base Webagency
Re: Building Own Generator [message #55707 is a reply to message #55704 ] Tue, 08 July 2008 10:54 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
The grid is placed in a panel, so all you have to do is use the panel as an item in your layout.

I use a grid as a formField, which requires setting some more config-options, but looks pretty similar, all you have to do is:


items = [
          // a normal field
          {
            name: 'voyage[eta_text]',
            fieldLabel: 'Overrule with text',
            labelSeparator: ':',
            qtip: 'text here will override latest ETA',
            width: 200,
            xtype: 'textfield',
            allowBlank: true
          },
          // a grid as a field
          {
            name: 'voyage[voyage_id]', 
            fieldLabel: 'Latest ETA\'s',
            xtype: 'listetagridpanel',

            filter: 'voyage-voyage_id',
            filter_key: this.key,

//            hideHeaders: false,
            enableColumnResize: false,
            enableColumnHide: false,
            enableColumnMove: false,
            enableDragDrop: false,
            enableHdMenu: false,

            width: 150,
            isFormField : true,
            border: true,
            bodyBorder: true,
            fieldClass : "x-form-field"
          },
        ]


For the result see http://tejohnston.dynora.eu/index.php/voyage/edit/voyage_id/ 1 (admin:admin, after login: reload to get the requested page) See tab-page ETA.

Also I prefer to use xtypes, instead of its direct constructor, but thats up to you, you can also call new ListModuleGridPanel({..options here..});

for an example of my layout.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>

  <?php sfContext::getInstance()->getResponse()->addJavascript('/sfExtjsThemePlugin/js/tiny_mce/tiny_mce', 'first'); ?>

  <?php include_partial('global/extIncludePartial') ?>
  <?php include_http_metas() ?>
  <?php include_metas() ?>

  <?php include_title() ?>

  <link rel="shortcut icon" href="/favicon.ico" />

</head>
<body>
<?php
  $sfExtjs2Plugin = new sfExtjs2Plugin(array('adapter'=>'ext'));

// init login-window
  $sfExtjs2Plugin->begin();
?>
  // preload login-window
  Ext.onReady(function() {Login.init('<?php echo $this->getContext()->getRequest()->getScriptName() ?>');}, Login);

<?php
  $sfExtjs2Plugin->end();

  // content
  echo $sf_data->getRaw('sf_content');

  //init app
  $sfExtjs2Plugin->begin();
?>

  Ext.onReady(function() {App.init('<?php echo $this->getContext()->getRequest()->getScriptName() ?>');}, App);

// not authorized exception
var A = Ext.lib.Ajax;
A.request = A.request.createInterceptor(function(method, uri, cb, data, options) {
  if (!A._locked) {
    // save the last request arguments
    A._lastRequest = Array.prototype.slice.call(arguments, 0);
  } else if (options.scope.options && options.scope.options.loggingIn) {
    return true; // allow your login only
  }
  return !A._locked; // cancel all future requests during lockout
}, A);

var sessionTimeoutHandler = function(statusCode, transaction, response, callback, isAbort) {
  A._locked = true;

  //repeat last query
  var withCallBack = function() {
    A._locked = false;
    A._lastRequest ? A.request.apply(A, A._lastRequest) : null;
    A._lastRequest = null;
  };

  Login.show(withCallBack);

};

A.onStatus([401], sessionTimeoutHandler);

<?php
$sfExtjs2Plugin->end();
?>



<div id="header">
  <div id="header_title_div">
    <img style="float:left;margin-left:10px;margin-right:10px;" src="/images/logos/tej.gif" alt="T.E. Johnston & Co. Holland b.v." />
    <div class="title">T.E. Johnston & Co. (Holland) b.v. Support System</div>
  </div>

  <div id="header_content"></div>

  <div id="menu">
    <div id="menu_opened_docs" class="opened docs"></div>
  </div>

</div>

</body>
</html>



and the _extIncludePartial
<?php

$js = sfConfig::get('extjs_default_javascripts', array());
   $js[] = '/js/app.js';
   $js[] = '/js/login.js';
   $js[] = '/js/Ext.ux.ContentPanel.js';
   $js[] = '/js/Ext.ux.MainMenu.js';
   $js[] = '/js/Ext.ux.OverviewPanel.js';

   $js[] = '/js/Ext.ux.VoyageEtaPanel.js';

   $js[] = '/sfExtjsThemePlugin/js/ext.ux.tinymce/Ext.ux.TinyMCE.min.js';


$sfExtjs2Plugin = new sfExtjs2Plugin(array('theme'=>'gray'),
                                     array('css' => array('/sfExtjsThemePlugin/css/symfony-extjs.css',
                                                          '/sfExtjsThemePlugin/css/collapsing-disabled',
                                                          '/css/parcel_overview'
                                            ),
                                           'js' => $js
                                     ));

$sfExtjs2Plugin->load();



all these js includes can be found at:
http://tejohnston.dynora.eu/js/app.js


Leon
Re: Building Own Generator [message #55732 is a reply to message #55707 ] Tue, 08 July 2008 14:27 Go to previous messageGo to next message
snk00sj  is currently offline snk00sj
Messages: 71
Registered: July 2006
Member
leon,
tnx for the fast reply.


i have no knowledge at all about ext, so typex/panels are not my cup of tea.

i am using a default admin generated module (list action) with the custom adminexttheme. Now all the sites content is in a wrapping div see : http://www.pastebin.be/12667

I added 'CONTENT SHOULD BE HERE' string

So the default symfony admin generator nicely puts its content where i put

  <div class="center">
    <?php echo $sf_data->getRaw('sf_content') ?>
  </div>


Whenever i use the ext admin theme, it gets replaced by the javascript functionality, causing the js grid to be loaded full page (without respecting my css/div.center guidelines.

So if you could add some info to your previous posts, which file, where to put, i would be happy to try it out, and eventually document it afterwards. I can't find a partial (in the cache) named : extIncludePartial

And i would like not to touch my existing layout php (only if needed). Any thoughts ?


Digital Base Webagency
Re: Building Own Generator [message #55758 is a reply to message #55732 ] Tue, 08 July 2008 17:36 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Hi snk00sj,

I don't think I can really help, unless you start learning Ext:
http://extjs.com/learn/Tutorials
and
http://extjs.com/deploy/dev/examples/samples.html

You cannot expect things to work when you simply put code in a div, doesn't work that way.

You can define to let the grid fill a predefined div, by setting the renderTo param, but its not very maintainable for big applications if you ask me.

http://extjs.com/learn/Tutorial:Playing_With_Ext_The_Easy_Wa y

Please take a look at the ext examples if you want to use ext and see how it is done. Also examples of Especially Saki are very useful ( can be found at the tutorials, and at http://www.extjs.eu )

Also the API can be of great help
http://extjs.com/deploy/dev/docs/


Leon
Re: Building Own Generator [message #56025 is a reply to message #55758 ] Sat, 12 July 2008 17:37 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Partials for the grid are implemented.

It now requires some significant partial code to make things work, this can probably made easier in the future, but for now it works!

First a Demo?

check this out:
http://tejohnston.dynora.eu/voyage/edit/voyage_id/1 (admin:admin)
Refresh the page after login so you see a voyage-edit panel with two tabs. Tab2 contains and ETA-list(grid from the ETA-module, while you are in the edit action of the voyage module), with actions to delete the ETAs. The eta-list filters: showing only eta related to this voyage!

I am aware this demo actually is a form-action, but I implemented it as a partial so you can have the control about in which column you want the partial. In the future I can also implement list.objectactions to make things (a little) backwards compatible.

To see only the eta list you can go this url: http://tejohnston.dynora.eu/eta
which simplifies things a little probably Wink (adding will not work, since the required foreign key voyage_id will be missing this way)

I think you can see this list is highly modified, so please don't be scared because of the number of gridpanel and render partials I also use).

its complete generator is:
generator:
  class:              sfExtjsPropelAdminGenerator
  param:
    model_class:      Eta
    theme:            extjs

    peer_method:          doSelectJoinRelatedForTitle
    peer_count_method:    doCount

    fields:
      eta:
        params:
          menuDisabled: true
          editable: false
          sortable: false
          fixed:    true
          width:    175
          renderer: this.renderDateAdded


    gridpanel:
      variable:
        partials:     _gridpanel_headerTpl #partial containing the header to add items
      method:
        partials:     [_gridpanel_syncFields, _gridpanel_addEta, _gridpanel_deleteButton_mouseEvents] #partials containing syncFields (to align the add Eta field), the addEtaField itself and the events to handle mouseEvents for the DeleteButton

    renderer:
      method:
        partials:     _renderer_mouseover #partial containing the mouseover tip renderer (above the eta-text)

    list:
      params:
        header: false
        bbar:   false
        tbar:   false

      display: [eta, _delete, +created_at, +created_by/username]

      actions: false



For the delete action I have the list.display[_delete] partial and a gridpanel.method.partial to handle its mouseEvents

The _delete partial contains the layout for the column,
_gridcolumn_delete.php:
<?php
  // partials for a delete column :O
?>
new Ext.ux.DeleteColumn()


The Ext.ux.DeleteColumn() is defined in a javascript file:
// namespace: Ext.ux
Ext.namespace('Ext.ux');

Ext.ux.DeleteColumn = function(){
    Ext.apply(this, {
        width: 22,
        header: '<div class="delete-col-hd"></div>',
        menuDisabled:true,
        fixed: true,
        tooltip: 'Click to delete this ETA',
        renderer: function(){
            return '<div class="delete-td"></div>';
        }
    });
};

You also need CSS and images to make this work.

And to make the button behave like a button I've added event-handlers like this,
_gridpanel_deleteButton_mouseEvents.php:
<?php
// auto-generated by sfPropelAdmin
// date: 2008/06/11 12:11:36
?>
<?php ob_start() ?>
    var index = this.getView().findRowIndex(t);
    return this.store.getAt(index);
<?php
  $source = ob_get_clean();

  // onRender
  $configArr = array(
    'parameters' => 't',
    'source' => $source
  );

  $gridpanel->attributes['getRecord'] = $sfExtjs2Plugin->asMethod($configArr);

  ob_start()
?>
    if((e.button==0) && Ext.fly(t).hasClass('delete-td')){
        e.stopEvent();
        Ext.fly(t).addClass('delete-td-down');
        this.activeButtonPressed = t;
    }
<?php
  $source = ob_get_clean();

  // onRender
  $configArr = array(
    'parameters' => 'e, t',
    'source' => $source
  );

  $gridpanel->attributes['onMouseDown'] = $sfExtjs2Plugin->asMethod($configArr);

  ob_start()
?>
    if(Ext.fly(t).hasClass('delete-td') && (this.activeButtonPressed == t)){
        e.stopEvent();

        Ext.fly(t).removeClass('delete-td-down');
        var record = this.getRecord(t);



        Ext.Msg.confirm('Confirm','Are you sure you want to delete this ETA?',function(btn,text){
            if(btn == 'yes'){
              var selectArr = [];
              Ext.Ajax.request({
                url: '<?php echo sfContext::getInstance()->getController()->genUrl('eta'.'/ajaxDelete') ?>',
                method: 'POST',
                params: {id: Ext.encode(record.data['eta_id'])},
                scope: this,
                success:  function(response){
                  try { var json_response = Ext.util.JSON.decode(response.responseText); } catch (e) {};
                  this.store.reload();
                  //TODO: throw event!
                },
                failure: function(response){
                  try { var json_response = Ext.util.JSON.decode(response.responseText); } catch (e) {};
                  Ext.Msg.alert('Error while deleting', json_response.message);
                }
              });
            }
          },this);
    }
    this.activeButtonPressed = null; // TODO: this should be done globally, if you release the button anywhere, the button is not pressed anymore...
<?php
  $source = ob_get_clean();

  // onRender
  $configArr = array(
    'parameters' => 'e, t',
    'source' => $source
  );

  $gridpanel->attributes['onMouseUp'] = $sfExtjs2Plugin->asMethod($configArr);

  ob_start()
?>
    if(Ext.fly(t).hasClass('delete-td')){
        if (this.activeButtonPressed == t) Ext.fly(t).addClass('delete-td-down');
        Ext.fly(t.parentNode).addClass('delete-back-over');
    }
<?php
  $source = ob_get_clean();

  // onRender
  $configArr = array(
    'parameters' => 'e, t',
    'source' => $source
  );

  $gridpanel->attributes['onMouseOver'] = $sfExtjs2Plugin->asMethod($configArr);

  ob_start()
?>
    if(Ext.fly(t).hasClass('delete-td')){
        Ext.fly(t).removeClass('delete-td-down');
        Ext.fly(t.parentNode).removeClass('delete-back-over');
    }
<?php
  $source = ob_get_clean();

  // onRender
  $configArr = array(
    'parameters' => 'e, t',
    'source' => $source
  );

  $gridpanel->attributes['onMouseOut'] = $sfExtjs2Plugin->asMethod($configArr);
?>



Especially those event-handlers should be made easier, but as as proof of concept I am very happy with the result!


Leon
Re: Building Own Generator [message #56031 is a reply to message #56025 ] Sat, 12 July 2008 19:50 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
this post os about improving the Editable ComboBoxes

At the moment the comboBoxes still aren't working really well, they force you to stay in the box as long as they contain invalid (unknown) data, which can be very annoying. Besides they sometimes have some strange errors where they don't seem to be aware they contain valid data, or visa versa.

With the code I currently have (Ext.ux.ComboBoxAutoLoad.js),
an implementation seen at http://extjs.com/forum/showthread.php?t=37781&page=2 from durlabh
and some new code, I would like to improve this.

The general problem with comboboxes has already been explained by me at http://extjs.com/forum/showthread.php?t=37781

In short:
ComboStores should always contain the display-value from the grid/form (solved, but can be improved by the post at page2).
Besides this, I would like to be able to add new values for the combo directly with it.

My idea about this second part (the adding/manipulation of the selected item) is the following:

improving the combo
A combo can be in 4 states (I think)
  1. Empty (the text-value = "")
  2. Valid (the text-value matches an item in the related table)
  3. New (the text-value does not match and needs to be added)
  4. Searching (the store is being queried to find if the value exists)


My first solution to improve the combos is to show the state of the combo with the help of an icon.
1. If the combo is empty, no icon is necessary,
2. When valid we can show an OK-icon Or Edit icon (to allow you to manipulate the item in a pop-up-window)
3. When it contains a new item, there should be an Add-icon.
4. when querying, the user sees an animated icon which shows it is searching.

Instead of keeping the user locked in the combofield, the user can now see (with the help of the icon) if the combo contains a valid value. If the combo contains an invalid field we can disable the submit-button of the form (or show a message which tells to enter a valid value in the combo else saving is not possible).

Any ideas/improvements/questions are again appreciated


Leon
Re: Building Own Generator [message #56051 is a reply to message #56031 ] Sun, 13 July 2008 17:59 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
The backwards compatibility bug is fixed (your generator.yml won't require list.display or edit.display anymore, it will show all fields in those cases)

I also implemented partials for edit/form-panel
edit-form-partials won't automatically get a fieldname anymore. Yyou need to set the field.name EXPLICITELY for edit-partials if you want to give one (with field.params.name), this field-name corresponds with the json-item-name it should show. If no name is set, the field will not be committed, nor loaded (which is a good thing)

This opens possibilities to show related items, E.G. when editing an assignment, you can show the related invoices (1 to many relation, where assignments won't have a foreign-key to invoices, but invoices do have a fk to assignment)

Ps. At the moment (list/edit)partials are NOT backwards compatible. I think in best case, we should try to return different results for ajax and non-ajax request from a partial (which has already been proposed a long time a go, don't know by who anymore, but like this):

<?php
switch($type) {

  case 'edit':
    echo "Edit";
  break;

  case 'ajax_edit':
//    use_helper('sfExtjsAppPasswordField');
//    echo generate_extjs_password_fields( $fieldLabel, $name );
    use_helper('Extjs');
    echo extjs_form_combobox(array());
  break;

  case 'list':
    echo 'partial in list-view';
  break;

  default:
    echo $type;
}
?>


I don't use this at the moment, and I haven't tested if this syntax is still working...

To keep normal symfony-partials and ExtJsThemePartials resemble each other as good as possible, it is important to do all data manipulation in the lib/model-objects (so don't define for instance $fullname = $first_name.' '.$last_name in your partial, but in your lib/model/user.php-object.

Partials should be used to define the field-type or other representation styles.

[Updated on: Sun, 13 July 2008 18:03]


Leon
Re: Building Own Generator [message #56120 is a reply to message #56031 ] Mon, 14 July 2008 14:54 Go to previous messageGo to next message
lukas  is currently offline lukas
Messages: 28
Registered: November 2007
Location: Switzerland
Junior Member
lvanderree wrote on Sat, 12 July 2008 19:50


At the moment the comboBoxes still aren't working really well, they force you to stay in the box as long as they contain invalid (unknown) data, which can be very annoying. Besides they sometimes have some strange errors where they don't seem to be aware they contain valid data, or visa versa.



I think we all made these observations, and can agree that it's a good idea to improve combo's.

Quote:


ComboStores should always contain the display-value from the grid/form (solved, but can be improved by the post at page2).
Besides this, I would like to be able to add new values for the combo directly with it.



the "add new values" part should be configurable. I don't always want to make the user able to add new values. (e.g. on course registration: imagine a user could add a new course we don't have)

Quote:


improving the combo
A combo can be in 4 states (I think)
  1. Empty (the text-value = "")
  2. Valid (the text-value matches an item in the related table)
  3. New (the text-value does not match and needs to be added)
  4. Searching (the store is being queried to find if the value exists)




concerning "Valid": An emptied option should be available to (as configurable behaivour) on fields that are not required (we talked about that). (e.g. PC Appliance sales: Some appliances boot from stick (eg firewalls), but you CAN have a hd for logs. It wouldn't be nice If I had to add a product "none" in my product table...)

concerning "New": Shouldn't be allowed in every case too (see add values above)

Quote:


My first solution to improve the combos is to show the state of the combo with the help of an icon.
1. If the combo is empty, no icon is necessary,
2. When valid we can show an OK-icon Or Edit icon (to allow you to manipulate the item in a pop-up-window)
3. When it contains a new item, there should be an Add-icon.
4. when querying, the user sees an animated icon which shows it is searching.

Instead of keeping the user locked in the combofield, the user can now see (with the help of the icon) if the combo contains a valid value. If the combo contains an invalid field we can disable the submit-button of the form (or show a message which tells to enter a valid value in the combo else saving is not possible).

Any ideas/improvements/questions are again appreciated


This solution should last for a while. With the appropriate server configuration you could even be faster than many company xy's serverbased ERP (eg the SAP / R3 insts) can build combos...
As long as it shows the sandclock-like thingie, the user will eat it Very Happy

carpe diem
lukas
Re: Building Own Generator [message #56165 is a reply to message #56120 ] Mon, 14 July 2008 22:11 Go to previous messageGo to next message
xnutsive  is currently offline xnutsive
Messages: 5
Registered: February 2008
Junior Member
Hi!
I'm using symfony 1.1 with extJs2Plugin.
I've just copied (not actually installed) sfExtjsThemePlugin.
If i edit my generator.yml for some module so it uses extjstheme, it throws lots of errors. I can fix some of them by modifying plugin's code, but i don't think this's a good solution.
So, the questions are:
1) Have you tried using extJsTheme with symfony 1.1?
2) Is it better to write a new theme from scratch using extJs if i only need sortable tables and forms for creating/editing elements, one-to-many and many-to-many relationships?
Re: Building Own Generator [message #56174 is a reply to message #56165 ] Mon, 14 July 2008 22:55 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Hi xnutsive,

this plugin hasn't been tested or created for SF1.1
I don't know if it would be wise to rewrite everything from scratch to support 1.1 There is a lot of stuff in this plugin which can be reused, but I can't tell what exactly needs to be changed, since I am working on SF1.0 only until I am graduated.

After that 1.2 will be released soon, and I would very much like to make it work under 1.2 So I think I will probably skip the 1.1 release.

I don't think it is possible to implement all features currently supported from scratch before the 1.2 release. there is too much implemented for that, so maybe it is wiser to use Sf1.0 instead?


Leon
Re: Building Own Generator [message #56202 is a reply to message #56174 ] Tue, 15 July 2008 06:36 Go to previous messageGo to next message
xnutsive  is currently offline xnutsive
Messages: 5
Registered: February 2008
Junior Member
Yeap...
I've decided to use your code as much as it's possible.
So, may be, i'll try it on 1.0, or, if it would be possible, i'll make it work with 1.1 release.
(It seems the only trouble is sfEvent architecture and new sfForms. I think i can fix it. The bad thing is that i have only two weeks until the project release.)
Re: Building Own Generator [message #56522 is a reply to message #56202 ] Sat, 19 July 2008 19:25 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Pure magic has been implemented!

'Using' has been replaced with Ext-BaseX 3.0 from Doug Hendricks, this together with an idea from KRavEN and some changes to ExtJs itself makes it possible to automagically show your modules edit and grid-panels!

all you have to do is write something like:
      var editWindow = new Ext.Window({
        items       : [
            {
                xtype       : ('Edit' + this.relatedModuleName + 'FormPanel').toLowerCase()
            }
        ]
      });
      editWindow.show();

And Extjs automatically loads the Object from the server when it has (automatically) found out that the xtype isn't registered yet! After that the instantiation of the panel for the window has been made, et Voila you have a edit-window for this module, without the need to include any (p)js-script!

There is one downside at the moment, I cannot make it work with script-injection into your documents header. So you won't be able to debug your javascript with firebug. BaseX3.0 is capable of injecting scripts into the header, but the instantiation of the object(panel) is done too fast, even though your browser has loaded the (pjs)script it didn't had time to evaluate its content while the browser already tries to create the panel... I haven't found out yet how to get around this, making it wait for an on-ready event or something, before continuing.
The advantage of this is that when you request a pjs-script while you are logged-out the script is being re-requested without a problem after successful login.


The only thing you have to do to make this work is update the svn for the sfExtjs2Plugin (which contains a hacked ExtJS (feature request is done at ExtJs)) and sfExtjsThemePlugin.
After that you should add the module which sfExtjTheme now has in your settings.yml enabled_modules
    enabled_modules:        [default, ajaxWebdebug, sfExtjsThemePluginXtypeManager]

This module makes it possible to automatically resolve the correct module/action for a given xtype.

A demo can again be found at http://tejohnston.dynora.eu/ (admin admin)


Leon
Re: Building Own Generator [message #56780 is a reply to message #24107 ] Wed, 23 July 2008 01:14 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Here a screenshot of what can be accomplished from the generator.yml config:

http://s7.directupload.net/images/080723/udi96x7r.png

you see
- fields (among which custom xtypes)
- fieldsets
- tabpages (recursive)
- panels below each other (overrule the default tabpanel-xtype)
- column-layouts

the code to accomplish this:
    edit:
      params:
        width: fill

      newtitle: "New parcel"
      title:  "Parcel: <b>%%subject%%</b>"

      content_xtype: contentpanel
      content_config:
        activeItem: 0

      display: [subject, instructions_made, +assignment_id]

      pages: # tabpages
        general:
          title: <img src="/images/barrel.png"/> General

          params:
            xtype: panel  # this panel will contain other panels, by default pages will be shown in tabpanels, but you can overrule the contain's xtype, this way you get pages below each other...

          pages:
            general_top:
              params:
                layout: column
                header: false

              display:
                "Product":    [product_id/name, country_id/name, quantity, stowage]
                "Survey":     [installation, ex_tank, contract]

              "params_Product":
                columnWidth: 0.5
                style: "margin:5px;"
              "params_Survey":
                columnWidth: 0.5
                style: "margin:5px;"

            general_bottom:
              params:
                header: false

              display:
                "Analysis":   [_todo]


        bl:
          title: <img src="/sfExtjsThemePlugin/images/silk_icons/icons/folder_page.png"/> Bill of Lading
          display:
            "Bill of Lading":     [number_of_bls, _bls, bl_to_agent]



Leon
Re: Building Own Generator [message #56848 is a reply to message #56780 ] Wed, 23 July 2008 15:54 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Hello All,

if you are user, or not (anymore) of this plugin, would you please help me and fill in my little poll and give some feedback which I can use for my master-thesis: http://www.symfony-project.org/forum/index.php/m/56847/#msg_ 56847

Thanks in advance


Leon
Re: Building Own Generator [message #56909 is a reply to message #24107 ] Thu, 24 July 2008 09:31 Go to previous messageGo to next message
BuGgZzY  is currently offline BuGgZzY
Messages: 7
Registered: February 2006
Junior Member
Hi,

first thanks for the great work.
I've tried the latest city and country sample but didn't get it really to work.
If i call test_dev.php/city it throws this error Parse error:
syntax error, unexpected '<' in .../cache/test/dev/modules/autoCity/actions/actions.class.ph p on line 438.

In the cache file this error appears at line 438:

Undefined property: sfExtjsAdminColumn::$key in /www/sfdemo10/plugins/sfExtjsThemePlugin/data/generator/sfPr opelAdmin/extjs/template/actions/actions.class.php on line 762

Maby is it possible to get the latest country and city test. I've found something from May in this thread but at the wiki there is a test from April. Don't know which one is the latest which will work.

Re: Building Own Generator [message #56913 is a reply to message #56909 ] Thu, 24 July 2008 09:48 Go to previous messageGo to next message
xnutsive  is currently offline xnutsive
Messages: 5
Registered: February 2008
Junior Member
Yeap, i've experienced the same error in symfony 1.1 Wink
Re: Building Own Generator [message #56914 is a reply to message #24107 ] Thu, 24 July 2008 09:55 Go to previous messageGo to next message
BuGgZzY  is currently offline BuGgZzY
Messages: 7
Registered: February 2006
Junior Member
Well i changed from symfony 1.1 back to symfony 1.0 because most of the plugins will not work at this time. So this error also occurs in 1.0.18-PRE.
Re: Building Own Generator [message #56922 is a reply to message #24107 ] Thu, 24 July 2008 11:12 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
This plugin isn still Symfony 1.0 depended, don't know if I will make it 1.1 compatible since 1.2 is already on its way. The problem is that I can't seem to get in contact with Fabien and discuss his plans and make the plugin match the roadmap for 1.2

Fortunately 1.0 is still a great framework, but it would be nicer to keep the plugin compatible with the latest Symfony version. (It is not that I cannot do that without Fabien, but I think some of the work made for this plugin, can be put right back into the core generator.)

About the City-Country plugin, I will take a look at that and post a new version on the wiki. I post a new message after I've done that.

Last night I've came to a pretty cool conclusion, you can write Ext-code in the generator.yml files, since json and yml are very much a like! So you can use the Ext-Api directly in the generator.

An example, this would setup a tbar in Json:
new Ext.Panel({
	tbar : [
		{text: 'OK', handler: okHandler, scope: this} 
	]
});


And this is how it is done in Yml:
    edit:
      newtitle: "New Item"
      title: "Edit: <b>%%name%%</b>"

      params:
        tbar:
          - {text: 'Do something', cls: 'x-btn-text-icon btn_create', handler: this.doSomething, scope: this}
          - {text: 'Or something', cls: 'x-btn-text-icon btn_mail', handler: "function(){alert('Easy');}", scope: 'this'}

        bbar: [{text: 'this is also valid'},{text: 'looks more similar but less easy to read'}]

      display:
        General: [name, other, fields]


Thanks to the brilliance of the sfExtjs2plugin with its quote except function it doesn't matter if you place ' around your values (like this for the scope).


Leon
Re: Building Own Generator [message #56924 is a reply to message #24107 ] Thu, 24 July 2008 11:32 Go to previous messageGo to next message
andrea.extera  is currently offline andrea.extera
Messages: 9
Registered: July 2008
Location: San Marino
Junior Member
hello,
i have tryed several times to install this plugin following the instruction contained in the page of the plugin but i never obtained something working Sad
in addition the downloadable example isn't complete at all.

i saw the sample at http://tejohnston.dynora.eu/ and i'm wondering if it is possible to have a sandbox of that project. maybe the author of this plugin can give me that?

thank you
Re: Building Own Generator [message #56926 is a reply to message #56924 ] Thu, 24 July 2008 11:37 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
That author will again be me Wink

Unfortunately I cannot give that as a sandbox, since it contains too much info about the specific company for competitive reasons.

I can try to change it somewhat and make it a sandbox.


Leon
Re: Building Own Generator [message #56927 is a reply to message #56922 ] Thu, 24 July 2008 11:40 Go to previous messageGo to next message
xnutsive  is currently offline xnutsive
Messages: 5
Registered: February 2008
Junior Member
You know, working with that plugin and trying to set it up to work with 1.1 i've understood one thing: it's a really GREAT job, thank you!

And.. a will agree with you, symfony 1.0 is quete cool and usable at the moment, still we have sfCompat, so i'd prefer using symfony 1.0 if i'd need Ext tables in my backend app.
However, it's no use to adaptize this plugin for 1.1, you better keep soldering on, untill 1.2 is done.
Re: Building Own Generator [message #56929 is a reply to message #24107 ] Thu, 24 July 2008 12:07 Go to previous messageGo to next message
andrea.extera  is currently offline andrea.extera
Messages: 9
Registered: July 2008
Location: San Marino
Junior Member
ok, I understand...

actually, the major problem i encountered is the installation, because it isn't well documented.. i know, write a godd documentation isn't not easy!

but if in some way you can pack your project i think will be a very good starting point!
Re: Building Own Generator [message #56933 is a reply to message #56926 ] Thu, 24 July 2008 13:46 Go to previous messageGo to next message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
The wiki contains a new Example: sfExtjsThemeExample.tgz
http://trac.symfony-project.org/wiki/sfExtjsThemePlugin

you have to checkout the latest version from sfExtjs2Plugin and sfExtjsThemePlugin yourself... (since these are quite large)

Maybe you also have to restore the symlinks from the webfolder to the plugins/web-folder

After that setup the database in the config/databases.yml and config/propel.ini files, of course setup your database itself and prepare your web-server.

finally run
symfony propel-build-all-load backend

and you should be up and running

I've seen some votes on my request for feedback already, thanks for that. I would appreciate any text-feedback as well. So I want to but, .... Or Yes, and I use it for this and this... Thanks again
http://www.symfony-project.org/forum/index.php/m/56847/#msg_ 56847


Leon
Re: Building Own Generator [message #56936 is a reply to message #24107 ] Thu, 24 July 2008 14:36 Go to previous messageGo to next message
andrea.extera  is currently offline andrea.extera
Messages: 9
Registered: July 2008
Location: San Marino
Junior Member
great!
thank you very much!

i set to work instantly!

i will give you a feedback Very Happy
Re: Building Own Generator [message #56937 is a reply to message #56936 ] Thu, 24 July 2008 14:42 Go to previous messageGo to previous message
lvanderree  is currently offline lvanderree
Messages: 652
Registered: June 2007
Location: Netherlands
Faithful Member
Good to hear this is working.

Please provide feedback, if possible also to help other community members by providing improvements for the Example, or updates for the wiki.

Have fun!


Leon
Previous Topic:i18n form question
Next Topic:German symfony workshops/trainings
Goto Forum:
  

powered by FUDforum - copyright ©2001-2004 FUD Forum Bulletin Board Software