Compare commits
No commits in common. "main" and "typescript" have entirely different histories.
main
...
typescript
|
@ -1,3 +1,3 @@
|
|||
> 1%
|
||||
last 2 versions
|
||||
not ie <= 8
|
||||
not dead
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
[*.{js,jsx,ts,tsx,vue}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
34
.eslintrc.js
34
.eslintrc.js
|
@ -3,15 +3,29 @@ module.exports = {
|
|||
env: {
|
||||
node: true
|
||||
},
|
||||
'extends': [
|
||||
'plugin:vue/essential',
|
||||
'@vue/standard'
|
||||
extends: [
|
||||
"plugin:vue/essential",
|
||||
"eslint:recommended",
|
||||
"@vue/typescript/recommended",
|
||||
"@vue/prettier",
|
||||
"@vue/prettier/@typescript-eslint"
|
||||
],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
},
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
}
|
||||
}
|
||||
ecmaVersion: 2020
|
||||
},
|
||||
rules: {
|
||||
"no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
|
||||
"no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: [
|
||||
"**/__tests__/*.{j,t}s?(x)",
|
||||
"**/tests/unit/**/*.spec.{j,t}s?(x)"
|
||||
],
|
||||
env: {
|
||||
jest: true
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,6 +2,7 @@
|
|||
node_modules
|
||||
/dist
|
||||
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
@ -10,6 +11,7 @@ node_modules
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
|
|
29
README.md
29
README.md
|
@ -1,2 +1,29 @@
|
|||
# Rebuilding Platform.sh with Vue.js and Tailwind CSS
|
||||
# Rebuilding Platform.sh with Vue.js, TypeScript and Tailwind CSS
|
||||
|
||||
## Project setup
|
||||
```
|
||||
yarn install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
yarn serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
yarn build
|
||||
```
|
||||
|
||||
### Run your unit tests
|
||||
```
|
||||
yarn test:unit
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
yarn lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
|
|
3
assets/css/tailwind.pcss
Normal file
3
assets/css/tailwind.pcss
Normal file
|
@ -0,0 +1,3 @@
|
|||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
|
@ -1,5 +1,3 @@
|
|||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
]
|
||||
}
|
||||
presets: ["@vue/cli-plugin-babel/preset"]
|
||||
};
|
||||
|
|
|
@ -1,30 +1,3 @@
|
|||
module.exports = {
|
||||
moduleFileExtensions: [
|
||||
'js',
|
||||
'jsx',
|
||||
'json',
|
||||
'vue'
|
||||
],
|
||||
transform: {
|
||||
'^.+\\.vue$': 'vue-jest',
|
||||
'.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 'jest-transform-stub',
|
||||
'^.+\\.jsx?$': 'babel-jest'
|
||||
},
|
||||
transformIgnorePatterns: [
|
||||
'/node_modules/'
|
||||
],
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1'
|
||||
},
|
||||
snapshotSerializers: [
|
||||
'jest-serializer-vue'
|
||||
],
|
||||
testMatch: [
|
||||
'**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
|
||||
],
|
||||
testURL: 'http://localhost/',
|
||||
watchPlugins: [
|
||||
'jest-watch-typeahead/filename',
|
||||
'jest-watch-typeahead/testname'
|
||||
]
|
||||
}
|
||||
preset: "@vue/cli-plugin-unit-jest/presets/typescript-and-babel"
|
||||
};
|
||||
|
|
56
package.json
56
package.json
|
@ -5,35 +5,39 @@
|
|||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint",
|
||||
"test:unit": "vue-cli-service test:unit"
|
||||
"test:unit": "vue-cli-service test:unit",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^2.6.5",
|
||||
"postcss": "^7.0.17",
|
||||
"sugarss": "^2.0.0",
|
||||
"tailwindcss-interaction-variants": "^2.0.0-beta.1",
|
||||
"tailwindcss-spaced-items": "^0.1.0",
|
||||
"tailwindcss-transforms": "^2.2.0",
|
||||
"tailwindcss-visuallyhidden": "^1.0.2",
|
||||
"vue": "^2.6.10",
|
||||
"vue-router": "^3.1.0"
|
||||
"@tailwindcss/postcss7-compat": "^2.0.2",
|
||||
"autoprefixer": "^9",
|
||||
"core-js": "^3.6.5",
|
||||
"postcss": "^7",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
|
||||
"tailwindcss-interaction-variants": "^5.0.0",
|
||||
"vue": "^2.6.11",
|
||||
"vue-class-component": "^7.2.3",
|
||||
"vue-property-decorator": "^9.1.2",
|
||||
"vue-router": "^3.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@fullhuman/postcss-purgecss": "^1.2.0",
|
||||
"@vue/cli-plugin-babel": "^3.6.0",
|
||||
"@vue/cli-plugin-eslint": "^3.6.0",
|
||||
"@vue/cli-plugin-unit-jest": "^3.6.3",
|
||||
"@vue/cli-service": "^3.10.0",
|
||||
"@vue/eslint-config-standard": "^4.0.0",
|
||||
"@vue/test-utils": "1.0.0-beta.29",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"babel-jest": "^23.6.0",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-vue": "^5.2.3",
|
||||
"postcss-import": "^12.0.1",
|
||||
"tailwindcss": "^1.0.6",
|
||||
"vue-template-compiler": "^2.5.21"
|
||||
"@types/jest": "^24.0.19",
|
||||
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
||||
"@typescript-eslint/parser": "^2.33.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.0",
|
||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||
"@vue/cli-plugin-router": "~4.5.0",
|
||||
"@vue/cli-plugin-typescript": "~4.5.0",
|
||||
"@vue/cli-plugin-unit-jest": "~4.5.0",
|
||||
"@vue/cli-service": "~4.5.0",
|
||||
"@vue/eslint-config-prettier": "^6.0.0",
|
||||
"@vue/eslint-config-typescript": "^5.0.2",
|
||||
"@vue/test-utils": "^1.0.3",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-prettier": "^3.1.3",
|
||||
"eslint-plugin-vue": "^6.2.2",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "~3.9.3",
|
||||
"vue-template-compiler": "^2.6.11"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,5 @@
|
|||
module.exports = {
|
||||
parser: 'sugarss',
|
||||
plugins: [
|
||||
require('postcss-import'),
|
||||
require('tailwindcss'),
|
||||
require('postcss-nested'),
|
||||
require('autoprefixer'),
|
||||
process.env.NODE_ENV === 'production' && require('@fullhuman/postcss-purgecss')({
|
||||
content: [
|
||||
'./src/**/*.vue',
|
||||
'./public/index.html',
|
||||
],
|
||||
defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || []
|
||||
})
|
||||
require('tailwindcss')
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
https://rebuilding-platformsh.netlify.com/* https://rebuilding-platformsh.oliverdavies.uk/:splat 301!
|
||||
|
|
@ -1,16 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title>rebuilding-platformsh</title>
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,600,700" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but rebuilding-platformsh doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
|
|
27
src/App.vue
27
src/App.vue
|
@ -1,29 +1,16 @@
|
|||
<template>
|
||||
<div class="min-h-screen antialiased font-sans bg-gray-200">
|
||||
<div id="app" class="min-h-screen antialiased font-sans bg-gray-200">
|
||||
<alert-message>
|
||||
<p>
|
||||
A clone of <a href="https://platform.sh">Platform.sh</a>’s new hosting dashboard.<br class="hidden sm:inline">
|
||||
Built with <a href="https://vuejs.org">Vue.js</a>
|
||||
and <a href="https://tailwindcss.com">Tailwind CSS</a>
|
||||
by <a href="https://www.oliverdavies.uk">Oliver Davies</a>.
|
||||
<!-- eslint-disable-next-line -->
|
||||
A clone of <a href="https://platform.sh">Platform.sh</a>’s hosting dashboard.<br class="hidden sm:inline" />
|
||||
<!-- eslint-disable-next-line -->
|
||||
Built with <a href="https://vuejs.org">Vue.js</a> and <a href="https://tailwindcss.com">Tailwind CSS</a> by <a href="https://www.oliverdavies.uk">Oliver Davies</a>.
|
||||
</p>
|
||||
</alert-message>
|
||||
|
||||
<router-view :projects="projects" ></router-view>
|
||||
<router-view />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style src="./assets/css/tailwind.css"></style>
|
||||
|
||||
<script>
|
||||
import projects from './data/projects.json'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
title: 'Rebuilding Platform.sh',
|
||||
projects
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style src="../assets/css/tailwind.pcss" lang="postcss" />
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
a:hover
|
||||
@apply underline
|
|
@ -1 +0,0 @@
|
|||
@import './components/search-form.css'
|
|
@ -1,3 +0,0 @@
|
|||
.search-form
|
||||
> input:focus + svg
|
||||
@apply opacity-100
|
|
@ -1,7 +0,0 @@
|
|||
@import 'tailwindcss/base'
|
||||
@import './base.css'
|
||||
|
||||
@import 'tailwindcss/components'
|
||||
@import './components.css'
|
||||
|
||||
@import 'tailwindcss/utilities'
|
Binary file not shown.
Before Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
Before Width: | Height: | Size: 477 KiB |
Binary file not shown.
Before Width: | Height: | Size: 124 KiB |
Binary file not shown.
Before Width: | Height: | Size: 237 KiB |
Binary file not shown.
Before Width: | Height: | Size: 76 KiB |
|
@ -1,14 +0,0 @@
|
|||
<template>
|
||||
<section class="bg-gun-powder p-3 text-center text-white text-sm font-semibold">
|
||||
<slot></slot>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<style type="postcss" scoped>
|
||||
a
|
||||
@apply underline
|
||||
|
||||
&:hover,
|
||||
&:focus
|
||||
@apply no-underline
|
||||
</style>
|
|
@ -1,27 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<header class="bg-gray-900 text-white pt-4 pb-12">
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="flex-1 flex justify-between items-center -mx-4">
|
||||
<div class="w-1/7 px-4">
|
||||
<router-link :to="{ name: 'projects' }">
|
||||
<svg alt="icon" class="w-6 h-6" viewBox="0 0 28 28" version="1.1" xmlns="http://www.w3.org/2000/svg"><defs><polygon id="path-1" points="0 0 27.6677333 0 27.6677333 11.0021333 0 11.0021333"></polygon><polygon id="path-3" points="0 0.0373333333 27.6677333 0.0373333333 27.6677333 3.7744 0 3.7744"></polygon><polygon id="path-5" points="0 0.365866667 27.6677333 0.365866667 27.6677333 6.01066667 0 6.01066667"></polygon></defs><g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g transform="translate(-61.000000, -43.000000)"><g transform="translate(61.000000, 43.000000)"><g><mask id="mask-2" fill="white"><use xlink:href="#path-1"></use></mask><g></g><polygon fill="#ffffff" mask="url(#mask-2)" points="-1.86666667 12.8688 29.5344 12.8688 29.5344 -1.86666667 -1.86666667 -1.86666667"></polygon></g><g transform="translate(0.000000, 23.893333)"><mask id="mask-4" fill="white"><use xlink:href="#path-3"></use></mask><polygon fill="#ffffff" mask="url(#mask-4)" points="-1.86666667 5.64106667 29.5344 5.64106667 29.5344 -1.82933333 -1.86666667 -1.82933333"></polygon></g><g transform="translate(0.000000, 14.186667)"><mask id="mask-6" fill="white"><use xlink:href="#path-5"></use></mask><polygon fill="#ffffff" mask="url(#mask-6)" points="-1.86666667 7.87733333 29.5344 7.87733333 29.5344 -1.5008 -1.86666667 -1.5008"></polygon></g></g></g></g></svg>
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<slot name="banner-left"></slot>
|
||||
|
||||
<div class="flex justify-end px-4">
|
||||
<button type="button" class="w-full inline-flex py-1 px-2 rounded font-semibold hover:bg-gray-700">
|
||||
Oliver Davies
|
||||
<svg class="ml-2 w-6 h-6" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M6.90002 9.8999C6.90002 9.5999 7.00002 9.3999 7.20002 9.1999C7.60002 8.7999 8.20002 8.7999 8.60002 9.1999L12.1 12.6999L15.6 9.1999C16 8.7999 16.6 8.7999 17 9.1999C17.4 9.5999 17.4 10.1999 17 10.5999L12.8 14.7999C12.4 15.1999 11.8 15.1999 11.4 14.7999L7.20002 10.5999C7.00002 10.3999 6.90002 10.1999 6.90002 9.8999Z" fill="#ffffff"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="container mx-auto px-4 py-3 -mt-8 mb-4 bg-charade shadow-lg">
|
||||
<slot name="sub-banner"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,5 +0,0 @@
|
|||
<template>
|
||||
<h1 class="font-bold text-2xl text-gray-800">
|
||||
<slot></slot>
|
||||
</h1>
|
||||
</template>
|
|
@ -1,22 +0,0 @@
|
|||
<template>
|
||||
<div class="flex-1 flex items-center text-xs">
|
||||
<ul class="flex spaced-x-1">
|
||||
<li class="flex items-center spaced-x-1">
|
||||
<router-link :to="{ name: 'projects' }" class="font-semibold text-white opacity-75">Projects</router-link>
|
||||
<svg class="h-6 w-6 fill-current text-white opacity-75 -rotate-90" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M6.9 9.9c0-.3.1-.5.3-.7.4-.4 1-.4 1.4 0l3.5 3.5 3.5-3.5c.4-.4 1-.4 1.4 0 .4.4.4 1 0 1.4l-4.2 4.2c-.4.4-1 .4-1.4 0l-4.2-4.2c-.2-.2-.3-.4-.3-.7z"/></svg>
|
||||
</li>
|
||||
<li class="flex items-center font-semibold" v-text="project.name"/>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
project: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,37 +0,0 @@
|
|||
<template>
|
||||
<article>
|
||||
<router-link :to="{ name: 'project', params: { id: project.id }}" class="group block hover:no-underline">
|
||||
<span class="block bg-gray-100 shadow-lg rounded overflow-hidden">
|
||||
<span class="block p-6">
|
||||
<h2 class="font-bold text-gray-800 group-hover:underline" v-text="project.name"/>
|
||||
<p class="text-gray-600" v-text="project.owner"/>
|
||||
<img v-bind="{
|
||||
alt: `Screenshot of ${project.name}`,
|
||||
src: projectImage
|
||||
}" class="w-full mt-4 rounded shadow-2xl" aria-hidden/>
|
||||
</span>
|
||||
|
||||
<span class="-mt-10 py-5 px-8 block relative bg-white">
|
||||
<p v-text="project.region"/>
|
||||
</span>
|
||||
</span>
|
||||
</router-link>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
project: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
projectImage () {
|
||||
return require(`@/assets/img/screenshots/${this.project.image}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,17 +0,0 @@
|
|||
<template>
|
||||
<div class="flex justify-between items-center -mx-4">
|
||||
<div class="px-4 flex-1">
|
||||
<form action="" class="search-form flex flex-row-reverse items-center">
|
||||
<input class="w-full text-sm bg-inherit text-white focus:outline-none" type="text" placeholder="Search projects">
|
||||
<svg class="fill-current text-white h-4 w-4 mr-3 opacity-50" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><mask id="project-search-input-mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="16" height="16"><path fill-rule="evenodd" clip-rule="evenodd" d="M11.8 10.3L15.7 14.2C16 14.6 16 15.2 15.6 15.6C15.2 16 14.6 16 14.2 15.6L10.3 11.7C9.3 12.5 7.9 13 6.5 13C2.9 13 0 10.1 0 6.50005C0 2.90005 2.9 4.57764e-05 6.5 4.57764e-05C10.1 4.57764e-05 13 2.90005 13.1 6.50005C13.1 7.90005 12.6 9.20005 11.8 10.3ZM2 6.50005C2 9.00005 4 11 6.5 11C9 11 11 9.00005 11 6.50005C11 4.00005 9 2.00005 6.5 2.00005C4 2.00005 2 4.00005 2 6.50005Z" fill="#32324c"></path></mask><g mask="url(#project-search-input-mask0)"><rect x="-4" y="-3.99995" width="24" height="24"></rect></g></svg>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="px-4">
|
||||
<a href="#0" class="inline-flex flex-row-reverse items-center px-4 py-2 rounded text-white text-sm bg-blue-700 hocus:bg-blue-800">
|
||||
Add project
|
||||
<svg class="h-3 w-4" xmlns="http://www.w3.org/2000/svg"><path d="M6 6v4H4V6H0V4h4V0h2v4h4v2z" fill="#fff" fill-rule="evenodd"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,34 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
class="p-2 text-gray-700 hover:bg-white hover:rounded hover:shadow"
|
||||
:class="{ 'bg-white rounded shadow text-blue-400': mode == 'grid'}"
|
||||
@click="$emit('changed', 'grid')"
|
||||
>
|
||||
<span class="visuallyhidden">View projects in a grid</span>
|
||||
<svg class="w-6 h-6 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22"><defs><clipPath id="a"><path d="M12.2 5v4.8H17V5zm0 12H17v-4.8h-4.8zM5 5h4.8v4.8H5zm0 12v-4.8h4.8V17z" fill="none" clip-rule="evenodd"/></clipPath><clipPath id="b"><path fill="none" d="M0 0h22v22H0z"/></clipPath><clipPath id="c"><path fill="none" d="M5 5h12v12H5z"/></clipPath></defs><g clip-path="url("#a")"><g clip-path="url("#b")" style="clip-path:url("#icon-grid-b")"><g clip-path="url("#c")"><path d="M0 0h22v22H0z"/></g></g></g></svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="ml-2 p-2 text-gray-700 hover:bg-white hover:rounded hover:shadow"
|
||||
:class="{ 'bg-white rounded shadow text-blue-400': mode == 'list'}"
|
||||
@click="$emit('changed', 'list')"
|
||||
>
|
||||
<span class="visuallyhidden">View projects in a list</span>
|
||||
<svg class="w-6 h-6 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 22"><defs><clipPath id="link-icon-a"><path d="M5,5V7H19V5Zm14,7V10H5v2ZM5,17H19V15H5Z" style="fill: none; clip-rule: evenodd;"></path></clipPath><clipPath id="link-icon-b"><rect width="24" height="22" style="fill: none;"></rect></clipPath><clipPath id="link-icon-c"><rect x="5" y="5" width="14" height="12" style="fill: none;"></rect></clipPath></defs><title>Asset 1</title><g style="clip-path: url("#link-icon-a");"><g style="clip-path: url("#link-icon-b");"><g style="clip-path: url("#link-icon-c");"><rect width="24" height="22"></rect></g></g></g></svg>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
mode: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
14
src/components/alert-message.vue
Normal file
14
src/components/alert-message.vue
Normal file
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<section
|
||||
class="bg-gun-powder p-3 text-center text-white text-sm font-semibold"
|
||||
>
|
||||
<slot></slot>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
|
||||
@Component
|
||||
export default class AlertMessage extends Vue {}
|
||||
</script>
|
|
@ -1,23 +0,0 @@
|
|||
[
|
||||
{
|
||||
"id": "1",
|
||||
"name": "Inviqa",
|
||||
"owner": "inviqa",
|
||||
"region": "Europe (West 1)",
|
||||
"image": "inviqa.jpeg"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"name": "oliverdavies.uk",
|
||||
"owner": "Oliver Davies",
|
||||
"region": "Europe (West 1)",
|
||||
"image": "oliver-davies.png"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"name": "PHP South Wales",
|
||||
"owner": "PHP South Wales organisers",
|
||||
"region": "Europe (West 1)",
|
||||
"image": "php-south-wales.png"
|
||||
}
|
||||
]
|
14
src/main.js
14
src/main.js
|
@ -1,14 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.component('alert-message', require('@/components/AlertMessage').default)
|
||||
Vue.component('banner', require('@/components/Banner').default)
|
||||
Vue.component('page-title', require('@/components/PageTitle').default)
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
13
src/main.ts
Normal file
13
src/main.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import Vue from "vue";
|
||||
import AlertMessage from "@/components/alert-message.vue";
|
||||
import App from "./App.vue";
|
||||
import router from "./router";
|
||||
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
Vue.component("AlertMessage", AlertMessage);
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
render: h => h(App)
|
||||
}).$mount("#app");
|
|
@ -1,24 +0,0 @@
|
|||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
import Project from '@/views/Project'
|
||||
import Projects from '@/views/Projects'
|
||||
|
||||
Vue.use(Router)
|
||||
|
||||
export default new Router({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'projects',
|
||||
component: Projects
|
||||
},
|
||||
{
|
||||
path: '/project/:id',
|
||||
name: 'project',
|
||||
component: Project,
|
||||
props: true
|
||||
}
|
||||
]
|
||||
})
|
21
src/router/index.ts
Normal file
21
src/router/index.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
import Vue from "vue";
|
||||
import VueRouter, { RouteConfig } from "vue-router";
|
||||
import Home from "../views/Home.vue";
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
const routes: Array<RouteConfig> = [
|
||||
{
|
||||
path: "/",
|
||||
name: "Home",
|
||||
component: Home
|
||||
}
|
||||
];
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: "history",
|
||||
base: process.env.BASE_URL,
|
||||
routes
|
||||
});
|
||||
|
||||
export default router;
|
13
src/shims-tsx.d.ts
vendored
Normal file
13
src/shims-tsx.d.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
import Vue, { VNode } from "vue";
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
// tslint:disable no-empty-interface
|
||||
interface Element extends VNode {}
|
||||
// tslint:disable no-empty-interface
|
||||
interface ElementClass extends Vue {}
|
||||
interface IntrinsicElements {
|
||||
[elem: string]: any;
|
||||
}
|
||||
}
|
||||
}
|
4
src/shims-vue.d.ts
vendored
Normal file
4
src/shims-vue.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
declare module "*.vue" {
|
||||
import Vue from "vue";
|
||||
export default Vue;
|
||||
}
|
11
src/views/Home.vue
Normal file
11
src/views/Home.vue
Normal file
|
@ -0,0 +1,11 @@
|
|||
<template>
|
||||
<div class="home">
|
||||
<h1>Rebuilding Platform.sh</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Vue } from "vue-property-decorator";
|
||||
|
||||
export default class Home extends Vue {}
|
||||
</script>
|
|
@ -1,51 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<banner>
|
||||
<template #banner-left>
|
||||
<project-breadcrumb :project="project"/>
|
||||
</template>
|
||||
|
||||
<template #sub-banner>
|
||||
<span class="text-white">Project and environment dropdowns</span>
|
||||
</template>
|
||||
</banner>
|
||||
|
||||
<div class="container mx-auto px-4">
|
||||
<div class="flex items-center">
|
||||
<div class="w-1/2">
|
||||
<nav>
|
||||
<a class="py-2 text-gray-900 text-xs uppercase tracking-widest border-b-2 border-gray-900 font-semibold" href="#">Overview</a>
|
||||
<a class="ml-6 py-2 text-gray-900 text-xs uppercase tracking-widest" href="#">Settings</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div class="w-1/2 flex items-center justify-end">
|
||||
<button type="button" class="py-1 pl-2 pr-4 flex items-center text-sm uppercase tracking-wider border border-periwinkle">
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 block fill-current text-gray-700"><path d="M6.90002 9.8999C6.90002 9.5999 7.00002 9.3999 7.20002 9.1999C7.60002 8.7999 8.20002 8.7999 8.60002 9.1999L12.1 12.6999L15.6 9.1999C16 8.7999 16.6 8.7999 17 9.1999C17.4 9.5999 17.4 10.1999 17 10.5999L12.8 14.7999C12.4 15.1999 11.8 15.1999 11.4 14.7999L7.20002 10.5999C7.00002 10.3999 6.90002 10.1999 6.90002 9.8999Z"></path></svg>
|
||||
<span class="ml-1">Git</span>
|
||||
</button>
|
||||
<button type="button" class="ml-3 py-1 pl-2 pr-4 flex items-center text-sm uppercase tracking-wider border border-periwinkle">
|
||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" class="w-6 h-6 block fill-current text-gray-700"><path d="M6.90002 9.8999C6.90002 9.5999 7.00002 9.3999 7.20002 9.1999C7.60002 8.7999 8.20002 8.7999 8.60002 9.1999L12.1 12.6999L15.6 9.1999C16 8.7999 16.6 8.7999 17 9.1999C17.4 9.5999 17.4 10.1999 17 10.5999L12.8 14.7999C12.4 15.1999 11.8 15.1999 11.4 14.7999L7.20002 10.5999C7.00002 10.3999 6.90002 10.1999 6.90002 9.8999Z"></path></svg>
|
||||
<span class="ml-1">CLI</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProjectBreadcrumb from '@/components/ProjectBreadcrumb'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ProjectBreadcrumb
|
||||
},
|
||||
|
||||
computed: {
|
||||
project () {
|
||||
return this.$attrs.projects[this.$attrs.id - 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,95 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<banner>
|
||||
<template #sub-banner>
|
||||
<project-search/>
|
||||
</template>
|
||||
</banner>
|
||||
|
||||
<main class="container mx-auto p-6">
|
||||
<div class="flex justify-between items-baseline">
|
||||
<page-title>All Projects</page-title>
|
||||
|
||||
<project-view-switcher @changed="projectViewSwitched" :mode="displayMode"></project-view-switcher>
|
||||
</div>
|
||||
|
||||
<div class="mt-6">
|
||||
<div
|
||||
v-if="displayMode == 'grid'"
|
||||
class="
|
||||
grid gap-8
|
||||
md:grid-cols-2
|
||||
xl:grid-cols-3
|
||||
"
|
||||
>
|
||||
<div
|
||||
v-for="project in projects"
|
||||
:key="project.id"
|
||||
>
|
||||
<project-card :project="project"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="displayMode == 'list'" class="pt-6 pb-6 mt-4 bg-white shadow-md">
|
||||
<table class="w-full">
|
||||
<thead>
|
||||
<tr class="border-b border-gray-300">
|
||||
<th class="w-1/2 pb-3 px-6 font-semibold text-left text-sm">Project name</th>
|
||||
<th class="pb-3 px-6 font-semibold text-left text-sm">Owner</th>
|
||||
<th class="w-1/4 pb-3 px-6 font-semibold text-left text-sm">Region</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="project in projects" :key="project.id">
|
||||
<td class="px-6 py-4">
|
||||
<router-link :to="{ name: 'project', params: { id: project.id }}" class="font-semibold text-sm hover:underline">{{ project.name }}</router-link>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<a href="#0" class="font-semibold text-sm hover:underline">{{ project.owner }}</a>
|
||||
</td>
|
||||
<td class="px-6 py-4">
|
||||
<a href="#0" class="font-semibold text-sm hover:underline">{{ project.region }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProjectCard from '@/components/ProjectCard'
|
||||
import ProjectSearch from '@/components/ProjectSearch'
|
||||
import ProjectViewSwitcher from '@/components/ProjectViewSwitcher'
|
||||
|
||||
export default {
|
||||
name: 'projects',
|
||||
|
||||
props: {
|
||||
projects: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
ProjectCard,
|
||||
ProjectSearch,
|
||||
ProjectViewSwitcher
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
displayMode: 'grid'
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
projectViewSwitched (mode) {
|
||||
this.displayMode = mode
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -1,5 +1,6 @@
|
|||
const { variants } = require('tailwindcss/defaultConfig')
|
||||
const { fontFamily, spacing } = require('tailwindcss/defaultTheme')
|
||||
const { variants } = require('tailwindcss/defaultConfig');
|
||||
const { fontFamily } = require('tailwindcss/defaultTheme');
|
||||
const variationPlugin = require('tailwindcss-interaction-variants');
|
||||
|
||||
module.exports = {
|
||||
theme: {
|
||||
|
@ -26,9 +27,6 @@ module.exports = {
|
|||
textDecoration: [...variants.textDecoration, 'group-hover', 'hocus', 'group-hocus']
|
||||
},
|
||||
plugins: [
|
||||
require('tailwindcss-interaction-variants')(),
|
||||
require('tailwindcss-spaced-items')({ values: spacing }),
|
||||
require('tailwindcss-transforms')(),
|
||||
require('tailwindcss-visuallyhidden')()
|
||||
variationPlugin
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
module.exports = {
|
||||
env: {
|
||||
jest: true
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import { shallowMount } from '@vue/test-utils'
|
||||
import HelloWorld from '@/components/HelloWorld.vue'
|
||||
|
||||
describe('HelloWorld.vue', () => {
|
||||
it('renders props.msg when passed', () => {
|
||||
const msg = 'new message'
|
||||
const wrapper = shallowMount(HelloWorld, {
|
||||
propsData: { msg }
|
||||
})
|
||||
expect(wrapper.text()).toMatch(msg)
|
||||
})
|
||||
})
|
12
tests/unit/example.spec.ts
Normal file
12
tests/unit/example.spec.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import HelloWorld from "@/components/HelloWorld.vue";
|
||||
|
||||
describe("HelloWorld.vue", () => {
|
||||
it("renders props.msg when passed", () => {
|
||||
const msg = "new message";
|
||||
const wrapper = shallowMount(HelloWorld, {
|
||||
propsData: { msg }
|
||||
});
|
||||
expect(wrapper.text()).toMatch(msg);
|
||||
});
|
||||
});
|
41
tsconfig.json
Normal file
41
tsconfig.json
Normal file
|
@ -0,0 +1,41 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true,
|
||||
"moduleResolution": "node",
|
||||
"experimentalDecorators": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"webpack-env",
|
||||
"jest"
|
||||
],
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"src/*"
|
||||
]
|
||||
},
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"scripthost"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"src/**/*.vue",
|
||||
"tests/**/*.ts",
|
||||
"tests/**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue