setting to make study chat accessible to all

pull/3144/head
Thibault Duplessis 2017-06-10 16:09:00 +02:00
parent ac502624e6
commit 4bd609aeff
10 changed files with 41 additions and 37 deletions

View File

@ -284,7 +284,8 @@ object BSONHandlers {
def reads(r: Reader) = Settings(
computer = r.get[UserSelection]("computer"),
explorer = r.get[UserSelection]("explorer"),
cloneable = r.getO[UserSelection]("cloneable") | UserSelection.Everyone
cloneable = r.getO[UserSelection]("cloneable") | Settings.init.cloneable,
chat = r.getO[UserSelection]("chat") | Settings.init.chat
)
private val writer = Macros.writer[Settings]
def writes(w: Writer, s: Settings) = writer write s

View File

@ -31,7 +31,8 @@ final class JsonView(
studyWrites.writes(study) ++ Json.obj(
"liked" -> liked,
"features" -> Json.obj(
"cloneable" -> allowed(study.settings.cloneable)
"cloneable" -> allowed(study.settings.cloneable),
"chat" -> allowed(study.settings.chat)
),
"chapters" -> chapters.map(chapterMetadataWrites.writes),
"chapter" -> Json.obj(

View File

@ -5,7 +5,8 @@ import lila.user.User
case class Settings(
computer: Settings.UserSelection,
explorer: Settings.UserSelection,
cloneable: Settings.UserSelection
cloneable: Settings.UserSelection,
chat: Settings.UserSelection
)
object Settings {
@ -13,7 +14,8 @@ object Settings {
val init = Settings(
computer = UserSelection.Everyone,
explorer = UserSelection.Everyone,
cloneable = UserSelection.Everyone
cloneable = UserSelection.Everyone,
chat = UserSelection.Contributor
)
sealed trait UserSelection {

View File

@ -92,11 +92,10 @@ private final class Socket(
"w" -> who(uid)
), noMessadata)
case ReloadMembers(members) => notifyVersion("members", members, noMessadata)
case ReloadChapters(chapters) => notifyVersion("chapters", chapters, noMessadata)
case ReloadAll => notifyVersion("reload", JsNull, noMessadata)
case ChangeChapter(uid) => notifyVersion("changeChapter", Json.obj(
"w" -> who(uid)
), noMessadata)
@ -257,7 +256,6 @@ private object Socket {
case class DeleteNode(position: Position.Ref, uid: Uid)
case class Promote(position: Position.Ref, toMainline: Boolean, uid: Uid)
case class SetPath(position: Position.Ref, uid: Uid)
case class ReloadMembers(members: StudyMembers)
case class SetShapes(position: Position.Ref, shapes: Shapes, uid: Uid)
case class SetComment(position: Position.Ref, comment: Comment, uid: Uid)
case class DeleteComment(position: Position.Ref, commentId: Comment.Id, uid: Uid)

View File

@ -28,7 +28,7 @@ case class Study(
def isMember(id: User.ID) = members contains id
def canChat = isMember _
def canChat(id: User.ID) = Settings.UserSelection.allows(settings.chat, this, id.some)
def canContribute(id: User.ID) = isOwner(id) || members.get(id).exists(_.canContribute)
@ -120,7 +120,8 @@ object Study {
visibility: String,
computer: String,
explorer: String,
cloneable: String
cloneable: String,
chat: String
) {
import Settings._
def vis = Visibility.byKey get visibility getOrElse Visibility.Public
@ -128,7 +129,8 @@ object Study {
comp <- UserSelection.byKey get computer
expl <- UserSelection.byKey get explorer
clon <- UserSelection.byKey get cloneable
} yield Settings(comp, expl, clon)
chat <- UserSelection.byKey get chat
} yield Settings(comp, expl, clon, chat)
}
case class WithChapter(study: Study, chapter: Chapter)

View File

@ -230,18 +230,14 @@ final class StudyApi(
bus.publish(lila.hub.actorApi.study.StudyMemberLostWriteAccess(userId, studyId.value), 'study)
}
studyRepo.setRole(study, userId, role) >>-
reloadMembers(study) >>-
lightStudyCache.refresh(studyId)
onMembersChange(study)
}
}
def invite(byUserId: User.ID, studyId: Study.Id, username: String, socket: ActorRef, onError: String => Unit) = sequenceStudy(studyId) { study =>
inviter(byUserId, study, username, socket).addEffects(
err => onError(err.getMessage),
_ => {
reloadMembers(study)
indexStudy(study)
}
_ => onMembersChange(study)
)
}
@ -249,8 +245,14 @@ final class StudyApi(
study.isMember(userId) ?? {
if (study.isPublic && study.canContribute(userId))
bus.publish(lila.hub.actorApi.study.StudyMemberLostWriteAccess(userId, studyId.value), 'study)
studyRepo.removeMember(study, userId) >>- lightStudyCache.refresh(studyId)
} >>- reloadMembers(study) >>- indexStudy(study)
studyRepo.removeMember(study, userId)
} >>- onMembersChange(study)
}
private def onMembersChange(study: Study) = {
lightStudyCache.refresh(study.id)
sendTo(study, Socket.ReloadAll)
indexStudy(study)
}
def setShapes(userId: User.ID, studyId: Study.Id, position: Position.Ref, shapes: Shapes, uid: Uid) = sequenceStudy(studyId) { study =>
@ -499,13 +501,6 @@ final class StudyApi(
private def reloadUid(study: Study, uid: Uid) =
sendTo(study, Socket.ReloadUid(uid))
private def reloadMembers(study: Study) =
studyRepo.membersById(study.id).foreach {
_ foreach { members =>
sendTo(study, Socket.ReloadMembers(members))
}
}
private def reloadChapters(study: Study) =
chapterRepo.orderedMetadataByStudy(study.id).foreach { chapters =>
sendTo(study, Socket.ReloadChapters(chapters))

View File

@ -388,6 +388,9 @@ div.underboard .notif.error {
margin: 0;
padding: 20px;
}
.study_overboard .align-left {
text-align: left;
}
.study_overboard .form .editor {
margin: -30px 0 30px 0;
}

View File

@ -90,7 +90,7 @@ module.exports = function(data, ctrl, tagTypes, practiceData) {
var configureAnalysis = function() {
if (ctrl.embed) return;
lichess.pubsub.emit('chat.writeable')(!!members.myMember());
lichess.pubsub.emit('chat.writeable')(data.features.chat);
var computer = data.chapter.features.computer || data.chapter.practice;
if (!computer) ctrl.getCeval().enabled(false);
ctrl.getCeval().allowed(computer);
@ -316,11 +316,6 @@ module.exports = function(data, ctrl, tagTypes, practiceData) {
if (vm.behind && d.w && d.w.u === ctrl.userId) resync();
else if (vm.behind === false) xhrReload();
},
members: function(d) {
members.update(d);
configureAnalysis();
m.redraw();
},
chapters: function(d) {
chapters.list(d);
m.redraw();

View File

@ -61,14 +61,15 @@ module.exports = {
},
content: [
m('h2', (isNew ? 'Create' : 'Edit') + ' study'),
m('form.material.form', {
m('form.material.form.align-left', {
onsubmit: function(e) {
ctrl.save({
name: e.target.querySelector('#study-name').value,
visibility: e.target.querySelector('#study-visibility').value,
computer: e.target.querySelector('#study-computer').value,
explorer: e.target.querySelector('#study-explorer').value,
cloneable: e.target.querySelector('#study-cloneable').value
cloneable: e.target.querySelector('#study-cloneable').value,
chat: e.target.querySelector('#study-chat').value
}, isNew);
e.stopPropagation();
return false;
@ -115,6 +116,12 @@ module.exports = {
choices: userSelectionChoices,
selected: data.settings.explorer
})),
m('div.game.form-group.half', select({
key: 'chat',
name: 'Chat',
choices: userSelectionChoices,
selected: data.settings.chat
})),
]),
dialog.button(isNew ? 'Start' : 'Save')
]),

View File

@ -9,7 +9,7 @@ import { userLink, bind } from './util';
const whisperRegex = /^\/w(?:hisper)?\s/;
export default function(ctrl: Ctrl): VNode[] {
export default function(ctrl: Ctrl): Array<VNode | undefined> {
if (!ctrl.vm.enabled) return [];
const scrollCb = (vnode: VNode) => {
const el = vnode.elm as HTMLElement
@ -37,10 +37,11 @@ export default function(ctrl: Ctrl): VNode[] {
];
const presets = presetView(ctrl.preset);
if (presets) vnodes.push(presets)
return vnodes
return vnodes;
}
function renderInput(ctrl: Ctrl) {
function renderInput(ctrl: Ctrl): VNode | undefined {
if (!ctrl.vm.writeable) return;
if ((ctrl.data.loginRequired && !ctrl.data.userId) || ctrl.data.restricted)
return h('input.lichess_say', {
attrs: {
@ -50,7 +51,6 @@ function renderInput(ctrl: Ctrl) {
});
let placeholder: string;
if (ctrl.vm.timeout) placeholder = 'You have been timed out.';
else if (!ctrl.vm.writeable) placeholder = 'Invited members only.';
else placeholder = ctrl.trans(ctrl.vm.placeholderKey);
return h('input.lichess_say', {
attrs: {