├── .babelrc
├── .electron-vue
├── build.js
├── dev-client.js
├── dev-runner.js
├── webpack.main.config.js
├── webpack.renderer.config.js
└── webpack.web.config.js
├── .eslintrc.js
├── .gitignore
├── README.md
├── build
└── icons
│ ├── 128.png
│ ├── 256.png
│ ├── 32.png
│ ├── 64.png
│ ├── icon.icns
│ ├── icon.ico
│ ├── out
│ ├── choose.png
│ ├── logo-vue1.png
│ ├── logo-vue2.png
│ ├── logo-vue3.png
│ ├── logo-vue4.png
│ ├── logo-yellow.png
│ ├── logo.png
│ └── votes.txt
│ └── src
│ ├── logo-grey-checkers.svg
│ ├── logo-grey.svg
│ ├── logo-vue1.svg
│ ├── logo-vue2.svg
│ ├── logo-vue3.svg
│ ├── logo-vue4.svg
│ └── logo-yellow.svg
├── dist
├── electron
│ └── .gitkeep
└── web
│ └── .gitkeep
├── package.json
├── src
├── index.ejs
├── main
│ ├── index.dev.js
│ └── index.js
└── renderer
│ ├── App.vue
│ ├── RepositoryHub.js
│ ├── assets
│ ├── .gitkeep
│ ├── css
│ │ ├── animate.css
│ │ ├── custom.css
│ │ ├── fonts
│ │ │ ├── MaterialIcons-Regular.woff2
│ │ │ ├── Roboto-Regular.woff2
│ │ │ ├── Roboto
│ │ │ │ ├── LICENSE.txt
│ │ │ │ ├── Roboto-Black.ttf
│ │ │ │ ├── Roboto-BlackItalic.ttf
│ │ │ │ ├── Roboto-Bold.ttf
│ │ │ │ ├── Roboto-BoldItalic.ttf
│ │ │ │ ├── Roboto-Italic.ttf
│ │ │ │ ├── Roboto-Light.ttf
│ │ │ │ ├── Roboto-LightItalic.ttf
│ │ │ │ ├── Roboto-Medium.ttf
│ │ │ │ ├── Roboto-MediumItalic.ttf
│ │ │ │ ├── Roboto-Regular.ttf
│ │ │ │ ├── Roboto-Thin.ttf
│ │ │ │ └── Roboto-ThinItalic.ttf
│ │ │ └── icon.css
│ │ ├── materialize-0.1.min.css
│ │ └── materialize.min.css
│ ├── img
│ │ └── user.png
│ └── logo.png
│ ├── components
│ ├── Avatar.vue
│ ├── Blih.vue
│ ├── Blih
│ │ ├── Page.vue
│ │ ├── Repositories.vue
│ │ ├── Repository.vue
│ │ ├── Settings.vue
│ │ ├── SshKey.vue
│ │ └── SshKeys.vue
│ ├── Charts
│ │ ├── ContributionsChart.js
│ │ ├── HistoryChart.js
│ │ └── LanguageChart.js
│ ├── Dialogs
│ │ ├── DialogBasic.vue
│ │ ├── DialogFile.vue
│ │ └── DialogForm.vue
│ ├── Error.vue
│ ├── FileTree.vue
│ ├── Git.vue
│ ├── Loader.vue
│ ├── Login.vue
│ ├── TileAvatar.vue
│ └── Welcome.vue
│ ├── helpers.js
│ ├── main.js
│ ├── mixins.js
│ ├── router
│ └── index.js
│ └── store
│ ├── actions.js
│ ├── defaults.js
│ ├── getters.js
│ ├── index.js
│ ├── mutations.js
│ └── state.js
├── static
├── .gitkeep
└── 256.png
└── todo.txt
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "comments": false,
3 | "env": {
4 | "main": {
5 | "presets": [
6 | ["env", {
7 | "targets": { "node": 7 }
8 | }],
9 | "stage-0"
10 | ]
11 | },
12 | "renderer": {
13 | "presets": [
14 | ["env", {
15 | "modules": false
16 | }],
17 | "stage-0"
18 | ]
19 | },
20 | "web": {
21 | "presets": [
22 | ["env", {
23 | "modules": false
24 | }],
25 | "stage-0"
26 | ]
27 | }
28 | },
29 | "plugins": ["transform-runtime"]
30 | }
31 |
--------------------------------------------------------------------------------
/.electron-vue/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.NODE_ENV = 'production'
4 |
5 | const { say } = require('cfonts')
6 | const chalk = require('chalk')
7 | const del = require('del')
8 | const { spawn } = require('child_process')
9 | const webpack = require('webpack')
10 | const Multispinner = require('multispinner')
11 |
12 |
13 | const mainConfig = require('./webpack.main.config')
14 | const rendererConfig = require('./webpack.renderer.config')
15 | const webConfig = require('./webpack.web.config')
16 |
17 | const doneLog = chalk.bgGreen.white(' DONE ') + ' '
18 | const errorLog = chalk.bgRed.white(' ERROR ') + ' '
19 | const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
20 | const isCI = process.env.CI || false
21 |
22 | if (process.env.BUILD_TARGET === 'clean') clean()
23 | else if (process.env.BUILD_TARGET === 'web') web()
24 | else build()
25 |
26 | function clean () {
27 | del.sync(['build/*', '!build/icons', '!build/icons/icon.*'])
28 | console.log(`\n${doneLog}\n`)
29 | process.exit()
30 | }
31 |
32 | function build () {
33 | greeting()
34 |
35 | del.sync(['dist/electron/*', '!.gitkeep'])
36 |
37 | const tasks = ['main', 'renderer']
38 | const m = new Multispinner(tasks, {
39 | preText: 'building',
40 | postText: 'process'
41 | })
42 |
43 | let results = ''
44 |
45 | m.on('success', () => {
46 | process.stdout.write('\x1B[2J\x1B[0f')
47 | console.log(`\n\n${results}`)
48 | console.log(`${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`)
49 | process.exit()
50 | })
51 |
52 | pack(mainConfig).then(result => {
53 | results += result + '\n\n'
54 | m.success('main')
55 | }).catch(err => {
56 | m.error('main')
57 | console.log(`\n ${errorLog}failed to build main process`)
58 | console.error(`\n${err}\n`)
59 | process.exit(1)
60 | })
61 |
62 | pack(rendererConfig).then(result => {
63 | results += result + '\n\n'
64 | m.success('renderer')
65 | }).catch(err => {
66 | m.error('renderer')
67 | console.log(`\n ${errorLog}failed to build renderer process`)
68 | console.error(`\n${err}\n`)
69 | process.exit(1)
70 | })
71 | }
72 |
73 | function pack (config) {
74 | return new Promise((resolve, reject) => {
75 | webpack(config, (err, stats) => {
76 | if (err) reject(err.stack || err)
77 | else if (stats.hasErrors()) {
78 | let err = ''
79 |
80 | stats.toString({
81 | chunks: false,
82 | colors: true
83 | })
84 | .split(/\r?\n/)
85 | .forEach(line => {
86 | err += ` ${line}\n`
87 | })
88 |
89 | reject(err)
90 | } else {
91 | resolve(stats.toString({
92 | chunks: false,
93 | colors: true
94 | }))
95 | }
96 | })
97 | })
98 | }
99 |
100 | function web () {
101 | del.sync(['dist/web/*', '!.gitkeep'])
102 | webpack(webConfig, (err, stats) => {
103 | if (err || stats.hasErrors()) console.log(err)
104 |
105 | console.log(stats.toString({
106 | chunks: false,
107 | colors: true
108 | }))
109 |
110 | process.exit()
111 | })
112 | }
113 |
114 | function greeting () {
115 | const cols = process.stdout.columns
116 | let text = ''
117 |
118 | if (cols > 85) text = 'lets-build'
119 | else if (cols > 60) text = 'lets-|build'
120 | else text = false
121 |
122 | if (text && !isCI) {
123 | say(text, {
124 | colors: ['yellow'],
125 | font: 'simple3d',
126 | space: false
127 | })
128 | } else console.log(chalk.yellow.bold('\n lets-build'))
129 | console.log()
130 | }
131 |
--------------------------------------------------------------------------------
/.electron-vue/dev-client.js:
--------------------------------------------------------------------------------
1 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
2 |
3 | hotClient.subscribe(event => {
4 | /**
5 | * Reload browser when HTMLWebpackPlugin emits a new index.html
6 | *
7 | * Currently disabled until jantimon/html-webpack-plugin#680 is resolved.
8 | * https://github.com/SimulatedGREG/electron-vue/issues/437
9 | * https://github.com/jantimon/html-webpack-plugin/issues/680
10 | */
11 | // if (event.action === 'reload') {
12 | // window.location.reload()
13 | // }
14 |
15 | /**
16 | * Notify `mainWindow` when `main` process is compiling,
17 | * giving notice for an expected reload of the `electron` process
18 | */
19 | if (event.action === 'compiling') {
20 | document.body.innerHTML += `
21 |
34 |
35 |
36 | Compiling Main Process...
37 |
38 | `
39 | }
40 | })
41 |
--------------------------------------------------------------------------------
/.electron-vue/dev-runner.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const chalk = require('chalk')
4 | const electron = require('electron')
5 | const path = require('path')
6 | const { say } = require('cfonts')
7 | const { spawn } = require('child_process')
8 | const webpack = require('webpack')
9 | const WebpackDevServer = require('webpack-dev-server')
10 | const webpackHotMiddleware = require('webpack-hot-middleware')
11 |
12 | const mainConfig = require('./webpack.main.config')
13 | const rendererConfig = require('./webpack.renderer.config')
14 |
15 | let electronProcess = null
16 | let manualRestart = false
17 | let hotMiddleware
18 |
19 | function logStats (proc, data) {
20 | let log = ''
21 |
22 | log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
23 | log += '\n\n'
24 |
25 | if (typeof data === 'object') {
26 | data.toString({
27 | colors: true,
28 | chunks: false
29 | }).split(/\r?\n/).forEach(line => {
30 | log += ' ' + line + '\n'
31 | })
32 | } else {
33 | log += ` ${data}\n`
34 | }
35 |
36 | log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
37 |
38 | console.log(log)
39 | }
40 |
41 | function startRenderer () {
42 | return new Promise((resolve, reject) => {
43 | rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
44 |
45 | const compiler = webpack(rendererConfig)
46 | hotMiddleware = webpackHotMiddleware(compiler, {
47 | log: false,
48 | heartbeat: 2500
49 | })
50 |
51 | compiler.plugin('compilation', compilation => {
52 | compilation.plugin('html-webpack-plugin-after-emit', (data, cb) => {
53 | hotMiddleware.publish({ action: 'reload' })
54 | cb()
55 | })
56 | })
57 |
58 | compiler.plugin('done', stats => {
59 | logStats('Renderer', stats)
60 | })
61 |
62 | const server = new WebpackDevServer(
63 | compiler,
64 | {
65 | contentBase: path.join(__dirname, '../'),
66 | quiet: true,
67 | before (app, ctx) {
68 | app.use(hotMiddleware)
69 | ctx.middleware.waitUntilValid(() => {
70 | resolve()
71 | })
72 | }
73 | }
74 | )
75 |
76 | server.listen(9080)
77 | })
78 | }
79 |
80 | function startMain () {
81 | return new Promise((resolve, reject) => {
82 | mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
83 |
84 | const compiler = webpack(mainConfig)
85 |
86 | compiler.plugin('watch-run', (compilation, done) => {
87 | logStats('Main', chalk.white.bold('compiling...'))
88 | hotMiddleware.publish({ action: 'compiling' })
89 | done()
90 | })
91 |
92 | compiler.watch({}, (err, stats) => {
93 | if (err) {
94 | console.log(err)
95 | return
96 | }
97 |
98 | logStats('Main', stats)
99 |
100 | if (electronProcess && electronProcess.kill) {
101 | manualRestart = true
102 | process.kill(electronProcess.pid)
103 | electronProcess = null
104 | startElectron()
105 |
106 | setTimeout(() => {
107 | manualRestart = false
108 | }, 5000)
109 | }
110 |
111 | resolve()
112 | })
113 | })
114 | }
115 |
116 | function startElectron () {
117 | electronProcess = spawn(electron, ['--inspect=5858', path.join(__dirname, '../dist/electron/main.js')])
118 |
119 | electronProcess.stdout.on('data', data => {
120 | electronLog(data, 'blue')
121 | })
122 | electronProcess.stderr.on('data', data => {
123 | electronLog(data, 'red')
124 | })
125 |
126 | electronProcess.on('close', () => {
127 | if (!manualRestart) process.exit()
128 | })
129 | }
130 |
131 | function electronLog (data, color) {
132 | let log = ''
133 | data = data.toString().split(/\r?\n/)
134 | data.forEach(line => {
135 | log += ` ${line}\n`
136 | })
137 | if (/[0-9A-z]+/.test(log)) {
138 | console.log(
139 | chalk[color].bold('┏ Electron -------------------') +
140 | '\n\n' +
141 | log +
142 | chalk[color].bold('┗ ----------------------------') +
143 | '\n'
144 | )
145 | }
146 | }
147 |
148 | function greeting () {
149 | const cols = process.stdout.columns
150 | let text = ''
151 |
152 | if (cols > 104) text = 'electron-vue'
153 | else if (cols > 76) text = 'electron-|vue'
154 | else text = false
155 |
156 | if (text) {
157 | say(text, {
158 | colors: ['yellow'],
159 | font: 'simple3d',
160 | space: false
161 | })
162 | } else console.log(chalk.yellow.bold('\n electron-vue'))
163 | console.log(chalk.blue(' getting ready...') + '\n')
164 | }
165 |
166 | function init () {
167 | greeting()
168 |
169 | Promise.all([startRenderer(), startMain()])
170 | .then(() => {
171 | startElectron()
172 | })
173 | .catch(err => {
174 | console.error(err)
175 | })
176 | }
177 |
178 | init()
179 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.main.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'main'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
10 |
11 | let mainConfig = {
12 | entry: {
13 | main: path.join(__dirname, '../src/main/index.js')
14 | },
15 | externals: [
16 | ...Object.keys(dependencies || {})
17 | ],
18 | module: {
19 | rules: [
20 | {
21 | test: /\.(js)$/,
22 | enforce: 'pre',
23 | exclude: /node_modules/,
24 | use: {
25 | loader: 'eslint-loader',
26 | options: {
27 | formatter: require('eslint-friendly-formatter')
28 | }
29 | }
30 | },
31 | {
32 | test: /\.js$/,
33 | use: 'babel-loader',
34 | exclude: /node_modules/
35 | },
36 | {
37 | test: /\.node$/,
38 | use: 'node-loader'
39 | }
40 | ]
41 | },
42 | node: {
43 | __dirname: process.env.NODE_ENV !== 'production',
44 | __filename: process.env.NODE_ENV !== 'production'
45 | },
46 | output: {
47 | filename: '[name].js',
48 | libraryTarget: 'commonjs2',
49 | path: path.join(__dirname, '../dist/electron')
50 | },
51 | plugins: [
52 | new webpack.NoEmitOnErrorsPlugin()
53 | ],
54 | resolve: {
55 | extensions: ['.js', '.json', '.node']
56 | },
57 | target: 'electron-main'
58 | }
59 |
60 | /**
61 | * Adjust mainConfig for development settings
62 | */
63 | if (process.env.NODE_ENV !== 'production') {
64 | mainConfig.plugins.push(
65 | new webpack.DefinePlugin({
66 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
67 | })
68 | )
69 | }
70 |
71 | /**
72 | * Adjust mainConfig for production settings
73 | */
74 | if (process.env.NODE_ENV === 'production') {
75 | mainConfig.plugins.push(
76 | new BabiliWebpackPlugin(),
77 | new webpack.DefinePlugin({
78 | 'process.env.NODE_ENV': '"production"'
79 | })
80 | )
81 | }
82 |
83 | module.exports = mainConfig
84 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.renderer.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'renderer'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
10 | const CopyWebpackPlugin = require('copy-webpack-plugin')
11 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
12 | const HtmlWebpackPlugin = require('html-webpack-plugin')
13 |
14 | /**
15 | * List of node_modules to include in webpack bundle
16 | *
17 | * Required for specific packages like Vue UI libraries
18 | * that provide pure *.vue files that need compiling
19 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
20 | */
21 | let whiteListedModules = ['vue']
22 |
23 | let rendererConfig = {
24 | devtool: '#cheap-module-eval-source-map',
25 | entry: {
26 | renderer: path.join(__dirname, '../src/renderer/main.js')
27 | },
28 | externals: [
29 | ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d))
30 | ],
31 | module: {
32 | rules: [
33 | {
34 | test: /\.(js|vue)$/,
35 | enforce: 'pre',
36 | exclude: /node_modules/,
37 | use: {
38 | loader: 'eslint-loader',
39 | options: {
40 | formatter: require('eslint-friendly-formatter')
41 | }
42 | }
43 | },
44 | {
45 | test: /\.css$/,
46 | use: ExtractTextPlugin.extract({
47 | fallback: 'style-loader',
48 | use: 'css-loader'
49 | })
50 | },
51 | {
52 | test: /\.html$/,
53 | use: 'vue-html-loader'
54 | },
55 | {
56 | test: /\.js$/,
57 | use: 'babel-loader',
58 | exclude: /node_modules/
59 | },
60 | {
61 | test: /\.node$/,
62 | use: 'node-loader'
63 | },
64 | {
65 | test: /\.vue$/,
66 | use: {
67 | loader: 'vue-loader',
68 | options: {
69 | extractCSS: process.env.NODE_ENV === 'production',
70 | loaders: {
71 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
72 | scss: 'vue-style-loader!css-loader!sass-loader'
73 | }
74 | }
75 | }
76 | },
77 | {
78 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
79 | use: {
80 | loader: 'url-loader',
81 | query: {
82 | limit: 10000,
83 | name: 'imgs/[name]--[folder].[ext]'
84 | }
85 | }
86 | },
87 | {
88 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
89 | loader: 'url-loader',
90 | options: {
91 | limit: 10000,
92 | name: 'media/[name]--[folder].[ext]'
93 | }
94 | },
95 | {
96 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
97 | use: {
98 | loader: 'url-loader',
99 | query: {
100 | limit: 10000,
101 | name: 'fonts/[name]--[folder].[ext]'
102 | }
103 | }
104 | }
105 | ]
106 | },
107 | node: {
108 | __dirname: process.env.NODE_ENV !== 'production',
109 | __filename: process.env.NODE_ENV !== 'production'
110 | },
111 | plugins: [
112 | new ExtractTextPlugin('styles.css'),
113 | new HtmlWebpackPlugin({
114 | filename: 'index.html',
115 | template: path.resolve(__dirname, '../src/index.ejs'),
116 | minify: {
117 | collapseWhitespace: true,
118 | removeAttributeQuotes: true,
119 | removeComments: true
120 | },
121 | nodeModules: process.env.NODE_ENV !== 'production'
122 | ? path.resolve(__dirname, '../node_modules')
123 | : false
124 | }),
125 | new webpack.HotModuleReplacementPlugin(),
126 | new webpack.NoEmitOnErrorsPlugin()
127 | ],
128 | output: {
129 | filename: '[name].js',
130 | libraryTarget: 'commonjs2',
131 | path: path.join(__dirname, '../dist/electron')
132 | },
133 | resolve: {
134 | alias: {
135 | '@': path.join(__dirname, '../src/renderer'),
136 | 'vue$': 'vue/dist/vue.esm.js'
137 | },
138 | extensions: ['.js', '.vue', '.json', '.css', '.node']
139 | },
140 | target: 'electron-renderer'
141 | }
142 |
143 | /**
144 | * Adjust rendererConfig for development settings
145 | */
146 | if (process.env.NODE_ENV !== 'production') {
147 | rendererConfig.plugins.push(
148 | new webpack.DefinePlugin({
149 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
150 | })
151 | )
152 | }
153 |
154 | /**
155 | * Adjust rendererConfig for production settings
156 | */
157 | if (process.env.NODE_ENV === 'production') {
158 | rendererConfig.devtool = ''
159 |
160 | rendererConfig.plugins.push(
161 | new BabiliWebpackPlugin(),
162 | new CopyWebpackPlugin([
163 | {
164 | from: path.join(__dirname, '../static'),
165 | to: path.join(__dirname, '../dist/electron/static'),
166 | ignore: ['.*']
167 | }
168 | ]),
169 | new webpack.DefinePlugin({
170 | 'process.env.NODE_ENV': '"production"'
171 | }),
172 | new webpack.LoaderOptionsPlugin({
173 | minimize: true
174 | })
175 | )
176 | }
177 |
178 | module.exports = rendererConfig
179 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.web.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'web'
4 |
5 | const path = require('path')
6 | const webpack = require('webpack')
7 |
8 | const BabiliWebpackPlugin = require('babili-webpack-plugin')
9 | const CopyWebpackPlugin = require('copy-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const HtmlWebpackPlugin = require('html-webpack-plugin')
12 |
13 | let webConfig = {
14 | devtool: '#cheap-module-eval-source-map',
15 | entry: {
16 | web: path.join(__dirname, '../src/renderer/main.js')
17 | },
18 | module: {
19 | rules: [
20 | {
21 | test: /\.(js|vue)$/,
22 | enforce: 'pre',
23 | exclude: /node_modules/,
24 | use: {
25 | loader: 'eslint-loader',
26 | options: {
27 | formatter: require('eslint-friendly-formatter')
28 | }
29 | }
30 | },
31 | {
32 | test: /\.css$/,
33 | use: ExtractTextPlugin.extract({
34 | fallback: 'style-loader',
35 | use: 'css-loader'
36 | })
37 | },
38 | {
39 | test: /\.html$/,
40 | use: 'vue-html-loader'
41 | },
42 | {
43 | test: /\.js$/,
44 | use: 'babel-loader',
45 | include: [ path.resolve(__dirname, '../src/renderer') ],
46 | exclude: /node_modules/
47 | },
48 | {
49 | test: /\.vue$/,
50 | use: {
51 | loader: 'vue-loader',
52 | options: {
53 | extractCSS: true,
54 | loaders: {
55 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
56 | scss: 'vue-style-loader!css-loader!sass-loader'
57 | }
58 | }
59 | }
60 | },
61 | {
62 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
63 | use: {
64 | loader: 'url-loader',
65 | query: {
66 | limit: 10000,
67 | name: 'imgs/[name].[ext]'
68 | }
69 | }
70 | },
71 | {
72 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
73 | use: {
74 | loader: 'url-loader',
75 | query: {
76 | limit: 10000,
77 | name: 'fonts/[name].[ext]'
78 | }
79 | }
80 | }
81 | ]
82 | },
83 | plugins: [
84 | new ExtractTextPlugin('styles.css'),
85 | new HtmlWebpackPlugin({
86 | filename: 'index.html',
87 | template: path.resolve(__dirname, '../src/index.ejs'),
88 | minify: {
89 | collapseWhitespace: true,
90 | removeAttributeQuotes: true,
91 | removeComments: true
92 | },
93 | nodeModules: false
94 | }),
95 | new webpack.DefinePlugin({
96 | 'process.env.IS_WEB': 'true'
97 | }),
98 | new webpack.HotModuleReplacementPlugin(),
99 | new webpack.NoEmitOnErrorsPlugin()
100 | ],
101 | output: {
102 | filename: '[name].js',
103 | path: path.join(__dirname, '../dist/web')
104 | },
105 | resolve: {
106 | alias: {
107 | '@': path.join(__dirname, '../src/renderer'),
108 | 'vue$': 'vue/dist/vue.esm.js'
109 | },
110 | extensions: ['.js', '.vue', '.json', '.css']
111 | },
112 | target: 'web'
113 | }
114 |
115 | /**
116 | * Adjust webConfig for production settings
117 | */
118 | if (process.env.NODE_ENV === 'production') {
119 | webConfig.devtool = ''
120 |
121 | webConfig.plugins.push(
122 | new BabiliWebpackPlugin(),
123 | new CopyWebpackPlugin([
124 | {
125 | from: path.join(__dirname, '../static'),
126 | to: path.join(__dirname, '../dist/web/static'),
127 | ignore: ['.*']
128 | }
129 | ]),
130 | new webpack.DefinePlugin({
131 | 'process.env.NODE_ENV': '"production"'
132 | }),
133 | new webpack.LoaderOptionsPlugin({
134 | minimize: true
135 | })
136 | )
137 | }
138 |
139 | module.exports = webConfig
140 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | parser: 'babel-eslint',
4 | parserOptions: {
5 | sourceType: 'module',
6 | ecmaVersion: '6'
7 | },
8 | env: {
9 | browser: true,
10 | node: true,
11 | 'es6': true
12 | },
13 | extends: 'standard',
14 | globals: {
15 | __static: true
16 | },
17 | plugins: [
18 | 'html'
19 | ],
20 | 'rules': {
21 | 'indent': [2, 'tab', { SwitchCase: 1 }],
22 | 'no-tabs': 0,
23 | 'arrow-parens': 0,
24 | 'no-console': process.env.NODE_ENV === 'production' ? 2 : 0,
25 | 'no-unused-vars': [2, { 'argsIgnorePattern': '^_' }],
26 | 'semi': [2, 'always']
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | dist/electron/*
3 | dist/web/*
4 | build/*
5 | !build/icons
6 | node_modules/
7 | npm-debug.log
8 | npm-debug.log.*
9 | thumbs.db
10 | !.gitkeep
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Blih Vue
8 |
9 |
10 | [](http://standardjs.com)
11 |
12 | > Managing repositories has never been easier.
13 |
14 | Blih Vue is an intuitive and easy-to-use app that helps you efficiently manage your Epitech repositories.
15 |
16 | ## Easy to use
17 |
18 | Sick of typing your password or to mess up the arguments order every time you use the Blih python script ?
19 |
20 | With Blih Vue, authenticate once and you're good to go ! Navigate seamlessly through the application and manage your keys and repositories with ease.
21 |
22 | ## Features
23 |
24 | * Browse, create, delete and edit your repositories :cloud:
25 | * Edit collaborators and their rights :busts_in_silhouette:
26 | * Get git insights on a repository :bar_chart:
27 | * Manage your SSH keys :key:
28 |
29 | ## Download
30 |
31 | Coming soon
32 |
33 | ## Build instructions
34 |
35 | Simply run `npm run build`. This will build the application for the current platform into the `build` folder.
36 |
37 | :information_source: You will first need to compile the native `nodegit` it on your platform or to download a pre-built binary. This step takes place when running `npm install`, but it may fail for several reasons.
38 |
39 | Then, `electron-rebuild` will rebuild the module against the version of Node.js that Electron is using.
40 |
41 | ### Troubleshooting
42 |
43 | #### When installing
44 |
45 | > ...
46 |
47 | This means you do not have the build tools required to compile native modules.
48 | * On Windows:
49 | Run `npm i -g windows-build-tools` as administrator to install C++ build tools, or do it manually.
50 |
51 | > fatal error: curl/curl.h: No such file or directory
52 |
53 | This happens when compiling nodegit from source. It requires the libcurl-dev package to be installed.
54 | * On Ubuntu:
55 | Run `apt install libcurl-dev` and install the appropriate package (`libcurl4-gnutls-dev` or similar).
56 |
57 | #### When running
58 |
59 | > libcurl.so.4: cannot open shared object file: No such file or directory
60 |
61 | That means nodegit cannot find the libcurl shared library.
--------------------------------------------------------------------------------
/build/icons/128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/128.png
--------------------------------------------------------------------------------
/build/icons/256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/256.png
--------------------------------------------------------------------------------
/build/icons/32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/32.png
--------------------------------------------------------------------------------
/build/icons/64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/64.png
--------------------------------------------------------------------------------
/build/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/icon.icns
--------------------------------------------------------------------------------
/build/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/icon.ico
--------------------------------------------------------------------------------
/build/icons/out/choose.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/out/choose.png
--------------------------------------------------------------------------------
/build/icons/out/logo-vue1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/out/logo-vue1.png
--------------------------------------------------------------------------------
/build/icons/out/logo-vue2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/out/logo-vue2.png
--------------------------------------------------------------------------------
/build/icons/out/logo-vue3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/out/logo-vue3.png
--------------------------------------------------------------------------------
/build/icons/out/logo-vue4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/out/logo-vue4.png
--------------------------------------------------------------------------------
/build/icons/out/logo-yellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/out/logo-yellow.png
--------------------------------------------------------------------------------
/build/icons/out/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/build/icons/out/logo.png
--------------------------------------------------------------------------------
/build/icons/out/votes.txt:
--------------------------------------------------------------------------------
1 | 1: 2
2 | 2: 4
3 | 3: 1
4 | 4: 2
5 | 5: 1
6 | 6: 2
--------------------------------------------------------------------------------
/build/icons/src/logo-grey-checkers.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | image/svg+xml
16 |
17 | blih
18 |
19 |
20 |
21 |
22 | blih
23 |
24 | Layer 1
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/build/icons/src/logo-grey.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | image/svg+xml
7 |
8 | blih
9 |
10 |
11 |
12 |
13 | blih
14 |
15 | Layer 1
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build/icons/src/logo-vue1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | image/svg+xml
7 |
8 | blih
9 |
10 |
11 |
12 |
13 | blih
14 |
15 | Layer 1
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build/icons/src/logo-vue2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | image/svg+xml
7 |
8 | blih
9 |
10 |
11 |
12 |
13 | blih
14 |
15 | Layer 1
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build/icons/src/logo-vue3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | image/svg+xml
7 |
8 | blih
9 |
10 |
11 |
12 |
13 | blih
14 |
15 | Layer 1
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build/icons/src/logo-vue4.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | image/svg+xml
7 |
8 | blih
9 |
10 |
11 |
12 |
13 | blih
14 |
15 | Layer 1
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build/icons/src/logo-yellow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | image/svg+xml
7 |
8 | blih
9 |
10 |
11 |
12 |
13 | blih
14 |
15 | Layer 1
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/dist/electron/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/dist/electron/.gitkeep
--------------------------------------------------------------------------------
/dist/web/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/dist/web/.gitkeep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blih-vue",
3 | "version": "0.0.0",
4 | "author": "Lucien Le Roux ",
5 | "description": "An electron-vue project",
6 | "license": null,
7 | "bugs": {
8 | "url": "https://github.com/kabukki/blih-vue/issues"
9 | },
10 | "main": "./dist/electron/main.js",
11 | "scripts": {
12 | "build": "node .electron-vue/build.js && electron-builder",
13 | "build:dir": "node .electron-vue/build.js && electron-builder --dir",
14 | "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
15 | "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
16 | "dev": "node .electron-vue/dev-runner.js",
17 | "lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src",
18 | "lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src",
19 | "pack": "npm run pack:main && npm run pack:renderer",
20 | "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
21 | "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
22 | "postinstall": "npm run lint:fix && electron-rebuild -f -w nodegit"
23 | },
24 | "build": {
25 | "productName": "BlihVue",
26 | "appId": "eu.datsite.kabukki.blihvue",
27 | "directories": {
28 | "output": "build"
29 | },
30 | "files": [
31 | "dist/electron/**/*"
32 | ],
33 | "dmg": {
34 | "contents": [
35 | {
36 | "x": 410,
37 | "y": 150,
38 | "type": "link",
39 | "path": "/Applications"
40 | },
41 | {
42 | "x": 130,
43 | "y": 150,
44 | "type": "file"
45 | }
46 | ]
47 | },
48 | "mac": {
49 | "icon": "build/icons/icon.icns"
50 | },
51 | "win": {
52 | "icon": "build/icons/256.png"
53 | },
54 | "linux": {
55 | "icon": "build/icons"
56 | }
57 | },
58 | "dependencies": {
59 | "blih": "^1.7.3",
60 | "chart.js": "^2.7.1",
61 | "electron-store": "^1.3.0",
62 | "fs-extra": "^5.0.0",
63 | "language-map": "^1.3.0",
64 | "moment": "^2.19.3",
65 | "nodegit": "^0.20.3",
66 | "rimraf": "^2.6.2",
67 | "ssh-fingerprint": "0.0.1",
68 | "vue": "^2.3.3",
69 | "vue-chartjs": "^3.2.1",
70 | "vue-router": "^2.5.3",
71 | "vuetify": "^1.0.6",
72 | "vuex": "^2.3.1"
73 | },
74 | "devDependencies": {
75 | "babel-core": "^6.25.0",
76 | "babel-eslint": "^7.2.3",
77 | "babel-loader": "^7.1.1",
78 | "babel-plugin-transform-runtime": "^6.23.0",
79 | "babel-preset-env": "^1.6.0",
80 | "babel-preset-stage-0": "^6.24.1",
81 | "babel-preset-stage-3": "^6.24.1",
82 | "babel-register": "^6.24.1",
83 | "babili-webpack-plugin": "^0.1.2",
84 | "blih": "^1.7.3",
85 | "cfonts": "^1.1.3",
86 | "chalk": "^2.1.0",
87 | "copy-webpack-plugin": "^4.0.1",
88 | "cross-env": "^5.0.5",
89 | "css-loader": "^0.28.4",
90 | "del": "^3.0.0",
91 | "devtron": "^1.4.0",
92 | "electron": "1.7.11",
93 | "electron-builder": "^19.19.1",
94 | "electron-debug": "^1.4.0",
95 | "electron-devtools-installer": "^2.2.0",
96 | "electron-rebuild": "^1.7.3",
97 | "eslint": "^4.17.0",
98 | "eslint-config-standard": "^11.0.0-beta.0",
99 | "eslint-friendly-formatter": "^3.0.0",
100 | "eslint-loader": "^1.9.0",
101 | "eslint-plugin-html": "^3.1.1",
102 | "eslint-plugin-import": "^2.8.0",
103 | "eslint-plugin-node": "^5.2.1",
104 | "eslint-plugin-promise": "^3.6.0",
105 | "eslint-plugin-standard": "^3.0.1",
106 | "extract-text-webpack-plugin": "^3.0.0",
107 | "file-loader": "^0.11.2",
108 | "html-webpack-plugin": "^2.30.1",
109 | "multispinner": "^0.2.1",
110 | "node-loader": "^0.6.0",
111 | "style-loader": "^0.18.2",
112 | "url-loader": "^0.5.9",
113 | "vue-html-loader": "^1.2.4",
114 | "vue-loader": "^13.0.5",
115 | "vue-style-loader": "^3.0.1",
116 | "vue-template-compiler": "^2.4.2",
117 | "webpack": "^3.5.2",
118 | "webpack-dev-server": "^2.7.1",
119 | "webpack-hot-middleware": "^2.18.2"
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Blih Vue
6 | <% if (htmlWebpackPlugin.options.nodeModules) { %>
7 |
8 |
11 | <% } %>
12 |
13 |
14 |
15 |
16 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/src/main/index.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is used specifically and only for development. It installs
3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to
4 | * modify this file, but it can be used to extend your development
5 | * environment.
6 | */
7 |
8 | /* eslint-disable */
9 |
10 | // Set environment for development
11 | process.env.NODE_ENV = 'development'
12 |
13 | // Install `electron-debug` with `devtron`
14 | require('electron-debug')({ showDevTools: true })
15 |
16 | // Install `vue-devtools`
17 | require('electron').app.on('ready', () => {
18 | let installExtension = require('electron-devtools-installer')
19 | installExtension.default(installExtension.VUEJS_DEVTOOLS)
20 | .then(() => {})
21 | .catch(err => {
22 | console.log('Unable to install `vue-devtools`: \n', err)
23 | })
24 | })
25 |
26 | // Require `main` process to boot app
27 | require('./index')
28 |
--------------------------------------------------------------------------------
/src/main/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import { app, BrowserWindow } from 'electron';
4 |
5 | /**
6 | * Set `__static` path to static files in production
7 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
8 | */
9 | if (process.env.NODE_ENV !== 'development') {
10 | global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\');
11 | }
12 |
13 | let mainWindow;
14 | const winURL = process.env.NODE_ENV === 'development'
15 | ? `http://localhost:9080`
16 | : `file://${__dirname}/index.html`;
17 |
18 | function createWindow () {
19 | /**
20 | * Initial window options
21 | */
22 | mainWindow = new BrowserWindow({
23 | height: 900,
24 | useContentSize: true,
25 | width: 1800,
26 | webPreferences: {
27 | webSecurity: false
28 | }
29 | });
30 |
31 | mainWindow.loadURL(winURL);
32 |
33 | mainWindow.on('closed', () => {
34 | mainWindow = null;
35 | });
36 | mainWindow.webContents.openDevTools();
37 | }
38 |
39 | app.on('ready', createWindow);
40 |
41 | app.on('window-all-closed', () => {
42 | if (process.platform !== 'darwin') {
43 | app.quit();
44 | }
45 | });
46 |
47 | app.on('activate', () => {
48 | if (mainWindow === null) {
49 | createWindow();
50 | }
51 | });
52 |
53 | /**
54 | * Auto Updater
55 | *
56 | * Uncomment the following code below and install `electron-updater` to
57 | * support auto updating. Code Signing with a valid certificate is required.
58 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating
59 | */
60 |
61 | /*
62 | import { autoUpdater } from 'electron-updater'
63 |
64 | autoUpdater.on('update-downloaded', () => {
65 | autoUpdater.quitAndInstall()
66 | })
67 |
68 | app.on('ready', () => {
69 | if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates()
70 | })
71 | */
72 |
--------------------------------------------------------------------------------
/src/renderer/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/src/renderer/RepositoryHub.js:
--------------------------------------------------------------------------------
1 | import Git from 'nodegit';
2 | import fs from 'fs-extra';
3 | import rimraf from 'rimraf';
4 | import path from 'path';
5 | import store from './store';
6 |
7 | export default class RepositoryHub {
8 | constructor (directory) {
9 | this.root = directory;
10 | }
11 |
12 | /*
13 | * Set up the hub (bare name)
14 | * Creates directory if it does not exist.
15 | */
16 | async init () {
17 | return fs.ensureDir(this.root);
18 | }
19 |
20 | /*
21 | * Set the current user
22 | */
23 | async use (name) {
24 | this.path = path.join(this.root, name);
25 | return fs.ensureDir(this.path);
26 | }
27 |
28 | /*
29 | * Add a repository
30 | */
31 | async add (name, url) {
32 | if (this.path) {
33 | const repoPath = path.join(this.path, name);
34 | try {
35 | await fs.ensureDir(repoPath);
36 | const repo = await Git.Repository.init(repoPath, 1); // 1 means the repository will be bare
37 | await Git.Remote.create(repo, 'origin', url);
38 | } catch (err) {
39 | return err;
40 | }
41 | } else {
42 | return Promise.reject(new Error('User is not set'));
43 | }
44 | }
45 |
46 | /*
47 | * If 'name' is specified, deletes this repository, otherwise delete all repositories
48 | */
49 | delete (name) {
50 | if (this.path) {
51 | return new Promise((resolve, reject) => {
52 | rimraf(path.join(this.path, name || '.'), {
53 | disableGlob: true
54 | }, err => {
55 | if (err) {
56 | reject(err);
57 | } else {
58 | resolve();
59 | }
60 | });
61 | });
62 | } else {
63 | return Promise.reject(new Error('User is not set'));
64 | }
65 | }
66 |
67 | /*
68 | * Perform a git fetch on a repository
69 | */
70 | update (name, onProgress) {
71 | if (this.path) {
72 | return Git.Repository.openBare(path.join(this.path, name))
73 | .then(repo => {
74 | return repo.fetch('origin', {
75 | callbacks: {
76 | credentials: (_url, _username) => Git.Cred.sshKeyNew(
77 | 'git',
78 | store.getters.publicKeyPath,
79 | store.getters.privateKeyPath,
80 | ''
81 | ),
82 | transferProgress: {
83 | // Reduce throttling to get a more accurate progress
84 | throttle: 50,
85 | callback (progress) {
86 | if (onProgress) {
87 | onProgress(progress);
88 | }
89 | }
90 | }
91 | }
92 | });
93 | });
94 | } else {
95 | return Promise.reject(new Error('User is not set'));
96 | }
97 | }
98 |
99 | /*
100 | * Get history for a repository on a given branch, defaulting to master
101 | */
102 | async history (name, branch) {
103 | if (this.path) {
104 | branch = branch || 'master';
105 | const repo = await Git.Repository.openBare(path.join(this.path, name));
106 | const first = await repo.getBranchCommit(`origin/${branch}`);
107 | return new Promise(
108 | (resolve, reject) => {
109 | let history = first.history(Git.Revwalk.SORT.TIME);
110 | history.on('end', resolve);
111 | history.on('error', reject);
112 | history.start();
113 | }
114 | );
115 | } else {
116 | return Promise.reject(new Error('User is not set'));
117 | }
118 | }
119 |
120 | /**
121 | * Recursively get children for a given tree
122 | * @param {Tree} tree The tree
123 | * @return {[Object]} Array of children (objects)
124 | */
125 | async getChildren (tree) {
126 | let files = [];
127 | const filemodeStr = {
128 | '0': 'unreadable',
129 | '16384': 'tree',
130 | '33188': 'blob',
131 | '33261': 'executable',
132 | '40960': 'link',
133 | '57344': 'commit'
134 | };
135 |
136 | for (const entry of tree.entries()) {
137 | const children = entry.isTree() ? await this.getChildren(await entry.getTree()) : null;
138 | const blob = entry.isBlob() ? await entry.getBlob() : null;
139 | files.push({
140 | name: entry.name(),
141 | sha: entry.sha(),
142 | type: filemodeStr[entry.filemode()],
143 | children,
144 | blob
145 | });
146 | }
147 | return files;
148 | }
149 |
150 | /*
151 | * Get file tree for a repository
152 | */
153 | async tree (name, branch) {
154 | if (this.path) {
155 | branch = branch || 'master';
156 | const repo = await Git.Repository.openBare(path.join(this.path, name));
157 | const first = await repo.getBranchCommit(`origin/${branch}`);
158 | const tree = await first.getTree();
159 |
160 | return this.getChildren(tree);
161 | } else {
162 | return Promise.reject(new Error('User is not set'));
163 | }
164 | }
165 |
166 | /*
167 | * Get branches
168 | */
169 | async branches (name) {
170 | if (this.path) {
171 | const repo = await Git.Repository.openBare(path.join(this.path, name));
172 | const refs = await repo.getReferences(Git.Reference.TYPE.LISTALL);
173 | return refs.filter(ref => ref.isRemote());
174 | } else {
175 | return Promise.reject(new Error('User is not set'));
176 | }
177 | }
178 |
179 | /**
180 | * Copy a repository to a non-bare one at the specified destination
181 | * @param {[type]} name the repository to copy
182 | * @param {[type]} destination where to copy it
183 | * @return {[type]} [description]
184 | */
185 | async copy (name, destination) {
186 | if (!this.path) {
187 | return Promise.reject(new Error('User is not set'));
188 | } else if (!destination) {
189 | return Promise.reject(new Error('Destination not specified'));
190 | } else {
191 | const newPath = path.join(destination, name);
192 | const oldRepo = await Git.Repository.openBare(path.join(this.path, name));
193 | /* Create new repo */
194 | await fs.ensureDir(newPath);
195 | await fs.copy(oldRepo.path(), path.join(newPath, '.git'));
196 | let newRepo = await Git.Repository.init(newPath, 0);
197 | /* Set it to non-bare */
198 | let config = await newRepo.config();
199 | await config.setString('core.bare', 'false');
200 | /* Checkout master */
201 | const first = await newRepo.getBranchCommit('origin/master');
202 | const branch = await newRepo.createBranch('master', first, 0);
203 | await newRepo.checkoutBranch(branch);
204 | }
205 | }
206 | };
207 |
--------------------------------------------------------------------------------
/src/renderer/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/.gitkeep
--------------------------------------------------------------------------------
/src/renderer/assets/css/animate.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | /*!
4 | * animate.css -http://daneden.me/animate
5 | * Version - 3.5.2
6 | * Licensed under the MIT license - http://opensource.org/licenses/MIT
7 | *
8 | * Copyright (c) 2017 Daniel Eden
9 | */
10 |
11 | .animated {
12 | animation-duration: 1s;
13 | animation-fill-mode: both;
14 | }
15 |
16 | .animated.infinite {
17 | animation-iteration-count: infinite;
18 | }
19 |
20 | .animated.hinge {
21 | animation-duration: 2s;
22 | }
23 |
24 | .animated.flipOutX,
25 | .animated.flipOutY,
26 | .animated.bounceIn,
27 | .animated.bounceOut {
28 | animation-duration: .75s;
29 | }
30 |
31 | @keyframes bounce {
32 | from, 20%, 53%, 80%, to {
33 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
34 | transform: translate3d(0,0,0);
35 | }
36 |
37 | 40%, 43% {
38 | animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
39 | transform: translate3d(0, -30px, 0);
40 | }
41 |
42 | 70% {
43 | animation-timing-function: cubic-bezier(0.755, 0.050, 0.855, 0.060);
44 | transform: translate3d(0, -15px, 0);
45 | }
46 |
47 | 90% {
48 | transform: translate3d(0,-4px,0);
49 | }
50 | }
51 |
52 | .bounce {
53 | animation-name: bounce;
54 | transform-origin: center bottom;
55 | }
56 |
57 | @keyframes flash {
58 | from, 50%, to {
59 | opacity: 1;
60 | }
61 |
62 | 25%, 75% {
63 | opacity: 0;
64 | }
65 | }
66 |
67 | .flash {
68 | animation-name: flash;
69 | }
70 |
71 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
72 |
73 | @keyframes pulse {
74 | from {
75 | transform: scale3d(1, 1, 1);
76 | }
77 |
78 | 50% {
79 | transform: scale3d(1.05, 1.05, 1.05);
80 | }
81 |
82 | to {
83 | transform: scale3d(1, 1, 1);
84 | }
85 | }
86 |
87 | .pulse {
88 | animation-name: pulse;
89 | }
90 |
91 | @keyframes rubberBand {
92 | from {
93 | transform: scale3d(1, 1, 1);
94 | }
95 |
96 | 30% {
97 | transform: scale3d(1.25, 0.75, 1);
98 | }
99 |
100 | 40% {
101 | transform: scale3d(0.75, 1.25, 1);
102 | }
103 |
104 | 50% {
105 | transform: scale3d(1.15, 0.85, 1);
106 | }
107 |
108 | 65% {
109 | transform: scale3d(.95, 1.05, 1);
110 | }
111 |
112 | 75% {
113 | transform: scale3d(1.05, .95, 1);
114 | }
115 |
116 | to {
117 | transform: scale3d(1, 1, 1);
118 | }
119 | }
120 |
121 | .rubberBand {
122 | animation-name: rubberBand;
123 | }
124 |
125 | @keyframes shake {
126 | from, to {
127 | transform: translate3d(0, 0, 0);
128 | }
129 |
130 | 10%, 30%, 50%, 70%, 90% {
131 | transform: translate3d(-10px, 0, 0);
132 | }
133 |
134 | 20%, 40%, 60%, 80% {
135 | transform: translate3d(10px, 0, 0);
136 | }
137 | }
138 |
139 | .shake {
140 | animation-name: shake;
141 | }
142 |
143 | @keyframes headShake {
144 | 0% {
145 | transform: translateX(0);
146 | }
147 |
148 | 6.5% {
149 | transform: translateX(-6px) rotateY(-9deg);
150 | }
151 |
152 | 18.5% {
153 | transform: translateX(5px) rotateY(7deg);
154 | }
155 |
156 | 31.5% {
157 | transform: translateX(-3px) rotateY(-5deg);
158 | }
159 |
160 | 43.5% {
161 | transform: translateX(2px) rotateY(3deg);
162 | }
163 |
164 | 50% {
165 | transform: translateX(0);
166 | }
167 | }
168 |
169 | .headShake {
170 | animation-timing-function: ease-in-out;
171 | animation-name: headShake;
172 | }
173 |
174 | @keyframes swing {
175 | 20% {
176 | transform: rotate3d(0, 0, 1, 15deg);
177 | }
178 |
179 | 40% {
180 | transform: rotate3d(0, 0, 1, -10deg);
181 | }
182 |
183 | 60% {
184 | transform: rotate3d(0, 0, 1, 5deg);
185 | }
186 |
187 | 80% {
188 | transform: rotate3d(0, 0, 1, -5deg);
189 | }
190 |
191 | to {
192 | transform: rotate3d(0, 0, 1, 0deg);
193 | }
194 | }
195 |
196 | .swing {
197 | transform-origin: top center;
198 | animation-name: swing;
199 | }
200 |
201 | @keyframes tada {
202 | from {
203 | transform: scale3d(1, 1, 1);
204 | }
205 |
206 | 10%, 20% {
207 | transform: scale3d(.9, .9, .9) rotate3d(0, 0, 1, -3deg);
208 | }
209 |
210 | 30%, 50%, 70%, 90% {
211 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
212 | }
213 |
214 | 40%, 60%, 80% {
215 | transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
216 | }
217 |
218 | to {
219 | transform: scale3d(1, 1, 1);
220 | }
221 | }
222 |
223 | .tada {
224 | animation-name: tada;
225 | }
226 |
227 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
228 |
229 | @keyframes wobble {
230 | from {
231 | transform: none;
232 | }
233 |
234 | 15% {
235 | transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg);
236 | }
237 |
238 | 30% {
239 | transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg);
240 | }
241 |
242 | 45% {
243 | transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg);
244 | }
245 |
246 | 60% {
247 | transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg);
248 | }
249 |
250 | 75% {
251 | transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg);
252 | }
253 |
254 | to {
255 | transform: none;
256 | }
257 | }
258 |
259 | .wobble {
260 | animation-name: wobble;
261 | }
262 |
263 | @keyframes jello {
264 | from, 11.1%, to {
265 | transform: none;
266 | }
267 |
268 | 22.2% {
269 | transform: skewX(-12.5deg) skewY(-12.5deg);
270 | }
271 |
272 | 33.3% {
273 | transform: skewX(6.25deg) skewY(6.25deg);
274 | }
275 |
276 | 44.4% {
277 | transform: skewX(-3.125deg) skewY(-3.125deg);
278 | }
279 |
280 | 55.5% {
281 | transform: skewX(1.5625deg) skewY(1.5625deg);
282 | }
283 |
284 | 66.6% {
285 | transform: skewX(-0.78125deg) skewY(-0.78125deg);
286 | }
287 |
288 | 77.7% {
289 | transform: skewX(0.390625deg) skewY(0.390625deg);
290 | }
291 |
292 | 88.8% {
293 | transform: skewX(-0.1953125deg) skewY(-0.1953125deg);
294 | }
295 | }
296 |
297 | .jello {
298 | animation-name: jello;
299 | transform-origin: center;
300 | }
301 |
302 | @keyframes bounceIn {
303 | from, 20%, 40%, 60%, 80%, to {
304 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
305 | }
306 |
307 | 0% {
308 | opacity: 0;
309 | transform: scale3d(.3, .3, .3);
310 | }
311 |
312 | 20% {
313 | transform: scale3d(1.1, 1.1, 1.1);
314 | }
315 |
316 | 40% {
317 | transform: scale3d(.9, .9, .9);
318 | }
319 |
320 | 60% {
321 | opacity: 1;
322 | transform: scale3d(1.03, 1.03, 1.03);
323 | }
324 |
325 | 80% {
326 | transform: scale3d(.97, .97, .97);
327 | }
328 |
329 | to {
330 | opacity: 1;
331 | transform: scale3d(1, 1, 1);
332 | }
333 | }
334 |
335 | .bounceIn {
336 | animation-name: bounceIn;
337 | }
338 |
339 | @keyframes bounceInDown {
340 | from, 60%, 75%, 90%, to {
341 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
342 | }
343 |
344 | 0% {
345 | opacity: 0;
346 | transform: translate3d(0, -3000px, 0);
347 | }
348 |
349 | 60% {
350 | opacity: 1;
351 | transform: translate3d(0, 25px, 0);
352 | }
353 |
354 | 75% {
355 | transform: translate3d(0, -10px, 0);
356 | }
357 |
358 | 90% {
359 | transform: translate3d(0, 5px, 0);
360 | }
361 |
362 | to {
363 | transform: none;
364 | }
365 | }
366 |
367 | .bounceInDown {
368 | animation-name: bounceInDown;
369 | }
370 |
371 | @keyframes bounceInLeft {
372 | from, 60%, 75%, 90%, to {
373 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
374 | }
375 |
376 | 0% {
377 | opacity: 0;
378 | transform: translate3d(-3000px, 0, 0);
379 | }
380 |
381 | 60% {
382 | opacity: 1;
383 | transform: translate3d(25px, 0, 0);
384 | }
385 |
386 | 75% {
387 | transform: translate3d(-10px, 0, 0);
388 | }
389 |
390 | 90% {
391 | transform: translate3d(5px, 0, 0);
392 | }
393 |
394 | to {
395 | transform: none;
396 | }
397 | }
398 |
399 | .bounceInLeft {
400 | animation-name: bounceInLeft;
401 | }
402 |
403 | @keyframes bounceInRight {
404 | from, 60%, 75%, 90%, to {
405 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
406 | }
407 |
408 | from {
409 | opacity: 0;
410 | transform: translate3d(3000px, 0, 0);
411 | }
412 |
413 | 60% {
414 | opacity: 1;
415 | transform: translate3d(-25px, 0, 0);
416 | }
417 |
418 | 75% {
419 | transform: translate3d(10px, 0, 0);
420 | }
421 |
422 | 90% {
423 | transform: translate3d(-5px, 0, 0);
424 | }
425 |
426 | to {
427 | transform: none;
428 | }
429 | }
430 |
431 | .bounceInRight {
432 | animation-name: bounceInRight;
433 | }
434 |
435 | @keyframes bounceInUp {
436 | from, 60%, 75%, 90%, to {
437 | animation-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
438 | }
439 |
440 | from {
441 | opacity: 0;
442 | transform: translate3d(0, 3000px, 0);
443 | }
444 |
445 | 60% {
446 | opacity: 1;
447 | transform: translate3d(0, -20px, 0);
448 | }
449 |
450 | 75% {
451 | transform: translate3d(0, 10px, 0);
452 | }
453 |
454 | 90% {
455 | transform: translate3d(0, -5px, 0);
456 | }
457 |
458 | to {
459 | transform: translate3d(0, 0, 0);
460 | }
461 | }
462 |
463 | .bounceInUp {
464 | animation-name: bounceInUp;
465 | }
466 |
467 | @keyframes bounceOut {
468 | 20% {
469 | transform: scale3d(.9, .9, .9);
470 | }
471 |
472 | 50%, 55% {
473 | opacity: 1;
474 | transform: scale3d(1.1, 1.1, 1.1);
475 | }
476 |
477 | to {
478 | opacity: 0;
479 | transform: scale3d(.3, .3, .3);
480 | }
481 | }
482 |
483 | .bounceOut {
484 | animation-name: bounceOut;
485 | }
486 |
487 | @keyframes bounceOutDown {
488 | 20% {
489 | transform: translate3d(0, 10px, 0);
490 | }
491 |
492 | 40%, 45% {
493 | opacity: 1;
494 | transform: translate3d(0, -20px, 0);
495 | }
496 |
497 | to {
498 | opacity: 0;
499 | transform: translate3d(0, 2000px, 0);
500 | }
501 | }
502 |
503 | .bounceOutDown {
504 | animation-name: bounceOutDown;
505 | }
506 |
507 | @keyframes bounceOutLeft {
508 | 20% {
509 | opacity: 1;
510 | transform: translate3d(20px, 0, 0);
511 | }
512 |
513 | to {
514 | opacity: 0;
515 | transform: translate3d(-2000px, 0, 0);
516 | }
517 | }
518 |
519 | .bounceOutLeft {
520 | animation-name: bounceOutLeft;
521 | }
522 |
523 | @keyframes bounceOutRight {
524 | 20% {
525 | opacity: 1;
526 | transform: translate3d(-20px, 0, 0);
527 | }
528 |
529 | to {
530 | opacity: 0;
531 | transform: translate3d(2000px, 0, 0);
532 | }
533 | }
534 |
535 | .bounceOutRight {
536 | animation-name: bounceOutRight;
537 | }
538 |
539 | @keyframes bounceOutUp {
540 | 20% {
541 | transform: translate3d(0, -10px, 0);
542 | }
543 |
544 | 40%, 45% {
545 | opacity: 1;
546 | transform: translate3d(0, 20px, 0);
547 | }
548 |
549 | to {
550 | opacity: 0;
551 | transform: translate3d(0, -2000px, 0);
552 | }
553 | }
554 |
555 | .bounceOutUp {
556 | animation-name: bounceOutUp;
557 | }
558 |
559 | @keyframes fadeIn {
560 | from {
561 | opacity: 0;
562 | }
563 |
564 | to {
565 | opacity: 1;
566 | }
567 | }
568 |
569 | .fadeIn {
570 | animation-name: fadeIn;
571 | }
572 |
573 | @keyframes fadeInDown {
574 | from {
575 | opacity: 0;
576 | transform: translate3d(0, -100%, 0);
577 | }
578 |
579 | to {
580 | opacity: 1;
581 | transform: none;
582 | }
583 | }
584 |
585 | .fadeInDown {
586 | animation-name: fadeInDown;
587 | }
588 |
589 | @keyframes fadeInDownBig {
590 | from {
591 | opacity: 0;
592 | transform: translate3d(0, -2000px, 0);
593 | }
594 |
595 | to {
596 | opacity: 1;
597 | transform: none;
598 | }
599 | }
600 |
601 | .fadeInDownBig {
602 | animation-name: fadeInDownBig;
603 | }
604 |
605 | @keyframes fadeInLeft {
606 | from {
607 | opacity: 0;
608 | transform: translate3d(-100%, 0, 0);
609 | }
610 |
611 | to {
612 | opacity: 1;
613 | transform: none;
614 | }
615 | }
616 |
617 | .fadeInLeft {
618 | animation-name: fadeInLeft;
619 | }
620 |
621 | @keyframes fadeInLeftBig {
622 | from {
623 | opacity: 0;
624 | transform: translate3d(-2000px, 0, 0);
625 | }
626 |
627 | to {
628 | opacity: 1;
629 | transform: none;
630 | }
631 | }
632 |
633 | .fadeInLeftBig {
634 | animation-name: fadeInLeftBig;
635 | }
636 |
637 | @keyframes fadeInRight {
638 | from {
639 | opacity: 0;
640 | transform: translate3d(100%, 0, 0);
641 | }
642 |
643 | to {
644 | opacity: 1;
645 | transform: none;
646 | }
647 | }
648 |
649 | .fadeInRight {
650 | animation-name: fadeInRight;
651 | }
652 |
653 | @keyframes fadeInRightBig {
654 | from {
655 | opacity: 0;
656 | transform: translate3d(2000px, 0, 0);
657 | }
658 |
659 | to {
660 | opacity: 1;
661 | transform: none;
662 | }
663 | }
664 |
665 | .fadeInRightBig {
666 | animation-name: fadeInRightBig;
667 | }
668 |
669 | @keyframes fadeInUp {
670 | from {
671 | opacity: 0;
672 | transform: translate3d(0, 100%, 0);
673 | }
674 |
675 | to {
676 | opacity: 1;
677 | transform: none;
678 | }
679 | }
680 |
681 | .fadeInUp {
682 | animation-name: fadeInUp;
683 | }
684 |
685 | @keyframes fadeInUpBig {
686 | from {
687 | opacity: 0;
688 | transform: translate3d(0, 2000px, 0);
689 | }
690 |
691 | to {
692 | opacity: 1;
693 | transform: none;
694 | }
695 | }
696 |
697 | .fadeInUpBig {
698 | animation-name: fadeInUpBig;
699 | }
700 |
701 | @keyframes fadeOut {
702 | from {
703 | opacity: 1;
704 | }
705 |
706 | to {
707 | opacity: 0;
708 | }
709 | }
710 |
711 | .fadeOut {
712 | animation-name: fadeOut;
713 | }
714 |
715 | @keyframes fadeOutDown {
716 | from {
717 | opacity: 1;
718 | }
719 |
720 | to {
721 | opacity: 0;
722 | transform: translate3d(0, 100%, 0);
723 | }
724 | }
725 |
726 | .fadeOutDown {
727 | animation-name: fadeOutDown;
728 | }
729 |
730 | @keyframes fadeOutDownBig {
731 | from {
732 | opacity: 1;
733 | }
734 |
735 | to {
736 | opacity: 0;
737 | transform: translate3d(0, 2000px, 0);
738 | }
739 | }
740 |
741 | .fadeOutDownBig {
742 | animation-name: fadeOutDownBig;
743 | }
744 |
745 | @keyframes fadeOutLeft {
746 | from {
747 | opacity: 1;
748 | }
749 |
750 | to {
751 | opacity: 0;
752 | transform: translate3d(-100%, 0, 0);
753 | }
754 | }
755 |
756 | .fadeOutLeft {
757 | animation-name: fadeOutLeft;
758 | }
759 |
760 | @keyframes fadeOutLeftBig {
761 | from {
762 | opacity: 1;
763 | }
764 |
765 | to {
766 | opacity: 0;
767 | transform: translate3d(-2000px, 0, 0);
768 | }
769 | }
770 |
771 | .fadeOutLeftBig {
772 | animation-name: fadeOutLeftBig;
773 | }
774 |
775 | @keyframes fadeOutRight {
776 | from {
777 | opacity: 1;
778 | }
779 |
780 | to {
781 | opacity: 0;
782 | transform: translate3d(100%, 0, 0);
783 | }
784 | }
785 |
786 | .fadeOutRight {
787 | animation-name: fadeOutRight;
788 | }
789 |
790 | @keyframes fadeOutRightBig {
791 | from {
792 | opacity: 1;
793 | }
794 |
795 | to {
796 | opacity: 0;
797 | transform: translate3d(2000px, 0, 0);
798 | }
799 | }
800 |
801 | .fadeOutRightBig {
802 | animation-name: fadeOutRightBig;
803 | }
804 |
805 | @keyframes fadeOutUp {
806 | from {
807 | opacity: 1;
808 | }
809 |
810 | to {
811 | opacity: 0;
812 | transform: translate3d(0, -100%, 0);
813 | }
814 | }
815 |
816 | .fadeOutUp {
817 | animation-name: fadeOutUp;
818 | }
819 |
820 | @keyframes fadeOutUpBig {
821 | from {
822 | opacity: 1;
823 | }
824 |
825 | to {
826 | opacity: 0;
827 | transform: translate3d(0, -2000px, 0);
828 | }
829 | }
830 |
831 | .fadeOutUpBig {
832 | animation-name: fadeOutUpBig;
833 | }
834 |
835 | @keyframes flip {
836 | from {
837 | transform: perspective(400px) rotate3d(0, 1, 0, -360deg);
838 | animation-timing-function: ease-out;
839 | }
840 |
841 | 40% {
842 | transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -190deg);
843 | animation-timing-function: ease-out;
844 | }
845 |
846 | 50% {
847 | transform: perspective(400px) translate3d(0, 0, 150px) rotate3d(0, 1, 0, -170deg);
848 | animation-timing-function: ease-in;
849 | }
850 |
851 | 80% {
852 | transform: perspective(400px) scale3d(.95, .95, .95);
853 | animation-timing-function: ease-in;
854 | }
855 |
856 | to {
857 | transform: perspective(400px);
858 | animation-timing-function: ease-in;
859 | }
860 | }
861 |
862 | .animated.flip {
863 | -webkit-backface-visibility: visible;
864 | backface-visibility: visible;
865 | animation-name: flip;
866 | }
867 |
868 | @keyframes flipInX {
869 | from {
870 | transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
871 | animation-timing-function: ease-in;
872 | opacity: 0;
873 | }
874 |
875 | 40% {
876 | transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
877 | animation-timing-function: ease-in;
878 | }
879 |
880 | 60% {
881 | transform: perspective(400px) rotate3d(1, 0, 0, 10deg);
882 | opacity: 1;
883 | }
884 |
885 | 80% {
886 | transform: perspective(400px) rotate3d(1, 0, 0, -5deg);
887 | }
888 |
889 | to {
890 | transform: perspective(400px);
891 | }
892 | }
893 |
894 | .flipInX {
895 | -webkit-backface-visibility: visible !important;
896 | backface-visibility: visible !important;
897 | animation-name: flipInX;
898 | }
899 |
900 | @keyframes flipInY {
901 | from {
902 | transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
903 | animation-timing-function: ease-in;
904 | opacity: 0;
905 | }
906 |
907 | 40% {
908 | transform: perspective(400px) rotate3d(0, 1, 0, -20deg);
909 | animation-timing-function: ease-in;
910 | }
911 |
912 | 60% {
913 | transform: perspective(400px) rotate3d(0, 1, 0, 10deg);
914 | opacity: 1;
915 | }
916 |
917 | 80% {
918 | transform: perspective(400px) rotate3d(0, 1, 0, -5deg);
919 | }
920 |
921 | to {
922 | transform: perspective(400px);
923 | }
924 | }
925 |
926 | .flipInY {
927 | -webkit-backface-visibility: visible !important;
928 | backface-visibility: visible !important;
929 | animation-name: flipInY;
930 | }
931 |
932 | @keyframes flipOutX {
933 | from {
934 | transform: perspective(400px);
935 | }
936 |
937 | 30% {
938 | transform: perspective(400px) rotate3d(1, 0, 0, -20deg);
939 | opacity: 1;
940 | }
941 |
942 | to {
943 | transform: perspective(400px) rotate3d(1, 0, 0, 90deg);
944 | opacity: 0;
945 | }
946 | }
947 |
948 | .flipOutX {
949 | animation-name: flipOutX;
950 | -webkit-backface-visibility: visible !important;
951 | backface-visibility: visible !important;
952 | }
953 |
954 | @keyframes flipOutY {
955 | from {
956 | transform: perspective(400px);
957 | }
958 |
959 | 30% {
960 | transform: perspective(400px) rotate3d(0, 1, 0, -15deg);
961 | opacity: 1;
962 | }
963 |
964 | to {
965 | transform: perspective(400px) rotate3d(0, 1, 0, 90deg);
966 | opacity: 0;
967 | }
968 | }
969 |
970 | .flipOutY {
971 | -webkit-backface-visibility: visible !important;
972 | backface-visibility: visible !important;
973 | animation-name: flipOutY;
974 | }
975 |
976 | @keyframes lightSpeedIn {
977 | from {
978 | transform: translate3d(100%, 0, 0) skewX(-30deg);
979 | opacity: 0;
980 | }
981 |
982 | 60% {
983 | transform: skewX(20deg);
984 | opacity: 1;
985 | }
986 |
987 | 80% {
988 | transform: skewX(-5deg);
989 | opacity: 1;
990 | }
991 |
992 | to {
993 | transform: none;
994 | opacity: 1;
995 | }
996 | }
997 |
998 | .lightSpeedIn {
999 | animation-name: lightSpeedIn;
1000 | animation-timing-function: ease-out;
1001 | }
1002 |
1003 | @keyframes lightSpeedOut {
1004 | from {
1005 | opacity: 1;
1006 | }
1007 |
1008 | to {
1009 | transform: translate3d(100%, 0, 0) skewX(30deg);
1010 | opacity: 0;
1011 | }
1012 | }
1013 |
1014 | .lightSpeedOut {
1015 | animation-name: lightSpeedOut;
1016 | animation-timing-function: ease-in;
1017 | }
1018 |
1019 | @keyframes rotateIn {
1020 | from {
1021 | transform-origin: center;
1022 | transform: rotate3d(0, 0, 1, -200deg);
1023 | opacity: 0;
1024 | }
1025 |
1026 | to {
1027 | transform-origin: center;
1028 | transform: none;
1029 | opacity: 1;
1030 | }
1031 | }
1032 |
1033 | .rotateIn {
1034 | animation-name: rotateIn;
1035 | }
1036 |
1037 | @keyframes rotateInDownLeft {
1038 | from {
1039 | transform-origin: left bottom;
1040 | transform: rotate3d(0, 0, 1, -45deg);
1041 | opacity: 0;
1042 | }
1043 |
1044 | to {
1045 | transform-origin: left bottom;
1046 | transform: none;
1047 | opacity: 1;
1048 | }
1049 | }
1050 |
1051 | .rotateInDownLeft {
1052 | animation-name: rotateInDownLeft;
1053 | }
1054 |
1055 | @keyframes rotateInDownRight {
1056 | from {
1057 | transform-origin: right bottom;
1058 | transform: rotate3d(0, 0, 1, 45deg);
1059 | opacity: 0;
1060 | }
1061 |
1062 | to {
1063 | transform-origin: right bottom;
1064 | transform: none;
1065 | opacity: 1;
1066 | }
1067 | }
1068 |
1069 | .rotateInDownRight {
1070 | animation-name: rotateInDownRight;
1071 | }
1072 |
1073 | @keyframes rotateInUpLeft {
1074 | from {
1075 | transform-origin: left bottom;
1076 | transform: rotate3d(0, 0, 1, 45deg);
1077 | opacity: 0;
1078 | }
1079 |
1080 | to {
1081 | transform-origin: left bottom;
1082 | transform: none;
1083 | opacity: 1;
1084 | }
1085 | }
1086 |
1087 | .rotateInUpLeft {
1088 | animation-name: rotateInUpLeft;
1089 | }
1090 |
1091 | @keyframes rotateInUpRight {
1092 | from {
1093 | transform-origin: right bottom;
1094 | transform: rotate3d(0, 0, 1, -90deg);
1095 | opacity: 0;
1096 | }
1097 |
1098 | to {
1099 | transform-origin: right bottom;
1100 | transform: none;
1101 | opacity: 1;
1102 | }
1103 | }
1104 |
1105 | .rotateInUpRight {
1106 | animation-name: rotateInUpRight;
1107 | }
1108 |
1109 | @keyframes rotateOut {
1110 | from {
1111 | transform-origin: center;
1112 | opacity: 1;
1113 | }
1114 |
1115 | to {
1116 | transform-origin: center;
1117 | transform: rotate3d(0, 0, 1, 200deg);
1118 | opacity: 0;
1119 | }
1120 | }
1121 |
1122 | .rotateOut {
1123 | animation-name: rotateOut;
1124 | }
1125 |
1126 | @keyframes rotateOutDownLeft {
1127 | from {
1128 | transform-origin: left bottom;
1129 | opacity: 1;
1130 | }
1131 |
1132 | to {
1133 | transform-origin: left bottom;
1134 | transform: rotate3d(0, 0, 1, 45deg);
1135 | opacity: 0;
1136 | }
1137 | }
1138 |
1139 | .rotateOutDownLeft {
1140 | animation-name: rotateOutDownLeft;
1141 | }
1142 |
1143 | @keyframes rotateOutDownRight {
1144 | from {
1145 | transform-origin: right bottom;
1146 | opacity: 1;
1147 | }
1148 |
1149 | to {
1150 | transform-origin: right bottom;
1151 | transform: rotate3d(0, 0, 1, -45deg);
1152 | opacity: 0;
1153 | }
1154 | }
1155 |
1156 | .rotateOutDownRight {
1157 | animation-name: rotateOutDownRight;
1158 | }
1159 |
1160 | @keyframes rotateOutUpLeft {
1161 | from {
1162 | transform-origin: left bottom;
1163 | opacity: 1;
1164 | }
1165 |
1166 | to {
1167 | transform-origin: left bottom;
1168 | transform: rotate3d(0, 0, 1, -45deg);
1169 | opacity: 0;
1170 | }
1171 | }
1172 |
1173 | .rotateOutUpLeft {
1174 | animation-name: rotateOutUpLeft;
1175 | }
1176 |
1177 | @keyframes rotateOutUpRight {
1178 | from {
1179 | transform-origin: right bottom;
1180 | opacity: 1;
1181 | }
1182 |
1183 | to {
1184 | transform-origin: right bottom;
1185 | transform: rotate3d(0, 0, 1, 90deg);
1186 | opacity: 0;
1187 | }
1188 | }
1189 |
1190 | .rotateOutUpRight {
1191 | animation-name: rotateOutUpRight;
1192 | }
1193 |
1194 | @keyframes hinge {
1195 | 0% {
1196 | transform-origin: top left;
1197 | animation-timing-function: ease-in-out;
1198 | }
1199 |
1200 | 20%, 60% {
1201 | transform: rotate3d(0, 0, 1, 80deg);
1202 | transform-origin: top left;
1203 | animation-timing-function: ease-in-out;
1204 | }
1205 |
1206 | 40%, 80% {
1207 | transform: rotate3d(0, 0, 1, 60deg);
1208 | transform-origin: top left;
1209 | animation-timing-function: ease-in-out;
1210 | opacity: 1;
1211 | }
1212 |
1213 | to {
1214 | transform: translate3d(0, 700px, 0);
1215 | opacity: 0;
1216 | }
1217 | }
1218 |
1219 | .hinge {
1220 | animation-name: hinge;
1221 | }
1222 |
1223 | @keyframes jackInTheBox {
1224 | from {
1225 | opacity: 0;
1226 | transform: scale(0.1) rotate(30deg);
1227 | transform-origin: center bottom;
1228 | }
1229 |
1230 | 50% {
1231 | transform: rotate(-10deg);
1232 | }
1233 |
1234 | 70% {
1235 | transform: rotate(3deg);
1236 | }
1237 |
1238 | to {
1239 | opacity: 1;
1240 | transform: scale(1);
1241 | }
1242 | }
1243 |
1244 | .jackInTheBox {
1245 | animation-name: jackInTheBox;
1246 | }
1247 |
1248 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
1249 |
1250 | @keyframes rollIn {
1251 | from {
1252 | opacity: 0;
1253 | transform: translate3d(-100%, 0, 0) rotate3d(0, 0, 1, -120deg);
1254 | }
1255 |
1256 | to {
1257 | opacity: 1;
1258 | transform: none;
1259 | }
1260 | }
1261 |
1262 | .rollIn {
1263 | animation-name: rollIn;
1264 | }
1265 |
1266 | /* originally authored by Nick Pettit - https://github.com/nickpettit/glide */
1267 |
1268 | @keyframes rollOut {
1269 | from {
1270 | opacity: 1;
1271 | }
1272 |
1273 | to {
1274 | opacity: 0;
1275 | transform: translate3d(100%, 0, 0) rotate3d(0, 0, 1, 120deg);
1276 | }
1277 | }
1278 |
1279 | .rollOut {
1280 | animation-name: rollOut;
1281 | }
1282 |
1283 | @keyframes zoomIn {
1284 | from {
1285 | opacity: 0;
1286 | transform: scale3d(.3, .3, .3);
1287 | }
1288 |
1289 | 50% {
1290 | opacity: 1;
1291 | }
1292 | }
1293 |
1294 | .zoomIn {
1295 | animation-name: zoomIn;
1296 | }
1297 |
1298 | @keyframes zoomInDown {
1299 | from {
1300 | opacity: 0;
1301 | transform: scale3d(.1, .1, .1) translate3d(0, -1000px, 0);
1302 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
1303 | }
1304 |
1305 | 60% {
1306 | opacity: 1;
1307 | transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
1308 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
1309 | }
1310 | }
1311 |
1312 | .zoomInDown {
1313 | animation-name: zoomInDown;
1314 | }
1315 |
1316 | @keyframes zoomInLeft {
1317 | from {
1318 | opacity: 0;
1319 | transform: scale3d(.1, .1, .1) translate3d(-1000px, 0, 0);
1320 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
1321 | }
1322 |
1323 | 60% {
1324 | opacity: 1;
1325 | transform: scale3d(.475, .475, .475) translate3d(10px, 0, 0);
1326 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
1327 | }
1328 | }
1329 |
1330 | .zoomInLeft {
1331 | animation-name: zoomInLeft;
1332 | }
1333 |
1334 | @keyframes zoomInRight {
1335 | from {
1336 | opacity: 0;
1337 | transform: scale3d(.1, .1, .1) translate3d(1000px, 0, 0);
1338 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
1339 | }
1340 |
1341 | 60% {
1342 | opacity: 1;
1343 | transform: scale3d(.475, .475, .475) translate3d(-10px, 0, 0);
1344 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
1345 | }
1346 | }
1347 |
1348 | .zoomInRight {
1349 | animation-name: zoomInRight;
1350 | }
1351 |
1352 | @keyframes zoomInUp {
1353 | from {
1354 | opacity: 0;
1355 | transform: scale3d(.1, .1, .1) translate3d(0, 1000px, 0);
1356 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
1357 | }
1358 |
1359 | 60% {
1360 | opacity: 1;
1361 | transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
1362 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
1363 | }
1364 | }
1365 |
1366 | .zoomInUp {
1367 | animation-name: zoomInUp;
1368 | }
1369 |
1370 | @keyframes zoomOut {
1371 | from {
1372 | opacity: 1;
1373 | }
1374 |
1375 | 50% {
1376 | opacity: 0;
1377 | transform: scale3d(.3, .3, .3);
1378 | }
1379 |
1380 | to {
1381 | opacity: 0;
1382 | }
1383 | }
1384 |
1385 | .zoomOut {
1386 | animation-name: zoomOut;
1387 | }
1388 |
1389 | @keyframes zoomOutDown {
1390 | 40% {
1391 | opacity: 1;
1392 | transform: scale3d(.475, .475, .475) translate3d(0, -60px, 0);
1393 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
1394 | }
1395 |
1396 | to {
1397 | opacity: 0;
1398 | transform: scale3d(.1, .1, .1) translate3d(0, 2000px, 0);
1399 | transform-origin: center bottom;
1400 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
1401 | }
1402 | }
1403 |
1404 | .zoomOutDown {
1405 | animation-name: zoomOutDown;
1406 | }
1407 |
1408 | @keyframes zoomOutLeft {
1409 | 40% {
1410 | opacity: 1;
1411 | transform: scale3d(.475, .475, .475) translate3d(42px, 0, 0);
1412 | }
1413 |
1414 | to {
1415 | opacity: 0;
1416 | transform: scale(.1) translate3d(-2000px, 0, 0);
1417 | transform-origin: left center;
1418 | }
1419 | }
1420 |
1421 | .zoomOutLeft {
1422 | animation-name: zoomOutLeft;
1423 | }
1424 |
1425 | @keyframes zoomOutRight {
1426 | 40% {
1427 | opacity: 1;
1428 | transform: scale3d(.475, .475, .475) translate3d(-42px, 0, 0);
1429 | }
1430 |
1431 | to {
1432 | opacity: 0;
1433 | transform: scale(.1) translate3d(2000px, 0, 0);
1434 | transform-origin: right center;
1435 | }
1436 | }
1437 |
1438 | .zoomOutRight {
1439 | animation-name: zoomOutRight;
1440 | }
1441 |
1442 | @keyframes zoomOutUp {
1443 | 40% {
1444 | opacity: 1;
1445 | transform: scale3d(.475, .475, .475) translate3d(0, 60px, 0);
1446 | animation-timing-function: cubic-bezier(0.550, 0.055, 0.675, 0.190);
1447 | }
1448 |
1449 | to {
1450 | opacity: 0;
1451 | transform: scale3d(.1, .1, .1) translate3d(0, -2000px, 0);
1452 | transform-origin: center bottom;
1453 | animation-timing-function: cubic-bezier(0.175, 0.885, 0.320, 1);
1454 | }
1455 | }
1456 |
1457 | .zoomOutUp {
1458 | animation-name: zoomOutUp;
1459 | }
1460 |
1461 | @keyframes slideInDown {
1462 | from {
1463 | transform: translate3d(0, -100%, 0);
1464 | visibility: visible;
1465 | }
1466 |
1467 | to {
1468 | transform: translate3d(0, 0, 0);
1469 | }
1470 | }
1471 |
1472 | .slideInDown {
1473 | animation-name: slideInDown;
1474 | }
1475 |
1476 | @keyframes slideInLeft {
1477 | from {
1478 | transform: translate3d(-100%, 0, 0);
1479 | visibility: visible;
1480 | }
1481 |
1482 | to {
1483 | transform: translate3d(0, 0, 0);
1484 | }
1485 | }
1486 |
1487 | .slideInLeft {
1488 | animation-name: slideInLeft;
1489 | }
1490 |
1491 | @keyframes slideInRight {
1492 | from {
1493 | transform: translate3d(100%, 0, 0);
1494 | visibility: visible;
1495 | }
1496 |
1497 | to {
1498 | transform: translate3d(0, 0, 0);
1499 | }
1500 | }
1501 |
1502 | .slideInRight {
1503 | animation-name: slideInRight;
1504 | }
1505 |
1506 | @keyframes slideInUp {
1507 | from {
1508 | transform: translate3d(0, 100%, 0);
1509 | visibility: visible;
1510 | }
1511 |
1512 | to {
1513 | transform: translate3d(0, 0, 0);
1514 | }
1515 | }
1516 |
1517 | .slideInUp {
1518 | animation-name: slideInUp;
1519 | }
1520 |
1521 | @keyframes slideOutDown {
1522 | from {
1523 | transform: translate3d(0, 0, 0);
1524 | }
1525 |
1526 | to {
1527 | visibility: hidden;
1528 | transform: translate3d(0, 100%, 0);
1529 | }
1530 | }
1531 |
1532 | .slideOutDown {
1533 | animation-name: slideOutDown;
1534 | }
1535 |
1536 | @keyframes slideOutLeft {
1537 | from {
1538 | transform: translate3d(0, 0, 0);
1539 | }
1540 |
1541 | to {
1542 | visibility: hidden;
1543 | transform: translate3d(-100%, 0, 0);
1544 | }
1545 | }
1546 |
1547 | .slideOutLeft {
1548 | animation-name: slideOutLeft;
1549 | }
1550 |
1551 | @keyframes slideOutRight {
1552 | from {
1553 | transform: translate3d(0, 0, 0);
1554 | }
1555 |
1556 | to {
1557 | visibility: hidden;
1558 | transform: translate3d(100%, 0, 0);
1559 | }
1560 | }
1561 |
1562 | .slideOutRight {
1563 | animation-name: slideOutRight;
1564 | }
1565 |
1566 | @keyframes slideOutUp {
1567 | from {
1568 | transform: translate3d(0, 0, 0);
1569 | }
1570 |
1571 | to {
1572 | visibility: hidden;
1573 | transform: translate3d(0, -100%, 0);
1574 | }
1575 | }
1576 |
1577 | .slideOutUp {
1578 | animation-name: slideOutUp;
1579 | }
1580 |
--------------------------------------------------------------------------------
/src/renderer/assets/css/custom.css:
--------------------------------------------------------------------------------
1 | /* latin */
2 | @font-face {
3 | font-family: 'Roboto';
4 | font-style: normal;
5 | font-weight: 400;
6 | src: local('Roboto'), local('Roboto-Regular'), url('./fonts/Roboto-Regular.woff2') format('woff2');
7 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215;
8 | }
9 |
10 | body {
11 | background-color: #fff;
12 | user-select: none;
13 | }
14 |
15 | html {
16 | overflow-y: auto;
17 | }
18 |
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/MaterialIcons-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/MaterialIcons-Regular.woff2
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto-Regular.woff2
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-Black.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-BlackItalic.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-BoldItalic.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-Light.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/Roboto/Roboto-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/css/fonts/Roboto/Roboto-ThinItalic.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/css/fonts/icon.css:
--------------------------------------------------------------------------------
1 | /* fallback */
2 | @font-face {
3 | font-family: 'Material Icons';
4 | font-style: normal;
5 | font-weight: 400;
6 | src: url('MaterialIcons-Regular.woff2') format('woff2');
7 | }
8 |
9 | .material-icons {
10 | font-family: 'Material Icons';
11 | font-weight: normal;
12 | font-style: normal;
13 | font-size: 24px;
14 | line-height: 1;
15 | letter-spacing: normal;
16 | text-transform: none;
17 | display: inline-block;
18 | white-space: nowrap;
19 | word-wrap: normal;
20 | direction: ltr;
21 | -webkit-font-feature-settings: 'liga';
22 | -webkit-font-smoothing: antialiased;
23 | }
24 |
--------------------------------------------------------------------------------
/src/renderer/assets/img/user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/img/user.png
--------------------------------------------------------------------------------
/src/renderer/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/src/renderer/assets/logo.png
--------------------------------------------------------------------------------
/src/renderer/components/Avatar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ letter }}
5 |
6 |
7 |
8 |
28 |
--------------------------------------------------------------------------------
/src/renderer/components/Blih.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ email }}
10 | {{ login }}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {{ link.icon }}
19 | {{ link.title }}
20 |
21 |
22 |
23 | {{ link.icon }}
24 | {{ link.title }}
25 |
26 |
27 |
28 |
29 |
30 | menu
31 |
32 |
33 | arrow_back
34 |
35 | {{ title }}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
89 |
90 |
92 |
--------------------------------------------------------------------------------
/src/renderer/components/Blih/Page.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | {{ snackbar.message }}
8 | Dismiss
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | Try again
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
64 |
--------------------------------------------------------------------------------
/src/renderer/components/Blih/Repositories.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Repositories
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | {{ category.name }}
29 |
30 |
31 |
34 |
35 | {{ repo.module.icon }}
36 |
37 |
38 |
39 | {{ repo.name }}
40 |
41 |
42 |
43 |
44 |
45 | cloud Showing {{ nbFiltered }} of {{ repositories.length }} repositories
46 |
47 |
48 |
49 |
50 | No repository matches your query.
51 |
52 |
53 |
54 |
55 | No repository was found.
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 | Create a new repository
67 |
68 |
69 |
70 |
71 | add
72 |
73 |
74 |
75 |
76 |
201 |
--------------------------------------------------------------------------------
/src/renderer/components/Blih/Repository.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ name }}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {{ label.icon }} {{ label.name }}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Description
30 | {{ info.description }}
31 |
32 |
33 | Creation date
34 | {{ legibleTime(info.creation_time) }}
35 |
36 |
37 | Visibility
38 | {{ info.public == 'True' ? 'Public' : 'Private' }}
39 |
40 |
41 |
42 |
43 |
44 | person_add
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 | Collaborators
53 |
54 |
55 |
56 |
57 |
58 |
59 | {{ collaborator.name }}
60 | {{ legibleRights(collaborator.rights) }}
61 |
62 |
63 | edit
64 |
65 |
66 |
67 |
68 |
69 | No ACL is set for this repository.
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | Danger zone
85 |
86 | delete_forever
87 | Delete repository
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | Delete repository ?
97 | This will delete the repository {{ name }} forever.
98 |
99 |
100 |
101 |
113 |
114 |
115 |
116 |
117 | Add a collaborator
118 |
119 |
120 |
121 |
122 |
127 |
128 |
129 |
130 | {{ data.item }}
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 | Allow the user to access the repository
141 |
142 |
143 |
144 |
145 |
146 |
147 | Allow the user to push to the remote
148 |
149 |
150 |
151 |
152 |
153 |
154 | Grant admin privileges
155 |
156 |
157 |
158 |
159 | {{ dialog_add.error }}
160 |
161 | Cancel
162 | Add
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 | Edit a collaborator's rights
174 |
175 |
176 |
177 |
178 |
179 | {{ dialog_edit.name }}
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 | Allow the user to access the repository
190 |
191 |
192 |
193 |
194 |
195 |
196 | Allow the user to push to the remote
197 |
198 |
199 |
200 |
201 |
202 |
203 | Grant admin privileges
204 |
205 |
206 |
207 |
208 |
209 | Cancel
210 | Edit
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
408 |
409 |
411 |
--------------------------------------------------------------------------------
/src/renderer/components/Blih/Settings.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Settings
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | Welcome page
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Appearance
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
palette Theme colors
41 |
Primary
42 |
Secondary
43 |
Accent
44 |
Error
45 |
Info
46 |
Success
47 |
Warning
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Git configuration
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | delete Empty cache
68 |
69 | info The cache holds local copies of repositories. This allows a faster experience because repositories only need to be updated and not entirely cloned again.
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | Collaborators
81 |
82 |
83 |
84 |
85 |
86 |
87 | {{ collaborator.name }}
88 | aka {{ collaborator.aliases.join(', ') }}
89 |
90 |
91 | edit
92 |
93 |
94 |
95 |
96 | people {{ collaborators.length }} collaborators
97 |
98 |
99 |
100 |
101 | No known collaborators. Try to browse your repositories first.
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Modules
111 |
112 |
113 |
114 |
115 |
116 | {{ module.icon }}
117 |
118 |
119 | {{ module.name }}
120 |
121 |
122 | edit
123 |
124 |
125 |
126 |
127 | extension {{ modules.length }} modules
128 |
129 |
130 |
131 |
132 | No known modules.
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 | Empty cache ?
142 | This will delete the local repositories for user {{ login }} .
143 |
144 |
145 |
146 |
147 | Edit a collaborator's details
148 |
149 |
150 |
151 |
152 | {{ dialogEditCollaborator.collaborator.name }}
153 |
154 |
155 |
156 |
157 |
158 |
159 | Picture
160 |
161 |
162 | Aliases
163 |
164 |
165 |
166 |
167 |
168 | {{ alias }}
169 |
170 |
171 | delete
172 |
173 |
174 |
175 |
176 | No aliases
177 |
178 | add Add an alias
179 |
180 | info Aliases are used to identify collaborators through commit author name, if it is not the same as their login.
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 | Add an alias
189 |
190 |
191 |
192 |
193 | Edit a module
194 |
195 |
196 |
197 |
198 | {{ dialogEditModule.module.icon }}
199 |
200 | {{ dialogEditModule.module.name }}
201 |
202 |
203 |
204 |
205 |
206 |
207 | Icon
208 |
209 |
210 |
211 |
212 | Color
213 |
214 |
215 |
216 |
217 | Matches
218 |
219 |
220 |
221 |
222 |
223 | {{ regexp }}
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
406 |
--------------------------------------------------------------------------------
/src/renderer/components/Blih/SshKey.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ name }}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | Type
20 | {{ type }}
21 |
22 |
23 | Fingerprint
24 | {{ fingerprint }}
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | Key contents
35 |
36 |
37 |
38 | file_download
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | Danger zone
48 |
49 | delete
50 | Delete
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 | Delete key ?
60 | This will delete the key "{{ name }}" forever.
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | Download a public key
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | Cancel
78 | Download
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
180 |
--------------------------------------------------------------------------------
/src/renderer/components/Blih/SshKeys.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | SSH keys
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
24 |
25 |
26 | {{ key.name }}
27 |
28 |
29 |
30 |
31 | vpn_key Showing {{ filtered.length }} of {{ keys.length }} keys
32 |
33 |
34 |
35 | No key matches your query.
36 |
37 |
38 | No key was found.
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | Upload a key
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 | Cancel
61 | Upload
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | file_upload
70 |
71 |
72 |
73 |
74 |
152 |
--------------------------------------------------------------------------------
/src/renderer/components/Charts/ContributionsChart.js:
--------------------------------------------------------------------------------
1 | import { Pie, mixins } from 'vue-chartjs';
2 | const { reactiveProp } = mixins;
3 |
4 | export default {
5 | extends: Pie,
6 | mixins: [reactiveProp],
7 | mounted () {
8 | this.renderChart(this.chartData);
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/src/renderer/components/Charts/HistoryChart.js:
--------------------------------------------------------------------------------
1 | import { Line, mixins } from 'vue-chartjs';
2 | const { reactiveProp } = mixins;
3 |
4 | export default {
5 | extends: Line,
6 | mixins: [reactiveProp],
7 | mounted () {
8 | this.renderChart(this.chartData, {
9 | scales: {
10 | xAxes: [{
11 | display: true
12 | }],
13 | yAxes: [{
14 | display: true
15 | }]
16 | }
17 | });
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/src/renderer/components/Charts/LanguageChart.js:
--------------------------------------------------------------------------------
1 | import { Pie, mixins } from 'vue-chartjs';
2 | const { reactiveProp } = mixins;
3 |
4 | export default {
5 | extends: Pie,
6 | mixins: [reactiveProp],
7 | mounted () {
8 | this.renderChart(this.chartData);
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/src/renderer/components/Dialogs/DialogBasic.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {{ closeText }}
16 | {{ action }}
17 |
18 |
19 |
20 |
21 |
22 |
60 |
--------------------------------------------------------------------------------
/src/renderer/components/Dialogs/DialogFile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{ name }}
6 |
7 |
8 |
9 |
10 |
11 |
12 | {{ index }}
13 | {{ line }}
14 |
15 |
16 |
17 |
18 |
19 |
20 | {{ lines.length }} lines — {{ size }} bytes
21 |
22 | Close
23 |
24 |
25 |
26 |
27 |
57 |
77 |
--------------------------------------------------------------------------------
/src/renderer/components/Dialogs/DialogForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
17 |
18 |
19 |
20 | Cancel
21 | {{ action }}
22 |
23 |
24 |
25 |
26 |
27 |
28 |
78 |
--------------------------------------------------------------------------------
/src/renderer/components/Error.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
error
4 |
Oops!
5 |
6 | An error occured.
7 | If you believe this behaviour is not expected, please report it at github.com/kabukki/blih-vue/issues
8 |
9 |
Details
10 |
11 |
({{ error.name }}) {{ error.message }}
12 |
13 |
Stack trace
14 |
15 |
{{ error.stack }}
16 |
17 |
18 |
19 |
20 |
38 |
39 |
59 |
--------------------------------------------------------------------------------
/src/renderer/components/FileTree.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ icon }} {{ file.name }}
5 |
6 |
7 |
9 |
10 |
11 |
12 |
99 |
--------------------------------------------------------------------------------
/src/renderer/components/Git.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Git
5 |
6 |
7 |
8 |
9 |
10 | Overview
11 | home
12 |
13 | Files
14 | folder
15 |
16 | History
17 | history
18 |
19 | Insights
20 | explore
21 |
22 |
23 |
24 |
25 |
26 | link URL: {{ url }}
27 |
28 |
29 | merge_type Branches: {{ branches.length }}
30 |
31 |
32 | code Commits: {{ commits.length }}
33 |
34 |
35 | content_copy Files: {{ nbFiles }}
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | info Click on a folder to expand it.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | {{ commit.message }} — {{ shortHash(commit.sha) }}
56 |
57 | {{ commit.author.name }}
58 | <{{ commit.author.email }}>
59 |
60 |
61 |
62 |
63 | {{ legibleTime(commit.date) }}
64 |
65 |
66 |
67 |
68 |
69 | history {{ commits.length }} commits (on branch {{ branch }} )
70 |
71 |
72 |
73 |
74 | No commits
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | Languages used
83 |
84 | No data
85 |
86 |
87 | Contrubutions
88 |
89 | No data
90 |
91 |
92 | Commit frequency
93 |
94 | No data
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | Error: {{ error.message }}
104 |
105 |
106 |
107 |
108 |
110 |
111 | Fetching data ... ({{ initProgress.value }}% done)
112 |
113 |
114 |
115 |
116 | cloud_download
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 | Clone a repository
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 | Cancel
136 | Clone
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 | {{ dialogDiff.commit.message }} —
146 | {{ shortHash(dialogDiff.commit.sha) }}
147 |
148 |
149 |
150 |
151 |
152 |
153 | {{ file.status.icon }}
154 |
155 |
156 | {{ file.oldFile }}
157 |
158 | {{ file.stats.insertions }} insertions
159 | —
160 | {{ file.stats.deletions }} deletions
161 |
162 |
163 |
164 |
165 | {{ file.status.str }}
166 |
167 |
168 |
169 |
170 |
171 |
172 | Nothing to show.
173 |
174 |
175 |
176 | edit
177 | Total: {{ dialogDiff.totalAdditions + dialogDiff.totalDeletions }} changes (
178 | {{ dialogDiff.totalAdditions }} /
179 | {{ dialogDiff.totalDeletions }} )
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
448 |
--------------------------------------------------------------------------------
/src/renderer/components/Loader.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
9 |
11 |
--------------------------------------------------------------------------------
/src/renderer/components/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Log in
9 |
10 |
15 |
21 |
22 | OK
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
94 |
--------------------------------------------------------------------------------
/src/renderer/components/TileAvatar.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ letter }}
5 |
6 |
7 |
8 |
28 |
--------------------------------------------------------------------------------
/src/renderer/components/Welcome.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | BLIH
9 | Bocal Lightweight Interface for Humans
10 | Get started
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
21 |
22 |
43 |
--------------------------------------------------------------------------------
/src/renderer/helpers.js:
--------------------------------------------------------------------------------
1 | import Store from 'electron-store';
2 | import map from 'language-map';
3 | import colors from 'vuetify/es5/util/colors';
4 | import moment from 'moment';
5 | import store from './store';
6 | import path from 'path';
7 | import os from 'os';
8 |
9 | const sshDir = path.join(os.homedir(), '.ssh');
10 |
11 | export function ignoreCaseSort (a, b) {
12 | if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
13 | else if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
14 | else return 0;
15 | };
16 |
17 | export function getConfig () {
18 | return new Store({
19 | defaults: {
20 | lastEmail: '',
21 | theme: 'Default',
22 | dark: false,
23 | welcome: true,
24 | publicKeyPath: path.join(sshDir, 'id_rsa.pub'),
25 | privateKeyPath: path.join(sshDir, 'id_rsa')
26 | }
27 | });
28 | }
29 |
30 | export function getData (defaults) {
31 | return new Store({
32 | name: 'data',
33 | defaults
34 | });
35 | }
36 |
37 | /**
38 | * Return the language corresponding to this file
39 | */
40 | export function getFileLanguage (filename) {
41 | const ext = filename.slice((filename.lastIndexOf('.') - 1 >>> 0) + 1);
42 | for (const key in map) {
43 | const language = map[key];
44 |
45 | if ((language.extensions && language.extensions.includes(ext)) ||
46 | (language.filenames && language.filenames.includes(filename))) {
47 | return {
48 | name: key,
49 | ...language
50 | };
51 | }
52 | }
53 | return null;
54 | }
55 |
56 | /**
57 | * Get languages of a tree returned by RepositoryHub
58 | * Returns { lang... }
59 | */
60 | export function getTreeLanguages (files) {
61 | let languages = {};
62 |
63 | for (const file of files) {
64 | if (file.children) {
65 | let clanguages = getTreeLanguages(file.children);
66 | for (const lang in clanguages) {
67 | if (!languages.hasOwnProperty(lang)) {
68 | languages[lang] = 0;
69 | }
70 | languages[lang] += clanguages[lang];
71 | }
72 | } else if (file.type !== 'blob') {
73 | continue;
74 | }
75 |
76 | let language = getFileLanguage(file.name);
77 | if (language === null) continue;
78 |
79 | if (!languages.hasOwnProperty(language.name)) {
80 | languages[language.name] = 0;
81 | }
82 | languages[language.name]++;
83 | }
84 |
85 | return languages;
86 | }
87 |
88 | /**
89 | * Get languages of a tree returned by RepositoryHub as a chart.js data object
90 | */
91 | export function getTreeLanguagesChart (files) {
92 | let chart = {};
93 | let languages = getTreeLanguages(files);
94 |
95 | chart.labels = Object.keys(languages);
96 | chart.datasets = [{
97 | data: Object.values(languages),
98 | backgroundColor: Object.keys(languages).map(lang => map[lang].color || colors.grey.lighten1)
99 | }];
100 |
101 | return chart;
102 | }
103 |
104 | /**
105 | * Get history of commits returned by RepositoryHub as a chart.js data object
106 | */
107 | export function getHistoryChart (history) {
108 | let chart = {};
109 | let commits = {};
110 |
111 | for (const commit of history) {
112 | const author = commit.author().name();
113 | const date = moment(commit.date(), 'YYYY-MM-DD hh:mm:ss ZZ');
114 |
115 | if (!commits.hasOwnProperty(author)) {
116 | commits[author] = {};
117 | }
118 | if (!commits[author].hasOwnProperty(date)) {
119 | commits[author][date] = 0;
120 | }
121 | commits[author][date]++;
122 | }
123 |
124 | // console.log(commits);
125 | chart.labels = [];
126 | chart.datasets = Object.keys(commits)
127 | .map(author => ({
128 | label: author,
129 | data: Object.keys(commits[author])
130 | .map(date => commits[author][date]),
131 | backgroundColor: store.getters.rawColorOf(author)
132 | }));
133 |
134 | return chart;
135 | }
136 |
137 | /**
138 | * Get contributions returned by RepositoryHub as a chart.js data object
139 | */
140 | export function getContributionsChart (history) {
141 | let chart = {};
142 | let commits = {};
143 |
144 | for (const commit of history) {
145 | const author = commit.author().name();
146 |
147 | if (!commits.hasOwnProperty(author)) {
148 | commits[author] = 0;
149 | }
150 | commits[author]++;
151 | }
152 |
153 | chart.labels = Object.keys(commits);
154 | chart.datasets = [{
155 | data: Object.values(commits),
156 | backgroundColor: Object.keys(commits).map(author => store.getters.rawColorOf(author))
157 | }];
158 |
159 | return chart;
160 | }
161 |
--------------------------------------------------------------------------------
/src/renderer/main.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | import App from './App';
4 | import store from './store';
5 | import router from './router';
6 |
7 | import Vuetify from 'vuetify';
8 |
9 | /* CSS */
10 | import 'vuetify/dist/vuetify.min.css';
11 | import './assets/css/fonts/icon.css';
12 | import './assets/css/custom.css';
13 |
14 | const theme = store.getters.themes.find(t => t.name === store.getters.theme);
15 | Vue.use(Vuetify, theme && {
16 | theme: theme.colors
17 | });
18 |
19 | Vue.config.productionTip = false;
20 |
21 | /* Skip welcome page ? */
22 | if (!store.getters.welcome) {
23 | router.push({ name: 'login' });
24 | }
25 |
26 | /* eslint-disable no-new */
27 | new Vue({
28 | components: { App },
29 | router,
30 | store,
31 | template: ' '
32 | }).$mount('#app');
33 |
--------------------------------------------------------------------------------
/src/renderer/mixins.js:
--------------------------------------------------------------------------------
1 | export const snackbar = {
2 | data () {
3 | return {
4 | snackbar: {
5 | show: false,
6 | color: '',
7 | message: ''
8 | }
9 | };
10 | },
11 | methods: {
12 | showSnackbar (color, message) {
13 | this.snackbar = {
14 | show: true,
15 | color,
16 | message
17 | };
18 | }
19 | }
20 | };
21 |
--------------------------------------------------------------------------------
/src/renderer/router/index.js:
--------------------------------------------------------------------------------
1 | /* eslint object-property-newline: 0 */
2 |
3 | import Vue from 'vue';
4 | import VueRouter from 'vue-router';
5 |
6 | import Welcome from '../components/Welcome';
7 | import Login from '../components/Login';
8 | import Blih from '../components/Blih';
9 | import Repositories from '../components/Blih/Repositories';
10 | import Repository from '../components/Blih/Repository';
11 | import SshKeys from '../components/Blih/SshKeys';
12 | import SshKey from '../components/Blih/SshKey';
13 | import Settings from '../components/Blih/Settings';
14 |
15 | Vue.use(VueRouter);
16 |
17 | export default new VueRouter({
18 | routes: [
19 | { path: '/', name: 'welcome', component: Welcome },
20 | { path: '/login', name: 'login', component: Login },
21 | { path: '/blih', name: 'blih', component: Blih, children: [
22 | { path: '/repositories', name: 'blih.repositories', component: Repositories },
23 | { path: '/repository/:name', name: 'blih.repository', component: Repository },
24 | { path: '/ssh-keys', name: 'blih.ssh-keys', component: SshKeys },
25 | { path: '/ssh-key/:name', name: 'blih.ssh-key', component: SshKey },
26 | { path: '/settings', name: 'blih.settings', component: Settings }
27 | ]},
28 | { path: '*', redirect: '/' }
29 | ]
30 | });
31 |
--------------------------------------------------------------------------------
/src/renderer/store/actions.js:
--------------------------------------------------------------------------------
1 | import Blih from 'blih';
2 |
3 | import { ignoreCaseSort } from '../helpers';
4 |
5 | export default {
6 | authenticate (context, credentials) {
7 | try {
8 | let api = new Blih({ email: credentials.email, password: credentials.password });
9 | return api.whoami()
10 | .then(data => {
11 | context.commit('AUTHENTICATE', {
12 | api,
13 | email: credentials.email,
14 | login: data
15 | });
16 | });
17 | } catch (err) {
18 | return Promise.reject(err);
19 | }
20 | },
21 | async updateRepositories (context) {
22 | const repos = await context.getters.api.listRepositories();
23 | context.commit('UPDATE_REPOSITORIES', {
24 | repositories: repos.sort(ignoreCaseSort)
25 | .map(r => Object.freeze({
26 | ...r,
27 | module: context.getters.getModule(r.name)
28 | }))
29 | });
30 | },
31 | createRepository (context, name) {
32 | return context.getters.api.createRepository(name)
33 | .then(_ => {
34 | context.commit('ADD_REPOSITORY', {
35 | name,
36 | label: context.getters.getModule(name)
37 | });
38 | });
39 | },
40 | deleteRepository (context, name) {
41 | return context.getters.api.deleteRepository(name)
42 | .then(_ => {
43 | context.commit('REMOVE_REPOSITORY', {
44 | name
45 | });
46 | });
47 | },
48 | updateKeys (context) {
49 | return context.getters.api.listKeys()
50 | .then(data => {
51 | context.commit('UPDATE_KEYS', { keys: data });
52 | });
53 | },
54 | uploadKey (context, key) {
55 | const oldKeys = context.getters.keys;
56 | return context.getters.api.uploadKey(key)
57 | .then(_ => context.dispatch('updateKeys'))
58 | // Return the new key
59 | .then(_ => context.getters.keys.filter(k => !oldKeys.find(ok => ok.name === k.name))[0]);
60 | },
61 | deleteKey (context, key) {
62 | return context.getters.api.deleteKey(key)
63 | .then(_ => {
64 | context.commit('REMOVE_KEY', {
65 | name: key
66 | });
67 | });
68 | },
69 | /* Config */
70 | setLastEmail (context, email) {
71 | context.commit('SET_LAST_EMAIL', { email });
72 | },
73 | setTheme (context, theme) {
74 | context.commit('SET_THEME', { theme });
75 | },
76 | setDark (context, value) {
77 | context.commit('SET_DARK', { value });
78 | },
79 | setWelcome (context, value) {
80 | context.commit('SET_WELCOME', { value });
81 | },
82 | setPublicKeyPath (context, path) {
83 | context.commit('SET_PUBLIC_KEY_PATH', { path });
84 | },
85 | setPrivateKeyPath (context, path) {
86 | context.commit('SET_PRIVATE_KEY_PATH', { path });
87 | },
88 | /* Data */
89 | addCollaborator (context, name) {
90 | if (!context.getters.collaborators.find(c => c.name === name)) {
91 | context.commit('ADD_COLLABORATOR', {
92 | name,
93 | picture: false,
94 | aliases: []
95 | });
96 | }
97 | },
98 | updateCollaborator (context, data) {
99 | if (context.getters.collaborators.find(c => c.name === data.name)) {
100 | context.commit('UPDATE_COLLABORATOR', data);
101 | }
102 | },
103 | updateModule (context, data) {
104 | if (context.getters.modules.find(c => c.name === data.name)) {
105 | context.commit('UPDATE_MODULE', data);
106 | }
107 | }
108 | };
109 |
--------------------------------------------------------------------------------
/src/renderer/store/defaults.js:
--------------------------------------------------------------------------------
1 | import colors from 'vuetify/es5/util/colors';
2 |
3 | /* Default data */
4 |
5 | export const collaborators = [
6 | {
7 | name: 'ramassage-tek',
8 | picture: false,
9 | aliases: []
10 | }
11 | ];
12 |
13 | export const colorMap = {
14 | a: 'red',
15 | b: 'pink',
16 | c: 'purple',
17 | d: 'deep-purple',
18 | e: 'indigo',
19 | f: 'blue',
20 | g: 'light-blue',
21 | h: 'cyan',
22 | i: 'teal',
23 | j: 'green',
24 | k: 'light-green',
25 | l: 'lime',
26 | m: 'yellow darken-1',
27 | n: 'amber',
28 | o: 'orange',
29 | p: 'deep-orange',
30 | q: 'brown',
31 | r: 'blue-grey',
32 | s: 'grey',
33 | t: 'red lighten-2',
34 | u: 'pink lighten-2',
35 | v: 'purple lighten-2',
36 | w: 'deep-purple lighten-2',
37 | x: 'indigo lighten-2',
38 | y: 'blue lighten-2',
39 | z: 'light-blue lighten-2',
40 | '0': 'cyan lighten-2',
41 | '1': 'teal lighten-2',
42 | '2': 'green lighten-2',
43 | '3': 'light-green lighten-2',
44 | '4': 'lime lighten-2',
45 | '5': 'yellow',
46 | '6': 'amber lighten-2',
47 | '7': 'orange lighten-2',
48 | '8': 'deep-orange lighten-2',
49 | '9': 'brown lighten-2',
50 | other: 'black'
51 | };
52 |
53 | export const rawColorMap = {
54 | a: colors.red.base,
55 | b: colors.pink.base,
56 | c: colors.purple.base,
57 | d: colors.deepPurple.base,
58 | e: colors.indigo.base,
59 | f: colors.blue.base,
60 | g: colors.lightBlue.base,
61 | h: colors.cyan.base,
62 | i: colors.teal.base,
63 | j: colors.green.base,
64 | k: colors.lightGreen.base,
65 | l: colors.lime.base,
66 | m: colors.yellow.darken1,
67 | n: colors.amber.base,
68 | o: colors.orange.base,
69 | p: colors.deepOrange.base,
70 | q: colors.brown.base,
71 | r: colors.blueGrey.base,
72 | s: colors.grey.base,
73 | t: colors.red.lighten2,
74 | u: colors.pink.lighten2,
75 | v: colors.purple.lighten2,
76 | w: colors.deepPurple.lighten2,
77 | x: colors.indigo.lighten2,
78 | y: colors.blue.lighten2,
79 | z: colors.lightBlue.lighten2,
80 | '0': colors.cyan.lighten2,
81 | '1': colors.teal.lighten2,
82 | '2': colors.green.lighten2,
83 | '3': colors.lightGreen.lighten2,
84 | '4': colors.lime.lighten2,
85 | '5': colors.yellow.lighten2,
86 | '6': colors.amber.lighten2,
87 | '7': colors.orange.lighten2,
88 | '8': colors.deepOrange.lighten2,
89 | '9': colors.brown.lighten2,
90 | other: colors.black
91 | };
92 |
93 | export const modules = [
94 | {
95 | name: 'Artificial Intelligence',
96 | icon: 'bubble_chart',
97 | color: 'green',
98 | regexp: [
99 | '^dante$', '^gomoku$', '^need4steak$'
100 | ]
101 | }, {
102 | name: 'Assembly',
103 | icon: 'code',
104 | color: 'brown',
105 | regexp: [
106 | '^asm_'
107 | ]
108 | }, {
109 | name: 'Mathematics',
110 | icon: 'functions',
111 | color: 'indigo',
112 | regexp: [
113 | '101pong', '102cipher', '103architect', '104intersection', '105torus', '106bombyx', '107transfer', '108trigo', '109titration', '110borwein',
114 | '201yams', '202unsold', '203hotline', '204ducks', '205IQ', '206neutrinos', '207demography', '208dowels', '208pegs', '209poll',
115 | '301dannon', '302separation', '303make', '304pacman', '305construction', '306radiator', '307multigrains', '308reedpipes', '309pollution'
116 | ]
117 | }, {
118 | name: 'French',
119 | icon: 'edit',
120 | color: 'red',
121 | regexp: [
122 | 'B1Lettre', 'B1Mailpro', 'B1Rush',
123 | 'B2EMPLOI', 'B2PRECISER', 'B2VENTE',
124 | 'B4BILAN', 'B4DIAPO', 'B4RECADRER',
125 | 'B53EMAILS', 'B5AVOCAT', 'B5MEMO', 'FICTION1',
126 | '^Disparition20\\d{2}'
127 | ]
128 | }, {
129 | name: 'CPE',
130 | icon: 'code',
131 | color: 'grey',
132 | regexp: [
133 | '^CPE_', '^marvin_', '^sudoki-bi$'
134 | ]
135 | }, {
136 | name: 'PSU',
137 | icon: 'code',
138 | color: 'amber',
139 | regexp: [
140 | '^PSU_'
141 | ]
142 | }, {
143 | name: 'C++',
144 | icon: 'code',
145 | color: 'lime',
146 | regexp: [
147 | '^cpp_(nanotekspice|arcade|spider)$'
148 | ]
149 | }, {
150 | name: 'Computer graphics',
151 | icon: 'desktop_windows',
152 | color: 'deep-orange',
153 | regexp: [
154 | '^(alphachannel|binarizer|chatty|chromatic|flip_part|flashlight|iconofsin|lightning|mystic|mystify|nocss|noise|starfield|stretcher|text_foot|whirlpool|xorshape)_20\\d{2}$',
155 | '^gfx_', '^tekadventure$', '^bsraytracer1$', '^raytracer1$', '^wireframe$', '^wolf3d$'
156 | ]
157 | }, {
158 | name: 'C Pool',
159 | icon: 'pool',
160 | color: 'light-blue',
161 | regexp: [
162 | '^Piscine_C', '^CPool_'
163 | ]
164 | }, {
165 | name: 'C++ Pool',
166 | icon: 'pool',
167 | color: 'cyan',
168 | regexp: [
169 | '^cpp_d[01]\\d[am]*', '^cpp_(gkrellm|santa|SKL)$'
170 | ]
171 | }, {
172 | name: '.NET',
173 | icon: 'code',
174 | color: 'teal',
175 | regexp: [
176 | '^DOT_'
177 | ]
178 | }, {
179 | name: 'OCaml',
180 | icon: 'code',
181 | color: 'yellow',
182 | regexp: [
183 | '^OCAML_'
184 | ]
185 | }, {
186 | name: 'Shell',
187 | icon: 'code',
188 | color: 'blue-grey',
189 | regexp: [
190 | '^SHL_'
191 | ]
192 | }, {
193 | name: 'Java',
194 | icon: 'code',
195 | color: 'orange',
196 | regexp: [
197 | '^Java_\\w+_20\\d{2}'
198 | ]
199 | }, {
200 | name: 'Internship',
201 | icon: 'work',
202 | color: 'pink',
203 | regexp: [
204 | '^stageTEK', '^internship_20\\d{2}$'
205 | ]
206 | }, {
207 | name: 'Security',
208 | icon: 'lock',
209 | color: 'deep-orange',
210 | regexp: [
211 | '^binary_seminar$'
212 | ]
213 | }, {
214 | name: 'Cryptography',
215 | icon: 'lock',
216 | color: 'deep-purple',
217 | regexp: [
218 | '^pamela$'
219 | ]
220 | }, {
221 | name: 'Android',
222 | icon: 'android',
223 | color: 'light-green',
224 | regexp: [
225 |
226 | ]
227 | }, {
228 | name: 'Synthesis pool',
229 | icon: 'pool',
230 | color: 'blue',
231 | regexp: [
232 | '^ADM_', 'automakefile', 'calendar', 'FASTAtools', 'palindrome', 'projTester', 'SBMLparser'
233 | ]
234 | }
235 | ];
236 |
237 | export const themes = [
238 | {
239 | name: 'Default',
240 | colors: {
241 | 'primary': '#1976D2',
242 | 'secondary': '#424242',
243 | 'accent': '#82B1FF',
244 | 'error': '#FF5252',
245 | 'warning': '#FFC107',
246 | 'info': '#2196F3',
247 | 'success': '#4CAF50'
248 | }
249 | }, {
250 | name: 'Halloween',
251 | colors: {
252 | 'primary': '#FB8C00',
253 | 'secondary': '#000000',
254 | 'accent': '#FFD180',
255 | 'error': '#F44336',
256 | 'warning': '#FFC107',
257 | 'info': '#2196F3',
258 | 'success': '#4CAF50'
259 | }
260 | }, {
261 | name: 'Christmas',
262 | colors: {
263 | 'primary': '#F44336',
264 | 'secondary': '#2E7D32',
265 | 'accent': '#795548',
266 | 'error': '#F44336',
267 | 'warning': '#FFC107',
268 | 'info': '#2196F3',
269 | 'success': '#4CAF50'
270 | }
271 | }
272 | ];
273 |
--------------------------------------------------------------------------------
/src/renderer/store/getters.js:
--------------------------------------------------------------------------------
1 | export default {
2 | api: state => state.api,
3 | email: state => state.email,
4 | login: state => state.login,
5 | repositories: state => state.repositories,
6 | keys: state => state.keys,
7 | /* Config */
8 | lastEmail: state => state.lastEmail,
9 | theme: state => state.theme,
10 | dark: state => state.dark,
11 | welcome: state => state.welcome,
12 | publicKeyPath: state => state.publicKeyPath,
13 | privateKeyPath: state => state.privateKeyPath,
14 | /* Data */
15 | collaborators: state => state.collaborators,
16 | colorMap: state => state.colorMap,
17 | rawColorMap: state => state.rawColorMap,
18 | colorOf: state => text => {
19 | const letter = (text && text.length) ? text[0].toLowerCase() : '?';
20 | return state.colorMap[letter] || state.colorMap['other'];
21 | },
22 | rawColorOf: state => text => {
23 | const letter = (text && text.length) ? text[0].toLowerCase() : '?';
24 | return state.rawColorMap[letter] || state.rawColorMap['other'];
25 | },
26 | modules: state => state.modules,
27 | getModule: state => repo => {
28 | for (const module of state.modules) {
29 | for (const regexp of module.regexp) {
30 | if (repo.match(regexp)) {
31 | return {
32 | name: module.name,
33 | icon: module.icon,
34 | color: module.color
35 | };
36 | }
37 | }
38 | }
39 | return null;
40 | },
41 | themes: state => state.themes
42 | };
43 |
--------------------------------------------------------------------------------
/src/renderer/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vuex from 'vuex';
3 |
4 | import state from './state';
5 | import mutations from './mutations';
6 | import getters from './getters';
7 | import actions from './actions';
8 |
9 | Vue.use(Vuex);
10 |
11 | /*
12 | * Vuex
13 | */
14 |
15 | export default new Vuex.Store({
16 | state,
17 | mutations,
18 | getters,
19 | actions,
20 | strict: process.env.NODE_ENV !== 'production'
21 | });
22 |
--------------------------------------------------------------------------------
/src/renderer/store/mutations.js:
--------------------------------------------------------------------------------
1 | import { ignoreCaseSort, getConfig, getData } from '../helpers';
2 |
3 | let [data, config] = [getData(), getConfig()];
4 |
5 | export default {
6 | AUTHENTICATE (state, payload) {
7 | state.api = payload.api;
8 | state.email = payload.email;
9 | state.login = payload.login;
10 | },
11 | UPDATE_REPOSITORIES (state, payload) {
12 | state.repositories = payload.repositories;
13 | },
14 | ADD_REPOSITORY (state, payload) {
15 | state.repositories.push(payload);
16 | state.repositories = state.repositories.sort(ignoreCaseSort);
17 | },
18 | REMOVE_REPOSITORY (state, payload) {
19 | state.repositories = state.repositories.filter(r => r.name !== payload.name);
20 | },
21 | UPDATE_KEYS (state, payload) {
22 | state.keys = payload.keys;
23 | },
24 | ADD_KEY (state, payload) {
25 | state.keys.push(payload);
26 | state.keys = state.keys.sort(ignoreCaseSort);
27 | },
28 | REMOVE_KEY (state, payload) {
29 | state.keys = state.keys.filter(k => k.name !== payload.name);
30 | },
31 | /* Config */
32 | SET_LAST_EMAIL (state, payload) {
33 | state.lastEmail = payload.email;
34 | config.set('lastEmail', state.lastEmail);
35 | },
36 | SET_THEME (state, payload) {
37 | state.theme = payload.theme;
38 | config.set('theme', state.theme);
39 | },
40 | SET_DARK (state, payload) {
41 | state.dark = payload.value;
42 | config.set('dark', state.dark);
43 | },
44 | SET_WELCOME (state, payload) {
45 | state.welcome = payload.value;
46 | config.set('welcome', state.welcome);
47 | },
48 | SET_PUBLIC_KEY_PATH (state, payload) {
49 | state.publicKeyPath = payload.path;
50 | config.set('publicKeyPath', state.publicKeyPath);
51 | },
52 | SET_PRIVATE_KEY_PATH (state, payload) {
53 | state.privateKeyPath = payload.path;
54 | config.set('privateKeyPath', state.privateKeyPath);
55 | },
56 | /* Data */
57 | ADD_COLLABORATOR (state, payload) {
58 | state.collaborators.push(payload);
59 | data.set('collaborators', state.collaborators.sort(ignoreCaseSort));
60 | },
61 | UPDATE_COLLABORATOR (state, payload) {
62 | let index = state.collaborators.findIndex(c => c.name === payload.name);
63 | if (index >= 0) {
64 | state.collaborators[index] = payload;
65 | data.set('collaborators', state.collaborators.sort(ignoreCaseSort));
66 | }
67 | },
68 | UPDATE_MODULE (state, payload) {
69 | let index = state.modules.findIndex(c => c.name === payload.name);
70 | if (index >= 0) {
71 | state.modules[index] = payload;
72 | data.set('modules', state.modules.sort(ignoreCaseSort));
73 | }
74 | }
75 | };
76 |
--------------------------------------------------------------------------------
/src/renderer/store/state.js:
--------------------------------------------------------------------------------
1 | import * as defaults from './defaults';
2 | import { ignoreCaseSort, getConfig, getData } from '../helpers';
3 |
4 | let [data, config] = [getData(defaults), getConfig()];
5 |
6 | // IDEA: one object for all config and data
7 | export default {
8 | api: null,
9 | email: null,
10 | login: null,
11 | repositories: [],
12 | keys: [],
13 | /* Config */
14 | lastEmail: config.get('lastEmail'),
15 | theme: config.get('theme'),
16 | dark: config.get('dark'),
17 | welcome: config.get('welcome'),
18 | publicKeyPath: config.get('publicKeyPath'),
19 | privateKeyPath: config.get('privateKeyPath'),
20 | /* Data */
21 | collaborators: data.get('collaborators').sort(ignoreCaseSort),
22 | colorMap: defaults.colorMap, // data.get('colorMap'),
23 | rawColorMap: defaults.rawColorMap,
24 | modules: defaults.modules.sort(ignoreCaseSort), // data.get('modules').sort(ignoreCaseSort),
25 | themes: defaults.themes.sort(ignoreCaseSort) // data.get('themes').sort(ignoreCaseSort)
26 | };
27 |
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/static/.gitkeep
--------------------------------------------------------------------------------
/static/256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kabukki/blih-vue/65a30b26aa49ea56a5c37a57d11ff8b4111909d3/static/256.png
--------------------------------------------------------------------------------
/todo.txt:
--------------------------------------------------------------------------------
1 | Upload component (vuetify front-end pack, Q2 2018)
2 | opti: page repositories keep-alive?
3 | diff dialog
4 | Bouton try again dans Git.vue on error
5 |
6 | --- problems ---
7 | production:
8 |
9 | --- ameliorations ---
10 | Dialogs:
11 | customisation des fields, decorations et leur position (avec form)
12 | repositoryHub global (avec vuex)
13 |
--------------------------------------------------------------------------------