├── .git-blame-ignore-revs
├── .github
├── CODEOWNERS
├── dependabot.yml
└── workflows
│ ├── ci.yml
│ └── scala-steward.yml
├── .gitignore
├── .scalafmt.conf
├── CONTRIBUTING.md
├── LICENSE.txt
├── build.sbt
├── logo.png
├── project
├── build.properties
└── plugins.sbt
├── readme.md
├── release.sh
├── scalikejdbc-play-dbapi-adapter
├── .gitignore
├── readme.md
├── src
│ ├── main
│ │ └── scala
│ │ │ └── scalikejdbc
│ │ │ ├── PlayDBApiAdapter.scala
│ │ │ └── PlayDBApiAdapterModule.scala
│ └── test
│ │ └── scala
│ │ └── scalikejdbc
│ │ └── PlayDBApiAdapterModuleSpec.scala
└── test
│ └── zentasks
│ ├── Procfile
│ ├── README
│ ├── app
│ ├── assets
│ │ ├── javascripts
│ │ │ └── main.coffee
│ │ └── stylesheets
│ │ │ ├── apps
│ │ │ └── _tasks.less
│ │ │ ├── libs
│ │ │ ├── _mate.less
│ │ │ ├── _reset.less
│ │ │ └── _theme.less
│ │ │ ├── login.less
│ │ │ ├── main.less
│ │ │ └── main
│ │ │ ├── _breadcrumb.less
│ │ │ ├── _drawer.less
│ │ │ ├── _header.less
│ │ │ ├── _layout.less
│ │ │ └── _widgets.less
│ ├── controllers
│ │ ├── Application.scala
│ │ ├── Projects.scala
│ │ └── Tasks.scala
│ ├── models
│ │ ├── Project.scala
│ │ ├── Task.scala
│ │ └── User.scala
│ └── views
│ │ ├── dashboard.scala.html
│ │ ├── login.scala.html
│ │ ├── main.scala.html
│ │ ├── projects
│ │ ├── group.scala.html
│ │ └── item.scala.html
│ │ └── tasks
│ │ ├── folder.scala.html
│ │ ├── index.scala.html
│ │ └── item.scala.html
│ ├── conf
│ ├── application.conf
│ ├── db
│ │ └── fixtures
│ │ │ ├── default
│ │ │ ├── project.sql
│ │ │ ├── project_member.sql
│ │ │ ├── task.sql
│ │ │ └── users.sql
│ │ │ └── secondary
│ │ │ ├── project.sql
│ │ │ ├── project_member.sql
│ │ │ ├── task.sql
│ │ │ └── users.sql
│ ├── evolutions
│ │ ├── default
│ │ │ └── 1.sql
│ │ └── secondary
│ │ │ └── 1.sql
│ ├── prod.conf
│ └── routes
│ ├── project
│ └── build.properties
│ └── public
│ ├── images
│ ├── arrow-left.png
│ ├── breadcrumb-1.png
│ ├── breadcrumb-2.png
│ ├── breadcrumb.png
│ ├── icons
│ │ ├── addRemove.png
│ │ ├── clock.png
│ │ ├── delete.png
│ │ ├── drawer.folder.png
│ │ ├── folder.png
│ │ ├── home.png
│ │ ├── options.png
│ │ ├── user.png
│ │ └── user2.png
│ ├── loading.gif
│ └── pattern.png
│ └── javascripts
│ ├── backbone-min.js
│ └── underscore-min.js
├── scalikejdbc-play-fixture
├── readme.md
└── src
│ ├── main
│ └── scala
│ │ └── scalikejdbc
│ │ ├── PlayFixtureModule.scala
│ │ └── play
│ │ ├── Fixture.scala
│ │ ├── FixtureNotFoundException.scala
│ │ └── FixtureSupport.scala
│ └── test
│ ├── resources
│ └── db
│ │ └── fixtures
│ │ ├── default
│ │ ├── project.sql
│ │ └── users.sql
│ │ └── secondary
│ │ └── a.sql
│ └── scala
│ └── scalikejdbc
│ └── play
│ ├── FixtureSpec.scala
│ └── FixtureSupportSpec.scala
├── scalikejdbc-play-initializer
├── .gitignore
├── readme.md
├── src
│ ├── main
│ │ └── scala
│ │ │ └── scalikejdbc
│ │ │ ├── PlayInitializer.scala
│ │ │ └── PlayModule.scala
│ └── test
│ │ └── scala
│ │ └── scalikejdbc
│ │ └── PlayModuleSpec.scala
└── test
│ └── zentasks
│ ├── Procfile
│ ├── README
│ ├── app
│ ├── assets
│ │ ├── javascripts
│ │ │ └── main.coffee
│ │ └── stylesheets
│ │ │ ├── apps
│ │ │ └── _tasks.less
│ │ │ ├── libs
│ │ │ ├── _mate.less
│ │ │ ├── _reset.less
│ │ │ └── _theme.less
│ │ │ ├── login.less
│ │ │ ├── main.less
│ │ │ └── main
│ │ │ ├── _breadcrumb.less
│ │ │ ├── _drawer.less
│ │ │ ├── _header.less
│ │ │ ├── _layout.less
│ │ │ └── _widgets.less
│ ├── controllers
│ │ ├── Application.scala
│ │ ├── Projects.scala
│ │ └── Tasks.scala
│ ├── models
│ │ ├── Project.scala
│ │ ├── Task.scala
│ │ └── User.scala
│ └── views
│ │ ├── dashboard.scala.html
│ │ ├── login.scala.html
│ │ ├── main.scala.html
│ │ ├── projects
│ │ ├── group.scala.html
│ │ └── item.scala.html
│ │ └── tasks
│ │ ├── folder.scala.html
│ │ ├── index.scala.html
│ │ └── item.scala.html
│ ├── conf
│ ├── application.conf
│ ├── db
│ │ ├── fixtures
│ │ │ ├── default
│ │ │ │ ├── project.sql
│ │ │ │ ├── project_member.sql
│ │ │ │ ├── task.sql
│ │ │ │ └── users.sql
│ │ │ └── secondary
│ │ │ │ ├── project.sql
│ │ │ │ ├── project_member.sql
│ │ │ │ ├── task.sql
│ │ │ │ └── users.sql
│ │ └── migration
│ │ │ ├── default
│ │ │ └── V1__create_tables.sql
│ │ │ └── secondary
│ │ │ └── V1__create_tables.sql
│ ├── prod.conf
│ └── routes
│ ├── project
│ └── build.properties
│ └── public
│ ├── images
│ ├── arrow-left.png
│ ├── breadcrumb-1.png
│ ├── breadcrumb-2.png
│ ├── breadcrumb.png
│ ├── icons
│ │ ├── addRemove.png
│ │ ├── clock.png
│ │ ├── delete.png
│ │ ├── drawer.folder.png
│ │ ├── folder.png
│ │ ├── home.png
│ │ ├── options.png
│ │ ├── user.png
│ │ └── user2.png
│ ├── loading.gif
│ └── pattern.png
│ └── javascripts
│ ├── backbone-min.js
│ └── underscore-min.js
└── windows_test_filter.sbt
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # Scala Steward: Reformat with scalafmt 3.8.2
2 | 1f5b2be4fa1dffb33489ff089ae197357c073f9c
3 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @seratch @xuwei-k
2 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "github-actions"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | pull_request:
4 | push:
5 | schedule:
6 | - cron: '0 15 * * 3'
7 | jobs:
8 | test:
9 | timeout-minutes: 30
10 | strategy:
11 | fail-fast: false
12 | matrix:
13 | os:
14 | - windows-latest
15 | - ubuntu-latest
16 | runs-on: ${{ matrix.os }}
17 | steps:
18 | - uses: actions/checkout@v4
19 | - uses: actions/setup-java@v4
20 | with:
21 | java-version: 11
22 | distribution: temurin
23 | - uses: sbt/setup-sbt@v1
24 | - uses: coursier/cache-action@v6
25 | - shell: bash
26 | run: |
27 | case ${{ matrix.os }} in
28 | "windows-latest")
29 | sbt -v -J-Dfile.encoding=Windows-31J "+test"
30 | ;;
31 | *)
32 | sbt -v scalafmtSbtCheck "+ scalafmtCheckAll" "+test"
33 | esac
34 |
--------------------------------------------------------------------------------
/.github/workflows/scala-steward.yml:
--------------------------------------------------------------------------------
1 | name: scala-steward
2 | on:
3 | push:
4 | branches: [ master ]
5 | schedule:
6 | - cron: '0 0 * * *'
7 | workflow_dispatch:
8 | jobs:
9 | scala-steward:
10 | runs-on: ubuntu-latest
11 | if: ${{ github.repository_owner == 'scalikejdbc' }}
12 | timeout-minutes: 20
13 | steps:
14 | - name: Generate token
15 | id: generate_token
16 | uses: tibdex/github-app-token@v2
17 | with:
18 | app_id: 89631
19 | private_key: ${{ secrets.SCALIKEJDBC_BOT_KEY }}
20 | - name: Launch Scala Steward
21 | uses: scala-steward-org/scala-steward-action@v2.75.0
22 | with:
23 | github-token: ${{ steps.generate_token.outputs.token }}
24 | author-email: "74833019+scalikejdbc-bot[bot]@users.noreply.github.com"
25 | author-name: scalikejdbc-bot[bot]
26 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .bsp
2 | .settings
3 | .classpath
4 | .project
5 | *.iml
6 | *.ipr
7 | *.iws
8 | dist/
9 | lib_managed/
10 | project/boot/
11 | project/plugins/project/
12 | target/
13 |
14 | # use glob syntax.
15 | syntax: glob
16 | *.ser
17 | *.class
18 | *~
19 | *.bak
20 | #*.off
21 | *.old
22 |
23 | # eclipse conf file
24 | .settings
25 | .classpath
26 | .project
27 | .manager
28 | .scala_dependencies
29 |
30 | # idea
31 | .idea
32 | *.iml
33 |
34 | # building
35 | target
36 | build
37 | null
38 | tmp*
39 | temp*
40 | !templates/
41 | dist
42 | test-output
43 | build.log
44 |
45 | # other scm
46 | .svn
47 | .CVS
48 | .hg*
49 |
50 | # switch to regexp syntax.
51 | # syntax: regexp
52 | # ^\.pc/
53 |
54 | #SHITTY output not in target directory
55 | build.log
56 | .DS_Store
57 | derby.log
58 |
59 | *.db
60 |
61 | .lib
62 | sbt
63 |
64 | logs
65 | sandbox/db
66 |
--------------------------------------------------------------------------------
/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | version = 3.9.4
2 | trailingCommas = keep
3 | docstrings.style = keep
4 | indent.defnSite = 2
5 | indent.caseSite = 2
6 | indent.extendSite = 2
7 | spaces.inImportCurlyBraces = true
8 | runner.dialect = scala213
9 |
10 | fileOverride {
11 | "glob:**/src/main/scala-3/**" {
12 | runner.dialect = scala3
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## ScalikeJDBC Contributors' Guide
2 |
3 | ### Issues
4 |
5 | - Questions should be posted to [ScalikeJDBC Users Group](https://groups.google.com/forum/#!forum/scalikejdbc-users-group)
6 | - Please describe about your issue in detail (version, situation, examples)
7 |
8 | ### Pull Requests
9 |
10 | - Send pull requests toward "develop" or "feature/xxx" branches
11 | - Compatibility always must be kept as far as possible
12 | - scalafmt must be applied to all Scala source code
13 | - Prefer creating scala source code for each class/object/trait (of course, except for sealed trait)
14 |
15 | #### Testing your pull request
16 |
17 | Testing with default settings is required when push changes:
18 |
19 | ```sh
20 | sbt test
21 | ```
22 |
23 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright 2013 ScalikeJDBC committers
2 |
3 | Licensed under the Apache License, Version 2.0 (the "License");
4 | you may not use this file except in compliance with the License.
5 | You may obtain a copy of the License at
6 |
7 | https://www.apache.org/licenses/LICENSE-2.0
8 |
9 | Unless required by applicable law or agreed to in writing, software
10 | distributed under the License is distributed on an "AS IS" BASIS,
11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12 | either express or implied. See the License for the specific language
13 | governing permissions and limitations under the License.
14 |
15 |
--------------------------------------------------------------------------------
/build.sbt:
--------------------------------------------------------------------------------
1 | lazy val scalikejdbcVersion = "4.3.3"
2 |
3 | // published dependency version
4 | lazy val defaultPlayVersion = play.core.PlayVersion.current
5 |
6 | // internal only
7 | lazy val h2Version = "2.3.232"
8 | lazy val postgresqlVersion = "42.7.6"
9 |
10 | lazy val commonSettings = Seq(
11 | scalaVersion := "2.13.16",
12 | crossScalaVersions := Seq("2.13.16", "3.3.6"),
13 | libraryDependencySchemes += "org.scala-lang.modules" %% "scala-parser-combinators" % "always",
14 | Test / fork := true,
15 | javaOptions ++= {
16 | if (scala.util.Properties.isWin) {
17 | Seq("-Dfile.encoding=Windows-31J")
18 | } else {
19 | Nil
20 | }
21 | },
22 | scalacOptions ++= Seq("-deprecation", "-unchecked")
23 | )
24 |
25 | commonSettings
26 |
27 | lazy val baseSettings = commonSettings ++ Seq(
28 | organization := "org.scalikejdbc",
29 | version := "3.0.1-scalikejdbc-4.3",
30 | publishTo := (
31 | if (isSnapshot.value)
32 | None
33 | else
34 | Some(Opts.resolver.sonatypeStaging)
35 | ),
36 | publishMavenStyle := true,
37 | libraryDependencies += "org.specs2" %% "specs2-core" % "4.21.0" % "test",
38 | Global / transitiveClassifiers := Seq(Artifact.SourceClassifier),
39 | Test / publishArtifact := false,
40 | pomIncludeRepository := { x => false },
41 | pomExtra := _pomExtra
42 | )
43 |
44 | // scalikejdbc-play-initializer
45 | lazy val scalikejdbcPlayInitializer = Project(
46 | id = "play-initializer",
47 | base = file("scalikejdbc-play-initializer")
48 | ).settings(
49 | baseSettings,
50 | name := "scalikejdbc-play-initializer",
51 | libraryDependencies ++= Seq(
52 | "org.scalikejdbc" %% "scalikejdbc" % scalikejdbcVersion % "provided",
53 | "org.scalikejdbc" %% "scalikejdbc-config" % scalikejdbcVersion % "provided",
54 | "org.playframework" %% "play" % defaultPlayVersion % "provided",
55 | // play-jdbc is needed to test with DBApi
56 | "org.playframework" %% "play-jdbc" % defaultPlayVersion % "test",
57 | "org.playframework" %% "play-test" % defaultPlayVersion % "test",
58 | "com.h2database" % "h2" % h2Version % "test",
59 | guice % "test"
60 | ),
61 | )
62 |
63 | // scalikejdbc-play-dbapi-adapter
64 | lazy val scalikejdbcPlayDBApiAdapter = Project(
65 | id = "play-dbapi-adapter",
66 | base = file("scalikejdbc-play-dbapi-adapter")
67 | ).settings(
68 | baseSettings,
69 | name := "scalikejdbc-play-dbapi-adapter",
70 | libraryDependencies ++= Seq(
71 | "org.scalikejdbc" %% "scalikejdbc" % scalikejdbcVersion % "provided",
72 | "org.scalikejdbc" %% "scalikejdbc-config" % scalikejdbcVersion % "provided",
73 | "org.playframework" %% "play" % defaultPlayVersion % "provided",
74 | "org.playframework" %% "play-jdbc" % defaultPlayVersion % "compile",
75 | "org.playframework" %% "play-test" % defaultPlayVersion % "test",
76 | "com.h2database" % "h2" % h2Version % "test",
77 | guice % "test"
78 | ),
79 | )
80 |
81 | // scalikejdbc-play-fixture
82 | lazy val scalikejdbcPlayFixture = Project(
83 | id = "play-fixture",
84 | base = file("scalikejdbc-play-fixture")
85 | ).settings(
86 | baseSettings,
87 | name := "scalikejdbc-play-fixture",
88 | libraryDependencies ++= Seq(
89 | "org.scalikejdbc" %% "scalikejdbc" % scalikejdbcVersion % "provided",
90 | "org.scalikejdbc" %% "scalikejdbc-config" % scalikejdbcVersion % "provided",
91 | "org.playframework" %% "play" % defaultPlayVersion % "provided",
92 | "org.playframework" %% "play-test" % defaultPlayVersion % "test",
93 | "com.h2database" % "h2" % h2Version % "test"
94 | ),
95 | Test / testOptions += Tests
96 | .Argument(TestFrameworks.Specs2, "sequential", "true"),
97 | ).dependsOn(scalikejdbcPlayInitializer)
98 |
99 | // play plugin zentasks example
100 | lazy val scalikejdbcPlayInitializerTestZentasks = {
101 | val appName = "play-initializer-test-zentasks"
102 |
103 | val appDependencies = Seq(
104 | "org.scalikejdbc" %% "scalikejdbc" % scalikejdbcVersion,
105 | "org.scalikejdbc" %% "scalikejdbc-config" % scalikejdbcVersion,
106 | "org.flywaydb" %% "flyway-play" % "9.1.0",
107 | "com.h2database" % "h2" % h2Version,
108 | "org.postgresql" % "postgresql" % postgresqlVersion
109 | )
110 |
111 | Project(appName, file("scalikejdbc-play-initializer/test/zentasks"))
112 | .enablePlugins(play.sbt.PlayScala, PlayNettyServer)
113 | .disablePlugins(PlayPekkoHttpServer)
114 | .settings(
115 | commonSettings,
116 | libraryDependencies ++= appDependencies,
117 | )
118 | .dependsOn(scalikejdbcPlayInitializer, scalikejdbcPlayFixture)
119 | }
120 |
121 | // play dbapi adapter zentasks example
122 | lazy val scalikejdbcPlayDBApiAdapterTestZentasks = {
123 | val appName = "play-dbapi-adapter-test-zentasks"
124 |
125 | val appDependencies = Seq(
126 | "org.scalikejdbc" %% "scalikejdbc" % scalikejdbcVersion,
127 | "org.scalikejdbc" %% "scalikejdbc-config" % scalikejdbcVersion,
128 | "com.h2database" % "h2" % h2Version,
129 | "org.postgresql" % "postgresql" % postgresqlVersion
130 | )
131 |
132 | Project(appName, file("scalikejdbc-play-dbapi-adapter/test/zentasks"))
133 | .enablePlugins(play.sbt.PlayScala, PlayNettyServer)
134 | .disablePlugins(PlayPekkoHttpServer)
135 | .settings(
136 | commonSettings,
137 | libraryDependencies ++= appDependencies,
138 | )
139 | .dependsOn(scalikejdbcPlayDBApiAdapter, scalikejdbcPlayFixture)
140 | }
141 |
142 | val jdbcDriverDependenciesInTestScope = Seq(
143 | "com.h2database" % "h2" % h2Version % "test",
144 | "org.apache.derby" % "derby" % "10.10.2.+" % "test",
145 | "org.xerial" % "sqlite-jdbc" % "3.7.+" % "test",
146 | "org.hsqldb" % "hsqldb" % "2.3.+" % "test",
147 | "com.mysql" % "mysql-connector-j" % "8.2.0" % "test",
148 | "org.postgresql" % "postgresql" % postgresqlVersion % "test"
149 | )
150 | val _pomExtra = https://scalikejdbc.org/
151 |
152 |
153 | Apache License, Version 2.0
154 | https://www.apache.org/licenses/LICENSE-2.0.html
155 | repo
156 |
157 |
158 |
159 | git@github.com:scalikejdbc/scalikejdbc-play-support.git
160 | scm:git:git@github.com:scalikejdbc/scalikejdbc-play-support.git
161 |
162 |
163 |
164 | seratch
165 | Kazuhiro Sera
166 | https://github.com/seratch
167 |
168 |
169 | xuwei-k
170 | Kenji Yoshida
171 | https://github.com/xuwei-k
172 |
173 |
174 | tkawachi
175 | Takashi Kawachi
176 | https://github.com/tkawachi
177 |
178 |
179 | tototoshi
180 | Toshiyuki Takahashi
181 | https://github.com/tototoshi
182 |
183 |
184 |
--------------------------------------------------------------------------------
/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/logo.png
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.11.0
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.5.4")
2 | addSbtPlugin("org.playframework" % "sbt-plugin" % "3.0.7")
3 | addSbtPlugin("com.github.sbt" % "sbt-pgp" % "2.3.1")
4 |
5 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-language:_")
6 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # ScalikeJDBC Play Support
2 |
3 | This is a project to enable using ScalikeJDBC in Play Framework apps seamlessly.
4 |
5 | https://scalikejdbc.org/
6 |
7 | ### Getting Started with Play 3.0
8 |
9 | #### build.sbt
10 |
11 | ```scala
12 | libraryDependencies ++= Seq(
13 | "com.h2database" % "h2" % "2.2.224", // your jdbc driver here
14 | "org.scalikejdbc" %% "scalikejdbc" % "4.3.0",
15 | "org.scalikejdbc" %% "scalikejdbc-config" % "4.3.0",
16 | "org.scalikejdbc" %% "scalikejdbc-play-initializer" % "3.0.0-scalikejdbc-4.3"
17 | )
18 | ```
19 |
20 | #### conf/application.conf
21 |
22 | ```
23 | # Database configuration
24 | # ~~~~~
25 | # You can declare as many datasources as you want.
26 | # By convention, the default datasource is named `default`
27 | db.default.driver=org.h2.Driver
28 | db.default.url="jdbc:h2:mem:play;DB_CLOSE_DELAY=-1"
29 | # NOTE: sclaikejdbc-config 2.2.6 doesn't support username, use 2.2.7 or higher
30 | db.default.username=sa
31 | db.default.password=sa
32 |
33 | # ScalikeJDBC original configuration
34 | #db.default.poolInitialSize=10
35 | #db.default.poolMaxSize=10
36 | #db.default.poolValidationQuery=
37 |
38 | scalikejdbc.global.loggingSQLErrors=true
39 | scalikejdbc.global.loggingSQLAndTime.enabled=true
40 | scalikejdbc.global.loggingSQLAndTime.singleLineMode=false
41 | scalikejdbc.global.loggingSQLAndTime.logLevel=debug
42 | scalikejdbc.global.loggingSQLAndTime.warningEnabled=true
43 | scalikejdbc.global.loggingSQLAndTime.warningThresholdMillis=5
44 | scalikejdbc.global.loggingSQLAndTime.warningLogLevel=warn
45 |
46 | play.modules.enabled += "scalikejdbc.PlayModule"
47 | ```
48 |
49 | #### app/controllers/Application.scala
50 |
51 | Now you can access ScalikeJDBC everywhere in your Play app!
52 |
53 | ```scala
54 | package controllers
55 |
56 | import javax.inject._
57 | import play.api._
58 | import play.api.mvc._
59 | import scalikejdbc._
60 |
61 | @Singleton
62 | class Application @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
63 | implicit val session: DBSession = AutoSession
64 |
65 | def index = Action {
66 | val accounts = {
67 | try sql"select * from accounts".toMap.list.apply()
68 | catch { case e: Exception =>
69 | sql"create table accounts(name varchar(100) not null)".execute.apply()
70 | Seq("Alice", "Bob", "Chris").foreach { name =>
71 | sql"insert into accounts values ($name)".update.apply()
72 | }
73 | sql"select * from accounts".toMap.list.apply()
74 | }
75 | }
76 | Ok(accounts.toString)
77 | }
78 | }
79 | ```
80 |
81 | ### Migration Guide
82 |
83 | Unfortunately, Play 2.4 is basically incompatible with Play plugins.
84 | Since Play 2.4, you need to switch to use Play modules instead.
85 |
86 | #### ScalikeJDBC integration with Play 2.0 - 2.3
87 |
88 | - scalikejdbc-play-plugin
89 | - scalikejdbc-play-dbplugin-adapter
90 | - scalikejdbc-play-fixture-plugin
91 |
92 | #### ScalikeJDBC integration with Play 2.4 or higher
93 |
94 | - scalikejdbc-play-initializer
95 | - scalikejdbc-play-dbapi-adapter
96 | - scalikejdbc-play-fixture
97 |
98 | ## License
99 |
100 | ```
101 | Copyright ScalikeJDBC committers
102 | Apache License, Version 2.0
103 | http://www.apache.org/licenses/LICENSE-2.0.html
104 | ```
105 |
--------------------------------------------------------------------------------
/release.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | sbt "+ play-initializer/publishSigned" \
4 | "+ play-dbapi-adapter/publishSigned" \
5 | "+ play-fixture/publishSigned"
6 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | .settings
3 | classpath
4 | .project
5 | *.iml
6 | *.ipr
7 | *.iws
8 | .DS_Store
9 | dist/
10 | lib_managed/
11 | project/boot/
12 | project/plugins/project/
13 | target/
14 |
15 | # use glob syntax.
16 | syntax: glob
17 | *.ser
18 | *.class
19 | *~
20 | *.bak
21 | #*.off
22 | *.old
23 |
24 | # eclipse conf file
25 | .settings
26 | .classpath
27 | .project
28 | .manager
29 | .scala_dependencies
30 |
31 | # idea
32 | .idea
33 | *.iml
34 |
35 | # building
36 | target
37 | build
38 | null
39 | tmp*
40 | temp*
41 | dist
42 | test-output
43 | build.log
44 |
45 | # other scm
46 | .svn
47 | .CVS
48 | .hg*
49 |
50 | # switch to regexp syntax.
51 | # syntax: regexp
52 | # ^\.pc/
53 |
54 | #SHITTY output not in target directory
55 | build.log
56 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/readme.md:
--------------------------------------------------------------------------------
1 | # ScalikeJDBC Play DBPlugin Adapter
2 |
3 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/src/main/scala/scalikejdbc/PlayDBApiAdapter.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 | * either express or implied. See the License for the specific language
14 | * governing permissions and limitations under the License.
15 | */
16 | package scalikejdbc
17 |
18 | import javax.inject._
19 | import org.slf4j.LoggerFactory
20 | import _root_.play.api._
21 | import _root_.play.api.inject._
22 | import _root_.play.api.db.{ DBApi, DBApiProvider }
23 | import scalikejdbc.config.{ TypesafeConfig, TypesafeConfigReader, DBs }
24 | import scala.concurrent.Future
25 |
26 | /**
27 | * The Play plugin to use ScalikeJDBC
28 | */
29 | @Singleton
30 | class PlayDBApiAdapter @Inject() (
31 | dbApi: DBApi,
32 | configuration: Configuration,
33 | lifecycle: ApplicationLifecycle
34 | ) {
35 |
36 | val logger = LoggerFactory.getLogger(this.getClass)
37 |
38 | /**
39 | * DBs with Play application configuration.
40 | */
41 | private[this] lazy val DBs = new DBs
42 | with TypesafeConfigReader
43 | with TypesafeConfig {
44 | override val config = configuration.underlying
45 | }
46 |
47 | private[this] lazy val loggingSQLErrors = configuration
48 | .getOptional[Boolean]("scalikejdbc.global.loggingSQLErrors")
49 | .getOrElse(true)
50 |
51 | def onStart(): Unit = {
52 | DBs.loadGlobalSettings()
53 | GlobalSettings.loggingSQLErrors = loggingSQLErrors
54 |
55 | dbApi.databases().foreach { db =>
56 | scalikejdbc.ConnectionPool.add(
57 | db.name,
58 | new DataSourceConnectionPool(db.dataSource)
59 | )
60 | }
61 |
62 | configuration
63 | .getOptional[String]("scalikejdbc.play.closeAllOnStop.enabled")
64 | .foreach { _ =>
65 | logger.warn(s"closeAllOnStop is ignored by PlayDBPluginAdapter")
66 | }
67 | }
68 |
69 | def onStop(): Unit = {
70 | val cache = SQLSyntaxSupportFeature.SQLSyntaxSupportLoadedColumns
71 | cache.clear()
72 | }
73 |
74 | lifecycle.addStopHook(() => Future.successful(onStop()))
75 | onStart()
76 | }
77 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/src/main/scala/scalikejdbc/PlayDBApiAdapterModule.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 | * either express or implied. See the License for the specific language
14 | * governing permissions and limitations under the License.
15 | */
16 | package scalikejdbc
17 |
18 | import _root_.play.api._
19 | import _root_.play.api.inject._
20 |
21 | /**
22 | * Play module
23 | */
24 | class PlayDBApiAdapterModule extends Module {
25 | def bindings(env: Environment, config: Configuration) = Seq(
26 | bind[PlayDBApiAdapter].toSelf.eagerly()
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/src/test/scala/scalikejdbc/PlayDBApiAdapterModuleSpec.scala:
--------------------------------------------------------------------------------
1 | package scalikejdbc
2 |
3 | import _root_.play.api.db.DBModule
4 | import _root_.play.api.inject.guice.GuiceApplicationBuilder
5 | import _root_.play.api.test.Helpers._
6 | import org.specs2.mutable.Specification
7 |
8 | object PlayDBApiAdapterModuleSpec extends Specification {
9 |
10 | sequential
11 |
12 | Class.forName("org.h2.Driver")
13 |
14 | def fakeAppWithDBModule = {
15 | val additionalConfiguration = Map(
16 | "db.default.driver" -> "org.h2.Driver",
17 | "db.default.url" -> "jdbc:h2:mem:default",
18 | "db.default.user" -> "sa",
19 | "db.default.password" -> "sa",
20 | "db.default.schema" -> "",
21 | "db.legacydb.driver" -> "org.h2.Driver",
22 | "db.legacydb.url" -> "jdbc:h2:mem:legacy",
23 | "db.legacydb.user" -> "l",
24 | "db.legacydb.password" -> "g",
25 | "db.legacydb.schema" -> "",
26 | "scalikejdbc.global.loggingSQLAndTime.enabled" -> "true",
27 | "scalikejdbc.global.loggingSQLAndTime.logLevel" -> "debug",
28 | "scalikejdbc.global.loggingSQLAndTime.warningEnabled" -> "true",
29 | "scalikejdbc.global.loggingSQLAndTime.warningThreasholdMillis" -> "1",
30 | "scalikejdbc.global.loggingSQLAndTime.warningLogLevel" -> "warn"
31 | )
32 | new GuiceApplicationBuilder()
33 | .configure(additionalConfiguration)
34 | .bindings(new PlayDBApiAdapterModule)
35 | .build()
36 | }
37 |
38 | def fakeAppWithoutDBModule = {
39 | val additionalConfiguration = Map(
40 | "logger.root" -> "INFO",
41 | "logger.play" -> "INFO",
42 | "logger.application" -> "DEBUG",
43 | "evolutionplugin" -> "disabled",
44 | "db.default.driver" -> "org.h2.Driver",
45 | "db.default.url" -> "jdbc:h2:mem:default",
46 | "db.default.user" -> "sa",
47 | "db.default.password" -> "sa",
48 | "db.default.schema" -> "",
49 | "db.default.poolInitialSize" -> "1",
50 | "db.default.poolMaxSize" -> "2",
51 | "db.default.poolValidationQuery" -> "select 1",
52 | "db.default.poolConnectionTimeoutMillis" -> "2000",
53 | "db.legacydb.driver" -> "org.h2.Driver",
54 | "db.legacydb.url" -> "jdbc:h2:mem:legacy",
55 | "db.legacydb.user" -> "l",
56 | "db.legacydb.password" -> "g",
57 | "db.legacydb.schema" -> "",
58 | "scalikejdbc.global.loggingSQLAndTime.enabled" -> "true",
59 | "scalikejdbc.global.loggingSQLAndTime.singleLineMode" -> "true",
60 | "scalikejdbc.global.loggingSQLAndTime.logLevel" -> "debug",
61 | "scalikejdbc.global.loggingSQLAndTime.warningEnabled" -> "true",
62 | "scalikejdbc.global.loggingSQLAndTime.warningThreasholdMillis" -> "1",
63 | "scalikejdbc.global.loggingSQLAndTime.warningLogLevel" -> "warn"
64 | )
65 | new GuiceApplicationBuilder()
66 | .configure(additionalConfiguration)
67 | .bindings(new PlayDBApiAdapterModule)
68 | .disable(classOf[DBModule])
69 | .build()
70 | }
71 |
72 | def simpleTest(table: String) = {
73 |
74 | try {
75 | DB autoCommit { implicit s =>
76 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
77 | SQL(
78 | "CREATE TABLE " + table + " (ID BIGINT PRIMARY KEY NOT NULL, NAME VARCHAR(256))"
79 | ).execute.apply()
80 | val insert = SQL(
81 | "INSERT INTO " + table + " (ID, NAME) VALUES (/*'id*/123, /*'name*/'Alice')"
82 | )
83 | insert.bindByName("id" -> 1, "name" -> "Alice").update.apply()
84 | insert.bindByName("id" -> 2, "name" -> "Bob").update.apply()
85 | insert.bindByName("id" -> 3, "name" -> "Eve").update.apply()
86 | }
87 |
88 | NamedDB("legacydb") autoCommit { implicit s =>
89 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
90 | SQL(
91 | "CREATE TABLE " + table + " (ID BIGINT PRIMARY KEY NOT NULL, NAME VARCHAR(256))"
92 | ).execute.apply()
93 | val insert = SQL(
94 | "INSERT INTO " + table + " (ID, NAME) VALUES (/*'id*/123, /*'name*/'Alice')"
95 | )
96 | insert.bindByName("id" -> 1, "name" -> "Alice").update.apply()
97 | insert.bindByName("id" -> 2, "name" -> "Bob").update.apply()
98 | insert.bindByName("id" -> 3, "name" -> "Eve").update.apply()
99 | insert.bindByName("id" -> 4, "name" -> "Fred").update.apply()
100 | }
101 |
102 | case class User(id: Long, name: Option[String])
103 |
104 | val users = DB readOnly { implicit s =>
105 | SQL("SELECT * FROM " + table)
106 | .map(rs => User(rs.long("id"), Option(rs.string("name"))))
107 | .list
108 | .apply()
109 | }
110 | users.size must_== (3)
111 |
112 | val usersInLegacy = NamedDB("legacydb") readOnly { implicit s =>
113 | SQL("SELECT * FROM " + table)
114 | .map(rs => User(rs.long("id"), Option(rs.string("name"))))
115 | .list
116 | .apply()
117 | }
118 | usersInLegacy.size must_== (4)
119 |
120 | } finally {
121 | DB autoCommit { implicit s =>
122 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
123 | }
124 | NamedDB("legacydb") autoCommit { implicit s =>
125 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
126 | }
127 | }
128 | }
129 |
130 | "PlayDBApiAdapterModule" should {
131 |
132 | "be available when DB plugin is also active" in {
133 | running(fakeAppWithDBModule) { simpleTest("user_withdbplugin") }
134 | }
135 |
136 | "not be available when DB plugin is not active" in {
137 | running(fakeAppWithoutDBModule) {} must throwA[RuntimeException]
138 | }
139 |
140 | }
141 |
142 | }
143 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/Procfile:
--------------------------------------------------------------------------------
1 | web: target/start -Dhttp.port=${PORT} -Ddb.default.url=$DATABASE_URL
2 |
3 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/README:
--------------------------------------------------------------------------------
1 | This advanced todo list demonstrates a modern AJAX-based web application. This is a work in progress, and we plan to add several features in the future releases. For now you can check it out to learn how to:
2 |
3 | - Integrate authentication, and security.
4 | - Use AJAX and the Javascript reverse routing.
5 | - Integrate with compiled assets - LESS CSS and CoffeeScript.
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/apps/_tasks.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // TASKS
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | .tasks {
8 | .folder {
9 | .box();
10 | > header {
11 | position: relative;
12 | padding: 4px 25px 4px 7px;
13 | input {
14 | display: inline-block;
15 | }
16 | input[type=text] {
17 | margin: 1px 0 0;
18 | }
19 | .options, .loader {
20 | position: absolute;
21 | top: 4px;
22 | right: 4px;
23 | }
24 | }
25 | > ul {
26 | > li {
27 | position: relative;
28 | padding: 4px 20px 4px 7px;
29 | border-bottom: 1px solid rgba(0,0,0,.05);
30 | -webkit-user-select: text;
31 | time {
32 | float: right;
33 | display: inline-block;
34 | margin: 0 10px;
35 | border-radius: 15px;
36 | background: url(/assets/images/icons/clock.png) 1px 1px no-repeat;
37 | background-color: @dueDateBackground;
38 | border: 1px solid @dueDateBorder;
39 | color: @dueDateColor;
40 | font-size: 11px;
41 | padding: 0 4px 1px 15px;
42 | }
43 | h4 {
44 | display: inline-block;
45 | font-weight: bold;
46 | }
47 | .deleteTask {
48 | .delete();
49 | top: 4px;
50 | right: 4px;
51 | }
52 | &:hover .deleteTask {
53 | opacity: 1;
54 | -webkit-transition-delay: 0;
55 | }
56 | .assignedTo {
57 | float: right;
58 | display: inline-block;
59 | margin: 0 10px;
60 | padding-left: 17px;
61 | color: @assignedToColor;
62 | background: url(/assets/images/icons/user2.png) 0 1px no-repeat;
63 | }
64 | }
65 | }
66 | .addTask {
67 | position: relative;
68 | border-radius: 0 0 4px 4px;
69 | padding: 5px 250px 5px 5px;
70 | background: white;
71 | &:after {
72 | content: " ";
73 | display: block;
74 | clear: both;
75 | }
76 | input {
77 | outline: none;
78 | }
79 | [name=taskBody] {
80 | width: 100%;
81 | border: 0;
82 | }
83 | .dueDate {
84 | position: absolute;
85 | right: 210px;
86 | top: 4px;
87 | width: 140px;
88 | border-radius: 15px;
89 | background: url(/assets/images/icons/clock.png) 2px 2px no-repeat;
90 | background-color: @dueDateBackground;
91 | border: 1px solid @dueDateBorder;
92 | color: @dueDateColor;
93 | font-size: 11px;
94 | padding: 1px 4px 1px 15px;
95 | &::-webkit-input-placeholder {
96 | color: inherit;
97 | }
98 | &:-moz-placeholder {
99 | color: inherit;
100 | }
101 | }
102 | .assignedTo {
103 | position: absolute;
104 | right: 5px;
105 | top: 5px;
106 | width: 195px;
107 | input {
108 | width: 180px;
109 | margin: 2px;
110 | border: 0;
111 | }
112 | }
113 | .assignToList {
114 | display: none;
115 | position: absolute;
116 | top: 100%;
117 | right: 0;
118 | min-width: 100%;
119 | background: rgba(0,0,0,.8);
120 | color: #eee;
121 | }
122 | [type=submit] {
123 | position: absolute;
124 | left: -3000px;
125 | visibility: hidden;
126 | }
127 | ul, div {
128 | display: inline-block;
129 | }
130 | }
131 | .loader {
132 | position: absolute;
133 | top: 5px;
134 | right: 6px;
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/libs/_mate.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // MATE: CSS helpers
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | // ------------------------ GRADIENTS
8 | .gradient(@from:#000, @to:#EEE) {
9 | background: @from;
10 | background-image: -webkit-gradient(linear, left top, left bottom, from(@from), to(@to));
11 | background-image: -moz-linear-gradient(top, @from, @to);
12 | }
13 |
14 | // ---------------------- TRANSITIONS
15 | .transition(@range: all, @time: 500ms, @ease: ease-in-out) {
16 | -moz-transition: @range @time @ease;
17 | -webkit-transition: @range @time @ease;
18 | -o-transition: @range @time @ease;
19 | transition: @range @time @ease;
20 | }
21 |
22 | // ------------------------ TRANSFORMS
23 | .transform(@props) {
24 | -moz-transform: @arguments;
25 | -webkit-transform: @arguments;
26 | -o-transform: @arguments;
27 | transform: @arguments;
28 | }
29 |
30 | // --------------------------- HELPERS
31 | .ellipsis() {
32 | white-space: nowrap;
33 | text-overflow: ellipsis;
34 | overflow: hidden;
35 | }
36 |
37 | .clear() {
38 | &:after {
39 | display: block;
40 | content: " ";
41 | clear: both;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/libs/_reset.less:
--------------------------------------------------------------------------------
1 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit;}
2 |
3 | table {border-collapse: collapse; border-spacing: 0;}
4 | caption, th, td {text-align: left; font-weight: normal;}
5 | form legend {display: none;}
6 | blockquote:before, blockquote:after, q:before, q:after {content: "";}
7 | blockquote, q {quotes: "" "";}
8 | ol, ul {list-style: none;}
9 | hr {display: none; visibility: hidden;}
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/libs/_theme.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // THEME
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | // ---------------------------- COLORS
8 | @mainBackground: #c7d1d8;
9 | @mainColor: #2a3a48;
10 | @drawerBackground: #e1e7ec;
11 | @folderColor: #6f8193;
12 | @projectColor: @mainColor;
13 | @layoutBorderColor: #606d78;
14 |
15 | @links: #4794c4;
16 | @linksHover: #2a5e88;
17 |
18 | @headerLight: #445868;
19 | @headerDark: @mainColor;
20 | @titleColor: #556b7b;
21 | @buttonColor: @mainBackground;
22 | @buttonHover: #fff;
23 |
24 | @activeColor: #5daad5;
25 |
26 | // Tasks
27 | @dueDateBackground: #accfe8;
28 | @dueDateBorder: #73a4ca;
29 | @dueDateColor: #246fa9;
30 | @assignedToColor: @titleColor;
31 |
32 | // Folders
33 | @folderBorder: #9ba5ad;
34 | @folderBackground: #dbe1e5;
35 | @folderHeaderLight: #f2f5f8;
36 | @folderHeaderDark: #dfe2e6;
37 | @folderTitle: #7a8a99;
38 |
39 | // Pannels
40 | @panBackground: rgba(0,0,0,.85);
41 | @panShadow: rgba(0,0,0,.8);
42 | @panText: #aaa;
43 | @panTitle: #fff;
44 | @panBorder: #333;
45 | @panButtonBackground: #444;
46 | @panButtonColor: #fff;
47 |
48 | // ----------------------------- FONTS
49 | @defaultFont: 13px "Lucida Grande","Helvetica Neue", sans-serif;
50 |
51 | // ----------------------------- SIZES
52 | @headerHeight: 40px;
53 | @drawerWidth: 220px;
54 | @navigationWidth: 70px;
55 | @breadcrumbHeight: 50px;
56 |
57 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/login.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // LOGIN
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | @import 'libs/_reset.less';
8 | @import 'libs/_mate.less';
9 | @import 'libs/_theme.less';
10 |
11 | // ----------------------- MAIN STYLES
12 | body {
13 | background: @mainBackground;
14 | color: @mainColor;
15 | font: @defaultFont;
16 | -webkit-font-smoothing: antialised;
17 | -webkit-user-select: none;
18 | }
19 |
20 | a {
21 | color: @links;
22 | text-decoration: none;
23 | &:hover {
24 | color: @linksHover;
25 | }
26 | }
27 |
28 | p.note {
29 | margin: 10px auto 0;
30 | width: 300px;
31 | padding: 20px;
32 | text-align: center;
33 | color: #445868;
34 | text-shadow: 1px 1px rgba(255,255,255,.6);
35 | em {
36 | font-weight: bold;
37 | }
38 | }
39 |
40 | form {
41 | margin: 100px auto 0;
42 | width: 300px;
43 | padding: 20px;
44 | background: #fff;
45 | border-radius: 5px;
46 | box-shadow: 0 2px 5px rgba(0,0,0,.3);
47 | text-align: center;
48 | h1 {
49 | margin: 0 0 10px;
50 | font-size: 20px;
51 | font-weight: bold;
52 | }
53 | p {
54 | width: inherit;
55 | margin: 5px 0;
56 | color: #999;
57 | }
58 | p.error {
59 | color: #c00;
60 | margin-bottom: 10px;
61 | text-shadow: 1px 1px rgba(0,0,0,.1);
62 | }
63 | p.success {
64 | color: #83BD41;
65 | margin-bottom: 10px;
66 | text-shadow: 1px 1px rgba(0,0,0,.1);
67 | }
68 | input {
69 | display: block;
70 | width: inherit;
71 | padding: 2px;
72 | background: rgba(0,0,0,.05);
73 | border: 1px solid rgba(0,0,0,.15);
74 | box-shadow: 0 1px 2px rgba(0,0,0,.1) inset;
75 | border-radius: 3px;
76 | font-size: 14px;
77 | &:invalid:not(:focus) {
78 | border-color: red;
79 | }
80 | }
81 | button {
82 | .button();
83 | display: block;
84 | width: inherit;
85 | font-size: 14px;
86 | }
87 | }
88 |
89 | nav {
90 | margin-top: 15px;
91 | a {
92 | display: inline-block;
93 | margin: 0 4px;
94 | }
95 | }
96 |
97 | // --------------------------- IMPORTS
98 | @import 'main/_widgets.less'; // Some shared elements
99 | @import 'main/_header.less'; // Top header + User bar
100 |
101 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/main.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // MAIN
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | @import 'libs/_reset.less';
8 | @import 'libs/_mate.less';
9 | @import 'libs/_theme.less';
10 |
11 | // ----------------------- MAIN STYLES
12 | body {
13 | background: @mainBackground;
14 | color: @mainColor;
15 | font: @defaultFont;
16 | -webkit-font-smoothing: antialised;
17 | -webkit-user-select: none;
18 | }
19 |
20 | a {
21 | color: @links;
22 | text-decoration: none;
23 | &:hover {
24 | color: @linksHover;
25 | }
26 | }
27 |
28 | // --------------------------- IMPORTS
29 | @import 'main/_layout.less'; // General grid
30 | @import 'main/_widgets.less'; // Some shared elements
31 | @import 'main/_drawer.less'; // Project drawer
32 | @import 'main/_header.less'; // Top header + User bar
33 | @import 'main/_breadcrumb.less'; // Breadcrumb + App menu
34 | @import 'apps/_tasks.less'; // Tasks
35 |
36 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/main/_breadcrumb.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // BREADCRUMB
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | #main > header {
8 | height: 39px;
9 | background: url(/assets/images/breadcrumb.png);
10 | border-bottom: 1px solid @layoutBorderColor;
11 | hgroup {
12 | height: inherit;
13 | overflow: hidden;
14 | float: left;
15 | > * {
16 | float: inherit;
17 | position: relative;
18 | height: inherit;
19 | line-height: 40px;
20 | margin-left: -25px;
21 | padding: 0 6px 0 13px;
22 | font-size: 18px;
23 | text-shadow: 1px 1px 0 rgba(255,255,255,.5);
24 | -webkit-border-image: url(/assets/images/breadcrumb-2.png) 0 30 0 20 stretch stretch;
25 | -moz-border-image: url(/assets/images/breadcrumb-2.png) 0 30 0 20 stretch stretch;
26 | border-image: url(/assets/images/breadcrumb-2.png) 0 30 0 20 stretch stretch;
27 | border-width: 0 30px 0 25px;
28 | color: @titleColor;
29 | -webkit-user-select: text;
30 | &:nth-child(2) {
31 | -webkit-border-image: url(/assets/images/breadcrumb-1.png) 0 30 0 1 stretch stretch;
32 | -moz-border-image: url(/assets/images/breadcrumb-1.png) 0 30 0 1 stretch stretch;
33 | border-image: url(/assets/images/breadcrumb-1.png) 0 30 0 2 stretch stretch;
34 | }
35 | &:first-child {
36 | padding-left: 20px;
37 | }
38 | &:nth-child(1) { z-index: 3; }
39 | &:nth-child(2) { z-index: 2; }
40 | &:nth-child(3) { z-index: 1; }
41 | }
42 | }
43 | .users {
44 | position: relative;
45 | margin: 8px 10px;
46 | float: right;
47 | .pannel();
48 | > dt {
49 | &:before {
50 | content: url(/assets/images/icons/user.png);
51 | padding-right: 4px;
52 | vertical-align: middle;
53 | }
54 | .button();
55 | }
56 | > dd {
57 | padding: 5px 10px;
58 | width: 300px;
59 | color: @panText;
60 | z-index: 99;
61 | }
62 | .wrap {
63 | overflow: auto;
64 | max-height: 350px;
65 | width: inherit;
66 | }
67 | h3 {
68 | margin: 10px 0 0;
69 | padding: 5px 0;
70 | font-size: 16px;
71 | color: @panTitle;
72 | &:first-of-type {
73 | margin: 0;
74 | }
75 | }
76 | dl {
77 | position: relative;
78 | border-top: 1px solid @panBorder;
79 | padding: 5px 17px 5px 0;
80 | dt {
81 | .ellipsis();
82 | span {
83 | opacity: .5;
84 | font-size: 11px;
85 | }
86 | }
87 | }
88 | .action {
89 | position: absolute;
90 | top: 5px;
91 | right: 0px;
92 | width: 16px;
93 | height: 16px;
94 | overflow: hidden;
95 | text-indent: -99em;
96 | background: #444 url(/assets/images/icons/addRemove.png) 0 1 no-repeat;
97 | border-radius: 10px;
98 | &:hover {
99 | background-color: green;
100 | }
101 | }
102 | .list .action {
103 | background-position: 0 -19px;
104 | &:hover {
105 | background-color: red;
106 | }
107 | }
108 | }
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/main/_drawer.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // PROJECTS DRAWER
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 | body {
7 | & > nav {
8 | padding: 10px 0 0;
9 | background: @drawerBackground;
10 | border-right: 1px solid @layoutBorderColor;
11 | }
12 | .dashboard {
13 | display: block;
14 | position: relative;
15 | font-size: 11px;
16 | font-weight: 700;
17 | text-transform: uppercase;
18 | padding: 10px 5px 5px 25px;
19 | background: url(/assets/images/icons/home.png) 6px 7px no-repeat;
20 | a {
21 | color: @folderColor;
22 | cursor: default;
23 | }
24 | }
25 | h4 {
26 | cursor: default;
27 | }
28 | }
29 |
30 | #projects {
31 | input {
32 | margin: 0;
33 | padding: 0;
34 | border: 0;
35 | font: inherit;
36 | }
37 | > li {
38 | position: relative;
39 | padding: 10px 5px 5px 25px;
40 | .options {
41 | position: absolute;
42 | top: 7px;
43 | right: 5px;
44 | button {
45 | border: none;
46 | }
47 | }
48 | .loader {
49 | top: 8px;
50 | right: 6px;
51 | }
52 | li {
53 | position: relative;
54 | padding: 0 0 0 25px;
55 | background: url(/assets/images/icons/folder.png) 1px 1px no-repeat;
56 | a {
57 | display: block;
58 | color: @projectColor;
59 | padding: 2px;
60 | }
61 | input[type=text] {
62 | padding: 2px 1px;
63 | }
64 | .delete {
65 | opacity: 0.1;
66 | }
67 | .loader {
68 | top: 2px;
69 | right: 2px;
70 | }
71 | &:hover {
72 | a {
73 | color: #000;
74 | }
75 | .delete {
76 | opacity: 1;
77 | //-webkit-transition-delay: 0;
78 | }
79 | }
80 | }
81 | .toggle {
82 | content: " ";
83 | position: absolute;
84 | left: 8px;
85 | top: 12px;
86 | display: inline-block;
87 | width: 12px;
88 | height: 12px;
89 | vertical-align: middle;
90 | background: url(/assets/images/icons/drawer.folder.png) 0 0 no-repeat;
91 | }
92 | > h4 {
93 | display: block;
94 | margin: 0 0 5px;
95 | padding: 0 1px;
96 | position: relative;
97 | color: @folderColor;
98 | font-size: 11px;
99 | font-weight: 700;
100 | text-transform: uppercase;
101 | }
102 | > input {
103 | margin: 0 0 5px;
104 | text-transform: uppercase;
105 | font-weight: bold;
106 | font-size: 11px;
107 | }
108 | &.closed {
109 | >ul {
110 | display: none;
111 | }
112 | .toggle {
113 | background-position: 0 -20px;
114 | }
115 | }
116 | }
117 | }
118 |
119 | #activity {
120 | position: absolute;
121 | bottom: 0;
122 | font-size: 11px;
123 | padding: 10px;
124 | }
125 |
126 | #newGroup {
127 | font-size: 13px;
128 | .new();
129 | margin: 15px 25px;
130 | }
131 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/main/_header.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // HEADER
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | body {
8 | & > header {
9 | box-sizing: border-box;
10 | padding: 10px;
11 | z-index: 9;
12 | .gradient(@headerLight, @headerDark);
13 | box-shadow: 0 0 7px rgba(0,0,0,.8),
14 | inset 0 1px 0 rgba(255,255,255,.2),
15 | inset 0 -1px 0 rgba(0,0,0,.8);
16 | }
17 | }
18 |
19 | #logo {
20 | color: #fff;
21 | font-weight: bold;
22 | font-size: 16px;
23 | text-transform: uppercase;
24 | letter-spacing: -2px;
25 | text-shadow: 1px 1px 0 #000;
26 | span {
27 | color: @activeColor;
28 | }
29 | }
30 |
31 | #user {
32 | position: absolute;
33 | right: 10px;
34 | top: 10px;
35 | > * {
36 | display: inline-block;
37 | }
38 | dt {
39 | color: #fff;
40 | span {
41 | opacity: .5;
42 | font-size: 11px;
43 | }
44 | }
45 | dd {
46 | a , button {
47 | .button();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/main/_layout.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // MAIN LAYOUT
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | body {
8 | & > header {
9 | position: absolute;
10 | top: 0;
11 | left: 0;
12 | right: 0;
13 | height: @headerHeight;
14 | }
15 | & > nav {
16 | position: absolute;
17 | top: @headerHeight;
18 | left: 0;
19 | width: @drawerWidth;
20 | bottom: 0;
21 | box-sizing: border-box;
22 | }
23 | & > section {
24 | position: absolute;
25 | top: @headerHeight;
26 | left: @drawerWidth;
27 | right: 0;
28 | bottom: 0;
29 | }
30 | }
31 |
32 | #main > header {
33 | position: absolute;
34 | top: 0;
35 | left: 0;
36 | right: 0;
37 | height: @breadcrumbHeight;
38 | }
39 |
40 | #main > article {
41 | position: absolute;
42 | top: 40px;
43 | left: 0;
44 | bottom: 0;
45 | right: 0;
46 | padding: 20px;
47 | overflow: auto;
48 | }
49 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/assets/stylesheets/main/_widgets.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // WIDGETS
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | // --------------------------- OPTIONS
8 | .pannel(){
9 | > dd {
10 | //display: none;
11 | .transform(scale(.001));
12 | .transition(-webkit-transform, 200ms, ease-out);
13 | -webkit-transform-origin: right top;
14 | -moz-transform-origin: right top;
15 | transform-origin: right top;
16 | position: absolute;
17 | top: 100%;
18 | right: -2px;
19 | width: 150px;
20 | margin: 7px 0px 0 0;
21 | padding: 5px;
22 | z-index: 99;
23 | background: @panBackground;
24 | border-radius: 5px;
25 | box-shadow: 0 2px 7px @panShadow;
26 | a, button {
27 | display: block;
28 | width: 100%;
29 | padding: 3px 10px;
30 | color: @panText;
31 | border-radius: 2px;
32 | background: none;
33 | &:hover {
34 | background: @panButtonBackground;
35 | color: @panButtonColor;
36 | }
37 | }
38 | &:before {
39 | content: " ";
40 | display: block;
41 | border-bottom: 6px solid @panBackground;
42 | border-left: 6px solid transparent;
43 | border-right: 6px solid transparent;
44 | border-top: none;
45 | margin-right: 0;
46 | margin-top: -12px;
47 | position: absolute;
48 | right: 5px;
49 | width: 1px;
50 | height: 1px;
51 | }
52 | }
53 | &.opened > dd {
54 | .transform(scale(1));
55 | }
56 | }
57 |
58 | .button() {
59 | padding: 2px 5px;
60 | border-radius: 3px;
61 | border: 1px solid @headerDark - #111;
62 | .gradient(fadeout(#bff, 80%), fadeout(#bff, 100%));
63 | background-color: @headerDark;
64 | box-shadow: 0 1px 4px rgba(0,0,0,.3),
65 | inset 0 1px 0 rgba(255,255,255,.2),
66 | inset 0 -1px 0 rgba(0,0,0,.2);
67 | text-shadow: -1px -1px 0 rgba(0,0,0,.3);
68 | color: @buttonColor;
69 | cursor: pointer;
70 | &:hover {
71 | .gradient(fadeout(#bff, 70%), fadeout(#bff, 100%));
72 | background-color: @headerDark;
73 | color: @buttonHover;
74 | }
75 | }
76 |
77 | .box() {
78 | border: 1px solid @folderBorder;
79 | background: @folderBackground;
80 | border-radius: 5px;
81 | margin: 0 0 20px;
82 | > header {
83 | border-radius: 5px 5px 0 0;
84 | .gradient(@folderHeaderLight, @folderHeaderDark);
85 | border-bottom: inherit;
86 | padding: 4px 7px;
87 | h3 {
88 | display: inline-block;
89 | font-size: 15px;
90 | font-weight: bold;
91 | color: @folderTitle;
92 | text-shadow: 1px 1px 0 #fff;
93 | }
94 | }
95 | }
96 | .options {
97 | width: 20px;
98 | height: 20px;
99 | position: relative;
100 | font-size: 11px;
101 | dt {
102 | width: inherit;
103 | cursor: pointer;
104 | height: inherit;
105 | text-indent: -9999em;
106 | background: url(/assets/images/icons/options.png) 0 0 no-repeat;
107 | }
108 | &:hover dt, &.opened dt, {
109 | background: url(/assets/images/icons/options.png) 0 -20px no-repeat;
110 | }
111 | .pannel();
112 | }
113 |
114 | .new {
115 | display: inline-block;
116 | .button();
117 | &:before {
118 | content: "+";
119 | font-size: 15px;
120 | line-height: 15px;
121 | font-weight: bold;
122 | color: @activeColor;
123 | padding-right: 4px;
124 | }
125 | }
126 |
127 | .delete {
128 | position: absolute;
129 | top: 0px;
130 | right: 0;
131 | border: none;
132 | padding: 0;
133 | width: 18px;
134 | height: 20px;
135 | overflow: hidden;
136 | text-indent: -99em;
137 | background: url(/assets/images/icons/delete.png) 0 1px no-repeat;
138 | .transition(opacity, 300ms, ease-in-out);
139 | -webkit-transition-delay: 100ms;
140 | z-index: 7;
141 | cursor: pointer;
142 | &:hover {
143 | background: url(/assets/images/icons/delete.png) 0 -19px no-repeat;
144 | }
145 | }
146 |
147 | .counter {
148 | color: #888;
149 | font-size: 11px;
150 | text-shadow: 1px 1px 0 rgba(255,255,255,.7);
151 | margin: 2px 5px;
152 | padding: 0px 3px;
153 | background: rgba(0,0,0,.05);
154 | border-radius: 10px;
155 | border: 1px solid rgba(0,0,0,.15);
156 | }
157 |
158 | .loader {
159 | display: none;
160 | overflow: hidden;
161 | text-indent: -99em;
162 | position: absolute;
163 | height: 16px;
164 | width: 16px;
165 | background: url(/assets/images/loading.gif);
166 | }
167 |
168 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/controllers/Application.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import javax.inject.{ Inject, Singleton }
4 |
5 | import models.{ Project, User, Task }
6 | import play.api.data.Form
7 | import play.api.data.Forms._
8 | import play.api.mvc._
9 | import play.api.routing.JavaScriptReverseRouter
10 | import views.html
11 | import scala.concurrent.Future
12 |
13 | @Singleton
14 | class Application @Inject() (controllerComponents: ControllerComponents)
15 | extends AbstractController(controllerComponents) {
16 |
17 | // -- Authentication
18 |
19 | val loginForm = Form(
20 | tuple(
21 | "email" -> text,
22 | "password" -> text
23 | ) verifying (
24 | "Invalid email or password",
25 | result =>
26 | result match {
27 | case (email, password) => User.authenticate(email, password).isDefined
28 | }
29 | )
30 | )
31 |
32 | /**
33 | * Login page.
34 | */
35 | def login = Action.async { implicit request =>
36 | Future.successful(Ok(html.login(loginForm)))
37 | }
38 |
39 | /**
40 | * Handle login form submission.
41 | */
42 | def authenticate = Action.async { implicit request =>
43 | Future.successful(
44 | loginForm
45 | .bindFromRequest()
46 | .fold(
47 | formWithErrors => BadRequest(html.login(formWithErrors)),
48 | user =>
49 | Redirect(routes.Projects.index()).withSession("email" -> user._1)
50 | )
51 | )
52 | }
53 |
54 | /**
55 | * Logout and clean the session.
56 | */
57 | def logout = Action.async {
58 | Future.successful(
59 | Redirect(routes.Application.login()).withNewSession
60 | .flashing("success" -> "You've been logged out")
61 | )
62 | }
63 |
64 | // -- Javascript routing
65 |
66 | def javascriptRoutes = Action.async { implicit request =>
67 | import routes.javascript._
68 | Future.successful(
69 | Ok(
70 | JavaScriptReverseRouter("jsRoutes")(
71 | Projects.add,
72 | Projects.delete,
73 | Projects.rename,
74 | Projects.addGroup,
75 | Projects.deleteGroup,
76 | Projects.renameGroup,
77 | Projects.addUser,
78 | Projects.removeUser,
79 | Tasks.addFolder,
80 | Tasks.renameFolder,
81 | Tasks.deleteFolder,
82 | Tasks.index,
83 | Tasks.add,
84 | Tasks.update,
85 | Tasks.delete
86 | )
87 | ).as("text/javascript")
88 | )
89 | }
90 |
91 | }
92 |
93 | /**
94 | * Provide security features
95 | */
96 | trait Secured { self: BaseController =>
97 |
98 | /**
99 | * Retrieve the connected user email.
100 | */
101 | private def username(request: RequestHeader) = request.session.get("email")
102 |
103 | /**
104 | * Redirect to login if the user in not authorized.
105 | */
106 | private def onUnauthorized(request: RequestHeader) =
107 | Results.Redirect(routes.Application.login())
108 |
109 | // --
110 |
111 | /**
112 | * Action for authenticated users.
113 | */
114 | def IsAuthenticated(f: => String => Request[AnyContent] => Result) =
115 | Security.Authenticated(username, onUnauthorized) { user =>
116 | Action(request => f(user)(request))
117 | }
118 |
119 | /**
120 | * Check if the connected user is a member of this project.
121 | */
122 | def IsMemberOf(project: Long)(f: => String => Request[AnyContent] => Result) =
123 | IsAuthenticated { user => request =>
124 | if (Project.isMember(project, user)) {
125 | f(user)(request)
126 | } else {
127 | Results.Forbidden
128 | }
129 | }
130 |
131 | /**
132 | * Check if the connected user is a owner of this task.
133 | */
134 | def IsOwnerOf(task: Long)(f: => String => Request[AnyContent] => Result) =
135 | IsAuthenticated { user => request =>
136 | if (Task.isOwner(task, user)) {
137 | f(user)(request)
138 | } else {
139 | Results.Forbidden
140 | }
141 | }
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/controllers/Projects.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import javax.inject.{ Inject, Singleton }
4 |
5 | import models._
6 | import play.api.data.Forms._
7 | import play.api.data._
8 | import play.api.mvc._
9 | import views._
10 |
11 | /**
12 | * Manage projects related operations.
13 | */
14 | @Singleton
15 | class Projects @Inject() (controllerComponents: ControllerComponents)
16 | extends AbstractController(controllerComponents)
17 | with Secured {
18 |
19 | /**
20 | * Display the dashboard.
21 | */
22 | def index = IsAuthenticated { username => _ =>
23 | User
24 | .findByEmail(username)
25 | .map { user =>
26 | Ok(
27 | html.dashboard(
28 | Project.findInvolving(username),
29 | Task.findTodoInvolving(username),
30 | user
31 | )
32 | )
33 | }
34 | .getOrElse(Forbidden)
35 | }
36 |
37 | // -- Projects
38 |
39 | /**
40 | * Add a project.
41 | */
42 | def add = IsAuthenticated { username => implicit request =>
43 | Form("group" -> nonEmptyText)
44 | .bindFromRequest()
45 | .fold(
46 | errors => BadRequest,
47 | folder =>
48 | Ok(
49 | views.html.projects.item(
50 | Project.create(NewProject(folder, "New project"), Seq(username))
51 | )
52 | )
53 | )
54 | }
55 |
56 | /**
57 | * Delete a project.
58 | */
59 | def delete(project: Long) = IsMemberOf(project) { username => _ =>
60 | Project.delete(project)
61 | Ok
62 | }
63 |
64 | /**
65 | * Rename a project.
66 | */
67 | def rename(project: Long) = IsMemberOf(project) { _ => implicit request =>
68 | Form("name" -> nonEmptyText)
69 | .bindFromRequest()
70 | .fold(
71 | errors => BadRequest,
72 | newName => {
73 | Project.rename(project, newName)
74 | Ok(newName)
75 | }
76 | )
77 | }
78 |
79 | // -- Project groups
80 |
81 | /**
82 | * Add a new project group.
83 | */
84 | def addGroup = IsAuthenticated { _ => _ =>
85 | Ok(html.projects.group("New group"))
86 | }
87 |
88 | /**
89 | * Delete a project group.
90 | */
91 | def deleteGroup(folder: String) = IsAuthenticated { _ => _ =>
92 | Project.deleteInFolder(folder)
93 | Ok
94 | }
95 |
96 | /**
97 | * Rename a project group.
98 | */
99 | def renameGroup(folder: String) = IsAuthenticated { _ => implicit request =>
100 | Form("name" -> nonEmptyText)
101 | .bindFromRequest()
102 | .fold(
103 | errors => BadRequest,
104 | newName => { Project.renameFolder(folder, newName); Ok(newName) }
105 | )
106 | }
107 |
108 | // -- Members
109 |
110 | /**
111 | * Add a project member.
112 | */
113 | def addUser(project: Long) = IsMemberOf(project) { _ => implicit request =>
114 | Form("user" -> nonEmptyText)
115 | .bindFromRequest()
116 | .fold(
117 | errors => BadRequest,
118 | user => { Project.addMember(project, user); Ok }
119 | )
120 | }
121 |
122 | /**
123 | * Remove a project member.
124 | */
125 | def removeUser(project: Long) = IsMemberOf(project) { _ => implicit request =>
126 | Form("user" -> nonEmptyText)
127 | .bindFromRequest()
128 | .fold(
129 | errors => BadRequest,
130 | user => { Project.removeMember(project, user); Ok }
131 | )
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/controllers/Tasks.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import javax.inject.{ Inject, Singleton }
4 |
5 | import models._
6 | import play.api.data.Forms._
7 | import play.api.data._
8 | import play.api.mvc.{ AbstractController, ControllerComponents }
9 | import views._
10 | import scala.concurrent.Future
11 |
12 | /**
13 | * Manage tasks related operations.
14 | */
15 | @Singleton
16 | class Tasks @Inject() (controllerComponents: ControllerComponents)
17 | extends AbstractController(controllerComponents)
18 | with Secured {
19 |
20 | /**
21 | * Display the tasks panel for this project.
22 | */
23 | def index(project: Long) = IsMemberOf(project) { _ => implicit request =>
24 | Project
25 | .findById(project)
26 | .map { p =>
27 | val tasks = Task.findByProject(project)
28 | val team = Project.membersOf(project)
29 | Ok(html.tasks.index(p, tasks, team))
30 | }
31 | .getOrElse(NotFound)
32 | }
33 |
34 | val taskForm = Form(
35 | tuple(
36 | "title" -> nonEmptyText,
37 | "dueDate" -> optional(date("MM/dd/yy")),
38 | "assignedTo" -> optional(text)
39 | )
40 | )
41 |
42 | // -- Tasks
43 |
44 | /**
45 | * Create a task in this project.
46 | */
47 | def add(project: Long, folder: String) = IsMemberOf(project) {
48 | _ => implicit request =>
49 | taskForm
50 | .bindFromRequest()
51 | .fold(
52 | errors => BadRequest,
53 | { case (title, dueDate, assignedTo) =>
54 | val task = Task.create(
55 | NewTask(folder, project, title, false, dueDate, assignedTo)
56 | )
57 | Ok(html.tasks.item(task))
58 | }
59 | )
60 | }
61 |
62 | /**
63 | * Update a task
64 | */
65 | def update(task: Long) = IsOwnerOf(task) { _ => implicit request =>
66 | Form("done" -> boolean)
67 | .bindFromRequest()
68 | .fold(
69 | errors => BadRequest,
70 | isDone => {
71 | Task.markAsDone(task, isDone)
72 | Ok
73 | }
74 | )
75 | }
76 |
77 | /**
78 | * Delete a task
79 | */
80 | def delete(task: Long) = IsOwnerOf(task) { _ => implicit request =>
81 | Task.delete(task)
82 | Ok
83 | }
84 |
85 | // -- Task folders
86 |
87 | /**
88 | * Add a new folder.
89 | */
90 | def addFolder = Action.async {
91 | Future.successful(Ok(html.tasks.folder("New folder")))
92 | }
93 |
94 | /**
95 | * Delete a full tasks folder.
96 | */
97 | def deleteFolder(project: Long, folder: String) = IsMemberOf(project) {
98 | _ => implicit request =>
99 | Task.deleteInFolder(project, folder)
100 | Ok
101 | }
102 |
103 | /**
104 | * Rename a tasks folder.
105 | */
106 | def renameFolder(project: Long, folder: String) = IsMemberOf(project) {
107 | _ => implicit request =>
108 | Form("name" -> nonEmptyText)
109 | .bindFromRequest()
110 | .fold(
111 | errors => BadRequest,
112 | newName => {
113 | Task.renameFolder(project, folder, newName)
114 | Ok(newName)
115 | }
116 | )
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/models/Project.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import scalikejdbc._
4 |
5 | case class ProjectMember(projectId: Long, userEmail: String)
6 |
7 | object ProjectMember extends SQLSyntaxSupport[ProjectMember] {
8 | def apply(syntax: SyntaxProvider[ProjectMember])(rs: WrappedResultSet) = {
9 | val p = syntax.resultName
10 | new ProjectMember(
11 | projectId = rs.long(p.projectId),
12 | userEmail = rs.string(p.userEmail)
13 | )
14 | }
15 | }
16 |
17 | case class NewProject(folder: String, name: String)
18 |
19 | case class Project(id: Long, folder: String, name: String)
20 |
21 | object Project extends SQLSyntaxSupport[Project] {
22 |
23 | def apply(syntax: SyntaxProvider[Project])(rs: WrappedResultSet) = {
24 | val p = syntax.resultName
25 | new Project(
26 | id = rs.long(p.id),
27 | folder = rs.string(p.folder),
28 | name = rs.string(p.name)
29 | )
30 | }
31 |
32 | private val p = Project.syntax("p")
33 | private val u = User.syntax("u")
34 | private val m = ProjectMember.syntax("m")
35 |
36 | private val auto = AutoSession
37 |
38 | def findById(id: Long)(implicit s: DBSession = auto): Option[Project] =
39 | withSQL {
40 | select.from(Project as p).where.eq(p.id, id)
41 | }.map(Project(p)).single.apply()
42 |
43 | def findInvolving(user: String)(implicit s: DBSession = auto): Seq[Project] =
44 | withSQL {
45 | select
46 | .from(Project as p)
47 | .join(ProjectMember as m)
48 | .on(p.id, m.projectId)
49 | .where
50 | .eq(m.userEmail, user)
51 | }.map(Project(p)).list.apply()
52 |
53 | def rename(id: Long, newName: String)(implicit s: DBSession = auto): Unit =
54 | applyUpdate {
55 | update(Project as p).set(p.name -> newName).where.eq(p.id, id)
56 | }
57 |
58 | def delete(id: Long)(implicit s: DBSession = auto): Unit = applyUpdate {
59 | deleteFrom(Project as p).where.eq(p.id, id)
60 | }
61 |
62 | def deleteInFolder(folder: String)(implicit s: DBSession = auto): Unit =
63 | applyUpdate {
64 | deleteFrom(Project as p).where.eq(p.folder, folder)
65 | }
66 |
67 | def renameFolder(folder: String, newName: String)(implicit
68 | s: DBSession = auto
69 | ): Unit = applyUpdate {
70 | update(Project as p).set(p.folder -> newName).where.eq(p.folder, folder)
71 | }
72 |
73 | def membersOf(project: Long)(implicit s: DBSession = auto): Seq[User] =
74 | withSQL {
75 | select
76 | .from(User as u)
77 | .join(ProjectMember as m)
78 | .on(m.userEmail, u.email)
79 | .where
80 | .eq(m.projectId, project)
81 | }.map(User(u)).list.apply()
82 |
83 | def addMember(project: Long, user: String)(implicit
84 | s: DBSession = auto
85 | ): Unit = applyUpdate {
86 | insert.into(ProjectMember).values(project, user)
87 | }
88 |
89 | def removeMember(project: Long, user: String)(implicit
90 | s: DBSession = auto
91 | ): Unit = applyUpdate {
92 | deleteFrom(ProjectMember as m).where
93 | .eq(m.projectId, project)
94 | .and
95 | .eq(m.userEmail, user)
96 | }
97 |
98 | def isMember(project: Long, user: String)(implicit
99 | s: DBSession = auto
100 | ): Boolean = withSQL {
101 | select(sqls"count(${u.email}) = 1 as is_member")
102 | .from(User as u)
103 | .join(ProjectMember as m)
104 | .on(m.userEmail, u.email)
105 | .where
106 | .eq(m.projectId, project)
107 | .and
108 | .eq(u.email, user)
109 | }.map(rs => rs.boolean("is_member").asInstanceOf[Boolean])
110 | .single
111 | .apply()
112 | .getOrElse(false)
113 |
114 | def create(project: NewProject, members: Seq[String])(implicit
115 | s: DBSession = auto
116 | ): Project = {
117 | // Insert the project
118 | val newId = sql"select next value for project_seq as v from dual"
119 | .map(_.long("v"))
120 | .single
121 | .apply()
122 | .get
123 | applyUpdate {
124 | insert.into(Project).values(newId, project.name, project.folder)
125 | }
126 | // Add members
127 | members foreach { email =>
128 | applyUpdate(insert.into(ProjectMember).values(newId, email))
129 | }
130 | Project(id = newId, name = project.name, folder = project.folder)
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/models/Task.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import java.util.Date
4 |
5 | import scalikejdbc._
6 |
7 | case class NewTask(
8 | folder: String,
9 | project: Long,
10 | title: String,
11 | done: Boolean,
12 | dueDate: Option[Date],
13 | assignedTo: Option[String]
14 | )
15 |
16 | case class Task(
17 | id: Long,
18 | folder: String,
19 | project: Long,
20 | title: String,
21 | done: Boolean,
22 | dueDate: Option[Date],
23 | assignedTo: Option[String]
24 | )
25 |
26 | object Task extends SQLSyntaxSupport[Task] {
27 |
28 | def apply(syntax: SyntaxProvider[Task])(rs: WrappedResultSet) = {
29 | val t = syntax.resultName
30 | new Task(
31 | id = rs.long(t.id),
32 | folder = rs.string(t.folder),
33 | project = rs.long(t.project),
34 | title = rs.string(t.title),
35 | done = rs.boolean(t.done),
36 | dueDate = rs.timestampOpt(t.dueDate),
37 | assignedTo = rs.stringOpt(t.assignedTo)
38 | )
39 | }
40 |
41 | def apply(t: SyntaxProvider[Task], p: SyntaxProvider[Project])(
42 | rs: WrappedResultSet
43 | ): (Task, Project) = (Task(t)(rs), Project(p)(rs))
44 |
45 | private val t = Task.syntax("t")
46 | private val p = Project.syntax("p")
47 | private val m = ProjectMember.syntax("m")
48 |
49 | private val auto = AutoSession
50 |
51 | def findById(id: Long)(implicit s: DBSession = auto): Option[Task] = withSQL {
52 | select.from(Task as t).where.eq(t.id, id)
53 | }.map(Task(t)).single.apply()
54 |
55 | def findTodoInvolving(
56 | user: String
57 | )(implicit s: DBSession = auto): Seq[(Task, Project)] = withSQL {
58 | select
59 | .from(Task as t)
60 | .join(ProjectMember as m)
61 | .on(m.projectId, t.project)
62 | .join(Project as p)
63 | .on(p.id, m.projectId)
64 | .where
65 | .append(sqls"${t.done} = false")
66 | .and
67 | .eq(m.userEmail, user)
68 | }.map(Task(t, p)).list.apply()
69 |
70 | def findByProject(project: Long)(implicit s: DBSession = auto): Seq[Task] =
71 | withSQL {
72 | select.from(Task as t).where.eq(t.project, project)
73 | }.map(Task(t)).list.apply()
74 |
75 | /**
76 | * Delete a task
77 | */
78 | def delete(id: Long)(implicit s: DBSession = auto): Unit = applyUpdate {
79 | deleteFrom(Task as t).where.eq(t.id, id)
80 | }
81 |
82 | def deleteInFolder(projectId: Long, folder: String)(implicit
83 | s: DBSession = auto
84 | ): Unit = applyUpdate {
85 | deleteFrom(Task as t).where
86 | .eq(t.project, projectId)
87 | .and
88 | .eq(t.folder, folder)
89 | }
90 |
91 | def markAsDone(taskId: Long, done: Boolean)(implicit
92 | s: DBSession = auto
93 | ): Unit = applyUpdate {
94 | update(Task as t).set(t.done -> done).where.eq(t.id, taskId)
95 | }
96 |
97 | def renameFolder(projectId: Long, folder: String, newName: String)(implicit
98 | s: DBSession = auto
99 | ): Unit = applyUpdate {
100 | update(Task as t)
101 | .set(t.folder -> newName)
102 | .where
103 | .eq(t.folder, folder)
104 | .and
105 | .eq(t.project, projectId)
106 | }
107 |
108 | def isOwner(task: Long, user: String)(implicit s: DBSession = auto): Boolean =
109 | withSQL {
110 | select(sqls"count(${t.id}) = 1 as v")
111 | .from(Task as t)
112 | .join(Project as p)
113 | .on(t.project, p.id)
114 | .join(ProjectMember as m)
115 | .on(m.projectId, p.id)
116 | .where
117 | .eq(m.userEmail, user)
118 | .and
119 | .eq(t.id, task)
120 | }.map(rs => rs.boolean("v").asInstanceOf[Boolean])
121 | .single
122 | .apply()
123 | .getOrElse(false)
124 |
125 | def create(task: NewTask)(implicit s: DBSession = auto): Task = {
126 | val newId = sql"select next value for task_seq as v from dual"
127 | .map(rs => rs.long("v"))
128 | .single
129 | .apply()
130 | .get
131 | applyUpdate {
132 | insert
133 | .into(Task)
134 | .values(
135 | newId,
136 | task.title,
137 | task.done,
138 | task.dueDate,
139 | task.assignedTo,
140 | task.project,
141 | task.folder
142 | )
143 | }
144 | Task(
145 | id = newId,
146 | folder = task.folder,
147 | project = task.project,
148 | title = task.title,
149 | done = task.done,
150 | dueDate = task.dueDate,
151 | assignedTo = task.assignedTo
152 | )
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/models/User.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import scalikejdbc._
4 |
5 | case class User(email: String, name: String, password: String)
6 |
7 | object User extends SQLSyntaxSupport[User] {
8 |
9 | override val tableName = "users"
10 | override val columns = Seq("email", "name", "password")
11 |
12 | def apply(syntax: SyntaxProvider[User])(rs: WrappedResultSet) = {
13 | val u = syntax.resultName
14 | new User(
15 | email = rs.string(u.email),
16 | name = rs.string(u.name),
17 | password = rs.string(u.password)
18 | )
19 | }
20 |
21 | private val u = User.syntax("u")
22 |
23 | private val auto = AutoSession
24 |
25 | def findByEmail(email: String)(implicit s: DBSession = auto): Option[User] =
26 | withSQL {
27 | select.from(User as u).where.eq(u.email, email)
28 | }.map(User(u)).single.apply()
29 |
30 | def findAll()(implicit s: DBSession = auto): Seq[User] = withSQL {
31 | select.from(User as u)
32 | }.map(User(u)).list.apply()
33 |
34 | def authenticate(email: String, password: String)(implicit
35 | s: DBSession = auto
36 | ): Option[User] = withSQL {
37 | select.from(User as u).where.eq(u.email, email).and.eq(u.password, password)
38 | }.map(User(u)).single.apply()
39 |
40 | def create(user: User)(implicit s: DBSession = auto): User = {
41 | applyUpdate {
42 | insert.into(User).values(user.email, user.name, user.password)
43 | }
44 | user
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/dashboard.scala.html:
--------------------------------------------------------------------------------
1 | @(projects: Seq[Project], todoTasks: Seq[(Task,Project)], user: User)
2 |
3 | @main(projects, user){
4 |
5 |
6 |
7 | Dashboard
8 | Tasks over all projects
9 |
10 |
11 |
12 |
13 | @todoTasks.groupBy(_._2).map {
14 | case (project, projectTasks) => {
15 |
16 |
20 |
21 | @projectTasks.map {
22 | case (task, _) => {
23 | @tasks.item(task, isEditable = false)
24 | }
25 | }
26 |
27 |
28 | }
29 | }
30 |
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/login.scala.html:
--------------------------------------------------------------------------------
1 | @(form: Form[(String,String)])(implicit flash: Flash)
2 |
3 |
4 |
5 | Zentasks
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 | @helper.form(routes.Application.authenticate()) {
16 |
17 | Sign in
18 |
19 | @form.globalError.map { error =>
20 |
21 | @error.message
22 |
23 | }
24 |
25 | @flash.get("success").map { message =>
26 |
27 | @message
28 |
29 | }
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | }
42 |
43 |
44 | Try guillaume@@sample.com with secret as password.
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/main.scala.html:
--------------------------------------------------------------------------------
1 | @(projects: Seq[Project], user: User)(body: Html)
2 |
3 |
4 |
5 | Zentasks
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Zentasks
18 |
19 | - @user.name (@user.email)
20 | -
21 | Logout
22 |
23 |
24 |
25 |
36 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/projects/group.scala.html:
--------------------------------------------------------------------------------
1 | @(group: String, projects: Seq[Project] = Nil)
2 |
3 |
4 |
5 | @group
6 | Loading
7 |
8 | - Options
9 | -
10 |
11 |
12 |
13 |
14 |
15 | @projects.map { project =>
16 | @views.html.projects.item(project)
17 | }
18 |
19 |
20 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/projects/item.scala.html:
--------------------------------------------------------------------------------
1 | @(project: Project)
2 |
3 |
4 | @project.name
5 |
6 | Loading
7 |
8 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/tasks/folder.scala.html:
--------------------------------------------------------------------------------
1 | @(folder: String, tasks: Seq[Task] = Nil)
2 |
3 |
4 |
18 |
19 | @tasks.map { task =>
20 | @views.html.tasks.item( task )
21 | }
22 |
23 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/tasks/index.scala.html:
--------------------------------------------------------------------------------
1 | @(project:Project, tasks: Seq[Task], team: Seq[User])
2 |
3 |
4 |
5 | @project.folder
6 | @project.name
7 |
8 |
9 | - Project's team
10 | -
11 |
12 |
Team mates
13 |
14 | @team.map { user =>
15 |
16 | - @user.name (@user.email)
17 | - Action
18 |
19 | }
20 |
21 |
Add a team mate
22 |
23 | @User.findAll().diff(team).map { user =>
24 |
25 | - @user.name (@user.email)
26 | - Action
27 |
28 | }
29 |
30 |
31 |
32 |
33 |
34 |
35 | @tasks.groupBy(_.folder).map {
36 | case (folder, tasks) => {
37 | @views.html.tasks.folder(folder, tasks)
38 | }
39 | }
40 | New folder
41 |
42 |
43 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/app/views/tasks/item.scala.html:
--------------------------------------------------------------------------------
1 | @(task: Task, isEditable: Boolean = true)
2 |
3 |
4 |
5 | @if(isEditable) {
6 |
7 | }
8 |
9 | @task.title
10 |
11 | @task.dueDate.map { date =>
12 |
13 | }
14 |
15 | @task.assignedTo.map { user =>
16 | @user
17 | }
18 |
19 | @if(isEditable) {
20 | Delete task
21 | Loading
22 | }
23 |
24 |
25 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/application.conf:
--------------------------------------------------------------------------------
1 | # Configuration
2 |
3 | application.name=Zentasks
4 |
5 | # Secret key
6 | # ~~~~~
7 | # The secret key is used to secure cryptographics functions.
8 | # If you deploy your application to several instances be sure to use the same key!
9 | application.secret="E27D^[_9W"
10 |
11 | # Database configuration
12 | # ~~~~~
13 | # You can declare as many datasources as you want.
14 | # By convention, the default datasource is named `default`
15 | db.default.driver=org.h2.Driver
16 | db.default.url="jdbc:h2:mem:play;DB_CLOSE_DELAY=-1"
17 | db.default.username=sa
18 | db.secondary.driver=org.h2.Driver
19 | db.secondary.url="jdbc:h2:mem:secondary;DB_CLOSE_DELAY=-1"
20 | db.default.fixtures.dev=[ "users.sql", "project.sql", "project_member.sql", "task.sql" ]
21 | db.default.fixtures.test=[ "users.sql", "project.sql", "project_member.sql", "task.sql" ]
22 | db.secondary.fixtures.test=[ "users.sql", "project.sql", "project_member.sql", "task.sql" ]
23 |
24 | #db.default.password=sa
25 |
26 | # ScalikeJDBC original configuration
27 | #db.default.poolInitialSize=10
28 | #db.default.poolMaxSize=10
29 | #db.default.poolValidationQuery=
30 |
31 | scalikejdbc.global.loggingSQLAndTime.enabled=true
32 | #scalikejdbc.global.loggingSQLAndTime.singleLineMode=true
33 | scalikejdbc.global.loggingSQLAndTime.logLevel=debug
34 | scalikejdbc.global.loggingSQLAndTime.warningEnabled=true
35 | scalikejdbc.global.loggingSQLAndTime.warningThresholdMillis=5
36 | scalikejdbc.global.loggingSQLAndTime.warningLogLevel=warn
37 |
38 | # You can disable the default DB plugin
39 | # dbplugin=disabled
40 | # evolutionplugin=disabled
41 |
42 | # Logger
43 | # ~~~~~
44 | # You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
45 |
46 | # Root logger:
47 | logger.root=DEBUG
48 |
49 | # Logger used by the framework:
50 | logger.play=DEBUG
51 |
52 | # Logger provided to your application:
53 | logger.application=DEBUG
54 |
55 | play.modules.enabled += "scalikejdbc.PlayModule"
56 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/default/project.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project (id, name, folder) VALUES (1, 'Play 2.0', 'Play framework');
4 | INSERT INTO project (id, name, folder) VALUES (2, 'Play 1.2.4', 'Play framework');
5 | INSERT INTO project (id, name, folder) VALUES (3, 'Website', 'Play framework');
6 | INSERT INTO project (id, name, folder) VALUES (4, 'Secret project', 'Zenexity');
7 | INSERT INTO project (id, name, folder) VALUES (5, 'Playmate', 'Zenexity');
8 | INSERT INTO project (id, name, folder) VALUES (6, 'Things to do', 'Personal');
9 | INSERT INTO project (id, name, folder) VALUES (7, 'Play samples', 'Zenexity');
10 | INSERT INTO project (id, name, folder) VALUES (8, 'Private', 'Personal');
11 | INSERT INTO project (id, name, folder) VALUES (9, 'Private', 'Personal');
12 | INSERT INTO project (id, name, folder) VALUES (10, 'Private', 'Personal');
13 | INSERT INTO project (id, name, folder) VALUES (11, 'Private', 'Personal');
14 | ALTER SEQUENCE project_seq RESTART WITH 12;
15 |
16 | # --- !Downs
17 | ALTER SEQUENCE project_seq RESTART WITH 1;
18 | DELETE FROM project;
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/default/project_member.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'guillaume@sample.com');
4 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'maxime@sample.com');
5 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'sadek@sample.com');
6 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'erwan@sample.com');
7 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'guillaume@sample.com');
8 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'erwan@sample.com');
9 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'guillaume@sample.com');
10 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'maxime@sample.com');
11 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'guillaume@sample.com');
12 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'maxime@sample.com');
13 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'sadek@sample.com');
14 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'erwan@sample.com');
15 | INSERT INTO project_member (project_id, user_email) VALUES (5, 'maxime@sample.com');
16 | INSERT INTO project_member (project_id, user_email) VALUES (6, 'guillaume@sample.com');
17 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'guillaume@sample.com');
18 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'maxime@sample.com');
19 | INSERT INTO project_member (project_id, user_email) VALUES (8, 'maxime@sample.com');
20 | INSERT INTO project_member (project_id, user_email) VALUES (9, 'guillaume@sample.com');
21 | INSERT INTO project_member (project_id, user_email) VALUES (10, 'erwan@sample.com');
22 | INSERT INTO project_member (project_id, user_email) VALUES (11, 'sadek@sample.com');
23 |
24 | # --- !Downs
25 |
26 | DELETE FROM project_member;
27 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/default/task.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1000, 'Fix the documentation', FALSE, null, 'guillaume@sample.com', 1, 'Todo');
4 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1001, 'Prepare the beta release', FALSE, '2011-11-15 00:00:00.0', null, 1, 'Urgent');
5 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1002, 'Buy some milk', FALSE, null, null, 9, 'Todo');
6 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1003, 'Check 1.2.4-RC2', FALSE, '2011-11-18 00:00:00.0', 'guillaume@sample.com', 2, 'Todo');
7 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1004, 'Finish zentask integration', TRUE, '2011-11-15 00:00:00.0', 'maxime@sample.com', 7, 'Todo');
8 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1005, 'Release the secret project', FALSE, '2012-01-01 00:00:00.0', 'sadek@sample.com', 4, 'Todo');
9 | ALTER SEQUENCE task_seq RESTART WITH 1006;
10 |
11 | # --- !Downs
12 | ALTER SEQUENCE task_seq RESTART WITH 1000;
13 | DELETE FROM task;
14 |
15 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/default/users.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 | INSERT INTO users (email, name, password) VALUES ('guillaume@sample.com', 'Guillaume Bort', 'secret');
3 | INSERT INTO users (email, name, password) VALUES ('maxime@sample.com', 'Maxime Dantec', 'secret');
4 | INSERT INTO users (email, name, password) VALUES ('sadek@sample.com', 'Sadek Drobi', 'secret');
5 | INSERT INTO users (email, name, password) VALUES ('erwan@sample.com', 'Erwan Loisant', 'secret');
6 |
7 |
8 | # --- !Downs
9 | DELETE FROM users;
10 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/secondary/project.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project (id, name, folder) VALUES (1, 'Play 2.0', 'Play framework');
4 | INSERT INTO project (id, name, folder) VALUES (2, 'Play 1.2.4', 'Play framewor');
5 | INSERT INTO project (id, name, folder) VALUES (3, 'Website', 'Play framework');
6 | INSERT INTO project (id, name, folder) VALUES (4, 'Secret project', 'Zenexity');
7 | INSERT INTO project (id, name, folder) VALUES (5, 'Playmate', 'Zenexity');
8 | INSERT INTO project (id, name, folder) VALUES (6, 'Things to do', 'Personal');
9 | INSERT INTO project (id, name, folder) VALUES (7, 'Play samples', 'Zenexity');
10 | INSERT INTO project (id, name, folder) VALUES (8, 'Private', 'Personal');
11 | INSERT INTO project (id, name, folder) VALUES (9, 'Private', 'Personal');
12 | INSERT INTO project (id, name, folder) VALUES (10, 'Private', 'Personal');
13 | INSERT INTO project (id, name, folder) VALUES (11, 'Private', 'Personal');
14 | ALTER SEQUENCE project_seq RESTART WITH 12;
15 |
16 | # --- !Downs
17 | ALTER SEQUENCE project_seq RESTART WITH 1;
18 | DELETE FROM project;
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/secondary/project_member.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'guillaume@sample.com');
4 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'maxime@sample.com');
5 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'sadek@sample.com');
6 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'erwan@sample.com');
7 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'guillaume@sample.com');
8 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'erwan@sample.com');
9 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'guillaume@sample.com');
10 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'maxime@sample.com');
11 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'guillaume@sample.com');
12 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'maxime@sample.com');
13 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'sadek@sample.com');
14 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'erwan@sample.com');
15 | INSERT INTO project_member (project_id, user_email) VALUES (5, 'maxime@sample.com');
16 | INSERT INTO project_member (project_id, user_email) VALUES (6, 'guillaume@sample.com');
17 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'guillaume@sample.com');
18 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'maxime@sample.com');
19 | INSERT INTO project_member (project_id, user_email) VALUES (8, 'maxime@sample.com');
20 | INSERT INTO project_member (project_id, user_email) VALUES (9, 'guillaume@sample.com');
21 | INSERT INTO project_member (project_id, user_email) VALUES (10, 'erwan@sample.com');
22 | INSERT INTO project_member (project_id, user_email) VALUES (11, 'sadek@sample.com');
23 |
24 | # --- !Downs
25 |
26 | DELETE FROM project_member;
27 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/secondary/task.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1000, 'Fix the documentation', FALSE, null, 'guillaume@sample.com', 1, 'Todo');
4 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1001, 'Prepare the beta release', FALSE, '2011-11-15 00:00:00.0', null, 1, 'Urgent');
5 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1002, 'Buy some milk', FALSE, null, null, 9, 'Todo');
6 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1003, 'Check 1.2.4-RC2', FALSE, '2011-11-18 00:00:00.0', 'guillaume@sample.com', 2, 'Todo');
7 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1004, 'Finish zentask integration', TRUE, '2011-11-15 00:00:00.0', 'maxime@sample.com', 7, 'Todo');
8 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1005, 'Release the secret project', FALSE, '2012-01-01 00:00:00.0', 'sadek@sample.com', 4, 'Todo');
9 | ALTER SEQUENCE task_seq RESTART WITH 1006;
10 |
11 | # --- !Downs
12 | ALTER SEQUENCE task_seq RESTART WITH 1000;
13 | DELETE FROM task;
14 |
15 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/db/fixtures/secondary/users.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 | INSERT INTO users (email, name, password) VALUES ('guillaume@sample.com', 'Guillaume Bort', 'secret');
3 | INSERT INTO users (email, name, password) VALUES ('maxime@sample.com', 'Maxime Dantec', 'secret');
4 | INSERT INTO users (email, name, password) VALUES ('sadek@sample.com', 'Sadek Drobi', 'secret');
5 | INSERT INTO users (email, name, password) VALUES ('erwan@sample.com', 'Erwan Loisant', 'secret');
6 |
7 |
8 | # --- !Downs
9 | DELETE FROM users;
10 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/evolutions/default/1.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 | drop table if exists users;
3 | create table users (
4 | email varchar(255) not null primary key,
5 | name varchar(255) not null,
6 | password varchar(255) not null
7 | );
8 |
9 | drop table if exists project;
10 | create table project (
11 | id bigint not null primary key,
12 | name varchar(255) not null,
13 | folder varchar(255) not null
14 | );
15 |
16 | drop sequence if exists project_seq;
17 | create sequence project_seq start with 1000;
18 |
19 | drop table if exists project_member;
20 | create table project_member (
21 | project_id bigint not null,
22 | user_email varchar(255) not null,
23 | foreign key(project_id) references project(id) on delete cascade,
24 | foreign key(user_email) references users(email) on delete cascade
25 | );
26 |
27 | drop table if exists task;
28 | create table task (
29 | id bigint not null primary key,
30 | title varchar(255) not null,
31 | done boolean,
32 | due_date timestamp,
33 | assigned_to varchar(255),
34 | project bigint not null,
35 | folder varchar(255),
36 | foreign key(assigned_to) references users(email) on delete set null,
37 | foreign key(project) references project(id) on delete cascade
38 | );
39 |
40 | drop sequence if exists task_seq;
41 | create sequence task_seq start with 1000;
42 |
43 | # --- !Downs
44 |
45 | drop sequence task_seq;
46 | drop table task;
47 | drop table project_member;
48 | drop sequence project_seq;
49 | drop table project;
50 | drop table users;
51 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/evolutions/secondary/1.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 | drop table if exists users;
3 | create table users (
4 | email varchar(255) not null primary key,
5 | name varchar(255) not null,
6 | password varchar(255) not null
7 | );
8 |
9 | drop table if exists project;
10 | create table project (
11 | id bigint not null primary key,
12 | name varchar(255) not null,
13 | folder varchar(255) not null
14 | );
15 |
16 | drop sequence if exists project_seq;
17 | create sequence project_seq start with 1000;
18 |
19 | drop table if exists project_member;
20 | create table project_member (
21 | project_id bigint not null,
22 | user_email varchar(255) not null,
23 | foreign key(project_id) references project(id) on delete cascade,
24 | foreign key(user_email) references users(email) on delete cascade
25 | );
26 |
27 | drop table if exists task;
28 | create table task (
29 | id bigint not null primary key,
30 | title varchar(255) not null,
31 | done boolean,
32 | due_date timestamp,
33 | assigned_to varchar(255),
34 | project bigint not null,
35 | folder varchar(255),
36 | foreign key(assigned_to) references users(email) on delete set null,
37 | foreign key(project) references project(id) on delete cascade
38 | );
39 |
40 | drop sequence if exists task_seq;
41 | create sequence task_seq start with 1000;
42 |
43 | # --- !Downs
44 |
45 | drop sequence task_seq;
46 | drop table task;
47 | drop table project_member;
48 | drop sequence project_seq;
49 | drop table project;
50 | drop table users;
51 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/prod.conf:
--------------------------------------------------------------------------------
1 | include "application.conf"
2 | db.default.driver=org.postgresql.Driver
3 | db.default.url=${DATABASE_URL}
4 |
5 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/conf/routes:
--------------------------------------------------------------------------------
1 | # Routes
2 | # This file defines all application routes (Higher priority routes first)
3 | # ~~~~
4 |
5 | # The home page
6 | GET / controllers.Projects.index()
7 |
8 | # Authentication
9 | GET /login controllers.Application.login()
10 | POST /login controllers.Application.authenticate()
11 | GET /logout controllers.Application.logout()
12 |
13 | # Projects
14 | POST /projects controllers.Projects.add()
15 |
16 | POST /projects/groups controllers.Projects.addGroup()
17 | DELETE /projects/groups controllers.Projects.deleteGroup(group: String)
18 | PUT /projects/groups controllers.Projects.renameGroup(group: String)
19 |
20 | DELETE /projects/:project controllers.Projects.delete(project: Long)
21 | PUT /projects/:project controllers.Projects.rename(project: Long)
22 |
23 | POST /projects/:project/team controllers.Projects.addUser(project: Long)
24 | DELETE /projects/:project/team controllers.Projects.removeUser(project: Long)
25 |
26 | # Tasks
27 | GET /projects/:project/tasks controllers.Tasks.index(project: Long)
28 | POST /projects/:project/tasks controllers.Tasks.add(project: Long, folder: String)
29 | PUT /tasks/:task controllers.Tasks.update(task: Long)
30 | DELETE /tasks/:task controllers.Tasks.delete(task: Long)
31 |
32 | POST /tasks/folder controllers.Tasks.addFolder()
33 | DELETE /projects/:project/tasks/folder controllers.Tasks.deleteFolder(project: Long, folder: String)
34 | PUT /project/:project/tasks/folder controllers.Tasks.renameFolder(project: Long, folder: String)
35 |
36 | # Javascript routing
37 | GET /assets/javascripts/routes controllers.Application.javascriptRoutes()
38 |
39 | # Map static resources from the /public folder to the /public path
40 | GET /assets/*file controllers.Assets.at(path="/public", file)
41 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.7
2 |
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/arrow-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/arrow-left.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/breadcrumb-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/breadcrumb-1.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/breadcrumb-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/breadcrumb-2.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/breadcrumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/breadcrumb.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/addRemove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/addRemove.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/clock.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/delete.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/drawer.folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/drawer.folder.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/folder.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/home.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/options.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/user.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/user2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/icons/user2.png
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/loading.gif
--------------------------------------------------------------------------------
/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-dbapi-adapter/test/zentasks/public/images/pattern.png
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/readme.md:
--------------------------------------------------------------------------------
1 | # ScalikeJDBC Play Fixture Plugin
2 |
3 | Please see the website.
4 |
5 | https://scalikejdbc.org/
6 |
7 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/main/scala/scalikejdbc/PlayFixtureModule.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 - 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 | * either express or implied. See the License for the specific language
14 | * governing permissions and limitations under the License.
15 | */
16 | package scalikejdbc
17 |
18 | import javax.inject._
19 | import _root_.play.api._
20 | import _root_.play.api.inject._
21 | import scala.concurrent.Future
22 |
23 | /**
24 | * Play Module
25 | */
26 | class PlayFixtureModule extends Module {
27 | def bindings(env: Environment, config: Configuration) =
28 | Seq(
29 | bind[PlayInitializer].toSelf.eagerly(),
30 | bind[PlayFixture].toSelf.eagerly()
31 | )
32 | }
33 |
34 | /**
35 | * The Play fixture plugin
36 | */
37 | @Singleton
38 | class PlayFixture @Inject() (
39 | configuration: Configuration,
40 | environment: Environment,
41 | playInitializer: PlayInitializer,
42 | lifecycle: ApplicationLifecycle
43 | ) extends scalikejdbc.play.FixtureSupport {
44 |
45 | private def isTest = environment.mode == Mode.Test
46 |
47 | private def isDev = environment.mode == Mode.Dev
48 |
49 | def onStart(): Unit = {
50 | if (isTest || isDev) {
51 | loadFixtures()(environment, configuration)
52 | }
53 | }
54 |
55 | def onStop(): Unit = {
56 | if (isTest || isDev) {
57 | cleanFixtures()(environment, configuration)
58 | }
59 | }
60 |
61 | lifecycle.addStopHook(() => Future.successful(onStop()))
62 | onStart()
63 | }
64 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/main/scala/scalikejdbc/play/Fixture.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 - 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package scalikejdbc.play
17 |
18 | import scala.io.Source
19 | import scala.io.Codec
20 | import java.io.File
21 |
22 | case class Fixture(file: File) {
23 |
24 | private def script: String = Source.fromFile(file)(Codec.UTF8).mkString
25 |
26 | private def isUpsMarker(s: String): Boolean = s.matches("""^#.*!Ups.*$""")
27 |
28 | private def isDownsMarker(s: String): Boolean = s.matches("""^#.*!Downs.*$""")
29 |
30 | def upScript: String =
31 | script.linesIterator
32 | .dropWhile { line => !isUpsMarker(line) }
33 | .dropWhile { line => isUpsMarker(line) }
34 | .takeWhile { line => !isDownsMarker(line) }
35 | .mkString("\n")
36 |
37 | def downScript: String =
38 | script.linesIterator
39 | .dropWhile { line => !isDownsMarker(line) }
40 | .dropWhile { line => isDownsMarker(line) }
41 | .mkString("\n")
42 | }
43 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/main/scala/scalikejdbc/play/FixtureNotFoundException.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 - 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package scalikejdbc.play
17 |
18 | class FixtureNotFoundException(message: String) extends Exception(message)
19 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/main/scala/scalikejdbc/play/FixtureSupport.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2013 - 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package scalikejdbc.play
17 |
18 | import _root_.play.api._
19 | import java.io.File
20 | import scala.jdk.CollectionConverters._
21 | import scalikejdbc._
22 |
23 | trait FixtureSupport {
24 |
25 | val fixturesRootPath: String = "db/fixtures"
26 |
27 | private def fixtureConfigKey(
28 | dbName: String
29 | )(implicit environment: Environment): String =
30 | if (environment.mode == Mode.Dev) {
31 | "db." + dbName + ".fixtures.dev"
32 | } else if (environment.mode == Mode.Test) {
33 | "db." + dbName + ".fixtures.test"
34 | } else {
35 | throw new UnsupportedOperationException(
36 | "Fixture feature is only provided for dev mode and test mode."
37 | )
38 | }
39 |
40 | def fixtures(implicit
41 | environment: Environment,
42 | configuration: Configuration
43 | ): Map[String, Seq[Fixture]] = {
44 | (for {
45 | dbConfig <- configuration.getOptional[Configuration]("db").toList
46 | subKey <- dbConfig.subKeys
47 | } yield {
48 | val dbName = subKey
49 | val fixtureNames: Seq[String] =
50 | try {
51 | configuration
52 | .getOptional[Seq[String]](fixtureConfigKey(subKey))
53 | .getOrElse(Nil)
54 | } catch {
55 | case e: PlayException => {
56 | configuration.getOptional[String](fixtureConfigKey(subKey)).toSeq
57 | }
58 | }
59 |
60 | val fixtureFiles = fixtureNames.map { fixtureName =>
61 | val resourceName =
62 | List(fixturesRootPath, dbName, fixtureName).mkString("/")
63 | environment.resource(resourceName) match {
64 | case Some(resource) => Fixture(new File(resource.getPath))
65 | case None =>
66 | throw new FixtureNotFoundException(
67 | "Fixture not found (%s)".format(resourceName)
68 | )
69 | }
70 | }
71 |
72 | dbName -> fixtureFiles
73 | }).toMap
74 | }
75 |
76 | def loadFixtures()(implicit
77 | environment: Environment,
78 | configuration: Configuration
79 | ): Unit = {
80 | for {
81 | (dbName, fs) <- fixtures
82 | f <- fs
83 | } {
84 | execute(dbName, f.upScript)
85 | }
86 | }
87 |
88 | def cleanFixtures()(implicit
89 | environment: Environment,
90 | configuration: Configuration
91 | ): Unit = {
92 | for {
93 | (dbName, fs) <- fixtures
94 | f <- fs.reverse
95 | } {
96 | execute(dbName, f.downScript)
97 | }
98 | }
99 |
100 | private def execute(dbName: String, script: String): Unit = {
101 | NamedDB(dbName) localTx { implicit session =>
102 | SQL(script).update.apply()
103 | }
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/test/resources/db/fixtures/default/project.sql:
--------------------------------------------------------------------------------
1 |
2 | # --- !Ups
3 | create table project (
4 | id bigint not null primary key,
5 | name varchar(255) not null,
6 | folder varchar(255) not null
7 | );
8 | create sequence project_seq start with 1000;
9 |
10 | # --- !Downs
11 | drop sequence project_seq;
12 | drop table project;
13 |
14 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/test/resources/db/fixtures/default/users.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 | create table users (
3 | email varchar(255) not null primary key,
4 | name varchar(255) not null,
5 | password varchar(255) not null
6 | );
7 |
8 | # --- !Downs
9 | drop table users;
10 |
11 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/test/resources/db/fixtures/secondary/a.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-fixture/src/test/resources/db/fixtures/secondary/a.sql
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/test/scala/scalikejdbc/play/FixtureSpec.scala:
--------------------------------------------------------------------------------
1 | package scalikejdbc.play
2 |
3 | import java.io.File
4 | import play.api.test._
5 | import play.api.test.Helpers._
6 | import play.api.libs.Files
7 | import org.specs2.mutable._
8 | import org.specs2.specification.BeforeAfterEach
9 |
10 | class FixtureSpec extends Specification with BeforeAfterEach {
11 |
12 | def before = {}
13 |
14 | def after = {}
15 |
16 | def fixture = {
17 | val script = """
18 | |
19 | |# --- !Ups
20 | |drop table users if exists;
21 | |create table users (
22 | | email varchar(255) not null primary key,
23 | | name varchar(255) not null,
24 | | password varchar(255) not null
25 | |);
26 | |
27 | |# --- !Downs
28 | |drop table users if exists;
29 | |
30 | |""".stripMargin
31 |
32 | val tmpfile = File.createTempFile("tmp", ".sql")
33 | tmpfile.deleteOnExit()
34 | val writer = new java.io.PrintWriter(tmpfile)
35 | try {
36 | writer.println(script)
37 | } finally {
38 | writer.close()
39 | }
40 | Fixture(tmpfile)
41 | }
42 |
43 | "Fixture" should {
44 |
45 | "has #upScript" in {
46 | val expected =
47 | """|drop table users if exists;
48 | |create table users (
49 | | email varchar(255) not null primary key,
50 | | name varchar(255) not null,
51 | | password varchar(255) not null
52 | |);
53 | |""".stripMargin
54 | fixture.upScript must_== expected
55 | }
56 |
57 | "has #downScript" in {
58 | val expected =
59 | """|drop table users if exists;
60 | |
61 | |""".stripMargin
62 | fixture.downScript must_== expected
63 | }
64 |
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/scalikejdbc-play-fixture/src/test/scala/scalikejdbc/play/FixtureSupportSpec.scala:
--------------------------------------------------------------------------------
1 | package scalikejdbc.play
2 |
3 | import org.specs2.mutable._
4 | import org.specs2.specification.BeforeAfterEach
5 | import play.api.{ Configuration, Environment }
6 |
7 | import scala.jdk.CollectionConverters._
8 |
9 | class FixtureSupportSpec extends Specification with BeforeAfterEach {
10 |
11 | def before = {}
12 |
13 | def after = {}
14 |
15 | val fixtureSupport = new FixtureSupport {}
16 |
17 | "FixtureSupport" should {
18 |
19 | "has #fixtures" in {
20 | val environment = Environment.simple()
21 | val configuration = Configuration(
22 | "play.modules.enabled" -> List(
23 | "scalikejdbc.PlayModule",
24 | "scalikejdbc.PlayFixtureModule"
25 | ),
26 | "db.default.fixtures.test" -> List("users.sql", "project.sql").asJava,
27 | "db.secondary.fixtures.test" -> "a.sql",
28 | "db.default.driver" -> "org.h2.Driver",
29 | "db.default.url" -> "jdbc:h2:mem:default;DB_CLOSE_DELAY=-1",
30 | "db.default.user" -> "sa",
31 | "db.default.password" -> "sa",
32 | "db.secondary.driver" -> "org.h2.Driver",
33 | "db.secondary.url" -> "jdbc:h2:mem:secondary;DB_CLOSE_DELAY=-1",
34 | "db.secondary.user" -> "l",
35 | "db.secondary.password" -> "g"
36 | )
37 | fixtureSupport.fixtures(environment, configuration) must have size 2
38 | }
39 |
40 | }
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | .settings
3 | classpath
4 | .project
5 | *.iml
6 | *.ipr
7 | *.iws
8 | .DS_Store
9 | dist/
10 | lib_managed/
11 | project/boot/
12 | project/plugins/project/
13 | target/
14 |
15 | # use glob syntax.
16 | syntax: glob
17 | *.ser
18 | *.class
19 | *~
20 | *.bak
21 | #*.off
22 | *.old
23 |
24 | # eclipse conf file
25 | .settings
26 | .classpath
27 | .project
28 | .manager
29 | .scala_dependencies
30 |
31 | # idea
32 | .idea
33 | *.iml
34 |
35 | # building
36 | target
37 | build
38 | null
39 | tmp*
40 | temp*
41 | dist
42 | test-output
43 | build.log
44 |
45 | # other scm
46 | .svn
47 | .CVS
48 | .hg*
49 |
50 | # switch to regexp syntax.
51 | # syntax: regexp
52 | # ^\.pc/
53 |
54 | #SHITTY output not in target directory
55 | build.log
56 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/readme.md:
--------------------------------------------------------------------------------
1 | # ScalikeJDBC Play Plugin
2 |
3 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/src/main/scala/scalikejdbc/PlayInitializer.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 - 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 | * either express or implied. See the License for the specific language
14 | * governing permissions and limitations under the License.
15 | */
16 | package scalikejdbc
17 |
18 | import javax.inject._
19 | import _root_.play.api._
20 | import _root_.play.api.inject._
21 | import scalikejdbc.config.{ TypesafeConfig, TypesafeConfigReader, DBs }
22 | import scala.concurrent.Future
23 |
24 | /**
25 | * The Play plugin to use ScalikeJDBC
26 | */
27 | @Singleton
28 | class PlayInitializer @Inject() (
29 | lifecycle: ApplicationLifecycle,
30 | configuration: Configuration
31 | ) {
32 |
33 | import PlayInitializer._
34 |
35 | // Play DB configuration
36 |
37 | private[this] lazy val playConfig = configuration
38 | .getOptional[Configuration]("scalikejdbc.play")
39 | .getOrElse(Configuration.empty)
40 |
41 | private[this] var closeAllOnStop = true
42 |
43 | private[this] lazy val loggingSQLErrors = configuration
44 | .getOptional[Boolean]("scalikejdbc.global.loggingSQLErrors")
45 | .getOrElse(true)
46 |
47 | /**
48 | * DBs with Play application configuration.
49 | */
50 | private[this] lazy val DBs = new DBs
51 | with TypesafeConfigReader
52 | with TypesafeConfig {
53 | override val config = configuration.underlying
54 | }
55 |
56 | def onStart(): Unit = {
57 | DBs.setupAll()
58 | GlobalSettings.loggingSQLErrors = loggingSQLErrors
59 | opt("closeAllOnStop", "enabled")(playConfig).foreach { enabled =>
60 | closeAllOnStop = enabled.toBoolean
61 | }
62 | }
63 |
64 | def onStop(): Unit = {
65 | if (closeAllOnStop) {
66 | ConnectionPool.closeAll()
67 | }
68 |
69 | val cache = SQLSyntaxSupportFeature.SQLSyntaxSupportLoadedColumns
70 | cache.clear()
71 | }
72 |
73 | lifecycle.addStopHook(() => Future.successful(onStop()))
74 | onStart()
75 | }
76 |
77 | object PlayInitializer {
78 | def opt(name: String, key: String)(implicit
79 | config: Configuration
80 | ): Option[String] = {
81 | config.getOptional[String](name + "." + key)
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/src/main/scala/scalikejdbc/PlayModule.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2012 - 2014 scalikejdbc.org
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 | * either express or implied. See the License for the specific language
14 | * governing permissions and limitations under the License.
15 | */
16 | package scalikejdbc
17 |
18 | import javax.inject._
19 | import _root_.play.api._
20 | import _root_.play.api.inject._
21 |
22 | /**
23 | * Play module
24 | */
25 | class PlayModule extends Module {
26 | def bindings(env: Environment, config: Configuration) = Seq(
27 | bind[PlayInitializer].toSelf.eagerly()
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/src/test/scala/scalikejdbc/PlayModuleSpec.scala:
--------------------------------------------------------------------------------
1 | package scalikejdbc
2 |
3 | import _root_.play.api.inject.guice.GuiceApplicationBuilder
4 | import _root_.play.api.test.Helpers._
5 | import org.specs2.mutable.Specification
6 |
7 | object PlayModuleSpec extends Specification {
8 |
9 | sequential
10 |
11 | Class.forName("org.h2.Driver")
12 |
13 | def fakeApp = {
14 | val additionalConfiguration = Map(
15 | "logger.root" -> "INFO",
16 | "logger.play" -> "INFO",
17 | "logger.application" -> "DEBUG",
18 | "dbplugin" -> "disabled",
19 | "evolutionplugin" -> "disabled",
20 | "db.default.driver" -> "org.h2.Driver",
21 | "db.default.url" -> "jdbc:h2:mem:default",
22 | "db.default.user" -> "sa",
23 | "db.default.password" -> "sa",
24 | "db.default.schema" -> "",
25 | "db.default.poolInitialSize" -> "1",
26 | "db.default.poolMaxSize" -> "2",
27 | "db.default.poolValidationQuery" -> "select 1",
28 | "db.default.poolConnectionTimeoutMillis" -> "2000",
29 | "db.legacydb.driver" -> "org.h2.Driver",
30 | "db.legacydb.url" -> "jdbc:h2:mem:legacy",
31 | "db.legacydb.user" -> "l",
32 | "db.legacydb.password" -> "g",
33 | "db.legacydb.schema" -> "",
34 | "scalikejdbc.global.loggingSQLAndTime.enabled" -> "true",
35 | "scalikejdbc.global.loggingSQLAndTime.singleLineMode" -> "true",
36 | "scalikejdbc.global.loggingSQLAndTime.logLevel" -> "debug",
37 | "scalikejdbc.global.loggingSQLAndTime.warningEnabled" -> "true",
38 | "scalikejdbc.global.loggingSQLAndTime.warningThreasholdMillis" -> "1",
39 | "scalikejdbc.global.loggingSQLAndTime.warningLogLevel" -> "warn"
40 | )
41 | new GuiceApplicationBuilder()
42 | .configure(additionalConfiguration)
43 | .bindings(new scalikejdbc.PlayModule)
44 | .build()
45 | }
46 |
47 | def fakeAppWithoutCloseAllOnStop = {
48 | val additionalConfiguration = Map(
49 | "db.default.driver" -> "org.h2.Driver",
50 | "db.default.url" -> "jdbc:h2:mem:default",
51 | "db.default.user" -> "sa",
52 | "db.default.password" -> "sa",
53 | "db.legacydb.driver" -> "org.h2.Driver",
54 | "db.legacydb.url" -> "jdbc:h2:mem:legacy",
55 | "db.legacydb.user" -> "l",
56 | "db.legacydb.password" -> "g",
57 | "scalikejdbc.play.closeAllOnStop.enabled" -> "false"
58 | )
59 | new GuiceApplicationBuilder()
60 | .configure(additionalConfiguration)
61 | .bindings(new scalikejdbc.PlayModule)
62 | .build()
63 | }
64 |
65 | def fakeAppWithDBPlugin = {
66 | val additionalConfiguration = Map(
67 | "db.default.driver" -> "org.h2.Driver",
68 | "db.default.url" -> "jdbc:h2:mem:default",
69 | "db.default.user" -> "sa",
70 | "db.default.password" -> "sa",
71 | "db.default.schema" -> "",
72 | "db.legacydb.driver" -> "org.h2.Driver",
73 | "db.legacydb.url" -> "jdbc:h2:mem:legacy",
74 | "db.legacydb.user" -> "l",
75 | "db.legacydb.password" -> "g",
76 | "db.legacydb.schema" -> "",
77 | "scalikejdbc.global.loggingSQLAndTime.enabled" -> "true",
78 | "scalikejdbc.global.loggingSQLAndTime.logLevel" -> "debug",
79 | "scalikejdbc.global.loggingSQLAndTime.warningEnabled" -> "true",
80 | "scalikejdbc.global.loggingSQLAndTime.warningThreasholdMillis" -> "1",
81 | "scalikejdbc.global.loggingSQLAndTime.warningLogLevel" -> "warn"
82 | )
83 | new GuiceApplicationBuilder()
84 | .configure(additionalConfiguration)
85 | .bindings(new scalikejdbc.PlayModule)
86 | .build()
87 | }
88 |
89 | def simpleTest(table: String) = {
90 |
91 | try {
92 |
93 | DB autoCommit { implicit s =>
94 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
95 | SQL(
96 | "CREATE TABLE " + table + " (ID BIGINT PRIMARY KEY NOT NULL, NAME VARCHAR(256))"
97 | ).execute.apply()
98 | val insert = SQL(
99 | "INSERT INTO " + table + " (ID, NAME) VALUES (/*'id*/123, /*'name*/'Alice')"
100 | )
101 | insert.bindByName("id" -> 1, "name" -> "Alice").update.apply()
102 | insert.bindByName("id" -> 2, "name" -> "Bob").update.apply()
103 | insert.bindByName("id" -> 3, "name" -> "Eve").update.apply()
104 | }
105 |
106 | NamedDB("legacydb") autoCommit { implicit s =>
107 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
108 | SQL(
109 | "CREATE TABLE " + table + " (ID BIGINT PRIMARY KEY NOT NULL, NAME VARCHAR(256))"
110 | ).execute.apply()
111 | val insert = SQL(
112 | "INSERT INTO " + table + " (ID, NAME) VALUES (/*'id*/123, /*'name*/'Alice')"
113 | )
114 | insert.bindByName("id" -> 1, "name" -> "Alice").update.apply()
115 | insert.bindByName("id" -> 2, "name" -> "Bob").update.apply()
116 | insert.bindByName("id" -> 3, "name" -> "Eve").update.apply()
117 | insert.bindByName("id" -> 4, "name" -> "Fred").update.apply()
118 | }
119 |
120 | case class User(id: Long, name: Option[String])
121 |
122 | val users = DB readOnly { implicit s =>
123 | SQL("SELECT * FROM " + table)
124 | .map(rs => User(rs.long("id"), Option(rs.string("name"))))
125 | .list
126 | .apply()
127 | }
128 | users.size must_== (3)
129 |
130 | val usersInLegacy = NamedDB("legacydb") readOnly { implicit s =>
131 | SQL("SELECT * FROM " + table)
132 | .map(rs => User(rs.long("id"), Option(rs.string("name"))))
133 | .list
134 | .apply()
135 | }
136 | usersInLegacy.size must_== (4)
137 |
138 | } finally {
139 | DB autoCommit { implicit s =>
140 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
141 | }
142 | NamedDB("legacydb") autoCommit { implicit s =>
143 | SQL("DROP TABLE " + table + " IF EXISTS").execute.apply()
144 | }
145 | }
146 |
147 | }
148 |
149 | "Play plugin" should {
150 |
151 | "be available when DB plugin is not active" in {
152 | running(fakeApp) {
153 | val settings = ConnectionPool.get("default").settings
154 | settings.initialSize must_== (1)
155 | settings.maxSize must_== (2)
156 | settings.validationQuery must_== ("select 1")
157 | settings.connectionTimeoutMillis must_== (2000)
158 | simpleTest("user_1")
159 | }
160 | running(fakeApp) { simpleTest("user_2") }
161 | running(fakeApp) { simpleTest("user_3") }
162 | }
163 |
164 | "be available when DB plugin is also active" in {
165 | running(fakeAppWithDBPlugin) { simpleTest("user_withdbplugin") }
166 | }
167 |
168 | "close connection pools after stopping Play app" in {
169 | try {
170 | // Play 2.0.4 throws Exception here
171 | running(fakeApp) { simpleTest("user_4") }
172 | } catch { case e: Exception => }
173 | simpleTest("user_5") must throwA[IllegalStateException](message =
174 | "Connection pool is not yet initialized."
175 | )
176 | }
177 |
178 | "skip closing connection pools after stopping Play app" in {
179 | running(fakeAppWithoutCloseAllOnStop) {
180 | simpleTest("user_4")
181 | }
182 | simpleTest("user_5")
183 | }
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/Procfile:
--------------------------------------------------------------------------------
1 | web: target/start -Dhttp.port=${PORT} -Ddb.default.url=$DATABASE_URL
2 |
3 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/README:
--------------------------------------------------------------------------------
1 | This advanced todo list demonstrates a modern AJAX-based web application. This is a work in progress, and we plan to add several features in the future releases. For now you can check it out to learn how to:
2 |
3 | - Integrate authentication, and security.
4 | - Use AJAX and the Javascript reverse routing.
5 | - Integrate with compiled assets - LESS CSS and CoffeeScript.
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/apps/_tasks.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // TASKS
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | .tasks {
8 | .folder {
9 | .box();
10 | > header {
11 | position: relative;
12 | padding: 4px 25px 4px 7px;
13 | input {
14 | display: inline-block;
15 | }
16 | input[type=text] {
17 | margin: 1px 0 0;
18 | }
19 | .options, .loader {
20 | position: absolute;
21 | top: 4px;
22 | right: 4px;
23 | }
24 | }
25 | > ul {
26 | > li {
27 | position: relative;
28 | padding: 4px 20px 4px 7px;
29 | border-bottom: 1px solid rgba(0,0,0,.05);
30 | -webkit-user-select: text;
31 | time {
32 | float: right;
33 | display: inline-block;
34 | margin: 0 10px;
35 | border-radius: 15px;
36 | background: url(/assets/images/icons/clock.png) 1px 1px no-repeat;
37 | background-color: @dueDateBackground;
38 | border: 1px solid @dueDateBorder;
39 | color: @dueDateColor;
40 | font-size: 11px;
41 | padding: 0 4px 1px 15px;
42 | }
43 | h4 {
44 | display: inline-block;
45 | font-weight: bold;
46 | }
47 | .deleteTask {
48 | .delete();
49 | top: 4px;
50 | right: 4px;
51 | }
52 | &:hover .deleteTask {
53 | opacity: 1;
54 | -webkit-transition-delay: 0;
55 | }
56 | .assignedTo {
57 | float: right;
58 | display: inline-block;
59 | margin: 0 10px;
60 | padding-left: 17px;
61 | color: @assignedToColor;
62 | background: url(/assets/images/icons/user2.png) 0 1px no-repeat;
63 | }
64 | }
65 | }
66 | .addTask {
67 | position: relative;
68 | border-radius: 0 0 4px 4px;
69 | padding: 5px 250px 5px 5px;
70 | background: white;
71 | &:after {
72 | content: " ";
73 | display: block;
74 | clear: both;
75 | }
76 | input {
77 | outline: none;
78 | }
79 | [name=taskBody] {
80 | width: 100%;
81 | border: 0;
82 | }
83 | .dueDate {
84 | position: absolute;
85 | right: 210px;
86 | top: 4px;
87 | width: 140px;
88 | border-radius: 15px;
89 | background: url(/assets/images/icons/clock.png) 2px 2px no-repeat;
90 | background-color: @dueDateBackground;
91 | border: 1px solid @dueDateBorder;
92 | color: @dueDateColor;
93 | font-size: 11px;
94 | padding: 1px 4px 1px 15px;
95 | &::-webkit-input-placeholder {
96 | color: inherit;
97 | }
98 | &:-moz-placeholder {
99 | color: inherit;
100 | }
101 | }
102 | .assignedTo {
103 | position: absolute;
104 | right: 5px;
105 | top: 5px;
106 | width: 195px;
107 | input {
108 | width: 180px;
109 | margin: 2px;
110 | border: 0;
111 | }
112 | }
113 | .assignToList {
114 | display: none;
115 | position: absolute;
116 | top: 100%;
117 | right: 0;
118 | min-width: 100%;
119 | background: rgba(0,0,0,.8);
120 | color: #eee;
121 | }
122 | [type=submit] {
123 | position: absolute;
124 | left: -3000px;
125 | visibility: hidden;
126 | }
127 | ul, div {
128 | display: inline-block;
129 | }
130 | }
131 | .loader {
132 | position: absolute;
133 | top: 5px;
134 | right: 6px;
135 | }
136 | }
137 | }
138 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/libs/_mate.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // MATE: CSS helpers
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | // ------------------------ GRADIENTS
8 | .gradient(@from:#000, @to:#EEE) {
9 | background: @from;
10 | background-image: -webkit-gradient(linear, left top, left bottom, from(@from), to(@to));
11 | background-image: -moz-linear-gradient(top, @from, @to);
12 | }
13 |
14 | // ---------------------- TRANSITIONS
15 | .transition(@range: all, @time: 500ms, @ease: ease-in-out) {
16 | -moz-transition: @range @time @ease;
17 | -webkit-transition: @range @time @ease;
18 | -o-transition: @range @time @ease;
19 | transition: @range @time @ease;
20 | }
21 |
22 | // ------------------------ TRANSFORMS
23 | .transform(@props) {
24 | -moz-transform: @arguments;
25 | -webkit-transform: @arguments;
26 | -o-transform: @arguments;
27 | transform: @arguments;
28 | }
29 |
30 | // --------------------------- HELPERS
31 | .ellipsis() {
32 | white-space: nowrap;
33 | text-overflow: ellipsis;
34 | overflow: hidden;
35 | }
36 |
37 | .clear() {
38 | &:after {
39 | display: block;
40 | content: " ";
41 | clear: both;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/libs/_reset.less:
--------------------------------------------------------------------------------
1 | html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td {margin: 0; padding: 0; border: 0; outline: 0; font-weight: inherit; font-style: inherit; font-size: 100%; font-family: inherit;}
2 |
3 | table {border-collapse: collapse; border-spacing: 0;}
4 | caption, th, td {text-align: left; font-weight: normal;}
5 | form legend {display: none;}
6 | blockquote:before, blockquote:after, q:before, q:after {content: "";}
7 | blockquote, q {quotes: "" "";}
8 | ol, ul {list-style: none;}
9 | hr {display: none; visibility: hidden;}
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/libs/_theme.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // THEME
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | // ---------------------------- COLORS
8 | @mainBackground: #c7d1d8;
9 | @mainColor: #2a3a48;
10 | @drawerBackground: #e1e7ec;
11 | @folderColor: #6f8193;
12 | @projectColor: @mainColor;
13 | @layoutBorderColor: #606d78;
14 |
15 | @links: #4794c4;
16 | @linksHover: #2a5e88;
17 |
18 | @headerLight: #445868;
19 | @headerDark: @mainColor;
20 | @titleColor: #556b7b;
21 | @buttonColor: @mainBackground;
22 | @buttonHover: #fff;
23 |
24 | @activeColor: #5daad5;
25 |
26 | // Tasks
27 | @dueDateBackground: #accfe8;
28 | @dueDateBorder: #73a4ca;
29 | @dueDateColor: #246fa9;
30 | @assignedToColor: @titleColor;
31 |
32 | // Folders
33 | @folderBorder: #9ba5ad;
34 | @folderBackground: #dbe1e5;
35 | @folderHeaderLight: #f2f5f8;
36 | @folderHeaderDark: #dfe2e6;
37 | @folderTitle: #7a8a99;
38 |
39 | // Pannels
40 | @panBackground: rgba(0,0,0,.85);
41 | @panShadow: rgba(0,0,0,.8);
42 | @panText: #aaa;
43 | @panTitle: #fff;
44 | @panBorder: #333;
45 | @panButtonBackground: #444;
46 | @panButtonColor: #fff;
47 |
48 | // ----------------------------- FONTS
49 | @defaultFont: 13px "Lucida Grande","Helvetica Neue", sans-serif;
50 |
51 | // ----------------------------- SIZES
52 | @headerHeight: 40px;
53 | @drawerWidth: 220px;
54 | @navigationWidth: 70px;
55 | @breadcrumbHeight: 50px;
56 |
57 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/login.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // LOGIN
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | @import 'libs/_reset.less';
8 | @import 'libs/_mate.less';
9 | @import 'libs/_theme.less';
10 |
11 | // ----------------------- MAIN STYLES
12 | body {
13 | background: @mainBackground;
14 | color: @mainColor;
15 | font: @defaultFont;
16 | -webkit-font-smoothing: antialised;
17 | -webkit-user-select: none;
18 | }
19 |
20 | a {
21 | color: @links;
22 | text-decoration: none;
23 | &:hover {
24 | color: @linksHover;
25 | }
26 | }
27 |
28 | p.note {
29 | margin: 10px auto 0;
30 | width: 300px;
31 | padding: 20px;
32 | text-align: center;
33 | color: #445868;
34 | text-shadow: 1px 1px rgba(255,255,255,.6);
35 | em {
36 | font-weight: bold;
37 | }
38 | }
39 |
40 | form {
41 | margin: 100px auto 0;
42 | width: 300px;
43 | padding: 20px;
44 | background: #fff;
45 | border-radius: 5px;
46 | box-shadow: 0 2px 5px rgba(0,0,0,.3);
47 | text-align: center;
48 | h1 {
49 | margin: 0 0 10px;
50 | font-size: 20px;
51 | font-weight: bold;
52 | }
53 | p {
54 | width: inherit;
55 | margin: 5px 0;
56 | color: #999;
57 | }
58 | p.error {
59 | color: #c00;
60 | margin-bottom: 10px;
61 | text-shadow: 1px 1px rgba(0,0,0,.1);
62 | }
63 | p.success {
64 | color: #83BD41;
65 | margin-bottom: 10px;
66 | text-shadow: 1px 1px rgba(0,0,0,.1);
67 | }
68 | input {
69 | display: block;
70 | width: inherit;
71 | padding: 2px;
72 | background: rgba(0,0,0,.05);
73 | border: 1px solid rgba(0,0,0,.15);
74 | box-shadow: 0 1px 2px rgba(0,0,0,.1) inset;
75 | border-radius: 3px;
76 | font-size: 14px;
77 | &:invalid:not(:focus) {
78 | border-color: red;
79 | }
80 | }
81 | button {
82 | .button();
83 | display: block;
84 | width: inherit;
85 | font-size: 14px;
86 | }
87 | }
88 |
89 | nav {
90 | margin-top: 15px;
91 | a {
92 | display: inline-block;
93 | margin: 0 4px;
94 | }
95 | }
96 |
97 | // --------------------------- IMPORTS
98 | @import 'main/_widgets.less'; // Some shared elements
99 | @import 'main/_header.less'; // Top header + User bar
100 |
101 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/main.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // MAIN
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | @import 'libs/_reset.less';
8 | @import 'libs/_mate.less';
9 | @import 'libs/_theme.less';
10 |
11 | // ----------------------- MAIN STYLES
12 | body {
13 | background: @mainBackground;
14 | color: @mainColor;
15 | font: @defaultFont;
16 | -webkit-font-smoothing: antialised;
17 | -webkit-user-select: none;
18 | }
19 |
20 | a {
21 | color: @links;
22 | text-decoration: none;
23 | &:hover {
24 | color: @linksHover;
25 | }
26 | }
27 |
28 | // --------------------------- IMPORTS
29 | @import 'main/_layout.less'; // General grid
30 | @import 'main/_widgets.less'; // Some shared elements
31 | @import 'main/_drawer.less'; // Project drawer
32 | @import 'main/_header.less'; // Top header + User bar
33 | @import 'main/_breadcrumb.less'; // Breadcrumb + App menu
34 | @import 'apps/_tasks.less'; // Tasks
35 |
36 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/main/_breadcrumb.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // BREADCRUMB
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | #main > header {
8 | height: 39px;
9 | background: url(/assets/images/breadcrumb.png);
10 | border-bottom: 1px solid @layoutBorderColor;
11 | hgroup {
12 | height: inherit;
13 | overflow: hidden;
14 | float: left;
15 | > * {
16 | float: inherit;
17 | position: relative;
18 | height: inherit;
19 | line-height: 40px;
20 | margin-left: -25px;
21 | padding: 0 6px 0 13px;
22 | font-size: 18px;
23 | text-shadow: 1px 1px 0 rgba(255,255,255,.5);
24 | -webkit-border-image: url(/assets/images/breadcrumb-2.png) 0 30 0 20 stretch stretch;
25 | -moz-border-image: url(/assets/images/breadcrumb-2.png) 0 30 0 20 stretch stretch;
26 | border-image: url(/assets/images/breadcrumb-2.png) 0 30 0 20 stretch stretch;
27 | border-width: 0 30px 0 25px;
28 | color: @titleColor;
29 | -webkit-user-select: text;
30 | &:nth-child(2) {
31 | -webkit-border-image: url(/assets/images/breadcrumb-1.png) 0 30 0 1 stretch stretch;
32 | -moz-border-image: url(/assets/images/breadcrumb-1.png) 0 30 0 1 stretch stretch;
33 | border-image: url(/assets/images/breadcrumb-1.png) 0 30 0 2 stretch stretch;
34 | }
35 | &:first-child {
36 | padding-left: 20px;
37 | }
38 | &:nth-child(1) { z-index: 3; }
39 | &:nth-child(2) { z-index: 2; }
40 | &:nth-child(3) { z-index: 1; }
41 | }
42 | }
43 | .users {
44 | position: relative;
45 | margin: 8px 10px;
46 | float: right;
47 | .pannel();
48 | > dt {
49 | &:before {
50 | content: url(/assets/images/icons/user.png);
51 | padding-right: 4px;
52 | vertical-align: middle;
53 | }
54 | .button();
55 | }
56 | > dd {
57 | padding: 5px 10px;
58 | width: 300px;
59 | color: @panText;
60 | z-index: 99;
61 | }
62 | .wrap {
63 | overflow: auto;
64 | max-height: 350px;
65 | width: inherit;
66 | }
67 | h3 {
68 | margin: 10px 0 0;
69 | padding: 5px 0;
70 | font-size: 16px;
71 | color: @panTitle;
72 | &:first-of-type {
73 | margin: 0;
74 | }
75 | }
76 | dl {
77 | position: relative;
78 | border-top: 1px solid @panBorder;
79 | padding: 5px 17px 5px 0;
80 | dt {
81 | .ellipsis();
82 | span {
83 | opacity: .5;
84 | font-size: 11px;
85 | }
86 | }
87 | }
88 | .action {
89 | position: absolute;
90 | top: 5px;
91 | right: 0px;
92 | width: 16px;
93 | height: 16px;
94 | overflow: hidden;
95 | text-indent: -99em;
96 | background: #444 url(/assets/images/icons/addRemove.png) 0 1 no-repeat;
97 | border-radius: 10px;
98 | &:hover {
99 | background-color: green;
100 | }
101 | }
102 | .list .action {
103 | background-position: 0 -19px;
104 | &:hover {
105 | background-color: red;
106 | }
107 | }
108 | }
109 | }
110 |
111 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/main/_drawer.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // PROJECTS DRAWER
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 | body {
7 | & > nav {
8 | padding: 10px 0 0;
9 | background: @drawerBackground;
10 | border-right: 1px solid @layoutBorderColor;
11 | }
12 | .dashboard {
13 | display: block;
14 | position: relative;
15 | font-size: 11px;
16 | font-weight: 700;
17 | text-transform: uppercase;
18 | padding: 10px 5px 5px 25px;
19 | background: url(/assets/images/icons/home.png) 6px 7px no-repeat;
20 | a {
21 | color: @folderColor;
22 | cursor: default;
23 | }
24 | }
25 | h4 {
26 | cursor: default;
27 | }
28 | }
29 |
30 | #projects {
31 | input {
32 | margin: 0;
33 | padding: 0;
34 | border: 0;
35 | font: inherit;
36 | }
37 | > li {
38 | position: relative;
39 | padding: 10px 5px 5px 25px;
40 | .options {
41 | position: absolute;
42 | top: 7px;
43 | right: 5px;
44 | button {
45 | border: none;
46 | }
47 | }
48 | .loader {
49 | top: 8px;
50 | right: 6px;
51 | }
52 | li {
53 | position: relative;
54 | padding: 0 0 0 25px;
55 | background: url(/assets/images/icons/folder.png) 1px 1px no-repeat;
56 | a {
57 | display: block;
58 | color: @projectColor;
59 | padding: 2px;
60 | }
61 | input[type=text] {
62 | padding: 2px 1px;
63 | }
64 | .delete {
65 | opacity: 0.1;
66 | }
67 | .loader {
68 | top: 2px;
69 | right: 2px;
70 | }
71 | &:hover {
72 | a {
73 | color: #000;
74 | }
75 | .delete {
76 | opacity: 1;
77 | //-webkit-transition-delay: 0;
78 | }
79 | }
80 | }
81 | .toggle {
82 | content: " ";
83 | position: absolute;
84 | left: 8px;
85 | top: 12px;
86 | display: inline-block;
87 | width: 12px;
88 | height: 12px;
89 | vertical-align: middle;
90 | background: url(/assets/images/icons/drawer.folder.png) 0 0 no-repeat;
91 | }
92 | > h4 {
93 | display: block;
94 | margin: 0 0 5px;
95 | padding: 0 1px;
96 | position: relative;
97 | color: @folderColor;
98 | font-size: 11px;
99 | font-weight: 700;
100 | text-transform: uppercase;
101 | }
102 | > input {
103 | margin: 0 0 5px;
104 | text-transform: uppercase;
105 | font-weight: bold;
106 | font-size: 11px;
107 | }
108 | &.closed {
109 | >ul {
110 | display: none;
111 | }
112 | .toggle {
113 | background-position: 0 -20px;
114 | }
115 | }
116 | }
117 | }
118 |
119 | #activity {
120 | position: absolute;
121 | bottom: 0;
122 | font-size: 11px;
123 | padding: 10px;
124 | }
125 |
126 | #newGroup {
127 | font-size: 13px;
128 | .new();
129 | margin: 15px 25px;
130 | }
131 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/main/_header.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // HEADER
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | body {
8 | & > header {
9 | box-sizing: border-box;
10 | padding: 10px;
11 | z-index: 9;
12 | .gradient(@headerLight, @headerDark);
13 | box-shadow: 0 0 7px rgba(0,0,0,.8),
14 | inset 0 1px 0 rgba(255,255,255,.2),
15 | inset 0 -1px 0 rgba(0,0,0,.8);
16 | }
17 | }
18 |
19 | #logo {
20 | color: #fff;
21 | font-weight: bold;
22 | font-size: 16px;
23 | text-transform: uppercase;
24 | letter-spacing: -2px;
25 | text-shadow: 1px 1px 0 #000;
26 | span {
27 | color: @activeColor;
28 | }
29 | }
30 |
31 | #user {
32 | position: absolute;
33 | right: 10px;
34 | top: 10px;
35 | > * {
36 | display: inline-block;
37 | }
38 | dt {
39 | color: #fff;
40 | span {
41 | opacity: .5;
42 | font-size: 11px;
43 | }
44 | }
45 | dd {
46 | a , button {
47 | .button();
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/main/_layout.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // MAIN LAYOUT
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | body {
8 | & > header {
9 | position: absolute;
10 | top: 0;
11 | left: 0;
12 | right: 0;
13 | height: @headerHeight;
14 | }
15 | & > nav {
16 | position: absolute;
17 | top: @headerHeight;
18 | left: 0;
19 | width: @drawerWidth;
20 | bottom: 0;
21 | box-sizing: border-box;
22 | }
23 | & > section {
24 | position: absolute;
25 | top: @headerHeight;
26 | left: @drawerWidth;
27 | right: 0;
28 | bottom: 0;
29 | }
30 | }
31 |
32 | #main > header {
33 | position: absolute;
34 | top: 0;
35 | left: 0;
36 | right: 0;
37 | height: @breadcrumbHeight;
38 | }
39 |
40 | #main > article {
41 | position: absolute;
42 | top: 40px;
43 | left: 0;
44 | bottom: 0;
45 | right: 0;
46 | padding: 20px;
47 | overflow: auto;
48 | }
49 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/assets/stylesheets/main/_widgets.less:
--------------------------------------------------------------------------------
1 | // -----------------------------------
2 | // WIDGETS
3 | // -----------------------------------
4 | // author: mda@zenexity.com - 2011
5 | // -----------------------------------
6 |
7 | // --------------------------- OPTIONS
8 | .pannel(){
9 | > dd {
10 | //display: none;
11 | .transform(scale(.001));
12 | .transition(-webkit-transform, 200ms, ease-out);
13 | -webkit-transform-origin: right top;
14 | -moz-transform-origin: right top;
15 | transform-origin: right top;
16 | position: absolute;
17 | top: 100%;
18 | right: -2px;
19 | width: 150px;
20 | margin: 7px 0px 0 0;
21 | padding: 5px;
22 | z-index: 99;
23 | background: @panBackground;
24 | border-radius: 5px;
25 | box-shadow: 0 2px 7px @panShadow;
26 | a, button {
27 | display: block;
28 | width: 100%;
29 | padding: 3px 10px;
30 | color: @panText;
31 | border-radius: 2px;
32 | background: none;
33 | &:hover {
34 | background: @panButtonBackground;
35 | color: @panButtonColor;
36 | }
37 | }
38 | &:before {
39 | content: " ";
40 | display: block;
41 | border-bottom: 6px solid @panBackground;
42 | border-left: 6px solid transparent;
43 | border-right: 6px solid transparent;
44 | border-top: none;
45 | margin-right: 0;
46 | margin-top: -12px;
47 | position: absolute;
48 | right: 5px;
49 | width: 1px;
50 | height: 1px;
51 | }
52 | }
53 | &.opened > dd {
54 | .transform(scale(1));
55 | }
56 | }
57 |
58 | .button() {
59 | padding: 2px 5px;
60 | border-radius: 3px;
61 | border: 1px solid @headerDark - #111;
62 | .gradient(fadeout(#bff, 80%), fadeout(#bff, 100%));
63 | background-color: @headerDark;
64 | box-shadow: 0 1px 4px rgba(0,0,0,.3),
65 | inset 0 1px 0 rgba(255,255,255,.2),
66 | inset 0 -1px 0 rgba(0,0,0,.2);
67 | text-shadow: -1px -1px 0 rgba(0,0,0,.3);
68 | color: @buttonColor;
69 | cursor: pointer;
70 | &:hover {
71 | .gradient(fadeout(#bff, 70%), fadeout(#bff, 100%));
72 | background-color: @headerDark;
73 | color: @buttonHover;
74 | }
75 | }
76 |
77 | .box() {
78 | border: 1px solid @folderBorder;
79 | background: @folderBackground;
80 | border-radius: 5px;
81 | margin: 0 0 20px;
82 | > header {
83 | border-radius: 5px 5px 0 0;
84 | .gradient(@folderHeaderLight, @folderHeaderDark);
85 | border-bottom: inherit;
86 | padding: 4px 7px;
87 | h3 {
88 | display: inline-block;
89 | font-size: 15px;
90 | font-weight: bold;
91 | color: @folderTitle;
92 | text-shadow: 1px 1px 0 #fff;
93 | }
94 | }
95 | }
96 | .options {
97 | width: 20px;
98 | height: 20px;
99 | position: relative;
100 | font-size: 11px;
101 | dt {
102 | width: inherit;
103 | cursor: pointer;
104 | height: inherit;
105 | text-indent: -9999em;
106 | background: url(/assets/images/icons/options.png) 0 0 no-repeat;
107 | }
108 | &:hover dt, &.opened dt, {
109 | background: url(/assets/images/icons/options.png) 0 -20px no-repeat;
110 | }
111 | .pannel();
112 | }
113 |
114 | .new {
115 | display: inline-block;
116 | .button();
117 | &:before {
118 | content: "+";
119 | font-size: 15px;
120 | line-height: 15px;
121 | font-weight: bold;
122 | color: @activeColor;
123 | padding-right: 4px;
124 | }
125 | }
126 |
127 | .delete {
128 | position: absolute;
129 | top: 0px;
130 | right: 0;
131 | border: none;
132 | padding: 0;
133 | width: 18px;
134 | height: 20px;
135 | overflow: hidden;
136 | text-indent: -99em;
137 | background: url(/assets/images/icons/delete.png) 0 1px no-repeat;
138 | .transition(opacity, 300ms, ease-in-out);
139 | -webkit-transition-delay: 100ms;
140 | z-index: 7;
141 | cursor: pointer;
142 | &:hover {
143 | background: url(/assets/images/icons/delete.png) 0 -19px no-repeat;
144 | }
145 | }
146 |
147 | .counter {
148 | color: #888;
149 | font-size: 11px;
150 | text-shadow: 1px 1px 0 rgba(255,255,255,.7);
151 | margin: 2px 5px;
152 | padding: 0px 3px;
153 | background: rgba(0,0,0,.05);
154 | border-radius: 10px;
155 | border: 1px solid rgba(0,0,0,.15);
156 | }
157 |
158 | .loader {
159 | display: none;
160 | overflow: hidden;
161 | text-indent: -99em;
162 | position: absolute;
163 | height: 16px;
164 | width: 16px;
165 | background: url(/assets/images/loading.gif);
166 | }
167 |
168 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/controllers/Application.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import javax.inject.{ Inject, Singleton }
4 |
5 | import models._
6 | import play.api.data.Forms._
7 | import play.api.data._
8 | import play.api.mvc._
9 | import play.api.routing.JavaScriptReverseRouter
10 | import views._
11 |
12 | import scala.concurrent.{ ExecutionContext, Future }
13 |
14 | @Singleton
15 | class Application @Inject() (controllerComponents: ControllerComponents)
16 | extends AbstractController(controllerComponents) {
17 |
18 | // -- Authentication
19 |
20 | val loginForm = Form(
21 | tuple(
22 | "email" -> text,
23 | "password" -> text
24 | ) verifying (
25 | "Invalid email or password",
26 | result =>
27 | result match {
28 | case (email, password) => User.authenticate(email, password).isDefined
29 | }
30 | )
31 | )
32 |
33 | /**
34 | * Login page.
35 | */
36 | def login = Action.async { implicit request =>
37 | Future.successful(Ok(html.login(loginForm)))
38 | }
39 |
40 | /**
41 | * Handle login form submission.
42 | */
43 | def authenticate = Action.async { implicit request =>
44 | Future.successful(
45 | loginForm
46 | .bindFromRequest()
47 | .fold(
48 | formWithErrors => BadRequest(html.login(formWithErrors)),
49 | user =>
50 | Redirect(routes.Projects.index()).withSession("email" -> user._1)
51 | )
52 | )
53 | }
54 |
55 | /**
56 | * Logout and clean the session.
57 | */
58 | def logout = Action.async {
59 | Future.successful(
60 | Redirect(routes.Application.login()).withNewSession
61 | .flashing("success" -> "You've been logged out")
62 | )
63 | }
64 |
65 | // -- Javascript routing
66 |
67 | def javascriptRoutes = Action.async { implicit request =>
68 | import routes.javascript._
69 | Future.successful(
70 | Ok(
71 | JavaScriptReverseRouter("jsRoutes")(
72 | Projects.add,
73 | Projects.delete,
74 | Projects.rename,
75 | Projects.addGroup,
76 | Projects.deleteGroup,
77 | Projects.renameGroup,
78 | Projects.addUser,
79 | Projects.removeUser,
80 | Tasks.addFolder,
81 | Tasks.renameFolder,
82 | Tasks.deleteFolder,
83 | Tasks.index,
84 | Tasks.add,
85 | Tasks.update,
86 | Tasks.delete
87 | )
88 | ).as("text/javascript")
89 | )
90 | }
91 |
92 | }
93 |
94 | /**
95 | * Provide security features
96 | */
97 | trait Secured { self: BaseController =>
98 |
99 | /**
100 | * Retrieve the connected user email.
101 | */
102 | private def username(request: RequestHeader) = request.session.get("email")
103 |
104 | /**
105 | * Redirect to login if the user in not authorized.
106 | */
107 | private def onUnauthorized(request: RequestHeader) =
108 | Results.Redirect(routes.Application.login())
109 |
110 | // --
111 |
112 | /**
113 | * Action for authenticated users.
114 | */
115 | def IsAuthenticated(f: => String => Request[AnyContent] => Result) =
116 | Security.Authenticated(username, onUnauthorized) { user =>
117 | Action(request => f(user)(request))
118 | }
119 |
120 | /**
121 | * Check if the connected user is a member of this project.
122 | */
123 | def IsMemberOf(project: Long)(f: => String => Request[AnyContent] => Result) =
124 | IsAuthenticated { user => request =>
125 | if (Project.isMember(project, user)) {
126 | f(user)(request)
127 | } else {
128 | Results.Forbidden
129 | }
130 | }
131 |
132 | /**
133 | * Check if the connected user is a owner of this task.
134 | */
135 | def IsOwnerOf(task: Long)(f: => String => Request[AnyContent] => Result) =
136 | IsAuthenticated { user => request =>
137 | if (Task.isOwner(task, user)) {
138 | f(user)(request)
139 | } else {
140 | Results.Forbidden
141 | }
142 | }
143 |
144 | }
145 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/controllers/Projects.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import javax.inject.{ Inject, Singleton }
4 |
5 | import models._
6 | import play.api.data.Forms._
7 | import play.api.data._
8 | import play.api.mvc._
9 | import views._
10 |
11 | /**
12 | * Manage projects related operations.
13 | */
14 | @Singleton
15 | class Projects @Inject() (controllerComponents: ControllerComponents)
16 | extends AbstractController(controllerComponents)
17 | with Secured {
18 |
19 | /**
20 | * Display the dashboard.
21 | */
22 | def index = IsAuthenticated { username => _ =>
23 | User
24 | .findByEmail(username)
25 | .map { user =>
26 | Ok(
27 | html.dashboard(
28 | Project.findInvolving(username),
29 | Task.findTodoInvolving(username),
30 | user
31 | )
32 | )
33 | }
34 | .getOrElse(Forbidden)
35 | }
36 |
37 | // -- Projects
38 |
39 | /**
40 | * Add a project.
41 | */
42 | def add = IsAuthenticated { username => implicit request =>
43 | Form("group" -> nonEmptyText)
44 | .bindFromRequest()
45 | .fold(
46 | errors => BadRequest,
47 | folder =>
48 | Ok(
49 | views.html.projects.item(
50 | Project.create(NewProject(folder, "New project"), Seq(username))
51 | )
52 | )
53 | )
54 | }
55 |
56 | /**
57 | * Delete a project.
58 | */
59 | def delete(project: Long) = IsMemberOf(project) { username => _ =>
60 | Project.delete(project)
61 | Ok
62 | }
63 |
64 | /**
65 | * Rename a project.
66 | */
67 | def rename(project: Long) = IsMemberOf(project) { _ => implicit request =>
68 | Form("name" -> nonEmptyText)
69 | .bindFromRequest()
70 | .fold(
71 | errors => BadRequest,
72 | newName => {
73 | Project.rename(project, newName)
74 | Ok(newName)
75 | }
76 | )
77 | }
78 |
79 | // -- Project groups
80 |
81 | /**
82 | * Add a new project group.
83 | */
84 | def addGroup = IsAuthenticated { _ => _ =>
85 | Ok(html.projects.group("New group"))
86 | }
87 |
88 | /**
89 | * Delete a project group.
90 | */
91 | def deleteGroup(folder: String) = IsAuthenticated { _ => _ =>
92 | Project.deleteInFolder(folder)
93 | Ok
94 | }
95 |
96 | /**
97 | * Rename a project group.
98 | */
99 | def renameGroup(folder: String) = IsAuthenticated { _ => implicit request =>
100 | Form("name" -> nonEmptyText)
101 | .bindFromRequest()
102 | .fold(
103 | errors => BadRequest,
104 | newName => { Project.renameFolder(folder, newName); Ok(newName) }
105 | )
106 | }
107 |
108 | // -- Members
109 |
110 | /**
111 | * Add a project member.
112 | */
113 | def addUser(project: Long) = IsMemberOf(project) { _ => implicit request =>
114 | Form("user" -> nonEmptyText)
115 | .bindFromRequest()
116 | .fold(
117 | errors => BadRequest,
118 | user => { Project.addMember(project, user); Ok }
119 | )
120 | }
121 |
122 | /**
123 | * Remove a project member.
124 | */
125 | def removeUser(project: Long) = IsMemberOf(project) { _ => implicit request =>
126 | Form("user" -> nonEmptyText)
127 | .bindFromRequest()
128 | .fold(
129 | errors => BadRequest,
130 | user => { Project.removeMember(project, user); Ok }
131 | )
132 | }
133 |
134 | }
135 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/controllers/Tasks.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import javax.inject.{ Inject, Singleton }
4 |
5 | import models._
6 | import play.api.data.Forms._
7 | import play.api.data._
8 | import play.api.mvc._
9 | import views._
10 | import scala.concurrent.Future
11 |
12 | /**
13 | * Manage tasks related operations.
14 | */
15 | @Singleton
16 | class Tasks @Inject() (controllerComponents: ControllerComponents)
17 | extends AbstractController(controllerComponents)
18 | with Secured {
19 |
20 | /**
21 | * Display the tasks panel for this project.
22 | */
23 | def index(project: Long) = IsMemberOf(project) { _ => implicit request =>
24 | Project
25 | .findById(project)
26 | .map { p =>
27 | val tasks = Task.findByProject(project)
28 | val team = Project.membersOf(project)
29 | Ok(html.tasks.index(p, tasks, team))
30 | }
31 | .getOrElse(NotFound)
32 | }
33 |
34 | val taskForm = Form(
35 | tuple(
36 | "title" -> nonEmptyText,
37 | "dueDate" -> optional(date("MM/dd/yy")),
38 | "assignedTo" -> optional(text)
39 | )
40 | )
41 |
42 | // -- Tasks
43 |
44 | /**
45 | * Create a task in this project.
46 | */
47 | def add(project: Long, folder: String) = IsMemberOf(project) {
48 | _ => implicit request =>
49 | taskForm
50 | .bindFromRequest()
51 | .fold(
52 | errors => BadRequest,
53 | { case (title, dueDate, assignedTo) =>
54 | val task = Task.create(
55 | NewTask(folder, project, title, false, dueDate, assignedTo)
56 | )
57 | Ok(html.tasks.item(task))
58 | }
59 | )
60 | }
61 |
62 | /**
63 | * Update a task
64 | */
65 | def update(task: Long) = IsOwnerOf(task) { _ => implicit request =>
66 | Form("done" -> boolean)
67 | .bindFromRequest()
68 | .fold(
69 | errors => BadRequest,
70 | isDone => {
71 | Task.markAsDone(task, isDone)
72 | Ok
73 | }
74 | )
75 | }
76 |
77 | /**
78 | * Delete a task
79 | */
80 | def delete(task: Long) = IsOwnerOf(task) { _ => implicit request =>
81 | Task.delete(task)
82 | Ok
83 | }
84 |
85 | // -- Task folders
86 |
87 | /**
88 | * Add a new folder.
89 | */
90 | def addFolder = Action.async {
91 | Future.successful(Ok(html.tasks.folder("New folder")))
92 | }
93 |
94 | /**
95 | * Delete a full tasks folder.
96 | */
97 | def deleteFolder(project: Long, folder: String) = IsMemberOf(project) {
98 | _ => implicit request =>
99 | Task.deleteInFolder(project, folder)
100 | Ok
101 | }
102 |
103 | /**
104 | * Rename a tasks folder.
105 | */
106 | def renameFolder(project: Long, folder: String) = IsMemberOf(project) {
107 | _ => implicit request =>
108 | Form("name" -> nonEmptyText)
109 | .bindFromRequest()
110 | .fold(
111 | errors => BadRequest,
112 | newName => {
113 | Task.renameFolder(project, folder, newName)
114 | Ok(newName)
115 | }
116 | )
117 | }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/models/Project.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import scalikejdbc._
4 |
5 | case class ProjectMember(projectId: Long, userEmail: String)
6 |
7 | object ProjectMember extends SQLSyntaxSupport[ProjectMember] {
8 | def apply(syntax: SyntaxProvider[ProjectMember])(rs: WrappedResultSet) = {
9 | val p = syntax.resultName
10 | new ProjectMember(
11 | projectId = rs.long(p.projectId),
12 | userEmail = rs.string(p.userEmail)
13 | )
14 | }
15 | }
16 |
17 | case class NewProject(folder: String, name: String)
18 |
19 | case class Project(id: Long, folder: String, name: String)
20 |
21 | object Project extends SQLSyntaxSupport[Project] {
22 |
23 | def apply(syntax: SyntaxProvider[Project])(rs: WrappedResultSet) = {
24 | val p = syntax.resultName
25 | new Project(
26 | id = rs.long(p.id),
27 | folder = rs.string(p.folder),
28 | name = rs.string(p.name)
29 | )
30 | }
31 |
32 | private val p = Project.syntax("p")
33 | private val u = User.syntax("u")
34 | private val m = ProjectMember.syntax("m")
35 |
36 | private val auto = AutoSession
37 |
38 | def findById(id: Long)(implicit s: DBSession = auto): Option[Project] =
39 | withSQL {
40 | select.from(Project as p).where.eq(p.id, id)
41 | }.map(Project(p)).single.apply()
42 |
43 | def findInvolving(user: String)(implicit s: DBSession = auto): Seq[Project] =
44 | withSQL {
45 | select
46 | .from(Project as p)
47 | .join(ProjectMember as m)
48 | .on(p.id, m.projectId)
49 | .where
50 | .eq(m.userEmail, user)
51 | }.map(Project(p)).list.apply()
52 |
53 | def rename(id: Long, newName: String)(implicit s: DBSession = auto): Unit =
54 | applyUpdate {
55 | update(Project as p).set(p.name -> newName).where.eq(p.id, id)
56 | }
57 |
58 | def delete(id: Long)(implicit s: DBSession = auto): Unit = applyUpdate {
59 | deleteFrom(Project as p).where.eq(p.id, id)
60 | }
61 |
62 | def deleteInFolder(folder: String)(implicit s: DBSession = auto): Unit =
63 | applyUpdate {
64 | deleteFrom(Project as p).where.eq(p.folder, folder)
65 | }
66 |
67 | def renameFolder(folder: String, newName: String)(implicit
68 | s: DBSession = auto
69 | ): Unit = applyUpdate {
70 | update(Project as p).set(p.folder -> newName).where.eq(p.folder, folder)
71 | }
72 |
73 | def membersOf(project: Long)(implicit s: DBSession = auto): Seq[User] =
74 | withSQL {
75 | select
76 | .from(User as u)
77 | .join(ProjectMember as m)
78 | .on(m.userEmail, u.email)
79 | .where
80 | .eq(m.projectId, project)
81 | }.map(User(u)).list.apply()
82 |
83 | def addMember(project: Long, user: String)(implicit
84 | s: DBSession = auto
85 | ): Unit = applyUpdate {
86 | insert.into(ProjectMember).values(project, user)
87 | }
88 |
89 | def removeMember(project: Long, user: String)(implicit
90 | s: DBSession = auto
91 | ): Unit = applyUpdate {
92 | deleteFrom(ProjectMember as m).where
93 | .eq(m.projectId, project)
94 | .and
95 | .eq(m.userEmail, user)
96 | }
97 |
98 | def isMember(project: Long, user: String)(implicit
99 | s: DBSession = auto
100 | ): Boolean = withSQL {
101 | select(sqls"count(${u.email}) = 1 as is_member")
102 | .from(User as u)
103 | .join(ProjectMember as m)
104 | .on(m.userEmail, u.email)
105 | .where
106 | .eq(m.projectId, project)
107 | .and
108 | .eq(u.email, user)
109 | }.map(rs => rs.boolean("is_member").asInstanceOf[Boolean])
110 | .single
111 | .apply()
112 | .getOrElse(false)
113 |
114 | def create(project: NewProject, members: Seq[String])(implicit
115 | s: DBSession = auto
116 | ): Project = {
117 | // Insert the project
118 | val newId = sql"select next value for project_seq as v from dual"
119 | .map(_.long("v"))
120 | .single
121 | .apply()
122 | .get
123 | applyUpdate {
124 | insert.into(Project).values(newId, project.name, project.folder)
125 | }
126 | // Add members
127 | members foreach { email =>
128 | applyUpdate(insert.into(ProjectMember).values(newId, email))
129 | }
130 | Project(id = newId, name = project.name, folder = project.folder)
131 | }
132 |
133 | }
134 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/models/Task.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import java.util.Date
4 |
5 | import scalikejdbc._
6 |
7 | case class NewTask(
8 | folder: String,
9 | project: Long,
10 | title: String,
11 | done: Boolean,
12 | dueDate: Option[Date],
13 | assignedTo: Option[String]
14 | )
15 |
16 | case class Task(
17 | id: Long,
18 | folder: String,
19 | project: Long,
20 | title: String,
21 | done: Boolean,
22 | dueDate: Option[Date],
23 | assignedTo: Option[String]
24 | )
25 |
26 | object Task extends SQLSyntaxSupport[Task] {
27 |
28 | def apply(syntax: SyntaxProvider[Task])(rs: WrappedResultSet) = {
29 | val t = syntax.resultName
30 | new Task(
31 | id = rs.long(t.id),
32 | folder = rs.string(t.folder),
33 | project = rs.long(t.project),
34 | title = rs.string(t.title),
35 | done = rs.boolean(t.done),
36 | dueDate = rs.timestampOpt(t.dueDate),
37 | assignedTo = rs.stringOpt(t.assignedTo)
38 | )
39 | }
40 |
41 | def apply(t: SyntaxProvider[Task], p: SyntaxProvider[Project])(
42 | rs: WrappedResultSet
43 | ): (Task, Project) = (Task(t)(rs), Project(p)(rs))
44 |
45 | private val t = Task.syntax("t")
46 | private val p = Project.syntax("p")
47 | private val m = ProjectMember.syntax("m")
48 |
49 | private val auto = AutoSession
50 |
51 | def findById(id: Long)(implicit s: DBSession = auto): Option[Task] = withSQL {
52 | select.from(Task as t).where.eq(t.id, id)
53 | }.map(Task(t)).single.apply()
54 |
55 | def findTodoInvolving(
56 | user: String
57 | )(implicit s: DBSession = auto): Seq[(Task, Project)] = withSQL {
58 | select
59 | .from(Task as t)
60 | .join(ProjectMember as m)
61 | .on(m.projectId, t.project)
62 | .join(Project as p)
63 | .on(p.id, m.projectId)
64 | .where
65 | .append(sqls"${t.done} = false")
66 | .and
67 | .eq(m.userEmail, user)
68 | }.map(Task(t, p)).list.apply()
69 |
70 | def findByProject(project: Long)(implicit s: DBSession = auto): Seq[Task] =
71 | withSQL {
72 | select.from(Task as t).where.eq(t.project, project)
73 | }.map(Task(t)).list.apply()
74 |
75 | /**
76 | * Delete a task
77 | */
78 | def delete(id: Long)(implicit s: DBSession = auto): Unit = applyUpdate {
79 | deleteFrom(Task as t).where.eq(t.id, id)
80 | }
81 |
82 | def deleteInFolder(projectId: Long, folder: String)(implicit
83 | s: DBSession = auto
84 | ): Unit = applyUpdate {
85 | deleteFrom(Task as t).where
86 | .eq(t.project, projectId)
87 | .and
88 | .eq(t.folder, folder)
89 | }
90 |
91 | def markAsDone(taskId: Long, done: Boolean)(implicit
92 | s: DBSession = auto
93 | ): Unit = applyUpdate {
94 | update(Task as t).set(t.done -> done).where.eq(t.id, taskId)
95 | }
96 |
97 | def renameFolder(projectId: Long, folder: String, newName: String)(implicit
98 | s: DBSession = auto
99 | ): Unit = applyUpdate {
100 | update(Task as t)
101 | .set(t.folder -> newName)
102 | .where
103 | .eq(t.folder, folder)
104 | .and
105 | .eq(t.project, projectId)
106 | }
107 |
108 | def isOwner(task: Long, user: String)(implicit s: DBSession = auto): Boolean =
109 | withSQL {
110 | select(sqls"count(${t.id}) = 1 as v")
111 | .from(Task as t)
112 | .join(Project as p)
113 | .on(t.project, p.id)
114 | .join(ProjectMember as m)
115 | .on(m.projectId, p.id)
116 | .where
117 | .eq(m.userEmail, user)
118 | .and
119 | .eq(t.id, task)
120 | }.map(rs => rs.boolean("v").asInstanceOf[Boolean])
121 | .single
122 | .apply()
123 | .getOrElse(false)
124 |
125 | def create(task: NewTask)(implicit s: DBSession = auto): Task = {
126 | val newId = sql"select next value for task_seq as v from dual"
127 | .map(rs => rs.long("v"))
128 | .single
129 | .apply()
130 | .get
131 | applyUpdate {
132 | insert
133 | .into(Task)
134 | .values(
135 | newId,
136 | task.title,
137 | task.done,
138 | task.dueDate,
139 | task.assignedTo,
140 | task.project,
141 | task.folder
142 | )
143 | }
144 | Task(
145 | id = newId,
146 | folder = task.folder,
147 | project = task.project,
148 | title = task.title,
149 | done = task.done,
150 | dueDate = task.dueDate,
151 | assignedTo = task.assignedTo
152 | )
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/models/User.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import scalikejdbc._
4 |
5 | case class User(email: String, name: String, password: String)
6 |
7 | object User extends SQLSyntaxSupport[User] {
8 |
9 | override val tableName = "users"
10 | override val columns = Seq("email", "name", "password")
11 |
12 | def apply(syntax: SyntaxProvider[User])(rs: WrappedResultSet) = {
13 | val u = syntax.resultName
14 | new User(
15 | email = rs.string(u.email),
16 | name = rs.string(u.name),
17 | password = rs.string(u.password)
18 | )
19 | }
20 |
21 | private val u = User.syntax("u")
22 |
23 | private val auto = AutoSession
24 |
25 | def findByEmail(email: String)(implicit s: DBSession = auto): Option[User] =
26 | withSQL {
27 | select.from(User as u).where.eq(u.email, email)
28 | }.map(User(u)).single.apply()
29 |
30 | def findAll()(implicit s: DBSession = auto): Seq[User] = withSQL {
31 | select.from(User as u)
32 | }.map(User(u)).list.apply()
33 |
34 | def authenticate(email: String, password: String)(implicit
35 | s: DBSession = auto
36 | ): Option[User] = withSQL {
37 | select.from(User as u).where.eq(u.email, email).and.eq(u.password, password)
38 | }.map(User(u)).single.apply()
39 |
40 | def create(user: User)(implicit s: DBSession = auto): User = {
41 | applyUpdate {
42 | insert.into(User).values(user.email, user.name, user.password)
43 | }
44 | user
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/dashboard.scala.html:
--------------------------------------------------------------------------------
1 | @(projects: Seq[Project], todoTasks: Seq[(Task,Project)], user: User)
2 |
3 | @main(projects, user){
4 |
5 |
6 |
7 | Dashboard
8 | Tasks over all projects
9 |
10 |
11 |
12 |
13 | @todoTasks.groupBy(_._2).map {
14 | case (project, projectTasks) => {
15 |
16 |
20 |
21 | @projectTasks.map {
22 | case (task, _) => {
23 | @tasks.item(task, isEditable = false)
24 | }
25 | }
26 |
27 |
28 | }
29 | }
30 |
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/login.scala.html:
--------------------------------------------------------------------------------
1 | @(form: Form[(String,String)])(implicit flash: Flash)
2 |
3 |
4 |
5 | Zentasks
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 | @helper.form(routes.Application.authenticate()) {
16 |
17 | Sign in
18 |
19 | @form.globalError.map { error =>
20 |
21 | @error.message
22 |
23 | }
24 |
25 | @flash.get("success").map { message =>
26 |
27 | @message
28 |
29 | }
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | }
42 |
43 |
44 | Try guillaume@@sample.com with secret as password.
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/main.scala.html:
--------------------------------------------------------------------------------
1 | @(projects: Seq[Project], user: User)(body: Html)
2 |
3 |
4 |
5 | Zentasks
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Zentasks
18 |
19 | - @user.name (@user.email)
20 | -
21 | Logout
22 |
23 |
24 |
25 |
36 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/projects/group.scala.html:
--------------------------------------------------------------------------------
1 | @(group: String, projects: Seq[Project] = Nil)
2 |
3 |
4 |
5 | @group
6 | Loading
7 |
8 | - Options
9 | -
10 |
11 |
12 |
13 |
14 |
15 | @projects.map { project =>
16 | @views.html.projects.item(project)
17 | }
18 |
19 |
20 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/projects/item.scala.html:
--------------------------------------------------------------------------------
1 | @(project: Project)
2 |
3 |
4 | @project.name
5 |
6 | Loading
7 |
8 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/tasks/folder.scala.html:
--------------------------------------------------------------------------------
1 | @(folder: String, tasks: Seq[Task] = Nil)
2 |
3 |
4 |
18 |
19 | @tasks.map { task =>
20 | @views.html.tasks.item( task )
21 | }
22 |
23 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/tasks/index.scala.html:
--------------------------------------------------------------------------------
1 | @(project:Project, tasks: Seq[Task], team: Seq[User])
2 |
3 |
4 |
5 | @project.folder
6 | @project.name
7 |
8 |
9 | - Project's team
10 | -
11 |
12 |
Team mates
13 |
14 | @team.map { user =>
15 |
16 | - @user.name (@user.email)
17 | - Action
18 |
19 | }
20 |
21 |
Add a team mate
22 |
23 | @User.findAll().diff(team).map { user =>
24 |
25 | - @user.name (@user.email)
26 | - Action
27 |
28 | }
29 |
30 |
31 |
32 |
33 |
34 |
35 | @tasks.groupBy(_.folder).map {
36 | case (folder, tasks) => {
37 | @views.html.tasks.folder(folder, tasks)
38 | }
39 | }
40 | New folder
41 |
42 |
43 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/app/views/tasks/item.scala.html:
--------------------------------------------------------------------------------
1 | @(task: Task, isEditable: Boolean = true)
2 |
3 |
4 |
5 | @if(isEditable) {
6 |
7 | }
8 |
9 | @task.title
10 |
11 | @task.dueDate.map { date =>
12 |
13 | }
14 |
15 | @task.assignedTo.map { user =>
16 | @user
17 | }
18 |
19 | @if(isEditable) {
20 | Delete task
21 | Loading
22 | }
23 |
24 |
25 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/application.conf:
--------------------------------------------------------------------------------
1 | # Configuration
2 |
3 | application.name=Zentasks
4 |
5 | # Secret key
6 | # ~~~~~
7 | # The secret key is used to secure cryptographics functions.
8 | # If you deploy your application to several instances be sure to use the same key!
9 | application.secret="E27D^[_9W"
10 |
11 | # Database configuration
12 | # ~~~~~
13 | # You can declare as many datasources as you want.
14 | # By convention, the default datasource is named `default`
15 | db.default.driver=org.h2.Driver
16 | db.default.url="jdbc:h2:mem:play;DB_CLOSE_DELAY=-1"
17 | db.default.username=sa
18 | db.secondary.driver=org.h2.Driver
19 | db.secondary.url="jdbc:h2:mem:secondary;DB_CLOSE_DELAY=-1"
20 | db.default.fixtures.dev=[ "users.sql", "project.sql", "project_member.sql", "task.sql" ]
21 | db.default.fixtures.test=[ "users.sql", "project.sql", "project_member.sql", "task.sql" ]
22 | db.secondary.fixtures.test=[ "users.sql", "project.sql", "project_member.sql", "task.sql" ]
23 |
24 | #db.default.password=sa
25 |
26 | # ScalikeJDBC original configuration
27 | #db.default.poolInitialSize=10
28 | #db.default.poolMaxSize=10
29 | #db.default.poolValidationQuery=
30 |
31 | scalikejdbc.global.loggingSQLAndTime.enabled=true
32 | #scalikejdbc.global.loggingSQLAndTime.singleLineMode=true
33 | scalikejdbc.global.loggingSQLAndTime.logLevel=debug
34 | scalikejdbc.global.loggingSQLAndTime.warningEnabled=true
35 | scalikejdbc.global.loggingSQLAndTime.warningThresholdMillis=5
36 | scalikejdbc.global.loggingSQLAndTime.warningLogLevel=warn
37 |
38 | # You can disable the default DB plugin
39 | dbplugin=disabled
40 | evolutionplugin=disabled
41 |
42 | # Logger
43 | # ~~~~~
44 | # You can also configure logback (http://logback.qos.ch/), by providing a logger.xml file in the conf directory .
45 |
46 | # Root logger:
47 | logger.root=DEBUG
48 |
49 | # Logger used by the framework:
50 | logger.play=DEBUG
51 |
52 | # Logger provided to your application:
53 | logger.application=DEBUG
54 |
55 | play.modules.enabled += "org.flywaydb.play.PlayModule"
56 | play.modules.enabled += "scalikejdbc.PlayModule"
57 | play.modules.enabled += "scalikejdbc.PlayFixtureModule"
58 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/default/project.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project (id, name, folder) VALUES (1, 'Play 2.0', 'Play framework');
4 | INSERT INTO project (id, name, folder) VALUES (2, 'Play 1.2.4', 'Play framework');
5 | INSERT INTO project (id, name, folder) VALUES (3, 'Website', 'Play framework');
6 | INSERT INTO project (id, name, folder) VALUES (4, 'Secret project', 'Zenexity');
7 | INSERT INTO project (id, name, folder) VALUES (5, 'Playmate', 'Zenexity');
8 | INSERT INTO project (id, name, folder) VALUES (6, 'Things to do', 'Personal');
9 | INSERT INTO project (id, name, folder) VALUES (7, 'Play samples', 'Zenexity');
10 | INSERT INTO project (id, name, folder) VALUES (8, 'Private', 'Personal');
11 | INSERT INTO project (id, name, folder) VALUES (9, 'Private', 'Personal');
12 | INSERT INTO project (id, name, folder) VALUES (10, 'Private', 'Personal');
13 | INSERT INTO project (id, name, folder) VALUES (11, 'Private', 'Personal');
14 | ALTER SEQUENCE project_seq RESTART WITH 12;
15 |
16 | # --- !Downs
17 | ALTER SEQUENCE project_seq RESTART WITH 1;
18 | DELETE FROM project;
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/default/project_member.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'guillaume@sample.com');
4 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'maxime@sample.com');
5 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'sadek@sample.com');
6 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'erwan@sample.com');
7 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'guillaume@sample.com');
8 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'erwan@sample.com');
9 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'guillaume@sample.com');
10 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'maxime@sample.com');
11 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'guillaume@sample.com');
12 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'maxime@sample.com');
13 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'sadek@sample.com');
14 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'erwan@sample.com');
15 | INSERT INTO project_member (project_id, user_email) VALUES (5, 'maxime@sample.com');
16 | INSERT INTO project_member (project_id, user_email) VALUES (6, 'guillaume@sample.com');
17 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'guillaume@sample.com');
18 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'maxime@sample.com');
19 | INSERT INTO project_member (project_id, user_email) VALUES (8, 'maxime@sample.com');
20 | INSERT INTO project_member (project_id, user_email) VALUES (9, 'guillaume@sample.com');
21 | INSERT INTO project_member (project_id, user_email) VALUES (10, 'erwan@sample.com');
22 | INSERT INTO project_member (project_id, user_email) VALUES (11, 'sadek@sample.com');
23 |
24 | # --- !Downs
25 |
26 | DELETE FROM project_member;
27 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/default/task.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1000, 'Fix the documentation', FALSE, null, 'guillaume@sample.com', 1, 'Todo');
4 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1001, 'Prepare the beta release', FALSE, '2011-11-15 00:00:00.0', null, 1, 'Urgent');
5 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1002, 'Buy some milk', FALSE, null, null, 9, 'Todo');
6 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1003, 'Check 1.2.4-RC2', FALSE, '2011-11-18 00:00:00.0', 'guillaume@sample.com', 2, 'Todo');
7 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1004, 'Finish zentask integration', TRUE, '2011-11-15 00:00:00.0', 'maxime@sample.com', 7, 'Todo');
8 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1005, 'Release the secret project', FALSE, '2012-01-01 00:00:00.0', 'sadek@sample.com', 4, 'Todo');
9 | ALTER SEQUENCE task_seq RESTART WITH 1006;
10 |
11 | # --- !Downs
12 | ALTER SEQUENCE task_seq RESTART WITH 1000;
13 | DELETE FROM task;
14 |
15 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/default/users.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 | INSERT INTO users (email, name, password) VALUES ('guillaume@sample.com', 'Guillaume Bort', 'secret');
3 | INSERT INTO users (email, name, password) VALUES ('maxime@sample.com', 'Maxime Dantec', 'secret');
4 | INSERT INTO users (email, name, password) VALUES ('sadek@sample.com', 'Sadek Drobi', 'secret');
5 | INSERT INTO users (email, name, password) VALUES ('erwan@sample.com', 'Erwan Loisant', 'secret');
6 |
7 |
8 | # --- !Downs
9 | DELETE FROM users;
10 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/secondary/project.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project (id, name, folder) VALUES (1, 'Play 2.0', 'Play framework');
4 | INSERT INTO project (id, name, folder) VALUES (2, 'Play 1.2.4', 'Play framewor');
5 | INSERT INTO project (id, name, folder) VALUES (3, 'Website', 'Play framework');
6 | INSERT INTO project (id, name, folder) VALUES (4, 'Secret project', 'Zenexity');
7 | INSERT INTO project (id, name, folder) VALUES (5, 'Playmate', 'Zenexity');
8 | INSERT INTO project (id, name, folder) VALUES (6, 'Things to do', 'Personal');
9 | INSERT INTO project (id, name, folder) VALUES (7, 'Play samples', 'Zenexity');
10 | INSERT INTO project (id, name, folder) VALUES (8, 'Private', 'Personal');
11 | INSERT INTO project (id, name, folder) VALUES (9, 'Private', 'Personal');
12 | INSERT INTO project (id, name, folder) VALUES (10, 'Private', 'Personal');
13 | INSERT INTO project (id, name, folder) VALUES (11, 'Private', 'Personal');
14 | ALTER SEQUENCE project_seq RESTART WITH 12;
15 |
16 | # --- !Downs
17 | ALTER SEQUENCE project_seq RESTART WITH 1;
18 | DELETE FROM project;
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/secondary/project_member.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'guillaume@sample.com');
4 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'maxime@sample.com');
5 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'sadek@sample.com');
6 | INSERT INTO project_member (project_id, user_email) VALUES (1, 'erwan@sample.com');
7 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'guillaume@sample.com');
8 | INSERT INTO project_member (project_id, user_email) VALUES (2, 'erwan@sample.com');
9 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'guillaume@sample.com');
10 | INSERT INTO project_member (project_id, user_email) VALUES (3, 'maxime@sample.com');
11 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'guillaume@sample.com');
12 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'maxime@sample.com');
13 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'sadek@sample.com');
14 | INSERT INTO project_member (project_id, user_email) VALUES (4, 'erwan@sample.com');
15 | INSERT INTO project_member (project_id, user_email) VALUES (5, 'maxime@sample.com');
16 | INSERT INTO project_member (project_id, user_email) VALUES (6, 'guillaume@sample.com');
17 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'guillaume@sample.com');
18 | INSERT INTO project_member (project_id, user_email) VALUES (7, 'maxime@sample.com');
19 | INSERT INTO project_member (project_id, user_email) VALUES (8, 'maxime@sample.com');
20 | INSERT INTO project_member (project_id, user_email) VALUES (9, 'guillaume@sample.com');
21 | INSERT INTO project_member (project_id, user_email) VALUES (10, 'erwan@sample.com');
22 | INSERT INTO project_member (project_id, user_email) VALUES (11, 'sadek@sample.com');
23 |
24 | # --- !Downs
25 |
26 | DELETE FROM project_member;
27 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/secondary/task.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 |
3 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1000, 'Fix the documentation', FALSE, null, 'guillaume@sample.com', 1, 'Todo');
4 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1001, 'Prepare the beta release', FALSE, '2011-11-15 00:00:00.0', null, 1, 'Urgent');
5 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1002, 'Buy some milk', FALSE, null, null, 9, 'Todo');
6 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1003, 'Check 1.2.4-RC2', FALSE, '2011-11-18 00:00:00.0', 'guillaume@sample.com', 2, 'Todo');
7 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1004, 'Finish zentask integration', TRUE, '2011-11-15 00:00:00.0', 'maxime@sample.com', 7, 'Todo');
8 | INSERT INTO task (id, title, done, due_date, assigned_to, project, folder) VALUES (1005, 'Release the secret project', FALSE, '2012-01-01 00:00:00.0', 'sadek@sample.com', 4, 'Todo');
9 | ALTER SEQUENCE task_seq RESTART WITH 1006;
10 |
11 | # --- !Downs
12 | ALTER SEQUENCE task_seq RESTART WITH 1000;
13 | DELETE FROM task;
14 |
15 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/fixtures/secondary/users.sql:
--------------------------------------------------------------------------------
1 | # --- !Ups
2 | INSERT INTO users (email, name, password) VALUES ('guillaume@sample.com', 'Guillaume Bort', 'secret');
3 | INSERT INTO users (email, name, password) VALUES ('maxime@sample.com', 'Maxime Dantec', 'secret');
4 | INSERT INTO users (email, name, password) VALUES ('sadek@sample.com', 'Sadek Drobi', 'secret');
5 | INSERT INTO users (email, name, password) VALUES ('erwan@sample.com', 'Erwan Loisant', 'secret');
6 |
7 |
8 | # --- !Downs
9 | DELETE FROM users;
10 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/migration/default/V1__create_tables.sql:
--------------------------------------------------------------------------------
1 | drop table if exists users;
2 | create table users (
3 | email varchar(255) not null primary key,
4 | name varchar(255) not null,
5 | password varchar(255) not null
6 | );
7 |
8 | drop table if exists project;
9 | create table project (
10 | id bigint not null primary key,
11 | name varchar(255) not null,
12 | folder varchar(255) not null
13 | );
14 |
15 | drop sequence if exists project_seq;
16 | create sequence project_seq start with 1000;
17 |
18 | drop table if exists project_member;
19 | create table project_member (
20 | project_id bigint not null,
21 | user_email varchar(255) not null,
22 | foreign key(project_id) references project(id) on delete cascade,
23 | foreign key(user_email) references users(email) on delete cascade
24 | );
25 |
26 | drop table if exists task;
27 | create table task (
28 | id bigint not null primary key,
29 | title varchar(255) not null,
30 | done boolean,
31 | due_date timestamp,
32 | assigned_to varchar(255),
33 | project bigint not null,
34 | folder varchar(255),
35 | foreign key(assigned_to) references users(email) on delete set null,
36 | foreign key(project) references project(id) on delete cascade
37 | );
38 |
39 | drop sequence if exists task_seq;
40 | create sequence task_seq start with 1000;
41 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/db/migration/secondary/V1__create_tables.sql:
--------------------------------------------------------------------------------
1 | drop table if exists users;
2 | create table users (
3 | email varchar(255) not null primary key,
4 | name varchar(255) not null,
5 | password varchar(255) not null
6 | );
7 |
8 | drop table if exists project;
9 | create table project (
10 | id bigint not null primary key,
11 | name varchar(255) not null,
12 | folder varchar(255) not null
13 | );
14 |
15 | drop sequence if exists project_seq;
16 | create sequence project_seq start with 1000;
17 |
18 | drop table if exists project_member;
19 | create table project_member (
20 | project_id bigint not null,
21 | user_email varchar(255) not null,
22 | foreign key(project_id) references project(id) on delete cascade,
23 | foreign key(user_email) references users(email) on delete cascade
24 | );
25 |
26 | drop table if exists task;
27 | create table task (
28 | id bigint not null primary key,
29 | title varchar(255) not null,
30 | done boolean,
31 | due_date timestamp,
32 | assigned_to varchar(255),
33 | project bigint not null,
34 | folder varchar(255),
35 | foreign key(assigned_to) references users(email) on delete set null,
36 | foreign key(project) references project(id) on delete cascade
37 | );
38 |
39 | drop sequence if exists task_seq;
40 | create sequence task_seq start with 1000;
41 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/prod.conf:
--------------------------------------------------------------------------------
1 | include "application.conf"
2 | db.default.driver=org.postgresql.Driver
3 | db.default.url=${DATABASE_URL}
4 |
5 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/conf/routes:
--------------------------------------------------------------------------------
1 | # Routes
2 | # This file defines all application routes (Higher priority routes first)
3 | # ~~~~
4 |
5 | # The home page
6 | GET / controllers.Projects.index()
7 |
8 | # Authentication
9 | GET /login controllers.Application.login()
10 | POST /login controllers.Application.authenticate()
11 | GET /logout controllers.Application.logout()
12 |
13 | # Projects
14 | POST /projects controllers.Projects.add()
15 |
16 | POST /projects/groups controllers.Projects.addGroup()
17 | DELETE /projects/groups controllers.Projects.deleteGroup(group: String)
18 | PUT /projects/groups controllers.Projects.renameGroup(group: String)
19 |
20 | DELETE /projects/:project controllers.Projects.delete(project: Long)
21 | PUT /projects/:project controllers.Projects.rename(project: Long)
22 |
23 | POST /projects/:project/team controllers.Projects.addUser(project: Long)
24 | DELETE /projects/:project/team controllers.Projects.removeUser(project: Long)
25 |
26 | # Tasks
27 | GET /projects/:project/tasks controllers.Tasks.index(project: Long)
28 | POST /projects/:project/tasks controllers.Tasks.add(project: Long, folder: String)
29 | PUT /tasks/:task controllers.Tasks.update(task: Long)
30 | DELETE /tasks/:task controllers.Tasks.delete(task: Long)
31 |
32 | POST /tasks/folder controllers.Tasks.addFolder()
33 | DELETE /projects/:project/tasks/folder controllers.Tasks.deleteFolder(project: Long, folder: String)
34 | PUT /project/:project/tasks/folder controllers.Tasks.renameFolder(project: Long, folder: String)
35 |
36 | # Javascript routing
37 | GET /assets/javascripts/routes controllers.Application.javascriptRoutes()
38 |
39 | # Map static resources from the /public folder to the /public path
40 | GET /assets/*file controllers.Assets.at(path="/public", file)
41 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.11
2 |
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/arrow-left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/arrow-left.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/breadcrumb-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/breadcrumb-1.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/breadcrumb-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/breadcrumb-2.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/breadcrumb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/breadcrumb.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/addRemove.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/addRemove.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/clock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/clock.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/delete.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/drawer.folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/drawer.folder.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/folder.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/home.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/options.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/user.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/icons/user2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/icons/user2.png
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/loading.gif
--------------------------------------------------------------------------------
/scalikejdbc-play-initializer/test/zentasks/public/images/pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/scalikejdbc/scalikejdbc-play-support/f2b16fcc53fd22c0bf1a278428c252b907c1398d/scalikejdbc-play-initializer/test/zentasks/public/images/pattern.png
--------------------------------------------------------------------------------
/windows_test_filter.sbt:
--------------------------------------------------------------------------------
1 | val excludeTestsIfWindows = Set(
2 | // TODO
3 | // new line char?
4 | "scalikejdbc.play.FixtureSpec",
5 | )
6 |
7 | ThisBuild / Test / testOptions ++= {
8 | if (scala.util.Properties.isWin) {
9 | Seq(Tests.Exclude(excludeTestsIfWindows))
10 | } else {
11 | Nil
12 | }
13 | }
14 |
--------------------------------------------------------------------------------