mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-31 15:37:19 +03:00
UBER-53: My Leads view (#3259)
Signed-off-by: Vyacheslav Tumanov <me@slavatumanov.me>
This commit is contained in:
parent
b7463a3a16
commit
1ada38e652
@ -124,6 +124,13 @@ export function createModel (builder: Builder): void {
|
||||
hidden: false,
|
||||
navigatorModel: {
|
||||
specials: [
|
||||
{
|
||||
id: 'my-leads',
|
||||
label: lead.string.MyLeads,
|
||||
icon: lead.icon.Lead,
|
||||
component: lead.component.MyLeads,
|
||||
position: 'top'
|
||||
},
|
||||
{
|
||||
id: 'customers',
|
||||
label: lead.string.Customers,
|
||||
@ -378,6 +385,10 @@ export function createModel (builder: Builder): void {
|
||||
filters: ['attachedTo']
|
||||
})
|
||||
|
||||
builder.mixin(lead.class.Lead, core.class.Class, notification.mixin.ClassCollaborators, {
|
||||
fields: ['createdBy', 'assignee']
|
||||
})
|
||||
|
||||
builder.mixin(lead.mixin.Customer, core.class.Class, view.mixin.ClassFilters, {
|
||||
filters: ['_class']
|
||||
})
|
||||
|
@ -13,6 +13,7 @@
|
||||
"Customer": "Customer",
|
||||
"Customers": "Customers",
|
||||
"Leads": "Leads",
|
||||
"MyLeads": "My Leads",
|
||||
"SelectCustomer": "Select customer",
|
||||
"Lead": "Lead",
|
||||
"Assignee": "Assignee",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"Customer": "Клиент",
|
||||
"Customers": "Клиенты",
|
||||
"Leads": "Сделки",
|
||||
"MyLeads": "Мои сделки",
|
||||
"SelectCustomer": "Выбрать клиента",
|
||||
"Lead": "Сделка",
|
||||
"Assignee": "Исполнитель",
|
||||
|
156
plugins/lead-resources/src/components/MyLeads.svelte
Normal file
156
plugins/lead-resources/src/components/MyLeads.svelte
Normal file
@ -0,0 +1,156 @@
|
||||
<!--
|
||||
// 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 { EmployeeAccount } from '@hcengineering/contact'
|
||||
import { AttachedDoc, Class, DocumentQuery, getCurrentAccount, Ref } from '@hcengineering/core'
|
||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||
import task, { Task } from '@hcengineering/task'
|
||||
import { IModeSelector, Label, resolvedLocationStore, SearchEdit, ModeSelector, Loading } from '@hcengineering/ui'
|
||||
import {
|
||||
FilterButton,
|
||||
getViewOptions,
|
||||
makeViewletKey,
|
||||
TableBrowser,
|
||||
viewOptionStore
|
||||
} from '@hcengineering/view-resources'
|
||||
import { IntlString } from '@hcengineering/platform'
|
||||
import ViewletSettingButton from '@hcengineering/view-resources/src/components/ViewletSettingButton.svelte'
|
||||
import view, { Viewlet, ViewletPreference } from '@hcengineering/view'
|
||||
import { onDestroy } from 'svelte'
|
||||
import FilterBar from '@hcengineering/view-resources/src/components/filter/FilterBar.svelte'
|
||||
import lead from '../plugin'
|
||||
import { Lead } from '@hcengineering/lead'
|
||||
|
||||
export let _class: Ref<Class<Lead>> = lead.class.Lead
|
||||
export let labelTasks = lead.string.MyLeads
|
||||
|
||||
let search = ''
|
||||
const currentUser = getCurrentAccount() as EmployeeAccount
|
||||
const assigned = { assignee: currentUser.employee }
|
||||
const created = { createdBy: currentUser._id }
|
||||
let subscribed = { _id: { $in: [] as Ref<Task>[] } }
|
||||
|
||||
$: baseQuery = updateBaseQuery(mode, { assigned, created, subscribed })
|
||||
function updateBaseQuery (mode: string, queries: { [key: string]: DocumentQuery<Lead> }) {
|
||||
return { ...queries[mode] }
|
||||
}
|
||||
let searchQuery: DocumentQuery<Lead> = { ...baseQuery }
|
||||
function updateSearchQuery (search: string): void {
|
||||
searchQuery = search === '' ? { ...baseQuery } : { ...baseQuery, $search: search }
|
||||
}
|
||||
$: if (baseQuery) updateSearchQuery(search)
|
||||
$: resultQuery = { ...searchQuery }
|
||||
|
||||
const subscribedQuery = createQuery()
|
||||
function getSubscribed () {
|
||||
subscribedQuery.query(
|
||||
_class,
|
||||
{ 'notification:mixin:Collaborators.collaborators': getCurrentAccount()._id },
|
||||
(result) => {
|
||||
const newSub = result.map((p) => p._id as Ref<AttachedDoc> as Ref<Lead>)
|
||||
const curSub = subscribed._id.$in
|
||||
if (curSub.length !== newSub.length || curSub.some((id, i) => newSub[i] !== id)) {
|
||||
subscribed = { _id: { $in: newSub } }
|
||||
}
|
||||
},
|
||||
{ sort: { _id: 1 } }
|
||||
)
|
||||
}
|
||||
$: if (mode === 'subscribed') getSubscribed()
|
||||
const config: [string, IntlString, object][] = [
|
||||
['assigned', view.string.Assigned, {}],
|
||||
['created', view.string.Created, {}],
|
||||
['subscribed', view.string.Subscribed, {}]
|
||||
]
|
||||
let [[mode]] = config
|
||||
function handleChangeMode (newMode: string) {
|
||||
if (newMode === mode) return
|
||||
mode = newMode
|
||||
}
|
||||
$: modeSelectorProps = {
|
||||
config,
|
||||
mode,
|
||||
onChange: handleChangeMode
|
||||
} as IModeSelector
|
||||
|
||||
let viewlet: Viewlet | undefined
|
||||
let loading = true
|
||||
|
||||
let key = makeViewletKey()
|
||||
let preference: ViewletPreference | undefined
|
||||
onDestroy(
|
||||
resolvedLocationStore.subscribe((loc) => {
|
||||
key = makeViewletKey(loc)
|
||||
})
|
||||
)
|
||||
|
||||
const preferenceQuery = createQuery()
|
||||
const client = getClient()
|
||||
client
|
||||
.findOne<Viewlet>(view.class.Viewlet, { attachTo: _class, descriptor: task.viewlet.StatusTable })
|
||||
.then((res) => {
|
||||
viewlet = res
|
||||
preferenceQuery.query(
|
||||
view.class.ViewletPreference,
|
||||
{
|
||||
attachedTo: res._id
|
||||
},
|
||||
(res) => {
|
||||
preference = res[0]
|
||||
loading = false
|
||||
},
|
||||
{ limit: 1 }
|
||||
)
|
||||
})
|
||||
$: viewOptions = getViewOptions(viewlet, $viewOptionStore)
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="ac-header full divide"
|
||||
class:header-with-mode-selector={modeSelectorProps !== undefined}
|
||||
class:header-without-label={!labelTasks}
|
||||
>
|
||||
<div class="ac-header__wrap-title">
|
||||
<span class="ac-header__title"><Label label={labelTasks} /></span>
|
||||
{#if modeSelectorProps !== undefined}
|
||||
<ModeSelector props={modeSelectorProps} />
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ac-header full divide search-start">
|
||||
<div class="ac-header-full small-gap">
|
||||
<SearchEdit bind:value={search} />
|
||||
<div class="buttons-divider" />
|
||||
<FilterButton {_class} />
|
||||
</div>
|
||||
{#if viewlet}
|
||||
<ViewletSettingButton bind:viewOptions {viewlet} />
|
||||
{/if}
|
||||
</div>
|
||||
<FilterBar {_class} query={searchQuery} {viewOptions} on:change={(e) => (resultQuery = e.detail)} />
|
||||
|
||||
{#if viewlet}
|
||||
{#if loading}
|
||||
<Loading />
|
||||
{:else}
|
||||
<TableBrowser
|
||||
{_class}
|
||||
config={preference?.config ?? viewlet.config}
|
||||
options={viewlet.options}
|
||||
query={resultQuery}
|
||||
showNotification
|
||||
/>
|
||||
{/if}
|
||||
{/if}
|
@ -27,6 +27,7 @@ import CreateCustomer from './components/CreateCustomer.svelte'
|
||||
import NewItemsHeader from './components/NewItemsHeader.svelte'
|
||||
import { getLeadTitle } from './utils'
|
||||
import EditFunnel from './components/EditFunnel.svelte'
|
||||
import MyLeads from './components/MyLeads.svelte'
|
||||
|
||||
export default async (): Promise<Resources> => ({
|
||||
component: {
|
||||
@ -40,7 +41,8 @@ export default async (): Promise<Resources> => ({
|
||||
Leads,
|
||||
CreateCustomer,
|
||||
NewItemsHeader,
|
||||
EditFunnel
|
||||
EditFunnel,
|
||||
MyLeads
|
||||
},
|
||||
function: {
|
||||
LeadTitleProvider: getLeadTitle
|
||||
|
@ -31,6 +31,7 @@ export default mergeIds(leadId, lead, {
|
||||
SelectCustomer: '' as IntlString,
|
||||
Customers: '' as IntlString,
|
||||
Leads: '' as IntlString,
|
||||
MyLeads: '' as IntlString,
|
||||
NoLeadsForDocument: '' as IntlString,
|
||||
LeadPlaceholder: '' as IntlString,
|
||||
CreateCustomer: '' as IntlString,
|
||||
@ -47,7 +48,8 @@ export default mergeIds(leadId, lead, {
|
||||
CreateCustomer: '' as AnyComponent,
|
||||
LeadsPresenter: '' as AnyComponent,
|
||||
CreateFunnel: '' as AnyComponent,
|
||||
EditFunnel: '' as AnyComponent
|
||||
EditFunnel: '' as AnyComponent,
|
||||
MyLeads: '' as AnyComponent
|
||||
},
|
||||
function: {
|
||||
LeadTitleProvider: '' as Resource<(client: Client, ref: Ref<Doc>) => Promise<string>>
|
||||
|
Loading…
Reference in New Issue
Block a user