lws 6.2.3 → 6.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 19a64229c67667d2f4be7cc06ef40cdb06433cb71ccea6699dadc9c288ce0ab2
4
- data.tar.gz: fe728933b84bd16634c2bff02b6633897708d28def2bd5c2d66e069bab0de5c1
3
+ metadata.gz: b78881916d363dc9fed830e0be6cecacc6b3928e699b047cb6004eab310f4ec8
4
+ data.tar.gz: 6de69f0e6437aeaf85cd1bdc1f6527a09cc0e9b33d200b377fb232ea932aa1b0
5
5
  SHA512:
6
- metadata.gz: 83a4ae6fa730a5039dcd360276c3c94e85d34b884f8ce16343ce7a18ea65e3c583efc1574610cdd5152d8a1e0e4c8a6cc3e3818b0aa3811f55769478915d1833
7
- data.tar.gz: 432272f9aae23ca1925a3ac1e2546146dcab56391808bcfd6fe625a6efb996b0449c72bf7fdce962b663e87007b26f97afc7cccdf346c413cc5fb0559f99f983
6
+ metadata.gz: 4f18155b4bf72c6572c9d2dac80d1bc2ad00b35bde4a4169806495fdd4deead5971d7da9c6b7954a7ec859d48a7ac067dfad71d1d8d92c79d557be760a90e2ce
7
+ data.tar.gz: a4935986105ecdf15dd71a6dc33b4b2d40ce5d14363eec241e87cef28904a3db94a542cbe37b9c1cd54955f6c5df60b49d83f11195fb733c414ea3c5ee084251
data/CHANGELOG.md CHANGED
@@ -1,15 +1,30 @@
1
1
  # LeftClick Web Services Changelog
2
2
 
3
- Up until v6.1.0, we used the standard Gem version numbering starting at v0.0.1.
4
- From v6.1.0 on the version will follow the API version of LWS in the major/minor
5
- part of te version.
3
+ Up until version 6.1.0, we used the standard Gem version numbering starting at
4
+ version 0.0.1. From version 6.1.0 on the version will follow the API version
5
+ of LWS in the major/minor part of te version.
6
+
7
+ The changelog follows the [Keep a Changelog] format from version 6.3.0 on.
8
+
9
+ ## [6.3.0] - 2019-09-05
10
+ ### Added
11
+ * Added slide, layout and related models to the DigitalSignage app (#12103)
12
+ * Added the `Storage` class to the DigitalSignage and Resource apps
13
+
14
+ ### Changed
15
+ * All non-persisted objects are always saved (even without changes)
16
+
17
+ ### Fixed
18
+ * Fixed typos in documentation
19
+ * Fixed some code style issues
20
+ * Default to an empty object if the API provides no data
6
21
 
7
22
  ## v6.2.3
8
23
 
9
24
  * Move common attributes to the generic model and add `url`/`url_html` (#12004)
10
25
  * Add password expiration attributes to the `Company` and `User` model of
11
- the Auth app
12
- * Add new attributes to the `Collection` model of the Resource app
26
+ the Auth app (#12012)
27
+ * Add new attributes to the `Collection` model of the Resource app (#12012)
13
28
 
14
29
  ## v6.2.2.1
15
30
 
@@ -122,3 +137,6 @@ part of te version.
122
137
  ## v0.0.1
123
138
 
124
139
  Initial release
140
+
141
+ [Keep a Changelog]: https://keepachangelog.com/en/1.0.0/
142
+ [6.3.0]: https://gitlab.leftclick.eu/platform/ruby-lws/compare/v6.2.3...v6.3.0
data/README.md CHANGED
@@ -97,7 +97,7 @@ arguments. It uses the production environment per default using the token
97
97
  provided by a command-line argument. These defaults can be overriden using
98
98
  the configuration. For example, to rename a map:
99
99
 
100
- ```
100
+ ```sh
101
101
  $ lwsconsole -t "my_token" -a maps
102
102
  [1] lwsconsole(LWS::Maps)> Map.all.map(&:name)
103
103
  => ["Gebouw 1",
data/lib/lws.rb CHANGED
@@ -38,7 +38,7 @@ module LWS
38
38
  # The list of supported apps (web service libraries) loaded by
39
39
  # {.setup}.
40
40
  SUPPORTED_APPS = [:generic, :auth, :corporate_website, :digital_signage,
41
- :maps, :presence, :resource, :ticket]
41
+ :maps, :presence, :resource, :ticket].freeze
42
42
 
43
43
  # @return [Config] the API configuration for the web services
44
44
  mattr_reader :config
@@ -33,6 +33,11 @@ module LWS::DigitalSignage
33
33
  use_api LWS::DigitalSignage.api
34
34
  end
35
35
 
36
+ # (see Generic::Storage)
37
+ class Storage < LWS::Generic::Storage
38
+ use_api LWS::DigitalSignage.api
39
+ end
40
+
36
41
  ### App specific classes
37
42
 
38
43
  # = The channel class
@@ -60,7 +65,7 @@ module LWS::DigitalSignage
60
65
  belongs_to :display, class_name: "LWS::DigitalSignage::Display"
61
66
  # :nocov:
62
67
  def display
63
- # Create a dummy method so that the original #display method is not used
68
+ # Create a dummy method so that the original #display method is not used
64
69
  association(:display).load
65
70
  end
66
71
  # :nocov:
@@ -147,7 +152,7 @@ module LWS::DigitalSignage
147
152
  # @!attribute parent
148
153
  # @return [Channel::Group, nil] the parent group of the channel group
149
154
  belongs_to :parent, class_name: "LWS::DigitalSignage::Channel::Group",
150
- foreign_key: "parent_id",
155
+ foreign_key: :parent_id,
151
156
  uri: "channel/groups/:id"
152
157
 
153
158
  # @!attribute parent_id
@@ -417,7 +422,7 @@ module LWS::DigitalSignage
417
422
  belongs_to :display, class_name: "LWS::DigitalSignage::Display"
418
423
  # :nocov:
419
424
  def display
420
- # Create a dummy method so that the original #display method is not used
425
+ # Create a dummy method so that the original #display method is not used
421
426
  association(:display).load
422
427
  end
423
428
  # :nocov:
@@ -447,7 +452,7 @@ module LWS::DigitalSignage
447
452
  # @!attribute aspect_ratio [r]
448
453
  # The aspect ratio is recalculated immediately when the width and/or
449
454
  # height of the resolution changes.
450
- #
455
+ #
451
456
  # @return [String] the aspect ratio of the resolution
452
457
  attribute :aspect_ratio
453
458
 
@@ -476,6 +481,317 @@ module LWS::DigitalSignage
476
481
  attribute :width
477
482
  end
478
483
 
484
+ # = The layout class
485
+ class Layout < LWS::Generic::Model
486
+ use_api LWS::DigitalSignage.api
487
+
488
+ # @!attribute id [r]
489
+ # @return [Integer] the (unique) ID of the layout
490
+ attribute :id
491
+
492
+ # @!attribute categories
493
+ # @return [Array<Layout::Category>] the categories associated with
494
+ # the layout
495
+ # FIXME: Missing endpoint in LWS
496
+ has_many :categories, class_name: "LWS::DigitalSignage::Layout::Category",
497
+ uri: "layout/:layout_id/categories(/:id)"
498
+
499
+ # @!attribute company
500
+ # @return [LWS::Auth::Company] the company the layout belongs to
501
+ belongs_to :company, class_name: "LWS::Auth::Company"
502
+
503
+ # @!attribute company_id
504
+ # @return [Integer] the ID of the company the layout belongs to
505
+ attribute :company_id
506
+
507
+ # @!attribute default_duration
508
+ # @return [5..3600] the default duration of a slide created from the layout
509
+ attribute :default_duration
510
+
511
+ # @!attribute description
512
+ # @return [String, nil] the description of the layout
513
+ attribute :description
514
+
515
+ # @!attribute favorite
516
+ # @return [Boolean] whether the layout is a favorite for the current account
517
+ attribute :favorite
518
+
519
+ # @!attribute name
520
+ # @return [String] the name of the layout
521
+ attribute :name
522
+
523
+ # @!attribute parent
524
+ # @return [Layout, nil] the parent of the layout
525
+ # FIXME: Missing parent_id field in LWS
526
+ belongs_to :parent, class_name: "LWS::DigitalSignage::Layout",
527
+ foreign_key: :parent_id,
528
+ uri: "layouts/:id"
529
+
530
+ # @!attribute parent_id
531
+ # @return [Integer, nil] the ID of the parent of the layout
532
+ attribute :parent_id
533
+
534
+ # @!attribute priority
535
+ # @return [Boolean] whether the layout has priority over others
536
+ attribute :priority
537
+
538
+ # @!attribute slides
539
+ # @return [Array<Slide>] the slides using the layout
540
+ has_many :slides, class_name: "LWS::DigitalSignage::Slide",
541
+ uri: "layouts/:layout_id/slides(/:id)"
542
+
543
+ # @!attribute trans
544
+ # @return ["cut", "fadein", "zoomin", "slidein"] the transition of the
545
+ # entire layout
546
+ attribute :trans
547
+
548
+ # @!attribute trans_direction
549
+ # @return ["left", "right", "up", "down"] the direction of the transition
550
+ # of the entire layout
551
+ attribute :trans_direction
552
+
553
+ # @!attribute trans_duration
554
+ # @return [Integer] the duration of the transition of the entire layout
555
+ attribute :trans_duration
556
+
557
+ # @!attribute versions
558
+ # @return [Array<Version>] the versions of the layout
559
+ has_many :versions, class_name: "LWS::DigitalSignage::Layout::Version",
560
+ uri: "layouts/:layout_id/versions(/:id)"
561
+
562
+ # @!attribute created_at [r]
563
+ # @return [String] the timestamp of when the layout was created
564
+ attribute :created_at
565
+
566
+ # @!attribute updated_at [r]
567
+ # @return [String] the timestamp of when the layout was last updated
568
+ attribute :updated_at
569
+ end
570
+
571
+ # = The layout category class
572
+ class Layout::Category < LWS::Generic::Model
573
+ use_api LWS::DigitalSignage.api
574
+ uri "layout/categories(/:id)"
575
+
576
+ # @!attribute id [r]
577
+ # @return [Integer] the (unique) ID of the layout category
578
+ attribute :id
579
+
580
+ # @!attribute description
581
+ # @return [String, nil] the description of the layout category
582
+ attribute :description
583
+
584
+ # @!attribute layouts
585
+ # @return [Array<Layout>] the layouts that are associated with
586
+ # the category
587
+ # FIXME: Missing endpoint in LWS
588
+ has_many :layouts, class_name: "LWS::DigitalSignage::Layout",
589
+ uri: "layout/categories/:category_id/layouts(/:id)"
590
+
591
+ # @!attribute name
592
+ # @return [String] the name of the layout category
593
+ attribute :name
594
+
595
+ # @!attribute created_at [r]
596
+ # @return [String] the timestamp of when the layout category was created
597
+ attribute :created_at
598
+
599
+ # @!attribute updated_at [r]
600
+ # @return [String] the timestamp of when the layout category was last updated
601
+ attribute :updated_at
602
+ end
603
+
604
+ # = The layout element class
605
+ #
606
+ # @note
607
+ # This class is only used within the context of the {Layout::Version} class.
608
+ class Layout::Element < LWS::Generic::Model
609
+ use_api LWS::DigitalSignage.api
610
+
611
+ # @!attribute id [r]
612
+ # @return [Integer] the (unique) ID of the layout element
613
+ attribute :id
614
+
615
+ # @!attribute asset_storage_ids
616
+ # @return [Array<String>] the storage IDs of the assets of the layout element
617
+ attribute :asset_storage_ids
618
+
619
+ # @!attribute asset_urls
620
+ # This is a list of mappings of the asset filename (key +"filename"+) to the
621
+ # asset URL (key +"url"+).
622
+ #
623
+ # @return [Array<Hash{String => String}>] the assets of the layout element
624
+ attribute :asset_urls
625
+
626
+ # @!attribute customizables
627
+ # @return [Array<Layout::Element::Customizable>] the customizable properties
628
+ # of the layout element
629
+ has_many :customizables, class_name: "LWS::DigitalSignage::Layout::Element::Customizable"
630
+
631
+ # @!attribute index
632
+ # @return [Integer, nil] the index of the element within the list of
633
+ # layout elements of the associated layout version
634
+ attribute :index
635
+
636
+ # @!attribute klass
637
+ # @return [String] the class of the layout element
638
+ attribute :klass
639
+
640
+ # @!attribute parent
641
+ # @return [Layout, nil] the parent of the layout element
642
+ # FIXME: Missing endpoint in LWS
643
+ belongs_to :parent, class_name: "LWS::DigitalSignage::Layout::Element",
644
+ foreign_key: :parent_id
645
+
646
+ # @!attribute parent_id
647
+ # @return [Integer, nil] the ID of the parent of the layout element
648
+ attribute :parent_id
649
+
650
+ # @!attribute properties
651
+ # @return [Array<Layout::Element::Property>] the properties of the layout
652
+ # element
653
+ has_many :properties, class_name: "LWS::DigitalSignage::Layout::Element::Property"
654
+
655
+ # @!attribute version
656
+ # @return [Layout::Verion] the layout version that contains the element
657
+ # FIXME: Missing endpoint in LWS
658
+ belongs_to :version, class_name: "LWS::DigitalSignage::Layout::Version",
659
+ foreign_key: :layout_version_id
660
+
661
+ # @!attribute created_at [r]
662
+ # @return [String] the timestamp of when the layout element was created
663
+ attribute :created_at
664
+
665
+ # @!attribute updated_at [r]
666
+ # @return [String] the timestamp of when the layout element was last
667
+ # updated
668
+ attribute :updated_at
669
+ end
670
+
671
+ # = The layout element customizable class
672
+ #
673
+ # @note
674
+ # This class is only used within the context of the {Layout::Element} class.
675
+ class Layout::Element::Customizable < LWS::Generic::Model
676
+ use_api LWS::DigitalSignage.api
677
+
678
+ # @!attribute id [r]
679
+ # @return [Integer] the (unique) ID of the layout element customizable
680
+ # property
681
+ attribute :id
682
+
683
+ # @!attribute attr
684
+ # @return [String] the customizable attribute/property name
685
+ attribute :attr
686
+
687
+ # @!attribute element
688
+ # @return [Layout::element] the layout element the customizable property
689
+ # is for
690
+ belongs_to :element, class_name: "LWS::DigitalSignage::Layout::Element"
691
+
692
+ # @!attribute element_id
693
+ # @return [Integer] the ID of the layout element the customizable is for
694
+ attribute :element_id
695
+
696
+ # @!attribute hint_message
697
+ # @return [String] the customizable attribute/property value
698
+ attribute :hint_message
699
+
700
+ # @!attribute presets
701
+ # @return [Array<Hash>] the presets for attribute values (label to value)
702
+ attribute :presets
703
+
704
+ # @!attribute uuid
705
+ # @return [String] the UUID of the customizable attribute/property
706
+ attribute :uuid
707
+
708
+ # @!attribute created_at [r]
709
+ # @return [String] the timestamp of when the layout element customizable
710
+ # was created
711
+ attribute :created_at
712
+
713
+ # @!attribute updated_at [r]
714
+ # @return [String] the timestamp of when the layout element customizable
715
+ # was last updated
716
+ attribute :updated_at
717
+ end
718
+
719
+ # = The layout element property class
720
+ #
721
+ # @note
722
+ # This class is only used within the context of the {Layout::Element} class.
723
+ class Layout::Element::Property < LWS::Generic::Model
724
+ use_api LWS::DigitalSignage.api
725
+
726
+ # @!attribute id [r]
727
+ # @return [Integer] the (unique) ID of the layout element property
728
+ attribute :id
729
+
730
+ # @!attribute attr
731
+ # @return [String] the attribute/property name
732
+ attribute :attr
733
+
734
+ # @!attribute element
735
+ # @return [Layout::Element] the layout element the property
736
+ # is for
737
+ belongs_to :element, class_name: "LWS::DigitalSignage::Layout::Element"
738
+
739
+ # @!attribute element_id
740
+ # @return [Integer] the ID of the layout element the property is for
741
+ attribute :element_id
742
+
743
+ # @!attribute locked
744
+ # @return [Boolean] whether the attribute/property value is locked
745
+ attribute :locked
746
+
747
+ # @!attribute value
748
+ # @return [String] the attribute/property value
749
+ attribute :value
750
+
751
+ # @!attribute created_at [r]
752
+ # @return [String] the timestamp of when the layout element was created
753
+ attribute :created_at
754
+
755
+ # @!attribute updated_at [r]
756
+ # @return [String] the timestamp of when the layout element was last
757
+ # updated
758
+ attribute :updated_at
759
+ end
760
+
761
+ # = The layout version class
762
+ #
763
+ # @note
764
+ # This class is only used within the context of the {Layout} class.
765
+ class Layout::Version < LWS::Generic::Model
766
+ use_api LWS::DigitalSignage.api
767
+ uri "layout/Layout_id/versions(/:id)"
768
+
769
+ # @!attribute id [r]
770
+ # @return [Integer] the (unique) ID of the layout version
771
+ attribute :id
772
+
773
+ # @!attribute elements
774
+ # @return [Array<Layout::Element>] the elements contained in the layout
775
+ # version
776
+ has_many :elements, class_name: "LWS::DigitalSignage::Layout::Element"
777
+
778
+ # @!attribute layout
779
+ # @return [Layout] the layout the layout version is for
780
+ belongs_to :layout
781
+
782
+ # @!attribute layout_id
783
+ # @return [Integer] the ID of the layout the layout version is for
784
+ attribute :layout_id
785
+
786
+ # @!attribute created_at [r]
787
+ # @return [String] the timestamp of when the layout version was created
788
+ attribute :created_at
789
+
790
+ # @!attribute updated_at [r]
791
+ # @return [String] the timestamp of when the layout version was last updated
792
+ attribute :updated_at
793
+ end
794
+
479
795
  # = The player class
480
796
  class Player < LWS::Generic::Model
481
797
  use_api LWS::DigitalSignage.api
@@ -556,7 +872,7 @@ module LWS::DigitalSignage
556
872
  # @!attribute release_channel_id
557
873
  # @return [Integer] the ID of the player OS release channel used by the
558
874
  # player
559
- attribute :releasee_channel_id
875
+ attribute :release_channel_id
560
876
 
561
877
  # @!attribute requests
562
878
  # @return [Array<Player::Feedback>] the requests for the player
@@ -613,7 +929,7 @@ module LWS::DigitalSignage
613
929
  # @!attribute supplier
614
930
  # @return [LWS::Auth::Company] the supplier of the component part
615
931
  belongs_to :supplier, class_name: "LWS::Auth::Company",
616
- foreign_key: "supplier_id",
932
+ foreign_key: :supplier_id,
617
933
  uri: "companies/:id"
618
934
 
619
935
  # @!attribute supplier_id
@@ -1368,7 +1684,7 @@ module LWS::DigitalSignage
1368
1684
  # @!attribute screenshot
1369
1685
  # This field should be set once the action has been processed (see
1370
1686
  # {#processed}) and the action is +"send_screenshot"+.
1371
- #
1687
+ #
1372
1688
  # @return [Player::Screenshot, nil] the player screenshot as a response to
1373
1689
  # the action request +"send_screenshot"+
1374
1690
  belongs_to :screenshot, class_name: "LWS::DigitalSignage::Player::Screenshot",
@@ -1429,6 +1745,128 @@ module LWS::DigitalSignage
1429
1745
  # @!attribute value
1430
1746
  # @return [String, nil] the value of the player tag
1431
1747
  attribute :value
1748
+
1749
+ # @!attribute created_at [r]
1750
+ # @return [String] the timestamp of when the player tag was created
1751
+ attribute :created_at
1752
+
1753
+ # @!attribute updated_at [r]
1754
+ # @return [String] the timestamp of when the player tag was last updated
1755
+ attribute :updated_at
1756
+ end
1757
+
1758
+ # = The slide class
1759
+ class Slide < LWS::Generic::Model
1760
+ use_api LWS::DigitalSignage.api
1761
+
1762
+ # @!attribute id [r]
1763
+ # @return [Integer] the (unique) ID of the slide
1764
+ attribute :id
1765
+
1766
+ # @!attribute account
1767
+ # @return [LWS::Auth::Account] the account used for creating the slide
1768
+ belongs_to :account, class_name: "LWS::Auth::Account"
1769
+
1770
+ # @!attribute account_id
1771
+ # @return [Integer] the ID of the account used for creating the slide
1772
+ attribute :account_id
1773
+
1774
+ # @!attribute company
1775
+ # @return [LWS::Auth::Company] the company the slide belongs to
1776
+ belongs_to :company, class_name: "LWS::Auth::Company"
1777
+
1778
+ # @!attribute company_id
1779
+ # @return [Integer] the ID of the company the slide belongs to
1780
+ attribute :company_id
1781
+
1782
+ # @!attribute layout
1783
+ # @return [LWS::Layout] the layout the slide uses
1784
+ belongs_to :layout
1785
+
1786
+ # @!attribute layout_id
1787
+ # @return [Integer] the ID of the layout the slide uses
1788
+ attribute :layout_id
1789
+
1790
+ # @!attribute name
1791
+ # @return [String] the name of the slide
1792
+ attribute :name
1793
+
1794
+ # @!attribute order_priority
1795
+ # @return [Integer] the order priority within a playlist for a channel
1796
+ attribute :order_priority
1797
+
1798
+ # @!attribute schedules
1799
+ # @return [Array<Schedule>] the slide schedules that apply for the slide
1800
+ # FIXME: Missing endpoint in LWS
1801
+ has_many :schedules, class_name: "LWS::DigitalSignage::Slide::Schedule"
1802
+
1803
+ # @!attribute created_at [r]
1804
+ # @return [string] the timestamp of when the slide was created
1805
+ attribute :created_at
1806
+
1807
+ # @!attribute updated_at [r]
1808
+ # @return [string] the timestamp of when the slide was last updated
1809
+ attribute :updated_at
1810
+ end
1811
+
1812
+ # = The slide schedule class
1813
+ class Slide::Schedule < LWS::Generic::Model
1814
+ use_api LWS::DigitalSignage.api
1815
+
1816
+ # @!attribute id [r]
1817
+ # @return [Integer] the (unique) ID of the slide schedule
1818
+ attribute :id
1819
+
1820
+ # @!attribute date_end
1821
+ # @return [Date] the date after which the slide schedule becomes inactive
1822
+ attribute :date_end
1823
+
1824
+ # @!attribute date_start
1825
+ # @return [Date] the date on which the slide schedule becomes active
1826
+ attribute :date_start
1827
+
1828
+ # @!attribute duration
1829
+ # @return [Integer] the duration of the slide within the slide schedule
1830
+ attribute :duration
1831
+
1832
+ # @!attribute name
1833
+ # @return [String] the name of the slide schedule
1834
+ attribute :name
1835
+
1836
+ # @!attribute priority
1837
+ # @return ["low", "normal", "high"] the priority of the slide schedule
1838
+ # with respect to other slide schedules
1839
+ attribute :priority
1840
+
1841
+ # @!attribute skip_every
1842
+ # @return [Integer] how many times to skip the slide within the slide
1843
+ # schedule
1844
+ attribute :skip_every
1845
+
1846
+ # @!attribute slides
1847
+ # @return [Array<Slide>] the slides that use the slide schedule
1848
+ # FIXME: Missing endpoint in LWS
1849
+ has_many :slides, class: "LWS::DigitalSignage::Slide"
1850
+
1851
+ # @!attribute time_end
1852
+ # @return [Time] the time after which the slide schedule becomes inactive
1853
+ attribute :time_end
1854
+
1855
+ # @!attribute time_start
1856
+ # @return [Time] the time on which the slide schedule becomes active
1857
+ attribute :time_start
1858
+
1859
+ # @!attribute visible
1860
+ # @return [Boolean] whether the slide is visible within the slide schedule
1861
+ attribute :visible
1862
+
1863
+ # @!attribute created_at [r]
1864
+ # @return [string] the timestamp of when the slide schedule was created
1865
+ attribute :created_at
1866
+
1867
+ # @!attribute updated_at [r]
1868
+ # @return [string] the timestamp of when the slide schedule was last updated
1869
+ attribute :updated_at
1432
1870
  end
1433
1871
 
1434
1872
  end
@@ -144,7 +144,7 @@ module LWS::Generic
144
144
  # @return [Hash, Trueclass] a mapping of attributes names to values,
145
145
  # or +true+ if no save action was necessary.
146
146
  def save
147
- return true unless changed?
147
+ return true unless changed? || !persisted?
148
148
  result = super
149
149
  changes_applied if result
150
150
  result
@@ -175,4 +175,72 @@ module LWS::Generic
175
175
  attribute :updated_at
176
176
  end
177
177
 
178
+ # = The storage class
179
+ #
180
+ # This class can be used to upload files for this app module.
181
+ class Storage
182
+ # @!visibility private
183
+ def self.use_api(api)
184
+ @connection = Faraday.new(url: api.url_prefix) do |c|
185
+ config = LWS.config
186
+
187
+ # Request
188
+ c.request :json
189
+
190
+ # Response
191
+ c.use LWS::JSONLogger, config.logger if config.json_debug
192
+ c.use LWS::HTTPLogger, config.logger, config.http_debug_headers if config.http_debug
193
+
194
+ # Adapter
195
+ if config.http_persistent
196
+ c.adapter :net_http_persistent
197
+ else
198
+ c.adapter Faraday.default_adapter
199
+ end
200
+ end
201
+ end
202
+
203
+ # Uploads a file (or IO object) to the storage of the app module.
204
+ #
205
+ # The resulting storage ID can be used in model attributes that refer to storage
206
+ # IDs (e.g. {DigitalSignage::Layout::Element#asset_storage_ids}).
207
+ #
208
+ # @param file_or_io [File, IO] the file (or IO object) to upload
209
+ # @param filename [String] the filename to use for the uploaded file/IO object
210
+ # @param content_type [String] the content type of the uploaded file/IO object
211
+ # @return [String, nil] the storage ID (if successful)
212
+ def self.create(file_or_io, filename, content_type = "application/octet-stream")
213
+ return nil if file_or_io.closed?
214
+
215
+ data = file_or_io.read
216
+ checksum = Digest::MD5.base64digest(data)
217
+ body = { blob: { filename: filename,
218
+ content_type: content_type,
219
+ byte_size: data.length,
220
+ checksum: checksum } }
221
+ res = @connection.post do |req|
222
+ req.url "rails/active_storage/direct_uploads"
223
+ req.headers["Accept"] = "application/json"
224
+ req.headers["Content-Type"] = "application/json"
225
+ req.body = body.to_json
226
+ end
227
+
228
+ if res.success?
229
+ result = JSON.parse(res.body)
230
+ res = @connection.put do |req|
231
+ req.url result.dig("direct_upload", "url")
232
+ result.dig("direct_upload", "headers").each do |hdr, val|
233
+ req.headers[hdr] = val
234
+ end
235
+ req.body = data
236
+ end
237
+ if res.success?
238
+ result["signed_id"]
239
+ end
240
+ else
241
+ nil
242
+ end
243
+ end
244
+ end
245
+
178
246
  end
@@ -33,6 +33,11 @@ module LWS::Resource
33
33
  use_api LWS::Resource.api
34
34
  end
35
35
 
36
+ # (see Generic::Storage)
37
+ class Storage < LWS::Generic::Storage
38
+ use_api LWS::Resource.api
39
+ end
40
+
36
41
  ### App specific classes
37
42
 
38
43
  # = The collection class
@@ -168,7 +173,7 @@ module LWS::Resource
168
173
  # = The collection post class
169
174
  class Collection::Post < Collection::Item
170
175
  use_api LWS::Resource.api
171
-
176
+
172
177
  # @!attribute author
173
178
  # @return [String] the author of the post
174
179
  attribute :author
@@ -176,11 +181,11 @@ module LWS::Resource
176
181
  # @!attribute avatar
177
182
  # @return [Hash] the URL information of the avatar image of the post
178
183
  attribute :avatar
179
-
184
+
180
185
  # @!attribute category
181
186
  # @return [String] the category of the post
182
187
  attribute :category
183
-
188
+
184
189
  # @!attribute comments
185
190
  # @return [String] the comments of the post
186
191
  attribute :comments
@@ -188,7 +193,7 @@ module LWS::Resource
188
193
  # @!attribute description
189
194
  # @return [String] the description of the post
190
195
  attribute :description
191
-
196
+
192
197
  # @!attribute description
193
198
  # @return [String] the description of the post
194
199
  attribute :enclosures
@@ -199,29 +204,29 @@ module LWS::Resource
199
204
 
200
205
  # @!attribute handle
201
206
  # @return [String] the handle of the post
202
- attribute :handle
207
+ attribute :handle
203
208
 
204
209
  # @!attribute link
205
210
  # @return [String] the link of the post
206
211
  attribute :link
207
-
212
+
208
213
  # @!attribute link
209
214
  # @return [String] the timestamp of the modification date of the post
210
215
  attribute :modification_date
211
-
216
+
212
217
  # @!attribute order_priority
213
218
  # @return [Integer] the order priority of the of the post (ascending;
214
219
  # 0 is lowers)
215
220
  attribute :order_priority
216
-
221
+
217
222
  # @!attribute link
218
223
  # @return [String] the timestamp of the publication date of the post
219
224
  attribute :publication_date
220
-
225
+
221
226
  # @!attribute source_url
222
227
  # @return [String] the source URL of the post
223
228
  attribute :source_url
224
-
229
+
225
230
  # @!attribute summary
226
231
  # @return [String] the summary of the post
227
232
  attribute :summary
@@ -376,7 +381,7 @@ module LWS::Resource
376
381
 
377
382
  # @!attribute observation
378
383
  # @return [Boolean] whether the weather location forecast is a
379
- # current observation
384
+ # current observation
380
385
  attribute :observation
381
386
 
382
387
  # @!attribute temperature
@@ -50,7 +50,7 @@ module LWS
50
50
  end
51
51
 
52
52
  end
53
-
53
+
54
54
  end
55
55
 
56
56
  end
@@ -18,7 +18,7 @@ module LWS
18
18
  class JSONParser < Faraday::Response::Middleware
19
19
 
20
20
  def parse(body)
21
- data = MultiJson.load(body, symbolize_keys: true)
21
+ data = MultiJson.load(body, symbolize_keys: true) || {}
22
22
  metadata = data.delete(:metadata)
23
23
  errors = data.delete(:errors)
24
24
 
@@ -10,7 +10,7 @@
10
10
 
11
11
 
12
12
  module LWS
13
-
13
+
14
14
  module Middleware
15
15
 
16
16
  # @private
data/lib/lws/version.rb CHANGED
@@ -13,6 +13,6 @@ module LWS
13
13
 
14
14
  # The LWS library version.
15
15
  # @note The major and minor version parts match the LWS API version!
16
- VERSION = '6.2.3'.freeze
16
+ VERSION = '6.3.0'.freeze
17
17
 
18
18
  end
@@ -240,6 +240,163 @@ class TestDigitalSignageDisplayResolution < MiniTest::Test
240
240
 
241
241
  end
242
242
 
243
+ class TestDigitalSignageLayout < MiniTest::Test
244
+
245
+ include LWS::DigitalSignage
246
+
247
+ def setup
248
+ @layout = Layout.find(1)
249
+ end
250
+
251
+ def test_valid
252
+ refute_nil(@layout)
253
+ assert_instance_of(Layout, @layout)
254
+ refute_nil(@layout.id)
255
+ end
256
+
257
+ def test_valid_associations
258
+ # FIXME: Missing endpoint in LWS
259
+ #assert_instance_of(Layout::Category, @layout.categories.first)
260
+ # FIXME: Missing parent_id field in LWS
261
+ #assert_instance_of(Layout, @layout.parent)
262
+ # FIXME: Missing endpoint in LWS
263
+ #assert_instance_of(Slide, @layout.slides.first)
264
+ assert_instance_of(Layout::Version, @layout.versions.find(1))
265
+ end
266
+
267
+ end
268
+
269
+ class TestDigitalSignageLayoutCategory < MiniTest::Test
270
+
271
+ include LWS::DigitalSignage
272
+
273
+ def setup
274
+ @layout_category = Layout::Category.find(1)
275
+ end
276
+
277
+ def test_valid
278
+ refute_nil(@layout_category)
279
+ assert_instance_of(Layout::Category, @layout_category)
280
+ refute_nil(@layout_category.id)
281
+ end
282
+
283
+ def test_valid_associations
284
+ # FIXME: Missing endpoint in LWS
285
+ #assert_instance_of(Layout, @layout_categories.layouts.first)
286
+ end
287
+
288
+ end
289
+
290
+ class TestDigitalSignageLayoutElement < MiniTest::Test
291
+
292
+ include LWS::DigitalSignage
293
+
294
+ def setup
295
+ @layout = Layout.find(1)
296
+ # Layout versions only exist as child objects of layouts
297
+ @layout_version = @layout.versions.find(1)
298
+ # Layout elements only exist as child objects of layout versions
299
+ @layout_element = @layout_version.elements.first
300
+ end
301
+
302
+ def test_valid
303
+ refute_nil(@layout_element)
304
+ assert_instance_of(Layout::Element, @layout_element)
305
+ refute_nil(@layout_element.id)
306
+ end
307
+
308
+ def test_valid_associations
309
+ assert_instance_of(Layout::Element::Customizable, @layout_element.customizables.first)
310
+ assert_instance_of(Layout::Element::Property, @layout_element.properties.first)
311
+ # FIXME: Missing endpoint in LWS
312
+ #assert_instance_of(Layout::Version, @layout_element.version)
313
+ #assert_equal(@layout_version, @layout_element.version)
314
+ # FIXME: Missing endpoint in LWS
315
+ #assert_instance_of(Layout::Element, @layout_element.parent)
316
+ end
317
+
318
+ end
319
+
320
+ class TestDigitalSignageLayoutElementCustomizable < MiniTest::Test
321
+
322
+ include LWS::DigitalSignage
323
+
324
+ def setup
325
+ @layout = Layout.find(1)
326
+ # Layout versions only exist as child objects of layouts
327
+ @layout_version = @layout.versions.find(1)
328
+ # Layout elements only exist as child objects of layout versions
329
+ @layout_element = @layout_version.elements.first
330
+ # Layout element customizables only exist as child objects of layout elements
331
+ @layout_element_customizable = @layout_element.customizables.first
332
+ end
333
+
334
+ def test_valid
335
+ refute_nil(@layout_element_customizable)
336
+ assert_instance_of(Layout::Element::Customizable, @layout_element_customizable)
337
+ refute_nil(@layout_element_customizable.id)
338
+ end
339
+
340
+ def test_valid_associations
341
+ # FIXME: Missing endpoint in LWS
342
+ #assert_instance_of(Layout::Element, @layout_element_customizable.element)
343
+ #assert_equal(@layout_element, @layout_element_customizable.element)
344
+ end
345
+
346
+ end
347
+
348
+ class TestDigitalSignageLayoutElementProperty < MiniTest::Test
349
+
350
+ include LWS::DigitalSignage
351
+
352
+ def setup
353
+ @layout = Layout.find(1)
354
+ # Layout versions only exist as child objects of layouts
355
+ @layout_version = @layout.versions.find(1)
356
+ # Layout elements only exist as child objects of layout versions
357
+ @layout_element = @layout_version.elements.first
358
+ # Layout element properties only exist as child objects of layout elements
359
+ @layout_element_property = @layout_element.properties.first
360
+ end
361
+
362
+ def test_valid
363
+ refute_nil(@layout_element_property)
364
+ assert_instance_of(Layout::Element::Property, @layout_element_property)
365
+ refute_nil(@layout_element_property.id)
366
+ end
367
+
368
+ def test_valid_associations
369
+ # FIXME: Missing endpoint in LWS
370
+ #assert_instance_of(Layout::Element, @layout_element_property.element)
371
+ #assert_equal(@layout_element, @layout_element_property.element)
372
+ end
373
+
374
+ end
375
+
376
+ class TestDigitalSignageLayoutVersion < MiniTest::Test
377
+
378
+ include LWS::DigitalSignage
379
+
380
+ def setup
381
+ @layout = Layout.find(1)
382
+ # Layout versions only exist as child objects of layouts
383
+ @layout_version = @layout.versions.find(1)
384
+ end
385
+
386
+ def test_valid
387
+ refute_nil(@layout_version)
388
+ assert_instance_of(Layout::Version, @layout_version)
389
+ refute_nil(@layout_version.id)
390
+ end
391
+
392
+ def test_valid_associations
393
+ assert_instance_of(Layout::Element, @layout_version.elements.first)
394
+ assert_instance_of(Layout, @layout_version.layout)
395
+ assert_equal(@layout, @layout_version.layout)
396
+ end
397
+
398
+ end
399
+
243
400
  class TestDigitalSignagePlayer < MiniTest::Test
244
401
 
245
402
  include LWS::DigitalSignage
@@ -828,3 +985,50 @@ class TestDigitalSignagePlayerTag < MiniTest::Test
828
985
  end
829
986
 
830
987
  end
988
+
989
+ class TestDigitalSignageSlide < MiniTest::Test
990
+
991
+ include LWS::DigitalSignage
992
+
993
+ def setup
994
+ @slide = Slide.find(1)
995
+ end
996
+
997
+ def test_valid
998
+ refute_nil(@slide)
999
+ assert_instance_of(Slide, @slide)
1000
+ refute_nil(@slide.id)
1001
+ end
1002
+
1003
+ def test_valid_associations
1004
+ assert_instance_of(LWS::Auth::Account, @slide.account)
1005
+ assert_instance_of(LWS::Auth::Company, @slide.company)
1006
+ assert_instance_of(Layout, @slide.layout)
1007
+ end
1008
+
1009
+ end
1010
+
1011
+ class TestDigitalSignageSlideSchedule < MiniTest::Test
1012
+
1013
+ include LWS::DigitalSignage
1014
+
1015
+ def setup
1016
+ @slide = Slide.find(1)
1017
+ # Slide schedules only exist as decendant objects of players
1018
+ # FIXME: Endpoint is missing in LWS
1019
+ @slide_schedule = @slide.schedules.first
1020
+ end
1021
+
1022
+ # FIXME: Endpoint is missing in LWS
1023
+ #def test_valid
1024
+ # refute_nil(@slide_schedule)
1025
+ # assert_instance_of(Slide::Schedule, @slide_schedule)
1026
+ # refute_nil(@slide_schedule.id)
1027
+ #end
1028
+
1029
+ # FIXME: Endpoint is missing in LWS
1030
+ #def test_valid_associations
1031
+ # assert_instance_of(Slide, @slide_schedules.slides.first)
1032
+ #end
1033
+
1034
+ end
data/test/generic_test.rb CHANGED
@@ -53,6 +53,12 @@ class TestGenericModel < MiniTest::Test
53
53
  end
54
54
 
55
55
  def test_dirty
56
+ # Always save a non-persisted object (even without changes)
57
+ configuration = Configuration.new
58
+ assert_empty(configuration.changes)
59
+ configuration.save
60
+ refute_empty(configuration.errors.messages)
61
+
56
62
  # No changes for a just found instance
57
63
  configuration = Configuration.find(@configuration.id)
58
64
  refute(configuration.changed?)
@@ -100,3 +106,14 @@ class TestGenericConfiguration < MiniTest::Test
100
106
  end
101
107
 
102
108
  end
109
+
110
+ class TestGenericStorage < MiniTest::Test
111
+
112
+ # Generic class needs to be accessed under some kind of app
113
+ include LWS::Resource
114
+
115
+ def test_upload
116
+ data = StringIO.new("some file contents\n")
117
+ refute_nil(Storage.create(data, "test.txt", "text/plain"))
118
+ end
119
+ end
@@ -20,7 +20,7 @@ require "test_helper"
20
20
  # * Collection::WeatherLocation
21
21
  # * Collection::WeatherLocation::Forecast
22
22
 
23
- class TestCollection < MiniTest::Test
23
+ class TestResourceCollection < MiniTest::Test
24
24
 
25
25
  include LWS::Resource
26
26
 
@@ -43,7 +43,7 @@ class TestCollection < MiniTest::Test
43
43
 
44
44
  end
45
45
 
46
- class TestCollectionItem < MiniTest::Test
46
+ class TestResourceCollectionItem < MiniTest::Test
47
47
 
48
48
  include LWS::Resource
49
49
 
@@ -65,7 +65,7 @@ class TestCollectionItem < MiniTest::Test
65
65
 
66
66
  end
67
67
 
68
- class TestFolder < MiniTest::Test
68
+ class TestResourceFolder < MiniTest::Test
69
69
 
70
70
  include LWS::Resource
71
71
 
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: 6.2.3
4
+ version: 6.3.0
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: 2019-03-25 00:00:00.000000000 Z
11
+ date: 2019-09-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday_middleware