From b6fa87b53ca62cf662f83cdd3e87464d499da9a7 Mon Sep 17 00:00:00 2001 From: euzu Date: Wed, 7 May 2025 13:03:08 +0200 Subject: [PATCH] refactored web ui video player refactored responsiveness --- frontend/public/assets/i18n/en_common.json | 2 +- .../src/component/form-view/form-view.scss | 15 ++++- .../main-config-view/main-config-view.scss | 8 --- .../main-config-view/main-config-view.tsx | 2 +- .../playlist-browser/playlist-browser.scss | 3 +- .../playlist-video/channel-view.scss | 61 +++++++++++++------ .../component/playlist-video/channel-view.tsx | 28 ++++++--- .../src/component/user-editor/user-editor.tsx | 2 +- .../src/component/user-view/user-view.scss | 13 +++- .../src/component/user-view/user-view.tsx | 24 ++++---- frontend/src/scss/_common.scss | 7 ++- frontend/src/scss/_default.scss | 3 + frontend/src/scss/_theme.scss | 1 + src/repository/user_repository.rs | 10 ++- 14 files changed, 122 insertions(+), 57 deletions(-) diff --git a/frontend/public/assets/i18n/en_common.json b/frontend/public/assets/i18n/en_common.json index c85c00749..c9d30582d 100644 --- a/frontend/public/assets/i18n/en_common.json +++ b/frontend/public/assets/i18n/en_common.json @@ -116,7 +116,7 @@ "IP": "IP", "TARGET": "Target", "TARGETS": "Targets", - "COMMENT": "Comment" + "NOTES": "Notes" }, "TITLE": { "USER_BOUQUET_EDITOR": "User group editor" diff --git a/frontend/src/component/form-view/form-view.scss b/frontend/src/component/form-view/form-view.scss index c2359e1c6..48df6e4b4 100644 --- a/frontend/src/component/form-view/form-view.scss +++ b/frontend/src/component/form-view/form-view.scss @@ -26,6 +26,13 @@ &__row { flex-flow: row nowrap; @include common.container_common(flex-start, 0); + @media (max-width: common.$media-size-mobile) { + flex-flow: column; + &:nth-child(even) { + background-color: var(--card-background-color-darker); + border-radius: var(--border-radius); + } + } } &__col { @@ -35,9 +42,13 @@ &-label { display: flex; - width: 7em; - justify-content: flex-end; + min-width: 10em; + width: 10em; + justify-content: flex-start; align-items: center; + @media (max-width: common.$media-size-mobile) { + justify-content: flex-start; + } } &-value { diff --git a/frontend/src/component/main-config-view/main-config-view.scss b/frontend/src/component/main-config-view/main-config-view.scss index 75f0ee5e6..f9781341c 100644 --- a/frontend/src/component/main-config-view/main-config-view.scss +++ b/frontend/src/component/main-config-view/main-config-view.scss @@ -35,14 +35,6 @@ padding-bottom: 4px; margin: 8px 0; } - .form-view__col-label { - width: 120px; - min-width: 120px; - max-width: 120px; - @media (max-width: common.$media-size-mobile) { - justify-content: flex-start; - } - } } &-help { diff --git a/frontend/src/component/main-config-view/main-config-view.tsx b/frontend/src/component/main-config-view/main-config-view.tsx index d37c727cd..69967ea70 100644 --- a/frontend/src/component/main-config-view/main-config-view.tsx +++ b/frontend/src/component/main-config-view/main-config-view.tsx @@ -72,7 +72,7 @@ const CONFIG_WEB_AUTH_FIELDS = [ name: 'secret', label: 'LABEL.SECRET', fieldType: FormFieldType.TEXT, - action: {icon: 'Clear', handler: getRandomHex} + action: {icon: 'Refresh', handler: getRandomHex} }, {name: 'userfile', label: 'LABEL.USERFILE', fieldType: FormFieldType.TEXT}, ]; diff --git a/frontend/src/component/playlist-browser/playlist-browser.scss b/frontend/src/component/playlist-browser/playlist-browser.scss index 33eadd606..c09ad4c45 100644 --- a/frontend/src/component/playlist-browser/playlist-browser.scss +++ b/frontend/src/component/playlist-browser/playlist-browser.scss @@ -16,11 +16,12 @@ &__toolbar { display: flex; - flex-flow: row; + flex-flow: row wrap; flex: 0 0 auto; box-sizing: border-box; overflow: hidden; background-color: inherit; + gap: 12px; .source-selector { flex: 1 1 auto; diff --git a/frontend/src/component/playlist-video/channel-view.scss b/frontend/src/component/playlist-video/channel-view.scss index cd06c2b5f..d0f5acc9d 100644 --- a/frontend/src/component/playlist-video/channel-view.scss +++ b/frontend/src/component/playlist-video/channel-view.scss @@ -1,6 +1,7 @@ @use '../../scss/common'; $menu-width: 300px; +$menu-width-closed: -288px; $item-height: 48px; .playlist-video { @@ -16,7 +17,6 @@ $item-height: 48px; .channel-view { display: flex; flex-flow: column; - border: 1px transparent; box-sizing: border-box; z-index: 2; font-size: 1rem; @@ -26,28 +26,41 @@ $item-height: 48px; bottom: 0; overflow: hidden; gap: 4px; - transition: width 0.4s ease; - width: 12px; - height: 90%; + transition: left 0.4s ease; + width: $menu-width; + height: 100%; background-color: transparent; + border: 1px solid var(--border-color); - &:hover { - background-color: #00000088; - border: 1px solid var(--border-color); - width: $menu-width; - .channel-view__content, - .channel-view__header { - display: flex; + &__closed { + left: $menu-width-closed; + border: none; + cursor:pointer; + &:hover { + background-color: var(--card-background-color); + } + .channel-view__header, + .channel-view__content { + display: none; } } + //&:hover { + // background-color: #00000088; + // border: 1px solid var(--border-color); + // width: $menu-width; + // .channel-view__content, + // .channel-view__header { + // display: flex; + // } + //} + &__header { - display: none; + display: flex; flex-flow: row; align-items: center; box-sizing: border-box; height: $item-height; - border-bottom:1px solid var(--border-color) } &__menu { @@ -59,13 +72,23 @@ $item-height: 48px; overflow: hidden; cursor: pointer; - &-disabled { - pointer-events: none; + &-title { + overflow: hidden; + white-space: nowrap; } - &:hover { - color: var(--icon-button-hover-color); - background-color: var(--icon-button-hover-background-color); + &-back, + &-title { + &:hover { + cursor: pointer; + color: var(--icon-button-hover-color); + background-color: var(--icon-button-hover-background-color); + } + } + + + &-disabled { + pointer-events: none; } &-back { @@ -98,7 +121,7 @@ $item-height: 48px; } &__content { - display: none; + display: flex; flex-flow: column; box-sizing: border-box; overflow-x: hidden; diff --git a/frontend/src/component/playlist-video/channel-view.tsx b/frontend/src/component/playlist-video/channel-view.tsx index a246e9508..f49a3aa42 100644 --- a/frontend/src/component/playlist-video/channel-view.tsx +++ b/frontend/src/component/playlist-video/channel-view.tsx @@ -3,6 +3,7 @@ import './channel-view.scss'; import React, {ReactNode, useCallback, useState} from "react"; import {getIconByName} from "../../icons/icons"; import useTranslator from "../../hook/use-translator"; +import {set} from "react-datepicker/dist/date_utils"; const getLogo = (item: PlaylistItem): string | undefined => { if (item.logo_small && item.logo_small.length > 0) { @@ -26,6 +27,7 @@ export default function ChannelView(props: ChannelViewProps) { const [selectedItem, setSelectedItem] = useState(); const [selectedGroup, setSelectedGroup] = useState(); const [selectedCategory, setSelectedCategory] = useState(PlaylistCategory.LIVE); + const [openChannelList, setOpenChannelList] = useState(true); const handleCategorySelect = useCallback((evt: any) => { let category = evt.target.dataset.category; @@ -52,6 +54,17 @@ export default function ChannelView(props: ChannelViewProps) { } }, [onPlay]); + const handleCloseChannelViewState = useCallback(() => { + setOpenChannelList(false); + }, []); + + + const handleOpenChannelViewState = useCallback(() => { + if (!openChannelList) { + setOpenChannelList(true); + } + }, [openChannelList]); + const handleBack = useCallback(() => { if (selectedGroup) { setSelectedGroup(undefined); @@ -122,15 +135,16 @@ export default function ChannelView(props: ChannelViewProps) { }, [data, selectedCategory, selectedGroup, selectedItem, renderSelectionContent, translate]); const renderMenu = useCallback((): ReactNode => { - return
-
{getIconByName('Back')}
- {selectedGroup?.name ?? ''} + return
+
{getIconByName('Clear')}
+ {selectedGroup && +
{getIconByName('Back')}
+ } +
{selectedGroup?.name ?? ''}
- }, [selectedGroup, handleBack]) + }, [selectedGroup, handleBack, handleCloseChannelViewState]) - return
+ return
{renderMenu()} {renderCategories()} diff --git a/frontend/src/component/user-editor/user-editor.tsx b/frontend/src/component/user-editor/user-editor.tsx index a0a77713c..92b9fb762 100644 --- a/frontend/src/component/user-editor/user-editor.tsx +++ b/frontend/src/component/user-editor/user-editor.tsx @@ -23,7 +23,7 @@ const COLUMNS = [ {name: 'status', label: 'LABEL.STATUS', fieldType: FormFieldType.SINGLE_SELECT, options: STATUS_OPTIONS}, {name: 'exp_date', label: 'LABEL.EXP_DATE', fieldType: FormFieldType.DATE}, {name: 'ui_enabled', label: 'LABEL.UI_ENABLED', fieldType: FormFieldType.CHECK}, - {name: 'comment', label: 'LABEL.COMMENT', fieldType: FormFieldType.TEXT} + {name: 'comment', label: 'LABEL.NOTES', fieldType: FormFieldType.TEXT} ]; interface UserViewProps { diff --git a/frontend/src/component/user-view/user-view.scss b/frontend/src/component/user-view/user-view.scss index 15206b3cc..f5996491c 100644 --- a/frontend/src/component/user-view/user-view.scss +++ b/frontend/src/component/user-view/user-view.scss @@ -157,6 +157,7 @@ dialog:not([open]) { &-row { display: table-row; width: auto; + height: 3rem; clear: both; border: 1px solid var(--table-border-color); } @@ -186,6 +187,7 @@ dialog:not([open]) { align-items: center; gap: 4px; } + &-action { cursor: pointer; span { @@ -196,6 +198,12 @@ dialog:not([open]) { } } + &-comment { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + } + .visibility { opacity: 0.5; cursor: pointer; @@ -209,12 +217,12 @@ dialog:not([open]) { display: flex; flex-flow: row; align-items: flex-end; - justify-content: flex-end; + justify-content: flex-start; padding-left: 4px; } span { padding: 4px; - transform: scale(0.7) translateY(5px); + transform: scale(0.9) translateY(5px); @include common.iconButton(); } } @@ -240,6 +248,7 @@ dialog:not([open]) { display: flex; flex-flow: column; gap: 4px; + height: auto; } &-col-label { diff --git a/frontend/src/component/user-view/user-view.tsx b/frontend/src/component/user-view/user-view.tsx index 40720403a..6267117f0 100644 --- a/frontend/src/component/user-view/user-view.tsx +++ b/frontend/src/component/user-view/user-view.tsx @@ -26,7 +26,7 @@ const renderBool = (value: any, hidden?: boolean) => { const renderComment = (value: any, hidden?: boolean) => { if (value?.length) { - return {getIconByName('Visibility')}; + return {value}; } return undefined; }; @@ -62,7 +62,7 @@ const COLUMNS = [ {field: 'status', label: 'LABEL.STATUS', render: renderStatus}, {field: 'exp_date', label: 'LABEL.EXP_DATE', render: renderExpDate}, {field: 'ui_enabled', label: 'LABEL.UI_ENABLED', render: renderBool}, - {field: 'comment', label: 'LABEL.COMMENT', render: renderComment, action: true}, + {field: 'comment', label: 'LABEL.NOTES', render: renderComment, action: true}, ] COLUMNS.forEach(col => { @@ -456,15 +456,17 @@ export default function UserView(props: UserViewProps) { {(filteredUser[target.target]?.user ?? target.credentials).map((usr, idx) =>
-
- - {getIconByName('PersonRemove')} - - - {getIconByName('Edit')} - +
+
+ + {getIconByName('PersonRemove')} + + + {getIconByName('Edit')} + +
{COLUMNS.map(c =>