datacontract-cli 0.10.3__py3-none-any.whl → 0.10.5__py3-none-any.whl

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.

Potentially problematic release.


This version of datacontract-cli might be problematic. Click here for more details.

Files changed (41) hide show
  1. datacontract/breaking/breaking.py +12 -0
  2. datacontract/breaking/breaking_rules.py +4 -0
  3. datacontract/catalog/catalog.py +2 -2
  4. datacontract/cli.py +42 -8
  5. datacontract/data_contract.py +84 -134
  6. datacontract/engines/soda/check_soda_execute.py +5 -0
  7. datacontract/engines/soda/connections/duckdb.py +1 -2
  8. datacontract/engines/soda/connections/sqlserver.py +43 -0
  9. datacontract/export/avro_converter.py +23 -2
  10. datacontract/export/bigquery_converter.py +107 -0
  11. datacontract/export/dbml_converter.py +118 -0
  12. datacontract/export/go_converter.py +98 -0
  13. datacontract/export/html_export.py +4 -2
  14. datacontract/export/jsonschema_converter.py +41 -2
  15. datacontract/export/rdf_converter.py +1 -2
  16. datacontract/export/sql_converter.py +1 -0
  17. datacontract/export/sql_type_converter.py +125 -4
  18. datacontract/imports/avro_importer.py +41 -14
  19. datacontract/imports/bigquery_importer.py +178 -0
  20. datacontract/imports/jsonschema_importer.py +148 -0
  21. datacontract/imports/sql_importer.py +2 -2
  22. datacontract/lint/resolve.py +1 -2
  23. datacontract/model/data_contract_specification.py +65 -1
  24. datacontract/publish/publish.py +32 -0
  25. datacontract/py.typed +0 -0
  26. datacontract/templates/datacontract.html +37 -346
  27. datacontract/templates/index.html +70 -5
  28. datacontract/templates/partials/datacontract_information.html +66 -0
  29. datacontract/templates/partials/datacontract_servicelevels.html +253 -0
  30. datacontract/templates/partials/datacontract_terms.html +44 -0
  31. datacontract/templates/partials/definition.html +99 -0
  32. datacontract/templates/partials/example.html +27 -0
  33. datacontract/templates/partials/model_field.html +97 -0
  34. datacontract/templates/partials/server.html +144 -0
  35. datacontract/templates/style/output.css +99 -13
  36. {datacontract_cli-0.10.3.dist-info → datacontract_cli-0.10.5.dist-info}/METADATA +276 -139
  37. {datacontract_cli-0.10.3.dist-info → datacontract_cli-0.10.5.dist-info}/RECORD +41 -26
  38. {datacontract_cli-0.10.3.dist-info → datacontract_cli-0.10.5.dist-info}/LICENSE +0 -0
  39. {datacontract_cli-0.10.3.dist-info → datacontract_cli-0.10.5.dist-info}/WHEEL +0 -0
  40. {datacontract_cli-0.10.3.dist-info → datacontract_cli-0.10.5.dist-info}/entry_points.txt +0 -0
  41. {datacontract_cli-0.10.3.dist-info → datacontract_cli-0.10.5.dist-info}/top_level.txt +0 -0
@@ -6,7 +6,7 @@
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
7
  {# <script src="https://cdn.tailwindcss.com"></script> #}
8
8
  <style>
9
- {{style | safe }}
9
+ {{ style | safe }}
10
10
  </style>
11
11
  </head>
12
12
  <body class="h-full">
@@ -58,78 +58,13 @@
58
58
 
59
59
  <div>
60
60
  <div class="space-y-6 mt-6">
61
- <section>
62
- <div class=" px-4 sm:px-0">
63
- <h1 class="text-base font-semibold leading-6 text-gray-900" id="info">Info</h1>
64
- <p class="text-sm text-gray-500">Information about the data contract</p>
65
- </div>
66
- <div class="mt-2 overflow-hidden shadow sm:rounded-lg bg-white">
67
-
68
- <div class="px-4 py-5 sm:px-6">
69
-
70
- <dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
71
- <div class="sm:col-span-1">
72
- <dt class="text-sm font-medium text-gray-500">Title</dt>
73
- <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.title }}</dd>
74
- </div>
75
-
76
- <div class="sm:col-span-1">
77
- <dt class="text-sm font-medium text-gray-500">Version</dt>
78
- <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.version }}</dd>
79
- </div>
80
-
81
- {% if datacontract.info.status %}
82
- <div class="sm:col-span-1">
83
- <dt class="text-sm font-medium text-gray-500">Status</dt>
84
- <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.status }}</dd>
85
- </div>
86
- {% endif %}
87
-
88
- {% if datacontract.info.description %}
89
- <div class="sm:col-span-2">
90
- <dt class="text-sm font-medium text-gray-500">Description</dt>
91
- <dd class="mt-1 text-sm text-gray-900" >
92
- <span class="whitespace-pre-wrap">{{ datacontract.info.description }}</span>
93
- </dd>
94
- </div>
95
- {% endif %}
96
-
97
- {% if datacontract.info.owner %}
98
- <div class="sm:col-span-1">
99
- <dt class="text-sm font-medium text-gray-500">Owner</dt>
100
- <dd class="mt-1 text-sm text-gray-900">
101
- <span>{{ datacontract.info.owner }}</span>
102
- </dd>
103
- </div>
104
- {% endif %}
105
-
106
- {% if datacontract.info.contact %}
107
- <div class="sm:col-span-1">
108
- <dt class="text-sm font-medium text-gray-500">Contact</dt>
109
- <dd class="mt-1 text-sm text-gray-900">
110
- {% if datacontract.info.contact.name %}
111
- {{ datacontract.info.contact.name }}
112
- {% endif %}
113
- {% if datacontract.info.contact.email %}
114
- <a href="mailto:{{ datacontract.info.contact.email }}" class="text-sky-500 hover:text-gray-700">{{ datacontract.info.contact.email }}</a>
115
- {% endif %}
116
- {% if datacontract.info.contact.url %}
117
- <div>
118
- <a href="{{ datacontract.info.contact.url }}" class="text-sky-500 hover:text-gray-700">{{ datacontract.info.contact.url }}</a>
119
- </div>
120
- {% endif %}
121
- </dd>
122
- </div>
123
- {% endif %}
124
-
125
- </dl>
126
- </div>
127
- </div>
61
+ <section id="information">
62
+ {{ render_partial('partials/datacontract_information.html', datacontract = datacontract) }}
128
63
  </section>
129
64
 
130
65
 
131
66
  {% if datacontract.servers %}
132
- <section>
67
+ <section id="servers">
133
68
  <div class="px-4 sm:px-0">
134
69
  <h1 class="text-base font-semibold leading-6 text-gray-900" id="servers">Servers</h1>
135
70
  <p class="text-sm text-gray-500">Servers of the data contract</p>
@@ -138,150 +73,7 @@
138
73
  <ul role="list" class="mt-2 divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-lg">
139
74
 
140
75
  {% for server_name, server in datacontract.servers.items() %}
141
- <li class="relative flex gap-x-6 px-4 py-5 sm:px-6">
142
- <div class="flex items-center gap-x-4">
143
- <div class="hidden sm:flex sm:flex-col">
144
- <dt class="text-sm font-medium text-gray-500">Server</dt>
145
- <dd class="mt-1 text-sm text-gray-900">{{server_name}}</dd>
146
- </div>
147
- </div>
148
-
149
- {% if server.type %}
150
- <div class="flex items-center gap-x-4">
151
- <div class="hidden sm:flex sm:flex-col">
152
- <dt class="text-sm font-medium text-gray-500">Type</dt>
153
- <dd class="mt-1 text-sm text-gray-900">{{server.type}}</dd>
154
- </div>
155
- </div>
156
- {% endif %}
157
-
158
- {% if server.project %}
159
- <div class="flex items-center gap-x-4">
160
- <div class="hidden sm:flex sm:flex-col">
161
- <dt class="text-sm font-medium text-gray-500">Project</dt>
162
- <dd class="mt-1 text-sm text-gray-900">{{server.project}}</dd>
163
- </div>
164
- </div>
165
- {% endif %}
166
-
167
- {% if server.dataset %}
168
- <div class="flex items-center gap-x-4">
169
- <div class="hidden sm:flex sm:flex-col">
170
- <dt class="text-sm font-medium text-gray-500">Dataset</dt>
171
- <dd class="mt-1 text-sm text-gray-900">{{server.dataset}}</dd>
172
- </div>
173
- </div>
174
- {% endif %}
175
-
176
- {% if server.location %}
177
- <div class="flex items-center gap-x-4">
178
- <div class="hidden sm:flex sm:flex-col">
179
- <dt class="text-sm font-medium text-gray-500">Location</dt>
180
- <dd class="mt-1 text-sm text-gray-900">{{server.location}}</dd>
181
- </div>
182
- </div>
183
- {% endif %}
184
-
185
- {% if server.endpointUrl %}
186
- <div class="flex items-center gap-x-4">
187
- <div class="hidden sm:flex sm:flex-col">
188
- <dt class="text-sm font-medium text-gray-500">Endpoint URL</dt>
189
- <dd class="mt-1 text-sm text-gray-900">{{server.endpointUrl}}</dd>
190
- </div>
191
- </div>
192
- {% endif %}
193
-
194
- {% if server.account %}
195
- <div class="flex items-center gap-x-4">
196
- <div class="hidden sm:flex sm:flex-col">
197
- <dt class="text-sm font-medium text-gray-500">Account</dt>
198
- <dd class="mt-1 text-sm text-gray-900">{{server.account}}</dd>
199
- </div>
200
- </div>
201
- {% endif %}
202
-
203
- {% if server.host %}
204
- <div class="flex items-center gap-x-4">
205
- <div class="hidden sm:flex sm:flex-col">
206
- <dt class="text-sm font-medium text-gray-500">Host</dt>
207
- <dd class="mt-1 text-sm text-gray-900">{{server.host}}</dd>
208
- </div>
209
- </div>
210
- {% endif %}
211
-
212
- {% if server.port %}
213
- <div class="flex items-center gap-x-4">
214
- <div class="hidden sm:flex sm:flex-col">
215
- <dt class="text-sm font-medium text-gray-500">Port</dt>
216
- <dd class="mt-1 text-sm text-gray-900">{{server.port}}</dd>
217
- </div>
218
- </div>
219
- {% endif %}
220
-
221
- {% if server.catalog %}
222
- <div class="flex items-center gap-x-4">
223
- <div class="hidden sm:flex sm:flex-col">
224
- <dt class="text-sm font-medium text-gray-500">Catalog</dt>
225
- <dd class="mt-1 text-sm text-gray-900">{{server.catalog}}</dd>
226
- </div>
227
- </div>
228
- {% endif %}
229
-
230
- {% if server.database %}
231
- <div class="flex items-center gap-x-4">
232
- <div class="hidden sm:flex sm:flex-col">
233
- <dt class="text-sm font-medium text-gray-500">Database</dt>
234
- <dd class="mt-1 text-sm text-gray-900">{{server.database}}</dd>
235
- </div>
236
- </div>
237
- {% endif %}
238
-
239
- {% if server.schema_ %}
240
- <div class="flex items-center gap-x-4">
241
- <div class="hidden sm:flex sm:flex-col">
242
- <dt class="text-sm font-medium text-gray-500">Schema</dt>
243
- <dd class="mt-1 text-sm text-gray-900">{{server.schema_}}</dd>
244
- </div>
245
- </div>
246
- {% endif %}
247
-
248
- {% if server.topic %}
249
- <div class="flex items-center gap-x-4">
250
- <div class="hidden sm:flex sm:flex-col">
251
- <dt class="text-sm font-medium text-gray-500">Topic</dt>
252
- <dd class="mt-1 text-sm text-gray-900">{{server.topic}}</dd>
253
- </div>
254
- </div>
255
- {% endif %}
256
-
257
- {% if server.path %}
258
- <div class="flex items-center gap-x-4">
259
- <div class="hidden sm:flex sm:flex-col">
260
- <dt class="text-sm font-medium text-gray-500">Path</dt>
261
- <dd class="mt-1 text-sm text-gray-900">{{server.path}}</dd>
262
- </div>
263
- </div>
264
- {% endif %}
265
-
266
- {% if server.format %}
267
- <div class="flex items-center gap-x-4">
268
- <div class="hidden sm:flex sm:flex-col">
269
- <dt class="text-sm font-medium text-gray-500">Format</dt>
270
- <dd class="mt-1 text-sm text-gray-900">{{server.format}}</dd>
271
- </div>
272
- </div>
273
- {% endif %}
274
-
275
- {% if server.delimiter %}
276
- <div class="flex items-center gap-x-4">
277
- <div class="hidden sm:flex sm:flex-col">
278
- <dt class="text-sm font-medium text-gray-500">Delimiter</dt>
279
- <dd class="mt-1 text-sm text-gray-900">{{server.delimiter}}</dd>
280
- </div>
281
- </div>
282
- {% endif %}
283
-
284
- </li>
76
+ {{ render_partial('partials/server.html', server_name = server_name, server = server) }}
285
77
  {% endfor %}
286
78
 
287
79
  </ul>
@@ -291,51 +83,8 @@
291
83
 
292
84
 
293
85
  {% if datacontract.terms %}
294
- <section>
295
- <div class="px-4 sm:px-0">
296
- <h1 class="text-base font-semibold leading-6 text-gray-900" id="terms">Terms</h1>
297
- <p class="text-sm text-gray-500">Terms and conditions of the data contract</p>
298
- </div>
299
- <div class="mt-2 overflow-hidden shadow sm:rounded-lg bg-white">
300
-
301
- <div class="px-4 py-5 sm:px-6">
302
-
303
- <dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
304
- <div class="sm:col-span-1">
305
- <dt class="text-sm font-medium text-gray-500">Usage</dt>
306
- <dd class="mt-1 text-sm text-gray-900" >
307
- <span class="whitespace-pre-wrap">{{ datacontract.terms.usage }}</span>
308
- </dd>
309
- </div>
310
-
311
- <div class="sm:col-span-1">
312
- <dt class="text-sm font-medium text-gray-500">Limitations</dt>
313
- <dd class="mt-1 text-sm text-gray-900" >
314
- <span class="whitespace-pre-wrap">{{ datacontract.terms.limitations }}</span>
315
- </dd>
316
- </div>
317
-
318
- {% if datacontract.terms.billing %}
319
- <div class="sm:col-span-1">
320
- <dt class="text-sm font-medium text-gray-500">Billing</dt>
321
- <dd class="mt-1 text-sm text-gray-900" >
322
- <span class="whitespace-pre-wrap">{{ datacontract.terms.billing }}</span>
323
- </dd>
324
- </div>
325
- {% endif %}
326
-
327
- {% if datacontract.terms.noticePeriod %}
328
- <div class="sm:col-span-1">
329
- <dt class="text-sm font-medium text-gray-500">Notice Period</dt>
330
- <dd class="mt-1 text-sm text-gray-900 flex" >
331
- <span class="whitespace-pre-wrap">{{ datacontract.terms.noticePeriod }}</span>
332
- </dd>
333
- </div>
334
- {% endif %}
335
-
336
- </dl>
337
- </div>
338
- </div>
86
+ <section id="terms">
87
+ {{ render_partial('partials/datacontract_terms.html', datacontract = datacontract) }}
339
88
  </section>
340
89
  {% endif %}
341
90
 
@@ -369,90 +118,9 @@
369
118
  </tr>
370
119
  </thead>
371
120
  <tbody class="divide-y divide-gray-200 bg-white">
372
-
373
121
  {% for field_name, field in model.fields.items() %}
374
-
375
- <tr>
376
- <td class="whitespace-nowrap py-2 pl-4 pr-2 text-sm font-medium text-gray-900 sm:pl-6 w-2/12">
377
- <div class="py-2 text-sm">
378
- {% if field.title %}
379
- <div>{{ field.title }}</div>
380
- {% endif %}
381
- <div class="font-mono">{{ field_name }}</div>
382
- {# TODO nested fields #}
383
- </div>
384
- </td>
385
- <td class="whitespace-nowrap px-1 py-2 text-sm text-gray-500 w-1/12">
386
- {% if field.type %}
387
- {{ field.type }}
388
- {% endif %}
389
- </td>
390
- <td class="px-3 py-2 text-sm text-gray-500 w-7/12">
391
- {% if field.description %}
392
- <div class="text-gray-500">{{ field.description }}</div>
393
- {% else %}
394
- <div class="text-gray-400">No description</div>
395
- {% endif %}
396
-
397
- {% if field.example %}
398
- <div class="mt-1 italic">
399
- Example: {{ field.example }}
400
- </div>
401
- {% endif %}
402
-
403
- <div>
404
- {% if field.primary %}
405
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">primary</span>
406
- {% endif %}
407
- {% if field.required %}
408
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">required</span>
409
- {% endif %}
410
- {% if field.unique %}
411
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">unique</span>
412
- {% endif %}
413
- {% if field.format %}
414
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">format:{{ field.format }}</span>
415
- {% endif %}
416
- {% if field.minLength %}
417
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">minLength:{{ field.minLength }}</span>
418
- {% endif %}
419
- {% if field.maxLength %}
420
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">maxLength:{{ field.maxLength }}</span>
421
- {% endif %}
422
- {% if field.pattern %}
423
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">pattern:{{ field.pattern }}</span>
424
- {% endif %}
425
- {% if field.precision %}
426
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">precision:{{ field.precision }}</span>
427
- {% endif %}
428
- {% if field.scale %}
429
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">scale:{{ field.scale }}</span>
430
- {% endif %}
431
- {% if field.minimum %}
432
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">minimum:{{ field.minimum }}</span>
433
- {% endif %}
434
- {% if field.exclusiveMinimum %}
435
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">exclusiveMinimum:{{ field.exclusiveMinimum }}</span>
436
- {% endif %}
437
- {% if field.maximum %}
438
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">maximum:{{ field.maximum }}</span>
439
- {% endif %}
440
- {% if field.exclusiveMaximum %}
441
- <span class="inline-flex items-center rounded-md bg-gray-50 px-1 py-1 text-xs font-medium text-gray-600 ring-1 ring-inset ring-gray-500/10 mr-1 mt-1">exclusiveMaximum:{{ field.exclusiveMaximum }}</span>
442
- {% endif %}
443
- {% if field.classification %}
444
- <span class="inline-flex items-center rounded-md bg-blue-50 px-1 py-1 text-xs font-medium text-blue-600 ring-1 ring-inset ring-blue-500/10 mr-1 mt-1">{{ field.classification }}</span>
445
- {% endif %}
446
- {% if field.pii %}
447
- <span class="inline-flex items-center rounded-md bg-yellow-50 px-1 py-1 text-xs font-medium text-yellow-600 ring-1 ring-inset ring-yellow-500/10 mr-1 mt-1">PII</span>
448
- {% endif %}
449
- </div>
450
-
451
- </td>
452
-
453
- </tr>
122
+ {{ render_partial('partials/model_field.html', nested = False, field_name=field_name, field = field, level = 0) }}
454
123
  {% endfor %}
455
-
456
124
  </tbody>
457
125
  </table>
458
126
  </div>
@@ -460,12 +128,38 @@
460
128
  </div>
461
129
  </div>
462
130
  {% endfor %}
463
-
464
131
  </section>
132
+
133
+ {% if datacontract.definitions %}
134
+ <section id="definitions">
135
+ <div class="px-4 sm:px-0">
136
+ <h1 class="text-base font-semibold leading-6 text-gray-900">Definitions</h1>
137
+ <p class="text-sm text-gray-500">Domain specific definitions in the data contract</p>
138
+ </div>
139
+
140
+ {% for definition_name, definition in datacontract.definitions.items() %}
141
+ {{ render_partial('partials/definition.html', definition_name = definition_name, definition = definition)}}
142
+ {% endfor %}
143
+ </section>
144
+ {% endif %}
465
145
 
466
- {# TODO add definitions #}
146
+ {% if datacontract.examples %}
147
+ <section id="examples">
148
+ <div class="px-4 sm:px-0">
149
+ <h1 class="text-base font-semibold leading-6 text-gray-900">Examples</h1>
150
+ <p class="text-sm text-gray-500">Examples for models in the data contract</p>
151
+ </div>
152
+ {% for example in datacontract.examples %}
153
+ {{ render_partial('partials/example.html', example = example) }}
154
+ {% endfor %}
155
+ </section>
156
+ {% endif %}
467
157
 
468
- {# TODO add service levels #}
158
+ {% if datacontract.servicelevels %}
159
+ <section id="servicelevels">
160
+ {{ render_partial('partials/datacontract_servicelevels.html', datacontract = datacontract ) }}
161
+ </section>
162
+ {% endif %}
469
163
 
470
164
  {% if quality_specification %}
471
165
  <section id="quality">
@@ -476,8 +170,6 @@
476
170
  <p class="text-sm text-gray-500">
477
171
  <span>{{ datacontract.quality.type }}</span>
478
172
  </p>
479
-
480
-
481
173
  </div>
482
174
  <div class="mt-2 overflow-hidden shadow sm:rounded-lg bg-white">
483
175
  <div class="px-4 py-5 sm:px-6">
@@ -490,7 +182,6 @@
490
182
  {% endif %}
491
183
 
492
184
  </div>
493
-
494
185
  </div>
495
186
 
496
187
  <div class="mt-6 text-sm text-gray-400">
@@ -14,7 +14,7 @@
14
14
  <div class="min-h-full flex flex-col">
15
15
 
16
16
  <nav class="bg-white shadow-sm">
17
- <div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
17
+ <div class="mx-auto max-w-7xl px-6 lg:px-8">
18
18
  <div class="flex h-16 justify-between">
19
19
  <div class="flex">
20
20
  <div class="flex flex-shrink-0 items-center mr-6">
@@ -32,9 +32,9 @@
32
32
 
33
33
  <main class="pb-7">
34
34
 
35
- <div class="pt-5 mx-auto max-w-7xl sm:px-6 lg:px-8">
35
+ <div class="pt-5 mx-auto max-w-7xl px-6 lg:px-8">
36
36
  <div>
37
- <div class="lg:flex lg:items-center lg:justify-between px-4 sm:px-0">
37
+ <div class="lg:flex lg:items-center lg:justify-between px-0">
38
38
  <div class="min-w-0 flex-1">
39
39
  <h2 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
40
40
  Data Contract Catalog</h2>
@@ -50,13 +50,44 @@
50
50
 
51
51
  <section id="catalog">
52
52
 
53
- {# TODO search and filter form #}
53
+ {% if contracts_size > 0 %}
54
+
55
+ <form aria-labelledby="filter-heading" class="pb-4" >
56
+ <h2 id="filter-heading" class="sr-only">Filters</h2>
57
+ <div class="sm:flex items-center justify-between">
58
+ <div class="sm:flex items-baseline space-x-8">
59
+ <div>
60
+ <div class="relative rounded-md shadow-sm">
61
+ <div class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-3">
62
+ <svg class="pointer-events-none absolute h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
63
+ <path fill-rule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clip-rule="evenodd" />
64
+ </svg>
65
+ </div>
66
+ <input type="text" name="q" id="search" class="block w-full sm:w-72 rounded-md border-0 py-1.5 pl-10 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" placeholder="Search">
67
+ </div>
68
+ </div>
69
+ </div>
70
+ </div>
71
+ </form>
72
+ {% endif %}
73
+
54
74
 
55
75
  <ul role="list" class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 ">
56
76
 
57
77
  {% for contract in contracts %}
58
78
 
59
- <li class="col-span-1 rounded-lg bg-white shadow hover:bg-gray-50">
79
+ <li class="col-span-1 rounded-lg bg-white shadow hover:bg-gray-50"
80
+ data-search="{{
81
+ contract.spec.info.title|lower }} {{
82
+ contract.spec.info.owner|lower if contract.spec.info.owner else '' }} {{
83
+ contract.spec.info.description|lower }} {%
84
+ for model_name, model in contract.spec.models.items() %}
85
+ {{ model.description|lower }} {%
86
+ for field_name, field in model.fields.items() %}
87
+ {{ field_name|lower }} {{ field.description|lower if field.description else '' }} {%
88
+ endfor %}
89
+ {% endfor %}
90
+ ">
60
91
  <a href="{{contract.html_link}}" >
61
92
  <div class="flex w-full justify-between space-x-1 p-6 pb-4">
62
93
  <div class="flex-1 truncate">
@@ -98,6 +129,10 @@
98
129
  {% endif %}
99
130
 
100
131
 
132
+ <div id="no-results" class="hidden text-sm text-gray-500">
133
+ No results found.
134
+ </div>
135
+
101
136
  </section>
102
137
 
103
138
  </div>
@@ -164,5 +199,35 @@
164
199
 
165
200
  </div>
166
201
 
202
+ <script>
203
+ document.addEventListener('DOMContentLoaded', function() {
204
+ const searchInput = document.getElementById('search');
205
+ const contractsList = document.querySelectorAll('#catalog li');
206
+ const noResults = document.getElementById('no-results');
207
+
208
+ searchInput.addEventListener('keyup', function() {
209
+ let visibleCount = 0; // Counter to track the number of visible items
210
+ const searchText = searchInput.value.toLowerCase();
211
+
212
+ contractsList.forEach(contract => {
213
+ const searchData = contract.getAttribute('data-search');
214
+ if (searchData && searchData.includes(searchText)) {
215
+ contract.style.display = '';
216
+ visibleCount++;
217
+ } else {
218
+ contract.style.display = 'none';
219
+ }
220
+ });
221
+
222
+ // Manage the visibility of the no results message
223
+ if (visibleCount === 0) {
224
+ noResults.classList.remove('hidden'); // Show the message if no items are visible
225
+ } else {
226
+ noResults.classList.add('hidden'); // Hide the message if there are visible items
227
+ }
228
+ });
229
+ });
230
+ </script>
231
+
167
232
  </body>
168
233
  </html>
@@ -0,0 +1,66 @@
1
+ <div class=" px-4 sm:px-0">
2
+ <h1 class="text-base font-semibold leading-6 text-gray-900" id="info">Info</h1>
3
+ <p class="text-sm text-gray-500">Information about the data contract</p>
4
+ </div>
5
+ <div class="mt-2 overflow-hidden shadow sm:rounded-lg bg-white">
6
+
7
+ <div class="px-4 py-5 sm:px-6">
8
+
9
+ <dl class="grid grid-cols-1 gap-x-4 gap-y-6 sm:grid-cols-2">
10
+ <div class="sm:col-span-1">
11
+ <dt class="text-sm font-medium text-gray-500">Title</dt>
12
+ <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.title }}</dd>
13
+ </div>
14
+
15
+ <div class="sm:col-span-1">
16
+ <dt class="text-sm font-medium text-gray-500">Version</dt>
17
+ <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.version }}</dd>
18
+ </div>
19
+
20
+ {% if datacontract.info.status %}
21
+ <div class="sm:col-span-1">
22
+ <dt class="text-sm font-medium text-gray-500">Status</dt>
23
+ <dd class="mt-1 text-sm text-gray-900">{{ datacontract.info.status }}</dd>
24
+ </div>
25
+ {% endif %}
26
+
27
+ {% if datacontract.info.description %}
28
+ <div class="sm:col-span-2">
29
+ <dt class="text-sm font-medium text-gray-500">Description</dt>
30
+ <dd class="mt-1 text-sm text-gray-900" >
31
+ <span class="whitespace-pre-wrap">{{ datacontract.info.description }}</span>
32
+ </dd>
33
+ </div>
34
+ {% endif %}
35
+
36
+ {% if datacontract.info.owner %}
37
+ <div class="sm:col-span-1">
38
+ <dt class="text-sm font-medium text-gray-500">Owner</dt>
39
+ <dd class="mt-1 text-sm text-gray-900">
40
+ <span>{{ datacontract.info.owner }}</span>
41
+ </dd>
42
+ </div>
43
+ {% endif %}
44
+
45
+ {% if datacontract.info.contact %}
46
+ <div class="sm:col-span-1">
47
+ <dt class="text-sm font-medium text-gray-500">Contact</dt>
48
+ <dd class="mt-1 text-sm text-gray-900">
49
+ {% if datacontract.info.contact.name %}
50
+ {{ datacontract.info.contact.name }}
51
+ {% endif %}
52
+ {% if datacontract.info.contact.email %}
53
+ <a href="mailto:{{ datacontract.info.contact.email }}" class="text-sky-500 hover:text-gray-700">{{ datacontract.info.contact.email }}</a>
54
+ {% endif %}
55
+ {% if datacontract.info.contact.url %}
56
+ <div>
57
+ <a href="{{ datacontract.info.contact.url }}" class="text-sky-500 hover:text-gray-700">{{ datacontract.info.contact.url }}</a>
58
+ </div>
59
+ {% endif %}
60
+ </dd>
61
+ </div>
62
+ {% endif %}
63
+
64
+ </dl>
65
+ </div>
66
+ </div>