Comments presenter (#364)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2021-11-25 17:46:51 +06:00 committed by GitHub
parent 0953576fac
commit 88bc3c6f88
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 1363 additions and 1145 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -43,6 +43,7 @@ export class TMessage extends TDoc implements Message {
}
@Model(chunter.class.Comment, core.class.Doc, DOMAIN_COMMENT)
@UX('Comment' as IntlString)
export class TComment extends TAttachedDoc implements Comment {
@Prop(TypeString(), 'Message' as IntlString)
@Index(IndexKind.FullText)
@ -127,6 +128,10 @@ export function createModel (builder: Builder): void {
presenter: chunter.component.AttachmentPresenter
})
builder.mixin(chunter.class.Comment, core.class.Class, view.mixin.AttributePresenter, {
presenter: chunter.component.CommentPresenter
})
builder.createDoc(activity.class.TxViewlet, core.space.Model, {
objectClass: chunter.class.Comment,
icon: chunter.icon.Chunter,

View File

@ -25,7 +25,9 @@ import type { TxViewlet } from '@anticrm/activity'
export default mergeIds(chunterId, chunter, {
component: {
AttachmentsPresenter: '' as AnyComponent,
AttachmentPresenter: '' as AnyComponent
AttachmentPresenter: '' as AnyComponent,
CommentsPresenter: '' as AnyComponent,
CommentPresenter: '' as AnyComponent
},
string: {
ApplicationLabelChunter: '' as IntlString,

View File

@ -46,6 +46,9 @@ export class TCandidate extends TPerson implements Candidate {
@Prop(TypeString(), 'Attachments' as IntlString)
attachments?: number
@Prop(TypeString(), 'Comments' as IntlString)
comments?: number
@Prop(TypeString(), 'Applications' as IntlString)
applications?: number
@ -133,6 +136,7 @@ export function createModel (builder: Builder): void {
'city',
{ presenter: recruit.component.ApplicationsPresenter, label: 'Apps' },
{ presenter: chunter.component.AttachmentsPresenter, label: 'Files' },
{ presenter: chunter.component.CommentsPresenter, label: 'Comments' },
'modifiedOn',
'channels'
]

View File

@ -24,7 +24,6 @@
"@anticrm/view": "~0.6.0",
"svelte": "^3.37.0",
"@anticrm/contact": "~0.6.2",
"@anticrm/chunter": "~0.6.0",
"@anticrm/login": "~0.6.1"
}
}

View File

@ -1,73 +0,0 @@
<!--
// Copyright © 2020, 2021 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 type { Comment } from '@anticrm/chunter'
import { getClient } from '../utils'
import type { Ref } from '@anticrm/core'
import MessageViewer from './MessageViewer.svelte'
import Avatar from './Avatar.svelte'
import { TimeSince } from '@anticrm/ui'
import contact, { Employee, EmployeeAccount, formatName } from '@anticrm/contact'
export let comment: Comment
let employee: EmployeeAccount | undefined
console.log('comment modified by', comment.modifiedBy)
const client = getClient()
client.findOne(contact.class.EmployeeAccount, { _id: comment.modifiedBy as Ref<EmployeeAccount> }).then(account => {employee = account})
</script>
<div class="flex-nowrap">
<div class="avatar"><Avatar size={'medium'} /></div>
<div class="flex-col-stretch message">
<div class="header">{#if employee}{formatName(employee.name)}{/if}<span><TimeSince value={comment.modifiedOn}/></span></div>
<div class="text"><MessageViewer message={comment.message} /></div>
</div>
</div>
<style lang="scss">
.avatar {
margin-right: 1rem;
}
.message {
margin-right: 1.25rem;
.header {
margin-bottom: .25rem;
font-weight: 500;
font-size: 1rem;
line-height: 150%;
color: var(--theme-caption-color);
span {
margin-left: .5rem;
font-weight: 400;
font-size: .875rem;
color: var(--theme-content-dark-color);
}
}
.text {
line-height: 150%;
color: var(--theme-content-color);
}
}
</style>

View File

@ -24,7 +24,6 @@ export { default as AttributeEditor } from './components/AttributeEditor.svelte'
export { default as AttributeBarEditor } from './components/AttributeBarEditor.svelte'
export { default as Card } from './components/Card.svelte'
export { default as Channels } from './components/Channels.svelte'
export { default as Backlink } from './components/Backlink.svelte'
export { default as PDFViewer } from './components/PDFViewer.svelte'
export { default as MessageBox } from './components/MessageBox.svelte'
export { default as SpaceCreateCard } from './components/SpaceCreateCard.svelte'

View File

@ -19,10 +19,11 @@
import type { Doc, Ref, Space } from '@anticrm/core'
import type { Comment } from '@anticrm/chunter'
import { ReferenceInput } from '@anticrm/text-editor'
import { createQuery, getClient, Backlink } from '@anticrm/presentation'
import { createQuery, getClient } from '@anticrm/presentation'
import { ScrollBox, Grid } from '@anticrm/ui'
import chunter from '@anticrm/chunter'
import CommentPresenter from './CommentPresenter.svelte'
export let object: Doc
export let space: Ref<Space>
@ -48,7 +49,7 @@ function onMessage(event: CustomEvent) {
{#if comments}
<Grid column={1} rowGap={1.5}>
{#each comments as comment}
<Backlink {comment} />
<CommentPresenter value={comment} />
{/each}
</Grid>
{/if}

View File

@ -0,0 +1,32 @@
<!--
// 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 { Ref, Doc, SortingOrder } from '@anticrm/core'
import { Table } from '@anticrm/view-resources'
import chunter from '@anticrm/chunter'
export let objectId: Ref<Doc>
</script>
<Table
_class={chunter.class.Comment}
config={['']}
options={ { limit: 3, sort: { modifiedOn: SortingOrder.Descending }} }
query={ { attachedTo: objectId } }
/>

View File

@ -0,0 +1,98 @@
<!--
// 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 { Avatar, getClient } from '@anticrm/presentation'
import type { Comment } from '@anticrm/chunter'
import contact, { EmployeeAccount, formatName } from '@anticrm/contact'
import { MessageViewer } from '@anticrm/presentation'
import { Account, Ref } from '@anticrm/core'
export let value: Comment
const client = getClient()
async function getUser (user: Ref<EmployeeAccount> | Ref<Account>): Promise<EmployeeAccount | undefined> {
return await client.findOne(contact.class.EmployeeAccount, { _id: user as Ref<EmployeeAccount> })
}
function getTime (time: number): string {
let options: Intl.DateTimeFormatOptions = { hour: 'numeric', minute: 'numeric'}
if (!isToday(time)) {
options = {
month: 'numeric',
day: 'numeric',
...options
}
}
return new Date(value.modifiedOn).toLocaleString('default', options)
}
function isToday (time: number): boolean {
const current = new Date()
const target = new Date(time)
return current.getDate() === target.getDate() && current.getMonth() === target.getMonth() && current.getFullYear() === target.getFullYear()
}
</script>
<div class="container">
<div class="avatar"><Avatar size={'medium'} /></div>
<div class="message">
<div class="header">
{#await getUser(value.modifiedBy) then user}
{#if user}{formatName(user.name)}{/if}
{/await}
<span>{getTime(value.modifiedOn)}</span>
</div>
<div class="text"><MessageViewer message={value.message}/></div>
</div>
</div>
<style lang="scss">
.container {
display: flex;
.avatar { min-width: 2.25rem; }
.message {
display: flex;
flex-direction: column;
width: 100%;
margin-left: 1rem;
.header {
font-weight: 500;
font-size: 1rem;
line-height: 150%;
color: var(--theme-caption-color);
margin-bottom: .25rem;
span {
margin-left: .5rem;
font-weight: 400;
font-size: .875rem;
line-height: 1.125rem;
opacity: .4;
}
}
.text {
line-height: 150%;
}
}
}
</style>

View File

@ -0,0 +1,32 @@
<!--
// 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 type { Doc } from '@anticrm/core'
import { Tooltip, IconComments } from '@anticrm/ui'
import CommentPopup from './CommentPopup.svelte'
export let value: Doc & { comments?: number }
</script>
{#if value.comments && value.comments > 0}
<Tooltip label={'Comments (' + value.comments + ')'} component={CommentPopup} props={{ objectId: value._id }}>
<div class="sm-tool-icon">
<span class="icon"><IconComments size="small"/></span>{value.comments}
</div>
</Tooltip>
{/if}

View File

@ -18,6 +18,8 @@ import ChannelView from './components/ChannelView.svelte'
import Activity from './components/Activity.svelte'
import AttachmentsPresenter from './components/AttachmentsPresenter.svelte'
import AttachmentPresenter from './components/AttachmentPresenter.svelte'
import CommentPresenter from './components/CommentPresenter.svelte'
import CommentsPresenter from './components/CommentsPresenter.svelte'
import TxCommentCreate from './components/activity/TxCommentCreate.svelte'
import TxAttachmentCreate from './components/activity/TxAttachmentCreate.svelte'
@ -29,10 +31,12 @@ export default async () => ({
ChannelView,
Activity,
AttachmentsPresenter,
AttachmentPresenter
AttachmentPresenter,
CommentPresenter,
CommentsPresenter
},
activity: {
TxCommentCreate: TxCommentCreate,
TxCommentCreate,
TxAttachmentCreate
}
})

View File

@ -34,6 +34,7 @@ export interface Candidates extends Space {}
export interface Candidate extends Person {
title?: string
attachments?: number
comments?: number
applications?: number
onsite?: boolean
remote?: boolean

File diff suppressed because it is too large Load Diff