Skip to content
This repository has been archived by the owner on Oct 17, 2019. It is now read-only.

Commit

Permalink
Add search filter to Records and domains (#93)
Browse files Browse the repository at this point in the history
  • Loading branch information
szok committed Jun 6, 2016
1 parent a1e9b99 commit ffc79e4
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 37 deletions.
11 changes: 7 additions & 4 deletions .editorconfig
@@ -1,17 +1,21 @@
# http://editorconfig.org
root = true

# Unix-style newlines with a newline ending every file
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.ts]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = 0
trim_trailing_whitespace = false

[*.{html,yml}]
indent_style = space
Expand All @@ -20,4 +24,3 @@ indent_size = 2
[*.{css,js,json,py}]
indent_style = space
indent_size = 4
insert_final_newline = true
35 changes: 30 additions & 5 deletions dnsaas/api/v2/views.py
@@ -1,5 +1,6 @@

"""Views and viewsets for DNSaaS API"""
import django_filters
import logging

from django.core.urlresolvers import reverse
Expand All @@ -17,7 +18,7 @@
SuperMaster,
)
from rest_framework import status
from rest_framework.filters import DjangoFilterBackend
from rest_framework import filters
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from rest_framework.permissions import DjangoObjectPermissions
from rest_framework.response import Response
Expand Down Expand Up @@ -51,7 +52,7 @@ def has_permission(self, request, view):

class FiltersMixin(object):

filter_backends = (DjangoFilterBackend,)
filter_backends = (filters.DjangoFilterBackend,)


class OwnerViewSet(FiltersMixin, ModelViewSet):
Expand All @@ -65,12 +66,22 @@ def perform_create(self, serializer, *args, **kwargs):
object_.email_owner(self.request.user)


class DomainFilter(django_filters.FilterSet):
name = django_filters.CharFilter(name='name', lookup_type='icontains')

class Meta:
model = Domain
fields = ['name', 'owner', 'type']


class DomainViewSet(OwnerViewSet):

queryset = Domain.objects.all().select_related('owner')
serializer_class = DomainSerializer
filter_fields = ('name', 'type', 'owner',)
permission_classes = (DomainPermission,)
filter_backends = (filters.DjangoFilterBackend, filters.SearchFilter)
filter_class = DomainFilter
search_fields = ['name', 'owner__username']


class RecordRequestsViewSet(FiltersMixin, ReadOnlyModelViewSet):
Expand All @@ -81,12 +92,26 @@ class RecordRequestsViewSet(FiltersMixin, ReadOnlyModelViewSet):
serializer_class = RecordRequestSerializer


class RecordFilter(django_filters.FilterSet):
content = django_filters.CharFilter(
name='content', lookup_type='icontains'
)
name = django_filters.CharFilter(
name='name', lookup_type='icontains'
)

class Meta:
model = Record
fields = ['name', 'content', 'domain', 'owner']


class RecordViewSet(OwnerViewSet):

queryset = Record.objects.all().select_related('owner', 'domain')
serializer_class = RecordSerializer
filter_fields = ('name', 'content', 'domain', 'owner',)
search_fields = filter_fields
filter_backends = (filters.DjangoFilterBackend, filters.SearchFilter)
filter_class = RecordFilter
search_fields = ['name', 'content', 'domain__name', 'owner__username']

def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
Expand Down
22 changes: 22 additions & 0 deletions ui/static/app/domain/domain.component.ts
Expand Up @@ -21,6 +21,10 @@ export class DomainComponent implements OnInit {
currentOffset: number = 0;
perPage: number = 20;
totalCount: number;
searchValue: string;
additionalRouteParams: {[key: string]: string} = {
"search": this.searchValue
};

constructor(
private domainService: DomainService,
Expand All @@ -29,11 +33,19 @@ export class DomainComponent implements OnInit {
) { }

ngOnInit() {
this.getDomains();
}

getDomains() {
let params: URLSearchParams = new URLSearchParams();
this.currentOffset = Number(this.routeParams.get("offset"));
params.set("limit", String(this.perPage));
params.set("offset", String(this.currentOffset));

if (this.searchValue) {
params.set("search", this.searchValue);
}

this.domainService.getDomains(params).map(
(response) => response.json()
).subscribe(
Expand All @@ -44,4 +56,14 @@ export class DomainComponent implements OnInit {
error => this.errorMessage = <any>error
);
}

onKeyUp(event: KeyboardEvent, value: string) {
if (value.length > 1) {
this.searchValue = value;
this.getDomains();
} else {
this.searchValue = null;
this.getDomains();
}
}
}
9 changes: 4 additions & 5 deletions ui/static/app/domain/domain.service.ts
Expand Up @@ -14,21 +14,20 @@ export class DomainService implements AutocompleteServiceInterface {
constructor(private http: HttpClient) {}

getDomains(search: URLSearchParams): Observable<Response> {
let url: string = "/api/domains/";
let url: string = "/api/v2/domains/";
return this.http.get(url, search).catch(this.handleError);
}

getAutocompleteSearchResults(value: string): Observable<Domain[]> {
let result: Array<{0: number, 1: string}> = [];
let url: string = "/api/domains/";
let url: string = "/api/v2/domains/";
let params: URLSearchParams = new URLSearchParams();
params.set("domain_name", value);

params.set("name", value);
return this.http.get(url, params).map(this.extractData).catch(this.handleError);
}

getAutocompleteCurrentValue(id: number): Observable<string> {
let url: string = `/api/domains/${id}/`;
let url: string = `/api/v2/domains/${id}/`;
return this.http.get(url).map(
response => {
let json = response.json();
Expand Down
4 changes: 2 additions & 2 deletions ui/static/app/record-request/record-request.service.ts
Expand Up @@ -18,12 +18,12 @@ export class RecordRequestService {

getRequests(search: URLSearchParams): Observable<Response> {
search.set("owner", String(this.authService.getUserId()));
let url: string = "/api/record-requests/";
let url: string = "/api/v2/record-requests/";
return this.http.get(url, search).catch(this.handleError);
}

getRequestById(id: string): Observable<RecordRequest> {
let url: string = `/api/record-requests/${id}/`;
let url: string = `/api/v2/record-requests/${id}/`;
return this.http.get(url).map(
this.extractSingleData
).catch(this.handleError);
Expand Down
23 changes: 20 additions & 3 deletions ui/static/app/record/record.component.ts
@@ -1,9 +1,9 @@
import { Component, OnInit } from "@angular/core";
import { CanActivate, Router, RouteParams } from "@angular/router-deprecated";
import { URLSearchParams, HTTP_PROVIDERS } from "@angular/http";
import { RecordService } from "./record.service";
import { Record } from "./record";
import { AuthService, isLoggedin } from "../auth/auth.service";
import { Record } from "./record";
import { RecordService } from "./record.service";
import { PaginationComponent } from "../pagination/pagination.component";
import "rxjs/add/observable/throw";

Expand Down Expand Up @@ -31,7 +31,11 @@ export class RecordComponent implements OnInit {
totalCount: number;
showAllRecords: boolean = false;
activeUser: string;
additionalRouteParams: {[key: string]: string} = {"showAll": "false"};
searchValue: string;
additionalRouteParams: {[key: string]: string} = {
"showAll": "false",
"search": this.searchValue
};

constructor(
private router: Router,
Expand All @@ -47,6 +51,16 @@ export class RecordComponent implements OnInit {
this.getRecords();
}

onKeyUp(event: KeyboardEvent, value: string) {
if (value.length > 1) {
this.searchValue = value;
this.getRecords();
} else {
this.searchValue = null;
this.getRecords();
}
}

getRecords() {
let params: URLSearchParams = new URLSearchParams();
this.currentOffset = Number(this.routeParams.get("offset"));
Expand All @@ -56,6 +70,9 @@ export class RecordComponent implements OnInit {
if (!this.showAllRecords) {
params.set("owner", String(this.authService.getUserId()));
}
if (this.searchValue) {
params.set("search", this.searchValue);
}

this.recordService.getRecords(params).map(
(response) => response.json()
Expand Down
12 changes: 5 additions & 7 deletions ui/static/app/record/record.service.ts
Expand Up @@ -14,25 +14,23 @@ export class RecordService {
constructor(private http: HttpClient) { }

getRecords(search: URLSearchParams): Observable<Response> {
let url: string = "/api/records/";
let url: string = "/api/v2/records/";
return this.http.get(url, search).catch(this.handleError);
}

getRecordById(id: string): Observable<Record> {
let url: string = `/api/records/${id}/`;
let url: string = `/api/v2/records/${id}/`;
return this.http.get(url).map(
this.extractSingleData
).catch(this.handleError);
}

updateOrCreateRecord(record: Record): Observable<Record> {
let url: string = "/api/records/";
// TODO change this to ID!
record.domain = `/api/domains/${record.domain_id}/`;
let url: string = "/api/v2/records/";
let body = JSON.stringify(record);
let request: any;
if (record.id) {
url = `/api/records/${record.id}/`;
url = `/api/v2/records/${record.id}/`;
request = this.http.patch(url, body);
} else {
request = this.http.post(url, body);
Expand All @@ -44,7 +42,7 @@ export class RecordService {
}

deleteRecord(record: Record) {
let url: string = `/api/records/${record.id}/`;
let url: string = `/api/v2/records/${record.id}/`;
return this.http.delete(url).catch(this.handleError);
}

Expand Down
3 changes: 1 addition & 2 deletions ui/static/app/record/record.ts
Expand Up @@ -3,8 +3,7 @@ import { Domain } from "../domain/domain";

export class Record {
public id: number;
public domain: string;
public domain_id: number; // TODO: remove if API will be ready!
public domain: number;
public name: string;
public content: string;
public type: string;
Expand Down
18 changes: 18 additions & 0 deletions ui/static/app/templates/domain.component.html
Expand Up @@ -3,6 +3,23 @@ <h1>Domains</h1>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<div class="row">
<div class="col-md-6">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Search by name, owner"
value="{{ searchValue }}"
#searchInput
(keyup)="onKeyUp($event, searchInput.value)"
/>
<div class="input-group-addon">
<span class="glyphicon glyphicon-search"></span>
</div>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div *ngIf="errorMessage" class="alert alert-success alert-danger">
Expand Down Expand Up @@ -40,6 +57,7 @@ <h1>Domains</h1>
routeName="Domains"
[totalCount]="totalCount"
[perPage]="perPage"
[additionalRouteParams]="additionalRouteParams"
[currentOffset]="currentOffset">
</pagination>
</div>
Expand Down
5 changes: 2 additions & 3 deletions ui/static/app/templates/record-detail.component.html
Expand Up @@ -18,15 +18,14 @@ <h1 *ngIf="!isCreate">Edit record</h1>
<form *ngIf="record" [ngFormModel]="recordForm" (ngSubmit)="onSubmit()" class="form-horizontal">
<fieldset>
<div class="form-group">
<label for="domain_id" class="col-sm-2 control-label">Domain
<label for="domain" class="col-sm-2 control-label">Domain
<span class="glyphicon glyphicon-info-sign" tooltip data-toggle="tooltip" data-placement="top" title="Use the left field to do Domain lookups in the fields name." aria-hidden="true"></span>
</label>
<div class="col-sm-6">
<!-- change domain_id to domain -->
<autocomplete
[forNgModel]="record"
[service]="domainService"
ngModelField="domain_id"
ngModelField="domain"
placeholder="Search domain">
</autocomplete>
</div>
Expand Down
33 changes: 27 additions & 6 deletions ui/static/app/templates/record.component.html
Expand Up @@ -3,12 +3,33 @@ <h1>Records</h1>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<div class="legend" [style.display]="showAllRecords ? 'block' : 'none'">
<span class="legend"></span> - Your records
</div>
<div class="btn-group btn-group-sm pull-right" role="group">
<button (click)="onSelectShowAllRecords()" type="button" class="btn {{ showAllRecords ? 'btn-default': 'btn-primary' }}">my records</button>
<button (click)="onSelectShowAllRecords('all')" type="button" class="btn {{ !showAllRecords ? 'btn-default': 'btn-primary' }}">all records</button>
<div class="row">
<div class="col-md-6">
<div class="input-group">
<input
type="text"
class="form-control"
placeholder="Search by name, content, domain name"
value="{{ searchValue }}"
#searchInput
(keyup)="onKeyUp($event, searchInput.value)"
/>
<div class="input-group-addon">
<span class="glyphicon glyphicon-search"></span>
</div>
</div>
</div>
<div class="col-md-2">
<div class="legend" [style.display]="showAllRecords ? 'block' : 'none'">
<span class="legend"></span> - Your records
</div>
</div>
<div class="col-md-4">
<div class="btn-group btn-group-sm pull-right" role="group">
<button (click)="onSelectShowAllRecords()" type="button" class="btn {{ showAllRecords ? 'btn-default': 'btn-primary' }}">my records</button>
<button (click)="onSelectShowAllRecords('all')" type="button" class="btn {{ !showAllRecords ? 'btn-default': 'btn-primary' }}">all records</button>
</div>
</div>
</div>
</div>
<div class="panel-body">
Expand Down

0 comments on commit ffc79e4

Please sign in to comment.