2014-01-08 1 views
1

결함을 기반으로하는 사용자 정의 그리드 쿼리를 사용할 때 나는 종종 연결된 사용자 스토리의 태그를 기준으로 필터링합니다. 실제 기능 계층 구조를 사용하고 싶습니다. 예 : 링크 된 기사가 주어진 기능이나 이니셔티브 아래에있는 모든 결함을 보여줍니다. 문서를 보면서이 작업을 수행 할 수 없습니다.특정 기능에 대한 요구 사항과 결함 위치를 쿼리하는 방법

답변

0

태그 속성은 Requirement가 상속하는 Artifact 객체에 존재하므로 Requirement.Tags를 탐색 할 수 있습니다. 지형지 물 속성이 요구 사항에 없습니다. 요구 사항을 상속 한 HierarchicalRequirement에 있으므로 Requirement.Feature를 통과 할 수 없습니다. 이 컨텍스트에서는 사용자 지정 그리드가 적합한 선택이 아닐 수 있습니다. 하지만 모든 관계를 보여주는 맞춤 앱을 작성할 수 있습니다. 다음은 두 가지 콤보 상자가있는 맞춤 앱입니다. 출시와 기능. 기능 콤보 상자는 릴리스 콤보 상자의 선택 내용을 기반으로 채워집니다. 두 번째 콤보 상자에서 지형지 물을 선택하면 그 지형지 물에 연결된 지형지 물의 하위 사례 및 결함 (있는 경우)이 모눈에 채워집니다. 전체 코드 in this repo이 표시되고 html file을 사용자 정의 페이지로 복사 할 수 있습니다.

Ext.define('CustomApp', { 
    extend: 'Rally.app.TimeboxScopedApp', 
    componentCls: 'app', 
    scopeType: 'release', 
    comboboxConfig: { 
     fieldLabel: 'Select a Release:', 
     labelWidth: 100, 
     width: 300 
    }, 
    addContent: function() { 
     this._makeCombobox(); 
    }, 

    onScopeChange: function() { 
     this._makeCombobox(); 
    }, 

    _makeCombobox: function() { 
    if (this.down('#features')) { 
     this.down('#features').destroy(); 
    } 
    var features = Ext.create('Rally.ui.combobox.ComboBox',{ 
     id: 'features', 
     storeConfig: { 
     model: 'PortfolioItem/Feature', 
     fetch: ['FormattedID','Name','Release', 'UserStories'], 
     pageSize: 100, 
     autoLoad: true, 
     filters: [this.getContext().getTimeboxScope().getQueryFilter()] 
     }, 
     fieldLabel: 'select Feature', 
     listeners:{ 
       ready: function(combobox){ 
      if (combobox.getRecord()) { 
      console.log('ready',combobox.getRecord().get('_ref')); 
      this._onFeatureSelected(combobox.getRecord()); 
      } 
      else{ 
      console.log('selected release has no features'); 
      if (this.down('#grid')) { 
       this.down('#grid').destroy(); 
      } 
      } 
     }, 
       select: function(combobox){ 
      if (combobox.getRecord()) { 
      console.log('select',combobox.getRecord().get('_ref')); 
      this._onFeatureSelected(combobox.getRecord()); 
      } 

       }, 
       scope: this 
      } 
    }); 
    this.add(features); 
    }, 
    _onFeatureSelected:function(feature){ 
    console.log('feature', feature.get('Name')); 

    var f = { 
      FormattedID: feature.get('FormattedID'), 
      Name: feature.get('Name'), 
      _ref: feature.get("_ref"), 
      UserStories: [] 
     }; 

    var collection = feature.getCollection('UserStories', {fetch: ['Name','FormattedID','Owner', 'Defects']}); 
    var that = this; 
    var count = collection.getCount(); 
    console.log(count); 
    var stories = []; 
    var pendingStories = count; 
     collection.load({ 
      callback: function(records, operation, success){ 
       Ext.Array.each(records, function(story){ 
      var s = { 
           FormattedID: story.get('FormattedID'), 
           Name: story.get('Name'), 
           _ref: story.get("_ref"), 
           DefectCount: story.get('Defects').Count, 
           Defects: [] 
          }; 
       var defects = story.getCollection('Defects'); 
       var defectcount = defects.getCount(); 
       var pendingDefects = defectcount; 
       defects.load({ 
           fetch: ['FormattedID'], 
           callback: function(records, operation, success){ 
            Ext.Array.each(records, function(defect){ 
             s.Defects.push({_ref: defect.get('_ref'), 
                 FormattedID: defect.get('FormattedID') 
                }); 
            }, this); 

            --pendingDefects; 
            if (pendingDefects === 0) { 
        console.log(story.get('FormattedID') + ' - ' + story.get('Name')); 
        --pendingStories; 
        if (pendingStories === 0) { 
         console.log('stories inside callback',stories); 
        } 

            } 
        console.log('makeGrid'); 
            that._makeGrid(stories); 
           }, 
           scope: this 
          }); 
      stories.push(s); 
      }, this);   
     } 

     }); 
    }, 

    _makeGrid: function(stories) { 
    var c = Ext.create('Ext.Container', { 
     layout: { 
     type: 'absolute' 
     }, 
     x: 400 
    }); 
    this.add(c); 
     this._store = Ext.create('Rally.data.custom.Store', { 
       data: stories, 
       pageSize: 100, 
       remoteSort:false 
      }); 

     if (!this.down('#grid')){ 
     c.add({ 
      xtype: 'rallygrid', 
      itemId: 'grid', 
      store: this._store, 
      columnCfgs: [ 
       { 
        text: 'Formatted ID', dataIndex: 'FormattedID', xtype: 'templatecolumn', 
        tpl: Ext.create('Rally.ui.renderer.template.FormattedIDTemplate') 
       }, 
       { 
        text: 'Name', dataIndex: 'Name' 
       }, 
     { 
        text: 'Defect Count', dataIndex: 'DefectCount' 
       }, 
       { 
        text: 'Defects', dataIndex: 'Defects', 
        renderer: function(value) { 
         var html = []; 
         Ext.Array.each(value, function(defect){ 
          html.push('<a href="' + Rally.nav.Manager.getDetailUrl(defect) + '">' + defect.FormattedID + '</a>') 
         }); 
         return html.join(', '); 
        } 
       } 
      ] 

     }); 
     } 
     else{ 
      this.down('#grid').reconfigure(this._store); 
     } 
    } 
}); 

enter image description here

: 여기

은 JS 파일입니다