From ce1167291e8e610181ebe439d31c8dc921126013 Mon Sep 17 00:00:00 2001 From: Oliver Marks Date: Sat, 4 Nov 2023 07:45:12 +0000 Subject: [PATCH] Add drone file. --- .drone.yml | 70 +++++++ deps.edn | 8 + development/resources/public/css/styles.css | 104 +++++++--- development/src/design.cljs | 211 +++++++++++--------- tailwind.config.js | 3 + 5 files changed, 283 insertions(+), 113 deletions(-) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..4f7deef --- /dev/null +++ b/.drone.yml @@ -0,0 +1,70 @@ +kind: pipeline +name: default +steps: + + - name: fetch-npm-deps + image: node + commands: + - npm install + + - name: fetch-clojure-deps + pull: always + image: clojure:tools-deps + volumes: + - name: cache + path: /drone/cache/ + commands: + - ls -la /drone/cache/.m2 + - clojure -Sdeps '{:mvn/local-repo "/drone/cache/.m2/repository"}' -P -M:shadow-cljs-run + + - name: build-clojure + pull: always + image: clojure:tools-deps + volumes: + - name: cache + path: /drone/cache/ + commands: + - ls -la /drone/cache/.m2 + - clj -Sdeps '{:mvn/local-repo "/drone/cache/.m2/repository"}' -Mshadow-cljs-run release app --debug + + - name: deploy-site + pull: True + image: appleboy/drone-scp + depends_on: + - build-clojure + settings: + host: blog.digitaloctave.com + port: 22 + username: + from_secret: ssh_user + key: + from_secret: ssh_key + target: /var/www/portfolio/frontend/${DRONE_COMMIT_SHA:0:10}/ + source: /drone/src/development/resources/public/* + strip_components: 4 + + - name: promote-deployed-site + pull: True + image: appleboy/drone-ssh + depends_on: + - deploy-site + settings: + host: blog.digitaloctave.com + port: 22 + username: + from_secret: SSH_USER + key: + from_secret: SSH_KEY + port: 22 + command_timeout: 5m + script: + - cd /var/www/portfolio/ + - rm /var/www/portfolio/promoted + - ln -s /var/www/portfolio/${DRONE_COMMIT_SHA:0:10} /var/www/portfolio/promoted + depends_on: + - deploy-site + +volumes: + - name: cache + host: + path: /tmp/drone/cache/ diff --git a/deps.edn b/deps.edn index 7318d97..c56ae41 100644 --- a/deps.edn +++ b/deps.edn @@ -1,4 +1,5 @@ {:paths ["development/src"] + :deps {no.cjohansen/portfolio {:mvn/version "2023.07.15"}} :aliases {:dev {:extra-paths ["development/src" ] :extra-deps {org.clojure/clojure {:mvn/version "1.10.3"} org.clojure/tools.deps.alpha {:mvn/version "0.12.1003"} @@ -10,6 +11,13 @@ no.cjohansen/portfolio {:mvn/version "2023.07.15"} djblue/portal {:mvn/version "0.48.0"}}} + :shadow-cljs-run + {:extra-deps {thheller/shadow-cljs {:mvn/version "2.25.2"} + refactor-nrepl/refactor-nrepl {:mvn/version "3.9.0"} + cider/piggieback {:mvn/version "0.5.3"}} + :extra-paths ["dev"] + :main-opts ["-m" "shadow.cljs.devtools.cli"]} + :test {:extra-paths []} :poly {:main-opts ["-m" "polylith.clj.core.poly-cli.core"] diff --git a/development/resources/public/css/styles.css b/development/resources/public/css/styles.css index 042e781..303d82b 100644 --- a/development/resources/public/css/styles.css +++ b/development/resources/public/css/styles.css @@ -574,6 +574,10 @@ video { visibility: visible; } +.invisible { + visibility: hidden; +} + .collapse { visibility: collapse; } @@ -594,10 +598,6 @@ video { position: relative; } -.clear-both { - clear: both; -} - .m-2 { margin: 0.5rem; } @@ -606,8 +606,8 @@ video { margin: 1rem; } -.m-8 { - margin: 2rem; +.m-auto { + margin: auto; } .mb-12 { @@ -634,6 +634,10 @@ video { margin-left: 2rem; } +.mr-2 { + margin-right: 0.5rem; +} + .mr-4 { margin-right: 1rem; } @@ -642,6 +646,10 @@ video { margin-right: 2rem; } +.mt-8 { + margin-top: 2rem; +} + .block { display: block; } @@ -678,8 +686,8 @@ video { height: 6rem; } -.h-52 { - height: 13rem; +.h-64 { + height: 16rem; } .w-1\/2 { @@ -702,10 +710,6 @@ video { flex-grow: 1; } -.grow { - flex-grow: 1; -} - .skew-x-12 { --tw-skew-x: 12deg; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -723,16 +727,12 @@ video { resize: both; } -.grid-cols-2 { - grid-template-columns: repeat(2, minmax(0, 1fr)); -} - .flex-row { flex-direction: row; } -.gap-8 { - gap: 2rem; +.flex-col { + flex-direction: column; } .truncate { @@ -780,6 +780,14 @@ video { padding: 2rem; } +.pl-4 { + padding-left: 1rem; +} + +.pr-4 { + padding-right: 1rem; +} + .text-left { text-align: left; } @@ -788,6 +796,10 @@ video { text-align: right; } +.align-top { + vertical-align: top; +} + .align-middle { vertical-align: middle; } @@ -899,12 +911,58 @@ video { } } -@media (min-width: 640px) { - .sm\:grid-cols-3 { - grid-template-columns: repeat(3, minmax(0, 1fr)); +@media (min-width: 768px) { + .md\:visible { + visibility: visible; } - .sm\:gap-6 { - gap: 1.5rem; + .md\:m-8 { + margin: 2rem; + } + + .md\:ml-2 { + margin-left: 0.5rem; + } + + .md\:ml-8 { + margin-left: 2rem; + } + + .md\:mr-2 { + margin-right: 0.5rem; + } + + .md\:mr-8 { + margin-right: 2rem; + } + + .md\:block { + display: block; + } + + .md\:w-4\/5 { + width: 80%; + } + + .md\:w-full { + width: 100%; + } + + .md\:flex-row { + flex-direction: row; + } + + .md\:bg-hero-developer { + background-image: url('/img/dev-02.png'); + } + + .md\:text-base { + font-size: 1rem; + line-height: 1.5rem; + } + + .md\:text-lg { + font-size: 1.125rem; + line-height: 1.75rem; } } diff --git a/development/src/design.cljs b/development/src/design.cljs index ddaed5d..fc9360d 100644 --- a/development/src/design.cljs +++ b/development/src/design.cljs @@ -3,11 +3,10 @@ [portfolio.dumdom :as d] [portfolio.dom :as r])) - (defn left-bar [] - [:div.m-4.p-4.text-2xl - [:h1.mb-8 [:i.fa-solid.fa-gear.ml-4] "Oliver Marks - Software Engineer"] - [:p.m-8 "Example projects"]]) + [:div.m-4.text-2xl + [:h1.mt-8 [:i.fa-solid.fa-gear.mr-2] "Oliver Marks - Software Engineer"] + [:p.mt-8 "Example projects"]]) (defn right-bar [] [:div @@ -19,115 +18,149 @@ [:div.p-4.border-t-4.border-slate-900.w-full]]) (defn page-header [] - [:header.flex.mb-12 - (left-bar) - [:div.grow] - (right-bar)]) + [:header.mb-12 + [:div.flex.flex-col + (right-bar) + (left-bar) + ;[:div.grow] + ] + [:p.mt-8 "Software engineer with over 20 years of experience in various languages technology's see below for technologies and projects developed personally and Professionally"]]) - -(defn tile [{:keys [title direction image description]}] - [:div.rounded-lg.mb-8.h-52.w-full - [:img.rounded-lg.h-24.w-24.ml-4.mr-4 - {:src "https://img.theplantscape.com/api/image/missing.jpg?p=medium" - :align (if (= direction "right") "right" "left")}] - [:h3.text-xl title] - - [:p description]]) +(defn tile [{:keys [title href direction image description]}] + [:div.rounded-lg.mt-8.mb-8.w-full + [:a {:href href} + [:img.rounded-lg.h-24.w-24.md:ml-2.md:mr-2 + {:src "https://img.theplantscape.com/api/image/missing.jpg?p=medium" + :class (if (= direction "right") "ml-4" "mr-4") + :align (if (= direction "right") "right" "left")}] + [:h3.text-xl:md:text-base title] + [:p.text-sm description]]]) (defn skills-list [title skills] - [:div.mb-8 + [:div.mb-8.align-top [:h3.m-4.text-2xl title] (into [:ul] (mapv (fn skill-item [{:keys [direction icon skill]}] - (if (= direction "right") - [:li.m-2.text-xl [:span [:i.mr-4 {:class (str "devicon-" icon "-plain")}] skill]] - [:li.m-2.text-xl [:span skill [:i.ml-4 {:class (str "devicon-" icon "-plain")}]]])) + (if (= direction "right") + [:li.m-2.text-xl {:class "md:text-lg"} + [:span [:i.mr-4 {:class (str "devicon-" icon "-plain")}] skill]] + [:li.m-2.text-xl {:class "md:text-base"} + [:span skill [:i.ml-4 {:class (str "devicon-" icon "-plain")}]]])) skills))]) -(defn shaped-circle [direction w h] - (if (= direction "right") -[:div.clear-both.ml-8.opacity-50 {:style {:float "right" :right "0px" - :width (str w "px") :height (str h "px") - :background-color "#666666" - :border-radius (str w "px 0px 0px " w "px") - :shape-outside (str "circle(" w "px at " w "px " w "px)") }}] - [:div.clear-both.mr-8.opacity-50 {:style {:float "left" - :width (str w "px") :height (str h "px") - :background-color "#666666" - :border-radius (str "0px " w "px " w "px 0px") - :shape-outside (str "circle(" w "px at 0px " w "px)") }}]) - ) +(defn shaped-circle + ([direction w h] (shaped-circle direction w h 0)) + ([direction w h offset] + (if (= direction "right") + [:div.hidden.right {:class "md:block"} + [:div.ml-8.opacity-50 + {:style {:float "right" :right "0px" + :width (str w "px") :height (str h "px") + :background-color "#666666" + :border-radius (str w "px 0px 0px " w "px") + :shape-margin "20px"; + :shape-outside (str "circle(" w "px at " (+ w offset) "px " w "px)")}}]] + [:div.hidden.left {:class "md:block"} + [:div.mr-8.opacity-50 + {:style {:float "left" + :width (str w "px") :height (str h "px") + :background-color "#666666" + :border-radius (str "0px " w "px " w "px 0px") + :shape-margin "20px"; + :shape-outside (str "circle(" w "px at 0px " w "px)")}}]]))) (defn dual-column-circle [] - [:section.w-full.flex {:style {:background-image "url(/img/dev-01.png)" - :background-repeat "no-repeat" - :background-position "center top" - :background-size "800px 800px"}} - [:div.align-middle.relative.text-right {:class "w-1/2" :style {:width "50%"}} - #_[:div.ml-8.opacity-50 {:style {:float "right" :right "0px" :width "200px" :height "400px" :background-color "#666666" - :border-radius "200px 0px 0px 200px" - :shape-outside "circle(200px at 200px 200px)"}}] - (shaped-circle "right" "150" "300") - (shaped-circle "right" "250" "500") - (skills-list "Operations" - [{:icon "googlecloud" :skill "Google Cloud"} - {:icon "digitalocean" :skill "Digitalocean"} - {:icon "docker" :skill "Docker"} - {:icon "kubernetes" :skill "Kubernetes"}]) - (tile {:title "GASP Air quality sensor" + [:section.w-full + {:class "md:bg-hero-developer" + :style {;;:background-image "url(/img/dev-02.png)" + :background-repeat "no-repeat" + :background-position "center top" + :background-size "800px 800px"}} + [:div.flex.w-full ;.flex-col + [:div.relative {:class "w-1/2" :style {:width "50%"}} + [:div.align-middle.text-right.w-full.h-64 + (shaped-circle "right" 120 240 20) + (skills-list "Operations" + [{:icon "googlecloud" :skill "Google Cloud"} + {:icon "digitalocean" :skill "Digitalocean"} + {:icon "docker" :skill "Docker"} + {:icon "kubernetes" :skill "Kubernetes"}])]] + [:div.relative {:class "w-1/2" :style {:width "50%"}} + [:div.align-middle.relative.text-left.w-full.h-64 + (shaped-circle "left" 120 240) + (skills-list + "Development" + [{:direction "right" :icon "clojure" :skill "Clojure"} + {:direction "right" :icon "javascript" :skill "Javascript"} + {:direction "right" :icon "python" :skill "Python"} + {:direction "right" :icon "c" :skill "C / Arduino"} + #_{:direction "right" :icon "sql" :skill "SQL / Datalog"}])]]] + + [:div.flex.w-full.flex-col.md:flex-row;.mt-48 + [:div {:class "w-full"} + [:div.align-middle.relative.text-right.w-full + {:style {:top "-60px"}} + [:div.invisible {:class "md:visible"} + (shaped-circle "right" 225 450)] + [:div.flex.flex-col.w-half.md:w-full + (tile {:title "GASP Air quality sensor" + :direction "right" + :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" + :href "https://gasp.digitaloctave.com" + :description "Single page site, which display's data relayed via mqtt from a physical device."}) + (tile {:title "Image scaling & resizing" + :direction "right" + :href "https://images.digitaloctave.com/" + :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" + :description "API to upload image's and handle scaling to different sizes"})]]] + + [:div {:class "w-full"} + [:div.align-middle.relative.text-left.w-full + {:style {:top "-60px"}} + [:div.invisible {:class "md:visible"} + (shaped-circle "left" 225 450)] + [:div.flex.flex-col.w-half.md:w-full + (tile {:title "GASP Air quality sensor" + :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" + :href "https://gasp.digitaloctave.com" + :description "Single page site, which display's data relayed via mqtt from a physical device."}) + (tile {:title "theplantscape" + :href "https://theplantscape.com" + :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" + :description "Site for designing and planning gardens"})]]]] + + [:div.flex.flex-col + (tile {:title "Compare & Recycle" :direction "right" + :href "https://www.compareandrecycle.co.uk/" :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" :description "Single page site, which display's data relayed via mqtt from a physical device."}) - (tile {:title "Image scaling & resizing" + (tile {:title "Wolsely - Stock management system" :direction "right" - :href "https://images.digitaloctave.com/" + :href "https://www.wolseley.co.uk/" :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" - :description "API to upload image's and handle scaling to different sizes"}) - (tile {:title "Image scaling & resizing" - :direction "right" - - :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" - :description "API to upload image's and handle scaling to different sizes"}) - - ] - [:div.align-middle.relative.text-left {:class "w-1/2" :style {:width "50%"}} - (shaped-circle "left" "150" "300") - (shaped-circle "left" "250" "500") - - #_[:div.mr-8.opacity-50 {:style {:float "left" :width "200px" :height "400px" :background-color "#666666" - :border-radius "0px 200px 200px 0px" - :shape-outside "circle(220px at 0px 200px)"}}] - (skills-list - "Development" - [{:direction "right" :icon "clojure" :skill "Clojure"} - {:direction "right" :icon "javascript" :skill "Javascript"} - {:direction "right" :icon "python" :skill "Python"} - {:direction "right" :icon "c" :skill "C / Arduino"}]) - (tile {:title "GASP Air quality sensor" - :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" - :href "https://gasp.digitaloctave.com" :description "Single page site, which display's data relayed via mqtt from a physical device."}) - (tile {:title "theplantscape" - :href "https://theplantscape.com" + (tile {:title "Taylor & Francis - Stock Management system" + :direction "right" + :href "https://taylorandfrancis.com/" :image "https://img.theplantscape.com/api/image/missing.jpg?p=medium" - :description "Site for designing and planning gardens"})]]) + :description "Single page site, which display's data relayed via mqtt from a physical device."})]]) -(d/defscene circle - dual-column-circle - ) +(d/defscene circle + dual-column-circle) (defn footer-blocks [blocks] - (into [:div.m-8.grid.grid-cols-2.gap-8.sm:gap-6.sm:grid-cols-3] + (into [:div.md:m-8.w-full] (mapv (fn footer-block [{:keys [title children]}] - [:div [:h2.mb-6.text-sm.font-semibold.text-gray-900.uppercase.dark:text-white title] + [:div.ml-8.w-full [:h2.mb-6.text-sm.font-semibold.text-gray-900.uppercase.dark:text-white title] (into [:ul.text-gray-500.dark:text-gray-400.font-medium] (mapv (fn footer-link [{:keys [title link]}] [:li.mb-4 [:a.hover:underline {:href link} title]]) children))]) blocks))) (defn page-footer [] - [:section.m-8.flex.flex-row - [:img.rounded-full {:src "https://img.theplantscape.com/api/image/missing.jpg?p=medium"}] + [:section.md:m-8.flex.flex-row + [:img.rounded-full.w-24.h-24 {:src "https://img.theplantscape.com/api/image/missing.jpg?p=medium"}] (footer-blocks [{:title "Social / Contact Me" :children [{:link "https://matrix.to/#/#theplantscape.com:matrix.org" :title "Chat"} {:link "https://fo.llow.social/u/olymk2@mastodon.social" :title "Masterdon"}]}])]) @@ -138,16 +171,14 @@ (d/defscene footer page-footer) - (d/defscene page - [:div.bg-slate-200 - [:div {:class "m-4/5"} + [:div.bg-slate-200.w-full + [:div.w-full.m-auto.pl-4.pr-4 {:class "md:w-4/5"} (page-header) (dual-column-circle) (split-bar) (page-footer)]]) - (defn launch [] (ui/start! {:config {:css-paths ["/css/styles.css" diff --git a/tailwind.config.js b/tailwind.config.js index 8794d31..a660b2d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -2,6 +2,9 @@ module.exports = { content: ['./development/resources/public/**/*.{html,js}'], theme: { extend: { + backgroundImage: { + 'hero-developer': "url('/img/dev-02.png')", + }, colors: { 'tps-text': '#000000', background: '#f7f7f7',