Extract special view (#1969)

Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com>
This commit is contained in:
Denis Bykhov 2022-06-01 18:13:12 +06:00 committed by GitHub
parent 5705281de5
commit ae6ee89582
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 67 additions and 344 deletions

View File

@ -121,7 +121,14 @@ export function createModel (builder: Builder): void {
id: 'Products',
label: inventory.string.Products,
icon: inventory.icon.Products,
component: inventory.component.Products
component: workbench.component.SpecialView,
componentProps: {
_class: inventory.class.Product,
icon: inventory.icon.Products,
label: inventory.string.Products,
createLabel: inventory.string.ProductCreateLabel,
createComponent: inventory.component.CreateProduct
}
}
],
spaces: []

View File

@ -33,7 +33,6 @@ export default mergeIds(inventoryId, inventory, {
},
component: {
Categories: '' as AnyComponent,
Products: '' as AnyComponent,
CreateProduct: '' as AnyComponent,
EditProduct: '' as AnyComponent,
CategoryPresenter: '' as AnyComponent,

View File

@ -106,7 +106,12 @@ export function createModel (builder: Builder): void {
id: 'customers',
label: lead.string.Customers,
icon: contact.icon.Person, // <-- Put contact general icon here.
component: lead.component.Customers,
component: workbench.component.SpecialView,
componentProps: {
_class: lead.mixin.Customer,
icon: lead.icon.Lead,
label: lead.string.Customers
},
position: 'top'
}
],

View File

@ -41,7 +41,6 @@ export default mergeIds(leadId, lead, {
KanbanCard: '' as AnyComponent,
LeadPresenter: '' as AnyComponent,
TemplatesIcon: '' as AnyComponent,
Customers: '' as AnyComponent,
Leads: '' as AnyComponent,
NewItemsHeader: '' as AnyComponent
},

View File

@ -173,18 +173,34 @@ export function createModel (builder: Builder): void {
},
{
id: applicantsId,
component: recruit.component.ApplicationsView,
component: workbench.component.SpecialView,
icon: recruit.icon.Application,
label: recruit.string.Applications,
createItemLabel: recruit.string.ApplicationCreateLabel,
componentProps: {
_class: recruit.class.Applicant,
icon: recruit.icon.Application,
label: recruit.string.Applications,
createLabel: recruit.string.ApplicationCreateLabel,
createComponent: recruit.component.CreateApplication,
descriptor: task.viewlet.StatusTable,
baseQuery: {
doneState: null
}
},
position: 'vacancy'
},
{
id: candidatesId,
component: recruit.component.Candidates,
component: workbench.component.SpecialView,
icon: contact.icon.Person,
label: recruit.string.Candidates,
createItemLabel: recruit.string.CandidateCreateLabel,
componentProps: {
_class: recruit.mixin.Candidate,
icon: contact.icon.Person,
label: recruit.string.Candidates,
createLabel: recruit.string.CandidateCreateLabel,
createComponent: recruit.component.CreateCandidate
},
position: 'vacancy'
},
{

View File

@ -66,7 +66,6 @@ export default mergeIds(recruitId, recruit, {
EditApplication: '' as AnyComponent,
TemplatesIcon: '' as AnyComponent,
Applications: '' as AnyComponent,
Candidates: '' as AnyComponent,
SkillsView: '' as AnyComponent,
Vacancies: '' as AnyComponent,
@ -77,7 +76,6 @@ export default mergeIds(recruitId, recruit, {
ReviewPresenter: '' as AnyComponent,
Opinions: '' as AnyComponent,
OpinionPresenter: '' as AnyComponent,
ApplicationsView: '' as AnyComponent,
NewCandidateHeader: '' as AnyComponent
},
template: {

View File

@ -23,7 +23,8 @@ export default mergeIds(workbenchId, workbench, {
component: {
ApplicationPresenter: '' as AnyComponent,
Archive: '' as AnyComponent,
SpaceBrowser: '' as AnyComponent
SpaceBrowser: '' as AnyComponent,
SpecialView: '' as AnyComponent
},
string: {
Application: '' as IntlString,

View File

@ -1,106 +0,0 @@
<!--
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021, 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 { createQuery, getClient } from '@anticrm/presentation'
import ui, {
Button,
EditWithIcon,
eventToHTMLElement,
Icon,
IconAdd,
IconSearch,
Label,
Loading,
showPopup
} from '@anticrm/ui'
import view, { Viewlet, ViewletPreference } from '@anticrm/view'
import { TableBrowser, ViewletSettingButton } from '@anticrm/view-resources'
import inventory from '../plugin'
import CreateProduct from './CreateProduct.svelte'
let search = ''
$: resultQuery = search === '' ? {} : { $search: search }
let descr: Viewlet | undefined
let loading = true
const preferenceQuery = createQuery()
let preference: ViewletPreference | undefined
const client = getClient()
client
.findOne<Viewlet>(view.class.Viewlet, {
attachTo: inventory.class.Product,
descriptor: view.viewlet.Table
})
.then((res) => {
descr = res
if (res !== undefined) {
preferenceQuery.query(
view.class.ViewletPreference,
{
attachedTo: res._id
},
(res) => {
preference = res[0]
loading = false
},
{ limit: 1 }
)
}
})
function showCreateDialog (ev: MouseEvent) {
showPopup(CreateProduct, { space: inventory.space.Products }, eventToHTMLElement(ev))
}
</script>
<div class="ac-header full withSettings">
<div class="ac-header__wrap-title">
<span class="ac-header__icon"><Icon icon={inventory.icon.Products} size={'small'} /></span>
<span class="ac-header__title"><Label label={inventory.string.Products} /></span>
</div>
<EditWithIcon
icon={IconSearch}
placeholder={ui.string.Search}
bind:value={search}
on:change={() => {
resultQuery = {}
}}
/>
<Button
label={inventory.string.ProductCreateLabel}
icon={IconAdd}
kind={'primary'}
on:click={(ev) => showCreateDialog(ev)}
/>
<ViewletSettingButton viewlet={descr} />
</div>
{#if descr}
{#if loading}
<Loading />
{:else}
<TableBrowser
_class={inventory.class.Product}
config={preference?.config ?? descr.config}
options={descr.options}
query={resultQuery}
showNotification
/>
{/if}
{/if}

View File

@ -22,9 +22,9 @@ import CategoryPresenter from './components/CategoryPresenter.svelte'
import CreateCategory from './components/CreateCategory.svelte'
import EditProduct from './components/EditProduct.svelte'
import ProductPresenter from './components/ProductPresenter.svelte'
import Products from './components/Products.svelte'
import VariantPresenter from './components/VariantPresenter.svelte'
import Variants from './components/Variants.svelte'
import CreateProduct from './components/CreateProduct.svelte'
async function createSubcategory (object: Doc): Promise<void> {
showPopup(CreateCategory, { attachedTo: object._id })
@ -37,10 +37,10 @@ export default async (): Promise<Resources> => ({
component: {
Categories,
CategoryPresenter,
Products,
ProductPresenter,
EditProduct,
Variants,
VariantPresenter
VariantPresenter,
CreateProduct
}
})

View File

@ -1,88 +0,0 @@
<!--
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 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 { Doc, DocumentQuery } from '@anticrm/core'
import { createQuery, getClient } from '@anticrm/presentation'
import { Icon, Label, Loading, SearchEdit } from '@anticrm/ui'
import view, { Viewlet, ViewletPreference } from '@anticrm/view'
import { TableBrowser, ViewletSettingButton } from '@anticrm/view-resources'
import lead from '../plugin'
let search = ''
let resultQuery: DocumentQuery<Doc> = {}
let descr: Viewlet | undefined
let loading = true
const preferenceQuery = createQuery()
let preference: ViewletPreference | undefined
const client = getClient()
client
.findOne<Viewlet>(view.class.Viewlet, {
attachTo: lead.mixin.Customer,
descriptor: view.viewlet.Table
})
.then((res) => {
descr = res
if (res !== undefined) {
preferenceQuery.query(
view.class.ViewletPreference,
{
attachedTo: res._id
},
(res) => {
preference = res[0]
loading = false
},
{ limit: 1 }
)
}
})
function updateResultQuery (search: string): void {
resultQuery = search === '' ? {} : { $search: search }
}
</script>
<div class="ac-header full withSettings">
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={lead.icon.Lead} size={'small'} /></div>
<span class="ac-header__title"><Label label={lead.string.Customers} /></span>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search)
}}
/>
<ViewletSettingButton viewlet={descr} />
</div>
{#if descr}
{#if loading}
<Loading />
{:else}
<TableBrowser
_class={lead.mixin.Customer}
config={preference?.config ?? descr.config}
options={descr.options}
query={resultQuery}
showNotification
/>
{/if}
{/if}

View File

@ -17,7 +17,6 @@
import { Resources } from '@anticrm/platform'
import CreateFunnel from './components/CreateFunnel.svelte'
import CreateLead from './components/CreateLead.svelte'
import Customers from './components/Customers.svelte'
import EditLead from './components/EditLead.svelte'
import KanbanCard from './components/KanbanCard.svelte'
import LeadPresenter from './components/LeadPresenter.svelte'
@ -35,7 +34,6 @@ export default async (): Promise<Resources> => ({
KanbanCard,
LeadPresenter,
TemplatesIcon,
Customers,
LeadsPresenter,
Leads,
CreateCustomer,

View File

@ -1,107 +0,0 @@
<!--
// Copyright © 2020, 2021 Anticrm Platform Contributors.
// Copyright © 2021 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 contact from '@anticrm/contact'
import { Doc, DocumentQuery } from '@anticrm/core'
import { createQuery, getClient } from '@anticrm/presentation'
import { Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@anticrm/ui'
import type { Filter } from '@anticrm/view'
import view, { Viewlet, ViewletPreference } from '@anticrm/view'
import { ActionContext, FilterButton, TableBrowser, ViewletSettingButton } from '@anticrm/view-resources'
import recruit from '../plugin'
import CreateCandidate from './CreateCandidate.svelte'
let search = ''
let resultQuery: DocumentQuery<Doc> = {}
let filters: Filter[] = []
const client = getClient()
let descr: Viewlet | undefined
let loading = true
const preferenceQuery = createQuery()
let preference: ViewletPreference | undefined
client
.findOne<Viewlet>(view.class.Viewlet, {
attachTo: recruit.mixin.Candidate,
descriptor: view.viewlet.Table
})
.then((res) => {
descr = res
if (res !== undefined) {
preferenceQuery.query(
view.class.ViewletPreference,
{
attachedTo: res._id
},
(res) => {
preference = res[0]
loading = false
},
{ limit: 1 }
)
}
})
async function updateResultQuery (search: string): Promise<void> {
resultQuery = search === '' ? {} : { $search: search }
}
$: updateResultQuery(search)
function showCreateDialog () {
showPopup(CreateCandidate, {}, 'top')
}
</script>
<div class="ac-header full withSettings">
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={contact.icon.Person} size={'small'} /></div>
<span class="ac-header__title"><Label label={recruit.string.Candidates} /></span>
<div class="ml-4"><FilterButton _class={recruit.mixin.Candidate} bind:filters /></div>
</div>
<SearchEdit
bind:value={search}
on:change={() => {
updateResultQuery(search)
}}
/>
<Button icon={IconAdd} label={recruit.string.CandidateCreateLabel} kind={'primary'} on:click={showCreateDialog} />
<ViewletSettingButton viewlet={descr} />
</div>
<ActionContext
context={{
mode: 'browser'
}}
/>
{#if descr}
{#if loading}
<Loading />
{:else}
<TableBrowser
_class={recruit.mixin.Candidate}
config={preference?.config ?? descr.config}
options={descr.options}
query={resultQuery}
bind:filters
showNotification
/>
{/if}
{/if}

View File

@ -23,8 +23,6 @@ import ApplicationItem from './components/ApplicationItem.svelte'
import ApplicationPresenter from './components/ApplicationPresenter.svelte'
import Applications from './components/Applications.svelte'
import ApplicationsPresenter from './components/ApplicationsPresenter.svelte'
import ApplicationsView from './components/ApplicationsView.svelte'
import Candidates from './components/Candidates.svelte'
import CreateApplication from './components/CreateApplication.svelte'
import CreateCandidate from './components/CreateCandidate.svelte'
import CreateVacancy from './components/CreateVacancy.svelte'
@ -140,7 +138,6 @@ export default async (): Promise<Resources> => ({
EditVacancy,
TemplatesIcon,
Applications,
Candidates,
CreateCandidate,
VacancyPresenter,
SkillsView,
@ -156,7 +153,6 @@ export default async (): Promise<Resources> => ({
Opinions,
OpinionPresenter,
OpinionsPresenter,
ApplicationsView,
NewCandidateHeader
},

View File

@ -13,35 +13,35 @@
// limitations under the License.
-->
<script lang="ts">
import { Doc, DocumentQuery } from '@anticrm/core'
import { Class, Doc, DocumentQuery, Ref } from '@anticrm/core'
import { Asset, IntlString } from '@anticrm/platform'
import { createQuery, getClient } from '@anticrm/presentation'
import { Applicant } from '@anticrm/recruit'
import task from '@anticrm/task'
import { Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@anticrm/ui'
import type { Filter } from '@anticrm/view'
import view, { Viewlet, ViewletPreference } from '@anticrm/view'
import { AnyComponent, Button, Icon, IconAdd, Label, Loading, SearchEdit, showPopup } from '@anticrm/ui'
import view, { Filter, Viewlet, ViewletDescriptor, ViewletPreference } from '@anticrm/view'
import { FilterButton, TableBrowser, ViewletSettingButton } from '@anticrm/view-resources'
import recruit from '../plugin'
import CreateApplication from './CreateApplication.svelte'
export let _class: Ref<Class<Doc>>
export let icon: Asset
export let label: IntlString
export let createLabel: IntlString | undefined
export let createComponent: AnyComponent | undefined
export let descriptor: Ref<ViewletDescriptor> = view.viewlet.Table
export let baseQuery: DocumentQuery<Doc> = {}
let search = ''
let resultQuery: DocumentQuery<Doc> = {}
const baseQuery: DocumentQuery<Applicant> = {
doneState: null
}
$: resultQuery = search === '' ? {} : { $search: search }
let filters: Filter[] = []
const client = getClient()
let descr: Viewlet | undefined
let loading = true
const preferenceQuery = createQuery()
let preference: ViewletPreference | undefined
const client = getClient()
client
.findOne<Viewlet>(view.class.Viewlet, {
attachTo: recruit.class.Applicant,
descriptor: task.viewlet.StatusTable
attachTo: _class,
descriptor
})
.then((res) => {
descr = res
@ -60,8 +60,9 @@
}
})
function showCreateDialog () {
showPopup(CreateApplication, {}, 'top')
function showCreateDialog (ev: MouseEvent) {
if (createComponent === undefined) return
showPopup(createComponent, {}, 'top')
}
function updateResultQuery (search: string): void {
@ -71,9 +72,9 @@
<div class="ac-header full withSettings">
<div class="ac-header__wrap-title">
<div class="ac-header__icon"><Icon icon={recruit.icon.Application} size={'small'} /></div>
<span class="ac-header__title"><Label label={recruit.string.Applications} /></span>
<div class="ml-4"><FilterButton _class={recruit.class.Applicant} bind:filters /></div>
<span class="ac-header__icon"><Icon {icon} size={'small'} /></span>
<span class="ac-header__title"><Label {label} /></span>
<div class="ml-4"><FilterButton {_class} bind:filters /></div>
</div>
<SearchEdit
@ -82,7 +83,9 @@
updateResultQuery(search)
}}
/>
<Button icon={IconAdd} label={recruit.string.ApplicationCreateLabel} kind={'primary'} on:click={showCreateDialog} />
{#if createLabel && createComponent}
<Button label={createLabel} icon={IconAdd} kind={'primary'} on:click={(ev) => showCreateDialog(ev)} />
{/if}
<ViewletSettingButton viewlet={descr} />
</div>
@ -91,7 +94,7 @@
<Loading />
{:else}
<TableBrowser
_class={recruit.class.Applicant}
{_class}
config={preference?.config ?? descr.config}
options={descr.options}
query={resultQuery}

View File

@ -19,6 +19,7 @@ import ApplicationPresenter from './components/ApplicationPresenter.svelte'
import Archive from './components/Archive.svelte'
import SpacePanel from './components/navigator/SpacePanel.svelte'
import SpaceBrowser from './components/SpaceBrowser.svelte'
import SpecialView from './components/SpecialView.svelte'
import WorkbenchApp from './components/WorkbenchApp.svelte'
import { doNavigate } from './utils'
@ -32,6 +33,7 @@ export default async (): Promise<Resources> => ({
ApplicationPresenter,
Archive,
SpacePanel,
SpecialView,
SpaceBrowser
},
function: {