Look schedule to room and/or time

This commit is contained in:
Lars Westermann 2019-06-02 18:44:01 +02:00
parent 0288150c6e
commit bd8f10f1e7
Signed by: lars.westermann
GPG key ID: 9D417FA5BB9D5E1D
14 changed files with 1418 additions and 521 deletions

View file

@ -3,15 +3,14 @@ package de.kif.common
import de.kif.common.model.Model
import de.westermann.kobserve.event.EventHandler
class CacheRepository<T : Model>(val repository: Repository<T>) : Repository<T> {
abstract class CachedRepository<T : Model>(val repository: Repository<T>) : Repository<T> {
override val onCreate = EventHandler<Long>()
override val onUpdate = EventHandler<Long>()
override val onDelete = EventHandler<Long>()
var cache: Map<Long, T> = emptyMap()
var cacheComplete: Boolean = false
private var cache: Map<Long, T> = emptyMap()
private var cacheComplete: Boolean = false
override suspend fun get(id: Long): T? {
return if (id in cache) {
@ -32,29 +31,37 @@ class CacheRepository<T : Model>(val repository: Repository<T>) : Repository<T>
}
override suspend fun update(model: T) {
val id = model.id
if (id != null) {
cache = cache - id
}
repository.update(model)
}
override suspend fun delete(id: Long) {
cache = cache - id
repository.delete(id)
}
override suspend fun all(): List<T> {
if (cacheComplete) {
return cache.values.toList()
return if (cacheComplete) {
cache.values.toList()
} else {
val all = repository.all()
cache = all.associateBy { it.id!! }
cacheComplete = true
return all
all
}
}
init {
repository.onCreate {
cacheComplete = false
cache = cache - it
}
repository.onUpdate {
cacheComplete = false
cache = cache - it
}
repository.onDelete {
cache = cache - it
}
}
}

View file

@ -10,6 +10,8 @@ data class Schedule(
val room: Room,
val day: Int,
val time: Int,
val lookRoom: Boolean,
val lookTime: Boolean,
override val createdAt: Long = 0,
override val updateAt: Long = 0
) : Model {
@ -27,4 +29,16 @@ data class Schedule(
fun getAbsoluteStartTime(): Int = day * 60 * 24 + time
fun getAbsoluteEndTime(): Int = getAbsoluteStartTime() + workGroup.length
companion object {
fun timeToString(time: Int): String {
var day = time % (24 * 60)
if (day < 0) day += 24 * 60
val hour = day / 60
val minute = day % 60
return hour.toString().padStart(2, '0') + ":" + minute.toString().padStart(2, '0')
}
}
}

View file

@ -78,8 +78,6 @@ class Calendar(calendar: HTMLElement) : View(calendar) {
}
}
val cont = document.getElementsByClassName("header-right")[0] as HTMLElement
val view = View.wrap(document.getElementById("calendar-check-constraints") as HTMLElement)
view.onClick {
launch {

View file

@ -1,6 +1,7 @@
package de.kif.frontend.views.calendar
import de.kif.common.CALENDAR_GRID_WIDTH
import de.kif.common.model.Room
import de.kif.common.model.Schedule
import de.kif.common.model.WorkGroup
import de.kif.frontend.iterator
@ -36,6 +37,9 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
var editable: Boolean = false
var moveLookRoom: Long? = null
var moveLookTime: Int? = null
private fun onMove(event: MouseEvent) {
val position = event.toPoint() - mouseDelta
@ -44,6 +48,13 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
}
if (cell != null) {
if (moveLookRoom != null && cell.roomId != moveLookRoom) {
return
}
if (moveLookTime != null && cell.time != moveLookTime) {
return
}
cell += this
if (newCell == null) {
@ -80,6 +91,10 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
}
}
launch {
calendarTools.setName(cell.getRoom(), cell.time)
}
newCell = cell
}
@ -104,7 +119,9 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
workGroup,
newRoom,
calendar.day,
newTime
newTime,
lookRoom = false,
lookTime = false
)
)
html.remove()
@ -127,6 +144,8 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
private var listeners: List<de.westermann.kobserve.event.EventListener<*>> = emptyList()
fun startDrag() {
classList += "drag"
listeners = listOf(
Body.onMouseMove.reference(this::onMove),
Body.onMouseUp.reference(this::onFinishMove),
@ -134,6 +153,8 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
)
}
private val calendarTools = CalendarTools(this)
init {
onMouseDown { event ->
if (!editable || event.target != html || "pending" in classList) {
@ -142,8 +163,6 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
}
launch {
classList += "drag"
val s = schedule.get()
val time = s.time / CALENDAR_GRID_WIDTH * CALENDAR_GRID_WIDTH
@ -153,22 +172,20 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
mouseDelta = event.toPoint() - p
moveLookRoom = if (s.lookRoom) s.room.id else null
moveLookTime = if (s.lookTime) s.time else null
startDrag()
}
event.preventDefault()
event.stopPropagation()
}
var calendarTools: CalendarTools? = null
for (item in html.children) {
if (item.classList.contains("calendar-tools")) {
calendarTools = CalendarTools(this, item)
break
}
}
if (calendarTools == null) {
calendarTools = CalendarTools(this, createHtmlView())
html.appendChild(calendarTools.html)
html.appendChild(calendarTools.html)
launch {
val s = schedule.get()
calendarTools.update(s)
}
}
@ -188,6 +205,7 @@ class CalendarEntry(private val calendar: Calendar, view: HTMLElement) : View(vi
}
load(schedule.workGroup)
calendarTools.update(schedule)
val time = schedule.time / CALENDAR_GRID_WIDTH * CALENDAR_GRID_WIDTH
val cell = calendar.calendarCells.find {

View file

@ -1,129 +1,116 @@
package de.kif.frontend.views.calendar
import de.kif.common.CALENDAR_GRID_WIDTH
import de.kif.frontend.iterator
import de.kif.common.model.Room
import de.kif.common.model.Schedule
import de.kif.frontend.launch
import de.kif.frontend.repository.ScheduleRepository
import de.westermann.kwebview.View
import de.westermann.kwebview.createHtmlView
import org.w3c.dom.HTMLAnchorElement
import org.w3c.dom.HTMLElement
import org.w3c.dom.events.EventListener
import de.westermann.kwebview.ViewCollection
import de.westermann.kwebview.components.*
class CalendarTools(entry: CalendarEntry, view: HTMLElement) : View(view) {
class CalendarTools(entry: CalendarEntry) : ViewCollection<View>() {
fun setName(room: Room, time: Int) {
nameView.text = room.name + " - " + Schedule.timeToString(time)
}
lateinit var schedule: Schedule
fun update(schedule: Schedule) {
this.schedule = schedule
setName(schedule.room, schedule.time)
lookRoomButton.classList["disabled"] = !schedule.lookRoom
lookTimeButton.classList["disabled"] = !schedule.lookTime
}
private lateinit var nameView: TextView
private lateinit var lookRoomButton: IconView
private lateinit var lookTimeButton: IconView
init {
var linkM10: HTMLAnchorElement? = null
var linkM5: HTMLAnchorElement? = null
var linkReset: HTMLAnchorElement? = null
var linkP5: HTMLAnchorElement? = null
var linkP10: HTMLAnchorElement? = null
var linkDel: HTMLAnchorElement? = null
boxView {
nameView = textView { }
for (element in html.children) {
when {
element.classList.contains("calendar-tools-m10") -> linkM10 = element as? HTMLAnchorElement
element.classList.contains("calendar-tools-m5") -> linkM5 = element as? HTMLAnchorElement
element.classList.contains("calendar-tools-reset") -> linkReset = element as? HTMLAnchorElement
element.classList.contains("calendar-tools-p5") -> linkP5 = element as? HTMLAnchorElement
element.classList.contains("calendar-tools-p10") -> linkP10 = element as? HTMLAnchorElement
element.classList.contains("calendar-tools-del") -> linkDel = element as? HTMLAnchorElement
lookRoomButton = iconView(MaterialIcon.GPS_FIXED) {
title = "Look room"
onClick {
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(lookRoom = "disabled" in this.classList))
}
}
}
lookTimeButton = iconView(MaterialIcon.ALARM) {
title = "Look time slot"
onClick {
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(lookTime = "disabled" in this.classList))
}
}
}
}
boxView {
textView("-10") {
title = "Schedule 10 minutes earlier"
onClick {
if (schedule.lookTime) return@onClick
linkM10 = linkM10 ?: run {
val link = createHtmlView<HTMLAnchorElement>()
link.classList.add("calendar-tools-m10")
link.textContent = "-10"
html.appendChild(link)
link
}
linkM10.removeAttribute("href")
linkM10.addEventListener("click", EventListener {
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time - 10))
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time - 10))
}
}
}
})
textView("-5") {
title = "Schedule 5 minutes earlier"
onClick {
if (schedule.lookTime) return@onClick
linkM5 = linkM5 ?: run {
val link = createHtmlView<HTMLAnchorElement>()
link.classList.add("calendar-tools-m5")
link.textContent = "-5"
html.appendChild(link)
link
}
linkM5.removeAttribute("href")
linkM5.addEventListener("click", EventListener {
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time - 5))
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time - 5))
}
}
}
})
textView("+5") {
title = "Schedule 5 minutes later"
onClick {
if (schedule.lookTime) return@onClick
linkReset = linkReset ?: run {
val link = createHtmlView<HTMLAnchorElement>()
link.classList.add("calendar-tools-reset")
link.textContent = "reset"
html.appendChild(link)
link
}
linkReset.removeAttribute("href")
linkReset.addEventListener("click", EventListener {
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time / CALENDAR_GRID_WIDTH * CALENDAR_GRID_WIDTH))
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time + 5))
}
}
}
})
textView("+10") {
title = "Schedule 10 minutes later"
onClick {
if (schedule.lookTime) return@onClick
linkP5 = linkP5 ?: run {
val link = createHtmlView<HTMLAnchorElement>()
link.classList.add("calendar-tools-p5")
link.textContent = "+5"
html.appendChild(link)
link
}
linkP5.removeAttribute("href")
linkP5.addEventListener("click", EventListener {
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time + 5))
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time + 10))
}
}
}
})
linkP10 = linkP10 ?: run {
val link = createHtmlView<HTMLAnchorElement>()
link.classList.add("calendar-tools-p10")
link.textContent = "+10"
html.appendChild(link)
link
}
linkP10.removeAttribute("href")
linkP10.addEventListener("click", EventListener {
entry.pending = true
launch {
val s = entry.schedule.get()
ScheduleRepository.update(s.copy(time = s.time + 10))
iconView(MaterialIcon.DELETE) {
title = "Delete"
onClick {
entry.pending = true
launch {
ScheduleRepository.delete(entry.scheduleId)
}
}
}
})
linkDel = linkDel ?: run {
val link = createHtmlView<HTMLAnchorElement>()
link.classList.add("calendar-tools-del")
link.textContent = "del"
html.appendChild(link)
link
}
linkDel.removeAttribute("href")
linkDel.addEventListener("click", EventListener {
entry.pending = true
launch {
ScheduleRepository.delete(entry.scheduleId)
}
})
}
}

View file

@ -0,0 +1,15 @@
package de.westermann.kwebview.components
import org.w3c.dom.Element
/**
* Base interface for all icons.
*
* @author lars
*/
interface Icon {
/**
* Dom element that represents an icon.
*/
val element: Element
}

View file

@ -0,0 +1,53 @@
package de.westermann.kwebview.components
import de.westermann.kobserve.Property
import de.westermann.kobserve.ReadOnlyProperty
import de.westermann.kobserve.property.property
import de.westermann.kwebview.KWebViewDsl
import de.westermann.kwebview.View
import de.westermann.kwebview.ViewCollection
import de.westermann.kwebview.createHtmlView
import org.w3c.dom.HTMLSpanElement
import kotlin.dom.clear
/**
* Represents all kinds of icon views.
*
* @author lars
*/
class IconView(icon: Icon?) : View(createHtmlView<HTMLSpanElement>()) {
override val html = super.html as HTMLSpanElement
fun bind(property: ReadOnlyProperty<Icon?>) {
iconProperty.bind(property)
}
fun unbind() {
iconProperty.unbind()
}
var icon: Icon? = null
set(value) {
field = value
html.clear()
value?.let {
html.appendChild(it.element)
}
iconProperty.invalidate()
}
val iconProperty: Property<Icon?> = property(this::icon)
init {
this.icon = icon
}
}
@KWebViewDsl
fun ViewCollection<in IconView>.iconView(icon: Icon? = null, init: IconView.() -> Unit = {}) =
IconView(icon).also(this::append).also(init)
@KWebViewDsl
fun ViewCollection<in IconView>.iconView(icon: ReadOnlyProperty<Icon?>, init: IconView.() -> Unit = {}) =
IconView(icon.value).also(this::append).also { it.bind(icon) }.also(init)

View file

@ -0,0 +1,948 @@
package de.westermann.kwebview.components
import org.w3c.dom.Element
import kotlin.browser.document
/**
* List of material design icons.
*/
enum class MaterialIcon(private val ligature: String) : Icon {
ROTATION_3D("3d_rotation"),
AC_UNIT("ac_unit"),
ACCESS_ALARM("access_alarm "),
ACCESS_ALARMS("access_alarms"),
ACCESS_TIME("access_time"),
ACCESSIBILITY("accessibility"),
ACCESSIBLE("accessible"),
ACCOUNT_BALANCE("account_balance"),
ACCOUNT_BALANCE_WALLET("account_balance_wallet"),
ACCOUNT_BOX("account_box"),
ACCOUNT_CIRCLE("account_circle"),
ADB("adb"),
ADD("add"),
ADD_A_PHOTO("add_a_photo"),
ADD_ALARM("add_alarm"),
ADD_ALERT("add_alert"),
ADD_BOX("add_box"),
ADD_CIRCLE("add_circle"),
ADD_CIRCLE_OUTLINE("add_circle_outline"),
ADD_LOCATION("add_location "),
ADD_SHOPPING_CART("add_shopping_cart"),
ADD_TO_PHOTOS("add_to_photos"),
ADD_TO_QUEUE("add_to_queue "),
ADJUST("adjust"),
AIRLINE_SEAT_FLAT("airline_seat_flat"),
AIRLINE_SEAT_FLAT_ANGLED("airline_seat_flat_angled"),
AIRLINE_SEAT_INDIVIDUAL_SUITE("airline_seat_individual_suite"),
AIRLINE_SEAT_LEGROOM_EXTRA("airline_seat_legroom_extra"),
AIRLINE_SEAT_LEGROOM_NORMAL("airline_seat_legroom_normal"),
AIRLINE_SEAT_LEGROOM_REDUCED("airline_seat_legroom_reduced"),
AIRLINE_SEAT_RECLINE_EXTRA("airline_seat_recline_extra"),
AIRLINE_SEAT_RECLINE_NORMAL("airline_seat_recline_normal"),
AIRPLANEMODE_ACTIVE("airplanemode_active"),
AIRPLANEMODE_INACTIVE("airplanemode_inactive"),
AIRPLAY("airplay"),
AIRPORT_SHUTTLE("airport_shuttle"),
ALARM("alarm"),
ALARM_ADD("alarm_add"),
ALARM_OFF("alarm_off"),
ALARM_ON("alarm_on"),
ALBUM("album"),
ALL_INCLUSIVE("all_inclusive"),
ALL_OUT("all_out"),
ANDROID("android"),
ANNOUNCEMENT("announcement "),
APPS("apps"),
ARCHIVE("archive"),
ARROW_BACK("arrow_back"),
ARROW_DOWNWARD("arrow_downward"),
ARROW_DROP_DOWN("arrow_drop_down"),
ARROW_DROP_DOWN_CIRCLE("arrow_drop_down_circle"),
ARROW_DROP_UP("arrow_drop_up"),
ARROW_FORWARD("arrow_forward"),
ARROW_UPWARD("arrow_upward "),
ART_TRACK("art_track"),
ASPECT_RATIO("aspect_ratio "),
ASSESSMENT("assessment"),
ASSIGNMENT("assignment"),
ASSIGNMENT_IND("assignment_ind"),
ASSIGNMENT_LATE("assignment_late"),
ASSIGNMENT_RETURN("assignment_return"),
ASSIGNMENT_RETURNED("assignment_returned"),
ASSIGNMENT_TURNED_IN("assignment_turned_in"),
ASSISTANT("assistant"),
ASSISTANT_PHOTO("assistant_photo"),
ATTACH_FILE("attach_file"),
ATTACH_MONEY("attach_money "),
ATTACHMENT("attachment"),
AUDIOTRACK("audiotrack"),
AUTORENEW("autorenew"),
AV_TIMER("av_timer"),
BACKSPACE("backspace"),
BACKUP("backup"),
BATTERY_ALERT("battery_alert"),
BATTERY_CHARGING_FULL("battery_charging_full"),
BATTERY_FULL("battery_full "),
BATTERY_STD("battery_std"),
BATTERY_UNKNOWN("battery_unknown"),
BEACH_ACCESS("beach_access "),
BEENHERE("beenhere"),
BLOCK("block"),
BLUETOOTH("bluetooth"),
BLUETOOTH_AUDIO("bluetooth_audio"),
BLUETOOTH_CONNECTED("bluetooth_connected"),
BLUETOOTH_DISABLED("bluetooth_disabled"),
BLUETOOTH_SEARCHING("bluetooth_searching"),
BLUR_CIRCULAR("blur_circular"),
BLUR_LINEAR("blur_linear"),
BLUR_OFF("blur_off"),
BLUR_ON("blur_on"),
BOOK("book"),
BOOKMARK("bookmark"),
BOOKMARK_BORDER("bookmark_border"),
BORDER_ALL("border_all"),
BORDER_BOTTOM("border_bottom"),
BORDER_CLEAR("border_clear "),
BORDER_COLOR("border_color "),
BORDER_HORIZONTAL("border_horizontal"),
BORDER_INNER("border_inner "),
BORDER_LEFT("border_left"),
BORDER_OUTER("border_outer "),
BORDER_RIGHT("border_right "),
BORDER_STYLE("border_style "),
BORDER_TOP("border_top"),
BORDER_VERTICAL("border_vertical"),
BRANDING_WATERMARK("branding_watermark"),
BRIGHTNESS_1("brightness_1 "),
BRIGHTNESS_2("brightness_2 "),
BRIGHTNESS_3("brightness_3 "),
BRIGHTNESS_4("brightness_4 "),
BRIGHTNESS_5("brightness_5 "),
BRIGHTNESS_6("brightness_6 "),
BRIGHTNESS_7("brightness_7 "),
BRIGHTNESS_AUTO("brightness_auto"),
BRIGHTNESS_HIGH("brightness_high"),
BRIGHTNESS_LOW("brightness_low"),
BRIGHTNESS_MEDIUM("brightness_medium"),
BROKEN_IMAGE("broken_image "),
BRUSH("brush"),
BUBBLE_CHART("bubble_chart "),
BUG_REPORT("bug_report"),
BUILD("build"),
BURST_MODE("burst_mode"),
BUSINESS("business"),
BUSINESS_CENTER("business_center"),
CACHED("cached"),
CAKE("cake"),
CALL("call"),
CALL_END("call_end"),
CALL_MADE("call_made"),
CALL_MERGE("call_merge"),
CALL_MISSED("call_missed"),
CALL_MISSED_OUTGOING("call_missed_outgoing"),
CALL_RECEIVED("call_received"),
CALL_SPLIT("call_split"),
CALL_TO_ACTION("call_to_action"),
CAMERA("camera"),
CAMERA_ALT("camera_alt"),
CAMERA_ENHANCE("camera_enhance"),
CAMERA_FRONT("camera_front "),
CAMERA_REAR("camera_rear"),
CAMERA_ROLL("camera_roll"),
CANCEL("cancel"),
CARD_GIFTCARD("card_giftcard"),
CARD_MEMBERSHIP("card_membership"),
CARD_TRAVEL("card_travel"),
CASINO("casino"),
CAST("cast"),
CAST_CONNECTED("cast_connected"),
CENTER_FOCUS_STRONG("center_focus_strong"),
CENTER_FOCUS_WEAK("center_focus_weak"),
CHANGE_HISTORY("change_history"),
CHAT("chat"),
CHAT_BUBBLE("chat_bubble"),
CHAT_BUBBLE_OUTLINE("chat_bubble_outline"),
CHECK("checkUpdates"),
CHECK_BOX("check_box"),
CHECK_BOX_OUTLINE_BLANK("check_box_outline_blank"),
CHECK_CIRCLE("check_circle "),
CHEVRON_LEFT("chevron_left "),
CHEVRON_RIGHT("chevron_right"),
CHILD_CARE("child_care"),
CHILD_FRIENDLY("child_friendly"),
CHROME_RR_MODE("chrome_rr_mode"),
CLASS("class"),
CLEAR("clear"),
CLEAR_ALL("clear_all"),
CLOSE("close"),
CLOSED_CAPTION("closed_caption"),
CLOUD("cloud"),
CLOUD_CIRCLE("cloud_circle "),
CLOUD_DONE("cloud_done"),
CLOUD_DOWNLOAD("cloud_download"),
CLOUD_OFF("cloud_off"),
CLOUD_QUEUE("cloud_queue"),
CLOUD_UPLOAD("cloud_upload "),
CODE("code"),
COLLECTIONS("collections"),
COLLECTIONS_BOOKMARK("collections_bookmark"),
COLOR_LENS("color_lens"),
COLORIZE("colorize"),
COMMENT("comment"),
COMPARE("compare"),
COMPARE_ARROWS("compare_arrows"),
COMPUTER("computer"),
CONFIRMATION_NUMBER("confirmation_number"),
CONTACT_MAIL("contact_mail "),
CONTACT_PHONE("contact_phone"),
CONTACTS("contacts"),
CONTENT_COPY("content_copy "),
CONTENT_CUT("content_cut"),
CONTENT_PASTE("content_paste"),
CONTROL_POINT("control_point"),
CONTROL_POINT_DUPLICATE("control_point_duplicate"),
COPYRIGHT("copyright"),
CREATE("onCreate"),
CREATE_NEW_FOLDER("create_new_folder"),
CREDIT_CARD("credit_card"),
CROP("crop"),
CROP_16_9("crop_16_9"),
CROP_3_2("crop_3_2"),
CROP_5_4("crop_5_4"),
CROP_7_5("crop_7_5"),
CROP_DIN("crop_din"),
CROP_FREE("crop_free"),
CROP_LANDSCAPE("crop_landscape"),
CROP_ORIGINAL("crop_original"),
CROP_PORTRAIT("crop_portrait"),
CROP_ROTATE("crop_rotate"),
CROP_SQUARE("crop_square"),
DASHBOARD("dashboard"),
DATA_USAGE("data_usage"),
DATE_RANGE("date_range"),
DEHAZE("dehaze"),
DELETE("delete"),
DELETE_FOREVER("delete_forever"),
DELETE_SWEEP("delete_sweep "),
DESCRIPTION("description"),
DESKTOP_MAC("desktop_mac"),
DESKTOP_WINDOWS("desktop_windows"),
DETAILS("details"),
DEVELOPER_BOARD("developer_board"),
DEVELOPER_MODE("developer_mode"),
DEVICE_HUB("device_hub"),
DEVICES("devices"),
DEVICES_OTHER("devices_other"),
DIALER_SIP("dialer_sip"),
DIALPAD("dialpad"),
DIRECTIONS("directions"),
DIRECTIONS_BIKE("directions_bike"),
DIRECTIONS_BOAT("directions_boat"),
DIRECTIONS_BUS("directions_bus"),
DIRECTIONS_CAR("directions_car"),
DIRECTIONS_RAILWAY("directions_railway"),
DIRECTIONS_RUN("directions_run"),
DIRECTIONS_SUBWAY("directions_subway"),
DIRECTIONS_TRANSIT("directions_transit"),
DIRECTIONS_WALK("directions_walk"),
DISC_FULL("disc_full"),
DNS("dns"),
DO_NOT_DISTURB("do_not_disturb"),
DO_NOT_DISTURB_ALT("do_not_disturb_alt"),
DO_NOT_DISTURB_OFF("do_not_disturb_off"),
DO_NOT_DISTURB_ON("do_not_disturb_on"),
DOCK("dock"),
DOMAIN("domain"),
DONE("done"),
DONE_ALL("done_all"),
DONUT_LARGE("donut_large"),
DONUT_SMALL("donut_small"),
DRAFTS("drafts"),
DRAG_HANDLE("drag_handle"),
DRIVE_ETA("drive_eta"),
DVR("dvr"),
EDIT("edit"),
EDIT_LOCATION("edit_location"),
EJECT("eject"),
EMAIL("email"),
ENHANCED_ENCRYPTION("enhanced_encryption"),
EQUALIZER("equalizer"),
ERROR("error"),
ERROR_OUTLINE("error_outline"),
EURO_SYMBOL("euro_symbol"),
EV_STATION("ev_station"),
EVENT("model"),
EVENT_AVAILABLE("event_available"),
EVENT_BUSY("event_busy"),
EVENT_NOTE("event_note"),
EVENT_SEAT("event_seat"),
EXIT_TO_APP("exit_to_app"),
EXPAND_LESS("expand_less"),
EXPAND_MORE("expand_more"),
EXPLICIT("explicit"),
EXPLORE("explore"),
EXPOSURE("exposure"),
EXPOSURE_NEG_1("exposure_neg_1"),
EXPOSURE_NEG_2("exposure_neg_2"),
EXPOSURE_PLUS_1("exposure_plus_1"),
EXPOSURE_PLUS_2("exposure_plus_2"),
EXPOSURE_ZERO("exposure_zero"),
EXTENSION("extension"),
FACE("face"),
FAST_FORWARD("fast_forward "),
FAST_REWIND("fast_rewind"),
FAVORITE("favorite"),
FAVORITE_BORDER("favorite_border"),
FEATURED_PLAY_LIST("featured_play_list"),
FEATURED_VIDEO("featured_video"),
FACK("fack"),
FIBER_DVR("fiber_dvr"),
FIBER_MANUAL_RECORD("fiber_manual_record"),
FIBER_NEW("fiber_new"),
FIBER_PIN("fiber_pin"),
FIBER_SMART_RECORD("fiber_smart_record"),
FILE_DOWNLOAD("file_download"),
FILE_UPLOAD("file_upload"),
FILTER("filter"),
FILTER_1("filter_1"),
FILTER_2("filter_2"),
FILTER_3("filter_3"),
FILTER_4("filter_4"),
FILTER_5("filter_5"),
FILTER_6("filter_6"),
FILTER_7("filter_7"),
FILTER_8("filter_8"),
FILTER_9("filter_9"),
FILTER_9_PLUS("filter_9_plus"),
FILTER_B_AND_W("filter_b_and_w"),
FILTER_CENTER_FOCUS("filter_center_focus"),
FILTER_DRAMA("filter_drama "),
FILTER_FRAMES("filter_frames"),
FILTER_HDR("filter_hdr"),
FILTER_LIST("filter_list"),
FILTER_NONE("filter_none"),
FILTER_TILT_SHIFT("filter_tilt_shift"),
FILTER_VINTAGE("filter_vintage"),
FIND_IN_PAGE("find_in_page "),
FIND_REPLACE("find_replace "),
FINGERPRINT("fingerprint"),
FIRST_PAGE("first_page"),
FITNESS_CENTER("fitness_center"),
FLAG("flag"),
FLARE("flare"),
FLASH_AUTO("flash_auto"),
FLASH_OFF("flash_off"),
FLASH_ON("flash_on"),
FLIGHT("flight"),
FLIGHT_LAND("flight_land"),
FLIGHT_TAKEOFF("flight_takeoff"),
FLIP("flip"),
FLIP_TO_BACK("flip_to_back "),
FLIP_TO_FRONT("flip_to_front"),
FOLDER("folder"),
FOLDER_OPEN("folder_open"),
FOLDER_SHARED("folder_shared"),
FOLDER_SPECIAL("folder_special"),
FONT_DOWNLOAD("font_download"),
FORMAT_ALIGN_CENTER("format_align_center"),
FORMAT_ALIGN_JUSTIFY("format_align_justify"),
FORMAT_ALIGN_LEFT("format_align_left"),
FORMAT_ALIGN_RIGHT("format_align_right"),
FORMAT_BOLD("format_bold"),
FORMAT_CLEAR("format_clear "),
FORMAT_COLOR_FILL("format_color_fill"),
FORMAT_COLOR_RESET("format_color_reset"),
FORMAT_COLOR_TEXT("format_color_text"),
FORMAT_INDENT_DECREASE("format_indent_decrease"),
FORMAT_INDENT_INCREASE("format_indent_increase"),
FORMAT_ITALIC("format_italic"),
FORMAT_LINE_SPACING("format_line_spacing"),
FORMAT_LIST_BULLETED("format_list_bulleted"),
FORMAT_LIST_NUMBERED("format_list_numbered"),
FORMAT_PAINT("format_paint "),
FORMAT_QUOTE("format_quote "),
FORMAT_SHAPES("format_shapes"),
FORMAT_SIZE("format_size"),
FORMAT_STRIKETHROUGH("format_strikethrough"),
FORMAT_TEXTDIRECTION_L_TO_R("format_textdirection_l_to_r"),
FORMAT_TEXTDIRECTION_R_TO_L("format_textdirection_r_to_l"),
FORMAT_UNDERLINED("format_underlined"),
FORUM("forum"),
FORWARD("forward"),
FORWARD_10("forward_10"),
FORWARD_30("forward_30"),
FORWARD_5("forward_5"),
FREE_BREAKFAST("free_breakfast"),
FULLSCREEN("fullscreen"),
FULLSCREEN_EXIT("fullscreen_exit"),
FUNCTIONS("functions"),
G_TRANSLATE("g_translate"),
GAMEPAD("gamepad"),
GAMES("games"),
GAVEL("gavel"),
GESTURE("gesture"),
GET_APP("get_app"),
GIF("gif"),
GOLF_COURSE("golf_course"),
GPS_FIXED("gps_fixed"),
GPS_NOT_FIXED("gps_not_fixed"),
GPS_OFF("gps_off"),
GRADE("grade"),
GRADIENT("gradient"),
GRAIN("grain"),
GRAPHIC_EQ("graphic_eq"),
GRID_OFF("grid_off"),
GRID_ON("grid_on"),
GROUP("group"),
GROUP_ADD("group_add"),
GROUP_WORK("group_work"),
HD("hd"),
HDR_OFF("hdr_off"),
HDR_ON("hdr_on"),
HDR_STRONG("hdr_strong"),
HDR_WEAK("hdr_weak"),
HEADSET("headset"),
HEADSET_MIC("headset_mic"),
HEALING("healing"),
HEARING("hearing"),
HELP("help"),
HELP_OUTLINE("help_outline "),
HIGH_QUALITY("high_quality "),
HIGHLIGHT("highlight"),
HIGHLIGHT_OFF("highlight_off"),
HISTORY("history"),
HOME("home"),
HOT_TUB("hot_tub"),
HOTEL("hotel"),
HOURGLASS_EMPTY("hourglass_empty"),
HOURGLASS_FULL("hourglass_full"),
HTTP("http"),
HTTPS("https"),
IMAGE("image"),
IMAGE_ASPECT_RATIO("image_aspect_ratio"),
IMPORT_CONTACTS("import_contacts"),
IMPORT_EXPORT("import_export"),
IMPORTANT_DEVICES("important_devices"),
INBOX("inbox"),
INDETERMINATE_CHECK_BOX("indeterminate_check_box"),
INFO("info"),
INFO_OUTLINE("info_outline "),
INPUT("input"),
INSERT_CHART("insert_chart "),
INSERT_COMMENT("insert_comment"),
INSERT_DRIVE_FILE("insert_drive_file"),
INSERT_EMOTICON("insert_emoticon"),
INSERT_INVITATION("insert_invitation"),
INSERT_LINK("insert_link"),
INSERT_PHOTO("insert_photo "),
INVERT_COLORS("invert_colors"),
INVERT_COLORS_OFF("invert_colors_off"),
ISO("iso"),
KEYBOARD("keyboard"),
KEYBOARD_ARROW_DOWN("keyboard_arrow_down"),
KEYBOARD_ARROW_LEFT("keyboard_arrow_left"),
KEYBOARD_ARROW_RIGHT("keyboard_arrow_right"),
KEYBOARD_ARROW_UP("keyboard_arrow_up"),
KEYBOARD_BACKSPACE("keyboard_backspace"),
KEYBOARD_CAPSLOCK("keyboard_capslock"),
KEYBOARD_HIDE("keyboard_hide"),
KEYBOARD_RETURN("keyboard_return"),
KEYBOARD_TAB("keyboard_tab "),
KEYBOARD_VOICE("keyboard_voice"),
KITCHEN("kitchen"),
LABEL("label"),
LABEL_OUTLINE("label_outline"),
LANDSCAPE("landscape"),
LANGUAGE("language"),
LAPTOP("laptop"),
LAPTOP_CHROMEBOOK("laptop_chromebook"),
LAPTOP_MAC("laptop_mac"),
LAPTOP_WINDOWS("laptop_windows"),
LAST_PAGE("last_page"),
LAUNCH("launch"),
LAYERS("layers"),
LAYERS_CLEAR("layers_clear "),
LEAK_ADD("leak_add"),
LEAK_REMOVE("leak_remove"),
LENS("lens"),
LIBRARY_ADD("library_add"),
LIBRARY_BOOKS("library_books"),
LIBRARY_MUSIC("library_music"),
LIGHTBULB_OUTLINE("lightbulb_outline"),
LINE_STYLE("line_style"),
LINE_WEIGHT("line_weight"),
LINEAR_SCALE("linear_scale "),
LINK("link"),
LINKED_CAMERA("linked_camera"),
LIST("list"),
LIVE_HELP("live_help"),
LIVE_TV("live_tv"),
LOCAL_ACTIVITY("local_activity"),
LOCAL_AIRPORT("local_airport"),
LOCAL_ATM("local_atm"),
LOCAL_BAR("local_bar"),
LOCAL_CAFE("local_cafe"),
LOCAL_CAR_WASH("local_car_wash"),
LOCAL_CONVENIENCE_STORE("local_convenience_store"),
LOCAL_DINING("local_dining "),
LOCAL_DRINK("local_drink"),
LOCAL_FLORIST("local_florist"),
LOCAL_GAS_STATION("local_gas_station"),
LOCAL_GROCERY_STORE("local_grocery_store"),
LOCAL_HOSPITAL("local_hospital"),
LOCAL_HOTEL("local_hotel"),
LOCAL_LAUNDRY_SERVICE("local_laundry_service"),
LOCAL_LIBRARY("local_library"),
LOCAL_MALL("local_mall"),
LOCAL_MOVIES("local_movies "),
LOCAL_OFFER("local_offer"),
LOCAL_PARKING("local_parking"),
LOCAL_PHARMACY("local_pharmacy"),
LOCAL_PHONE("local_phone"),
LOCAL_PIZZA("local_pizza"),
LOCAL_PLAY("local_play"),
LOCAL_POST_OFFICE("local_post_office"),
LOCAL_PRINTSHOP("local_printshop"),
LOCAL_SEE("local_see"),
LOCAL_SHIPPING("local_shipping"),
LOCAL_TAXI("local_taxi"),
LOCATION_CITY("location_city"),
LOCATION_DISABLED("location_disabled"),
LOCATION_OFF("location_off "),
LOCATION_ON("location_on"),
LOCATION_SEARCHING("location_searching"),
LOCK("lock"),
LOCK_OPEN("lock_open"),
LOCK_OUTLINE("lock_outline "),
LOOKS("looks"),
LOOKS_3("looks_3"),
LOOKS_4("looks_4"),
LOOKS_5("looks_5"),
LOOKS_6("looks_6"),
LOOKS_ONE("looks_one"),
LOOKS_TWO("looks_two"),
LOOP("loop"),
LOUPE("loupe"),
LOW_PRIORITY("low_priority "),
LOYALTY("loyalty"),
MAIL("mail"),
MAIL_OUTLINE("mail_outline "),
MAP("map"),
MARKUNREAD("markunread"),
MARKUNREAD_MAILBOX("markunread_mailbox"),
MEMORY("memory"),
MENU("menu"),
MERGE_TYPE("merge_type"),
MESSAGE("message"),
MIC("mic"),
MIC_NONE("mic_none"),
MIC_OFF("mic_off"),
MMS("mms"),
MODE_COMMENT("mode_comment "),
MODE_EDIT("mode_edit"),
MONETIZATION_ON("monetization_on"),
MONEY_OFF("money_off"),
MONOCHROME_PHOTOS("monochrome_photos"),
MOOD("mood"),
MOOD_BAD("mood_bad"),
MORE("more"),
MORE_HORIZ("more_horiz"),
MORE_VERT("more_vert"),
MOTORCYCLE("motorcycle"),
MOUSE("mouse"),
MOVE_TO_INBOX("move_to_inbox"),
MOVIE("movie"),
MOVIE_CREATION("movie_creation"),
MOVIE_FILTER("movie_filter "),
MULTILINE_CHART("multiline_chart"),
MUSIC_NOTE("music_note"),
MUSIC_VIDEO("music_video"),
MY_LOCATION("my_location"),
NATURE("nature"),
NATURE_PEOPLE("nature_people"),
NAVIGATE_BEFORE("navigate_before"),
NAVIGATE_NEXT("navigate_next"),
NAVIGATION("navigationDrawer"),
NEAR_ME("near_me"),
NETWORK_CELL("network_cell "),
NETWORK_CHECK("network_check"),
NETWORK_LOCKED("network_locked"),
NETWORK_WIFI("network_wifi "),
NEW_RELEASES("new_releases "),
NEXT_WEEK("next_week"),
NFC("nfc"),
NO_ENCRYPTION("no_encryption"),
NO_SIM("no_sim"),
NOT_INTERESTED("not_interested"),
NOTE("note"),
NOTE_ADD("note_add"),
NOTIFICATIONS("notifications"),
NOTIFICATIONS_ACTIVE("notifications_active"),
NOTIFICATIONS_NONE("notifications_none"),
NOTIFICATIONS_OFF("notifications_off"),
NOTIFICATIONS_PAUSED("notifications_paused"),
OFFLINE_PIN("offline_pin"),
ONDEMAND_VIDEO("ondemand_video"),
OPACITY("opacity"),
OPEN_IN_BROWSER("open_in_browser"),
OPEN_IN_NEW("open_in_new"),
OPEN_WITH("open_with"),
PAGES("pages"),
PAGEVIEW("pageview"),
PALETTE("palette"),
PAN_TOOL("pan_tool"),
PANORAMA("panorama"),
PANORAMA_FISH_EYE("panorama_fish_eye"),
PANORAMA_HORIZONTAL("panorama_horizontal"),
PANORAMA_VERTICAL("panorama_vertical"),
PANORAMA_WIDE_ANGLE("panorama_wide_angle"),
PARTY_MODE("party_mode"),
PAUSE("pause"),
PAUSE_CIRCLE_FILLED("pause_circle_filled"),
PAUSE_CIRCLE_OUTLINE("pause_circle_outline"),
PAYMENT("payment"),
PEOPLE("people"),
PEOPLE_OUTLINE("people_outline"),
PERM_CAMERA_MIC("perm_camera_mic"),
PERM_CONTACT_CALENDAR("perm_contact_calendar"),
PERM_DATA_SETTING("perm_data_setting"),
PERM_DEVICE_INFORMATION("perm_device_information"),
PERM_IDENTITY("perm_identity"),
PERM_MEDIA("perm_media"),
PERM_PHONE_MSG("perm_phone_msg"),
PERM_SCAN_WIFI("perm_scan_wifi"),
PERSON("person"),
PERSON_ADD("person_add"),
PERSON_OUTLINE("person_outline"),
PERSON_PIN("person_pin"),
PERSON_PIN_CIRCLE("person_pin_circle"),
PERSONAL_VIDEO("personal_video"),
PETS("pets"),
PHONE("phone"),
PHONE_ANDROID("phone_android"),
PHONE_BLUETOOTH_SPEAKER("phone_bluetooth_speaker"),
PHONE_FORWARDED("phone_forwarded"),
PHONE_IN_TALK("phone_in_talk"),
PHONE_IPHONE("phone_iphone "),
PHONE_LOCKED("phone_locked "),
PHONE_MISSED("phone_missed "),
PHONE_PAUSED("phone_paused "),
PHONELINK("phonelink"),
PHONELINK_ERASE("phonelink_erase"),
PHONELINK_LOCK("phonelink_lock"),
PHONELINK_OFF("phonelink_off"),
PHONELINK_RING("phonelink_ring"),
PHONELINK_SETUP("phonelink_setup"),
PHOTO("photo"),
PHOTO_ALBUM("photo_album"),
PHOTO_CAMERA("photo_camera "),
PHOTO_FILTER("photo_filter "),
PHOTO_LIBRARY("photo_library"),
PHOTO_SIZE_SELECT_ACTUAL("photo_size_select_actual"),
PHOTO_SIZE_SELECT_LARGE("photo_size_select_large"),
PHOTO_SIZE_SELECT_SMALL("photo_size_select_small"),
PICTURE_AS_PDF("picture_as_pdf"),
PICTURE_IN_PICTURE("picture_in_picture"),
PICTURE_IN_PICTURE_ALT("picture_in_picture_alt"),
PIE_CHART("pie_chart"),
PIE_CHART_OUTLINED("pie_chart_outlined"),
PIN_DROP("pin_drop"),
PLACE("place"),
PLAY_ARROW("play_arrow"),
PLAY_CIRCLE_FILLED("play_circle_filled"),
PLAY_CIRCLE_OUTLINE("play_circle_outline"),
PLAY_FOR_WORK("play_for_work"),
PLAYLIST_ADD("playlist_add "),
PLAYLIST_ADD_CHECK("playlist_add_check"),
PLAYLIST_PLAY("playlist_play"),
PLUS_ONE("plus_one"),
POLL("poll"),
POLYMER("polymer"),
POOL("pool"),
PORTABLE_WIFI_OFF("portable_wifi_off"),
PORTRAIT("portrait"),
POWER("power"),
POWER_INPUT("power_input"),
POWER_SETTINGS_NEW("power_settings_new"),
PREGNANT_WOMAN("pregnant_woman"),
PRESENT_TO_ALL("present_to_all"),
PRINT("print"),
PRIORITY_HIGH("priority_high"),
PUBLIC("public"),
PUBLISH("publish"),
QUERY_BUILDER("query_builder"),
QUESTION_ANSWER("question_answer"),
QUEUE("queue"),
QUEUE_MUSIC("queue_music"),
QUEUE_PLAY_NEXT("queue_play_next"),
RADIO("radio"),
RADIO_BUTTON_CHECKED("radio_button_checked"),
RADIO_BUTTON_UNCHECKED("radio_button_unchecked"),
RATE_REVIEW("rate_review"),
RECEIPT("receipt"),
RECENT_ACTORS("recent_actors"),
RECORD_VOICE_OVER("record_voice_over"),
RM("rm"),
REDO("redo"),
REFRESH("refresh"),
REMOVE("remove"),
REMOVE_CIRCLE("remove_circle"),
REMOVE_CIRCLE_OUTLINE("remove_circle_outline"),
REMOVE_FROM_QUEUE("remove_from_queue"),
REMOVE_RED_EYE("remove_red_eye"),
REMOVE_SHOPPING_CART("remove_shopping_cart"),
REORDER("reorder"),
REPEAT("repeat"),
REPEAT_ONE("repeat_one"),
REPLAY("replay"),
REPLAY_10("replay_10"),
REPLAY_30("replay_30"),
REPLAY_5("replay_5"),
REPLY("reply"),
REPLY_ALL("reply_all"),
REPORT("report"),
REPORT_PROBLEM("report_problem"),
RESTAURANT("restaurant"),
RESTAURANT_MENU("restaurant_menu"),
RESTORE("restore"),
RESTORE_PAGE("restore_page "),
RING_VOLUME("ring_volume"),
ROOM("room"),
ROOM_SERVICE("room_service "),
ROTATE_90_DEGREES_CCW("rotate_90_degrees_ccw"),
ROTATE_LEFT("rotate_left"),
ROTATE_RIGHT("rotate_right "),
ROUNDED_CORNER("rounded_corner"),
ROUTER("router"),
ROWING("rowing"),
RSS_FEED("rss_feed"),
RV_HOOKUP("rv_hookup"),
SATELLITE("satellite"),
SAVE("save"),
SCANNER("scanner"),
SCHEDULE("schedule"),
SCHOOL("school"),
SCREEN_LOCK_LANDSCAPE("screen_lock_landscape"),
SCREEN_LOCK_PORTRAIT("screen_lock_portrait"),
SCREEN_LOCK_ROTATION("screen_lock_rotation"),
SCREEN_ROTATION("screen_rotation"),
SCREEN_SHARE("screen_share "),
SD_CARD("sd_card"),
SD_STORAGE("sd_storage"),
SEARCH("search"),
SECURITY("security"),
SELECT_ALL("select_all"),
SEND("send"),
SENTIMENT_DISSATISFIED("sentiment_dissatisfied"),
SENTIMENT_NEUTRAL("sentiment_neutral"),
SENTIMENT_SATISFIED("sentiment_satisfied"),
SENTIMENT_VERY_DISSATISFIED("sentiment_very_dissatisfied"),
SENTIMENT_VERY_SATISFIED("sentiment_very_satisfied"),
SETTINGS("settings"),
SETTINGS_APPLICATIONS("settings_applications"),
SETTINGS_BACKUP_RESTORE("settings_backup_restore"),
SETTINGS_BLUETOOTH("settings_bluetooth"),
SETTINGS_BRIGHTNESS("settings_brightness"),
SETTINGS_CELL("settings_cell"),
SETTINGS_ETHERNET("settings_ethernet"),
SETTINGS_INPUT_ANTENNA("settings_input_antenna"),
SETTINGS_INPUT_COMPONENT("settings_input_component"),
SETTINGS_INPUT_COMPOSITE("settings_input_composite"),
SETTINGS_INPUT_HDMI("settings_input_hdmi"),
SETTINGS_INPUT_SVIDEO("settings_input_svideo"),
SETTINGS_OVERSCAN("settings_overscan"),
SETTINGS_PHONE("settings_phone"),
SETTINGS_POWER("settings_power"),
SETTINGS_REMOTE("settings_remote"),
SETTINGS_SYSTEM_DAYDREAM("settings_system_daydream"),
SETTINGS_VOICE("settings_voice"),
SHARE("share"),
SHOP("shop"),
SHOP_TWO("shop_two"),
SHOPPING_BASKET("shopping_basket"),
SHOPPING_CART("shopping_cart"),
SHORT_TEXT("short_text"),
SHOW_CHART("show_chart"),
SHUFFLE("shuffle"),
SIGNAL_CELLULAR_4_BAR("signal_cellular_4_bar"),
SIGNAL_CELLULAR_CONNECTED_NO_INTERNET_4_BAR("signal_cellular_connected_no_internet_4_bar"),
SIGNAL_CELLULAR_NO_SIM("signal_cellular_no_sim"),
SIGNAL_CELLULAR_NULL("signal_cellular_null"),
SIGNAL_CELLULAR_OFF("signal_cellular_off"),
SIGNAL_WIFI_4_BAR("signal_wifi_4_bar"),
SIGNAL_WIFI_4_BAR_LOCK("signal_wifi_4_bar_lock"),
SIGNAL_WIFI_OFF("signal_wifi_off"),
SIM_CARD("sim_card"),
SIM_CARD_ALERT("sim_card_alert"),
SKIP_NEXT("skip_next"),
SKIP_PREVIOUS("skip_previous"),
SLIDESHOW("slideshow"),
SLOW_MOTION_VIDEO("slow_motion_video"),
SMARTPHONE("smartphone"),
SMOKE_FREE("smoke_free"),
SMOKING_ROOMS("smoking_rooms"),
SMS("sms"),
SMS_FAILED("sms_failed"),
SNOOZE("snooze"),
SORT("sort"),
SORT_BY_ALPHA("sort_by_alpha"),
SPA("spa"),
SPACE_BAR("space_bar"),
SPEAKER("speaker"),
SPEAKER_GROUP("speaker_group"),
SPEAKER_NOTES("speaker_notes"),
SPEAKER_NOTES_OFF("speaker_notes_off"),
SPEAKER_PHONE("speaker_phone"),
SPELLCHECK("spellcheck"),
STAR("star"),
STAR_BORDER("star_border"),
STAR_HALF("star_half"),
STARS("stars"),
STAY_CURRENT_LANDSCAPE("stay_current_landscape"),
STAY_CURRENT_PORTRAIT("stay_current_portrait"),
STAY_PRIMARY_LANDSCAPE("stay_primary_landscape"),
STAY_PRIMARY_PORTRAIT("stay_primary_portrait"),
STOP("stop"),
STOP_SCREEN_SHARE("stop_screen_share"),
STORAGE("storage"),
STORE("store"),
STORE_MALL_DIRECTORY("store_mall_directory"),
STRAIGHTEN("straighten"),
STREETVIEW("streetview"),
STRIKETHROUGH_S("strikethrough_s"),
STYLE("style"),
SUBDIRECTORY_ARROW_LEFT("subdirectory_arrow_left"),
SUBDIRECTORY_ARROW_RIGHT("subdirectory_arrow_right"),
SUBJECT("subject"),
SUBSCRIPTIONS("subscriptions"),
SUBTITLES("subtitles"),
SUBWAY("subway"),
SUPERVISOR_ACCOUNT("supervisor_account"),
SURROUND_SOUND("surround_sound"),
SWAP_CALLS("swap_calls"),
SWAP_HORIZ("swap_horiz"),
SWAP_VERT("swap_vert"),
SWAP_VERTICAL_CIRCLE("swap_vertical_circle"),
SWITCH_CAMERA("switch_camera"),
SWITCH_VIDEO("switch_video "),
SYNC("sync"),
SYNC_DISABLED("sync_disabled"),
SYNC_PROBLEM("sync_problem "),
SYSTEM_UPDATE("system_update"),
SYSTEM_UPDATE_ALT("system_update_alt"),
TAB("tab"),
TAB_UNSELECTED("tab_unselected"),
TABLET("tablet"),
TABLET_ANDROID("tablet_android"),
TABLET_MAC("tablet_mac"),
TAG_FACES("tag_faces"),
TAP_AND_PLAY("tap_and_play "),
TERRAIN("terrain"),
TEXT_FIELDS("text_fields"),
TEXT_FORMAT("text_format"),
TEXTSMS("textsms"),
TEXTURE("texture"),
THEATERS("theaters"),
THUMB_DOWN("thumb_down"),
THUMB_UP("thumb_up"),
THUMBS_UP_DOWN("thumbs_up_down"),
TIME_TO_LEAVE("time_to_leave"),
TIMELAPSE("timelapse"),
TIMELINE("timeline"),
TIMER("timer"),
TIMER_10("timer_10"),
TIMER_3("timer_3"),
TIMER_OFF("timer_off"),
TITLE("title"),
TOC("toc"),
TODAY("today"),
TOLL("toll"),
TONALITY("tonality"),
TOUCH_APP("touch_app"),
TOYS("toys"),
TRACK_CHANGES("track_changes"),
TRAFFIC("traffic"),
TRAIN("train"),
TRAM("tram"),
TRANSFER_WITHIN_A_STATION("transfer_within_a_station"),
TRANSFORM("transform"),
TRANSLATE("translate"),
TRENDING_DOWN("trending_down"),
TRENDING_FLAT("trending_flat"),
TRENDING_UP("trending_up"),
TUNE("tune"),
TURNED_IN("turned_in"),
TURNED_IN_NOT("turned_in_not"),
TV("tv"),
UNARCHIVE("unarchive"),
UNDO("undo"),
UNFOLD_LESS("unfold_less"),
UNFOLD_MORE("unfold_more"),
UPDATE("update"),
USB("usb"),
VERIFIED_USER("verified_user"),
VERTICAL_ALIGN_BOTTOM("vertical_align_bottom"),
VERTICAL_ALIGN_CENTER("vertical_align_center"),
VERTICAL_ALIGN_TOP("vertical_align_top"),
VIBRATION("vibration"),
VIDEO_CALL("video_call"),
VIDEO_LABEL("video_label"),
VIDEO_LIBRARY("video_library"),
VIDEOCAM("videocam"),
VIDEOCAM_OFF("videocam_off "),
VIDEOGAME_ASSET("videogame_asset"),
VIEW_AGENDA("view_agenda"),
VIEW_ARRAY("view_array"),
VIEW_CAROUSEL("view_carousel"),
VIEW_COLUMN("view_column"),
VIEW_COMFY("view_comfy"),
VIEW_COMPACT("view_compact "),
VIEW_DAY("view_day"),
VIEW_HEADLINE("view_headline"),
VIEW_LIST("view_list"),
VIEW_MODULE("view_module"),
VIEW_QUILT("view_quilt"),
VIEW_STREAM("view_stream"),
VIEW_WEEK("view_week"),
VIGNETTE("vignette"),
VISIBILITY("visibility"),
VISIBILITY_OFF("visibility_off"),
VOICE_CHAT("voice_chat"),
VOICEMAIL("voicemail"),
VOLUME_DOWN("volume_down"),
VOLUME_MUTE("volume_mute"),
VOLUME_OFF("volume_off"),
VOLUME_UP("volume_up"),
VPN_KEY("vpn_key"),
VPN_LOCK("vpn_lock"),
WALLPAPER("wallpaper"),
WARNING("warning"),
WATCH("watch"),
WATCH_LATER("watch_later"),
WB_AUTO("wb_auto"),
WB_CLOUDY("wb_cloudy"),
WB_INCANDESCENT("wb_incandescent"),
WB_IRIDESCENT("wb_iridescent"),
WB_SUNNY("wb_sunny"),
WC("wc"),
WEB("web"),
WEB_ASSET("web_asset"),
WEEKEND("weekend"),
WHATSHOT("whatshot"),
WIDGETS("widgets"),
WIFI("wifi"),
WIFI_LOCK("wifi_lock"),
WIFI_TETHERING("wifi_tethering"),
WORK("work"),
WRAP_TEXT("wrap_text"),
YOUTUBE_SEARCHED_FOR("youtube_searched_for"),
ZOOM_IN("zoom_in"),
ZOOM_OUT("zoom_out"),
ZOOM_OUT_MAP("zoom_out_map ");
override val element: Element
get() = document.createElement("i").apply {
classList.add("material-icons")
textContent = ligature
}
}

View file

@ -1,39 +1,59 @@
$background-primary-color: #fff;
$background-secondary-color: #fcfcfc;
$text-primary-color: #333;
$text-secondary-color: rgba($text-primary-color, 0.5);
$primary-color: #B11D33;
$primary-text-color: #fff;
$error-color: #F00;
$error-text-color: #fff;
$error-background-color: rgba($error-color, 0.5);
$input-border-color: #888;
$table-border-color: rgba($text-primary-color, 0.1);
$table-header-color: rgba($text-primary-color, 0.06);
$shadow-color: rgba($text-primary-color, 0.8);
$icon-color-focused: rgba($text-primary-color, 0.87);
$icon-color: rgba($text-primary-color, 0.54);
$icon-color-inactive: rgba($text-primary-color, 0.38);
$bg-disabled-color: rgba($text-primary-color, .26);
$bg-enabled-color: rgba($primary-color, .5);
$lever-disabled-color: $background-primary-color;
$lever-enabled-color: $primary-color;
$error-background-color: rgba($error-color, 0.5);
@mixin color-setting {
:root {
--background-primary-color: $background-primary-color;
--background-secondary-color: $background-secondary-color;
--text-primary-color: $text-primary-color;
--text-secondary-color: $text-secondary-color;
--primary-color: $primary-color;
--primary-text-color: $primary-text-color;
--error-color: $error-color;
--error-text-color: $error-text-color;
--error-background-color: $error-background-color;
--input-border-color: $input-border-color;
--table-border-color: $table-border-color;
--table-header-color: $table-header-color;
--shadow-color: $shadow-color;
--icon-color-focused: $icon-color-focused;
--icon-color: $icon-color;
--icon-color-inactive: $icon-color-inactive;
--bg-disabled-color: $bg-disabled-color;
--bg-enabled-color: $bg-enabled-color;
--lever-disabled-color: $lever-disabled-color;
--lever-enabled-color: $lever-enabled-color;
--error-background-color: $error-background-color;
}
}

View file

@ -2,20 +2,30 @@
$background-primary-color: #2d2d2d;
$background-secondary-color: #373737;
$text-primary-color: #fff;
$text-secondary-color: rgba($text-primary-color, 0.5);
$primary-color: #dd213d;
$primary-text-color: #fff;
$error-color: #F00;
$error-text-color: #fff;
$error-background-color: rgba($error-color, 0.5);
$input-border-color: #888;
$table-border-color: rgba($text-primary-color, 0.1);
$table-header-color: rgba($text-primary-color, 0.06);
$shadow-color: rgba($text-primary-color, 0.8);
$icon-color-focused: rgba($text-primary-color, 1.0);
$icon-color: rgba($text-primary-color, 0.7);
$icon-color-inactive: rgba($text-primary-color, 0.5);
$bg-disabled-color: rgba($text-primary-color, .26);
$bg-enabled-color: rgba($primary-color, .5);
$lever-disabled-color: $background-primary-color;
$lever-enabled-color: $primary-color;
$error-background-color: rgba($error-color, 0.5);
@include color-setting;

View file

@ -26,6 +26,8 @@ body, html {
margin: 0;
padding: 0;
overflow-x: hidden;
& > *:last-child {
//margin-bottom: 1rem;
}
@ -549,18 +551,18 @@ form {
}
.calendar-edit {
width: 16rem;
width: 0;
height: 100%;
display: block;
position: absolute;
right: 0;
top: 0;
transition: width $transitionTime;
.calendar-edit-main {
position: sticky;
margin-left: 16rem;
opacity: 0;
transition: margin-left $transitionTime, opacity $transitionTime, visibility $transitionTime;
transition: opacity $transitionTime, visibility $transitionTime;
top: 1rem;
visibility: hidden;
height: 100vh;
@ -610,7 +612,7 @@ form {
z-index: 2;
.calendar-tools {
display: none;
display: block;
}
}
@ -635,8 +637,11 @@ form {
border-right: solid 1px var(--table-border-color);
}
.calendar-edit {
width: 16rem;
}
.calendar-edit-main {
margin-left: 0;
opacity: 1;
visibility: visible;
}
@ -644,19 +649,71 @@ form {
.calendar-tools {
position: absolute;
top: -3rem;
top: -5rem;
right: 0;
background-color: #fff;
padding: 0.2rem 0.5rem;
background-color: var(--background-primary-color);
border-radius: $border-radius;
display: none;
z-index: 10;
width: max-content;
border: solid 1px var(--input-border-color);
box-shadow: 0 0.1rem 0.2rem var(--primary-text-color);
box-shadow: 0 0.1rem 0.2rem var(--shadow-color);
a {
padding: 0.2rem;
div {
clear: left;
span {
float: left;
display: block;
width: 2rem;
line-height: 2rem;
height: 2rem;
text-align: center;
color: var(--icon-color-focused);
transition: color $transitionTime, background-color $transitionTime;
box-sizing: content-box;
i {
font-size: 1rem;
}
&:hover {
background: var(--table-header-color);
}
&.disabled {
color: var(--icon-color-inactive);
}
&:first-child {
padding-left: 0.5rem;
}
&:last-child {
padding-right: 0.5rem;
}
}
&:first-child {
span:first-child {
color: var(--text-primary-color);
width: 6rem;
&:hover {
background-color: transparent;
}
}
span {
padding-top: 0.2rem;
}
}
&:last-child {
span {
padding-bottom: 0.2rem;
}
}
}
&::after {
@ -669,10 +726,6 @@ form {
}
}
.calendar[data-editable=false] .calendar-tools {
display: none !important;
}
.calendar-entry {
position: absolute;
display: block;
@ -706,7 +759,7 @@ form {
z-index: 2;
.calendar-tools {
display: none;
display: block;
}
}
@ -729,161 +782,154 @@ form {
@include no-select()
}
.calendar-table-time-to-room {
.calendar-table-box {
display: flex;
flex-wrap: nowrap;
flex-direction: column;
width: max-content;
height: max-content;
.calendar-header, .calendar-row {
display: flex;
flex-wrap: nowrap;
flex-direction: row;
width: max-content;
}
.calendar-header {
line-height: 2rem;
height: 2rem;
.calendar-cell:not(:first-child) {
font-size: 0.8rem;
width: 6rem;
position: relative;
padding-left: 0.2rem;
&::before {
content: '';
height: 100%;
left: 0;
top: 0;
border-left: solid 1px var(--table-border-color);
position: absolute;
}
}
height: max-content;
}
.calendar-row {
border-top: solid 1px var(--table-border-color);
line-height: 3rem;
height: 3rem;
.calendar-cell {
position: relative;
width: 1.5rem;
&:nth-child(2n + 2)::before {
content: '';
height: 100%;
left: 0;
top: 0;
border-left: solid 1px var(--table-border-color);
position: absolute;
}
&:hover {
background-color: var(--table-header-color);
}
.calendar-entry {
top: 0.5rem !important;
bottom: 0.5rem;
width: 0;
left: 0;
height: auto !important;
}
}
}
.calendar-cell:first-child {
width: 6rem;
left: 0;
text-align: center;
border-right: solid 1px var(--table-border-color);
}
&.room-to-time {
.calendar-header {
line-height: 2rem;
height: 2rem;
width: 100%;
.calendar-link {
display: block;
width: 100%;
height: 100%;
}
}
.calendar-table-room-to-time {
.calendar-header, .calendar-row {
display: flex;
flex-wrap: nowrap;
width: max-content;
}
.calendar-header {
line-height: 2rem;
height: 2rem;
.calendar-cell:not(:first-child) {
width: 12rem;
position: relative;
padding-left: 0.2rem;
&::before {
content: '';
height: 100%;
left: 0;
top: 0;
border-left: solid 1px var(--table-border-color);
position: absolute;
}
}
}
.calendar-row {
line-height: 2rem;
height: 1.3rem;
.calendar-cell {
position: relative;
width: 12rem;
&::before {
content: '';
height: 100%;
width: 100%;
left: 0;
top: 0;
border-left: solid 1px var(--table-border-color);
position: absolute;
.calendar-cell:first-child {
flex-grow: 1;
text-align: center;
}
&:hover {
background-color: var(--table-header-color);
}
.calendar-entry {
top: 0.1rem;
bottom: 0;
width: auto !important;
left: 0.1rem !important;
right: 0.1rem;
}
a {
.calendar-cell:not(:first-child) {
width: 12rem;
position: relative;
padding-left: 0.2rem;
&::before {
content: '';
height: 100%;
left: 0;
top: 0;
border-left: solid 1px var(--table-border-color);
position: absolute;
}
}
}
.calendar-cell:first-child::before {
border-left: none;
}
.calendar-row {
line-height: 2rem;
height: 1.3rem;
&:nth-child(4n + 2) .calendar-cell::before {
border-top: solid 1px var(--table-border-color);
.calendar-cell {
position: relative;
width: 12rem;
&::before {
content: '';
height: 100%;
width: 100%;
left: 0;
top: 0;
border-left: solid 1px var(--table-border-color);
position: absolute;
}
.calendar-entry {
top: 0.1rem;
bottom: 0;
width: auto !important;
left: 0.1rem !important;
right: 0.1rem;
}
}
.calendar-cell:first-child {
width: 6rem;
left: 0;
text-align: center;
}
.calendar-cell:first-child::before {
border-left: none;
}
&:nth-child(4n + 2) .calendar-cell::before {
border-top: solid 1px var(--table-border-color);
}
}
}
.calendar-cell:first-child {
width: 6rem;
left: 0;
text-align: center;
}
&.time-to-room {
flex-direction: row;
.calendar-link {
display: block;
width: 100%;
height: 100%;
.calendar-header, .calendar-row {
flex-direction: column;
line-height: 3rem;
.calendar-cell {
height: 3rem;
}
}
.calendar-header {
.calendar-cell {
position: relative;
width: 6rem;
&:not(:first-child) {
border-top: solid 1px var(--table-border-color);
}
}
}
.calendar-row {
.calendar-cell {
position: relative;
width: 1.5rem;
&:not(:first-child) {
border-top: solid 1px var(--table-border-color);
}
.calendar-entry {
top: 0.5rem !important;
bottom: 0.5rem;
width: 0;
left: 0;
height: auto !important;
}
&:first-child {
font-size: 0.8rem;
position: relative;
padding-left: 0.2rem;
}
}
&:nth-child(2n + 2) .calendar-cell::before {
content: '';
height: 100%;
left: 0;
top: 0;
border-left: solid 1px var(--table-border-color);
position: absolute;
}
}
}
}

View file

@ -59,6 +59,8 @@ object DbSchedule : Table() {
val roomId = long("room_id").index()
val day = integer("day").index()
val time = integer("time_slot")
val lookRoom = bool("look_room").default(false)
val lookTime = bool("look_time").default(false)
val createdAt = long("createdAt")
val updatedAt = long("updatedAt")

View file

@ -24,6 +24,8 @@ object ScheduleRepository : Repository<Schedule> {
val roomId = row[DbSchedule.roomId]
val day = row[DbSchedule.day]
val time = row[DbSchedule.time]
val lookRoom = row[DbSchedule.lookRoom]
val lookTime = row[DbSchedule.lookTime]
val createdAt = row[DbSchedule.createdAt]
val updatedAt = row[DbSchedule.updatedAt]
@ -33,7 +35,7 @@ object ScheduleRepository : Repository<Schedule> {
val room = RoomRepository.get(roomId)
?: throw IllegalStateException("Room for schedule does not exist!")
return Schedule(id, workGroup, room, day, time, createdAt, updatedAt)
return Schedule(id, workGroup, room, day, time, lookRoom, lookTime, createdAt, updatedAt)
}
override suspend fun get(id: Long): Schedule? {
@ -55,6 +57,8 @@ object ScheduleRepository : Repository<Schedule> {
it[roomId] = model.room.id ?: throw IllegalArgumentException("Room does not exist!")
it[day] = model.day
it[time] = model.time
it[lookRoom] = model.lookRoom
it[lookTime] = model.lookTime
it[createdAt] = now
it[updatedAt] = now
@ -77,6 +81,8 @@ object ScheduleRepository : Repository<Schedule> {
it[roomId] = model.room.id ?: throw IllegalArgumentException("Room does not exist!")
it[day] = model.day
it[time] = model.time
it[lookRoom] = model.lookRoom
it[lookTime] = model.lookTime
it[updatedAt] = now
}

View file

@ -3,23 +3,16 @@ package de.kif.backend.route
import com.soywiz.klock.*
import com.soywiz.klock.locale.german
import de.kif.backend.Configuration
import de.kif.backend.authenticateOrRedirect
import de.kif.backend.isAuthenticated
import de.kif.backend.repository.RoomRepository
import de.kif.backend.repository.ScheduleRepository
import de.kif.backend.repository.WorkGroupRepository
import de.kif.backend.view.MainTemplate
import de.kif.backend.view.MenuTemplate
import de.kif.backend.view.TableTemplate
import de.kif.backend.view.respondMain
import de.kif.common.CALENDAR_GRID_WIDTH
import de.kif.common.Search
import de.kif.common.model.Permission
import de.kif.common.model.Room
import de.kif.common.model.Schedule
import io.ktor.application.call
import io.ktor.html.insert
import io.ktor.html.respondHtmlTemplate
import io.ktor.response.respondRedirect
import io.ktor.routing.Route
import io.ktor.routing.get
@ -59,116 +52,22 @@ private fun DIV.calendarCell(schedule: Schedule?) {
attributes["data-id"] = schedule.id.toString()
+schedule.workGroup.name
div("calendar-tools") {
a(
classes = "calendar-tools-m10",
href = "/calendar/${schedule.day}/${schedule.id}/delete?redirect=/calendar/${schedule.day}/${schedule.room.id}/${schedule.time - 10}/${schedule.workGroup.id}"
) { +"-10" }
a(
classes = "calendar-tools-m5",
href = "/calendar/${schedule.day}/${schedule.id}/delete?redirect=/calendar/${schedule.day}/${schedule.room.id}/${schedule.time - 5}/${schedule.workGroup.id}"
) { +"-05" }
a(
classes = "calendar-tools-reset",
href = "/calendar/${schedule.day}/${schedule.id}/delete?redirect=/calendar/${schedule.day}/${schedule.room.id}/${schedule.time / CALENDAR_GRID_WIDTH * CALENDAR_GRID_WIDTH}/${schedule.workGroup.id}"
) { +"reset" }
a(
classes = "calendar-tools-p5",
href = "/calendar/${schedule.day}/${schedule.id}/delete?redirect=/calendar/${schedule.day}/${schedule.room.id}/${schedule.time + 5}/${schedule.workGroup.id}"
) { +"+05" }
a(
classes = "calendar-tools-p10",
href = "/calendar/${schedule.day}/${schedule.id}/delete?redirect=/calendar/${schedule.day}/${schedule.room.id}/${schedule.time + 10}/${schedule.workGroup.id}"
) { +"+10" }
a(
classes = "calendar-tools-del",
href = "/calendar/${schedule.day}/${schedule.id}/delete"
) { +"del" }
}
}
}
}
private fun DIV.renderTimeToRoom(
private fun DIV.renderCalendar(
orientation: CalendarOrientation,
day: Int,
from: Int,
to: Int,
rooms: List<Room>,
schedules: Map<Room, Map<Int, Schedule>>,
allowEdit: Boolean
schedules: Map<Room, Map<Int, Schedule>>
) {
val gridLabelWidth = 60
val minutesOfDay = to - from
div("calendar-table-time-to-room") {
div("calendar-header") {
div("calendar-cell") {
span {
+"Room"
}
}
for (i in 0 until minutesOfDay / gridLabelWidth) {
div("calendar-cell") {
span {
val time = ((i * gridLabelWidth + from) % MINUTES_OF_DAY).let {
if (it < 0) it + MINUTES_OF_DAY else it
}
val minutes = (time % 60).toString().padStart(2, '0')
val hours = (time / 60).toString().padStart(2, '0')
+"$hours:$minutes"
}
}
}
}
for (room in rooms) {
div("calendar-row") {
div("calendar-cell") {
span {
+room.name
}
}
for (i in 0 until minutesOfDay / CALENDAR_GRID_WIDTH) {
val start = i * CALENDAR_GRID_WIDTH + from
val end = (i + 1) * CALENDAR_GRID_WIDTH + from - 1
div("calendar-cell") {
val time = i * CALENDAR_GRID_WIDTH
val minutes = (time % 60).toString().padStart(2, '0')
val hours = (time / 60).toString().padStart(2, '0')
title = "$hours:$minutes"
attributes["data-time"] = start.toString()
attributes["data-room"] = room.id.toString()
attributes["data-day"] = day.toString()
val schedule = (start..end).mapNotNull { schedules[room]?.get(it) }.firstOrNull()
calendarCell(schedule)
val href = if (allowEdit) "/calendar/$day/${room.id}/$start" else null
a(href, classes = "calendar-link")
}
}
}
}
}
}
private fun DIV.renderRoomToTime(
day: Int,
from: Int,
to: Int,
rooms: List<Room>,
schedules: Map<Room, Map<Int, Schedule>>,
allowEdit: Boolean
) {
val gridLabelWidth = 60
val minutesOfDay = to - from
div("calendar-table-room-to-time") {
div("calendar-table-box ${orientation.name.toLowerCase().replace("_", "-")}") {
div("calendar-header") {
div("calendar-cell") {
span {
@ -210,14 +109,11 @@ private fun DIV.renderRoomToTime(
attributes["data-time"] = start.toString()
attributes["data-room"] = room.id.toString()
attributes["data-day"] = day.toString()
title = timeString
title = room.name + " - " + timeString
val schedule = (start..end).mapNotNull { schedules[room]?.get(it) }.firstOrNull()
calendarCell(schedule)
val href = if (allowEdit) "/calendar/$day/${room.id}/$start" else null
a(href, classes = "calendar-link")
}
}
}
@ -351,24 +247,14 @@ fun Route.calendar() {
attributes["data-editable"] = editable.toString()
div("calendar-table") {
when (orientation) {
CalendarOrientation.ROOM_TO_TIME -> renderRoomToTime(
day,
min,
max,
rooms,
schedules,
editable
)
CalendarOrientation.TIME_TO_ROOM -> renderTimeToRoom(
day,
min,
max,
rooms,
schedules,
editable
)
}
renderCalendar(
orientation,
day,
min,
max,
rooms,
schedules
)
}
if (editable) {
@ -390,119 +276,6 @@ fun Route.calendar() {
}
}
}
get("/calendar/{day}/{room}/{time}") {
authenticateOrRedirect(Permission.SCHEDULE) { user ->
val day = call.parameters["day"]?.toIntOrNull() ?: return@get
val time = call.parameters["time"]?.toIntOrNull() ?: return@get
val roomId = call.parameters["room"]?.toLongOrNull() ?: return@get
val search = call.parameters["search"] ?: ""
val list = WorkGroupRepository.all()
val room = RoomRepository.get(roomId) ?: return@get
respondMain {
menuTemplate {
this.user = user
active = MenuTemplate.Tab.WORK_GROUP
}
content {
h1 { +"Select work groups" }
insert(TableTemplate()) {
searchValue = search
action {
a("/calendar/$day") {
button(classes = "form-btn btn-primary") {
+"Cancel"
}
}
}
header {
th {
+"Name"
}
th {
+"Interested"
}
th {
+"Track"
}
th {
+"Projector"
}
th {
+"Resolution"
}
th {
+"Length"
}
}
for (u in list) {
val s = u.createSearch()
if (Search.match(search, s)) {
val href = "/calendar/$day/${room.id}/$time/${u.id}"
entry {
attributes["data-search"] = s.stringify()
td {
a(href) {
+u.name
}
}
td {
+u.interested.toString()
}
td {
+(u.track?.name ?: "")
}
td {
+u.projector.toString()
}
td {
+u.resolution.toString()
}
td {
+u.length.toString()
}
}
}
}
}
}
}
}
}
get("/calendar/{day}/{room}/{time}/{workgroup}") {
authenticateOrRedirect(Permission.SCHEDULE) { user ->
val day = call.parameters["day"]?.toIntOrNull() ?: return@get
val time = call.parameters["time"]?.toIntOrNull() ?: return@get
val roomId = call.parameters["room"]?.toLongOrNull() ?: return@get
val workGroupId = call.parameters["workgroup"]?.toLongOrNull() ?: return@get
val room = RoomRepository.get(roomId) ?: return@get
val workGroup = WorkGroupRepository.get(workGroupId) ?: return@get
val schedule = Schedule(null, workGroup, room, day, time)
ScheduleRepository.create(schedule)
val redirect = call.parameters["redirect"]
call.respondRedirect(redirect ?: "/calendar/$day")
}
}
get("/calendar/{day}/{schedule}/delete") {
authenticateOrRedirect(Permission.SCHEDULE) { user ->
val day = call.parameters["day"]?.toIntOrNull() ?: return@get
val scheduleId = call.parameters["schedule"]?.toLongOrNull() ?: return@get
ScheduleRepository.delete(scheduleId)
val redirect = call.parameters["redirect"]
call.respondRedirect(redirect ?: "/calendar/$day")
}
}
}
enum class CalendarOrientation {