Default values (#2792)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-03-21 22:08:45 +06:00 committed by GitHub
parent 79fbb9e6f3
commit 95ea0aab98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 118 additions and 31 deletions

View File

@ -152,6 +152,7 @@ export class TAttribute extends TDoc implements AnyAttribute {
type!: Type<any>
label!: IntlString
isCustom?: boolean
defaultValue?: any
}
@Model(core.class.Type, core.class.Obj, DOMAIN_MODEL)

View File

@ -115,6 +115,7 @@ export interface Attribute<T extends PropertyType> extends Doc, UXObject {
index?: IndexKind
shortLabel?: IntlString
isCustom?: boolean
defaultValue?: any
// Extra customization properties
[key: string]: any
@ -192,6 +193,11 @@ export type Data<T extends Doc> = Omit<T, keyof Doc>
*/
export type AttachedData<T extends AttachedDoc> = Omit<T, keyof AttachedDoc>
/**
* @public
*/
export type DocData<T extends Doc> = T extends AttachedDoc ? AttachedData<T> : Data<T>
// T Y P E S
/**

View File

@ -13,9 +13,10 @@
// limitations under the License.
//
import { Account, AnyAttribute, Class, Doc, DocIndexState, IndexKind, Obj, Ref } from './classes'
import { FindResult } from './storage'
import { Account, AnyAttribute, Class, Doc, DocData, DocIndexState, IndexKind, Obj, Ref } from './classes'
import core from './component'
import { Hierarchy } from './hierarchy'
import { FindResult } from './storage'
function toHex (value: number, chars: number): string {
const result = value.toString(16)
@ -199,3 +200,23 @@ export function concatLink (host: string, path: string): string {
return `${host}${path}`
}
}
/**
* @public
*/
export function fillDefaults<T extends Doc> (
hierarchy: Hierarchy,
object: DocData<T> | T,
_class: Ref<Class<T>>
): DocData<T> | T {
const baseClass = hierarchy.isDerived(_class, core.class.AttachedDoc) ? core.class.AttachedDoc : core.class.Doc
const attributes = hierarchy.getAllAttributes(_class, baseClass)
for (const attribute of attributes) {
if (attribute[1].defaultValue !== undefined) {
if ((object as any)[attribute[0]] === undefined) {
;(object as any)[attribute[0]] = attribute[1].defaultValue
}
}
}
return object
}

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import { Channel, findContacts, Organization } from '@hcengineering/contact'
import { AttachedData, generateId, Ref, TxOperations, WithLookup } from '@hcengineering/core'
import { AttachedData, fillDefaults, generateId, Ref, TxOperations, WithLookup } from '@hcengineering/core'
import { Card, getClient, InlineAttributeBar } from '@hcengineering/presentation'
import { Button, createFocusManager, EditBox, FocusHandler, IconInfo, Label } from '@hcengineering/ui'
import { createEventDispatcher } from 'svelte'
@ -37,6 +37,9 @@
const dispatch = createEventDispatcher()
const client = getClient()
const hierarchy = client.getHierarchy()
fillDefaults(hierarchy, object, contact.class.Organization)
async function createOrganization () {
await client.createDoc(contact.class.Organization, contact.space.Contacts, object, id)

View File

@ -22,6 +22,7 @@
Account,
Class,
Client,
fillDefaults,
Doc,
FindOptions,
generateId,
@ -99,6 +100,7 @@
const dispatch = createEventDispatcher()
const client = getClient()
const hierarchy = client.getHierarchy()
fillDefaults(hierarchy, doc, recruit.class.Applicant)
export function canClose (): boolean {
return (preserveCandidate || _candidate === undefined) && assignee === undefined
@ -184,6 +186,7 @@
dueDate: null,
createOn: Date.now()
}
fillDefaults(hierarchy, doc, recruit.class.Applicant)
}
}

View File

@ -23,6 +23,7 @@
AttachedData,
Data,
Doc,
fillDefaults,
generateId,
MixinData,
Ref,
@ -109,8 +110,11 @@
remote: draft?.remote
} as Candidate
}
const client = getClient()
const hierarchy = client.getHierarchy()
const object: Candidate = toCandidate(draft)
fillDefaults(hierarchy, object, recruit.mixin.Candidate)
function resumeDraft () {
return {
@ -125,7 +129,6 @@
let resume = resumeDraft() as resumeFile
const dispatch = createEventDispatcher()
const client = getClient()
let inputFile: HTMLInputElement
let loading = false
@ -544,6 +547,7 @@
object.avatar = undefined
object.onsite = undefined
object.remote = undefined
fillDefaults(hierarchy, object, recruit.mixin.Candidate)
}
export async function onOutsideClick () {

View File

@ -15,7 +15,15 @@
<script lang="ts">
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
import contact, { Organization } from '@hcengineering/contact'
import core, { Data, FindResult, generateId, getCurrentAccount, Ref, SortingOrder } from '@hcengineering/core'
import core, {
Data,
fillDefaults,
FindResult,
generateId,
getCurrentAccount,
Ref,
SortingOrder
} from '@hcengineering/core'
import { Card, createQuery, getClient, InlineAttributeBar, MessageBox, UserBox } from '@hcengineering/presentation'
import { Vacancy as VacancyClass } from '@hcengineering/recruit'
import tags from '@hcengineering/tags'
@ -69,7 +77,6 @@
fullDescription: '',
location: ''
}
export function canClose (): boolean {
return name === '' && templateId !== undefined
}
@ -77,7 +84,9 @@
let changed = false
const client = getClient()
const hierarchy = client.getHierarchy()
const templateQ = createQuery()
fillDefaults(hierarchy, vacancyData, recruit.class.Vacancy)
$: templateQ.query(task.class.KanbanTemplate, { _id: templateId }, (result) => {
const { _class, _id, description, ...templateData } = result[0]
vacancyData = { ...(templateData as unknown as Data<VacancyClass>), fullDescription: description }

View File

@ -69,6 +69,7 @@
"Visibility": "Visibility",
"Hidden": "Hidden",
"Configure": "Configure",
"InviteSettings": "Workspace invite settings"
"InviteSettings": "Workspace invite settings",
"DefaultValue": "Default value"
}
}

View File

@ -70,6 +70,7 @@
"Visibility": "Видимость",
"Hidden": "Спрятанный",
"Configure": "Настроить",
"InviteSettings": "Настройки приглашений в пространство"
"InviteSettings": "Настройки приглашений в пространство",
"DefaultValue": "Значение по умолчанию"
}
}

View File

@ -36,6 +36,7 @@
let name: string
let type: Type<PropertyType> | undefined
let index: IndexKind | undefined
let defaultValue: any | undefined
let is: AnyComponent | undefined
const client = getClient()
const hierarchy = client.getHierarchy()
@ -49,7 +50,8 @@
name: name.trim().replace('/', '').replace(' ', '') + '_' + generateId(),
label: getEmbeddedLabel(name),
isCustom: true,
type
type,
defaultValue
}
if (index !== undefined) {
data.index = index
@ -89,6 +91,7 @@
const handleChange = (e: any) => {
type = e.detail?.type
index = e.detail?.index
defaultValue = e.detail?.defaultValue
}
</script>

View File

@ -26,6 +26,7 @@
let name: string
let type: Type<PropertyType> | undefined = attribute.type
let index: IndexKind | undefined = attribute.index
let defaultValue: any | undefined = attribute.defaultValue
let is: AnyComponent | undefined
const client = getClient()
@ -40,6 +41,9 @@
if (newLabel !== attribute.label) {
update.label = newLabel
}
if (defaultValue !== attribute.defaultValue) {
update.defaultValue = defaultValue
}
if (!exist) {
if (index !== attribute.index) {
update.index = index
@ -83,6 +87,7 @@
const handleChange = (e: any) => {
type = e.detail?.type
index = e.detail?.index
defaultValue = e.detail?.defaultValue
}
</script>
@ -119,6 +124,7 @@
{is}
props={{
type,
defaultValue,
editable: !exist
}}
on:change={handleChange}

View File

@ -17,6 +17,7 @@
import { TypeEnum } from '@hcengineering/model'
import presentation, { getClient } from '@hcengineering/presentation'
import { Button, Label, showPopup } from '@hcengineering/ui'
import { EnumEditor } from '@hcengineering/view-resources'
import { createEventDispatcher } from 'svelte'
import setting from '../../plugin'
import EnumSelect from './EnumSelect.svelte'
@ -24,11 +25,12 @@
export let type: EnumOf | undefined
export let editable: boolean = true
export let value: Enum | undefined
export let defaultValue: string | undefined
const client = getClient()
const dispatch = createEventDispatcher()
$: value && dispatch('change', { type: TypeEnum(value._id) })
$: value && changeEnum(value)
$: ref = value?._id ?? type?.of
const create = {
@ -36,6 +38,11 @@
component: setting.component.EditEnum
}
function changeEnum (value: Enum) {
type = TypeEnum(value._id)
dispatch('change', { type, defaultValue })
}
async function updateSelected (ref: Ref<Enum> | undefined) {
value = ref !== undefined ? await client.findOne(core.class.Enum, { _id: ref }) : undefined
}
@ -48,24 +55,42 @@
}
</script>
<div class="flex-row-center flex-grow">
<Label label={core.string.Enum} />
<div class="ml-4">
{#if editable}
<EnumSelect label={core.string.Enum} bind:value {create} />
{:else if value}
{value.name}
<div>
<div class="flex-row-center flex-grow">
<Label label={core.string.Enum} />
<div class="ml-4">
{#if editable}
<EnumSelect label={core.string.Enum} bind:value {create} />
{:else if value}
{value.name}
{/if}
</div>
{#if value}
<div class="ml-2">
<Button
icon={setting.icon.Setting}
kind={'no-border'}
size={'small'}
showTooltip={{ label: presentation.string.Edit }}
on:click={edit}
/>
</div>
{/if}
</div>
{#if value}
<div class="ml-2">
<Button
icon={setting.icon.Setting}
kind={'no-border'}
size={'small'}
showTooltip={{ label: presentation.string.Edit }}
on:click={edit}
/>
{#if value && type}
<div class="flex-row-center mt-2">
<Label label={setting.string.DefaultValue} />
<div class="ml-2">
<EnumEditor
label={setting.string.DefaultValue}
{type}
value={defaultValue ?? ''}
onChange={(e) => {
defaultValue = e
dispatch('change', { type, defaultValue })
}}
/>
</div>
</div>
{/if}
</div>

View File

@ -62,6 +62,7 @@ export default mergeIds(settingId, setting, {
ShowAttribute: '' as IntlString,
Visibility: '' as IntlString,
Hidden: '' as IntlString,
InviteSettings: '' as IntlString
InviteSettings: '' as IntlString,
DefaultValue: '' as IntlString
}
})

View File

@ -21,6 +21,7 @@
AttachedData,
Data,
Doc,
fillDefaults,
generateId,
Ref,
SortingOrder,
@ -95,6 +96,8 @@
export let onDraftChanged: () => void
const draft: IssueDraft | undefined = shouldSaveDraft ? getUserDraft(tracker.class.IssueDraft) : undefined
const client = getClient()
const hierarchy = client.getHierarchy()
let subIssuesComponent: SubIssues
@ -145,6 +148,7 @@
childInfo: []
}
: toIssue(defaultIssue, draft)
fillDefaults(hierarchy, object, tracker.class.Issue)
function resetObject (): void {
templateId = undefined
@ -156,6 +160,7 @@
updateIssueStatusId(currentProject, status)
updateAssigneeId(currentProject)
}
fillDefaults(hierarchy, object, tracker.class.Issue)
}
let templateId: Ref<IssueTemplate> | undefined = draft?.template?.template
@ -223,7 +228,6 @@
$: updateTemplate(template)
const dispatch = createEventDispatcher()
const client = getClient()
const statusesQuery = createQuery()
const spaceQuery = createQuery()

View File

@ -40,8 +40,6 @@
export let _id: Ref<Doc>
export let _class: Ref<Class<Doc>>
console.log('OPEN EDIT DOC')
let realObjectClass: Ref<Class<Doc>> = _class
let lastId: Ref<Doc> = _id
let lastClass: Ref<Class<Doc>> = _class

View File

@ -145,7 +145,8 @@ export {
TreeNode,
TreeItem,
StringEditor,
DocNavLink
DocNavLink,
EnumEditor
}
export default async (): Promise<Resources> => ({