@expcluster/permission-groups 7.0.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.
Files changed (91) hide show
  1. package/LICENSE.md +21 -0
  2. package/controller.ts +434 -0
  3. package/dist/browser/messages.d.ts +527 -0
  4. package/dist/browser/messages.d.ts.map +1 -0
  5. package/dist/browser/messages.js +561 -0
  6. package/dist/browser/messages.js.map +1 -0
  7. package/dist/browser/package.json +49 -0
  8. package/dist/browser/tsconfig.browser.tsbuildinfo +1 -0
  9. package/dist/browser/web/components/AssignmentForm.d.ts +7 -0
  10. package/dist/browser/web/components/AssignmentForm.d.ts.map +1 -0
  11. package/dist/browser/web/components/AssignmentForm.js +29 -0
  12. package/dist/browser/web/components/AssignmentForm.js.map +1 -0
  13. package/dist/browser/web/components/AssignmentsTable.d.ts +2 -0
  14. package/dist/browser/web/components/AssignmentsTable.d.ts.map +1 -0
  15. package/dist/browser/web/components/AssignmentsTable.js +61 -0
  16. package/dist/browser/web/components/AssignmentsTable.js.map +1 -0
  17. package/dist/browser/web/components/DeleteConfirm.d.ts +6 -0
  18. package/dist/browser/web/components/DeleteConfirm.d.ts.map +1 -0
  19. package/dist/browser/web/components/DeleteConfirm.js +7 -0
  20. package/dist/browser/web/components/DeleteConfirm.js.map +1 -0
  21. package/dist/browser/web/components/GroupForm.d.ts +5 -0
  22. package/dist/browser/web/components/GroupForm.d.ts.map +1 -0
  23. package/dist/browser/web/components/GroupForm.js +22 -0
  24. package/dist/browser/web/components/GroupForm.js.map +1 -0
  25. package/dist/browser/web/components/GroupViewPage.d.ts +2 -0
  26. package/dist/browser/web/components/GroupViewPage.d.ts.map +1 -0
  27. package/dist/browser/web/components/GroupViewPage.js +161 -0
  28. package/dist/browser/web/components/GroupViewPage.js.map +1 -0
  29. package/dist/browser/web/components/GroupsTable.d.ts +2 -0
  30. package/dist/browser/web/components/GroupsTable.d.ts.map +1 -0
  31. package/dist/browser/web/components/GroupsTable.js +29 -0
  32. package/dist/browser/web/components/GroupsTable.js.map +1 -0
  33. package/dist/browser/web/components/RoleMappingForm.d.ts +7 -0
  34. package/dist/browser/web/components/RoleMappingForm.d.ts.map +1 -0
  35. package/dist/browser/web/components/RoleMappingForm.js +32 -0
  36. package/dist/browser/web/components/RoleMappingForm.js.map +1 -0
  37. package/dist/browser/web/components/RoleMappingsTable.d.ts +2 -0
  38. package/dist/browser/web/components/RoleMappingsTable.d.ts.map +1 -0
  39. package/dist/browser/web/components/RoleMappingsTable.js +64 -0
  40. package/dist/browser/web/components/RoleMappingsTable.js.map +1 -0
  41. package/dist/browser/web/index.d.ts +13 -0
  42. package/dist/browser/web/index.d.ts.map +1 -0
  43. package/dist/browser/web/index.js +60 -0
  44. package/dist/browser/web/index.js.map +1 -0
  45. package/dist/node/controller.d.ts +37 -0
  46. package/dist/node/controller.d.ts.map +1 -0
  47. package/dist/node/controller.js +372 -0
  48. package/dist/node/controller.js.map +1 -0
  49. package/dist/node/index.d.ts +10 -0
  50. package/dist/node/index.d.ts.map +1 -0
  51. package/dist/node/index.js +196 -0
  52. package/dist/node/index.js.map +1 -0
  53. package/dist/node/instance.d.ts +40 -0
  54. package/dist/node/instance.d.ts.map +1 -0
  55. package/dist/node/instance.js +155 -0
  56. package/dist/node/instance.js.map +1 -0
  57. package/dist/node/messages.d.ts +527 -0
  58. package/dist/node/messages.d.ts.map +1 -0
  59. package/dist/node/messages.js +620 -0
  60. package/dist/node/messages.js.map +1 -0
  61. package/dist/node/tsconfig.node.tsbuildinfo +1 -0
  62. package/dist/web/manifest.json +10 -0
  63. package/dist/web/static/exp_groups.afefd90b210f7c8e0df2.js +543 -0
  64. package/dist/web/static/index_ts.f7d30aa0c13ff0be393a.js +22 -0
  65. package/dist/web/static/main.c2178975889c1c720e80.js +653 -0
  66. package/dist/web/static/messages_ts.65a81c17fb37953c5d68.js +22 -0
  67. package/dist/web/static/package_json.aab0d3f37da0567c250c.js +22 -0
  68. package/dist/web/static/vendors-node_modules_pnpm_ant-design_icons_6_2_3_rea_94b50600dfe79448cabf92d130d83059_node_mo-c79f54.cf768c64b40c811ce6c9.js +273 -0
  69. package/dist/web/static/vendors-node_modules_pnpm_sinclair_typebox_0_30_4_node_modules_sinclair_typebox_typebox_js.7fa46fac84f2e9324e54.js +22 -0
  70. package/dist/web/static/web_index_tsx-webpack_sharing_consume_default_react.b4766180f4d467b7b24f.js +102 -0
  71. package/index.ts +183 -0
  72. package/instance.ts +171 -0
  73. package/messages.ts +692 -0
  74. package/module/control.lua +438 -0
  75. package/module/globals.lua +11 -0
  76. package/module/module.json +12 -0
  77. package/module/module_exports.lua +3 -0
  78. package/package.json +47 -0
  79. package/tsconfig.browser.json +4 -0
  80. package/tsconfig.json +7 -0
  81. package/tsconfig.node.json +5 -0
  82. package/web/components/AssignmentForm.tsx +74 -0
  83. package/web/components/AssignmentsTable.tsx +111 -0
  84. package/web/components/DeleteConfirm.tsx +16 -0
  85. package/web/components/GroupForm.tsx +45 -0
  86. package/web/components/GroupViewPage.tsx +287 -0
  87. package/web/components/GroupsTable.tsx +49 -0
  88. package/web/components/RoleMappingForm.tsx +106 -0
  89. package/web/components/RoleMappingsTable.tsx +107 -0
  90. package/web/index.tsx +108 -0
  91. package/webpack.config.js +34 -0
@@ -0,0 +1,438 @@
1
+ --[[-- ExpGroups
2
+ Adds permission group syncing to clusterio
3
+ ]]
4
+
5
+ local clusterio_api = require("modules/clusterio/api")
6
+ local compat = require("modules/clusterio/compat") --[[@as LibCompat]]
7
+
8
+ --- Top level module table, contains event handlers and public methods
9
+ --- @class ExpGroups
10
+ local ExpGroups = {}
11
+
12
+ --- @class ExpPermissionGroups.GroupPermissions
13
+ --- @field is_blacklist boolean
14
+ --- @field permissions string[]?
15
+
16
+ --- @class ExpPermissionGroups.GroupRecord
17
+ --- @field id number
18
+ --- @field name string
19
+ --- @field permissions ExpPermissionGroups.GroupPermissions?
20
+ --- @field is_deleted boolean
21
+
22
+ --- @class ExpPermissionGroups.AssignmentRecord
23
+ --- @field name string
24
+ --- @field group_id number
25
+ --- @field is_deleted boolean
26
+
27
+ --- @class ExpPermissionGroups.ScriptData
28
+ --- @field factorio_to_clusterio_id table<number, number?>
29
+ --- @field clusterio_id_to_group table<number, LuaPermissionGroup?>
30
+ --- @field dirty_groups table<number, LuaPermissionGroup>
31
+ --- @field dirty_players table<string, LuaPlayer>
32
+ --- @field emit_updates boolean
33
+ local script_data = {}
34
+
35
+ local function setup_script_data()
36
+ if compat.script_data["exp_groups"] == nil then
37
+ --- @type ExpPermissionGroups.ScriptData
38
+ compat.script_data["exp_groups"] = {
39
+ factorio_to_clusterio_id = {},
40
+ clusterio_id_to_group = {},
41
+ dirty_groups = {},
42
+ dirty_players = {},
43
+ emit_updates = false,
44
+ }
45
+ end
46
+
47
+ ExpGroups.on_load()
48
+ end
49
+
50
+ --[[
51
+ Helper methods
52
+ ]]
53
+
54
+ --- Get the default factorio permission group
55
+ --- @return LuaPermissionGroup
56
+ local function get_default_group()
57
+ return assert(game.permissions.get_group("Default"))
58
+ end
59
+
60
+ --- Move all players from one group to another
61
+ --- @param group_src LuaPermissionGroup
62
+ --- @param group_dst LuaPermissionGroup
63
+ local function move_players(group_src, group_dst)
64
+ local add_player = group_dst.add_player
65
+ for _, player in pairs(group_src.players) do
66
+ add_player(player)
67
+ end
68
+ end
69
+
70
+ --- Apply an encoded permission definition to a group
71
+ --- @param group LuaPermissionGroup
72
+ --- @param permissions ExpPermissionGroups.GroupPermissions
73
+ local function decode_group_permissions(group, permissions)
74
+ -- Construct a hash map for faster lookup
75
+ local action_map = {}
76
+ for _, input_action_name in pairs(assert(permissions.permissions)) do
77
+ action_map[input_action_name] = true
78
+ end
79
+
80
+ -- Apply the whitelist / backlist to the group
81
+ local is_blacklist = permissions.is_blacklist
82
+ local action_allowed = not is_blacklist
83
+ for input_action_name, input_action in pairs(defines.input_action) do
84
+ if action_map[input_action_name] then
85
+ group.set_allows_action(input_action, action_allowed)
86
+ else
87
+ group.set_allows_action(input_action, is_blacklist)
88
+ end
89
+ end
90
+ end
91
+
92
+ --- Encode the permissions of a group in a shorthand format
93
+ --- @param group LuaPermissionGroup
94
+ --- @return ExpPermissionGroups.GroupPermissions
95
+ local function encode_group_permissions(group)
96
+ local whitelist = {} --- @type string[]
97
+ local blacklist = {} --- @type string[]
98
+ local whitelist_index = 0
99
+ local blacklist_index = 0
100
+
101
+ -- Construct the whitelist and blacklist
102
+ local allows_action = group.allows_action
103
+ for input_action_name, input_action in pairs(defines.input_action) do
104
+ if allows_action(input_action) then
105
+ whitelist[whitelist_index] = input_action_name
106
+ whitelist_index = whitelist_index + 1
107
+ else
108
+ blacklist[blacklist_index] = input_action_name
109
+ blacklist_index = blacklist_index + 1
110
+ end
111
+ end
112
+
113
+ -- Return the whitelist if it is smaller
114
+ if blacklist_index > whitelist_index then
115
+ return whitelist_index > 0
116
+ and { is_blacklist = false, permissions = whitelist }
117
+ or { is_blacklist = false }
118
+ end
119
+
120
+ -- Otherwise return the blacklist as it is smaller
121
+ return blacklist_index > 0
122
+ and { is_blacklist = true, permissions = blacklist }
123
+ or { is_blacklist = true }
124
+ end
125
+
126
+ --[[
127
+ State handlers
128
+ ]]
129
+
130
+ --- Update the factorio permission group
131
+ --- @param group_record ExpPermissionGroups.GroupRecord
132
+ local function update_group(group_record)
133
+ assert(not group_record.is_deleted)
134
+
135
+ -- Try find the group by id and then then name
136
+ local group = script_data.clusterio_id_to_group[group_record.id]
137
+ if not group then
138
+ group = game.permissions.get_group(group_record.name)
139
+ end
140
+
141
+ -- Create a new group or update the found group
142
+ if not group or not group.valid then
143
+ group = assert(game.permissions.create_group(group_record.name))
144
+ else
145
+ group.name = group_record.name
146
+ end
147
+
148
+ -- Update the permissions for the group
149
+ if group_record.permissions then
150
+ decode_group_permissions(group, group_record.permissions)
151
+ end
152
+
153
+ -- Update the script data
154
+ script_data.factorio_to_clusterio_id[group.group_id] = group_record.id
155
+ script_data.clusterio_id_to_group[group_record.id] = group
156
+ end
157
+
158
+ --- Delete the factorio permission group
159
+ --- @param group_record ExpPermissionGroups.GroupRecord
160
+ local function delete_group(group_record)
161
+ assert(group_record.is_deleted)
162
+
163
+ local default_group = get_default_group()
164
+ local group = script_data.clusterio_id_to_group[group_record.id]
165
+ if group then
166
+ move_players(group, default_group)
167
+ group.destroy()
168
+ end
169
+ end
170
+
171
+ --- Update an assignment by moving the player to their new group
172
+ --- @param assignment_record ExpPermissionGroups.AssignmentRecord
173
+ local function update_assignment(assignment_record)
174
+ assert(not assignment_record.is_deleted)
175
+
176
+ local group = script_data.clusterio_id_to_group[assignment_record.group_id]
177
+ local player = assert(game.get_player(assignment_record.name))
178
+ if group then
179
+ group.add_player(player)
180
+ end
181
+ end
182
+
183
+ --- Clear an assignment by moving the player to the default group
184
+ --- @param assignment_record ExpPermissionGroups.AssignmentRecord
185
+ local function delete_assignment(assignment_record)
186
+ assert(assignment_record.is_deleted)
187
+
188
+ local default_group = get_default_group()
189
+ local player = assert(game.get_player(assignment_record.name))
190
+ default_group.add_player(player)
191
+ end
192
+
193
+ --[[
194
+ Public methods
195
+ ]]
196
+
197
+ --- Restore local references to persistent script data after load
198
+ function ExpGroups.on_load()
199
+ script_data = compat.script_data["exp_groups"]
200
+ end
201
+
202
+ --- Enable or disable emitting lua changes back to the instance plugin
203
+ --- @param enabled boolean?
204
+ function ExpGroups.set_emit_events(enabled)
205
+ script_data.emit_updates = enabled ~= false
206
+ end
207
+
208
+ --- Replace local state with expected controller state on startup
209
+ --- @param group_records ExpPermissionGroups.GroupRecord[]
210
+ function ExpGroups.initialise_groups(group_records)
211
+ local _emit_events = script_data.emit_updates
212
+ script_data.emit_updates = false
213
+
214
+ -- Update all the received groups
215
+ local seen_clusterio_ids = {} --- @type table<number, boolean>
216
+ for _, group_record in pairs(group_records) do
217
+ update_group(group_record)
218
+ seen_clusterio_ids[group_record.id] = true
219
+ end
220
+
221
+ -- Cleanup the script data, removing stale group ids
222
+ local factorio_to_clusterio_id = script_data.factorio_to_clusterio_id
223
+ local clusterio_id_to_group = script_data.clusterio_id_to_group
224
+ for factorio_id, clusterio_id in pairs(factorio_to_clusterio_id) do
225
+ if not seen_clusterio_ids[clusterio_id] then
226
+ factorio_to_clusterio_id[factorio_id] = nil
227
+ clusterio_id_to_group[clusterio_id] = nil
228
+ end
229
+ end
230
+
231
+ -- Remove all other groups
232
+ local default_group = get_default_group()
233
+ local default_group_id = default_group.group_id
234
+ for _, group in pairs(game.permissions.groups) do
235
+ if not factorio_to_clusterio_id[group.group_id] and group.group_id ~= default_group_id then
236
+ move_players(group, default_group)
237
+ group.destroy()
238
+ end
239
+ end
240
+
241
+ script_data.emit_updates = _emit_events
242
+ end
243
+
244
+ --- Receive an updated version of a group record
245
+ --- @param group_record ExpPermissionGroups.GroupRecord
246
+ function ExpGroups.receive_group_update(group_record)
247
+ local _emit_events = script_data.emit_updates
248
+ script_data.emit_updates = false
249
+
250
+ if group_record.is_deleted then
251
+ delete_group(group_record)
252
+ else
253
+ update_group(group_record)
254
+ end
255
+
256
+ script_data.emit_updates = _emit_events
257
+ end
258
+
259
+ --- Receive an updated version of a assignment record
260
+ --- @param assignment_record ExpPermissionGroups.AssignmentRecord
261
+ function ExpGroups.receive_assignment_update(assignment_record)
262
+ local _emit_events = script_data.emit_updates
263
+ script_data.emit_updates = false
264
+
265
+ if assignment_record.is_deleted then
266
+ delete_assignment(assignment_record)
267
+ else
268
+ update_assignment(assignment_record)
269
+ end
270
+
271
+ script_data.emit_updates = _emit_events
272
+ end
273
+
274
+ --- Get the current script data for debugging purposes
275
+ --- @package
276
+ function ExpGroups._script_data()
277
+ return script_data
278
+ end
279
+
280
+ --[[
281
+ IPC events
282
+ ]]
283
+
284
+ --- Emit a group update to the instance plugin
285
+ --- @param group LuaPermissionGroup
286
+ local function emit_group_update(group)
287
+ clusterio_api.send_json("exp_group:group_updated", {
288
+ group_name = group.name,
289
+ group_id = script_data.factorio_to_clusterio_id[group.group_id],
290
+ permissions = encode_group_permissions(group),
291
+ })
292
+ end
293
+
294
+ --- Emit a group deletion to the instance plugin
295
+ --- @param group_id number
296
+ --- @param group_name string
297
+ local function emit_group_delete(group_id, group_name)
298
+ clusterio_api.send_json("exp_group:group_deleted", {
299
+ group_name = group_name,
300
+ group_id = script_data.factorio_to_clusterio_id[group_id],
301
+ })
302
+ end
303
+
304
+ --- Emit a player assignment to the instance plugin
305
+ --- @param assignments table<string, number>
306
+ local function emit_player_assignments(assignments)
307
+ clusterio_api.send_json("exp_group:player_assignments", {
308
+ assignments = assignments
309
+ })
310
+ end
311
+
312
+ --[[
313
+ IPC event queuing
314
+ ]]
315
+
316
+ --- Mark a group as changed
317
+ --- @param group LuaPermissionGroup
318
+ local function mark_group_dirty(group)
319
+ script_data.dirty_groups[group.group_id] = group
320
+ end
321
+
322
+ --- Mark a player as changed
323
+ --- @param player LuaPlayer
324
+ local function mark_player_dirty(player)
325
+ script_data.dirty_players[player.name] = player
326
+ end
327
+
328
+ --- Flush queued group updates to the instance plugin
329
+ local function flush_group_updates()
330
+ -- Check if updates should be updated
331
+ if not script_data.emit_updates then
332
+ script_data.dirty_groups = {}
333
+ return
334
+ end
335
+
336
+ -- Get all the groups and emit their updates
337
+ for _, group in pairs(script_data.dirty_groups) do
338
+ if group.valid then
339
+ emit_group_update(group)
340
+ end
341
+ end
342
+
343
+ script_data.dirty_groups = {}
344
+ end
345
+
346
+ --- Flush queued player updates to the instance plugin
347
+ local function flush_player_updates()
348
+ -- Check if updates should be updated
349
+ if not script_data.emit_updates then
350
+ script_data.dirty_players = {}
351
+ return
352
+ end
353
+
354
+ -- Construct the update payload
355
+ local assignments = {} --- @type table<string, number>
356
+ for player_name, player in pairs(script_data.dirty_players) do
357
+ local group = player.valid and player.permission_group
358
+ if group then
359
+ assignments[player_name] = script_data.factorio_to_clusterio_id[group.group_id]
360
+ end
361
+ end
362
+
363
+ emit_player_assignments(assignments)
364
+
365
+ script_data.dirty_players = {}
366
+ end
367
+
368
+ --[[
369
+ Factorio events
370
+ ]]
371
+
372
+ --- Handle clusterio server startup
373
+ local function on_server_startup()
374
+ setup_script_data()
375
+ end
376
+
377
+ --- Handle creation of permission groups
378
+ --- @param event EventData.on_permission_group_added
379
+ local function on_permission_group_added(event)
380
+ -- Check if updates should be updated
381
+ if not script_data.emit_updates then
382
+ return
383
+ end
384
+
385
+ mark_group_dirty(event.group)
386
+ end
387
+
388
+ --- Handle deletion of permission groups
389
+ --- @param event EventData.on_permission_group_deleted
390
+ local function on_permission_group_deleted(event)
391
+ -- Check if updates should be updated
392
+ if not script_data.emit_updates then
393
+ return
394
+ end
395
+
396
+ emit_group_delete(event.id, event.group_name)
397
+ end
398
+
399
+ --- Handle edits make to permission groups
400
+ --- @param event EventData.on_permission_group_edited
401
+ local function on_permission_group_edited(event)
402
+ -- Check if updates should be updated
403
+ if not script_data.emit_updates then
404
+ return
405
+ end
406
+
407
+ -- Check if this is a player or group event
408
+ if event.type == "add-player" or event.type == "remove-player" then
409
+ local player = assert(game.get_player(event.other_player_index))
410
+ mark_player_dirty(player)
411
+ else
412
+ mark_group_dirty(event.group)
413
+ end
414
+ end
415
+
416
+ --- Periodically flush queued changes
417
+ local function on_nth_tick_flush()
418
+ flush_group_updates()
419
+ flush_player_updates()
420
+ end
421
+
422
+ local e = defines.events
423
+
424
+ local events = {
425
+ [clusterio_api.events.on_server_startup] = on_server_startup,
426
+ [e.on_multiplayer_init] = on_server_startup,
427
+ [e.on_permission_group_added] = on_permission_group_added,
428
+ [e.on_permission_group_deleted] = on_permission_group_deleted,
429
+ [e.on_permission_group_edited] = on_permission_group_edited,
430
+ }
431
+
432
+ local on_nth_tick = {
433
+ [300] = on_nth_tick_flush,
434
+ }
435
+
436
+ ExpGroups.events = events --- @package
437
+ ExpGroups.on_nth_tick = on_nth_tick --- @package
438
+ return ExpGroups
@@ -0,0 +1,11 @@
1
+ --[[
2
+ It is best practice to not expose any globals because all modules share a global environment
3
+ However, sometimes you need globals, for example to access functions within rcon commands
4
+ Therefore, we advise that this should be the only file in your module to expose globals
5
+ Typically this would be your control file as shown in the example below
6
+ ]]
7
+
8
+ --- @diagnostic disable: global-in-non-module
9
+
10
+ -- Access using `/sc exp_groups.foo()`
11
+ exp_groups = require("modules/exp_groups/control")
@@ -0,0 +1,12 @@
1
+ {
2
+ "name": "exp_groups",
3
+ "load": [
4
+ "control.lua"
5
+ ],
6
+ "require": [
7
+ "globals.lua"
8
+ ],
9
+ "dependencies": {
10
+ "clusterio": "*"
11
+ }
12
+ }
@@ -0,0 +1,3 @@
1
+
2
+ -- Access the exports from other modules using require("modules/exp_groups")
3
+ return require("modules/exp_groups/control")
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@expcluster/permission-groups",
3
+ "version": "7.0.1",
4
+ "description": "Clusterio plugin providing syncing of permission groups",
5
+ "author": "Cooldude2606 <https://github.com/Cooldude2606>",
6
+ "license": "MIT",
7
+ "repository": "explosivegaming/ExpCluster",
8
+ "main": "dist/node/index.js",
9
+ "engines": {
10
+ "node": ">=18"
11
+ },
12
+ "peerDependencies": {
13
+ "@clusterio/controller": "^2.0.0-alpha.27",
14
+ "@clusterio/host": "^2.0.0-alpha.27",
15
+ "@clusterio/lib": "^2.0.0-alpha.27",
16
+ "@clusterio/web_ui": "^2.0.0-alpha.27"
17
+ },
18
+ "devDependencies": {
19
+ "@ant-design/icons": "^6.2.3",
20
+ "@types/node": "^20.17.19",
21
+ "@types/react": "^18.3.18",
22
+ "antd": "^5.24.2",
23
+ "react": "^18.2.0",
24
+ "react-dom": "^18.2.0",
25
+ "react-router-dom": "^6.29.0",
26
+ "typescript": "^5.7.3",
27
+ "webpack": "^5.98.0",
28
+ "webpack-cli": "^5.1.4",
29
+ "webpack-merge": "^5.9.0",
30
+ "@clusterio/controller": "^2.0.0-alpha.27",
31
+ "@clusterio/host": "^2.0.0-alpha.27",
32
+ "@clusterio/lib": "^2.0.0-alpha.27",
33
+ "@clusterio/web_ui": "^2.0.0-alpha.27"
34
+ },
35
+ "dependencies": {
36
+ "@sinclair/typebox": "^0.30.4"
37
+ },
38
+ "publishConfig": {
39
+ "access": "public"
40
+ },
41
+ "keywords": [
42
+ "clusterio",
43
+ "clusterio-plugin",
44
+ "factorio"
45
+ ],
46
+ "scripts": {}
47
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "extends": "../tsconfig.browser.json",
3
+ "include": [ "web/**/*.tsx", "web/**/*.ts", "messages.ts", "package.json" ],
4
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.node.json" },
5
+ { "path": "./tsconfig.browser.json" }
6
+ ]
7
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../tsconfig.node.json",
3
+ "include": ["./**/*.ts"],
4
+ "exclude": ["test/*", "./dist/*"],
5
+ }
@@ -0,0 +1,74 @@
1
+ import React, { useContext, useEffect } from "react";
2
+ import { Modal, Form, Select } from "antd";
3
+
4
+ import { ControlContext, useUsers } from "@clusterio/web_ui";
5
+ import * as messages from "../../messages";
6
+ import type { WebPlugin } from "..";
7
+
8
+ export default function AssignmentForm({ open, setOpen, initial }: {
9
+ open: boolean,
10
+ setOpen: (open: boolean) => void,
11
+ initial?: messages.AssignmentRecord,
12
+ }) {
13
+ const control = useContext(ControlContext);
14
+ const plugin = control.plugins.get("exp_groups") as WebPlugin;
15
+
16
+ const [groups] = plugin.useGroups();
17
+ const [users] = useUsers();
18
+
19
+ const [form] = Form.useForm();
20
+
21
+ function submit(values: any) {
22
+ if (initial) {
23
+ control.send(new messages.AssignmentUpdateRequest(
24
+ new messages.AssignmentRecord(
25
+ values.name,
26
+ values.groupId,
27
+ )
28
+ ));
29
+ } else {
30
+ control.send(new messages.AssignmentCreateRequest(
31
+ values.name,
32
+ values.groupId,
33
+ ));
34
+ }
35
+
36
+ setOpen(false);
37
+ }
38
+
39
+ useEffect(() => {
40
+ if (open) {
41
+ form.resetFields();
42
+ form.setFieldsValue(initial);
43
+ }
44
+ }, [open, initial]);
45
+
46
+ return <Modal
47
+ title={initial ? "Edit Assignment" : "Create Assignment"}
48
+ open={open}
49
+ onCancel={() => setOpen(false)}
50
+ onOk={() => form.submit()}
51
+ >
52
+ <Form form={form} onFinish={submit}>
53
+ <Form.Item name="name" label="Player" rules={[{ required: true }]}>
54
+ <Select disabled={Boolean(initial)} showSearch>
55
+ {[...users.values()].map(u => (
56
+ <Select.Option key={u.name} value={u.name}>
57
+ {u.name}
58
+ </Select.Option>
59
+ ))}
60
+ </Select>
61
+ </Form.Item>
62
+
63
+ <Form.Item name="groupId" label="Group" rules={[{ required: true }]}>
64
+ <Select>
65
+ {[...groups.values()].map(g => (
66
+ <Select.Option key={g.id} value={g.id}>
67
+ {g.name}
68
+ </Select.Option>
69
+ ))}
70
+ </Select>
71
+ </Form.Item>
72
+ </Form>
73
+ </Modal>;
74
+ }