JoanGiner commited on
Commit
3759fd0
·
0 Parent(s):

first commit

Browse files
Files changed (6) hide show
  1. .gitignore +2 -0
  2. app.py +24 -0
  3. dataModel.py +10 -0
  4. eventHanlder.py +13 -0
  5. requirements.txt +0 -0
  6. sdc_view.py +380 -0
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ .venv
2
+ __pycache__
app.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ import json
4
+ import argparse
5
+ import streamlit as st
6
+ from sdc_view import render_sdc
7
+
8
+
9
+ ##
10
+ ## Streamlit!
11
+ ##
12
+ st.set_page_config(page_title="The Software Diversity Card", page_icon=":woman_and_man_holding_hands:", layout="wide")
13
+
14
+ # Hide the deploy button
15
+ st.markdown("""
16
+ <style>
17
+ [data-testid="stAppDeployButton"] { visibility: hidden; }
18
+ .stMainBlockContainer { max-width: 1280px; }
19
+ </style>
20
+ """,
21
+ unsafe_allow_html=True)
22
+
23
+ render_sdc()
24
+
dataModel.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ class DevelopmentTeam():
2
+ """ hey """
3
+ members: str | None = None
4
+
5
+
6
+ class AST():
7
+ """main SDC data object, representation of the AST"""
8
+ SDC_governance_funders: str | None = None
9
+ SDC_development_team: DevelopmentTeam | None = None
10
+
eventHanlder.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from dataModel import AST
2
+ import streamlit as st
3
+
4
+ def handle_value_change(event, metadata, key: str, index: int = 0):
5
+
6
+ print(event)
7
+ print(metadata)
8
+ print(key)
9
+ print("this is changing the state")
10
+ print(st.session_state[key])
11
+ if event == "governance_projectType":
12
+ AST.SDC_governance_projecType = st.session_state[key]
13
+
requirements.txt ADDED
Binary file (1.69 kB). View file
 
sdc_view.py ADDED
@@ -0,0 +1,380 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from dataModel import AST
3
+ from eventHanlder import handle_value_change
4
+ import json
5
+
6
+
7
+
8
+ def render_sdc():
9
+
10
+
11
+ country_options = [
12
+ "USA", "Canada", "Mexico", "UK", "Germany",
13
+ "France", "Italy", "Spain", "Australia", "Japan"
14
+ ]
15
+ EducationalLevelType = ['earlyChildhood','primary','lowerSecondary','upperSecondary','postSecondaryNonTertiary','shortCycleTertiary','bachelorEquivalent','masterEquivalent','doctorateEquivalent']
16
+ SESType = ['upperClass' ,'upperMiddleClass' ,'middleClass' , 'lowerMiddleClass' , 'lowerClass']
17
+ SkillLevelType = ['expert' , 'proficient' , 'advanced' , 'competent' , 'beginner']
18
+ ISO3166 = ['Andorra', 'UnitedArabEmirates', 'Afghanistan', 'AntiguaandBarbuda', 'Anguilla', 'Albania', 'Armenia', 'Angola', 'Antarctica', 'Argentina', 'AmericanSamoa', 'Austria', 'Australia', 'Aruba', 'ÅlandIslands', 'Azerbaijan', 'BosniaandHerzegovina', 'Barbados', 'Bangladesh', 'Belgium', 'BurkinaFaso', 'Bulgaria', 'Bahrain', 'Burundi', 'Benin', 'SaintBarthélemy', 'Bermuda', 'BruneiDarussalam', 'Bolivia,PlurinationalStateof', 'Bonaire,SintEustatiusandSaba', 'Brazil', 'Bahamas', 'Bhutan', 'BouvetIsland', 'Botswana', 'Belarus', 'Belize', 'Canada', 'Cocos(Keeling)Islands', 'Congo,DemocraticRepublicofthe', 'CentralAfricanRepublic', 'Congo', 'Switzerland', 'CôtedIvoire', 'CookIslands', 'Chile', 'Cameroon', 'China', 'Colombia', 'CostaRica', 'Cuba', 'CaboVerde', 'Curaçao', 'ChristmasIsland', 'Cyprus', 'Czechia', 'Germany', 'Djibouti', 'Denmark', 'Dominica', 'DominicanRepublic', 'Algeria', 'Ecuador', 'Estonia', 'Egypt', 'WesternSahara', 'Eritrea', 'Spain', 'Ethiopia', 'Finland', 'Fiji', 'FalklandIslands(Malvinas)', 'Micronesia,FederatedStatesof', 'FaroeIslands', 'France', 'Gabon', 'UnitedKingdomofGreatBritainandNorthernIreland', 'Grenada', 'Georgia', 'FrenchGuiana', 'Guernsey', 'Ghana', 'Gibraltar', 'Greenland', 'Gambia', 'Guinea', 'Guadeloupe', 'EquatorialGuinea', 'Greece', 'SouthGeorgiaandtheSouthSandwichIslands', 'Guatemala', 'Guam', 'Guinea-Bissau', 'Guyana', 'HongKong', 'HeardIslandandMcDonaldIslands', 'Honduras', 'Croatia', 'Haiti', 'Hungary', 'Indonesia', 'Ireland', 'Israel', 'IsleofMan', 'India', 'BritishIndianOceanTerritory', 'Iraq', 'Iran,IslamicRepublicof', 'Iceland', 'Italy', 'Jersey', 'Jamaica', 'Jordan', 'Japan', 'Kenya', 'Kyrgyzstan', 'Cambodia', 'Kiribati', 'Comoros', 'SaintKittsandNevis', 'Korea,DemocraticPeoplesRepublicof', 'Korea,Republicof', 'Kuwait', 'CaymanIslands', 'Kazakhstan', 'LaoPeoplesDemocraticRepublic', 'Lebanon', 'SaintLucia', 'Liechtenstein', 'SriLanka', 'Liberia', 'Lesotho', 'Lithuania', 'Luxembourg', 'Latvia', 'Libya', 'Morocco', 'Monaco', 'Moldova,Republicof', 'Montenegro', 'SaintMartin(Frenchpart)', 'Madagascar', 'MarshallIslands', 'NorthMacedonia', 'Mali', 'Myanmar', 'Mongolia', 'Macao', 'NorthernMarianaIslands', 'Martinique', 'Mauritania', 'Montserrat', 'Malta', 'Mauritius', 'Maldives', 'Malawi', 'Mexico', 'Malaysia', 'Mozambique', 'Namibia', 'NewCaledonia', 'Niger', 'NorfolkIsland', 'Nigeria', 'Nicaragua', 'Netherlands,Kingdomofthe', 'Norway', 'Nepal', 'Nauru', 'Niue', 'NewZealand', 'Oman', 'Panama', 'Peru', 'FrenchPolynesia', 'PapuaNewGuinea', 'Philippines', 'Pakistan', 'Poland', 'SaintPierreandMiquelon', 'Pitcairn', 'PuertoRico', 'Palestine,Stateof', 'Portugal', 'Palau', 'Paraguay', 'Qatar', 'Réunion', 'Romania', 'Serbia', 'RussianFederation', 'Rwanda', 'SaudiArabia', 'SolomonIslands', 'Seychelles', 'Sudan', 'Sweden', 'Singapore', 'SaintHelena,AscensionandTristandaCunha', 'Slovenia', 'SvalbardandJanMayen', 'Slovakia', 'SierraLeone', 'SanMarino', 'Senegal', 'Somalia', 'Suriname', 'SouthSudan', 'SaoTomeandPrincipe', 'ElSalvador', 'SintMaarten(Dutchpart)', 'SyrianArabRepublic', 'Eswatini', 'TurksandCaicosIslands', 'Chad', 'FrenchSouthernTerritories', 'Togo', 'Thailand', 'Tajikistan', 'Tokelau', 'Timor-Leste', 'Turkmenistan', 'Tunisia', 'Tonga', 'Türkiye', 'TrinidadandTobago', 'Tuvalu', 'Taiwan,ProvinceofChina', 'Tanzania,UnitedRepublicof', 'Ukraine', 'Uganda', 'UnitedStatesMinorOutlyingIslands', 'UnitedStatesofAmerica', 'Uruguay', 'Uzbekistan', 'HolySee', 'SaintVincentandtheGrenadines', 'Venezuela,BolivarianRepublicof', 'VirginIslands(British)', 'VirginIslands(U.S.)', 'VietNam', 'Vanuatu', 'WallisandFutuna', 'Samoa', 'Yemen', 'Mayotte', 'SouthAfrica', 'Zambia', 'Zimbabwe']
19
+ ISO639 = ['Afar' , 'Abkhazian', 'Avestan' , 'Afrikaans' , 'Akan' , 'Amharic' , 'Aragonese','Arabic','Assamese','Avaric','Aymara','Azerbaijani','Bashkir','Belarusian','Bulgarian','Bislama','Bambara','Bengali','Tibetan','Breton','Bosnian','Catalan-Valencian','Chechen','Chamorro','Corsican','Cree','Czech','ChurchSlavonic-OldSlavonic-OldChurchSlavonic','Chuvash','Welsh','Danish','German','Divehi-Dhivehi-Maldivian','Dzongkha','Ewe','GreekModern','English','Esperanto','Spanish-Castilian','Estonian','Basque','Persian','Fulah','Finnish','Fijian','Faroese','French','WesternFrisian','Irish','Gaelic-ScottishGaelic','Galician','Guarani','Gujarati','Manx','Hausa','Hebrew','Hindi','HiriMotu','Croatian','Haitian-HaitianCreole','Hungarian','Armenian','Herero','Interlingua','Indonesian','Interlingue-Occidental','Igbo','SichuanYi-Nuosu','Inupiaq','Ido','Icelandic','Italian','Inuktitut','Japanese','Javanese','Georgian','Kongo','Kikuyu-Gikuyu','Kuanyama-Kwanyama','Kazakh','Kalaallisut-Greenlandic','CentralKhmer','Kannada','Korean','Kanuri','Kashmiri','Kurdish','Komi','Cornish','Kyrgyz-Kirghiz','Latin','Luxembourgish-Letzeburgesch','Ganda','Limburgan-Limburger-Limburgish','Lingala','Lao','Lithuanian','Luba-Katanga','Latvian','Malagasy','Marshallese','Maori','Macedonian','Malayalam','Mongolian','Marathi','Malay','Maltese','Burmese','Nauru','NorwegianBokmål','NorthNdebele','Nepali','Ndonga','Dutch-Flemish','NorwegianNynorsk','Norwegian','SouthNdebele','Navajo-Navaho','Chichewa-Chewa-Nyanja','Occitan','Ojibwa','Oromo','Oriya','Ossetian-Ossetic','Punjabi-Panjabi','Pali','Polish','Pashto-Pushto','Portuguese','Quechua','Romansh','Rundi','Romanian-Moldavian-Moldovan','Russian','Kinyarwanda','Sanskrit','Sardinian','Sindhi','NorthernSami','Sango','Sinhala-Sinhalese','Slovak','Slovenian','Samoan','Shona','Somali','Albanian','Serbian','Swati','SouthernSotho','Sundanese','Swedish','Swahili','Tamil','Telugu','Tajik','Thai','Tigrinya','Turkmen','Tagalog','Tswana','Tonga','Turkish','Tsonga','Tatar','Twi','Tahitian','Uighur-Uyghur','Ukrainian','Urdu','Uzbek','Venda','Vietnamese','Volapük','Walloon','Wolof','Xhosa','Yiddish','Yoruba','Zhuang-Chuang','Chinese','Zulu']
20
+
21
+ # Example of how to filter and serialize session state
22
+ def serialize_session_state():
23
+ # Filter out only serializable items (i.e., strings, numbers, lists, dicts)
24
+ serializable_state = {key: value for key, value in st.session_state["form_data"].items() if isinstance(value, (str, int, float, list, dict))}
25
+
26
+ # Serialize the filtered session state to JSON
27
+ return json.dumps(serializable_state, indent=4)
28
+
29
+
30
+ # Function to load cached data (initializes only once)
31
+ @st.cache_data
32
+ def load_cached_data():
33
+ return {}
34
+
35
+ # Initialize session state with cached data
36
+ if "form_data" not in st.session_state:
37
+ st.session_state.form_data = load_cached_data()
38
+
39
+ # Function to save to cache when any input changes
40
+ def save_to_cache():
41
+ st.cache_data.clear()
42
+ st.cache_data(lambda: st.session_state.form_data) # Save updated form data
43
+
44
+ # Function to save input into cache
45
+ def save_to_cache():
46
+ st.cache_data.clear() # Clear old cache before saving
47
+ st.cache_data(lambda: st.session_state) # Save updated state
48
+
49
+ # Function to create a text area with caching
50
+ def cached_text_area(label, key, placeholder=""):
51
+ if key not in st.session_state.form_data:
52
+ st.session_state.form_data[key] = "" # Initialize dynamically
53
+
54
+ st.text_area(
55
+ label=label,
56
+ placeholder=placeholder,
57
+ key=key,
58
+ value=st.session_state.form_data.get(key, ""), # Load from session state
59
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1],
60
+ )
61
+
62
+ # Function to create a text area with caching
63
+ def cached_text_input(label, key, placeholder=""):
64
+ if key not in st.session_state.form_data:
65
+ st.session_state.form_data[key] = "" # Initialize dynamically
66
+
67
+ st.text_input(
68
+ label=label,
69
+ placeholder=placeholder,
70
+ key=key,
71
+ value=st.session_state.form_data.get(key, ""), # Load from session state
72
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1],
73
+ )
74
+ # Function to create a text area with caching
75
+ def cached_radio_input(label, options, key, help=""):
76
+ if key not in st.session_state.form_data:
77
+ st.session_state.form_data[key] = "" # Initialize dynamically
78
+
79
+ st.radio(
80
+ label=label,
81
+ options=options,
82
+ key=key,
83
+ help=help,
84
+ #value=st.session_state.form_data.get(key, ""), # Load from session state
85
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1],
86
+ horizontal=True
87
+ )
88
+
89
+ def cached_multiple_radio(key,options,label):
90
+
91
+ # Initialize session state for selected countries if needed
92
+ if key not in st.session_state:
93
+ st.session_state[key] = []
94
+ # Display the multiselect widget
95
+ st.multiselect(
96
+ label,
97
+ options=options,
98
+ key=key,
99
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1]
100
+ )
101
+
102
+ # Function to create a text area with caching
103
+ def participant(key):
104
+ colr, coll = st.columns([1, 1])
105
+ with colr:
106
+ cached_text_input("Name", f"{key}_name", "Name or identifier of the participants")
107
+ # Initialize session state for the number input if it doesn't exist
108
+ agekey = f"{key}_age"
109
+ if agekey not in st.session_state:
110
+ st.session_state[agekey] = 0 # default value
111
+ # Display a number input widget
112
+ st.number_input(
113
+ label="The age of the participant:",
114
+ key=agekey,
115
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1]
116
+ )
117
+ cached_text_input("Location", f"{key}_location", "The title of the card")
118
+ cached_radio_input("WorkplaceType", ["Presential", "Hybrid", "Remote"], f"{key}_workdplace", "The title of the card")
119
+ cached_text_input("Ethnicity", f"{key}_ethincity", "The title of the card")
120
+ cached_text_input("Gender", f"{key}_gender", "The title of the card")
121
+ cached_text_input("Disabilities", f"{key}_disabilities", "The title of the card")
122
+ cached_text_input("Sexual Orientation", f"{key}_sexualOrientation", "The title of the card")
123
+ cached_text_input("Religion", f"{key}_religion", "The title of the card")
124
+ with coll:
125
+
126
+ cached_multiple_radio(f"{key}_countries",ISO3166,"Select one or several countries:")
127
+ cached_multiple_radio(f"{key}_edlevel",EducationalLevelType,"Educational Level")
128
+ cached_multiple_radio( f"{key}_sociostati", SESType,"Socioeconomic Status")
129
+ cached_multiple_radio( f"{key}_skills", SkillLevelType,"Skill Level")
130
+ cached_multiple_radio( f"{key}_languages", ISO3166, "Select one or several langauges spoken by the participant:")
131
+
132
+ # Initialize session state for the number input if it doesn't exist
133
+ tenkey = f"{key}_tenure"
134
+ if tenkey not in st.session_state:
135
+ st.session_state[tenkey] = 0 # default value
136
+
137
+ # Display a number input widget
138
+ st.number_input(
139
+ label="The professioanl tenure of the participant in years",
140
+ key=tenkey,
141
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[tenkey]}), save_to_cache())[1]
142
+ )
143
+
144
+ def organization(key):
145
+ cached_text_input("Organization name", f"{key}_name", "Name or identifier of the organization")
146
+ group(key)
147
+
148
+ def group(key):
149
+ colr, coll = st.columns([1, 1])
150
+ with colr:
151
+ agekey = f"{key}_age"
152
+ if agekey not in st.session_state:
153
+ st.session_state[agekey] = 0 # default value
154
+ # Display a number input widget
155
+ st.slider(
156
+ label="The age of the participant:",
157
+ value=60,
158
+ min_value=0,
159
+ max_value=120,
160
+ key=agekey,
161
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[agekey]}), save_to_cache())[1]
162
+ )
163
+ cached_text_input("Location", f"{key}_location", "Location of the organization")
164
+ cached_radio_input("WorkplaceType", ["Presential", "Hybrid", "Remote"], f"{key}_workplace", "The kind of organization")
165
+ cached_text_input("Ethnicities", f"{key}_ethnicities", "Ethinicities present in the organization, comma sepparated ")
166
+ cached_text_input("Genders", f"{key}_genders", "Distribution and presence of gender presence, domma sepparated ")
167
+ cached_text_input("Disabilities", f"{key}_disabilities", "Disabilities present in the organization, comma sepparated ")
168
+ cached_text_input("Religious Beliefs", f"{key}_religious", "Disabilities present in the organization, comma sepparated ")
169
+ with coll:
170
+ cached_multiple_radio(f"{key}_countries",ISO3166,"Select one or several countries:")
171
+ cached_multiple_radio(f"{key}_edlevel",EducationalLevelType,"Educational Level")
172
+ cached_multiple_radio( f"{key}_sociostati", SESType,"Socioeconomic Status")
173
+ cached_multiple_radio( f"{key}_skills", SkillLevelType,"Skill Level")
174
+ cached_multiple_radio( f"{key}_languages", ISO3166, "Select one or several langauges spoken by the participant:")
175
+ # Initialize session state for the number input if it doesn't exist
176
+ agekey = f"{key}_tenure"
177
+ if agekey not in st.session_state:
178
+ st.session_state[agekey] = 0 # default value
179
+
180
+ # Display a number input widget
181
+ st.number_input(
182
+ label="The professioanl tenure of the participant in years",
183
+ key=agekey,
184
+ on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1]
185
+ )
186
+
187
+ def init_state(key):
188
+ if key not in st.session_state:
189
+ st.session_state[key] = []
190
+
191
+ def add_text_area(key):
192
+ init_state(key)
193
+ st.session_state[key].append("")
194
+
195
+ def remove_text_area(index,key):
196
+ if key in st.session_state and 0 <= index < len(st.session_state[key]):
197
+ st.session_state[key].pop(index)
198
+ st.rerun() # Rerun to update the interface
199
+ ##
200
+ ## Title
201
+ ##
202
+ st.title("The Software Diversity Card :woman_and_man_holding_hands: :memo:")
203
+
204
+ st.markdown("""\
205
+ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
206
+ """)
207
+
208
+ ##
209
+ ## Master info
210
+ ##
211
+ cached_text_input("The name of the software project", "master_title", "The title of the card")
212
+ cached_text_area("A description of the software project", "master_desc", "The title of the card")
213
+
214
+
215
+ with st.expander("**Document the teams and crowds in your software**", expanded=True):
216
+ governance, usageContext, participants = st.tabs([
217
+ "Governance",
218
+ "Usage context",
219
+ "Participants"
220
+ ])
221
+
222
+ with governance:
223
+ col1, col2 = st.columns([1, 2])
224
+ with col1:
225
+ cached_text_input("Project Type", "governance_projectType", "Specify the type of software project (private, public funded, non-profit, driven by an open-source community, etc.)")
226
+
227
+ with col2:
228
+ # Multiple value
229
+ key = "governance_govProcesses"
230
+ init_state(key)
231
+ if st.button("Add governament processes"):
232
+ add_text_area(key)
233
+ # Loop over the array and create a text area with a remove button for each element
234
+ for idx, text in enumerate(st.session_state[key]):
235
+ # Create two columns: one for the text area, one for the remove button
236
+ col1, col2 = st.columns([6, 1])
237
+ with col1:
238
+ cached_text_area(f"Governament process {idx + 1}", f"governance_govProcesses{idx}", "Specific the governance rules of the software project. For instance, the funders, or the role and the relation between the different bodies that governs the software.")
239
+ with col2:
240
+ if st.button("Remove", key=f"{key}_remove_{idx}"):
241
+ remove_text_area(idx,key)
242
+
243
+ # BODIES
244
+ key = "governance_bodies"
245
+ init_state(key)
246
+ if st.button("Add governament bodies"):
247
+ add_text_area(key)
248
+ # Loop over the array and create a text area with a remove button for each element
249
+
250
+ for idx, text in enumerate(st.session_state[key]):
251
+ # Create two columns: one for the text area, one for the remove button
252
+ with st.container(border=True):
253
+ col1, col2 = st.columns([2, 2])
254
+ with col1:
255
+ cached_text_input("Body name", f"{key}_{idx}_name", "The name of id of the body")
256
+ cached_text_area("Body description", f"{key}_{idx}_description", "A description of the body")
257
+
258
+
259
+ with col2:
260
+ if st.button("Remove", key=f"{key}_remove_{idx}"):
261
+ remove_text_area(idx,key)
262
+ cached_radio_input(f"Body type", ['funders', 'directors', 'administrators', 'other'], f"{key}_{idx}_type")
263
+
264
+ st.text("If participants in the body are individuals please use the individuals tab. If not, leave it blank.")
265
+ # Button to add a new text area
266
+ org, individual = st.tabs([
267
+ "Organization",
268
+ "Individual",
269
+ ])
270
+ with individual:
271
+ participant(f"{key}_{idx}_participant")
272
+ with org:
273
+ organization(f"{key}_{idx}_organization")
274
+
275
+
276
+ with usageContext:
277
+ ##
278
+ ## Age
279
+ ##
280
+ age_checkbox = st.radio("Do you want to specifiy the age of your students?", ["No", "Yes"])
281
+ if age_checkbox == "Yes":
282
+ age_input = st.slider("Age: (**required**)", min_value=0, max_value=100, step=1)
283
+
284
+
285
+
286
+ with participants:
287
+ st.write("the participants")
288
+
289
+
290
+
291
+ ## Showing the generated card and the generated JSON
292
+ st.divider()
293
+ promptTab, impTab = st.tabs(["**Compiled card in markdown**", "**Generated JSON**" ])
294
+ with promptTab:
295
+ html_str= f"""
296
+ # The Software diversity card of {st.session_state["master_title"]}
297
+ {st.session_state["master_desc"]}
298
+ ## 🏢 Teams Summary
299
+
300
+ <table>
301
+ <tr>
302
+ <th>Name</th>
303
+ <th>Type</th>
304
+ <th>Age Range</th>
305
+ <th>Ethnicities</th>
306
+ <th>Genders</th>
307
+ <th>Team Size</th>
308
+ <th>Average Tenure</th>
309
+ <th>Start Date</th>
310
+ <th>Location</th>
311
+ </tr>
312
+ <tr>
313
+ <td><strong>DevelopmentTeam</strong></td>
314
+ <td>DevelopmentTeam</td>
315
+ <td>25-30</td>
316
+ <td>Colombian, Brazilian, Argentinian, French, Spanish, Pakistani, Serbian, Iranian, Moroccan, Italian</td>
317
+ <td>Male 80%, Female 20%</td>
318
+ <td>15</td>
319
+ <td>4.3</td>
320
+ <td>11-08-2022</td>
321
+ <td>Luxembourg</td>
322
+ </tr>
323
+ <tr>
324
+ <td><strong>Usability Testers</strong></td>
325
+ <td>Tester Team</td>
326
+ <td>22-24</td>
327
+ <td>French</td>
328
+ <td>Non-disclosed</td>
329
+ <td>18</td>
330
+ <td>0.5</td>
331
+ <td>17-10-2023</td>
332
+ <td>University of Luxembourg</td>
333
+ </tr>
334
+ <tr>
335
+ <td><strong>Computer Science Students</strong></td>
336
+ <td>Target Community</td>
337
+ <td>18-100</td>
338
+ <td>Non-disclosed</td>
339
+ <td>Non-disclosed</td>
340
+ <td>-</td>
341
+ <td>0</td>
342
+ <td>-</td>
343
+ <td>France & Luxembourg</td>
344
+ </tr>
345
+ <tr>
346
+ <td><strong>Climate Public Servants</strong></td>
347
+ <td>Target Community</td>
348
+ <td>20-100</td>
349
+ <td>Non-disclosed</td>
350
+ <td>Non-disclosed</td>
351
+ <td>-</td>
352
+ <td>3-5</td>
353
+ <td>-</td>
354
+ <td>Luxembourg</td>
355
+ </tr>
356
+ </table>
357
+
358
+ ---
359
+ """
360
+ # Provide a download button
361
+ st.download_button(
362
+ label="Download Markdown",
363
+ data=html_str,
364
+ file_name="SoftareDiveristyCard.md",
365
+ mime="text/markdown"
366
+ )
367
+ st.markdown(html_str, unsafe_allow_html=True)
368
+ with impTab:
369
+
370
+ # Convert the session state to a JSON string
371
+ session_state_json = json.dumps(serialize_session_state(), indent=4)
372
+ st.download_button(
373
+ label="Download JSON",
374
+ data=session_state_json,
375
+ file_name="SoftareDiveristyCard.json",
376
+ mime="application/json"
377
+ )
378
+ # Display the session state as pretty JSON
379
+ st.json(serialize_session_state())
380
+