@featurevisor/site 1.35.3 → 2.0.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featurevisor/site",
3
- "version": "1.35.3",
3
+ "version": "2.0.0",
4
4
  "description": "Static site for Featurevisor",
5
5
  "main": "dist",
6
6
  "scripts": {
@@ -59,7 +59,7 @@
59
59
  "webpack-merge": "^5.10.0"
60
60
  },
61
61
  "dependencies": {
62
- "@featurevisor/types": "1.35.3"
62
+ "@featurevisor/types": "2.0.0"
63
63
  },
64
- "gitHead": "253ff5dade7c9ee953f6a57cda097a6c9ed93aa2"
64
+ "gitHead": "9817e05a07735294c750ee921991509b67015afd"
65
65
  }
@@ -36,7 +36,7 @@ import {
36
36
  } from "./ShowFeature";
37
37
 
38
38
  import { SearchIndexContext } from "../contexts/SearchIndexContext";
39
- import { SearchIndex } from "@featurevisor/types";
39
+ import type { SearchIndex } from "@featurevisor/types";
40
40
 
41
41
  export function App() {
42
42
  const [fetchedSearchIndex, setSearchIndex] = React.useState(undefined);
@@ -33,11 +33,6 @@ export function ListAttributes() {
33
33
  <div className="flex items-center justify-between">
34
34
  <p className="text-md relative font-bold text-slate-600">
35
35
  {attribute.key}{" "}
36
- {attribute.capture && (
37
- <span className="ml-1 rounded-full bg-green-100 px-2 py-1 text-xs font-medium text-green-800">
38
- capture
39
- </span>
40
- )}
41
36
  {attribute.archived && (
42
37
  <span className="ml-1 rounded-full bg-red-100 px-2 py-1 text-xs font-medium text-red-800">
43
38
  archived
@@ -29,12 +29,6 @@ export function DisplayAttributeOverview() {
29
29
  <dt className="text-sm font-medium text-gray-500">Type</dt>
30
30
  <dd className="mt-1 text-sm text-gray-900">{attribute.type}</dd>
31
31
  </div>
32
- <div>
33
- <dt className="text-sm font-medium text-gray-500">Capture</dt>
34
- <dd className="mt-1 text-sm text-gray-900">
35
- {attribute.capture === true ? <span>Yes</span> : <span>No</span>}
36
- </dd>
37
- </div>
38
32
  <div className="col-span-2">
39
33
  <dt className="text-sm font-medium text-gray-500">Description</dt>
40
34
  <dd className="mt-1 text-sm text-gray-900">
@@ -111,7 +111,9 @@ export function DisplayFeatureForceTable() {
111
111
  const { environmentKey } = useParams();
112
112
 
113
113
  const envKey = environmentKey as string;
114
- const force = feature.environments ? feature.environments[envKey].force : feature.force;
114
+
115
+ const force =
116
+ feature.force && !Array.isArray(feature.rules) ? feature.force[envKey] : feature.force;
115
117
 
116
118
  if (!force || force.length === 0) {
117
119
  return <p>n/a</p>;
@@ -184,7 +186,8 @@ export function DisplayFeatureForceTable() {
184
186
 
185
187
  export function DisplayFeatureForce() {
186
188
  const { feature } = useOutletContext() as any;
187
- const environmentKeys = feature.environments ? Object.keys(feature.environments).sort() : [];
189
+ const environmentKeys =
190
+ feature.force && !Array.isArray(feature.force) ? Object.keys(feature.force).sort() : [];
188
191
 
189
192
  const environmentTabs = environmentKeys.map((environmentKey) => {
190
193
  return {
@@ -228,8 +231,11 @@ export function DisplayFeatureRulesTable() {
228
231
  const { environmentKey } = useParams();
229
232
 
230
233
  const envKey = environmentKey as string;
231
- const rules = feature.environments ? feature.environments[envKey].rules : feature.rules;
232
- const expose = feature.environments ? feature.environments[envKey].expose : feature.expose;
234
+ const rules = !Array.isArray(feature.rules) ? feature.rules[envKey] : feature.rules;
235
+ const expose =
236
+ typeof feature.expose !== "undefined" && !Array.isArray(feature.rules)
237
+ ? feature.expose[envKey]
238
+ : feature.expose;
233
239
 
234
240
  if (!rules || rules.length === 0) {
235
241
  return <p>n/a</p>;
@@ -304,7 +310,7 @@ export function DisplayFeatureRulesTable() {
304
310
 
305
311
  export function DisplayFeatureRules() {
306
312
  const { feature } = useOutletContext() as any;
307
- const environmentKeys = feature.environments ? Object.keys(feature.environments).sort() : [];
313
+ const environmentKeys = feature.rules ? Object.keys(feature.rules).sort() : [];
308
314
 
309
315
  const environmentTabs = environmentKeys.map((environmentKey) => {
310
316
  return {
@@ -390,15 +396,17 @@ export function DisplayFeatureVariations() {
390
396
  <th className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
391
397
  {variation.variables && (
392
398
  <ul className="list-inside list-disc text-left">
393
- {variation.variables.map((v) => {
399
+ {Object.keys(variation.variables).map((variableKey) => {
400
+ const variableValue = variation.variables[variableKey];
401
+
394
402
  return (
395
- <li key={v.key}>
396
- <span className="font-semibold">{v.key}</span>:{" "}
397
- {typeof v.value === "string" ? (
398
- v.value
403
+ <li key={variableKey}>
404
+ <span className="font-semibold">{variableKey}</span>:{" "}
405
+ {typeof variableValue === "string" ? (
406
+ variableValue
399
407
  ) : (
400
408
  <pre className="rounded bg-gray-100 px-2 py-1 text-red-400">
401
- <code>{JSON.stringify(v.value, null, 2)}</code>
409
+ <code>{JSON.stringify(variableValue, null, 2)}</code>
402
410
  </pre>
403
411
  )}
404
412
  </li>
@@ -422,7 +430,7 @@ export function DisplayFeatureVariations() {
422
430
  export function DisplayFeatureVariablesSchema() {
423
431
  const { feature } = useOutletContext() as any;
424
432
 
425
- if (!feature.variablesSchema || feature.variablesSchema.length === 0) {
433
+ if (!feature.variablesSchema) {
426
434
  return <p>n/a</p>;
427
435
  }
428
436
 
@@ -440,32 +448,33 @@ export function DisplayFeatureVariablesSchema() {
440
448
  </thead>
441
449
 
442
450
  <tbody>
443
- {feature.variablesSchema.map((variableSchema, index) => {
444
- return (
445
- <tr key={variableSchema.key} className={index % 2 === 0 ? undefined : "bg-gray-50"}>
446
- <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
447
- {variableSchema.key}
448
- </td>
449
- <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
450
- {variableSchema.type}
451
- </td>
452
- <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
453
- {variableSchema.type === "string" ? (
454
- variableSchema.defaultValue
455
- ) : (
456
- <pre>
457
- <code className="rounded bg-gray-100 px-2 py-1 text-red-400">
458
- {JSON.stringify(variableSchema.defaultValue, null, 2)}
459
- </code>
460
- </pre>
461
- )}
462
- </td>
463
- <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
464
- {variableSchema.description || <span>n/a</span>}
465
- </td>
466
- </tr>
467
- );
468
- })}
451
+ {feature.variablesSchema &&
452
+ Object.keys(feature.variablesSchema).map((variableKey, index) => {
453
+ const variableSchema = feature.variablesSchema[variableKey];
454
+
455
+ return (
456
+ <tr key={variableSchema.key} className={index % 2 === 0 ? undefined : "bg-gray-50"}>
457
+ <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">{variableKey}</td>
458
+ <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
459
+ {variableSchema.type}
460
+ </td>
461
+ <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
462
+ {variableSchema.type === "string" ? (
463
+ variableSchema.defaultValue
464
+ ) : (
465
+ <pre>
466
+ <code className="rounded bg-gray-100 px-2 py-1 text-red-400">
467
+ {JSON.stringify(variableSchema.defaultValue, null, 2)}
468
+ </code>
469
+ </pre>
470
+ )}
471
+ </td>
472
+ <td className="py-4 pl-4 pr-3 text-sm font-medium text-gray-700">
473
+ {variableSchema.description || <span>n/a</span>}
474
+ </td>
475
+ </tr>
476
+ );
477
+ })}
469
478
  </tbody>
470
479
  </table>
471
480
  );
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
 
3
- import { SearchIndex } from "@featurevisor/types";
3
+ import type { SearchIndex } from "@featurevisor/types";
4
4
 
5
5
  export interface SearchIndexProps {
6
6
  isLoaded: boolean;
@@ -1,5 +1,5 @@
1
1
  import { useContext } from "react";
2
- import { SearchIndex } from "@featurevisor/types";
2
+ import type { SearchIndex } from "@featurevisor/types";
3
3
 
4
4
  import { SearchIndexContext } from "../contexts/SearchIndexContext";
5
5
 
@@ -1,11 +1,10 @@
1
- import { SearchIndex } from "@featurevisor/types";
1
+ import type { SearchIndex } from "@featurevisor/types";
2
2
 
3
3
  export interface Query {
4
4
  keyword: string;
5
5
  tags: string[];
6
6
  environments: string[];
7
7
  archived?: boolean;
8
- capture?: boolean;
9
8
  hasVariations?: boolean;
10
9
  hasVariables?: boolean;
11
10
  variableKeys?: string[];
@@ -18,7 +17,6 @@ export function parseSearchQuery(queryString: string) {
18
17
  tags: [],
19
18
  environments: [],
20
19
  archived: undefined,
21
- capture: undefined,
22
20
  };
23
21
 
24
22
  const parts = queryString.split(" ");
@@ -44,14 +42,6 @@ export function parseSearchQuery(queryString: string) {
44
42
  } else if (archived === "false") {
45
43
  query.archived = false;
46
44
  }
47
- } else if (part.startsWith("capture:")) {
48
- const capture = part.replace("capture:", "");
49
-
50
- if (capture === "true") {
51
- query.capture = true;
52
- } else if (capture === "false") {
53
- query.capture = false;
54
- }
55
45
  } else if (part.startsWith("variable:")) {
56
46
  const variableKey = part.replace("variable:", "");
57
47
 
@@ -95,20 +85,20 @@ export function isEnabledInEnvironment(feature: any, environment: string) {
95
85
  return false;
96
86
  }
97
87
 
98
- if (feature.environments) {
88
+ if (!Array.isArray(feature.rules)) {
99
89
  // with environments
100
- if (!feature.environments[environment]) {
90
+ if (!feature.rules[environment]) {
101
91
  return false;
102
92
  }
103
93
 
104
- if (feature.environments[environment].expose === false) {
94
+ if (feature.rules[environment].expose === false) {
105
95
  return false;
106
96
  }
107
97
 
108
- if (feature.environments[environment].rules.some((rule: any) => rule.percentage > 0)) {
98
+ if (feature.rules[environment].some((rule: any) => rule.percentage > 0)) {
109
99
  return true;
110
100
  }
111
- } else {
101
+ } else if (feature.rules) {
112
102
  // no environments
113
103
  if (feature.rules.some((rule: any) => rule.percentage > 0)) {
114
104
  return true;
@@ -120,7 +110,7 @@ export function isEnabledInEnvironment(feature: any, environment: string) {
120
110
 
121
111
  export function isEnabledInAnyEnvironment(feature: any) {
122
112
  // no environments
123
- if (feature.rules) {
113
+ if (Array.isArray(feature.rules)) {
124
114
  if (feature.rules.some((rule: any) => rule.percentage > 0)) {
125
115
  return true;
126
116
  }
@@ -129,7 +119,7 @@ export function isEnabledInAnyEnvironment(feature: any) {
129
119
  }
130
120
 
131
121
  // with environments
132
- const environments = Object.keys(feature.environments);
122
+ const environments = Object.keys(feature.rules);
133
123
 
134
124
  for (const environment of environments) {
135
125
  const isEnabled = isEnabledInEnvironment(feature, environment);
@@ -206,7 +196,7 @@ export function getFeaturesByQuery(query: Query, data: SearchIndex) {
206
196
  if (!feature.variablesSchema) {
207
197
  matched = false;
208
198
  } else {
209
- const keysFromFeature = feature.variablesSchema.map((v: any) => v.key);
199
+ const keysFromFeature = Object.keys(feature.variablesSchema);
210
200
 
211
201
  if (query.variableKeys.some((k) => keysFromFeature.indexOf(k) === -1)) {
212
202
  matched = false;
@@ -253,16 +243,6 @@ export function getAttributesByQuery(query: Query, data: SearchIndex) {
253
243
  }
254
244
  }
255
245
 
256
- if (typeof query.capture === "boolean") {
257
- if (query.capture && a.capture !== query.capture) {
258
- matched = false;
259
- }
260
-
261
- if (!query.capture && a.capture === true) {
262
- matched = false;
263
- }
264
- }
265
-
266
246
  return matched;
267
247
  })
268
248
  .sort((a, b) => a.key.localeCompare(b.key));