Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feature/add lecture time change #1168

Open
wants to merge 85 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
84d18ee
started wit hrefactor of course management
mono424 Aug 23, 2023
eb2fcd7
Merge branch 'dev' into improvement/refactor-course-mgmt
mono424 Aug 28, 2023
429ad67
add dao & route
mono424 Aug 28, 2023
d1ea050
update route
mono424 Aug 28, 2023
8aa4d69
started wit hfetching
mono424 Aug 28, 2023
db3f3bb
Add changeset abstraction
mono424 Aug 28, 2023
0225a59
cleanup file
mono424 Aug 28, 2023
29c0977
remove get all streams again, as there is AdminJson method
mono424 Aug 28, 2023
0f32725
Its rendering
mono424 Aug 28, 2023
797d00d
further dev :S
mono424 Aug 28, 2023
17f460a
added some directive
mono424 Aug 28, 2023
ca9c567
little fixes
mono424 Aug 28, 2023
246fa48
...
mono424 Aug 28, 2023
1e66fc9
... no idea...
mono424 Aug 28, 2023
e36890d
right path i guess
mono424 Aug 29, 2023
fcf15c2
changeset working except video sections
mono424 Aug 29, 2023
e576712
fix discard files
mono424 Aug 29, 2023
c25956a
save from laptop
mono424 Sep 3, 2023
5102141
Add changeset doku
mono424 Sep 3, 2023
7518b5d
make private works like charm
mono424 Sep 3, 2023
8416d26
changing works pretty well
mono424 Sep 3, 2023
8afb2b9
add video upload
mono424 Sep 3, 2023
f4a005f
add series update
mono424 Sep 3, 2023
a258dc5
ported transcoding
mono424 Sep 3, 2023
184b0aa
add readme and lecture hall select
mono424 Sep 5, 2023
81e783d
more description
mono424 Sep 5, 2023
cffbf3e
simplified lecture hall set
mono424 Sep 5, 2023
5548883
Merge branch 'dev' into improvement/refactor-course-mgmt
mono424 Sep 5, 2023
2db8643
linter
mono424 Sep 5, 2023
098b2d5
more fixes
mono424 Sep 5, 2023
91f80cf
:)
mono424 Sep 5, 2023
b224222
add attachments
mono424 Sep 10, 2023
0a65347
:)
mono424 Sep 10, 2023
1b97d1a
Merge branch 'dev' into improvement/refactor-course-mgmt
mono424 Sep 11, 2023
74b180d
add video sections to admin streams
mono424 Sep 11, 2023
85a17f5
main functionality
mono424 Sep 11, 2023
f21f0db
using fetch wrtappers
mono424 Sep 14, 2023
0b939c6
moved uploadFile and postFormData
mono424 Sep 14, 2023
09105a4
Merge branch 'dev' into improvement/refactor-course-sections
mono424 Sep 14, 2023
df179a7
fix linteer
mono424 Sep 14, 2023
4408da4
Impl. Feedback
mono424 Sep 14, 2023
394218e
add video sections to admin streams
mono424 Sep 11, 2023
61b36b5
main functionality
mono424 Sep 11, 2023
f78c548
using fetch wrtappers
mono424 Sep 14, 2023
74cd080
moved uploadFile and postFormData
mono424 Sep 14, 2023
a6cf16e
version workers with tag (#1157)
joschahenningsen Sep 13, 2023
f1ad4a0
fix linteer
mono424 Sep 14, 2023
bf11272
Merge branch 'improvement/refactor-course-sections' of github.com:jos…
mono424 Sep 14, 2023
859555c
fix delete lecture
mono424 Sep 14, 2023
d375cf7
reenable page reload on create
mono424 Sep 14, 2023
8755076
Merge branch 'improvement/refactor-course-mgmt' into improvement/refa…
mono424 Sep 15, 2023
1b1b1ab
some linter fixes
mono424 Sep 15, 2023
b996d07
fix merge complications
mono424 Sep 15, 2023
7bb8870
fix changeset; adding onchange listener
mono424 Sep 15, 2023
8c132ec
fixed adding sections
mono424 Sep 15, 2023
6c57fa0
added directives
mono424 Sep 15, 2023
8090778
fix typo
mono424 Sep 15, 2023
c810b4c
improved directives
mono424 Sep 15, 2023
96ba056
design improvement
mono424 Sep 15, 2023
44d2031
fixed creating and deleting
mono424 Sep 15, 2023
2ebd58a
add sections fixed
mono424 Sep 15, 2023
738087a
cleanup
mono424 Sep 15, 2023
f11c393
:)
mono424 Sep 15, 2023
0beec3a
fix alpine js error issues
mono424 Sep 15, 2023
7e63051
remoev console log
mono424 Sep 15, 2023
a50db12
nested :)
mono424 Sep 15, 2023
0da5f03
remove console log
mono424 Sep 15, 2023
6a181d2
lint-fix
mono424 Sep 15, 2023
cc9f2d0
Merge branch 'dev' into improvement/refactor-course-sections
mono424 Sep 21, 2023
34248ac
started with inputs
mono424 Sep 21, 2023
3a5743c
added some thorttleing
mono424 Sep 27, 2023
233eff1
added throttling
mono424 Sep 27, 2023
6003511
fix start date comparator
mono424 Sep 27, 2023
fbe9497
fix end date related to start date
mono424 Sep 27, 2023
9d8640b
ad debug output and fix update handler leak
mono424 Sep 27, 2023
1063708
UI looks great
mono424 Sep 27, 2023
2e3ce8c
:)
mono424 Sep 27, 2023
957dae1
chack if legal end date
mono424 Sep 27, 2023
3aa37df
add frontend calls
mono424 Sep 27, 2023
a1f8d82
changing works
mono424 Sep 27, 2023
e937127
fixed textarea issues
mono424 Sep 27, 2023
03dec0b
lint fix
mono424 Sep 27, 2023
b057ced
Merge branch 'dev' into feature/add-lecture-time-change
mono424 Sep 30, 2023
2e81910
fix backend was writing at the same time to db ...
mono424 Sep 30, 2023
5e6b3ec
lint fix
mono424 Sep 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions api/courses.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func configGinCourseRouter(router *gin.Engine, daoWrapper dao.DaoWrapper) {
courses.POST("/deleteLectures", routes.deleteLectures)
courses.POST("/renameLecture/:streamID", routes.renameLecture)
courses.POST("/updateLectureSeries/:streamID", routes.updateLectureSeries)
courses.POST("/updateStartEnd/:streamID", routes.updateStartEnd)
courses.PUT("/updateDescription/:streamID", routes.updateDescription)
courses.DELETE("/deleteLectureSeries/:streamID", routes.deleteLectureSeries)
courses.POST("/submitCut", routes.submitCut)
Expand Down Expand Up @@ -991,6 +992,43 @@ func (r coursesRoutes) updateDescription(c *gin.Context) {
}
}

type changeDateTime struct {
Start time.Time `json:"start" binding:"required"`
End time.Time `json:"end" binding:"required"`
}

func (r coursesRoutes) updateStartEnd(c *gin.Context) {
var req changeDateTime
if err := c.Bind(&req); err != nil {
_ = c.Error(tools.RequestError{
Status: http.StatusBadRequest,
CustomMessage: "invalid body",
Err: err,
})
return
}

stream, err := r.StreamsDao.GetStreamByID(context.Background(), c.Param("streamID"))
if err != nil {
_ = c.Error(tools.RequestError{
Status: http.StatusNotFound,
CustomMessage: "can not find stream",
Err: err,
})
return
}
stream.Start = req.Start
stream.End = req.End
if err = r.StreamsDao.UpdateStream(stream); err != nil {
_ = c.Error(tools.RequestError{
Status: http.StatusInternalServerError,
CustomMessage: "couldn't update lecture Description",
Err: err,
})
return
}
}

func (r coursesRoutes) renameLecture(c *gin.Context) {
sIDInt, err := strconv.Atoi(c.Param("streamID"))
if err != nil {
Expand Down
40 changes: 23 additions & 17 deletions web/assets/init-admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ document.addEventListener("alpine:init", () => {
const changeSet = evaluate(expression);
const fieldName = value || el.name;

if (el.type === "file") {
if (el.type.toLowerCase() === "file") {
const isSingle = modifiers.includes("single")

const changeHandler = (e) => {
Expand All @@ -103,7 +103,7 @@ document.addEventListener("alpine:init", () => {
changeSet.removeListener(onChangeSetUpdateHandler);
el.removeEventListener('change', changeHandler)
})
} else if (el.type === "checkbox") {
} else if (el.type.toLowerCase() === "checkbox") {
const changeHandler = (e) => {
changeSet.patch(fieldName, e.target.checked);
};
Expand All @@ -121,7 +121,7 @@ document.addEventListener("alpine:init", () => {
changeSet.removeListener(onChangeSetUpdateHandler);
el.removeEventListener('change', changeHandler)
})
} else if (el.tagName === "textarea" || textInputTypes.includes(el.type)) {
} else if (el.tagName.toLowerCase() === "textarea" || textInputTypes.includes(el.type.toLowerCase())) {
const keyupHandler = (e) => changeSet.patch(fieldName, convert(modifiers, e.target.value));
const changeHandler = (e) => changeSet.patch(fieldName, convert(modifiers, e.target.value));

Expand Down Expand Up @@ -172,23 +172,29 @@ document.addEventListener("alpine:init", () => {
*
* Modifiers:
* - "text": When provided, the directive will also update the element's innerText.
* - "value": When provided, the directive will also update the element's value.
*
* Custom Events:
* - "csupdate": Custom event triggered when the change set is updated.
* The detail property of the event object contains the new value of the specified field.
*/
Alpine.directive("change-set-listen", (el, { expression, modifiers }, { effect, evaluate, cleanup }) => {
effect(() => {
const [changeSetExpression, fieldName = null] = expression.split(".");
const changeSet = evaluate(changeSetExpression);
const [changeSetExpression, fieldName = null] = expression.split(".");
let changeSet = evaluate(changeSetExpression);

const onChangeSetUpdateHandler = (data) => {
const value = fieldName != null ? data[fieldName] : data;
if (modifiers.includes("text")) {
el.innerText = `${value}`;
}
el.dispatchEvent(new CustomEvent(nativeEventName, { detail: { changeSet, value } }));
};
const onChangeSetUpdateHandler = (data) => {
const value = fieldName != null ? data[fieldName] : data;
if (modifiers.includes("text")) {
el.innerText = `${value}`;
}
if (modifiers.includes("value")) {
el.value = value;
}
el.dispatchEvent(new CustomEvent(nativeEventName, { detail: { changeSet, value } }));
};

effect(() => {
changeSet = evaluate(changeSetExpression);

if (!changeSet) {
return;
Expand All @@ -197,11 +203,11 @@ document.addEventListener("alpine:init", () => {
changeSet.removeListener(onChangeSetUpdateHandler);
onChangeSetUpdateHandler(changeSet.get());
changeSet.listen(onChangeSetUpdateHandler);

cleanup(() => {
changeSet.removeListener(onChangeSetUpdateHandler);
})
});

cleanup(() => {
changeSet.removeListener(onChangeSetUpdateHandler);
})
});

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,48 @@
</div>
</template>
</article>

<header class="border-b dark:border-gray-600 w-full">
<h6 class="text-sm text-5 font-light">Date and Time</h6>
</header>
<article class="w-full mb-2 flex"
x-data="{ startId: $id('date-input'), endId: $id('date-input') }"
>
<label :for="startId" class="grow mr-2">
<span class="text-sm text-5">Start</span>
<input class="tl-input"
name="newStartDate"
:id="startId"
x-change-set-listen="changeSet.startDate"
x-on-change-set-update="$el._flatpickr.setDate(flatpickr.formatDate(changeSet.get().startDate, 'Y-m-d H:i'))"
x-init="flatpickr($el, {enableTime: true, time_24hr: true, altInput: true, altFormat:'Y-m-d H:i', dateFormat:'Z', allowInput: true, onChange: (date) => changeSet.patch('start', flatpickr.formatDate(date[0], 'Z')) })"
/>
</label>
<template x-if="!lectureData.premiere && !lectureData.vodup">
<label :for="endId">
<span class="text-sm text-5">End</span>
<span :class="lectureData.duration > 0 ? 'text-sm font-light bg-gray-500/20 px-1 rounded opacity-75' : 'text-sm font-light bg-red-500 px-1 rounded opacity-75'"
x-text="lectureData.durationFormatted">

</span>
<input class="tl-input"
name="newEndTime"
:id="endId"
x-change-set-listen="changeSet.endDate"
x-on-change-set-update="$el._flatpickr.setDate(flatpickr.formatDate(changeSet.get().endDate, 'H:i'))"
x-init="flatpickr($el, {enableTime: true, noCalendar: true, altInput: true, altFormat: 'H:i', time_24hr: true, allowInput: true, onChange: (date) => {
const startDate = changeSet.get().startDate;
let val = date[0];
val.setDate(startDate.getDate());
val.setMonth(startDate.getMonth());
val.setFullYear(startDate.getFullYear());
changeSet.patch('end', flatpickr.formatDate(val, 'Z'))
}})"
/>
</label>
</template>
</article>

<header class="border-b dark:border-gray-600 w-full">
<h6 class="text-sm text-5 font-light">Title and Description</h6>
</header>
Expand Down Expand Up @@ -395,7 +437,7 @@
</button>
<button
@click="saveEdit();"
:disabled="!isDirty || isSaving"
:disabled="!isDirty || isSaving || isInvalid"
class="px-8 py-3 text-2 rounded text-white bg-indigo-500 hover:bg-indigo-600 disabled:opacity-20 disabled:hover:bg-indigo-500"
x-text="isSaving ? 'loading ...' : (uiEditMode === admin.UIEditMode.single ? 'Save Lecture' : 'Save Series')"
></button>
Expand Down
39 changes: 31 additions & 8 deletions web/ts/api/admin-lecture-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ export interface UpdateLectureMetaRequest {
isChatEnabled?: boolean;
}

export interface UpdateLectureStartEndRequest {
start: Date;
end: Date;
}

export class LectureFile {
readonly id: number;
readonly fileType: number;
Expand Down Expand Up @@ -187,8 +192,9 @@ export interface Lecture {
startDateFormatted: string;
startTimeFormatted: string;
endDate: Date;
endDateFormatted: string;
endTimeFormatted: string;
duration: number;
durationFormatted: string;

// Clientside pseudo fields
newCombinedVideo: File | null;
Expand Down Expand Up @@ -230,25 +236,25 @@ export const AdminLectureList = {
* @param request
*/
updateMetadata: async function (courseId: number, lectureId: number, request: UpdateLectureMetaRequest) {
const promises = [];
const promises: (() => Promise<Response>)[] = [];
if (request.name !== undefined) {
promises.push(
promises.push(() =>
post(`/api/course/${courseId}/renameLecture/${lectureId}`, {
name: request.name,
}),
);
}

if (request.description !== undefined) {
promises.push(
promises.push(() =>
put(`/api/course/${courseId}/updateDescription/${lectureId}`, {
name: request.description,
}),
);
}

if (request.lectureHallId !== undefined) {
promises.push(
promises.push(() =>
post("/api/setLectureHall", {
streamIds: [lectureId],
lectureHall: request.lectureHallId,
Expand All @@ -257,16 +263,23 @@ export const AdminLectureList = {
}

if (request.isChatEnabled !== undefined) {
promises.push(
promises.push(() =>
patch(`/api/stream/${lectureId}/chat/enabled`, {
lectureId,
isChatEnabled: request.isChatEnabled,
}),
);
}

const errors = (await Promise.all(promises)).filter((res) => res.status !== StatusCodes.OK);
if (errors.length > 0) {
let errors = 0;
for (const promise of promises) {
const res = await promise();
if (res.status !== StatusCodes.OK) {
errors++;
}
}

if (errors > 0) {
console.error(errors);
throw Error("Failed to update all data.");
}
Expand All @@ -281,6 +294,16 @@ export const AdminLectureList = {
await post(`/api/course/${courseId}/updateLectureSeries/${lectureId}`);
},

/**
* Updates date time of a lecture.
* @param courseId
* @param lectureId
* @param request
*/
updateStartEnd: async function (courseId: number, lectureId: number, { start, end }: UpdateLectureStartEndRequest) {
await post(`/api/course/${courseId}/updateStartEnd/${lectureId}`, { start, end });
},

/**
* Add sections to a lecture
* @param lectureId
Expand Down
Loading
Loading