Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2022-06-03 11:24:38 +07:00 committed by GitHub
parent d5cfa868f5
commit 6bb8bf5e1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 131 additions and 24 deletions

3
.gitignore vendored
View File

@ -71,4 +71,5 @@ common/autoinstallers/*/.npmrc
bundle.js
dist
tsconfig.tsbuildinfo
ingest-attachment-*.zip
ingest-attachment-*.zip
tsdoc-metadata.json

View File

@ -389,9 +389,9 @@ export function createModel (builder: Builder): void {
input: 'focus',
category: recruit.category.Recruit,
target: contact.class.Person,
context: { mode: ['context', 'browser'] }
context: { mode: ['context', 'browser'] },
override: [recruit.action.CreateGlobalApplication]
})
createAction(builder, {
action: view.actionImpl.ShowPopup,
actionProps: {
@ -428,23 +428,27 @@ export function createModel (builder: Builder): void {
}
})
createAction(builder, {
action: view.actionImpl.ShowPopup,
actionProps: {
component: recruit.component.CreateApplication,
element: 'top'
createAction(
builder,
{
action: view.actionImpl.ShowPopup,
actionProps: {
component: recruit.component.CreateApplication,
element: 'top'
},
label: recruit.string.CreateApplication,
icon: recruit.icon.Create,
keyBinding: [],
input: 'none',
category: recruit.category.Recruit,
target: core.class.Doc,
context: {
mode: ['workbench', 'browser'],
application: recruit.app.Recruit
}
},
label: recruit.string.CreateApplication,
icon: recruit.icon.Create,
keyBinding: [],
input: 'none',
category: recruit.category.Recruit,
target: core.class.Doc,
context: {
mode: ['workbench', 'browser'],
application: recruit.app.Recruit
}
})
recruit.action.CreateGlobalApplication
)
builder.createDoc(
task.class.KanbanTemplateSpace,

View File

@ -25,7 +25,8 @@ import type { Action, ActionCategory, ViewAction } from '@anticrm/view'
export default mergeIds(recruitId, recruit, {
action: {
CreateOpinion: '' as Ref<Action>
CreateOpinion: '' as Ref<Action>,
CreateGlobalApplication: '' as Ref<Action>
},
actionImpl: {
CreateOpinion: '' as ViewAction

View File

@ -36,10 +36,17 @@
<slot name="header" />
<span class="antiCard-header__divider"></span>
{/if}
<span class="antiCard-header__title"><Label {label} params={labelProps ?? {}} /></span>
<span class="antiCard-header__title">
{#if $$slots.title}
<slot name="title" />
{:else}
<Label {label} params={labelProps ?? {}} />
{/if}
</span>
</div>
<div class="buttons-group small-gap">
<Button
id={'card-close'}
focusIndex={10002}
icon={IconClose}
kind={'transparent'}

View File

@ -14,7 +14,7 @@
"MakePrivateDescription": "Only members can see it",
"CreateAnApplication": "New Application",
"NoApplicationsForCandidate": "There are no applications for this candidate.",
"CreateApplication": "Create an Application",
"CreateApplication": "New Application",
"ApplicationCreateLabel": "Application",
"SelectVacancy": "Select vacancy",
"Candidate": "Candidate",

View File

@ -27,6 +27,7 @@
eventToHTMLElement,
FocusHandler,
getPlatformColor,
Label,
showPopup,
Status as StatusControl
} from '@anticrm/ui'
@ -223,6 +224,24 @@
bind:space={doc.space}
/>
</svelte:fragment>
<svelte:fragment slot="title">
<div class="flex-row-center gap-2">
{#if preserveCandidate}
<UserBox
readonly
_class={contact.class.Person}
options={{ sort: { modifiedOn: -1 } }}
excluded={existingApplicants}
label={recruit.string.Candidate}
placeholder={recruit.string.Candidates}
bind:value={doc.attachedTo}
kind={'no-border'}
size={'small'}
/>
{/if}
<Label label={recruit.string.CreateApplication} />
</div>
</svelte:fragment>
<StatusControl slot="error" {status} />
<svelte:fragment slot="pool">
{#key doc}

View File

@ -116,15 +116,19 @@ export function filterActions (
actions: Array<WithLookup<Action>>,
derived: Ref<Class<Doc>> = core.class.Doc
): Array<WithLookup<Action>> {
const result: Array<WithLookup<Action>> = []
let result: Array<WithLookup<Action>> = []
const hierarchy = client.getHierarchy()
const clazz = hierarchy.getClass(doc._class)
const ignoreActions = hierarchy.as(clazz, view.mixin.IgnoreActions)
const ignore = ignoreActions?.actions ?? []
const overrideRemove: Array<Ref<Action>> = []
for (const action of actions) {
if (ignore.includes(action._id)) {
continue
}
if (action.override !== undefined) {
overrideRemove.push(...action.override)
}
if (action.query !== undefined) {
const r = matchQuery([doc], action.query, doc._class, hierarchy)
if (r.length === 0) {
@ -138,5 +142,8 @@ export function filterActions (
result.push(action)
}
}
if (overrideRemove.length > 0) {
result = result.filter((it) => !overrideRemove.includes(it._id))
}
return result
}

View File

@ -235,6 +235,10 @@ export interface Action<T extends Doc = Doc, P = Record<string, any>> extends Do
// Context action is defined for
context: ViewContext
// A list of actions replaced by this one.
// For example it could be global action and action for focus class, second one fill override first one.
override?: Ref<Action>[]
}
/**

View File

@ -0,0 +1,64 @@
import { expect, test } from '@playwright/test'
import { PlatformSetting, PlatformURI } from './utils'
test.use({
storageState: PlatformSetting
})
test.describe('actions tests', () => {
test.beforeEach(async ({ page }) => {
// Create user and workspace
await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp`)
})
test('action-new-candidate', async ({ page }) => {
await page.click('[id="app-recruit\\:string\\:RecruitApplication"]')
await page.click('text=Candidates')
await expect(page).toHaveURL(
`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/recruit%3Aapp%3ARecruit/candidates`
)
await page.click('td:has-text("Frontend Engineer")')
await page.press('body', 'Meta+k')
await page.fill('[placeholder="type\\ to\\ filter\\.\\.\\."]', 'Candidate')
expect(await page.locator('div.selectPopup :text("New Candidate")').count()).toBe(1)
await page.click('div.selectPopup :text("New Candidate")')
await page.click('button#card-close')
})
test('action-switch-vacancies', async ({ page }) => {
await page.click('[id="app-recruit\\:string\\:RecruitApplication"]')
await page.click('text=Candidates')
await expect(page).toHaveURL(
`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/recruit%3Aapp%3ARecruit/candidates`
)
await page.press('body', 'Meta+k')
await page.fill('[placeholder="type\\ to\\ filter\\.\\.\\."]', 'go to')
expect(await page.locator('div.selectPopup :text("Go To Vacancies")').count()).toBe(1)
await page.click('div.selectPopup :text("Go To Vacancies")')
await expect(page).toHaveURL(
`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/recruit%3Aapp%3ARecruit/vacancies`
)
})
test('action-switch-applications', async ({ page }) => {
await page.click('[id="app-recruit\\:string\\:RecruitApplication"]')
await page.click('text=Candidates')
await expect(page).toHaveURL(
`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/recruit%3Aapp%3ARecruit/candidates`
)
await page.press('body', 'Meta+k')
await page.fill('[placeholder="type\\ to\\ filter\\.\\.\\."]', 'go to')
expect(await page.locator('div.selectPopup :text("Go To Applications")').count()).toBe(1)
await page.click('div.selectPopup :text("Go To Applications")')
await expect(page).toHaveURL(
`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/recruit%3Aapp%3ARecruit/applicants`
)
})
})

View File

@ -20,7 +20,7 @@ test.describe('recruit tests', () => {
const first = 'Elton-' + generateId(4)
const last = 'John-' + generateId(4)
const loc = 'Cupertino'
const email = 'ej@test.com'
const email = `ej-${generateId(4)}@test.com`
const firstName = page.locator('[placeholder="John"]')
await firstName.click()