Dashboard fixes

Signed-off-by: John Molakvoæ <skjnldsv@protonmail.com>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
This commit is contained in:
John Molakvoæ 2022-04-26 09:20:59 +02:00 committed by nextcloud-command
parent 7ab1fcf3c4
commit fe47cf40da
14 changed files with 95 additions and 127 deletions

View file

@ -54,55 +54,3 @@
#appmenu li a:focus::before {
display: none !important;
}
$has-custom-logo: variable_exists('theming-logo-mime') and $theming-logo-mime != '';
body.dashboard--inverted:not(.dashboard--dark) {
// Do not invert the default logo
@if ($has-custom-logo == false) {
$image-logo: url(icon-color-path('logo', 'logo', #ffffff, 1, true));
#header .logo {
background-image: $image-logo !important;
opacity: 1;
}
}
#app-dashboard > h2 {
color: #fff;
}
#appmenu li span {
color: #fff;
}
#appmenu svg image {
filter: invert(0);
}
#appmenu .icon-more-white,
.header-right > div:not(#settings) > *:first-child {
filter: invert(1) hue-rotate(180deg);
}
}
body.dashboard--dark:not(.dashboard--inverted) {
// invert the default logo
@if ($has-custom-logo == false) {
$image-logo: url(icon-color-path('logo', 'logo', #000000, 1, true));
#header .logo {
background-image: $image-logo !important;
opacity: 1;
}
}
#app-dashboard > h2 {
color: #000;
}
#appmenu li span {
color: #000;
}
#appmenu svg {
filter: invert(1) hue-rotate(180deg) !important;
}
#appmenu .icon-more-white,
.header-right > div:not(#settings) > *:first-child {
filter: invert(1) hue-rotate(180deg) !important;
}
}

View file

@ -40,6 +40,7 @@ use OCP\Lock\LockedException;
use OCP\PreConditionNotMetException;
class BackgroundService {
// true when the background is bright and need dark icons
public const THEMING_MODE_DARK = 'dark';
public const SHIPPED_BACKGROUNDS = [

View file

@ -16,7 +16,8 @@
@end="saveLayout">
<div v-for="panelId in layout" :key="panels[panelId].id" class="panel">
<div class="panel--header">
<h2 :class="panels[panelId].iconClass">
<h2>
<div :class="panels[panelId].iconClass" role="img" />
{{ panels[panelId].title }}
</h2>
</div>
@ -27,24 +28,26 @@
</Draggable>
<div class="footer">
<a class="edit-panels icon-rename"
tabindex="0"
@click="showModal"
@keyup.enter="showModal"
@keyup.space="showModal">{{ t('dashboard', 'Customize') }}</a>
<Button @click="showModal">
<template #icon>
<Pencil :size="20" />
</template>
{{ t('dashboard', 'Customize') }}
</Button>
</div>
<Modal v-if="modal" size="large" @close="closeModal">
<div class="modal__content">
<h3>{{ t('dashboard', 'Edit widgets') }}</h3>
<ol class="panels">
<li v-for="status in sortedAllStatuses" :key="status">
<li v-for="status in sortedAllStatuses" :key="status" :class="'panel-' + status">
<input :id="'status-checkbox-' + status"
type="checkbox"
class="checkbox"
:checked="isStatusActive(status)"
@input="updateStatusCheckbox(status, $event.target.checked)">
<label :for="'status-checkbox-' + status" :class="statusInfo[status].icon">
<label :for="'status-checkbox-' + status">
<div :class="statusInfo[status].icon" role="img" />
{{ statusInfo[status].text }}
</label>
</li>
@ -55,13 +58,14 @@
v-bind="{swapThreshold: 0.30, delay: 500, delayOnTouchOnly: true, touchStartThreshold: 3}"
handle=".draggable"
@end="saveLayout">
<li v-for="panel in sortedPanels" :key="panel.id">
<li v-for="panel in sortedPanels" :key="panel.id" :class="'panel-' + panel.id">
<input :id="'panel-checkbox-' + panel.id"
type="checkbox"
class="checkbox"
:checked="isActive(panel)"
@input="updateCheckbox(panel, $event.target.checked)">
<label :for="'panel-checkbox-' + panel.id" :class="isActive(panel) ? 'draggable ' + panel.iconClass : panel.iconClass">
<label :for="'panel-checkbox-' + panel.id" :class="{ draggable: isActive(panel) }">
<div :class="panel.iconClass" role="img" />
{{ panel.title }}
</label>
</li>
@ -89,13 +93,16 @@
</template>
<script>
import Vue from 'vue'
import { loadState } from '@nextcloud/initial-state'
import { getCurrentUser } from '@nextcloud/auth'
import Modal from '@nextcloud/vue/dist/Components/Modal'
import Draggable from 'vuedraggable'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import { loadState } from '@nextcloud/initial-state'
import axios from '@nextcloud/axios'
import Button from '@nextcloud/vue/dist/Components/Button'
import Draggable from 'vuedraggable'
import Modal from '@nextcloud/vue/dist/Components/Modal'
import Pencil from 'vue-material-design-icons/Pencil.vue'
import Vue from 'vue'
import isMobile from './mixins/isMobile'
import BackgroundSettings from './components/BackgroundSettings'
import getBackgroundUrl from './helpers/getBackgroundUrl'
@ -106,6 +113,7 @@ const background = loadState('dashboard', 'background')
const themingDefaultBackground = loadState('dashboard', 'themingDefaultBackground')
const version = loadState('dashboard', 'version')
const shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')
const statusInfo = {
weather: {
text: t('dashboard', 'Weather'),
@ -118,15 +126,18 @@ const statusInfo = {
}
export default {
name: 'App',
name: 'DashboardApp',
components: {
Modal,
Draggable,
BackgroundSettings,
Button,
Draggable,
Modal,
Pencil,
},
mixins: [
isMobile,
],
data() {
return {
isAdmin: getCurrentUser().isAdmin,
@ -163,6 +174,7 @@ export default {
backgroundImage: `url(${this.backgroundImage})`,
}
},
greeting() {
const time = this.timer.getHours()
@ -203,12 +215,14 @@ export default {
const shouldShowName = this.displayName && this.uid !== this.displayName
return { text: shouldShowName ? good[partOfDay].withName : good[partOfDay].generic }
},
isActive() {
return (panel) => this.layout.indexOf(panel.id) > -1
},
isStatusActive() {
return (status) => !(status in this.enabledStatuses) || this.enabledStatuses[status]
},
sortedAllStatuses() {
return Object.keys(this.allCallbacksStatus).slice().sort(this.sortStatuses)
},
@ -226,6 +240,7 @@ export default {
return this.registeredStatus.slice().sort(this.sortStatuses)
},
},
watch: {
callbacks() {
this.rerenderPanels()
@ -245,6 +260,7 @@ export default {
}
},
},
mounted() {
this.updateGlobalStyles()
this.updateSkipLink()
@ -261,6 +277,7 @@ export default {
destroyed() {
window.removeEventListener('scroll', this.handleScroll)
},
methods: {
/**
* Method to register panels that will be called by the integrating apps
@ -342,16 +359,14 @@ export default {
this.updateGlobalStyles()
},
updateGlobalStyles() {
document.body.setAttribute('data-dashboard-background', this.background)
if (window.OCA.Theming.inverted) {
document.body.classList.add('dashboard--inverted')
}
const shippedBackgroundTheme = shippedBackgroundList[this.background] ? shippedBackgroundList[this.background].theming : 'light'
if (shippedBackgroundTheme === 'dark') {
document.body.classList.add('dashboard--dark')
// Override primary-invert-if-bright and color-primary-text if background is set
const isBackgroundBright = shippedBackgroundList[this.background]?.theming === 'dark'
if (isBackgroundBright) {
document.querySelector('#header').style.setProperty('--primary-invert-if-bright', 'invert(100%)')
document.querySelector('#header').style.setProperty('--color-primary-text', '#000000')
} else {
document.body.classList.remove('dashboard--dark')
document.querySelector('#header').style.removeProperty('--primary-invert-if-bright')
document.querySelector('#header').style.removeProperty('--color-primary-text')
}
},
updateSkipLink() {
@ -411,19 +426,9 @@ export default {
background-repeat: no-repeat;
background-attachment: fixed;
background-color: var(--color-primary);
--color-background-translucent: rgba(255, 255, 255, 0.8);
--color-background-translucent: rgba(var(--color-main-background-rgb), 0.8);
--background-blur: blur(10px);
#body-user.theme--dark & {
background-color: var(--color-main-background);
--color-background-translucent: rgba(24, 24, 24, 0.8);
}
#body-user.theme--highcontrast & {
background-color: var(--color-main-background);
--color-background-translucent: var(--color-main-background);
}
> h2 {
color: var(--color-primary-text);
text-align: center;
@ -486,20 +491,27 @@ export default {
}
> h2 {
display: block;
display: flex;
align-items: center;
flex-grow: 1;
margin: 0;
font-size: 20px;
line-height: 24px;
font-weight: bold;
background-size: 32px;
background-position: 14px 12px;
padding: 16px 8px 16px 60px;
padding: 16px 8px;
height: 56px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: grab;
div {
background-size: 32px;
width: 32px;
height: 32px;
margin-right: 16px;
background-position: center;
filter: var(--background-invert-if-dark);
}
}
}
@ -519,7 +531,8 @@ export default {
}
.footer {
text-align: center;
display: flex;
justify-content: center;
transition: bottom var(--animation-slow) ease-in-out;
bottom: 0;
padding: 44px 0;
@ -537,6 +550,8 @@ export default {
text-align: center;
}
.button,
.button-vue
.edit-panels,
.statuses ::v-deep .action-item .action-item__menutoggle,
.statuses ::v-deep .action-item.action-item--open .action-item__menutoggle {
@ -576,18 +591,29 @@ export default {
background-color: var(--color-background-hover);
border: 2px solid var(--color-main-background);
border-radius: var(--border-radius-large);
background-size: 24px;
background-position: 16px 16px;
text-align: left;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
div {
position: absolute;
top: 16px;
width: 24px;
height: 24px;
background-size: 24px;
}
&:hover {
border-color: var(--color-primary);
}
}
// Do not invert status icons
&:not(.panel-status) label div {
filter: var(--background-invert-if-dark);
}
input[type='checkbox'].checkbox + label:before {
position: absolute;
right: 12px;

View file

@ -181,10 +181,6 @@ export default {
content: '';
display: block;
height: 100%;
body.theme--dark & {
background-image: var(--icon-checkmark-000);
}
}
}
}

View file

@ -21,7 +21,7 @@
*/
import Vue from 'vue'
import App from './App.vue'
import DashboardApp from './DashboardApp.vue'
import { translate as t } from '@nextcloud/l10n'
import VTooltip from '@nextcloud/vue/dist/Directives/Tooltip'
import { getRequestToken } from '@nextcloud/auth'
@ -40,7 +40,7 @@ if (!window.OCA.Files) {
Object.assign(window.OCA.Files, { App: { fileList: { filesClient: OC.Files.getClient() } } }, window.OCA.Files)
const Dashboard = Vue.extend(App)
const Dashboard = Vue.extend(DashboardApp)
const Instance = new Dashboard({}).$mount('#app-content-vue')
window.OCA.Dashboard = {

View file

@ -24,10 +24,6 @@
@include icon-color('app', 'user_status', $color-black, 1);
}
body.theme--dark .icon-user-status {
@include icon-color('app', 'user_status', $color-white, 1);
}
.icon-user-status-online {
background-image: url('../img/user-status-online.svg');
}
@ -44,7 +40,3 @@ body.theme--dark .icon-user-status {
.icon-user-status-invisible {
@include icon-color('user-status-invisible', 'user_status', $color-black, 1);
}
body.theme--dark .icon-user-status-invisible {
@include icon-color('user-status-invisible', 'user_status', $color-white, 1);
}

View file

@ -37,8 +37,10 @@
</DashboardWidgetItem>
</template>
<template #empty-content>
<EmptyContent id="user_status-widget-empty-content"
icon="icon-user-status">
<EmptyContent id="user_status-widget-empty-content">
<template #icon>
<div class="icon-user-status" />
</template>
{{ t('user_status', 'No recent status changes') }}
</EmptyContent>
</template>
@ -47,9 +49,9 @@
<script>
import { DashboardWidget, DashboardWidgetItem } from '@nextcloud/vue-dashboard'
import { loadState } from '@nextcloud/initial-state'
import Avatar from '@nextcloud/vue/dist/Components/Avatar'
import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent'
import { loadState } from '@nextcloud/initial-state'
import moment from '@nextcloud/moment'
export default {
@ -118,5 +120,11 @@ export default {
#user_status-widget-empty-content {
text-align: center;
margin-top: 5vh;
.icon-user-status {
width: 64px;
height: 64px;
background-size: 64px;
filter: var(--background-invert-if-dark);
}
}
</style>

View file

@ -521,9 +521,6 @@ export default {
.icon-weather-status {
background-image: url('./../img/app-dark.svg');
}
body.theme--dark .icon-weather-status {
background-image: url('./../img/app.svg');
}
.icon-clearsky-day {
background-image: url('./../img/sun.svg');
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long