Files
huly-platform/plugins/task-resources/src/components/StatusTableView.svelte
T
2022-05-13 13:38:54 +07:00

240 lines
6.5 KiB
Svelte

<!--
// 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 { Class, DocumentQuery, FindOptions, Ref, SortingOrder } from '@anticrm/core'
import { createQuery } from '@anticrm/presentation'
import { DoneState, SpaceWithStates, State, Task } from '@anticrm/task'
import Label from '@anticrm/ui/src/components/Label.svelte'
import { TableBrowser } from '@anticrm/view-resources'
import task from '../plugin'
import Lost from './icons/Lost.svelte'
import Won from './icons/Won.svelte'
import StatesBar from './state/StatesBar.svelte'
export let _class: Ref<Class<Task>>
export let space: Ref<SpaceWithStates>
export let options: FindOptions<Task> | undefined
export let config: string[]
export let search: string
let doneStatusesView: boolean = false
let state: Ref<State> | undefined = undefined
let selectedDoneStates: Set<Ref<DoneState>> = new Set<Ref<DoneState>>()
$: resConfig = updateConfig(config)
let query = {}
let doneStates: DoneState[] = []
let withoutDone: boolean = false
function updateConfig (config: string[]): string[] {
if (state !== undefined) {
return config.filter((p) => p !== '$lookup.state')
}
if (selectedDoneStates.size === 1) {
return config.filter((p) => p !== '$lookup.doneState')
}
return config
}
const doneStateQuery = createQuery()
doneStateQuery.query(
task.class.DoneState,
{
space
},
(res) => (doneStates = res),
{
sort: {
_class: SortingOrder.Descending,
rank: SortingOrder.Descending
}
}
)
async function updateQuery (search: string, selectedDoneStates: Set<Ref<DoneState>>): Promise<void> {
resConfig = updateConfig(config)
const result = {} as DocumentQuery<Task>
if (search !== '') {
result.$search = search
}
result.space = space
if (state) {
result.state = state
}
if (selectedDoneStates.size > 0) {
result.doneState = {
$in: Array.from(selectedDoneStates)
}
} else if (withoutDone) {
result.doneState = null
}
query = result
}
function doneStateClick (id: Ref<DoneState>): void {
withoutDone = false
if (selectedDoneStates.has(id)) {
selectedDoneStates.delete(id)
} else {
selectedDoneStates.add(id)
}
selectedDoneStates = selectedDoneStates
updateQuery(search, selectedDoneStates)
}
function noDoneClick (): void {
withoutDone = !withoutDone
selectedDoneStates.clear()
selectedDoneStates = selectedDoneStates
updateQuery(search, selectedDoneStates)
}
$: updateQuery(search, selectedDoneStates)
</script>
<div class="flex-between mb-4 header">
<div class="flex-row-center buttons">
<div
class="button flex-center"
class:active={!doneStatusesView}
on:click={() => {
doneStatusesView = false
state = undefined
withoutDone = false
selectedDoneStates.clear()
updateQuery(search, selectedDoneStates)
}}
>
<Label label={task.string.AllStates} />
</div>
<div
class="button flex-center ml-3"
class:active={doneStatusesView}
on:click={() => {
doneStatusesView = true
state = undefined
selectedDoneStates.clear()
updateQuery(search, selectedDoneStates)
}}
>
<Label label={task.string.DoneStates} />
</div>
</div>
<div
class="flex-row-center caption-color states"
class:antiStatesBar={doneStatusesView}
class:justify-end={doneStatusesView}
>
{#if doneStatusesView}
<div
class="doneState withoutDone flex-center whitespace-nowrap"
class:disable={!withoutDone}
on:click={() => {
noDoneClick()
}}
>
<Label label={task.string.NoDoneState} />
</div>
{#each doneStates as state}
<div
class="doneState flex-center whitespace-nowrap"
class:won={state._class === task.class.WonState}
class:lost={state._class === task.class.LostState}
class:disable={!selectedDoneStates.has(state._id)}
on:click={() => {
doneStateClick(state._id)
}}
>
{#if state._class === task.class.WonState}
<Won size="medium" />
{:else}
<Lost size="medium" />
{/if}
<span class="ml-2">
{state.title}
</span>
</div>
{/each}
{:else}
<StatesBar bind:state {space} on:change={() => updateQuery(search, selectedDoneStates)} />
{/if}
</div>
</div>
<div class="statustableview-container">
<TableBrowser {_class} {query} config={resConfig} {options} showNotification />
</div>
<style lang="scss">
.statustableview-container {
flex-grow: 1;
margin-bottom: 0.75rem;
min-height: 0;
height: 100%;
}
.header {
margin-left: 2.5rem;
margin-right: 1.75rem;
.buttons {
padding: 0.125rem 0;
}
.states {
max-width: 75%;
}
}
.button {
height: 2.5rem;
padding: 0.5rem 0.75rem;
border: 1px solid transparent;
border-radius: 0.5rem;
cursor: pointer;
&:hover {
background-color: var(--theme-button-bg-enabled);
border-color: var(--theme-button-border-enabled);
}
&.active {
background-color: var(--theme-button-bg-enabled);
color: var(--theme-caption-color);
border-color: var(--theme-button-border-enabled);
}
}
.doneState {
padding: 0.5rem 0.75rem;
height: 2.5rem;
border: 1px solid var(--theme-button-border-enabled);
border-radius: 0.5rem;
cursor: pointer;
&.won {
background-color: #60b96e;
}
&.lost {
background-color: #f06c63;
}
&.withoutDone {
background-color: var(--theme-bg-focused-color);
}
&.disable {
background-color: var(--theme-button-bg-enabled);
}
}
.doneState + .doneState {
margin-left: 0.75rem;
}
</style>