lws 7.0.0 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/lwsconsole +5 -1
- data/lib/lws.rb +1 -1
- data/lib/lws/apps/digital_signage.rb +94 -89
- data/lib/lws/apps/generic.rb +72 -7
- data/lib/lws/apps/presence.rb +70 -3
- data/lib/lws/apps/resource.rb +20 -0
- data/lib/lws/version.rb +1 -1
- data/test/digital_signage_test.rb +8 -62
- data/test/generic_test.rb +38 -2
- data/test/test_helper.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 71a8d517993d1edc2f3ee98d57c5e8d96722e8c30f3022e346eaeee1f548a8b8
|
4
|
+
data.tar.gz: ca21b87824d2470ebfde323df4e979be95ca943d79df42ab454d66626ab50532
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0bc0ba9e36161be2702592791d1c4baad190714b39fe5fe67e2e0b78c61cf80e5a53be2ce3d820497052b87e587f5efdfd0253fd4561f97debabfd961fb8b0d5
|
7
|
+
data.tar.gz: 6db01df5b9610858c985e4d1ab711cf29538a9bed8601437a7f476c3d633417ed910a93ed0b32b3ed9d88a7d993667f2ae8a03689c4afd4e4e959cbc417cdee2
|
data/bin/lwsconsole
CHANGED
@@ -134,7 +134,11 @@ end
|
|
134
134
|
|
135
135
|
# Set up Pry
|
136
136
|
FileUtils.mkdir_p("#{ENV['HOME']}/.local/share/LeftClick")
|
137
|
-
Pry.config.
|
137
|
+
if Pry.config.history_file
|
138
|
+
Pry.config.history_file = "#{ENV['HOME']}/.local/share/LeftClick/lws_history"
|
139
|
+
else
|
140
|
+
Pry.config.history.file = "#{ENV['HOME']}/.local/share/LeftClick/lws_history"
|
141
|
+
end
|
138
142
|
Pry.config.prompt_name = PROG_NAME
|
139
143
|
|
140
144
|
# Print an LWS setup summary
|
data/lib/lws.rb
CHANGED
@@ -60,7 +60,7 @@ module LWS
|
|
60
60
|
# config.api_token_middleware = TokenAuthenticator
|
61
61
|
# config.caching_object = MyRedisCache.new
|
62
62
|
# config.environment = :development
|
63
|
-
# config.
|
63
|
+
# config.endpoints = { maps: "https://maps.leftclick.cloud" }
|
64
64
|
# config.http_debug = true
|
65
65
|
# config.json_debug = true
|
66
66
|
# config.logger = Rails.logger
|
@@ -78,6 +78,10 @@ module LWS::DigitalSignage
|
|
78
78
|
# @return [Array<Channel::Group>] the groups the channel is a member of
|
79
79
|
has_many :groups, class_name: "LWS::DigitalSignage::Channel::Group"
|
80
80
|
|
81
|
+
# @!attribute marquee_config
|
82
|
+
# @return [String] the marquee/ticker tape configuration (JSON) of the channel
|
83
|
+
attribute :marquee_config
|
84
|
+
|
81
85
|
# @!attribute name
|
82
86
|
# @return [String] the name of the channel
|
83
87
|
attribute :name
|
@@ -100,6 +104,10 @@ module LWS::DigitalSignage
|
|
100
104
|
# @return [Boolean] whether remote control is enabled for the channel
|
101
105
|
attribute :remote_control
|
102
106
|
|
107
|
+
# @!attribute slides
|
108
|
+
# @return [Array<Slide>] the slides schedules on the channel
|
109
|
+
has_many :slides, class_name: "LWS::DigitalSignage::Slide"
|
110
|
+
|
103
111
|
# @!attribute tags
|
104
112
|
# @return [Array<Channel::Tag>] the tags of the channel
|
105
113
|
has_many :tags, class_name: "LWS::DigitalSignage::Channel::Tag"
|
@@ -159,6 +167,10 @@ module LWS::DigitalSignage
|
|
159
167
|
# @return [Integer, nil] the ID of the parent group of the channel group
|
160
168
|
attribute :parent_id
|
161
169
|
|
170
|
+
# @!attribute slides
|
171
|
+
# @return [Array<Slide>] the slides schedules on the channel group
|
172
|
+
has_many :slides, class_name: "LWS::DigitalSignage::Slide"
|
173
|
+
|
162
174
|
#@!attribute tags
|
163
175
|
# @return [Array<Channel::Group::Tag>] the tags of the channel group
|
164
176
|
has_many :tags, class_name: "LWS::DigitalSignage::Channel::Group::Tag",
|
@@ -512,6 +524,10 @@ module LWS::DigitalSignage
|
|
512
524
|
# @return [Boolean] whether the layout is a favorite for the current account
|
513
525
|
attribute :favorite
|
514
526
|
|
527
|
+
# @!attribute kind
|
528
|
+
# @return ["marquee", "slide"] the kind of the layout
|
529
|
+
attribute :kind
|
530
|
+
|
515
531
|
# @!attribute name
|
516
532
|
# @return [String] the name of the layout
|
517
533
|
attribute :name
|
@@ -575,6 +591,10 @@ module LWS::DigitalSignage
|
|
575
591
|
# @!attribute name
|
576
592
|
# @return [String] the name of the layout category
|
577
593
|
attribute :name
|
594
|
+
|
595
|
+
# @!attribute translated_name
|
596
|
+
# @return [String] the translated name of the layout category
|
597
|
+
attribute :name
|
578
598
|
end
|
579
599
|
|
580
600
|
# = The layout element class
|
@@ -624,6 +644,10 @@ module LWS::DigitalSignage
|
|
624
644
|
# element
|
625
645
|
has_many :properties, class_name: "LWS::DigitalSignage::Layout::Element::Property"
|
626
646
|
|
647
|
+
# @!attribute title
|
648
|
+
# @return [String, nil] the title of the layout element
|
649
|
+
attribute :title
|
650
|
+
|
627
651
|
# @!attribute version
|
628
652
|
# @return [Layout::Verion] the layout version that contains the element
|
629
653
|
# FIXME: Missing endpoint in LWS
|
@@ -709,6 +733,10 @@ module LWS::DigitalSignage
|
|
709
733
|
# version
|
710
734
|
has_many :elements, class_name: "LWS::DigitalSignage::Layout::Element"
|
711
735
|
|
736
|
+
# @!attribute height
|
737
|
+
# @return [Integer] the intended height of the layout version
|
738
|
+
attribute :width
|
739
|
+
|
712
740
|
# @!attribute layout
|
713
741
|
# @return [Layout] the layout the layout version is for
|
714
742
|
belongs_to :layout
|
@@ -716,6 +744,28 @@ module LWS::DigitalSignage
|
|
716
744
|
# @!attribute layout_id
|
717
745
|
# @return [Integer] the ID of the layout the layout version is for
|
718
746
|
attribute :layout_id
|
747
|
+
|
748
|
+
# @!attribute rotation
|
749
|
+
# @return ["landscape", "portrait"] the rotation (orientation) of the
|
750
|
+
# layout version
|
751
|
+
attribute :rotation
|
752
|
+
|
753
|
+
# @!attribute rotation_angle
|
754
|
+
# @return [0, 90] the rotation angle of the layout version
|
755
|
+
attribute :rotation_angle
|
756
|
+
|
757
|
+
# @!attribute status [r]
|
758
|
+
# @return ["initializing", "creating_pack", "creating_thumbnail", "available", "archive"]
|
759
|
+
# the status of the layout version
|
760
|
+
attribute :status
|
761
|
+
|
762
|
+
# @!attribute thumbnail_url
|
763
|
+
# @return [String, nil] the URL of the thumbnail of the layout version
|
764
|
+
attribute :thumbnail_url
|
765
|
+
|
766
|
+
# @!attribute width
|
767
|
+
# @return [Integer] the intended width of the layout version
|
768
|
+
attribute :width
|
719
769
|
end
|
720
770
|
|
721
771
|
# = The player class
|
@@ -752,8 +802,16 @@ module LWS::DigitalSignage
|
|
752
802
|
attribute :configuration_id
|
753
803
|
|
754
804
|
# @!attribute feedbacks
|
755
|
-
# @return [
|
756
|
-
|
805
|
+
# @return [Hash{String=>String}] a mapping of player feedback key/values
|
806
|
+
attribute :feedbacks
|
807
|
+
|
808
|
+
# @!attribute [r] health_percentage
|
809
|
+
# @return [Fixnum] the health of the player (percentage)
|
810
|
+
attribute :health_percentage
|
811
|
+
|
812
|
+
# @!attribute [r] hostname
|
813
|
+
# @return [String] the hostname used by the player (for DHCP for example)
|
814
|
+
attribute :hostname
|
757
815
|
|
758
816
|
# @!attribute logs
|
759
817
|
# @return [Array<Player::Log>] the logs of the player
|
@@ -770,7 +828,7 @@ module LWS::DigitalSignage
|
|
770
828
|
# @!attribute model
|
771
829
|
# @return [Player::Model] the model of the player
|
772
830
|
belongs_to :model, class_name: "LWS::DigitalSignage::Player::Model",
|
773
|
-
|
831
|
+
uri: "player/models/:id"
|
774
832
|
|
775
833
|
# @!attribute model_id
|
776
834
|
# @return [Integer] the ID of the model of the player
|
@@ -780,15 +838,27 @@ module LWS::DigitalSignage
|
|
780
838
|
# @return [Array<Player::Notification>] the notifications for the player
|
781
839
|
has_many :notifications, class_name: "LWS::DigitalSignage::Player::Notification"
|
782
840
|
|
783
|
-
# @!attribute
|
841
|
+
# @!attribute operational_hours [r]
|
842
|
+
# @return [String, nil] the number of hours the player has been operational
|
843
|
+
attribute :operational_hours
|
844
|
+
|
845
|
+
# @!attribute operational_since [r]
|
784
846
|
# @return [String, nil] the date/time when the player became operational
|
785
847
|
# for the first time
|
786
848
|
attribute :operational_since
|
787
849
|
|
850
|
+
# @!attribute os_release_version
|
851
|
+
# @return [String, nil] the OS version the player is using (if known)
|
852
|
+
attribute :os_release_version
|
853
|
+
|
788
854
|
# @!attribute parts
|
789
855
|
# @return [Array<Player::Component::Part>] the parts of the player
|
790
856
|
has_many :parts, class_name: "LWS::DigitalSignage::Player::Component::Part"
|
791
857
|
|
858
|
+
# @!attribute registration_locked
|
859
|
+
# @return [Boolean] whether registarion is locked for the player
|
860
|
+
attribute :registration_locked
|
861
|
+
|
792
862
|
# @!attribute release_channel
|
793
863
|
# @return [Player::Os::ReleaseChannel] the player OS release channel used
|
794
864
|
# by the player
|
@@ -801,7 +871,7 @@ module LWS::DigitalSignage
|
|
801
871
|
attribute :release_channel_id
|
802
872
|
|
803
873
|
# @!attribute requests
|
804
|
-
# @return [Array<Player::
|
874
|
+
# @return [Array<Player::Request>] the requests for the player
|
805
875
|
has_many :requests, class_name: "LWS::DigitalSignage::Player::Request"
|
806
876
|
|
807
877
|
# @!attribute screenshots
|
@@ -816,10 +886,14 @@ module LWS::DigitalSignage
|
|
816
886
|
# @return [Boolean] whether the player is being serviced/is in service
|
817
887
|
attribute :service
|
818
888
|
|
819
|
-
# @!attribute status
|
889
|
+
# @!attribute status [r]
|
820
890
|
# @return ["unknown", "good", "warning", "bad"] the player status
|
821
891
|
attribute :status
|
822
892
|
|
893
|
+
# @!attribute status_reason [r]
|
894
|
+
# @return [String] the reason for the current player status
|
895
|
+
attribute :status_reason
|
896
|
+
|
823
897
|
# @!attribute tags
|
824
898
|
# @return [Array<Player::Tag>] the tags of the player
|
825
899
|
has_many :tags, class_name: "LWS::DigitalSignage::Player::Tag"
|
@@ -970,75 +1044,6 @@ module LWS::DigitalSignage
|
|
970
1044
|
attribute :value
|
971
1045
|
end
|
972
1046
|
|
973
|
-
# = The player feedback class
|
974
|
-
#
|
975
|
-
# @note
|
976
|
-
# This class is only used within the context of the {Player} class.
|
977
|
-
class Player::Feedback < LWS::Generic::Model
|
978
|
-
use_api LWS::DigitalSignage.api
|
979
|
-
uri "players/:player_id/feedbacks(/:id)"
|
980
|
-
|
981
|
-
# @!attribute player
|
982
|
-
# @return [Player] the player the feedback is originating from
|
983
|
-
belongs_to :player, class_name: "LWS::DigitalSignage::Player"
|
984
|
-
|
985
|
-
# @!attribute player_id
|
986
|
-
# @return [Integer] the ID of the player the feedback is originating from
|
987
|
-
attribute :player_id
|
988
|
-
|
989
|
-
# @!attribute release
|
990
|
-
# @return [Player::Os::Branch::Release] the player OS branch release the
|
991
|
-
# feedback is related to
|
992
|
-
# FIXME: Missing branch_id field in LWS
|
993
|
-
belongs_to :release, class_name: "LWS::DigitalSignage::Player::Os::Branch::Release",
|
994
|
-
uri: "player/os/branches/:branch_id/releases/:id"
|
995
|
-
|
996
|
-
# @!attribute release_id
|
997
|
-
# @return [Integer] the ID of the player OS branch release the feedback
|
998
|
-
# is related to
|
999
|
-
|
1000
|
-
# @!attribute results
|
1001
|
-
# @return [Array<Player::Feedback::Result>] the results of the player feedback
|
1002
|
-
# FIXME: Chained associations don't work yet in Spyke (#89)
|
1003
|
-
has_many :results, class_name: "LWS::DigitalSignage::Player::Feedback::Result",
|
1004
|
-
uri: "players/:player_id/feedbacks/:feedback_id/results(/:id)"
|
1005
|
-
end
|
1006
|
-
|
1007
|
-
# = The player feedback result class
|
1008
|
-
#
|
1009
|
-
# @note
|
1010
|
-
# This class is only used within the context of the {Player::Feedback}
|
1011
|
-
# class.
|
1012
|
-
class Player::Feedback::Result < LWS::Generic::Model
|
1013
|
-
use_api LWS::DigitalSignage.api
|
1014
|
-
uri "players/:player_id/feedbacks/:feedback_id/results(/:id)"
|
1015
|
-
|
1016
|
-
# @!attribute feedback
|
1017
|
-
# @return [Player::Feedback] the player feedback the result is a part of
|
1018
|
-
belongs_to :feedback, class_name: "LWS::DigitalSignage::Player::Feedback",
|
1019
|
-
uri: "players/:player_id/feedbacks/:id"
|
1020
|
-
|
1021
|
-
# @!attribute feedback_id
|
1022
|
-
# @return [Player::Feedback] the ID of the player feedback the result is a part of
|
1023
|
-
attribute :feedback_id
|
1024
|
-
|
1025
|
-
# @!attribute key
|
1026
|
-
# @return [String] the key of the player feedback result
|
1027
|
-
attribute :key
|
1028
|
-
|
1029
|
-
# @!attribute player
|
1030
|
-
# @return [Player] the player the feedback result is for
|
1031
|
-
belongs_to :player, class_name: "LWS::DigitalSignage::Player"
|
1032
|
-
|
1033
|
-
# @!attribute player_id
|
1034
|
-
# @return [Integer] the ID of the player the feedback result is for
|
1035
|
-
attribute :player_id
|
1036
|
-
|
1037
|
-
# @!attribute value
|
1038
|
-
# @return [String] the value of the player feedback result
|
1039
|
-
attribute :value
|
1040
|
-
end
|
1041
|
-
|
1042
1047
|
# = The player log class
|
1043
1048
|
#
|
1044
1049
|
# @note
|
@@ -1562,20 +1567,6 @@ module LWS::DigitalSignage
|
|
1562
1567
|
# @return [String, nil] the optional argument for the player request
|
1563
1568
|
attribute :argument
|
1564
1569
|
|
1565
|
-
# @!attribute feedback
|
1566
|
-
# This field should be set once the action has been processed (see
|
1567
|
-
# {#processed}) and the action is +"send_feedback"+.
|
1568
|
-
#
|
1569
|
-
# @return [Player::Feedback, nil] the player feedback as a response to the
|
1570
|
-
# action request +"send_status"+
|
1571
|
-
belongs_to :feedback, class_name: "LWS::DigitalSignage::Player::Feedback",
|
1572
|
-
uri: "players/:player_id/feedbacks/:id"
|
1573
|
-
|
1574
|
-
# @!attribute feedback_id
|
1575
|
-
# @return [Integer, nil] the ID of the player feedback as a response to the
|
1576
|
-
# action request +"send_status"+
|
1577
|
-
attribute :feedback_id
|
1578
|
-
|
1579
1570
|
# @!attribute log
|
1580
1571
|
# This field should be set once the action has been processed (see
|
1581
1572
|
# {#processed}) and the action is +"send_logs"+.
|
@@ -1685,6 +1676,15 @@ module LWS::DigitalSignage
|
|
1685
1676
|
# @return [Integer] the ID of the account used for creating the slide
|
1686
1677
|
attribute :account_id
|
1687
1678
|
|
1679
|
+
# @!attribute channels
|
1680
|
+
# @return [Array<Channel>] the channels the slide is scheduled on
|
1681
|
+
has_many :channels, class_name: "LWS::DigitalSignage::Channel"
|
1682
|
+
|
1683
|
+
# @!attribute channel_groups
|
1684
|
+
# @return [Array<Channel::Group>] the channel group the slide is
|
1685
|
+
# scheduled on
|
1686
|
+
has_many :channel_groups, class_name: "LWS::DigitalSignage::Channel::Group"
|
1687
|
+
|
1688
1688
|
# @!attribute company
|
1689
1689
|
# @return [LWS::Auth::Company] the company the slide belongs to
|
1690
1690
|
belongs_to :company, class_name: "LWS::Auth::Company"
|
@@ -1713,6 +1713,11 @@ module LWS::DigitalSignage
|
|
1713
1713
|
# @return [Array<Schedule>] the slide schedules that apply for the slide
|
1714
1714
|
# FIXME: Missing endpoint in LWS
|
1715
1715
|
has_many :schedules, class_name: "LWS::DigitalSignage::Slide::Schedule"
|
1716
|
+
|
1717
|
+
# @!attribute status [r]
|
1718
|
+
# @return ["initializing", "waiting_content", "available", "error"]
|
1719
|
+
# the status of the slide
|
1720
|
+
attribute :status
|
1716
1721
|
end
|
1717
1722
|
|
1718
1723
|
# = The slide schedule class
|
data/lib/lws/apps/generic.rb
CHANGED
@@ -150,8 +150,9 @@ module LWS::Generic
|
|
150
150
|
result
|
151
151
|
end
|
152
152
|
|
153
|
-
# Extracts a nested attribute
|
153
|
+
# Extracts a nested attribute value specified by the sequence of attribute names
|
154
154
|
# by calling dig at each step, returning +nil+ if any intermediate step is +nil+.
|
155
|
+
# @return [Object, nil] the digged up value or +nil+
|
155
156
|
def dig(*attrs)
|
156
157
|
attr = attrs.shift
|
157
158
|
value = send(attr)
|
@@ -161,6 +162,20 @@ module LWS::Generic
|
|
161
162
|
value.dig(*attrs)
|
162
163
|
end
|
163
164
|
|
165
|
+
# Returns a deep copy of the model.
|
166
|
+
# @return [Model] a deep copy of the model
|
167
|
+
def deep_dup
|
168
|
+
dup_obj = super
|
169
|
+
dup_obj.instance_eval do
|
170
|
+
@changed_attributes = @changed_attributes.deep_dup
|
171
|
+
@previously_changed = @previously_changed.deep_dup
|
172
|
+
@scope = @scope.deep_dup
|
173
|
+
@spyke_attributes = @spyke_attributes.deep_dup
|
174
|
+
@uri_template = @uri_template.deep_dup
|
175
|
+
end
|
176
|
+
dup_obj
|
177
|
+
end
|
178
|
+
|
164
179
|
end
|
165
180
|
|
166
181
|
# = The configuration class
|
@@ -180,9 +195,11 @@ module LWS::Generic
|
|
180
195
|
class Storage
|
181
196
|
# @!visibility private
|
182
197
|
def self.use_api(api)
|
183
|
-
|
184
|
-
config = LWS.config
|
198
|
+
config = LWS.config
|
185
199
|
|
200
|
+
# A connection to Active Storage (with JSON request/response, but without
|
201
|
+
# token authentication and caching).
|
202
|
+
@as_connection = Faraday.new(url: api.url_prefix) do |c|
|
186
203
|
# Request
|
187
204
|
c.request :json
|
188
205
|
|
@@ -197,6 +214,36 @@ module LWS::Generic
|
|
197
214
|
c.adapter Faraday.default_adapter
|
198
215
|
end
|
199
216
|
end
|
217
|
+
|
218
|
+
# A plain file connection to LWS (with token autnentication and caching but without
|
219
|
+
# JSON request/response).
|
220
|
+
@lws_connection = Faraday.new(url: api.url_prefix) do |c|
|
221
|
+
# Request
|
222
|
+
if config.caching_object
|
223
|
+
c.use FaradayMiddleware::Caching, config.caching_object
|
224
|
+
end
|
225
|
+
c.use LWS::Middleware::RequestHeaders, config.api_token
|
226
|
+
c.use config.api_token_middleware if config.api_token_middleware.present?
|
227
|
+
|
228
|
+
# Response
|
229
|
+
c.use FaradayMiddleware::FollowRedirects, limit: 3
|
230
|
+
c.use LWS::HTTPLogger, config.logger, config.http_debug_headers if config.http_debug
|
231
|
+
|
232
|
+
# Adapter
|
233
|
+
if config.http_persistent
|
234
|
+
c.adapter :net_http_persistent
|
235
|
+
else
|
236
|
+
c.adapter Faraday.default_adapter
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# (see .upload)
|
242
|
+
# @deprecated
|
243
|
+
# To have a consistent upload/download naming counterpart, this
|
244
|
+
# method has been deprecated. Use {.upload} instead.
|
245
|
+
def self.create(file_or_io, filename, content_type = "application/octet-stream")
|
246
|
+
upload(file_or_io, filename, content_type)
|
200
247
|
end
|
201
248
|
|
202
249
|
# Uploads a file (or IO object) to the storage of the app module.
|
@@ -208,7 +255,7 @@ module LWS::Generic
|
|
208
255
|
# @param filename [String] the filename to use for the uploaded file/IO object
|
209
256
|
# @param content_type [String] the content type of the uploaded file/IO object
|
210
257
|
# @return [String, nil] the storage ID (if successful)
|
211
|
-
def self.
|
258
|
+
def self.upload(file_or_io, filename, content_type = "application/octet-stream")
|
212
259
|
return nil if file_or_io.closed?
|
213
260
|
|
214
261
|
data = file_or_io.read
|
@@ -217,7 +264,7 @@ module LWS::Generic
|
|
217
264
|
content_type: content_type,
|
218
265
|
byte_size: data.length,
|
219
266
|
checksum: checksum } }
|
220
|
-
res = @
|
267
|
+
res = @as_connection.post do |req|
|
221
268
|
req.url "rails/active_storage/direct_uploads"
|
222
269
|
req.headers["Accept"] = "application/json"
|
223
270
|
req.headers["Content-Type"] = "application/json"
|
@@ -226,7 +273,7 @@ module LWS::Generic
|
|
226
273
|
|
227
274
|
if res.success?
|
228
275
|
result = JSON.parse(res.body)
|
229
|
-
res = @
|
276
|
+
res = @as_connection.put do |req|
|
230
277
|
req.url result.dig("direct_upload", "url")
|
231
278
|
result.dig("direct_upload", "headers").each do |hdr, val|
|
232
279
|
req.headers[hdr] = val
|
@@ -240,6 +287,24 @@ module LWS::Generic
|
|
240
287
|
nil
|
241
288
|
end
|
242
289
|
end
|
243
|
-
end
|
244
290
|
|
291
|
+
# Downloads a file at the provided URL from the storage using the
|
292
|
+
# appropriate API tokens.
|
293
|
+
#
|
294
|
+
# This method can be used to download images/assets/etc. from LWS using
|
295
|
+
# URLs provided by attributes that end with +_url+.
|
296
|
+
# @param url [String] the URL to download the file from
|
297
|
+
# @return [String] the contents of the file
|
298
|
+
def self.download(url)
|
299
|
+
return nil if url.nil?
|
300
|
+
|
301
|
+
unless url.start_with? @lws_connection.url_prefix.to_s
|
302
|
+
raise ArgumentError,
|
303
|
+
"URL does not belong to this LWS app (endpoint: #{@lws_connection.url_prefix})"
|
304
|
+
end
|
305
|
+
|
306
|
+
res = @lws_connection.get(url)
|
307
|
+
res.body
|
308
|
+
end
|
309
|
+
end
|
245
310
|
end
|
data/lib/lws/apps/presence.rb
CHANGED
@@ -129,10 +129,18 @@ module LWS::Presence
|
|
129
129
|
attribute :capacity_used_precentage_tree
|
130
130
|
|
131
131
|
# @!attribute checkin_status
|
132
|
-
# @return ["available", "busy", "away",
|
132
|
+
# @return ["available", "busy", "away", nil]
|
133
133
|
# the presence status to set people to when checking in
|
134
134
|
attribute :checkin_status
|
135
135
|
|
136
|
+
# @!attribute checkout_alter_status
|
137
|
+
# @return ["available", "unavailable", "maintenance_cleaning",
|
138
|
+
# "maintenance_technical", "permanent_available",
|
139
|
+
# "permanent_unavailable", "permanent_maintenance_cleaning",
|
140
|
+
# "permanent_maintenance_technical", nil] the status to set the
|
141
|
+
# location to when someone checks out
|
142
|
+
attribute :checkout_alter_status
|
143
|
+
|
136
144
|
# @!attribute checkout_location
|
137
145
|
# @return [Location, nil] the location to move people to when they
|
138
146
|
# are checked out
|
@@ -157,13 +165,24 @@ module LWS::Presence
|
|
157
165
|
# @return [Array<Integer>] the IDs of the underlying locations of the location
|
158
166
|
attribute :descendant_ids
|
159
167
|
|
168
|
+
# @!attribute image_storage_id
|
169
|
+
# @return [String, nil] the storage ID of the image of the location
|
170
|
+
attribute :image_storage_id
|
171
|
+
|
172
|
+
# @!attribute image_url
|
173
|
+
# @note
|
174
|
+
# To be able retrieve this, the token needs to be passed via +X-Token+
|
175
|
+
# in the HTTP request headers!
|
176
|
+
# @return [String, nil] the URL of the image of the location
|
177
|
+
attribute :image_url
|
178
|
+
|
160
179
|
# @!attribute lat
|
161
180
|
# @return [Float] the latitude of the location
|
162
181
|
attribute :lat
|
163
182
|
|
164
183
|
# @!attribute logoff_time
|
165
|
-
#
|
166
|
-
#
|
184
|
+
# The format of the time is +HH:MM+ and should be interpreted in the time zone
|
185
|
+
# of the location (see also {#time_zone}).
|
167
186
|
# @return [String] the time everybody is automatically logged off
|
168
187
|
attribute :logoff_time
|
169
188
|
|
@@ -221,6 +240,13 @@ module LWS::Presence
|
|
221
240
|
# @return [Array<Reader>] the (RFID/code/ID/...) readers linked to this location
|
222
241
|
has_many :readers
|
223
242
|
|
243
|
+
# @!attribute status
|
244
|
+
# @return ["available", "unavailable", "maintenance_cleaning",
|
245
|
+
# "maintenance_technical", "permanent_available",
|
246
|
+
# "permanent_unavailable", "permanent_maintenance_cleaning",
|
247
|
+
# "permanent_maintenance_technical"] the status of the location
|
248
|
+
attribute :status
|
249
|
+
|
224
250
|
# @!attribute time_zone
|
225
251
|
# @return [String] the time zone of the location
|
226
252
|
attribute :time_zone
|
@@ -238,6 +264,17 @@ module LWS::Presence
|
|
238
264
|
use_api LWS::Presence.api
|
239
265
|
uri "locations/:location_id/maps(/:id)"
|
240
266
|
|
267
|
+
# @!attribute image_storage_id
|
268
|
+
# @return [String, nil] the storage ID of the image of the map
|
269
|
+
attribute :image_storage_id
|
270
|
+
|
271
|
+
# @!attribute image_url
|
272
|
+
# @note
|
273
|
+
# To be able retrieve this, the token needs to be passed via +X-Token+
|
274
|
+
# in the HTTP request headers!
|
275
|
+
# @return [String, nil] the URL of the image of the map
|
276
|
+
attribute :image_url
|
277
|
+
|
241
278
|
# @!attribute location
|
242
279
|
# @return [Location] the location the map belongs to
|
243
280
|
belongs_to :location
|
@@ -251,6 +288,9 @@ module LWS::Presence
|
|
251
288
|
attribute :name
|
252
289
|
|
253
290
|
# @!attribute picture_url
|
291
|
+
# @deprecated
|
292
|
+
# Unauthenticated retrieval of the picture will not longer be supported
|
293
|
+
# in upcoming releases of LWS. Use {#image_url} instead!
|
254
294
|
# @return [String, nil] the URL of the picture of the map
|
255
295
|
attribute :picture_url
|
256
296
|
|
@@ -359,6 +399,17 @@ module LWS::Presence
|
|
359
399
|
# @return [Array<Appointment>] the appointments involving the person
|
360
400
|
has_many :appointments
|
361
401
|
|
402
|
+
# @!attribute avatar_storage_id
|
403
|
+
# @return [String, nil] the storage ID of the avatar of the person
|
404
|
+
attribute :avatar_storage_id
|
405
|
+
|
406
|
+
# @!attribute avatar_url
|
407
|
+
# @note
|
408
|
+
# To be able retrieve this, the token needs to be passed via +X-Token+
|
409
|
+
# in the HTTP request headers!
|
410
|
+
# @return [String, nil] the URL of the avatar of the person
|
411
|
+
attribute :avatar_url
|
412
|
+
|
362
413
|
# @!attribute company
|
363
414
|
# @return [LWS::Auth::Company] the company the person belongs to
|
364
415
|
belongs_to :company, class_name: "LWS::Auth::Company"
|
@@ -422,6 +473,14 @@ module LWS::Presence
|
|
422
473
|
# @return [Integer] the ID of the location the person is located at
|
423
474
|
attribute :location_id
|
424
475
|
|
476
|
+
# @!attribute location_status_change_permissions
|
477
|
+
# @return [Array<"available", "unavailable", "maintenance_cleaning",
|
478
|
+
# "maintenance_technical", "permanent_available",
|
479
|
+
# "permanent_unavailable", "permanent_maintenance_cleaning",
|
480
|
+
# "permanent_maintenance_technical">] the location statuses the person
|
481
|
+
# will clear to available on check-in
|
482
|
+
attribute :location_status_change_permissions
|
483
|
+
|
425
484
|
# @!attribute long
|
426
485
|
# @return [Float, nil] the exact longitude of the person's location
|
427
486
|
attribute :long
|
@@ -457,6 +516,9 @@ module LWS::Presence
|
|
457
516
|
attribute :phone_mobile
|
458
517
|
|
459
518
|
# @!attribute picture_url
|
519
|
+
# @deprecated
|
520
|
+
# Unauthenticated retrieval of the picture will not longer be supported
|
521
|
+
# in upcoming releases of LWS. Use {#avatar_url} instead!
|
460
522
|
# @return [String, nil] the URL of the picture of the person
|
461
523
|
attribute :picture_url
|
462
524
|
|
@@ -512,4 +574,9 @@ module LWS::Presence
|
|
512
574
|
attribute :node
|
513
575
|
end
|
514
576
|
|
577
|
+
# (see Generic::Storage)
|
578
|
+
class Storage < LWS::Generic::Storage
|
579
|
+
use_api LWS::Presence.api
|
580
|
+
end
|
581
|
+
|
515
582
|
end
|
data/lib/lws/apps/resource.rb
CHANGED
@@ -108,6 +108,11 @@ module LWS::Resource
|
|
108
108
|
# @return [String] the URL of a preview of the collection
|
109
109
|
attribute :preview_url
|
110
110
|
|
111
|
+
# @!attribute processing
|
112
|
+
# @return [Boolean] whether the collection is being processed (i.e. it is
|
113
|
+
# not ready for use)
|
114
|
+
attribute :processing
|
115
|
+
|
111
116
|
# @!attribute uuid
|
112
117
|
# @return [String] the UUID used for unique file name generation
|
113
118
|
attribute :uuid
|
@@ -537,6 +542,21 @@ module LWS::Resource
|
|
537
542
|
# @!attribute parent_id
|
538
543
|
# @return [Integer, nil] the ID of the parent folder of the folder
|
539
544
|
attribute :parent_id
|
545
|
+
|
546
|
+
# @!attribute permission
|
547
|
+
# A UNIX-style permission that indicates whether the folder is shared and
|
548
|
+
# who can read/write in it:
|
549
|
+
# * 700: not shared (the default), only readable/writable by the
|
550
|
+
# associated account
|
551
|
+
# * 740: readable by anyone in the company
|
552
|
+
# * 770: readable/writeable by anyone in the company
|
553
|
+
# @return ["700", "740", "770"] the (share) permission of the folder
|
554
|
+
attribute :permission
|
555
|
+
|
556
|
+
# @!attribute temporary
|
557
|
+
# @return [Boolean] whether the folder is temporary and thus will be
|
558
|
+
# deleted after some time
|
559
|
+
attribute :temporary
|
540
560
|
end
|
541
561
|
|
542
562
|
end
|
data/lib/lws/version.rb
CHANGED
@@ -30,6 +30,8 @@ class TestDigitalSignageChannel < MiniTest::Test
|
|
30
30
|
assert_instance_of(Display, @channel.display)
|
31
31
|
assert_instance_of(Channel::Group, @channel.groups.first)
|
32
32
|
assert_instance_of(Player, @channel.players.first)
|
33
|
+
# FIXME: Missing endpoint in LWS
|
34
|
+
#assert_instance_of(Slide, @channel.slides.first)
|
33
35
|
assert_instance_of(Channel::Tag, @channel.tags.first)
|
34
36
|
assert_instance_of(Channel::TimeSchedule, @channel.time_schedule)
|
35
37
|
assert_instance_of(Channel::TimeScheduleOverride, @channel.time_schedule_overrides.first)
|
@@ -55,6 +57,8 @@ class TestDigitalSignageChannelGroup < MiniTest::Test
|
|
55
57
|
assert_instance_of(Channel, @channel_group.channels.first)
|
56
58
|
assert_instance_of(LWS::Auth::Company, @channel_group.company)
|
57
59
|
assert_instance_of(Channel::Group, @channel_group.parent)
|
60
|
+
# FIXME: Missing endpoint in LWS
|
61
|
+
#assert_instance_of(Slide, @channel_group.slides.first)
|
58
62
|
assert_instance_of(Channel::Group::Tag, @channel_group.tags.first)
|
59
63
|
assert_instance_of(Channel::TimeScheduleOverride, @channel_group.time_schedule_overrides.first)
|
60
64
|
end
|
@@ -157,7 +161,7 @@ class TestDigitalSignageChannelTimeScheduleOverride < MiniTest::Test
|
|
157
161
|
include LWS::DigitalSignage
|
158
162
|
|
159
163
|
def setup
|
160
|
-
@channel_time_schedule_override = Channel::TimeScheduleOverride.
|
164
|
+
@channel_time_schedule_override = Channel::TimeScheduleOverride.find(1)
|
161
165
|
end
|
162
166
|
|
163
167
|
def test_valid
|
@@ -526,64 +530,6 @@ class TestDigitalSignagePlayerConfigurationSetting < MiniTest::Test
|
|
526
530
|
|
527
531
|
end
|
528
532
|
|
529
|
-
class TestDigitalSignagePlayerFeedback < MiniTest::Test
|
530
|
-
|
531
|
-
include LWS::DigitalSignage
|
532
|
-
|
533
|
-
def setup
|
534
|
-
@player = Player.find(1)
|
535
|
-
# Player feedbacks only exist as child objects of players
|
536
|
-
@player_feedback = @player.feedbacks.first
|
537
|
-
end
|
538
|
-
|
539
|
-
def test_valid
|
540
|
-
refute_nil(@player_feedback)
|
541
|
-
assert_instance_of(Player::Feedback, @player_feedback)
|
542
|
-
refute_nil(@player_feedback.id)
|
543
|
-
end
|
544
|
-
|
545
|
-
def test_valid_associations
|
546
|
-
assert_instance_of(Player, @player_feedback.player)
|
547
|
-
assert_equal(@player, @player_feedback.player)
|
548
|
-
# FIXME: Missing branch_id field in LWS
|
549
|
-
#assert_instance_of(Player::Os::Branch::Release, @player_feedback.release)
|
550
|
-
# FIXME: Chained associations don't work yet in Spyke (#89)
|
551
|
-
#assert_instance_of(Player::Feedback::Result, @player_feedback.results.first)
|
552
|
-
end
|
553
|
-
|
554
|
-
end
|
555
|
-
|
556
|
-
class TestDigitalSignagePlayerFeedbackResult < MiniTest::Test
|
557
|
-
|
558
|
-
include LWS::DigitalSignage
|
559
|
-
|
560
|
-
def setup
|
561
|
-
@player = Player.find(1)
|
562
|
-
# Player feedbacks only exist as decendant objects of players
|
563
|
-
@player_feedback = @player.feedbacks.all.first
|
564
|
-
# Player feedback results only exist as decendant objects of player
|
565
|
-
# feedbacks
|
566
|
-
# FIXME: Chained associations don't work yet in Spyke (#89)
|
567
|
-
#@player_feedback_result = @player_feedback.results.first
|
568
|
-
end
|
569
|
-
|
570
|
-
# FIXME: Chained associations don't work yet in Spyke (#89)
|
571
|
-
#def test_valid
|
572
|
-
# refute_nil(@player_feedback_result)
|
573
|
-
# assert_instance_of(Player::Feedback::Result, @player_feedback_result)
|
574
|
-
# refute_nil(@player_feedback_result.id)
|
575
|
-
#end
|
576
|
-
|
577
|
-
# FIXME: Chained associations don't work yet in Spyke (#89)
|
578
|
-
#def test_valid_associations
|
579
|
-
# assert_instance_of(Player, @player_feedback_result.player)
|
580
|
-
# assert_equal(@player, @player_feedback_result.player)
|
581
|
-
# assert_instance_of(Player::Feedback, @player_feedback_result.feedback)
|
582
|
-
# assert_equal(@player_feedback, @player_feedback_result.feedback)
|
583
|
-
#end
|
584
|
-
|
585
|
-
end
|
586
|
-
|
587
533
|
class TestDigitalSignagePlayerLog < MiniTest::Test
|
588
534
|
|
589
535
|
include LWS::DigitalSignage
|
@@ -926,9 +872,7 @@ class TestDigitalSignagePlayerRequest < MiniTest::Test
|
|
926
872
|
assert_equal(@player, @player_request.player)
|
927
873
|
# FIXME: Chained associations don't work yet in Spyke (#89)
|
928
874
|
#if @player_request.processed
|
929
|
-
# if @player_request.
|
930
|
-
# assert_instance_of(Player::Feedback, @player_request.feedback)
|
931
|
-
# elsif @player_request.log.present?
|
875
|
+
# if @player_request.log.present?
|
932
876
|
# assert_instance_of(Player::Log, @player_request.log)
|
933
877
|
# elsif @player_request.screenshot.present?
|
934
878
|
# assert_instance_of(Player::Screenshot, @player_request.screenshot)
|
@@ -1002,6 +946,8 @@ class TestDigitalSignageSlide < MiniTest::Test
|
|
1002
946
|
|
1003
947
|
def test_valid_associations
|
1004
948
|
assert_instance_of(LWS::Auth::Account, @slide.account)
|
949
|
+
assert_instance_of(Channel, @slide.channels.first)
|
950
|
+
assert_instance_of(Channel::Group, @slide.channel_groups.first)
|
1005
951
|
assert_instance_of(LWS::Auth::Company, @slide.company)
|
1006
952
|
assert_instance_of(Layout, @slide.layout)
|
1007
953
|
end
|
data/test/generic_test.rb
CHANGED
@@ -106,6 +106,20 @@ class TestGenericModel < MiniTest::Test
|
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
|
+
def test_deep_dup
|
110
|
+
company = LWS::Auth::Company.find(1)
|
111
|
+
company_dup = company.deep_dup
|
112
|
+
|
113
|
+
# The object itself
|
114
|
+
refute_equal(company.object_id, company_dup.object_id)
|
115
|
+
# An object as attribute value
|
116
|
+
refute_equal(company.address.object_id, company_dup.address.object_id)
|
117
|
+
# A related object
|
118
|
+
refute_equal(company.contact_person.object_id, company_dup.contact_person.object_id)
|
119
|
+
# An item in array of related objects
|
120
|
+
refute_equal(company.accounts.first.object_id, company_dup.accounts.first.object_id)
|
121
|
+
end
|
122
|
+
|
109
123
|
end
|
110
124
|
|
111
125
|
class TestGenericConfiguration < MiniTest::Test
|
@@ -128,15 +142,37 @@ end
|
|
128
142
|
class TestGenericStorage < MiniTest::Test
|
129
143
|
|
130
144
|
# Generic class needs to be accessed under some kind of app
|
131
|
-
include LWS::
|
145
|
+
include LWS::Presence
|
132
146
|
|
133
147
|
def test_upload
|
134
148
|
data = StringIO.new("some file contents\n")
|
149
|
+
refute_nil(Storage.upload(data, "test.txt", "text/plain"))
|
150
|
+
|
151
|
+
# Test the deprecated method (for now)
|
135
152
|
refute_nil(Storage.create(data, "test.txt", "text/plain"))
|
136
153
|
|
137
154
|
# Also test using the default HTTP adapter.
|
138
155
|
reconfigure(http_persistent: false)
|
139
156
|
data = StringIO.new("some more file contents\n")
|
140
|
-
refute_nil(Storage.
|
157
|
+
refute_nil(Storage.upload(data, "test2.txt", "text/plain"))
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_download
|
161
|
+
location = Location.find(1)
|
162
|
+
refute_nil(location.image_url)
|
163
|
+
|
164
|
+
data = Storage.download(location.image_url)
|
165
|
+
assert(data.size > 0)
|
166
|
+
|
167
|
+
assert_nil(Storage.download(nil))
|
168
|
+
|
169
|
+
assert_raises(ArgumentError) do
|
170
|
+
Storage.download("https://doesnot.exist.tld/some/file")
|
171
|
+
end
|
172
|
+
|
173
|
+
# Also test using the default HTTP adapter.
|
174
|
+
reconfigure(http_persistent: false)
|
175
|
+
data = Storage.download(location.image_url)
|
176
|
+
assert(data.size > 0)
|
141
177
|
end
|
142
178
|
end
|
data/test/test_helper.rb
CHANGED
@@ -23,7 +23,7 @@ SimpleCov.at_exit do
|
|
23
23
|
result.format!
|
24
24
|
simplecov_test_suites = ['minitest']
|
25
25
|
parallel_offset = ENV['PARALLEL_TEST_GROUPS'] ? ENV['PARALLEL_TEST_GROUPS'].to_i - 1 : 0
|
26
|
-
minimum_coverage =
|
26
|
+
minimum_coverage = 95
|
27
27
|
# Count the number of commas in the command name to figure out how many result groups were combined into this result
|
28
28
|
if result.command_name.scan(/,/).size + 1 >= simplecov_test_suites.size + (parallel_offset * 2) # two parallel suites
|
29
29
|
# We only want to enforce minimum coverage after all test suites finish
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lws
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 7.
|
4
|
+
version: 7.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- LeftClick B.V.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday_middleware
|