Compare commits

...

7 Commits

Author SHA1 Message Date
oguzhankoral 18caf16621 WIP 2024-02-12 18:09:31 +03:00
oguzhankoral c781534950 Trigger sketchup only saved stream not exists 2024-02-12 11:52:18 +03:00
oguzhankoral 886ede61e1 Enrich selected account info and fix same user id issue 2024-02-12 11:31:02 +03:00
oguzhankoral 5a42ea39ce Disable reload 2024-02-12 11:30:39 +03:00
Oğuzhan Koral ab7397bf55 Feat (FE2): CNX-8702 fe2 urls (#320)
* Recreate ApolloProvider whenever account switches

- It is a force-push of reload page whenever user switches account. It doesn't hurt

* Fix FE2 urls and streamWrapper flag argument
2024-02-03 02:36:41 +03:00
Oğuzhan Koral f79547f781 Reset UI location to center of SketchUp (#319) 2024-01-31 23:00:46 +03:00
Oğuzhan Koral 2152f1c90e Feat (Mapper): CNX-8309 Family instances (#318)
* Implement New Revit Family option

* Filter family types for 'Family Instance'

* Adjust available mapping methods according to selection

* Set hard coded categories just once and source families when source set/updated

* Implement family instance mapping

* Pass group selection info if only group selected

* Exclude definitions from conversion escape

- Previously we were using definition mappings only for direct shape conversions but now they can live in instances

* Add direct shape option to components back

* Calculate rotation of family instance

* Fix transformation matrix

* Use insertion point for instances

* Set inputs for mapped definition
2024-01-08 18:40:55 +03:00
28 changed files with 678 additions and 222 deletions
@@ -0,0 +1,22 @@
# frozen_string_literal: true
require_relative 'action'
require_relative '../mapper/category/revit_category'
require_relative '../mapper/category/revit_family_category'
module SpeckleConnector
module Actions
# Collects mapper selection info.
class MapperInitialized < Action
# @param state [States::State] the current state of the {App::SpeckleConnectorApp}
# @return [States::State] the new updated state object
def self.update_state(state, _data)
init_parameters = {
categories: Mapper::Category::RevitCategory.to_a,
familyCategories: Mapper::Category::RevitFamilyCategory.to_a
}.freeze
state.with_mapper_init_queue(init_parameters)
end
end
end
end
@@ -2,6 +2,7 @@
require_relative 'action' require_relative 'action'
require_relative '../mapper/category/revit_category' require_relative '../mapper/category/revit_category'
require_relative '../mapper/category/revit_family_category'
require_relative '../sketchup_model/reader/mapper_reader' require_relative '../sketchup_model/reader/mapper_reader'
require_relative '../sketchup_model/reader/speckle_entities_reader' require_relative '../sketchup_model/reader/speckle_entities_reader'
require_relative '../sketchup_model/dictionary/speckle_entity_dictionary_handler' require_relative '../sketchup_model/dictionary/speckle_entity_dictionary_handler'
@@ -35,6 +36,7 @@ module SpeckleConnector
end end
def get_mapping_info(state, selection) def get_mapping_info(state, selection)
source_exist = !state.speckle_state.speckle_mapper_state.mapper_source.nil?
selection = filter_out_levels(selection) selection = filter_out_levels(selection)
grouped_by_type = group_by_type(selection) grouped_by_type = group_by_type(selection)
@@ -45,10 +47,23 @@ module SpeckleConnector
# Return Direct Shape itself if multiple kinds of element are selected like Edge and Face. # Return Direct Shape itself if multiple kinds of element are selected like Edge and Face.
# OR single type is equal to only direct shape supports. # OR single type is equal to only direct shape supports.
return multiple_supported_selection_info(selection) if supported_entity_count > 1
# FIXME: Distinguish selection info according to selection elegantly!!!
if grouped_by_type.keys.first == Sketchup::ComponentInstance
return component_selection_info(selection, source_exist)
end
return group_selection_info(selection) if grouped_by_type.keys.first == Sketchup::Group
if supported_entity_count > 1 || if supported_entity_count > 1 ||
(supported_entity_count == 1 && (supported_entity_count == 1 &&
MAPPER_DIRECT_SHAPE_SUPPORTED_ENTITY_TYPES.include?(grouped_by_type.keys.first)) MAPPER_DIRECT_SHAPE_SUPPORTED_ENTITY_TYPES.include?(grouped_by_type.keys.first))
return direct_shape_selection_info(selection) if source_exist
return direct_shape_selection_info_with_source(selection, [])
else
return direct_shape_selection_info(selection, source_exist)
end
end end
# Only single type selections remained after this point. # Only single type selections remained after this point.
@@ -73,29 +88,54 @@ module SpeckleConnector
EMPTY_SELECTION = { EMPTY_SELECTION = {
selection: [], selection: [],
mappingMethods: [], mappingMethods: []
categories: []
}.freeze }.freeze
def direct_shape_selection_info(selection) def multiple_supported_selection_info(selection)
{ {
selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection), selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection),
mappingMethods: ['Direct Shape'], mappingMethods: ['Direct Shape']
categories: Mapper::Category::RevitCategory.to_a }.freeze
end
def component_selection_info(selection, source_exist)
if source_exist
{
selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection),
mappingMethods: ['Direct Shape', 'New Revit Family', 'Family Instance']
}.freeze
else
{
selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection),
mappingMethods: ['Direct Shape', 'New Revit Family']
}.freeze
end
end
def group_selection_info(selection)
{
selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection),
mappingMethods: ['Direct Shape']
}.freeze
end
def direct_shape_selection_info(selection, source_exist)
methods = ['Direct Shape', 'New Revit Family']
methods.append('Family Instance') if source_exist
{
selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection),
mappingMethods: methods
}.freeze }.freeze
end end
def direct_shape_selection_info_with_default(selection, methods) def direct_shape_selection_info_with_default(selection, methods)
{ {
selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection), selection: SketchupModel::Reader::MapperReader.entities_schema_details(selection),
mappingMethods: ['Direct Shape'] + methods, mappingMethods: ['Direct Shape'] + methods
categories: Mapper::Category::RevitCategory.to_a
}.freeze }.freeze
end end
def direct_shape_selection_info_with_source(state, filtered_selection, methods) def direct_shape_selection_info_with_source(filtered_selection, methods)
types = state.speckle_state.speckle_mapper_state.mapper_source.types
levels = state.speckle_state.speckle_mapper_state.mapper_source.levels
instances = @selection.grep(Sketchup::ComponentInstance) instances = @selection.grep(Sketchup::ComponentInstance)
selected_level = instances.find do |i| selected_level = instances.find do |i|
DICTIONARY::SpeckleEntityDictionaryHandler DICTIONARY::SpeckleEntityDictionaryHandler
@@ -109,8 +149,6 @@ module SpeckleConnector
selection: READER::MapperReader.entities_schema_details(filtered_selection), selection: READER::MapperReader.entities_schema_details(filtered_selection),
mappingMethods: ['Direct Shape'] + methods, mappingMethods: ['Direct Shape'] + methods,
categories: Mapper::Category::RevitCategory.to_a, categories: Mapper::Category::RevitCategory.to_a,
types: types,
levels: levels,
selectedLevelName: selected_level_name selectedLevelName: selected_level_name
}.freeze }.freeze
end end
@@ -119,13 +157,13 @@ module SpeckleConnector
def face_selection_info(state, faces) def face_selection_info(state, faces)
source_exist = !state.speckle_state.speckle_mapper_state.mapper_source.nil? source_exist = !state.speckle_state.speckle_mapper_state.mapper_source.nil?
grouped_by_verticality = faces.group_by { |face| face.normal.perpendicular?(VECTOR_Z) } grouped_by_verticality = faces.group_by { |face| face.normal.perpendicular?(VECTOR_Z) }
return direct_shape_selection_info(faces) if grouped_by_verticality.length == 2 return direct_shape_selection_info(faces, source_exist) if grouped_by_verticality.length == 2
if source_exist if source_exist
if grouped_by_verticality.keys.first if grouped_by_verticality.keys.first
direct_shape_selection_info_with_source(state, faces, ['Wall']) direct_shape_selection_info_with_source(faces, ['Wall'])
else else
direct_shape_selection_info_with_source(state, faces, ['Floor']) direct_shape_selection_info_with_source(faces, ['Floor'])
end end
else else
if grouped_by_verticality.keys.first if grouped_by_verticality.keys.first
@@ -141,7 +179,7 @@ module SpeckleConnector
if source_exist if source_exist
methods = ['Column', 'Beam', 'Pipe', 'Duct'] methods = ['Column', 'Beam', 'Pipe', 'Duct']
direct_shape_selection_info_with_source(state, edges, methods) direct_shape_selection_info_with_source(edges, methods)
else else
default_methods = ['Default Column', 'Default Beam', 'Default Pipe', 'Default Duct'] default_methods = ['Default Column', 'Default Beam', 'Default Pipe', 'Default Duct']
direct_shape_selection_info_with_default(edges, default_methods) direct_shape_selection_info_with_default(edges, default_methods)
@@ -1,6 +1,7 @@
# frozen_string_literal: true # frozen_string_literal: true
require_relative 'action' require_relative 'action'
require_relative '../constants/type_constants'
require_relative '../mapper/mapper_source' require_relative '../mapper/mapper_source'
require_relative '../speckle_objects/built_elements/revit/revit_element_type' require_relative '../speckle_objects/built_elements/revit/revit_element_type'
@@ -20,13 +21,15 @@ module SpeckleConnector
def update_state(state) def update_state(state)
levels = convert_levels(state, @base['@Levels']) levels = convert_levels(state, @base['@Levels'])
types = convert_types(@base['@Types']) types = convert_types(@base['@Types'])
family_instances = convert_family_instance_types(@base['@Types'])
mapper_source = Mapper::MapperSource.new(@stream_id, @commit_id, levels, types) mapper_source = Mapper::MapperSource.new(@stream_id, @commit_id, levels, types)
new_speckle_state = state.speckle_state.with_mapper_source(mapper_source) new_speckle_state = state.speckle_state.with_mapper_source(mapper_source)
state = state.with_speckle_state(new_speckle_state) state = state.with_speckle_state(new_speckle_state)
state.with_add_queue('mapperSourceUpdated', @stream_id, [ state.with_add_queue('mapperSourceUpdated', @stream_id, [
{ is_string: false, val: levels.to_json }, { is_string: false, val: levels.to_json },
{ is_string: false, val: types.to_json } { is_string: false, val: types.to_json },
{ is_string: false, val: family_instances.to_json }
]) ])
end end
@@ -43,6 +46,27 @@ module SpeckleConnector
end.compact.to_h end.compact.to_h
end end
def convert_family_instance_types(types)
family_instance_types = {}
types.each do |type, type_elements|
next if type_elements.nil? || !type_elements.is_a?(Array) || type == '__closure'
# skip type if there is no any revit symbol element type
symbol_element_types = type_elements.select do |t|
t['speckle_type'] == OBJECTS_BUILTELEMENTS_REVIT_REVITSYMBOLELEMENTTYPE &&
t['placementType'] == 'OneLevelBased'
end
next if symbol_element_types.empty?
elements = type_elements.map do |type_element|
SpeckleObjects::BuiltElements::Revit::RevitElementType.to_native(type_element)
end
elements = elements.group_by { |e| e[:family] }
family_instance_types.merge!(elements)
end
family_instance_types
end
def convert_levels(state, levels) def convert_levels(state, levels)
levels.collect do |level| levels.collect do |level|
SpeckleObjects::BuiltElements::Level.to_native(state, level, @stream_id) SpeckleObjects::BuiltElements::Level.to_native(state, level, @stream_id)
@@ -0,0 +1,27 @@
# frozen_string_literal: true
require_relative 'command'
require_relative '../states/initial_state'
require_relative '../ui/vue_view'
require_relative '../actions/initialize_speckle'
require_relative '../observers/factory'
module SpeckleConnector
module Commands
# Command to reset Speckle UI window location onto center of SketchUp window.
class ResetWindowLocation < Command
private
def _run
app = self.app
vue_view = app.ui_controller.user_interfaces[Ui::SPECKLE_UI_ID]
if vue_view
vue_view.dialog.reset_dialog_location
else
puts "Speckle UI didn't initialized!"
end
end
end
end
end
@@ -3,6 +3,7 @@
require_relative 'menu_command_handler' require_relative 'menu_command_handler'
require_relative 'action_command' require_relative 'action_command'
require_relative 'initialize_speckle' require_relative 'initialize_speckle'
require_relative 'reset_window_location'
require_relative '../actions/one_click_send' require_relative '../actions/one_click_send'
module SpeckleConnector module SpeckleConnector
@@ -10,6 +11,7 @@ module SpeckleConnector
# Speckle menu commands that adds them to Sketchup menu and toolbar. # Speckle menu commands that adds them to Sketchup menu and toolbar.
class SpeckleMenuCommands class SpeckleMenuCommands
CMD_INITIALIZE_SPECKLE = :initialize_speckle CMD_INITIALIZE_SPECKLE = :initialize_speckle
CMD_RESET_WINDOW_LOCATION_SPECKLE = :reset_window_location_speckle
CMD_SEND_TO_SPECKLE = :send_to_speckle CMD_SEND_TO_SPECKLE = :send_to_speckle
CMD_RECEIVE_FROM_SPECKLE = :receive_from_speckle CMD_RECEIVE_FROM_SPECKLE = :receive_from_speckle
@@ -26,6 +28,9 @@ module SpeckleConnector
commands.add_to_menu!(CMD_INITIALIZE_SPECKLE, speckle_menu) commands.add_to_menu!(CMD_INITIALIZE_SPECKLE, speckle_menu)
commands.add_to_toolbar!(CMD_INITIALIZE_SPECKLE, speckle_toolbar) commands.add_to_toolbar!(CMD_INITIALIZE_SPECKLE, speckle_toolbar)
commands[CMD_RESET_WINDOW_LOCATION_SPECKLE] = reset_window_location_command(app)
commands.add_to_menu!(CMD_RESET_WINDOW_LOCATION_SPECKLE, speckle_menu)
# commands[CMD_SEND_TO_SPECKLE] = send_command(app) # commands[CMD_SEND_TO_SPECKLE] = send_command(app)
# commands.add_to_menu!(CMD_SEND_TO_SPECKLE, speckle_menu) # commands.add_to_menu!(CMD_SEND_TO_SPECKLE, speckle_menu)
# commands.add_to_toolbar!(CMD_SEND_TO_SPECKLE, speckle_toolbar) # commands.add_to_toolbar!(CMD_SEND_TO_SPECKLE, speckle_toolbar)
@@ -42,6 +47,17 @@ module SpeckleConnector
cmd cmd
end end
def self.reset_window_location_command(app)
cmd = MenuCommandHandler.sketchup_command(
ResetWindowLocation.new(app), 'Reset Window Location'
)
cmd.tooltip = 'Bring Speckle window onto center of SketchUp window'
cmd.status_bar_text = 'Bring Speckle window onto center of SketchUp window'
cmd.small_icon = '../../img/s2logo.png'
cmd.large_icon = '../../img/s2logo.png'
cmd
end
def self.send_command(app) def self.send_command(app)
cmd = MenuCommandHandler.sketchup_command( cmd = MenuCommandHandler.sketchup_command(
ActionCommand.new(app, Actions::OneClickSend), 'Send to Speckle' ActionCommand.new(app, Actions::OneClickSend), 'Send to Speckle'
@@ -14,8 +14,10 @@ module SpeckleConnector
OBJECTS_BUILTELEMENTS_DEFAULT_WALL = 'Objects.BuiltElements.Wall' OBJECTS_BUILTELEMENTS_DEFAULT_WALL = 'Objects.BuiltElements.Wall'
OBJECTS_BUILTELEMENTS_REVIT_WALL = 'Objects.BuiltElements.Wall:Objects.BuiltElements.Revit.RevitWall' OBJECTS_BUILTELEMENTS_REVIT_WALL = 'Objects.BuiltElements.Wall:Objects.BuiltElements.Revit.RevitWall'
OBJECTS_BUILTELEMENTS_REVIT_DIRECTSHAPE = 'Objects.BuiltElements.Revit.DirectShape' OBJECTS_BUILTELEMENTS_REVIT_DIRECTSHAPE = 'Objects.BuiltElements.Revit.DirectShape'
OBJECTS_BUILTELEMENTS_REVIT_FAMILY_INSTANCE = 'Objects.BuiltElements.Revit.FamilyInstance'
OBJECTS_BUILTELEMENTS_REVIT_PARAMETER = 'Objects.BuiltElements.Revit.Parameter' OBJECTS_BUILTELEMENTS_REVIT_PARAMETER = 'Objects.BuiltElements.Revit.Parameter'
OBJECTS_BUILTELEMENTS_REVIT_REVITELEMENTTYPE = 'Objects.BuiltElements.Revit.RevitElementType' OBJECTS_BUILTELEMENTS_REVIT_REVITELEMENTTYPE = 'Objects.BuiltElements.Revit.RevitElementType'
OBJECTS_BUILTELEMENTS_REVIT_REVITSYMBOLELEMENTTYPE = 'Objects.BuiltElements.Revit.RevitElementType:Objects.BuiltElements.Revit.RevitSymbolElementType'
OBJECTS_GEOMETRY_LINE = 'Objects.Geometry.Line' OBJECTS_GEOMETRY_LINE = 'Objects.Geometry.Line'
OBJECTS_GEOMETRY_POLYLINE = 'Objects.Geometry.Polyline' OBJECTS_GEOMETRY_POLYLINE = 'Objects.Geometry.Polyline'
@@ -64,19 +64,14 @@ module SpeckleConnector
def convert(entity, preferences, speckle_state, parent = :base) def convert(entity, preferences, speckle_state, parent = :base)
convert = method(:convert) convert = method(:convert)
unless SketchupModel::Reader::MapperReader.mapped_with_schema?(entity) unless SketchupModel::Reader::MapperReader.mapped_with_schema?(entity) &&
!entity.is_a?(Sketchup::ComponentDefinition)
return from_native_to_speckle(entity, preferences, speckle_state, parent, &convert) return from_native_to_speckle(entity, preferences, speckle_state, parent, &convert)
end end
return speckle_state, nil return speckle_state, nil
end end
def from_mapped_to_speckle(entity, path, preferences)
direct_shape = SpeckleObjects::BuiltElements::Revit::DirectShape
.from_entity(speckle_state, entity, path, @units, preferences)
return [direct_shape, [entity]]
end
# rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/MethodLength
def from_native_to_speckle(entity, preferences, speckle_state, parent, &convert) def from_native_to_speckle(entity, preferences, speckle_state, parent, &convert)
if entity.is_a?(Sketchup::Edge) if entity.is_a?(Sketchup::Edge)
@@ -118,7 +118,8 @@ module SpeckleConnector
VibrationManagement: 106, VibrationManagement: 106,
Walls: 107, Walls: 107,
StructConnectionWelds: 108, StructConnectionWelds: 108,
Windows: 109 Windows: 109,
Railings: 110
}.freeze }.freeze
end end
# rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/MethodLength
@@ -0,0 +1,79 @@
# frozen_string_literal: true
module SpeckleConnector
module Mapper
module Category
# Revit categories for families.
class RevitFamilyCategory < Hash
class << self
# rubocop:disable Metrics/MethodLength
def dictionary
{
AudioVisualDevices: 9,
CableTrayFitting: 16,
Casework: 19,
Columns: 21,
CommunicationDevices: 22,
ConduitFitting: 23,
DataDevices: 30,
Doors: 32,
DuctAccessory: 33,
ElectricalEquipment: 38,
ElectricalFixtures: 39,
Entourage: 40,
FireAlarmDevices: 42,
FireProtection: 43,
FoodServiceEquipment: 45,
Furniture: 46,
FurnitureSystems: 47,
GenericAnnotation: 48,
GenericModel: 49,
Hardscape: 51,
LightingDevices: 52,
LightingFixtures: 53,
Lines: 54,
Mass: 55,
MechanicalEquipment: 56,
MedicalEquipment: 57,
NurseCallDevices: 58,
Parking: 59,
PipeAccessory: 68,
PipeFitting: 69,
Planting: 74,
PlumbingFixtures: 76,
Roads: 80,
SecurityDevices: 82,
Signage: 84,
Site: 85,
SpecialityEquipment: 86,
Sprinklers: 87,
StructuralFramingSystem: 89,
StructuralColumns: 90,
StructConnections: 91,
StructuralFoundation: 93,
StructuralFraming: 94,
StructuralStiffener: 97,
TemporaryStructure: 100,
VerticalCirculation: 103,
Windows: 109,
Railings: 110
}.freeze
end
# rubocop:enable Metrics/MethodLength
def reverse_dictionary
dictionary.collect { |k, v| [v, k] }.to_h
end
def to_a
dictionary.collect { |k, v| { key: k, value: v } }.to_a
end
def reverse_to_a
dictionary.collect { |k, v| { key: v, value: k } }.to_a
end
end
end
end
end
end
+2 -1
View File
@@ -4,6 +4,7 @@ require_relative '../speckle_objects/built_elements/revit/revit_floor'
require_relative '../speckle_objects/built_elements/revit/revit_wall' require_relative '../speckle_objects/built_elements/revit/revit_wall'
require_relative '../speckle_objects/built_elements/default_floor' require_relative '../speckle_objects/built_elements/default_floor'
require_relative '../speckle_objects/built_elements/default_wall' require_relative '../speckle_objects/built_elements/default_wall'
require_relative '../speckle_objects/other/mapped_block_wrapper'
require_relative '../sketchup_model/query/entity' require_relative '../sketchup_model/query/entity'
require_relative '../sketchup_model/reader/mapper_reader' require_relative '../sketchup_model/reader/mapper_reader'
require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler' require_relative '../sketchup_model/dictionary/speckle_schema_dictionary_handler'
@@ -31,7 +32,7 @@ module SpeckleConnector
mapped_selection mapped_selection
end end
def self.to_speckle(speckle_state, entity, units, global_transformation: nil) def self.to_speckle(speckle_state, entity, units, model_preferences, global_transformation: nil, path: nil)
speckle_schema = SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler.speckle_schema_to_speckle(entity) speckle_schema = SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler.speckle_schema_to_speckle(entity)
return speckle_schema if speckle_schema.nil? return speckle_schema if speckle_schema.nil?
@@ -89,7 +89,7 @@ module SpeckleConnector
mapped_selection mapped_selection
end end
def self.from_entity(speckle_state, entity, path, units, preferences) def self.from_entity(speckle_state, entity, path, units, model_preferences)
schema = DICTIONARY::SpeckleSchemaDictionaryHandler.attribute_dictionary(entity) schema = DICTIONARY::SpeckleSchemaDictionaryHandler.attribute_dictionary(entity)
if schema.nil? && entity.respond_to?(:definition) if schema.nil? && entity.respond_to?(:definition)
schema = DICTIONARY::SpeckleSchemaDictionaryHandler.attribute_dictionary(entity.definition) schema = DICTIONARY::SpeckleSchemaDictionaryHandler.attribute_dictionary(entity.definition)
@@ -103,7 +103,7 @@ module SpeckleConnector
entity.definition.entities, [Sketchup::Face], path.append(entity) entity.definition.entities, [Sketchup::Face], path.append(entity)
) )
end end
base_geometries = group_faces_under_mesh_by_material(speckle_state, entities_with_path, units, preferences) base_geometries = group_faces_under_mesh_by_material(speckle_state, entities_with_path, units, model_preferences)
DirectShape.new( DirectShape.new(
name: schema[:name], category: schema[:category], units: units, name: schema[:name], category: schema[:category], units: units,
base_geometries: base_geometries, application_id: entity.persistent_id base_geometries: base_geometries, application_id: entity.persistent_id
@@ -111,13 +111,13 @@ module SpeckleConnector
end end
# rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/MethodLength
def self.group_faces_under_mesh_by_material(speckle_state, faces_with_path, units, preferences) def self.group_faces_under_mesh_by_material(speckle_state, faces_with_path, units, model_preferences)
mesh_groups = {} mesh_groups = {}
faces_with_path.each do |face_with_path| faces_with_path.each do |face_with_path|
face = face_with_path[0] face = face_with_path[0]
entity_path = face_with_path[1..-1] entity_path = face_with_path[1..-1]
parent_material = QUERY::Entity.parent_material(entity_path) parent_material = QUERY::Entity.parent_material(entity_path)
mesh_group_id = Geometry::Mesh.get_mesh_group_id(face, preferences[:model], parent_material) mesh_group_id = Geometry::Mesh.get_mesh_group_id(face, model_preferences, parent_material)
if mesh_groups.key?(mesh_group_id) if mesh_groups.key?(mesh_group_id)
mesh_group = mesh_groups[mesh_group_id] mesh_group = mesh_groups[mesh_group_id]
@@ -126,7 +126,7 @@ module SpeckleConnector
else else
mesh = Geometry::Mesh.from_face( mesh = Geometry::Mesh.from_face(
speckle_state: speckle_state, speckle_state: speckle_state,
face: face, units: units, model_preferences: preferences[:model], face: face, units: units, model_preferences: model_preferences,
global_transform: QUERY::Entity.global_transformation(face, entity_path), global_transform: QUERY::Entity.global_transformation(face, entity_path),
parent_material: parent_material parent_material: parent_material
) )
@@ -0,0 +1,37 @@
# frozen_string_literal: true
require_relative '../../base'
require_relative '../../../constants/type_constants'
module SpeckleConnector
module SpeckleObjects
module BuiltElements
module Revit
# Family instance for Revit mappings.
class FamilyInstance < Base
SPECKLE_TYPE = OBJECTS_BUILTELEMENTS_REVIT_FAMILY_INSTANCE
READER = SketchupModel::Reader
QUERY = SketchupModel::Query
DICTIONARY = SketchupModel::Dictionary
# rubocop:disable Metrics/ParameterLists
def initialize(family:, type:, level:, units:, base_point:, rotation:, application_id: nil)
super(
speckle_type: SPECKLE_TYPE,
total_children_count: 0,
application_id: application_id,
id: nil
)
self[:family] = family
self[:type] = type
self[:level] = level
self[:units] = units
self[:basePoint] = base_point
self[:rotation] = rotation
end
# rubocop:enable Metrics/ParameterLists
end
end
end
end
end
@@ -154,7 +154,7 @@ module SpeckleConnector
has_any_soften_edge = face.edges.any?(&:soft?) has_any_soften_edge = face.edges.any?(&:soft?)
att = dictionaries.any? ? { is_soften: has_any_soften_edge, dictionaries: dictionaries } att = dictionaries.any? ? { is_soften: has_any_soften_edge, dictionaries: dictionaries }
: { is_soften: has_any_soften_edge } : { is_soften: has_any_soften_edge }
speckle_schema = Mapper.to_speckle(speckle_state, face, units, global_transformation: global_transform) speckle_schema = Mapper.to_speckle(speckle_state, face, units, model_preferences, global_transformation: global_transform)
material = face.material || face.back_material || parent_material material = face.material || face.back_material || parent_material
speckle_mesh = Mesh.new( speckle_mesh = Mesh.new(
units: units, units: units,
@@ -5,6 +5,8 @@ require_relative 'transform'
require_relative 'block_definition' require_relative 'block_definition'
require_relative '../base' require_relative '../base'
require_relative '../geometry/bounding_box' require_relative '../geometry/bounding_box'
require_relative '../other/mapped_block_wrapper'
require_relative '../built_elements/revit/family_instance'
require_relative '../../sketchup_model/dictionary/base_dictionary_handler' require_relative '../../sketchup_model/dictionary/base_dictionary_handler'
require_relative '../../sketchup_model/dictionary/speckle_schema_dictionary_handler' require_relative '../../sketchup_model/dictionary/speckle_schema_dictionary_handler'
require_relative '../../sketchup_model/query/layer' require_relative '../../sketchup_model/query/layer'
@@ -40,7 +42,7 @@ module SpeckleConnector
self[:renderMaterial] = render_material self[:renderMaterial] = render_material
self[:transform] = transform self[:transform] = transform
self[:sketchup_attributes] = sketchup_attributes if sketchup_attributes.any? self[:sketchup_attributes] = sketchup_attributes if sketchup_attributes.any?
self[:SpeckleSchema] = speckle_schema if speckle_schema.any? self[:speckle_schema] = speckle_schema if speckle_schema.any?
# FIXME: Since blockDefinition sends with @ as detached, block basePlane renders on viewer. # FIXME: Since blockDefinition sends with @ as detached, block basePlane renders on viewer.
self['@@definition'] = block_definition self['@@definition'] = block_definition
end end
@@ -72,7 +74,7 @@ module SpeckleConnector
# @param component_instance [Sketchup::ComponentInstance] component instance to convert Speckle BlockInstance # @param component_instance [Sketchup::ComponentInstance] component instance to convert Speckle BlockInstance
# rubocop:disable Metrics/MethodLength # rubocop:disable Metrics/MethodLength
def self.from_component_instance(component_instance, units, preferences, speckle_state, &convert) def self.from_component_instance(component_instance, units, preferences, speckle_state, path: nil, &convert)
new_speckle_state, block_definition = convert.call( new_speckle_state, block_definition = convert.call(
component_instance.definition, component_instance.definition,
preferences, preferences,
@@ -82,11 +84,20 @@ module SpeckleConnector
speckle_state = new_speckle_state speckle_state = new_speckle_state
dictionaries = SketchupModel::Dictionary::BaseDictionaryHandler dictionaries = SketchupModel::Dictionary::BaseDictionaryHandler
.attribute_dictionaries_to_speckle(component_instance, preferences[:model]) .attribute_dictionaries_to_speckle(component_instance, preferences)
att = dictionaries.any? ? { dictionaries: dictionaries } : {} att = dictionaries.any? ? { dictionaries: dictionaries } : {}
speckle_schema = SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler speckle_schema = SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler
.speckle_schema_to_speckle(component_instance) .speckle_schema_to_speckle(component_instance)
if speckle_schema.empty?
speckle_schema = SketchupModel::Dictionary::SpeckleSchemaDictionaryHandler
.speckle_schema_to_speckle(component_instance.definition)
end
# transform into global if any path provided
transformation = component_instance.transformation
transformation = SketchupModel::Query::Entity.global_transformation(component_instance, path) if path
block_instance = BlockInstance.new( block_instance = BlockInstance.new(
units: units, units: units,
is_sketchup_group: false, is_sketchup_group: false,
@@ -96,13 +107,45 @@ module SpeckleConnector
else else
RenderMaterial.from_material(component_instance.material) RenderMaterial.from_material(component_instance.material)
end, end,
transform: Other::Transform.from_transformation(component_instance.transformation, units), transform: Other::Transform.from_transformation(transformation, units),
block_definition: block_definition, block_definition: block_definition,
layer: SketchupModel::Query::Layer.entity_path(component_instance), layer: SketchupModel::Query::Layer.entity_path(component_instance),
sketchup_attributes: att, sketchup_attributes: att,
speckle_schema: speckle_schema, speckle_schema: speckle_schema,
application_id: component_instance.persistent_id.to_s application_id: component_instance.persistent_id.to_s
) )
if speckle_schema
case speckle_schema['method']
when 'New Revit Family'
# duplicate already converted one to attach without speckle schema into mapped block wrapper
copy_block_instance = block_instance.clone(freeze: true)
block_instance['@SpeckleSchema'] = SpeckleObjects::Other::MappedBlockWrapper.new(
category: speckle_schema['category'],
units: units,
instance: copy_block_instance,
application_id: component_instance.persistent_id.to_s
)
when 'Family Instance'
level = speckle_state.speckle_mapper_state.mapper_source
.levels.find { |l| l[:name] == speckle_schema['level'] }
family = speckle_schema['family']
type = speckle_schema['family_type']
block_instance['@SpeckleSchema'] = SpeckleObjects::BuiltElements::Revit::FamilyInstance.new(
family: family,
type: type,
level: level,
units: units,
base_point: SpeckleObjects::Geometry::Point.from_vertex(
component_instance.definition.insertion_point.transform(transformation),
units
),
rotation: calculate_rotation(transformation.to_a),
application_id: component_instance.persistent_id.to_s
)
end
end
return speckle_state, block_instance return speckle_state, block_instance
end end
# rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/MethodLength
@@ -228,6 +271,26 @@ module SpeckleConnector
instance_transform = instance.transformation instance_transform = instance.transformation
instance.transform!(instance_transform * transform.inverse * instance_transform.inverse) instance.transform!(instance_transform * transform.inverse * instance_transform.inverse)
end end
def self.calculate_rotation(matrix)
# Ensure the matrix is a flat array with 16 elements
unless matrix.is_a?(Array) && matrix.size == 16
raise ArgumentError, 'Matrix must be an array with 16 elements'
end
# Extract the elements of the 2x2 rotation sub-matrix
cos_theta = matrix[0] # First column, first row
sin_theta = matrix[1] # Second column, first row
# Calculate the rotation angle in radians
theta = Math.atan2(sin_theta, cos_theta)
# Ensure the angle is between -π and π
theta -= 2 * Math::PI while theta > Math::PI
theta += 2 * Math::PI while theta < -Math::PI
theta
end
end end
end end
end end
@@ -0,0 +1,25 @@
# frozen_string_literal: true
require_relative '../base'
module SpeckleConnector
module SpeckleObjects
module Other
# MappedBlockWrapper object definition for Speckle.
class MappedBlockWrapper < Base
SPECKLE_TYPE = 'Objects.Other.MappedBlockWrapper'
def initialize(category:, units:, instance:, application_id: nil)
super(
speckle_type: SPECKLE_TYPE,
total_children_count: 0,
application_id: application_id,
id: nil
)
self[:category] = category
self[:units] = units
self[:instance] = instance
end
end
end
end
end
@@ -27,6 +27,27 @@ module SpeckleConnector
self[:active_layer] = active_layer self[:active_layer] = active_layer
end end
def self.to_native(state, model_collection, layer, entities, &convert_to_native)
elements = model_collection['elements']
views = model_collection['@Views']
if views
views.each do |view|
new_state, _converted_entities = convert_to_native.call(state, view, layer, entities)
state = new_state
end
end
elements.each do |element|
new_state, _converted_entities = convert_to_native.call(state, element, layer, entities)
state = new_state
end
active_layer = model_collection['active_layer']
state.sketchup_state.sketchup_model.active_layer = active_layer unless active_layer.nil?
return state, []
end
def self.from_sketchup_model(sketchup_model, speckle_state, units, preferences, &convert) def self.from_sketchup_model(sketchup_model, speckle_state, units, preferences, &convert)
model_collection = ModelCollection.new( model_collection = ModelCollection.new(
name: 'Sketchup Model', active_layer: sketchup_model.active_layer.display_name, name: 'Sketchup Model', active_layer: sketchup_model.active_layer.display_name,
@@ -60,36 +81,17 @@ module SpeckleConnector
def self.collect_mapped_entities(speckle_state, sketchup_model, units, preferences, &convert) def self.collect_mapped_entities(speckle_state, sketchup_model, units, preferences, &convert)
mapped_entities = Mapper.mapped_entities_on_selection(sketchup_model) mapped_entities = Mapper.mapped_entities_on_selection(sketchup_model)
mapped_entities.collect do |entity_with_path| mapped_entities.collect do |entity_with_path|
convert_mapped_entity(speckle_state, entity_with_path, preferences, units) convert_mapped_entity(speckle_state, entity_with_path, preferences, units, &convert)
end end
end end
def self.to_native(state, model_collection, layer, entities, &convert_to_native) def self.convert_mapped_entity(speckle_state, entity_with_path, preferences, units, &convert)
elements = model_collection['elements']
views = model_collection['@Views']
if views
views.each do |view|
new_state, _converted_entities = convert_to_native.call(state, view, layer, entities)
state = new_state
end
end
elements.each do |element|
new_state, _converted_entities = convert_to_native.call(state, element, layer, entities)
state = new_state
end
active_layer = model_collection['active_layer']
state.sketchup_state.sketchup_model.active_layer = active_layer unless active_layer.nil?
return state, []
end
def self.convert_mapped_entity(speckle_state, entity_with_path, preferences, units)
entity = entity_with_path[0] entity = entity_with_path[0]
path = entity_with_path[1..-1] path = entity_with_path[1..-1]
method = SPECKLE_SCHEMA_DICTIONARY_HANDLER.get_attribute(entity, 'method') method = SPECKLE_SCHEMA_DICTIONARY_HANDLER.get_attribute(entity, 'method')
if entity.is_a?(Sketchup::ComponentInstance) && method.nil?
method = SPECKLE_SCHEMA_DICTIONARY_HANDLER.get_attribute(entity.definition, 'method')
end
if !method.nil? && (method.include?('Floor') || method.include?('Wall')) && entity.is_a?(Sketchup::Face) if !method.nil? && (method.include?('Floor') || method.include?('Wall')) && entity.is_a?(Sketchup::Face)
global_transformation = QUERY::Entity.global_transformation(entity, path) global_transformation = QUERY::Entity.global_transformation(entity, path)
@@ -99,8 +101,19 @@ module SpeckleConnector
return [floor, [entity]] return [floor, [entity]]
end end
direct_shape = DIRECT_SHAPE.from_entity(speckle_state, entity, path, units, preferences) if method == 'Direct Shape'
return [direct_shape, [entity]] direct_shape = DIRECT_SHAPE.from_entity(speckle_state, entity, path, units, preferences)
return [direct_shape, [entity]]
end
if ['New Revit Family', 'Family Instance'].include?(method)
_speckle_state, block_instance = SpeckleObjects::Other::BlockInstance.from_component_instance(
entity, units, preferences, speckle_state, path: path, &convert
)
return [block_instance, [entity]]
end
nil
end end
end end
end end
@@ -75,6 +75,12 @@ module SpeckleConnector
with(:@message_queue => new_queue) with(:@message_queue => new_queue)
end end
def with_mapper_init_queue(init_parameters)
new_queue = message_queue.merge({ "mapperInitialized":
"mapperInitialized(#{JSON.generate(init_parameters)})" })
with(:@message_queue => new_queue)
end
def with_mapper_deselection_queue def with_mapper_deselection_queue
new_queue = message_queue.merge({ "entitiesDeselected": 'entitiesDeselected()' }) new_queue = message_queue.merge({ "entitiesDeselected": 'entitiesDeselected()' })
with(:@message_queue => new_queue) with(:@message_queue => new_queue)
+5
View File
@@ -50,6 +50,11 @@ module SpeckleConnector
with(:@speckle_state => new_speckle_state) with(:@speckle_state => new_speckle_state)
end end
def with_mapper_init_queue(init_parameters)
new_speckle_state = speckle_state.with_mapper_init_queue(init_parameters)
with(:@speckle_state => new_speckle_state)
end
def with_empty_stream_queue def with_empty_stream_queue
new_speckle_state = speckle_state.with(:@stream_queue => {}) new_speckle_state = speckle_state.with(:@stream_queue => {})
with(:@speckle_state => new_speckle_state) with(:@speckle_state => new_speckle_state)
+4
View File
@@ -57,6 +57,10 @@ module SpeckleConnector
html_dialog.execute_script(data) html_dialog.execute_script(data)
end end
def reset_dialog_location
html_dialog.center
end
private private
# @return [UI::HtmlDialog] the Sketchup interface to dialog # @return [UI::HtmlDialog] the Sketchup interface to dialog
+3 -1
View File
@@ -18,6 +18,7 @@ require_relative '../commands/apply_mappings'
require_relative '../commands/clear_mappings' require_relative '../commands/clear_mappings'
require_relative '../commands/mapper_source_updated' require_relative '../commands/mapper_source_updated'
require_relative '../actions/mapper_initialized'
require_relative '../actions/reload_accounts' require_relative '../actions/reload_accounts'
require_relative '../actions/load_saved_streams' require_relative '../actions/load_saved_streams'
require_relative '../actions/init_local_accounts' require_relative '../actions/init_local_accounts'
@@ -93,7 +94,8 @@ module SpeckleConnector
select_mappings_from_table: Commands::ActionCommand.new(@app, Actions::SelectMappingsFromTable), select_mappings_from_table: Commands::ActionCommand.new(@app, Actions::SelectMappingsFromTable),
show_all_entities: Commands::ActionCommand.new(@app, Actions::ShowAllEntities), show_all_entities: Commands::ActionCommand.new(@app, Actions::ShowAllEntities),
mapper_source_updated: Commands::MapperSourceUpdated.new(@app), mapper_source_updated: Commands::MapperSourceUpdated.new(@app),
clear_mapper_source: Commands::ActionCommand.new(@app, Actions::ClearMapperSource) clear_mapper_source: Commands::ActionCommand.new(@app, Actions::ClearMapperSource),
mapper_initialized: Commands::ActionCommand.new(@app, Actions::MapperInitialized)
}.freeze }.freeze
end end
# rubocop:enable Metrics/MethodLength # rubocop:enable Metrics/MethodLength
+30 -8
View File
@@ -48,21 +48,25 @@
<v-img v-if="user.avatar" :src="user.avatar" /> <v-img v-if="user.avatar" :src="user.avatar" />
<v-img v-else :src="`https://robohash.org/` + user.id + `.png?size=40x40`" /> <v-img v-else :src="`https://robohash.org/` + user.id + `.png?size=40x40`" />
</v-avatar> </v-avatar>
<div>
<b>{{ user.name }}</b>
</div>
<div class="caption"> <div class="caption">
{{ user.company }} {{ user.company }}
<br /> <br />
{{ user.bio ? 'Bio: ' + user.bio : '' }} {{ user.bio ? 'Bio: ' + user.bio : '' }}
</div> </div>
<div>
<b>{{ user.name }}</b>
<br />
<b>{{ user.email }}</b>
</div>
<div class="caption">
<b>{{ serverInfo.canonicalUrl }}</b>
</div>
</v-card-text> </v-card-text>
<v-card-text v-if="accounts()"> <v-card-text v-if="accounts()">
<v-divider class="my-3" /> <v-divider class="my-3" />
<div v-for="account in accounts()" :key="account.id"> <div v-for="account in accounts()" :key="account.id">
<v-btn <v-btn
v-if="account.userInfo.id != user.id" v-if="account.id != activeAccount().id"
rounded rounded
large large
class="my-1 elevation-0" class="my-1 elevation-0"
@@ -101,12 +105,12 @@
</v-container> </v-container>
<create-stream-dialog <create-stream-dialog
v-if="accounts().length !== 0" v-if="accounts().length !== 0"
:is-f-e2="preferences && preferences.user && preferences.user.fe2" :is-f-e2-terms="preferences && preferences.user && preferences.user.fe2"
:account-id="activeAccount().userInfo.id" :account-id="activeAccount().userInfo.id"
:server-url="activeAccount().serverInfo.url" :server-url="activeAccount().serverInfo.url"
/> />
<v-container v-if="accounts().length !== 0" fluid> <v-container v-if="accounts().length !== 0" fluid>
<router-view :stream-search-query="streamSearchQuery" /> <router-view :stream-search-query="streamSearchQuery"/>
</v-container> </v-container>
<v-container v-else> <v-container v-else>
<login/> <login/>
@@ -128,6 +132,7 @@
/*global sketchup*/ /*global sketchup*/
import { bus } from './main' import { bus } from './main'
import userQuery from './graphql/user.gql' import userQuery from './graphql/user.gql'
import serverInfoQuery from './graphql/serverInfo.gql'
import { onLogin } from './vue-apollo' import { onLogin } from './vue-apollo'
import Login from "@/views/Login"; import Login from "@/views/Login";
@@ -147,7 +152,12 @@ global.loadAccounts = function (accounts) {
let uuid = localStorage.getItem('uuid') let uuid = localStorage.getItem('uuid')
if (accounts.length !== 0){ if (accounts.length !== 0){
if (uuid) { if (uuid) {
global.setSelectedAccount(accounts.find((acct) => acct['userInfo']['id'] === uuid)) var account = accounts.find((acct) => acct['userInfo']['id'] === uuid)
if (account){
global.setSelectedAccount(account)
}else{
global.setSelectedAccount(accounts.find((acct) => acct['isDefault']))
}
} else { } else {
global.setSelectedAccount(accounts.find((acct) => acct['isDefault'])) global.setSelectedAccount(accounts.find((acct) => acct['isDefault']))
} }
@@ -159,6 +169,7 @@ global.setSelectedAccount = function (account) {
localStorage.setItem('serverUrl', account['serverInfo']['url']) localStorage.setItem('serverUrl', account['serverInfo']['url'])
localStorage.setItem('SpeckleSketchup.AuthToken', account['token']) localStorage.setItem('SpeckleSketchup.AuthToken', account['token'])
localStorage.setItem('uuid', account['userInfo']['id']) localStorage.setItem('uuid', account['userInfo']['id'])
localStorage.setItem('frontend2', account['serverInfo']['frontend2'])
bus.$emit('selected-account-reloaded') bus.$emit('selected-account-reloaded')
} }
@@ -199,6 +210,9 @@ export default {
apollo: { apollo: {
user: { user: {
query: userQuery query: userQuery
},
serverInfo: {
query: serverInfoQuery
} }
}, },
mounted() { mounted() {
@@ -241,6 +255,14 @@ export default {
switchAccount(account) { switchAccount(account) {
this.$mixpanel.track('Connector Action', { name: 'Account Select' }) this.$mixpanel.track('Connector Action', { name: 'Account Select' })
global.setSelectedAccount(account) global.setSelectedAccount(account)
// Force pushes to reload page to create ApolloClient from scratch
// setTimeout(() => {
// // timeout to wait a bit for potential sketchup.exec in the mean time calls
// location.reload()
// }, 200);
this.$apollo.queries.user.refetch()
this.$apollo.queries.serverInfo.refetch()
}, },
requestRefresh() { requestRefresh() {
sketchup.exec({name: 'reload_accounts', data: {}}) sketchup.exec({name: 'reload_accounts', data: {}})
+85 -46
View File
@@ -171,7 +171,7 @@
class="pt-0" class="pt-0"
label="Family" label="Family"
:disabled="!entitySelected" :disabled="!entitySelected"
:items="families" :items="inputFamilies"
density="compact" density="compact"
clearable clearable
@change="onSelectedFamilyChange" @change="onSelectedFamilyChange"
@@ -208,7 +208,7 @@
v-model="selectedCategory" v-model="selectedCategory"
class="pt-0" class="pt-0"
label="Category" label="Category"
:items="availableCategories" :items="selectedMethod === 'New Revit Family' ? familyCategories : categories"
item-value="value" item-value="value"
item-text="key" item-text="key"
:disabled="!entitySelected" :disabled="!entitySelected"
@@ -282,14 +282,19 @@ import {groupBy} from "@/utils/groupBy";
import MappingSource from "@/components/MapperSource.vue"; import MappingSource from "@/components/MapperSource.vue";
import {sourceMap} from "@vue/cli-service/lib/config/terserOptions"; import {sourceMap} from "@vue/cli-service/lib/config/terserOptions";
global.mapperSourceUpdated = function (streamId, levels, types) { global.mapperSourceUpdated = function (streamId, levels, types, familyInstances) {
console.log(`Mapper source updated for ${streamId}.`) console.log(`Mapper source updated for ${streamId}.`)
bus.$emit('mapper-source-updated', JSON.stringify(levels), JSON.stringify(types), JSON.stringify(familyInstances))
} }
global.entitySelected = function (selectionParameters) { global.entitySelected = function (selectionParameters) {
bus.$emit('entities-selected', JSON.stringify(selectionParameters)) bus.$emit('entities-selected', JSON.stringify(selectionParameters))
} }
global.mapperInitialized = function (initParameters) {
bus.$emit('mapper-initialized', JSON.stringify(initParameters))
}
global.entitiesDeselected = function () { global.entitiesDeselected = function () {
bus.$emit('entities-deselected') bus.$emit('entities-deselected')
} }
@@ -343,7 +348,7 @@ export default {
entitySelected: false, entitySelected: false,
selectedEntityCount: 0, selectedEntityCount: 0,
selectedEntities: [], selectedEntities: [],
allFamilyTypes: {},
familyTypes: [], familyTypes: [],
lastSelectedEntity: null, lastSelectedEntity: null,
@@ -355,10 +360,17 @@ export default {
name: "", name: "",
availableMethods: [], availableMethods: [],
availableCategories: [], categories: [],
families: [], familyCategories: [],
allTypes: {},
inputCategories: [],
inputFamilies: [],
inputFamilyTypes: {},
// comes from source
types: {},
levels: [], levels: [],
familyInstanceTypes: {}, // comes from source as filtered
mappedEntityCount: 0, mappedEntityCount: 0,
mappedEntities: [], mappedEntities: [],
@@ -531,6 +543,14 @@ export default {
this.categorySelectionActive = true this.categorySelectionActive = true
this.nameSelectionActive = true this.nameSelectionActive = true
} }
else if (this.selectedMethod === 'New Revit Family'){
this.categorySelectionActive = true
}
else if (this.selectedMethod === 'Family Instance'){
this.typeSelectionActive = true
this.familySelectionActive = true
this.levelSelectionActive = true
}
else if (nativeDefaultMethods.includes(this.selectedMethod)){ else if (nativeDefaultMethods.includes(this.selectedMethod)){
this.typeSelectionActive = false this.typeSelectionActive = false
this.familySelectionActive = false this.familySelectionActive = false
@@ -545,52 +565,63 @@ export default {
} }
}, },
getTypesFromSelectedFamily(){ getTypesFromSelectedFamily(){
this.familyTypes = this.allFamilyTypes[this.selectedFamily] // There is no sense to set selected family type if method is not selected
this.selectedFamilyType = this.familyTypes[0].type if (this.selectedMethod){
if (this.selectedFamily === null || this.selectedFamily === undefined){ if (this.sourceState !== 'Not Set'){
this.selectedFamily = this.families[0] this.familyTypes = this.inputFamilyTypes[this.selectedFamily]
} this.selectedFamilyType = this.familyTypes[0].type
if (this.familyTypes === null ||this.familyTypes === undefined){ if (this.selectedFamilyType === null || this.selectedFamilyType === undefined){
this.familyTypes = this.allFamilyTypes[this.selectedFamily] this.selectedFamilyType = this.familyTypes[0].type
} }
if (this.selectedFamilyType === null || this.selectedFamilyType === undefined){ }
this.selectedFamilyType = this.familyTypes[0].type if (this.selectedFamily === null || this.selectedFamily === undefined){
this.selectedFamily = this.inputFamilies[0]
}
if (this.familyTypes === null ||this.familyTypes === undefined){
this.familyTypes = this.inputFamilyTypes[this.selectedFamily]
}
} }
}, },
getFamiliesFromSelectedMethod(){ getFamiliesFromSelectedMethod(){
switch (this.selectedMethod) { switch (this.selectedMethod) {
case 'Floor': case 'Floor':
this.families = Object.keys(this.allTypes['Floors']); this.inputFamilies = Object.keys(this.types['Floors']);
this.allFamilyTypes = this.allTypes['Floors'] this.inputFamilyTypes = this.types['Floors']
break; break;
case 'Wall': case 'Wall':
this.families = Object.keys(this.allTypes['Walls']); this.inputFamilies = Object.keys(this.types['Walls']);
this.allFamilyTypes = this.allTypes['Walls'] this.inputFamilyTypes = this.types['Walls']
break; break;
case 'Column': case 'Column':
this.families = Object.keys(this.allTypes['Columns']); this.inputFamilies = Object.keys(this.types['Columns']);
this.allFamilyTypes = this.allTypes['Columns'] this.inputFamilyTypes = this.types['Columns']
break; break;
case 'Beam': case 'Beam':
this.families = Object.keys(this.allTypes['Beams']); this.inputFamilies = Object.keys(this.types['Beams']);
this.allFamilyTypes = this.allTypes['Beams'] this.inputFamilyTypes = this.types['Beams']
break; break;
case 'Pipe': case 'Pipe':
this.families = Object.keys(this.allTypes['Piping System']); this.inputFamilies = Object.keys(this.types['Piping System']);
this.allFamilyTypes = this.allTypes['Piping System'] this.inputFamilyTypes = this.types['Piping System']
break; break;
case 'Duct': case 'Duct':
this.families = Object.keys(this.allTypes['Duct System']); this.inputFamilies = Object.keys(this.types['Duct System']);
this.allFamilyTypes = this.allTypes['Duct System'] this.inputFamilyTypes = this.types['Duct System']
break;
case 'Family Instance':
this.inputFamilies = Object.keys(this.familyInstanceTypes);
this.inputFamilyTypes = this.familyInstanceTypes
break; break;
default: default:
break; break;
} }
if (this.selectedFamily === null || this.selectedFamily === undefined){ if (this.selectedMethod){
this.selectedFamily = this.families[0] if (this.selectedFamily === null || this.selectedFamily === undefined){
} this.selectedFamily = this.inputFamilies[0]
if (this.selectedLevel === null || this.selectedLevel === undefined){ }
this.selectedLevel = this.levels[0].name if (this.selectedLevel === null || this.selectedLevel === undefined){
this.selectedLevel = this.levels[0].name
}
} }
}, },
hideOptionalMappingInputs(){ hideOptionalMappingInputs(){
@@ -608,7 +639,6 @@ export default {
}, },
clearInputs(){ clearInputs(){
this.availableMethods = [] this.availableMethods = []
this.availableCategories = []
this.selectedEntities = [] this.selectedEntities = []
this.selectionTableData = [] this.selectionTableData = []
this.selectedEntityCount = 0 this.selectedEntityCount = 0
@@ -620,8 +650,6 @@ export default {
this.selectedLevel = null this.selectedLevel = null
this.selectedFamily = null this.selectedFamily = null
this.selectedFamilyType = null this.selectedFamilyType = null
this.allTypes = null
this.familyTypes = null
}, },
getSelectionTableData(){ getSelectionTableData(){
let groupByClass = groupBy('entityType') let groupByClass = groupBy('entityType')
@@ -683,6 +711,12 @@ export default {
} }
this.selectedMethod = this.lastSelectedEntity['definition']['schema']['method'] this.selectedMethod = this.lastSelectedEntity['definition']['schema']['method']
this.selectedCategory = this.lastSelectedEntity['definition']['schema']['category'] this.selectedCategory = this.lastSelectedEntity['definition']['schema']['category']
this.selectedFamily = this.lastSelectedEntity['definition']['schema']['family']
this.getFamiliesFromSelectedMethod()
this.getTypesFromSelectedFamily()
this.selectedFamilyType = this.lastSelectedEntity['definition']['schema']['family_type']
this.selectedLevel = this.lastSelectedEntity['definition']['schema']['level']
this.updateMappingInputs()
} }
} }
// Otherwise set entity mappings. // Otherwise set entity mappings.
@@ -694,7 +728,6 @@ export default {
}else{ }else{
this.name = this.lastSelectedEntity['entityName'] this.name = this.lastSelectedEntity['entityName']
} }
console.log("entity not mapped")
this.updateMappingInputs() this.updateMappingInputs()
this.getFamiliesFromSelectedMethod() this.getFamiliesFromSelectedMethod()
this.getTypesFromSelectedFamily() this.getTypesFromSelectedFamily()
@@ -706,7 +739,6 @@ export default {
this.name = this.lastSelectedEntity['schema']['name'] this.name = this.lastSelectedEntity['schema']['name']
} }
this.selectedMethod = this.lastSelectedEntity['schema']['method'] this.selectedMethod = this.lastSelectedEntity['schema']['method']
console.log("entity is mapped")
this.updateMappingInputs() this.updateMappingInputs()
this.selectedFamily = this.lastSelectedEntity['schema']['family'] this.selectedFamily = this.lastSelectedEntity['schema']['family']
this.selectedCategory = this.lastSelectedEntity['schema']['category'] this.selectedCategory = this.lastSelectedEntity['schema']['category']
@@ -814,18 +846,11 @@ export default {
this.selectedFamily = null this.selectedFamily = null
this.selectedFamilyType = null this.selectedFamilyType = null
this.selectedLevel = null this.selectedLevel = null
this.familyTypes = null
this.levels = null
this.availableMethods = null this.availableMethods = null
this.availableCategories = null
this.allTypes = null
}, },
getDataFromSelection(selectionParameters){ getDataFromSelection(selectionParameters){
this.availableMethods = selectionParameters.mappingMethods this.availableMethods = selectionParameters.mappingMethods
this.availableCategories = selectionParameters.categories
this.selectedEntities = selectionParameters.selection this.selectedEntities = selectionParameters.selection
this.allTypes = selectionParameters.types
this.levels = selectionParameters.levels
this.selectedLevel = selectionParameters.selectedLevelName this.selectedLevel = selectionParameters.selectedLevelName
}, },
updateStatesFromSelectionData(){ updateStatesFromSelectionData(){
@@ -838,8 +863,22 @@ export default {
} }
}, },
mounted() { mounted() {
sketchup.exec({name: "mapper_initialized", data: {}})
sketchup.exec({name: "collect_mapped_entities", data: {}}) sketchup.exec({name: "collect_mapped_entities", data: {}})
bus.$on('mapper-initialized', async (initParameters) => {
const initPars = JSON.parse(initParameters)
this.categories = initPars.categories
this.familyCategories = initPars.familyCategories
})
bus.$on('mapper-source-updated', async (levels, types, familyInstances) => {
// Parse data to json object
this.familyInstanceTypes = JSON.parse(familyInstances)
this.levels = JSON.parse(levels)
this.types = JSON.parse(types)
})
bus.$on('entities-selected', async (selectionParameters) => { bus.$on('entities-selected', async (selectionParameters) => {
// Parse data to json object // Parse data to json object
const selectionPars = JSON.parse(selectionParameters) const selectionPars = JSON.parse(selectionParameters)
-5
View File
@@ -219,9 +219,4 @@ export default {
} }
} }
} }
</script> </script>
<style scoped>
</style>
+97 -88
View File
@@ -1,10 +1,6 @@
<template> <template>
<v-card <v-card v-if="stream" :class="`mb-3 rounded-lg grey ${$vuetify.theme.dark ? 'darken-4' : 'lighten-4'}`"
v-if="stream" @mouseenter="hover = true" @mouseleave="hover = false">
:class="`mb-3 rounded-lg grey ${$vuetify.theme.dark ? 'darken-4' : 'lighten-4'}`"
@mouseenter="hover = true"
@mouseleave="hover = false"
>
<v-toolbar flat height="70" :color="getColor(invalid)"> <v-toolbar flat height="70" :color="getColor(invalid)">
<v-btn v-tooptip="''" icon small outlined class="delta-btn" v-if="invalid" @click="activateDiffing"> <v-btn v-tooptip="''" icon small outlined class="delta-btn" v-if="invalid" @click="activateDiffing">
<v-icon v-if="!diffing" class="toggleUpDown" :class='{ "rotate": diffing }' small>mdi-eye-off-outline</v-icon> <v-icon v-if="!diffing" class="toggleUpDown" :class='{ "rotate": diffing }' small>mdi-eye-off-outline</v-icon>
@@ -12,12 +8,8 @@
</v-btn> </v-btn>
<v-toolbar-title class="ml-0" style="position: relative; left: -10px"> <v-toolbar-title class="ml-0" style="position: relative; left: -10px">
<!-- Uncomment when pinning is in place and add style="position: relative; left: -10px" to the element above :) --> <!-- Uncomment when pinning is in place and add style="position: relative; left: -10px" to the element above :) -->
<v-btn <v-btn v-tooltip="`Pin this ${streamText.toLowerCase()} - it will be saved to this file.`" icon x-small
v-tooltip="`Pin this ${streamText.toLowerCase()} - it will be saved to this file.`" @click="toggleSavedStream">
icon
x-small
@click="toggleSavedStream"
>
<v-icon v-if="saved" x-small>mdi-pin</v-icon> <v-icon v-if="saved" x-small>mdi-pin</v-icon>
<v-icon v-else x-small>mdi-pin-outline</v-icon> <v-icon v-else x-small>mdi-pin-outline</v-icon>
</v-btn> </v-btn>
@@ -29,24 +21,12 @@
<v-btn v-tooltip="'View online'" icon small class="mr-3" @click="openInWeb"> <v-btn v-tooltip="'View online'" icon small class="mr-3" @click="openInWeb">
<v-icon small>mdi-open-in-new</v-icon> <v-icon small>mdi-open-in-new</v-icon>
</v-btn> </v-btn>
<v-btn <v-btn v-tooltip="'Send'" icon class="mr-3 elevation-2" :loading="loadingSend" @click="send">
v-tooltip="'Send'"
icon
class="mr-3 elevation-2"
:loading="loadingSend"
@click="send"
>
<!-- <v-icon>mdi-upload</v-icon> --> <!-- <v-icon>mdi-upload</v-icon> -->
<v-img v-if="$vuetify.theme.dark" src="@/assets/SenderWhite.png" max-width="30" /> <v-img v-if="$vuetify.theme.dark" src="@/assets/SenderWhite.png" max-width="30" />
<v-img v-else src="@/assets/Sender.png" max-width="30" /> <v-img v-else src="@/assets/Sender.png" max-width="30" />
</v-btn> </v-btn>
<v-btn <v-btn v-tooltip="'Receive'" icon class="elevation-2" :loading="loadingReceive" @click="receive">
v-tooltip="'Receive'"
icon
class="elevation-2"
:loading="loadingReceive"
@click="receive"
>
<!-- <v-icon>mdi-download</v-icon> --> <!-- <v-icon>mdi-download</v-icon> -->
<v-img v-if="$vuetify.theme.dark" src="@/assets/ReceiverWhite.png" max-width="30" /> <v-img v-if="$vuetify.theme.dark" src="@/assets/ReceiverWhite.png" max-width="30" />
<v-img v-else src="@/assets/Receiver.png" max-width="30" /> <v-img v-else src="@/assets/Receiver.png" max-width="30" />
@@ -66,11 +46,8 @@
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">
<v-slide-x-transition> <v-slide-x-transition>
<div v-show="hover"> <div v-show="hover">
<create-branch-dialog <create-branch-dialog :is-f-e2="preferences && preferences.user && preferences.user.fe2"
:is-f-e2="preferences && preferences.user && preferences.user.fe2" :stream-name="stream.name" :stream-id="streamId" />
:stream-name="stream.name"
:stream-id="streamId"
/>
</div> </div>
</v-slide-x-transition> </v-slide-x-transition>
<v-chip v-if="stream.branches" small v-bind="attrs" class="mr-1" v-on="on"> <v-chip v-if="stream.branches" small v-bind="attrs" class="mr-1" v-on="on">
@@ -80,42 +57,30 @@
</template> </template>
<!-- Branch list --> <!-- Branch list -->
<v-list dense> <v-list dense>
<v-list-item <v-list-item v-for="(branch, index) in stream.branches.items" :key="index" link
v-for="(branch, index) in stream.branches.items" @click="switchBranch(branch.name)">
:key="index"
link
@click="switchBranch(branch.name)"
>
<v-list-item-title class="text-caption font-weight-regular"> <v-list-item-title class="text-caption font-weight-regular">
<v-icon v-if="branch.name === branchName" small class="mr-1 float-left"> <v-icon v-if="branch.name === branchName" small class="mr-1 float-left">
mdi-check mdi-check
</v-icon> </v-icon>
<v-icon v-else small class="mr-1 float-left">mdi-source-branch</v-icon> <v-icon v-else small class="mr-1 float-left">mdi-source-branch</v-icon>
{{ branch.name }} ({{ branch.commits.totalCount }}) {{ branch.name }} ({{ branch && branch.commits ? branch.commits.totalCount : 0 }})
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
</v-list> </v-list>
</v-menu> </v-menu>
<v-menu offset-y> <v-menu offset-y>
<template #activator="{ on, attrs }"> <template #activator="{ on, attrs }">
<v-chip v-if="stream.commits" small v-bind="attrs" v-on="on"> <v-chip v-if="stream && stream.commits" small v-bind="attrs" v-on="on">
<v-icon small class="mr-1 float-left">mdi-source-commit</v-icon> <v-icon small class="mr-1 float-left">mdi-source-commit</v-icon>
{{ selectedBranch.commits.items.length ? commitId : 'no commits' }} {{ selectedBranch.commits.items.length ? commitId : 'no commits' }}
</v-chip> </v-chip>
</template> </template>
<v-list dense> <v-list v-if="selectedBranch && selectedBranch.commits" dense>
<v-list-item <v-list-item v-for="(commit, index) in selectedBranch.commits.items" :key="index" link
v-for="(commit, index) in selectedBranch.commits.items" @click="switchCommit(commit.id)">
:key="index"
link
@click="switchCommit(commit.id)"
>
<v-list-item-title class="text-caption font-weight-regular"> <v-list-item-title class="text-caption font-weight-regular">
<v-icon <v-icon v-if="(commitId == 'latest' && index == 0) || commit.id == commitId" small class="mr-1 float-left">
v-if="(commitId == 'latest' && index == 0) || commit.id == commitId"
small
class="mr-1 float-left"
>
mdi-check mdi-check
</v-icon> </v-icon>
<v-icon v-else small class="mr-1 float-left">mdi-source-commit</v-icon> <v-icon v-else small class="mr-1 float-left">mdi-source-commit</v-icon>
@@ -131,24 +96,14 @@
<div class="flex-grow-1 px-4"> <div class="flex-grow-1 px-4">
<v-slide-y-transition> <v-slide-y-transition>
<div v-show="hover"> <div v-show="hover">
<v-text-field <v-text-field v-model="commitMessage" xxxclass="small-text-field" hide-details dense flat
v-model="commitMessage" :placeholder="`Write your ${commitText.toLowerCase()} message here`" />
xxxclass="small-text-field"
hide-details
dense
flat
:placeholder="`Write your ${commitText.toLowerCase()} message here`"
/>
</div> </div>
</v-slide-y-transition> </v-slide-y-transition>
</div> </div>
</v-card-text> </v-card-text>
<v-progress-linear <v-progress-linear v-if="(loadingSend || loadingReceive) && loadingStage" key="progress-bar" height="14"
v-if="(loadingSend || loadingReceive) && loadingStage" indeterminate>
key="progress-bar"
height="14"
indeterminate
>
<div class="text-caption"> <div class="text-caption">
{{ loadingStage }} {{ loadingStage }}
</div> </div>
@@ -164,8 +119,9 @@
import gql from 'graphql-tag' import gql from 'graphql-tag'
import { bus } from '../main' import { bus } from '../main'
import streamQuery from '../graphql/stream.gql' import streamQuery from '../graphql/stream.gql'
import projectQuery from '../graphql/project.gql'
import ObjectLoader from '@speckle/objectloader' import ObjectLoader from '@speckle/objectloader'
import {HostApplications} from '@/utils/hostApplications' import { HostApplications } from '@/utils/hostApplications'
global.convertedFromSketchup = function (streamId, batches, commitId, totalChildrenCount) { global.convertedFromSketchup = function (streamId, batches, commitId, totalChildrenCount) {
bus.$emit(`sketchup-objects-${streamId}`, batches, commitId, totalChildrenCount) bus.$emit(`sketchup-objects-${streamId}`, batches, commitId, totalChildrenCount)
@@ -212,7 +168,8 @@ export default {
streamText: '', streamText: '',
branchText: '', branchText: '',
commitText: '', commitText: '',
preferences: {} preferences: {},
filterBranchIds: []
} }
}, },
apollo: { apollo: {
@@ -225,6 +182,18 @@ export default {
} }
} }
}, },
project: {
prefetch: true,
query: projectQuery,
variables() {
return {
projectId: this.streamId,
filter: {
ids: this.filterBranchIds
}
}
}
},
$subscribe: { $subscribe: {
commitCreated: { commitCreated: {
query: gql` query: gql`
@@ -302,7 +271,39 @@ export default {
this.commitText = pref.user.fe2 ? 'Version' : 'Commit' this.commitText = pref.user.fe2 ? 'Version' : 'Commit'
}) })
// Collect preferences to render UI according to it // Collect preferences to render UI according to it
sketchup.exec({name: "collect_preferences", data: {}}) sketchup.exec({ name: "collect_preferences", data: {} })
bus.$on(`set-stream-branch-commit-${this.streamId}`, async (branchId, commitId) => {
console.log(branchId, "branchId");
let res = await this.$apollo.query({
query: gql`
query Project($projectId: String!, $filter: ProjectModelsFilter) {
project(id: $projectId) {
id
name
models (filter: $filter) {
items {
id
name
versions {
items {
id
}
}
}
}
}
}
`,
variables: {
projectId: this.streamId,
filter: {
ids: [branchId]
}
}
})
console.log(res.data);
})
bus.$on(`deactivate-diffing-${this.streamId}`, () => { bus.$on(`deactivate-diffing-${this.streamId}`, () => {
this.diffing = false this.diffing = false
@@ -347,11 +348,11 @@ export default {
this.$mixpanel.track('Send', { method: 'OneClick' }) this.$mixpanel.track('Send', { method: 'OneClick' })
}) })
if (this.saved) sketchup.exec({name: "notify_connected", data: {stream_id: this.streamId}}) if (this.saved) sketchup.exec({ name: "notify_connected", data: { stream_id: this.streamId } })
}, },
methods: { methods: {
getColor(invalid){ getColor(invalid) {
if(invalid){ if (invalid) {
return "#ffdfdf" return "#ffdfdf"
} else { } else {
return "" return ""
@@ -361,7 +362,9 @@ export default {
return new Promise((resolve) => setTimeout(resolve, ms)) return new Promise((resolve) => setTimeout(resolve, ms))
}, },
openInWeb() { openInWeb() {
window.open(`${localStorage.getItem('serverUrl')}/streams/${this.streamId}`) var url = localStorage.getItem('frontend2') === "true" ? `${localStorage.getItem('serverUrl')}/projects/${this.streamId}` : `${localStorage.getItem('serverUrl')}/streams/${this.streamId}`
window.open(url)
this.$mixpanel.track('Connector Action', { name: 'Open In Web' }) this.$mixpanel.track('Connector Action', { name: 'Open In Web' })
}, },
switchBranch(branchName) { switchBranch(branchName) {
@@ -373,22 +376,22 @@ export default {
this.$mixpanel.track('Connector Action', { name: 'Commit Switch' }) this.$mixpanel.track('Connector Action', { name: 'Commit Switch' })
this.commitId = commitId this.commitId = commitId
}, },
activateDiffing(){ activateDiffing() {
if (this.diffing){ if (this.diffing) {
this.diffing = false this.diffing = false
sketchup.exec({name: "deactivate_diffing", data: {}}) sketchup.exec({ name: "deactivate_diffing", data: {} })
return return
} }
this.diffing = true this.diffing = true
bus.$emit("deactivate-diffing-except", (this.streamId)) bus.$emit("deactivate-diffing-except", (this.streamId))
sketchup.exec({name: "activate_diffing", data: {stream_id: this.streamId}}) sketchup.exec({ name: "activate_diffing", data: { stream_id: this.streamId } })
}, },
toggleSavedStream() { toggleSavedStream() {
if (this.saved) { if (this.saved) {
sketchup.exec({name: "remove_stream", data: {stream_id: this.streamId}}) sketchup.exec({ name: "remove_stream", data: { stream_id: this.streamId } })
this.$mixpanel.track('Connector Action', { name: 'Stream Remove' }) this.$mixpanel.track('Connector Action', { name: 'Stream Remove' })
} else { } else {
sketchup.exec({name: "save_stream", data: {stream_id: this.streamId}}) sketchup.exec({ name: "save_stream", data: { stream_id: this.streamId } })
this.$mixpanel.track('Connector Action', { name: 'Stream Save' }) this.$mixpanel.track('Connector Action', { name: 'Stream Save' })
} }
}, },
@@ -399,7 +402,7 @@ export default {
const isMultiplayer = this.selectedCommit.authorId !== selectedAccount['userInfo']['id'] const isMultiplayer = this.selectedCommit.authorId !== selectedAccount['userInfo']['id']
const sourceApp = this.selectedCommit.sourceApplication const sourceApp = this.selectedCommit.sourceApplication
const sourceAppSlug = HostApplications.GetHostAppFromString(sourceApp).slug const sourceAppSlug = HostApplications.GetHostAppFromString(sourceApp).slug
this.$mixpanel.track('Receive', { isMultiplayer: isMultiplayer, sourceHostApp: sourceAppSlug, sourceHostAppVersion: sourceApp}) this.$mixpanel.track('Receive', { isMultiplayer: isMultiplayer, sourceHostApp: sourceAppSlug, sourceHostAppVersion: sourceApp })
const refId = this.selectedCommit?.referencedObject const refId = this.selectedCommit?.referencedObject
if (!refId) { if (!refId) {
this.loadingReceive = false this.loadingReceive = false
@@ -416,14 +419,16 @@ export default {
let rootObj = await loader.getAndConstructObject(this.updateLoadingStage) let rootObj = await loader.getAndConstructObject(this.updateLoadingStage)
sketchup.exec({name:"receive_objects" , data: { sketchup.exec({
name: "receive_objects", data: {
base: rootObj, base: rootObj,
stream_name: this.stream.name, stream_name: this.stream.name,
stream_id: this.streamId, stream_id: this.streamId,
branch_name: this.selectedCommit.branchName, branch_name: this.selectedCommit.branchName,
branch_id: this.selectedCommit.id, branch_id: this.selectedCommit.id,
source_app: this.selectedCommit.sourceApplication source_app: this.selectedCommit.sourceApplication
}}) }
})
await this.$apollo.mutate({ await this.$apollo.mutate({
mutation: gql` mutation: gql`
@@ -449,7 +454,7 @@ export default {
this.loadingStage = 'converting' this.loadingStage = 'converting'
this.loadingSend = true this.loadingSend = true
this.$mixpanel.track('Send') this.$mixpanel.track('Send')
sketchup.exec({name:"send_selection" , data: {stream_id: this.streamId}}) sketchup.exec({ name: "send_selection", data: { stream_id: this.streamId } })
console.log('>>> SpeckleSketchUp: Objects requested from SketchUp') console.log('>>> SpeckleSketchUp: Objects requested from SketchUp')
await this.sleep(2000) await this.sleep(2000)
}, },
@@ -479,7 +484,7 @@ export default {
} }
const t1 = Date.now() const t1 = Date.now()
const elapsedTime = (t1-t0) / 1000 const elapsedTime = (t1 - t0) / 1000
console.log(`Upload time: ${elapsedTime} second`) console.log(`Upload time: ${elapsedTime} second`)
let commit = { let commit = {
@@ -501,13 +506,12 @@ export default {
} }
}) })
console.log('>>> SpeckleSketchUp: Sent to stream: ' + this.streamId, commit) console.log('>>> SpeckleSketchUp: Sent to stream: ' + this.streamId, commit)
const url = localStorage.getItem('frontend2') === 'true' ? `${localStorage.getItem('serverUrl')}/projects/${this.streamId}/models/${this.selectedBranch.id}@${res.data.commitCreate}` : `${localStorage.getItem('serverUrl')}/streams/${this.streamId}/commits/${res.data.commitCreate}`
this.$eventHub.$emit('notification', { this.$eventHub.$emit('notification', {
text: 'Model selection sent!\n', text: 'Model selection sent!\n',
action: { action: {
name: 'View in Web', name: 'View in Web',
url: `${localStorage.getItem('serverUrl')}/streams/${this.streamId}/commits/${ url: url
res.data.commitCreate
}`
} }
}) })
this.$apollo.queries.stream.refetch() this.$apollo.queries.stream.refetch()
@@ -555,6 +559,7 @@ export default {
.fade-leave-active { .fade-leave-active {
transition: opacity 0.2s ease-in; transition: opacity 0.2s ease-in;
} }
.fade-enter, .fade-enter,
.fade-leave-to { .fade-leave-to {
opacity: 0; opacity: 0;
@@ -565,27 +570,31 @@ export default {
max-height: 1200px; max-height: 1200px;
overflow: hidden; overflow: hidden;
} }
.expand-leave-active { .expand-leave-active {
transition: all 0.3s ease; transition: all 0.3s ease;
max-height: 1200px; max-height: 1200px;
overflow: hidden; overflow: hidden;
} }
.expand-enter, .expand-enter,
.expand-leave-to { .expand-leave-to {
max-height: 0; max-height: 0;
opacity: 0; opacity: 0;
} }
.v-text-field >>> input { .v-text-field>>>input {
font-size: 0.9em; font-size: 0.9em;
} }
.v-text-field >>> label {
.v-text-field>>>label {
font-size: 0.9em; font-size: 0.9em;
} }
.btn-fix:focus::before { .btn-fix:focus::before {
opacity: 0 !important; opacity: 0 !important;
} }
.btn-fix:hover::before { .btn-fix:hover::before {
opacity: 0.08 !important; opacity: 0.08 !important;
} }
@@ -17,13 +17,13 @@
> >
mdi-plus-circle mdi-plus-circle
</v-icon> </v-icon>
{{ `Create New ${isFE2 ? 'Project': 'Stream'}` }} {{ `Create New ${isFE2Terms ? 'Project': 'Stream'}` }}
</v-btn> </v-btn>
</template> </template>
<v-card> <v-card>
<v-card-title class="text-h5"> <v-card-title class="text-h5">
{{ `Create a New ${isFE2 ? 'Project' : 'Stream'}` }} {{ `Create a New ${isFE2Terms ? 'Project' : 'Stream'}` }}
</v-card-title> </v-card-title>
<v-container class="px-6" pb-0> <v-container class="px-6" pb-0>
<!-- <!--
@@ -56,7 +56,7 @@
hide-details hide-details
dense dense
flat flat
:placeholder="`${isFE2 ? 'Project' : 'Stream'} Name (Optional)`" :placeholder="`${isFE2Terms ? 'Project' : 'Stream'} Name (Optional)`"
/> />
<v-text-field <v-text-field
v-model="description" v-model="description"
@@ -68,7 +68,7 @@
/> />
<v-switch <v-switch
v-model="privateStream" v-model="privateStream"
:label="`Private ${isFE2 ? 'Project' : 'Stream'}`" :label="`Private ${isFE2Terms ? 'Project' : 'Stream'}`"
></v-switch> ></v-switch>
</v-container> </v-container>
@@ -171,7 +171,7 @@ export default {
type: String, type: String,
default: null default: null
}, },
isFE2: { isFE2Terms: {
type: Boolean, type: Boolean,
default: false default: false
} }
@@ -205,7 +205,7 @@ export default {
}, },
async getStream(){ async getStream(){
try { try {
const streamWrapper = new StreamWrapper(this.createStreamByIdText, this.accountId, this.serverUrl, this.isFE2) const streamWrapper = new StreamWrapper(this.createStreamByIdText, this.accountId, this.serverUrl, localStorage.getItem('frontend2') === 'true')
let res = await this.$apollo.query({ let res = await this.$apollo.query({
query: gql` query: gql`
query Stream($id: String!){ query Stream($id: String!){
@@ -250,7 +250,9 @@ export default {
this.$eventHub.$emit('notification', { this.$eventHub.$emit('notification', {
text: 'Stream Added by URL!\n', text: 'Stream Added by URL!\n',
}) })
bus.$emit('stream-added-by-id-or-url', stream.id) console.log(streamWrapper);
console.log(streamWrapper.branchName.slice(0, -1), "stream-added-by-id-or-url");
await bus.$emit('stream-added-by-id-or-url', stream.id, streamWrapper.branchName.slice(0, -1), streamWrapper.commitId)
this.$mixpanel.track('Connector Action', { name: 'Stream Add From URL' }) this.$mixpanel.track('Connector Action', { name: 'Stream Add From URL' })
} }
catch (e){ catch (e){
+17
View File
@@ -0,0 +1,17 @@
query Project($projectId: String!, $filter: ProjectModelsFilter) {
project(id: $projectId) {
id
name
models (filter: $filter) {
items {
id
name
versions {
items {
id
}
}
}
}
}
}
+6
View File
@@ -0,0 +1,6 @@
query{
serverInfo {
name
canonicalUrl
}
}
+10 -4
View File
@@ -17,7 +17,7 @@
</div> </div>
<div v-if="allStreamsList" class="mt-5"> <div v-if="allStreamsList" class="mt-5">
<div v-for="stream in allStreamsList" :key="stream.id"> <div v-for="stream in allStreamsList" :key="stream.id">
<stream-card :stream-id="stream.id" /> <stream-card :stream-id="stream.id"/>
</div> </div>
<div class="actions text-center"> <div class="actions text-center">
<v-btn <v-btn
@@ -59,7 +59,10 @@ export default {
StreamCard: () => import('@/components/StreamCard') StreamCard: () => import('@/components/StreamCard')
}, },
props: { props: {
streamSearchQuery: { type: String, default: null } streamSearchQuery: {
type: String,
default: null
}
}, },
data() { data() {
return { return {
@@ -117,16 +120,19 @@ export default {
bus.$on('set-saved-streams', (streamIds) => { bus.$on('set-saved-streams', (streamIds) => {
this.savedStreams = streamIds this.savedStreams = streamIds
}) })
bus.$on('stream-added-by-id-or-url', (streamId) => { bus.$on('stream-added-by-id-or-url', async(streamId, branchId, commitId) => {
if (!this.savedStreams){ if (!this.savedStreams){
this.savedStreams = [] this.savedStreams = []
this.savedStreams.push(streamId) this.savedStreams.push(streamId)
sketchup.exec({name: "save_stream", data: {stream_id: streamId}})
} else { } else {
if (!this.savedStreams.includes(streamId)){ if (!this.savedStreams.includes(streamId)){
this.savedStreams.push(streamId) this.savedStreams.push(streamId)
sketchup.exec({name: "save_stream", data: {stream_id: streamId}})
} }
} }
sketchup.exec({name: "save_stream", data: {stream_id: streamId}}) await bus.$emit(`set-stream-branch-commit-${streamId}`, branchId, commitId)
}) })
sketchup.exec({name: "load_saved_streams", data: {}}) sketchup.exec({name: "load_saved_streams", data: {}})
console.log('LAUNCHED') console.log('LAUNCHED')