Merge pull request #22357 from nextcloud/enh/dashboard/toggle-statuses
Ability to toggle statuses in dashboard
This commit is contained in:
commit
487d17dd55
|
@ -28,6 +28,7 @@ return [
|
|||
'routes' => [
|
||||
['name' => 'dashboard#index', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'dashboard#updateLayout', 'url' => '/layout', 'verb' => 'POST'],
|
||||
['name' => 'dashboard#updateStatuses', 'url' => '/statuses', 'verb' => 'POST'],
|
||||
['name' => 'dashboard#getBackground', 'url' => '/background', 'verb' => 'GET'],
|
||||
['name' => 'dashboard#setBackground', 'url' => '/background/{type}', 'verb' => 'POST'],
|
||||
]
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -103,7 +103,10 @@ class DashboardController extends Controller {
|
|||
'url' => $widget->getUrl()
|
||||
];
|
||||
}, $this->dashboardManager->getWidgets());
|
||||
$configStatuses = $this->config->getUserValue($this->userId, 'dashboard', 'statuses', '{}');
|
||||
$statuses = json_decode($configStatuses, true);
|
||||
$this->inititalStateService->provideInitialState('dashboard', 'panels', $widgets);
|
||||
$this->inititalStateService->provideInitialState('dashboard', 'statuses', $statuses);
|
||||
$this->inititalStateService->provideInitialState('dashboard', 'layout', $userLayout);
|
||||
$this->inititalStateService->provideInitialState('dashboard', 'firstRun', $this->config->getUserValue($this->userId, 'dashboard', 'firstRun', '1') === '1');
|
||||
$this->inititalStateService->provideInitialState('dashboard', 'shippedBackgrounds', BackgroundService::SHIPPED_BACKGROUNDS);
|
||||
|
@ -131,6 +134,16 @@ class DashboardController extends Controller {
|
|||
return new JSONResponse(['layout' => $layout]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @param string $statuses
|
||||
* @return JSONResponse
|
||||
*/
|
||||
public function updateStatuses(string $statuses): JSONResponse {
|
||||
$this->config->setUserValue($this->userId, 'dashboard', 'statuses', $statuses);
|
||||
return new JSONResponse(['statuses' => $statuses]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*/
|
||||
|
|
|
@ -38,6 +38,18 @@
|
|||
<Modal v-if="modal" @close="closeModal">
|
||||
<div class="modal__content">
|
||||
<h3>{{ t('dashboard', 'Edit widgets') }}</h3>
|
||||
<ol class="panels">
|
||||
<li v-for="status in sortedAllStatuses" :key="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">
|
||||
{{ statusInfo[status].text }}
|
||||
</label>
|
||||
</li>
|
||||
</ol>
|
||||
<Draggable v-model="layout"
|
||||
class="panels"
|
||||
tag="ol"
|
||||
|
@ -90,6 +102,16 @@ const firstRun = loadState('dashboard', 'firstRun')
|
|||
const background = loadState('dashboard', 'background')
|
||||
const version = loadState('dashboard', 'version')
|
||||
const shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')
|
||||
const statusInfo = {
|
||||
weather: {
|
||||
text: t('dashboard', 'Weather'),
|
||||
icon: 'icon-weather-status',
|
||||
},
|
||||
status: {
|
||||
text: t('dashboard', 'Status'),
|
||||
icon: 'icon-user-status-online',
|
||||
},
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
|
@ -108,6 +130,9 @@ export default {
|
|||
registeredStatus: [],
|
||||
callbacks: {},
|
||||
callbacksStatus: {},
|
||||
allCallbacksStatus: {},
|
||||
statusInfo,
|
||||
enabledStatuses: loadState('dashboard', 'statuses'),
|
||||
panels,
|
||||
firstRun,
|
||||
displayName: getCurrentUser()?.displayName,
|
||||
|
@ -162,6 +187,12 @@ export default {
|
|||
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((a, b) => a > b)
|
||||
},
|
||||
sortedPanels() {
|
||||
return Object.values(this.panels).sort((a, b) => {
|
||||
const indexA = this.layout.indexOf(a.id)
|
||||
|
@ -224,10 +255,15 @@ export default {
|
|||
Vue.set(this.callbacks, app, callback)
|
||||
},
|
||||
registerStatus(app, callback) {
|
||||
this.registeredStatus.push(app)
|
||||
this.$nextTick(() => {
|
||||
Vue.set(this.callbacksStatus, app, callback)
|
||||
})
|
||||
// always save callbacks in case user enables the status later
|
||||
Vue.set(this.allCallbacksStatus, app, callback)
|
||||
// register only if status is enabled or missing from config
|
||||
if (this.isStatusActive(app)) {
|
||||
this.registeredStatus.push(app)
|
||||
this.$nextTick(() => {
|
||||
Vue.set(this.callbacksStatus, app, callback)
|
||||
})
|
||||
}
|
||||
},
|
||||
rerenderPanels() {
|
||||
for (const app in this.callbacks) {
|
||||
|
@ -253,6 +289,11 @@ export default {
|
|||
layout: this.layout.join(','),
|
||||
})
|
||||
},
|
||||
saveStatuses() {
|
||||
axios.post(generateUrl('/apps/dashboard/statuses'), {
|
||||
statuses: JSON.stringify(this.enabledStatuses),
|
||||
})
|
||||
},
|
||||
showModal() {
|
||||
this.modal = true
|
||||
this.firstRun = false
|
||||
|
@ -296,6 +337,30 @@ export default {
|
|||
document.body.classList.remove('dashboard--dark')
|
||||
}
|
||||
},
|
||||
updateStatusCheckbox(app, checked) {
|
||||
if (checked) {
|
||||
this.enableStatus(app)
|
||||
} else {
|
||||
this.disableStatus(app)
|
||||
}
|
||||
},
|
||||
enableStatus(app) {
|
||||
this.enabledStatuses[app] = true
|
||||
this.registerStatus(app, this.allCallbacksStatus[app])
|
||||
this.saveStatuses()
|
||||
},
|
||||
disableStatus(app) {
|
||||
this.enabledStatuses[app] = false
|
||||
const i = this.registeredStatus.findIndex((s) => s === app)
|
||||
if (i !== -1) {
|
||||
this.registeredStatus.splice(i, 1)
|
||||
Vue.set(this.statuses, app, { mounted: false })
|
||||
this.$nextTick(() => {
|
||||
Vue.delete(this.callbacksStatus, app)
|
||||
})
|
||||
}
|
||||
this.saveStatuses()
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -142,12 +142,12 @@ export default {
|
|||
|
||||
.background {
|
||||
width: 176px;
|
||||
height: 96px;
|
||||
margin: 8px;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
height: 96px;
|
||||
margin: 8px;
|
||||
background-size: cover;
|
||||
background-position: center center;
|
||||
text-align: center;
|
||||
border-radius: var(--border-radius-large);
|
||||
border-radius: var(--border-radius-large);
|
||||
border: 2px solid var(--color-main-background);
|
||||
overflow: hidden;
|
||||
|
||||
|
@ -166,8 +166,8 @@ export default {
|
|||
|
||||
&.active,
|
||||
&:hover,
|
||||
&:focus {
|
||||
border: 2px solid var(--color-primary);
|
||||
&:focus {
|
||||
border: 2px solid var(--color-primary);
|
||||
}
|
||||
|
||||
&.active:not(.icon-loading):after {
|
||||
|
@ -178,6 +178,10 @@ export default {
|
|||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
|
||||
body.theme--dark & {
|
||||
background-image: var(--icon-checkmark-000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
@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-away {
|
||||
@include icon-color('user-status-away', 'user_status', '#F4A331', 2);
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -360,6 +360,12 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.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');
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue