Repository: zeppelin Updated Branches: refs/heads/master 4a466d060 -> 8d18703e3
[ZEPELIN-2209] Add pagination to Helium menu ### What is this PR for? Like I did in #2126, added pagination to Helium menu in Zeppelin. 10 pkgs will be shown per 1 page. ### What type of PR is it? Improvement ### What is the Jira issue? [ZEPPELIN-2209](https://issues.apache.org/jira/browse/ZEPPELIN-2209) ### How should this be tested? 1. Replace temporarily [ZeppelinConfiguration.java#L46](https://github.com/apache/zeppelin/blob/master/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java#L46) with [this url](https://raw.githubusercontent.com/AhyoungRyu/spark-notebook-example/master/helium.json) 2. Build \w below command and restart Zeppelin server ``` $ mvn clean package -DskipTests -pl 'zeppelin-zengine, zeppelin-server, zeppelin-interpreter' ``` 3. Start web dev server under `ZEPPELIN_HOME/zeppelin-web` and browse `localhost:9000` ``` $ yarn run dev ``` 4. Go to Helium menu -> Click `INTERPRETER` btn (Currently the other types of pkg are registered in online registry less than 10. That's why I request to change online registry URI in step 1) 5. Check the pagination works well or not ### Screenshots (if appropriate)  ### Questions: * Does the licenses files need update? no * Is there breaking changes for older versions? no * Does this needs documentation? no Author: AhyoungRyu <fbdkdu...@hanmail.net> Closes #2174 from AhyoungRyu/add/paginationToHeliumMenu and squashes the following commits: ceab2c5 [AhyoungRyu] hide arrows when current page is on first & last 7150e7c [AhyoungRyu] Resolve confilct manually 5b7958f [AhyoungRyu] Fix pkg orderBy published 5a7674a [AhyoungRyu] Add pagination to Helium menu Project: http://git-wip-us.apache.org/repos/asf/zeppelin/repo Commit: http://git-wip-us.apache.org/repos/asf/zeppelin/commit/8d18703e Tree: http://git-wip-us.apache.org/repos/asf/zeppelin/tree/8d18703e Diff: http://git-wip-us.apache.org/repos/asf/zeppelin/diff/8d18703e Branch: refs/heads/master Commit: 8d18703e3b76b2c8d2d0cf6efab7644940849e7e Parents: 4a466d0 Author: AhyoungRyu <fbdkdu...@hanmail.net> Authored: Thu Mar 30 00:14:28 2017 +0900 Committer: ahyoungryu <ahyoung...@apache.org> Committed: Fri Mar 31 10:53:29 2017 +0900 ---------------------------------------------------------------------- .../src/app/helium/helium.controller.js | 62 ++++-- zeppelin-web/src/app/helium/helium.css | 24 ++ zeppelin-web/src/app/helium/helium.html | 222 ++++++++++--------- 3 files changed, 184 insertions(+), 124 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/zeppelin/blob/8d18703e/zeppelin-web/src/app/helium/helium.controller.js ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/helium/helium.controller.js b/zeppelin-web/src/app/helium/helium.controller.js index 0565ec1..615f811 100644 --- a/zeppelin-web/src/app/helium/helium.controller.js +++ b/zeppelin-web/src/app/helium/helium.controller.js @@ -37,9 +37,15 @@ export default function HeliumCtrl($scope, $rootScope, $sce, // get all package info and set config heliumService.getAllPackageInfoAndDefaultPackages() .then(({ pkgSearchResults, defaultPackages }) => { + // pagination + $scope.itemsPerPage = 10; + $scope.currentPage = 1; + $scope.maxSize = 5; + $scope.pkgSearchResults = pkgSearchResults; $scope.defaultPackages = defaultPackages; - classifyPkgType($scope.defaultPackages) + classifyPkgType($scope.defaultPackages); + return heliumService.getAllPackageConfigs() }) .then(defaultPackageConfigs => { @@ -52,38 +58,58 @@ export default function HeliumCtrl($scope, $rootScope, $sce, $scope.bundleOrder = visPackageOrder; $scope.bundleOrderChanged = false; }); - } + }; + + var orderPackageByPubDate = function(a, b) { + if (!a.pkg.published) { + // Because local registry pkgs don't have 'published' field, put current time instead to show them first + a.pkg.published = new Date().getTime() + } - var classifyPkgType = function(packageInfos) { - var vizTypePkg = {} - var spellTypePkg = {} - var intpTypePkg = {} - var appTypePkg = {} + return new Date(a.pkg.published).getTime() - new Date(b.pkg.published).getTime(); + }; + + var classifyPkgType = function(packageInfo) { + var allTypesOfPkg = {}; + var vizTypePkg = []; + var spellTypePkg = []; + var intpTypePkg = []; + var appTypePkg = []; - for (var name in packageInfos) { - var pkgs = packageInfos[name] - var pkgType = pkgs.pkg.type + var packageInfoArr = Object.keys(packageInfo).map(key => packageInfo[key]) + packageInfoArr = packageInfoArr.sort(orderPackageByPubDate).reverse(); + + for (var name in packageInfoArr) { + var pkgs = packageInfoArr[name]; + var pkgType = pkgs.pkg.type; switch (pkgType) { case HeliumType.VISUALIZATION: - vizTypePkg[name] = pkgs; + vizTypePkg.push(pkgs); break; case HeliumType.SPELL: - spellTypePkg[name] = pkgs; + spellTypePkg.push(pkgs); break; case HeliumType.INTERPRETER: - intpTypePkg[name] = pkgs; + intpTypePkg.push(pkgs); break; case HeliumType.APPLICATION: - appTypePkg[name] = pkgs; + appTypePkg.push(pkgs); break; } } - $scope.vizTypePkg = vizTypePkg - $scope.spellTypePkg = spellTypePkg - $scope.appTypePkg = appTypePkg - $scope.intpTypePkg = intpTypePkg + var pkgsArr = [ + vizTypePkg, + spellTypePkg, + intpTypePkg, + appTypePkg + ] + for (var idx in _.keys(HeliumType)) { + allTypesOfPkg[_.keys(HeliumType)[idx]] = pkgsArr[idx]; + } + + $scope.allTypesOfPkg = allTypesOfPkg; }; $scope.bundleOrderListeners = { http://git-wip-us.apache.org/repos/asf/zeppelin/blob/8d18703e/zeppelin-web/src/app/helium/helium.css ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/helium/helium.css b/zeppelin-web/src/app/helium/helium.css index 2e64df3..f44258c 100644 --- a/zeppelin-web/src/app/helium/helium.css +++ b/zeppelin-web/src/app/helium/helium.css @@ -201,3 +201,27 @@ .heliumConfigValueText { vertical-align: top; } + + +/* hide arrows when current page is on first & last */ +.hide-first-boundaries.pagination > .disabled > a, +.hide-first-boundaries.pagination > li:first-child > a, +.hide-first-boundaries.pagination > li:first-child > span { + display: none; +} + +.hide-first-boundaries.pagination > .active > a { + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; +} + +.hide-last-boundaries.pagination > .disabled > a, +.hide-last-boundaries.pagination > li:last-child > a, +.hide-last-boundaries.pagination > li:last-child > span { + display: none; +} + +.hide-last-boundaries.pagination > .active > a { + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; +} http://git-wip-us.apache.org/repos/asf/zeppelin/blob/8d18703e/zeppelin-web/src/app/helium/helium.html ---------------------------------------------------------------------- diff --git a/zeppelin-web/src/app/helium/helium.html b/zeppelin-web/src/app/helium/helium.html index 8c2fe92..b960fe8 100644 --- a/zeppelin-web/src/app/helium/helium.html +++ b/zeppelin-web/src/app/helium/helium.html @@ -76,120 +76,130 @@ limitations under the License. <em>Currently there is no available package to be listed</em> </div> </div> - <div class="row heliumPackageList" - ng-repeat="pkgSearchResult in defaultPackages | toArray:false | orderBy: 'pkg.published':true" - ng-show="$parent.pkgListByType === pkgSearchResult.pkg.type"> - <div class="col-md-12"> - <div class="heliumPackageHead"> - <div class="heliumPackageIcon" - ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'" - ng-bind-html=pkgSearchResult.pkg.icon></div> - <div class="heliumPackageIcon" - ng-if="pkgSearchResult.pkg.type === 'INTERPRETER'" - ng-bind-html=intpDefaultIcon></div> - <div class="heliumPackageName"> - <span ng-if="hasNpmLink(pkgSearchResult)"> - <a target="_blank" href="https://www.npmjs.com/package/{{pkgSearchResult.pkg.name}}">{{pkgSearchResult.pkg.name}}</a> - </span> - <span ng-if="!hasNpmLink(pkgSearchResult) && !hasMavenLink(pkgSearchResult)" ng-class="{'heliumLocalPackage': isLocalPackage(pkgSearchResult)}"> - {{pkgSearchResult.pkg.name}} + <div ng-repeat="(types, defaultPackages) in allTypesOfPkg"> + <div class="row heliumPackageList" + ng-repeat="pkgSearchResult in defaultPackages.slice(((currentPage-1)*itemsPerPage), ((currentPage)*itemsPerPage))" + ng-show="$parent.pkgListByType === pkgSearchResult.pkg.type"> + <div class="col-md-12"> + <div class="heliumPackageHead"> + <div class="heliumPackageIcon" + ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'" + ng-bind-html=pkgSearchResult.pkg.icon></div> + <div class="heliumPackageIcon" + ng-if="pkgSearchResult.pkg.type === 'INTERPRETER'" + ng-bind-html=intpDefaultIcon></div> + <div class="heliumPackageName"> + <span ng-if="hasNpmLink(pkgSearchResult)"> + <a target="_blank" href="https://www.npmjs.com/package/{{pkgSearchResult.pkg.name}}">{{pkgSearchResult.pkg.name}}</a> + </span> + <span ng-if="!hasNpmLink(pkgSearchResult) && !hasMavenLink(pkgSearchResult)" ng-class="{'heliumLocalPackage': isLocalPackage(pkgSearchResult)}"> + {{pkgSearchResult.pkg.name}} + </span> + <span ng-if="hasMavenLink(pkgSearchResult)"> + <a target="_blank" + href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22{{pkgSearchResult.pkg.artifact.split('@')[0]}}%22%20AND%20v%3A%22{{pkgSearchResult.pkg.artifact.split('@')[1]}}%22"> + {{pkgSearchResult.pkg.name}} + </a> + </span> + <span class="heliumType">{{pkgSearchResult.pkg.type}}</span> + </div> + <div ng-show="!pkgSearchResult.enabled" + ng-click="enable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact, pkgSearchResult.pkg.type, pkgSearchResult.pkg.groupId, pkgSearchResult.pkg.description)" + class="btn btn-success btn-xs" + style="float:right">Enable</div> + <div ng-show="pkgSearchResult.enabled" + ng-click="disable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact)" + ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'" + class="btn btn-info btn-xs" + style="float:right">Disable</div> + <div ng-show="configExists(pkgSearchResult)" + ng-click="toggleConfigButton(pkgSearchResult)" + ng-class="getConfigButtonClass(pkgSearchResult)" + class="btn btn-default btn-xs spellConfigButton" + style="float:right; margin-right:5px;">Config</div> + </div> + <div ng-class="{heliumPackageDisabledArtifact: !pkgSearchResult.enabled, heliumPackageEnabledArtifact: pkgSearchResult.enabled}"> + {{pkgSearchResult.pkg.artifact}} + <span ng-show="pkgSearchResults[pkgSearchResult.pkg.name].length > 0" + ng-click="toggleVersions(pkgSearchResult.pkg.name)"> + versions </span> - <span ng-if="hasMavenLink(pkgSearchResult)"> + </div> + <ul class="heliumPackageVersions" + ng-show="showVersions[pkgSearchResult.pkg.name]"> + <li class="heliumPackageDisabledArtifact" + ng-repeat="pkgSearchResult in pkgSearchResults[pkgSearchResult.pkg.name]"> + {{pkgSearchResult.pkg.artifact}} - + <span ng-click="enable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact, pkgSearchResult.pkg.type, pkgSearchResult.pkg.groupId)" + ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'" + style="margin-left:3px;cursor:pointer;text-decoration: underline;color:#3071a9"> + enable + </span> <a target="_blank" + ng-if="pkgSearchResult.pkg.type === 'INTERPRETER'" + style="margin-left:3px;cursor:pointer;text-decoration: underline;color:#3071a9" href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22{{pkgSearchResult.pkg.artifact.split('@')[0]}}%22%20AND%20v%3A%22{{pkgSearchResult.pkg.artifact.split('@')[1]}}%22"> - {{pkgSearchResult.pkg.name}} + see more </a> - </span> - <span class="heliumType">{{pkgSearchResult.pkg.type}}</span> - </div> - <div ng-show="!pkgSearchResult.enabled" - ng-click="enable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact, pkgSearchResult.pkg.type, pkgSearchResult.pkg.groupId, pkgSearchResult.pkg.description)" - class="btn btn-success btn-xs" - style="float:right">Enable</div> - <div ng-show="pkgSearchResult.enabled" - ng-click="disable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact)" - ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'" - class="btn btn-info btn-xs" - style="float:right">Disable</div> - <div ng-show="configExists(pkgSearchResult)" - ng-click="toggleConfigButton(pkgSearchResult)" - ng-class="getConfigButtonClass(pkgSearchResult)" - class="btn btn-default btn-xs spellConfigButton" - style="float:right; margin-right:5px;">Config</div> - </div> - <div ng-class="{heliumPackageDisabledArtifact: !pkgSearchResult.enabled, heliumPackageEnabledArtifact: pkgSearchResult.enabled}"> - {{pkgSearchResult.pkg.artifact}} - <span ng-show="pkgSearchResults[pkgSearchResult.pkg.name].length > 0" - ng-click="toggleVersions(pkgSearchResult.pkg.name)"> - versions - </span> - </div> - <ul class="heliumPackageVersions" - ng-show="showVersions[pkgSearchResult.pkg.name]"> - <li class="heliumPackageDisabledArtifact" - ng-repeat="pkgSearchResult in pkgSearchResults[pkgSearchResult.pkg.name]"> - {{pkgSearchResult.pkg.artifact}} - - <span ng-click="enable(pkgSearchResult.pkg.name, pkgSearchResult.pkg.artifact, pkgSearchResult.pkg.type, pkgSearchResult.pkg.groupId)" - ng-if="pkgSearchResult.pkg.type !== 'INTERPRETER'" - style="margin-left:3px;cursor:pointer;text-decoration: underline;color:#3071a9"> - enable - </span> - <a target="_blank" - ng-if="pkgSearchResult.pkg.type === 'INTERPRETER'" - style="margin-left:3px;cursor:pointer;text-decoration: underline;color:#3071a9" - href="http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22{{pkgSearchResult.pkg.artifact.split('@')[0]}}%22%20AND%20v%3A%22{{pkgSearchResult.pkg.artifact.split('@')[1]}}%22"> - see more - </a> - </li> - </ul> - <div class="heliumPackageDescription" ng-bind-html="getDescriptionText(pkgSearchResult)" /> - <div ng-if="pkgSearchResult.pkg.type === 'SPELL' && pkgSearchResult.pkg.spell" - class="spellInfo"> - <div> - <span class="spellInfoDesc">MAGIC</span> - <span class="spellInfoValue">{{pkgSearchResult.pkg.spell.magic}} </span> - </div> - <div> - <span class="spellInfoDesc">USAGE</span> - <pre class="spellUsage">{{pkgSearchResult.pkg.spell.usage}} </pre> + </li> + </ul> + <div class="heliumPackageDescription" ng-bind-html="getDescriptionText(pkgSearchResult)" /> + <div ng-if="pkgSearchResult.pkg.type === 'SPELL' && pkgSearchResult.pkg.spell" + class="spellInfo"> + <div> + <span class="spellInfoDesc">MAGIC</span> + <span class="spellInfoValue">{{pkgSearchResult.pkg.spell.magic}} </span> + </div> + <div> + <span class="spellInfoDesc">USAGE</span> + <pre class="spellUsage">{{pkgSearchResult.pkg.spell.usage}} </pre> + </div> </div> - </div> - <!--start: config--> - <div class="heliumConfig" ng-if="configOpened(pkgSearchResult)"> - <h5>Configuration</h5> - <table class="heliumConfigTable table table-striped"> - <tr> - <th>Name</th> - <th>Type</th> - <th>Description</th> - <th>Value</th> - </tr> - <tr> - </tr> - <tr data-ng-repeat="cfg in defaultPackageConfigs[pkgSearchResult.pkg.name]"> - <td style="vertical-align: middle;">{{cfg.name}}</td> - <td style="vertical-align: middle;">{{cfg.type}}</td> - <td style="vertical-align: middle;">{{cfg.description}}</td> - <td> - <div class="input-group"> - <input type="text" class="form-control" style="border-radius: 5px;" - data-ng-model="cfg.value" placeholder="{{cfg.defaultValue}}" /> - </div> - </td> - </tr> - </table> + <!--start: config--> + <div class="heliumConfig" ng-if="configOpened(pkgSearchResult)"> + <h5>Configuration</h5> + <table class="heliumConfigTable table table-striped"> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Value</th> + </tr> + <tr> + </tr> + <tr data-ng-repeat="cfg in defaultPackageConfigs[pkgSearchResult.pkg.name]"> + <td style="vertical-align: middle;">{{cfg.name}}</td> + <td style="vertical-align: middle;">{{cfg.type}}</td> + <td style="vertical-align: middle;">{{cfg.description}}</td> + <td> + <div class="input-group"> + <input type="text" class="form-control" style="border-radius: 5px;" + data-ng-model="cfg.value" placeholder="{{cfg.defaultValue}}" /> + </div> + </td> + </tr> + </table> - <div> - <button class="btn btn-primary" - ng-click="saveConfig(pkgSearchResult)">Save</button> - <button class="btn btn-default" - ng-click="toggleConfigButton(pkgSearchResult)">Close</button> + <div> + <button class="btn btn-primary" + ng-click="saveConfig(pkgSearchResult)">Save</button> + <button class="btn btn-default" + ng-click="toggleConfigButton(pkgSearchResult)">Close</button> + </div> </div> - </div> - <!--end: config--> + <!--end: config--> + </div> + </div> + <div class="text-center" style="margin-top: 20px;" ng-if="getPackageSize(defaultPackages, pkgListByType) !== 0"> + <pagination boundary-links="true" total-items="defaultPackages.length" + ng-model="$parent.currentPage" class="pagination-sm" + ng-show="$parent.pkgListByType === types" + max-size="maxSize" + items-per-page="itemsPerPage" + ng-class="{'hide-first-boundaries': $parent.currentPage == 1, 'hide-last-boundaries': $parent.currentPage >= defaultPackages.length/itemsPerPage}" + previous-text="‹" next-text="›" first-text="«" last-text="»"></pagination> </div> - </div> -</div> +</div> \ No newline at end of file