persistent, shareable practice chapter URLs
parent
e28b563d3e
commit
ecd1e3f644
|
@ -24,14 +24,20 @@ object Practice extends LilaController {
|
|||
}
|
||||
|
||||
def show(sectionId: String, studySlug: String, studyId: String) = Open { implicit ctx =>
|
||||
OptionFuResult(env.api.getStudyWithFirstOngoingChapter(ctx.me, studyId)) { us =>
|
||||
analysisJson(us) map {
|
||||
case (analysisJson, studyJson) => Ok(html.practice.show(us, lila.practice.JsonView.JsData(
|
||||
study = studyJson,
|
||||
analysis = analysisJson,
|
||||
practice = lila.practice.JsonView(us))))
|
||||
}
|
||||
} map NoCache
|
||||
OptionFuResult(env.api.getStudyWithFirstOngoingChapter(ctx.me, studyId))(showUserPractice)
|
||||
}
|
||||
|
||||
def showChapter(sectionId: String, studySlug: String, studyId: String, chapterId: String) = Open { implicit ctx =>
|
||||
OptionFuResult(env.api.getStudyWithChapter(ctx.me, studyId, chapterId))(showUserPractice)
|
||||
}
|
||||
|
||||
private def showUserPractice(us: lila.practice.UserStudy)(implicit ctx: Context) = analysisJson(us) map {
|
||||
case (analysisJson, studyJson) => NoCache(Ok(
|
||||
html.practice.show(us, lila.practice.JsonView.JsData(
|
||||
study = studyJson,
|
||||
analysis = analysisJson,
|
||||
practice = lila.practice.JsonView(us)))
|
||||
))
|
||||
}
|
||||
|
||||
def chapter(studyId: String, chapterId: String) = Open { implicit ctx =>
|
||||
|
@ -45,7 +51,7 @@ object Practice extends LilaController {
|
|||
}
|
||||
|
||||
private def analysisJson(us: UserStudy)(implicit ctx: Context): Fu[(JsObject, JsObject)] = us match {
|
||||
case UserStudy(_, _, chapters, WithChapter(study, chapter)) =>
|
||||
case UserStudy(_, _, chapters, WithChapter(study, chapter), _) =>
|
||||
val pov = UserAnalysis.makePov(chapter.root.fen.value.some, chapter.setup.variant)
|
||||
Env.round.jsonView.userAnalysisJson(pov, ctx.pref, chapter.setup.orientation, owner = false) zip
|
||||
studyEnv.jsonView(study, chapters, chapter, ctx.me) map {
|
||||
|
|
|
@ -160,6 +160,7 @@ GET /features controllers.Plan.features
|
|||
# Practice
|
||||
GET /practice controllers.Practice.index
|
||||
GET /practice/:sectionId/:studySlug/:studyId controllers.Practice.show(sectionId: String, studySlug: String, studyId: String)
|
||||
GET /practice/:sectionId/:studySlug/:studyId/:chapterId controllers.Practice.showChapter(sectionId: String, studySlug: String, studyId: String, chapterId: String)
|
||||
POST /practice/complete/:chapterId/:moves controllers.Practice.complete(chapterId: String, moves: Int)
|
||||
GET /practice/$studyId<\w{8}>/$chapterId<\w{8}> controllers.Practice.chapter(studyId: String, chapterId: String)
|
||||
GET /practice/config controllers.Practice.config
|
||||
|
|
|
@ -26,6 +26,7 @@ object JsonView {
|
|||
|
||||
def apply(us: UserStudy) = Json.obj(
|
||||
"study" -> us.practiceStudy,
|
||||
"url" -> us.url,
|
||||
"completion" -> JsObject {
|
||||
us.practiceStudy.chapters.flatMap { c =>
|
||||
us.practice.progress.chapters collectFirst {
|
||||
|
|
|
@ -40,8 +40,8 @@ final class PracticeApi(
|
|||
study = rawSc.study.rewindTo(rawSc.chapter).withoutMembers,
|
||||
chapter = rawSc.chapter.withoutChildren)
|
||||
practiceStudy <- up.structure study sc.study.id
|
||||
if up.structure hasStudy sc.study.id
|
||||
} yield UserStudy(up, practiceStudy, chapters, sc)
|
||||
section <- up.structure findSection sc.study.id
|
||||
} yield UserStudy(up, practiceStudy, chapters, sc, section)
|
||||
|
||||
object config {
|
||||
def get = configStore.get map (_ | PracticeConfig.empty)
|
||||
|
|
|
@ -13,6 +13,15 @@ case class PracticeStructure(
|
|||
s.id -> s
|
||||
}.toMap
|
||||
|
||||
lazy val sectionsByStudyIds: Map[Study.Id, PracticeSection] =
|
||||
sections.flatMap { sec =>
|
||||
sec.studies.map { stu =>
|
||||
stu.id -> sec
|
||||
}
|
||||
}.toMap
|
||||
|
||||
def findSection(id: Study.Id): Option[PracticeSection] = sectionsByStudyIds get id
|
||||
|
||||
def hasStudy(id: Study.Id) = studiesByIds contains id
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,14 @@ case class UserPractice(
|
|||
}
|
||||
|
||||
case class UserStudy(
|
||||
practice: UserPractice,
|
||||
practiceStudy: PracticeStudy,
|
||||
chapters: List[Chapter.Metadata],
|
||||
study: Study.WithChapter)
|
||||
practice: UserPractice,
|
||||
practiceStudy: PracticeStudy,
|
||||
chapters: List[Chapter.Metadata],
|
||||
study: Study.WithChapter,
|
||||
section: PracticeSection) {
|
||||
|
||||
def url = s"/practice/${section.id}/${practiceStudy.slug}/${study.study.id}"
|
||||
}
|
||||
|
||||
case class Completion(done: Int, total: Int) {
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ module.exports = function(root, studyData, data) {
|
|||
nbMoves(0);
|
||||
won(false);
|
||||
comment(makeComment(root.tree.root));
|
||||
history.replaceState(null, studyData.chapter.name, data.url + '/' + studyData.chapter.id);
|
||||
};
|
||||
onLoad();
|
||||
|
||||
|
|
Loading…
Reference in New Issue