├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml ├── stale.yml └── workflows │ └── ruby.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Gemfile ├── Gemfile.lock ├── LICENSE.md ├── README.md ├── Rakefile ├── SECURITY.md ├── app ├── assets │ ├── builds │ │ └── spina │ │ │ └── tailwind.css │ ├── config │ │ └── spina │ │ │ └── manifest.js │ ├── fonts │ │ └── spina │ │ │ ├── Metropolis-Black.woff2 │ │ │ ├── Metropolis-BlackItalic.woff2 │ │ │ ├── Metropolis-Bold.woff2 │ │ │ ├── Metropolis-BoldItalic.woff2 │ │ │ ├── Metropolis-ExtraBold.woff2 │ │ │ ├── Metropolis-ExtraBoldItalic.woff2 │ │ │ ├── Metropolis-ExtraLight.woff2 │ │ │ ├── Metropolis-ExtraLightItalic.woff2 │ │ │ ├── Metropolis-Light.woff2 │ │ │ ├── Metropolis-LightItalic.woff2 │ │ │ ├── Metropolis-Medium.woff2 │ │ │ ├── Metropolis-MediumItalic.woff2 │ │ │ ├── Metropolis-Regular.woff2 │ │ │ ├── Metropolis-RegularItalic.woff2 │ │ │ ├── Metropolis-SemiBold.woff2 │ │ │ ├── Metropolis-SemiBoldItalic.woff2 │ │ │ ├── Metropolis-Thin.woff2 │ │ │ └── Metropolis-ThinItalic.woff2 │ ├── icons │ │ ├── heroicons │ │ │ ├── mini │ │ │ │ ├── academic-cap.svg │ │ │ │ ├── adjustments-horizontal.svg │ │ │ │ ├── adjustments-vertical.svg │ │ │ │ ├── archive-box-arrow-down.svg │ │ │ │ ├── archive-box-x-mark.svg │ │ │ │ ├── archive-box.svg │ │ │ │ ├── arrow-down-circle.svg │ │ │ │ ├── arrow-down-left.svg │ │ │ │ ├── arrow-down-on-square-stack.svg │ │ │ │ ├── arrow-down-on-square.svg │ │ │ │ ├── arrow-down-right.svg │ │ │ │ ├── arrow-down-tray.svg │ │ │ │ ├── arrow-down.svg │ │ │ │ ├── arrow-left-circle.svg │ │ │ │ ├── arrow-left-on-rectangle.svg │ │ │ │ ├── arrow-left.svg │ │ │ │ ├── arrow-long-down.svg │ │ │ │ ├── arrow-long-left.svg │ │ │ │ ├── arrow-long-right.svg │ │ │ │ ├── arrow-long-up.svg │ │ │ │ ├── arrow-path.svg │ │ │ │ ├── arrow-right-circle.svg │ │ │ │ ├── arrow-right-on-rectangle.svg │ │ │ │ ├── arrow-right.svg │ │ │ │ ├── arrow-top-right-on-square.svg │ │ │ │ ├── arrow-trending-down.svg │ │ │ │ ├── arrow-trending-up.svg │ │ │ │ ├── arrow-up-circle.svg │ │ │ │ ├── arrow-up-left.svg │ │ │ │ ├── arrow-up-on-square-stack.svg │ │ │ │ ├── arrow-up-on-square.svg │ │ │ │ ├── arrow-up-right.svg │ │ │ │ ├── arrow-up-tray.svg │ │ │ │ ├── arrow-up.svg │ │ │ │ ├── arrow-uturn-down.svg │ │ │ │ ├── arrow-uturn-left.svg │ │ │ │ ├── arrow-uturn-right.svg │ │ │ │ ├── arrow-uturn-up.svg │ │ │ │ ├── arrows-pointing-in.svg │ │ │ │ ├── arrows-pointing-out.svg │ │ │ │ ├── arrows-right-left.svg │ │ │ │ ├── arrows-up-down.svg │ │ │ │ ├── at-symbol.svg │ │ │ │ ├── backspace.svg │ │ │ │ ├── backward.svg │ │ │ │ ├── banknotes.svg │ │ │ │ ├── bars-2.svg │ │ │ │ ├── bars-3-bottom-left.svg │ │ │ │ ├── bars-3-bottom-right.svg │ │ │ │ ├── bars-3-center-left.svg │ │ │ │ ├── bars-3.svg │ │ │ │ ├── bars-4.svg │ │ │ │ ├── bars-arrow-down.svg │ │ │ │ ├── bars-arrow-up.svg │ │ │ │ ├── beaker.svg │ │ │ │ ├── bell-alert.svg │ │ │ │ ├── bell-slash.svg │ │ │ │ ├── bell-snooze.svg │ │ │ │ ├── bell.svg │ │ │ │ ├── bolt-slash.svg │ │ │ │ ├── bolt.svg │ │ │ │ ├── book-open.svg │ │ │ │ ├── bookmark-slash.svg │ │ │ │ ├── bookmark-square.svg │ │ │ │ ├── bookmark.svg │ │ │ │ ├── briefcase.svg │ │ │ │ ├── building-library.svg │ │ │ │ ├── building-office-2.svg │ │ │ │ ├── building-office.svg │ │ │ │ ├── building-storefront.svg │ │ │ │ ├── cake.svg │ │ │ │ ├── calculator.svg │ │ │ │ ├── calendar-days.svg │ │ │ │ ├── calendar.svg │ │ │ │ ├── camera.svg │ │ │ │ ├── chart-bar-square.svg │ │ │ │ ├── chart-bar.svg │ │ │ │ ├── chart-pie.svg │ │ │ │ ├── chat-bubble-bottom-center-text.svg │ │ │ │ ├── chat-bubble-bottom-center.svg │ │ │ │ ├── chat-bubble-left-ellipsis.svg │ │ │ │ ├── chat-bubble-left-right.svg │ │ │ │ ├── chat-bubble-left.svg │ │ │ │ ├── chat-bubble-oval-left-ellipsis.svg │ │ │ │ ├── chat-bubble-oval-left.svg │ │ │ │ ├── check-badge.svg │ │ │ │ ├── check-circle.svg │ │ │ │ ├── check.svg │ │ │ │ ├── chevron-double-down.svg │ │ │ │ ├── chevron-double-left.svg │ │ │ │ ├── chevron-double-right.svg │ │ │ │ ├── chevron-double-up.svg │ │ │ │ ├── chevron-down.svg │ │ │ │ ├── chevron-left.svg │ │ │ │ ├── chevron-right.svg │ │ │ │ ├── chevron-up-down.svg │ │ │ │ ├── chevron-up.svg │ │ │ │ ├── circle-stack.svg │ │ │ │ ├── clipboard-document-check.svg │ │ │ │ ├── clipboard-document-list.svg │ │ │ │ ├── clipboard-document.svg │ │ │ │ ├── clipboard.svg │ │ │ │ ├── clock.svg │ │ │ │ ├── cloud-arrow-down.svg │ │ │ │ ├── cloud-arrow-up.svg │ │ │ │ ├── cloud.svg │ │ │ │ ├── code-bracket-square.svg │ │ │ │ ├── code-bracket.svg │ │ │ │ ├── cog-6-tooth.svg │ │ │ │ ├── cog-8-tooth.svg │ │ │ │ ├── cog.svg │ │ │ │ ├── command-line.svg │ │ │ │ ├── computer-desktop.svg │ │ │ │ ├── cpu-chip.svg │ │ │ │ ├── credit-card.svg │ │ │ │ ├── cube.svg │ │ │ │ ├── currency-dollar.svg │ │ │ │ ├── currency-euro.svg │ │ │ │ ├── currency-pound.svg │ │ │ │ ├── currency-rupee.svg │ │ │ │ ├── currency-yen.svg │ │ │ │ ├── cursor-arrow-rays.svg │ │ │ │ ├── cursor-arrow-ripple.svg │ │ │ │ ├── device-phone-mobile.svg │ │ │ │ ├── device-tablet.svg │ │ │ │ ├── document-arrow-down.svg │ │ │ │ ├── document-arrow-up.svg │ │ │ │ ├── document-chart-bar.svg │ │ │ │ ├── document-check.svg │ │ │ │ ├── document-duplicate.svg │ │ │ │ ├── document-magnifying-glass.svg │ │ │ │ ├── document-minus.svg │ │ │ │ ├── document-plus.svg │ │ │ │ ├── document-text.svg │ │ │ │ ├── document.svg │ │ │ │ ├── ellipsis-horizontal-circle.svg │ │ │ │ ├── ellipsis-horizontal.svg │ │ │ │ ├── ellipsis-vertical.svg │ │ │ │ ├── envelope-open.svg │ │ │ │ ├── envelope.svg │ │ │ │ ├── exclaimation-circle.svg │ │ │ │ ├── exclaimation-triangle.svg │ │ │ │ ├── exclamation-circle.svg │ │ │ │ ├── exclamation-triangle.svg │ │ │ │ ├── eye-slash.svg │ │ │ │ ├── eye.svg │ │ │ │ ├── face-frown.svg │ │ │ │ ├── face-smile.svg │ │ │ │ ├── film.svg │ │ │ │ ├── finger-print.svg │ │ │ │ ├── fire.svg │ │ │ │ ├── flag.svg │ │ │ │ ├── folder-arrow-down.svg │ │ │ │ ├── folder-minus.svg │ │ │ │ ├── folder-open.svg │ │ │ │ ├── folder-plus.svg │ │ │ │ ├── folder.svg │ │ │ │ ├── forward.svg │ │ │ │ ├── funnel.svg │ │ │ │ ├── gif.svg │ │ │ │ ├── gift-top.svg │ │ │ │ ├── gift.svg │ │ │ │ ├── globe-alt.svg │ │ │ │ ├── globe-americas.svg │ │ │ │ ├── globe-asia-australia.svg │ │ │ │ ├── globe-europe-africa.svg │ │ │ │ ├── hand-raised.svg │ │ │ │ ├── hand-thumb-down.svg │ │ │ │ ├── hand-thumb-up.svg │ │ │ │ ├── hashtag.svg │ │ │ │ ├── heart.svg │ │ │ │ ├── home-modern.svg │ │ │ │ ├── home.svg │ │ │ │ ├── identification.svg │ │ │ │ ├── inbox-arrow-down.svg │ │ │ │ ├── inbox-stack.svg │ │ │ │ ├── inbox.svg │ │ │ │ ├── information-circle.svg │ │ │ │ ├── key.svg │ │ │ │ ├── language.svg │ │ │ │ ├── lifebuoy.svg │ │ │ │ ├── light-bulb.svg │ │ │ │ ├── link.svg │ │ │ │ ├── list-bullet.svg │ │ │ │ ├── lock-closed.svg │ │ │ │ ├── lock-open.svg │ │ │ │ ├── magnifying-glass-circle.svg │ │ │ │ ├── magnifying-glass-minus.svg │ │ │ │ ├── magnifying-glass-plus.svg │ │ │ │ ├── magnifying-glass.svg │ │ │ │ ├── map-pin.svg │ │ │ │ ├── map.svg │ │ │ │ ├── megaphone.svg │ │ │ │ ├── microphone.svg │ │ │ │ ├── minus-circle.svg │ │ │ │ ├── minus.svg │ │ │ │ ├── moon.svg │ │ │ │ ├── musical-note.svg │ │ │ │ ├── newspaper.svg │ │ │ │ ├── no-symbol.svg │ │ │ │ ├── paper-airplane.svg │ │ │ │ ├── paper-clip.svg │ │ │ │ ├── pause.svg │ │ │ │ ├── pencil-square.svg │ │ │ │ ├── pencil.svg │ │ │ │ ├── phone-arrow-down-left.svg │ │ │ │ ├── phone-arrow-up-right.svg │ │ │ │ ├── phone-x-mark.svg │ │ │ │ ├── phone.svg │ │ │ │ ├── photo.svg │ │ │ │ ├── play-pause.svg │ │ │ │ ├── play.svg │ │ │ │ ├── plus-circle.svg │ │ │ │ ├── plus.svg │ │ │ │ ├── presentation-chart-bar.svg │ │ │ │ ├── presentation-chart-line.svg │ │ │ │ ├── printer.svg │ │ │ │ ├── puzzle-piece.svg │ │ │ │ ├── qr-code.svg │ │ │ │ ├── question-mark-circle.svg │ │ │ │ ├── queue-list.svg │ │ │ │ ├── radio.svg │ │ │ │ ├── receipt-percent.svg │ │ │ │ ├── receipt-refund.svg │ │ │ │ ├── rectangle-group.svg │ │ │ │ ├── rectangle-stack.svg │ │ │ │ ├── rss.svg │ │ │ │ ├── scale.svg │ │ │ │ ├── scissors.svg │ │ │ │ ├── server-stack.svg │ │ │ │ ├── server.svg │ │ │ │ ├── share.svg │ │ │ │ ├── shield-check.svg │ │ │ │ ├── shield-exclamation.svg │ │ │ │ ├── shopping-bag.svg │ │ │ │ ├── shopping-cart.svg │ │ │ │ ├── signal-slash.svg │ │ │ │ ├── signal.svg │ │ │ │ ├── sparkles.svg │ │ │ │ ├── speaker-wave.svg │ │ │ │ ├── speaker-x-mark.svg │ │ │ │ ├── square-2-stack.svg │ │ │ │ ├── squares-2x2.svg │ │ │ │ ├── squares-plus.svg │ │ │ │ ├── star.svg │ │ │ │ ├── stop.svg │ │ │ │ ├── sun.svg │ │ │ │ ├── swatch.svg │ │ │ │ ├── table-cells.svg │ │ │ │ ├── tag.svg │ │ │ │ ├── ticket.svg │ │ │ │ ├── trash.svg │ │ │ │ ├── truck.svg │ │ │ │ ├── user-circle.svg │ │ │ │ ├── user-group.svg │ │ │ │ ├── user-plus.svg │ │ │ │ ├── user.svg │ │ │ │ ├── users.svg │ │ │ │ ├── video-camera-slash.svg │ │ │ │ ├── video-camera.svg │ │ │ │ ├── view-columns.svg │ │ │ │ ├── wifi.svg │ │ │ │ ├── wrench-screwdriver.svg │ │ │ │ ├── wrench.svg │ │ │ │ ├── x-circle.svg │ │ │ │ └── x-mark.svg │ │ │ ├── outline │ │ │ │ ├── academic-cap.svg │ │ │ │ ├── adjustments-horizontal.svg │ │ │ │ ├── adjustments-vertical.svg │ │ │ │ ├── archive-box-arrow-down.svg │ │ │ │ ├── archive-box-x-mark.svg │ │ │ │ ├── archive-box.svg │ │ │ │ ├── arrow-down-circle.svg │ │ │ │ ├── arrow-down-left.svg │ │ │ │ ├── arrow-down-on-square-stack.svg │ │ │ │ ├── arrow-down-on-square.svg │ │ │ │ ├── arrow-down-right.svg │ │ │ │ ├── arrow-down-tray.svg │ │ │ │ ├── arrow-down.svg │ │ │ │ ├── arrow-left-circle.svg │ │ │ │ ├── arrow-left-on-rectangle.svg │ │ │ │ ├── arrow-left.svg │ │ │ │ ├── arrow-long-down.svg │ │ │ │ ├── arrow-long-left.svg │ │ │ │ ├── arrow-long-right.svg │ │ │ │ ├── arrow-long-up.svg │ │ │ │ ├── arrow-path.svg │ │ │ │ ├── arrow-right-circle.svg │ │ │ │ ├── arrow-right-on-rectangle.svg │ │ │ │ ├── arrow-right.svg │ │ │ │ ├── arrow-top-right-on-square.svg │ │ │ │ ├── arrow-trending-down.svg │ │ │ │ ├── arrow-trending-up.svg │ │ │ │ ├── arrow-up-circle.svg │ │ │ │ ├── arrow-up-left.svg │ │ │ │ ├── arrow-up-on-square-stack.svg │ │ │ │ ├── arrow-up-on-square.svg │ │ │ │ ├── arrow-up-right.svg │ │ │ │ ├── arrow-up-tray.svg │ │ │ │ ├── arrow-up.svg │ │ │ │ ├── arrow-uturn-down.svg │ │ │ │ ├── arrow-uturn-left.svg │ │ │ │ ├── arrow-uturn-right.svg │ │ │ │ ├── arrow-uturn-up.svg │ │ │ │ ├── arrows-pointing-in.svg │ │ │ │ ├── arrows-pointing-out.svg │ │ │ │ ├── arrows-right-left.svg │ │ │ │ ├── arrows-up-down.svg │ │ │ │ ├── at-symbol.svg │ │ │ │ ├── backspace.svg │ │ │ │ ├── backward.svg │ │ │ │ ├── banknotes.svg │ │ │ │ ├── bars-2.svg │ │ │ │ ├── bars-3-bottom-left.svg │ │ │ │ ├── bars-3-bottom-right.svg │ │ │ │ ├── bars-3-center-left.svg │ │ │ │ ├── bars-3.svg │ │ │ │ ├── bars-4.svg │ │ │ │ ├── bars-arrow-down.svg │ │ │ │ ├── bars-arrow-up.svg │ │ │ │ ├── beaker.svg │ │ │ │ ├── bell-alert.svg │ │ │ │ ├── bell-slash.svg │ │ │ │ ├── bell-snooze.svg │ │ │ │ ├── bell.svg │ │ │ │ ├── bolt-slash.svg │ │ │ │ ├── bolt.svg │ │ │ │ ├── book-open.svg │ │ │ │ ├── bookmark-slash.svg │ │ │ │ ├── bookmark-square.svg │ │ │ │ ├── bookmark.svg │ │ │ │ ├── briefcase.svg │ │ │ │ ├── building-library.svg │ │ │ │ ├── building-office-2.svg │ │ │ │ ├── building-office.svg │ │ │ │ ├── building-storefront.svg │ │ │ │ ├── cake.svg │ │ │ │ ├── calculator.svg │ │ │ │ ├── calendar-days.svg │ │ │ │ ├── calendar.svg │ │ │ │ ├── camera.svg │ │ │ │ ├── chart-bar-square.svg │ │ │ │ ├── chart-bar.svg │ │ │ │ ├── chart-pie.svg │ │ │ │ ├── chat-bubble-bottom-center-text.svg │ │ │ │ ├── chat-bubble-bottom-center.svg │ │ │ │ ├── chat-bubble-left-ellipsis.svg │ │ │ │ ├── chat-bubble-left-right.svg │ │ │ │ ├── chat-bubble-left.svg │ │ │ │ ├── chat-bubble-oval-left-ellipsis.svg │ │ │ │ ├── chat-bubble-oval-left.svg │ │ │ │ ├── check-badge.svg │ │ │ │ ├── check-circle.svg │ │ │ │ ├── check.svg │ │ │ │ ├── chevron-double-down.svg │ │ │ │ ├── chevron-double-left.svg │ │ │ │ ├── chevron-double-right.svg │ │ │ │ ├── chevron-double-up.svg │ │ │ │ ├── chevron-down.svg │ │ │ │ ├── chevron-left.svg │ │ │ │ ├── chevron-right.svg │ │ │ │ ├── chevron-up-down.svg │ │ │ │ ├── chevron-up.svg │ │ │ │ ├── circle-stack.svg │ │ │ │ ├── clipboard-document-check.svg │ │ │ │ ├── clipboard-document-list.svg │ │ │ │ ├── clipboard-document.svg │ │ │ │ ├── clipboard.svg │ │ │ │ ├── clock.svg │ │ │ │ ├── cloud-arrow-down.svg │ │ │ │ ├── cloud-arrow-up.svg │ │ │ │ ├── cloud.svg │ │ │ │ ├── code-bracket-square.svg │ │ │ │ ├── code-bracket.svg │ │ │ │ ├── cog-6-tooth.svg │ │ │ │ ├── cog-8-tooth.svg │ │ │ │ ├── cog.svg │ │ │ │ ├── command-line.svg │ │ │ │ ├── computer-desktop.svg │ │ │ │ ├── cpu-chip.svg │ │ │ │ ├── credit-card.svg │ │ │ │ ├── cube.svg │ │ │ │ ├── currency-dollar.svg │ │ │ │ ├── currency-euro.svg │ │ │ │ ├── currency-pound.svg │ │ │ │ ├── currency-rupee.svg │ │ │ │ ├── currency-yen.svg │ │ │ │ ├── cursor-arrow-rays.svg │ │ │ │ ├── cursor-arrow-ripple.svg │ │ │ │ ├── device-phone-mobile.svg │ │ │ │ ├── device-tablet.svg │ │ │ │ ├── document-arrow-down.svg │ │ │ │ ├── document-arrow-up.svg │ │ │ │ ├── document-chart-bar.svg │ │ │ │ ├── document-check.svg │ │ │ │ ├── document-duplicate.svg │ │ │ │ ├── document-magnifying-glass.svg │ │ │ │ ├── document-minus.svg │ │ │ │ ├── document-plus.svg │ │ │ │ ├── document-text.svg │ │ │ │ ├── document.svg │ │ │ │ ├── ellipsis-horizontal-circle.svg │ │ │ │ ├── ellipsis-horizontal.svg │ │ │ │ ├── ellipsis-vertical.svg │ │ │ │ ├── envelope-open.svg │ │ │ │ ├── envelope.svg │ │ │ │ ├── exclaimation-circle.svg │ │ │ │ ├── exclaimation-triangle.svg │ │ │ │ ├── exclamation-circle.svg │ │ │ │ ├── exclamation-triangle.svg │ │ │ │ ├── eye-slash.svg │ │ │ │ ├── eye.svg │ │ │ │ ├── face-frown.svg │ │ │ │ ├── face-smile.svg │ │ │ │ ├── film.svg │ │ │ │ ├── finger-print.svg │ │ │ │ ├── fire.svg │ │ │ │ ├── flag.svg │ │ │ │ ├── folder-arrow-down.svg │ │ │ │ ├── folder-minus.svg │ │ │ │ ├── folder-open.svg │ │ │ │ ├── folder-plus.svg │ │ │ │ ├── folder.svg │ │ │ │ ├── forward.svg │ │ │ │ ├── funnel.svg │ │ │ │ ├── gif.svg │ │ │ │ ├── gift-top.svg │ │ │ │ ├── gift.svg │ │ │ │ ├── globe-alt.svg │ │ │ │ ├── globe-americas.svg │ │ │ │ ├── globe-asia-australia.svg │ │ │ │ ├── globe-europe-africa.svg │ │ │ │ ├── hand-raised.svg │ │ │ │ ├── hand-thumb-down.svg │ │ │ │ ├── hand-thumb-up.svg │ │ │ │ ├── hashtag.svg │ │ │ │ ├── heart.svg │ │ │ │ ├── home-modern.svg │ │ │ │ ├── home.svg │ │ │ │ ├── identification.svg │ │ │ │ ├── inbox-arrow-down.svg │ │ │ │ ├── inbox-stack.svg │ │ │ │ ├── inbox.svg │ │ │ │ ├── information-circle.svg │ │ │ │ ├── key.svg │ │ │ │ ├── language.svg │ │ │ │ ├── lifebuoy.svg │ │ │ │ ├── light-bulb.svg │ │ │ │ ├── link.svg │ │ │ │ ├── list-bullet.svg │ │ │ │ ├── lock-closed.svg │ │ │ │ ├── lock-open.svg │ │ │ │ ├── magnifying-glass-circle.svg │ │ │ │ ├── magnifying-glass-minus.svg │ │ │ │ ├── magnifying-glass-plus.svg │ │ │ │ ├── magnifying-glass.svg │ │ │ │ ├── map-pin.svg │ │ │ │ ├── map.svg │ │ │ │ ├── megaphone.svg │ │ │ │ ├── microphone.svg │ │ │ │ ├── minus-circle.svg │ │ │ │ ├── minus.svg │ │ │ │ ├── moon.svg │ │ │ │ ├── musical-note.svg │ │ │ │ ├── newspaper.svg │ │ │ │ ├── no-symbol.svg │ │ │ │ ├── paper-airplane.svg │ │ │ │ ├── paper-clip.svg │ │ │ │ ├── pause.svg │ │ │ │ ├── pencil-square.svg │ │ │ │ ├── pencil.svg │ │ │ │ ├── phone-arrow-down-left.svg │ │ │ │ ├── phone-arrow-up-right.svg │ │ │ │ ├── phone-x-mark.svg │ │ │ │ ├── phone.svg │ │ │ │ ├── photo.svg │ │ │ │ ├── play-pause.svg │ │ │ │ ├── play.svg │ │ │ │ ├── plus-circle.svg │ │ │ │ ├── plus.svg │ │ │ │ ├── presentation-chart-bar.svg │ │ │ │ ├── presentation-chart-line.svg │ │ │ │ ├── printer.svg │ │ │ │ ├── puzzle-piece.svg │ │ │ │ ├── qr-code.svg │ │ │ │ ├── question-mark-circle.svg │ │ │ │ ├── queue-list.svg │ │ │ │ ├── radio.svg │ │ │ │ ├── receipt-percent.svg │ │ │ │ ├── receipt-refund.svg │ │ │ │ ├── rectangle-group.svg │ │ │ │ ├── rectangle-stack.svg │ │ │ │ ├── rss.svg │ │ │ │ ├── scale.svg │ │ │ │ ├── scissors.svg │ │ │ │ ├── server-stack.svg │ │ │ │ ├── server.svg │ │ │ │ ├── share.svg │ │ │ │ ├── shield-check.svg │ │ │ │ ├── shield-exclamation.svg │ │ │ │ ├── shopping-bag.svg │ │ │ │ ├── shopping-cart.svg │ │ │ │ ├── signal-slash.svg │ │ │ │ ├── signal.svg │ │ │ │ ├── sparkles.svg │ │ │ │ ├── speaker-wave.svg │ │ │ │ ├── speaker-x-mark.svg │ │ │ │ ├── square-2-stack.svg │ │ │ │ ├── squares-2x2.svg │ │ │ │ ├── squares-plus.svg │ │ │ │ ├── star.svg │ │ │ │ ├── stop.svg │ │ │ │ ├── sun.svg │ │ │ │ ├── swatch.svg │ │ │ │ ├── table-cells.svg │ │ │ │ ├── tag.svg │ │ │ │ ├── ticket.svg │ │ │ │ ├── trash.svg │ │ │ │ ├── truck.svg │ │ │ │ ├── user-circle.svg │ │ │ │ ├── user-group.svg │ │ │ │ ├── user-plus.svg │ │ │ │ ├── user.svg │ │ │ │ ├── users.svg │ │ │ │ ├── video-camera-slash.svg │ │ │ │ ├── video-camera.svg │ │ │ │ ├── view-columns.svg │ │ │ │ ├── wifi.svg │ │ │ │ ├── wrench-screwdriver.svg │ │ │ │ ├── wrench.svg │ │ │ │ ├── x-circle.svg │ │ │ │ └── x-mark.svg │ │ │ └── solid │ │ │ │ ├── academic-cap.svg │ │ │ │ ├── adjustments-horizontal.svg │ │ │ │ ├── adjustments-vertical.svg │ │ │ │ ├── archive-box-arrow-down.svg │ │ │ │ ├── archive-box-x-mark.svg │ │ │ │ ├── archive-box.svg │ │ │ │ ├── arrow-down-circle.svg │ │ │ │ ├── arrow-down-left.svg │ │ │ │ ├── arrow-down-on-square-stack.svg │ │ │ │ ├── arrow-down-on-square.svg │ │ │ │ ├── arrow-down-right.svg │ │ │ │ ├── arrow-down-tray.svg │ │ │ │ ├── arrow-down.svg │ │ │ │ ├── arrow-left-circle.svg │ │ │ │ ├── arrow-left-on-rectangle.svg │ │ │ │ ├── arrow-left.svg │ │ │ │ ├── arrow-long-down.svg │ │ │ │ ├── arrow-long-left.svg │ │ │ │ ├── arrow-long-right.svg │ │ │ │ ├── arrow-long-up.svg │ │ │ │ ├── arrow-path.svg │ │ │ │ ├── arrow-right-circle.svg │ │ │ │ ├── arrow-right-on-rectangle.svg │ │ │ │ ├── arrow-right.svg │ │ │ │ ├── arrow-top-right-on-square.svg │ │ │ │ ├── arrow-trending-down.svg │ │ │ │ ├── arrow-trending-up.svg │ │ │ │ ├── arrow-up-circle.svg │ │ │ │ ├── arrow-up-left.svg │ │ │ │ ├── arrow-up-on-square-stack.svg │ │ │ │ ├── arrow-up-on-square.svg │ │ │ │ ├── arrow-up-right.svg │ │ │ │ ├── arrow-up-tray.svg │ │ │ │ ├── arrow-up.svg │ │ │ │ ├── arrow-uturn-down.svg │ │ │ │ ├── arrow-uturn-left.svg │ │ │ │ ├── arrow-uturn-right.svg │ │ │ │ ├── arrow-uturn-up.svg │ │ │ │ ├── arrows-pointing-in.svg │ │ │ │ ├── arrows-pointing-out.svg │ │ │ │ ├── arrows-right-left.svg │ │ │ │ ├── arrows-up-down.svg │ │ │ │ ├── at-symbol.svg │ │ │ │ ├── backspace.svg │ │ │ │ ├── backward.svg │ │ │ │ ├── banknotes.svg │ │ │ │ ├── bars-2.svg │ │ │ │ ├── bars-3-bottom-left.svg │ │ │ │ ├── bars-3-bottom-right.svg │ │ │ │ ├── bars-3-center-left.svg │ │ │ │ ├── bars-3.svg │ │ │ │ ├── bars-4.svg │ │ │ │ ├── bars-arrow-down.svg │ │ │ │ ├── bars-arrow-up.svg │ │ │ │ ├── beaker.svg │ │ │ │ ├── bell-alert.svg │ │ │ │ ├── bell-slash.svg │ │ │ │ ├── bell-snooze.svg │ │ │ │ ├── bell.svg │ │ │ │ ├── bolt-slash.svg │ │ │ │ ├── bolt.svg │ │ │ │ ├── book-open.svg │ │ │ │ ├── bookmark-slash.svg │ │ │ │ ├── bookmark-square.svg │ │ │ │ ├── bookmark.svg │ │ │ │ ├── briefcase.svg │ │ │ │ ├── building-library.svg │ │ │ │ ├── building-office-2.svg │ │ │ │ ├── building-office.svg │ │ │ │ ├── building-storefront.svg │ │ │ │ ├── cake.svg │ │ │ │ ├── calculator.svg │ │ │ │ ├── calendar-days.svg │ │ │ │ ├── calendar.svg │ │ │ │ ├── camera.svg │ │ │ │ ├── chart-bar-square.svg │ │ │ │ ├── chart-bar.svg │ │ │ │ ├── chart-pie.svg │ │ │ │ ├── chat-bubble-bottom-center-text.svg │ │ │ │ ├── chat-bubble-bottom-center.svg │ │ │ │ ├── chat-bubble-left-ellipsis.svg │ │ │ │ ├── chat-bubble-left-right.svg │ │ │ │ ├── chat-bubble-left.svg │ │ │ │ ├── chat-bubble-oval-left-ellipsis.svg │ │ │ │ ├── chat-bubble-oval-left.svg │ │ │ │ ├── check-badge.svg │ │ │ │ ├── check-circle.svg │ │ │ │ ├── check.svg │ │ │ │ ├── chevron-double-down.svg │ │ │ │ ├── chevron-double-left.svg │ │ │ │ ├── chevron-double-right.svg │ │ │ │ ├── chevron-double-up.svg │ │ │ │ ├── chevron-down.svg │ │ │ │ ├── chevron-left.svg │ │ │ │ ├── chevron-right.svg │ │ │ │ ├── chevron-up-down.svg │ │ │ │ ├── chevron-up.svg │ │ │ │ ├── circle-stack.svg │ │ │ │ ├── clipboard-document-check.svg │ │ │ │ ├── clipboard-document-list.svg │ │ │ │ ├── clipboard-document.svg │ │ │ │ ├── clipboard.svg │ │ │ │ ├── clock.svg │ │ │ │ ├── cloud-arrow-down.svg │ │ │ │ ├── cloud-arrow-up.svg │ │ │ │ ├── cloud.svg │ │ │ │ ├── code-bracket-square.svg │ │ │ │ ├── code-bracket.svg │ │ │ │ ├── code-square.svg │ │ │ │ ├── code.svg │ │ │ │ ├── cog-6-tooth.svg │ │ │ │ ├── cog-8-tooth.svg │ │ │ │ ├── cog.svg │ │ │ │ ├── command-line.svg │ │ │ │ ├── computer-desktop.svg │ │ │ │ ├── cpu-chip.svg │ │ │ │ ├── credit-card.svg │ │ │ │ ├── cube.svg │ │ │ │ ├── currency-dollar.svg │ │ │ │ ├── currency-euro.svg │ │ │ │ ├── currency-pound.svg │ │ │ │ ├── currency-rupee.svg │ │ │ │ ├── currency-yen.svg │ │ │ │ ├── cursor-arrow-rays.svg │ │ │ │ ├── cursor-arrow-ripple.svg │ │ │ │ ├── device-phone-mobile.svg │ │ │ │ ├── device-tablet.svg │ │ │ │ ├── document-arrow-down.svg │ │ │ │ ├── document-arrow-up.svg │ │ │ │ ├── document-chart-bar.svg │ │ │ │ ├── document-check.svg │ │ │ │ ├── document-duplicate.svg │ │ │ │ ├── document-magnifying-glass.svg │ │ │ │ ├── document-minus.svg │ │ │ │ ├── document-plus.svg │ │ │ │ ├── document-text.svg │ │ │ │ ├── document.svg │ │ │ │ ├── ellipsis-horizontal-circle.svg │ │ │ │ ├── ellipsis-horizontal.svg │ │ │ │ ├── ellipsis-vertical.svg │ │ │ │ ├── envelope-open.svg │ │ │ │ ├── envelope.svg │ │ │ │ ├── exclaimation-circle.svg │ │ │ │ ├── exclaimation-triangle.svg │ │ │ │ ├── exclamation-circle.svg │ │ │ │ ├── exclamation-triangle.svg │ │ │ │ ├── eye-slash.svg │ │ │ │ ├── eye.svg │ │ │ │ ├── face-frown.svg │ │ │ │ ├── face-smile.svg │ │ │ │ ├── film.svg │ │ │ │ ├── finger-print.svg │ │ │ │ ├── fire.svg │ │ │ │ ├── flag.svg │ │ │ │ ├── folder-arrow-down.svg │ │ │ │ ├── folder-minus.svg │ │ │ │ ├── folder-open.svg │ │ │ │ ├── folder-plus.svg │ │ │ │ ├── folder.svg │ │ │ │ ├── forward.svg │ │ │ │ ├── funnel.svg │ │ │ │ ├── gif.svg │ │ │ │ ├── gift-top.svg │ │ │ │ ├── gift.svg │ │ │ │ ├── globe-alt.svg │ │ │ │ ├── globe-americas.svg │ │ │ │ ├── globe-asia-australia.svg │ │ │ │ ├── globe-europe-africa.svg │ │ │ │ ├── hand-raised.svg │ │ │ │ ├── hand-thumb-down.svg │ │ │ │ ├── hand-thumb-up.svg │ │ │ │ ├── hashtag.svg │ │ │ │ ├── heart.svg │ │ │ │ ├── home-modern.svg │ │ │ │ ├── home.svg │ │ │ │ ├── identification.svg │ │ │ │ ├── inbox-arrow-down.svg │ │ │ │ ├── inbox-stack.svg │ │ │ │ ├── inbox.svg │ │ │ │ ├── information-circle.svg │ │ │ │ ├── key.svg │ │ │ │ ├── language.svg │ │ │ │ ├── lifebuoy.svg │ │ │ │ ├── light-bulb.svg │ │ │ │ ├── link.svg │ │ │ │ ├── list-bullet.svg │ │ │ │ ├── lock-closed.svg │ │ │ │ ├── lock-open.svg │ │ │ │ ├── magnifying-glass-circle.svg │ │ │ │ ├── magnifying-glass-minus.svg │ │ │ │ ├── magnifying-glass-plus.svg │ │ │ │ ├── magnifying-glass.svg │ │ │ │ ├── map-pin.svg │ │ │ │ ├── map.svg │ │ │ │ ├── megaphone.svg │ │ │ │ ├── microphone.svg │ │ │ │ ├── minus-circle.svg │ │ │ │ ├── minus.svg │ │ │ │ ├── moon.svg │ │ │ │ ├── musical-note.svg │ │ │ │ ├── newspaper.svg │ │ │ │ ├── no-symbol.svg │ │ │ │ ├── paper-airplane.svg │ │ │ │ ├── paper-clip.svg │ │ │ │ ├── pause.svg │ │ │ │ ├── pencil-square.svg │ │ │ │ ├── pencil.svg │ │ │ │ ├── phone-arrow-down-left.svg │ │ │ │ ├── phone-arrow-up-right.svg │ │ │ │ ├── phone-x-mark.svg │ │ │ │ ├── phone.svg │ │ │ │ ├── photo.svg │ │ │ │ ├── play-pause.svg │ │ │ │ ├── play.svg │ │ │ │ ├── plus-circle.svg │ │ │ │ ├── plus.svg │ │ │ │ ├── presentation-chart-bar.svg │ │ │ │ ├── presentation-chart-line.svg │ │ │ │ ├── printer.svg │ │ │ │ ├── puzzle-piece.svg │ │ │ │ ├── qr-code.svg │ │ │ │ ├── question-mark-circle.svg │ │ │ │ ├── queue-list.svg │ │ │ │ ├── radio.svg │ │ │ │ ├── receipt-percent.svg │ │ │ │ ├── receipt-refund.svg │ │ │ │ ├── rectangle-group.svg │ │ │ │ ├── rectangle-stack.svg │ │ │ │ ├── rss.svg │ │ │ │ ├── scale.svg │ │ │ │ ├── scissors.svg │ │ │ │ ├── server-stack.svg │ │ │ │ ├── server.svg │ │ │ │ ├── share.svg │ │ │ │ ├── shield-check.svg │ │ │ │ ├── shield-exclamation.svg │ │ │ │ ├── shopping-bag.svg │ │ │ │ ├── shopping-cart.svg │ │ │ │ ├── signal-slash.svg │ │ │ │ ├── signal.svg │ │ │ │ ├── sparkles.svg │ │ │ │ ├── speaker-wave.svg │ │ │ │ ├── speaker-x-mark.svg │ │ │ │ ├── square-2-stack.svg │ │ │ │ ├── squares-2x2.svg │ │ │ │ ├── squares-plus.svg │ │ │ │ ├── star.svg │ │ │ │ ├── stop.svg │ │ │ │ ├── sun.svg │ │ │ │ ├── swatch.svg │ │ │ │ ├── table-cells.svg │ │ │ │ ├── tag.svg │ │ │ │ ├── ticket.svg │ │ │ │ ├── trash.svg │ │ │ │ ├── truck.svg │ │ │ │ ├── user-circle.svg │ │ │ │ ├── user-group.svg │ │ │ │ ├── user-plus.svg │ │ │ │ ├── user.svg │ │ │ │ ├── users.svg │ │ │ │ ├── video-camera-slash.svg │ │ │ │ ├── video-camera.svg │ │ │ │ ├── view-columns.svg │ │ │ │ ├── wifi.svg │ │ │ │ ├── wrench-screwdriver.svg │ │ │ │ ├── wrench.svg │ │ │ │ ├── x-circle.svg │ │ │ │ └── x-mark.svg │ │ └── spina │ │ │ ├── barchart.svg │ │ │ ├── bars.svg │ │ │ ├── bold.svg │ │ │ ├── brush.svg │ │ │ ├── camera.svg │ │ │ ├── caret-down.svg │ │ │ ├── caret-left.svg │ │ │ ├── caret-right.svg │ │ │ ├── caret-up.svg │ │ │ ├── cart.svg │ │ │ ├── chart-outline.svg │ │ │ ├── check.svg │ │ │ ├── chevron-down.svg │ │ │ ├── chevron-left.svg │ │ │ ├── chevron-right.svg │ │ │ ├── chevron-up.svg │ │ │ ├── code.svg │ │ │ ├── cog-outline.svg │ │ │ ├── cog.svg │ │ │ ├── comment.svg │ │ │ ├── cross.svg │ │ │ ├── customer-outline.svg │ │ │ ├── document.svg │ │ │ ├── dots.svg │ │ │ ├── exclamation.svg │ │ │ ├── export.svg │ │ │ ├── eye.svg │ │ │ ├── filter.svg │ │ │ ├── home.svg │ │ │ ├── image.svg │ │ │ ├── inbox-outline.svg │ │ │ ├── indent.svg │ │ │ ├── info.svg │ │ │ ├── italic.svg │ │ │ ├── large-check.svg │ │ │ ├── link.svg │ │ │ ├── list-ol.svg │ │ │ ├── list-ul.svg │ │ │ ├── list.svg │ │ │ ├── lock.svg │ │ │ ├── mail-outline.svg │ │ │ ├── mail.svg │ │ │ ├── media-library.svg │ │ │ ├── megaphone.svg │ │ │ ├── min.svg │ │ │ ├── outdent.svg │ │ │ ├── pages.svg │ │ │ ├── pencil-outline.svg │ │ │ ├── pencil.svg │ │ │ ├── picture-o.svg │ │ │ ├── plus.svg │ │ │ ├── power-off.svg │ │ │ ├── preview.svg │ │ │ ├── preview │ │ │ ├── icons_spina-preview.html │ │ │ └── ics_spina-preview.html │ │ │ ├── product-outline.svg │ │ │ ├── quote-right.svg │ │ │ ├── random.svg │ │ │ ├── redo.svg │ │ │ ├── refresh.svg │ │ │ ├── search.svg │ │ │ ├── shop.svg │ │ │ ├── social-outline.svg │ │ │ ├── strikethrough.svg │ │ │ ├── trash.svg │ │ │ ├── undo.svg │ │ │ ├── upload-outline.svg │ │ │ └── users-outline.svg │ ├── images │ │ └── spina │ │ │ ├── .gitkeep │ │ │ ├── favicon.png │ │ │ ├── spina.png │ │ │ └── spina.svg │ ├── javascripts │ │ └── spina │ │ │ ├── application.js │ │ │ ├── controllers │ │ │ ├── application.js │ │ │ ├── attachment_picker_controller.js │ │ │ ├── auto_file_upload_controller.js │ │ │ ├── autofocus_controller.js │ │ │ ├── button_controller.js │ │ │ ├── confetti_controller.js │ │ │ ├── confirm_controller.js │ │ │ ├── data_binding_controller.js │ │ │ ├── delegate_click_controller.js │ │ │ ├── editor_insert_images_controller.js │ │ │ ├── embed_controller.js │ │ │ ├── embed_tag_controller.js │ │ │ ├── exists_controller.js │ │ │ ├── form_controller.js │ │ │ ├── hotkeys_controller.js │ │ │ ├── image_collection_controller.js │ │ │ ├── image_fade_in_controller.js │ │ │ ├── index.js │ │ │ ├── infinite_scroll_controller.js │ │ │ ├── loading_button_controller.js │ │ │ ├── media_picker_controller.js │ │ │ ├── media_picker_modal_controller.js │ │ │ ├── modal_controller.js │ │ │ ├── navigation_controller.js │ │ │ ├── page_collapse_controller.js │ │ │ ├── page_select_controller.js │ │ │ ├── parent_pages_controller.js │ │ │ ├── repeater_controller.js │ │ │ ├── reveal_controller.js │ │ │ ├── select_controller.js │ │ │ ├── select_placeholder_controller.js │ │ │ ├── selectable_controller.js │ │ │ ├── shortcuts_controller.js │ │ │ ├── sortable_controller.js │ │ │ ├── switch_controller.js │ │ │ ├── tabs_controller.js │ │ │ ├── toggle_controller.js │ │ │ ├── trix_controller.js │ │ │ └── unique_id_controller.js │ │ │ └── libraries │ │ │ ├── canvas-confetti.js │ │ │ ├── canvas-confetti@1.3.2.js │ │ │ ├── debounce.js │ │ │ ├── hotkeys.js │ │ │ ├── hotkeys@3.8.7.js │ │ │ ├── sortablejs.js │ │ │ ├── sortablejs@1.13.0.js │ │ │ ├── trix.js │ │ │ └── trix@1.3.1.esm.js │ └── stylesheets │ │ └── spina │ │ ├── animate.css │ │ ├── application.tailwind.css │ │ ├── fonts-propshaft.css │ │ └── fonts-sprockets.css.erb ├── components │ └── spina │ │ ├── application_component.rb │ │ ├── forms │ │ ├── auto_file_upload_component.html.erb │ │ ├── auto_file_upload_component.rb │ │ ├── editor_insert_images_meta_component.html.erb │ │ ├── editor_insert_images_meta_component.rb │ │ ├── file_upload_component.html.erb │ │ ├── file_upload_component.rb │ │ ├── group_component.html.erb │ │ ├── group_component.rb │ │ ├── label_component.rb │ │ ├── password_field_component.html.erb │ │ ├── password_field_component.rb │ │ ├── search_component.html.erb │ │ ├── search_component.rb │ │ ├── switch_component.html.erb │ │ ├── switch_component.rb │ │ ├── text_field_component.html.erb │ │ ├── text_field_component.rb │ │ ├── trix_toolbar_component.html.erb │ │ └── trix_toolbar_component.rb │ │ ├── hooks │ │ ├── hook_component.rb │ │ └── partial_component.rb │ │ ├── main_navigation │ │ ├── link_component.html.erb │ │ ├── link_component.rb │ │ ├── sub_nav_component.html.erb │ │ └── sub_nav_component.rb │ │ ├── media_picker │ │ ├── image_component.html.erb │ │ ├── image_component.rb │ │ ├── modal_component.html.erb │ │ └── modal_component.rb │ │ ├── pages │ │ ├── actions_component.html.erb │ │ ├── actions_component.rb │ │ ├── list_component.html.erb │ │ ├── list_component.rb │ │ ├── location_component.html.erb │ │ ├── location_component.rb │ │ ├── new_page_button_component.html.erb │ │ ├── new_page_button_component.rb │ │ ├── page_component.html.erb │ │ ├── page_component.rb │ │ ├── page_select_component.html.erb │ │ ├── page_select_component.rb │ │ ├── tab_button_component.html.erb │ │ ├── tab_button_component.rb │ │ ├── translations_component.html.erb │ │ └── translations_component.rb │ │ └── user_interface │ │ ├── dropdown_button_component.rb │ │ ├── dropdown_component.html.erb │ │ ├── dropdown_component.rb │ │ ├── flash_message_component.html.erb │ │ ├── flash_message_component.rb │ │ ├── header_component.html.erb │ │ ├── header_component.rb │ │ ├── modal_component.html.erb │ │ ├── modal_component.rb │ │ ├── tab_link_component.html.erb │ │ ├── tab_link_component.rb │ │ ├── translations_component.html.erb │ │ └── translations_component.rb ├── controllers │ ├── concerns │ │ └── spina │ │ │ ├── api │ │ │ └── paginable.rb │ │ │ ├── current_spina_account.rb │ │ │ ├── current_theme.rb │ │ │ └── frontend.rb │ └── spina │ │ ├── admin │ │ ├── accounts_controller.rb │ │ ├── admin_controller.rb │ │ ├── attachments_controller.rb │ │ ├── embeds_controller.rb │ │ ├── images_controller.rb │ │ ├── layout_controller.rb │ │ ├── media_folders_controller.rb │ │ ├── media_picker_controller.rb │ │ ├── move_pages_controller.rb │ │ ├── navigation_items_controller.rb │ │ ├── navigations_controller.rb │ │ ├── page_select_options_controller.rb │ │ ├── page_translations_controller.rb │ │ ├── pages_controller.rb │ │ ├── parent_pages_controller.rb │ │ ├── password_resets_controller.rb │ │ ├── resource_select_options_controller.rb │ │ ├── resources_controller.rb │ │ ├── sessions_controller.rb │ │ ├── settings_controller.rb │ │ ├── theme_controller.rb │ │ └── users_controller.rb │ │ ├── api │ │ ├── api_controller.rb │ │ ├── images_controller.rb │ │ ├── navigations_controller.rb │ │ ├── pages_controller.rb │ │ └── resources_controller.rb │ │ ├── application_controller.rb │ │ ├── pages_controller.rb │ │ └── sitemaps_controller.rb ├── helpers │ └── spina │ │ ├── admin │ │ ├── icons_helper.rb │ │ ├── images_helper.rb │ │ └── pages_helper.rb │ │ ├── attachments_helper.rb │ │ ├── images_helper.rb │ │ ├── pages_helper.rb │ │ └── spina_helper.rb ├── jobs │ └── spina │ │ ├── application_job.rb │ │ ├── replace_signed_id_job.rb │ │ └── resource_pages_update_job.rb ├── mailers │ └── spina │ │ ├── application_mailer.rb │ │ └── user_mailer.rb ├── models │ ├── concerns │ │ └── spina │ │ │ ├── attachable.rb │ │ │ ├── gravatar.rb │ │ │ ├── partable.rb │ │ │ └── translated_content.rb │ └── spina │ │ ├── account.rb │ │ ├── application_record.rb │ │ ├── attachment.rb │ │ ├── current.rb │ │ ├── embeds │ │ ├── base.rb │ │ ├── button.rb │ │ ├── vimeo.rb │ │ └── youtube.rb │ │ ├── image.rb │ │ ├── media_folder.rb │ │ ├── navigation.rb │ │ ├── navigation_item.rb │ │ ├── page.rb │ │ ├── parts │ │ ├── attachment.rb │ │ ├── base.rb │ │ ├── image.rb │ │ ├── image_collection.rb │ │ ├── image_variant.rb │ │ ├── line.rb │ │ ├── multi_line.rb │ │ ├── option.rb │ │ ├── page_link.rb │ │ ├── repeater.rb │ │ ├── repeater_content.rb │ │ ├── resource_link.rb │ │ └── text.rb │ │ ├── resource.rb │ │ ├── rewrite_rule.rb │ │ ├── setting.rb │ │ └── user.rb ├── presenters │ └── spina │ │ ├── content_presenter.rb │ │ ├── menu_presenter.rb │ │ └── rich_text_presenter.rb ├── serializers │ └── spina │ │ └── api │ │ ├── base_serializer.rb │ │ ├── image_serializer.rb │ │ ├── navigation_serializer.rb │ │ ├── page_serializer.rb │ │ └── resource_serializer.rb └── views │ ├── layouts │ └── spina │ │ ├── admin │ │ ├── admin.html.erb │ │ ├── application.html.erb │ │ └── sessions.html.erb │ │ └── mail.html.erb │ └── spina │ ├── admin │ ├── accounts │ │ └── edit.html.erb │ ├── attachments │ │ ├── _attachment.html.erb │ │ ├── edit.html.erb │ │ ├── index.html.erb │ │ └── show.html.erb │ ├── embeds │ │ └── new.html.erb │ ├── images │ │ ├── _image.html.erb │ │ ├── edit.html.erb │ │ ├── index.html.erb │ │ ├── show.html.erb │ │ └── update.turbo_stream.erb │ ├── layout │ │ └── edit.html.erb │ ├── media_folders │ │ ├── _form.html.erb │ │ ├── _media_folder.html.erb │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── media_picker │ │ └── show.html.erb │ ├── move_pages │ │ └── new.html.erb │ ├── navigation_items │ │ ├── _form.html.erb │ │ ├── _navigation_item.html.erb │ │ ├── _page_form.html.erb │ │ ├── _url_form.html.erb │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── navigations │ │ ├── _navigation.html.erb │ │ ├── edit.html.erb │ │ └── index.html.erb │ ├── page_select_options │ │ ├── index.html.erb │ │ └── show.html.erb │ ├── pages │ │ ├── _button_advanced.html.erb │ │ ├── _button_page_content.html.erb │ │ ├── _button_search_engines.html.erb │ │ ├── _form.html.erb │ │ ├── _form_advanced.html.erb │ │ ├── _form_page_content.html.erb │ │ ├── _form_search_engines.html.erb │ │ ├── _new_page_form.html.erb │ │ ├── children.html.erb │ │ ├── edit.html.erb │ │ ├── edit_content.html.erb │ │ ├── edit_template.html.erb │ │ ├── index.html.erb │ │ ├── new.html.erb │ │ └── sort_one.turbo_stream.erb │ ├── parent_pages │ │ └── index.html.erb │ ├── parts │ │ ├── attachments │ │ │ ├── _attachment.html.erb │ │ │ └── _form.html.erb │ │ ├── image_collections │ │ │ ├── _fields.html.erb │ │ │ └── _form.html.erb │ │ ├── images │ │ │ └── _form.html.erb │ │ ├── lines │ │ │ └── _form.html.erb │ │ ├── multi_lines │ │ │ └── _form.html.erb │ │ ├── options │ │ │ └── _form.html.erb │ │ ├── page_links │ │ │ └── _form.html.erb │ │ ├── repeaters │ │ │ ├── _fields.html.erb │ │ │ └── _form.html.erb │ │ ├── resource_links │ │ │ └── _form.html.erb │ │ └── texts │ │ │ └── _form.html.erb │ ├── password_resets │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── resource_select_options │ │ ├── index.html.erb │ │ └── show.html.erb │ ├── resources │ │ └── edit.html.erb │ ├── sessions │ │ └── new.html.erb │ ├── settings │ │ ├── _string_field.html.erb │ │ ├── _text_field.html.erb │ │ ├── _wysiwyg_field.html.erb │ │ └── edit.html.erb │ ├── shared │ │ ├── _flash.html.erb │ │ ├── _navigation.html.erb │ │ └── _version.html.erb │ ├── theme │ │ └── edit.html.erb │ └── users │ │ ├── _form.html.erb │ │ ├── _user.html.erb │ │ ├── edit.html.erb │ │ ├── index.html.erb │ │ └── new.html.erb │ ├── embeds │ ├── buttons │ │ ├── _button.html.erb │ │ ├── _button_fields.html.erb │ │ └── _trix_button.html.erb │ ├── vimeos │ │ ├── _thumbnail.html.erb │ │ ├── _vimeo.html.erb │ │ └── _vimeo_fields.html.erb │ └── youtubes │ │ ├── _thumbnail.html.erb │ │ ├── _youtube.html.erb │ │ └── _youtube_fields.html.erb │ ├── sitemaps │ └── show.xml.builder │ └── user_mailer │ ├── forgot_password.html.erb │ └── forgot_password.text.erb ├── bin └── rails ├── config ├── initializers │ ├── importmap.rb │ └── yaml_column_permitted_classes.rb ├── locales │ ├── TH.yml │ ├── bg.yml │ ├── cs.yml │ ├── da.yml │ ├── de.yml │ ├── en.yml │ ├── es.yml │ ├── fr.yml │ ├── id.yml │ ├── it.yml │ ├── nl.yml │ ├── pl.yml │ ├── pt-BR.yml │ ├── ro.yml │ ├── ru.yml │ ├── sv.yml │ ├── tr.yml │ └── zh-CN.yml └── routes.rb ├── db ├── migrate │ ├── 10_create_spina_image_collections.rb │ ├── 11_create_spina_resources.rb │ ├── 12_add_url_title_to_spina_page_translations.rb │ ├── 13_add_json_attributes_to_spina_accounts.rb │ ├── 14_add_json_attributes_to_spina_pages.rb │ ├── 15_add_slug_to_spina_resources.rb │ ├── 16_add_ancestry_cache_columns_to_spina_pages.rb │ ├── 17_add_custom_urls_to_spina_navigation_items.rb │ ├── 18_change_default_spina_resources_slug.rb │ ├── 1_create_spina_tables.rb │ ├── 2_create_spina_translation_tables.rb │ ├── 3_create_spina_navigations.rb │ ├── 4_add_password_reset_token_to_spina_users.rb │ ├── 5_remove_translated_columns.rb │ ├── 6_create_spina_options.rb │ ├── 7_create_spina_settings.rb │ ├── 8_create_spina_media_folders.rb │ └── 9_create_spina_images.rb └── seeds.rb ├── docs ├── v1 │ ├── 0_introduction.md │ ├── 1_getting_started.md │ ├── 2_themes.md │ ├── advanced │ │ └── 1_svg_files.md │ ├── getting_help │ │ └── 1_support.md │ ├── getting_started │ │ ├── 1_installing_ruby.md │ │ ├── 2_install_spina.md │ │ └── 3_existing_project.md │ └── themes │ │ ├── 1_page_parts.md │ │ ├── 2_view_templates.md │ │ ├── 3_navigations.md │ │ ├── 4_custom_pages.md │ │ └── 5_resources.md └── v2 │ ├── 1_getting_started.md │ ├── 2_themes.md │ ├── 3_rendering_content.md │ ├── 4_api.md │ ├── 5_support.md │ ├── 6_advanced.md │ ├── advanced │ ├── 1_create_custom_parts.md │ ├── 2_svg_files.md │ ├── 3_authentication.md │ └── 4_tailwind.md │ ├── api │ ├── 1_enabling_the_api.md │ ├── 2_authentication.md │ ├── 3_pagination.md │ ├── 4_pages.md │ ├── 5_navigations.md │ ├── 6_resources.md │ └── 7_images.md │ ├── getting_started │ ├── 1_installing_ruby.md │ ├── 2_installing_spina.md │ ├── 3_existing_project.md │ ├── 4_upgrading.md │ ├── 5_caching_uploads.md │ └── 6_deploying.md │ ├── rendering_content │ ├── 10_resource_link.md │ ├── 1_line.md │ ├── 2_multi_line.md │ ├── 3_rich_text.md │ ├── 4_image.md │ ├── 5_image_collection.md │ ├── 6_attachment.md │ ├── 7_option.md │ ├── 8_repeating_content.md │ └── 9_page_link.md │ └── themes │ ├── 1_parts.md │ ├── 2_view_templates.md │ ├── 3_layout_parts.md │ ├── 4_navigations.md │ ├── 5_custom_pages.md │ └── 6_resources.md ├── lib ├── generators │ └── spina │ │ ├── embed_generator.rb │ │ ├── install_generator.rb │ │ ├── tailwind_config_generator.rb │ │ └── templates │ │ ├── app │ │ ├── assets │ │ │ └── config │ │ │ │ └── spina │ │ │ │ └── tailwind.config.js.tt │ │ ├── models │ │ │ └── spina │ │ │ │ └── embeds │ │ │ │ └── embed.rb.tt │ │ └── views │ │ │ ├── default │ │ │ ├── pages │ │ │ │ ├── homepage.html.erb │ │ │ │ └── show.html.erb │ │ │ └── shared │ │ │ │ └── _navigation.html.erb │ │ │ ├── demo │ │ │ ├── pages │ │ │ │ ├── demo.html.erb │ │ │ │ ├── homepage.html.erb │ │ │ │ └── show.html.erb │ │ │ └── shared │ │ │ │ ├── _languages.html.erb │ │ │ │ └── _navigation.html.erb │ │ │ ├── layouts │ │ │ ├── default │ │ │ │ └── application.html.erb │ │ │ └── demo │ │ │ │ └── application.html.erb │ │ │ └── spina │ │ │ └── embeds │ │ │ ├── _fields.html.erb │ │ │ └── _partial.html.erb │ │ └── config │ │ └── initializers │ │ ├── mobility.rb │ │ ├── spina.rb │ │ └── themes │ │ ├── default.rb │ │ └── demo.rb ├── spina.rb ├── spina │ ├── admin_sectionable.rb │ ├── attr_json_monkeypatch.rb │ ├── attr_json_spina_parts_model.rb │ ├── authentication │ │ ├── basic.rb │ │ └── sessions.rb │ ├── embeddable.rb │ ├── embeds.rb │ ├── embeds │ │ └── trix_conversion.rb │ ├── engine.rb │ ├── part.rb │ ├── plugin.rb │ ├── railtie.rb │ ├── theme.rb │ ├── theme_reloader.rb │ └── version.rb └── tasks │ ├── install.rake │ └── tailwind.rake ├── spina.gemspec └── test ├── application_system_test_case.rb ├── dummy ├── .ruby-version ├── Rakefile ├── app │ ├── assets │ │ ├── images │ │ │ ├── .keep │ │ │ └── spina │ │ │ │ └── view_template_previews │ │ │ │ └── show.png │ │ └── stylesheets │ │ │ ├── application.css │ │ │ └── demo │ │ │ └── application.css │ ├── channels │ │ └── application_cable │ │ │ ├── channel.rb │ │ │ └── connection.rb │ ├── controllers │ │ ├── application_controller.rb │ │ └── concerns │ │ │ └── .keep │ ├── helpers │ │ └── application_helper.rb │ ├── jobs │ │ └── application_job.rb │ ├── mailers │ │ └── application_mailer.rb │ ├── models │ │ ├── application_record.rb │ │ └── concerns │ │ │ └── .keep │ └── views │ │ ├── demo │ │ ├── pages │ │ │ ├── demo.html.erb │ │ │ ├── different_layout.html.erb │ │ │ ├── homepage.html.erb │ │ │ └── show.html.erb │ │ └── shared │ │ │ ├── _languages.html.erb │ │ │ └── _navigation.html.erb │ │ └── layouts │ │ ├── application.html.erb │ │ ├── demo │ │ ├── application.html.erb │ │ └── different_layout.html.erb │ │ ├── mailer.html.erb │ │ └── mailer.text.erb ├── bin │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── cable.yml │ ├── credentials.yml.enc │ ├── database.yml │ ├── database.yml.ci │ ├── environment.rb │ ├── environments │ │ ├── development.rb │ │ ├── production.rb │ │ └── test.rb │ ├── initializers │ │ ├── application_controller_renderer.rb │ │ ├── assets.rb │ │ ├── backtrace_silencers.rb │ │ ├── content_security_policy.rb │ │ ├── cookies_serializer.rb │ │ ├── feature_policy.rb │ │ ├── filter_parameter_logging.rb │ │ ├── inflections.rb │ │ ├── mime_types.rb │ │ ├── mobility.rb │ │ ├── new_framework_defaults_8_0.rb │ │ ├── spina.rb │ │ ├── svg.rb │ │ ├── themes │ │ │ ├── default.rb │ │ │ └── demo.rb │ │ └── wrap_parameters.rb │ ├── locales │ │ └── en.yml │ ├── master.key │ ├── puma.rb │ ├── routes.rb │ ├── spring.rb │ └── storage.yml ├── db │ └── schema.rb ├── lib │ └── assets │ │ └── .keep ├── log │ └── .keep └── public │ ├── 400.html │ ├── 404.html │ ├── 406-unsupported-browser.html │ ├── 422.html │ ├── 500.html │ ├── apple-touch-icon-precomposed.png │ ├── apple-touch-icon.png │ ├── favicon.ico │ ├── icon.png │ ├── icon.svg │ └── robots.txt ├── factories ├── accounts.rb ├── media_folder.rb ├── navigation.rb ├── page │ └── translations.rb ├── pages.rb ├── parts.rb ├── resources.rb └── users.rb ├── fixtures └── files │ └── spina.png ├── functional └── spina │ ├── admin │ ├── sessions_controller_test.rb │ └── settings_controller_test.rb │ └── pages_controller_test.rb ├── integration └── spina │ ├── admin │ ├── accounts_test.rb │ ├── attachments_test.rb │ ├── images_test.rb │ ├── login_test.rb │ ├── logout_test.rb │ ├── media_folders_test.rb │ ├── media_picker_test.rb │ ├── navigations_test.rb │ ├── pages_test.rb │ ├── password_resets_test.rb │ ├── resources_test.rb │ └── users_test.rb │ ├── api │ ├── images_test.rb │ ├── navigations_test.rb │ ├── pages_test.rb │ └── resources_test.rb │ ├── authentication │ ├── basic_authentication_test.rb │ ├── custom_authentication_test.rb │ └── session_authentication_test.rb │ ├── pages_test.rb │ ├── plugin_test.rb │ └── sitemaps_test.rb ├── mailers └── previews │ └── spina │ └── user_mailer_preview.rb ├── models └── spina │ ├── account_test.rb │ ├── navigation_item_test.rb │ ├── page_test.rb │ └── part_test.rb ├── system └── spina │ └── admin │ ├── editing_pages_test.rb │ ├── editing_resources_test.rb │ └── searching_media_library_test.rb ├── test_helper.rb └── unit └── spina └── theme_reloader_test.rb /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # Sponsorship through Open Collective 2 | 3 | open_collective: spina 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Context 2 | 3 | ### Changes proposed in this pull request 4 | 5 | ### Guidance to review 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /app/assets/config/spina/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../../images/spina 2 | //= link_tree ../../fonts/spina 3 | 4 | //= link_directory ../../javascripts/spina/controllers 5 | //= link_directory ../../javascripts/spina/libraries 6 | 7 | //= link spina/animate.css 8 | //= link spina/fonts-sprockets.css 9 | //= link spina/tailwind.css 10 | 11 | //= link spina/application.js 12 | -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-Black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-Black.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-BlackItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-BlackItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-Bold.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-BoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-BoldItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-ExtraBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-ExtraBold.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-ExtraBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-ExtraBoldItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-ExtraLight.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-ExtraLight.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-ExtraLightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-ExtraLightItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-Light.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-LightItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-LightItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-Medium.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-MediumItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-MediumItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-Regular.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-RegularItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-RegularItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-SemiBold.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-SemiBoldItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-SemiBoldItalic.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-Thin.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-Thin.woff2 -------------------------------------------------------------------------------- /app/assets/fonts/spina/Metropolis-ThinItalic.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/fonts/spina/Metropolis-ThinItalic.woff2 -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/archive-box.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-down-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-down-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-down-on-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-down-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-long-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-long-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-long-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-long-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-right-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-up-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-up-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-up-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-uturn-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-uturn-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-uturn-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/arrow-uturn-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/at-symbol.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/backward.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bars-2.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bars-3-bottom-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bars-3-bottom-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bars-3-center-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bars-3.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bolt.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bookmark-slash.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bookmark-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/bookmark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/camera.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/chart-pie.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/chat-bubble-oval-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/check-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/check.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/chevron-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/clock.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/cloud-arrow-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/cloud.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/cube.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/device-tablet.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/document-minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/document.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/ellipsis-horizontal-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/ellipsis-horizontal.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/ellipsis-vertical.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/envelope.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/exclaimation-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/exclamation-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/flag.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/forward.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/hand-raised.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/home.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/key.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/lock-closed.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/lock-open.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/magnifying-glass-circle.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/magnifying-glass-minus.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/magnifying-glass.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/microphone.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/minus-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/moon.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/no-symbol.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/paper-airplane.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/pause.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/pencil.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/play.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/plus-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/plus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/question-mark-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/queue-list.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/share.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/square-2-stack.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/stop.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/tag.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/user-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/user-plus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/user.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/video-camera.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/view-columns.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/x-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/mini/x-mark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-down-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-down-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-down-on-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-down-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-down-tray.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-left-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-left-on-rectangle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-long-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-long-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-long-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-long-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-right-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-right-on-rectangle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-top-right-on-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-trending-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-trending-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-up-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-up-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-up-on-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-up-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-up-tray.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-uturn-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-uturn-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-uturn-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrow-uturn-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrows-pointing-in.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrows-pointing-out.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrows-right-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/arrows-up-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/at-symbol.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-2.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-3-bottom-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-3-bottom-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-3-center-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-3.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-4.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-arrow-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bars-arrow-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bolt-slash.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bolt.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bookmark-slash.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bookmark-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/bookmark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/building-library.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/building-office.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chart-bar-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chart-pie.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/check-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/check.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-double-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-double-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-double-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-double-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-up-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/chevron-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/clock.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/cloud-arrow-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/cloud-arrow-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/cloud.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/code-bracket-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/code-bracket.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/command-line.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/credit-card.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/cube.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/currency-euro.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/currency-rupee.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/currency-yen.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/cursor-arrow-rays.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/cursor-arrow-ripple.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/device-phone-mobile.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/device-tablet.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/ellipsis-horizontal.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/ellipsis-vertical.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/exclaimation-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/exclaimation-triangle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/exclamation-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/exclamation-triangle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/flag.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/folder-minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/hashtag.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/heart.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/information-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/key.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/link.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/lock-closed.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/lock-open.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/magnifying-glass-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/magnifying-glass-minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/magnifying-glass-plus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/magnifying-glass.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/map-pin.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/microphone.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/minus-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/moon.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/no-symbol.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/paper-airplane.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/paper-clip.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/pause.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/pencil.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/play-pause.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/play.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/plus-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/plus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/queue-list.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/rss.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/stop.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/sun.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/user-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/user.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/video-camera.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/view-columns.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/wifi.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/x-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/outline/x-mark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-down-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-down-on-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-down-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-long-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-long-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-long-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-long-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-up-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-up-on-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-up-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-uturn-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-uturn-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-uturn-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/arrow-uturn-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/backward.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bars-2.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bars-3-bottom-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bars-3-bottom-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bars-3-center-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bars-3.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bolt.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bookmark-slash.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bookmark-square.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/bookmark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/check-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/check.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/chevron-double-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/chevron-down.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/chevron-left.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/chevron-right.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/chevron-up.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/clock.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/cloud.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/cube.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/ellipsis-horizontal.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/ellipsis-vertical.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/envelope.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/exclaimation-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/exclamation-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/folder-minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/folder.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/forward.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/lock-closed.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/lock-open.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/magnifying-glass.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/minus-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/minus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/moon.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/paper-airplane.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/pause.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/pencil.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/play.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/plus-circle.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/plus.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/queue-list.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/share.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/square-2-stack.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/stop.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/user.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/video-camera.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/view-columns.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/heroicons/solid/x-mark.svg: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/assets/icons/spina/bars.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/bold.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/caret-down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/caret-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/caret-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/caret-up.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/chevron-down.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/chevron-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/chevron-right.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/chevron-up.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/comment.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/image.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/italic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/icons/spina/lock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/assets/icons/spina/redo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/spina/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/images/spina/.gitkeep -------------------------------------------------------------------------------- /app/assets/images/spina/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/images/spina/favicon.png -------------------------------------------------------------------------------- /app/assets/images/spina/spina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/app/assets/images/spina/spina.png -------------------------------------------------------------------------------- /app/assets/javascripts/spina/application.js: -------------------------------------------------------------------------------- 1 | import "@hotwired/turbo-rails" 2 | import "libraries/trix" 3 | import "controllers" 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/application.js: -------------------------------------------------------------------------------- 1 | import { Application } from "@hotwired/stimulus" 2 | 3 | const application = Application.start() 4 | 5 | // Configure Stimulus 6 | application.warnings = true 7 | application.debug = false 8 | window.Stimulus = application 9 | 10 | export { application } 11 | 12 | -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/autofocus_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | 5 | connect() { 6 | this.element.focus() 7 | } 8 | 9 | } -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/delegate_click_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | 5 | click() { 6 | this.targetElement.click() 7 | } 8 | 9 | get targetElement() { 10 | return document.querySelector(this.element.dataset.delegateClickTarget) 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/exists_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | 5 | connect() { 6 | const event = document.createEvent("CustomEvent") 7 | event.initCustomEvent("exists", true, true, null) 8 | this.element.dispatchEvent(event) 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/index.js: -------------------------------------------------------------------------------- 1 | import { application } from "controllers/application" 2 | 3 | // Eager load all Stimulus controllers 4 | import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading" 5 | eagerLoadControllersFrom("controllers", application) 6 | -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/page_select_controller.js: -------------------------------------------------------------------------------- 1 | import SelectController from 'controllers/select_controller' 2 | 3 | export default class extends SelectController { } 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/shortcuts_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | static get targets() { 5 | return [ "confirm" ] 6 | } 7 | 8 | connect() { 9 | } 10 | 11 | confirmClick(event) { 12 | if (event.key === 'Enter') this.confirmTarget.click() 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /app/assets/javascripts/spina/controllers/toggle_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | static get targets() { 5 | return [ "container" ] 6 | } 7 | 8 | toggle() { 9 | this.containerTarget.classList.toggle('hidden') 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /app/assets/javascripts/spina/libraries/canvas-confetti.js: -------------------------------------------------------------------------------- 1 | export { default } from "libraries/canvas-confetti@1.3.2" 2 | -------------------------------------------------------------------------------- /app/assets/javascripts/spina/libraries/hotkeys.js: -------------------------------------------------------------------------------- 1 | export { default } from "libraries/hotkeys@3.8.7" 2 | -------------------------------------------------------------------------------- /app/assets/javascripts/spina/libraries/sortablejs.js: -------------------------------------------------------------------------------- 1 | export { default } from "libraries/sortablejs@1.13.0" 2 | -------------------------------------------------------------------------------- /app/components/spina/application_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class ApplicationComponent < ViewComponent::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/components/spina/forms/editor_insert_images_meta_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Forms 3 | class EditorInsertImagesMetaComponent < ApplicationComponent 4 | attr_reader :images, :trix_target_id 5 | 6 | def initialize(trix_target_id: nil, images:[]) 7 | @trix_target_id = trix_target_id 8 | @images = images 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/components/spina/forms/group_component.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 |
7 | <%= description %> 8 |
9 |
10 | 11 |
12 | <%= content %> 13 |
14 |
-------------------------------------------------------------------------------- /app/components/spina/forms/group_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Forms 3 | class GroupComponent < ApplicationComponent 4 | attr_reader :label, :description 5 | 6 | def initialize(label:, description: "") 7 | @label = label 8 | @description = description 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/components/spina/forms/label_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Forms 3 | class LabelComponent < ApplicationComponent 4 | attr_reader :f, :method 5 | 6 | def initialize(f, method) 7 | @f = f 8 | @method = method 9 | end 10 | 11 | def call 12 | f.label method, class: "font-medium text-sm text-gray-700 block" 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/components/spina/forms/password_field_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Forms 3 | class PasswordFieldComponent < TextFieldComponent 4 | end 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/components/spina/forms/search_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Forms 3 | class SearchComponent < ApplicationComponent 4 | attr_accessor :f, :method 5 | 6 | def initialize(f, method) 7 | @f = f 8 | @method = method 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/components/spina/forms/switch_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Forms 3 | class SwitchComponent < ApplicationComponent 4 | attr_accessor :f, :method 5 | 6 | def initialize(f, method) 7 | @f = f 8 | @method = method 9 | end 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/components/spina/forms/trix_toolbar_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Forms 3 | class TrixToolbarComponent < ApplicationComponent 4 | def initialize(trix_id) 5 | @trix_id = trix_id 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/components/spina/main_navigation/link_component.html.erb: -------------------------------------------------------------------------------- 1 |
  • > 2 | <%= link_to @path, class: "block p-3 leading-none text-white hover:opacity-100 transition-opacity font-semibold #{css_classes}" do %> 3 | <%= @label %> 4 | <% end %> 5 |
  • -------------------------------------------------------------------------------- /app/components/spina/media_picker/image_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module MediaPicker 3 | class ImageComponent < ApplicationComponent 4 | def initialize(image:) 5 | @image = image 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/components/spina/pages/actions_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Pages 3 | class ActionsComponent < ApplicationComponent 4 | def initialize(page:, locale: I18n.locale) 5 | @page = page 6 | @locale = locale 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/components/spina/pages/page_select_component.html.erb: -------------------------------------------------------------------------------- 1 | <%= helpers.select_tag name, helpers.options_for_select(options, {selected: selected, disabled: disabled}), include_blank: include_blank, class: "form-select hover:bg-gray-100 border-none focus:ring-0 bg-none shadow-none bg-transparent border-none cursor-pointer pr-2 w-full truncate", data: {controller: "select-placeholder", action: "select-placeholder#update"} %> -------------------------------------------------------------------------------- /app/components/spina/pages/tab_button_component.html.erb: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /app/components/spina/pages/tab_button_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Pages 3 | class TabButtonComponent < ApplicationComponent 4 | def initialize(tab_name:) 5 | @tab_name = tab_name 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/components/spina/user_interface/dropdown_component.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | <%= button %> 3 | 4 | <%= menu %> 5 |
    -------------------------------------------------------------------------------- /app/components/spina/user_interface/flash_message_component.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | <%= @message %> 3 |
    -------------------------------------------------------------------------------- /app/components/spina/user_interface/header_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module UserInterface 3 | class HeaderComponent < ApplicationComponent 4 | renders_one :actions 5 | renders_one :navigation 6 | renders_one :after_breadcrumbs 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/components/spina/user_interface/modal_component.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module UserInterface 3 | class ModalComponent < ApplicationComponent 4 | def initialize(size: "max-w-lg") 5 | @size = size 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/components/spina/user_interface/tab_link_component.html.erb: -------------------------------------------------------------------------------- 1 | <%= link_to @url, class: "block px-3 leading-relaxed py-1 hover:text-gray-800 rounded-md text-gray-400 font-medium text-sm flex items-center whitespace-nowrap #{css_classes}" do %> 2 | <%= content || @name %> 3 | <% end %> -------------------------------------------------------------------------------- /app/controllers/concerns/spina/current_theme.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module CurrentTheme 3 | extend ActiveSupport::Concern 4 | 5 | included do 6 | before_action :current_theme 7 | helper_method :current_theme 8 | end 9 | 10 | private 11 | 12 | def current_theme 13 | Spina::Current.theme ||= ::Spina::Theme.find_by_name(current_spina_account.theme) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/controllers/spina/admin/parent_pages_controller.rb: -------------------------------------------------------------------------------- 1 | module Spina::Admin 2 | class ParentPagesController < AdminController 3 | def index 4 | @resource = Spina::Resource.find_by(id: params[:resource_id]) 5 | @pages = Spina::Page.where(resource: @resource).sorted.includes(:translations) 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/spina/api/images_controller.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Api 3 | class ImagesController < ApiController 4 | def show 5 | @image = Spina::Image.find(params[:id]) 6 | render json: Spina::Api::ImageSerializer.new(@image, {params: {view_context: view_context}}).serializable_hash.to_json 7 | end 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/controllers/spina/application_controller.rb: -------------------------------------------------------------------------------- 1 | class Spina::ApplicationController < Spina.frontend_parent_controller.constantize 2 | include Spina.config.authentication.constantize 3 | include Spina::CurrentTheme 4 | include Spina::CurrentSpinaAccount 5 | 6 | helper Spina::Engine.helpers 7 | 8 | protect_from_forgery with: :exception 9 | end 10 | -------------------------------------------------------------------------------- /app/controllers/spina/pages_controller.rb: -------------------------------------------------------------------------------- 1 | class Spina::PagesController < Spina::ApplicationController 2 | include Spina::Frontend 3 | 4 | before_action :authorize_page 5 | 6 | helper_method :page 7 | 8 | def homepage 9 | render_with_template(page) 10 | end 11 | 12 | private 13 | 14 | def authorize_page 15 | raise ActiveRecord::RecordNotFound unless page.live? || logged_in? 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/controllers/spina/sitemaps_controller.rb: -------------------------------------------------------------------------------- 1 | class Spina::SitemapsController < Spina::ApplicationController 2 | def show 3 | I18n.locale = I18n.default_locale 4 | @pages = Spina::Page.live.sorted 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/helpers/spina/admin/images_helper.rb: -------------------------------------------------------------------------------- 1 | module Spina::Admin 2 | module ImagesHelper 3 | def ratio_tailwind_class_for_image_part(image) 4 | case image.options.try(:[], :ratio) 5 | when "portrait" 6 | "w-28" 7 | when "landscape" 8 | "w-48" 9 | when "wide" 10 | "w-80" 11 | else 12 | "w-36" # Square (default) 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/helpers/spina/attachments_helper.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module AttachmentsHelper 3 | def file_url(file) 4 | main_app.url_for(file) 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/helpers/spina/spina_helper.rb: -------------------------------------------------------------------------------- 1 | module Spina::SpinaHelper 2 | def spina_importmap_tags(entry_point = "application") 3 | safe_join [ 4 | javascript_inline_importmap_tag(Spina.config.importmap.to_json(resolver: self)), 5 | javascript_importmap_module_preload_tags(Spina.config.importmap), 6 | javascript_import_module_tag(entry_point) 7 | ], "\n" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/jobs/spina/application_job.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class ApplicationJob < ActiveJob::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /app/jobs/spina/resource_pages_update_job.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class ResourcePagesUpdateJob < ApplicationJob 3 | queue_as { Spina.config.queues[:page_updates] } 4 | 5 | def perform(resource_id) 6 | Page.where(resource_id: resource_id).roots.find_each(batch_size: 100) do |page| 7 | page.save 8 | end 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/mailers/spina/application_mailer.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class ApplicationMailer < ActionMailer::Base 3 | default Spina.config.mailer_defaults 4 | 5 | layout "spina/mail" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/mailers/spina/user_mailer.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class UserMailer < ApplicationMailer 3 | def forgot_password(user, user_agent_string = nil) 4 | @user = user 5 | @browser = Browser.new(user_agent_string) 6 | 7 | mail to: @user.email, 8 | subject: t("spina.user_mailer.forgot_password.subject") 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/models/spina/application_record.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class ApplicationRecord < ActiveRecord::Base 3 | self.abstract_class = true 4 | 5 | # Remove Spina namespace from partial paths 6 | def to_partial_path 7 | super.gsub(/\Aspina\//, "") 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/models/spina/current.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class Current < ActiveSupport::CurrentAttributes 3 | attribute :page 4 | attribute :account 5 | attribute :user 6 | attribute :theme 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/models/spina/embeds/base.rb: -------------------------------------------------------------------------------- 1 | module Spina::Embeds 2 | class Base 3 | include ActiveModel::Model 4 | include Spina::Embeddable 5 | include Spina::Embeds::TrixConversion 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/spina/embeds/button.rb: -------------------------------------------------------------------------------- 1 | module Spina::Embeds 2 | class Button < Base 3 | attributes :url, :label 4 | 5 | heroicon "cursor-click" 6 | 7 | validates :url, :label, presence: true 8 | 9 | def to_trix_partial_path 10 | "spina/embeds/buttons/trix_button" 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/spina/media_folder.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class MediaFolder < ApplicationRecord 3 | has_many :images, dependent: :nullify 4 | 5 | validates :name, presence: true, uniqueness: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/spina/parts/base.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class Base 4 | include AttrJson::Model 5 | 6 | attr_json_config(unknown_key: :strip) 7 | 8 | attr_json :name, :string 9 | 10 | attr_accessor :title, :hint, :item_name 11 | 12 | def label 13 | content&.to_s 14 | end 15 | 16 | def content 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/models/spina/parts/line.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class Line < Base 4 | attr_json :content, :string, default: "" 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/spina/parts/multi_line.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class MultiLine < Base 4 | attr_json :content, :string, default: "" 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/spina/parts/option.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class Option < Base 4 | attr_json :value, :string, default: "" 5 | 6 | attr_accessor :options 7 | 8 | def content 9 | value 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/spina/parts/page_link.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class PageLink < Base 4 | attr_json :page_id, :integer, default: nil 5 | attr_json :text, :string, default: nil 6 | 7 | attr_accessor :options 8 | 9 | def content 10 | ::Spina::Page.live.find_by(id: page_id) 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/models/spina/parts/repeater.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class Repeater < Base 4 | include AttrJson::NestedAttributes 5 | 6 | attr_json :content, RepeaterContent.to_type, array: true 7 | attr_json_accepts_nested_attributes_for :content 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/models/spina/parts/resource_link.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class ResourceLink < Base 4 | attr_json :resource_id, :integer, default: nil 5 | 6 | attr_accessor :options 7 | 8 | def content 9 | ::Spina::Resource.find_by(id: resource_id) 10 | end 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/spina/parts/text.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Parts 3 | class Text < Base 4 | attr_json :content, :string, default: "" 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/models/spina/rewrite_rule.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class RewriteRule < ApplicationRecord 3 | validates :old_path, uniqueness: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/models/spina/setting.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class Setting < ApplicationRecord 3 | validates :plugin, presence: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/serializers/spina/api/base_serializer.rb: -------------------------------------------------------------------------------- 1 | module Spina::Api 2 | class BaseSerializer 3 | include JSONAPI::Serializer 4 | singleton_class.include Spina::Engine.routes.url_helpers 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/views/layouts/spina/admin/sessions.html.erb: -------------------------------------------------------------------------------- 1 | <%= render template: 'layouts/spina/admin/application' %> -------------------------------------------------------------------------------- /app/views/spina/admin/attachments/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= render @attachment %> -------------------------------------------------------------------------------- /app/views/spina/admin/images/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::UserInterface::ModalComponent.new(size: "max-w-screen-lg w-auto") do |modal| %> 2 | <%= image_tag preview_url(@image) %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/images/update.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.remove @image %> 2 | 3 | <% if @image.media_folder %> 4 | <%= turbo_stream.update @image.media_folder %> 5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/spina/admin/media_folders/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= render(Spina::UserInterface::ModalComponent.new) do |component| %> 2 | <%= render 'form' %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/media_folders/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render(Spina::UserInterface::ModalComponent.new) do |component| %> 2 | <%= render 'form' %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/media_picker/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::MediaPicker::ModalComponent.new(params[:target], images: @images, media_folder: @media_folder) %> -------------------------------------------------------------------------------- /app/views/spina/admin/navigation_items/_page_form.html.erb: -------------------------------------------------------------------------------- 1 |
    2 |
    3 | <%= render Spina::Pages::PageSelectComponent.new("navigation_item[page_id]", @pages, include_blank: t("spina.navigations.choose_page"), disabled: @navigation.navigation_items.pluck(:page_id), selected: @navigation_item.page_id) %> 4 |
    5 |
    -------------------------------------------------------------------------------- /app/views/spina/admin/navigation_items/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= render(Spina::UserInterface::ModalComponent.new) do %> 2 | <%= render 'form' %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/navigation_items/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render(Spina::UserInterface::ModalComponent.new) do %> 2 | <%= render 'form' %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/navigations/_navigation.html.erb: -------------------------------------------------------------------------------- 1 | <%= link_to navigation.label, spina.edit_admin_navigation_path(navigation) %> -------------------------------------------------------------------------------- /app/views/spina/admin/navigations/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::UserInterface::HeaderComponent.new %> 2 | 3 |
    4 |
    5 | <%=t 'spina.navigations.no_navigations' %> 6 |
    7 |
    8 | -------------------------------------------------------------------------------- /app/views/spina/admin/page_select_options/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_frame_tag :page_title do %> 2 | <%= @page.title %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /app/views/spina/admin/pages/_button_advanced.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::Pages::TabButtonComponent.new(tab_name: 'advanced') do %> 2 | <%= heroicon('cog-8-tooth', style: :solid, class: 'w-4 h-4 mr-1 -ml-1 opacity-75') %> 3 | <%= t("spina.pages.advanced") %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /app/views/spina/admin/pages/_button_page_content.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::Pages::TabButtonComponent.new(tab_name: 'page_content') do %> 2 | <%= heroicon('document-text', class: 'w-4 h-4 mr-1 -ml-1 opacity-75') %> 3 | <%= t("spina.pages.page_content") %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /app/views/spina/admin/pages/_button_search_engines.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::Pages::TabButtonComponent.new(tab_name: 'search_engines') do %> 2 | <%= heroicon('search', style: :mini, class: 'w-4 h-4 mr-1 -ml-1 opacity-75') %> 3 | 4 | SEO 5 | <% end %> 6 | -------------------------------------------------------------------------------- /app/views/spina/admin/pages/_form_page_content.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | 5 | <%= render Spina::Forms::TextFieldComponent.new(f, :title, size: "lg") %> 6 | 7 | 8 |
    9 | -------------------------------------------------------------------------------- /app/views/spina/admin/pages/children.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_frame_tag "page_#{@page.id}_children" do %> 2 | <%= render Spina::Pages::ListComponent.new(pages: @children, sortable: params[:sortable] == "true", draggable: params[:draggable] == "true") %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/pages/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'form' %> 2 | -------------------------------------------------------------------------------- /app/views/spina/admin/pages/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render(Spina::UserInterface::ModalComponent.new) do %> 2 | <%= render 'new_page_form' %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /app/views/spina/admin/pages/sort_one.turbo_stream.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream.replace @bottom_page do %> 2 | <%= render Spina::Pages::PageComponent.new(page: @top_page, draggable: false) %> 3 | <% end %> 4 | 5 | <%= turbo_stream.replace @top_page do %> 6 | <%= render Spina::Pages::PageComponent.new(page: @bottom_page, draggable: false) %> 7 | <% end %> 8 | 9 | <%= turbo_stream.update("flash", partial: "spina/admin/shared/flash") %> -------------------------------------------------------------------------------- /app/views/spina/admin/parent_pages/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_frame_tag("parent_pages") do %> 2 | <%= render Spina::Pages::PageSelectComponent.new("page[parent_id]", @pages, include_blank: t('spina.pages.no_parent_page'), selected: params[:parent_id], disabled: params[:page_id]) %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/parts/attachments/_attachment.html.erb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/views/spina/admin/parts/lines/_form.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    <%= f.object.hint %>
    4 |
    5 | <%= f.text_field :content, class: "form-input block w-full max-w-5xl sm:text-sm sm:leading-5" %> 6 |
    7 |
    -------------------------------------------------------------------------------- /app/views/spina/admin/parts/multi_lines/_form.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    <%= f.object.hint %>
    4 |
    5 | <%= f.text_area :content, placeholder: f.object.title, class: "form-input mt-1 w-full" %> 6 |
    7 |
    8 | -------------------------------------------------------------------------------- /app/views/spina/admin/parts/options/_form.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | 3 |
    <%= f.object.hint %>
    4 | 5 | <%= f.select :value, f.object.options, {include_blank: t("spina.options.choose_option")}, class: "form-select mt-1" %> 6 |
    7 | -------------------------------------------------------------------------------- /app/views/spina/admin/resource_select_options/show.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_frame_tag :resource_title do %> 2 | <%= @resource.label %> 3 | <% end %> 4 | -------------------------------------------------------------------------------- /app/views/spina/admin/settings/_string_field.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::Forms::GroupComponent.new(label: t("spina.#{plugin.namespace}.settings.#{attribute}")) do %> 2 | <%= render Spina::Forms::LabelComponent.new(f, attribute) %> 3 | <%= render Spina::Forms::TextFieldComponent.new(f, attribute) %> 4 | <% end %> 5 | -------------------------------------------------------------------------------- /app/views/spina/admin/settings/_text_field.html.erb: -------------------------------------------------------------------------------- 1 | <%= render Spina::Forms::GroupComponent.new(label: t("spina.#{plugin.namespace}.settings.#{attribute}")) do %> 2 | <%= render Spina::Forms::LabelComponent.new(f, attribute) %> 3 | 4 | <%= f.text_area attribute, class: "form-input mt-1 w-full" %> 5 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/admin/shared/_flash.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | <% flash.each do |type, message| %> 3 | <%= render Spina::UserInterface::FlashMessageComponent.new(type: type, message: message) %> 4 | <% end %> 5 |
    6 | -------------------------------------------------------------------------------- /app/views/spina/admin/users/edit.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'form' %> -------------------------------------------------------------------------------- /app/views/spina/admin/users/new.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'form' %> -------------------------------------------------------------------------------- /app/views/spina/embeds/buttons/_button.html.erb: -------------------------------------------------------------------------------- 1 | <%= link_to button.url do %> 2 | <%= button.label %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/embeds/buttons/_trix_button.html.erb: -------------------------------------------------------------------------------- 1 | <%= button_tag type: :button, class: "btn btn-default" do %> 2 | <%= button.label %> 3 | <% end %> -------------------------------------------------------------------------------- /app/views/spina/embeds/vimeos/_vimeo.html.erb: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/views/spina/embeds/vimeos/_vimeo_fields.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | Vimeo 3 |
    4 | Embed a Vimeo video 5 |
    6 |
    7 | 8 | <%= render Spina::Forms::LabelComponent.new(f, :url) %> 9 | <%= render Spina::Forms::TextFieldComponent.new(f, :url, autofocus: true) %> 10 | -------------------------------------------------------------------------------- /app/views/spina/embeds/youtubes/_youtube.html.erb: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/views/spina/embeds/youtubes/_youtube_fields.html.erb: -------------------------------------------------------------------------------- 1 |
    2 | Youtube 3 |
    4 | Embed a Youtube video 5 |
    6 |
    7 | 8 | <%= render Spina::Forms::LabelComponent.new(f, :url) %> 9 | <%= render Spina::Forms::TextFieldComponent.new(f, :url, autofocus: true) %> 10 | -------------------------------------------------------------------------------- /db/migrate/12_add_url_title_to_spina_page_translations.rb: -------------------------------------------------------------------------------- 1 | class AddUrlTitleToSpinaPageTranslations < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :spina_page_translations, :url_title, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/13_add_json_attributes_to_spina_accounts.rb: -------------------------------------------------------------------------------- 1 | class AddJsonAttributesToSpinaAccounts < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :spina_accounts, :json_attributes, :jsonb 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/14_add_json_attributes_to_spina_pages.rb: -------------------------------------------------------------------------------- 1 | class AddJsonAttributesToSpinaPages < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :spina_pages, :json_attributes, :jsonb 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/15_add_slug_to_spina_resources.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToSpinaResources < ActiveRecord::Migration[5.2] 2 | def change 3 | add_column :spina_resources, :slug, :jsonb 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/16_add_ancestry_cache_columns_to_spina_pages.rb: -------------------------------------------------------------------------------- 1 | class AddAncestryCacheColumnsToSpinaPages < ActiveRecord::Migration[6.0] 2 | def change 3 | add_column :spina_pages, :ancestry_depth, :integer, default: 0 4 | add_column :spina_pages, :ancestry_children_count, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/18_change_default_spina_resources_slug.rb: -------------------------------------------------------------------------------- 1 | class ChangeDefaultSpinaResourcesSlug < ActiveRecord::Migration[7.0] 2 | def up 3 | change_column :spina_resources, :slug, :jsonb, default: {} 4 | end 5 | 6 | def down 7 | change_column :spina_resources, :slug, :jsonb, default: nil 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/4_add_password_reset_token_to_spina_users.rb: -------------------------------------------------------------------------------- 1 | class AddPasswordResetTokenToSpinaUsers < ActiveRecord::Migration[5.0] 2 | def change 3 | add_column :spina_users, :password_reset_token, :string 4 | add_column :spina_users, :password_reset_sent_at, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/6_create_spina_options.rb: -------------------------------------------------------------------------------- 1 | class CreateSpinaOptions < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :spina_options do |t| 4 | t.string :value 5 | t.timestamps 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/7_create_spina_settings.rb: -------------------------------------------------------------------------------- 1 | class CreateSpinaSettings < ActiveRecord::Migration[5.0] 2 | def change 3 | create_table :spina_settings do |t| 4 | t.string :plugin 5 | t.jsonb :preferences, default: {} 6 | t.timestamps 7 | end 8 | 9 | add_index :spina_settings, :plugin 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/8_create_spina_media_folders.rb: -------------------------------------------------------------------------------- 1 | class CreateSpinaMediaFolders < ActiveRecord::Migration[5.1] 2 | def change 3 | create_table :spina_media_folders do |t| 4 | t.string :name 5 | t.timestamps 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/9_create_spina_images.rb: -------------------------------------------------------------------------------- 1 | class CreateSpinaImages < ActiveRecord::Migration[5.2] 2 | def change 3 | create_table :spina_images do |t| 4 | t.integer :media_folder_id 5 | 6 | t.timestamps 7 | end 8 | add_index :spina_images, :media_folder_id 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | puts "Seeding #{__FILE__} from Spina::Engine" 2 | -------------------------------------------------------------------------------- /docs/v1/1_getting_started.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | Spina is a CMS for Rails 6.0. 4 | 5 | If you haven't built anything with Rails before, no sweat, watch the video and you'll be up and running in no time! 6 | If you're already familiar with Rails, just skip to the install instructions. 7 | 8 | [youtube nxRfd93QqBA] 9 | -------------------------------------------------------------------------------- /docs/v1/2_themes.md: -------------------------------------------------------------------------------- 1 | # Themes 2 | 3 | The installer generates a few initializers that contain necessary configuration for Spina. 4 | 5 | In the initializers folder there's a new folder named themes. Inside you will find a configuration file named default.rb. This file contains all of your theme-specific settings. You can define multiple Page parts, View templates and Custom pages. -------------------------------------------------------------------------------- /docs/v1/getting_help/1_support.md: -------------------------------------------------------------------------------- 1 | # Support & community 2 | 3 | Got stuck? [Join our Discord community](https://discord.gg/bv5Mu4XYcN) and ask for help! Spina has a great community of Rails developers willing to help you out. -------------------------------------------------------------------------------- /docs/v1/getting_started/2_install_spina.md: -------------------------------------------------------------------------------- 1 | # Install Spina CMS 2 | 3 | To start using Spina CMS add the following line to your Gemfile: 4 | 5 | ``` 6 | gem 'spina' 7 | ``` 8 | 9 | Make sure you run the installer to get started. 10 | 11 | ``` 12 | rails spina:install 13 | ``` 14 | 15 | The installer will help you setup your first user. 16 | Then start `rails s` and access Spina at `/admin`. 17 | -------------------------------------------------------------------------------- /docs/v1/themes/2_view_templates.md: -------------------------------------------------------------------------------- 1 | # View templates 2 | 3 | Each theme typically has a few different view templates which make up your website. By default Spina generates a homepage and show template. 4 | 5 | The views for these templates are stored in app/views/default/pages. -------------------------------------------------------------------------------- /docs/v1/themes/4_custom_pages.md: -------------------------------------------------------------------------------- 1 | # Custom pages 2 | 3 | You can define custom pages for your theme that will be generated when bootstrapping your website. You can define whether or not they're deletable. By default Spina creates a custom page named Homepage which is not deletable. -------------------------------------------------------------------------------- /docs/v2/2_themes.md: -------------------------------------------------------------------------------- 1 | # Themes 2 | 3 | The installer generates a few initializers that contain necessary configuration for Spina. 4 | 5 | In the initializers folder there's a new folder named themes. Inside you will find a configuration file named default.rb. This file contains all of your theme-specific settings. You can define multiple parts, view templates and custom pages. -------------------------------------------------------------------------------- /docs/v2/3_rendering_content.md: -------------------------------------------------------------------------------- 1 | # Rendering content 2 | 3 | Spina features 8 built-in parts that you can use to build pages. 4 | 5 | - `Spina::Parts::Line` 6 | - `Spina::Parts::MultiLine` 7 | - `Spina::Parts::Text` 8 | - `Spina::Parts::Image` 9 | - `Spina::Parts::ImageCollection` 10 | - `Spina::Parts::Attachment` 11 | - `Spina::Parts::Option` 12 | - `Spina::Parts::Repeater` 13 | 14 | Learn more about them in the next chapters. -------------------------------------------------------------------------------- /docs/v2/4_api.md: -------------------------------------------------------------------------------- 1 | # API 2 | -------------------------------------------------------------------------------- /docs/v2/5_support.md: -------------------------------------------------------------------------------- 1 | # Support & community 2 | 3 | Got stuck? [Join our Discord community](https://discord.gg/bv5Mu4XYcN) and ask for help! Spina has a great community of Rails developers willing to help you out. -------------------------------------------------------------------------------- /docs/v2/6_advanced.md: -------------------------------------------------------------------------------- 1 | # Advanced 2 | 3 | Some websites require more functionality than SpinaCMS includes by default. There are many plugins you can use to extend Spina. If those don't satisfy your needs there's also the option to add custom functionality. The next chapters will show you how to customize Spina. -------------------------------------------------------------------------------- /docs/v2/getting_started/6_deploying.md: -------------------------------------------------------------------------------- 1 | # Deploying 2 | 3 | Deploying a Spina CMS project is no different than any other Rails project. Spina includes a task that you can run on your first deployment in a production environment: 4 | 5 | ``` 6 | rails spina:first_deploy 7 | ``` 8 | 9 | This task does the same thing as the install task, except for copying files. -------------------------------------------------------------------------------- /docs/v2/themes/2_view_templates.md: -------------------------------------------------------------------------------- 1 | # View templates 2 | 3 | Each theme typically has a few different view templates which make up your website. By default Spina generates a homepage and show template. 4 | 5 | The views for these templates are stored in app/views/default/pages. -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/default/pages/homepage.html.erb: -------------------------------------------------------------------------------- 1 |

    <%= current_page.title %>

    2 | <%= content.html :text %> -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/default/pages/show.html.erb: -------------------------------------------------------------------------------- 1 |

    <%= current_page.title %>

    2 | <%= content.html(:text) %> 3 | 4 | -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/default/shared/_navigation.html.erb: -------------------------------------------------------------------------------- 1 | <% presenter = Spina::MenuPresenter.new(Spina::Page.all) %> 2 | <%= presenter.to_html %> 3 | -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/demo/pages/homepage.html.erb: -------------------------------------------------------------------------------- 1 |

    <%= current_page.title %>

    2 | <%= content.html(:body) %> 3 | 4 | -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/demo/pages/show.html.erb: -------------------------------------------------------------------------------- 1 |

    <%= current_page.title %>

    2 | <%= content.html(:text) %> 3 | 4 | -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/demo/shared/_languages.html.erb: -------------------------------------------------------------------------------- 1 | <% if Spina.locales.size > 1 %> 2 |
    3 | <%= Spina.locales.map{|l| link_to_unless(l == I18n.locale, l.upcase, root_url(params: {locale: l}))}.join(' / ').html_safe %> 4 |
    5 | <% end %> -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/demo/shared/_navigation.html.erb: -------------------------------------------------------------------------------- 1 | <% presenter = Spina::MenuPresenter.new(Spina::Page.all) %> 2 | <%= presenter.to_html %> -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/layouts/default/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= current_spina_account.name %> 5 | <%= csrf_meta_tags %> 6 | 7 | 8 | <%= render 'default/shared/navigation' %> 9 | 10 | <%= yield %> 11 | 12 | -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/layouts/demo/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | <%= current_spina_account.name %> 5 | <%= csrf_meta_tags %> 6 | 7 | 8 | <%= render 'demo/shared/languages' %> 9 | <%= render 'demo/shared/navigation' %> 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /lib/generators/spina/templates/app/views/spina/embeds/_partial.html.erb: -------------------------------------------------------------------------------- 1 | 2 | Your embed 3 | -------------------------------------------------------------------------------- /lib/generators/spina/templates/config/initializers/mobility.rb: -------------------------------------------------------------------------------- 1 | Mobility.configure do 2 | plugins do 3 | backend :table 4 | active_record 5 | reader 6 | writer 7 | backend_reader 8 | query 9 | cache 10 | presence 11 | fallbacks false # default to false, enable if passed fallbacks: true 12 | locale_accessors 13 | default 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/spina/embeds.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | module Embeds 3 | def self.constantize(embeddable_type) 4 | return nil if embeddable_type.blank? 5 | name = embeddable_type.camelize.demodulize.to_s 6 | "Spina::Embeds::#{name}".safe_constantize 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /lib/spina/version.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | VERSION = "2.20.0" 3 | end 4 | -------------------------------------------------------------------------------- /test/dummy/.ruby-version: -------------------------------------------------------------------------------- 1 | 3.3.5 2 | -------------------------------------------------------------------------------- /test/dummy/Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative "config/application" 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /test/dummy/app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/app/assets/images/.keep -------------------------------------------------------------------------------- /test/dummy/app/assets/images/spina/view_template_previews/show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/app/assets/images/spina/view_template_previews/show.png -------------------------------------------------------------------------------- /test/dummy/app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | before_action :set_some_variable 3 | 4 | private 5 | 6 | def set_some_variable 7 | @some_variable = "Some variable is set!" 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/dummy/app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /test/dummy/app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | def some_helper_method 3 | "This is some helper method" 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/dummy/app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | # Automatically retry jobs that encountered a deadlock 3 | # retry_on ActiveRecord::Deadlocked 4 | 5 | # Most jobs are safe to ignore if the underlying records are no longer available 6 | # discard_on ActiveJob::DeserializationError 7 | end 8 | -------------------------------------------------------------------------------- /test/dummy/app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: "from@example.com" 3 | layout "mailer" 4 | end 5 | -------------------------------------------------------------------------------- /test/dummy/app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /test/dummy/app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/app/models/concerns/.keep -------------------------------------------------------------------------------- /test/dummy/app/views/demo/pages/different_layout.html.erb: -------------------------------------------------------------------------------- 1 | View template with a different layout -------------------------------------------------------------------------------- /test/dummy/app/views/demo/pages/homepage.html.erb: -------------------------------------------------------------------------------- 1 |

    <%= current_page.title %>

    2 | 3 | <%= content.html :body %> 4 | 5 | <%= some_helper_method %> 6 | -------------------------------------------------------------------------------- /test/dummy/app/views/demo/pages/show.html.erb: -------------------------------------------------------------------------------- 1 |

    <%= current_page.title %>

    2 | <%= content.html :text %> 3 | 4 | <%= content.html :body %> 5 | 6 | <%= content.attachment_url(:attachment) %> 7 | 8 | <%= content.image_url(:image) %> 9 | 10 | <%= content(:line) %> 11 | 12 | <%= content(:line) %> 13 | -------------------------------------------------------------------------------- /test/dummy/app/views/demo/shared/_languages.html.erb: -------------------------------------------------------------------------------- 1 | <% if Spina.locales.size > 1 %> 2 |
    3 | <%= Spina.locales.map{|l| link_to_unless(l == I18n.locale, l.upcase, root_url(params: {locale: l}))}.join(' / ').html_safe %> 4 |
    5 | <% end %> -------------------------------------------------------------------------------- /test/dummy/app/views/demo/shared/_navigation.html.erb: -------------------------------------------------------------------------------- 1 | <% presenter = Spina::MenuPresenter.new(Spina::Page.all) %> 2 | <% presenter.list_item_css = "list-item" %> 3 | <% presenter.active_list_item_css = "list-item active" %> 4 | <% presenter.current_list_item_css = "list-item current" %> 5 | <%= presenter.to_html %> -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dummy 5 | <%= csrf_meta_tags %> 6 | <%= csp_meta_tag %> 7 | 8 | <%= stylesheet_link_tag 'application', media: 'all' %> 9 | 10 | 11 | 12 | <%= yield %> 13 | 14 | 15 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /test/dummy/app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /test/dummy/bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | exec "./bin/rails", "server", *ARGV 3 | -------------------------------------------------------------------------------- /test/dummy/bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /test/dummy/bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /test/dummy/config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative "config/environment" 4 | 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /test/dummy/config/boot.rb: -------------------------------------------------------------------------------- 1 | # Set up gems listed in the Gemfile. 2 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../Gemfile", __dir__) 3 | 4 | require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"]) 5 | $LOAD_PATH.unshift File.expand_path("../../../lib", __dir__) 6 | -------------------------------------------------------------------------------- /test/dummy/config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: test 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: dummy_production 11 | -------------------------------------------------------------------------------- /test/dummy/config/database.yml.ci: -------------------------------------------------------------------------------- 1 | test: 2 | adapter: postgresql 3 | encoding: unicode 4 | pool: 5 5 | host: localhost 6 | username: postgres 7 | password: postgres 8 | database: postgres -------------------------------------------------------------------------------- /test/dummy/config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Version of your assets, change this if you want to expire all your assets. 4 | Rails.application.config.assets.version = "1.0" 5 | 6 | # Add additional assets to the asset load path. 7 | # Rails.application.config.assets.paths << Emoji.images_path 8 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /test/dummy/config/initializers/mobility.rb: -------------------------------------------------------------------------------- 1 | Mobility.configure do 2 | plugins do 3 | backend :table 4 | active_record 5 | reader 6 | writer 7 | backend_reader 8 | query 9 | cache 10 | presence 11 | fallbacks false # default to false, enable if passed fallbacks: true 12 | locale_accessors 13 | default 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/dummy/config/locales/en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | spina: 3 | spina_test: 4 | title: Test plugin 5 | settings: 6 | test_setting: Test setting 7 | foobar: Foobar 8 | -------------------------------------------------------------------------------- /test/dummy/config/master.key: -------------------------------------------------------------------------------- 1 | cc9b474907a9c68d76ffdaac8dc77eb3 -------------------------------------------------------------------------------- /test/dummy/config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | mount Spina::Engine => "/" 3 | end 4 | -------------------------------------------------------------------------------- /test/dummy/config/spring.rb: -------------------------------------------------------------------------------- 1 | Spring.watch( 2 | ".ruby-version", 3 | ".rbenv-vars", 4 | "tmp/restart.txt", 5 | "tmp/caching-dev.txt" 6 | ) 7 | -------------------------------------------------------------------------------- /test/dummy/lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/lib/assets/.keep -------------------------------------------------------------------------------- /test/dummy/log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/log/.keep -------------------------------------------------------------------------------- /test/dummy/public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /test/dummy/public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/public/apple-touch-icon.png -------------------------------------------------------------------------------- /test/dummy/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/public/favicon.ico -------------------------------------------------------------------------------- /test/dummy/public/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/dummy/public/icon.png -------------------------------------------------------------------------------- /test/dummy/public/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /test/dummy/public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /test/factories/accounts.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :account, class: "Spina::Account" do 3 | name { "My Website" } 4 | email { "bram@spinacms.com" } 5 | preferences { {"theme" => "demo"} } 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /test/factories/media_folder.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :media_folder, class: "Spina::MediaFolder" do 3 | name { "Header images" } 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/factories/navigation.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :navigation, class: "Spina::Navigation" do 3 | name { "custom-nav" } 4 | label { "Custom nav" } 5 | end 6 | 7 | factory :navigation_item, class: "Spina::NavigationItem" do 8 | association :page, title: "A page" 9 | kind { "page" } 10 | navigation 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /test/factories/page/translations.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :page_translation, class: "Spina::Page::Translation" do 3 | locale { "nl" } 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /test/factories/parts.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :base_part, class: "Spina::Parts::Base" do 3 | skip_create 4 | 5 | factory :line_part, class: "Spina::Parts::Line" do 6 | content { "a line of text" } 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/factories/resources.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :resource, class: "Spina::Resource" do 3 | name { "resource" } 4 | label { "Resource" } 5 | 6 | factory :breweries do 7 | name { "breweries" } 8 | label { "Breweries" } 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /test/factories/users.rb: -------------------------------------------------------------------------------- 1 | FactoryBot.define do 2 | factory :user, class: "Spina::User" do 3 | name { "Bram" } 4 | email { "bram@denkgroot.com" } 5 | password { "4Jvp9TUGoYrt2cXyrRpK_vsPd4J7" } 6 | password_confirmation { password } 7 | admin { true } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /test/fixtures/files/spina.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SpinaCMS/Spina/00d69897b7fa9b0540ff952c72eac6e3b62dbfc9/test/fixtures/files/spina.png -------------------------------------------------------------------------------- /test/mailers/previews/spina/user_mailer_preview.rb: -------------------------------------------------------------------------------- 1 | module Spina 2 | class UserMailerPreview < ActionMailer::Preview 3 | def forgot_password 4 | UserMailer.forgot_password(Spina::User.first, "Mozilla/5.0 (iPhone; CPU iPhone OS 11_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1") 5 | end 6 | end 7 | end 8 | --------------------------------------------------------------------------------