зеркало из https://github.com/mozilla/shinysurvey.git
initial commit
This commit is contained in:
Родитель
9d122f8082
Коммит
169a0ce91d
|
@ -0,0 +1,91 @@
|
|||
getSurvey <- function() {
|
||||
library(tidyverse)
|
||||
library(lubridate)
|
||||
library(stringr)
|
||||
raw <- read_csv("survey.csv")
|
||||
|
||||
# sample size to work with the data
|
||||
#raw <- raw[1:1000,]
|
||||
|
||||
# handle NAs
|
||||
raw[is.na(raw)] <- "Unknown"
|
||||
|
||||
# format data
|
||||
data <- raw %>%
|
||||
mutate(`Date Submitted`=mdy_hms(`Date Submitted`),
|
||||
`Time Started`=mdy_hms(`Time Started`),
|
||||
Age=as.factor(`Age (optional)`),
|
||||
`Frequency of Use`=case_when(
|
||||
str_detect(`How often do you use Facebook?`,"I’m not on Facebook") ~ "Not on Facebook",
|
||||
str_detect(`How often do you use Facebook?`,"constantly") ~ "Constant User",
|
||||
str_detect(`How often do you use Facebook?`,"day") ~ "Daily User",
|
||||
TRUE ~ "Occasional User"),
|
||||
`Tech Knowledge` = as.factor(`I consider myself:`),
|
||||
`Facebook Users and Non-users` = case_when(
|
||||
`Frequency of Use` == "Not on Facebook" ~ "Non-user",
|
||||
TRUE ~ "User"),
|
||||
`I know how to: Change Facebook privacy settings` = case_when(
|
||||
str_detect(`Change your Facebook privacy settings:Check all the items you currently know how to do:`,"Unknown") ~ "No",
|
||||
TRUE ~ "Yes"),
|
||||
`I know how to: Opt out of allowing third-party apps to track me and my friends` = case_when(
|
||||
str_detect(`Opt out of allowing third-party apps to track you and your friends:Check all the items you currently know how to do:`,"Unknown") ~ "No",
|
||||
TRUE ~ "Yes"),
|
||||
`I know how to: Publish something so only a few of my friends can see it` = case_when(
|
||||
str_detect(`Publish something so only a few of your friends can see it:Check all the items you currently know how to do:`,"Unknown") ~ "No",
|
||||
TRUE ~ "Yes"),
|
||||
`I know how to: Browse Facebook while limiting its ability to track me` = case_when(
|
||||
str_detect(`Browse Facebook while limiting its ability to track you:Check all the items you currently know how to do:`,"Unknown") ~ "No",
|
||||
TRUE ~ "Yes"),
|
||||
`I know how to: Delete my Facebook page` = case_when(
|
||||
str_detect(`Delete your Facebook page:Check all the items you currently know how to do:`,"Unknown") ~ "No",
|
||||
TRUE ~ "Yes"),
|
||||
`I know how to: Create a targeted Facebook ad` = case_when(
|
||||
str_detect(`Create a targeted Facebook ad:Check all the items you currently know how to do:`, "Unknown") ~ "No",
|
||||
TRUE ~ "Yes"),
|
||||
`I know how to: Find out all the data Facebook has collected on me` = case_when(
|
||||
str_detect(`Find out all the data Facebook has collected on me already:Check all the items you currently know how to do:`,"Unknown") ~ "No",
|
||||
TRUE ~ "Yes"),
|
||||
`I know how to: Make a backup of all of my content on Facebook (photos, videos, etc.)` = case_when(
|
||||
str_detect(`Make a backup of all my content on Facebook (photos, videos, etc):Check all the items you currently know how to do:`, "Unknown") ~ "No",
|
||||
TRUE ~ "Yes")
|
||||
) %>%
|
||||
select(c(`Response ID`:Country),
|
||||
`Link Name`,
|
||||
c(Age:`Facebook Users and Non-users`),
|
||||
c(`I consider myself:`:`Do you know what types of personal information Facebook collects about you?`),
|
||||
`Would you consider paying for a version of Facebook that doesn’t make money off you by collecting and selling your data?`,
|
||||
`Have you made any changes on Facebook as a result of the recent Cambridge Analytica and Facebook revelations?`,
|
||||
c(`I know how to: Change Facebook privacy settings`:`I know how to: Make a backup of all of my content on Facebook (photos, videos, etc.)`)
|
||||
) %>%
|
||||
gather(`I consider myself:`:`I know how to: Make a backup of all of my content on Facebook (photos, videos, etc.)`,key="Question",value="Answer") %>%
|
||||
mutate(Chart = case_when(
|
||||
str_detect(Question,"How concerned are you") ~ "Histogram",
|
||||
str_detect(Question,"what types of personal information") ~ "Stacked",
|
||||
str_detect(Question,"Have you made any changes") ~ "Stacked",
|
||||
TRUE ~ "Stacked"
|
||||
))
|
||||
|
||||
|
||||
return(data)
|
||||
}
|
||||
|
||||
getDownloadableSurvey <- function() {
|
||||
library(tidyverse)
|
||||
library(lubridate)
|
||||
library(stringr)
|
||||
raw <- read_csv("survey.csv")
|
||||
|
||||
# sample size to work with the data
|
||||
#raw <- raw[1:1000,]
|
||||
|
||||
# handle NAs
|
||||
raw[is.na(raw)] <- "Unknown"
|
||||
data <- raw %>%
|
||||
select(c(`Response ID`),
|
||||
Country,
|
||||
c(`I consider myself:`:`Would you consider paying for a version of Facebook that doesn’t make money off you by collecting and selling your data?`),
|
||||
`Age (optional)`
|
||||
)
|
||||
|
||||
return(data)
|
||||
}
|
|
@ -0,0 +1,274 @@
|
|||
library(shiny)
|
||||
library(tidyverse)
|
||||
library(lubridate)
|
||||
library(stringr)
|
||||
library(ggthemes)
|
||||
library(scales)
|
||||
|
||||
source("functions.R")
|
||||
survey <- getSurvey()
|
||||
|
||||
|
||||
# Define server logic required to draw a histogram
|
||||
server <- function(input, output) {
|
||||
|
||||
|
||||
questions <- unique(survey$Question)
|
||||
countries <- survey %>%
|
||||
count(Country) %>%
|
||||
filter(n>1000) %>%
|
||||
select(Country)
|
||||
|
||||
# populate dropdown of questions
|
||||
output$questionDropdown <- renderUI({
|
||||
selectInput("question",label=NULL,questions,width="100%")
|
||||
})
|
||||
|
||||
# populate filter dropdown
|
||||
output$selectorDropdown <- renderUI({
|
||||
options <- c("None","Age","Tech Knowledge","Facebook Users and Non-users","Country")
|
||||
selectInput("filterSelector", label=NULL,
|
||||
options)
|
||||
})
|
||||
|
||||
# populate individual filter dropdown
|
||||
output$inSelectorDropdown <- renderUI({
|
||||
if (is.null(input$filterSelector)) {
|
||||
return()
|
||||
} else if (input$filterSelector == "None") {
|
||||
return()
|
||||
} else {
|
||||
options <- survey %>%
|
||||
mutate(Vars=get(input$filterSelector)) %>%
|
||||
count(Vars) %>%
|
||||
filter(n>10000)
|
||||
options_list <- unique(options$Vars)
|
||||
selectInput("inFilterSelector", label="Select a filter:",
|
||||
sort(options_list))
|
||||
}
|
||||
})
|
||||
|
||||
output$message <- renderUI({
|
||||
if (is.null(input$question)) {
|
||||
return(NULL)
|
||||
} else if (input$filterSelector != "None" & is.null(input$inFilterSelector)) {
|
||||
return(NULL)
|
||||
} else {
|
||||
if(checkValidity()) {
|
||||
return(NULL)
|
||||
} else {
|
||||
div(class="box box-solid box-warning",style="padding:20px;",
|
||||
p("There isn't enough data for the filters you selected. Try changing the filtering criteria.")
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# populate compare dropdown
|
||||
output$compareDropdown <- renderUI({
|
||||
selectInput("compareSelector",label=NULL,c("None","Age","Tech Knowledge","Facebook Users and Non-users","Frequency of Use"),selected="None")
|
||||
})
|
||||
|
||||
valid <- reactive(
|
||||
checkValidity()
|
||||
)
|
||||
|
||||
# find what kind of chart we need
|
||||
chartType <- reactive(
|
||||
survey %>%
|
||||
filter(Question==input$question) %>%
|
||||
select(Chart) %>%
|
||||
head(1)
|
||||
)
|
||||
|
||||
# check if enough responses are gathered
|
||||
checkValidity <- function() {
|
||||
data <- raw()
|
||||
if (input$compareSelector != "None") {
|
||||
totals <- data %>%
|
||||
group_by(Answer,Vars) %>%
|
||||
summarize(count=sum(n)) %>%
|
||||
mutate(valid=ifelse(count>10,TRUE,FALSE))
|
||||
} else {
|
||||
totals <- data %>%
|
||||
group_by(Answer) %>%
|
||||
summarize(count=sum(n)) %>%
|
||||
mutate(valid=ifelse(count>10,TRUE,FALSE))
|
||||
}
|
||||
valid <<- all(totals$valid)
|
||||
return(all(totals$valid))
|
||||
}
|
||||
|
||||
# return only if enough responses exist
|
||||
data <- reactive(
|
||||
if (is.null(input$question)) {
|
||||
return(NULL)
|
||||
} else if (input$filterSelector != "None" & is.null(input$inFilterSelector)) {
|
||||
return(NULL)
|
||||
} else if (checkValidity()) {
|
||||
raw()
|
||||
} else {
|
||||
return(NULL)
|
||||
}
|
||||
)
|
||||
|
||||
# applyg filtering logic, if needed
|
||||
raw <- reactive(
|
||||
if (is.null(input$question)) {
|
||||
return(NULL)
|
||||
} else if (input$filterSelector != "None" & is.null(input$inFilterSelector)) {
|
||||
return(NULL)
|
||||
} else {
|
||||
|
||||
#initial filtering
|
||||
if (input$filterSelector != "None") {
|
||||
filtered <- survey %>%
|
||||
filter(Answer != "Unknown") %>%
|
||||
filter(Question==input$question,get(input$filterSelector)==input$inFilterSelector)
|
||||
} else {
|
||||
filtered <- survey %>%
|
||||
filter(Answer != "Unknown") %>%
|
||||
filter(Question==input$question)
|
||||
}
|
||||
|
||||
# check if results are to be compared
|
||||
if (input$compareSelector != "None") {
|
||||
data <- filtered %>%
|
||||
count(Answer,Vars=get(input$compareSelector))
|
||||
|
||||
totals <- data %>%
|
||||
group_by(Vars) %>%
|
||||
summarize(total=sum(n))
|
||||
|
||||
data <- left_join(data,totals) %>%
|
||||
filter(total > 20) %>%
|
||||
mutate(share=round((n/total)*100,digits=2))
|
||||
} else {
|
||||
data <- filtered %>%
|
||||
count(Answer) %>%
|
||||
mutate(share=n/sum(n)*100)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
output$Question <- renderText({
|
||||
if (is.null(input$question)) {
|
||||
return()
|
||||
} else {
|
||||
input$question
|
||||
}
|
||||
})
|
||||
|
||||
# render plot output
|
||||
output$answerPlot <- renderPlot({
|
||||
if (is.null(data())) {
|
||||
return()
|
||||
} else {
|
||||
|
||||
data <- data()
|
||||
|
||||
chart <- ggplot(data)
|
||||
if (chartType() == "Histogram") {
|
||||
if (input$compareSelector != "None" && input$compareSelector != "Country") {
|
||||
chart <- chart +
|
||||
geom_bar(aes(x=as.integer(Answer),y=share,fill=Vars),position="dodge",stat="identity") +
|
||||
scale_x_continuous()
|
||||
} else {
|
||||
chart <- chart +
|
||||
geom_bar(aes(x=as.integer(Answer),y=share),fill="#1FBEC3",position="dodge",stat="identity") +
|
||||
scale_x_continuous()
|
||||
}
|
||||
} else {
|
||||
if (input$compareSelector != "None" && input$compareSelector != "Country") {
|
||||
chart <- chart +
|
||||
geom_bar(aes(x=Answer,y=share,fill=Vars),position="dodge",stat="identity") +
|
||||
scale_x_discrete(labels = function(x) str_wrap(x, width = 20))
|
||||
} else {
|
||||
chart <- chart +
|
||||
geom_bar(aes(x=Answer,y=share),fill="#1FBEC3",position="dodge",stat="identity") +
|
||||
scale_x_discrete(labels = function(x) str_wrap(x, width = 20))
|
||||
}
|
||||
}
|
||||
|
||||
# common chart elements
|
||||
chart <- chart +
|
||||
labs(y="Share (in %)", x="Answer") +
|
||||
theme(legend.background=element_rect(color="#357CA5",size=0.5,linetype = "solid")) +
|
||||
theme(legend.position="top") +
|
||||
theme_hc(base_size = 18,base_family="Helvetica") +
|
||||
guides(fill=guide_legend(nrow=4,byrow=TRUE,title="Categories",title.position = "top"))
|
||||
chart
|
||||
}
|
||||
})
|
||||
|
||||
# render sample sizes table
|
||||
output$totalSamples <- renderTable({
|
||||
if (is.null(data())) {
|
||||
return()
|
||||
} else {
|
||||
if (input$compareSelector != "None" && input$compareSelector != "Country") {
|
||||
data <- data()
|
||||
data %>%
|
||||
group_by(Categories = Vars) %>%
|
||||
summarize(Sample=sum(n),Share=str_c(round(Sample/sum(data$n)*100,digits=2),"%"))
|
||||
} else {
|
||||
data() %>%
|
||||
summarize(Sample=sum(n))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# render table with answers
|
||||
output$answerTable <- renderTable({
|
||||
if (is.null(data())) {
|
||||
return()
|
||||
} else {
|
||||
if (input$compareSelector != "None" && input$compareSelector != "Country") {
|
||||
data() %>%
|
||||
select(-n,-total) %>%
|
||||
mutate(share=percent(share/100)) %>%
|
||||
spread(Vars,share)
|
||||
} else {
|
||||
data() %>%
|
||||
mutate(n=format(n,format="d",big.mark = ","),share=percent(share/100))
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# render table with answers
|
||||
output$simpleTable <- renderTable({
|
||||
if (is.null(data())) {
|
||||
return()
|
||||
}
|
||||
data() %>%
|
||||
mutate(n=format(n,format="d", big.mark=","),share=percent(share/100))
|
||||
})
|
||||
|
||||
# render table with answers
|
||||
output$valueTable <- renderTable({
|
||||
if (is.null(data())) {
|
||||
return()
|
||||
} else {
|
||||
if (input$compareSelector != "None" && input$compareSelector != "Country") {
|
||||
data() %>%
|
||||
select(-share,-total) %>%
|
||||
mutate(n=format(n,format="d",big.mark=",")) %>%
|
||||
spread(Vars,n)
|
||||
} else {
|
||||
return()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
# handle download
|
||||
output$download <- downloadHandler(
|
||||
filename = function() {
|
||||
"facebook_survey.csv"
|
||||
},
|
||||
content = function(con) {
|
||||
data <- getDownloadableSurvey()
|
||||
write.csv(data, con)
|
||||
}
|
||||
)
|
||||
|
||||
}
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,95 @@
|
|||
library(shiny)
|
||||
library(shinydashboard)
|
||||
library(markdown)
|
||||
library(shinycssloaders)
|
||||
|
||||
ui <- dashboardPage(title="How do you feel about Facebook?",
|
||||
skin="black",
|
||||
dashboardHeader(
|
||||
title=span(img(src="mozilla.png",alt="Mozilla", width = 100)),titleWidth = "230px"
|
||||
),
|
||||
dashboardSidebar(width="230px",
|
||||
h2("Facebook Survey Results"),
|
||||
sidebarMenu(
|
||||
menuItem("Explore Data", tabName = "explore",icon = icon("bar-chart-o")),
|
||||
menuItem("About the Survey", tabName = "about",icon = icon("info-circle")),
|
||||
menuItem("Download Data", tabName = "download",icon = icon("download"))
|
||||
)
|
||||
|
||||
),
|
||||
dashboardBody(
|
||||
tags$head(
|
||||
tags$link(rel = "stylesheet", type = "text/css", href = "styles.css")
|
||||
),
|
||||
tabItems(
|
||||
tabItem("explore",
|
||||
fluidRow(
|
||||
box(
|
||||
width = 6, status = "primary", solidHeader = TRUE,
|
||||
title = "Select a question:",
|
||||
uiOutput("questionDropdown")
|
||||
),
|
||||
box(
|
||||
width = 3, status = "primary", solidHeader = TRUE,
|
||||
title = "Compare results by:",
|
||||
uiOutput("compareDropdown")
|
||||
),
|
||||
box(
|
||||
width = 3, status = "primary", solidHeader = TRUE,
|
||||
title = "Filter results by:",
|
||||
uiOutput("selectorDropdown"),
|
||||
conditionalPanel(
|
||||
condition = "input.filterSelector!='None'",
|
||||
uiOutput("inSelectorDropdown")
|
||||
)
|
||||
)
|
||||
),
|
||||
fluidRow(
|
||||
tabBox(
|
||||
id="main1",width=12,
|
||||
tabPanel("Plot",
|
||||
div(
|
||||
width=12,
|
||||
uiOutput("message")
|
||||
),
|
||||
withSpinner(plotOutput("answerPlot",height="650px"),type=3,color.background="#ffffff",color="#3C8DBC")
|
||||
),
|
||||
tabPanel("Data",
|
||||
div(id="dataWrap",
|
||||
conditionalPanel(
|
||||
condition="input.compareSelector!='None'",
|
||||
tabBox(id="tabs",width=12,
|
||||
tabPanel("Sample size",
|
||||
tableOutput("totalSamples")
|
||||
),
|
||||
tabPanel("Share (in %)",
|
||||
tableOutput("answerTable")
|
||||
),
|
||||
tabPanel("Total #",
|
||||
tableOutput("valueTable")
|
||||
)
|
||||
)
|
||||
),
|
||||
conditionalPanel(
|
||||
condition="input.compareSelector=='None'",
|
||||
h4("Results"),
|
||||
tableOutput("simpleTable")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
tabItem("about",
|
||||
includeMarkdown("www/about.md")
|
||||
),
|
||||
tabItem("download",
|
||||
h3("You can download all 46,619 anonymized results from the survey (.csv file, 31MB)"),
|
||||
p(
|
||||
downloadButton("download", "Download results")
|
||||
),
|
||||
p("Mozilla is making this data available under a CC BY 4.0 license")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,110 @@
|
|||
### About the survey and this tool
|
||||
|
||||
Facebook has been in the news a lot lately and we wanted to know how you feel. We plan to use this survey to understand how Mozilla can better support and advocate for you and your personal information online. The survey was conducted using SurveyGizmo in April 2018, gathering in total 46,619 responses. The survey was meant to capture how people feel about Facebook, particularly in light of the recent Cambridge Analytica revelations. We built this tool so you can explore the results of the survey yourself.
|
||||
|
||||
This was not a scientific poll. This was as self-selecting survey targeted mostly at people on the Mozilla Foundation email list, the Pocket newsletter email list, through the Mozilla Twitter channel, through a Medium blog post, and through users sharing with friends and family.
|
||||
|
||||
|
||||
### Survey
|
||||
|
||||
Below is the full copy of the survey, which you can also find [here](https://www.surveygizmo.com/s3/4273732/facebook-survey).
|
||||
|
||||
|
||||
#### Question #1: I consider myself:
|
||||
- Super Nerd: I build my own computers, run my own servers, code my own apps. I’m basically Mr Robot.
|
||||
- Technically Savvy: I know my way around a computer pretty well. When anyone in my family needs technical help, I’m the one they call.
|
||||
- Average User: I know enough to get by.
|
||||
- Luddite: Technology scares me! I only use it when I have to.
|
||||
|
||||
#### Question #2: How concerned are you about the safety of your personal information online?
|
||||
- Slider value 1 - 10 ( 1 = not very concerned, 10 = very concerned)
|
||||
|
||||
#### Question #3: Who is most responsible for keeping my personal information safe online?
|
||||
- Government
|
||||
- Me
|
||||
- Companies
|
||||
- I'm not sure
|
||||
|
||||
#### Question #4: When it comes to your personal information, which best sums up your feelings:
|
||||
- I’ve got nothing to hide.
|
||||
- I’m not really sure what the danger is with all this data collection. It’s just the world we live in these days.
|
||||
- I’d rather not have all my personal information out there in the world, but what can I do?
|
||||
- I want to be able to control what personal information is available to others.
|
||||
- I’m very private. I don’t want any of my personal information out there without my consent.
|
||||
|
||||
#### Question #5: How often do you use Facebook?
|
||||
- I’m on Facebook constantly
|
||||
- I check it a couple times a day
|
||||
- I check it once a day, if I have time
|
||||
- I check it a few times a week
|
||||
- I maybe check it once a month
|
||||
- I’m not on Facebook
|
||||
|
||||
#### Question #6: How do you feel about Facebook?
|
||||
- I love it! I can’t imagine my life without it.
|
||||
- It’s cool. I enjoy it most days.
|
||||
- Eh. I’m not sure about all this.
|
||||
- Pretty wary. I’m not real sure it’s good for me.
|
||||
- Scared as hell! Facebook is going to doom us all.
|
||||
|
||||
#### Question #7: Which of the following do you like most about Facebook?
|
||||
- Staying connected with people I care about
|
||||
- Getting the news from places I care about
|
||||
- Cats, cats, doggos, and more cats
|
||||
- Watching all the drama
|
||||
- It’s good for my business, I rely on it for that
|
||||
- None of the above
|
||||
|
||||
#### Question #8: Which of the following do you like least about Facebook?
|
||||
- Trolls and mean people
|
||||
- All the drama
|
||||
- They’re collecting all this data on me and I don’t know how that works
|
||||
- They’re collecting all this data on me and I do know how that works
|
||||
- I feel like I’m stuck in a bubble and don’t see enough other viewpoints
|
||||
- It’s a waste of my time
|
||||
|
||||
#### Question 9: Do you know what types of personal information Facebook collects about you?
|
||||
- Yes
|
||||
- No
|
||||
- I am not sure
|
||||
- If yes, list any of the types of personal information you know Facebook collects
|
||||
|
||||
#### Question #10: Check all the items you currently know how to do:
|
||||
- Change your Facebook privacy settings
|
||||
- Opt out of allowing third-party apps to track you and your friends
|
||||
- Publish something so only a few of your friends can see it
|
||||
- Browse Facebook while limiting its ability to track you
|
||||
- Delete your Facebook page
|
||||
- Create a targeted Facebook ad
|
||||
- Find out all the data Facebook has collected on me already
|
||||
- Make a backup of all my content on Facebook (photos, videos, etc)
|
||||
|
||||
#### Question 11: Have you made any changes on Facebook as a result of the recent Cambridge Analytica and Facebook revelations?
|
||||
- Yes
|
||||
- No
|
||||
- If yes, what were those actions (open answer)
|
||||
|
||||
#### Question 12: Would you consider paying for a version of Facebook that doesn’t make money off you by collecting and selling your data?
|
||||
- Yes, I’d pay up to $10 per month
|
||||
- Yes, I’d pay more than $10 per month
|
||||
- No, I wouldn’t pay anything
|
||||
- Not sure
|
||||
|
||||
#### Country/State (optional)
|
||||
|
||||
#### Gender (optional)
|
||||
- Female
|
||||
- Male
|
||||
- Non-binary/ third gender
|
||||
- Prefer to self-describe _________________
|
||||
- Prefer not to say
|
||||
|
||||
#### Age (optional)
|
||||
- 18-24 years old
|
||||
- 25-34 years old
|
||||
- 35-44 years old
|
||||
- 45-54 years old
|
||||
- 55-64 years old
|
||||
- 65-74 years old
|
||||
- 75 years or older
|
||||
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 25 KiB |
|
@ -0,0 +1,9 @@
|
|||
#dataWrap {
|
||||
height:650px;
|
||||
overflow-y:scroll;
|
||||
}
|
||||
|
||||
.sidebar h2 {
|
||||
text-align:center;
|
||||
padding:10px;
|
||||
}
|
Загрузка…
Ссылка в новой задаче