import WithRender from "./edit-type-dropdown.vue" ; import Vue from "vue" ; import { Component , Prop , Ref , Watch } from "vue-property-decorator" ; import { Field , FieldOptionUpdate , FieldUpdate , Line , Marker , Type } from "facilmap-types" ; import { clone } from "facilmap-utils" ; import { canControl , mergeObject } from "../../utils/utils" ; import { isEqual } from "lodash" ; import { showErrorToast } from "../../utils/toasts" ; import ColourField from "../ui/colour-field/colour-field" ; import draggable from "vuedraggable" ; import Icon from "../ui/icon/icon" ; import FormModal from "../ui/form-modal/form-modal" ; import ShapeField from "../ui/shape-field/shape-field" ; import SizeField from "../ui/size-field/size-field" ; import SymbolField from "../ui/symbol-field/symbol-field" ; import WidthField from "../ui/width-field/width-field" ; import { extend , ValidationProvider } from "vee-validate" ; import "./edit-type-dropdown.scss" ; import { Context } from "../facilmap/facilmap" ; import { InjectContext } from "../../utils/decorators" ; extend ( "uniqueFieldOptionValue" , { validate : ( value , args ) => { const field = args . field ?. field ; return ! field || field . options ! . filter ( ( option ) => option . value == value ) . length <= 1 ; } , message : "Multiple options cannot have the same label." , params : [ "field" ] , computesRequired : true } ) ; extend ( "fieldOptionNumber" , { validate : ( { field , type } , args ) => { return getControlNumber ( type , field ) == 0 || ( ! ! field . options && field . options . length > 0 ) ; } , message : "Controlling fields need to have at least one option." , params : [ "controlNumber" ] } ) ; function getControlNumber ( type , field ) { return [ field . controlColour , ... ( type . type == "marker" ? [ field . controlSize , field . controlSymbol , field . controlShape ] : [ ] ) , ... ( type . type == "line" ? [ field . controlWidth ] : [ ] ) ] . filter ( ( v ) => v ) . length ; } @ WithRender @ Component ( { components : { ColourField , draggable , Icon , FormModal , ShapeField , SizeField , SymbolField , ValidationProvider , WidthField } } ) export default class EditTypeDropdown extends Vue { @ InjectContext ( ) context ! : Context ; @ Prop ( { type : String , required : true } ) id ! : string ; @ Prop ( { type : Object , required : true } ) type ! : Type ; @ Prop ( { type : Object , required : true } ) field ! : Field ; @ Ref ( ) fieldValidationProvider ? : InstanceType < typeof ValidationProvider > ; fieldValue : FieldUpdate = null as any ; initialize ( ) { this . fieldValue = clone ( this . initialField ) ; } clear ( ) { this . fieldValue = null as any ; } get initialField ( ) : FieldUpdate { const field = clone ( this . field ) ; if ( field . type == 'checkbox' ) { if ( ! field . options || field . options . length != 2 ) { field . options = [ { value : '' } , { value : field . name } ] ; } if ( field . options [ 0 ] . value == "0" ) field . options [ 0 ] . value = "" ; if ( field . options [ 1 ] . value == "1" ) field . options [ 1 ] . value = field . name ; } for ( let option of ( field . options || [ ] ) ) option . oldValue = option . value ; return field ; } @ Watch ( "field" , { deep : true } ) handleFieldChange ( newField , oldField ) { if ( this . fieldValue ) { if ( newField == null ) { this . $bvModal . hide ( this . id ) ; } else { mergeObject ( oldField , newField , this . fieldValue ) ; } } } @ Watch ( "fieldValue" , { deep : true } ) handleChange ( field ) { this . fieldValidationProvider ?. validate ( { type : this . type , field } ) ; } get isModified ( ) : boolean { return ! isEqual ( this . fieldValue , this . initialField ) ; } get canControl ( ) : Array < keyof Marker | keyof Line > { return canControl ( this . type , this . field ) ; } addOption ( ) { if ( this . fieldValue . options == null ) Vue . set ( this . fieldValue , "options" , [ ] ) ; this . fieldValue . options ! . push ( { value : "" } ) ; } async deleteOption ( option ) { if ( ! await this . $bvModal . msgBoxConfirm ( `Do you really want to delete the option “${ option . value }”?` ) ) return ; var idx = this . fieldValue . options ! . indexOf ( option ) ; if ( idx != - 1 ) this . fieldValue . options ! . splice ( idx , 1 ) ; } save ( ) { this . $bvToast . hide ( `fm${ this . context . id }-edit-type-dropdown-error` ) ; const idx = this . type . fields . indexOf ( this . field ) ; if ( idx === - 1 ) showErrorToast ( this , `fm${ this . context . id }-edit-type-dropdown-error` , "Error updating field" , new Error ( "The field cannot be found on the type anymore." ) ) ; else { Vue . nextTick ( ( ) => { Vue . set ( this . type . fields , idx , this . fieldValue ) ; } ) ; this . $bvModal . hide ( this . id ) ; } } get controlNumber ( ) : number { return getControlNumber ( this . type , this . fieldValue ) ; } }