From f86630d49cb1da3d55dd3e793d441248caddd6c3 Mon Sep 17 00:00:00 2001 From: Adhita Selvaraj Date: Thu, 19 Jul 2018 15:35:53 -0700 Subject: [PATCH] check if katib is deployed and include it in CentralUI (#1242) --- components/centraldashboard/Dockerfile | 15 + components/centraldashboard/Gopkg.lock | 356 ++++++++++++++++++ components/centraldashboard/Gopkg.toml | 38 ++ .../centraldashboard/{frontend => }/Makefile | 3 +- components/centraldashboard/dashboard.go | 78 ++++ .../centraldashboard/frontend/Dockerfile | 8 - .../centraldashboard/frontend/dashboard.go | 19 - .../frontend/index/index.html | 1 + .../frontend/index/styles.css | 5 + .../frontend/layout/layout.html | 35 ++ .../frontend/layout/styles.css | 245 ++++++++++++ 11 files changed, 774 insertions(+), 29 deletions(-) create mode 100644 components/centraldashboard/Dockerfile create mode 100644 components/centraldashboard/Gopkg.lock create mode 100644 components/centraldashboard/Gopkg.toml rename components/centraldashboard/{frontend => }/Makefile (98%) create mode 100644 components/centraldashboard/dashboard.go delete mode 100644 components/centraldashboard/frontend/Dockerfile delete mode 100644 components/centraldashboard/frontend/dashboard.go create mode 100644 components/centraldashboard/frontend/layout/layout.html create mode 100644 components/centraldashboard/frontend/layout/styles.css diff --git a/components/centraldashboard/Dockerfile b/components/centraldashboard/Dockerfile new file mode 100644 index 00000000000..c2f876a8b14 --- /dev/null +++ b/components/centraldashboard/Dockerfile @@ -0,0 +1,15 @@ +FROM golang:1.10 AS builder + +# Download and install the latest release of dep +ADD https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 /usr/bin/dep +RUN chmod +x /usr/bin/dep + +# Copy the code from the host and compile it +WORKDIR $GOPATH/src/github.com/kubeflow/kubeflow/components/centraldashboard +COPY Gopkg.toml Gopkg.lock ./ +RUN dep ensure --vendor-only +COPY . ./ +ENV PORT_1=8082 +RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix nocgo -o app . +EXPOSE 8082 +ENTRYPOINT ["./app"] diff --git a/components/centraldashboard/Gopkg.lock b/components/centraldashboard/Gopkg.lock new file mode 100644 index 00000000000..a7896f8d79e --- /dev/null +++ b/components/centraldashboard/Gopkg.lock @@ -0,0 +1,356 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "cloud.google.com/go" + packages = ["compute/metadata"] + revision = "aad3f485ee528456e0768f20397b4d9dd941e755" + version = "v0.25.0" + +[[projects]] + name = "github.com/ghodss/yaml" + packages = ["."] + revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7" + version = "v1.0.0" + +[[projects]] + name = "github.com/gogo/protobuf" + packages = [ + "proto", + "sortkeys" + ] + revision = "1adfc126b41513cc696b209667c8656ea7aac67c" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/glog" + packages = ["."] + revision = "23def4e6c14b4da8ac2ed8007337bc5eb5007998" + +[[projects]] + name = "github.com/golang/protobuf" + packages = [ + "proto", + "ptypes", + "ptypes/any", + "ptypes/duration", + "ptypes/timestamp" + ] + revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265" + version = "v1.1.0" + +[[projects]] + branch = "master" + name = "github.com/google/btree" + packages = ["."] + revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4" + +[[projects]] + branch = "master" + name = "github.com/google/gofuzz" + packages = ["."] + revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1" + +[[projects]] + name = "github.com/googleapis/gnostic" + packages = [ + "OpenAPIv2", + "compiler", + "extensions" + ] + revision = "7c663266750e7d82587642f65e60bc4083f1f84e" + version = "v0.2.0" + +[[projects]] + branch = "master" + name = "github.com/gregjones/httpcache" + packages = [ + ".", + "diskcache" + ] + revision = "9cad4c3443a7200dd6400aef47183728de563a38" + +[[projects]] + name = "github.com/imdario/mergo" + packages = ["."] + revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58" + version = "v0.3.5" + +[[projects]] + name = "github.com/json-iterator/go" + packages = ["."] + revision = "ab8a2e0c74be9d3be70b3184d9acc634935ded82" + version = "1.1.4" + +[[projects]] + name = "github.com/modern-go/concurrent" + packages = ["."] + revision = "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" + version = "1.0.3" + +[[projects]] + name = "github.com/modern-go/reflect2" + packages = ["."] + revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd" + version = "1.0.1" + +[[projects]] + branch = "master" + name = "github.com/petar/GoLLRB" + packages = ["llrb"] + revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4" + +[[projects]] + name = "github.com/peterbourgon/diskv" + packages = ["."] + revision = "5f041e8faa004a95c88a202771f4cc3e991971e6" + version = "v2.0.1" + +[[projects]] + name = "github.com/spf13/pflag" + packages = ["."] + revision = "583c0c0531f06d5278b7d917446061adc344b5cd" + version = "v1.0.1" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["ssh/terminal"] + revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = [ + "context", + "context/ctxhttp", + "http/httpguts", + "http2", + "http2/hpack", + "idna" + ] + revision = "d0887baf81f4598189d4e12a37c6da86f0bba4d0" + +[[projects]] + branch = "master" + name = "golang.org/x/oauth2" + packages = [ + ".", + "google", + "internal", + "jws", + "jwt" + ] + revision = "ef147856a6ddbb60760db74283d2424e98c87bff" + +[[projects]] + branch = "master" + name = "golang.org/x/sys" + packages = [ + "unix", + "windows" + ] + revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2" + +[[projects]] + name = "golang.org/x/text" + packages = [ + "collate", + "collate/build", + "internal/colltab", + "internal/gen", + "internal/tag", + "internal/triegen", + "internal/ucd", + "language", + "secure/bidirule", + "transform", + "unicode/bidi", + "unicode/cldr", + "unicode/norm", + "unicode/rangetable" + ] + revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" + version = "v0.3.0" + +[[projects]] + branch = "master" + name = "golang.org/x/time" + packages = ["rate"] + revision = "fbb02b2291d28baffd63558aa44b4b56f178d650" + +[[projects]] + name = "google.golang.org/appengine" + packages = [ + ".", + "internal", + "internal/app_identity", + "internal/base", + "internal/datastore", + "internal/log", + "internal/modules", + "internal/remote_api", + "internal/urlfetch", + "urlfetch" + ] + revision = "b1f26356af11148e710935ed1ac8a7f5702c7612" + version = "v1.1.0" + +[[projects]] + name = "gopkg.in/inf.v0" + packages = ["."] + revision = "d2d2541c53f18d2a059457998ce2876cc8e67cbf" + version = "v0.9.1" + +[[projects]] + name = "gopkg.in/yaml.v2" + packages = ["."] + revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" + version = "v2.2.1" + +[[projects]] + branch = "master" + name = "k8s.io/api" + packages = [ + "admissionregistration/v1alpha1", + "admissionregistration/v1beta1", + "apps/v1", + "apps/v1beta1", + "apps/v1beta2", + "authentication/v1", + "authentication/v1beta1", + "authorization/v1", + "authorization/v1beta1", + "autoscaling/v1", + "autoscaling/v2beta1", + "batch/v1", + "batch/v1beta1", + "batch/v2alpha1", + "certificates/v1beta1", + "core/v1", + "events/v1beta1", + "extensions/v1beta1", + "networking/v1", + "policy/v1beta1", + "rbac/v1", + "rbac/v1alpha1", + "rbac/v1beta1", + "scheduling/v1alpha1", + "scheduling/v1beta1", + "settings/v1alpha1", + "storage/v1", + "storage/v1alpha1", + "storage/v1beta1" + ] + revision = "183f3326a9353bd6d41430fc80f96259331d029c" + +[[projects]] + name = "k8s.io/apimachinery" + packages = [ + "pkg/api/errors", + "pkg/api/meta", + "pkg/api/resource", + "pkg/apis/meta/v1", + "pkg/apis/meta/v1/unstructured", + "pkg/apis/meta/v1beta1", + "pkg/conversion", + "pkg/conversion/queryparams", + "pkg/fields", + "pkg/labels", + "pkg/runtime", + "pkg/runtime/schema", + "pkg/runtime/serializer", + "pkg/runtime/serializer/json", + "pkg/runtime/serializer/protobuf", + "pkg/runtime/serializer/recognizer", + "pkg/runtime/serializer/streaming", + "pkg/runtime/serializer/versioning", + "pkg/selection", + "pkg/types", + "pkg/util/clock", + "pkg/util/errors", + "pkg/util/framer", + "pkg/util/intstr", + "pkg/util/json", + "pkg/util/net", + "pkg/util/runtime", + "pkg/util/sets", + "pkg/util/validation", + "pkg/util/validation/field", + "pkg/util/wait", + "pkg/util/yaml", + "pkg/version", + "pkg/watch", + "third_party/forked/golang/reflect" + ] + revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae" + +[[projects]] + name = "k8s.io/client-go" + packages = [ + "discovery", + "kubernetes", + "kubernetes/scheme", + "kubernetes/typed/admissionregistration/v1alpha1", + "kubernetes/typed/admissionregistration/v1beta1", + "kubernetes/typed/apps/v1", + "kubernetes/typed/apps/v1beta1", + "kubernetes/typed/apps/v1beta2", + "kubernetes/typed/authentication/v1", + "kubernetes/typed/authentication/v1beta1", + "kubernetes/typed/authorization/v1", + "kubernetes/typed/authorization/v1beta1", + "kubernetes/typed/autoscaling/v1", + "kubernetes/typed/autoscaling/v2beta1", + "kubernetes/typed/batch/v1", + "kubernetes/typed/batch/v1beta1", + "kubernetes/typed/batch/v2alpha1", + "kubernetes/typed/certificates/v1beta1", + "kubernetes/typed/core/v1", + "kubernetes/typed/events/v1beta1", + "kubernetes/typed/extensions/v1beta1", + "kubernetes/typed/networking/v1", + "kubernetes/typed/policy/v1beta1", + "kubernetes/typed/rbac/v1", + "kubernetes/typed/rbac/v1alpha1", + "kubernetes/typed/rbac/v1beta1", + "kubernetes/typed/scheduling/v1alpha1", + "kubernetes/typed/scheduling/v1beta1", + "kubernetes/typed/settings/v1alpha1", + "kubernetes/typed/storage/v1", + "kubernetes/typed/storage/v1alpha1", + "kubernetes/typed/storage/v1beta1", + "pkg/apis/clientauthentication", + "pkg/apis/clientauthentication/v1alpha1", + "pkg/apis/clientauthentication/v1beta1", + "pkg/version", + "plugin/pkg/client/auth/exec", + "plugin/pkg/client/auth/gcp", + "rest", + "rest/watch", + "third_party/forked/golang/template", + "tools/auth", + "tools/clientcmd", + "tools/clientcmd/api", + "tools/clientcmd/api/latest", + "tools/clientcmd/api/v1", + "tools/metrics", + "tools/reference", + "transport", + "util/cert", + "util/connrotation", + "util/flowcontrol", + "util/homedir", + "util/integer", + "util/jsonpath" + ] + revision = "7d04d0e2a0a1a4d4a1cd6baa432a2301492e4e65" + version = "v8.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "a809ecb2810c12c9ddfa35eb4ed60eedf54c598c42bcbf717c3aa97c5b7fe287" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/components/centraldashboard/Gopkg.toml b/components/centraldashboard/Gopkg.toml new file mode 100644 index 00000000000..bee01f82706 --- /dev/null +++ b/components/centraldashboard/Gopkg.toml @@ -0,0 +1,38 @@ +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" +# +# [prune] +# non-go = false +# go-tests = true +# unused-packages = true + + +[[constraint]] + name = "k8s.io/apimachinery" + revision = "103fd098999dc9c0c88536f5c9ad2e5da39373ae" + +[[constraint]] + name = "k8s.io/client-go" + version = "8.0.0" + +[prune] + go-tests = true + unused-packages = true diff --git a/components/centraldashboard/frontend/Makefile b/components/centraldashboard/Makefile similarity index 98% rename from components/centraldashboard/frontend/Makefile rename to components/centraldashboard/Makefile index b8ec158b9f3..baa52797e72 100644 --- a/components/centraldashboard/frontend/Makefile +++ b/components/centraldashboard/Makefile @@ -3,7 +3,7 @@ IMG = gcr.io/kubeflow-images-public/centraldashboard # List any changed files. We only include files in the notebooks directory. # because that is the code in the docker image. # In particular we exclude changes to the ksonnet configs. -CHANGED_FILES := $(shell git diff-files --relative=components/centraldashboard/frontend) +CHANGED_FILES := $(shell git diff-files --relative=components/centraldashboard) ifeq ($(strip $(CHANGED_FILES)),) # Changed files is empty; not dirty @@ -27,7 +27,6 @@ build: @echo Built $(IMG):latest @echo Built $(IMG):$(TAG) - # Build but don't attach the latest tag. This allows manual testing/inspection of the image # first. push: build diff --git a/components/centraldashboard/dashboard.go b/components/centraldashboard/dashboard.go new file mode 100644 index 00000000000..25accd59fd6 --- /dev/null +++ b/components/centraldashboard/dashboard.go @@ -0,0 +1,78 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "os" + "regexp" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + + // Uncomment the following line to load the gcp plugin (only required to authenticate against GKE clusters). + _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" +) + +var ( + port = os.Getenv("PORT_1") +) + +// Call GetClient from client/manager.go to obtain Cluster configs. +// Use client info from GetClient to call SearchKatib from findservice/findservice.go. +// SearchKatib will return a boolean true if Katib is deployed. + +func main() { + + clientset := GetClient() + isKatibDeployed := SearchKatibPods(clientset) + + indexServer := http.FileServer(http.Dir("frontend/layout/")) + if isKatibDeployed { + indexServer = http.FileServer(http.Dir("frontend/index/")) + } + + http.Handle("/", indexServer) + log.Println("Listening on", ":"+port) + log.Fatal(http.ListenAndServe(":"+port, nil)) +} + +// GetClient gets client information +func GetClient() *kubernetes.Clientset { + config, err := rest.InClusterConfig() + if err != nil { + panic(err.Error()) + } + // creates the clientset + clientset, err := kubernetes.NewForConfig(config) + if err != nil { + panic(err.Error()) + } + + return clientset +} + +//SearchKatibPods searches across the cluster to see if Katib is deployed. +func SearchKatibPods(clientset *kubernetes.Clientset) bool { + + pods, err := clientset.CoreV1().Pods("").List(metav1.ListOptions{}) + if err != nil { + fmt.Printf("Error in regexp") + } + + katibpod := "vizier*" + r, err := regexp.Compile(katibpod) + + if err != nil { + fmt.Printf("There is a problem with your regexp.\n") + } + + for _, pod := range pods.Items { + if r.MatchString(pod.Name) == true { + fmt.Printf("Match found\npod namespace: %s\npod name: %s\n", pod.Namespace, pod.Name) + } + } + + return true +} diff --git a/components/centraldashboard/frontend/Dockerfile b/components/centraldashboard/frontend/Dockerfile deleted file mode 100644 index aa777a29ceb..00000000000 --- a/components/centraldashboard/frontend/Dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -# build prod -FROM golang:alpine -LABEL maintainer="Adhita Selvaraj " -WORKDIR /go/src/frontend -ADD . /go/src/frontend -ENV PORT_1=8082 -CMD [ "go", "run", "dashboard.go" ] -EXPOSE 8082 diff --git a/components/centraldashboard/frontend/dashboard.go b/components/centraldashboard/frontend/dashboard.go deleted file mode 100644 index 7d88e3cac64..00000000000 --- a/components/centraldashboard/frontend/dashboard.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "log" - "net/http" - "os" -) - -var ( - port = os.Getenv("PORT_1") -) - -func main() { - - indexServer := http.FileServer(http.Dir("index/")) - http.Handle("/", indexServer) - log.Println("Listening on", ":"+port) - log.Fatal(http.ListenAndServe(":"+port, nil)) -} diff --git a/components/centraldashboard/frontend/index/index.html b/components/centraldashboard/frontend/index/index.html index cdb094cd16a..e33ce4099fc 100644 --- a/components/centraldashboard/frontend/index/index.html +++ b/components/centraldashboard/frontend/index/index.html @@ -25,6 +25,7 @@

Kubeflow

JupyterHub TFJob Dashboard k8s Dashboard + Katib Dashboard
diff --git a/components/centraldashboard/frontend/index/styles.css b/components/centraldashboard/frontend/index/styles.css index 826c52d1fb3..bb7d67ff14a 100644 --- a/components/centraldashboard/frontend/index/styles.css +++ b/components/centraldashboard/frontend/index/styles.css @@ -16,6 +16,11 @@ html, body { margin-right: -15px !important; } +.isDisabled { + color: currentColor; + opacity: 0.5; +} + .navbar-right { float: right!important; } diff --git a/components/centraldashboard/frontend/layout/layout.html b/components/centraldashboard/frontend/layout/layout.html new file mode 100644 index 00000000000..3b0fac40929 --- /dev/null +++ b/components/centraldashboard/frontend/layout/layout.html @@ -0,0 +1,35 @@ + + + + + + + + + Kubeflow + + + + + + + + + + + + +
+
+ + diff --git a/components/centraldashboard/frontend/layout/styles.css b/components/centraldashboard/frontend/layout/styles.css new file mode 100644 index 00000000000..bb7d67ff14a --- /dev/null +++ b/components/centraldashboard/frontend/layout/styles.css @@ -0,0 +1,245 @@ +html, body { + font-family: 'Roboto', sans-serif; + margin: 0; + padding: 0; +} + +.navbar-collapse.collapse { + display: block!important; +} + +.navbar-nav>li, .navbar-nav { + float: left !important; +} + +.navbar-nav.navbar-right:last-child { + margin-right: -15px !important; +} + +.isDisabled { + color: currentColor; + opacity: 0.5; +} + +.navbar-right { + float: right!important; +} + +.mdl-demo .mdl-layout__header-row { + padding-left: 40px; +} +.mdl-demo .mdl-layout__tab-bar-button { + display: none; +} +.mdl-demo .mdl-layout.is-small-screen .mdl-layout__tab-bar .mdl-button { + display: none; +} +.mdl-demo .mdl-layout:not(.is-small-screen) .mdl-layout__tab-bar, +.mdl-demo .mdl-layout:not(.is-small-screen) .mdl-layout__tab-bar-container { + overflow: visible; +} +.mdl-demo .mdl-layout__tab-bar-container { + height: 64px; +} +.mdl-demo .mdl-layout__tab-bar { + padding: 0; + padding-left: 16px; + box-sizing: border-box; + height: 100%; + width: 100%; +} +.mdl-demo .mdl-layout__tab-bar .mdl-layout__tab { + height: 64px; + line-height: 64px; +} +.mdl-demo .mdl-layout__tab-bar .mdl-layout__tab.is-active::after { + background-color: white; + height: 4px; +} +.mdl-demo main > .mdl-layout__tab-panel { + padding: 8px; + padding-top: 48px; +} +.mdl-demo .mdl-card { + height: auto; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} +.mdl-demo .mdl-card > * { + height: auto; +} +.mdl-demo .mdl-card .mdl-card__supporting-text { + margin: 40px; + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + padding: 0; + color: inherit; + width: calc(100% - 80px); +} +.mdl-demo.mdl-demo .mdl-card__supporting-text h4 { + margin-top: 0; + margin-bottom: 20px; +} +.mdl-demo .mdl-card__actions { + margin: 0; + padding: 4px 40px; + color: inherit; +} +.mdl-demo .mdl-card__actions a { + color: #00BCD4; + margin: 0; +} +.mdl-demo .mdl-card__actions a:hover, +.mdl-demo .mdl-card__actions a:active { + color: inherit; + background-color: transparent; +} +.mdl-demo .mdl-card__supporting-text + .mdl-card__actions { + border-top: 1px solid rgba(0, 0, 0, 0.12); +} +.mdl-demo #add { + position: absolute; + right: 40px; + top: 36px; + z-index: 999; +} + +.button-holder { + text-align: justify +} + +.mdl-demo .mdl-layout__content section:not(:last-of-type) { + position: relative; + margin-bottom: 48px; +} +.mdl-demo section.section--center { + max-width: 860px; +} +.mdl-demo #features section.section--center1 { + max-width: 620px; +} +.mdl-demo section > header{ + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-justify-content: center; + -ms-flex-pack: center; + justify-content: center; +} +.mdl-demo section > .section__play-btn { + min-height: 200px; +} +.mdl-demo section > .section__input { + color: #00BCD4; +} +.mdl-demo section > header > .material-icons { + font-size: 3rem; +} +.mdl-demo section > button { + position: absolute; + z-index: 99; + top: 8px; + right: 8px; +} +.mdl-demo section .section__circle { + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-align-items: center; + -ms-flex-align: center; + align-items: center; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + -webkit-flex-grow: 0; + -ms-flex-positive: 0; + flex-grow: 0; + -webkit-flex-shrink: 1; + -ms-flex-negative: 1; + flex-shrink: 1; +} +.mdl-demo section .section__text { + -webkit-flex-grow: 1; + -ms-flex-positive: 1; + flex-grow: 1; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + padding-top: 8px; +} +.mdl-demo section .section__text h5 { + font-size: inherit; + margin: 0; + margin-bottom: 0.5em; +} +.mdl-demo section .section__text a { + text-decoration: none; +} +.mdl-demo section .section__circle-container > .section__circle-container__circle { + width: 64px; + height: 64px; + border-radius: 32px; + margin: 8px 0; +} +.mdl-demo .mdl-layout__tab .section__center { + margin: 50px; + align-items: center; +} +.mdl-demo section.section--footer .section__circle--big { + width: 100px; + height: 100px; + border-radius: 50px; + margin: 8px 32px; +} +.mdl-demo .is-small-screen section.section--footer .section__circle--big { + width: 50px; + height: 50px; + border-radius: 25px; + margin: 8px 16px; +} +.mdl-demo section.section--footer { + padding: 64px 0; + margin: 0 -8px -8px -8px; +} +.mdl-demo section.section--center .section__text:not(:last-child) { + border-bottom: 1px solid rgba(0,0,0,.13); +} + +.mdl-demo .mdl-layout__tab-panel { + background-color: white; + align-self: center; +} +.mdl-demo .toc { + border-left: 4px solid #C1EEF4; + margin: 24px; + padding: 0; + padding-left: 8px; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-flex-direction: column; + -ms-flex-direction: column; + flex-direction: column; +} +.mdl-demo .toc h4 { + font-size: 0.9rem; + margin-top: 0; +} +.mdl-demo .toc a { + color: #4DD0E1; + text-decoration: none; + font-size: 16px; + line-height: 28px; + display: block; +} +.mdl-demo .mdl-menu__container { + z-index: 99; +}