// // 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. // import type { AnyAttribute, Class, Client, Doc, DocumentQuery, FindOptions, Lookup, Mixin, Obj, ObjQueryType, Ref, Space, Type, UXObject } from '@anticrm/core' import { Asset, IntlString, Plugin, plugin, Resource, Status } from '@anticrm/platform' import type { Preference } from '@anticrm/preference' import type { AnyComponent, AnySvelteComponent, PopupAlignment, PopupPosAlignment } from '@anticrm/ui' /** * @public */ export interface KeyFilter { _class: Ref> key: string component: AnyComponent label: IntlString icon: Asset | undefined } /** * @public */ export interface FilterMode extends Doc { label: IntlString result: Resource<(filter: Filter, onUpdate: () => void) => Promise>> } /** * @public */ export interface Filter { key: KeyFilter nested?: Filter mode: Ref modes: Ref[] value: any[] index: number onRemove?: () => void } /** * @public */ export interface ClassFilters extends Class { filters: (KeyFilter | string)[] } /** * @public */ export interface AttributeFilter extends Class> { component: AnyComponent } /** * @public */ export interface AttributeEditor extends Class { inlineEditor: AnyComponent // If defined could be used for ShowEditor declarative actions. popup?: AnyComponent } /** * @public */ export interface CollectionEditor extends Class { editor: AnyComponent inlineEditor?: AnyComponent } /** * @public */ export interface ArrayEditor extends Class { editor?: AnyComponent inlineEditor?: AnyComponent } /** * @public */ export interface CollectionPresenter extends Class { presenter: AnyComponent } /** * @public */ export interface AttributePresenter extends Class { presenter: AnyComponent } /** * @public */ export interface ObjectEditor extends Class { editor: AnyComponent } /** * @public */ export interface SpaceHeader extends Class { header: AnyComponent } /** * @public */ export interface SpaceName extends Class { getName: Resource<(client: Client, space: Space) => Promise> } /** * @public */ export interface ObjectEditorHeader extends Class { editor: AnyComponent } /** * @public */ export interface ObjectValidator extends Class { validator: Resource<(doc: T, client: Client) => Promise> } /** * @public */ export interface ObjectTitle extends Class { titleProvider: Resource<(client: Client, ref: Ref) => Promise> } /** * @public */ export interface ViewletDescriptor extends Doc, UXObject { component: AnyComponent } /** * @public */ export interface Viewlet extends Doc { attachTo: Ref> descriptor: Ref options?: FindOptions config: (BuildModelKey | string)[] hiddenKeys?: string[] } /** * @public */ export interface LinkPresenter extends Doc { pattern: string component: AnyComponent } /** * @public * * "Alt + K" =\> Alt and K should be pressed together * "J T" - J and then T shold be pressed. */ export type KeyBinding = string /** * @public */ export type ViewActionInput = 'focus' | 'selection' | 'any' | 'none' /** * @public */ export type ViewAction> = Resource< (doc: Doc | Doc[] | undefined, evt: Event, params?: T) => Promise > /** * @public */ export interface ActionCategory extends Doc, UXObject { // Does category is visible for use in popup. visible: boolean } /** * @public */ export type ActionGroup = 'create' | 'edit' | 'associate' | 'copy' | 'tools' | 'other' /** * @public */ export interface Action> extends Doc, UXObject { // Action implementation details action: ViewAction

// Action implementation parameters actionProps?: P // If specified, will show sub menu based on actionPopup/actionProps actionPopup?: AnyComponent // If specified, action could be used only with one item selected. // single - one object is required // any - one or multiple objects are required // any - any input is suitable. input: ViewActionInput inline?: boolean // Focus and/or all selection document should match target class. target: Ref> // Action is applicable only for objects matching criteria query?: DocumentQuery // If defined, types should be matched to proposed list inputProps?: Record>> // Kayboard bindings keyBinding?: KeyBinding[] // short description for action. description?: IntlString // Action category, for UI. category: Ref // 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[] } /** * @public * context - only for context menu actions. * workbench - global actions per application or entire workbench. * browser - actions for list/table/kanban browsing. * editor - actions for selected editor context. * panel - for panel based actions. * popup - for popup based actions, like Close of Popup. * input - for input based actions, some actions should be available for input controls. */ export type ViewContextType = 'context' | 'workbench' | 'browser' | 'editor' | 'panel' | 'popup' | 'input' | 'none' /** * @public */ export interface ViewContext { mode: ViewContextType | ViewContextType[] // Active application application?: Ref // Optional groupping group?: ActionGroup } /** * @public */ export interface IgnoreActions extends Class { actions: Ref[] } /** * @public */ export interface HTMLPresenter extends Class { presenter: Resource<(doc: Doc) => string> } /** * @public */ export interface TextPresenter extends Class { presenter: Resource<(doc: Doc) => string> } /** * @public */ export interface PreviewPresenter extends Class { presenter: AnyComponent } /** * @public */ export const viewId = 'view' as Plugin /** * @public */ export interface BuildModelKey { key: string presenter?: AnyComponent // A set of extra props passed to presenter. props?: Record label?: IntlString sortingKey?: string | string[] // On client sorting function sortingFunction?: (a: Doc, b: Doc) => number } /** * @public */ export interface AttributeModel { key: string label: IntlString _class: Ref> presenter: AnySvelteComponent // Extra properties for component props?: Record sortingKey: string | string[] // Extra icon if applicable icon?: Asset attribute?: AnyAttribute collectionAttr: boolean } /** * @public */ export interface BuildModelOptions { client: Client _class: Ref> keys: (BuildModelKey | string)[] lookup?: Lookup ignoreMissing?: boolean } /** * Define document create popup widget * * @public * */ export interface ObjectFactory extends Class { component: AnyComponent } /** * @public */ export interface ViewletPreference extends Preference { attachedTo: Ref config: (BuildModelKey | string)[] } /** * @public */ const view = plugin(viewId, { mixin: { ClassFilters: '' as Ref>, AttributeFilter: '' as Ref>, AttributeEditor: '' as Ref>, CollectionPresenter: '' as Ref>, CollectionEditor: '' as Ref>, ArrayEditor: '' as Ref>, AttributePresenter: '' as Ref>, ObjectEditor: '' as Ref>, ObjectEditorHeader: '' as Ref>, ObjectValidator: '' as Ref>, ObjectFactory: '' as Ref>, ObjectTitle: '' as Ref>, SpaceHeader: '' as Ref>, SpaceName: '' as Ref>, IgnoreActions: '' as Ref>, HTMLPresenter: '' as Ref>, TextPresenter: '' as Ref>, PreviewPresenter: '' as Ref> }, class: { ViewletPreference: '' as Ref>, ViewletDescriptor: '' as Ref>, Viewlet: '' as Ref>, Action: '' as Ref>, ActionCategory: '' as Ref>, LinkPresenter: '' as Ref>, FilterMode: '' as Ref> }, action: { Delete: '' as Ref, Move: '' as Ref, MoveLeft: '' as Ref, MoveRight: '' as Ref, MoveUp: '' as Ref, MoveDown: '' as Ref, SelectItem: '' as Ref, SelectItemAll: '' as Ref, SelectItemNone: '' as Ref, SelectUp: '' as Ref, SelectDown: '' as Ref, ShowPreview: '' as Ref, ShowActions: '' as Ref, // Edit document Open: '' as Ref }, viewlet: { Table: '' as Ref }, component: { ObjectPresenter: '' as AnyComponent, EditDoc: '' as AnyComponent, SpacePresenter: '' as AnyComponent, BooleanTruePresenter: '' as AnyComponent, ValueSelector: '' as AnyComponent }, string: { CustomizeView: '' as IntlString, LabelNA: '' as IntlString, View: '' as IntlString }, icon: { Table: '' as Asset, Card: '' as Asset, Delete: '' as Asset, MoreH: '' as Asset, Move: '' as Asset, Archive: '' as Asset, Statuses: '' as Asset, Setting: '' as Asset, Open: '' as Asset, ArrowRight: '' as Asset, Views: '' as Asset, Pin: '' as Asset, Model: '' as Asset, ViewButton: '' as Asset }, category: { General: '' as Ref, GeneralNavigation: '' as Ref, Navigation: '' as Ref, Editor: '' as Ref, MarkdownFormatting: '' as Ref }, filter: { FilterObjectIn: '' as Ref, FilterObjectNin: '' as Ref, FilterValueIn: '' as Ref, FilterValueNin: '' as Ref, FilterBefore: '' as Ref, FilterAfter: '' as Ref, FilterNestedMatch: '' as Ref, FilterNestedDontMatch: '' as Ref }, popup: { PositionElementAlignment: '' as Resource<(e?: Event) => PopupAlignment | undefined> }, actionImpl: { UpdateDocument: '' as ViewAction<{ key: string value: any ask?: boolean label?: IntlString message?: IntlString }>, ShowPanel: '' as ViewAction<{ component?: AnyComponent element?: PopupPosAlignment rightSection?: AnyComponent }>, ShowPopup: '' as ViewAction<{ component: AnyComponent element?: PopupPosAlignment | Resource<(e?: Event) => PopupAlignment | undefined> _id?: string _class?: string _space?: string value?: string values?: string props?: Record // Will copy values from selection document to props fillProps?: Record }>, ShowEditor: '' as ViewAction<{ element?: PopupPosAlignment | Resource<(e?: Event) => PopupAlignment | undefined> attribute: string props?: Record }>, ValueSelector: '' as ViewAction<{ attribute: string // Class object finder _class?: Ref> query?: DocumentQuery queryOptions?: FindOptions // Will copy values from selection document to query // If set of docs passed, will do $in for values. fillQuery?: Record // A list of fields with matched values to perform action. docMatches?: string[] searchField?: string // Or list of values to select from values?: { icon?: Asset, label: IntlString, id: number | string }[] placeholder?: IntlString }> } }) export default view