|
77 | 77 | {name: 'changes', type: 'integer'},
|
78 | 78 | {name: 'diff', type: 'string'}
|
79 | 79 | ]
|
| 80 | + }); Ext.define('changeset.model.Organization', { |
| 81 | + extend: 'Ext.data.Model', |
| 82 | + idProperty: 'login', |
| 83 | + fields: [ |
| 84 | + {name: 'url', type: 'string'}, |
| 85 | + {name: 'login', type: 'string'} |
| 86 | + ] |
80 | 87 | }); Ext.define('changeset.model.Repository', {
|
81 | 88 | extend: 'Ext.data.Model',
|
82 | 89 | idProperty: 'name',
|
|
224 | 231 | * Base url for all Github api requests.
|
225 | 232 | */
|
226 | 233 | apiUrl: 'https://api.github.com',
|
227 |
| - |
| 234 | + |
228 | 235 | /**
|
229 | 236 | * @cfg {Int}
|
230 | 237 | * Page size to use for api calls.
|
|
237 | 244 |
|
238 | 245 | constructor: function(config) {
|
239 | 246 | Ext.apply(this, config);
|
240 |
| - |
| 247 | + |
241 | 248 | var urlParts = window.location.href.split('?');
|
242 | 249 | this.stateId = 'githubAdapter-' + urlParts[0];
|
243 | 250 | if (urlParts.length > 1) {
|
|
284 | 291 | username: this.username,
|
285 | 292 | authToken: this.authToken,
|
286 | 293 | repository: this.repository,
|
| 294 | + organization: this.organization, |
287 | 295 | branch: this.branch
|
288 | 296 | };
|
289 | 297 | },
|
|
296 | 304 | return 'Login to your GitHub account';
|
297 | 305 | },
|
298 | 306 |
|
| 307 | + /** |
| 308 | + * Get the currently logged in user's username |
| 309 | + * @return {String} |
| 310 | + */ |
| 311 | + getUserName: function() { |
| 312 | + return this.username; |
| 313 | + }, |
| 314 | + |
299 | 315 | /**
|
300 | 316 | * Return a url to the repository.
|
301 | 317 | * @return {String}
|
|
317 | 333 | * @param {changeset.model.Repository}
|
318 | 334 | */
|
319 | 335 | setRepository: function(repository) {
|
320 |
| - if( !this.repository || this.repository.name !== repository.raw.name ) { |
| 336 | + if( !this.repository || this.repository.name !== repository.get('name') ) { |
321 | 337 | this.branch = null;
|
322 | 338 | }
|
323 | 339 | this.repository = repository.raw;
|
324 | 340 | this.fireEvent('statechange', this);
|
325 | 341 | },
|
326 | 342 |
|
| 343 | + /* |
| 344 | + * Gets the currently selected organization. |
| 345 | + * @return {Object} |
| 346 | + */ |
| 347 | + getOrganization: function() { |
| 348 | + return this.organization; |
| 349 | + }, |
| 350 | + |
| 351 | + /* |
| 352 | + * Set the repository to fetch data from. |
| 353 | + * @param {changeset.model.Repository} |
| 354 | + */ |
| 355 | + setOrganization: function(organization) { |
| 356 | + if (!this.organization || this.organization.login !== organization.get('login')) { |
| 357 | + this.repository = null; |
| 358 | + this.branch = null; |
| 359 | + } |
| 360 | + this.organization = organization.raw || organization.data; |
| 361 | + this.fireEvent('statechange', this); |
| 362 | + }, |
| 363 | + |
327 | 364 | /*
|
328 | 365 | * Gets the currently selected branch.
|
329 | 366 | * @return {Object}
|
|
342 | 379 | },
|
343 | 380 |
|
344 | 381 | /**
|
345 |
| - * Constructs a store which populates repository models. |
| 382 | + * Constructs a store which populates organization models. |
346 | 383 | * @param {Function} callback Function to call after store is created.
|
347 | 384 | * @param {Object} scope Scope to execute callback with.
|
348 | 385 | */
|
349 |
| - getRepositoryStore: function(callback, scope) { |
| 386 | + getOrganizationStore: function(callback, scope) { |
350 | 387 | var url = [
|
351 | 388 | this.apiUrl,
|
352 |
| - 'user', |
353 |
| - 'repos' |
| 389 | + 'users', |
| 390 | + this.username, |
| 391 | + 'orgs' |
354 | 392 | ].join('/');
|
355 | 393 |
|
356 | 394 | var store = Ext.create('Ext.data.Store', {
|
357 |
| - model: 'changeset.model.Repository', |
| 395 | + model: 'changeset.model.Organization', |
358 | 396 | proxy: Ext.create('changeset.data.github.Proxy', {
|
359 | 397 | url: url
|
360 | 398 | })
|
|
363 | 401 | callback.call(scope, store);
|
364 | 402 | },
|
365 | 403 |
|
| 404 | + /** |
| 405 | + * Constructs a store which populates repository models. |
| 406 | + * @param {Function} callback Function to call after store is created. |
| 407 | + * @param {Object} scope Scope to execute callback with. |
| 408 | + */ |
| 409 | + getRepositoryStore: function(callback, scope) { |
| 410 | + var url = [this.apiUrl]; |
| 411 | + |
| 412 | + if (this.organization.url) { |
| 413 | + url = url.concat([ |
| 414 | + 'orgs', |
| 415 | + this.organization.login, |
| 416 | + 'repos' |
| 417 | + ]); |
| 418 | + } else { |
| 419 | + url = url.concat([ |
| 420 | + 'user', |
| 421 | + 'repos' |
| 422 | + ]); |
| 423 | + } |
| 424 | + |
| 425 | + var store = Ext.create('Ext.data.Store', { |
| 426 | + model: 'changeset.model.Repository', |
| 427 | + proxy: Ext.create('changeset.data.github.Proxy', { |
| 428 | + url: url.join('/') |
| 429 | + }), |
| 430 | + buffered: true, |
| 431 | + pageSize: this.pageSize, |
| 432 | + listeners: { |
| 433 | + load: { |
| 434 | + fn: function(store, records, successful, eOpts) { |
| 435 | + if (successful && records.length === store.pageSize) { |
| 436 | + store.prefetchPage(store.currentPage + 1); |
| 437 | + return false; |
| 438 | + } |
| 439 | + }, |
| 440 | + single: true |
| 441 | + }, |
| 442 | + prefetch: function(store, records, successful, operation, eOpts) { |
| 443 | + if (successful) { |
| 444 | + store.add(records); |
| 445 | + if (records.length === store.pageSize) { |
| 446 | + store.prefetchPage(store.currentPage + 1); |
| 447 | + } else { |
| 448 | + store.fireEvent('load'); |
| 449 | + } |
| 450 | + } |
| 451 | + } |
| 452 | + } |
| 453 | + }); |
| 454 | + |
| 455 | + callback.call(scope, store); |
| 456 | + }, |
| 457 | + |
366 | 458 | /**
|
367 | 459 | * Constructs a store which populates branch models.
|
368 | 460 | * @param {Function} callback Function to call after store is created.
|
|
462 | 554 | }
|
463 | 555 | })
|
464 | 556 | });
|
465 |
| - |
| 557 | + |
466 | 558 | callback.call(scope, store);
|
467 | 559 | },
|
468 | 560 |
|
|
513 | 605 | * @param {String} password Password to login with.
|
514 | 606 | */
|
515 | 607 | authenticate: function(username, password) {
|
516 |
| - this.username = username; |
| 608 | + this.username = username; |
517 | 609 |
|
518 | 610 | Ext.Ajax.request({
|
519 | 611 | url: this.apiUrl + '/authorizations',
|
|
548 | 640 | */
|
549 | 641 | logout: function() {
|
550 | 642 | this.repository = null;
|
| 643 | + this.organization = null; |
551 | 644 | this.branch = null;
|
552 | 645 | this.username = null;
|
553 | 646 | this.authToken = null;
|
|
600 | 693 | }
|
601 | 694 | },
|
602 | 695 |
|
603 |
| - _onBeforeAjaxRequest: function(ext, opts) { |
| 696 | + _onBeforeAjaxRequest: function(ext, opts) { |
604 | 697 | if (Ext.isEmpty(opts.headers)) {
|
605 | 698 | opts.headers = {};
|
606 | 699 | }
|
|
673 | 766 |
|
674 | 767 | model: 'changeset.model.Commit',
|
675 | 768 |
|
| 769 | + constructor: function() { |
| 770 | + this.callParent(arguments); |
| 771 | + this.on('beforeload', function(store, operation, eOpts) { |
| 772 | + this._addShaToOptions(1); |
| 773 | + }, this, {single:true}); |
| 774 | + }, |
| 775 | + |
676 | 776 | /**
|
677 | 777 | * Github's commit endpoint's paging is a little funky.
|
678 | 778 | *
|
|
1684 | 1784 | }]
|
1685 | 1785 | });
|
1686 | 1786 |
|
1687 |
| - this._addRepoChooser(); |
| 1787 | + this._addOrganizationChooser(); |
1688 | 1788 | },
|
1689 | 1789 |
|
1690 |
| - _addFilter: function() { |
1691 |
| - if (this.down('changesetfilter')) { |
1692 |
| - return; |
1693 |
| - } |
| 1790 | + _addOrganizationChooser: function() { |
| 1791 | + var toolbar = this.down('#topToolbar'), |
| 1792 | + valueField = 'login'; |
1694 | 1793 |
|
1695 |
| - var toolbar = this.down('#topToolbar'); |
1696 |
| - var filter = toolbar.insert(4, { |
1697 |
| - xtype: 'changesetfilter', |
1698 |
| - width: 210, |
1699 |
| - listeners: { |
1700 |
| - filter: this._onFilter, |
1701 |
| - afterrender: function(cmp) { |
1702 |
| - var tip = Ext.create('Rally.ui.tooltip.ToolTip', { |
1703 |
| - target: cmp.getEl(), |
1704 |
| - anchor: 'right', |
1705 |
| - hideDelay: 0, |
1706 |
| - html: 'Filter commits by: <br /> <ul><li>-- message</li><li>-- author</li><li>-- revision</li></ul>' |
1707 |
| - }); |
1708 |
| - }, |
1709 |
| - scope: this |
1710 |
| - } |
1711 |
| - }); |
| 1794 | + this.adapter.getOrganizationStore(function(store) { |
| 1795 | + var combo = toolbar.insert(2, { |
| 1796 | + xtype: 'rallycombobox', |
| 1797 | + margin: '0 5 0 0', |
| 1798 | + store: store, |
| 1799 | + fieldLabel: 'Org:', |
| 1800 | + labelWidth: 30, |
| 1801 | + displayField: valueField, |
| 1802 | + // allowNoEntry: true, |
| 1803 | + // noEntryText: this.adapter.getUserName(), |
| 1804 | + listeners: { |
| 1805 | + beforeselect: function(combo, record) { |
| 1806 | + if (record && record.get('login') !== this.adapter.getOrganization().login) { |
| 1807 | + this._onOrganizationSelect(record); |
| 1808 | + } |
| 1809 | + }, |
| 1810 | + scope: this |
| 1811 | + } |
| 1812 | + }); |
| 1813 | + |
| 1814 | + store.on('load', function() { |
| 1815 | + store.insert(0, [{login: this.adapter.getUserName(), url: null}]); |
| 1816 | + var org = this.adapter.getOrganization(), |
| 1817 | + selectedOrg = org ? store.findRecord('login', org.login) : store.getAt(0); |
| 1818 | + combo.select(selectedOrg); |
| 1819 | + this._onOrganizationSelect(selectedOrg); |
| 1820 | + }, this, {single: true}); |
| 1821 | + store.load(); |
| 1822 | + }, this); |
| 1823 | + }, |
| 1824 | + |
| 1825 | + _onOrganizationSelect: function(organization) { |
| 1826 | + this.adapter.setOrganization(organization); |
| 1827 | + this.removeAll(); |
| 1828 | + this._addRepoChooser(); |
1712 | 1829 | },
|
1713 | 1830 |
|
1714 | 1831 | _addRepoChooser: function() {
|
1715 |
| - var toolbar = this.down('#topToolbar'); |
1716 |
| - var valueField = 'name'; |
| 1832 | + var toolbar = this.down('#topToolbar'), |
| 1833 | + valueField = 'name', |
| 1834 | + combo = toolbar.down('#repoChooser'); |
| 1835 | + if (combo) { |
| 1836 | + toolbar.remove(combo); |
| 1837 | + } |
| 1838 | + |
1717 | 1839 | this.adapter.getRepositoryStore(function(store) {
|
1718 |
| - var combo = toolbar.insert(2, { |
| 1840 | + var combo = toolbar.insert(3, { |
1719 | 1841 | xtype: 'rallycombobox',
|
| 1842 | + itemId: 'repoChooser', |
1720 | 1843 | margin: '0 5 0 0',
|
1721 | 1844 | store: store,
|
1722 | 1845 | fieldLabel: 'Repo:',
|
|
1735 | 1858 | store.on('load', function() {
|
1736 | 1859 | var repo = this.adapter.getRepository();
|
1737 | 1860 | var selectedRepo = repo ? store.findRecord('name', repo.name) : store.getAt(0);
|
1738 |
| - combo.select(selectedRepo); |
1739 |
| - this._onRepositorySelect(selectedRepo); |
| 1861 | + if (selectedRepo) { |
| 1862 | + combo.select(selectedRepo); |
| 1863 | + this._onRepositorySelect(selectedRepo); |
| 1864 | + } |
1740 | 1865 | }, this, {single: true});
|
| 1866 | + |
1741 | 1867 | store.load();
|
1742 | 1868 | }, this);
|
1743 | 1869 | },
|
|
1757 | 1883 |
|
1758 | 1884 | var valueField = 'name';
|
1759 | 1885 | this.adapter.getBranchStore(function(store) {
|
1760 |
| - combo = toolbar.insert(3, { |
| 1886 | + combo = toolbar.insert(4, { |
1761 | 1887 | xtype: 'rallycombobox',
|
1762 | 1888 | itemId: 'branchChooser',
|
1763 | 1889 | margin: '0 5 0 0',
|
|
1776 | 1902 | });
|
1777 | 1903 |
|
1778 | 1904 | store.on('load', function() {
|
1779 |
| - var branch = this.adapter.getBranch(); |
1780 |
| - var selectedBranch = branch ? store.findRecord('name', branch.name) : store.getAt(0); |
| 1905 | + var currentBranch = this.adapter.getBranch(), |
| 1906 | + branchName = currentBranch ? currentBranch.name : 'master', |
| 1907 | + selectedBranch = store.findRecord('name', branchName); |
| 1908 | + selectedBranch = selectedBranch || store.getAt(0); |
| 1909 | + |
1781 | 1910 | combo.select(selectedBranch);
|
1782 | 1911 | this._onBranchSelect(selectedBranch);
|
1783 | 1912 | }, this, {single: true});
|
|
1792 | 1921 | this._addGrid();
|
1793 | 1922 | },
|
1794 | 1923 |
|
| 1924 | + _addFilter: function() { |
| 1925 | + if (this.down('changesetfilter')) { |
| 1926 | + return; |
| 1927 | + } |
| 1928 | + |
| 1929 | + var toolbar = this.down('#topToolbar'); |
| 1930 | + var filter = toolbar.insert(5, { |
| 1931 | + xtype: 'changesetfilter', |
| 1932 | + width: 210, |
| 1933 | + listeners: { |
| 1934 | + filter: this._onFilter, |
| 1935 | + afterrender: function(cmp) { |
| 1936 | + var tip = Ext.create('Rally.ui.tooltip.ToolTip', { |
| 1937 | + target: cmp.getEl(), |
| 1938 | + anchor: 'right', |
| 1939 | + hideDelay: 0, |
| 1940 | + html: 'Filter commits by: <br /> <ul><li>-- message</li><li>-- author</li><li>-- revision</li></ul>' |
| 1941 | + }); |
| 1942 | + }, |
| 1943 | + scope: this |
| 1944 | + } |
| 1945 | + }); |
| 1946 | + }, |
| 1947 | + |
1795 | 1948 | _addGrid: function() {
|
1796 | 1949 | var callback = function(store) {
|
1797 | 1950 | var grid = this.add({
|
|
0 commit comments