Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ui component #4

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
38f6fd7
Add ui client
atomkevich May 3, 2016
8fe4d54
Delete uiDesigner.xml
atomkevich May 3, 2016
9a9f4e7
Delete jsLibraryMappings.xml
atomkevich May 3, 2016
da43c75
Delete vcs.xml
atomkevich May 3, 2016
a6db745
Add examples
atomkevich May 3, 2016
dabc22b
Merge remote-tracking branch 'origin/master'
atomkevich May 3, 2016
21bf96a
Add examples
atomkevich May 3, 2016
af8208a
Fix code review
atomkevich May 3, 2016
9fe5a64
Merge remote-tracking branch 'upstream/master'
atomkevich May 3, 2016
2da46c1
Change structure of application
atomkevich May 4, 2016
82b183d
Change structure of application
atomkevich May 4, 2016
b71bcfd
Add description
atomkevich May 4, 2016
c1d50f3
Add description
atomkevich May 4, 2016
8bc3fce
Merge remote-tracking branch 'upstream/master'
atomkevich May 5, 2016
03ff1bf
Merge remote-tracking branch 'upstream/master'
atomkevich May 5, 2016
fdc7922
Update travis badge to point to fvlad build
fvlad May 7, 2016
a57abfc
Merge remote-tracking branch 'origin/master' into client
fvlad May 7, 2016
2f9e168
Move client files around
fvlad May 8, 2016
e5172b9
Merge pull request #1 from fvlad/client
atomkevich May 10, 2016
5fddb32
add scoring
atomkevich May 10, 2016
22cb596
add scoring
atomkevich May 10, 2016
243b627
Merge remote-tracking branch 'upstream/master'
atomkevich May 11, 2016
d56e6bc
Add mxm client
atomkevich May 11, 2016
2b0abdb
fix config version
atomkevich May 11, 2016
34b2d99
fix versions for 7 java
atomkevich May 11, 2016
98ca929
fix versions for 7 java
atomkevich May 11, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
.lib/
dist/*
target/
.idea/*
lib_managed/
src_managed/
project/boot/
Expand All @@ -28,4 +29,8 @@ Icon?
.idea/

# Vagrant
.vagrant/
.vagrant/

# nodejs
node_modules/

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ lyrics-engine
=============

[![Join the chat at https://gitter.im/scalalab3/lyrics-engine](https://badges.gitter.im/scalalab3/lyrics-engine.svg)](https://gitter.im/scalalab3/lyrics-engine?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/scalalab3/lyrics-engine.svg?branch=master)](https://travis-ci.org/scalalab3/lyrics-engine)
[![Build Status](https://travis-ci.org/fvlad/lyrics-engine.svg?branch=master)](https://travis-ci.org/fvlad/lyrics-engine)


Development
Expand Down
13 changes: 12 additions & 1 deletion api/README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
Launch SBT:

$ sbt

Build UI component

$ cd lyrics-engine/api/src/main/resources
$ npm install
$ grunt
$ ls lyrics-engine/api/src/main/resources/js/scripts/ (home.js, recommend.js)


To compile everything and run all tests:

Expand All @@ -14,4 +22,7 @@ To start the application:

To stop the application:

> re-stop
> re-stop


An example of our site you can see by the link **/lyrics-engine/examples**
7 changes: 6 additions & 1 deletion api/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ libraryDependencies ++= {
"io.spray" %% "spray-testkit" % sprayV % "test",
"com.typesafe.akka" %% "akka-actor" % akkaV,
"com.typesafe.akka" %% "akka-testkit" % akkaV % "test",
"org.specs2" %% "specs2-core" % "2.3.11" % "test"
"org.specs2" %% "specs2-core" % "2.3.11" % "test",
"io.spray" %% "spray-json" % "1.3.2",
"org.scalacheck" %% "scalacheck" % "1.13.1" % "test",
"org.scalatest" %% "scalatest" % "2.2.0" % "test",
"org.mongodb" % "bson" % "3.2.2"

)
}

4 changes: 4 additions & 0 deletions api/src/main/resources/application.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,8 @@ akka {

spray.can.server {
request-timeout = 1s
}
http {
interface = "0.0.0.0"
port = 9000
}
18 changes: 7 additions & 11 deletions api/src/main/scala/scalalab3/lyricsengine/Boot.scala
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
package scalalab3.lyricsengine

import akka.actor._
import akka.actor.{Props, ActorSystem}
import akka.io.IO
import akka.pattern.ask
import akka.util.Timeout
import com.typesafe.config.ConfigFactory
import spray.can.Http

import scala.concurrent.duration._

import akka.pattern.ask
/**
* @author Vlad Fefelov
*/
object Boot extends App {

// we need an ActorSystem to host our application in
implicit val system = ActorSystem("on-spray-can")

// create and start our service actor
val service = system.actorOf(Props[LyricsServiceActor], "http-service")
implicit val system = ActorSystem("song-recommendation-system")

val service = system.actorOf(Props[LyricsServiceActor], "lyrics-service")
val config = ConfigFactory.load();
implicit val timeout = Timeout(5 seconds)
// start a new HTTP server on port 8080 with our service actor as the handler
IO(Http).ask(Http.Bind(service, interface = "localhost", port = 8080))
IO(Http) ? Http.Bind(service, interface = config.getString("http.interface"), port = config.getInt("http.port"))
}
37 changes: 37 additions & 0 deletions api/src/main/scala/scalalab3/lyricsengine/CorsSupport.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package scalalab3.lyricsengine

/**
* Created by atomkevich on 5/5/16.
*/

import spray.http.{HttpMethods, HttpMethod, HttpResponse, AllOrigins}
import spray.http.HttpHeaders._
import spray.http.HttpMethods._
import spray.routing._

// see also https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
trait CORSSupport {
this: HttpService =>

private val allowOriginHeader = `Access-Control-Allow-Origin`(AllOrigins)
private val optionsCorsHeaders = List(
`Access-Control-Allow-Headers`("Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding, Accept-Language, Host, Referer, User-Agent"),
`Access-Control-Max-Age`(1728000))

def cors[T]: Directive0 = mapRequestContext { ctx => ctx.withRouteResponseHandling({
//It is an option requeset for a resource that responds to some other method
case Rejected(x) if (ctx.request.method.equals(HttpMethods.OPTIONS) && !x.filter(_.isInstanceOf[MethodRejection]).isEmpty) => {
val allowedMethods: List[HttpMethod] = x.filter(_.isInstanceOf[MethodRejection]).map(rejection=> {
rejection.asInstanceOf[MethodRejection].supported
})
ctx.complete(HttpResponse().withHeaders(
`Access-Control-Allow-Methods`(OPTIONS, allowedMethods :_*) :: allowOriginHeader ::
optionsCorsHeaders
))
}
}).withHttpResponseHeadersMapped { headers =>
allowOriginHeader :: headers

}
}
}
82 changes: 67 additions & 15 deletions api/src/main/scala/scalalab3/lyricsengine/LyricsService.scala
Original file line number Diff line number Diff line change
@@ -1,27 +1,53 @@
package scalalab3.lyricsengine

import akka.actor.Actor
import akka.actor.{Actor, Props}
import akka.pattern.ask
import akka.util.Timeout
import spray.http.StatusCodes
import spray.routing.HttpService
import spray.json.DefaultJsonProtocol
import spray.routing.{Directives, HttpService}

import scala.concurrent.duration._
import scala.language.postfixOps
import scala.util.{Failure, Success}
import scalalab3.lyricsengine.domain.SongMeta
import scalalab3.lyricsengine.scoring.ScoringActor

// we don't implement our route structure directly in the service actor because
// we want to be able to test it independently, without having to spin up an actor
class LyricsServiceActor extends Actor with LyricsService {

// the HttpService trait defines only one abstract member, which
// connects the services environment to the enclosing actor or test
def actorRefFactory = context

// this actor only runs our route, but you could add
// other things here, like request stream processing
// or timeout handling
implicit val system = context.system

def receive = runRoute(route)


}

object SongMetaJsonSupport extends DefaultJsonProtocol {
implicit val trackFormat = jsonFormat5(SongMeta)
}

// this trait defines our service behavior independently from the service actor
trait LyricsService extends HttpService {
trait LyricsService extends HttpService with CORSSupport with Directives {
implicit val timeout = Timeout(10 seconds)

val scoringActor = actorRefFactory.actorOf(Props[ScoringActor])

val route =
val songs = List(
SongMeta(Some(1), Some("artist1"), Some("songName1"), Some("album1"), "text1"),
SongMeta(Some(2), Some("artist1"), Some("songName1"), Some("album1"), "text1"),
SongMeta(Some(3), Some("artist1"), Some("songName1"), Some("album1"), "text1"),
SongMeta(Some(4), Some("artist1"), Some("songName1"), Some("album1"), "text1"),
SongMeta(Some(5), Some("artist1"), Some("songName1"), Some("album1"), "text1"))
val route = cors {
import spray.httpx.SprayJsonSupport._

import SongMetaJsonSupport._
import scala.concurrent.ExecutionContext.Implicits.global
// implicit def executionContext = actorRefFactory.dispatcher
path("match") {
post {
entity(as[String]) { msg =>
Expand All @@ -31,12 +57,38 @@ trait LyricsService extends HttpService {
}
}
} ~
path("health") {
get {
complete {
StatusCodes.OK
path("health") {
get {
complete {
StatusCodes.OK
}
}
} ~
pathPrefix("api") {
path("search") {
get {
complete(songs)
}
} ~
path("recommend") {
post {
entity(as[SongMeta]) { song: SongMeta =>
//TODO: Check if song has id. If not - song doesn't present in out system.
// So using mxm client find full song meta with id or otherwise generate unique object id.
// Then async save to mongoDB.
//TODO: FIX TRACK ID
val recommendedSongIds = ask(scoringActor, song.copy(trackId = Some(0))).mapTo[List[Long]]
onComplete(recommendedSongIds) {
case Success(ids) => {
//TODO: find songs by ids in mongoDB
ids.foreach(println)
complete(songs)
}
case Failure(ex) => complete(s"An error occurred: ${ex.getMessage}")
}
}
}
}
}
}

}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package scalalab3.lyricsengine

import akka.actor.ActorSystem
import org.specs2.mutable.Specification
import spray.http._
import spray.testkit.Specs2RouteTest

class LyricsServiceSpec extends Specification with Specs2RouteTest with LyricsService {
def actorRefFactory = system
implicit def actorRefFactory: ActorSystem = system

"LyricsService" should {

Expand Down
7 changes: 5 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ scalaVersion := "2.11.8"

lazy val domain = project in file("domain")
lazy val parser = project in file("parser") dependsOn domain
lazy val api = project in file("api")

lazy val scoring = project in file("scoring") dependsOn domain
lazy val api = project in file("api") dependsOn scoring
lazy val client = project in file("client")
lazy val model = project in file("model") dependsOn parser
lazy val mxm = project in file("mxm") dependsOn domain
33 changes: 33 additions & 0 deletions client/Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

watch: {
react: {
files: 'js/react_components/*.jsx',
tasks: ['browserify']
}
},

browserify: {
options: {
transform: [ require('grunt-react').browserify ]
},
client: {
src: ['js/react_components/*.jsx', 'js/react_components/modules/Home.jsx'],
dest: 'js/scripts/home.js'
},
js: {
src: ['js/react_components/*.jsx', 'js/react_components/modules/Recommend.jsx'],
dest: 'js/scripts/recommend.js'
}
}
});

grunt.loadNpmTasks('grunt-browserify');
grunt.loadNpmTasks('grunt-contrib-watch');

grunt.registerTask('default', [
'browserify'
]);
};
Loading