Skip to content

Commit df5b475

Browse files
replace legacy shell-based sample data tool with integrated SampleData module and add performance test artifacts
1 parent 579decb commit df5b475

18 files changed

Lines changed: 209 additions & 929 deletions

File tree

modules/SampleData/SampleData.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
// Copyright 2012-2026 OpenBroadcaster, Inc.
4+
// SPDX-License-Identifier: AGPL-3.0-or-later
5+
6+
namespace OpenBroadcaster\Modules\SampleData;
7+
8+
use OpenBroadcaster\Base\Module;
9+
10+
class SampleData extends Module
11+
{
12+
public $name = 'SampleData v1.0';
13+
public $description = 'Seed sample data profiles into a fresh Observer instance.';
14+
15+
public function callbacks()
16+
{
17+
}
18+
19+
public function install()
20+
{
21+
$this->permission_enable('administration', 'import_sample_data', 'import sample data profiles into Observer');
22+
23+
return true;
24+
}
25+
26+
public function uninstall()
27+
{
28+
$this->permission_disable('import_sample_data');
29+
30+
return true;
31+
}
32+
33+
public function purge()
34+
{
35+
$this->permission_delete('import_sample_data');
36+
37+
return true;
38+
}
39+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
// Copyright 2012-2026 OpenBroadcaster, Inc.
4+
// SPDX-License-Identifier: AGPL-3.0-or-later
5+
6+
namespace OpenBroadcaster\Modules\SampleData\Controllers;
7+
8+
use OpenBroadcaster\Base\Controller;
9+
10+
class SampleData extends Controller
11+
{
12+
public function __construct()
13+
{
14+
parent::__construct();
15+
16+
$this->user->require_permission('import_sample_data');
17+
$this->SampleDataModel = $this->load->model('SampleData', 'SampleData');
18+
}
19+
20+
public function listProfiles()
21+
{
22+
$profiles = $this->SampleDataModel('listProfiles');
23+
return [true, 'Sample data profiles.', $profiles];
24+
}
25+
26+
public function runProfile()
27+
{
28+
$profile = trim((string) $this->data('profile'));
29+
30+
if ($profile === '' || !preg_match('/^[a-z0-9_]+$/', $profile)) {
31+
return [false, 'Invalid profile name.'];
32+
}
33+
34+
$result = $this->SampleDataModel('runProfile', $profile);
35+
36+
if (!$result['success']) {
37+
return [false, $result['error'], ['log' => $result['log']]];
38+
}
39+
40+
return [true, 'Sample data imported.', ['log' => $result['log']]];
41+
}
42+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!--/*
2+
Copyright 2012-2026 OpenBroadcaster, Inc.
3+
SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/-->
5+
6+
<h1>Import Sample Data</h1>
7+
8+
<p id="sampledata_module-info">Pick a sample data profile and click "Import" to seed your installation. The action is idempotent — items that already exist are skipped, never overwritten.</p>
9+
10+
<table class="table">
11+
<tr>
12+
<td><label for="sampledata_module-profile">Profile</label></td>
13+
<td><select id="sampledata_module-profile"></select></td>
14+
</tr>
15+
<tr>
16+
<td colspan="2"><p id="sampledata_module-description"></p></td>
17+
</tr>
18+
<tr>
19+
<td colspan="2"><button id="sampledata_module-import" class="button">Import Selected Profile</button></td>
20+
</tr>
21+
</table>
22+
23+
<pre id="sampledata_module-log" style="display: none; white-space: pre-wrap; background: #111; color: #eee; padding: 1em; border-radius: 4px; margin-top: 1em;"></pre>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2012-2026 OpenBroadcaster, Inc.
2+
// SPDX-License-Identifier: AGPL-3.0-or-later
3+
4+
OBModules.SampleData = new Object();
5+
6+
OBModules.SampleData.init = function () {
7+
OB.Callbacks.add('ready', 0, OBModules.SampleData.initMenu);
8+
};
9+
10+
OBModules.SampleData.initMenu = function () {
11+
OB.UI.addSubMenuItem(
12+
'admin',
13+
'Import Sample Data',
14+
'import_sample_data',
15+
OBModules.SampleData.importPage,
16+
110,
17+
'import_sample_data'
18+
);
19+
};
20+
21+
OBModules.SampleData.importPage = function () {
22+
OB.UI.replaceMain('modules/sampledata/sampledata.html');
23+
24+
OBModules.SampleData.profiles = {};
25+
$('#sampledata_module-profile').html('<option value="">Loading…</option>');
26+
$('#sampledata_module-import').prop('disabled', true);
27+
$('#sampledata_module-log').hide().text('');
28+
29+
OB.API.post('sampledata', 'listProfiles', {}, function (response) {
30+
if (!response.status) {
31+
$('#sampledata_module-info').text('Error loading sample data profiles.');
32+
return;
33+
}
34+
35+
var profiles = response.data || [];
36+
var $select = $('#sampledata_module-profile');
37+
$select.empty();
38+
39+
if (profiles.length === 0) {
40+
$select.append('<option value="">No profiles found</option>');
41+
$('#sampledata_module-import').prop('disabled', true);
42+
return;
43+
}
44+
45+
$.each(profiles, function (_, profile) {
46+
OBModules.SampleData.profiles[profile.directory] = profile;
47+
$select.append(
48+
$('<option></option>').val(profile.directory).text(profile.name)
49+
);
50+
});
51+
52+
OBModules.SampleData.updateDescription();
53+
$('#sampledata_module-import').prop('disabled', false);
54+
});
55+
56+
$('#sampledata_module-profile').off('change').on('change', OBModules.SampleData.updateDescription);
57+
$('#sampledata_module-import').off('click').on('click', function () {
58+
OBModules.SampleData.runImport(false);
59+
});
60+
};
61+
62+
OBModules.SampleData.updateDescription = function () {
63+
var dir = $('#sampledata_module-profile').val();
64+
var profile = OBModules.SampleData.profiles[dir];
65+
$('#sampledata_module-description').text(profile ? (profile.description || '') : '');
66+
};
67+
68+
OBModules.SampleData.runImport = function (confirmed) {
69+
var dir = $('#sampledata_module-profile').val();
70+
if (!dir) {
71+
return;
72+
}
73+
74+
if (!confirmed) {
75+
OB.UI.confirm(
76+
'Import sample data profile "' + dir + '"?\n\nThis will create permission groups, users, playlists, a sample player and schedule, and apply settings. The action is idempotent — existing items are skipped — but it cannot be undone.',
77+
function () { OBModules.SampleData.runImport(true); },
78+
'Yes, Import',
79+
'No, Cancel',
80+
'delete'
81+
);
82+
return;
83+
}
84+
85+
$('#sampledata_module-info').text('Importing…');
86+
$('#sampledata_module-import').prop('disabled', true);
87+
$('#sampledata_module-log').show().text('');
88+
89+
OB.API.post('sampledata', 'runProfile', { profile: dir }, function (response) {
90+
var log = (response.data && response.data.log) ? response.data.log.join('\n') : '';
91+
$('#sampledata_module-log').text(log);
92+
93+
if (response.status) {
94+
$('#sampledata_module-info').text('Sample data imported.');
95+
} else {
96+
$('#sampledata_module-info').text('Import failed: ' + (response.msg || 'unknown error'));
97+
}
98+
99+
$('#sampledata_module-import').prop('disabled', false);
100+
});
101+
};

tools/sampledata/profiles/en_community_radio/categories.json renamed to modules/SampleData/profiles/en_community_radio/categories.json

File renamed without changes.

tools/sampledata/profiles/en_community_radio/genres.json renamed to modules/SampleData/profiles/en_community_radio/genres.json

File renamed without changes.

tools/sampledata/profiles/en_community_radio/groups.json renamed to modules/SampleData/profiles/en_community_radio/groups.json

File renamed without changes.

tools/sampledata/profiles/en_community_radio/manifest.json renamed to modules/SampleData/profiles/en_community_radio/manifest.json

File renamed without changes.

tools/sampledata/profiles/en_community_radio/metadata_fields.json renamed to modules/SampleData/profiles/en_community_radio/metadata_fields.json

File renamed without changes.

tools/sampledata/profiles/en_community_radio/playlists.json renamed to modules/SampleData/profiles/en_community_radio/playlists.json

File renamed without changes.

0 commit comments

Comments
 (0)