2022-06-08 15:49:50 +00:00
|
|
|
|
<!--
|
|
|
|
|
// 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 contact from '@anticrm/contact'
|
2022-06-24 06:05:05 +00:00
|
|
|
|
import { DocumentQuery, FindOptions, SortingOrder } from '@anticrm/core'
|
|
|
|
|
import { IntlString } from '@anticrm/platform'
|
2022-06-08 15:49:50 +00:00
|
|
|
|
import { createQuery } from '@anticrm/presentation'
|
2022-06-24 06:05:05 +00:00
|
|
|
|
import { Project } from '@anticrm/tracker'
|
2022-08-03 07:05:19 +00:00
|
|
|
|
import { Button, IconAdd, Label, showPopup } from '@anticrm/ui'
|
2022-06-08 15:49:50 +00:00
|
|
|
|
import tracker from '../../plugin'
|
|
|
|
|
import { getIncludedProjectStatuses, projectsTitleMap, ProjectsViewMode } from '../../utils'
|
|
|
|
|
import NewProject from './NewProject.svelte'
|
|
|
|
|
import ProjectsListBrowser from './ProjectsListBrowser.svelte'
|
|
|
|
|
|
2022-06-24 06:05:05 +00:00
|
|
|
|
export let label: IntlString
|
2022-06-08 15:49:50 +00:00
|
|
|
|
export let query: DocumentQuery<Project> = {}
|
|
|
|
|
export let search: string = ''
|
|
|
|
|
export let mode: ProjectsViewMode = 'all'
|
|
|
|
|
|
|
|
|
|
const ENTRIES_LIMIT = 200
|
|
|
|
|
const resultProjectsQuery = createQuery()
|
|
|
|
|
|
|
|
|
|
const projectOptions: FindOptions<Project> = {
|
|
|
|
|
sort: { modifiedOn: SortingOrder.Descending },
|
|
|
|
|
limit: ENTRIES_LIMIT,
|
|
|
|
|
lookup: { lead: contact.class.Employee, members: contact.class.Employee }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let resultProjects: Project[] = []
|
|
|
|
|
|
|
|
|
|
$: includedProjectStatuses = getIncludedProjectStatuses(mode)
|
|
|
|
|
$: title = projectsTitleMap[mode]
|
|
|
|
|
$: includedProjectsQuery = { status: { $in: includedProjectStatuses } }
|
|
|
|
|
|
|
|
|
|
$: baseQuery = {
|
|
|
|
|
...includedProjectsQuery,
|
|
|
|
|
...query
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$: resultQuery = search === '' ? baseQuery : { $search: search, ...baseQuery }
|
|
|
|
|
|
|
|
|
|
$: resultProjectsQuery.query<Project>(
|
|
|
|
|
tracker.class.Project,
|
|
|
|
|
{ ...resultQuery },
|
|
|
|
|
(result) => {
|
|
|
|
|
resultProjects = result
|
|
|
|
|
},
|
|
|
|
|
projectOptions
|
|
|
|
|
)
|
|
|
|
|
|
2022-06-24 06:05:05 +00:00
|
|
|
|
const space = typeof query.space === 'string' ? query.space : tracker.team.DefaultTeam
|
2022-06-08 15:49:50 +00:00
|
|
|
|
const showCreateDialog = async () => {
|
2022-06-24 06:05:05 +00:00
|
|
|
|
showPopup(NewProject, { space, targetElement: null }, null)
|
2022-06-08 15:49:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const handleViewModeChanged = (newMode: ProjectsViewMode) => {
|
|
|
|
|
if (newMode === undefined || newMode === mode) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mode = newMode
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
<div class="fs-title flex-between header">
|
|
|
|
|
<div class="flex-center">
|
2022-06-24 06:05:05 +00:00
|
|
|
|
<Label {label} />
|
2022-06-08 15:49:50 +00:00
|
|
|
|
<div class="projectTitle">
|
|
|
|
|
› <Label label={title} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<Button size="small" icon={IconAdd} label={tracker.string.Project} kind="secondary" on:click={showCreateDialog} />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="itemsContainer">
|
|
|
|
|
<div class="flex-center">
|
|
|
|
|
<div class="flex-center">
|
|
|
|
|
<div class="buttonWrapper">
|
|
|
|
|
<Button
|
|
|
|
|
size="small"
|
|
|
|
|
shape="rectangle-right"
|
|
|
|
|
selected={mode === 'all'}
|
|
|
|
|
label={tracker.string.AllProjects}
|
|
|
|
|
on:click={() => handleViewModeChanged('all')}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="buttonWrapper">
|
|
|
|
|
<Button
|
|
|
|
|
size="small"
|
|
|
|
|
shape="rectangle"
|
|
|
|
|
selected={mode === 'backlog'}
|
|
|
|
|
label={tracker.string.BacklogProjects}
|
|
|
|
|
on:click={() => handleViewModeChanged('backlog')}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="buttonWrapper">
|
|
|
|
|
<Button
|
|
|
|
|
size="small"
|
|
|
|
|
shape="rectangle"
|
|
|
|
|
selected={mode === 'active'}
|
|
|
|
|
label={tracker.string.ActiveProjects}
|
|
|
|
|
on:click={() => handleViewModeChanged('active')}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="buttonWrapper">
|
|
|
|
|
<Button
|
|
|
|
|
size="small"
|
|
|
|
|
shape="rectangle-left"
|
|
|
|
|
selected={mode === 'closed'}
|
|
|
|
|
label={tracker.string.ClosedProjects}
|
|
|
|
|
on:click={() => handleViewModeChanged('closed')}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2022-08-03 07:05:19 +00:00
|
|
|
|
<!-- <div class="ml-3 filterButton">
|
2022-06-08 15:49:50 +00:00
|
|
|
|
<Button
|
|
|
|
|
size="small"
|
|
|
|
|
icon={IconAdd}
|
|
|
|
|
kind={'link-bordered'}
|
|
|
|
|
borderStyle={'dashed'}
|
|
|
|
|
label={tracker.string.Filter}
|
|
|
|
|
on:click={() => {}}
|
|
|
|
|
/>
|
2022-08-03 07:05:19 +00:00
|
|
|
|
</div> -->
|
2022-06-08 15:49:50 +00:00
|
|
|
|
</div>
|
2022-08-03 07:05:19 +00:00
|
|
|
|
<!-- <div class="flex-center">
|
2022-06-08 15:49:50 +00:00
|
|
|
|
<div class="flex-center">
|
|
|
|
|
<div class="buttonWrapper">
|
|
|
|
|
<Button selected size="small" shape="rectangle-right" icon={tracker.icon.ProjectsList} />
|
|
|
|
|
</div>
|
|
|
|
|
<div class="buttonWrapper">
|
|
|
|
|
<Button size="small" shape="rectangle-left" icon={tracker.icon.ProjectsTimeline} />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="ml-3">
|
|
|
|
|
<Button size="small" icon={IconOptions} />
|
|
|
|
|
</div>
|
2022-08-03 07:05:19 +00:00
|
|
|
|
</div> -->
|
2022-06-08 15:49:50 +00:00
|
|
|
|
</div>
|
|
|
|
|
<ProjectsListBrowser
|
|
|
|
|
_class={tracker.class.Project}
|
|
|
|
|
itemsConfig={[
|
|
|
|
|
{ key: '', presenter: tracker.component.IconPresenter },
|
2022-06-20 14:11:14 +00:00
|
|
|
|
{ key: '', presenter: tracker.component.ProjectPresenter, props: { kind: 'list' } },
|
2022-06-08 15:49:50 +00:00
|
|
|
|
{
|
|
|
|
|
key: '$lookup.lead',
|
|
|
|
|
presenter: tracker.component.LeadPresenter,
|
2022-06-24 06:05:05 +00:00
|
|
|
|
props: { defaultClass: contact.class.Employee, shouldShowLabel: false }
|
2022-06-08 15:49:50 +00:00
|
|
|
|
},
|
|
|
|
|
{ key: '', presenter: tracker.component.ProjectMembersPresenter, props: { kind: 'link' } },
|
|
|
|
|
{ key: '', presenter: tracker.component.TargetDatePresenter },
|
|
|
|
|
{ key: '', presenter: tracker.component.ProjectStatusPresenter }
|
|
|
|
|
]}
|
|
|
|
|
projects={resultProjects}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<style lang="scss">
|
|
|
|
|
.header {
|
|
|
|
|
min-height: 3.5rem;
|
|
|
|
|
padding-left: 2.25rem;
|
|
|
|
|
padding-right: 1.35rem;
|
|
|
|
|
border-bottom: 1px solid var(--theme-button-border-hovered);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.projectTitle {
|
|
|
|
|
display: flex;
|
|
|
|
|
margin-left: 0.25rem;
|
|
|
|
|
color: var(--content-color);
|
|
|
|
|
font-size: 0.8125rem;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.itemsContainer {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
padding: 0.65rem 1.35rem 0.65rem 2.25rem;
|
|
|
|
|
border-bottom: 1px solid var(--theme-button-border-hovered);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.buttonWrapper {
|
|
|
|
|
margin-right: 1px;
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.filterButton {
|
|
|
|
|
color: var(--caption-color);
|
|
|
|
|
}
|
|
|
|
|
</style>
|