Index: storm.js
===================================================================
--- storm.js	(revision 692)
+++ storm.js	(working copy)
@@ -2,41 +2,24 @@
 
 function storm_empty_select(_select) {
   if(_select == undefined) return;
-  for (var i=_select.length-1; i>=0; i--) {
-    _select.remove(i);
-  }
+  $(_select).html('');
 };
 
 function storm_fill_select(_select, _items, _with_all_option, _all_text) {
-  if(_select == undefined) return;
-
+  var output = '';
   if(_with_all_option) {
-    opt=new Option();
-    opt.value = 0;
-    opt.text = _all_text;
-    try
-    {
-      _select.add(opt, null); // standards compliant
-    }
-    catch(ex)
-    {
-      _select.add(opt); // IE only
-    }
+    output += '<option value="0">' + _all_text + '</option>';
   }
-
   for (key in _items) {
-    opt=new Option();
-    opt.value = key;
-    opt.text = _items[key];
-    try
-    {
-      _select.add(opt, null); // standards compliant
+    if (typeof _items[key] == 'string') {
+      output += '<option value="' + key + '">' + _items[key] + '</option>';
     }
-    catch(ex)
-    {
-      _select.add(opt); // IE only
+    else {
+      output += '<optgroup label="' + key + '">' + storm_fill_select(undefined, _items[key], false, _all_text) + '</optgroup>';
     }
   }
+  if(_select == undefined) return output;
+  $(_select).html(output);
 };
 
 function storm_popup(sender, name, title, width, height, content_id, position) {
Index: storm.module
===================================================================
--- storm.module	(revision 692)
+++ storm.module	(working copy)
@@ -793,3 +793,155 @@
     }
   }
 }
+
+/**
+ * Get a list of people and teams for select boxes
+ *
+ * Params:
+ *  $organization_nid
+ *    Leave blank to get a list of all teams and persons, otherwise also provide
+ *  $project_nid
+ *    to get a limited list of teams and persons following the following logic:
+ *    - If the project is assigned to a person, only that person is listed as an option
+ *    - If the project is assigned to a team, all team members are listed as options
+ *    - If the project is neither assigned to a person nor a team, all people that are
+ *      assigned to the given origanization are listed as options
+ *    - In addition, if the project is assigned to a manager, that person is also listed
+ *    - Finally, look into all existing teams and list those teams that exclusively
+ *      contain members that are already selected
+ *    If $organization_nid is provided but $project_nid is omitted, then the logic is as
+ *    above, just for all projects of the given organization.
+ *
+ */
+function storm_get_assignment_options($organization_nid = 0, $project_nid = 0) {
+  $teams = t('Teams:');
+  $people = t('People:');
+  $options = array();
+  if (!$organization_nid) {
+    $options['all'] = t('- no filter -');
+    $options['mine'] = t('- mine -');
+  }
+  $options['none'] = t('- unassigned -');
+  if (module_exists('stormteam')) {
+    $options[$teams] = array();
+  }
+  if (module_exists('stormperson')) {
+    $options[$people] = array();
+  }
+  $add_org_people = TRUE;
+  if ($organization_nid) {
+    $add_org_people = FALSE;
+    $manager = array();
+    $projects = array();
+    if ($project_nid) {
+      $projects[] = $project_nid;
+    }
+    else {
+      $sql  = "SELECT n.nid FROM {node} AS n
+        INNER JOIN {stormproject} AS spr
+          ON n.vid=spr.vid
+        WHERE n.status=1
+          AND n.type='stormproject'
+          AND spr.organization_nid=%d";
+      $sql = stormproject_access_sql($sql);
+      $result = db_query(db_rewrite_sql($sql), $organization_nid);
+      while ($project = db_fetch_object($result)) {
+        $projects[] = $project->nid;
+      }
+      $add_org_people = TRUE;
+    }
+    foreach ($projects as $pid) {
+      $project = node_load($pid);
+      if ($project->manager_nid) {
+        $manager[] = node_load($project->manager_nid);
+      }
+      if ($project->assigned_nid) {
+        $node = node_load($project->assigned_nid);
+        if ($node->type == 'stormperson') {
+          if (module_exists('stormperson')) {
+            $options[$people][$node->nid] = $node->title;
+          }
+        }
+        else { // ($node->type == 'stormteam')
+          if (module_exists('stormteam')) {
+            $options[$teams][$node->nid] = $node->title;
+            foreach ($node->members_array as $nid => $name) {
+              $options[$people][$nid] = $name;
+            }
+          }
+        }
+      }
+      else {
+        $add_org_people = TRUE;
+      }
+    }
+  }
+  if ($add_org_people) {
+    if (module_exists('stormperson')) {
+      $where = isset($organization_nid) ? 'WHERE spe.organization_nid = %d' : '';
+      $sql = "SELECT  spe.nid,
+                      spe.fullname,
+                      n.title
+                  FROM {node} n
+                  INNER JOIN {stormperson} spe
+                    ON n.vid = spe.vid
+                  $where
+                  ORDER BY spe.fullname ASC";
+      $sql = stormperson_access_sql($sql);
+      $sql = db_rewrite_sql($sql);
+      $result = db_query($sql, array($organization_nid));
+      while ($person = db_fetch_object($result)) {
+        $options[$people][$person->nid] = ($person->fullname) ? $person->fullname : $person->title;
+        if (empty($options[$people][$person->nid])) {
+          $options[$people][$person->nid] = t('Person !nid', array('!nid' => $person->nid));
+        }
+      }
+    }
+  }
+  else {
+    if (isset($manager) && module_exists('stormperson')) {
+      foreach ($manager as $manager_node) {
+        if (!array_key_exists($manager_node->nid, $options[$people])) {
+          $options[$people][$manager_node->nid] = $manager_node->title;
+        }
+      }
+    }
+  }
+  if (module_exists('stormteam')) {
+    $sql = "SELECT  n.nid,
+                    n.title,
+                    ste.members
+                FROM {node} n
+                INNER JOIN {stormteam} ste
+                  ON n.vid = ste.vid
+                WHERE n.type = 'stormteam'
+                ORDER BY n.title ASC";
+    $sql = stormteam_access_sql($sql);
+    $sql = db_rewrite_sql($sql);
+    $result = db_query($sql);
+    while ($team = db_fetch_object($result)) {
+      if (!array_key_exists($team->nid, $options[$teams])) {
+        $add_team = TRUE;
+        if (isset($organization_nid)) {
+          //Check if all team members are relevant to current org or project
+          foreach (unserialize($team->members) as $nid => $name) {
+            if (!array_key_exists($nid, $options[$people])) {
+              $add_team = FALSE;
+              break;
+            }
+          }
+        }
+        if ($add_team) {
+          $options[$teams][$team->nid] = $team->title;
+        }
+      }
+    }
+  }
+  if (!sizeof($options[$people])) {
+    unset($options[$people]);
+  }
+  if (!sizeof($options[$teams])) {
+    unset($options[$teams]);
+  }
+  return $options;
+}
Index: stormnote/stormnote.admin.inc
===================================================================
--- stormnote/stormnote.admin.inc	(revision 692)
+++ stormnote/stormnote.admin.inc	(working copy)
@@ -167,7 +167,7 @@
     '#title' => t('Organization'),
     '#default_value' => $organization_nid,
     '#options' => $organizations,
-    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-task-nid', true, 'All')"),
+    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-task-nid', '', true, 'All')"),
   );
 
   $s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormproject} AS spr ON spr.vid=n.vid
@@ -186,7 +186,7 @@
     '#default_value' => $project_nid,
     '#options' => $projects,
     '#process' => array('storm_dependent_select_process'),
-    '#attributes' => array('onchange' => "stormtask_project_tasks(this, 'edit-task-nid', true, 'All')"),
+    '#attributes' => array('onchange' => "stormtask_project_tasks('edit-organization-nid', this, 'edit-task-nid', '', true, 'All')"),
   );
 
   $s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormtask} AS sta ON sta.nid=n.nid WHERE n.status=1 AND n.type='stormtask' AND sta.project_nid=%d ORDER BY title ";
Index: stormnote/stormnote.module
===================================================================
--- stormnote/stormnote.module	(revision 692)
+++ stormnote/stormnote.module	(working copy)
@@ -292,7 +292,7 @@
     '#default_value' => $node->organization_nid,
     '#options' => $organizations,
     '#required' => true,
-    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-parent-nid', true, '-')"),
+    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-parent-nid', '', true, '-')"),
   );
 
   $s = "SELECT n.nid, n.title FROM {node} n INNER JOIN {stormproject} spr ON spr.vid=n.vid WHERE spr.organization_nid=%d AND n.status=1 AND n.type='stormproject' ORDER BY n.title";
@@ -309,7 +309,7 @@
     '#default_value' => $node->project_nid,
     '#options' => array(0 => '-') + $projects,
     '#process' => array('storm_dependent_select_process'),
-    '#attributes' => array('onchange' => "stormtask_project_tasks(this, 'edit-task-nid', true, '-')"),
+    '#attributes' => array('onchange' => "stormtask_project_tasks('edit-organization-nid', this, 'edit-task-nid', '', true, '-')"),
   );
 
   $tree = _stormtask_get_tree($node->project_nid);
Index: stormtask/stormtask.admin.inc
===================================================================
--- stormtask/stormtask.admin.inc	(revision 692)
+++ stormtask/stormtask.admin.inc	(working copy)
@@ -405,6 +405,12 @@
   exit();
 }
 
+function _stormtask_project_assignments_js($organization_nid, $project_nid) {
+  $assignments = storm_get_assignment_options($organization_nid, $project_nid);
+  print drupal_to_js($assignments);
+  exit();
+}
+
 function stormtask_list() {
   $breadcrumb = array();
   $breadcrumb[] = l(t('Storm'), 'storm');
Index: stormtask/stormtask.js
===================================================================
--- stormtask/stormtask.js	(revision 692)
+++ stormtask/stormtask.js	(working copy)
@@ -1,6 +1,6 @@
 // $Id: stormtask.js,v 1.1.4.1 2009/04/13 11:35:03 magnity Exp $
 
-function stormtask_project_tasks(_project_select, _task_select_id, _with_all_option, _all_text) {
+function stormtask_project_tasks(_organization_select_id, _project_select, _task_select_id, _assign_select_id, _with_all_option, _all_text) {
   var task_select = $("#" + _task_select_id).get(0);
   storm_empty_select(task_select);
   var project_nid = _project_select.value;
@@ -16,11 +16,30 @@
       storm_fill_select(task_select, items, _with_all_option, _all_text);
     }
   });
+
+  var organization_select = $("#" + _organization_select_id).get(0);
+  var organization_nid = organization_select.value;
+  if (!organization_nid) organization_nid=0;
+  var assign_select = $("#" + _assign_select_id).get(0);
+  if (assign_select) {
+    storm_empty_select(assign_select);
+    $.ajax({
+      type: "GET",
+      async: true,
+      url: Drupal.settings.storm.project_assignments_url + Drupal.encodeURIComponent(organization_nid) + '/' + Drupal.encodeURIComponent(project_nid),
+      dataType: "string",
+      success: function (data) {
+        var items = Drupal.parseJson(data);
+        storm_fill_select(assign_select, items, false, _all_text);
+      }
+    });
+  }
 };
 
-function stormtask_organization_project_tasks(_organization_select, _project_select_id, _task_select_id, _with_all_option, _all_text) {
+function stormtask_organization_project_tasks(_organization_select, _project_select_id, _task_select_id, _assign_select_id, _with_all_option, _all_text) {
   stormproject_organization_projects(_organization_select, _project_select_id, _with_all_option, _all_text);
   var project_select = $("#" + _project_select_id).get(0);
-  stormtask_project_tasks(project_select, _task_select_id, _with_all_option, _all_text);
+  var _organization_select_id = $(_organization_select).attr('id');
+  stormtask_project_tasks(_organization_select_id, project_select, _task_select_id, _assign_select_id, _with_all_option, _all_text);
 };
 
Index: stormtask/stormtask.module
===================================================================
--- stormtask/stormtask.module	(revision 692)
+++ stormtask/stormtask.module	(working copy)
@@ -39,7 +39,8 @@
 function stormtask_init() {
   $settings = array(
     'storm' => array(
-      'project_tasks_url' => url('storm/project_tasks_js/')
+      'project_tasks_url' => url('storm/project_tasks_js/'),
+      'project_assignments_url' => url('storm/project_assignments_js/'),
     ),
   );
   drupal_add_js($settings, 'setting');
@@ -235,6 +236,14 @@
     'file' => 'stormtask.admin.inc',
     'type' => MENU_CALLBACK,
   );
+  $items['storm/project_assignments_js/%'] = array(
+    'title' => 'Assignments',
+    'page callback' => '_stormtask_project_assignments_js',
+    'page arguments' => array(2, 3),
+    'access arguments' => array('Storm task: access'),
+    'file' => 'stormtask.admin.inc',
+    'type' => MENU_CALLBACK,
+  );
   $items['storm/tasks'] = array(
     'title' => 'Tasks',
     'description' => 'Storm Tasks',
@@ -477,7 +486,7 @@
     '#default_value' => $node->organization_nid,
     '#options' => $organizations,
     '#required' => true,
-    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-parent-nid', true, '-')"),
+    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-parent-nid', 'edit-assigned-nid', true, '-')"),
   );
   
   $s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormproject} AS spr ON spr.vid=n.vid
@@ -497,7 +506,7 @@
     '#options' => $projects,
     '#process' => array('storm_dependent_select_process'),
     '#required' => true,
-    '#attributes' => array('onchange' => "stormtask_project_tasks(this, 'edit-parent-nid', true, '-')"),
+    '#attributes' => array('onchange' => "stormtask_project_tasks('edit-organization-nid', this, 'edit-parent-nid', 'edit-assigned-nid', true, '-')"),
   );
   
   $form['group1']['project_nid_old'] = array(
@@ -655,34 +664,8 @@
     '#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group5') : -16,
   );
   
-  $options = array(0 => '-');
-  
-  if (module_exists('stormperson')) {
-    $s_per = "SELECT n.nid, n.title FROM {node} n INNER JOIN {stormperson} spe ON n.vid=spe.vid WHERE n.type='stormperson' ORDER BY n.title";
-    $s_per = stormperson_access_sql($s_per);
-    $s_per = db_rewrite_sql($s_per);
-    $r_per = db_query($s_per);
-    $people = array();
-    while ($person = db_fetch_object($r_per)) {
-      $people[$person->nid] = $person->title;
-    }
-    
-    $options = $options + array(-1 => '-PEOPLE-') + $people;
-  }
-  
-  if (module_exists('stormteam')) {
-    $s_team = "SELECT n.nid, n.title FROM {node} n INNER JOIN {stormteam} ste ON n.vid=ste.vid WHERE n.type='stormteam' ORDER BY n.title";
-    $s_team = stormteam_access_sql($s_team);
-    $s_team = db_rewrite_sql($s_team);
-    $r_team = db_query($s_team);
-    $teams = array();
-    while ($team = db_fetch_object($r_team)) {
-      $teams[$team->nid] = $team->title;
-    }
-    
-    $options = $options + array(-2 => '-TEAMS-') + $teams;
-  }
-  
+  $options = storm_get_assignment_options($node->organization_nid, $node->project_nid);
+
   $form['group5']['assigned_nid'] = array(
     '#type' => 'select',
     '#title' => t('Assigned to'),
Index: stormticket/stormticket.admin.inc
===================================================================
--- stormticket/stormticket.admin.inc	(revision 692)
+++ stormticket/stormticket.admin.inc	(working copy)
@@ -273,7 +273,7 @@
     '#title' => t('Organization'),
     '#default_value' => $organization_nid,
     '#options' => $organizations,
-    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-task-nid', true, 'All')"),
+    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-task-nid', 'edit-assigned-nid', true, 'All')"),
   );
 
   $s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormproject} AS spr ON spr.vid=n.vid
@@ -292,7 +292,7 @@
     '#default_value' => $project_nid,
     '#options' => $projects,
     '#process' => array('storm_dependent_select_process'),
-    '#attributes' => array('onchange' => "stormtask_project_tasks(this, 'edit-task-nid', true, 'All')"),
+    '#attributes' => array('onchange' => "stormtask_project_tasks('edit-organization-nid', this, 'edit-task-nid', 'edit-assigned-nid', true, 'All')"),
   );
 
   $s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormtask} AS sta
Index: stormticket/stormticket.js
===================================================================
--- stormticket/stormticket.js	(revision 692)
+++ stormticket/stormticket.js	(working copy)
@@ -30,7 +30,7 @@
 };
 
 function stormticket_project_task_tickets(_project_select, _organization_select_id, _task_select_id, _ticket_select_id, _with_all_option, _all_text) {
-  stormtask_project_tasks(_project_select, _task_select_id, _with_all_option, _all_text);
+  stormtask_project_tasks(_organization_select_id, _project_select, _task_select_id, '', _with_all_option, _all_text);
   var task_select = $("#" + _task_select_id).get(0);
   stormticket_task_tickets(task_select, _organization_select_id, _project_select.id, _ticket_select_id, _with_all_option, _all_text);
 };
Index: stormticket/stormticket.module
===================================================================
--- stormticket/stormticket.module	(revision 692)
+++ stormticket/stormticket.module	(working copy)
@@ -389,7 +389,7 @@
     '#default_value' => $node->organization_nid,
     '#options' => $organizations,
     '#required' => TRUE,
-    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-parent-nid', true, '-')"),
+    '#attributes' => array('onchange' => "stormtask_organization_project_tasks(this, 'edit-project-nid', 'edit-parent-nid', 'edit-assigned-nid', true, '-')"),
   );
   
   $s = "SELECT n.nid, n.title FROM {node} AS n INNER JOIN {stormproject} AS spr ON spr.vid=n.vid WHERE spr.organization_nid=%d AND n.status=1 AND n.type='stormproject' ORDER BY n.title";
@@ -406,7 +406,7 @@
     '#default_value' => $node->project_nid,
     '#options' => array(0 => '-') + $projects,
     '#process' => array('storm_dependent_select_process'),
-    '#attributes' => array('onchange' => "stormtask_project_tasks(this, 'edit-task-nid', true, '-')"),
+    '#attributes' => array('onchange' => "stormtask_project_tasks('edit-organization-nid', this, 'edit-task-nid', 'edit-assigned-nid', true, '-')"),
   );
 
   $tree = _stormtask_get_tree($node->project_nid);
@@ -533,34 +533,8 @@
     '#weight' => module_exists('content') ? content_extra_field_weight($node->type, 'group5') : -16,
   );
   
-  $options = array(0 => '-');
+  $options = storm_get_assignment_options($node->organization_nid, $node->project_nid);
   
-  if (module_exists('stormperson')) {
-    $s_per = "SELECT n.nid, n.title FROM {node} n INNER JOIN {stormperson} spe ON n.vid=spe.vid WHERE n.type='stormperson' ORDER BY n.title";
-    $s_per = stormperson_access_sql($s_per);
-    $s_per = db_rewrite_sql($s_per);
-    $r_per = db_query($s_per);
-    $people = array();
-    while ($person = db_fetch_object($r_per)) {
-      $people[$person->nid] = $person->title;
-    }
-    
-    $options = $options + array(-1 => '-PEOPLE-') + $people;
-  }
-  
-  if (module_exists('stormteam')) {
-    $s_team = "SELECT n.nid, n.title FROM {node} n INNER JOIN {stormteam} ste ON n.vid=ste.vid WHERE n.type='stormteam' ORDER BY n.title";
-    $s_team = stormteam_access_sql($s_team);
-    $s_team = db_rewrite_sql($s_team);
-    $r_team = db_query($s_team);
-    $teams = array();
-    while ($team = db_fetch_object($r_team)) {
-      $teams[$team->nid] = $team->title;
-    }
-    
-    $options = $options + array(-2 => '-TEAMS-') + $teams;
-  }
-  
   $form['group5']['assigned_nid'] = array(
     '#type' => 'select',
     '#title' => t('Assigned to'),
