diff --git a/modules/study/src/main/StudyApi.scala b/modules/study/src/main/StudyApi.scala index 9192f3041284..900582422241 100644 --- a/modules/study/src/main/StudyApi.scala +++ b/modules/study/src/main/StudyApi.scala @@ -771,22 +771,24 @@ final class StudyApi( def editStudy(studyId: StudyId, data: Study.Data)(who: Who) = sequenceStudy(studyId): study => - canActAsOwner(study, who.u).flatMap { asOwner => - asOwner.option(data.settings).so { settings => - val newStudy = study.copy( - name = Study.toName(data.name), - flair = data.flair.flatMap(flairApi.find), - settings = settings, - visibility = data.vis, - description = settings.description.option { - study.description.filter(_.nonEmpty) | "-" - } - ) - (newStudy != study).so { - studyRepo.updateSomeFields(newStudy).andDo(sendTo(study.id)(_.reloadAll)).andDo(indexStudy(study)) - } - } - } + canActAsOwner(study, who.u).flatMap: asOwner => + asOwner + .option(data.settings) + .so: settings => + val newStudy = study + .copy( + name = Study.toName(data.name), + flair = data.flair.flatMap(flairApi.find), + settings = settings, + visibility = data.vis, + description = settings.description.option: + study.description.filter(_.nonEmpty) | "-" + ) + (newStudy != study).so: + studyRepo + .updateSomeFields(newStudy) + .andDo(sendTo(study.id)(_.reloadAll)) + .andDo(indexStudy(study)) def delete(study: Study) = sequenceStudy(study.id): study => diff --git a/modules/study/src/main/StudyRepo.scala b/modules/study/src/main/StudyRepo.scala index 7dbecd8b862a..d2e95128ff03 100644 --- a/modules/study/src/main/StudyRepo.scala +++ b/modules/study/src/main/StudyRepo.scala @@ -125,18 +125,19 @@ final class StudyRepo(private[study] val coll: AsyncColl)(using .void def updateSomeFields(s: Study): Funit = + import toBSONValueOption.given coll: _.update .one( $id(s.id), - $set( - "position" -> s.position, - "name" -> s.name, + $setsAndUnsets( + "position" -> s.position.some, + "name" -> s.name.some, "flair" -> s.flair, - "settings" -> s.settings, - "visibility" -> s.visibility, - "description" -> ~s.description, - "updatedAt" -> nowInstant + "settings" -> s.settings.some, + "visibility" -> s.visibility.some, + "description" -> s.description, + "updatedAt" -> nowInstant.some ) ) .void diff --git a/ui/analyse/src/study/studyForm.ts b/ui/analyse/src/study/studyForm.ts index bf9ccf360018..fa04021cb3a8 100644 --- a/ui/analyse/src/study/studyForm.ts +++ b/ui/analyse/src/study/studyForm.ts @@ -2,6 +2,7 @@ import { VNode } from 'snabbdom'; import * as licon from 'common/licon'; import { prop } from 'common'; import { snabDialog } from 'common/dialog'; +import flairPickerLoader from 'common/flairPicker'; import { bindSubmit, bindNonPassive, onInsert, looseH as h } from 'common/snabbdom'; import { emptyRedButton } from '../view/util'; import { StudyData } from './interfaces'; @@ -123,7 +124,7 @@ export function view(ctrl: StudyForm): VNode { h( 'details.form-control.emoji-details', { - hook: onInsert(el => flairPicker(el)), + hook: onInsert(el => flairPickerLoader(el)), }, [ h('summary.button.button-metal.button-no-upper', [ @@ -141,6 +142,7 @@ export function view(ctrl: StudyForm): VNode { }), ], ), + data.flair && h(removeEmojiButton, 'Delete'), ]), h('div.form-group', [ h('label.form-label', { attrs: { for: 'study-name' } }, ctrl.trans.noarg('name')), @@ -272,29 +274,4 @@ export function view(ctrl: StudyForm): VNode { }); } -// TODO FIXME -// copied from ui/bits/src/load/flairPicker.ts -function flairPicker(element: HTMLElement) { - const parent = $(element).parent(); - const close = () => element.removeAttribute('open'); - const onEmojiSelect = (i?: { id: string; src: string }) => { - parent.find('input[name="flair"]').val(i?.id ?? ''); - parent.find('.uflair').remove(); - if (i) parent.find('.flair-container').append(''); - close(); - }; - parent.find('.emoji-remove').on('click', e => { - e.preventDefault(); - onEmojiSelect(); - $(e.target).remove(); - }); - $(element).on('toggle', () => - site.asset.loadEsm('bits.flairPicker', { - init: { - element: element.querySelector('.flair-picker')!, - close, - onEmojiSelect, - }, - }), - ); -} +const removeEmojiButton = emptyRedButton + '.text.emoji-remove'; diff --git a/ui/bits/src/bits.account.ts b/ui/bits/src/bits.account.ts index 9dab290051bb..411af0f1d483 100644 --- a/ui/bits/src/bits.account.ts +++ b/ui/bits/src/bits.account.ts @@ -1,11 +1,11 @@ import * as licon from 'common/licon'; import * as xhr from 'common/xhr'; import { addPasswordVisibilityToggleListener } from 'common/password'; -import flairPicker from './load/flairPicker'; +import flairPickerLoader from 'common/flairPicker'; site.load.then(() => { $('.emoji-details').each(function (this: HTMLElement) { - flairPicker(this); + flairPickerLoader(this); }); addPasswordVisibilityToggleListener(); diff --git a/ui/bits/src/bits.dailyFeed.ts b/ui/bits/src/bits.dailyFeed.ts index ece122742c3d..868202ec6206 100644 --- a/ui/bits/src/bits.dailyFeed.ts +++ b/ui/bits/src/bits.dailyFeed.ts @@ -1,5 +1,5 @@ -import flairPicker from './load/flairPicker'; +import flairPickerLoader from 'common/flairPicker'; $('.emoji-details').each(function (this: HTMLElement) { - flairPicker(this); + flairPickerLoader(this); }); diff --git a/ui/bits/src/bits.team.ts b/ui/bits/src/bits.team.ts index 4a19881a0a38..376f70ea1288 100644 --- a/ui/bits/src/bits.team.ts +++ b/ui/bits/src/bits.team.ts @@ -1,5 +1,5 @@ import * as xhr from 'common/xhr'; -import flairPicker from './load/flairPicker'; +import flairPickerLoader from 'common/flairPicker'; interface TeamOpts { id: string; @@ -29,5 +29,5 @@ $('button.explain').on('click', e => { }); $('.emoji-details').each(function (this: HTMLElement) { - flairPicker(this); + flairPickerLoader(this); }); diff --git a/ui/bits/src/load/flairPicker.ts b/ui/common/src/flairPicker.ts similarity index 91% rename from ui/bits/src/load/flairPicker.ts rename to ui/common/src/flairPicker.ts index 27de0c373e89..2c041396c62a 100644 --- a/ui/bits/src/load/flairPicker.ts +++ b/ui/common/src/flairPicker.ts @@ -1,4 +1,4 @@ -export default function flairPicker(element: HTMLElement) { +export default function flairPickerLoader(element: HTMLElement) { const parent = $(element).parent(); const close = () => element.removeAttribute('open'); const onEmojiSelect = (i?: { id: string; src: string }) => {