Takumon/mean-blog

View on GitHub
src/app/shared/services/article.service.ts

Summary

Maintainability
B
5 hrs
Test Coverage
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams} from '@angular/common/http';
import * as moment from 'moment';
import { Observable } from 'rxjs';
import 'rxjs';
import { ArticleModel, ArticleWithUserModel, UserModel } from '../../shared/models';



/**
 * 登録(Create)、更新(Update)、削除時(delete)のレスポンス
 */
interface CudResponse {
  message: string;
  obj: ArticleModel;
}

/**
 * いいねの登録(Create)、削除時(delete)のレスポンス
 */
export interface VoteCudResponse {
  message: string;
  obj: UserModel[];
}


/**
 * 検索条件を複数件取得する際の検索条件
 */
export interface SearchArticlesCondition {
  author?: {
    _id?: string | string[];
    userId?: string | string[];
  };
  dateFrom?: string;
  dateTo?: string;
  voter?: string | string[];
}

/**
 * 検索時のページング、ソート条件
 */
export interface PageAndSortOption {
  skip?: number;
  limit?: number;
  sort?: Object;
}

/**
 * Http通信用オプション
 */
interface HttpOption {
  condition?: SearchArticlesCondition;
  withUser?: boolean;
}

@Injectable()
export class ArticleService {
  private baseUrl = '/api/articles';

  constructor(
    private http: HttpClient,
  ) {}

  /**
   * 複数件取得
   *
   * @param condition 検索条件
   * @param paginAndSortOptions ページング条件とソート条件
   * @param withUser 取得情報にユーザ情報を付与するか
   * @return 指定した検索条件とページング条件に一致するモデルのリスト
   */
  get(
    condition: SearchArticlesCondition,
    paginAndSortOptions: PageAndSortOption,
    withUser: boolean = false): Observable<{count: number, articles: ArticleModel[] | ArticleWithUserModel[] }> {
    const URL = this.baseUrl;

    // 検索条件にページング条件をマージする
    const options = this.constructOptions({ condition: Object.assign({}, condition, paginAndSortOptions), withUser });

    return this.http.get<{count: number, articles: ArticleModel[] | ArticleWithUserModel[]}>(URL, options);
  }


  /**
   * 一件取得
   * @param _id 取得するモデルの_id
   * @param withUser 取得情報にユーザ情報を付与するか
   * @return 指定した_idに一致するモデル
   */
  getById(_id: string, withUser: boolean = false): Observable<ArticleModel | ArticleWithUserModel> {
    const URL = `${this.baseUrl}/${_id}`;

    const options = this.constructOptions({ withUser });

    return this.http.get<ArticleModel | ArticleWithUserModel>(URL, options);
  }

  /**
   * 登録
   *
   * @param model 登録するモデル
   * @return 登録後のモデル
   */
  update(model: ArticleModel): Observable<CudResponse> {
    const URL = `${this.baseUrl}/${model._id}`;

    return this.http.put<CudResponse>(URL, model);
  }

  /**
   * 更新(差分更新)
   *
   * @param model 更新するモデル(更新対象のプロパティのみ定義したモデル)
   * @return 更新後のモデル
   */
  register(model: ArticleModel): Observable<CudResponse> {
    const URL = this.baseUrl;

    return this.http.post<CudResponse>(URL, model);
  }

  /**
   * 削除(論理削除)
   *
   * @param _id 削除対象モデルの_id
   * @return 削除したモデル
   */
  delete(_id: string): Observable<CudResponse> {
    const URL = `${this.baseUrl}/${_id}`;

    return this.http.delete<CudResponse>(URL);
  }



  /**
   * いいねを検索
   *
   * @param _idOfArticle 記事_id
   * @param withUser 取得情報にユーザ情報を付与するか
   */
  getVote(_idOfArticle: string, withUser = false): Observable<string[] | UserModel[]> {
    const URL = `${this.baseUrl}/${_idOfArticle}/vote`;

    const options = this.constructOptions({ withUser });

    return this.http.get<string[]>(URL, options);
  }

  /**
   * いいねを登録
   *
   * @param _idOfArticle いいねの対象記事の_id
   * @param _idOfUser いいねをするユーザの_id
   */
  registerVote(_idOfArticle: string, _idOfUser: string): Observable<VoteCudResponse> {
    const URL = `${this.baseUrl}/${_idOfArticle}/vote`;

    return this.http.post<VoteCudResponse>(URL, {'voter': _idOfUser});
  }

  /**
   * いいねを削除
   *
   * @param _idOfArticle いいねの対象記事の_id
   * @param _idOfUser いいねをするユーザの_id
   */
  deleteVote(_idOfArticle: string, _idOfUser: string): Observable<VoteCudResponse> {
    const URL = `${this.baseUrl}/${_idOfArticle}/vote/${_idOfUser}`;

    return this.http.delete<VoteCudResponse>(URL);
  }


  /**
   * 指定した引数を元にHttp通信用オプションを生成する
   *
   * @param httpOption
   * @return http通信用オプション
   */
  private constructOptions(httpOption: HttpOption): {params: HttpParams} {
    let params = new HttpParams();

    if (httpOption.condition) {
      params = params.set('condition', JSON.stringify(httpOption.condition));
    }

    if (httpOption.withUser) {
      params = params.set('withUser', 'true');
    }

    return { params };
  }
}