mirror of
https://github.com/jbcr/core.git
synced 2026-04-02 22:32:20 +02:00
Added All Skin Changes
This commit is contained in:
@@ -1,9 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
rm -rf vendor
|
||||
mkdir -p vendor/
|
||||
|
||||
wget https://github.com/sparksuite/simplemde-markdown-editor/archive/1.11.2.tar.gz -O vendor/simplemde-markdown-editor.tgz
|
||||
mkdir -p vendor/simplemde-markdown-editor
|
||||
tar -xvzf vendor/simplemde-markdown-editor.tgz --strip-components=1 -C vendor/simplemde-markdown-editor
|
||||
|
||||
103
assets/js/Components/Admin/Sidebar.vue
Normal file
103
assets/js/Components/Admin/Sidebar.vue
Normal file
@@ -0,0 +1,103 @@
|
||||
<template>
|
||||
<nav class="admin__sidebar--nav">
|
||||
<a class="admin__sidebar--brand" href="/bolt">
|
||||
<img :src="brand" alt="Bolt Four">
|
||||
</a>
|
||||
<div class="admin__sidebar--create">
|
||||
<button class="btn btn-outline-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="fas fa-magic mr-2"></i> New
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<a
|
||||
class="dropdown-item"
|
||||
v-for="(item, index) in menuLinks('Content')"
|
||||
:key="index"
|
||||
:href="`/bolt/edit/${item.slug}`"
|
||||
v-if="!item.singleton"
|
||||
>
|
||||
{{item.singular_name}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<!-- loop through menu seperators -->
|
||||
<div v-for="(item, index) in menuSeparator" :key="index">
|
||||
<p class="admin__sidebar--separator">
|
||||
{{item.name}}
|
||||
</p>
|
||||
<ul class="admin__sidebar--menu">
|
||||
<!-- loop through menu items matching seperator name -->
|
||||
<li v-for="(item, index) in menuLinks(item.name)" :key="index">
|
||||
<template v-if="item.singleton">
|
||||
<a :href="item.records[0].editlink" class="admin__sidebar--link">
|
||||
<i class="fas mr-2 link--icon" :class="item.icon_one"></i><span class="link--text">{{item.name}}</span>
|
||||
</a>
|
||||
</template>
|
||||
<template v-else>
|
||||
<a :href="item.link" class="admin__sidebar--link" :class="{'has-menu': item.records !== null}">
|
||||
<i class="fas mr-2 link--icon" :class="item.icon_one"></i><span class="link--text">{{item.name}}</span>
|
||||
<!-- loop through menu item records -->
|
||||
<template v-if="item.records !== null">
|
||||
<i class="fas fa-caret-right link--caret"></i>
|
||||
<ul class="link--menu">
|
||||
<!-- create new record -->
|
||||
<li v-if="item.contenttype !== null" class="link--create">
|
||||
<a :href="`/bolt/edit/${item.slug}`">
|
||||
<i class="fas fa-plus mr-2"></i><span>New {{item.singular_name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li v-for="(record, index) in item.records" :key="index">
|
||||
<a :href="record.editlink">
|
||||
<i class="fas mr-2" :class="item.icon_one"></i><span>{{record.title}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- end loop -->
|
||||
</template>
|
||||
</a>
|
||||
</template>
|
||||
</li>
|
||||
<!-- end loop -->
|
||||
</ul>
|
||||
</div>
|
||||
<!-- end loop -->
|
||||
</div>
|
||||
<button class="admin__sidebar--slim" @click="slimMenu()"><i class="fas fa-arrows-alt-h"></i></button>
|
||||
<footer class="admin__sidebar--footer">
|
||||
Bolt {{version}}
|
||||
</footer>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContentAPI from "../../service/api/content";
|
||||
|
||||
export default {
|
||||
name: "admin-sidebar",
|
||||
props: ["brand", "menu", "version"],
|
||||
mounted(){
|
||||
console.log(this.menu);
|
||||
},
|
||||
methods: {
|
||||
slimMenu(){
|
||||
const admin = document.querySelector('.admin');
|
||||
const sidebar = document.querySelector('.admin__sidebar');
|
||||
admin.classList.toggle('is-slim')
|
||||
sidebar.classList.toggle('is-slim')
|
||||
},
|
||||
menuLinks(type){
|
||||
if(type === 'Content'){
|
||||
return this.menu.filter(item => item.contenttype !== null)
|
||||
}
|
||||
if(type === 'Settings'){
|
||||
return this.menu.filter(item => item.contenttype === null && item.type !== 'separator' && item.name !== 'Dashboard')
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
menuSeparator(){
|
||||
return this.menu.filter(item => item.type === 'separator')
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
64
assets/js/Components/Admin/Topbar.vue
Normal file
64
assets/js/Components/Admin/Topbar.vue
Normal file
@@ -0,0 +1,64 @@
|
||||
<template>
|
||||
<nav class="admin__header--topbar" role="toolbar" aria-label="Toolbar with button groups">
|
||||
<h2 class="admin__header--title" v-html="title"></h2>
|
||||
|
||||
<ul class="admin__header--toolbar">
|
||||
<li>
|
||||
<button class="toolbar--link">
|
||||
<i class="fas fa-search"></i>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
<a class="toolbar--link" href="/" target="_blank">
|
||||
<i class="fas fa-external-link-square-alt"></i>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<button class="toolbar--link" type="button" data-toggle="dropdown">
|
||||
<span class="text"><i class="fas fa-user-circle"></i></span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right">
|
||||
<a href="/bolt/profile-edit" class="dropdown-item">Edit profile</a>
|
||||
<a href="/bolt/logout" class="dropdown-item">Logout</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
name: "admin-topbar",
|
||||
props: ["title"]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.nav.btn-toolbar {
|
||||
margin: 0.5rem 1rem 0 3rem;
|
||||
|
||||
.nav-item {
|
||||
flex-grow: 0;
|
||||
margin-right: 0.6rem;
|
||||
}
|
||||
|
||||
.nav-item.topbar-title {
|
||||
font-family: "Source Sans Pro", serif;
|
||||
font-size: 22px;
|
||||
color: #222;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: left;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.btn-light {
|
||||
background-color: #eee;
|
||||
border: 1px solid #d8d8d8;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,193 +0,0 @@
|
||||
<template>
|
||||
<nav class="nav flex-column nav-fill">
|
||||
<div class="logo">
|
||||
<h2>Bolt</h2>
|
||||
</div>
|
||||
<!-- TODO: Maybe we need to parse the data somewhere else -->
|
||||
<template v-for="menuitem in JSON.parse(sidebarmenudata)">
|
||||
|
||||
<!-- separators -->
|
||||
<hr v-if="menuitem.type"/>
|
||||
<div v-if="menuitem.type" class="nav-item separator">
|
||||
<i class="fas" :class="menuitem.icon_one"></i>
|
||||
{{ menuitem.name }}
|
||||
</div>
|
||||
|
||||
<!-- Non-contenttype links -->
|
||||
<a v-else-if="!menuitem.contenttype" :href="menuitem.link" class="nav-item nav-link" :key="menuitem.id">
|
||||
<span v-if="!menuitem.type" class="fa-stack">
|
||||
<i class="fas fa-square fa-stack-2x"></i>
|
||||
<i class="fas fa-stack-1x" :class="menuitem.icon_one"></i>
|
||||
</span>
|
||||
{{ menuitem.name }}
|
||||
</a>
|
||||
|
||||
<!-- Contenttypes -->
|
||||
|
||||
|
||||
<div v-else="" class="dropdown" :key="menuitem.id" :class="[ menuitem.active ? 'current' : '' ]">
|
||||
<a :href="menuitem.link" button class="nav-item nav-link dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" data-trigger="hover">
|
||||
<span class="fa-stack">
|
||||
<i class="fas fa-square fa-stack-2x"></i>
|
||||
<i class="fas fa-stack-1x" :class="menuitem.icon_many"></i>
|
||||
</span>
|
||||
{{ menuitem.name }}
|
||||
</a>
|
||||
|
||||
<!-- that are not Singleton -->
|
||||
<div v-if="!menuitem.singleton" class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<a v-for="record in getRecordsPerContenttype(menuitem.contenttype)" :key="record.id" class="dropdown-item" :href="'/bolt/edit/' + record.id">
|
||||
<i class="fas icon" :class="menuitem.icon_one"></i>
|
||||
{{ record.magictitle }}
|
||||
</a>
|
||||
<div class="btn-group" role="group">
|
||||
<a class="btn btn-light btn-sm" :href="'/bolt/content/' + menuitem.contenttype">
|
||||
<i class="fas icon" :class="menuitem.icon_one"></i>
|
||||
View {{ menuitem.name }}
|
||||
</a>
|
||||
<a class="btn btn-light btn-sm" :href="'/bolt/edit/' + menuitem.contenttype">
|
||||
<i class="fas fa-plus icon"></i>
|
||||
New {{ menuitem.name }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ContentAPI from "../../service/api/content";
|
||||
|
||||
export default {
|
||||
name: "sidebar",
|
||||
props: ["sidebarmenudata"],
|
||||
data() {
|
||||
return {
|
||||
message: "",
|
||||
loading: true,
|
||||
records: []
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getRecordsPerContenttype(contenttypeslug) {
|
||||
if (localStorage.getItem("records-" + contenttypeslug) === null) {
|
||||
return this.records[contenttypeslug];
|
||||
} else {
|
||||
return ContentAPI.getRecords(contenttypeslug);
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
let sidebarmenudata = JSON.parse(this.sidebarmenudata);
|
||||
|
||||
for (let i = 0; i < sidebarmenudata.length; i++) {
|
||||
if (sidebarmenudata[i].contenttype) {
|
||||
setTimeout(() => {
|
||||
ContentAPI.fetchRecords(sidebarmenudata[i].contenttype)
|
||||
.then(records => {
|
||||
this.$set(this.records, sidebarmenudata[i].contenttype, records);
|
||||
})
|
||||
.catch(error => console.log(error));
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../../../scss/settings";
|
||||
|
||||
nav.flex-column {
|
||||
background-color: $sidebar-background;
|
||||
|
||||
hr {
|
||||
border-top-width: 0;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
color: #fff;
|
||||
background: $sidebar-background;
|
||||
text-align: center;
|
||||
margin: 1rem;
|
||||
|
||||
h2 {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
color: #ddd !important;
|
||||
padding-top: 0.6rem;
|
||||
padding-bottom: 0.6rem;
|
||||
text-align: left;
|
||||
|
||||
a {
|
||||
color: #ddd !important;
|
||||
}
|
||||
|
||||
.fa-stack {
|
||||
height: 2.3em;
|
||||
margin-right: 0.5rem;
|
||||
|
||||
i:last-child {
|
||||
color: #444;
|
||||
}
|
||||
}
|
||||
|
||||
& > i.dropdown.icon {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
&.separator {
|
||||
padding: 1rem 1rem 0.5rem;
|
||||
color: rgba(200, 200, 200, 0.5) !important;
|
||||
.fas {
|
||||
padding: 0 1.1rem 0 0.65rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.active,
|
||||
&.current {
|
||||
background-color: $sidebar-active !important;
|
||||
color: #fff !important;
|
||||
|
||||
> a {
|
||||
color: #fff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
transform: translateX(140px) !important;
|
||||
padding-bottom: 0;
|
||||
|
||||
a {
|
||||
padding: 0.25rem 0.75rem;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
width: 100%;
|
||||
background-color: #eee;
|
||||
border-top: 1px solid #ddd;
|
||||
margin-top: 0.5rem;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background-color: #eee;
|
||||
border: 0;
|
||||
flex: 1;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
.btn:hover {
|
||||
background-color: #ccc;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,66 +0,0 @@
|
||||
<template>
|
||||
<div class="nav btn-toolbar nav-fill" role="toolbar" aria-label="Toolbar with button groups">
|
||||
<span class="topbar-title nav-item" v-html="title">{{ title }}</span>
|
||||
<div class="input-group nav-item">
|
||||
<div class="input-group-prepend">
|
||||
<div class="input-group-text" id="btnGroupAddon">@</div>
|
||||
</div>
|
||||
<input type="text" class="form-control" placeholder="Search …" aria-label="Search …" aria-describedby="btnGroupAddon">
|
||||
</div>
|
||||
|
||||
<a href="/" class="btn btn-light nav-item">
|
||||
<i class="fas fa-external-link-square-alt"></i> View site
|
||||
</a>
|
||||
|
||||
<div class="btn-group nav-item" role="group">
|
||||
<button id="btnGroupDrop1" type="button" class="btn btn-light dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="text"><i class="fas fa-user-circle"></i> Admin</span>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="btnGroupDrop1">
|
||||
<a href="/bolt/profile-edit" class="dropdown-item">Edit profile</a>
|
||||
<a href="/bolt/logout" class="dropdown-item">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
module.exports = {
|
||||
data: function() {
|
||||
return {
|
||||
title: this.$attrs["title"]
|
||||
};
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.nav.btn-toolbar {
|
||||
margin: 0.5rem 1rem 0 3rem;
|
||||
|
||||
.nav-item {
|
||||
flex-grow: 0;
|
||||
margin-right: 0.6rem;
|
||||
}
|
||||
|
||||
.nav-item.topbar-title {
|
||||
font-family: "Source Sans Pro", serif;
|
||||
font-size: 22px;
|
||||
color: #222;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: left;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.btn-light {
|
||||
background-color: #eee;
|
||||
border: 1px solid #d8d8d8;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -2,15 +2,15 @@ import Vue from "vue";
|
||||
/**
|
||||
* Editor Components
|
||||
*/
|
||||
import Sidebar from "../Components/Base/Sidebar";
|
||||
import Topbar from "../Components/Base/Topbar";
|
||||
import DashboardNews from "../Components/Base/DashboardNews";
|
||||
import DashboardContentList from "../Components/Base/DashboardContentList";
|
||||
import Sidebar from "../Components/Admin/Sidebar";
|
||||
import Topbar from "../Components/Admin/Topbar";
|
||||
import DashboardNews from "../Components/Admin/DashboardNews";
|
||||
import DashboardContentList from "../Components/Admin/DashboardContentList";
|
||||
/**
|
||||
* Register Components
|
||||
*/
|
||||
Vue.component("sidebar", Sidebar);
|
||||
Vue.component("topbar", Topbar);
|
||||
Vue.component("admin-sidebar", Sidebar);
|
||||
Vue.component("admin-topbar", Topbar);
|
||||
Vue.component("dashboardnews", DashboardNews);
|
||||
Vue.component("dashboardcontentlist", DashboardContentList);
|
||||
|
||||
@@ -34,4 +34,4 @@ window.jQuery = $;
|
||||
* Vue Components
|
||||
*/
|
||||
import "./Views/editor";
|
||||
import "./Views/base";
|
||||
import "./Views/admin";
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
html,
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol";
|
||||
font-size: 13px;
|
||||
line-height: 1.5;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
@media only screen and (min-width: 1025px) {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 1281px) {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
background: $main-background;
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4,
|
||||
h5,
|
||||
h6 {
|
||||
font-family: "Source Sans Pro", serif;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: bold;
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
line-height: 4rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: grid;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
grid-template-areas:
|
||||
"topbar"
|
||||
"sidebar"
|
||||
"content"
|
||||
"sidebar2"
|
||||
"footer";
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 600px) {
|
||||
.wrapper {
|
||||
grid-template-columns: 12.6rem auto 21rem;
|
||||
grid-template-rows: 3.6rem auto 2rem;
|
||||
grid-template-areas:
|
||||
"sidebar topbar topbar"
|
||||
"sidebar content aside"
|
||||
"sidebar footer footer";
|
||||
}
|
||||
|
||||
.wrapper.has-widecontent {
|
||||
grid-template-columns: 12.6rem auto 21rem;
|
||||
grid-template-rows: 3.6rem auto 2rem;
|
||||
grid-template-areas:
|
||||
"sidebar topbar topbar"
|
||||
"sidebar content content"
|
||||
"sidebar footer footer";
|
||||
}
|
||||
}
|
||||
|
||||
#sidebar {
|
||||
grid-area: sidebar;
|
||||
background-color: $sidebar-background;
|
||||
border-right: 1px solid #233;
|
||||
}
|
||||
|
||||
header {
|
||||
grid-area: topbar;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
#content,
|
||||
#vuecontent {
|
||||
grid-area: content;
|
||||
padding: 2rem 3rem;
|
||||
}
|
||||
|
||||
#widecontent {
|
||||
grid-area: content;
|
||||
padding: 2rem 3rem;
|
||||
+ aside {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
grid-area: footer;
|
||||
}
|
||||
|
||||
aside {
|
||||
grid-area: aside;
|
||||
padding: 2rem 2rem 2rem 0;
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
//** Styling
|
||||
@import './vendor/vendor';
|
||||
@import './layout/layout';
|
||||
@import './modules/modules';
|
||||
|
||||
|
||||
@import "settings";
|
||||
@import "textstyles";
|
||||
@import "layout";
|
||||
@import "bootstrap-overrides";
|
||||
@import "forms";
|
||||
@import "listings";
|
||||
|
||||
66
assets/scss/layout/_admin.scss
Normal file
66
assets/scss/layout/_admin.scss
Normal file
@@ -0,0 +1,66 @@
|
||||
//** Layout | Admin
|
||||
|
||||
$admin-header-height: 80px;
|
||||
$admin-sidebar-width: 180px;
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
background: color('gray')
|
||||
}
|
||||
|
||||
// Main Layout Grid
|
||||
|
||||
.admin {
|
||||
|
||||
// Flexbox Fallback
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
// Grid
|
||||
display: grid;
|
||||
height: 100vh;
|
||||
|
||||
grid-template-rows: auto 1fr auto;
|
||||
grid-template-columns: $admin-sidebar-width 1fr;
|
||||
grid-template-areas: "sidebar header"
|
||||
"sidebar body";
|
||||
// Slim Sidebar
|
||||
&.is-slim {
|
||||
grid-template-columns: $admin-sidebar-width / 3 1fr;
|
||||
&__sidebar {
|
||||
flex: 0 0 $admin-sidebar-width / 3;
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
flex-basis: 100%;
|
||||
grid-area: header;
|
||||
height: $admin-header-height;
|
||||
position: relative;
|
||||
padding: 0 $spacer * 2;
|
||||
}
|
||||
|
||||
&__sidebar {
|
||||
flex: 0 0 $admin-sidebar-width;
|
||||
grid-area: sidebar;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
&__body {
|
||||
flex: 1;
|
||||
grid-area: body;
|
||||
padding: $spacer * 2;
|
||||
>.container{
|
||||
display: flex;
|
||||
}
|
||||
&--main{
|
||||
padding-right: $spacer * 3;
|
||||
flex: 100%;
|
||||
}
|
||||
&--aside{
|
||||
flex: 0 0 $admin-sidebar-width * 1.25;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
3
assets/scss/layout/layout.scss
Normal file
3
assets/scss/layout/layout.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
//** Layouts
|
||||
|
||||
@import './_admin';
|
||||
45
assets/scss/modules/admin/_header.scss
Normal file
45
assets/scss/modules/admin/_header.scss
Normal file
@@ -0,0 +1,45 @@
|
||||
//** Admin | Header
|
||||
|
||||
.admin__header{
|
||||
&--title{
|
||||
font-weight: $font-weight-light;
|
||||
font-size: $h3-font-size;
|
||||
}
|
||||
&--topbar{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
&--toolbar{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
li{
|
||||
display: inline-flex;
|
||||
margin-right: $spacer;
|
||||
&:last-child{
|
||||
margin-right: 0;
|
||||
}
|
||||
.toolbar--link{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: $white;
|
||||
box-shadow: $custom-range-thumb-box-shadow;
|
||||
border-radius: 100%;
|
||||
&:hover{
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
i{
|
||||
color: theme-color('primary')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
185
assets/scss/modules/admin/_sidebar.scss
Normal file
185
assets/scss/modules/admin/_sidebar.scss
Normal file
@@ -0,0 +1,185 @@
|
||||
//** Admin | Sidebar
|
||||
|
||||
.admin__sidebar{
|
||||
position: relative;
|
||||
z-index: 1000;
|
||||
background: $white;
|
||||
height: 100%;
|
||||
box-shadow: 0 0 40px 0 transparentize(theme-color('secondary'), 0.9);
|
||||
&.is-slim{
|
||||
.admin__sidebar--brand{
|
||||
padding: $spacer $spacer / 2;
|
||||
img{
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
}
|
||||
.admin__sidebar--create, .admin__sidebar--separator, .admin__sidebar--footer{
|
||||
display: none;
|
||||
}
|
||||
.admin__sidebar--link{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: $spacer $spacer / 2;
|
||||
.link--icon{
|
||||
font-size: 110%;
|
||||
margin: 0;
|
||||
width: auto;
|
||||
}
|
||||
.link--text{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.admin__sidebar--slim{
|
||||
width: $admin-sidebar-width / 3;
|
||||
}
|
||||
}
|
||||
&--brand{
|
||||
padding: $spacer;
|
||||
text-align: center;
|
||||
display: block;
|
||||
img{
|
||||
height: 64px;
|
||||
}
|
||||
}
|
||||
&--create{
|
||||
padding: $spacer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
&--separator{
|
||||
padding: 0 $spacer;
|
||||
margin: $spacer / 2 0;
|
||||
color: $gray-600;
|
||||
font-weight: $font-weight-bold;
|
||||
text-transform: uppercase;
|
||||
font-size: $small-font-size;
|
||||
letter-spacing: 1.2px;
|
||||
}
|
||||
&--menu{
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
list-style: none;
|
||||
}
|
||||
&--link{
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: $spacer / 1.5 $spacer;
|
||||
display: block;
|
||||
color: $gray-600;
|
||||
font-weight: $font-weight-bold;
|
||||
letter-spacing: 1.2px;
|
||||
font-size: 95%;
|
||||
&:hover{
|
||||
background: darken($white, 2%);
|
||||
text-decoration: none;
|
||||
.link--icon{
|
||||
transform: scale(1.2);
|
||||
}
|
||||
}
|
||||
&.has-menu{
|
||||
&:hover, &:focus{
|
||||
.link--caret{
|
||||
color: theme-color('primary');
|
||||
transform: translateX(2px);
|
||||
}
|
||||
.link--menu{
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
.link--icon{
|
||||
transition: $transition-base;
|
||||
transform-origin: center;
|
||||
color: theme-color('primary');
|
||||
width: 20px;
|
||||
}
|
||||
.link--caret{
|
||||
transition: $transition-base;
|
||||
color: $gray-400;
|
||||
width: 15px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.link--menu{
|
||||
background: theme-color('secondary');
|
||||
border-radius: 0 $border-radius $border-radius 0;
|
||||
position: absolute;
|
||||
left: 100%;
|
||||
top: 0;
|
||||
width: $admin-sidebar-width * 1.5;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
visibility: hidden;
|
||||
li{
|
||||
&.link--create{
|
||||
border-bottom: dashed 1px darken(theme-color('secondary'), 10%);
|
||||
a{
|
||||
font-weight: $font-weight-bold;
|
||||
letter-spacing: 1.2px;
|
||||
padding: $spacer;
|
||||
}
|
||||
}
|
||||
a{
|
||||
padding: $spacer / 2 $spacer;
|
||||
color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: $font-weight-normal;
|
||||
letter-spacing: initial;
|
||||
&:hover{
|
||||
background: darken(theme-color('secondary'), 10%);
|
||||
text-decoration: none;
|
||||
}
|
||||
span{
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&--slim{
|
||||
width: $admin-sidebar-width;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
text-align: center;
|
||||
color: theme-color('primary');
|
||||
font-size: $font-size-lg;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 40px;
|
||||
&:hover, &:focus{
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
&--footer{
|
||||
-webkit-backface-visibility: hidden;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: 40px;
|
||||
width: $admin-sidebar-width;
|
||||
padding: 0 $spacer;
|
||||
background: darken($white, 2%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: theme-color('secondary');
|
||||
font-weight: $font-weight-bold;
|
||||
text-transform: uppercase;
|
||||
font-size: $small-font-size;
|
||||
letter-spacing: 1.2px;
|
||||
}
|
||||
}
|
||||
4
assets/scss/modules/admin/admin.scss
Normal file
4
assets/scss/modules/admin/admin.scss
Normal file
@@ -0,0 +1,4 @@
|
||||
//** Admin Modules
|
||||
|
||||
@import '_sidebar';
|
||||
@import '_header';
|
||||
@@ -1,5 +0,0 @@
|
||||
//** Admin | Sidebar
|
||||
|
||||
.admin__sidebar{
|
||||
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
//** Admin Modules
|
||||
|
||||
@import '_sidebar.scss';
|
||||
38
assets/scss/modules/editor/_tabbar.scss
Normal file
38
assets/scss/modules/editor/_tabbar.scss
Normal file
@@ -0,0 +1,38 @@
|
||||
//** Editor | Tab Bar
|
||||
|
||||
.editor__tabbar{
|
||||
margin-bottom: $spacer * 2;
|
||||
border-bottom: solid 2px $gray-400;
|
||||
.nav-item{
|
||||
color: $gray-600;
|
||||
position: relative;
|
||||
&:after{
|
||||
transition: $transition-base;
|
||||
position: absolute;
|
||||
bottom: -2px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 2px;
|
||||
background: theme-color('primary');
|
||||
transform-origin: center;
|
||||
transform: scaleX(0);
|
||||
content: '';
|
||||
}
|
||||
span{
|
||||
transition: $transition-base;
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
letter-spacing: 1.2px;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
&.active, &.show{
|
||||
&:after{
|
||||
transform: scaleX(1);
|
||||
}
|
||||
span{
|
||||
transform: translateY(-2px);
|
||||
color: theme-color('primary');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
assets/scss/modules/editor/editor.scss
Normal file
3
assets/scss/modules/editor/editor.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
//** Editor Modules
|
||||
|
||||
@import '_tabbar';
|
||||
@@ -1,4 +1,5 @@
|
||||
//** Modules
|
||||
|
||||
@import './base/base';
|
||||
@import './admin/admin';
|
||||
@import './editor/editor';
|
||||
@import './fields/fields';
|
||||
|
||||
1
assets/scss/vendor/bootstrap/_overrides.scss
vendored
1
assets/scss/vendor/bootstrap/_overrides.scss
vendored
@@ -7,6 +7,7 @@ $colors: (
|
||||
$theme-colors: (
|
||||
"primary": #2e2ec2,
|
||||
"secondary": #4c5377,
|
||||
"success": #08bb68,
|
||||
"status-published": #7fa800,
|
||||
"status-draft": #0569e2,
|
||||
"status-held": #ca2300,
|
||||
|
||||
2
assets/scss/vendor/bootstrap/bootstrap.scss
vendored
2
assets/scss/vendor/bootstrap/bootstrap.scss
vendored
@@ -1,4 +1,4 @@
|
||||
//** Bootstrap
|
||||
|
||||
@import '_overrides.scss';
|
||||
@import "~bootstrap/scss/bootstrap";
|
||||
@import "~bootstrap/scss/bootstrap";
|
||||
12608
public/assets/bolt.css
12608
public/assets/bolt.css
File diff suppressed because one or more lines are too long
78856
public/assets/bolt.js
78856
public/assets/bolt.js
File diff suppressed because one or more lines are too long
7
public/assets/brand.svg
Normal file
7
public/assets/brand.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 121 105">
|
||||
<g fill="#2e2ec2" fill-rule="evenodd">
|
||||
<path d="M29.843 103.857L0 51.812 30.25 0l60.088.23 29.844 52.05-30.245 51.818-60.084-.23-.01-.011zm6.5438-9.9537l.00785.00889 47.0855.18581L107.182 52.23562l-23.3876-42.0498L36.70577 10 13 51.85753 36.3868 93.9033z"/>
|
||||
<path fill-rule="nonzero" d="M42 42h10v20H42z"/>
|
||||
<path fill-rule="nonzero" d="M49.95 47h30v10h-30z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 450 B |
@@ -1 +1,101 @@
|
||||
!function(r){function n(e){if(t[e])return t[e].exports;var o=t[e]={i:e,l:!1,exports:{}};return r[e].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var e=window.webpackJsonp;window.webpackJsonp=function(t,u,c){for(var f,i,p,a=0,s=[];a<t.length;a++)i=t[a],o[i]&&s.push(o[i][0]),o[i]=0;for(f in u)Object.prototype.hasOwnProperty.call(u,f)&&(r[f]=u[f]);for(e&&e(t,u,c);s.length;)s.shift()();if(c)for(a=0;a<c.length;a++)p=n(n.s=c[a]);return p};var t={},o={2:0};n.m=r,n.c=t,n.d=function(r,e,t){n.o(r,e)||Object.defineProperty(r,e,{configurable:!1,enumerable:!0,get:t})},n.n=function(r){var e=r&&r.__esModule?function(){return r.default}:function(){return r};return n.d(e,"a",e),e},n.o=function(r,n){return Object.prototype.hasOwnProperty.call(r,n)},n.p="/assets/",n.oe=function(r){throw console.error(r),r}}([]);
|
||||
/******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // install a JSONP callback for chunk loading
|
||||
/******/ var parentJsonpFunction = window["webpackJsonp"];
|
||||
/******/ window["webpackJsonp"] = function webpackJsonpCallback(chunkIds, moreModules, executeModules) {
|
||||
/******/ // add "moreModules" to the modules object,
|
||||
/******/ // then flag all "chunkIds" as loaded and fire callback
|
||||
/******/ var moduleId, chunkId, i = 0, resolves = [], result;
|
||||
/******/ for(;i < chunkIds.length; i++) {
|
||||
/******/ chunkId = chunkIds[i];
|
||||
/******/ if(installedChunks[chunkId]) {
|
||||
/******/ resolves.push(installedChunks[chunkId][0]);
|
||||
/******/ }
|
||||
/******/ installedChunks[chunkId] = 0;
|
||||
/******/ }
|
||||
/******/ for(moduleId in moreModules) {
|
||||
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
|
||||
/******/ modules[moduleId] = moreModules[moduleId];
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ if(parentJsonpFunction) parentJsonpFunction(chunkIds, moreModules, executeModules);
|
||||
/******/ while(resolves.length) {
|
||||
/******/ resolves.shift()();
|
||||
/******/ }
|
||||
/******/ if(executeModules) {
|
||||
/******/ for(i=0; i < executeModules.length; i++) {
|
||||
/******/ result = __webpack_require__(__webpack_require__.s = executeModules[i]);
|
||||
/******/ }
|
||||
/******/ }
|
||||
/******/ return result;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
/******/
|
||||
/******/ // objects to store loaded and loading chunks
|
||||
/******/ var installedChunks = {
|
||||
/******/ 2: 0
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
/******/
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId]) {
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
/******/ }
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ i: moduleId,
|
||||
/******/ l: false,
|
||||
/******/ exports: {}
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
/******/
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.l = true;
|
||||
/******/
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
/******/
|
||||
/******/
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
/******/
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
/******/
|
||||
/******/ // define getter function for harmony exports
|
||||
/******/ __webpack_require__.d = function(exports, name, getter) {
|
||||
/******/ if(!__webpack_require__.o(exports, name)) {
|
||||
/******/ Object.defineProperty(exports, name, {
|
||||
/******/ configurable: false,
|
||||
/******/ enumerable: true,
|
||||
/******/ get: getter
|
||||
/******/ });
|
||||
/******/ }
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
||||
/******/ __webpack_require__.n = function(module) {
|
||||
/******/ var getter = module && module.__esModule ?
|
||||
/******/ function getDefault() { return module['default']; } :
|
||||
/******/ function getModuleExports() { return module; };
|
||||
/******/ __webpack_require__.d(getter, 'a', getter);
|
||||
/******/ return getter;
|
||||
/******/ };
|
||||
/******/
|
||||
/******/ // Object.prototype.hasOwnProperty.call
|
||||
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
||||
/******/
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "/assets/";
|
||||
/******/
|
||||
/******/ // on error function for async loading
|
||||
/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([]);
|
||||
10949
public/assets/vendor.js
10949
public/assets/vendor.js
File diff suppressed because one or more lines are too long
@@ -14,41 +14,50 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="admin wrapper has-{{ block('container') }}">
|
||||
<div class="admin has-{{ block('container') }}">
|
||||
|
||||
<header data-vue-routing="{{ vueRouting|default() }}">
|
||||
<Topbar title="{{ block('title') }}"></Topbar>
|
||||
<!-- Admin Header -->
|
||||
<header class="admin__header">
|
||||
<div class="container">
|
||||
<admin-topbar title="{{ block('title') }}"></admin-topbar>
|
||||
</div>
|
||||
</header>
|
||||
<!-- End Admin Header -->
|
||||
|
||||
|
||||
<div id="sidebar">
|
||||
<Sidebar sidebarmenudata="{{ sidebarmenu() }}">side</Sidebar>
|
||||
<!-- Admin Sidebar -->
|
||||
<div id="sidebar" class="admin__sidebar">
|
||||
<admin-sidebar
|
||||
:brand="'{{ asset('assets/brand.svg') }}'"
|
||||
:menu="{{ sidebarmenu() }}"
|
||||
:version="'{{ version|default('unknown') }}'"
|
||||
></admin-sidebar >
|
||||
</div>
|
||||
<!-- End Admin Sidebar -->
|
||||
|
||||
<div id="{% block container %}content{% endblock %}">
|
||||
|
||||
{{ include('_partials/_flash_messages.twig') }}
|
||||
|
||||
{% block main %}
|
||||
{% endblock %}
|
||||
|
||||
<!-- Admin Main -->
|
||||
<div class="admin__body" id="{% block container %}content{% endblock %}">
|
||||
<div class="container">
|
||||
{{ include('_partials/_flash_messages.twig') }}
|
||||
<main class="admin__body--main">
|
||||
{% block main %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
<aside class="admin__body--aside">
|
||||
{% block aside %}
|
||||
{% endblock %}
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside>
|
||||
{% block aside %}
|
||||
{% endblock %}
|
||||
</aside>
|
||||
|
||||
<footer>
|
||||
Bolt {{ version|default('unknown') }}
|
||||
</footer>
|
||||
<!-- End Admin Main -->
|
||||
|
||||
</div>
|
||||
|
||||
{% block javascripts %}
|
||||
<script src="{{ asset('assets/manifest.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendor.js') }}"></script>
|
||||
<script src="{{ asset('assets/bolt.js') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
@@ -10,23 +10,49 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block main %}
|
||||
|
||||
<form method="post" id="editcontent" >
|
||||
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('editrecord') }}">
|
||||
|
||||
<!-- fields -->
|
||||
{% for key, fielddefinition in record.definition.fields %}
|
||||
{% set groups = record.definition.groups %}
|
||||
<nav>
|
||||
<ul class="nav editor__tabbar" role="tablist">
|
||||
{% for group in groups %}
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-item nav-link {% if loop.first %}active{% endif %}"
|
||||
id="{{group|slug}}-tab-link"
|
||||
data-toggle="pill"
|
||||
href="#{{group|slug}}-tab"
|
||||
role="tab"
|
||||
aria-controls="{{group|slug}}"
|
||||
aria-selected="false"
|
||||
>
|
||||
<span>{{group|capitalize}}</span></a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
{% for group in groups %}
|
||||
<div class="tab-pane {% if loop.first %}show active{% endif %}" id="{{group|slug}}-tab" role="tabpanel" aria-labelledby="{{group|slug}}-tab-link">
|
||||
{% for key, fielddefinition in record.definition.fields %}
|
||||
{% set type = fielddefinition.type %}
|
||||
{% set field = record.field(key) %}
|
||||
{% set fieldgroup = fielddefinition.group %}
|
||||
{% if not field %}
|
||||
{% set field = fieldfactory(fielddefinition, key) %}
|
||||
{% endif %}
|
||||
{% if fieldgroup == group %}
|
||||
{% include ['editcontent/fields/' ~ type ~ '.twig', 'editcontent/fields/generic.twig' ] with { 'field': field} %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% set type = fielddefinition.type %}
|
||||
{% set field = record.field(key) %}
|
||||
{% if not field %}
|
||||
{% set field = fieldfactory(fielddefinition, key) %}
|
||||
{% endif %}
|
||||
|
||||
{% include ['editcontent/fields/' ~ type ~ '.twig', 'editcontent/fields/generic.twig' ] with { 'field': field} %}
|
||||
|
||||
{% endfor %}
|
||||
|
||||
<input type="submit" class="btn btn-primary" value="Save">
|
||||
|
||||
@@ -42,7 +68,7 @@
|
||||
<div class="card-body">
|
||||
<form class="ui form">
|
||||
|
||||
<button type="submit" class="btn btn-primary mb-3" form="editcontent">
|
||||
<button type="submit" class="btn btn-success mb-3" form="editcontent">
|
||||
<i class="fas fa-save mr-2"></i>Save
|
||||
</button>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user