#72 Package search
Merged 5 months ago by a2batic. Opened 6 months ago by amitosh.
amitosh/Fedora-app package-search  into  master

file modified
+8 -2

@@ -19,6 +19,8 @@ 

  import { MorePage} from '../pages/more/more';

  import { NotificationsPage} from '../pages/notifications/notifications';

  import { WomenPage } from '../pages/women/women';

+ import { PackageSearchPage } from '../pages/package-search/package-search';

+ import { ViewPackagePage } from '../pages/view-package/view-package';

  

  import { Browser } from '../providers/browser/browser';

  

@@ -32,7 +34,9 @@ 

      CalendarPage,

      MorePage,

      NotificationsPage,

-     WomenPage

+     WomenPage,

+     PackageSearchPage,

+     ViewPackagePage

    ],

    imports: [

      BrowserModule,

@@ -50,7 +54,9 @@ 

      HomePage,

      MorePage,

      NotificationsPage,

-     WomenPage

+     WomenPage,

+     PackageSearchPage,

+     ViewPackagePage

    ],

    providers: [

      Browser,

file modified
+19 -0

@@ -122,3 +122,22 @@ 

      background-color: #fff !important;

      box-shadow: 0 2px 4px 0 rgba(86, 86, 86, 0.05);

  }

+ 

+ [padding] ion-list ion-item {

+     h1:first-child,

+     h2:first-child,

+     h3:first-child,

+     h4:first-child,

+     h5:first-child,

+     h6:first-child {

+         margin-top: unset;

+     }

+ }

+ 

+ .pkg-lib {

+   color: #03A9F4

+ }

+ 

+ .pkg-devel {

+   color: #FFEB3B;

+ }

file modified
+6 -10

@@ -4,15 +4,11 @@ 

    See http://ionicframework.com/docs/components/#navigation for more info on

    Ionic pages and navigation.

  -->

- <ion-header>

- 

-   <ion-navbar>

-     <ion-title>more</ion-title>

-   </ion-navbar>

- 

- </ion-header>

- 

- 

  <ion-content padding>

- 

+   <ion-list>

+     <button ion-item (click)="open('packageSearch')">

+       <ion-icon name="search" item-start></ion-icon>

+         Package Search

+     </button>

+   </ion-list>

  </ion-content>

file modified
+11 -2

@@ -1,5 +1,6 @@ 

  import { Component } from '@angular/core';

- import { NavController, NavParams } from 'ionic-angular';

+ import { NavController } from 'ionic-angular';

+ import { PackageSearchPage } from '../package-search/package-search';

  

  @Component({

    selector: 'page-more',

@@ -7,6 +8,14 @@ 

  })

  export class MorePage {

  

-   constructor(public navCtrl: NavController, public navParams: NavParams) {

+   pages = {

+     packageSearch: PackageSearchPage

+   };

+ 

+   constructor(private navCtrl: NavController) {

+   }

+ 

+   open(page:string) {

+     this.navCtrl.push(this.pages[page]);

    }

  }

@@ -0,0 +1,28 @@ 

+ <!--

+   Generated template for the SearchPage page.

+ 

+   See http://ionicframework.com/docs/components/#navigation for more info on

+   Ionic pages and navigation.

+ -->

+ <ion-header>

+ 

+   <ion-navbar>

+     <ion-title>Fedora Package Search</ion-title>

+   </ion-navbar>

+ 

+ </ion-header>

+ 

+ 

+ <ion-content padding>

+   <ion-searchbar [(ngModel)]="searchQuery" (cancel)="clear()" (change)="search()" autocorrect="off"></ion-searchbar>

+   <ion-list>

+     <ion-list-header *ngIf="packages.length > 0">

+         Showing {{ matches }} results

+       </ion-list-header>

+     <ion-item (click)="showPackage(pkg)" *ngFor="let pkg of packages">

+       <ion-icon [ngClass]="getPackageType(pkg)" name="cube" item-start></ion-icon>

+       <h2>{{ pkg.name }}</h2>

+       <h3>{{ pkg.summary }}</h3>

+     </ion-item>

+   </ion-list>

+ </ion-content>

@@ -0,0 +1,3 @@ 

+ page-search {

+ 

+ }

@@ -0,0 +1,45 @@ 

+ import { Component } from '@angular/core';

+ import { NavController } from 'ionic-angular';

+ import { PackageSearchProvider, Package } from '../../providers/package-search/package-search';

+ import { ViewPackagePage } from '../view-package/view-package';

+ import { getPackageType } from '../../utils';

+ 

+ const RESULTS_PER_PAGE = 10;

+ 

+ @Component({

+   templateUrl: 'package-search.html',

+   providers: [PackageSearchProvider]

+ })

+ export class PackageSearchPage {

+ 

+   private searchQuery:string;

+   private offset = 0;

+   private matches = 0;

+   private packages:Package[] = [];

+ 

+   constructor(public navCtrl: NavController, private searchProvider:PackageSearchProvider) {

+   }

+ 

+   search() {

+     this.searchProvider.search(this.searchQuery, RESULTS_PER_PAGE, this.offset)

+       .subscribe( r => {

+         this.packages = r.packages;

+         this.offset = r.offset;

+         this.matches = r.matches;

+       });

+   }

+ 

+   clear() {

+     this.packages = [];

+     this.offset = 0;

+     this.matches = 0;

+   }

+ 

+   showPackage(pkg:Package) {

+     this.navCtrl.push(ViewPackagePage, { pkg });

+   }

+ 

+   getPackageType(pkg:Package) {

+     return getPackageType(pkg.name);

+   }

+ }

@@ -0,0 +1,36 @@ 

+ <!--

+   Generated template for the ViewPackagePage page.

+ 

+   See http://ionicframework.com/docs/components/#navigation for more info on

+   Ionic pages and navigation.

+ -->

+ <ion-header>

+ 

+   <ion-navbar>

+     <ion-title>Package {{ pkg.name }}</ion-title>

+   </ion-navbar>

+ 

+ </ion-header>

+ 

+ 

+ <ion-content padding>

+   <h1>{{ pkg.name }}</h1>

+   <p>{{ pkg.summary }}</p>

+   <p *ngIf="pkg.upstreamUrl">

+     <a href="{{ pkg.upstreamUrl }}">{{ pkg.upstreamUrl }}</a>

+   </p>

+   <h3>Description</h3>

+   <p>{{ pkg.description }}</p>

+   <h3>Install</h3>

+   <p class="code-block" padding>

+     <code>$ <span>sudo dnf install {{ pkg.name }}</span></code>

+   </p>

+   <h3 *ngIf="pkg.subPackages.length > 0">Sub packages</h3>

+   <ion-list *ngIf="pkg.subPackages.length > 0">

+     <ion-item (click)="showPackage(pkg)" *ngFor="let pkg of pkg.subPackages">

+       <ion-icon [ngClass]="getPackageType(pkg)" name="cube" item-start></ion-icon>

+       <h2>{{ pkg.name }}</h2>

+       <h3>{{ pkg.summary }}</h3>

+     </ion-item>

+   </ion-list>

+ </ion-content>

@@ -0,0 +1,6 @@ 

+ page-view-package {

+   .code-block {

+     background: #f0f0f0;

+     border-radius: 3px;

+   }

+ }

@@ -0,0 +1,32 @@ 

+ import { Component } from '@angular/core';

+ import { NavController, NavParams } from 'ionic-angular';

+ import { Package } from 'providers/package-search/package-search';

+ import { getPackageType } from '../../utils';

+ 

+ /**

+  * Generated class for the ViewPackagePage page.

+  *

+  * See https://ionicframework.com/docs/components/#navigation for more info on

+  * Ionic pages and navigation.

+  */

+ 

+ @Component({

+   selector: 'page-view-package',

+   templateUrl: 'view-package.html',

+ })

+ export class ViewPackagePage {

+ 

+   private pkg: Package;

+ 

+   constructor(public navCtrl: NavController, public navParams: NavParams) {

+     this.pkg = this.navParams.get('pkg') || {};

+   }

+ 

+   showPackage(pkg: Package) {

+     this.navCtrl.push(ViewPackagePage, { pkg });

+   }

+ 

+   getPackageType(pkg:Package) {

+     return getPackageType(pkg.name);

+   }

+ }

@@ -0,0 +1,62 @@ 

+ import { HttpClient } from '@angular/common/http';

+ import { Injectable } from '@angular/core';

+ import { Observable } from 'rxjs/Observable';

+ 

+ const API_ENDPOINT = 'https://apps.fedoraproject.org/packages/fcomm_connector/xapian/query/search_packages/';

+ 

+ export interface SearchResult {

+   matches: number,

+   count: number,

+   offset: number,

+   pageSize: number,

+   packages: Package[]

+ }

+ 

+ export interface Package {

+   name: string,

+   summary: string,

+   upstreamUrl: string,

+   description: string,

+   branch: string,

+   develOwner: string,

+   subPackages: Package[]

+ }

+ 

+ function mapPackage(pkg: any): Package {

+   return {

+     name: pkg.name,

+     summary: pkg.summary,

+     upstreamUrl: pkg.upstream_url,

+     description: pkg.description,

+     branch: pkg.branch,

+     develOwner: pkg.devel_owner,

+     subPackages: pkg.sub_pkgs ? pkg.sub_pkgs.map(mapPackage) : false

+   };

+ }

+ 

+ @Injectable()

+ export class PackageSearchProvider {

+ 

+   constructor(private http: HttpClient) {

+   }

+ 

+   public search(query: string, limit = 10, offset = 0): Observable<SearchResult> {

+     const queryObjectStr = JSON.stringify({

+       filters: {

+         search: query

+       },

+       rows_per_page: limit,

+       start_row: offset

+     });

+ 

+     return this.http.get(`${API_ENDPOINT}/${queryObjectStr}`)

+       .map((res: any) => ({

+         matches: res.total_rows,

+         count: res.visible_rows,

+         offset: res.start_row,

+         pageSize: res.rows_per_page,

+         packages: res.rows.map(mapPackage)

+       }));

+   }

+ 

+ }

file modified
+24 -0

@@ -38,3 +38,27 @@ 

      return jsDate[1] + ' ' + jsDate[2] + ', ' + jsDate[3];

    }

  }

+ 

+ /**

+  * Return the type of package from it names.

+  *

+  * Matches the name against the Fedora packaging guidelines

+  * Taken from: https://fedoraproject.org/wiki/Packaging:Naming?rd=Packaging:NamingGuidelines

+  * @param pkgName package name

+  */

+ export function getPackageType(pkgName:string) {

+   if (pkgName.endsWith('-devel')) {

+     return 'pkg-devel';

+   } else if (pkgName.endsWith('-libs')) {

+     return 'pkg-lib';

+   } else if(pkgName.endsWith('-doc')) {

+     return 'pkg-doc';

+   } else if(/^\w*-langpack(-[a-zA-Z]{2})?$/.test(pkgName)) {

+     return 'pkg-langpack';

+   } else if(pkgName.endsWith('-fonts')) {

+     return 'pkg-font';

+   }

+ 

+   return '';

+ }

+