Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
-- +micrate Up
-- SQL in section 'Up' is executed when this migration is applied

-- +micrate StatementBegin
DO
$$
BEGIN
IF NOT EXISTS (SELECT *
FROM pg_type typ
INNER JOIN pg_namespace nsp
ON nsp.oid = typ.typnamespace
WHERE nsp.nspname = current_schema()
AND typ.typname = 'signage_plugin_plugin_type') THEN
CREATE TYPE signage_plugin_plugin_type AS ENUM (
'PLUGIN',
'WIDGET'
);
END IF;
END;
$$
LANGUAGE plpgsql;
-- +micrate StatementEnd

ALTER TABLE "signage_plugin"
ADD COLUMN IF NOT EXISTS plugin_type public.signage_plugin_plugin_type NOT NULL DEFAULT 'PLUGIN'::public.signage_plugin_plugin_type;

-- templates position widget plugins over signage displays
CREATE TABLE IF NOT EXISTS "signage_template"(
id UUID PRIMARY KEY DEFAULT uuidv7(),
authority_id TEXT NOT NULL,
background_item_id TEXT,
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL,

name TEXT NOT NULL,
description TEXT,
tags TEXT[] NOT NULL DEFAULT '{}'::TEXT[],
layouts JSONB NOT NULL DEFAULT '[]'::jsonb,
full_screen_takeover BOOLEAN NOT NULL DEFAULT FALSE,
CHECK (jsonb_typeof(layouts) = 'array'),
FOREIGN KEY (authority_id) REFERENCES authority(id) ON DELETE CASCADE,
FOREIGN KEY (background_item_id) REFERENCES playlist_items(id) ON DELETE SET NULL
);

CREATE INDEX IF NOT EXISTS signage_template_authority_id_index ON "signage_template" USING BTREE (authority_id);
CREATE INDEX IF NOT EXISTS signage_template_background_item_id_index ON "signage_template" USING BTREE (background_item_id);
CREATE INDEX IF NOT EXISTS signage_template_tags_index ON "signage_template" USING GIN (tags);

-- junction attaching templates to control systems, each row optionally
-- scoped by a schedule. A schedule-less row is the default template for
-- the pairing (at most one, enforced by the partial unique index).
CREATE TABLE IF NOT EXISTS "system_templates"(
id UUID PRIMARY KEY DEFAULT uuidv7(),
control_system_id TEXT NOT NULL,
template_id UUID NOT NULL,
created_at TIMESTAMPTZ NOT NULL,
updated_at TIMESTAMPTZ NOT NULL,

schedule JSONB,
CHECK (schedule IS NULL OR jsonb_typeof(schedule) = 'object'),
FOREIGN KEY (control_system_id) REFERENCES sys(id) ON DELETE CASCADE,
FOREIGN KEY (template_id) REFERENCES signage_template(id) ON DELETE CASCADE
);

CREATE INDEX IF NOT EXISTS system_templates_control_system_id_index ON "system_templates" USING BTREE (control_system_id);
CREATE INDEX IF NOT EXISTS system_templates_template_id_index ON "system_templates" USING BTREE (template_id);
CREATE UNIQUE INDEX IF NOT EXISTS system_templates_default_unique ON "system_templates" (control_system_id, template_id) WHERE schedule IS NULL;

-- +micrate Down
-- SQL section 'Down' is executed when this migration is rolled back

DROP TABLE IF EXISTS "system_templates";
DROP TABLE IF EXISTS "signage_template";
ALTER TABLE "signage_plugin" DROP COLUMN IF EXISTS plugin_type;

-- Drop the enum type
DROP TYPE IF EXISTS public.signage_plugin_plugin_type;
2 changes: 1 addition & 1 deletion spec/booking_clash_perf_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ module PlaceOS::Model
b1 = recurring.call("desk-1", start_time, end_time, 0b1111111, rec_end)
b1.save!
b2 = recurring.call("desk-1", start_time + 30.minutes, end_time + 30.minutes, 0b1111111, rec_end)
b2.clashing_bookings.map(&.id).uniq.should contain b1.id
b2.clashing_bookings.map(&.id).uniq!.should contain b1.id
b2.clashing?.should be_true
end

Expand Down
58 changes: 58 additions & 0 deletions spec/generator.cr
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,64 @@ module PlaceOS::Model
)
end

def self.widget_plugin(
name : String = Faker::Hacker.noun,
authority : Authority? = nil,
**args,
)
plugin = signage_plugin(**args, name: name, authority: authority)
plugin.plugin_type = SignagePlugin::PluginType::Widget
plugin
end

def self.layout(
plugin : SignagePlugin? = nil,
position : SignageTemplate::Layout::Position = SignageTemplate::Layout::Position::Top,
x_pos : Float32? = nil,
y_pos : Float32? = 0.25_f32,
plugin_params : Hash(String, JSON::Any) = {} of String => JSON::Any,
)
SignageTemplate::Layout.new(
position: position,
plugin_id: plugin.try(&.id),
x_pos: x_pos,
y_pos: y_pos,
plugin_params: plugin_params,
)
end

def self.signage_template(
name : String = Faker::Hacker.noun,
authority : Authority? = nil,
layouts : Array(SignageTemplate::Layout) = [] of SignageTemplate::Layout,
tags : Array(String) = [] of String,
)
unless authority
existing = Authority.find_by_domain("localhost")
authority = existing || self.authority.save!
end

template = SignageTemplate.new
template.name = name
template.authority_id = authority.id.as(String)
template.layouts = layouts
template.tags = tags
template
end

def self.system_template(
template : SignageTemplate? = nil,
control_system : ControlSystem = control_system.save!,
schedule : Playlist::Schedule? = nil,
)
template ||= signage_template.save!
sys_template = SignageTemplate::SystemTemplate.new
sys_template.control_system_id = control_system.id.as(String)
sys_template.template_id = template.id.as(UUID)
sys_template.schedule = schedule
sys_template
end

def self.revision(playlist : Playlist = playlist.save!, user : User = user.save!)
rev = Playlist::Revision.new
rev.playlist_id = playlist.id
Expand Down
2 changes: 2 additions & 0 deletions spec/helper.cr
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ Spec.after_suite do
# Models that inherit directly from ::PgORM::Base (not ModelBase) —
# cleared in dependency order (children first so FKs don't fire).
[
PlaceOS::Model::SignageTemplate::SystemTemplate,
PlaceOS::Model::SignageTemplate,
PlaceOS::Model::PendingMail,
PlaceOS::Model::GroupHistory,
PlaceOS::Model::GroupInvitation,
Expand Down
14 changes: 14 additions & 0 deletions spec/signage_plugin_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,19 @@ module PlaceOS::Model
plugin.save.should eq false
plugin.errors.any? { |e| e.field == :uri }.should eq true
end

it "defaults plugin_type to Plugin" do
plugin = Generator.signage_plugin.save!

found = SignagePlugin.find(plugin.id.as(String))
found.plugin_type.should eq SignagePlugin::PluginType::Plugin
end

it "persists a Widget plugin_type" do
plugin = Generator.widget_plugin.save!

found = SignagePlugin.find(plugin.id.as(String))
found.plugin_type.should eq SignagePlugin::PluginType::Widget
end
end
end
Loading
Loading