I have the following query:
public List<Object> findNearbyGangs(double lat, double lng, double distance) {
Query query = this.entityManager.createNativeQuery("SELECT id, (6371 * acos (cos(radians(:latitude)) * cos(radians(latitude)) * cos(radians(longitude) - radians(:longitude)) + sin(radians(:latitude)) * sin(radians(latitude)))) AS distance FROM Gang g GROUP BY id HAVING distance < :distance ORDER BY distance")
.setParameter("latitude", lat)
.setParameter("longitude", lng)
.setParameter("distance", distance);
List<Object> objects = query.getResultList();
return objects;
}
which objects contain:
[
[
3,
0
],
[
321,
0
],
[
353,
1.3575295456440253
]
]
How do I parse this object so that id = 3 and distance = 0, id = 321 and distance = 0, and so on?
I asked on Stackoverflow but got no response so I ended up figuring it out myself:
public List<NearbyGang> getNearbyGangs(Double longitude, Double latitude, int radius) {
List<Object> nearbyGangsFromDatabase = this.gangRepositoryImpl.findNearbyGangs(longitude, latitude, radius);
List<NearbyGang> nearbyGangs = new ArrayList<NearbyGang>();
for (Object object : nearbyGangsFromDatabase) {
Class oClass = object.getClass();
if (oClass.isArray()) {
for (int i = 0; i < Array.getLength(object); i++) {
BigInteger gangId = (BigInteger) Array.get(object, 0);
Gang gang = this.getById(gangId.longValue()).get();
Double distance = (Double) Array.get(object, 1);
NearbyGang nearbyGang = new NearbyGang(gang, distance);
nearbyGangs.add(nearbyGang);
}
}
}
return nearbyGangs;
}
Improvements welcomed.
One of my favourite things to do is refactor legacy code. I get to see the thinking process that went into solving the problem. It’s like standing on the shoulders of giants.
private function convertActivityToArray(array $activity)
{
$activityArray = array();
$previousGroupNumber = null;
/** @var Activity $activityItem */
foreach ($activity as $activityItem) {
$type = $activityItem->getType();
$groupNumber = $activityItem->getGroupNumber();
$user = $activityItem->getUser();
$name = $user->getName();
$avatar = $this->request->getScheme() .'://' . $this->request->getHttpHost() . $this->request->getBasePath() . '/uploads/avatar/' . $user->getAvatar();
$data = $activityItem->getData();
$created = $activityItem->getCreatedAt();
$activityArray[$groupNumber]['type'] = $type;
$activityArray[$groupNumber]['created'] = $created;
if ($type == ActivityType::Like) {
if ($groupNumber != $previousGroupNumber) {
$data['documentaryThumbnail'] = $this->request->getScheme() .'://' . $this->request->getHttpHost() . $this->request->getBasePath() . '/uploads/posters/' . $data['documentaryThumbnail'];
$activityArray[$groupNumber]['parent']['data'] = $data;
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
} else {
$data['documentaryThumbnail'] = $this->request->getScheme() .'://' . $this->request->getHttpHost() . $this->request->getBasePath() . '/uploads/posters/' . $data['documentaryThumbnail'];
$child['data'] = $data;
$child['user']['name'] = $name;
$child['user']['avatar'] = $avatar;
$activityArray[$groupNumber]['child'][] = $child;
}
} else if ($type == ActivityType::Comment) {
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
$activityArray[$groupNumber]['parent']['data'] = $data;
} else if ($type == ActivityType::Joined) {
if ($groupNumber != $previousGroupNumber) {
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
} else {
$child['user']['name'] = $name;
$child['user']['avatar'] = $avatar;#
$activityArray[$groupNumber]['child'][] = $child;
}
} else if ($type == ActivityType::Added) {
if ($groupNumber != $previousGroupNumber) {
$activityArray[$groupNumber]['parent']['data'] = $data;
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
} else {
$child['data'] = $data;
$child['user']['name'] = $name;
$child['user']['avatar'] = $avatar;
$activityArray[$groupNumber]['child'][] = $child;
}
}
$previousGroupNumber = $groupNumber;
}
return $activityArray;
}
First we refactor $data.
$data = $activityItem->getData();
$data is an array stored in the database like this:
Joined Data:
a:2:{s:6:"userId";s:1:"1";s:8:"username";s:8:"mbwagner";}
Watchlisted Data
a:5:{s:13:"documentaryId";i:728;s:16:"documentaryTitle";s:24:"The U.S. vs. John Lennon";s:18:"documentaryExcerpt";s:160:"In retrospect, it seems absurd that the United States government felt so threatened by the presence of John Lennon that they tried to have him deported. But tha";s:20:"documentaryThumbnail";s:24:"cover/usvsjohnlennon.jpg";s:15:"documentarySlug";s:22:"the-u-s-vs-john-lennon";}
The problem with this way is the data is hardcoded into the database, what happens if the data changes? So I decide to populate data on the fly.
Replace:
$data = $activityItem->getData();
with:
$dataStrategyContext = new DataStrategyContext(
$type,
$this->request,
$this->documentaryService,
$this->commentService);
$data = $dataStrategyContext->createData($activityItem);
Here we use the Strategy Pattern to populate data.
class DataStrategyContext
{
/**
* @var StrategyInterface|null
*/
private $strategy = null;
public function __construct(
string $type,
Request $request,
DocumentaryService $documentaryService,
CommentService $commentService)
{
switch ($type) {
case ActivityType::WATCHLIST:
$this->strategy = new StrategyWatchlist(
$request,
$documentaryService
);
break;
case ActivityType::COMMENT:
$this->strategy = new StrategyComment(
$request,
$commentService
);
break;
case ActivityType::JOINED:
$this->strategy = new StrategyJoined();
break;
case ActivityType::ADDED:
$this->strategy = new StrategyAdded(
$documentaryService
);
break;
}
}
/**
* @param Activity $activityEntity
* @return mixed
*/
public function createData(Activity $activityEntity)
{
return $this->strategy->createData($activityEntity);
}
}
StrategyWatchlist would look like the following:
class StrategyWatchlist implements StrategyInterface
{
/**
* @var Request
*/
private $request;
/**
* @var DocumentaryService
*/
private $documentaryService;
/**
* @param Request $request
* @param DocumentaryService $documentaryService
*/
public function __construct(
Request $request,
DocumentaryService $documentaryService)
{
$this->request = $request;
$this->documentaryService = $documentaryService;
}
/**
* @param Activity $activityEntity
* @return Data
*/
public function createData(Activity $activityEntity)
{
$documentaryId = $activityEntity->getObjectId();
$documentary = $this->documentaryService->getDocumentaryById($documentaryId);
$watchlistData = new WatchlistData();
$watchlistData->setDocumentaryId($documentary->getId());
$watchlistData->setDocumentaryTitle($documentary->getTitle());
$watchlistData->setDocumentarySlug($documentary->getSlug());
$watchlistData->setDocumentarySummary($documentary->getSummary());
$poster = $this->request->getScheme() .'://' . $this->request->getHttpHost() . $this->request->getBasePath() . '/uploads/posters/' . $documentary->getPoster();
$watchlistData->setDocumentaryPoster($poster);
return $watchlistData;
}
}
The next thing is to refactor parent and children from this:
if ($type == ActivityType::Like) {
if ($groupNumber != $previousGroupNumber) {
$data['documentaryThumbnail'] = $this->request->getScheme() .'://' . $this->request->getHttpHost() . $this->request->getBasePath() . '/uploads/posters/' . $data['documentaryThumbnail'];
$activityArray[$groupNumber]['parent']['data'] = $data;
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
} else {
$data['documentaryThumbnail'] = $this->request->getScheme() .'://' . $this->request->getHttpHost() . $this->request->getBasePath() . '/uploads/posters/' . $data['documentaryThumbnail'];
$child['data'] = $data;
$child['user']['name'] = $name;
$child['user']['avatar'] = $avatar;
$activityArray[$groupNumber]['child'][] = $child;
}
} else if ($type == ActivityType::Comment) {
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
$activityArray[$groupNumber]['parent']['data'] = $data;
} else if ($type == ActivityType::Joined) {
if ($groupNumber != $previousGroupNumber) {
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
} else {
$child['user']['name'] = $name;
$child['user']['avatar'] = $avatar;#
$activityArray[$groupNumber]['child'][] = $child;
}
} else if ($type == ActivityType::Added) {
if ($groupNumber != $previousGroupNumber) {
$activityArray[$groupNumber]['parent']['data'] = $data;
$activityArray[$groupNumber]['parent']['user']['name'] = $name;
$activityArray[$groupNumber]['parent']['user']['avatar'] = $avatar;
} else {
$child['data'] = $data;
$child['user']['name'] = $name;
$child['user']['avatar'] = $avatar;
$activityArray[$groupNumber]['child'][] = $child;
}
}
$previousGroupNumber = $groupNumber;
}
After refactoring and creating ActivityParent and ActivityChild it should look like this:
if ($type == ActivityType::Like) {
if ($groupNumber != $previousGroupNumber) {
$activityParent = new ActivityParent();
$activityParent->setName($name);
$activityParent->setUsername($username);
$activityParent->setAvatar($avatar);
$activityParent->setData($data);
$activityArray[$groupNumber]['parent'] = $activityParent->toArray();
} else {
$activityChild = new ActivityChild();
$activityChild->setData($data);
$activityChild->setUsername($username);
$activityChild->setName($name);
$activityChild->setAvatar($avatar);
$activityArray[$groupNumber]['child'][] = $activityChild->toArray();
}
} else if ($type == ActivityType::Comment) {
$activityParent = new ActivityParent();
$activityParent->setName($name);
$activityParent->setUsername($username);
$activityParent->setAvatar($avatar);
$activityParent->setData($data);
} else if ($type == ActivityType::Joined) {
if ($groupNumber != $previousGroupNumber) {
$activityParent = new ActivityParent();
$activityParent->setName($name);
$activityParent->setUsername($username);
$activityParent->setAvatar($avatar);
$activityParent->setData($data);
} else {
$activityChild = new ActivityChild();
$activityChild->setData($data);
$activityChild->setUsername($username);
$activityChild->setName($name);
$activityChild->setAvatar($avatar);
$activityArray[$groupNumber]['child'][] = $activityChild->toArray();
}
} else if ($type == ActivityType::Added) {
if ($groupNumber != $previousGroupNumber) {
$activityParent = new ActivityParent();
$activityParent->setName($name);
$activityParent->setUsername($username);
$activityParent->setAvatar($avatar);
$activityParent->setData($data);
} else {
$activityChild = new ActivityChild();
$activityChild->setData($data);
$activityChild->setUsername($username);
$activityChild->setName($name);
$activityChild->setAvatar($avatar);
$activityArray[$groupNumber]['child'][] = $activityChild->toArray();
}
}
$previousGroupNumber = $groupNumber;
}
Notice there are duplicate times when we create ActivityParent and ActivityChild. Only certain types have children:
class ActivityType
{
const LIKE = "like";
const COMMENT = "comment";
const FOLLOW = "follow";
const JOINED = "joined";
const ADDED = "added";
/**
* @return array
*/
public static function getAllTypes()
{
return [
self::LIKE,
self::ADDED,
self::JOINED,
self::COMMENT,
self::FOLLOW
];
}
/**
* @return array
*/
public static function getTypesWithChildren()
{
return [
self::LIKE,
self::JOINED,
self::ADDED
];
}
/**
* @param string $type
* @return bool
*/
public static function hasChildren(string $type)
{
return in_array($type, self::getTypesWithChildren());
}
}
Then we update the convertActivityToArray() function to this:
$hasChildren = ActivityType::hasChildren($type);
if ($hasChildren) {
if ($groupNumber != $previousGroupNumber) {
$activityParent = new ActivityParent();
$activityParent->setName($name);
$activityParent->setUsername($username);
$activityParent->setAvatar($avatar);
$activityParent->setData($data);
$activityArray[$groupNumber]['parent'] = $activityParent->toArray();
} else {
$activityChild = new ActivityChild();
$activityChild->setData($data);
$activityChild->setUsername($username);
$activityChild->setName($name);
$activityChild->setAvatar($avatar);
$activityArray[$groupNumber]['child'][] = $activityChild->toArray();
}
} else {
$activityParent = new ActivityParent();
$activityParent->setName($name);
$activityParent->setUsername($username);
$activityParent->setAvatar($avatar);
$activityParent->setData($data);
$activityArray[$groupNumber]['parent'] = $activityParent->toArray();
}
Notice ActivityParent and ActivityChild are doing the same thing so I refactored it to just ActivityObject. Plus I moved it above the IF statements.
$activityObject = new ActivityObject();
$activityObject->setName($name);
$activityObject->setUsername($username);
$activityObject->setAvatar($avatar);
$activityObject->setData($data);
$hasChildren = ActivityType::hasChildren($type);
if ($hasChildren) {
if ($groupNumber != $previousGroupNumber) {
$activityArray[$groupNumber]['parent'] = $activityObject->toArray();
} else {
$activityArray[$groupNumber]['child'][] = $activityObject->toArray();
}
} else {
$activityArray[$groupNumber]['parent'] = $activityObject->toArray();
}
Next we add ActivityItemOject to hold the array keys and values.
class ActivityItemObject
{
/**
* @var string
*/
private $type;
/**
* @var \DateTime
*/
private $created;
/**
* @var ActivityObject
*/
private $parent;
/**
* @var ActivityObject[]
*/
private $children;
public function __construct()
{
$this->children = [];
}
.....
/**
* @return array
*/
public function toArray()
{
$children = [];
foreach ($this->children as $child) {
$children[] = $child->toArray();
}
$array = [
'type' => $this->type,
'created' => $this->created,
'parent' => $this->parent->toArray(),
'child' => $children
];
return $array;
}
And finally the completed code:
/**
* @param ArrayCollection|Activity[] $activity
* @return array
*/
private function convertActivityToArray(array $activity)
{
$activityMap = [];
$previousGroupNumber = 0;
/** @var Activity $activityEntity */
foreach ($activity as $activityItem) {
$groupNumber = $activityItem->getGroupNumber();
if (array_key_exists($groupNumber, $activityMap) != null) {
$activityItemObject = $activityMap[$groupNumber];
} else {
$activityItemObject = new ActivityItemObject();
}
$type = $activityItem->getType();
$created = $activityItem->getCreatedAt();
$activityItemObject->setType($type);
$activityItemObject->setCreated($created);
$dataStrategyContext = new DataStrategyContext(
$type,
$this->request,
$this->documentaryService,
$this->commentService);
$data = $dataStrategyContext->createData($activityItem);
$user = $activityItem->getUser();
$name = $user->getName();
$avatar = $this->request->getScheme() .'://' . $this->request->getHttpHost() . $this->request->getBasePath() . '/uploads/avatar/' . $user->getAvatar();
$username = $user->getUsername();
$activityObject = new ActivityObject();
$activityObject->setName($name);
$activityObject->setUsername($username);
$activityObject->setAvatar($avatar);
$activityObject->setData($data);
$hasChildren = ActivityType::hasChildren($type);
if ($hasChildren) {
if ($groupNumber != $previousGroupNumber) {
$activityItemObject->setParent($activityObject);
} else {
$activityItemObject->addChild($activityObject);
}
} else {
$activityItemObject->setParent($activityObject);
}
$activityMap[$groupNumber] = $activityItemObject;
$previousGroupNumber = $groupNumber;
}
$display = [];
/** @var ActivityItemObject $value */
foreach ($activityMap as $key => $value) {
$display[$key] = $value->toArray();
}
return $display;
}
Here’s the code for creating new documentary series.
import { YoutubeService } from './../../../../services/youtube.service';
import { OMDBService } from './../../../../services/omdb.service';
import { AngularEditorConfig } from '@kolkov/angular-editor';
import { FormBuilder, FormControl, Validators, FormArray, FormGroup } from '@angular/forms';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { CategoryService } from './../../../../services/category.service';
import { VideoSourceService } from './../../../../services/video-source.service';
import { HttpParams } from '@angular/common/http';
import { YearService } from './../../../../services/year.service';
import { UserService } from './../../../../services/user.service';
import { DocumentaryService } from './../../../../services/documentary.service';
import { Router, ActivatedRoute } from '@angular/router';
import { Episodic } from './../../../../models/episodic.model';
import { Documentary } from 'src/app/models/documentary.model';
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
import { Location } from "@angular/common";
@Component({
selector: 'app-documentary-add-episodic',
templateUrl: './documentary-add-episodic.component.html',
styleUrls: ['./documentary-add-episodic.component.css']
})
export class DocumentaryAddEpisodicComponent implements OnInit {
private documentary: Documentary;
private form: FormGroup;
private imdbForm: FormGroup;
private youtubeForm: FormGroup;
private submitted = false;
private errors = null;
private posterImgURL;
private wideImgURL;
private thumbnailImgURLDict = {};
private page;
private slug;
private editMode = false;
private me;
private config: any;
private seasonIndex;
private episodeIndex;
editorConfig: AngularEditorConfig = {
editable: true,
spellcheck: true,
height: '25rem',
minHeight: '5rem',
placeholder: 'Enter text here...',
translate: 'no',
uploadUrl: 'v1/images', // if needed
};
private showPage = false;
private hasToggledForm = false;
private showForm = false;
private showAddTitleButton = true;
private showDocumentaries = true;
private isFetchingYears = false;
private isFetchingVideoSources = false;
private isFetchingCategories = false;
private isFetchingDocumentaries = false;
private isFetchingDocumentariesFromIMDB = false;
private isFetchingDocumentaryFromIMDB = false;
private showSearchedDocumentariesFromIMDB = false;
private showSearchedDocumentaryFromIMDB = false;
private searchedDocumentariesFromIMDB;
private searchedDocumentaryFromIMDB;
private isFetchingVideosFromYoutube = false;
private showSearchedVideosFromYoutube = false;
private searchedVideosFromYoutube;
private years;
private videoSources;
private categories;
private myDocumentaries;
private queryParamsSubscription;
private routeParamsSubscription;
private documentaryBySlugSubscription;
private meSubscription;
private videoSourcesSubscription;
private categoriesSubscription;
private getByImdbIdSubscription;
private ombdSearchSubscription;
private youtubeByIdSubscription;
private youtubeSearchSubscription;
private closeResult: string;
private seasonNumber = 1;
private episodeNumber = 1;
private imdbType;
constructor(
private documentaryService: DocumentaryService,
private userService: UserService,
private yearService: YearService,
private videoSourceService: VideoSourceService,
private categoryService: CategoryService,
private omdbService: OMDBService,
private youtubeService: YoutubeService,
private route: ActivatedRoute,
private cd: ChangeDetectorRef,
private router: Router,
private location: Location,
private modalService: NgbModal,
private fb: FormBuilder
) { }
ngOnInit() {
this.initModel();
this.queryParamsSubscription = this.route
.queryParams
.subscribe(params => {
this.page = +params['page'] || 1;
this.routeParamsSubscription = this.route
.paramMap
.subscribe(params => {
this.slug = params['params']['slug'];
this.editMode = this.slug != null;
if (this.editMode) {
this.documentaryBySlugSubscription = this.documentaryService
.getDocumentaryBySlug(this.slug)
.subscribe((result: any) => {
this.documentary = result;
this.toggleForm();
this.showPage = true;
});
} else {
this.meSubscription = this.userService
.getMe()
.subscribe(me => {
this.me = me;
if (!this.hasToggledForm) {
this.fetchDocumentaries();
this.showPage = true;
}
})
}
})
})
}
initModel() {
this.documentary = new Documentary();
let episodic = new Episodic();
this.documentary.episodic = episodic;
}
toggleForm() {
this.showAddTitleButton = false;
this.showDocumentaries = false;
this.showForm = !this.showForm;
this.initYears();
this.initVideoSources();
this.initCategories();
this.initForm();
}
initForm(seasons = null) {
let title = this.documentary.title;
let category = this.documentary.category;
let storyline = this.documentary.storyline;
let summary = this.documentary.summary;
// let videoSource = null;
//if (this.documentary.standalone.videoSource) {
// videoSource = this.documentary.standalone.videoSource.id
// }
//let videoId = this.documentary.standalone.videoId;
let year = this.documentary.year;
let yearFrom = this.documentary.yearFrom;
let yearTo = this.documentary.yearTo;
//let length = this.documentary.length;
let poster = this.documentary.poster;
this.posterImgURL = this.documentary.poster;
let wideImage = this.documentary.wideImage;
this.wideImgURL = this.documentary.wideImage;
let imdbId = this.documentary.imdbId;
this.form = this.fb.group({
'title': new FormControl(title, [Validators.required]),
'category': new FormControl(category, [Validators.required]),
'storyline': new FormControl(storyline, [Validators.required]),
'summary': new FormControl(summary, [Validators.required]),
'yearFrom': new FormControl(yearFrom, [Validators.required]),
'yearTo': new FormControl(yearTo, [Validators.required]),
'poster': new FormControl(poster, [Validators.required]),
'wideImage': new FormControl(wideImage, [Validators.required]),
'imdbId': new FormControl(imdbId),
'seasons': this.fb.array([], Validators.required)
});
if (seasons != null) {
seasons.forEach(season => {
this.addSeason(season);
});
}
console.log("this.thumbnailImgURLDict");
console.log(this.thumbnailImgURLDict);
}
getEpisodeNumber(episode) {
return episode.value.number;
}
getSeasonNumber(season) {
return season.value.number;
}
addSeason(season = null) {
if (season != null) {
this.seasonNumber = season.number;
}
let control = <FormArray>this.form.controls.seasons;
control.push(
this.fb.group({
'number': new FormControl(this.seasonNumber, [Validators.required]),
'episodes': this.fb.array([], Validators.required)
})
);
if (season != null) {
let episodes = season.episodes;
if (season != null && episodes != null) {
episodes.forEach(episode => {
let episodesControl = control.at(this.seasonNumber - 1).get('episodes');
this.addEpisode(episodesControl, season, episode);
})
}
}
if (season == null) {
this.seasonNumber++;
}
}
deleteSeason(number) {
var seasonsFormArray = this.form.get("seasons") as FormArray;
let index = 0;
seasonsFormArray.value.forEach(seasonArray => {
if (number == seasonArray.number) {
seasonsFormArray.removeAt(index);
return;
}
index++;
});
}
deleteEpisode(control, index) {
control.removeAt(index);
}
insertEpisode(control, index) {
let title;
let storyline;
let summary;
let year;
let length;
let imdbId;
let videoId;
let videoSource = 2;
let thumbnail;
let episodeNumber;
control.insert(index,
this.fb.group({
'number': new FormControl(episodeNumber, [Validators.required]),
'title': new FormControl(title, [Validators.required]),
'imdbId': new FormControl(imdbId),
'storyline': new FormControl(storyline, [Validators.required]),
'summary': new FormControl(summary, [Validators.required]),
'length': new FormControl(length, [Validators.required]),
'year': new FormControl(year, [Validators.required]),
'videoSource': new FormControl(videoSource, [Validators.required]),
'videoId': new FormControl(videoId, [Validators.required]),
'thumbnail': new FormControl(thumbnail, [Validators.required]),
}));
}
addEpisode(control, season, episode = null) {
let title;
let storyline;
let summary;
let year;
let length;
let imdbId;
let videoId;
let videoSource = 2;
let thumbnail;
let episodeNumber;
if (episode != null) {
episodeNumber = episode.number;
title = episode.title;
imdbId = episode.imdbId;
thumbnail = episode.thumbnail;
summary = episode.summary;
storyline = episode.storyline;
year = episode.year;
videoId = episode.videoId;
videoSource = 2;
length = episode.length;
if (this.thumbnailImgURLDict[season.number] == undefined) {
this.thumbnailImgURLDict[season.number] = {};
}
if (this.thumbnailImgURLDict[season.number][episode.number] == undefined) {
this.thumbnailImgURLDict[season.number][episode.number] = {};
}
this.thumbnailImgURLDict[season.number][episode.number] = thumbnail;
}
control.push(
this.fb.group({
'number': new FormControl(episodeNumber, [Validators.required]),
'title': new FormControl(title, [Validators.required]),
'imdbId': new FormControl(imdbId),
'storyline': new FormControl(storyline, [Validators.required]),
'summary': new FormControl(summary, [Validators.required]),
'length': new FormControl(length, [Validators.required]),
'year': new FormControl(year, [Validators.required]),
'videoSource': new FormControl(videoSource, [Validators.required]),
'videoId': new FormControl(videoId, [Validators.required]),
'thumbnail': new FormControl(thumbnail, [Validators.required]),
}));
}
get f() { return this.form.controls; }
getThumbnailForSeasonAndEpsiode(seasonNumber: number, episodeNumber: number) {
if (this.thumbnailImgURLDict[seasonNumber] == undefined) {
this.thumbnailImgURLDict[seasonNumber] = {};
}
return this.thumbnailImgURLDict[seasonNumber][episodeNumber];
}
onThumbnailChange(event, seasonIndex, episodeIndex) {
console.log(event);
let reader = new FileReader();
if (event.target.files && event.target.files.length) {
const [file] = event.target.files;
reader.readAsDataURL(file);
reader.onload = () => {
var seasonsFormArray = this.form.get("seasons") as FormArray;
var episodesFormArray = seasonsFormArray.at(seasonIndex).get("episodes") as FormArray;
episodesFormArray.at(episodeIndex)['controls']['thumbnail'].patchValue(reader.result);
let seasonNumber = seasonsFormArray.at(seasonIndex).value.number;
let episodeNumber = episodesFormArray.at(episodeIndex).value.number;
if (this.thumbnailImgURLDict[seasonNumber] == undefined) {
this.thumbnailImgURLDict[seasonNumber] = {};
}
this.thumbnailImgURLDict[seasonNumber][episodeNumber] = reader.result;
}
this.cd.markForCheck();
};
}
openIMDBModal(content, imdbType) {
console.log(imdbType);
this.imdbType = imdbType;
this.initIMDBFrom();
console.log(content);
this.modalService.open(content, { ariaLabelledBy: 'modal-omdb' }).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${reason}`;
});
}
initIMDBFrom() {
let title = this.form.value.title;
this.imdbForm = new FormGroup({
'title': new FormControl(title, [Validators.required])
});
}
imdbView(imdbId) {
console.log("imdbId");
console.log(imdbId);
this.isFetchingDocumentaryFromIMDB = true;
this.showSearchedDocumentariesFromIMDB = false;
this.showSearchedDocumentaryFromIMDB = true;
let imdbType = this.imdbType;
this.omdbService.getByImdbId(imdbId, imdbType)
.subscribe((result: any) => {
this.searchedDocumentaryFromIMDB = result;
this.isFetchingDocumentaryFromIMDB = false;
console.log("searchedDocumentaryFromIMDB");
console.log(this.searchedDocumentaryFromIMDB);
})
}
imdbSelect() {
let selectedDocumentary = this.searchedDocumentaryFromIMDB;
console.log("selectedDocumentary");
console.log(selectedDocumentary);
console.log("this.form");
console.log(this.form);
if (this.form.value.title == null) {
this.documentary.title = selectedDocumentary.title;
} else {
this.documentary.title = this.form.value.title;
}
if (this.form.value.imdbId != selectedDocumentary.imdbId) {
this.documentary.imdbId = selectedDocumentary.imdbId;
}
if (this.form.value.storyline == null) {
this.documentary.storyline = selectedDocumentary.storyline;
} else {
this.documentary.storyline = this.form.value.storyline;
}
if (this.form.value.yearFrom == null) {
this.documentary.yearFrom = selectedDocumentary.yearFrom;
} else {
this.documentary.yearFrom = this.form.value.yearFrom;
}
if (this.form.value.yearTo == null) {
this.documentary.yearTo = selectedDocumentary.yearTo;
} else {
this.documentary.yearTo = this.form.value.yearTo;
}
if (this.form.value.poster == null) {
this.documentary.poster = selectedDocumentary.poster;
this.posterImgURL = selectedDocumentary.poster;
} else {
this.documentary.poster = this.form.value.poster;
this.posterImgURL = this.form.value.poster;
}
let seasons = selectedDocumentary.seasons;
this.initForm(seasons);
this.modalService.dismissAll();
}
searchOMDB() {
this.isFetchingDocumentariesFromIMDB = true;
this.showSearchedDocumentaryFromIMDB = false;
this.showSearchedDocumentariesFromIMDB = true;
let titleOrId = this.imdbForm.value.title;
let imdbType = this.imdbType;
this.getByImdbIdSubscription = this.omdbService.getByImdbId(titleOrId, imdbType)
.subscribe((result: any) => {
result = [result];
this.searchedDocumentariesFromIMDB = result;
this.isFetchingDocumentariesFromIMDB = false;
},
(error) => {
this.ombdSearchSubscription = this.omdbService.getSearchedDocumentaries(titleOrId, imdbType)
.subscribe((result: any) => {
this.searchedDocumentariesFromIMDB = result;
this.isFetchingDocumentariesFromIMDB = false;
});
});
}
openYoutubeModal(content, seasonIndex: number, episodeIndex: number) {
this.seasonIndex = seasonIndex;
this.episodeIndex = episodeIndex;
this.initYoutubeForm();
this.modalService.open(content, { ariaLabelledBy: 'modal-youtube' }).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${reason}`;
});
}
initYoutubeForm() {
let seasonIndex = this.seasonIndex;
let episodeIndex = this.episodeIndex;
let seasonsFormArray = this.form.get("seasons") as FormArray;
let episodesFormArray = seasonsFormArray.at(seasonIndex).get("episodes") as FormArray;
let titleOrId = episodesFormArray.at(episodeIndex)['controls']['title'].value;
this.youtubeForm = new FormGroup({
'title': new FormControl(titleOrId, [Validators.required])
});
}
searchYoutube() {
this.isFetchingVideosFromYoutube = true;
this.showSearchedVideosFromYoutube = true;
let titleOrId = this.youtubeForm.value.title;
this.youtubeByIdSubscription = this.youtubeService.getById(titleOrId)
.subscribe((result: any) => {
this.searchedVideosFromYoutube = result['items'];
this.isFetchingVideosFromYoutube = false;
}, (error) => {
this.youtubeSearchSubscription = this.youtubeService.getSearchedDocumentaries(titleOrId)
.subscribe((result: any) => {
this.searchedVideosFromYoutube = result['items'];
this.isFetchingVideosFromYoutube = false;
});
});
}
youtubeSelect(selectedVideo) {
let seasonIndex = this.seasonIndex;
let episodeIndex = this.episodeIndex;
let seasonsFormArray = this.form.get("seasons") as FormArray;
let episodesFormArray = seasonsFormArray.at(seasonIndex).get("episodes") as FormArray;
let title = episodesFormArray.at(episodeIndex)['controls']['title'].value;
if (title == null || !title.trim()) {
let selectedTitle = selectedVideo.snippet.title;
episodesFormArray.at(episodeIndex)['controls']['title'].patchValue(selectedTitle);
}
let videoId = episodesFormArray.at(episodeIndex)['controls']['videoId'].value;
if (videoId == null || !videoId.trim()) {
let selectedVideoId = selectedVideo.id.videoId;
episodesFormArray.at(episodeIndex)['controls']['videoId'].patchValue(selectedVideoId);
}
let thumbnail = episodesFormArray.at(episodeIndex)['controls']['thumbnail'].value;
if (thumbnail == null || !thumbnail.trim()) {
let selectedThumbnail = selectedVideo.snippet.thumbnails.default.url;
episodesFormArray.at(episodeIndex)['controls']['thumbnail'].patchValue(selectedThumbnail);
let seasonNumber = seasonsFormArray.at(seasonIndex).value.number;
let episodeNumber = episodesFormArray.at(episodeIndex).value.number;
if (this.thumbnailImgURLDict[seasonNumber] == undefined) {
this.thumbnailImgURLDict[seasonNumber] = {};
}
this.thumbnailImgURLDict[seasonNumber][episodeNumber] = selectedThumbnail;
}
this.episodeIndex = null;
this.seasonIndex = null;
this.modalService.dismissAll();
}
fetchDocumentaries() {
if (this.editMode) {
this.showDocumentaries = false;
return;
}
this.isFetchingDocumentaries = true;
let params = new HttpParams();
params = params.append('page', this.page.toString());
this.location.go(this.router.url.split("?")[0], params.toString());
this.documentaryService.getMyEpisodicDocumentaries(params, this.me.username)
.subscribe(result => {
this.config = {
itemsPerPage: 5,
currentPage: this.page,
totalItems: result['count_results']
};
this.myDocumentaries = result['items'];
this.isFetchingDocumentaries = false;
this.showDocumentaries = true;
this.showAddTitleButton = true;
})
}
pageChanged(event) {
this.config.currentPage = event;
this.page = event;
this.fetchDocumentaries();
}
initYears() {
this.isFetchingYears = true;
this.years = this.yearService.getAllYearsForForm();
this.isFetchingYears = false;
}
initVideoSources() {
this.isFetchingVideoSources = true;
let params: HttpParams;
this.videoSourcesSubscription = this.videoSourceService.getAll(params)
.subscribe(result => {
this.videoSources = result;
console.log("this.videoSources");
console.log(this.videoSources);
this.isFetchingVideoSources = false;
});
}
initCategories() {
this.isFetchingCategories = true;
let params: HttpParams;
this.categoriesSubscription = this.categoryService.getAll(params)
.subscribe(result => {
this.categories = result;
this.isFetchingCategories = false;
});
}
onSubmit() {
this.errors = null;
console.log(this.f);
console.log(this.form.value);
this.submitted = true;
let formValue = this.form.value;
if (formValue.seasons.length === 0) {
this.errors = "You must add a season";
}
if (formValue.seasons[0].episodes.length === 0) {
this.errors = "You must add an episode";
}
if (!this.form.valid) {
return;
}
this.errors = null;
if (this.editMode) {
this.documentaryService.editEpisodicDocumentary(this.documentary.id, formValue)
.subscribe((result: any) => {
//this.reset();
this.router.navigate(["/add/episodic"]);
},
(error) => {
console.log(error);
this.errors = error.error;
});
} else {
this.documentaryService.createEpisodicDocumentary(formValue)
.subscribe((result: any) => {
//this.reset();
this.router.navigate(["/add/episodic"]);
},
(error) => {
console.log(error);
this.errors = error.error;
});
}
}
ngOnDestroy() {
this.queryParamsSubscription.unsubscribe();
this.routeParamsSubscription.unsubscribe();
if (this.documentaryBySlugSubscription != null) {
this.documentaryBySlugSubscription.unsubscribe();
}
if (this.meSubscription != null) {
this.meSubscription.unsubscribe();
}
if (this.getByImdbIdSubscription != null) {
this.getByImdbIdSubscription.unsubscribe();
}
if (this.ombdSearchSubscription != null) {
this.ombdSearchSubscription.unsubscribe();
}
this.meSubscription.unsubscribe();
}
}
See also: The Criteria Pattern
import { Status } from './../../models/status.model';
import { CategoryService } from './../../services/category.service';
import { VideoSourceService } from './../../services/video-source.service';
import { VideoSource } from './../../models/video-source.model';
import { ActivatedRoute, Router } from '@angular/router';
import { DocumentaryService } from './../../services/documentary.service';
import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpParams } from '@angular/common/http';
import { Documentary } from './../../models/documentary.model';
import { Location } from "@angular/common";
import { Category } from 'src/app/models/category.model';
@Component({
selector: 'app-admin-documentaries',
templateUrl: './admin-documentaries.component.html',
styleUrls: ['./admin-documentaries.component.css']
})
export class AdminDocumentariesComponent implements OnInit, OnDestroy {
private documentariesSubscription;
private queryParamsSubscription;
private videoSourcesSubscription;
private categoriesSubscription;
public documentaries: Array<Documentary>;
public videoSources: Array<VideoSource>;
public categories: Array<Category>;
public statuses: Array<Status> = [
{ id: 'pending', name: 'Pending' },
{ id: 'publish', name: 'Published' }
];
public featuredOptions = [
{ id: true },
{ id: false }
];
config: any;
private page;
private videoSource;
private previousVideoSource;
private previousCategory;
private category;
private status;
private previousStatus;
private featured;
private previousFeatured;
constructor(
private service: DocumentaryService,
private videoSourceService: VideoSourceService,
private categoryService: CategoryService,
private route: ActivatedRoute,
private location: Location,
private router: Router) { }
ngOnInit() {
this.queryParamsSubscription = this.route
.queryParams
.subscribe(params => {
this.page = +params['page'] || 1;
this.videoSource = +params['videoSource'] || 'all';
this.category = +params['category'] || 'all';
this.status = params['status'] || 'all';
this.featured = params['featured'] || 'all';
this.fetchVideoSources();
this.fetchCategories();
this.fetchDocumentaries();
})
}
fetchDocumentaries() {
let params = new HttpParams();
if (this.videoSource) {
if (this.videoSource != 'all') {
params = params.append('videoSource', this.videoSource.toString());
if (this.videoSource != this.previousVideoSource) {
this.page = 1;
}
}
this.previousVideoSource = this.videoSource;
}
if (this.category) {
if (this.category != 'all') {
params = params.append('category', this.category.toString());
if (this.category != this.previousCategory) {
this.page = 1;
}
}
this.previousCategory = this.category;
}
if (this.status) {
if (this.status != 'all') {
params = params.append('status', this.status.toString());
if (this.status != this.previousStatus) {
this.page = 1;
}
}
this.previousStatus = this.status;
}
if (this.featured) {
if (this.featured != 'all') {
params = params.append('featured', this.featured.toString());
if (this.featured != this.previousFeatured) {
this.page = 1;
}
}
this.previousFeatured = this.featured;
}
params = params.append('page', this.page.toString());
this.location.go(this.router.url.split("?")[0], params.toString());
this.documentariesSubscription = this.service.getAllDocumentaries(params)
.subscribe(
result => {
this.config = {
itemsPerPage: 12,
currentPage: this.page,
totalItems: result['count_results']
};
this.documentaries = result['items'];
console.log(result);
}
);
}
fetchVideoSources() {
this.videoSourcesSubscription = this.videoSourceService.getAllVideoSources()
.subscribe(result => {
this.videoSources = <any> result;
});
}
fetchCategories() {
this.categoriesSubscription = this.categoryService.getAllCategories()
.subscribe(result => {
this.categories = <any> result;
});
}
pageChanged(event) {
console.log(event);
this.config.currentPage = event;
this.page = event;
this.fetchDocumentaries();
}
onVideoSourceSelected(value: string) {
this.videoSource = value;
this.fetchDocumentaries();
}
onCategoriesSelected(value: string) {
this.category = value;
this.fetchDocumentaries();
}
onStatusSelected(value: string) {
this.status = value;
this.fetchDocumentaries();
}
onFeaturedSelected(value: string) {
this.featured = value;
this.fetchDocumentaries();
}
ngOnDestroy() {
this.documentariesSubscription.unsubscribe();
this.queryParamsSubscription.unsubscribe();
this.videoSourcesSubscription.unsubscribe();
this.categoriesSubscription.unsubscribe();
}
}