wip ref(settings): move out group managment from settings

This commit is contained in:
Clem Fern 2023-07-23 17:18:26 +02:00
parent 21df033012
commit 1903ec5995
3 changed files with 48 additions and 65 deletions

View File

@ -24,8 +24,10 @@
type='text', type='text',
alwaysVisibleTypeahead, alwaysVisibleTypeahead,
placeholder='Ungrouped', placeholder='Ungrouped',
[(ngModel)]='profile.group', [(ngModel)]='profileGroup',
[ngbTypeahead]='groupTypeahead', [ngbTypeahead]='groupTypeahead',
[inputFormatter]="groupFormatter",
[resultFormatter]="groupFormatter",
) )
.mb-3(*ngIf='!defaultsMode') .mb-3(*ngIf='!defaultsMode')

View File

@ -2,7 +2,8 @@
import { Observable, OperatorFunction, debounceTime, map, distinctUntilChanged } from 'rxjs' import { Observable, OperatorFunction, debounceTime, map, distinctUntilChanged } from 'rxjs'
import { Component, Input, ViewChild, ViewContainerRef, ComponentFactoryResolver, Injector } from '@angular/core' import { Component, Input, ViewChild, ViewContainerRef, ComponentFactoryResolver, Injector } from '@angular/core'
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigProxy, ConfigService, Profile, ProfileProvider, ProfileSettingsComponent, ProfilesService, TAB_COLORS } from 'tabby-core' import { ConfigProxy, ConfigService, PartialProfileGroup, Profile, ProfileProvider, ProfileSettingsComponent, ProfilesService, TAB_COLORS, ProfileGroup } from 'tabby-core'
import { v4 as uuidv4 } from 'uuid'
const iconsData = require('../../../tabby-core/src/icons.json') const iconsData = require('../../../tabby-core/src/icons.json')
const iconsClassList = Object.keys(iconsData).map( const iconsClassList = Object.keys(iconsData).map(
@ -20,7 +21,8 @@ export class EditProfileModalComponent<P extends Profile> {
@Input() profileProvider: ProfileProvider<P> @Input() profileProvider: ProfileProvider<P>
@Input() settingsComponent: new () => ProfileSettingsComponent<P> @Input() settingsComponent: new () => ProfileSettingsComponent<P>
@Input() defaultsMode = false @Input() defaultsMode = false
groupNames: string[] @Input() profileGroup: PartialProfileGroup<ProfileGroup> | string | undefined
groups: PartialProfileGroup<ProfileGroup>[]
@ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef @ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef
private _profile: Profile private _profile: Profile
@ -33,11 +35,12 @@ export class EditProfileModalComponent<P extends Profile> {
config: ConfigService, config: ConfigService,
private modalInstance: NgbActiveModal, private modalInstance: NgbActiveModal,
) { ) {
this.groupNames = [...new Set( if (!this.defaultsMode) {
(config.store.profiles as Profile[]) this.profilesService.getProfileGroups().then(groups => {
.map(x => x.group) this.groups = groups
.filter(x => !!x), this.profileGroup = groups.find(g => g.id === this.profile.group)
)].sort() as string[] })
}
} }
colorsAutocomplete = text$ => text$.pipe( colorsAutocomplete = text$ => text$.pipe(
@ -72,13 +75,15 @@ export class EditProfileModalComponent<P extends Profile> {
} }
} }
groupTypeahead = (text$: Observable<string>) => groupTypeahead: OperatorFunction<string, readonly PartialProfileGroup<ProfileGroup>[]> = (text$: Observable<string>) =>
text$.pipe( text$.pipe(
debounceTime(200), debounceTime(200),
distinctUntilChanged(), distinctUntilChanged(),
map(q => this.groupNames.filter(x => !q || x.toLowerCase().includes(q.toLowerCase()))), map(q => this.groups.filter(g => !q || g.name.toLowerCase().includes(q.toLowerCase()))),
) )
groupFormatter = (g: PartialProfileGroup<ProfileGroup>) => g.name
iconSearch: OperatorFunction<string, string[]> = (text$: Observable<string>) => iconSearch: OperatorFunction<string, string[]> = (text$: Observable<string>) =>
text$.pipe( text$.pipe(
debounceTime(200), debounceTime(200),
@ -86,7 +91,20 @@ export class EditProfileModalComponent<P extends Profile> {
) )
save () { save () {
this.profile.group ||= undefined if (!this.profileGroup) {
this.profile.group = undefined
} else {
if (typeof this.profileGroup === 'string') {
const newGroup: PartialProfileGroup<ProfileGroup> = {
id: uuidv4(),
name: this.profileGroup
}
this.groups.push(newGroup)
this.profileGroup = newGroup
}
this.profile.group = this.profileGroup.id
}
this.settingsComponentInstance?.save?.() this.settingsComponentInstance?.save?.()
this.profile.__cleanup() this.profile.__cleanup()
this.modalInstance.close(this._profile) this.modalInstance.close(this._profile)

View File

@ -4,16 +4,9 @@ import slugify from 'slugify'
import deepClone from 'clone-deep' import deepClone from 'clone-deep'
import { Component, Inject } from '@angular/core' import { Component, Inject } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService, Platform, AppHotkeyProvider } from 'tabby-core' import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService, Platform, AppHotkeyProvider, ProfileGroup, PartialProfileGroup } from 'tabby-core'
import { EditProfileModalComponent } from './editProfileModal.component' import { EditProfileModalComponent } from './editProfileModal.component'
interface ProfileGroup {
name?: string
profiles: PartialProfile<Profile>[]
editable: boolean
collapsed: boolean
}
_('Filter') _('Filter')
_('Ungrouped') _('Ungrouped')
@ -26,7 +19,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
profiles: PartialProfile<Profile>[] = [] profiles: PartialProfile<Profile>[] = []
builtinProfiles: PartialProfile<Profile>[] = [] builtinProfiles: PartialProfile<Profile>[] = []
templateProfiles: PartialProfile<Profile>[] = [] templateProfiles: PartialProfile<Profile>[] = []
profileGroups: ProfileGroup[] profileGroups: PartialProfileGroup<ProfileGroup>[]
filter = '' filter = ''
Platform = Platform Platform = Platform
@ -158,55 +151,27 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
} }
} }
refresh (): void { async refresh (): Promise<void> {
this.profiles = this.config.store.profiles this.profiles = this.config.store.profiles
this.profileGroups = [] const groups = await this.profilesService.getProfileGroups(true, true)
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}') groups.sort((a, b) => a.name.localeCompare(b.name))
groups.sort((a, b) => (a.id === 'built-in' ? 1 : 0) - (b.id === 'built-in' ? 1 : 0))
for (const profile of this.profiles) { groups.sort((a, b) => (a.id === 'ungrouped' ? 0 : 1) - (b.id === 'ungrouped' ? 0 : 1))
// Group null, undefined and empty together this.profileGroups = groups
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
let group = this.profileGroups.find(x => x.name === (profile.group || ''))
if (!group) {
group = {
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
name: profile.group || '',
profiles: [],
editable: true,
collapsed: profileGroupCollapsed[profile.group ?? ''] ?? false,
}
this.profileGroups.push(group)
}
group.profiles.push(profile)
} }
this.profileGroups.sort((a, b) => a.name?.localeCompare(b.name ?? '') ?? -1) async editGroup (group: PartialProfileGroup<ProfileGroup>): Promise<void> {
const builtIn = {
name: this.translate.instant('Built-in'),
profiles: this.builtinProfiles,
editable: false,
collapsed: false,
}
builtIn.collapsed = profileGroupCollapsed[builtIn.name ?? ''] ?? false
this.profileGroups.push(builtIn)
}
async editGroup (group: ProfileGroup): Promise<void> {
const modal = this.ngbModal.open(PromptModalComponent) const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = this.translate.instant('New name') modal.componentInstance.prompt = this.translate.instant('New name')
modal.componentInstance.value = group.name modal.componentInstance.value = group.name
const result = await modal.result const result = await modal.result
if (result) { if (result) {
for (const profile of this.profiles.filter(x => x.group === group.name)) { group.name = result.value
profile.group = result.value
}
this.config.store.profiles = this.profiles
await this.config.save() await this.config.save()
} }
} }
async deleteGroup (group: ProfileGroup): Promise<void> { async deleteGroup (group: PartialProfileGroup<ProfileGroup>): Promise<void> {
if ((await this.platform.showMessageBox( if ((await this.platform.showMessageBox(
{ {
type: 'warning', type: 'warning',
@ -231,18 +196,18 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
cancelId: 0, cancelId: 0,
}, },
)).response === 0) { )).response === 0) {
for (const profile of this.profiles.filter(x => x.group === group.name)) { for (const profile of this.profiles.filter(x => x.group === group.id)) {
delete profile.group delete profile.group
} }
} else { } else {
this.config.store.profiles = this.config.store.profiles.filter(x => x.group !== group.name) this.config.store.profiles = this.config.store.profiles.filter(x => x.group !== group.id)
} }
await this.config.save() await this.config.save()
} }
} }
isGroupVisible (group: ProfileGroup): boolean { isGroupVisible (group: PartialProfileGroup<ProfileGroup>): boolean {
return !this.filter || group.profiles.some(x => this.isProfileVisible(x)) return !this.filter || (group.profiles ?? []).some(x => this.isProfileVisible(x))
} }
isProfileVisible (profile: PartialProfile<Profile>): boolean { isProfileVisible (profile: PartialProfile<Profile>): boolean {
@ -270,11 +235,9 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
}[this.profilesService.providerForProfile(profile)?.id ?? ''] ?? 'warning' }[this.profilesService.providerForProfile(profile)?.id ?? ''] ?? 'warning'
} }
toggleGroupCollapse (group: ProfileGroup): void { toggleGroupCollapse (group: PartialProfileGroup<ProfileGroup>): void {
group.collapsed = !group.collapsed group.collapsed = !group.collapsed
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}') this.profilesService.saveProfileGroupCollapse(group)
profileGroupCollapsed[group.name ?? ''] = group.collapsed
window.localStorage.profileGroupCollapsed = JSON.stringify(profileGroupCollapsed)
} }
async editDefaults (provider: ProfileProvider<Profile>): Promise<void> { async editDefaults (provider: ProfileProvider<Profile>): Promise<void> {