mirror of
https://github.com/Eugeny/tabby.git
synced 2025-06-08 13:30:02 +00:00
feat(core/settings): Eugeny/tabby#3999 Allow groups to specify settings that hosts inherit
This commit is contained in:
parent
0ef24ddf1d
commit
695c5ba670
@ -65,8 +65,8 @@ export class ProfilesService {
|
|||||||
* Return ConfigProxy for a given Profile
|
* Return ConfigProxy for a given Profile
|
||||||
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
|
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
|
||||||
*/
|
*/
|
||||||
getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>, skipUserDefaults = false): T {
|
getConfigProxyForProfile <T extends Profile> (profile: PartialProfile<T>, skipGlobalDefaults = false, skipGroupDefaults = false): T {
|
||||||
const defaults = this.getProfileDefaults(profile, skipUserDefaults).reduce(configMerge, {})
|
const defaults = this.getProfileDefaults(profile, skipGlobalDefaults, skipGroupDefaults).reduce(configMerge, {})
|
||||||
return new ConfigProxy(profile, defaults) as unknown as T
|
return new ConfigProxy(profile, defaults) as unknown as T
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,12 +373,14 @@ export class ProfilesService {
|
|||||||
* Always return something, empty object if no defaults found
|
* Always return something, empty object if no defaults found
|
||||||
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
|
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
|
||||||
*/
|
*/
|
||||||
getProfileDefaults (profile: PartialProfile<Profile>, skipUserDefaults = false): any {
|
getProfileDefaults (profile: PartialProfile<Profile>, skipGlobalDefaults = false, skipGroupDefaults = false): any[] {
|
||||||
const provider = this.providerForProfile(profile)
|
const provider = this.providerForProfile(profile)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
this.profileDefaults,
|
this.profileDefaults,
|
||||||
provider?.configDefaults ?? {},
|
provider?.configDefaults ?? {},
|
||||||
!provider || skipUserDefaults ? {} : this.getProviderDefaults(provider),
|
provider && !skipGlobalDefaults ? this.getProviderDefaults(provider) : {},
|
||||||
|
provider && !skipGlobalDefaults && !skipGroupDefaults ? this.getProviderProfileGroupDefaults(profile.group ?? '', provider) : {},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,6 +388,14 @@ export class ProfilesService {
|
|||||||
* Methods used to interract with ProfileGroup
|
* Methods used to interract with ProfileGroup
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronously return an Array of the existing ProfileGroups
|
||||||
|
* Does not return builtin groups
|
||||||
|
*/
|
||||||
|
getSyncProfileGroups (): PartialProfileGroup<ProfileGroup>[] {
|
||||||
|
return deepClone(this.config.store.groups ?? [])
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return an Array of the existing ProfileGroups
|
* Return an Array of the existing ProfileGroups
|
||||||
* arg: includeProfiles (default: false) -> if false, does not fill up the profiles field of ProfileGroup
|
* arg: includeProfiles (default: false) -> if false, does not fill up the profiles field of ProfileGroup
|
||||||
@ -397,7 +407,7 @@ export class ProfilesService {
|
|||||||
profiles = await this.getProfiles(includeNonUserGroup, true)
|
profiles = await this.getProfiles(includeNonUserGroup, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
let groups: PartialProfileGroup<ProfileGroup>[] = deepClone(this.config.store.groups ?? [])
|
let groups: PartialProfileGroup<ProfileGroup>[] = this.getSyncProfileGroups()
|
||||||
groups = groups.map(x => {
|
groups = groups.map(x => {
|
||||||
x.editable = true
|
x.editable = true
|
||||||
|
|
||||||
@ -516,4 +526,13 @@ export class ProfilesService {
|
|||||||
return this.config.store.groups.find(g => g.id === groupId)?.name ?? groupId
|
return this.config.store.groups.find(g => g.id === groupId)?.name ?? groupId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return defaults for a given group ID and provider
|
||||||
|
* Always return something, empty object if no defaults found
|
||||||
|
* arg: skipUserDefaults -> do not merge global provider defaults in ConfigProxy
|
||||||
|
*/
|
||||||
|
getProviderProfileGroupDefaults (groupId: string, provider: ProfileProvider<Profile>): any {
|
||||||
|
return this.getSyncProfileGroups().find(g => g.id === groupId)?.defaults?.[provider.id] ?? {}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
.modal-header
|
||||||
|
h3.m-0 {{group.name}}
|
||||||
|
|
||||||
|
.modal-body
|
||||||
|
.row
|
||||||
|
.col-12.col-lg-4
|
||||||
|
.mb-3
|
||||||
|
label(translate) Name
|
||||||
|
input.form-control(
|
||||||
|
type='text',
|
||||||
|
autofocus,
|
||||||
|
[(ngModel)]='group.name',
|
||||||
|
)
|
||||||
|
|
||||||
|
.col-12.col-lg-8
|
||||||
|
.form-line.content-box
|
||||||
|
.header
|
||||||
|
.title(translate) Default profile group settings
|
||||||
|
.description(translate) These apply to all profiles of a given type in this group
|
||||||
|
|
||||||
|
.list-group.mt-3.mb-3.content-box
|
||||||
|
a.list-group-item.list-group-item-action(
|
||||||
|
(click)='editDefaults(provider)',
|
||||||
|
*ngFor='let provider of providers'
|
||||||
|
) {{provider.name|translate}}
|
||||||
|
|
||||||
|
.modal-footer
|
||||||
|
button.btn.btn-primary((click)='save()', translate) Save
|
||||||
|
button.btn.btn-danger((click)='cancel()', translate) Cancel
|
@ -0,0 +1,34 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
|
||||||
|
import { ConfigProxy, ProfileGroup, Profile, ProfileProvider } from 'tabby-core'
|
||||||
|
|
||||||
|
/** @hidden */
|
||||||
|
@Component({
|
||||||
|
templateUrl: './editProfileGroupModal.component.pug',
|
||||||
|
})
|
||||||
|
export class EditProfileGroupModalComponent<G extends ProfileGroup> {
|
||||||
|
@Input() group: G & ConfigProxy
|
||||||
|
@Input() providers: ProfileProvider<Profile>[]
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private modalInstance: NgbActiveModal,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
save () {
|
||||||
|
this.modalInstance.close({ group: this.group })
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel () {
|
||||||
|
this.modalInstance.dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
editDefaults (provider: ProfileProvider<Profile>) {
|
||||||
|
this.modalInstance.close({ group: this.group, provider })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EditProfileGroupModalComponentResult<G extends ProfileGroup> {
|
||||||
|
group: G
|
||||||
|
provider?: ProfileProvider<Profile>
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
.modal-header(*ngIf='!defaultsMode')
|
.modal-header(*ngIf='defaultsMode === "disabled"')
|
||||||
h3.m-0 {{profile.name}}
|
h3.m-0 {{profile.name}}
|
||||||
|
|
||||||
.modal-header(*ngIf='defaultsMode')
|
.modal-header(*ngIf='defaultsMode !== "disabled"')
|
||||||
h3.m-0(
|
h3.m-0(
|
||||||
translate='Defaults for {type}',
|
translate='Defaults for {type}',
|
||||||
[translateParams]='{type: profileProvider.name}'
|
[translateParams]='{type: profileProvider.name}'
|
||||||
@ -10,7 +10,7 @@
|
|||||||
.modal-body
|
.modal-body
|
||||||
.row
|
.row
|
||||||
.col-12.col-lg-4
|
.col-12.col-lg-4
|
||||||
.mb-3(*ngIf='!defaultsMode')
|
.mb-3(*ngIf='defaultsMode === "disabled"')
|
||||||
label(translate) Name
|
label(translate) Name
|
||||||
input.form-control(
|
input.form-control(
|
||||||
type='text',
|
type='text',
|
||||||
@ -18,7 +18,7 @@
|
|||||||
[(ngModel)]='profile.name',
|
[(ngModel)]='profile.name',
|
||||||
)
|
)
|
||||||
|
|
||||||
.mb-3(*ngIf='!defaultsMode')
|
.mb-3(*ngIf='defaultsMode === "disabled"')
|
||||||
label(translate) Group
|
label(translate) Group
|
||||||
input.form-control(
|
input.form-control(
|
||||||
type='text',
|
type='text',
|
||||||
@ -28,9 +28,10 @@
|
|||||||
[ngbTypeahead]='groupTypeahead',
|
[ngbTypeahead]='groupTypeahead',
|
||||||
[inputFormatter]="groupFormatter",
|
[inputFormatter]="groupFormatter",
|
||||||
[resultFormatter]="groupFormatter",
|
[resultFormatter]="groupFormatter",
|
||||||
|
[editable]="false"
|
||||||
)
|
)
|
||||||
|
|
||||||
.mb-3(*ngIf='!defaultsMode')
|
.mb-3(*ngIf='defaultsMode === "disabled"')
|
||||||
label(translate) Icon
|
label(translate) Icon
|
||||||
.input-group
|
.input-group
|
||||||
input.form-control(
|
input.form-control(
|
||||||
|
@ -3,7 +3,6 @@ import { Observable, OperatorFunction, debounceTime, map, distinctUntilChanged }
|
|||||||
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, PartialProfileGroup, Profile, ProfileProvider, ProfileSettingsComponent, ProfilesService, TAB_COLORS, ProfileGroup } 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,8 +19,8 @@ export class EditProfileModalComponent<P extends Profile> {
|
|||||||
@Input() profile: P & ConfigProxy
|
@Input() profile: P & ConfigProxy
|
||||||
@Input() profileProvider: ProfileProvider<P>
|
@Input() profileProvider: ProfileProvider<P>
|
||||||
@Input() settingsComponent: new () => ProfileSettingsComponent<P>
|
@Input() settingsComponent: new () => ProfileSettingsComponent<P>
|
||||||
@Input() defaultsMode = false
|
@Input() defaultsMode: 'enabled'|'group'|'disabled' = 'disabled'
|
||||||
@Input() profileGroup: PartialProfileGroup<ProfileGroup> | string | undefined
|
@Input() profileGroup: PartialProfileGroup<ProfileGroup> | undefined
|
||||||
groups: PartialProfileGroup<ProfileGroup>[]
|
groups: PartialProfileGroup<ProfileGroup>[]
|
||||||
@ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef
|
@ViewChild('placeholder', { read: ViewContainerRef }) placeholder: ViewContainerRef
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ export class EditProfileModalComponent<P extends Profile> {
|
|||||||
config: ConfigService,
|
config: ConfigService,
|
||||||
private modalInstance: NgbActiveModal,
|
private modalInstance: NgbActiveModal,
|
||||||
) {
|
) {
|
||||||
if (!this.defaultsMode) {
|
if (this.defaultsMode === 'disabled') {
|
||||||
this.profilesService.getProfileGroups().then(groups => {
|
this.profilesService.getProfileGroups().then(groups => {
|
||||||
this.groups = groups
|
this.groups = groups
|
||||||
this.profileGroup = groups.find(g => g.id === this.profile.group)
|
this.profileGroup = groups.find(g => g.id === this.profile.group)
|
||||||
@ -59,7 +58,7 @@ export class EditProfileModalComponent<P extends Profile> {
|
|||||||
|
|
||||||
ngOnInit () {
|
ngOnInit () {
|
||||||
this._profile = this.profile
|
this._profile = this.profile
|
||||||
this.profile = this.profilesService.getConfigProxyForProfile(this.profile, this.defaultsMode)
|
this.profile = this.profilesService.getConfigProxyForProfile(this.profile, this.defaultsMode === 'enabled', this.defaultsMode === 'group')
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit () {
|
ngAfterViewInit () {
|
||||||
@ -94,14 +93,6 @@ export class EditProfileModalComponent<P extends Profile> {
|
|||||||
if (!this.profileGroup) {
|
if (!this.profileGroup) {
|
||||||
this.profile.group = undefined
|
this.profile.group = undefined
|
||||||
} else {
|
} else {
|
||||||
if (typeof this.profileGroup === 'string') {
|
|
||||||
const newGroup: PartialProfileGroup<ProfileGroup> = {
|
|
||||||
id: uuidv4(),
|
|
||||||
name: this.profileGroup,
|
|
||||||
}
|
|
||||||
this.profilesService.newProfileGroup(newGroup, false, false)
|
|
||||||
this.profileGroup = newGroup
|
|
||||||
}
|
|
||||||
this.profile.group = this.profileGroup.id
|
this.profile.group = this.profileGroup.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,17 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
|||||||
i.fas.fa-fw.fa-search
|
i.fas.fa-fw.fa-search
|
||||||
input.form-control(type='search', [placeholder]='"Filter"|translate', [(ngModel)]='filter')
|
input.form-control(type='search', [placeholder]='"Filter"|translate', [(ngModel)]='filter')
|
||||||
|
|
||||||
button.btn.btn-primary.flex-shrink-0.ms-3((click)='newProfile()')
|
div(ngbDropdown).d-inline-block.flex-shrink-0.ms-3
|
||||||
|
button.btn.btn-primary(ngbDropdownToggle)
|
||||||
|
i.fas.fa-fw.fa-plus
|
||||||
|
span(translate) New
|
||||||
|
div(ngbDropdownMenu)
|
||||||
|
button(ngbDropdownItem, (click)='newProfile()')
|
||||||
i.fas.fa-fw.fa-plus
|
i.fas.fa-fw.fa-plus
|
||||||
span(translate) New profile
|
span(translate) New profile
|
||||||
|
button(ngbDropdownItem, (click)='newProfileGroup()')
|
||||||
|
i.fas.fa-fw.fa-plus
|
||||||
|
span(translate) New profile Group
|
||||||
|
|
||||||
.list-group.mt-3.mb-3
|
.list-group.mt-3.mb-3
|
||||||
ng-container(*ngFor='let group of profileGroups')
|
ng-container(*ngFor='let group of profileGroups')
|
||||||
@ -37,17 +45,17 @@ ul.nav-tabs(ngbNav, #nav='ngbNav')
|
|||||||
.list-group-item.list-group-item-action.d-flex.align-items-center(
|
.list-group-item.list-group-item-action.d-flex.align-items-center(
|
||||||
(click)='toggleGroupCollapse(group)'
|
(click)='toggleGroupCollapse(group)'
|
||||||
)
|
)
|
||||||
.fa.fa-fw.fa-chevron-right(*ngIf='group.collapsed')
|
.fa.fa-fw.fa-chevron-right(*ngIf='group.collapsed && group.profiles?.length > 0')
|
||||||
.fa.fa-fw.fa-chevron-down(*ngIf='!group.collapsed')
|
.fa.fa-fw.fa-chevron-down(*ngIf='!group.collapsed && group.profiles?.length > 0')
|
||||||
span.ms-3.me-auto {{group.name || ("Ungrouped"|translate)}}
|
span.ms-3.me-auto {{group.name || ("Ungrouped"|translate)}}
|
||||||
button.btn.btn-sm.btn-link.hover-reveal.ms-2(
|
button.btn.btn-sm.btn-link.hover-reveal.ms-2(
|
||||||
*ngIf='group.editable && group.name',
|
*ngIf='group.editable && group.name',
|
||||||
(click)='$event.stopPropagation(); editGroup(group)'
|
(click)='$event.stopPropagation(); editProfileGroup(group)'
|
||||||
)
|
)
|
||||||
i.fas.fa-pencil-alt
|
i.fas.fa-pencil-alt
|
||||||
button.btn.btn-sm.btn-link.hover-reveal.ms-2(
|
button.btn.btn-sm.btn-link.hover-reveal.ms-2(
|
||||||
*ngIf='group.editable && group.name',
|
*ngIf='group.editable && group.name',
|
||||||
(click)='$event.stopPropagation(); deleteGroup(group)'
|
(click)='$event.stopPropagation(); deleteProfileGroup(group)'
|
||||||
)
|
)
|
||||||
i.fas.fa-trash-alt
|
i.fas.fa-trash-alt
|
||||||
ng-container(*ngIf='!group.collapsed')
|
ng-container(*ngIf='!group.collapsed')
|
||||||
|
@ -4,6 +4,7 @@ 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, ProfileGroup, PartialProfileGroup } from 'tabby-core'
|
import { ConfigService, HostAppService, Profile, SelectorService, ProfilesService, PromptModalComponent, PlatformService, BaseComponent, PartialProfile, ProfileProvider, TranslateService, Platform, ProfileGroup, PartialProfileGroup } from 'tabby-core'
|
||||||
import { EditProfileModalComponent } from './editProfileModal.component'
|
import { EditProfileModalComponent } from './editProfileModal.component'
|
||||||
|
import { EditProfileGroupModalComponent, EditProfileGroupModalComponentResult } from './editProfileGroupModal.component'
|
||||||
|
|
||||||
_('Filter')
|
_('Filter')
|
||||||
_('Ungrouped')
|
_('Ungrouped')
|
||||||
@ -140,27 +141,73 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async refresh (): Promise<void> {
|
async newProfileGroup (): Promise<void> {
|
||||||
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}')
|
const modal = this.ngbModal.open(PromptModalComponent)
|
||||||
const groups = await this.profilesService.getProfileGroups(true, true)
|
modal.componentInstance.prompt = this.translate.instant('New group name')
|
||||||
groups.sort((a, b) => a.name.localeCompare(b.name))
|
const result = await modal.result
|
||||||
groups.sort((a, b) => (a.id === 'built-in' || !a.editable ? 1 : 0) - (b.id === 'built-in' || !b.editable ? 1 : 0))
|
if (result?.value.trim()) {
|
||||||
groups.sort((a, b) => (a.id === 'ungrouped' ? 0 : 1) - (b.id === 'ungrouped' ? 0 : 1))
|
await this.profilesService.newProfileGroup({ id: '', name: result.value })
|
||||||
this.profileGroups = groups.map(g => ProfilesSettingsTabComponent.intoPartialCollapsableProfileGroup(g, profileGroupCollapsed[g.id] ?? false))
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async editGroup (group: PartialProfileGroup<CollapsableProfileGroup>): Promise<void> {
|
async editProfileGroup (group: PartialProfileGroup<CollapsableProfileGroup>): Promise<void> {
|
||||||
const modal = this.ngbModal.open(PromptModalComponent)
|
const result = await this.showProfileGroupEditModal(group)
|
||||||
modal.componentInstance.prompt = this.translate.instant('New name')
|
if (!result) {
|
||||||
modal.componentInstance.value = group.name
|
return
|
||||||
const result = await modal.result
|
}
|
||||||
if (result) {
|
Object.assign(group, result)
|
||||||
group.name = result.value
|
|
||||||
await this.profilesService.writeProfileGroup(ProfilesSettingsTabComponent.collapsableIntoPartialProfileGroup(group))
|
await this.profilesService.writeProfileGroup(ProfilesSettingsTabComponent.collapsableIntoPartialProfileGroup(group))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async showProfileGroupEditModal (group: PartialProfileGroup<CollapsableProfileGroup>): Promise<PartialProfileGroup<CollapsableProfileGroup>|null> {
|
||||||
|
const modal = this.ngbModal.open(
|
||||||
|
EditProfileGroupModalComponent,
|
||||||
|
{ size: 'lg' },
|
||||||
|
)
|
||||||
|
|
||||||
|
modal.componentInstance.group = deepClone(group)
|
||||||
|
modal.componentInstance.providers = this.profileProviders
|
||||||
|
|
||||||
|
const result: EditProfileGroupModalComponentResult<CollapsableProfileGroup> | null = await modal.result.catch(() => null)
|
||||||
|
if (!result) {
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteGroup (group: PartialProfileGroup<ProfileGroup>): Promise<void> {
|
if (result.provider) {
|
||||||
|
return this.editProfileGroupDefaults(result.group, result.provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.group
|
||||||
|
}
|
||||||
|
|
||||||
|
private async editProfileGroupDefaults (group: PartialProfileGroup<CollapsableProfileGroup>, provider: ProfileProvider<Profile>): Promise<PartialProfileGroup<CollapsableProfileGroup>|null> {
|
||||||
|
const modal = this.ngbModal.open(
|
||||||
|
EditProfileModalComponent,
|
||||||
|
{ size: 'lg' },
|
||||||
|
)
|
||||||
|
const model = group.defaults?.[provider.id] ?? {}
|
||||||
|
model.type = provider.id
|
||||||
|
modal.componentInstance.profile = Object.assign({}, model)
|
||||||
|
modal.componentInstance.profileProvider = provider
|
||||||
|
modal.componentInstance.defaultsMode = 'group'
|
||||||
|
|
||||||
|
const result = await modal.result.catch(() => null)
|
||||||
|
if (result) {
|
||||||
|
// Fully replace the config
|
||||||
|
for (const k in model) {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||||
|
delete model[k]
|
||||||
|
}
|
||||||
|
Object.assign(model, result)
|
||||||
|
if (!group.defaults) {
|
||||||
|
group.defaults = {}
|
||||||
|
}
|
||||||
|
group.defaults[provider.id] = model
|
||||||
|
}
|
||||||
|
return this.showProfileGroupEditModal(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteProfileGroup (group: PartialProfileGroup<ProfileGroup>): Promise<void> {
|
||||||
if ((await this.platform.showMessageBox(
|
if ((await this.platform.showMessageBox(
|
||||||
{
|
{
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
@ -193,6 +240,15 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async refresh (): Promise<void> {
|
||||||
|
const profileGroupCollapsed = JSON.parse(window.localStorage.profileGroupCollapsed ?? '{}')
|
||||||
|
const groups = await this.profilesService.getProfileGroups(true, true)
|
||||||
|
groups.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
|
groups.sort((a, b) => (a.id === 'built-in' || !a.editable ? 1 : 0) - (b.id === 'built-in' || !b.editable ? 1 : 0))
|
||||||
|
groups.sort((a, b) => (a.id === 'ungrouped' ? 0 : 1) - (b.id === 'ungrouped' ? 0 : 1))
|
||||||
|
this.profileGroups = groups.map(g => ProfilesSettingsTabComponent.intoPartialCollapsableProfileGroup(g, profileGroupCollapsed[g.id] ?? false))
|
||||||
|
}
|
||||||
|
|
||||||
isGroupVisible (group: PartialProfileGroup<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))
|
||||||
}
|
}
|
||||||
@ -223,6 +279,9 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toggleGroupCollapse (group: PartialProfileGroup<CollapsableProfileGroup>): void {
|
toggleGroupCollapse (group: PartialProfileGroup<CollapsableProfileGroup>): void {
|
||||||
|
if (group.profiles?.length === 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
group.collapsed = !group.collapsed
|
group.collapsed = !group.collapsed
|
||||||
this.saveProfileGroupCollapse(group)
|
this.saveProfileGroupCollapse(group)
|
||||||
}
|
}
|
||||||
@ -236,7 +295,7 @@ export class ProfilesSettingsTabComponent extends BaseComponent {
|
|||||||
model.type = provider.id
|
model.type = provider.id
|
||||||
modal.componentInstance.profile = Object.assign({}, model)
|
modal.componentInstance.profile = Object.assign({}, model)
|
||||||
modal.componentInstance.profileProvider = provider
|
modal.componentInstance.profileProvider = provider
|
||||||
modal.componentInstance.defaultsMode = true
|
modal.componentInstance.defaultsMode = 'enabled'
|
||||||
const result = await modal.result
|
const result = await modal.result
|
||||||
|
|
||||||
// Fully replace the config
|
// Fully replace the config
|
||||||
|
@ -7,6 +7,7 @@ import { InfiniteScrollModule } from 'ngx-infinite-scroll'
|
|||||||
import TabbyCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider, HotkeysService, AppService } from 'tabby-core'
|
import TabbyCorePlugin, { ToolbarButtonProvider, HotkeyProvider, ConfigProvider, HotkeysService, AppService } from 'tabby-core'
|
||||||
|
|
||||||
import { EditProfileModalComponent } from './components/editProfileModal.component'
|
import { EditProfileModalComponent } from './components/editProfileModal.component'
|
||||||
|
import { EditProfileGroupModalComponent } from './components/editProfileGroupModal.component'
|
||||||
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
|
import { HotkeyInputModalComponent } from './components/hotkeyInputModal.component'
|
||||||
import { HotkeySettingsTabComponent } from './components/hotkeySettingsTab.component'
|
import { HotkeySettingsTabComponent } from './components/hotkeySettingsTab.component'
|
||||||
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component'
|
import { MultiHotkeyInputComponent } from './components/multiHotkeyInput.component'
|
||||||
@ -48,6 +49,7 @@ import { HotkeySettingsTabProvider, WindowSettingsTabProvider, VaultSettingsTabP
|
|||||||
],
|
],
|
||||||
declarations: [
|
declarations: [
|
||||||
EditProfileModalComponent,
|
EditProfileModalComponent,
|
||||||
|
EditProfileGroupModalComponent,
|
||||||
HotkeyInputModalComponent,
|
HotkeyInputModalComponent,
|
||||||
HotkeySettingsTabComponent,
|
HotkeySettingsTabComponent,
|
||||||
MultiHotkeyInputComponent,
|
MultiHotkeyInputComponent,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user