diff --git a/plugins/calendar-resources/src/components/Events.svelte b/plugins/calendar-resources/src/components/Events.svelte index 26d04cfa7f..e5ab5da7ab 100644 --- a/plugins/calendar-resources/src/components/Events.svelte +++ b/plugins/calendar-resources/src/components/Events.svelte @@ -16,10 +16,9 @@ import { Event } from '@hcengineering/calendar' import { Class, DocumentQuery, Ref, Space, WithLookup } from '@hcengineering/core' import { Asset, IntlString } from '@hcengineering/platform' - import { createQuery } from '@hcengineering/presentation' - import { AnyComponent, Button, Component, Label, Loading, showPopup, TabList, IconAdd } from '@hcengineering/ui' - import view, { Viewlet, ViewletPreference } from '@hcengineering/view' - import { getViewOptions, setActiveViewletId, viewOptionStore } from '@hcengineering/view-resources' + import { AnyComponent, Button, Component, IconAdd, Label, Loading, showPopup } from '@hcengineering/ui' + import { Viewlet, ViewletPreference } from '@hcengineering/view' + import { ViewletSelector, getViewOptions, viewOptionStore } from '@hcengineering/view-resources' import calendar from '../plugin' // import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui' @@ -33,23 +32,10 @@ export let createComponent: AnyComponent | undefined = calendar.component.CreateEvent export let createLabel: IntlString | undefined = calendar.string.CreateEvent - const viewletQuery = createQuery() const search = '' let resultQuery: DocumentQuery<Event> = {} let viewlets: WithLookup<Viewlet>[] = [] - viewletQuery.query( - view.class.Viewlet, - { attachTo: _class }, - (res) => { - viewlets = res - if (viewlet === undefined || res.findIndex((p) => p._id === viewlet?._id) === -1) { - viewlet = res[0] - setActiveViewletId(viewlet._id) - } - }, - { lookup: { descriptor: view.class.ViewletDescriptor } } - ) function updateResultQuery (search: string): void { resultQuery = search === '' ? { ...query } : { ...query, $search: search } @@ -66,30 +52,9 @@ let viewlet: WithLookup<Viewlet> | undefined - const preferenceQuery = createQuery() let preference: ViewletPreference | undefined let loading = true - $: viewlet && - preferenceQuery.query( - view.class.ViewletPreference, - { - attachedTo: viewlet._id - }, - (res) => { - preference = res[0] - loading = false - }, - { limit: 1 } - ) - $: viewslist = viewlets.map((views) => { - return { - id: views._id, - icon: views.$lookup?.descriptor?.icon, - tooltip: views.$lookup?.descriptor?.label - } - }) - $: viewOptions = getViewOptions(viewlet, $viewOptionStore) </script> @@ -99,16 +64,7 @@ </div> <div class="ac-header-full medium-gap mb-1"> - {#if viewlets.length > 1} - <TabList - items={viewslist} - multiselect={false} - selected={viewlet?._id} - on:select={(result) => { - if (result.detail !== undefined) viewlet = viewlets.find((vl) => vl._id === result.detail.id) - }} - /> - {/if} + <ViewletSelector bind:viewlet bind:loading bind:preference bind:viewlets viewletQuery={{ attachTo: _class }} /> <Button icon={IconAdd} label={createLabel} kind={'accented'} on:click={showCreateDialog} /> </div> </div> diff --git a/plugins/contact-resources/src/components/Contacts.svelte b/plugins/contact-resources/src/components/Contacts.svelte index 7686e25a7e..0dfcaaf32c 100644 --- a/plugins/contact-resources/src/components/Contacts.svelte +++ b/plugins/contact-resources/src/components/Contacts.svelte @@ -18,7 +18,13 @@ import { ActionContext } from '@hcengineering/presentation' import { Button, Label, Loading, SearchEdit, showPopup } from '@hcengineering/ui' import view, { Viewlet, ViewletPreference, ViewOptions } from '@hcengineering/view' - import { FilterBar, FilterButton, TableBrowser, ViewletSettingButton } from '@hcengineering/view-resources' + import { + FilterBar, + FilterButton, + TableBrowser, + ViewletSelector, + ViewletSettingButton + } from '@hcengineering/view-resources' import contact from '../plugin' import CreateContact from './CreateContact.svelte' // import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui' @@ -68,16 +74,17 @@ <FilterButton _class={contact.class.Contact} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton - bind:viewOptions + <ViewletSelector + hidden + bind:viewlet + bind:preference + bind:loading viewletQuery={{ attachTo: contact.class.Contact, descriptor: view.viewlet.Table }} - bind:viewlet - bind:preference - bind:loading /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size={'small'} /> --> </div> </div> diff --git a/plugins/contact-resources/src/components/Members.svelte b/plugins/contact-resources/src/components/Members.svelte index cc9a34a4e0..8c7002e036 100644 --- a/plugins/contact-resources/src/components/Members.svelte +++ b/plugins/contact-resources/src/components/Members.svelte @@ -18,7 +18,7 @@ import { createQuery, getClient } from '@hcengineering/presentation' import { Button, Icon, IconAdd, Label, showPopup } from '@hcengineering/ui' import { Viewlet, ViewletPreference } from '@hcengineering/view' - import { Table, ViewletSettingButton } from '@hcengineering/view-resources' + import { Table, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources' import contact from '../plugin' import UsersPopup from './UsersPopup.svelte' import IconMembersOutline from './icons/MembersOutline.svelte' @@ -75,13 +75,14 @@ <Label label={contact.string.Members} /> </span> <div class="buttons-group xsmall-gap"> - <ViewletSettingButton - viewletQuery={{ _id: contact.viewlet.TableMember }} - kind={'ghost'} + <ViewletSelector + hidden bind:viewlet bind:preference bind:loading + viewletQuery={{ _id: contact.viewlet.TableMember }} /> + <ViewletSettingButton kind={'ghost'} bind:viewlet /> <Button id={contact.string.AddMember} icon={IconAdd} kind={'ghost'} on:click={createApp} /> </div> </div> diff --git a/plugins/document-resources/src/components/Documents.svelte b/plugins/document-resources/src/components/Documents.svelte index 8d8964debb..ec9c4a139d 100644 --- a/plugins/document-resources/src/components/Documents.svelte +++ b/plugins/document-resources/src/components/Documents.svelte @@ -20,7 +20,7 @@ import { ActionContext } from '@hcengineering/presentation' import { Label, Loading, SearchEdit } from '@hcengineering/ui' import view, { Viewlet, ViewletPreference } from '@hcengineering/view' - import { FilterButton, TableBrowser, ViewletSettingButton } from '@hcengineering/view-resources' + import { FilterButton, TableBrowser, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources' import document from '../plugin' export let query: DocumentQuery<Document> = {} @@ -57,15 +57,17 @@ <FilterButton _class={document.class.Document} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton + <ViewletSelector + hidden + bind:viewlet + bind:preference + bind:loading viewletQuery={{ attachTo: document.class.Document, descriptor: view.viewlet.Table }} - bind:viewlet - bind:preference - bind:loading /> + <ViewletSettingButton bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size={'small'} /> --> </div> </div> diff --git a/plugins/hr-resources/src/components/DepartmentStaff.svelte b/plugins/hr-resources/src/components/DepartmentStaff.svelte index 0c76d26141..e19e0bf9eb 100644 --- a/plugins/hr-resources/src/components/DepartmentStaff.svelte +++ b/plugins/hr-resources/src/components/DepartmentStaff.svelte @@ -20,7 +20,7 @@ import { createQuery, getClient } from '@hcengineering/presentation' import { Button, IconAdd, Label, Scroller, eventToHTMLElement, showPopup } from '@hcengineering/ui' import { Viewlet, ViewletPreference } from '@hcengineering/view' - import { Table, ViewletSettingButton } from '@hcengineering/view-resources' + import { Table, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources' import hr from '../plugin' import { addMember } from '../utils' @@ -73,13 +73,14 @@ <Label label={hr.string.Members} /> </span> <div class="flex-row-center gap-2 reverse"> - <ViewletSettingButton - viewletQuery={{ _id: hr.viewlet.TableMember }} - kind={'ghost'} + <ViewletSelector + hidden bind:viewlet bind:preference bind:loading + viewletQuery={{ _id: hr.viewlet.TableMember }} /> + <ViewletSettingButton kind={'ghost'} bind:viewlet /> <Button id={hr.string.AddEmployee} icon={IconAdd} kind={'ghost'} on:click={add} /> </div> </div> diff --git a/plugins/hr-resources/src/components/schedule/MonthTableView.svelte b/plugins/hr-resources/src/components/schedule/MonthTableView.svelte index ec8a81bc1c..17dc4ce249 100644 --- a/plugins/hr-resources/src/components/schedule/MonthTableView.svelte +++ b/plugins/hr-resources/src/components/schedule/MonthTableView.svelte @@ -20,7 +20,7 @@ import { getEmbeddedLabel } from '@hcengineering/platform' import { Button, Label, Loading, showPopup, tableToCSV } from '@hcengineering/ui' import { BuildModelKey, Viewlet, ViewletPreference } from '@hcengineering/view' - import { TableBrowser, ViewletSettingButton } from '@hcengineering/view-resources' + import { TableBrowser, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources' import hr from '../../plugin' import { EmployeeReports, @@ -367,7 +367,14 @@ <div class="clear-mins" /> <div class="ac-header-full small-gap"> <Button label={getEmbeddedLabel('Export')} on:click={(evt) => exportTable(evt)} /> - <ViewletSettingButton viewletQuery={{ _id: hr.viewlet.StaffStats }} bind:viewlet bind:preference bind:loading /> + <ViewletSelector + hidden + bind:viewlet + bind:preference + bind:loading + viewletQuery={{ _id: hr.viewlet.StaffStats }} + /> + <ViewletSettingButton bind:viewlet /> </div> </div> {#if viewlet} diff --git a/plugins/lead-resources/src/components/MyLeads.svelte b/plugins/lead-resources/src/components/MyLeads.svelte index 12eb33ec0e..e60b5cf0b6 100644 --- a/plugins/lead-resources/src/components/MyLeads.svelte +++ b/plugins/lead-resources/src/components/MyLeads.svelte @@ -21,7 +21,13 @@ import task from '@hcengineering/task' import { IModeSelector, Label, Loading, ModeSelector, resolvedLocationStore, SearchEdit } from '@hcengineering/ui' import { Viewlet, ViewletPreference, ViewOptions } from '@hcengineering/view' - import { FilterBar, FilterButton, TableBrowser, ViewletSettingButton } from '@hcengineering/view-resources' + import { + FilterBar, + FilterButton, + TableBrowser, + ViewletSelector, + ViewletSettingButton + } from '@hcengineering/view-resources' import { createEventDispatcher } from 'svelte' import lead from '../plugin' @@ -102,16 +108,17 @@ <div class="buttons-divider" /> <FilterButton {_class} /> </div> - <ViewletSettingButton - bind:viewOptions + <ViewletSelector + hidden + bind:viewlet + bind:preference + bind:loading viewletQuery={{ attachTo: _class, descriptor: task.viewlet.StatusTable }} - bind:viewlet - bind:preference - bind:loading /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> </div> <FilterBar {_class} query={searchQuery} {viewOptions} on:change={(e) => (resultQuery = e.detail)} /> diff --git a/plugins/recruit-resources/src/components/Applications.svelte b/plugins/recruit-resources/src/components/Applications.svelte index be23c60925..a79d962fc9 100644 --- a/plugins/recruit-resources/src/components/Applications.svelte +++ b/plugins/recruit-resources/src/components/Applications.svelte @@ -16,7 +16,7 @@ import type { Doc, Ref } from '@hcengineering/core' import { Button, Icon, IconAdd, Label, Scroller, showPopup } from '@hcengineering/ui' import { Viewlet, ViewletPreference } from '@hcengineering/view' - import { Table, ViewletSettingButton } from '@hcengineering/view-resources' + import { Table, ViewletsSettingButton } from '@hcengineering/view-resources' import recruit from '../plugin' import CreateApplication from './CreateApplication.svelte' import IconApplication from './icons/Application.svelte' @@ -44,7 +44,7 @@ <Label label={recruit.string.Applications} /> </span> <div class="flex-row-center gap-2 reverse"> - <ViewletSettingButton + <ViewletsSettingButton viewletQuery={{ _id: recruit.viewlet.VacancyApplicationsEmbeddeed }} kind={'ghost'} bind:viewlet diff --git a/plugins/recruit-resources/src/components/Organizations.svelte b/plugins/recruit-resources/src/components/Organizations.svelte index 05e411b66a..91dac4b4fb 100644 --- a/plugins/recruit-resources/src/components/Organizations.svelte +++ b/plugins/recruit-resources/src/components/Organizations.svelte @@ -19,7 +19,13 @@ import { Applicant, Vacancy } from '@hcengineering/recruit' import { Button, IconAdd, Label, Loading, SearchEdit, showPopup } from '@hcengineering/ui' import view, { BuildModelKey, Viewlet, ViewletPreference, ViewOptions } from '@hcengineering/view' - import { FilterBar, FilterButton, TableBrowser, ViewletSettingButton } from '@hcengineering/view-resources' + import { + FilterBar, + FilterButton, + TableBrowser, + ViewletSelector, + ViewletSettingButton + } from '@hcengineering/view-resources' import recruit from '../plugin' import CreateOrganization from './CreateOrganization.svelte' import VacancyListApplicationsPopup from './organizations/VacancyListApplicationsPopup.svelte' @@ -205,16 +211,17 @@ <FilterButton _class={recruit.mixin.VacancyList} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton - bind:viewOptions + <ViewletSelector + hidden viewletQuery={{ attachTo: recruit.mixin.VacancyList, descriptor: view.viewlet.Table }} - bind:viewlet bind:preference bind:loading + bind:viewlet /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size={'small'} /> --> </div> </div> diff --git a/plugins/recruit-resources/src/components/Vacancies.svelte b/plugins/recruit-resources/src/components/Vacancies.svelte index 412415e4e5..c48d8c2e5d 100644 --- a/plugins/recruit-resources/src/components/Vacancies.svelte +++ b/plugins/recruit-resources/src/components/Vacancies.svelte @@ -18,7 +18,13 @@ import { Vacancy } from '@hcengineering/recruit' import { Button, IconAdd, Label, Loading, SearchEdit, showPopup, tableToCSV } from '@hcengineering/ui' import view, { BuildModelKey, ViewOptions, Viewlet, ViewletPreference } from '@hcengineering/view' - import { FilterBar, FilterButton, TableBrowser, ViewletSettingButton } from '@hcengineering/view-resources' + import { + FilterBar, + FilterButton, + TableBrowser, + ViewletSelector, + ViewletSettingButton + } from '@hcengineering/view-resources' import recruit from '../plugin' import CreateVacancy from './CreateVacancy.svelte' @@ -149,16 +155,17 @@ <FilterButton _class={recruit.class.Vacancy} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton - bind:viewOptions + <ViewletSelector + hidden viewletQuery={{ attachTo: recruit.class.Vacancy, descriptor: view.viewlet.Table }} - bind:viewlet bind:preference bind:loading + bind:viewlet /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size={'small'} /> --> </div> </div> diff --git a/plugins/recruit-resources/src/components/VacancyApplications.svelte b/plugins/recruit-resources/src/components/VacancyApplications.svelte index 8b418f4c8a..e8717423f1 100644 --- a/plugins/recruit-resources/src/components/VacancyApplications.svelte +++ b/plugins/recruit-resources/src/components/VacancyApplications.svelte @@ -18,7 +18,7 @@ import { recruitId, Vacancy } from '@hcengineering/recruit' import { Button, Icon, IconAdd, Label, Loading, resizeObserver, Scroller, showPopup } from '@hcengineering/ui' import { Viewlet, ViewletPreference } from '@hcengineering/view' - import { NavLink, Table, ViewletSettingButton } from '@hcengineering/view-resources' + import { NavLink, Table, ViewletsSettingButton } from '@hcengineering/view-resources' import recruit from '../plugin' import CreateApplication from './CreateApplication.svelte' import IconApplication from './icons/Application.svelte' @@ -53,7 +53,7 @@ </NavLink> </span> <div class="flex-row-center gap-2 reverse"> - <ViewletSettingButton + <ViewletsSettingButton viewletQuery={{ _id: recruit.viewlet.VacancyApplicationsShort }} kind={'ghost'} bind:viewlet diff --git a/plugins/task-resources/src/components/AssignedTasks.svelte b/plugins/task-resources/src/components/AssignedTasks.svelte index b9b1f6810f..51af24af7c 100644 --- a/plugins/task-resources/src/components/AssignedTasks.svelte +++ b/plugins/task-resources/src/components/AssignedTasks.svelte @@ -29,7 +29,13 @@ SearchEdit } from '@hcengineering/ui' import { Viewlet, ViewletPreference, ViewOptions } from '@hcengineering/view' - import { FilterBar, FilterButton, TableBrowser, ViewletSettingButton } from '@hcengineering/view-resources' + import { + FilterBar, + FilterButton, + TableBrowser, + ViewletSelector, + ViewletSettingButton + } from '@hcengineering/view-resources' import { createEventDispatcher } from 'svelte' import task from '../plugin' @@ -152,13 +158,14 @@ <div class="buttons-divider" /> <FilterButton {_class} /> </div> - <ViewletSettingButton - bind:viewOptions - viewletQuery={{ attachTo: _class, descriptor: task.viewlet.StatusTable }} + <ViewletSelector + hidden bind:viewlet bind:preference bind:loading + viewletQuery={{ attachTo: _class, descriptor: task.viewlet.StatusTable }} /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> </div> <FilterBar {_class} query={searchQuery} {viewOptions} on:change={(e) => (resultQuery = e.detail)} /> diff --git a/plugins/tracker-resources/src/components/components/ComponentBrowser.svelte b/plugins/tracker-resources/src/components/components/ComponentBrowser.svelte index 87122f2646..fd08324330 100644 --- a/plugins/tracker-resources/src/components/components/ComponentBrowser.svelte +++ b/plugins/tracker-resources/src/components/components/ComponentBrowser.svelte @@ -16,14 +16,14 @@ import { DocumentQuery, WithLookup } from '@hcengineering/core' import { IntlString } from '@hcengineering/platform' import { Component } from '@hcengineering/tracker' - import { Button, IconAdd, Label, SearchEdit, TabList, resolvedLocationStore, showPopup } from '@hcengineering/ui' + import { Button, IconAdd, Label, SearchEdit, resolvedLocationStore, showPopup } from '@hcengineering/ui' import { ViewOptions, Viewlet } from '@hcengineering/view' import { FilterBar, FilterButton, + ViewletSelector, ViewletSettingButton, - makeViewletKey, - updateActiveViewlet + makeViewletKey } from '@hcengineering/view-resources' import { onDestroy } from 'svelte' import tracker from '../../plugin' @@ -86,15 +86,7 @@ </div> <div class="ac-header-full medium-gap mb-1"> - {#if viewlets && viewlets.length > 1} - <TabList - items={views} - selected={viewlet?._id} - kind="normal" - on:select={({ detail }) => - (viewlet = viewlets && detail?.id ? updateActiveViewlet(viewlets, detail.id) : viewlet)} - /> - {/if} + <ViewletSelector bind:viewlet bind:viewlets viewletQuery={{ attachTo: tracker.class.Component }} /> <Button icon={IconAdd} label={tracker.string.Component} kind="accented" on:click={showCreateDialog} /> </div> </div> @@ -106,12 +98,7 @@ <FilterButton _class={tracker.class.Component} {space} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton - bind:viewOptions - viewletQuery={{ attachTo: tracker.class.Component }} - bind:viewlet - bind:viewlets - /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size="small" /> --> </div> </div> diff --git a/plugins/tracker-resources/src/components/issues/IssuesView.svelte b/plugins/tracker-resources/src/components/issues/IssuesView.svelte index 0f0831e128..cec1f7c294 100644 --- a/plugins/tracker-resources/src/components/issues/IssuesView.svelte +++ b/plugins/tracker-resources/src/components/issues/IssuesView.svelte @@ -16,7 +16,7 @@ export let modeSelectorProps: IModeSelector | undefined = undefined let viewlet: WithLookup<Viewlet> | undefined = undefined - let viewlets: WithLookup<Viewlet>[] | undefined = undefined + const viewlets: WithLookup<Viewlet>[] | undefined = undefined let viewOptions: ViewOptions | undefined let search = '' @@ -51,6 +51,7 @@ bind:viewlet bind:search showLabelSelector={$$slots.label_selector} + viewletQuery={{ attachTo: tracker.class.Issue, variant: { $ne: 'subissue' } }} {viewlets} {label} {space} @@ -60,12 +61,7 @@ <slot name="label_selector" /> </svelte:fragment> <svelte:fragment slot="extra"> - <ViewletSettingButton - bind:viewOptions - viewletQuery={{ attachTo: tracker.class.Issue, variant: { $ne: 'subissue' } }} - bind:viewlet - bind:viewlets - /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> {#if asideFloat && $$slots.aside} <div class="buttons-divider" /> <Button diff --git a/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte b/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte index 4986e6cea1..bdffe62e05 100644 --- a/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte +++ b/plugins/tracker-resources/src/components/issues/edit/SubIssues.svelte @@ -29,7 +29,7 @@ showPopup } from '@hcengineering/ui' import view, { ViewOptions, Viewlet, ViewletPreference } from '@hcengineering/view' - import { ViewletSettingButton, createFilter, setFilters } from '@hcengineering/view-resources' + import { ViewletsSettingButton, createFilter, setFilters } from '@hcengineering/view-resources' import { afterUpdate } from 'svelte' import tracker from '../../../plugin' import CreateIssue from '../../CreateIssue.svelte' @@ -147,7 +147,7 @@ {/if} <div class="flex-row-center gap-2"> {#if hasSubIssues} - <ViewletSettingButton + <ViewletsSettingButton bind:viewOptions viewletQuery={{ _id: tracker.viewlet.SubIssues }} kind={'ghost'} diff --git a/plugins/tracker-resources/src/components/issues/related/RelatedIssuesSection.svelte b/plugins/tracker-resources/src/components/issues/related/RelatedIssuesSection.svelte index c3718b0f98..8dbe9633dd 100644 --- a/plugins/tracker-resources/src/components/issues/related/RelatedIssuesSection.svelte +++ b/plugins/tracker-resources/src/components/issues/related/RelatedIssuesSection.svelte @@ -5,7 +5,7 @@ import { Issue, trackerId } from '@hcengineering/tracker' import { Button, Component, Icon, IconAdd, Label, showPopup } from '@hcengineering/ui' import { ViewOptions, Viewlet } from '@hcengineering/view' - import { ViewletSettingButton, getAdditionalHeader } from '@hcengineering/view-resources' + import { ViewletsSettingButton, getAdditionalHeader } from '@hcengineering/view-resources' import viewplg from '@hcengineering/view-resources/src/plugin' import { fade } from 'svelte/transition' import tracker from '../../../plugin' @@ -56,7 +56,7 @@ <span class="flex-grow" /> {/if} <div class="flex-row-center gap-2"> - <ViewletSettingButton + <ViewletsSettingButton bind:viewOptions viewletQuery={{ _id: tracker.viewlet.SubIssues }} kind={'ghost'} diff --git a/plugins/tracker-resources/src/components/milestones/MilestoneBrowser.svelte b/plugins/tracker-resources/src/components/milestones/MilestoneBrowser.svelte index c5287f5759..fdcec5f6ff 100644 --- a/plugins/tracker-resources/src/components/milestones/MilestoneBrowser.svelte +++ b/plugins/tracker-resources/src/components/milestones/MilestoneBrowser.svelte @@ -18,7 +18,7 @@ import { Milestone } from '@hcengineering/tracker' import { Button, IconAdd, Label, SearchEdit, TabItem, TabList, showPopup } from '@hcengineering/ui' import { ViewOptions, Viewlet } from '@hcengineering/view' - import { FilterBar, FilterButton, ViewletSettingButton } from '@hcengineering/view-resources' + import { FilterBar, FilterButton, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources' import tracker from '../../plugin' import { MilestoneViewMode, getIncludedMilestoneStatuses, milestoneTitleMap } from '../../utils' import MilestoneContent from './MilestoneContent.svelte' @@ -99,7 +99,8 @@ <FilterButton _class={tracker.class.Milestone} {space} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton bind:viewOptions viewletQuery={{ attachTo: tracker.class.Milestone }} bind:viewlet /> + <ViewletSelector viewletQuery={{ attachTo: tracker.class.Milestone }} bind:viewlet /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size={'small'} /> --> </div> </div> diff --git a/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte b/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte index 3fb57ae3a1..794b4dad39 100644 --- a/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte +++ b/plugins/tracker-resources/src/components/templates/IssueTemplatesView.svelte @@ -80,12 +80,7 @@ /> <div class="buttons-divider" /> {/if} - <ViewletSettingButton - bind:viewOptions - viewletQuery={{ attachTo: tracker.class.IssueTemplate }} - bind:viewlet - bind:viewlets - /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> </svelte:fragment> </SpaceHeader> <slot name="afterHeader" /> diff --git a/plugins/view-resources/src/components/SpaceHeader.svelte b/plugins/view-resources/src/components/SpaceHeader.svelte index 4e042d81a8..8316795028 100644 --- a/plugins/view-resources/src/components/SpaceHeader.svelte +++ b/plugins/view-resources/src/components/SpaceHeader.svelte @@ -1,27 +1,19 @@ <script lang="ts"> - import { Class, Doc, Ref, Space } from '@hcengineering/core' - import { TabList, SearchEdit, IModeSelector, ModeSelector } from '@hcengineering/ui' + import { Class, Doc, DocumentQuery, Ref, Space, WithLookup } from '@hcengineering/core' + import { IModeSelector, ModeSelector, SearchEdit } from '@hcengineering/ui' import { Viewlet } from '@hcengineering/view' - import { WithLookup } from '@hcengineering/core' - import { setActiveViewletId } from '../utils' + import ViewletSelector from './ViewletSelector.svelte' import FilterButton from './filter/FilterButton.svelte' export let space: Ref<Space> | undefined = undefined export let _class: Ref<Class<Doc>> export let viewlet: WithLookup<Viewlet> | undefined + export let viewletQuery: DocumentQuery<Viewlet> | undefined = undefined export let viewlets: WithLookup<Viewlet>[] = [] export let label: string export let search: string export let showLabelSelector = false export let modeSelectorProps: IModeSelector | undefined = undefined - - $: viewslist = viewlets.map((views) => { - return { - id: views._id, - icon: views.$lookup?.descriptor?.icon, - tooltip: views.$lookup?.descriptor?.label - } - }) </script> <div @@ -42,24 +34,7 @@ {/if} </div> <div class="mb-1 clear-mins"> - {#if viewlets.length > 1} - <TabList - items={viewslist} - multiselect={false} - selected={viewlet?._id} - onlyIcons - on:select={(result) => { - if (result.detail !== undefined) { - if (viewlet?._id === result.detail.id) return - viewlet = viewlets.find((vl) => vl._id === result.detail.id) - - if (viewlet) { - setActiveViewletId(viewlet._id) - } - } - }} - /> - {/if} + <ViewletSelector bind:viewlet bind:viewlets viewletQuery={viewletQuery ?? { attachTo: _class }} /> <slot name="header-tools" /> </div> </div> diff --git a/plugins/view-resources/src/components/ViewletSelector.svelte b/plugins/view-resources/src/components/ViewletSelector.svelte new file mode 100644 index 0000000000..c286ae117e --- /dev/null +++ b/plugins/view-resources/src/components/ViewletSelector.svelte @@ -0,0 +1,104 @@ +<script lang="ts"> + import { createEventDispatcher, onDestroy } from 'svelte' + import { activeViewlet, makeViewletKey, setActiveViewletId } from '../utils' + import { TabList, resolvedLocationStore } from '@hcengineering/ui' + import view, { Viewlet, ViewletPreference } from '@hcengineering/view' + import { DocumentQuery, Ref, WithLookup } from '@hcengineering/core' + import { createQuery } from '@hcengineering/presentation' + + export let viewlet: WithLookup<Viewlet> | undefined + export let viewlets: WithLookup<Viewlet>[] = [] + export let viewletQuery: DocumentQuery<Viewlet> + export let preference: ViewletPreference | undefined = undefined + export let loading = true + export let hidden = false + + const query = createQuery() + + $: query.query( + view.class.Viewlet, + viewletQuery, + (res) => { + viewlets = res + dispatch('viewlets', viewlets) + }, + { + lookup: { + descriptor: view.class.ViewletDescriptor + } + } + ) + + let key = makeViewletKey() + + onDestroy( + resolvedLocationStore.subscribe((loc) => { + key = makeViewletKey(loc) + }) + ) + + $: getActiveViewlet(viewlets, $activeViewlet, key) + + const dispatch = createEventDispatcher() + + function getActiveViewlet ( + viewlets: WithLookup<Viewlet>[], + activeViewlet: Record<string, Ref<Viewlet> | null>, + key: string + ) { + if (viewlets.length === 0) return + const newViewlet = viewlets.find((viewlet) => viewlet?._id === activeViewlet[key]) ?? viewlets[0] + if (viewlet?._id !== newViewlet?._id) { + viewlet = newViewlet + setActiveViewletId(newViewlet._id) + dispatch('viewlet', viewlet) + } + } + + $: viewslist = viewlets.map((views) => { + return { + id: views._id, + icon: views.$lookup?.descriptor?.icon, + tooltip: views.$lookup?.descriptor?.label + } + }) + + const preferenceQuery = createQuery() + + $: if (viewlet != null) { + preferenceQuery.query( + view.class.ViewletPreference, + { + attachedTo: viewlet._id + }, + (res) => { + preference = res[0] + loading = false + dispatch('loading', loading) + dispatch('preference', preference) + }, + { limit: 1 } + ) + } else { + preferenceQuery.unsubscribe() + } +</script> + +{#if viewlets.length > 1 && !hidden} + <TabList + items={viewslist} + multiselect={false} + selected={viewlet?._id} + on:select={(result) => { + if (result.detail !== undefined) { + if (viewlet?._id === result.detail.id) { + return + } + viewlet = viewlets.find((vl) => vl._id === result.detail.id) + if (viewlet) { + setActiveViewletId(viewlet._id) + } + } + }} + /> +{/if} diff --git a/plugins/view-resources/src/components/ViewletSettingButton.svelte b/plugins/view-resources/src/components/ViewletSettingButton.svelte index 3fbcc5f9c2..64286c13ff 100644 --- a/plugins/view-resources/src/components/ViewletSettingButton.svelte +++ b/plugins/view-resources/src/components/ViewletSettingButton.svelte @@ -13,28 +13,16 @@ // limitations under the License. --> <script lang="ts"> - import { DocumentQuery, Ref, WithLookup } from '@hcengineering/core' - import { createQuery } from '@hcengineering/presentation' - import { Button, ButtonKind, resolvedLocationStore, showPopup } from '@hcengineering/ui' - import { ViewOptions, Viewlet, ViewletPreference } from '@hcengineering/view' - import { createEventDispatcher, onDestroy } from 'svelte' + import { Button, ButtonKind, showPopup } from '@hcengineering/ui' + import { ViewOptions, Viewlet } from '@hcengineering/view' import view from '../plugin' - import { activeViewlet, makeViewletKey, setActiveViewletId } from '../utils' import { getViewOptions, viewOptionStore } from '../viewOptions' import ViewOptionsButton from './ViewOptionsButton.svelte' import ViewletSetting from './ViewletSetting.svelte' - export let viewletQuery: DocumentQuery<Viewlet> = {} export let kind: ButtonKind = 'regular' export let viewOptions: ViewOptions | undefined = undefined - - export let loading = true - export let viewlet: Viewlet | undefined = undefined - export let viewlets: WithLookup<Viewlet>[] = [] - export let preference: ViewletPreference | undefined = undefined - - const dispatch = createEventDispatcher() let btn: HTMLButtonElement @@ -43,67 +31,6 @@ } $: viewOptions = getViewOptions(viewlet, $viewOptionStore) - - const query = createQuery() - - $: query.query( - view.class.Viewlet, - viewletQuery, - (res) => { - viewlets = res - dispatch('viewlets', viewlets) - }, - { - lookup: { - descriptor: view.class.ViewletDescriptor - } - } - ) - - let key = makeViewletKey() - - onDestroy( - resolvedLocationStore.subscribe((loc) => { - key = makeViewletKey(loc) - }) - ) - - $: getActiveViewlet(viewlets, $activeViewlet, key) - - function getActiveViewlet ( - viewlets: WithLookup<Viewlet>[], - activeViewlet: Record<string, Ref<Viewlet> | null>, - key: string - ) { - if (viewlets.length === 0) return - const newViewlet = viewlets.find((viewlet) => viewlet?._id === activeViewlet[key]) ?? viewlets[0] - if (viewlet?._id !== newViewlet?._id) { - preference = undefined - viewlet = newViewlet - setActiveViewletId(newViewlet._id) - dispatch('viewlet', viewlet) - } - } - - const preferenceQuery = createQuery() - - $: if (viewlet != null) { - preferenceQuery.query( - view.class.ViewletPreference, - { - attachedTo: viewlet._id - }, - (res) => { - preference = res[0] - loading = false - dispatch('loading', loading) - dispatch('preference', preference) - }, - { limit: 1 } - ) - } else { - preferenceQuery.unsubscribe() - } </script> {#if viewlet} diff --git a/plugins/view-resources/src/components/ViewletsSettingButton.svelte b/plugins/view-resources/src/components/ViewletsSettingButton.svelte new file mode 100644 index 0000000000..221a7b339e --- /dev/null +++ b/plugins/view-resources/src/components/ViewletsSettingButton.svelte @@ -0,0 +1,97 @@ +<!-- +// Copyright © 2022 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +--> +<script lang="ts"> + import { DocumentQuery, WithLookup } from '@hcengineering/core' + import { createQuery } from '@hcengineering/presentation' + import { Button, ButtonKind, showPopup } from '@hcengineering/ui' + import { ViewOptions, Viewlet, ViewletPreference } from '@hcengineering/view' + import { createEventDispatcher } from 'svelte' + import view from '../plugin' + import { getViewOptions, viewOptionStore } from '../viewOptions' + import ViewOptionsButton from './ViewOptionsButton.svelte' + import ViewletSetting from './ViewletSetting.svelte' + + export let viewletQuery: DocumentQuery<Viewlet> = {} + export let kind: ButtonKind = 'regular' + export let viewOptions: ViewOptions | undefined = undefined + + export let viewlet: Viewlet | undefined = undefined + export let viewlets: WithLookup<Viewlet>[] = [] + export let preference: ViewletPreference | undefined = undefined + export let loading = true + + const dispatch = createEventDispatcher() + + let btn: HTMLButtonElement + + function clickHandler (event: MouseEvent) { + showPopup(ViewletSetting, { viewlet }, btn) + } + + $: viewOptions = getViewOptions(viewlet, $viewOptionStore) + + const query = createQuery() + + $: query.query( + view.class.Viewlet, + viewletQuery, + (res) => { + viewlets = res + viewlet = viewlets[0] + dispatch('viewlets', viewlets) + }, + { + lookup: { + descriptor: view.class.ViewletDescriptor + } + } + ) + + const preferenceQuery = createQuery() + + $: if (viewlet != null) { + preferenceQuery.query( + view.class.ViewletPreference, + { + attachedTo: viewlet._id + }, + (res) => { + preference = res[0] + loading = false + }, + { limit: 1 } + ) + } else { + preferenceQuery.unsubscribe() + } +</script> + +{#if viewlet} + <div class="flex-row-center gap-2 reverse"> + {#if viewOptions} + <ViewOptionsButton {viewlet} {kind} {viewOptions} /> + {/if} + <Button + icon={view.icon.Configure} + label={view.string.Show} + {kind} + shrink={1} + adaptiveShrink={'sm'} + showTooltip={{ label: view.string.CustomizeView, direction: 'bottom' }} + bind:input={btn} + on:click={clickHandler} + /> + </div> +{/if} diff --git a/plugins/view-resources/src/index.ts b/plugins/view-resources/src/index.ts index 4596be7796..87be2ea08d 100644 --- a/plugins/view-resources/src/index.ts +++ b/plugins/view-resources/src/index.ts @@ -131,6 +131,9 @@ export { default as TableBrowser } from './components/TableBrowser.svelte' export { default as ValueSelector } from './components/ValueSelector.svelte' export { default as FilterRemovedNotification } from './components/filter/FilterRemovedNotification.svelte' export { default as ParentsNavigator } from './components/ParentsNavigator.svelte' +export { default as ViewletSelector } from './components/ViewletSelector.svelte' +export { default as ViewletsSettingButton } from './components/ViewletsSettingButton.svelte' + export * from './filter' export * from './selection' export * from './utils' diff --git a/plugins/view-resources/src/viewOptions.ts b/plugins/view-resources/src/viewOptions.ts index 52d703275d..73081b137e 100644 --- a/plugins/view-resources/src/viewOptions.ts +++ b/plugins/view-resources/src/viewOptions.ts @@ -99,6 +99,14 @@ export function migrateViewOpttions (): void { if (!Array.isArray(res.groupBy)) { res.groupBy = [res.groupBy] } + let ind = res.groupBy.findIndex((p) => p === 'state') + while (ind !== -1) { + res.groupBy[ind] = 'status' + ind = res.groupBy.findIndex((p) => p === 'state') + } + if (res.orderBy[0] === 'state') { + res.orderBy[0] = 'status' + } localStorage.setItem(key, JSON.stringify(res)) } } diff --git a/plugins/workbench-resources/src/components/SpaceHeader.svelte b/plugins/workbench-resources/src/components/SpaceHeader.svelte index 3a82dfb0c0..df3f97371d 100644 --- a/plugins/workbench-resources/src/components/SpaceHeader.svelte +++ b/plugins/workbench-resources/src/components/SpaceHeader.svelte @@ -17,9 +17,9 @@ import core, { WithLookup } from '@hcengineering/core' import { IntlString } from '@hcengineering/platform' import presentation, { createQuery } from '@hcengineering/presentation' - import { AnyComponent, Button, IconAdd, SearchEdit, TabList, showPopup } from '@hcengineering/ui' + import { AnyComponent, Button, IconAdd, SearchEdit, showPopup } from '@hcengineering/ui' import { ViewOptions, Viewlet } from '@hcengineering/view' - import { FilterButton, ViewletSettingButton, setActiveViewletId } from '@hcengineering/view-resources' + import { FilterButton, ViewletSelector, ViewletSettingButton } from '@hcengineering/view-resources' import { createEventDispatcher } from 'svelte' import Header from './Header.svelte' @@ -52,14 +52,6 @@ dispatch('search', '') } - $: viewslist = viewlets.map((views) => { - return { - id: views._id, - icon: views.$lookup?.descriptor?.icon, - tooltip: views.$lookup?.descriptor?.label - } - }) - // $: twoRows = $deviceInfo.twoRows </script> @@ -68,19 +60,7 @@ <Header {space} {_class} /> <div class="ac-header-full medium-gap mb-1"> - {#if viewlets.length > 1} - <TabList - items={viewslist} - multiselect={false} - selected={viewlet?._id} - on:select={(result) => { - if (result.detail !== undefined) { - viewlet = viewlets.find((vl) => vl._id === result.detail.id) - if (viewlet) setActiveViewletId(viewlet._id) - } - }} - /> - {/if} + <ViewletSelector {viewletQuery} bind:viewlet bind:viewlets /> {#if createItemDialog} <Button icon={IconAdd} label={createItemLabel} kind={'accented'} on:click={(ev) => showCreateDialog(ev)} /> {/if} @@ -94,7 +74,7 @@ <FilterButton {_class} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton bind:viewOptions {viewletQuery} bind:viewlet bind:viewlets /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size={'small'} /> --> </div> </div> diff --git a/plugins/workbench-resources/src/components/SpecialView.svelte b/plugins/workbench-resources/src/components/SpecialView.svelte index 1a9b42604b..a38e1b9cae 100644 --- a/plugins/workbench-resources/src/components/SpecialView.svelte +++ b/plugins/workbench-resources/src/components/SpecialView.svelte @@ -15,19 +15,10 @@ <script lang="ts"> import { Class, Doc, DocumentQuery, Ref, Space, WithLookup } from '@hcengineering/core' import { Asset, IntlString } from '@hcengineering/platform' - import { - AnyComponent, - Button, - Component, - IconAdd, - Label, - Loading, - SearchEdit, - TabList, - showPopup - } from '@hcengineering/ui' + import { AnyComponent, Button, Component, IconAdd, Label, Loading, SearchEdit, showPopup } from '@hcengineering/ui' import { ViewOptions, Viewlet, ViewletDescriptor, ViewletPreference } from '@hcengineering/view' - import { FilterBar, FilterButton, ViewletSettingButton, setActiveViewletId } from '@hcengineering/view-resources' + import { FilterBar, FilterButton, ViewletSettingButton } from '@hcengineering/view-resources' + import ViewletSelector from '@hcengineering/view-resources/src/components/ViewletSelector.svelte' export let _class: Ref<Class<Doc>> export let space: Ref<Space> | undefined = undefined @@ -55,14 +46,6 @@ if (createComponent === undefined) return showPopup(createComponent, createComponentProps, 'top') } - - $: viewslist = viewlets.map((views) => { - return { - id: views._id, - icon: views.$lookup?.descriptor?.icon, - tooltip: views.$lookup?.descriptor?.label - } - }) </script> <div class="ac-header full divide caption-height"> @@ -71,24 +54,16 @@ </div> <div class="ac-header-full medium-gap mb-1"> - {#if viewlets.length > 1} - <TabList - items={viewslist} - multiselect={false} - selected={viewlet?._id} - on:select={(result) => { - if (result.detail !== undefined) { - if (viewlet?._id === result.detail.id) { - return - } - viewlet = viewlets.find((vl) => vl._id === result.detail.id) - if (viewlet) { - setActiveViewletId(viewlet._id) - } - } - }} - /> - {/if} + <ViewletSelector + bind:viewlet + bind:preference + bind:viewlets + viewletQuery={{ + attachTo: _class, + variant: { $exists: false }, + ...(descriptors !== undefined ? { descriptor: { $in: descriptors } } : {}) + }} + /> {#if createLabel && createComponent} <Button icon={IconAdd} @@ -108,17 +83,7 @@ <FilterButton {_class} /> </div> <div class="ac-header-full medium-gap"> - <ViewletSettingButton - bind:viewOptions - viewletQuery={{ - attachTo: _class, - variant: { $exists: false }, - ...(descriptors !== undefined ? { descriptor: { $in: descriptors } } : {}) - }} - bind:viewlets - bind:viewlet - bind:preference - /> + <ViewletSettingButton bind:viewOptions bind:viewlet /> <!-- <ActionIcon icon={IconMoreH} size={'small'} /> --> </div> </div>