mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-03 13:53:42 +00:00
Merge remote-tracking branch 'origin/develop'
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
commit
d1096a5b0d
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@ -509,9 +509,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: hardcoreeng
|
username: hardcoreeng
|
||||||
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
|
||||||
- name: Docker push staging
|
# - name: Docker push staging
|
||||||
if: ${{ github.ref == 'refs/heads/main' }}
|
# if: ${{ github.ref == 'refs/heads/main' }}
|
||||||
run: node common/scripts/install-run-rush.js docker:staging -v
|
# run: node common/scripts/install-run-rush.js docker:staging -v
|
||||||
- name: Docker push tag
|
- name: Docker push tag
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
|
||||||
run: |
|
run: |
|
||||||
|
@ -11,11 +11,23 @@ then
|
|||||||
version="${a[0]}.${a[1]}.${c}-staging"
|
version="${a[0]}.${a[1]}.${c}-staging"
|
||||||
echo "Tagging stating $1 with version ${version}"
|
echo "Tagging stating $1 with version ${version}"
|
||||||
docker tag "$1:$rev_version" "$1:$version"
|
docker tag "$1:$rev_version" "$1:$version"
|
||||||
docker push "$1:$version"
|
for n in {1..5}; do
|
||||||
|
docker push "$1:$version" && break
|
||||||
|
echo 'Docker failed to push, wait 5 seconds'
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
else
|
else
|
||||||
echo "Tagging release $1 with version ${version}"
|
echo "Tagging release $1 with version ${version}"
|
||||||
docker tag "$1:$rev_version" "$1:$version"
|
docker tag "$1:$rev_version" "$1:$version"
|
||||||
docker tag "$1:$rev_version" "$1:latest"
|
docker tag "$1:$rev_version" "$1:latest"
|
||||||
docker push "$1:$version"
|
for n in {1..5}; do
|
||||||
docker push "$1:latest"
|
docker push "$1:$version" && break
|
||||||
|
echo 'Docker failed to push, wait 5 seconds'
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
for n in {1..5}; do
|
||||||
|
docker push "$1:latest" && break
|
||||||
|
echo 'Docker failed to push, wait 5 seconds'
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
fi
|
fi
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
echo "Tagging release $1 with version $2"
|
echo "Tagging release $1 with version $2"
|
||||||
docker tag "$1" "$1:$2"
|
docker tag "$1" "$1:$2"
|
||||||
docker push "$1:$2"
|
for n in {1..5}; do
|
||||||
|
docker push "$1:$2" && break
|
||||||
|
echo 'Docker failed to push, wait 5 seconds'
|
||||||
|
sleep 5
|
||||||
|
done
|
@ -32,12 +32,11 @@ import {
|
|||||||
import attachment from '@hcengineering/model-attachment'
|
import attachment from '@hcengineering/model-attachment'
|
||||||
import contact from '@hcengineering/model-contact'
|
import contact from '@hcengineering/model-contact'
|
||||||
import core, { TAttachedDoc, TDoc } from '@hcengineering/model-core'
|
import core, { TAttachedDoc, TDoc } from '@hcengineering/model-core'
|
||||||
import notification from '@hcengineering/model-notification'
|
|
||||||
import view, { createAction } from '@hcengineering/model-view'
|
import view, { createAction } from '@hcengineering/model-view'
|
||||||
import setting from '@hcengineering/setting'
|
import setting from '@hcengineering/setting'
|
||||||
import love from '@hcengineering/model-love'
|
|
||||||
|
|
||||||
import gmail from './plugin'
|
import gmail from './plugin'
|
||||||
|
import { defineNotifications } from './notification'
|
||||||
|
|
||||||
export { gmailId } from '@hcengineering/gmail'
|
export { gmailId } from '@hcengineering/gmail'
|
||||||
export { gmailOperation } from './migration'
|
export { gmailOperation } from './migration'
|
||||||
@ -215,32 +214,6 @@ export function createModel (builder: Builder): void {
|
|||||||
gmail.action.WriteEmail
|
gmail.action.WriteEmail
|
||||||
)
|
)
|
||||||
|
|
||||||
builder.createDoc(
|
|
||||||
notification.class.NotificationGroup,
|
|
||||||
core.space.Model,
|
|
||||||
{
|
|
||||||
label: gmail.string.Email,
|
|
||||||
icon: contact.icon.Email
|
|
||||||
},
|
|
||||||
gmail.ids.EmailNotificationGroup
|
|
||||||
)
|
|
||||||
|
|
||||||
builder.createDoc(
|
|
||||||
notification.class.NotificationType,
|
|
||||||
core.space.Model,
|
|
||||||
{
|
|
||||||
label: gmail.string.NewMessage,
|
|
||||||
generated: false,
|
|
||||||
hidden: false,
|
|
||||||
txClasses: [core.class.TxCreateDoc],
|
|
||||||
objectClass: gmail.class.Message,
|
|
||||||
group: gmail.ids.EmailNotificationGroup,
|
|
||||||
allowedForAuthor: true,
|
|
||||||
defaultEnabled: false
|
|
||||||
},
|
|
||||||
gmail.ids.EmailNotification
|
|
||||||
)
|
|
||||||
|
|
||||||
builder.mixin(gmail.class.Message, core.class.Class, core.mixin.FullTextSearchContext, {
|
builder.mixin(gmail.class.Message, core.class.Class, core.mixin.FullTextSearchContext, {
|
||||||
parentPropagate: false
|
parentPropagate: false
|
||||||
})
|
})
|
||||||
@ -259,35 +232,9 @@ export function createModel (builder: Builder): void {
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(
|
builder.mixin(gmail.class.Message, core.class.Class, view.mixin.ObjectTitle, {
|
||||||
notification.class.NotificationProvider,
|
titleProvider: gmail.function.MessageTitleProvider
|
||||||
core.space.Model,
|
|
||||||
{
|
|
||||||
icon: contact.icon.Email,
|
|
||||||
label: gmail.string.Email,
|
|
||||||
description: gmail.string.EmailNotificationsDescription,
|
|
||||||
defaultEnabled: true,
|
|
||||||
canDisable: true,
|
|
||||||
depends: notification.providers.InboxNotificationProvider,
|
|
||||||
order: 300
|
|
||||||
},
|
|
||||||
gmail.providers.EmailNotificationProvider
|
|
||||||
)
|
|
||||||
|
|
||||||
builder.createDoc(notification.class.NotificationProviderDefaults, core.space.Model, {
|
|
||||||
provider: notification.providers.InboxNotificationProvider,
|
|
||||||
ignoredTypes: [],
|
|
||||||
enabledTypes: [gmail.ids.EmailNotification]
|
|
||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(notification.class.NotificationProviderDefaults, core.space.Model, {
|
defineNotifications(builder)
|
||||||
provider: gmail.providers.EmailNotificationProvider,
|
|
||||||
ignoredTypes: [
|
|
||||||
gmail.ids.EmailNotification,
|
|
||||||
notification.ids.CollaboratoAddNotification,
|
|
||||||
love.ids.InviteNotification,
|
|
||||||
love.ids.KnockNotification
|
|
||||||
],
|
|
||||||
enabledTypes: []
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
82
models/gmail/src/notification.ts
Normal file
82
models/gmail/src/notification.ts
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// Copyright © 2024 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.
|
||||||
|
//
|
||||||
|
|
||||||
|
import notification from '@hcengineering/model-notification'
|
||||||
|
import core from '@hcengineering/model-core'
|
||||||
|
import contact from '@hcengineering/model-contact'
|
||||||
|
import love from '@hcengineering/model-love'
|
||||||
|
import { type Builder } from '@hcengineering/model'
|
||||||
|
|
||||||
|
import gmail from './plugin'
|
||||||
|
|
||||||
|
export function defineNotifications (builder: Builder): void {
|
||||||
|
builder.createDoc(
|
||||||
|
notification.class.NotificationGroup,
|
||||||
|
core.space.Model,
|
||||||
|
{
|
||||||
|
label: gmail.string.Email,
|
||||||
|
icon: contact.icon.Email
|
||||||
|
},
|
||||||
|
gmail.ids.EmailNotificationGroup
|
||||||
|
)
|
||||||
|
|
||||||
|
builder.createDoc(
|
||||||
|
notification.class.NotificationType,
|
||||||
|
core.space.Model,
|
||||||
|
{
|
||||||
|
label: gmail.string.NewMessage,
|
||||||
|
generated: false,
|
||||||
|
hidden: false,
|
||||||
|
txClasses: [core.class.TxCreateDoc],
|
||||||
|
objectClass: gmail.class.Message,
|
||||||
|
group: gmail.ids.EmailNotificationGroup,
|
||||||
|
allowedForAuthor: true,
|
||||||
|
defaultEnabled: false
|
||||||
|
},
|
||||||
|
gmail.ids.EmailNotification
|
||||||
|
)
|
||||||
|
|
||||||
|
builder.createDoc(
|
||||||
|
notification.class.NotificationProvider,
|
||||||
|
core.space.Model,
|
||||||
|
{
|
||||||
|
icon: contact.icon.Email,
|
||||||
|
label: gmail.string.Email,
|
||||||
|
description: gmail.string.EmailNotificationsDescription,
|
||||||
|
defaultEnabled: true,
|
||||||
|
canDisable: true,
|
||||||
|
depends: notification.providers.InboxNotificationProvider,
|
||||||
|
order: 300
|
||||||
|
},
|
||||||
|
gmail.providers.EmailNotificationProvider
|
||||||
|
)
|
||||||
|
|
||||||
|
builder.createDoc(notification.class.NotificationProviderDefaults, core.space.Model, {
|
||||||
|
provider: notification.providers.InboxNotificationProvider,
|
||||||
|
ignoredTypes: [],
|
||||||
|
enabledTypes: [gmail.ids.EmailNotification]
|
||||||
|
})
|
||||||
|
|
||||||
|
builder.createDoc(notification.class.NotificationProviderDefaults, core.space.Model, {
|
||||||
|
provider: gmail.providers.EmailNotificationProvider,
|
||||||
|
ignoredTypes: [
|
||||||
|
gmail.ids.EmailNotification,
|
||||||
|
notification.ids.CollaboratoAddNotification,
|
||||||
|
love.ids.InviteNotification,
|
||||||
|
love.ids.KnockNotification
|
||||||
|
],
|
||||||
|
enabledTypes: []
|
||||||
|
})
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { type Doc, type Ref } from '@hcengineering/core'
|
import { type Client, type Doc, type Ref } from '@hcengineering/core'
|
||||||
import { type IntlString, mergeIds, type Resource } from '@hcengineering/platform'
|
import { type IntlString, mergeIds, type Resource } from '@hcengineering/platform'
|
||||||
import { gmailId } from '@hcengineering/gmail'
|
import { gmailId } from '@hcengineering/gmail'
|
||||||
import gmail from '@hcengineering/gmail-resources/src/plugin'
|
import gmail from '@hcengineering/gmail-resources/src/plugin'
|
||||||
@ -52,6 +52,7 @@ export default mergeIds(gmailId, gmail, {
|
|||||||
GmailWriteMessage: '' as AnyComponent
|
GmailWriteMessage: '' as AnyComponent
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
HasEmail: '' as Resource<(doc?: Doc | Doc[] | undefined) => Promise<boolean>>
|
HasEmail: '' as Resource<(doc?: Doc | Doc[] | undefined) => Promise<boolean>>,
|
||||||
|
MessageTitleProvider: '' as Resource<(client: Client, ref: Ref<Doc>, doc?: Doc) => Promise<string>>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -177,7 +177,7 @@
|
|||||||
<MessageTimestamp date={message.createdOn ?? message.modifiedOn} shortTime />
|
<MessageTimestamp date={message.createdOn ?? message.modifiedOn} shortTime />
|
||||||
</span>
|
</span>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="min-w-6 mt-1 relative flex-no-shrink">
|
<div class="avatar mt-1 relative flex-no-shrink">
|
||||||
{#if $$slots.icon}
|
{#if $$slots.icon}
|
||||||
<slot name="icon" />
|
<slot name="icon" />
|
||||||
{:else if person}
|
{:else if person}
|
||||||
@ -344,6 +344,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 2.5rem;
|
||||||
|
height: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
@ -16,9 +16,15 @@
|
|||||||
import { DisplayDocUpdateMessage, DocUpdateMessageViewlet } from '@hcengineering/activity'
|
import { DisplayDocUpdateMessage, DocUpdateMessageViewlet } from '@hcengineering/activity'
|
||||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { Component, Icon, IconAdd, IconDelete } from '@hcengineering/ui'
|
import { AnyComponent, Component, Icon, IconAdd, IconDelete } from '@hcengineering/ui'
|
||||||
import view from '@hcengineering/view'
|
import view, { ObjectPanel } from '@hcengineering/view'
|
||||||
import { buildRemovedDoc, checkIsObjectRemoved, DocNavLink, getDocLinkTitle } from '@hcengineering/view-resources'
|
import {
|
||||||
|
buildRemovedDoc,
|
||||||
|
checkIsObjectRemoved,
|
||||||
|
DocNavLink,
|
||||||
|
getDocLinkTitle,
|
||||||
|
isAttachedDoc
|
||||||
|
} from '@hcengineering/view-resources'
|
||||||
|
|
||||||
export let objectClass: DisplayDocUpdateMessage['objectClass']
|
export let objectClass: DisplayDocUpdateMessage['objectClass']
|
||||||
export let objectId: DisplayDocUpdateMessage['objectId']
|
export let objectId: DisplayDocUpdateMessage['objectId']
|
||||||
@ -59,6 +65,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$: void loadObject(objectId, objectClass)
|
$: void loadObject(objectId, objectClass)
|
||||||
|
|
||||||
|
function getPanelComponent (object: Doc, objectPanel?: ObjectPanel): AnyComponent {
|
||||||
|
if (objectPanel !== undefined) {
|
||||||
|
return objectPanel.component
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isAttachedDoc(object)) {
|
||||||
|
return view.component.AttachedDocPanel
|
||||||
|
}
|
||||||
|
|
||||||
|
return view.component.EditDoc
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if object}
|
{#if object}
|
||||||
@ -84,7 +102,7 @@
|
|||||||
{object}
|
{object}
|
||||||
colorInherit
|
colorInherit
|
||||||
disabled={action === 'remove'}
|
disabled={action === 'remove'}
|
||||||
component={objectPanel?.component ?? view.component.EditDoc}
|
component={getPanelComponent(object, objectPanel)}
|
||||||
shrink={0}
|
shrink={0}
|
||||||
>
|
>
|
||||||
<span class="overflow-label select-text">{value}</span>
|
<span class="overflow-label select-text">{value}</span>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import contact, { Channel } from '@hcengineering/contact'
|
import contact, { Channel } from '@hcengineering/contact'
|
||||||
import { Class, Ref } from '@hcengineering/core'
|
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { AnyComponent, Component } from '@hcengineering/ui'
|
import { AnyComponent, Component } from '@hcengineering/ui'
|
||||||
import { channelProviders } from '../utils'
|
import { channelProviders } from '../utils'
|
||||||
@ -23,6 +23,7 @@
|
|||||||
export let _id: Ref<Channel>
|
export let _id: Ref<Channel>
|
||||||
export let _class: Ref<Class<Channel>>
|
export let _class: Ref<Class<Channel>>
|
||||||
export let embedded: boolean = false
|
export let embedded: boolean = false
|
||||||
|
export let selectedDoc: Ref<Doc> | undefined = undefined
|
||||||
export let activityMessage: DocUpdateMessage | undefined = undefined
|
export let activityMessage: DocUpdateMessage | undefined = undefined
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
@ -52,7 +53,7 @@
|
|||||||
_id: channel?.attachedTo,
|
_id: channel?.attachedTo,
|
||||||
_class: channel?.attachedToClass,
|
_class: channel?.attachedToClass,
|
||||||
channel,
|
channel,
|
||||||
messageId: activityMessage?.objectId
|
messageId: selectedDoc ?? activityMessage?.objectId
|
||||||
}}
|
}}
|
||||||
on:close
|
on:close
|
||||||
/>
|
/>
|
||||||
|
@ -25,7 +25,7 @@ import IconGmail from './components/icons/GmailColor.svelte'
|
|||||||
import Main from './components/Main.svelte'
|
import Main from './components/Main.svelte'
|
||||||
import NewMessages from './components/NewMessages.svelte'
|
import NewMessages from './components/NewMessages.svelte'
|
||||||
import gmail from '@hcengineering/gmail'
|
import gmail from '@hcengineering/gmail'
|
||||||
import { checkHasEmail } from './utils'
|
import { checkHasEmail, MessageTitleProvider } from './utils'
|
||||||
|
|
||||||
export default async (): Promise<Resources> => ({
|
export default async (): Promise<Resources> => ({
|
||||||
component: {
|
component: {
|
||||||
@ -40,7 +40,8 @@ export default async (): Promise<Resources> => ({
|
|||||||
GmailSharedMessage
|
GmailSharedMessage
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
HasEmail: checkHasEmail
|
HasEmail: checkHasEmail,
|
||||||
|
MessageTitleProvider
|
||||||
},
|
},
|
||||||
handler: {
|
handler: {
|
||||||
DisconnectHandler: async () => {
|
DisconnectHandler: async () => {
|
||||||
|
@ -5,7 +5,7 @@ import contact, {
|
|||||||
type PersonAccount,
|
type PersonAccount,
|
||||||
getName as getContactName
|
getName as getContactName
|
||||||
} from '@hcengineering/contact'
|
} from '@hcengineering/contact'
|
||||||
import { type Doc, type IdMap, type Ref, toIdMap } from '@hcengineering/core'
|
import { type Client, type Doc, type IdMap, type Ref, toIdMap } from '@hcengineering/core'
|
||||||
import { type Message, type SharedMessage } from '@hcengineering/gmail'
|
import { type Message, type SharedMessage } from '@hcengineering/gmail'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import gmail from './plugin'
|
import gmail from './plugin'
|
||||||
@ -129,3 +129,9 @@ export function getName (
|
|||||||
return emp != null ? `${getContactName(h, emp)} (${emailVal})` : emailVal
|
return emp != null ? `${getContactName(h, emp)} (${emailVal})` : emailVal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function MessageTitleProvider (client: Client, ref: Ref<Message>, doc?: Message): Promise<string> {
|
||||||
|
const object = doc ?? (await client.findOne(gmail.class.Message, { _id: ref }))
|
||||||
|
|
||||||
|
return object?.subject ?? ''
|
||||||
|
}
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
{#if doc && panelComponent}
|
{#if doc && panelComponent}
|
||||||
<Component
|
<Component
|
||||||
is={panelComponent}
|
is={panelComponent}
|
||||||
props={{ embedded, _id: doc.attachedTo, _class: doc.attachedToClass, ...props }}
|
props={{ embedded, _id: doc.attachedTo, _class: doc.attachedToClass, selectedDoc: _id, ...props }}
|
||||||
on:close
|
on:close
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -249,7 +249,7 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar
|
|||||||
params: null
|
params: null
|
||||||
}
|
}
|
||||||
ctx.derived.txes.push(tx)
|
ctx.derived.txes.push(tx)
|
||||||
ctx.derived.targets.security = (it) => {
|
ctx.derived.targets['security' + tx._id] = (it) => {
|
||||||
// TODO: I'm not sure it is called
|
// TODO: I'm not sure it is called
|
||||||
if (it._id === tx._id) {
|
if (it._id === tx._id) {
|
||||||
return targets
|
return targets
|
||||||
@ -383,8 +383,10 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar
|
|||||||
await this.processTx(ctx, tx)
|
await this.processTx(ctx, tx)
|
||||||
const res = await this.provideTx(ctx, tx)
|
const res = await this.provideTx(ctx, tx)
|
||||||
for (const txd of ctx.derived.txes) {
|
for (const txd of ctx.derived.txes) {
|
||||||
|
if (txd._id !== tx._id) {
|
||||||
await this.processTx(ctx, txd)
|
await this.processTx(ctx, txd)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user