JoanGiner's picture
bugfixes to the tool
a8b72a9
import streamlit as st
import json
import datetime
import urllib.parse
import os
from markdownGenerator import *
from jsonGenerator import *
def render_sdc():
## Constant of the Software diversity card
EducationalLevelType = ['earlyChildhood','primary','lowerSecondary','upperSecondary','postSecondaryNonTertiary','shortCycleTertiary','bachelorEquivalent','masterEquivalent','doctorateEquivalent']
SESType = ['upperClass' ,'upperMiddleClass' ,'middleClass' , 'lowerMiddleClass' , 'lowerClass']
SkillLevelType = ['expert' , 'proficient' , 'advanced' , 'competent' , 'beginner']
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']
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']
## The file where the state is
STATE_FILE = "besser_example.json"
SAVE_FILE = "session_state.json"
def load_state():
"""Load state from file and update session_state."""
if os.path.exists(STATE_FILE):
try:
with open(STATE_FILE, "r") as f:
data = json.load(f)
st.session_state.update(data)
st.session_state['form_data'] = data
return unflatten(st.session_state["form_data"])
except Exception as e:
st.error(f"Error loading state: {e}")
def save_state():
"""Save the current session_state to file."""
try:
# Convert session_state to a regular dict before dumping
with open(SAVE_FILE, "w") as f:
json.dump(dict(st.session_state['form_data']), f)
except Exception as e:
st.error(f"Error saving state: {e}")
# Run this only once on first load.
#if "loaded" not in st.session_state:
# load_state()
# st.session_state["loaded"] = True
# Example of how to filter and serialize session state
def serialize_session_state():
# Filter out only serializable items (i.e., strings, numbers, lists, dicts)
serializable_state = {key: value for key, value in st.session_state["form_data"].items() if isinstance(value, (str, int, float, list, dict))}
# Serialize the filtered session state to JSON
return json.dumps(serializable_state, indent=4)
# Function to load cached data (initializes only once)
@st.cache_data
def load_cached_data():
return {}
# Initialize session state with cached data
if "form_data" not in st.session_state:
st.session_state.form_data = load_cached_data()
# Function to save to cache when any input changes
def save_to_cache():
st.cache_data.clear()
st.cache_data(lambda: st.session_state.form_data) # Save updated form data
# Function to create a text area with caching
def cached_text_area(label, key, placeholder=""):
if key not in st.session_state.form_data:
st.session_state.form_data[key] = "" # Initialize dynamically
st.text_area(
label=label,
placeholder=placeholder,
key=key,
value=st.session_state.form_data.get(key, ""), # Load from session state
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1],
)
save_state()
# Function to create a text area with caching
def cached_text_input(label, key, placeholder=""):
if key not in st.session_state.form_data:
st.session_state.form_data[key] = "" # Initialize dynamically
st.text_input(
label=label,
placeholder=placeholder,
key=key,
value=st.session_state.form_data.get(key, ""), # Load from session state
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1],
)
save_state()
# Function to create a text area with caching
def cached_radio_input(label, options, key, help=""):
if key not in st.session_state.form_data or st.session_state.form_data[key] not in options:
st.session_state.form_data[key] = options[0] # Initialize dynamically
st.radio(
label=label,
options=options,
key=key,
help=help,
#value=st.session_state.form_data.get(key, ""), # Load from session state
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1],
horizontal=True
)
save_state()
def cached_multiple_radio(key,options,label):
# Initialize session state for selected countries if needed
if key not in st.session_state:
st.session_state[key] = []
default = []
else:
default = st.session_state[key]
# Display the multiselect widget
st.multiselect(
label,
options=options,
default=default,
key=key,
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1]
)
def cached_range_input(key, value, label ):
if key not in st.session_state.form_data:
st.session_state.form_data[key] = value # Initialize dynamically
else:
st.session_state[key] = st.session_state.form_data[key]
# Display a number input widget
st.slider(
label=label,
min_value=0,
max_value=120,
value=value,
key=key,
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[key]}), save_to_cache())[1]
)
save_state()
def cached_date_input(label, key):
if key not in st.session_state:
st.session_state[key] = []
st.date_input(
label=label,
value=datetime.date(2019, 7, 6),
key=key,
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[f"{key}_startdate"]}), save_to_cache())[1]
)
def participant(key):
colr, coll = st.columns([1, 1])
with colr:
cached_text_input("Name", f"{key}_name", "Name or identifier of the participants")
# Initialize session state for the number input if it doesn't exist
agekey = f"{key}_age"
if agekey not in st.session_state:
st.session_state.form_data[agekey] = 0 # default value
# Display a number input widget
st.number_input(
label="The age of the participant:",
key=agekey,
on_change=lambda: (st.session_state.form_data.update({agekey: st.session_state[agekey]}), save_to_cache())[1]
)
cached_text_input("Location", f"{key}_location", "The title of the card")
cached_radio_input("WorkplaceType", ["Presential", "Hybrid", "Remote"], f"{key}_workdplace", "The title of the card")
cached_text_input("Ethnicity", f"{key}_ethincity", "The title of the card")
cached_text_input("Gender", f"{key}_gender", "The title of the card")
cached_text_input("Disabilities", f"{key}_disabilities", "The title of the card")
cached_text_input("Sexual Orientation", f"{key}_sexualOrientation", "The title of the card")
cached_text_input("Religion", f"{key}_religion", "The title of the card")
with coll:
cached_multiple_radio(f"{key}_countries",ISO3166,"Select one or several countries:")
cached_multiple_radio(f"{key}_edlevel",EducationalLevelType,"Educational Level")
cached_multiple_radio( f"{key}_sociostati", SESType,"Socioeconomic Status")
cached_multiple_radio( f"{key}_skills", SkillLevelType,"Skill Level")
cached_multiple_radio( f"{key}_languages", ISO3166, "Select one or several langauges spoken by the participant:")
# Initialize session state for the number input if it doesn't exist
tenkey = f"{key}_tenure"
if tenkey not in st.session_state:
st.session_state[tenkey] = 0 # default value
# Display a number input widget
st.number_input(
label="The professioanl tenure of the participant in years",
key=tenkey,
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[tenkey]}), save_to_cache())[1]
)
def organization(key):
cached_text_input("Organization name", f"{key}_name", "Name or identifier of the organization")
group(key)
def team(key):
cached_range_input(f"{key}_size", 0, "The size of the group")
group(key)
def group(key):
colr, coll = st.columns([1, 1])
with colr:
cached_range_input(f"{key}_age",(10,20), "The age range of the participants")
cached_text_input("Location", f"{key}_location", "Location of the organization")
cached_radio_input("WorkplaceType", ["Presential", "Hybrid", "Remote"], f"{key}_workplace", "The kind of organization")
cached_text_input("Ethnicities", f"{key}_ethnicities", "Ethinicities present in the organization, comma sepparated ")
cached_text_input("Genders", f"{key}_genders", "Distribution and presence of gender presence, comma sepparated ")
cached_text_input("Disabilities", f"{key}_disabilities", "Disabilities present in the organization, comma sepparated ")
cached_text_input("Religious Beliefs", f"{key}_religious", "Disabilities present in the organization, comma sepparated ")
with coll:
cached_multiple_radio(f"{key}_countries",ISO3166,"Select one or several countries:")
cached_multiple_radio(f"{key}_edlevel",EducationalLevelType,"Educational Level")
cached_multiple_radio( f"{key}_sociostati", SESType,"Socioeconomic Status")
cached_multiple_radio( f"{key}_skills", SkillLevelType,"Skill Level")
cached_multiple_radio( f"{key}_languages", ISO639, "Select one or several langauges spoken by the participant:")
# Initialize session state for the number input if it doesn't exist
agekey = f"{key}_tenure"
if agekey not in st.session_state:
st.session_state[agekey] = 0 # default value
# Display a number input widget
st.number_input(
label="The professioanl tenure of the participant in years",
key=agekey,
on_change=lambda: (st.session_state.form_data.update({key: st.session_state[agekey]}), save_to_cache())[1]
)
def init_state(key):
if key not in st.session_state.form_data:
st.session_state.form_data[key] = []
def add_text_area(key):
init_state(key)
st.session_state.form_data[key].append("")
def remove_text_area(index,key):
if key in st.session_state.form_data and 0 <= index < len(st.session_state.form_data[key]):
st.session_state.form_data[key].pop(index)
st.rerun() # Rerun to update the interface
##
## Title
##
col1, col2 = st.columns([8, 2])
with col1:
st.title("The Software Diversity Card Generator :busts_in_silhouette: ")
with col2:
# Theme options
themes = {
"Light": {
"primaryColor": "#4CAF50",
"backgroundColor": "#FFFFFF",
"secondaryBackgroundColor": "#F0F2F6",
"textColor": "#262730",
},
"Cool Blue": {
"primaryColor" : "#007ACC", # A vibrant, clear blue
"backgroundColor" : "#E6F7FF" , # A light, airy blue for a fresh feel
"secondaryBackgroundColor" : "#B3E0FF", # A gentle pastel blue
"textColor" : "#003366" , # Deep navy for contrast
"font" : "sans serif",
},
"Dark": {
"primaryColor": "#BB86FC",
"backgroundColor": "#121212",
"secondaryBackgroundColor": "#1E1E1E",
"textColor": "#E0E0E0",
},
"Solarized": {
"primaryColor": "#268BD2",
"backgroundColor": "#FDF6E3",
"secondaryBackgroundColor": "#EEE8D5",
"textColor": "#657B83",
}
}
# UI to select a theme
theme_choice = st.selectbox("Choose a theme:", list(themes.keys()))
# Apply theme
selected_theme = themes[theme_choice]
st.markdown(
f"""
<style>
.stApp {{
background-color: {selected_theme["backgroundColor"]};
color: {selected_theme["textColor"]};
}}
.stButton > button {{
background-color: {selected_theme["primaryColor"]};
color: white;
}}
.stSidebar {{
background-color: {selected_theme["secondaryBackgroundColor"]};
}}
</style>
""",
unsafe_allow_html=True
)
st.markdown("""\
Welcome to the Software Diversity Card Generator—a form-based application designed to empower you to highlight and promote diversity in software projects. Our innovative tool helps you generate comprehensive diversity cards in both JSON and Markdown formats, offering a transparent overview of the varied teams involved in development and governance, the user groups engaged in testing, and the tailored software adaptations for different social groups. By providing a structured model, an extended JSON syntax, and a toolkit backed by real-world examples, our platform aims to foster inclusive practices that can be embraced by open-source communities, academic journals, and forward-thinking businesses alike.
""")
colp, colt, = st.columns([3,7])
with colp:
st.markdown("""\
Want to see **what it is possible? See an example!**
""")
with colt:
if st.button("Load Besser's diversity card", type="secondary"):
unflattenedJson = load_state()
##
## Master info
##
cached_text_input("The name of the software project", "master_title", "The title of the card")
cached_text_area("A description of the software project", "master_desc", "The title of the card")
st.markdown(
"""
<style>
div[data-testid=stVerticalBlockBorderWrapper] div[data-baseweb="tab-list"] button p {
font-size: x-large;
}
.st-emotion-cache-0 esjhkag0 div[data-baseweb="tab-list"] {
padding-left: 22%;
}
</style>
""",
unsafe_allow_html=True
)
with st.container( border=True):
##st.subheader("Describe the different teams in the software project")
governance, usageContext, participants = st.tabs([
"🏢 **Governance**",
":twisted_rightwards_arrows: **Usage Context**",
":hammer_and_wrench: **Participants**"
])
with governance:
col1, col2 = st.columns([3, 2])
with col2:
#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.)")
cached_multiple_radio("governance_projectType",["public funded", "research", "private", "private non-profit", "driven by open-source community", "citizen science"],"Specify the type of software project")
with col1:
# Multiple value
key = "governance_govProcesses"
init_state(key)
st.write("Define the set of government process of your software project")
if st.button("Add government processes"):
add_text_area(key)
# Loop over the array and create a text area with a remove button for each element
for idx, processes in enumerate(st.session_state.form_data[key]):
# Create two columns: one for the text area, one for the remove button
col1, col2 = st.columns([6, 1])
with col1:
cached_text_area(f"Government 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.")
with col2:
if st.button("Remove", key=f"remove_{key}_{idx}"):
remove_text_area(idx,key)
# BODIES
st.write("Add the different types of government bodies of your software project (boards and funders)")
key = "governance_bodies"
init_state(key)
if st.button("Add government bodies"):
add_text_area(key)
# Loop over the array and create a text area with a remove button for each element
for idx, text in enumerate(st.session_state.form_data[key]):
# Create two columns: one for the text area, one for the remove button
with st.container(border=True):
st.subheader(f"Governance body:", divider="gray")
col1, col2 = st.columns([3, 2])
with col1:
cached_text_input("Body name", f"{key}_{idx}_name", "The name of id of the body")
cached_text_area("Body description", f"{key}_{idx}_description", "A description of the body")
with col2:
cached_multiple_radio(f"{key}_{idx}_type", ['funders', 'directors', 'administrators', 'other'], f"Body role type" )
if st.button("Remove", key=f"{key}_remove_{idx}"):
remove_text_area(idx,f"{key}")
with st.expander("If needed provide detailed information about the organizations or individuals involved in the governance", expanded=False):
# Button to add a new text area
org, individual = st.tabs([
"Organization",
"Individual",
])
with individual:
participant(f"{key}_{idx}_participant")
with org:
organization(f"{key}_{idx}_organization")
with usageContext:
colr, coll = st.columns([1, 1])
with colr:
key = "usageContext"
cached_text_area("Social context",f"{key}_description", "Description of the usage and social context of the app")
with coll:
cached_multiple_radio(f"{key}_countries",ISO3166,"The countries where the app is intended to be deployed and used")
cached_multiple_radio( f"{key}_languages", ISO639, "The relevant languages for the app usage's context")
targetCommunities, adaptations = st.tabs([
"Targeted Communities",
"Adpatations",
])
with targetCommunities:
keyTarget = key+"_targetCommunity"
init_state(keyTarget)
if st.button("Add target communities"):
add_text_area(keyTarget)
# Loop over the array and create a text area with a remove button for each element
for idx, text in enumerate(st.session_state.form_data[keyTarget]):
st.subheader(f"Target community:", divider="gray")
cached_text_input("Name",f"{keyTarget}_{idx}_name", "Name or ID of the target community")
cached_text_area("Description",f"{keyTarget}_{idx}_description", "Description of the target community")
group(f"{keyTarget}_{idx}")
if st.button("Remove", key=f"{keyTarget}_remove_{idx}"):
remove_text_area(idx,keyTarget)
# Adaptations
with adaptations:
keyAdapt = key+"_adaptation"
init_state(keyAdapt)
if st.button("Add adaptations"):
add_text_area(keyAdapt)
for idx, text in enumerate(st.session_state.form_data[keyAdapt]):
st.subheader(f"Adaptation:", divider="gray")
cached_text_input("Name",f"{keyAdapt}_{idx}_name", "Name or ID of the adaptation")
cached_text_area("Description",f"{keyAdapt}_{idx}_description", "Description of the adaptation")
if st.button("Remove", key=f"{keyAdapt}_remove_{idx}"):
remove_text_area(idx,keyAdapt)
with participants:
# Participants
st.write("Add the different teams participating the software project")
key = "participants"
init_state(key)
if st.button("Add a team of participants"):
add_text_area(key)
# Loop over the array and create a text area with a remove button for each element
for idx, text in enumerate(st.session_state.form_data[key]):
# Create two columns: one for the text area, one for the remove button
with st.container(border=True):
st.subheader(f"Participant team:", divider="gray")
col1, col2 = st.columns([2, 2])
with col1:
cached_text_input("Team name", f"{key}_{idx}_name", "The name of id of the team")
cached_text_area("Team description", f"{key}_{idx}_description", "A description of the team")
with col2:
if st.button("Remove", key=f"{key}_remove_{idx}"):
remove_text_area(idx,f"{key}_remove_{idx}")
cached_multiple_radio(f"{key}_{idx}_type", ['Development Team', 'NonCoding Contributor', 'Tester Team', 'Public Reporter TEam'], f"Team role type" )
team(f"{key}_{idx}")
## Showing the generated card and the generated JSON
st.divider()
st.subheader("The generated card")
markDownTab, jsonTab = st.tabs(["**Compiled card in markdown**", "**Generated JSON**" ])
unflattenedJson = unflatten(st.session_state["form_data"])
with markDownTab:
# Provide a download button
st.download_button(
label="Download Markdown",
data=generate_markdown(unflattenedJson),
file_name="SoftareDiveristyCard.md",
mime="text/markdown"
)
st.text("Preview:")
st.markdown(generate_markdown(unflattenedJson), unsafe_allow_html=True)
with jsonTab:
# Convert the session state to a JSON string
if 'master_title' in st.session_state:
filename = f"{st.session_state['master_title']}_diveristy_card.json"
else:
filename = f"diveristy_card.json"
session_state_json = json.dumps(serialize_session_state(), indent=4)
st.download_button(
label="Download JSON",
data=session_state_json,
file_name=filename,
mime="application/json"
)
# Display the session state as pretty JSON
st.text("Preview:")
st.json(unflattenedJson)