paperless-ngx/src-ui/src/app/services/settings.service.ts

641 lines
16 KiB
TypeScript
Raw Normal View History

import { DOCUMENT } from '@angular/common'
2022-05-07 00:05:51 -07:00
import { HttpClient } from '@angular/common/http'
import {
EventEmitter,
Inject,
Injectable,
LOCALE_ID,
Renderer2,
RendererFactory2,
} from '@angular/core'
import { Meta } from '@angular/platform-browser'
import { CookieService } from 'ngx-cookie-service'
import { first, Observable, tap } from 'rxjs'
import {
BRIGHTNESS,
estimateBrightnessForColor,
hexToHsl,
} from 'src/app/utils/color'
2022-05-07 00:05:51 -07:00
import { environment } from 'src/environments/environment'
2023-12-19 22:36:35 -08:00
import { UiSettings, SETTINGS, SETTINGS_KEYS } from '../data/ui-settings'
import { User } from '../data/user'
import {
PermissionAction,
PermissionType,
PermissionsService,
} from './permissions.service'
2022-05-07 01:53:37 -07:00
import { ToastService } from './toast.service'
2023-12-19 22:36:35 -08:00
import { SavedView } from '../data/saved-view'
import { CustomFieldsService } from './rest/custom-fields.service'
import { DEFAULT_DISPLAY_FIELDS, DisplayField } from '../data/document'
2020-12-29 17:09:07 +01:00
export interface LanguageOption {
code: string
name: string
englishName?: string
/**
* A date format string for use by the date selectors. MUST contain 'yyyy', 'mm' and 'dd'.
*/
dateInputFormat?: string
}
2023-12-19 15:02:05 -08:00
const LANGUAGE_OPTIONS = [
{
code: 'en-us',
name: $localize`English (US)`,
englishName: 'English (US)',
dateInputFormat: 'mm/dd/yyyy',
},
{
code: 'af-za',
name: $localize`Afrikaans`,
englishName: 'Afrikaans',
dateInputFormat: 'yyyy-mm-dd',
},
{
code: 'ar-ar',
name: $localize`Arabic`,
englishName: 'Arabic',
dateInputFormat: 'yyyy-mm-dd',
},
{
code: 'be-by',
name: $localize`Belarusian`,
englishName: 'Belarusian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'bg-bg',
name: $localize`Bulgarian`,
englishName: 'Bulgarian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'ca-es',
name: $localize`Catalan`,
englishName: 'Catalan',
dateInputFormat: 'dd/mm/yyyy',
},
{
code: 'cs-cz',
name: $localize`Czech`,
englishName: 'Czech',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'da-dk',
name: $localize`Danish`,
englishName: 'Danish',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'de-de',
name: $localize`German`,
englishName: 'German',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'el-gr',
name: $localize`Greek`,
englishName: 'Greek',
dateInputFormat: 'dd/mm/yyyy',
},
{
code: 'en-gb',
name: $localize`English (GB)`,
englishName: 'English (GB)',
dateInputFormat: 'dd/mm/yyyy',
},
{
code: 'es-es',
name: $localize`Spanish`,
englishName: 'Spanish',
dateInputFormat: 'dd/mm/yyyy',
},
{
code: 'fi-fi',
name: $localize`Finnish`,
englishName: 'Finnish',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'fr-fr',
name: $localize`French`,
englishName: 'French',
dateInputFormat: 'dd/mm/yyyy',
},
{
code: 'hu-hu',
name: $localize`Hungarian`,
englishName: 'Hungarian',
dateInputFormat: 'yyyy.mm.dd',
},
{
code: 'it-it',
name: $localize`Italian`,
englishName: 'Italian',
dateInputFormat: 'dd/mm/yyyy',
},
2024-02-03 11:37:21 -08:00
{
code: 'ja-jp',
name: $localize`Japanese`,
englishName: 'Japanese',
dateInputFormat: 'yyyy/mm/dd',
},
2023-12-19 15:02:05 -08:00
{
code: 'lb-lu',
name: $localize`Luxembourgish`,
englishName: 'Luxembourgish',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'nl-nl',
name: $localize`Dutch`,
englishName: 'Dutch',
dateInputFormat: 'dd-mm-yyyy',
},
{
code: 'no-no',
name: $localize`Norwegian`,
englishName: 'Norwegian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'pl-pl',
name: $localize`Polish`,
englishName: 'Polish',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'pt-br',
name: $localize`Portuguese (Brazil)`,
englishName: 'Portuguese (Brazil)',
dateInputFormat: 'dd/mm/yyyy',
},
{
code: 'pt-pt',
name: $localize`Portuguese`,
englishName: 'Portuguese',
dateInputFormat: 'dd/mm/yyyy',
},
{
code: 'ro-ro',
name: $localize`Romanian`,
englishName: 'Romanian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'ru-ru',
name: $localize`Russian`,
englishName: 'Russian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'sk-sk',
name: $localize`Slovak`,
englishName: 'Slovak',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'sl-si',
name: $localize`Slovenian`,
englishName: 'Slovenian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'sr-cs',
name: $localize`Serbian`,
englishName: 'Serbian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'sv-se',
name: $localize`Swedish`,
englishName: 'Swedish',
dateInputFormat: 'yyyy-mm-dd',
},
{
code: 'tr-tr',
name: $localize`Turkish`,
englishName: 'Turkish',
dateInputFormat: 'yyyy-mm-dd',
},
{
code: 'uk-ua',
name: $localize`Ukrainian`,
englishName: 'Ukrainian',
dateInputFormat: 'dd.mm.yyyy',
},
{
code: 'zh-cn',
name: $localize`Chinese Simplified`,
englishName: 'Chinese Simplified',
dateInputFormat: 'yyyy-mm-dd',
},
]
const ISO_LANGUAGE_OPTION: LanguageOption = {
code: 'iso-8601',
name: $localize`ISO 8601`,
dateInputFormat: 'yyyy-mm-dd',
}
2020-12-29 17:09:07 +01:00
@Injectable({
providedIn: 'root',
2020-12-29 17:09:07 +01:00
})
export class SettingsService {
2022-05-07 08:11:10 -07:00
protected baseUrl: string = environment.apiBaseUrl + 'ui_settings/'
2022-05-07 00:05:51 -07:00
private settings: Object = {}
2023-12-19 22:36:35 -08:00
currentUser: User
2022-05-09 11:08:28 -07:00
public settingsSaved: EventEmitter<any> = new EventEmitter()
frontend unit tests toasts component testing conditional import of angular setup-jest for vscode-jest support Update jest.config.js Create open-documents.service.spec.ts Add unit tests for all REST services settings service test Remove component from settings service test Create permissions.service.spec.ts upload documents service tests Update package.json Create toast.service.spec.ts Tasks service test Statistics widget component tests Update permissions.service.ts Create app.component.spec.ts settings component testing tasks component unit testing Management list component generic tests Some management component tests document notes component unit tests Create document-list.component.spec.ts Create save-view-config-dialog.component.spec.ts Create filter-editor.component.spec.ts small and large document cards unit testing Create bulk-editor.component.spec.ts document detail unit tests saving work on documentdetail component spec Create document-asn.component.spec.ts dashboard & widgets unit testing Fix ResizeObserver mock common component unit tests fix some merge errors Update app-frame.component.spec.ts Create page-header.component.spec.ts input component unit tests FilterableDropdownComponent unit testing and found minor errors update taskservice unit tests Edit dialogs unit tests Create date-dropdown.component.spec.ts Remove selectors from guard tests confirm dialog component tests app frame component test Miscellaneous component tests Update document-list-view.service.spec.ts directives unit tests Remove unused resizeobserver mock guard unit tests Update query-params.spec.ts try to fix flaky playwright filter rules utils & testing Interceptor unit tests Pipes unit testing Utils unit tests Update upload-documents.service.spec.ts consumer status service tests Update setup-jest.ts Create document-list-view.service.spec.ts Update app-routing.module.ts
2023-05-23 15:02:54 -07:00
private _renderer: Renderer2
public get renderer(): Renderer2 {
return this._renderer
}
public dashboardIsEmpty: boolean = false
public globalDropzoneEnabled: boolean = true
public globalDropzoneActive: boolean = false
public organizingSidebarSavedViews: boolean = false
private _allDisplayFields: Array<{ id: DisplayField; name: string }> =
DEFAULT_DISPLAY_FIELDS
public get allDisplayFields(): Array<{ id: DisplayField; name: string }> {
return this._allDisplayFields
}
2021-01-01 22:38:26 +01:00
constructor(
2022-05-07 00:05:51 -07:00
rendererFactory: RendererFactory2,
2021-01-15 12:50:34 +01:00
@Inject(DOCUMENT) private document,
private cookieService: CookieService,
private meta: Meta,
2022-05-07 00:05:51 -07:00
@Inject(LOCALE_ID) private localeId: string,
2022-05-07 01:53:37 -07:00
protected http: HttpClient,
private toastService: ToastService,
private permissionsService: PermissionsService,
private customFieldsService: CustomFieldsService
2021-01-01 22:38:26 +01:00
) {
frontend unit tests toasts component testing conditional import of angular setup-jest for vscode-jest support Update jest.config.js Create open-documents.service.spec.ts Add unit tests for all REST services settings service test Remove component from settings service test Create permissions.service.spec.ts upload documents service tests Update package.json Create toast.service.spec.ts Tasks service test Statistics widget component tests Update permissions.service.ts Create app.component.spec.ts settings component testing tasks component unit testing Management list component generic tests Some management component tests document notes component unit tests Create document-list.component.spec.ts Create save-view-config-dialog.component.spec.ts Create filter-editor.component.spec.ts small and large document cards unit testing Create bulk-editor.component.spec.ts document detail unit tests saving work on documentdetail component spec Create document-asn.component.spec.ts dashboard & widgets unit testing Fix ResizeObserver mock common component unit tests fix some merge errors Update app-frame.component.spec.ts Create page-header.component.spec.ts input component unit tests FilterableDropdownComponent unit testing and found minor errors update taskservice unit tests Edit dialogs unit tests Create date-dropdown.component.spec.ts Remove selectors from guard tests confirm dialog component tests app frame component test Miscellaneous component tests Update document-list-view.service.spec.ts directives unit tests Remove unused resizeobserver mock guard unit tests Update query-params.spec.ts try to fix flaky playwright filter rules utils & testing Interceptor unit tests Pipes unit testing Utils unit tests Update upload-documents.service.spec.ts consumer status service tests Update setup-jest.ts Create document-list-view.service.spec.ts Update app-routing.module.ts
2023-05-23 15:02:54 -07:00
this._renderer = rendererFactory.createRenderer(null, null)
2022-05-07 00:05:51 -07:00
}
// this is called by the app initializer in app.module
2023-12-19 22:36:35 -08:00
public initializeSettings(): Observable<UiSettings> {
return this.http.get<UiSettings>(this.baseUrl).pipe(
2022-05-17 16:12:59 -07:00
first(),
tap((uisettings) => {
Object.assign(this.settings, uisettings.settings)
2024-01-13 11:57:25 -08:00
if (this.get(SETTINGS_KEYS.APP_TITLE)?.length) {
environment.appTitle = this.get(SETTINGS_KEYS.APP_TITLE)
}
2022-05-17 16:12:59 -07:00
this.maybeMigrateSettings()
// to update lang cookie
if (this.settings['language']?.length)
this.setLanguage(this.settings['language'])
2023-03-03 19:50:06 -08:00
this.currentUser = uisettings.user
this.permissionsService.initialize(
uisettings.permissions,
this.currentUser
)
this.initializeDisplayFields()
2022-05-17 16:12:59 -07:00
})
)
2021-01-01 22:38:26 +01:00
}
public initializeDisplayFields() {
this._allDisplayFields = DEFAULT_DISPLAY_FIELDS
this._allDisplayFields = this._allDisplayFields
?.map((field) => {
if (
field.id === DisplayField.NOTES &&
!this.get(SETTINGS_KEYS.NOTES_ENABLED)
) {
return null
}
if (
[
DisplayField.TITLE,
DisplayField.CREATED,
DisplayField.ADDED,
DisplayField.ASN,
DisplayField.SHARED,
].includes(field.id)
) {
return field
}
let type: PermissionType = Object.values(PermissionType).find((t) =>
t.includes(field.id)
)
if (field.id === DisplayField.OWNER) {
type = PermissionType.User
}
return this.permissionsService.currentUserCan(
PermissionAction.View,
type
)
? field
: null
})
.filter((f) => f)
if (
this.permissionsService.currentUserCan(
PermissionAction.View,
PermissionType.CustomField
)
) {
this.customFieldsService.listAll().subscribe((r) => {
this._allDisplayFields = this._allDisplayFields.concat(
r.results.map((field) => {
return {
id: `${DisplayField.CUSTOM_FIELD}${field.id}` as any,
name: field.name,
}
})
)
})
}
}
get displayName(): string {
return (
this.currentUser.first_name ??
this.currentUser.username ??
''
).trim()
}
public updateAppearanceSettings(
darkModeUseSystem = null,
darkModeEnabled = null,
themeColor = null
): void {
darkModeUseSystem ??= this.get(SETTINGS_KEYS.DARK_MODE_USE_SYSTEM)
darkModeEnabled ??= this.get(SETTINGS_KEYS.DARK_MODE_ENABLED)
themeColor ??= this.get(SETTINGS_KEYS.THEME_COLOR)
2021-01-01 22:38:26 +01:00
if (darkModeUseSystem) {
this._renderer.setAttribute(
this.document.documentElement,
'data-bs-theme',
'auto'
)
2021-01-01 22:38:26 +01:00
} else {
this._renderer.setAttribute(
this.document.documentElement,
'data-bs-theme',
darkModeEnabled ? 'dark' : 'light'
)
2021-01-01 22:38:26 +01:00
}
if (themeColor) {
2022-03-09 15:34:26 -08:00
const hsl = hexToHsl(themeColor)
const bgBrightnessEstimate = estimateBrightnessForColor(themeColor)
if (bgBrightnessEstimate == BRIGHTNESS.DARK) {
frontend unit tests toasts component testing conditional import of angular setup-jest for vscode-jest support Update jest.config.js Create open-documents.service.spec.ts Add unit tests for all REST services settings service test Remove component from settings service test Create permissions.service.spec.ts upload documents service tests Update package.json Create toast.service.spec.ts Tasks service test Statistics widget component tests Update permissions.service.ts Create app.component.spec.ts settings component testing tasks component unit testing Management list component generic tests Some management component tests document notes component unit tests Create document-list.component.spec.ts Create save-view-config-dialog.component.spec.ts Create filter-editor.component.spec.ts small and large document cards unit testing Create bulk-editor.component.spec.ts document detail unit tests saving work on documentdetail component spec Create document-asn.component.spec.ts dashboard & widgets unit testing Fix ResizeObserver mock common component unit tests fix some merge errors Update app-frame.component.spec.ts Create page-header.component.spec.ts input component unit tests FilterableDropdownComponent unit testing and found minor errors update taskservice unit tests Edit dialogs unit tests Create date-dropdown.component.spec.ts Remove selectors from guard tests confirm dialog component tests app frame component test Miscellaneous component tests Update document-list-view.service.spec.ts directives unit tests Remove unused resizeobserver mock guard unit tests Update query-params.spec.ts try to fix flaky playwright filter rules utils & testing Interceptor unit tests Pipes unit testing Utils unit tests Update upload-documents.service.spec.ts consumer status service tests Update setup-jest.ts Create document-list-view.service.spec.ts Update app-routing.module.ts
2023-05-23 15:02:54 -07:00
this._renderer.addClass(this.document.body, 'primary-dark')
this._renderer.removeClass(this.document.body, 'primary-light')
} else {
frontend unit tests toasts component testing conditional import of angular setup-jest for vscode-jest support Update jest.config.js Create open-documents.service.spec.ts Add unit tests for all REST services settings service test Remove component from settings service test Create permissions.service.spec.ts upload documents service tests Update package.json Create toast.service.spec.ts Tasks service test Statistics widget component tests Update permissions.service.ts Create app.component.spec.ts settings component testing tasks component unit testing Management list component generic tests Some management component tests document notes component unit tests Create document-list.component.spec.ts Create save-view-config-dialog.component.spec.ts Create filter-editor.component.spec.ts small and large document cards unit testing Create bulk-editor.component.spec.ts document detail unit tests saving work on documentdetail component spec Create document-asn.component.spec.ts dashboard & widgets unit testing Fix ResizeObserver mock common component unit tests fix some merge errors Update app-frame.component.spec.ts Create page-header.component.spec.ts input component unit tests FilterableDropdownComponent unit testing and found minor errors update taskservice unit tests Edit dialogs unit tests Create date-dropdown.component.spec.ts Remove selectors from guard tests confirm dialog component tests app frame component test Miscellaneous component tests Update document-list-view.service.spec.ts directives unit tests Remove unused resizeobserver mock guard unit tests Update query-params.spec.ts try to fix flaky playwright filter rules utils & testing Interceptor unit tests Pipes unit testing Utils unit tests Update upload-documents.service.spec.ts consumer status service tests Update setup-jest.ts Create document-list-view.service.spec.ts Update app-routing.module.ts
2023-05-23 15:02:54 -07:00
this._renderer.addClass(this.document.body, 'primary-light')
this._renderer.removeClass(this.document.body, 'primary-dark')
}
document.documentElement.style.setProperty(
'--pngx-primary',
`${+hsl.h * 360},${hsl.s * 100}%`
)
document.documentElement.style.setProperty(
'--pngx-primary-lightness',
`${hsl.l * 100}%`
)
2022-03-09 15:19:42 -08:00
} else {
this._renderer.removeClass(this.document.body, 'primary-dark')
this._renderer.removeClass(this.document.body, 'primary-light')
document.documentElement.style.removeProperty('--pngx-primary')
document.documentElement.style.removeProperty('--pngx-primary-lightness')
}
2021-01-01 22:38:26 +01:00
}
2020-12-29 17:09:07 +01:00
getLanguageOptions(): LanguageOption[] {
// Sort languages by localized name at runtime
2023-12-19 15:02:05 -08:00
return LANGUAGE_OPTIONS.sort((a, b) => {
return a.name < b.name ? -1 : 1
})
2021-01-15 12:50:34 +01:00
}
getDateLocaleOptions(): LanguageOption[] {
2023-12-19 15:02:05 -08:00
return [ISO_LANGUAGE_OPTION].concat(this.getLanguageOptions())
}
2021-01-15 12:50:34 +01:00
private getLanguageCookieName() {
let prefix = ''
2021-01-15 12:50:34 +01:00
if (this.meta.getTag('name=cookie_prefix')) {
prefix = this.meta.getTag('name=cookie_prefix').content
}
return `${prefix || ''}django_language`
}
getLanguage(): string {
2022-05-07 02:14:20 -07:00
return this.get(SETTINGS_KEYS.LANGUAGE)
2021-01-15 12:50:34 +01:00
}
setLanguage(language: string) {
2022-05-07 02:14:20 -07:00
this.set(SETTINGS_KEYS.LANGUAGE, language)
if (language?.length) {
// for Django
2021-01-15 12:50:34 +01:00
this.cookieService.set(this.getLanguageCookieName(), language)
} else {
this.cookieService.delete(this.getLanguageCookieName())
}
}
getLocalizedDateInputFormat(): string {
let dateLocale =
this.get(SETTINGS_KEYS.DATE_LOCALE) ||
this.getLanguage() ||
this.localeId.toLowerCase()
return (
this.getDateLocaleOptions().find((o) => o.code == dateLocale)
?.dateInputFormat || 'yyyy-mm-dd'
)
}
2022-09-30 12:30:23 -07:00
private getSettingRawValue(key: string): any {
let value = undefined
2022-05-07 00:05:51 -07:00
// parse key:key:key into nested object
const keys = key.replace('general-settings:', '').split(':')
let settingObj = this.settings
keys.forEach((keyPart, index) => {
keyPart = keyPart.replace(/-/g, '_')
if (!settingObj.hasOwnProperty(keyPart)) return
if (index == keys.length - 1) value = settingObj[keyPart]
else settingObj = settingObj[keyPart]
})
2022-09-30 12:30:23 -07:00
return value
}
get(key: string): any {
let setting = SETTINGS.find((s) => s.key == key)
if (!setting) {
return undefined
2022-09-30 12:30:23 -07:00
}
let value = this.getSettingRawValue(key)
2020-12-29 17:09:07 +01:00
// special case to fallback
if (key === SETTINGS_KEYS.DEFAULT_PERMS_OWNER && value === undefined) {
return this.currentUser.id
}
if (value !== undefined) {
if (value === null) {
return null
}
2020-12-29 17:09:07 +01:00
switch (setting.type) {
case 'boolean':
2020-12-29 17:09:07 +01:00
return JSON.parse(value)
case 'number':
2020-12-29 17:09:07 +01:00
return +value
case 'string':
2020-12-29 17:09:07 +01:00
return value
default:
return value
}
} else {
return setting.default
}
}
set(key: string, value: any) {
2022-05-07 00:05:51 -07:00
// parse key:key:key into nested object
let settingObj = this.settings
const keys = key.replace('general-settings:', '').split(':')
keys.forEach((keyPart, index) => {
keyPart = keyPart.replace(/-/g, '_')
if (!settingObj.hasOwnProperty(keyPart)) settingObj[keyPart] = {}
if (index == keys.length - 1) settingObj[keyPart] = value
else settingObj = settingObj[keyPart]
})
2020-12-29 17:09:07 +01:00
}
2022-09-30 12:30:23 -07:00
private settingIsSet(key: string): boolean {
let value = this.getSettingRawValue(key)
return value != undefined
2022-09-30 12:30:23 -07:00
}
2022-05-07 00:05:51 -07:00
storeSettings(): Observable<any> {
return this.http.post(this.baseUrl, { settings: this.settings }).pipe(
tap((results) => {
if (results.success) {
this.settingsSaved.emit()
}
})
)
2020-12-29 17:09:07 +01:00
}
2022-05-07 01:53:37 -07:00
maybeMigrateSettings() {
if (
!this.settings.hasOwnProperty('documentListSize') &&
localStorage.getItem(SETTINGS_KEYS.DOCUMENT_LIST_SIZE)
) {
// lets migrate
const successMessage = $localize`Successfully completed one-time migratration of settings to the database!`
const errorMessage = $localize`Unable to migrate settings to the database, please try saving manually.`
try {
for (const setting in SETTINGS_KEYS) {
const key = SETTINGS_KEYS[setting]
const value = localStorage.getItem(key)
this.set(key, value)
}
2022-05-07 02:14:20 -07:00
this.set(
SETTINGS_KEYS.LANGUAGE,
this.cookieService.get(this.getLanguageCookieName())
)
2022-05-07 01:53:37 -07:00
} catch (error) {
this.toastService.showError(errorMessage)
console.log(error)
}
this.storeSettings()
.pipe(first())
.subscribe({
next: () => {
this.updateAppearanceSettings()
this.toastService.showInfo(successMessage)
},
error: (e) => {
this.toastService.showError(errorMessage)
console.log(e)
},
})
}
2022-09-30 12:30:23 -07:00
if (
!this.settingIsSet(SETTINGS_KEYS.UPDATE_CHECKING_ENABLED) &&
this.get(SETTINGS_KEYS.UPDATE_CHECKING_BACKEND_SETTING) != 'default'
2022-09-30 12:30:23 -07:00
) {
this.set(
SETTINGS_KEYS.UPDATE_CHECKING_ENABLED,
this.get(SETTINGS_KEYS.UPDATE_CHECKING_BACKEND_SETTING).toString() ===
'true'
)
this.storeSettings()
.pipe(first())
.subscribe({
error: (e) => {
this.toastService.showError(
'Error migrating update checking setting'
)
console.log(e)
},
})
2022-09-30 12:30:23 -07:00
}
}
get updateCheckingIsSet(): boolean {
return this.settingIsSet(SETTINGS_KEYS.UPDATE_CHECKING_ENABLED)
2022-09-30 12:30:23 -07:00
}
2022-09-21 21:44:15 -07:00
offerTour(): boolean {
return this.dashboardIsEmpty && !this.get(SETTINGS_KEYS.TOUR_COMPLETE)
2022-09-21 21:44:15 -07:00
}
completeTour() {
const tourCompleted = this.get(SETTINGS_KEYS.TOUR_COMPLETE)
if (!tourCompleted) {
this.set(SETTINGS_KEYS.TOUR_COMPLETE, true)
this.storeSettings()
.pipe(first())
.subscribe(() => {
this.toastService.showInfo(
$localize`You can restart the tour from the settings page.`
)
})
}
}
2023-12-19 22:36:35 -08:00
updateDashboardViewsSort(dashboardViews: SavedView[]): Observable<any> {
this.set(SETTINGS_KEYS.DASHBOARD_VIEWS_SORT_ORDER, [
...new Set(dashboardViews.map((v) => v.id)),
])
return this.storeSettings()
}
2023-12-19 22:36:35 -08:00
updateSidebarViewsSort(sidebarViews: SavedView[]): Observable<any> {
this.set(SETTINGS_KEYS.SIDEBAR_VIEWS_SORT_ORDER, [
...new Set(sidebarViews.map((v) => v.id)),
])
return this.storeSettings()
}
2020-12-29 17:09:07 +01:00
}