mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
Activity: filters (#2395)
* Activity: filters Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
46b70a2e9c
commit
90bc1da39f
@ -71,7 +71,7 @@
|
|||||||
"@hcengineering/contact-assets": "~0.6.0",
|
"@hcengineering/contact-assets": "~0.6.0",
|
||||||
"@hcengineering/activity": "~0.6.0",
|
"@hcengineering/activity": "~0.6.0",
|
||||||
"@hcengineering/activity-assets": "~0.6.0",
|
"@hcengineering/activity-assets": "~0.6.0",
|
||||||
"@hcengineering/activity-resources": "~0.6.0",
|
"@hcengineering/activity-resources": "~0.6.1",
|
||||||
"@hcengineering/automation": "~0.6.0",
|
"@hcengineering/automation": "~0.6.0",
|
||||||
"@hcengineering/automation-assets": "~0.6.0",
|
"@hcengineering/automation-assets": "~0.6.0",
|
||||||
"@hcengineering/automation-resources": "~0.6.0",
|
"@hcengineering/automation-resources": "~0.6.0",
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import type { TxViewlet } from '@hcengineering/activity'
|
import type { ActivityFilter, DisplayTx, TxViewlet } from '@hcengineering/activity'
|
||||||
import activity from '@hcengineering/activity'
|
import activity from '@hcengineering/activity'
|
||||||
import core, { Class, Doc, DocumentQuery, DOMAIN_MODEL, Ref, Tx } from '@hcengineering/core'
|
import core, { Class, Doc, DocumentQuery, DOMAIN_MODEL, Ref, Tx } from '@hcengineering/core'
|
||||||
import { Builder, Model } from '@hcengineering/model'
|
import { Builder, Model } from '@hcengineering/model'
|
||||||
import { TDoc } from '@hcengineering/model-core'
|
import { TDoc } from '@hcengineering/model-core'
|
||||||
import type { Asset, IntlString } from '@hcengineering/platform'
|
import type { Asset, IntlString, Resource } from '@hcengineering/platform'
|
||||||
import { AnyComponent } from '@hcengineering/ui'
|
import { AnyComponent } from '@hcengineering/ui'
|
||||||
|
|
||||||
@Model(activity.class.TxViewlet, core.class.Doc, DOMAIN_MODEL)
|
@Model(activity.class.TxViewlet, core.class.Doc, DOMAIN_MODEL)
|
||||||
@ -36,6 +36,12 @@ export class TTxViewlet extends TDoc implements TxViewlet {
|
|||||||
hideOnRemove!: boolean
|
hideOnRemove!: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createModel (builder: Builder): void {
|
@Model(activity.class.ActivityFilter, core.class.Class, DOMAIN_MODEL)
|
||||||
builder.createModel(TTxViewlet)
|
export class TActivityFilter extends TDoc implements ActivityFilter {
|
||||||
|
label!: IntlString
|
||||||
|
filter!: Resource<(txes: DisplayTx[]) => DisplayTx[]>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createModel (builder: Builder): void {
|
||||||
|
builder.createModel(TTxViewlet, TActivityFilter)
|
||||||
}
|
}
|
||||||
|
@ -96,6 +96,11 @@ export function createModel (builder: Builder): void {
|
|||||||
attachment.ids.TxAttachmentCreate
|
attachment.ids.TxAttachmentCreate
|
||||||
)
|
)
|
||||||
|
|
||||||
|
builder.createDoc(activity.class.ActivityFilter, core.space.Model, {
|
||||||
|
label: attachment.string.FilterAttachments,
|
||||||
|
filter: attachment.filter.AttachmentsFilter
|
||||||
|
})
|
||||||
|
|
||||||
builder.createDoc(
|
builder.createDoc(
|
||||||
view.class.ActionCategory,
|
view.class.ActionCategory,
|
||||||
core.space.Model,
|
core.space.Model,
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import type { TxViewlet } from '@hcengineering/activity'
|
import type { DisplayTx, TxViewlet } from '@hcengineering/activity'
|
||||||
import { attachmentId } from '@hcengineering/attachment'
|
import { attachmentId } from '@hcengineering/attachment'
|
||||||
import attachment from '@hcengineering/attachment-resources/src/plugin'
|
import attachment from '@hcengineering/attachment-resources/src/plugin'
|
||||||
import type { Ref } from '@hcengineering/core'
|
import type { Ref } from '@hcengineering/core'
|
||||||
import type { IntlString } from '@hcengineering/platform'
|
import type { IntlString, Resource } from '@hcengineering/platform'
|
||||||
import { mergeIds } from '@hcengineering/platform'
|
import { mergeIds } from '@hcengineering/platform'
|
||||||
import type { AnyComponent } from '@hcengineering/ui'
|
import type { AnyComponent } from '@hcengineering/ui'
|
||||||
import type { ActionCategory } from '@hcengineering/view'
|
import type { ActionCategory } from '@hcengineering/view'
|
||||||
@ -38,7 +38,8 @@ export default mergeIds(attachmentId, attachment, {
|
|||||||
SavedAttachments: '' as IntlString,
|
SavedAttachments: '' as IntlString,
|
||||||
Description: '' as IntlString,
|
Description: '' as IntlString,
|
||||||
PinAttachment: '' as IntlString,
|
PinAttachment: '' as IntlString,
|
||||||
UnPinAttachment: '' as IntlString
|
UnPinAttachment: '' as IntlString,
|
||||||
|
FilterAttachments: '' as IntlString
|
||||||
},
|
},
|
||||||
ids: {
|
ids: {
|
||||||
TxAttachmentCreate: '' as Ref<TxViewlet>
|
TxAttachmentCreate: '' as Ref<TxViewlet>
|
||||||
@ -48,5 +49,8 @@ export default mergeIds(attachmentId, attachment, {
|
|||||||
},
|
},
|
||||||
category: {
|
category: {
|
||||||
Attachments: '' as Ref<ActionCategory>
|
Attachments: '' as Ref<ActionCategory>
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
AttachmentsFilter: '' as Resource<(txes: DisplayTx[]) => DisplayTx[]>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -473,6 +473,16 @@ export function createModel (builder: Builder, options = { addApplication: true
|
|||||||
chunter.ids.TxBacklinkRemove
|
chunter.ids.TxBacklinkRemove
|
||||||
)
|
)
|
||||||
|
|
||||||
|
builder.createDoc(activity.class.ActivityFilter, core.space.Model, {
|
||||||
|
label: chunter.string.FilterComments,
|
||||||
|
filter: chunter.filter.CommentsFilter
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.createDoc(activity.class.ActivityFilter, core.space.Model, {
|
||||||
|
label: chunter.string.FilterBacklinks,
|
||||||
|
filter: chunter.filter.BacklinksFilter
|
||||||
|
})
|
||||||
|
|
||||||
builder.mixin(chunter.class.ChunterMessage, core.class.Class, view.mixin.ClassFilters, {
|
builder.mixin(chunter.class.ChunterMessage, core.class.Class, view.mixin.ClassFilters, {
|
||||||
filters: ['space', 'modifiedOn', 'createBy', '_class']
|
filters: ['space', 'modifiedOn', 'createBy', '_class']
|
||||||
})
|
})
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import type { TxViewlet } from '@hcengineering/activity'
|
import type { DisplayTx, TxViewlet } from '@hcengineering/activity'
|
||||||
import { Channel, chunterId } from '@hcengineering/chunter'
|
import { Channel, chunterId } from '@hcengineering/chunter'
|
||||||
import chunter from '@hcengineering/chunter-resources/src/plugin'
|
import chunter from '@hcengineering/chunter-resources/src/plugin'
|
||||||
import type { Ref, Space } from '@hcengineering/core'
|
import type { Ref, Space } from '@hcengineering/core'
|
||||||
@ -67,7 +67,9 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
SavedMessages: '' as IntlString,
|
SavedMessages: '' as IntlString,
|
||||||
ThreadMessage: '' as IntlString,
|
ThreadMessage: '' as IntlString,
|
||||||
Reactions: '' as IntlString,
|
Reactions: '' as IntlString,
|
||||||
Emoji: '' as IntlString
|
Emoji: '' as IntlString,
|
||||||
|
FilterComments: '' as IntlString,
|
||||||
|
FilterBacklinks: '' as IntlString
|
||||||
},
|
},
|
||||||
viewlet: {
|
viewlet: {
|
||||||
Chat: '' as Ref<ViewletDescriptor>
|
Chat: '' as Ref<ViewletDescriptor>
|
||||||
@ -89,5 +91,9 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
ChunterBrowserVisible: '' as Resource<(spaces: Space[]) => boolean>
|
ChunterBrowserVisible: '' as Resource<(spaces: Space[]) => boolean>
|
||||||
|
},
|
||||||
|
filter: {
|
||||||
|
CommentsFilter: '' as Resource<(txes: DisplayTx[]) => DisplayTx[]>,
|
||||||
|
BacklinksFilter: '' as Resource<(txes: DisplayTx[]) => DisplayTx[]>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
{#if $$slots.header}
|
{#if $$slots.header}
|
||||||
<div class="header-row between">
|
<div class="header-row between">
|
||||||
{#if $$slots.header}<slot name="header" />{/if}
|
{#if $$slots.header}<slot name="header" />{/if}
|
||||||
<div class="buttons-group xsmall-gap ml-4" style:align-self={'flex-start'}>
|
<div class="buttons-group xsmall-gap ml-4" style:align-self={'flex-end'}>
|
||||||
<slot name="tools" />
|
<slot name="tools" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -527,6 +527,7 @@ input.search {
|
|||||||
.min-h-7 { min-height: 1.75rem; }
|
.min-h-7 { min-height: 1.75rem; }
|
||||||
.min-h-30 { min-height: 7.5rem; }
|
.min-h-30 { min-height: 7.5rem; }
|
||||||
.min-h-60 { min-height: 15rem; }
|
.min-h-60 { min-height: 15rem; }
|
||||||
|
.max-w-2 { max-width: .5rem; }
|
||||||
.max-w-9 { max-width: 2.25rem; }
|
.max-w-9 { max-width: 2.25rem; }
|
||||||
.max-w-30 { max-width: 7.5rem; }
|
.max-w-30 { max-width: 7.5rem; }
|
||||||
.max-w-60 { max-width: 15rem; }
|
.max-w-60 { max-width: 15rem; }
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<label class="checkbox" class:circle class:primary class:checked>
|
<label class="checkbox" class:circle class:primary class:readonly class:checked>
|
||||||
<input class="chBox" disabled={readonly} type="checkbox" bind:checked on:change={handleValueChanged} />
|
<input class="chBox" disabled={readonly} type="checkbox" bind:checked on:change={handleValueChanged} />
|
||||||
<svg class="checkSVG" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
<svg class="checkSVG" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
{#if checked}
|
{#if checked}
|
||||||
@ -71,6 +71,10 @@
|
|||||||
background-color: var(--primary-bg-color);
|
background-color: var(--primary-bg-color);
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
}
|
}
|
||||||
|
&.readonly.checked {
|
||||||
|
background-color: var(--dark-color);
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
.chBox {
|
.chBox {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -94,8 +98,8 @@
|
|||||||
&:not(:disabled) + .checkSVG {
|
&:not(:disabled) + .checkSVG {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
&:disabled + .checkSVG {
|
&:disabled + .checkSVG .check {
|
||||||
filter: grayscale(70%);
|
fill: var(--content-color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.checkSVG {
|
.checkSVG {
|
||||||
|
@ -45,7 +45,8 @@
|
|||||||
maxWidth: '',
|
maxWidth: '',
|
||||||
maxHeight: '',
|
maxHeight: '',
|
||||||
minWidth: '',
|
minWidth: '',
|
||||||
minHeight: ''
|
minHeight: '',
|
||||||
|
transform: ''
|
||||||
},
|
},
|
||||||
showOverlay: false,
|
showOverlay: false,
|
||||||
direction: 'bottom'
|
direction: 'bottom'
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
"CollectionUpdated": "Update {collection}",
|
"CollectionUpdated": "Update {collection}",
|
||||||
"Added": "added",
|
"Added": "added",
|
||||||
"Removed": "removed",
|
"Removed": "removed",
|
||||||
"From": "from"
|
"From": "from",
|
||||||
|
"All": "All"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@
|
|||||||
"CollectionUpdated": "Обновлена {collection}",
|
"CollectionUpdated": "Обновлена {collection}",
|
||||||
"Added": "добавила(а)",
|
"Added": "добавила(а)",
|
||||||
"Removed": "удалил(а)",
|
"Removed": "удалил(а)",
|
||||||
"From": "из"
|
"From": "из",
|
||||||
|
"All": "Все"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,17 +13,20 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import activity, { TxViewlet } from '@hcengineering/activity'
|
import activity, { TxViewlet, ActivityFilter } from '@hcengineering/activity'
|
||||||
import chunter from '@hcengineering/chunter'
|
import chunter from '@hcengineering/chunter'
|
||||||
import core, { Class, Doc, Ref, SortingOrder } from '@hcengineering/core'
|
import core, { Class, Doc, Ref, SortingOrder } from '@hcengineering/core'
|
||||||
import { getResource } from '@hcengineering/platform'
|
import { getResource, IntlString } from '@hcengineering/platform'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import notification from '@hcengineering/notification'
|
import notification from '@hcengineering/notification'
|
||||||
import { Component, Grid, IconActivity, Label, Scroller } from '@hcengineering/ui'
|
import { Component, Grid, IconActivity, Label, Scroller, Button, showPopup } from '@hcengineering/ui'
|
||||||
import { ActivityKey, activityKey, DisplayTx, newActivity } from '../activity'
|
import { ActivityKey, activityKey, DisplayTx, newActivity } from '../activity'
|
||||||
import TxView from './TxView.svelte'
|
import TxView from './TxView.svelte'
|
||||||
import { filterCollectionTxes } from './utils'
|
import { filterCollectionTxes } from './utils'
|
||||||
import { Writable } from 'svelte/store'
|
import { Writable } from 'svelte/store'
|
||||||
|
import view from '@hcengineering/view'
|
||||||
|
import activityPlg from '../plugin'
|
||||||
|
import FilterPopup from './FilterPopup.svelte'
|
||||||
|
|
||||||
export let object: Doc
|
export let object: Doc
|
||||||
export let integrate: boolean = false
|
export let integrate: boolean = false
|
||||||
@ -31,10 +34,18 @@
|
|||||||
export let transparent: boolean = false
|
export let transparent: boolean = false
|
||||||
|
|
||||||
let txes: DisplayTx[] = []
|
let txes: DisplayTx[] = []
|
||||||
|
let txesF: DisplayTx[] = []
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const attrs = client.getHierarchy().getAllAttributes(object._class)
|
const attrs = client.getHierarchy().getAllAttributes(object._class)
|
||||||
|
|
||||||
|
let filterLabel: IntlString = activityPlg.string.All
|
||||||
|
const filters: ActivityFilter[] = []
|
||||||
|
const saved = localStorage.getItem('activity-filter')
|
||||||
|
let selectedFilter: Ref<Doc> | 'All' = saved !== null && saved !== undefined ? JSON.parse(saved) : 'All'
|
||||||
|
$: localStorage.setItem('activity-filter', JSON.stringify(selectedFilter))
|
||||||
|
client.findAll(activity.class.ActivityFilter, {}).then((res) => res.map((it) => filters.push(it)))
|
||||||
|
|
||||||
const activityQuery = newActivity(client, attrs)
|
const activityQuery = newActivity(client, attrs)
|
||||||
getResource(notification.function.GetNotificationClient).then((res) => {
|
getResource(notification.function.GetNotificationClient).then((res) => {
|
||||||
lastViews = res().getLastViews()
|
lastViews = res().getLastViews()
|
||||||
@ -82,6 +93,25 @@
|
|||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let optionsBtn: HTMLButtonElement
|
||||||
|
const handleOptions = () => {
|
||||||
|
showPopup(FilterPopup, { selectedFilter, filters }, optionsBtn, (res) => {
|
||||||
|
if (res === undefined) return
|
||||||
|
if (res.action === 'select') selectedFilter = res.value as Ref<Doc> | 'All'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$: if (selectedFilter || txes) {
|
||||||
|
const filter = filters.find((it) => it._id === selectedFilter)
|
||||||
|
if (filter) {
|
||||||
|
filterLabel = filter.label
|
||||||
|
getResource(filter.filter).then((result) => (txesF = result(txes)))
|
||||||
|
} else {
|
||||||
|
filterLabel = activityPlg.string.All
|
||||||
|
txesF = txes
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if !integrate || transparent}
|
{#if !integrate || transparent}
|
||||||
@ -96,9 +126,9 @@
|
|||||||
<div class="flex-col flex-grow min-h-0" class:background-accent-bg-color={!transparent}>
|
<div class="flex-col flex-grow min-h-0" class:background-accent-bg-color={!transparent}>
|
||||||
<Scroller>
|
<Scroller>
|
||||||
<div class="p-10 select-text" id={activity.string.Activity}>
|
<div class="p-10 select-text" id={activity.string.Activity}>
|
||||||
{#if txes}
|
{#if txesF}
|
||||||
<Grid column={1} rowGap={1.5}>
|
<Grid column={1} rowGap={1.5}>
|
||||||
{#each txes as tx, i}
|
{#each txesF as tx, i}
|
||||||
<TxView {tx} {viewlets} isNew={newTxPos === i} />
|
<TxView {tx} {viewlets} isNew={newTxPos === i} />
|
||||||
{/each}
|
{/each}
|
||||||
</Grid>
|
</Grid>
|
||||||
@ -117,6 +147,15 @@
|
|||||||
<div class="antiSection-header mt-6">
|
<div class="antiSection-header mt-6">
|
||||||
<div class="antiSection-header__icon"><IconActivity size={'small'} /></div>
|
<div class="antiSection-header__icon"><IconActivity size={'small'} /></div>
|
||||||
<span class="antiSection-header__title"><Label label={activity.string.Activity} /></span>
|
<span class="antiSection-header__title"><Label label={activity.string.Activity} /></span>
|
||||||
|
<span class="dark-color text-md"><Label label={filterLabel} /></span>
|
||||||
|
<div class="w-2 min-w-2 max-w-2" />
|
||||||
|
<Button
|
||||||
|
bind:input={optionsBtn}
|
||||||
|
icon={view.icon.ViewButton}
|
||||||
|
kind={'transparent'}
|
||||||
|
shape={'circle'}
|
||||||
|
on:click={handleOptions}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if showCommenInput}
|
{#if showCommenInput}
|
||||||
<div class="ref-input">
|
<div class="ref-input">
|
||||||
@ -124,9 +163,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="p-activity select-text" id={activity.string.Activity}>
|
<div class="p-activity select-text" id={activity.string.Activity}>
|
||||||
{#if txes}
|
{#if txesF}
|
||||||
<Grid column={1} rowGap={1.5}>
|
<Grid column={1} rowGap={1.5}>
|
||||||
{#each txes as tx, i}
|
{#each txesF as tx, i}
|
||||||
<TxView {tx} {viewlets} isNew={newTxPos === i} />
|
<TxView {tx} {viewlets} isNew={newTxPos === i} />
|
||||||
{/each}
|
{/each}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
113
plugins/activity-resources/src/components/FilterPopup.svelte
Normal file
113
plugins/activity-resources/src/components/FilterPopup.svelte
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2020 Anticrm Platform Contributors.
|
||||||
|
//
|
||||||
|
// 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 { createEventDispatcher, onMount } from 'svelte'
|
||||||
|
import { IntlString } from '@hcengineering/platform'
|
||||||
|
import { Label, resizeObserver, CheckBox } from '@hcengineering/ui'
|
||||||
|
import { Doc, Ref } from '@hcengineering/core'
|
||||||
|
import { ActivityFilter } from '@hcengineering/activity'
|
||||||
|
import activity from '../plugin'
|
||||||
|
|
||||||
|
export let selectedFilter: Ref<Doc> | 'All' = 'All'
|
||||||
|
export let filters: ActivityFilter[] = []
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
|
interface ActionMenu {
|
||||||
|
label: IntlString
|
||||||
|
checked: boolean
|
||||||
|
value: Ref<Doc> | 'All'
|
||||||
|
}
|
||||||
|
const menu: ActionMenu[] = [
|
||||||
|
{
|
||||||
|
label: activity.string.All,
|
||||||
|
checked: selectedFilter === 'All',
|
||||||
|
value: 'All'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
filters.map((fl) => menu.push({ label: fl.label, checked: selectedFilter === fl._id, value: fl._id }))
|
||||||
|
|
||||||
|
let popup: HTMLElement
|
||||||
|
$: popup?.focus()
|
||||||
|
|
||||||
|
const btns: HTMLElement[] = []
|
||||||
|
let activeElement: HTMLElement
|
||||||
|
const keyDown = (ev: KeyboardEvent): void => {
|
||||||
|
console.log('[KEY]', ev.key)
|
||||||
|
const n = btns.indexOf(activeElement) ?? 0
|
||||||
|
if (ev.key === ' ' || ev.key === 'Enter') {
|
||||||
|
ev.preventDefault()
|
||||||
|
ev.stopPropagation()
|
||||||
|
btns[n].focus()
|
||||||
|
btns[n].click()
|
||||||
|
}
|
||||||
|
if (ev.key === 'ArrowDown') {
|
||||||
|
if (n < btns.length - 1) {
|
||||||
|
activeElement = btns[n + 1]
|
||||||
|
}
|
||||||
|
ev.preventDefault()
|
||||||
|
ev.stopPropagation()
|
||||||
|
}
|
||||||
|
if (ev.key === 'ArrowUp') {
|
||||||
|
if (n > 0) {
|
||||||
|
activeElement = btns[n - 1]
|
||||||
|
}
|
||||||
|
ev.preventDefault()
|
||||||
|
ev.stopPropagation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
if (btns[0]) {
|
||||||
|
btns[0].focus()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="antiPopup"
|
||||||
|
use:resizeObserver={() => {
|
||||||
|
dispatch('changeContent')
|
||||||
|
}}
|
||||||
|
on:keydown={keyDown}
|
||||||
|
>
|
||||||
|
<div class="ap-space" />
|
||||||
|
<div class="ap-scroll">
|
||||||
|
<div class="ap-box" bind:this={popup}>
|
||||||
|
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||||
|
{#each menu as item, i}
|
||||||
|
<button
|
||||||
|
bind:this={btns[i]}
|
||||||
|
class="ap-menuItem flex-row-center withIcon"
|
||||||
|
class:hover={btns[i] === activeElement}
|
||||||
|
on:mousemove={() => {
|
||||||
|
if (btns[i] !== activeElement) activeElement = btns[i]
|
||||||
|
}}
|
||||||
|
on:click={() => {
|
||||||
|
dispatch('close', { action: 'select', value: item.value })
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div class="flex-center justify-end mr-3 pointer-events-none">
|
||||||
|
<CheckBox checked={item.checked} />
|
||||||
|
</div>
|
||||||
|
<span class="overflow-label">
|
||||||
|
<Label label={item.label} />
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="ap-space" />
|
||||||
|
</div>
|
@ -28,6 +28,7 @@ export default mergeIds(activityId, activity, {
|
|||||||
System: '' as IntlString,
|
System: '' as IntlString,
|
||||||
Added: '' as IntlString,
|
Added: '' as IntlString,
|
||||||
Removed: '' as IntlString,
|
Removed: '' as IntlString,
|
||||||
From: '' as IntlString
|
From: '' as IntlString,
|
||||||
|
All: '' as IntlString
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -13,8 +13,21 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import type { Class, Doc, DocumentQuery, Ref, Tx } from '@hcengineering/core'
|
import type {
|
||||||
import type { Asset, IntlString, Plugin } from '@hcengineering/platform'
|
AttachedDoc,
|
||||||
|
Attribute,
|
||||||
|
Class,
|
||||||
|
Collection,
|
||||||
|
Doc,
|
||||||
|
DocumentQuery,
|
||||||
|
Ref,
|
||||||
|
Tx,
|
||||||
|
TxCreateDoc,
|
||||||
|
TxCUD,
|
||||||
|
TxMixin,
|
||||||
|
TxUpdateDoc
|
||||||
|
} from '@hcengineering/core'
|
||||||
|
import type { Asset, IntlString, Plugin, Resource } from '@hcengineering/platform'
|
||||||
import { plugin } from '@hcengineering/platform'
|
import { plugin } from '@hcengineering/platform'
|
||||||
import type { AnyComponent } from '@hcengineering/ui'
|
import type { AnyComponent } from '@hcengineering/ui'
|
||||||
|
|
||||||
@ -47,23 +60,64 @@ export interface TxViewlet extends Doc {
|
|||||||
// If defined and true, will hide all transactions from object in case it is deleted.
|
// If defined and true, will hide all transactions from object in case it is deleted.
|
||||||
hideOnRemove?: boolean
|
hideOnRemove?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transaction being displayed.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface DisplayTx {
|
||||||
|
// Source tx
|
||||||
|
tx: TxCUD<Doc>
|
||||||
|
|
||||||
|
// A set of collapsed transactions.
|
||||||
|
txes: DisplayTx[]
|
||||||
|
txDocIds?: Set<Ref<Doc>>
|
||||||
|
|
||||||
|
// type check for createTx
|
||||||
|
createTx?: TxCreateDoc<Doc>
|
||||||
|
|
||||||
|
// Type check for updateTx
|
||||||
|
updateTx?: TxUpdateDoc<Doc>
|
||||||
|
|
||||||
|
// Type check for updateTx
|
||||||
|
mixinTx?: TxMixin<Doc, Doc>
|
||||||
|
|
||||||
|
// Document in case it is required.
|
||||||
|
doc?: Doc
|
||||||
|
|
||||||
|
updated: boolean
|
||||||
|
mixin: boolean
|
||||||
|
removed: boolean
|
||||||
|
|
||||||
|
collectionAttribute?: Attribute<Collection<AttachedDoc>>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export interface ActivityFilter extends Doc {
|
||||||
|
label: IntlString
|
||||||
|
filter: Resource<(txes: DisplayTx[]) => DisplayTx[]>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export const activityId = 'activity' as Plugin
|
export const activityId = 'activity' as Plugin
|
||||||
|
|
||||||
export default plugin(activityId, {
|
export default plugin(activityId, {
|
||||||
|
icon: {
|
||||||
|
Activity: '' as Asset
|
||||||
|
},
|
||||||
string: {
|
string: {
|
||||||
Delete: '' as IntlString,
|
Delete: '' as IntlString,
|
||||||
Edit: '' as IntlString,
|
Edit: '' as IntlString,
|
||||||
Edited: '' as IntlString,
|
Edited: '' as IntlString,
|
||||||
Activity: '' as IntlString
|
Activity: '' as IntlString
|
||||||
},
|
},
|
||||||
icon: {
|
|
||||||
Activity: '' as Asset
|
|
||||||
},
|
|
||||||
class: {
|
class: {
|
||||||
TxViewlet: '' as Ref<Class<TxViewlet>>
|
TxViewlet: '' as Ref<Class<TxViewlet>>,
|
||||||
|
ActivityFilter: '' as Ref<Class<ActivityFilter>>
|
||||||
},
|
},
|
||||||
component: {
|
component: {
|
||||||
Activity: '' as AnyComponent
|
Activity: '' as AnyComponent
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
"Description": "Description",
|
"Description": "Description",
|
||||||
"Pinned": "Important",
|
"Pinned": "Important",
|
||||||
"PinAttachment": "Mark important",
|
"PinAttachment": "Mark important",
|
||||||
"UnPinAttachment": "Mark less important"
|
"UnPinAttachment": "Mark less important",
|
||||||
|
"FilterAttachments": "Attachments"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
"Description": "Описание",
|
"Description": "Описание",
|
||||||
"Pinned": "Важное",
|
"Pinned": "Важное",
|
||||||
"PinAttachment": "Пометить как важное",
|
"PinAttachment": "Пометить как важное",
|
||||||
"UnPinAttachment": "Убрать пометку важное"
|
"UnPinAttachment": "Убрать пометку важное",
|
||||||
|
"FilterAttachments": "Вложения"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
"@hcengineering/text-editor": "~0.6.0",
|
"@hcengineering/text-editor": "~0.6.0",
|
||||||
"@hcengineering/login": "~0.6.1",
|
"@hcengineering/login": "~0.6.1",
|
||||||
"filesize": "^8.0.3",
|
"filesize": "^8.0.3",
|
||||||
"@hcengineering/preference": "^0.6.1"
|
"@hcengineering/preference": "^0.6.1",
|
||||||
|
"@hcengineering/activity": "~0.6.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ import FileDownload from './components/icons/FileDownload.svelte'
|
|||||||
import Photos from './components/Photos.svelte'
|
import Photos from './components/Photos.svelte'
|
||||||
import AttachmentStyledBox from './components/AttachmentStyledBox.svelte'
|
import AttachmentStyledBox from './components/AttachmentStyledBox.svelte'
|
||||||
import { deleteFile, uploadFile } from './utils'
|
import { deleteFile, uploadFile } from './utils'
|
||||||
|
import { DisplayTx } from '@hcengineering/activity'
|
||||||
|
|
||||||
export {
|
export {
|
||||||
AddAttachment,
|
AddAttachment,
|
||||||
@ -221,7 +222,14 @@ export async function DeleteAttachment (attach: Attachment): Promise<void> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function attachmentsFilter (txes: DisplayTx[]): DisplayTx[] {
|
||||||
|
return txes.filter((tx) => tx.tx.objectClass === attachment.class.Attachment)
|
||||||
|
}
|
||||||
|
|
||||||
export default async (): Promise<Resources> => ({
|
export default async (): Promise<Resources> => ({
|
||||||
|
filter: {
|
||||||
|
AttachmentsFilter: attachmentsFilter
|
||||||
|
},
|
||||||
component: {
|
component: {
|
||||||
AttachmentsPresenter,
|
AttachmentsPresenter,
|
||||||
AttachmentPresenter,
|
AttachmentPresenter,
|
||||||
|
@ -66,6 +66,8 @@
|
|||||||
"ChunterBrowser": "Search",
|
"ChunterBrowser": "Search",
|
||||||
"Messages": "Messages",
|
"Messages": "Messages",
|
||||||
"NoResults": "No results",
|
"NoResults": "No results",
|
||||||
"CopyLink": "Copy link"
|
"CopyLink": "Copy link",
|
||||||
|
"FilterComments": "Comments",
|
||||||
|
"FilterBacklinks": "Backlinks"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -66,6 +66,8 @@
|
|||||||
"ChunterBrowser": "Поиск",
|
"ChunterBrowser": "Поиск",
|
||||||
"Messages": "Сообщения",
|
"Messages": "Сообщения",
|
||||||
"NoResults": "Нет результатов",
|
"NoResults": "Нет результатов",
|
||||||
"CopyLink": "Копировать ссылку"
|
"CopyLink": "Копировать ссылку",
|
||||||
|
"FilterComments": "Коментарии",
|
||||||
|
"FilterBacklinks": "Упоминания"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -52,6 +52,7 @@ import ConvertDmToPrivateChannelModal from './components/ConvertDmToPrivateChann
|
|||||||
import { getDmName } from './utils'
|
import { getDmName } from './utils'
|
||||||
import { writable } from 'svelte/store'
|
import { writable } from 'svelte/store'
|
||||||
import { updateBacklinksList } from './backlinks'
|
import { updateBacklinksList } from './backlinks'
|
||||||
|
import { DisplayTx } from '../../activity/lib'
|
||||||
|
|
||||||
export { default as Header } from './components/Header.svelte'
|
export { default as Header } from './components/Header.svelte'
|
||||||
export { classIcon } from './utils'
|
export { classIcon } from './utils'
|
||||||
@ -206,7 +207,19 @@ async function update (source: Doc, key: string, target: RelatedDocument[], msg:
|
|||||||
await updateBacklinksList(getClient(), q, backlinks)
|
await updateBacklinksList(getClient(), q, backlinks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function commentsFilter (txes: DisplayTx[]): DisplayTx[] {
|
||||||
|
return txes.filter((tx) => tx.tx.objectClass === chunter.class.Comment)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function backlinksFilter (txes: DisplayTx[]): DisplayTx[] {
|
||||||
|
return txes.filter((tx) => tx.tx.objectClass === chunter.class.Backlink)
|
||||||
|
}
|
||||||
|
|
||||||
export default async (): Promise<Resources> => ({
|
export default async (): Promise<Resources> => ({
|
||||||
|
filter: {
|
||||||
|
CommentsFilter: commentsFilter,
|
||||||
|
BacklinksFilter: backlinksFilter
|
||||||
|
},
|
||||||
component: {
|
component: {
|
||||||
CommentInput,
|
CommentInput,
|
||||||
CreateChannel,
|
CreateChannel,
|
||||||
|
@ -387,7 +387,7 @@
|
|||||||
<UpDownNavigator element={documentObject} />
|
<UpDownNavigator element={documentObject} />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="header">
|
||||||
<span class="fs-title flex-row-center">
|
<span class="fs-title flex-row-center flex-shrink gap-1-5">
|
||||||
<EditBox
|
<EditBox
|
||||||
bind:value={name}
|
bind:value={name}
|
||||||
placeholder={document.string.DocumentNamePlaceholder}
|
placeholder={document.string.DocumentNamePlaceholder}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
"@hcengineering/notification": "~0.6.4",
|
"@hcengineering/notification": "~0.6.4",
|
||||||
"@hcengineering/ui": "^0.6.2",
|
"@hcengineering/ui": "^0.6.2",
|
||||||
"@hcengineering/presentation": "~0.6.2",
|
"@hcengineering/presentation": "~0.6.2",
|
||||||
"@hcengineering/activity-resources": "~0.6.0",
|
"@hcengineering/activity-resources": "~0.6.1",
|
||||||
"@hcengineering/activity": "~0.6.0",
|
"@hcengineering/activity": "~0.6.0",
|
||||||
"@hcengineering/contact": "~0.6.8",
|
"@hcengineering/contact": "~0.6.8",
|
||||||
"@hcengineering/core": "^0.6.17",
|
"@hcengineering/core": "^0.6.17",
|
||||||
|
@ -73,7 +73,7 @@
|
|||||||
"@hcengineering/contact-assets": "~0.6.0",
|
"@hcengineering/contact-assets": "~0.6.0",
|
||||||
"@hcengineering/activity": "~0.6.0",
|
"@hcengineering/activity": "~0.6.0",
|
||||||
"@hcengineering/activity-assets": "~0.6.0",
|
"@hcengineering/activity-assets": "~0.6.0",
|
||||||
"@hcengineering/activity-resources": "~0.6.0",
|
"@hcengineering/activity-resources": "~0.6.1",
|
||||||
"@hcengineering/telegram": "~0.6.2",
|
"@hcengineering/telegram": "~0.6.2",
|
||||||
"@hcengineering/telegram-assets": "~0.6.0",
|
"@hcengineering/telegram-assets": "~0.6.0",
|
||||||
"@hcengineering/telegram-resources": "~0.6.0",
|
"@hcengineering/telegram-resources": "~0.6.0",
|
||||||
|
Loading…
Reference in New Issue
Block a user