[New Feature] Add web folder to support web documentation
This commit is contained in:
72
docs/website/src/css/_shared.scss
Normal file
72
docs/website/src/css/_shared.scss
Normal file
@@ -0,0 +1,72 @@
|
||||
%link-style {
|
||||
display: initial;
|
||||
color: var(--ifm-font-color-base);
|
||||
background-color: rgba(187, 239, 253, 0.3);
|
||||
line-height: calc(var(--ifm-font-size-base) + 4px);
|
||||
border-bottom: 1px solid var(--ifm-hr-border-color);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(187, 239, 253, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
%link-style-dark {
|
||||
background-color: rgba(97, 218, 251, 0.12);
|
||||
border-bottom-color: rgba(97, 218, 251, 0.3);
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(97, 218, 251, 0.4);
|
||||
border-bottom-color: var(--brand);
|
||||
}
|
||||
}
|
||||
|
||||
%hash-link-style {
|
||||
background-color: transparent;
|
||||
border-bottom: 0;
|
||||
color: var(--subtle);
|
||||
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
color: var(--brand);
|
||||
}
|
||||
}
|
||||
|
||||
%button-link-style {
|
||||
display: inline-block;
|
||||
padding: 8px 16px;
|
||||
border: 1px solid var(--ifm-color-emphasis-300);
|
||||
border-radius: var(--ifm-global-radius);
|
||||
color: var(--ifm-color-content-secondary);
|
||||
|
||||
&:hover {
|
||||
background: var(--ifm-menu-color-background-hover);
|
||||
color: var(--ifm-link-color);
|
||||
}
|
||||
}
|
||||
|
||||
%scrollbar-style {
|
||||
&::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: #888;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #f1f1f1;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
%scrollbar-style-dark {
|
||||
&::-webkit-scrollbar-track {
|
||||
background: #141414;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb {
|
||||
background: var(--ifm-color-emphasis-200);
|
||||
}
|
||||
}
|
||||
1809
docs/website/src/css/customTheme.scss
Normal file
1809
docs/website/src/css/customTheme.scss
Normal file
File diff suppressed because it is too large
Load Diff
802
docs/website/src/css/index.scss
Normal file
802
docs/website/src/css/index.scss
Normal file
@@ -0,0 +1,802 @@
|
||||
@import "shared";
|
||||
|
||||
.homepage {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
/* ActionButton */
|
||||
|
||||
.ActionButton {
|
||||
padding: 0.75rem 1.5rem;
|
||||
text-align: center;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 400;
|
||||
text-decoration: none !important;
|
||||
border-bottom: none;
|
||||
transition: all 0.2s ease-out;
|
||||
max-width: 50%;
|
||||
|
||||
&.primary {
|
||||
color: var(--dark);
|
||||
background-color: var(--brand);
|
||||
|
||||
&:hover {
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
background: none;
|
||||
color: var(--brand);
|
||||
|
||||
&::after {
|
||||
content: "›";
|
||||
font-size: 24px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.ActionButton {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
/* AcknowledgementList */
|
||||
|
||||
.AcknowledgementList {
|
||||
display: grid;
|
||||
padding: 0;
|
||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||||
grid-gap: 16px;
|
||||
|
||||
.item {
|
||||
list-style: none;
|
||||
|
||||
a img {
|
||||
border-radius: 20%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Community */
|
||||
|
||||
.Community .content {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.firstP img {
|
||||
float: left;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.Community .Heading {
|
||||
width: 100%;
|
||||
padding: 0 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 481px) and (max-width: 960px) {
|
||||
.Community .Heading {
|
||||
width: 100%;
|
||||
padding: 0 4rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.Community .AcknowledgementList {
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
margin: 2rem auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
.Community .column.first {
|
||||
border-right: 1px solid var(--ifm-table-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
/* Cross Platform */
|
||||
|
||||
.CrossPlatform {
|
||||
svg {
|
||||
max-width: 400px;
|
||||
margin: -20px 0;
|
||||
|
||||
text {
|
||||
fill: var(--ifm-color-content-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
.CrossPlatform .TwoColumns {
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
|
||||
.CrossPlatform svg {
|
||||
max-width: 100%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 481px) and (max-width: 960px) {
|
||||
.CrossPlatform .column.last {
|
||||
width: 86%;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fast Refresh */
|
||||
|
||||
/* Make video flush with the bottom */
|
||||
.FastRefresh {
|
||||
margin-bottom: -50px;
|
||||
}
|
||||
|
||||
/* Get rid of extra padding at the bottom of the video */
|
||||
.FastRefresh .column.last {
|
||||
margin-bottom: -6px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.FastRefresh .column.last {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.FastRefresh video {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 481px) and (max-width: 960px) {
|
||||
.FastRefresh .TwoColumns {
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
|
||||
.FastRefresh .column.last {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.FastRefresh video {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
/* Give video more space than text */
|
||||
.FastRefresh .TwoColumns {
|
||||
grid-template-columns: 2fr 1fr;
|
||||
}
|
||||
|
||||
/* Make video flush with top of section */
|
||||
.FastRefresh .last {
|
||||
margin-top: -50px;
|
||||
}
|
||||
|
||||
/* Need to set video height so it'll fit */
|
||||
.FastRefresh video {
|
||||
height: 340px;
|
||||
/* width: 100%; */
|
||||
}
|
||||
}
|
||||
|
||||
/* Get Started */
|
||||
|
||||
.GetStarted,
|
||||
.GetStarted p {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.GetStarted .Heading {
|
||||
color: var(--brand);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.GetStarted .content {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.GetStarted .steps {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.GetStarted .steps li {
|
||||
font-size: 28px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.GetStarted .steps li p {
|
||||
font-size: 17px;
|
||||
}
|
||||
|
||||
.GetStarted .terminal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-left: 1px solid gray;
|
||||
border-right: 1px solid gray;
|
||||
border-top: 1px solid gray;
|
||||
border-top-left-radius: 10px;
|
||||
border-top-right-radius: 10px;
|
||||
padding: 30px 30px 0px 30px;
|
||||
width: 600px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.GetStarted .terminal::before {
|
||||
content: "○ ○ ○";
|
||||
color: gray;
|
||||
font-size: 16px;
|
||||
position: absolute;
|
||||
left: 15px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.GetStarted code {
|
||||
color: white;
|
||||
font-size: 18px;
|
||||
position: relative;
|
||||
background: none;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.GetStarted code:first-child::before {
|
||||
content: ">";
|
||||
position: absolute;
|
||||
left: -13px;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 760px) {
|
||||
.GetStarted .content {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.GetStarted .steps li {
|
||||
margin-left: -1rem;
|
||||
}
|
||||
|
||||
.GetStarted .terminal {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Header Hero */
|
||||
|
||||
.HeaderHero {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.HeaderHero .TwoColumns .column {
|
||||
max-width: initial;
|
||||
}
|
||||
|
||||
.HeaderHero .socialLinks {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
max-width: 1200px;
|
||||
margin: -10px auto 0;
|
||||
|
||||
.twitter-follow-button,
|
||||
.github-button {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.HeaderHero .TwoColumns {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.HeaderHero .title {
|
||||
font-size: 84px;
|
||||
color: var(--brand);
|
||||
line-height: 1;
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.HeaderHero .tagline {
|
||||
font-size: 36px;
|
||||
line-height: 1.3;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.HeaderHero .buttons {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.HeaderHero .image {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
.HeaderHero .TwoColumns {
|
||||
grid-template-columns: 3fr 1fr;
|
||||
}
|
||||
|
||||
.HeaderHero .TwoColumns .column.left {
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.HeaderHero .TwoColumns .column.right {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 481px) and (max-width: 960px) {
|
||||
.HeaderHero .column.first {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.HeaderHero .column.last {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 760px) {
|
||||
.HeaderHero .title {
|
||||
font-size: 60px;
|
||||
}
|
||||
|
||||
.HeaderHero .tagline {
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.HeaderHero .socialLinks {
|
||||
margin-top: -2rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Heading */
|
||||
|
||||
.Heading {
|
||||
font-size: 25px;
|
||||
color: var(--ifm-font-color-base);
|
||||
line-height: 1.2;
|
||||
margin-top: 0;
|
||||
margin-bottom: 20px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
/* Home page */
|
||||
|
||||
.HomePage {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Logo Animation */
|
||||
|
||||
.LogoAnimation {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 760px) {
|
||||
.LogoAnimation {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.LogoAnimation .screen {
|
||||
transition: all 850ms ease-in-out;
|
||||
stroke-opacity: 0;
|
||||
transform: scale(2.25, 1.33) rotate(0);
|
||||
stroke-width: 5px;
|
||||
}
|
||||
|
||||
.LogoAnimation .background {
|
||||
fill: var(--dark);
|
||||
}
|
||||
|
||||
.LogoAnimation .logoInner {
|
||||
transform: scale(1);
|
||||
transition: all 850ms ease-in-out;
|
||||
transition-delay: 50ms;
|
||||
}
|
||||
|
||||
.LogoAnimation.mobile .logoInner,
|
||||
.LogoAnimation.mobile2 .logoInner {
|
||||
transform: scale(0.4);
|
||||
}
|
||||
|
||||
.LogoAnimation.desktop .logoInner {
|
||||
transform: scale(0.5);
|
||||
}
|
||||
|
||||
.LogoAnimation.laptop .logoInner {
|
||||
transform: scale(0.35);
|
||||
}
|
||||
|
||||
.LogoAnimation.full .screen {
|
||||
stroke-opacity: 0;
|
||||
transform: scale(2.25, 1.33) rotate(0);
|
||||
opacity: 1;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.LogoAnimation.mobile .screen {
|
||||
stroke-opacity: 1;
|
||||
transform: scale(1) rotate(0);
|
||||
opacity: 1;
|
||||
stroke-width: 5px;
|
||||
}
|
||||
|
||||
.LogoAnimation.desktop .screen {
|
||||
stroke-opacity: 1;
|
||||
transform: scale(1.125, 1.1) rotate(-90deg);
|
||||
opacity: 1;
|
||||
stroke-width: 8px;
|
||||
}
|
||||
|
||||
.LogoAnimation.laptop .screen {
|
||||
stroke-opacity: 1;
|
||||
transform: scale(0.83) rotate(-90deg);
|
||||
opacity: 1;
|
||||
stroke-width: 5px;
|
||||
}
|
||||
|
||||
.LogoAnimation.mobile2 .screen {
|
||||
stroke-opacity: 1;
|
||||
opacity: 1;
|
||||
stroke-width: 5px;
|
||||
transform: scale(1) rotate(-180deg);
|
||||
}
|
||||
|
||||
.LogoAnimation.full2 .screen {
|
||||
stroke-opacity: 0;
|
||||
transform: scale(2.25, 1.33) rotate(-180deg);
|
||||
}
|
||||
|
||||
.LogoAnimation:not(.mobile):not(.mobile2) .speaker {
|
||||
opacity: 0;
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
||||
.LogoAnimation:not(.desktop) .stand {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
||||
.LogoAnimation:not(.laptop) .base {
|
||||
transform: scaleX(0);
|
||||
}
|
||||
|
||||
.LogoAnimation .speaker,
|
||||
.LogoAnimation .stand,
|
||||
.LogoAnimation .base {
|
||||
transition: all 850ms ease-in-out;
|
||||
}
|
||||
|
||||
/* Native Apps */
|
||||
|
||||
.AdvancedBioMaker {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
.AdvancedBioMaker .column.last {
|
||||
max-height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 481px) and (max-width: 960px) {
|
||||
.AdvancedBioMaker .column.last {
|
||||
width: 66.7%;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
.AdvancedBioMaker {
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
/* Correct for whitespace in the image of phones */
|
||||
.AdvancedBioMaker .column.left {
|
||||
margin-top: -25px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Native Code */
|
||||
|
||||
.WrittenPython .column.last {
|
||||
margin-bottom: -50px;
|
||||
}
|
||||
|
||||
.WrittenPython pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.WrittenPython .prism-code {
|
||||
border-radius: 0;
|
||||
font-size: 80%;
|
||||
background-color: #282c34;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.WrittenPython .column.last {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.WrittenPython .prism-code {
|
||||
font-size: 10px;
|
||||
padding: 1.25rem 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 481px) and (max-width: 960px) {
|
||||
.WrittenPython .TwoColumns {
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
|
||||
.WrittenPython .column.last {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
background-color: var(--dark);
|
||||
height: 28rem;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.WrittenPython .prism-code {
|
||||
width: 30rem;
|
||||
margin: 0 auto;
|
||||
padding: 1.25rem 0rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
.WrittenPython .TwoColumns .column.right {
|
||||
/* Make flush with top and bottom */
|
||||
margin-top: -50px;
|
||||
/* Get rid of default left padding */
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.WrittenPython .column.right .prism-code {
|
||||
/* Bleed background into the right */
|
||||
margin-right: -9999px;
|
||||
padding: 16px 1.5rem;
|
||||
height: 460px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Native Development */
|
||||
|
||||
.RichFeatures {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.RichFeatures .dissection {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.RichFeatures .dissection img {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
.RichFeatures .TwoColumns {
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.RichFeatures .dissection {
|
||||
height: 350px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 481px) and (max-width: 960px) {
|
||||
.RichFeatures .dissection {
|
||||
height: 450px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
.RichFeatures .dissection {
|
||||
height: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Section */
|
||||
|
||||
.Section {
|
||||
width: 100%;
|
||||
padding-top: 50px;
|
||||
padding-bottom: 50px;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.Section + .Section {
|
||||
border-top: 1px solid var(--ifm-table-border-color);
|
||||
}
|
||||
|
||||
.Section.tint {
|
||||
background-color: var(--ifm-menu-color-background-active);
|
||||
}
|
||||
|
||||
.Section.dark {
|
||||
background-color: var(--dark);
|
||||
}
|
||||
|
||||
.Section p a {
|
||||
@extend %link-style;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .Section p a {
|
||||
@extend %link-style-dark;
|
||||
}
|
||||
|
||||
/* VideoContent */
|
||||
|
||||
.VideoContent {
|
||||
.twitter-follow-button {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
.VideoContent .TwoColumns {
|
||||
grid-gap: 2rem;
|
||||
}
|
||||
|
||||
.VideoContent .column.last {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the full-width video won't fit, make it full-width.
|
||||
* https://jameshfisher.com/2017/08/30/how-do-i-make-a-full-width-iframe/
|
||||
*/
|
||||
.VideoContent .vidWrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-top: 56.25%;
|
||||
}
|
||||
|
||||
.VideoContent iframe {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
/* Give more width for the video */
|
||||
.VideoContent .TwoColumns {
|
||||
grid-template-columns: 1fr 2fr;
|
||||
}
|
||||
|
||||
.VideoContent iframe {
|
||||
width: 560px;
|
||||
height: 315px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Two columns */
|
||||
|
||||
.TwoColumns {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.TwoColumns .column {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.TwoColumns .column.first {
|
||||
grid-area: first;
|
||||
}
|
||||
|
||||
.TwoColumns .column.last {
|
||||
grid-area: last;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 961px) {
|
||||
.TwoColumns {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
grid-template-areas: "first last";
|
||||
}
|
||||
|
||||
.TwoColumns.reverse {
|
||||
grid-template-areas: "last first";
|
||||
}
|
||||
|
||||
.TwoColumns .column {
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
.TwoColumns .column.left {
|
||||
padding-right: 50px;
|
||||
}
|
||||
|
||||
.TwoColumns .column.right {
|
||||
padding-left: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 960px) {
|
||||
.TwoColumns,
|
||||
.TwoColumns.reverse {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-areas: "first" "last";
|
||||
}
|
||||
|
||||
.TwoColumns .column {
|
||||
padding: 0 4rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 480px) {
|
||||
.TwoColumns .column {
|
||||
padding: 0 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Twitter Follow Button */
|
||||
|
||||
.twitter-follow-button {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
height: 28px;
|
||||
box-sizing: border-box;
|
||||
padding: 1px 10px 1px 9px;
|
||||
background-color: #1b95e0;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
font-weight: 400;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
line-height: 26px;
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
background-color: #0c7abf;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
top: 4px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
margin-right: 4px;
|
||||
background: transparent 0 0 no-repeat;
|
||||
background-image: url(data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2072%2072%22%3E%3Cpath%20fill%3D%22none%22%20d%3D%22M0%200h72v72H0z%22%2F%3E%3Cpath%20class%3D%22icon%22%20fill%3D%22%23fff%22%20d%3D%22M68.812%2015.14c-2.348%201.04-4.87%201.744-7.52%202.06%202.704-1.62%204.78-4.186%205.757-7.243-2.53%201.5-5.33%202.592-8.314%203.176C56.35%2010.59%2052.948%209%2049.182%209c-7.23%200-13.092%205.86-13.092%2013.093%200%201.026.118%202.02.338%202.98C25.543%2024.527%2015.9%2019.318%209.44%2011.396c-1.125%201.936-1.77%204.184-1.77%206.58%200%204.543%202.312%208.552%205.824%2010.9-2.146-.07-4.165-.658-5.93-1.64-.002.056-.002.11-.002.163%200%206.345%204.513%2011.638%2010.504%2012.84-1.1.298-2.256.457-3.45.457-.845%200-1.666-.078-2.464-.23%201.667%205.2%206.5%208.985%2012.23%209.09-4.482%203.51-10.13%205.605-16.26%205.605-1.055%200-2.096-.06-3.122-.184%205.794%203.717%2012.676%205.882%2020.067%205.882%2024.083%200%2037.25-19.95%2037.25-37.25%200-.565-.013-1.133-.038-1.693%202.558-1.847%204.778-4.15%206.532-6.774z%22%2F%3E%3C%2Fsvg%3E);
|
||||
}
|
||||
}
|
||||
139
docs/website/src/css/showcase.scss
Normal file
139
docs/website/src/css/showcase.scss
Normal file
@@ -0,0 +1,139 @@
|
||||
@import "shared";
|
||||
|
||||
.showcaseSection {
|
||||
max-width: 800px;
|
||||
margin: 64px auto;
|
||||
text-align: center;
|
||||
padding: 0 20px;
|
||||
|
||||
.showcase img {
|
||||
height: 100px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.logos img {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.info {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
p a {
|
||||
@extend %link-style;
|
||||
}
|
||||
|
||||
.form-button {
|
||||
@extend %button-link-style;
|
||||
margin-bottom: 36px;
|
||||
border-width: 2px;
|
||||
font-weight: 500;
|
||||
|
||||
&:hover {
|
||||
border-color: var(--ifm-color-primary);
|
||||
color: var(--ifm-font-color-base) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .showcaseSection {
|
||||
p a {
|
||||
@extend %link-style-dark;
|
||||
}
|
||||
|
||||
.form-button {
|
||||
color: var(--ifm-color-secondary-dark);
|
||||
}
|
||||
}
|
||||
|
||||
.home-showcase-section {
|
||||
max-width: 800px;
|
||||
margin: 20px auto 20px auto;
|
||||
text-align: center;
|
||||
padding-bottom: 40px;
|
||||
|
||||
p {
|
||||
max-width: 560px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
.pinned img {
|
||||
width: 150px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.footnote {
|
||||
font-size: 12px;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.home-showcase-section {
|
||||
h2 {
|
||||
font-size: 31px;
|
||||
line-height: 40px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.showcase img {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.showcaseHeader {
|
||||
padding-bottom: 15px;
|
||||
padding-top: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.showcase {
|
||||
margin: 30px auto 30px auto;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
|
||||
h3 {
|
||||
margin-bottom: 0;
|
||||
line-height: 21px;
|
||||
padding: 5px 5px 2px;
|
||||
font-size: 21px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 5px;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
h3,
|
||||
p {
|
||||
color: var(--ifm-color-emphasis-800);
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-device-width: 840px) {
|
||||
.showcaseSection {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 600px) {
|
||||
.showcase {
|
||||
width: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 960px) {
|
||||
.showcase {
|
||||
width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (min-device-width: 736px) {
|
||||
.showcaseSection .showcase img {
|
||||
width: 100px;
|
||||
max-height: 100px;
|
||||
}
|
||||
}
|
||||
47
docs/website/src/css/versions.scss
Normal file
47
docs/website/src/css/versions.scss
Normal file
@@ -0,0 +1,47 @@
|
||||
@import "shared";
|
||||
|
||||
.versions-page {
|
||||
max-width: 960px;
|
||||
padding: 28px;
|
||||
|
||||
h1 {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
code {
|
||||
white-space: pre;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
p a,
|
||||
td a {
|
||||
@extend %link-style;
|
||||
|
||||
code {
|
||||
background: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
table th,
|
||||
table td {
|
||||
min-width: 100px;
|
||||
font-size: 15px;
|
||||
padding: 8px 20px;
|
||||
}
|
||||
|
||||
.versions {
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .versions-page {
|
||||
p a,
|
||||
td a {
|
||||
@extend %link-style-dark;
|
||||
}
|
||||
}
|
||||
45
docs/website/src/pages/animations/_dissectionAnimation.js
Normal file
45
docs/website/src/pages/animations/_dissectionAnimation.js
Normal file
@@ -0,0 +1,45 @@
|
||||
export function setupDissectionAnimation() {
|
||||
const section = document.querySelector('.RichFeatures');
|
||||
const dissection = document.querySelector('.RichFeatures .dissection');
|
||||
const images = dissection.children;
|
||||
const numImages = images.length;
|
||||
|
||||
const fadeDistance = 40;
|
||||
const navbarHeight = 60;
|
||||
|
||||
function clamp(val, min, max) {
|
||||
return Math.min(max, Math.max(min, val));
|
||||
}
|
||||
|
||||
// Scale the percent so that `min` goes to 0% and `max` goes to 100%
|
||||
function scalePercent(percent, min, max) {
|
||||
const scale = max - min;
|
||||
return clamp((percent - min) / scale, 0, 1);
|
||||
}
|
||||
|
||||
// Get the percentage that the image should be on the screen given
|
||||
// how much the entire container is scrolled
|
||||
// so we can fine-tune at what screen % the animation starts and stops
|
||||
function getImagePercent(index, scrollPercent) {
|
||||
const start = index / numImages;
|
||||
return clamp((scrollPercent - start) * numImages, 0, 1);
|
||||
}
|
||||
|
||||
function onScroll() {
|
||||
const elPos = section.getBoundingClientRect().top - navbarHeight;
|
||||
const height = window.innerHeight;
|
||||
const screenPercent = 1 - clamp(elPos / height, 0, 1);
|
||||
const scaledPercent = scalePercent(screenPercent, 0.2, 0.9);
|
||||
for (let i = 0; i < numImages; i++) {
|
||||
const imgPercent = getImagePercent(i, scaledPercent);
|
||||
images[i].style.opacity = imgPercent;
|
||||
|
||||
const translation = fadeDistance * (1 - imgPercent);
|
||||
images[i].style.left = `${translation}px`;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('scroll', onScroll);
|
||||
|
||||
return () => window.removeEventListener('scroll', onScroll);
|
||||
}
|
||||
49
docs/website/src/pages/animations/_headerAnimation.js
Normal file
49
docs/website/src/pages/animations/_headerAnimation.js
Normal file
@@ -0,0 +1,49 @@
|
||||
export function setupHeaderAnimations() {
|
||||
const steps = ['full', 'mobile', 'desktop', 'laptop', 'mobile2', 'full2'];
|
||||
const intervals = [1250, 1500, 1500, 1500, 1500, 1250];
|
||||
|
||||
let i = 0;
|
||||
const timeouts = [];
|
||||
|
||||
const logo = document.querySelector('.LogoAnimation');
|
||||
|
||||
function animateStep() {
|
||||
const prev = steps[i];
|
||||
logo.classList.remove(prev);
|
||||
i = (i + 1) % steps.length;
|
||||
const current = steps[i];
|
||||
const timeout = intervals[i];
|
||||
logo.classList.add(current);
|
||||
|
||||
timeouts.push(setTimeout(animateStep, timeout));
|
||||
}
|
||||
|
||||
// only start the animation if the document is visible on load
|
||||
if (!document.hidden) {
|
||||
timeouts.push(
|
||||
setTimeout(() => {
|
||||
logo.classList.remove('init');
|
||||
animateStep();
|
||||
}, 2000)
|
||||
);
|
||||
}
|
||||
|
||||
function onVisibilityChange() {
|
||||
if (document.hidden) {
|
||||
timeouts.forEach(timeout => {
|
||||
clearTimeout(timeout);
|
||||
});
|
||||
// clear the timeouts array
|
||||
timeouts.length = 0;
|
||||
} else {
|
||||
// restart the animation when visible
|
||||
animateStep();
|
||||
}
|
||||
}
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
document.addEventListener('visibilitychange', onVisibilityChange, false);
|
||||
|
||||
return () =>
|
||||
document.removeEventListener('visibilitychange', onVisibilityChange);
|
||||
}
|
||||
36
docs/website/src/pages/help.md
Normal file
36
docs/website/src/pages/help.md
Normal file
@@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Community
|
||||
description: The OpenDBM Community
|
||||
wrapperClassName: 'community-page'
|
||||
---
|
||||
|
||||
# The OpenDBM Community
|
||||
|
||||
There are some developers / researchers around the world using OpenDBM. This is a brief overview of where you can find them.
|
||||
|
||||
## Where To Get Help
|
||||
|
||||
If you need help with your OpenDBM library, the right place to go depends on the type of help that you need.
|
||||
|
||||
### Repository
|
||||
|
||||
The core of **OpenDBM** is worked on full-time by AiCure's OpenDBM team. But there are far more people in the community who make key contributions and fix things. If the issue you are facing is code related, you should consider checking the open issues in the [main repository](https://github.com/AiCure/open_dbm/issues). If you cannot find an existing issue, please [use the Bug Report template](https://github.com/AiCure/open_dbm/issues/new?assignees=&labels=&template=bug_report.yaml) to create an issue with a minimal example.
|
||||
|
||||
### Stack Overflow
|
||||
|
||||
Many members of the community use Stack Overflow to ask questions. Read through the [existing questions](http://stackoverflow.com/questions/tagged/opendbm?sort=frequent) tagged with **opendbm** or [ask your own](http://stackoverflow.com/questions/ask?tags=opendbm)!
|
||||
|
||||
## Staying up to date
|
||||
### Discussion
|
||||
|
||||
OpenDBM is still a young library, and its rapid release cycle leaves the door open for discussing how it can evolve at every step of the way. If you want to know the discussions that are talking about, you can read through the [Discussions](https://github.com/AiCure/open_dbm/discussions).
|
||||
|
||||
### Conferences
|
||||
|
||||
You can check the [OpenDBM Meetups](https://aicure.com/opendbm/) that happen around the world.
|
||||
|
||||
## Communities
|
||||
|
||||
### Forum-like groups
|
||||
|
||||
We want to ensure that OpenDBM feels like a community of like-minded researchers and clinicians. Hence, there are a few ways we encourage users to stay involved––and why we encourage you [to join DiME, too!](https://www.dimesociety.org/)
|
||||
495
docs/website/src/pages/index.js
Normal file
495
docs/website/src/pages/index.js
Normal file
@@ -0,0 +1,495 @@
|
||||
import React, {useEffect} from 'react';
|
||||
import GitHubButton from 'react-github-btn';
|
||||
|
||||
import Head from '@docusaurus/Head';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
import Layout from '@theme/Layout';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
import CrossPlatformSVG from '../../static/img/homepage/cross-platform.svg';
|
||||
import {setupDissectionAnimation} from './animations/_dissectionAnimation';
|
||||
import {setupHeaderAnimations} from './animations/_headerAnimation';
|
||||
|
||||
const textContent = {
|
||||
intro: `
|
||||
OpenDBM is a software package that allows for calculation of digital biomarkers from video/audio of a person's
|
||||
behavior by combining tools to measure behavioral characteristics like facial activity, voice, and movement into a single package for measurement of overall behavior.
|
||||
<br/><br/>
|
||||
<strong>Ease of use</strong>. OpenDBM is designed for ease of use, expanding the availability of such tools to the wider scientific community.
|
||||
`,
|
||||
writtenPython: `
|
||||
It using Python language so you can integrate with other biomaker or ML libraries
|
||||
<br/><br/>
|
||||
<strong>Many OS platforms</strong>, one code. You can focus on building researching medical purpose
|
||||
and the single codebase can share code across platforms. With OpenDBM,
|
||||
one team can maintain multiple OS platforms and share a common researching application.
|
||||
`,
|
||||
codeExample: `
|
||||
from opendbm.facial import FacialActivity
|
||||
|
||||
model = FacialActivity()
|
||||
|
||||
m.fit()
|
||||
landmark = model.get_landmark()
|
||||
landmark.mean()
|
||||
landmark.std()
|
||||
`,
|
||||
forResearchers: `
|
||||
Through OpenDBM, a user can objectively and sensitively measure behavioral characteristics such as facial activity, vocal acoustics,
|
||||
characteristics of speech, patterns of movement, and oculomotion. <br/><br/>
|
||||
From those behavioral characteristics, they can measure clinically meaningful symptomatology such as emotional expressivity, prosody
|
||||
of voice, valence of speech, and severity of tremor––among many others.
|
||||
`,
|
||||
talks: `
|
||||
We’ve recorded some instructional videos (listed and linked to within the documentation) that should help the user get through
|
||||
common steps such as installation, usage, etc.
|
||||
`,
|
||||
};
|
||||
|
||||
function Heading({text}) {
|
||||
return <h2 className="Heading">{text}</h2>;
|
||||
}
|
||||
|
||||
function ActionButton({href, type = 'primary', target, children}) {
|
||||
return (
|
||||
<a className={`ActionButton ${type}`} href={href} target={target}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
function TextColumn({title, text, moreContent}) {
|
||||
return (
|
||||
<>
|
||||
<Heading text={title} />
|
||||
<div dangerouslySetInnerHTML={{__html: text}} />
|
||||
{moreContent}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function HomeCallToAction() {
|
||||
return (
|
||||
<>
|
||||
<ActionButton
|
||||
type="primary"
|
||||
href={useBaseUrl('docs/getting-started')}
|
||||
target="_self">
|
||||
Get started
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
type="secondary"
|
||||
href={useBaseUrl('docs/tutorial')}
|
||||
target="_self">
|
||||
Learn basics
|
||||
</ActionButton>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function GitHubStarButton() {
|
||||
return (
|
||||
<div className="github-button">
|
||||
<GitHubButton
|
||||
href="https://github.com/AiCure/open_dbm"
|
||||
data-icon="octicon-star"
|
||||
data-size="large"
|
||||
aria-label="Star AiCure/open_dbm on GitHub">
|
||||
Star
|
||||
</GitHubButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function Section({
|
||||
element = 'section',
|
||||
children,
|
||||
className,
|
||||
background = 'light',
|
||||
}) {
|
||||
const El = element;
|
||||
return <El className={`Section ${className} ${background}`}>{children}</El>;
|
||||
}
|
||||
|
||||
function TwoColumns({columnOne, columnTwo, reverse}) {
|
||||
return (
|
||||
<div className={`TwoColumns ${reverse ? 'reverse' : ''}`}>
|
||||
<div className={`column first ${reverse ? 'right' : 'left'}`}>
|
||||
{columnOne}
|
||||
</div>
|
||||
<div className={`column last ${reverse ? 'left' : 'right'}`}>
|
||||
{columnTwo}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ScreenRect({className, fill, stroke}) {
|
||||
return (
|
||||
<rect
|
||||
className={`screen ${className || ''}`}
|
||||
rx="3%"
|
||||
width="180"
|
||||
height="300"
|
||||
x="-90"
|
||||
y="-150"
|
||||
fill={fill}
|
||||
stroke={stroke}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function LogoAnimation() {
|
||||
return (
|
||||
<svg
|
||||
className="LogoAnimation init"
|
||||
width={350}
|
||||
height={350}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="-200 -200 400 400">
|
||||
<title>OpenDBM logo</title>
|
||||
<clipPath id="screen">
|
||||
<ScreenRect fill="none" stroke="gray" />
|
||||
</clipPath>
|
||||
<rect
|
||||
x="-25"
|
||||
y="120"
|
||||
width="50"
|
||||
height="25"
|
||||
rx="2"
|
||||
fill="white"
|
||||
stroke="none"
|
||||
className="stand"
|
||||
/>
|
||||
<polygon
|
||||
points="-125,90 125,90 160,145 -160,145"
|
||||
fill="white"
|
||||
stroke="white"
|
||||
strokeWidth="5"
|
||||
strokeLinejoin="round"
|
||||
className="base"
|
||||
/>
|
||||
<ScreenRect className="background" stroke="none" />
|
||||
<g clipPath="url(#screen)" className="logo">
|
||||
<g className="logoInner">
|
||||
<circle cx="0" cy="0" r="30" fill="#61dafb" />
|
||||
<g stroke="#61dafb" strokeWidth="15" fill="none" id="logo">
|
||||
<ellipse rx="165" ry="64" />
|
||||
<ellipse rx="165" ry="64" transform="rotate(60)" />
|
||||
<ellipse rx="165" ry="64" transform="rotate(120)" />
|
||||
</g>
|
||||
</g>
|
||||
<line
|
||||
x1="-30"
|
||||
x2="30"
|
||||
y1="130"
|
||||
y2="130"
|
||||
stroke="white"
|
||||
strokeWidth="8"
|
||||
strokeLinecap="round"
|
||||
className="speaker"
|
||||
/>
|
||||
</g>
|
||||
<ScreenRect fill="none" stroke="white" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
function HeaderHero() {
|
||||
return (
|
||||
<Section background="dark" className="HeaderHero">
|
||||
<div className="socialLinks">
|
||||
<GitHubStarButton />
|
||||
</div>
|
||||
<TwoColumns
|
||||
reverse
|
||||
columnOne={
|
||||
<img alt="" src={useBaseUrl('img/homepage/biomaker_logo2.gif')} />
|
||||
}
|
||||
columnTwo={
|
||||
<>
|
||||
<h1 className="title">OpenDBM</h1>
|
||||
<p className="tagline">Digital Biomaker Library.</p>
|
||||
<div className="buttons">
|
||||
<HomeCallToAction />
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function AdvancedBioMaker() {
|
||||
return (
|
||||
<Section className="AdvancedBioMaker" background="light">
|
||||
<TwoColumns
|
||||
reverse
|
||||
columnOne={
|
||||
<TextColumn
|
||||
title="Advanced Digital Biomaker"
|
||||
text={textContent.intro}
|
||||
/>
|
||||
}
|
||||
columnTwo={<img alt="" src={useBaseUrl('img/homepage/biomaker.png')} />}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function WrittenPython() {
|
||||
return (
|
||||
<Section className="WrittenPython" background="tint">
|
||||
<TwoColumns
|
||||
columnOne={
|
||||
<TextColumn
|
||||
title="Written in Python—support all OS platforms"
|
||||
text={textContent.writtenPython}
|
||||
/>
|
||||
}
|
||||
columnTwo={
|
||||
<CodeBlock language="jsx">{textContent.codeExample}</CodeBlock>
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function RichFeatures() {
|
||||
return (
|
||||
<Section className="RichFeatures" background="light">
|
||||
<TwoColumns
|
||||
reverse
|
||||
columnOne={
|
||||
<TextColumn
|
||||
title="Rich Features for Researchers"
|
||||
text={textContent.forResearchers}
|
||||
/>
|
||||
}
|
||||
columnTwo={
|
||||
<div className="dissection">
|
||||
<img alt="" src={useBaseUrl('img/homepage/features.png')} />
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function VideoContent() {
|
||||
return (
|
||||
<div>
|
||||
<Section className="VideoContent" background="tint">
|
||||
<br />
|
||||
<TwoColumns
|
||||
columnOne={
|
||||
<TextColumn title="Talks and Videos" text={textContent.talks} />
|
||||
}
|
||||
columnTwo={
|
||||
<div className="vidWrapper">
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/PNS-TQX5CFc"
|
||||
title="OpenDBM Virtual Training"
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<TwoColumns
|
||||
columnOne={
|
||||
<>
|
||||
<p>
|
||||
The{' '}
|
||||
<a href="https://github.com/AiCure/open_dbm/graphs/contributors">
|
||||
OpenDBM Contributor Team
|
||||
</a>{' '}
|
||||
has put together a short video where they explained about the
|
||||
installation in some platforms.
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
columnTwo={
|
||||
<div className="vidWrapper">
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/CfNFBcf41u0"
|
||||
title="OpenDBM Installation on Mac"
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
/>
|
||||
<br></br>
|
||||
<iframe
|
||||
src="https://www.youtube.com/embed/TKON5UcxrwQ"
|
||||
title="OpenDBM How to use on Mac"
|
||||
frameBorder="0"
|
||||
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
|
||||
allowFullScreen
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/* Community */
|
||||
|
||||
function AcknowledgementList() {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
const apps = siteConfig.customFields.users.filter(app => app.pinned);
|
||||
|
||||
return (
|
||||
<ul className="AcknowledgementList">
|
||||
{apps.map((app, i) => {
|
||||
const imgSource = !app.icon.startsWith('http')
|
||||
? useBaseUrl('img/showcase/' + app.icon)
|
||||
: app.icon;
|
||||
return (
|
||||
<li key={i} className="item">
|
||||
{app.infoLink ? (
|
||||
<a href={app.infoLink}>
|
||||
<img src={imgSource} alt={app.name} />
|
||||
</a>
|
||||
) : (
|
||||
<img src={imgSource} alt={app.name} />
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
function Community() {
|
||||
return (
|
||||
<Section className="Community" background="light">
|
||||
<div className="content">
|
||||
<Heading text="Community Driven" />
|
||||
<TwoColumns
|
||||
columnOne={
|
||||
<>
|
||||
<p className="firstP">
|
||||
<img src={useBaseUrl(`img/header_logo.png`)} alt="" />
|
||||
<span>
|
||||
AiCure released OpenDBM in 2020 and has been maintaining it
|
||||
ever since.
|
||||
</span>
|
||||
</p>
|
||||
<p>
|
||||
We want to ensure that OpenDBM feels like a community of
|
||||
like-minded researchers and clinicians. Hence, there are a few
|
||||
ways we encourage users to stay involved––and why we encourage
|
||||
you to join DiME, too! Most importantly, if you’re interested in
|
||||
OpenDBM, star the repo and sign up for our listserv for all
|
||||
updates.
|
||||
</p>
|
||||
<p>
|
||||
If you’re thinking about contributing to OpenDBM––to which we
|
||||
say kudos––please{' '}
|
||||
<span>
|
||||
<a href="opendbm@aicure.com">reach out to us.</a>
|
||||
</span>{' '}
|
||||
We’ve written{' '}
|
||||
<span>
|
||||
<a href="https://github.com/AiCure/open_dbm/blob/master/CODE_OF_CONDUCT.md">
|
||||
code of conduct
|
||||
</a>
|
||||
</span>{' '}
|
||||
and{' '}
|
||||
<span>
|
||||
<a href="https://github.com/AiCure/open_dbm/blob/master/CONTRIBUTING.md">
|
||||
contribution guidelines
|
||||
</a>
|
||||
</span>{' '}
|
||||
but also want to do whatever we can to help.
|
||||
</p>
|
||||
</>
|
||||
}
|
||||
columnTwo={
|
||||
<>
|
||||
<p>
|
||||
<strong>Acknowledgements</strong> <br></br>A point that was
|
||||
mentioned earlier and cannot be emphasized enough is that
|
||||
OpenDBM is simply a compilation of existing but disparate
|
||||
open-source software tools that we’ve built on top of. All these
|
||||
tools are of course listed in the OpenDBM dependencies but we
|
||||
want to acknowledge just a few here: OpenFace, built on OpenCV,
|
||||
is at the heart of all facial measures and even some of the
|
||||
movement ones. Parselmouth and its reliance on the Praat
|
||||
software library lies behind most of the vocal acoustic
|
||||
measures. DeepSpeech was used for all speech transcription and
|
||||
NLTK is utilized for a lot of language metrics. OpenDBM would
|
||||
not be possible without these––and several other––open source
|
||||
software packages.
|
||||
</p>
|
||||
<AcknowledgementList />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
function GetStarted() {
|
||||
return (
|
||||
<Section className="GetStarted" background="dark">
|
||||
<div className="content">
|
||||
<Heading text="Give it a try" />
|
||||
<ol className="steps">
|
||||
<li>
|
||||
<p>Run this</p>
|
||||
<div className="terminal">
|
||||
<code>pip install opendbm</code>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<p>Read these</p>
|
||||
<HomeCallToAction />
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
|
||||
const useHomePageAnimations = () => {
|
||||
useEffect(() => setupHeaderAnimations(), []);
|
||||
useEffect(() => setupDissectionAnimation(), []);
|
||||
};
|
||||
|
||||
const Index = () => {
|
||||
useHomePageAnimations();
|
||||
return (
|
||||
<Layout
|
||||
description="A digital biomaker reader based on Python"
|
||||
wrapperClassName="homepage">
|
||||
<Head>
|
||||
<title>OpenDBM · Digital Biomaker Library</title>
|
||||
<meta
|
||||
property="og:title"
|
||||
content="OpenDBM · Digital Biomaker Library"
|
||||
/>
|
||||
<meta
|
||||
property="twitter:title"
|
||||
content="OpenDBM · Digital Biomaker Library"
|
||||
/>
|
||||
</Head>
|
||||
<HeaderHero />
|
||||
<AdvancedBioMaker />
|
||||
<WrittenPython />
|
||||
<RichFeatures />
|
||||
<VideoContent />
|
||||
<Community />
|
||||
<GetStarted />
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
||||
119
docs/website/src/pages/showcase.js
Normal file
119
docs/website/src/pages/showcase.js
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Copyright (c) AiCure, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||
|
||||
const renderApp = (app, i) => {
|
||||
return (
|
||||
<div className="showcase" key={i}>
|
||||
<div>
|
||||
<a href={app.infoLink}>{renderAppIcon(app)}</a>
|
||||
<h3>{app.name}</h3>
|
||||
{renderLinks(app)}
|
||||
{renderInfo(app.infoTitle, app.infoLink)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const renderAppIcon = app => {
|
||||
let imgSource = app.icon;
|
||||
if (!app.icon.startsWith('http')) {
|
||||
imgSource = useBaseUrl('img/showcase/' + app.icon);
|
||||
}
|
||||
return <img src={imgSource} alt={app.name} />;
|
||||
};
|
||||
|
||||
const renderInfo = (title, uri) => {
|
||||
return uri ? (
|
||||
<p className="info">
|
||||
<a href={uri} target="_blank">
|
||||
{title}
|
||||
</a>
|
||||
</p>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const renderLinks = app => {
|
||||
if (!app.linkAppStore && !app.linkPlayStore) {
|
||||
return;
|
||||
}
|
||||
|
||||
const linkAppStore = app.linkAppStore ? (
|
||||
<a href={app.linkAppStore} target="_blank">
|
||||
iOS
|
||||
</a>
|
||||
) : null;
|
||||
const linkPlayStore = app.linkPlayStore ? (
|
||||
<a href={app.linkPlayStore} target="_blank">
|
||||
Android
|
||||
</a>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<p>
|
||||
{linkPlayStore}
|
||||
{linkPlayStore && linkAppStore ? ' • ' : ''}
|
||||
{linkAppStore}
|
||||
</p>
|
||||
);
|
||||
};
|
||||
|
||||
const Showcase = () => {
|
||||
const {siteConfig} = useDocusaurusContext();
|
||||
|
||||
const showcaseApps = siteConfig.customFields.users;
|
||||
const pinnedApps = showcaseApps.filter(app => app.pinned);
|
||||
const featuredApps = showcaseApps
|
||||
.filter(app => !app.pinned)
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
const apps = pinnedApps.concat(featuredApps);
|
||||
|
||||
return (
|
||||
<Layout
|
||||
title="Who's using OpenDBM?"
|
||||
description="Some already using openDBM. You can check these below">
|
||||
<div className="showcaseSection">
|
||||
<div className="prose">
|
||||
<h1>Who's using OpenDBM?</h1>
|
||||
<p>
|
||||
This section attempts to list all peer-reviewed scientific articlces
|
||||
that have used OpenDBM for measurement of digital biomarkers.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<ul>
|
||||
<li>
|
||||
Galatzer-Levy, I., Abbas, A., Koesmahargyo, V., Yadav, V.,
|
||||
Perez-Rodriguez, M. M., Rosenfield, P., ... & Hansen, B. J.
|
||||
(2020). Facial and vocal markers of schizophrenia measured using
|
||||
remote smartphone assessments. medRxiv.
|
||||
</li>
|
||||
<li>
|
||||
Galatzer-Levy, I. R., Abbas, A., Ries, A., Homan, S.,
|
||||
Koesmahargyo, V., Yadav, V., ... & Scholz, U. (2020). Validation
|
||||
of Visual and Auditory Digital Markers of Suicidality in Acutely
|
||||
Suicidal Psychiatric In-Patients. medRxiv.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<a
|
||||
className="form-button"
|
||||
href="https://forms.gle/Hb6bDL1GJvG1ByUX7"
|
||||
target="_blank">
|
||||
To add to this list, please simply fill out this form.
|
||||
</a>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Showcase;
|
||||
119
docs/website/src/pages/versions.js
Normal file
119
docs/website/src/pages/versions.js
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
* Copyright (c) AiCure, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import Layout from '@theme/Layout';
|
||||
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
const versions = require('../../versions.json');
|
||||
|
||||
const VersionItem = ({version, currentVersion}) => {
|
||||
const versionName = version === 'next' ? 'Master' : version;
|
||||
|
||||
const isCurrentVersion = currentVersion === version;
|
||||
const isNext = version === 'next';
|
||||
const isRC = version.toUpperCase().indexOf('-RC') !== -1;
|
||||
|
||||
const latestMajorVersion = versions[0].toUpperCase().replace('-RC', '');
|
||||
const documentationLink = (
|
||||
<a
|
||||
href={useBaseUrl(
|
||||
'docs/' + (isCurrentVersion ? '' : version + '/') + 'getting-started'
|
||||
)}>
|
||||
Documentation
|
||||
</a>
|
||||
);
|
||||
let releaseNotesURL = 'https://github.com/AiCure/open_dbm/releases';
|
||||
let releaseNotesTitle = 'Changelog';
|
||||
if (isNext) {
|
||||
releaseNotesURL = `https://github.com/AiCure/open_dbm/compare/${latestMajorVersion}-stable...main`;
|
||||
releaseNotesTitle = 'Commits since ' + latestMajorVersion;
|
||||
} else if (!isRC) {
|
||||
releaseNotesURL = `https://github.com/AiCure/open_dbm/releases/tag/v${version}.0`;
|
||||
}
|
||||
|
||||
const releaseNotesLink = <a href={releaseNotesURL}>{releaseNotesTitle}</a>;
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<th>{versionName}</th>
|
||||
<td>{documentationLink}</td>
|
||||
<td>{releaseNotesLink}</td>
|
||||
</tr>
|
||||
);
|
||||
};
|
||||
|
||||
const Versions = () => {
|
||||
const currentVersion = versions.length > 0 ? versions[0] : null;
|
||||
const latestVersions = ['next'].concat(
|
||||
versions.filter(version => version.indexOf('-RC') !== -1)
|
||||
);
|
||||
const stableVersions = versions.filter(
|
||||
version => version.indexOf('-RC') === -1 && version !== currentVersion
|
||||
);
|
||||
|
||||
return (
|
||||
<Layout title="Versions" wrapperClassName="versions-page">
|
||||
<h1>OpenDBM versions</h1>
|
||||
<p>
|
||||
When we want to plan for a release, a new release candidate is created
|
||||
off the <code>master</code> branch of{' '}
|
||||
<a href={'https://github.com/AiCure/open_dbm'}>
|
||||
<code>AiCure/open_dbm</code>
|
||||
</a>
|
||||
. The release candidate will be online for some time to allow
|
||||
contributors like yourself to{' '}
|
||||
<a href={useBaseUrl('docs/upgrading')}>verify the changes</a> and to
|
||||
identify any issues by{' '}
|
||||
<a href="https://github.com/AiCure/open_dbm/issues">
|
||||
writing clear, actionable bug reports
|
||||
</a>
|
||||
. Eventually, the release candidate will be promoted to{' '}
|
||||
<code>master</code> .
|
||||
</p>
|
||||
|
||||
<h2>Latest version</h2>
|
||||
<p>
|
||||
The most recent stable version will be publish automatically whenever a
|
||||
new release tag is created using the{' '}
|
||||
<code>github git tag [new version]</code> command.
|
||||
</p>
|
||||
<table className="versions">
|
||||
<tbody>
|
||||
<VersionItem
|
||||
key={'version_' + currentVersion}
|
||||
version={currentVersion}
|
||||
currentVersion={currentVersion}
|
||||
/>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Previous versions</h2>
|
||||
<table className="versions">
|
||||
<tbody>
|
||||
{stableVersions.map(version => (
|
||||
<VersionItem
|
||||
key={'version_' + version}
|
||||
version={version}
|
||||
currentVersion={currentVersion}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Archived versions</h2>
|
||||
<p>
|
||||
The documentation for versions below <code>0.2.0</code> can be found on
|
||||
the separate docs word{' '}
|
||||
<a href="https://docs.google.com/document/d/1O6OUSY9FHFCZfpIWu3Kgg0Q_dyp073xjjQ2K3viEffU/edit#heading=h.ttfc0bhy0aif">
|
||||
in here
|
||||
</a>
|
||||
.
|
||||
</p>
|
||||
</Layout>
|
||||
);
|
||||
};
|
||||
|
||||
export default Versions;
|
||||
3
docs/website/src/theme/BlogSidebar/Desktop/index.d.ts
vendored
Normal file
3
docs/website/src/theme/BlogSidebar/Desktop/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/// <reference types="react" />
|
||||
import type { Props } from "@theme/BlogSidebar/Desktop";
|
||||
export default function BlogSidebarDesktop({ sidebar }: Props): JSX.Element;
|
||||
47
docs/website/src/theme/BlogSidebar/Desktop/index.js
Normal file
47
docs/website/src/theme/BlogSidebar/Desktop/index.js
Normal file
@@ -0,0 +1,47 @@
|
||||
import React from 'react';
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import {translate} from '@docusaurus/Translate';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
export default function BlogSidebarDesktop({sidebar}) {
|
||||
let cachedYear = null;
|
||||
return (
|
||||
<aside className="col col--3">
|
||||
<nav
|
||||
className={clsx(styles.sidebar, 'thin-scrollbar')}
|
||||
aria-label={translate({
|
||||
id: 'theme.blog.sidebar.navAriaLabel',
|
||||
message: 'Blog recent posts navigation',
|
||||
description: 'The ARIA label for recent posts in the blog sidebar',
|
||||
})}>
|
||||
<div className={clsx(styles.sidebarHeader, 'margin-bottom--md')}>
|
||||
{sidebar.title}
|
||||
</div>
|
||||
<ul className={clsx(styles.sidebarItemList, 'clean-list')}>
|
||||
{sidebar.items.map(item => {
|
||||
const postYear = item.permalink.split('/')[2];
|
||||
const yearHeader = cachedYear !== postYear && (
|
||||
<h5 className={styles.sidebarItemTitle}>{postYear}</h5>
|
||||
);
|
||||
cachedYear = postYear;
|
||||
return (
|
||||
<>
|
||||
{yearHeader}
|
||||
<li key={item.permalink} className={styles.sidebarItem}>
|
||||
<Link
|
||||
isNavLink
|
||||
to={item.permalink}
|
||||
className={styles.sidebarItemLink}
|
||||
activeClassName={styles.sidebarItemLinkActive}>
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</nav>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
60
docs/website/src/theme/BlogSidebar/Desktop/styles.module.css
Normal file
60
docs/website/src/theme/BlogSidebar/Desktop/styles.module.css
Normal file
@@ -0,0 +1,60 @@
|
||||
.sidebar {
|
||||
max-height: calc(100vh - (var(--ifm-navbar-height) + 2rem));
|
||||
overflow-y: auto;
|
||||
position: sticky;
|
||||
top: var(--ifm-navbar-height);
|
||||
padding: 20px 12px 0 0;
|
||||
margin-left: -20px;
|
||||
}
|
||||
|
||||
.sidebarHeader {
|
||||
font-size: var(--ifm-h4-font-size);
|
||||
font-weight: var(--ifm-font-weight-bold);
|
||||
padding-left: 12px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.sidebarItemTitle {
|
||||
margin: 0.75rem 0 0.5rem;
|
||||
color: var(--subtle);
|
||||
padding-left: 12px;
|
||||
border-bottom: 0.01rem solid var(--ifm-table-border-color);
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.sidebarItemList {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.sidebarItem {
|
||||
margin-top: 0.1rem;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.sidebarItemLink {
|
||||
color: var(--ifm-font-color-base);
|
||||
padding: 4px 8px;
|
||||
display: block;
|
||||
border-left: 4px solid transparent;
|
||||
border-radius: 0.25rem;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.sidebarItemLink:hover {
|
||||
background: var(--ifm-menu-color-background-active);
|
||||
color: var(--ifm-font-color-base);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.sidebarItemLinkActive {
|
||||
color: var(--ifm-font-color-base);
|
||||
background: var(--ifm-menu-color-background-active);
|
||||
border-left-color: var(--ifm-menu-color-active);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@media (max-width: 996px) {
|
||||
.sidebar {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
3
docs/website/src/theme/BlogSidebar/Mobile/index.d.ts
vendored
Normal file
3
docs/website/src/theme/BlogSidebar/Mobile/index.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/// <reference types="react" />
|
||||
import type { Props } from "@theme/BlogSidebar/Mobile";
|
||||
export default function BlogSidebarMobile(props: Props): JSX.Element;
|
||||
41
docs/website/src/theme/BlogSidebar/Mobile/index.js
Normal file
41
docs/website/src/theme/BlogSidebar/Mobile/index.js
Normal file
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import Link from '@docusaurus/Link';
|
||||
import {NavbarSecondaryMenuFiller} from '@docusaurus/theme-common';
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function BlogSidebarMobileSecondaryMenu({sidebar}) {
|
||||
let cachedYear = null;
|
||||
return (
|
||||
<ul className="menu__list blog-menu__list">
|
||||
{sidebar.items.map(item => {
|
||||
const postYear = item.permalink.split('/')[2];
|
||||
const yearHeader = cachedYear !== postYear && (
|
||||
<h5 className={styles.sidebarItemTitle}>{postYear}</h5>
|
||||
);
|
||||
cachedYear = postYear;
|
||||
return (
|
||||
<>
|
||||
{yearHeader}
|
||||
<li key={item.permalink} className="menu__list-item">
|
||||
<Link
|
||||
isNavLink
|
||||
to={item.permalink}
|
||||
className="menu__link"
|
||||
activeClassName="menu__link--active">
|
||||
{item.title}
|
||||
</Link>
|
||||
</li>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
export default function BlogSidebarMobile(props) {
|
||||
return (
|
||||
<NavbarSecondaryMenuFiller
|
||||
component={BlogSidebarMobileSecondaryMenu}
|
||||
props={props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
.sidebarItemTitle {
|
||||
margin: 0.75rem 0 0.5rem;
|
||||
color: var(--subtle);
|
||||
padding-left: 12px;
|
||||
border-bottom: 0.01rem solid var(--ifm-table-border-color);
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
18
docs/website/src/theme/DocItemFooter/index.js
Normal file
18
docs/website/src/theme/DocItemFooter/index.js
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Copyright (c) AiCure, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
import React from 'react';
|
||||
import DocItemFooterOriginal from '@theme-original/DocItemFooter';
|
||||
import DocsRating from '../../../core/DocsRating';
|
||||
|
||||
export default function DocItemFooter(props) {
|
||||
return (
|
||||
<>
|
||||
<DocsRating label={props.content.metadata.unversionedId} />
|
||||
<DocItemFooterOriginal {...props} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* Copyright (c) AiCure, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
import React from 'react';
|
||||
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
|
||||
import DropdownNavbarItem from '@theme/NavbarItem/DropdownNavbarItem';
|
||||
import {
|
||||
useVersions,
|
||||
useLatestVersion,
|
||||
useActiveDocContext,
|
||||
} from '@docusaurus/plugin-content-docs/client';
|
||||
import {useDocsPreferredVersion} from '@docusaurus/theme-common';
|
||||
import {translate} from '@docusaurus/Translate';
|
||||
|
||||
const getVersionMainDoc = version =>
|
||||
version.docs.find(doc => doc.id === version.mainDocId);
|
||||
|
||||
export default function DocsVersionDropdownNavbarItem({
|
||||
mobile,
|
||||
docsPluginId,
|
||||
dropdownActiveClassDisabled,
|
||||
dropdownItemsBefore,
|
||||
dropdownItemsAfter,
|
||||
...props
|
||||
}) {
|
||||
const activeDocContext = useActiveDocContext(docsPluginId);
|
||||
const versions = useVersions(docsPluginId);
|
||||
const latestVersion = useLatestVersion(docsPluginId);
|
||||
const {preferredVersion, savePreferredVersionName} =
|
||||
useDocsPreferredVersion(docsPluginId);
|
||||
|
||||
// (CUSTOM) Hide version dropdown on non-versioned pages
|
||||
if (!activeDocContext.activeDoc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// (CUSTOM) Show only `next` and last 5 versions in the dropdown
|
||||
const reducedVersions = versions.slice(0, 6);
|
||||
|
||||
function getItems() {
|
||||
const versionLinks = reducedVersions.map(version => {
|
||||
// We try to link to the same doc, in another version
|
||||
// When not possible, fallback to the "main doc" of the version
|
||||
const versionDoc =
|
||||
activeDocContext?.alternateDocVersions[version.name] ||
|
||||
getVersionMainDoc(version);
|
||||
return {
|
||||
isNavLink: true,
|
||||
label: version.label,
|
||||
to: versionDoc.path,
|
||||
isActive: () => version === activeDocContext?.activeVersion,
|
||||
onClick: () => {
|
||||
savePreferredVersionName(version.name);
|
||||
},
|
||||
};
|
||||
});
|
||||
return [...dropdownItemsBefore, ...versionLinks, ...dropdownItemsAfter];
|
||||
}
|
||||
|
||||
const items = getItems();
|
||||
const dropdownVersion =
|
||||
activeDocContext.activeVersion ?? preferredVersion ?? latestVersion; // Mobile dropdown is handled a bit differently
|
||||
|
||||
const dropdownLabel =
|
||||
mobile && items
|
||||
? translate({
|
||||
id: 'theme.navbar.mobileVersionsDropdown.label',
|
||||
message: 'Versions',
|
||||
description:
|
||||
'The label for the navbar versions dropdown on mobile view',
|
||||
})
|
||||
: dropdownVersion.label;
|
||||
const dropdownTo =
|
||||
mobile && items ? undefined : getVersionMainDoc(dropdownVersion).path; // We don't want to render a version dropdown with 0 or 1 item
|
||||
// If we build the site with a single docs version (onlyIncludeVersions: ['1.0.0'])
|
||||
// We'd rather render a button instead of a dropdown
|
||||
|
||||
if (items.length <= 1) {
|
||||
return (
|
||||
<DefaultNavbarItem
|
||||
{...props}
|
||||
mobile={mobile}
|
||||
label={dropdownLabel}
|
||||
to={dropdownTo}
|
||||
isActive={dropdownActiveClassDisabled ? () => false : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownNavbarItem
|
||||
{...props}
|
||||
mobile={mobile}
|
||||
label={dropdownLabel}
|
||||
to={dropdownTo}
|
||||
items={items}
|
||||
isActive={dropdownActiveClassDisabled ? () => false : undefined}
|
||||
/>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user