@saltcorn/builder 0.9.2 → 0.9.3-beta.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.
@@ -0,0 +1,163 @@
1
+ import { readFileSync } from "fs";
2
+ import { join } from "path";
3
+
4
+ export const fixturesData = () => {
5
+ const { tables, views } = JSON.parse(
6
+ readFileSync(join(__dirname, "schema_data.json"))
7
+ );
8
+ return { tables, views };
9
+ };
10
+
11
+ let nextFieldId = 3000;
12
+
13
+ export const withAnotherUserField = () => {
14
+ const { tables, views } = JSON.parse(JSON.stringify(fixturesData()));
15
+ const uiit = tables.find(({ name }) => name === "user_interested_in_topic");
16
+ uiit.foreign_keys.push({
17
+ name: "another_user",
18
+ id: nextFieldId++,
19
+ table_id: uiit.id,
20
+ reftable_name: "users",
21
+ is_unique: false,
22
+ });
23
+ return { tables, views };
24
+ };
25
+
26
+ export const withSecondTopicField = () => {
27
+ const { tables, views } = JSON.parse(JSON.stringify(withAnotherUserField()));
28
+ const bit = tables.find(({ name }) => name === "blog_in_topic");
29
+ bit.foreign_keys.push({
30
+ name: "second_topic",
31
+ id: nextFieldId++,
32
+ table_id: bit.id,
33
+ reftable_name: "topics",
34
+ is_unique: false,
35
+ });
36
+ return { tables, views };
37
+ };
38
+
39
+ export const withMultipleInbounds = () => {
40
+ const { tables, views } = JSON.parse(JSON.stringify(withSecondTopicField()));
41
+ const nextTableId = tables.length + 1;
42
+ tables.push({
43
+ name: "second_inbound",
44
+ id: nextTableId,
45
+ foreign_keys: [
46
+ {
47
+ name: "topic",
48
+ id: nextFieldId++,
49
+ table_id: nextTableId,
50
+ reftable_name: "topics",
51
+ is_unique: false,
52
+ },
53
+ {
54
+ name: "user",
55
+ id: nextFieldId++,
56
+ table_id: nextTableId,
57
+ reftable_name: "users",
58
+ is_unique: false,
59
+ },
60
+ ],
61
+ });
62
+ return { tables, views };
63
+ };
64
+
65
+ export const withKeyFromLayerTwo = () => {
66
+ const { tables, views } = JSON.parse(JSON.stringify(withMultipleInbounds()));
67
+ const inboundInbound = tables.find(({ name }) => name === "inbound_inbound");
68
+ inboundInbound.foreign_keys.push({
69
+ name: "post_from_layer_two",
70
+ id: nextFieldId++,
71
+ table_id: inboundInbound.id,
72
+ reftable_name: "blog_posts",
73
+ is_unique: false,
74
+ });
75
+ return { tables, views };
76
+ };
77
+
78
+ export const withKeyFromLayerThree = () => {
79
+ const { tables, views } = JSON.parse(JSON.stringify(withKeyFromLayerTwo()));
80
+ const nextTableId = tables.length + 1;
81
+ tables.push({
82
+ name: "inbound_level_three",
83
+ id: nextTableId,
84
+ foreign_keys: [
85
+ {
86
+ name: "inbound_level_two",
87
+ id: nextFieldId++,
88
+ table_id: nextTableId,
89
+ reftable_name: "inbound_inbound",
90
+ is_unique: false,
91
+ },
92
+ {
93
+ name: "topic",
94
+ id: nextFieldId++,
95
+ table_id: nextTableId,
96
+ reftable_name: "topics",
97
+ is_unique: false,
98
+ },
99
+ ],
100
+ });
101
+ return { tables, views };
102
+ };
103
+
104
+ export const withSimplePostTopicrelation = () => {
105
+ const { tables, views } = JSON.parse(JSON.stringify(fixturesData()));
106
+ const simpleTopicsId = tables.length + 1;
107
+ const simplePostsId = simpleTopicsId + 1;
108
+ const simplePostInboundId = simplePostsId + 1;
109
+ tables.push({
110
+ name: "simple_posts",
111
+ id: simplePostsId,
112
+ foreign_keys: [
113
+ {
114
+ name: "topic",
115
+ table_id: simplePostsId,
116
+ id: nextFieldId++,
117
+ reftable_name: "simple_topics",
118
+ is_unique: false,
119
+ },
120
+ ],
121
+ });
122
+ tables.push({
123
+ name: "simple_topics",
124
+ id: simpleTopicsId,
125
+ foreign_keys: [],
126
+ });
127
+ tables.push({
128
+ name: "simple_post_inbound",
129
+ id: simplePostInboundId,
130
+ foreign_keys: [
131
+ {
132
+ name: "post",
133
+ table_id: simplePostInboundId,
134
+ id: nextFieldId++,
135
+ reftable_name: "simple_posts",
136
+ is_unique: false,
137
+ },
138
+ {
139
+ name: "topic",
140
+ table_id: simplePostInboundId,
141
+ id: nextFieldId++,
142
+ reftable_name: "simple_topics",
143
+ is_unique: false,
144
+ },
145
+ ],
146
+ });
147
+ const users = tables.find(({ name }) => name === "users");
148
+ users.foreign_keys.push({
149
+ name: "favsimpletopic",
150
+ table_id: users.id,
151
+ id: nextFieldId++,
152
+ reftable_name: "simple_topics",
153
+ is_unique: false,
154
+ });
155
+
156
+ views.push({
157
+ name: "simple_posts_list",
158
+ table_id: simplePostsId,
159
+ display_type: "NO_ROW_LIMIT",
160
+ });
161
+
162
+ return { tables, views };
163
+ };
@@ -1,273 +0,0 @@
1
- /*global $ */
2
- import React, { Fragment, useContext, useState } from "react";
3
- import {
4
- parseRelationPath,
5
- parseLegacyRelation,
6
- removeWhitespaces,
7
- } from "./utils";
8
-
9
- const parseRelations = (allOptions, viewname, parentTbl) => {
10
- const viewtable = allOptions.view_name_opts
11
- ? allOptions.view_name_opts.find((opt) => opt.name === viewname)?.table
12
- : undefined;
13
- const options = allOptions.view_relation_opts[viewname] || [];
14
- const result = { table: parentTbl, inboundKeys: [], fkeys: [] };
15
- if (!viewtable) return result;
16
- for (const { value } of options) {
17
- let path = null;
18
- if (value.startsWith(".")) {
19
- path = parseRelationPath(value, allOptions.fk_options);
20
- } else {
21
- const [prefix, rest] = value.split(":");
22
- path = parseLegacyRelation(prefix, rest, parentTbl);
23
- }
24
- if (path.length > 0) buildLevels(value, path, result, parentTbl);
25
- else console.log(`The relation path '${value}' is invalid`);
26
- }
27
- return result;
28
- };
29
-
30
- const buildLevels = (path, parsed, result, parentTbl) => {
31
- let currentLevel = result;
32
- for (const relation of parsed) {
33
- if (relation.type === "Inbound") {
34
- const existing = currentLevel.inboundKeys.find(
35
- (key) => key.name === relation.key && key.table === relation.table
36
- );
37
- if (existing) {
38
- currentLevel = existing;
39
- } else {
40
- const nextLevel = {
41
- name: relation.key,
42
- table: relation.table,
43
- inboundKeys: [],
44
- fkeys: [],
45
- };
46
- currentLevel.inboundKeys.push(nextLevel);
47
- currentLevel = nextLevel;
48
- }
49
- } else if (relation.type === "Foreign") {
50
- const existing = currentLevel.fkeys.find(
51
- (key) => key.name === relation.key
52
- );
53
- if (existing) {
54
- currentLevel = existing;
55
- } else {
56
- const nextLevel = {
57
- name: relation.key,
58
- table: relation.table,
59
- inboundKeys: [],
60
- fkeys: [],
61
- };
62
- currentLevel.fkeys.push(nextLevel);
63
- currentLevel = nextLevel;
64
- }
65
- } else if (relation.type === "Independent") {
66
- result.fkeys.push({
67
- name: "None (no relation)",
68
- table: "",
69
- inboundKeys: [],
70
- fkeys: [],
71
- relPath: path,
72
- });
73
- } else if (relation.type === "Own") {
74
- result.fkeys.push({
75
- name: `${parentTbl} (same table)`,
76
- table: "",
77
- inboundKeys: [],
78
- fkeys: [],
79
- relPath: path,
80
- });
81
- } else if (relation.type === "OneToOneShow") {
82
- result.inboundKeys.push({
83
- name: relation.key,
84
- table: relation.table,
85
- inboundKeys: [],
86
- fkeys: [],
87
- relPath: path,
88
- });
89
- }
90
- }
91
- currentLevel.relPath = path;
92
- };
93
-
94
- export const RelationPicker = ({ options, viewname, update }) => {
95
- const maxRecLevelDefault = 10;
96
- const [maxRecLevel, setMaxRecLevel] = useState(maxRecLevelDefault);
97
- const relationLevels = parseRelations(options, viewname, options.tableName);
98
-
99
- const levelClasses = (level) => {
100
- const classes = [];
101
- for (let i = level; i < maxRecLevel; i++) {
102
- classes.push(`.dropdown_level_${i}.show`);
103
- }
104
- return classes.join(",");
105
- };
106
-
107
- const activeClasses = (level) => {
108
- const classes = [];
109
- for (let i = level; i < maxRecLevel; i++) {
110
- classes.push(`.item_level_${i}.active`);
111
- }
112
- return classes.join(",");
113
- };
114
-
115
- const buildPicker = (level, reclevel) => {
116
- return (
117
- <div className="dropdown-menu">
118
- <h5 className="join-table-header text-center">{level.table}</h5>
119
- <ul className="ps-0 mb-0">
120
- {
121
- // foreign keys
122
- level.fkeys.map((fkey) => {
123
- const hasSubLevels =
124
- fkey.fkeys.length > 0 || fkey.inboundKeys.length > 0;
125
- const identifier = removeWhitespaces(
126
- `${fkey.name}_${fkey.table}_${level.table}_${reclevel}`
127
- );
128
-
129
- return hasSubLevels ? (
130
- <li
131
- key={`${identifier}_fkey_key`}
132
- className={`dropdown-item ${identifier}_fkey_item item_level_${reclevel} ${
133
- reclevel < 5 ? "dropstart" : "dropdown"
134
- }`}
135
- role="button"
136
- >
137
- <div
138
- className={`dropdown-toggle ${identifier}_fkey_toggle dropdown_level_${reclevel}`}
139
- role="button"
140
- aria-expanded="false"
141
- onClick={() => {
142
- $(
143
- `.${identifier}_fkey_toggle,${levelClasses(reclevel)}`
144
- ).dropdown("toggle");
145
- if (reclevel > maxRecLevel) setMaxRecLevel(reclevel);
146
- $(activeClasses(reclevel)).removeClass("active");
147
- $(`.${identifier}_fkey_item`).addClass(() => "active");
148
- }}
149
- >
150
- {fkey.name}
151
- </div>
152
- {buildPicker(fkey, reclevel + 1)}
153
- </li>
154
- ) : (
155
- <li
156
- key={`${identifier}_fkey_key`}
157
- className="dropdown-item"
158
- role="button"
159
- onClick={() => {
160
- update(fkey.relPath);
161
- $(".dropdown-item.active").removeClass("active");
162
- $(`${levelClasses(0)}`).dropdown("toggle");
163
- setMaxRecLevel(maxRecLevelDefault);
164
- }}
165
- >
166
- {fkey.name}
167
- </li>
168
- );
169
- })
170
- }
171
- {
172
- // inbound keys
173
- level.inboundKeys.map((inboundKey) => {
174
- const hasSubLevels =
175
- inboundKey.fkeys.length > 0 ||
176
- inboundKey.inboundKeys.length > 0;
177
- const identifier = removeWhitespaces(
178
- `${inboundKey.name}_${inboundKey.table}_${level.table}_${reclevel}`
179
- );
180
- return hasSubLevels ? (
181
- <div key={`${identifier}_inboundkey_key_div`}>
182
- <li
183
- key={`${identifier}_inboundkey_key`}
184
- className={`dropdown-item ${identifier}_inbound_item item_level_${reclevel} ${
185
- reclevel < 5 ? "dropstart" : "dropdown"
186
- }`}
187
- role="button"
188
- >
189
- <div
190
- className={`dropdown-toggle ${identifier}_inbound_toggle dropdown_level_${reclevel}`}
191
- role="button"
192
- aria-expanded="false"
193
- onClick={() => {
194
- $(
195
- `.${identifier}_inbound_toggle,${levelClasses(
196
- reclevel
197
- )}`
198
- ).dropdown("toggle");
199
- if (reclevel > maxRecLevel) setMaxRecLevel(reclevel);
200
- $(activeClasses(reclevel)).removeClass("active");
201
- $(`.${identifier}_inbound_item`).addClass(
202
- () => "active"
203
- );
204
- }}
205
- >
206
- {inboundKey.name} (from {inboundKey.table})
207
- </div>
208
- {buildPicker(inboundKey, reclevel + 1)}
209
- </li>
210
- {/* it's a level and a direct link */}
211
- {inboundKey.relPath ? (
212
- <li
213
- key={`${identifier}_inboundkey_key_direct`}
214
- className="dropdown-item"
215
- role="button"
216
- onClick={() => {
217
- update(inboundKey.relPath);
218
- $(".dropdown-item.active").removeClass("active");
219
- $(`${levelClasses(0)}`).dropdown("toggle");
220
- setMaxRecLevel(maxRecLevelDefault);
221
- }}
222
- >
223
- {inboundKey.name} (from {inboundKey.table})
224
- </li>
225
- ) : (
226
- ""
227
- )}
228
- </div>
229
- ) : (
230
- <li
231
- key={`${identifier}_inboundkey_key`}
232
- className="dropdown-item"
233
- role="button"
234
- onClick={() => {
235
- update(inboundKey.relPath);
236
- $(".dropdown-item.active").removeClass("active");
237
- $(`${levelClasses(0)}`).dropdown("toggle");
238
- setMaxRecLevel(maxRecLevelDefault);
239
- }}
240
- >
241
- {inboundKey.name} (from {inboundKey.table})
242
- </li>
243
- );
244
- })
245
- }
246
- </ul>
247
- </div>
248
- );
249
- };
250
-
251
- return (
252
- <div>
253
- <label>Relation</label>
254
- <div style={{ zIndex: 10000 }} className="dropstart">
255
- <button
256
- id="_relation_picker_toggle_"
257
- className="btn btn-outline-primary dropdown-toggle dropdown_level_0 mb-1"
258
- aria-expanded="false"
259
- onClick={() => {
260
- $(".dropdown-item.active").removeClass("active");
261
- $(`#_relation_picker_toggle_,${levelClasses(0)}`).dropdown(
262
- "toggle"
263
- );
264
- setMaxRecLevel(maxRecLevelDefault);
265
- }}
266
- >
267
- Select
268
- </button>
269
- {buildPicker(relationLevels, 1)}
270
- </div>
271
- </div>
272
- );
273
- };