From 324a5aa347a4352a4f89fb70cfe2ded51e56b0d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment?= Date: Fri, 28 Sep 2018 21:20:15 +0200 Subject: [PATCH] refactoring --- .babelrc | 12 ++ .gitignore | 8 ++ .gitmodules | 9 ++ Makefile | 56 ++++++++ README.md | 0 copy_lib.js | 20 +++ lib_list.txt | 3 + package.json | 20 +++ server.js | 22 +++ src/dependencies.pug | 27 ++++ src/index.pug | 36 +++++ src/menu.pug | 27 ++++ src/pages/channel-chat.pug | 2 + src/pages/channel-create.pug | 7 + src/pages/channel-edit.pug | 7 + src/pages/channel-profile.pug | 38 +++++ src/pages/channel.pug | 15 ++ src/pages/channels.pug | 7 + src/pages/job-offers.pug | 40 ++++++ src/pages/member-chat.pug | 2 + src/pages/member-edit.pug | 97 +++++++++++++ src/pages/member-profile.pug | 13 ++ src/pages/member.pug | 12 ++ src/pages/members.pug | 1 + src/pages/project-chat.pug | 2 + src/pages/project-create.pug | 7 + src/pages/project-edit.pug | 7 + src/pages/project-profile.pug | 16 +++ src/pages/project.pug | 15 ++ src/pages/projects.pug | 29 ++++ src/scripts/hd-app.js | 61 ++++++++ src/scripts/index.js | 15 ++ src/styles/functions.scss | 0 src/styles/icons.scss | 264 ++++++++++++++++++++++++++++++++++ src/styles/index.scss | 10 ++ src/styles/main.scss | 41 ++++++ src/styles/menu.scss | 133 +++++++++++++++++ src/styles/mixins.scss | 149 +++++++++++++++++++ src/styles/variables.scss | 17 +++ src/variables.pug | 2 + 40 files changed, 1249 insertions(+) create mode 100644 .babelrc create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 Makefile create mode 100644 README.md create mode 100644 copy_lib.js create mode 100644 lib_list.txt create mode 100644 package.json create mode 100644 server.js create mode 100644 src/dependencies.pug create mode 100644 src/index.pug create mode 100644 src/menu.pug create mode 100644 src/pages/channel-chat.pug create mode 100644 src/pages/channel-create.pug create mode 100644 src/pages/channel-edit.pug create mode 100644 src/pages/channel-profile.pug create mode 100644 src/pages/channel.pug create mode 100644 src/pages/channels.pug create mode 100644 src/pages/job-offers.pug create mode 100644 src/pages/member-chat.pug create mode 100644 src/pages/member-edit.pug create mode 100644 src/pages/member-profile.pug create mode 100644 src/pages/member.pug create mode 100644 src/pages/members.pug create mode 100644 src/pages/project-chat.pug create mode 100644 src/pages/project-create.pug create mode 100644 src/pages/project-edit.pug create mode 100644 src/pages/project-profile.pug create mode 100644 src/pages/project.pug create mode 100644 src/pages/projects.pug create mode 100644 src/scripts/hd-app.js create mode 100644 src/scripts/index.js create mode 100644 src/styles/functions.scss create mode 100644 src/styles/icons.scss create mode 100644 src/styles/index.scss create mode 100644 src/styles/main.scss create mode 100644 src/styles/menu.scss create mode 100644 src/styles/mixins.scss create mode 100644 src/styles/variables.scss create mode 100644 src/variables.pug diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..5877e72 --- /dev/null +++ b/.babelrc @@ -0,0 +1,12 @@ +{ + "presets": [ + [ + "@babel/preset-env", + { + "targets": { + "browsers": ["last 2 versions", "ie >= 9"] + } + } + ] + ] +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b3107b3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/node_modules +/www/index.html +/www/styles/ +/www/scripts/ +/www/lib +!/www/lib/sib-core +!/www/lib/sib-router +!/www/lib/sib-chat \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..99cd617 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "www/lib/sib-core"] + path = www/lib/sib-core + url = git@git.happy-dev.fr:startinblox/sib-core.git +[submodule "www/lib/sib-router"] + path = www/lib/sib-router + url = git@git.happy-dev.fr:startinblox/sib-router.git +[submodule "www/lib/sib-chat"] + path = www/lib/sib-chat + url = git@git.happy-dev.fr:startinblox/sib-chat.git diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ea0ad7f --- /dev/null +++ b/Makefile @@ -0,0 +1,56 @@ +SCRIPT_SRC := $(wildcard src/scripts/*.js) + +SCRIPT_DEST := $(SCRIPT_SRC:src/%=www/%) + +default: build + +clean: + git clean -fXd + + +install: node_modules copy_lib submodules + +submodules: + git submodule init + git submodule update + +build: www/index.html www/styles/index.css $(SCRIPT_DEST) + +watch: + @echo 'watching for change' + @echo 'press Ctrl+C to stop' + @while true; do \ + $(MAKE) --silent build; \ + sleep 0.5; \ + done + +serve: + node server + +# npm +node_modules: + npm install + +# vendor lib +copy_lib: + @node copy_lib.js + +# pug +www/index.html: src/index.pug $(wildcard src/*.pug src/*/*.pug) + @echo pug: $< ➜ $@ + @node_modules/.bin/pug --pretty $< --out $(dir $@) || touch $@ + +# sass +www/styles/index.css: src/styles/index.scss $(wildcard src/*.scss src/*/*.scss) + @echo sass: $< ➜ $@ + @node_modules/.bin/node-sass $< $@ --source-map true || touch $@ + +# babel +www/%.js: src/%.js + @echo babel: $< ➜ $@ + @mkdir -p $(dir $@) + @node_modules/.bin/babel $< --out-file $@ --source-maps || touch $@ + +.PHONY: default install submodules copy_lib build watch serve clean + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/copy_lib.js b/copy_lib.js new file mode 100644 index 0000000..4cc6932 --- /dev/null +++ b/copy_lib.js @@ -0,0 +1,20 @@ +const { basename, join, resolve } = require('path'); +const { readFileSync, lstatSync } = require('fs'); +const { exec } = require('child_process'); + +const distDir = 'www/lib'; + +const filelist = readFileSync('lib_list.txt', 'utf-8').split(/\r?\n/); + +exec(`mkdir -p ${distDir}`, () => { + filelist.forEach(path => { + path = resolve(path); + const filename = basename(path); + const dest = lstatSync(path).isDirectory() + ? distDir + : join(distDir, filename); + const cmd = `rsync -ru ${path} ${dest}`; + console.log(cmd); + exec(cmd); + }); +}); diff --git a/lib_list.txt b/lib_list.txt new file mode 100644 index 0000000..6127584 --- /dev/null +++ b/lib_list.txt @@ -0,0 +1,3 @@ +node_modules/normalize.css/normalize.css +node_modules/@webcomponents/webcomponentsjs +node_modules/@webcomponents/html-imports/src/html-imports.js \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..3cddfa8 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "hd-app", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@babel/core": "^7.1.0", + "@babel/preset-env": "^7.1.0", + "@babel/cli": "^7.1.0", + "node-sass": "^4.9.3", + "pug-cli": "^1.0.0-alpha6", + "browser-sync": "^2.24.7", + "express": "^4.16.3" + }, + "dependencies": { + "@webcomponents/html-imports": "^1.2.0", + "@webcomponents/webcomponentsjs": "^1.2.7", + "normalize.css": "^8.0.0", + "simple-line-icons": "^2.4.1" + } +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..7637428 --- /dev/null +++ b/server.js @@ -0,0 +1,22 @@ +const port = 9000; +const distPath = 'www'; +// express server +const { join } = require('path'); +const express = require('express'); +const app = express(); +app + .use(express.static(distPath)) + .use('/src', express.static(join(__dirname, 'src'))) + .get(/^[^.]*$/, (req, rep) => + rep.sendFile(join(__dirname, distPath, '/index.html')), + ) + .listen(port); +// browser sync +const bs = require('browser-sync').create(); +bs.init({ + files: [distPath + '/**/*'], + proxy: `http://localhost:${port}`, + open: false, + notify: false, + //tunnel: true, +}); diff --git a/src/dependencies.pug b/src/dependencies.pug new file mode 100644 index 0000000..f0cbd56 --- /dev/null +++ b/src/dependencies.pug @@ -0,0 +1,27 @@ +// Scripts +script(src="lib/webcomponentsjs/webcomponents-loader.js") +//- script(src="lib/html-imports.js") + +//- script(src="https://unpkg.com/@webcomponents/webcomponentsjs@1.2.7/webcomponents-loader.js") + +script(src="scripts/index.js") + +// Stylesheets +link(rel='stylesheet', href='lib/normalize.css') +link(rel='stylesheet', href="styles/index.css") +link( + rel='stylesheet' + href='https://fonts.googleapis.com/css?family=Open+Sans:400,400i,700,700i&subset=latin-ext' +) + +// Web components + +//- local +link(rel='import', href='lib/sib-core/sib-display.html') +link(rel='import', href='lib/sib-router/sib-router.html') + //-link(rel='import', href='lib/sib-chat/sib-chat.html') + +//- cdn + link(rel='import', href="https://cdn.happy-dev.fr/sib-core/sib-display.html") + link(rel='import', href="https://cdn.happy-dev.fr/sib-router/sib-router.html") + //- link(rel='import', href="https://cdn.happy-dev.fr/sib-chat/sib-chat.html") diff --git a/src/index.pug b/src/index.pug new file mode 100644 index 0000000..10d9265 --- /dev/null +++ b/src/index.pug @@ -0,0 +1,36 @@ +include variables.pug + +html(lang="en") + head + meta(charset="UTF-8") + title HD App + meta(name="viewport", content="width=device-width, initial-scale=1.0") + meta(http-equiv="X-UA-Compatible", content="ie=edge") + include dependencies.pug + body + header#header + #logo + img(src="img/logo.png" width=166/2 height=48/2) + #subContainer + include menu.pug + main#mainContainer + //- #dashboard(hidden) + include pages/dashboard.pug + #members(hidden) + include pages/members.pug + #member(hidden) + div include pages/member.pug + #job-offers(hidden) + include pages/job-offers.pug + #projects(hidden) + include pages/projects.pug + #project(hidden) + include pages/project.pug + //- #client-creation(hidden) + include pages/client-creation.pug + #channels(hidden) + include pages/channels.pug + #channel(hidden) + include pages/channel.pug + //- #search(hidden) + include pages/search.pug \ No newline at end of file diff --git a/src/menu.pug b/src/menu.pug new file mode 100644 index 0000000..b1613a0 --- /dev/null +++ b/src/menu.pug @@ -0,0 +1,27 @@ +.btn-toggle +div + nav#navbar + sib-router#navbar-router(default-route='members') + div(hidden) + div#menu-items + sib-route(name='members') + div.icon-people Membres + sib-route(hidden, name='member', id-prefix=`${sdn}/members/`) + sib-route(name='job-offers') + div.icon-briefcase Job offers + div + div.icon-folder-alt Projets + sib-display( + data-src=`${sdn}/projects/`, + data-fields='name', + next='project' + ) + sib-route(hidden, name='project', id-prefix=`${sdn}/projects/`) + div + div.icon-bubbles Channels + sib-display( + data-src=`${sdn}/channels/`, + data-fields='name', + next='channel' + ) + sib-route(hidden, name='channel', id-prefix=`${sdn}/channels/`) \ No newline at end of file diff --git a/src/pages/channel-chat.pug b/src/pages/channel-chat.pug new file mode 100644 index 0000000..2e54d66 --- /dev/null +++ b/src/pages/channel-chat.pug @@ -0,0 +1,2 @@ +#channel-chat.chat-view(style='display: none', bind-resources='') + sib-chat(data-authentication='login', data-auto-login='true', data-bosh-service-url='https://jabber.happy-dev.fr/http-bind/', data-debug='false', data-locales-url='en', bind-resources='') \ No newline at end of file diff --git a/src/pages/channel-create.pug b/src/pages/channel-create.pug new file mode 100644 index 0000000..5e7b303 --- /dev/null +++ b/src/pages/channel-create.pug @@ -0,0 +1,7 @@ +#channel-create(style='display: none') + sib-form( + data-src=`${sdn}/channels/`, + range-owner=`${sdn}/members/`, + widget-members='sib-form-multiple-dropdown', + range-members=`${sdn}/members/` + ) diff --git a/src/pages/channel-edit.pug b/src/pages/channel-edit.pug new file mode 100644 index 0000000..9244226 --- /dev/null +++ b/src/pages/channel-edit.pug @@ -0,0 +1,7 @@ +#channel-edit(style='display: none') + sib-form( + range-owner=`${sdn}/members/`, + widget-members='sib-form-multiple-dropdown', + range-members=`${sdn}/members/`, + bind-resources='' + ) diff --git a/src/pages/channel-profile.pug b/src/pages/channel-profile.pug new file mode 100644 index 0000000..b7dad0b --- /dev/null +++ b/src/pages/channel-profile.pug @@ -0,0 +1,38 @@ +script. + document.addEventListener('WebComponentsReady', function(event) { + document.addEventListener("HTMLImportsLoaded", function(event) { + class HDAppMember extends SIBWidget { + get template() { + return ` +
+ +
+ `; + } + + render() { + store.get(this.value).then( (value) => { + this._value = value; + this.innerHTML = this.template; + }); + } + } + customElements.define("hdapp-member", HDAppMember); + }); + }); + +#channel-profile(style='display: none') + sib-display( + data-fields='name, description, owner', + widget-owner='hdapp-member', + bind-resources='' + ) + h2.section.skills Participants + sib-display( + id-suffix='members', + data-fields='avatar, user', + widget-avatar='sib-display-img', + widget-user='hdapp-userinfo', + bind-resources='' + ) + diff --git a/src/pages/channel.pug b/src/pages/channel.pug new file mode 100644 index 0000000..e91ee19 --- /dev/null +++ b/src/pages/channel.pug @@ -0,0 +1,15 @@ +#channel(style='display: none') + sib-router#channel-router(default-route='channel-profile') + sib-route(name='channel-chat') + div Chat + sib-route(name='channel-profile') + div Info + sib-route(name='channel-edit') + div Éditer + sib-route(name='channel-create') + div Nouveau + #network-views-container + include channel-chat.pug + include channel-profile.pug + include channel-edit.pug + include channel-create.pug diff --git a/src/pages/channels.pug b/src/pages/channels.pug new file mode 100644 index 0000000..70d99f5 --- /dev/null +++ b/src/pages/channels.pug @@ -0,0 +1,7 @@ +#channels(style='display: none') + sib-display#channels-list( + data-src=`${sdn}/channels/`, + data-fields='name, description', + search-fields='name, description', + next='channel' + ) diff --git a/src/pages/job-offers.pug b/src/pages/job-offers.pug new file mode 100644 index 0000000..8835bce --- /dev/null +++ b/src/pages/job-offers.pug @@ -0,0 +1,40 @@ +script. + document.addEventListener('WebComponentsReady', function(event) { + document.addEventListener('HTMLImportsLoaded', function(event) { + class HDAppAuthor extends SIBDisplayLookupList { + get parentElement() { + return 'div'; + } + getTemplate(value, index) { + var firstname, lastname; + if (typeof value == 'object') + if (Object.keys(value).length > 1) { + firstname = value.user.first_name; + lastname = value.user.last_name; + } else { + store.get(value).then(resource => { + this.value.push(resource); + this.render(); + }); + if (Array.isArray(this.value)) + this.value.splice(this.value.indexOf(value), 1); + else this.value = []; + return ''; + } + return `${firstname} ${lastname}`; + } + } + customElements.define('hdapp-author', HDAppAuthor); + }); + }); + +div + h1 Job offers + sib-display#offers-list( + data-src=`${sdn}/job-offers/`, + data-fields='author, title, description, skills', + set-searchset='title, description', + widget-skills='sib-display-lookuplist', + widget-author='hdapp-author', + search-fields='searchset' + ) \ No newline at end of file diff --git a/src/pages/member-chat.pug b/src/pages/member-chat.pug new file mode 100644 index 0000000..92f71ee --- /dev/null +++ b/src/pages/member-chat.pug @@ -0,0 +1,2 @@ +#member-chat.chat-view(style='display: none', bind-resources='') + sib-chat(data-authentication='login', data-auto-login='true', data-bosh-service-url='https://jabber.happy-dev.fr/http-bind/', data-debug='false', data-locales-url='en', bind-resources='') diff --git a/src/pages/member-edit.pug b/src/pages/member-edit.pug new file mode 100644 index 0000000..598a586 --- /dev/null +++ b/src/pages/member-edit.pug @@ -0,0 +1,97 @@ +// script. + class LDPFormImgUpload extends SIBWidget { + get template() { + return ` + `; + } + + render() { + store.get(this.value).then( (value) => { + this._value = value; + this.innerHTML = this.template; + }); + } + } + customElements.define("ldp-form-img-upload", LDPFormImgUpload); + widget-avatar="ldp-form-img-upload" + +#member-edit(style='display: none') + label.d-none(for='avatar-input') + img#avatar-preview(src='', style='width: 100%;') + input#avatar-input.d-none(accept='image/*', name='avatar', value='', type='file') + sib-form.edit-form( + data-fields='user, avatar, bio, cell, jabberID, number, pseudo, skills, website', + widget-user='hdapp-usereditinfo', + range-cell=`${sdn}/cells/`, widget-skills='sib-form-multiple-dropdown', + range-skills=`${sdn}/skills/`, + bind-resources='' + ) +#crop-modal + .crop-wrapper + img#crop-preview(src='') + .control-bar + button#cancel-img-cropping.btn.btn-link Annuler + i#rotate-img.fa.fa-undo(aria-hidden='true') + button#crop-img.btn.btn-link Valider + + +//-script. + // Constant declaration + const avatarPreview = document.querySelector("#avatar-preview"); + const avatarInput = document.querySelector("#avatar-input"); + const cropModal = document.querySelector("#crop-modal"); + const cropPreview = cropModal.querySelector("#crop-preview"); + const $cropPreview = $(cropPreview); + + // Triggers cropping on image upload + avatarInput.addEventListener("change", function(e) { + var img = avatarInput.files[0]; + var reader = new FileReader(); + + reader.onloadend = function () { + cropPreview.src = reader.result; + cropModal.classList.add("cropping-mode"); + } + + if (img) { + reader.readAsDataURL(img);//reads the data as a URL + } + }); + cropPreview.addEventListener("load", () => { + $cropPreview.cropper({ + aspectRatio: 1/1, + viewMode: 3, + zoomable: false, + }); + }); + + + // Rotate image + cropModal.querySelector("#rotate-img").addEventListener("click", () => { + $cropPreview.cropper("rotate", -90); + }); + + + // Cancel cropping + cropModal.querySelector("#cancel-img-cropping").addEventListener("click", () => { + closeCropping(); + }); + + // Shortcut + document.querySelector("body").addEventListener("keydown", function(e) { + // Escape key + if (e.keyCode == 27 && cropModal.classList.contains("cropping-mode")) { + closeCropping(); + } + }); + function closeCropping() { + cropModal.classList.remove("cropping-mode"); + avatarInput.value = null; + } + + + // Validating cropping + cropModal.querySelector("#crop-img").addEventListener("click", () => { + avatarPreview.src = $cropPreview.cropper("getCroppedCanvas").toDataURL() + closeCropping(); + }); diff --git a/src/pages/member-profile.pug b/src/pages/member-profile.pug new file mode 100644 index 0000000..a8ace40 --- /dev/null +++ b/src/pages/member-profile.pug @@ -0,0 +1,13 @@ +#member-profile(style='display: none') + sib-display#member-info( + data-fields='header, cell, number, roles, website, skills', + set-header='avatar, user, pseudonym, bio' + set-pseudonym='before-pseudo, pseudo' + widget-avatar='sib-display-img', + widget-user='hdapp-userinfo', + widget-cell='hdapp-usercell', + widget-number='sib-display-tel', + widget-roles='sib-display-lookuplist', + widget-skills='sib-display-lookuplist', + bind-resources='' + ) diff --git a/src/pages/member.pug b/src/pages/member.pug new file mode 100644 index 0000000..d815b25 --- /dev/null +++ b/src/pages/member.pug @@ -0,0 +1,12 @@ +#member(style='display: none') + sib-router#member-router(default-route='member-profile') + sib-route(name='member-chat') + div Chat + sib-route(name='member-profile') + div Voir + sib-route(name='member-edit') + div Éditer + #member-views-container + include member-chat.pug + include member-profile.pug + include member-edit.pug diff --git a/src/pages/members.pug b/src/pages/members.pug new file mode 100644 index 0000000..27ac9fa --- /dev/null +++ b/src/pages/members.pug @@ -0,0 +1 @@ +div member \ No newline at end of file diff --git a/src/pages/project-chat.pug b/src/pages/project-chat.pug new file mode 100644 index 0000000..e2aebf9 --- /dev/null +++ b/src/pages/project-chat.pug @@ -0,0 +1,2 @@ +#project-chat.chat-view(style='display: none', bind-resources='') + sib-chat(data-authentication='login', data-auto-login='true', data-bosh-service-url='https://jabber.happy-dev.fr/http-bind/', data-debug='false', data-locales-url='en', bind-resources='') diff --git a/src/pages/project-create.pug b/src/pages/project-create.pug new file mode 100644 index 0000000..69a9607 --- /dev/null +++ b/src/pages/project-create.pug @@ -0,0 +1,7 @@ +#project-create(style='display: none') + sib-form( + data-src=`${sdn}/projects/`, + range-client=`${sdn}/clients/`, + widget-team='sib-form-multiple-dropdown', + range-team=`${sdn}/members/` + ) diff --git a/src/pages/project-edit.pug b/src/pages/project-edit.pug new file mode 100644 index 0000000..dd6c902 --- /dev/null +++ b/src/pages/project-edit.pug @@ -0,0 +1,7 @@ +#project-edit(style='display: none') + sib-form( + range-client=`${sdn}/clients/`, + widget-team='sib-form-multiple-dropdown', + range-team=`${sdn}/members/`, + bind-resources='' + ) diff --git a/src/pages/project-profile.pug b/src/pages/project-profile.pug new file mode 100644 index 0000000..2ac5023 --- /dev/null +++ b/src/pages/project-profile.pug @@ -0,0 +1,16 @@ +#project-profile(style='display: none') + sib-display( + data-fields='title, description, client', + set-title='number, name' + widget-client='hdapp-client', + bind-resources='' + ) + h3 Team + sib-display.members-list-condensed( + id-suffix='team', + data-fields='avatar, user', + widget-avatar='sib-display-img', + widget-user='hdapp-userinfo', + next='member', + bind-resources='' + ) diff --git a/src/pages/project.pug b/src/pages/project.pug new file mode 100644 index 0000000..3b873d3 --- /dev/null +++ b/src/pages/project.pug @@ -0,0 +1,15 @@ +#project(style='display: none') + sib-router#project-router(default-route='project-profile') + sib-route(name='project-chat') + div Chat + sib-route(name='project-profile') + div Voir + sib-route(name='project-edit') + div Éditer + sib-route(name='project-create') + div Nouveau + #project-views-container + include project-chat.pug + include project-profile.pug + include project-edit.pug + include project-create.pug diff --git a/src/pages/projects.pug b/src/pages/projects.pug new file mode 100644 index 0000000..ea6fd6d --- /dev/null +++ b/src/pages/projects.pug @@ -0,0 +1,29 @@ +script. + document.addEventListener('WebComponentsReady', function(event) { + document.addEventListener("HTMLImportsLoaded", function(event) { + class HDAppClient extends SIBWidget { + get template() { + + return ``; + } + + render() { + store.get(this.value).then( (value) => { + this._value = value; + this.innerHTML = this.template; + }); + } + } + customElements.define("hdapp-client", HDAppClient); + }); + }); + +#projects(style='display: none') + h1 Projects + sib-display( + data-src=`${sdn}/projects/`, + data-fields='number, client, name', + widget-client='hdapp-client', + search-fields='number, name', + next='project' + ) diff --git a/src/scripts/hd-app.js b/src/scripts/hd-app.js new file mode 100644 index 0000000..a38a099 --- /dev/null +++ b/src/scripts/hd-app.js @@ -0,0 +1,61 @@ +document.addEventListener("DOMContentLoaded", function(event) { + // Constants declaration + const navBar = document.querySelector("#navbar"); + const searchBar = document.querySelector("#search-bar"); + const searchView = document.querySelector("#search-view"); + const searchInput = searchBar.querySelector("#search-input"); + const btnToggle = document.querySelector(".btn-toggle"); + + + // Shortcuts + window.addEventListener("keydown", function(e) { + // CTRL + K triggers the search feature + if ((e.keyCode == 75 || e.keyCode == 80) && (e.ctrlKey === true || e.metaKey === true)) { + e.preventDefault(); + e.stopPropagation(); + openSearchBar(); + } + + // Escape key + else if (e.keyCode == 27 && navBar.classList.contains("search-mode")) { + closeSearchBar(); + } + }); + + searchBar.querySelector("#close-search-icon").addEventListener("click", emptySearchBar); + + function openSearchBar(e) { + navBar.classList.add("search-mode"); + searchBar.querySelector("#search-input").focus(); + searchView.classList.add("search-mode"); + } + + function closeSearchBar(e) { + navBar.classList.remove("search-mode"); + searchView.classList.remove("search-mode"); + } + + function emptySearchBar(e) { + searchInput.value = ''; + openSearchBar(); + searchInput.focus; + } + + + // Synchronizes the search input with the s + searchInput.addEventListener("keyup", (e) => { + searchView.querySelectorAll("ldp-form input[type=text]").forEach((el) => { + el.value = searchInput.value; + }); + }); + + + btnToggle.addEventListener('click', e => { + navBar.classList.toggle('open'); + e.stopPropagation(); + }); + + window.addEventListener('click', e=>{ + navBar.classList.remove('open'); + }); +}); diff --git a/src/scripts/index.js b/src/scripts/index.js new file mode 100644 index 0000000..482a879 --- /dev/null +++ b/src/scripts/index.js @@ -0,0 +1,15 @@ +document.addEventListener('DOMContentLoaded', function(event) { + // Constants declaration + const navBar = document.querySelector('#navbar'); + const btnToggle = document.querySelector('.btn-toggle'); + if (!navBar || !btnToggle) return; + + btnToggle.addEventListener('click', e => { + navBar.classList.toggle('open'); + e.stopPropagation(); + }); + + window.addEventListener('click', e => { + navBar.classList.remove('open'); + }); +}); diff --git a/src/styles/functions.scss b/src/styles/functions.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/styles/icons.scss b/src/styles/icons.scss new file mode 100644 index 0000000..434251a --- /dev/null +++ b/src/styles/icons.scss @@ -0,0 +1,264 @@ +@font-face { + font-family: 'simple-line-icons'; + src: url('../fonts/simple-line-icons.eot?23594131'); + src: url('../fonts/simple-line-icons.eot?23594131#iefix') + format('embedded-opentype'), + url('../fonts/simple-line-icons.woff2?23594131') format('woff2'), + url('../fonts/simple-line-icons.woff?23594131') format('woff'), + url('../fonts/simple-line-icons.ttf?23594131') format('truetype'), + url('../fonts/simple-line-icons.svg?23594131#simple-line-icons') + format('svg'); + font-weight: normal; + font-style: normal; +} +/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */ +/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */ +/* +@media screen and (-webkit-min-device-pixel-ratio:0) { + @font-face { + font-family: 'simple-line-icons'; + src: url('../font/simple-line-icons.svg?23594131#simple-line-icons') format('svg'); + } +} +*/ +%icon, +[class^='icon-']:before, +[class*=' icon-']:before { + font-family: 'simple-line-icons'; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: 0.2em; + text-align: center; + /* opacity: .8; */ + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + /* remove if not needed */ + margin-left: 0.2em; + + /* you can be more comfortable with increased icons size */ + /* font-size: 120%; */ + + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /* Uncomment for 3D effect */ + // text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); +} + +$icons: ( + user-female: '\e000', + people: '\e001', + user-follow: '\e002', + user-following: '\e003', + user-unfollow: '\e004', + user: '\e005', + trophy: '\e006', + speedometer: '\e007', + social-youtube: '\e008', + social-twitter: '\e009', + social-tumblr: '\e00a', + social-facebook: '\e00b', + social-dropbox: '\e00c', + social-dribbble: '\e00d', + shield: '\e00e', + screen-tablet: '\e00f', + screen-smartphone: '\e010', + screen-desktop: '\e011', + plane: '\e012', + notebook: '\e013', + mustache: '\e014', + mouse: '\e015', + magnet: '\e016', + magic-wand: '\e017', + hourglass: '\e018', + graduation: '\e019', + ghost: '\e01a', + game-controller: '\e01b', + fire: '\e01c', + eyeglass: '\e01d', + envelope-open: '\e01e', + envolope-letter: '\e01f', + energy: '\e020', + emotsmile: '\e021', + disc: '\e022', + cursor-move: '\e023', + crop: '\e024', + credit-card: '\e025', + chemistry: '\e026', + bell: '\e027', + badge: '\e028', + anchor: '\e029', + wallet: '\e02a', + vector: '\e02b', + speech: '\e02c', + puzzle: '\e02d', + printer: '\e02e', + present: '\e02f', + playlist: '\e030', + pin: '\e031', + picture: '\e032', + map: '\e033', + layers: '\e034', + handbag: '\e035', + globe-alt: '\e036', + globe: '\e037', + frame: '\e038', + folder-alt: '\e039', + film: '\e03a', + feed: '\e03b', + earphones-alt: '\e03c', + earphones: '\e03d', + drop: '\e03e', + drawar: '\e03f', + docs: '\e040', + directions: '\e041', + direction: '\e042', + diamond: '\e043', + cup: '\e044', + compass: '\e045', + call-out: '\e046', + call-in: '\e047', + call-end: '\e048', + calculator: '\e049', + bubbles: '\e04a', + briefcase: '\e04b', + book-open: '\e04c', + basket-loaded: '\e04d', + basket: '\e04e', + bag: '\e04f', + action-undo: '\e050', + action-redo: '\e051', + wrench: '\e052', + umbrella: '\e053', + trash: '\e054', + tag: '\e055', + support: '\e056', + size-fullscreen: '\e057', + size-actual: '\e058', + shuffle: '\e059', + share-alt: '\e05a', + share: '\e05b', + rocket: '\e05c', + question: '\e05d', + pie-chart: '\e05e', + pencil: '\e05f', + note: '\e060', + music-tone-alt: '\e061', + music-tone: '\e062', + microphone: '\e063', + loop: '\e064', + logout: '\e065', + login: '\e066', + list: '\e067', + like: '\e068', + home: '\e069', + grid: '\e06a', + graph: '\e06b', + equalizer: '\e06c', + dislike: '\e06d', + cursor: '\e06e', + control-start: '\e06f', + control-rewind: '\e070', + control-play: '\e071', + control-pause: '\e072', + control-forward: '\e073', + control-end: '\e074', + calender: '\e075', + bulb: '\e076', + chart: '\e077', + arrow-up-circle: '\e078', + arrow-right-circle: '\e079', + arrow-left-circle: '\e07a', + arrow-down-circle: '\e07b', + ban: '\e07c', + bubble: '\e07d', + camrecorder: '\e07e', + camera: '\e07f', + check: '\e080', + clock: '\e081', + close: '\e082', + cloud-download: '\e083', + cloud-upload: '\e084', + doc: '\e085', + envolope: '\e086', + eye: '\e087', + flag: '\e088', + folder: '\e089', + heart: '\e08a', + info: '\e08b', + key: '\e08c', + link: '\e08d', + lock: '\e08e', + lock-open: '\e08f', + magnifier: '\e090', + magnifier-add: '\e091', + magnifier-remove: '\e092', + paper-clip: '\e093', + paper-plane: '\e094', + plus: '\e095', + location-pin: '\e096', + power: '\e097', + refresh: '\e098', + reload: '\e099', + settings: '\e09a', + star: '\e09b', + symble-female: '\e09c', + symbol-male: '\e09d', + target: '\e09e', + volume-1: '\e09f', + volume-2: '\e0a0', + volume-off: '\e0a1', + phone: '\e600', + menu: '\e601', + options-vertical: '\e602', + options: '\e603', + arrow-down: '\e604', + arrow-left: '\e605', + arrow-right: '\e606', + arrow-up: '\e607', + paypal: '\e608', + social-instagram: '\e609', + social-linkedin: '\e60a', + social-pintarest: '\e60b', + social-github: '\e60c', + social-google: '\e60d', + social-reddit: '\e60e', + social-skype: '\e60f', + social-behance: '\e610', + social-foursqare: '\e611', + social-soundcloud: '\e612', + social-spotify: '\e613', + social-stumbleupon: '\e614', + minus: '\e615', + organization: '\e616', + exclamation: '\e617', + social-vkontakte: '\e618', + event: '\e619', + social-steam: '\e620', +); + + +@each $name, $code in $icons { + .icon-#{$name} { + &:before { + content: $code; + } + } +} +@mixin icon($code) { + @extend %icon; + @extend .icon-#{$code}; +} \ No newline at end of file diff --git a/src/styles/index.scss b/src/styles/index.scss new file mode 100644 index 0000000..ebca3ee --- /dev/null +++ b/src/styles/index.scss @@ -0,0 +1,10 @@ +@charset "UTF-8"; +@import + 'icons', + 'variables', + 'functions', + 'mixins', + 'main'; + +@import 'menu' + diff --git a/src/styles/main.scss b/src/styles/main.scss new file mode 100644 index 0000000..2ad4686 --- /dev/null +++ b/src/styles/main.scss @@ -0,0 +1,41 @@ +@import 'variables'; + +[hidden] { + display: none !important; +} + +html { + font-family: Open Sans, sans-serif; + font-size: 13px; + background-color: $color-grey-light; +} + +#header { + background-color: $color-white; + position: relative; + @include border-shadow(bottom); + border: solid $color-white; + border-width: 1px 0; +} + +#logo { + margin: 1.4em; +} + +html, +body { + height: 100%; +} + +#subContainer { + display: flex; + min-height: 100%; +} + +#mainContainer { + flex: 1 1 0px; +} + +h1,h2,h3,h4,h5,h6{ + color: $color-black; +} \ No newline at end of file diff --git a/src/styles/menu.scss b/src/styles/menu.scss new file mode 100644 index 0000000..499979f --- /dev/null +++ b/src/styles/menu.scss @@ -0,0 +1,133 @@ +// #navbar{} +// #navbar-router{} + +.btn-toggle { + @include icon('menu'); + display: none; + position: absolute; + top: 0; + left: 0; + background-color: $color-white; + color: $color-black; + font-size: 2em; + padding: 0.72em; + cursor: pointer; +} + +#navbar { + background-color: $color-white; + color: $color-grey; + max-width: 16rem; + position: sticky; + top: 0; + height: 100%; + max-height: 100vh; + &.open { + transform: translateX(0); + } + @include border-shadow(right); +} + +@media (max-width: 32rem) { + .btn-toggle { + display: block; + } + #navbar { + transform: translateX(-100%); + transition: transform 0.5s ease; + position: absolute; + top: auto; + z-index: 1; + } + #header { + padding-left: 5rem; + } +} + +#menu-items { + > * { + display: block; + border-top: 1px solid $color-grey; + &:last-child { + border-bottom: 1px solid $color-grey; + } + sib-route { + display: block; + cursor: pointer; + } + cursor: pointer; + &[active] { + color: $color-black; + > div:before { + background-color: $color-yellow-light; + transform: perspective(1000px) translateZ(1px) scale(0.8); + } + } + > div { + text-align: center; + text-transform: uppercase; + &:before { + display: block; + margin: -0.5em auto 0; + font-size: 2em; + border-radius: 100%; + padding: 0.7em; + transform: perspective(1000px) translateZ(1px) scale(1); + will-change: transform; + transition: + all .3s ease, + transform .3s cubic-bezier(0.175, 0.885, 0.32, 1.4); + } + width: max-content; + padding: 2em; + } + &[id-prefix] { + display: none; + } + > sib-display { + display: block; + font-size: 0.9em; + color: #aaa; + > div { + margin-bottom: 1.5em; + > sib-display { + cursor: pointer; + display: block; + padding: 0.5em 2em; + } + } + } + } +} + +/* sub menu (right menu) */ + +#mainContainer > div { + display: flex; + flex-direction: row-reverse; + align-items: flex-start; + > sib-router { + display: block; + background-color: #ccc; + sib-route { + display: block; + > div { + position: relative; + padding: 1em 2em; + border-bottom: 1px solid #888; + } + &[active] { + font-weight: bold; + > div:before { + content: '<'; + position: absolute; + transform: translateX(-150%); + } + } + } + } + > div { + margin: 0.5em; + flex: 1 1 0px; + } +} diff --git a/src/styles/mixins.scss b/src/styles/mixins.scss new file mode 100644 index 0000000..9f2722d --- /dev/null +++ b/src/styles/mixins.scss @@ -0,0 +1,149 @@ +@charset "UTF-8"; +@mixin debug { + $hsla: hsla(random(360), 100%, 50%, 0.3); + background-color: $hsla; +} +@mixin log($v) { + font-family: '__log__:#{$v}'; +} + +@mixin offset($corner: 1, $x: 0, $y: 0) { + // corner: + // 1-----2 + // | | + // | | + // 3-----4 + position: absolute; + @if ($corner == 1) { + top: $y; + left: $x; + } + @if ($corner == 2) { + top: $y; + right: $x; + } + @if ($corner == 3) { + bottom: $y; + left: $x; + } + @if ($corner == 4) { + bottom: $y; + right: $x; + } +} + +@mixin position($top: 0, $right: null, $bottom: null, $left: null) { + // --1-- + // | | + // 4 2 + // | | + // --3-- + @if ($right == null) { + $right: $top; + } + + @if ($bottom == null) { + $bottom: $top; + } + + @if ($left == null) { + $left: $right; + } + + position: absolute; + top: $top; + left: $left; + right: $right; + bottom: $bottom; +} + +@mixin pos($pos: 5, $position: absolute) { + // ╔═──┐ ╔═══╗ ┌──═╗ + // │ 1 │ │ 2 │ │ 3 │ + // └───┘ └───┘ └───┘ + // ╔═──┐ ╔═══╗ ┌──═╗ + // ║ 4 │ ║ 5 ║ │ 6 ║ + // ╚═──┘ ╚═══╝ └──═╝ + // ┌───┐ ┌───┐ ┌───┐ + // │ 7 │ │ 8 │ │ 9 │ + // ╚═──┘ ╚═══╝ └──═╝ + + $mod: ($pos - 1) % 3; + + position: $position; + @if ($pos <= 6) { + top: 0; + } + @if ($mod <= 1) { + left: 0; + } + @if ($mod >= 1) { + right: 0; + } + @if ($pos >= 4) { + bottom: 0; + } +} + +@mixin border-shadow($border: top, $size: 4px, $opacity: 0.05, $color: black) { + &:after { + content: ''; + position: absolute; + top: if(($border == bottom), auto, 0); + left: if(($border == right), auto, 0); + right: if(($border == left), auto, 0); + bottom: if(($border == top), auto, 0); + background-image: linear-gradient(to #{$border}, $color, transparent); + #{$border}: -$size; + opacity: $opacity; + @if($border == top or $border == bottom) { + height: $size; + }@else{ + width: $size; + } + } +} + +@mixin align($horizontal: center, $vertical: middle) { + text-align: $horizontal; + white-space: nowrap; + &:after, + > * { + display: inline-block; + vertical-align: $vertical; + } + &:after { + content: ''; + height: 100%; + width: 0; + visibility: hidden; + } + > * { + //text-align:left; + white-space: normal; + } +} + +@mixin list-reset($deep: 0) { + padding: 0; + margin: 0; + display: block; + list-style: none; + @if ($deep == 0) { + > li { + padding: 0; + margin: 0; + display: block; + list-style: none; + } + } @else { + ul, + ol, + li { + padding: 0; + margin: 0; + display: block; + list-style: none; + } + } +} diff --git a/src/styles/variables.scss b/src/styles/variables.scss new file mode 100644 index 0000000..ed98ad7 --- /dev/null +++ b/src/styles/variables.scss @@ -0,0 +1,17 @@ +$color-white: #fff; +$color-black: #36383B; +$color-grey: #898F95; +$color-grey-light: #F0F3F6; + +$color-yellow: #FFB700; +$color-yellow-light: #FFD759; + +%button{ + border-radius: 100em +} + +%button-yellow{ + @extend %button; + background-color: $color-yellow; + color: $color-white; +} \ No newline at end of file diff --git a/src/variables.pug b/src/variables.pug new file mode 100644 index 0000000..dd28afe --- /dev/null +++ b/src/variables.pug @@ -0,0 +1,2 @@ +- var sdn = process.env.SDN || 'http://127.0.0.1:8000' +- var cdn = process.env.CDN || 'https://cdn.happy-dev.fr' \ No newline at end of file