Kanban prototype on cryptpad
parent
f324d33723
commit
4b83f2991a
@ -0,0 +1,671 @@
|
|||||||
|
@import (once) "../../customize/src/less2/include/browser.less";
|
||||||
|
@import (once) "../../customize/src/less2/include/toolbar.less";
|
||||||
|
@import (once) "../../customize/src/less2/include/markdown.less";
|
||||||
|
@import (once) '../../customize/src/less2/include/fileupload.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/alertify.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/tokenfield.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/tools.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/avatar.less';
|
||||||
|
@import (once) '../../customize/src/less2/include/creation.less';
|
||||||
|
|
||||||
|
.toolbar_main(
|
||||||
|
@bg-color: @colortheme_kanban-bg,
|
||||||
|
@warn-color: @colortheme_kanban-warn,
|
||||||
|
@color: @colortheme_kanban-color
|
||||||
|
);
|
||||||
|
.fileupload_main();
|
||||||
|
.alertify_main();
|
||||||
|
.tokenfield_main();
|
||||||
|
.creation_main();
|
||||||
|
|
||||||
|
@kanban-fore: #555;
|
||||||
|
|
||||||
|
@kanban-th-bg: @colortheme_kanban-th-bg;
|
||||||
|
@kanban-th-fg: @colortheme_kanban-th-fg;
|
||||||
|
@kanban-th-user-bg: darken(@kanban-th-bg, 10%);
|
||||||
|
@kanban-editing: lighten(@kanban-th-bg, 10%);
|
||||||
|
@kanban-winner: darken(@kanban-th-bg, 15%);
|
||||||
|
@kanban-td-bg: @kanban-th-bg;
|
||||||
|
@kanban-td-fg: @kanban-th-fg;
|
||||||
|
|
||||||
|
@kanban-help-bg: @colortheme_kanban-help-bg;
|
||||||
|
|
||||||
|
@kanban-uncommitted-cell: #eee;
|
||||||
|
@kanban-uncommitted-bg: #ddd; //lighten(@kanban-th-bg, 50%);
|
||||||
|
@kanban-uncommitted-text: black;
|
||||||
|
|
||||||
|
@kanban-placeholder: #fff;
|
||||||
|
@kanban-border-color: #555;
|
||||||
|
@kanban-cover-color: #000;
|
||||||
|
@kanban-fg: #000;
|
||||||
|
@kanban-option-yellow: #ff5;
|
||||||
|
@kanban-option-gray: #ccc;
|
||||||
|
|
||||||
|
@kanban-add-color: #fff;
|
||||||
|
@kanban-add-bg: #777;
|
||||||
|
@kanban-add-bg-alt: #444;
|
||||||
|
|
||||||
|
.bottom-left(@s: 5px) { border-bottom-left-radius: @s; }
|
||||||
|
.top-left(@s: 5px) { border-top-left-radius: @s; }
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
overflow-x: hidden;
|
||||||
|
|
||||||
|
#cp-app-kanban-content {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0;
|
||||||
|
#cp-app-kanban-form {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
&.cp-app-kanban-readonly {
|
||||||
|
#cp-app-kanban-table-scroll {
|
||||||
|
max-width: ~"calc(75% - 30px - 100px)";
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
table tr td:last-child {
|
||||||
|
margin-left: 0; // uncommitted is hidden
|
||||||
|
}
|
||||||
|
td.cp-app-kanban-table-uncommitted {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.cp-app-kanban-published {
|
||||||
|
#cp-app-kanban-create-option {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-remove[data-rt-id^="y"], .cp-app-kanban-table-edit[data-rt-id^="y"] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
tr.cp-app-kanban-table-uncommitted {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"], textarea {
|
||||||
|
background-color: white;
|
||||||
|
color: black;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="text"][disabled], textarea[disabled] {
|
||||||
|
background-color: transparent;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The placeholder color only seems to effect Safari when not set
|
||||||
|
|
||||||
|
input[type="text"][disabled]::placeholder {
|
||||||
|
color: @kanban-placeholder;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
table#cp-app-kanban-table {
|
||||||
|
margin: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-table-container {
|
||||||
|
position: relative;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-table-container button {
|
||||||
|
border-radius: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-create-user {
|
||||||
|
display: inline-flex;
|
||||||
|
height: 20px;
|
||||||
|
padding: 0 5px;
|
||||||
|
margin: 2px auto;
|
||||||
|
width: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
color: @kanban-add-color;
|
||||||
|
background: @kanban-add-bg;
|
||||||
|
&:hover {
|
||||||
|
background: @kanban-add-bg-alt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cp-app-kanban-create-option {
|
||||||
|
order: 3;
|
||||||
|
display: inline-flex;
|
||||||
|
width: 46px;
|
||||||
|
height: 20px;
|
||||||
|
margin: 2px;
|
||||||
|
padding: 0;
|
||||||
|
color: @kanban-add-color;
|
||||||
|
background: @kanban-add-bg;
|
||||||
|
&:hover {
|
||||||
|
background: @kanban-add-bg-alt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cp-app-kanban-table-scroll {
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: auto;
|
||||||
|
margin-left: 25%;
|
||||||
|
max-width: ~"calc(75% - 100px - 100px)";
|
||||||
|
width: auto;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.cp-markdown-toolbar {
|
||||||
|
margin: auto;
|
||||||
|
min-width: 80%;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-description {
|
||||||
|
&~ .CodeMirror {
|
||||||
|
margin: auto;
|
||||||
|
min-width: 80%;
|
||||||
|
width: 80%;
|
||||||
|
min-height: 200px;
|
||||||
|
height: 200px;
|
||||||
|
border: 1px solid black;
|
||||||
|
.CodeMirror-placeholder {
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cp-app-kanban-description-published {
|
||||||
|
display: none;
|
||||||
|
padding: 15px;
|
||||||
|
margin: auto;
|
||||||
|
|
||||||
|
min-width: 80%;
|
||||||
|
width: 80%;
|
||||||
|
min-height: 7em;
|
||||||
|
color: #000;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
background-color: #eeeeee;
|
||||||
|
font: @colortheme_app-font;
|
||||||
|
text-align: left;
|
||||||
|
media-tag > * {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 20em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
div.cp-app-kanban-published {
|
||||||
|
div.cp-app-kanban-realtime {
|
||||||
|
#cp-app-kanban-description {
|
||||||
|
display: none;
|
||||||
|
&~ .CodeMirror {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cp-app-kanban-description-published {
|
||||||
|
display: block;
|
||||||
|
&:empty {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cp-app-kanban-nocomments {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-comments {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#cp-app-kanban-help {
|
||||||
|
width: 100%;
|
||||||
|
margin: auto;
|
||||||
|
padding: 20px 10%;
|
||||||
|
background: @kanban-help-bg;
|
||||||
|
}
|
||||||
|
|
||||||
|
// from cryptpad.less
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
tr {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
.tools_unselectable();
|
||||||
|
border-right: 1px solid @kanban-border-color;
|
||||||
|
padding: 12px;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
&:last-child {
|
||||||
|
border-right: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div.cp-app-kanban-realtime {
|
||||||
|
display: block;
|
||||||
|
max-height: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
|
||||||
|
input {
|
||||||
|
&[type="text"] {
|
||||||
|
height: 1em;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
> textarea {
|
||||||
|
width: 50%;
|
||||||
|
height: 15vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
.cp-app-kanban-table-scrolled {
|
||||||
|
tr td:last-child {
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
tr td:nth-last-child(2) {
|
||||||
|
right: 100px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
width: ~"calc(100% - 1px)";
|
||||||
|
.cp-app-kanban-table-editing {
|
||||||
|
background-color: @kanban-editing;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-uncommitted {
|
||||||
|
.cp-app-kanban-table-cover {
|
||||||
|
background-color: @kanban-uncommitted-cell !important;
|
||||||
|
}
|
||||||
|
div.cp-app-kanban-table-text-cell {
|
||||||
|
background-color: @kanban-uncommitted-bg !important;
|
||||||
|
color: @kanban-uncommitted-text !important;
|
||||||
|
}
|
||||||
|
text-align: center;
|
||||||
|
background-color: @kanban-uncommitted-bg !important;
|
||||||
|
color: @kanban-uncommitted-text !important;
|
||||||
|
}
|
||||||
|
tr {
|
||||||
|
height: 28px;
|
||||||
|
/* Options */
|
||||||
|
td:first-child {
|
||||||
|
position:absolute;
|
||||||
|
left: 0;
|
||||||
|
top: auto;
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
/* Uncommitted column */
|
||||||
|
td:nth-last-child(2) {
|
||||||
|
position: absolute;
|
||||||
|
top: auto;
|
||||||
|
width: 100px;
|
||||||
|
min-width: unset !important;
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
/* Results */
|
||||||
|
td:last-child {
|
||||||
|
color: @kanban-th-fg;
|
||||||
|
position:absolute;
|
||||||
|
top: auto;
|
||||||
|
margin-left: 100px;
|
||||||
|
width: 100px;
|
||||||
|
min-width: unset !important;
|
||||||
|
background-color: @kanban-th-bg;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
|
||||||
|
div.cp-app-kanban-table-text-cell {
|
||||||
|
height: 28px;
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.cp-app-kanban-table-remove {
|
||||||
|
order: 1;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-edit {
|
||||||
|
order: 3;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
min-width: 0;
|
||||||
|
order: 2;
|
||||||
|
flex: 1;
|
||||||
|
height: 24px;
|
||||||
|
border: 0px;
|
||||||
|
margin: 2px;
|
||||||
|
&[disabled] {
|
||||||
|
background-color: transparent;
|
||||||
|
color: @kanban-td-fg;
|
||||||
|
//font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.cp-app-kanban-table-checkbox-cell {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
height: 100%;
|
||||||
|
min-width: 100px;
|
||||||
|
|
||||||
|
div.cp-app-kanban-table-checkbox-contain {
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
label {
|
||||||
|
background-color: transparent;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
&[type="number"] {
|
||||||
|
&:not(.editable) {
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
~ .cp-app-kanban-table-cover {
|
||||||
|
line-height: 28px;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
color: @kanban-cover-color;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"][value="0"] {
|
||||||
|
~ .cp-app-kanban-table-cover {
|
||||||
|
background-color: @colortheme_cp-red;
|
||||||
|
&:after { content: "✖"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input[type="number"][value="1"] {
|
||||||
|
~ .cp-app-kanban-table-cover {
|
||||||
|
background-color: @colortheme_cp-green;
|
||||||
|
&:after { content: "✔"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input[type="number"][value="2"] {
|
||||||
|
~ .cp-app-kanban-table-cover {
|
||||||
|
background-color: @kanban-option-yellow;
|
||||||
|
&:after { content: "~"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input[type="number"][value="3"] {
|
||||||
|
~ .cp-app-kanban-table-cover {
|
||||||
|
background-color: @kanban-option-gray;
|
||||||
|
&:after { content: "?"; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
&[type="text"] {
|
||||||
|
height: auto;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
span {
|
||||||
|
.tools_unselectable();
|
||||||
|
}
|
||||||
|
thead {
|
||||||
|
height: 52px;
|
||||||
|
tr {
|
||||||
|
height: 52px;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
padding: 0px 5px;
|
||||||
|
background: @kanban-th-bg;
|
||||||
|
color: @kanban-th-fg;
|
||||||
|
&:not(:last-child) {
|
||||||
|
border-right: 1px solid rgba(255,255,255,0.2);
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
height: 52px;
|
||||||
|
line-height: 52px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&:nth-last-child(2) {
|
||||||
|
border-right: 1px solid @kanban-border-color;
|
||||||
|
}
|
||||||
|
&.cp-app-kanban-table-own {
|
||||||
|
background: @kanban-th-user-bg;
|
||||||
|
.cp-app-kanban-table-lock {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
span {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-bookmark {
|
||||||
|
color: darken(@kanban-th-fg, 30%);
|
||||||
|
&.cp-app-kanban-table-bookmark-full {
|
||||||
|
color: @kanban-th-fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
&[type="text"] {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
break-after: always;
|
||||||
|
width: ~"calc(100% - 2px)"; // borders...
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 1px 5px;
|
||||||
|
margin: 1px;
|
||||||
|
&[disabled] {
|
||||||
|
color: @kanban-th-fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tbody {
|
||||||
|
td:first-child {
|
||||||
|
background: @kanban-td-bg;
|
||||||
|
color: @kanban-td-fg;
|
||||||
|
}
|
||||||
|
td.cp-app-kanban-table-winner {
|
||||||
|
background-color: @kanban-winner;
|
||||||
|
&:last-child { font-weight: bold; }
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-text-cell {
|
||||||
|
input[type="text"] {
|
||||||
|
width: ~"calc(100% - 50px)";
|
||||||
|
padding: 0 0.5em;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-edit {
|
||||||
|
float:right;
|
||||||
|
margin: 2px 10px 0 0;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-remove {
|
||||||
|
float: left;
|
||||||
|
margin: 2px 0 0 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tr:not(:first-child) {
|
||||||
|
td:not(:first-child) {
|
||||||
|
label {
|
||||||
|
border-top: 1px solid @kanban-border-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-edit {
|
||||||
|
//color: @kanban-cover-color;
|
||||||
|
cursor: pointer;
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
tr {
|
||||||
|
th {
|
||||||
|
input[type="text"][disabled] {
|
||||||
|
background-color: transparent;
|
||||||
|
color: @kanban-fore;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-table-remove {
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tbody {
|
||||||
|
tr {
|
||||||
|
td {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tfoot {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cp-app-kanban-nocomments {
|
||||||
|
color: #999;
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px;
|
||||||
|
font: @colortheme_app-font;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-comments {
|
||||||
|
width: 50%;
|
||||||
|
margin: 20px auto;
|
||||||
|
min-width: 400px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
display: none;
|
||||||
|
button {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-comments-add {
|
||||||
|
input, textarea {
|
||||||
|
border: 1px solid black;
|
||||||
|
width: 90%;
|
||||||
|
margin: 5px 5%;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
padding: 5px;
|
||||||
|
height: 26px;
|
||||||
|
&[disabled] {
|
||||||
|
background: #eee;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
padding: 5px;
|
||||||
|
height: 8em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#cp-app-kanban-comments-list {
|
||||||
|
.cp-app-kanban-comments-list-el {
|
||||||
|
width: 90%;
|
||||||
|
margin: 5px 5%;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-comments-list-msg {
|
||||||
|
display: flex;
|
||||||
|
background: #eee;
|
||||||
|
padding: 5px 10px;
|
||||||
|
.cp-app-kanban-comments-list-msg-text {
|
||||||
|
flex: 1;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-comments-list-msg-actions {
|
||||||
|
button {
|
||||||
|
padding: 0;
|
||||||
|
width: 25px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.cp-app-kanban-comments-list-data {
|
||||||
|
background: #ddd;
|
||||||
|
padding: 5px 10px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.cp-app-kanban-comments-list-data-name {
|
||||||
|
margin-left: 10px;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.cp-app-kanban-comments-list-data-avatar { .avatar_main(30px); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 500px) {
|
||||||
|
#cp-app-kanban-table-scroll {
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
table {
|
||||||
|
tr {
|
||||||
|
td {
|
||||||
|
&:first-child {
|
||||||
|
position: unset;
|
||||||
|
min-width: 100px;
|
||||||
|
&:hover:not(:empty) {
|
||||||
|
position: absolute;
|
||||||
|
min-width: 100px;
|
||||||
|
width: auto;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:nth-last-child(2) {
|
||||||
|
position: unset;
|
||||||
|
}
|
||||||
|
&:last-child {
|
||||||
|
position: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#cp-app-kanban-comments {
|
||||||
|
min-width: 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>CryptPad</title>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="referrer" content="no-referrer" />
|
||||||
|
<script async data-bootload="main.js" data-main="/common/boot.js?ver=1.0" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
#sbox-iframe {
|
||||||
|
position:fixed;
|
||||||
|
top:0px;
|
||||||
|
left:0px;
|
||||||
|
bottom:0px;
|
||||||
|
right:0px;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
border:none;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
#sbox-filePicker-iframe {
|
||||||
|
position: fixed;
|
||||||
|
top:0; left:0;
|
||||||
|
bottom:0; right:0;
|
||||||
|
width:100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe id="sbox-iframe">
|
@ -0,0 +1,43 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html class="cp-app-noscroll">
|
||||||
|
<head>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<script async data-bootload="/kanban/inner.js" data-main="/common/sframe-boot.js?ver=1.6" src="/bower_components/requirejs/require.js?ver=2.3.5"></script>
|
||||||
|
<style>
|
||||||
|
.loading-hidden { display: none; }
|
||||||
|
#editor1 { display: none; }
|
||||||
|
html, body {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#myKanban {
|
||||||
|
overflow-x: auto;
|
||||||
|
padding: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
background: #00B961;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info {
|
||||||
|
background: #2A92BF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
background: #F4CE46;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
background: #FB7D44;
|
||||||
|
}
|
||||||
|
</head>
|
||||||
|
<body class="cp-app-kanban">
|
||||||
|
</body>
|
@ -0,0 +1,628 @@
|
|||||||
|
define([
|
||||||
|
'jquery',
|
||||||
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
|
'/common/toolbar3.js',
|
||||||
|
'json.sortify',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/bower_components/nthen/index.js',
|
||||||
|
'/common/sframe-common.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/api/config',
|
||||||
|
'/common/common-realtime.js',
|
||||||
|
'/customize/pages.js',
|
||||||
|
'/customize/messages.js',
|
||||||
|
'/customize/application_config.js',
|
||||||
|
'/common/common-thumbnail.js',
|
||||||
|
'/bower_components/chainpad/chainpad.dist.js',
|
||||||
|
|
||||||
|
'/bower_components/secure-fabric.js/dist/fabric.min.js',
|
||||||
|
'/bower_components/file-saver/FileSaver.min.js',
|
||||||
|
|
||||||
|
'css!/bower_components/bootstrap/dist/css/bootstrap.min.css',
|
||||||
|
'less!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||||
|
'less!/customize/src/less2/main.less',
|
||||||
|
'css!/kanban/jkanban.css',
|
||||||
|
'/kanban/jkanban.js',
|
||||||
|
], function (
|
||||||
|
$,
|
||||||
|
Crypto,
|
||||||
|
Toolbar,
|
||||||
|
JSONSortify,
|
||||||
|
Util,
|
||||||
|
nThen,
|
||||||
|
SFCommon,
|
||||||
|
UI,
|
||||||
|
ApiConfig,
|
||||||
|
CommonRealtime,
|
||||||
|
Pages,
|
||||||
|
Messages,
|
||||||
|
AppConfig,
|
||||||
|
Thumb,
|
||||||
|
ChainPad)
|
||||||
|
{
|
||||||
|
var saveAs = window.saveAs;
|
||||||
|
|
||||||
|
var APP = window.APP = {
|
||||||
|
$: $
|
||||||
|
};
|
||||||
|
var Fabric = APP.Fabric = window.fabric;
|
||||||
|
|
||||||
|
var stringify = function (obj) {
|
||||||
|
return JSONSortify(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
var toolbar;
|
||||||
|
|
||||||
|
var andThen = function (common) {
|
||||||
|
var config = {};
|
||||||
|
/* Initialize Fabric */
|
||||||
|
var canvas = APP.canvas = null;
|
||||||
|
var $canvas = $('canvas');
|
||||||
|
var readOnly = false;
|
||||||
|
|
||||||
|
var setEditable = function (bool) {
|
||||||
|
APP.editable = bool;
|
||||||
|
if (readOnly && bool) { return; }
|
||||||
|
};
|
||||||
|
|
||||||
|
var saveImage = APP.saveImage = function () {
|
||||||
|
};
|
||||||
|
|
||||||
|
APP.FM = common.createFileManager({});
|
||||||
|
APP.upload = function (title) {
|
||||||
|
};
|
||||||
|
|
||||||
|
var initializing = true;
|
||||||
|
var $bar = $('#cp-toolbar');
|
||||||
|
var Title;
|
||||||
|
var cpNfInner;
|
||||||
|
var metadataMgr;
|
||||||
|
|
||||||
|
config = {
|
||||||
|
readOnly: readOnly,
|
||||||
|
patchTransformer: ChainPad.NaiveJSONTransformer,
|
||||||
|
// cryptpad debug logging (default is 1)
|
||||||
|
// logLevel: 0,
|
||||||
|
validateContent: function (content) {
|
||||||
|
try {
|
||||||
|
JSON.parse(content);
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Failed to parse, rejecting patch");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var stringifyInner = function (textValue) {
|
||||||
|
var obj = {
|
||||||
|
content: textValue,
|
||||||
|
metadata: metadataMgr.getMetadataLazy()
|
||||||
|
};
|
||||||
|
// stringify the json and send it into chainpad
|
||||||
|
return stringify(obj);
|
||||||
|
};
|
||||||
|
|
||||||
|
var onLocal = config.onLocal = function () {
|
||||||
|
if (initializing) { return; }
|
||||||
|
if (readOnly) { return; }
|
||||||
|
|
||||||
|
var content = stringifyInner(Kanban.getBoardsJSON());
|
||||||
|
console.log("Updating content " + content);
|
||||||
|
|
||||||
|
try {
|
||||||
|
APP.realtime.contentUpdate(content);
|
||||||
|
} catch (e) {
|
||||||
|
APP.unrecoverable = true;
|
||||||
|
setEditable(false);
|
||||||
|
APP.toolbar.errorState(true, e.message);
|
||||||
|
var msg = Messages.chainpadError;
|
||||||
|
UI.errorLoadingScreen(msg, true, true);
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var initThumbnails = function () {
|
||||||
|
var oldThumbnailState;
|
||||||
|
var privateDat = metadataMgr.getPrivateData();
|
||||||
|
if (!privateDat.thumbnails) { return; }
|
||||||
|
var hash = privateDat.availableHashes.editHash ||
|
||||||
|
privateDat.availableHashes.viewHash;
|
||||||
|
var href = privateDat.pathname + '#' + hash;
|
||||||
|
var mkThumbnail = function () {
|
||||||
|
if (!hash) { return; }
|
||||||
|
if (initializing) { return; }
|
||||||
|
if (!APP.realtime) { return; }
|
||||||
|
var content = APP.realtime.getUserDoc();
|
||||||
|
if (content === oldThumbnailState) { return; }
|
||||||
|
/*
|
||||||
|
var D = Thumb.getResizedDimensions($canvas[0], 'pad');
|
||||||
|
Thumb.fromCanvas($canvas[0], D, function (err, b64) {
|
||||||
|
oldThumbnailState = content;
|
||||||
|
Thumb.setPadThumbnail(common, href, b64);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
window.setInterval(mkThumbnail, Thumb.UPDATE_INTERVAL);
|
||||||
|
window.setTimeout(mkThumbnail, Thumb.UPDATE_FIRST);
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onInit = function (info) {
|
||||||
|
readOnly = metadataMgr.getPrivateData().readOnly;
|
||||||
|
|
||||||
|
Title = common.createTitle({});
|
||||||
|
|
||||||
|
var configTb = {
|
||||||
|
displayed: [
|
||||||
|
'userlist',
|
||||||
|
'title',
|
||||||
|
'useradmin',
|
||||||
|
'spinner',
|
||||||
|
'newpad',
|
||||||
|
'share',
|
||||||
|
'limit',
|
||||||
|
'unpinnedWarning'
|
||||||
|
],
|
||||||
|
title: Title.getTitleConfig(),
|
||||||
|
metadataMgr: metadataMgr,
|
||||||
|
readOnly: readOnly,
|
||||||
|
realtime: info.realtime,
|
||||||
|
sfCommon: common,
|
||||||
|
$container: $bar,
|
||||||
|
$contentContainer: $('#cp-app-kanban-content')
|
||||||
|
};
|
||||||
|
toolbar = APP.toolbar = Toolbar.create(configTb);
|
||||||
|
Title.setToolbar(toolbar);
|
||||||
|
|
||||||
|
var $rightside = toolbar.$rightside;
|
||||||
|
var $drawer = toolbar.$drawer;
|
||||||
|
|
||||||
|
/* save as template */
|
||||||
|
if (!metadataMgr.getPrivateData().isTemplate) {
|
||||||
|
var templateObj = {
|
||||||
|
rt: info.realtime,
|
||||||
|
getTitle: function () { return metadataMgr.getMetadata().title; }
|
||||||
|
};
|
||||||
|
var $templateButton = common.createButton('template', true, templateObj);
|
||||||
|
$rightside.append($templateButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add an export button */
|
||||||
|
var $export = common.createButton('export', true, {}, saveImage);
|
||||||
|
$drawer.append($export);
|
||||||
|
|
||||||
|
if (common.isLoggedIn()) {
|
||||||
|
common.createButton('savetodrive', true, {}, function () {})
|
||||||
|
.click(function () {
|
||||||
|
UI.prompt(Messages.exportPrompt, document.title + '.png',
|
||||||
|
function (name) {
|
||||||
|
if (name === null || !name.trim()) { return; }
|
||||||
|
APP.upload(name);
|
||||||
|
});
|
||||||
|
}).appendTo($rightside);
|
||||||
|
|
||||||
|
common.createButton('hashtag', true).appendTo($rightside);
|
||||||
|
}
|
||||||
|
|
||||||
|
var $forget = common.createButton('forget', true, {}, function (err) {
|
||||||
|
if (err) { return; }
|
||||||
|
setEditable(false);
|
||||||
|
});
|
||||||
|
$rightside.append($forget);
|
||||||
|
|
||||||
|
var $properties = common.createButton('properties', true);
|
||||||
|
toolbar.$drawer.append($properties);
|
||||||
|
|
||||||
|
var $appContainer = $('#cp-app-kanban-container');
|
||||||
|
var helpMenu = common.createHelpMenu(['kanban']);
|
||||||
|
$appContainer.prepend(helpMenu.menu);
|
||||||
|
toolbar.$drawer.append(helpMenu.button);
|
||||||
|
|
||||||
|
metadataMgr.onChange(function () {
|
||||||
|
var md = metadataMgr.getMetadata();
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onReady = function (info) {
|
||||||
|
if (APP.realtime !== info.realtime) {
|
||||||
|
APP.realtime = info.realtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
var userDoc = APP.realtime.getUserDoc();
|
||||||
|
var isNew = false;
|
||||||
|
var newDoc = '';
|
||||||
|
if (userDoc === "" || userDoc === "{}") { isNew = true; }
|
||||||
|
|
||||||
|
if (userDoc !== "") {
|
||||||
|
var hjson = JSON.parse(userDoc);
|
||||||
|
|
||||||
|
if (hjson && hjson.metadata) {
|
||||||
|
metadataMgr.updateMetadata(hjson.metadata);
|
||||||
|
}
|
||||||
|
if (typeof (hjson) !== 'object' || Array.isArray(hjson) ||
|
||||||
|
(hjson.metadata && typeof(hjson.metadata.type) !== 'undefined' &&
|
||||||
|
hjson.metadata.type !== 'kanban')) {
|
||||||
|
var errorText = Messages.typeError;
|
||||||
|
UI.errorLoadingScreen(errorText);
|
||||||
|
throw new Error(errorText);
|
||||||
|
}
|
||||||
|
newDoc = hjson.content;
|
||||||
|
|
||||||
|
// launch the kanban code
|
||||||
|
config.initKanban(newDoc);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Title.updateTitle(Title.defaultTitle);
|
||||||
|
config.initKanban();
|
||||||
|
}
|
||||||
|
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
if (newDoc) {
|
||||||
|
}
|
||||||
|
}).nThen(function () {
|
||||||
|
setEditable(!readOnly);
|
||||||
|
initializing = false;
|
||||||
|
config.onLocal();
|
||||||
|
UI.removeLoadingScreen();
|
||||||
|
|
||||||
|
initThumbnails();
|
||||||
|
|
||||||
|
|
||||||
|
if (readOnly) { return; }
|
||||||
|
|
||||||
|
var privateDat = metadataMgr.getPrivateData();
|
||||||
|
var skipTemp = Util.find(privateDat,
|
||||||
|
['settings', 'general', 'creation', 'noTemplate']);
|
||||||
|
var skipCreation = Util.find(privateDat, ['settings', 'general', 'creation', 'skip']);
|
||||||
|
if (isNew && (!AppConfig.displayCreationScreen || (!skipTemp && skipCreation))) {
|
||||||
|
common.openTemplatePicker();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onRemote = function () {
|
||||||
|
if (initializing) { return; }
|
||||||
|
var userDoc = APP.realtime.getUserDoc();
|
||||||
|
|
||||||
|
console.log("Received content: " + userDoc);
|
||||||
|
|
||||||
|
var json = JSON.parse(userDoc);
|
||||||
|
var remoteDoc = json.content;
|
||||||
|
|
||||||
|
var currentContent = stringify(Kanban.getBoardsJSON());
|
||||||
|
var remoteContent = stringify(json.content);
|
||||||
|
|
||||||
|
|
||||||
|
if (currentContent !== remoteContent) {
|
||||||
|
// reinit kanban (TODO: optimize to diff only)
|
||||||
|
console.log("Content is different.. Applying content");
|
||||||
|
config.Kanban.setBoards(remoteDoc);
|
||||||
|
common.notify();
|
||||||
|
}
|
||||||
|
if (readOnly) { setEditable(false); }
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onAbort = function () {
|
||||||
|
if (APP.unrecoverable) { return; }
|
||||||
|
// inform of network disconnect
|
||||||
|
setEditable(false);
|
||||||
|
toolbar.failed();
|
||||||
|
UI.alert(Messages.common_connectionLost, undefined, true);
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onConnectionChange = function (info) {
|
||||||
|
if (APP.unrecoverable) { return; }
|
||||||
|
setEditable(info.state);
|
||||||
|
if (info.state) {
|
||||||
|
initializing = true;
|
||||||
|
//UI.findOKButton().click();
|
||||||
|
} else {
|
||||||
|
//UI.alert(Messages.common_connectionLost, undefined, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
config.onError = function (err) {
|
||||||
|
common.onServerError(err, toolbar, function () {
|
||||||
|
APP.unrecoverable = true;
|
||||||
|
setEditable(false);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
config.initKanban = function(boards) {
|
||||||
|
var defaultBoards = [
|
||||||
|
{
|
||||||
|
"id": "todo",
|
||||||
|
"title": "To Do",
|
||||||
|
"color": "blue",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"title": "Item 1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Item 2"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "working",
|
||||||
|
"title": "Working",
|
||||||
|
"color": "orange",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"title": "Item 3",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Item 4",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "done",
|
||||||
|
"title": "Done",
|
||||||
|
"color": "green",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"title": "Item 5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Item 6",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|
||||||
|
if (boards==null) {
|
||||||
|
console.log("Initializing with default boards content");
|
||||||
|
boards = defaultBoards;
|
||||||
|
} else {
|
||||||
|
console.log("Initializing with boards content " + boards);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove any existing elements
|
||||||
|
$(".kanban-container-outer").remove();
|
||||||
|
|
||||||
|
window.Kanban = config.Kanban = new jKanban({
|
||||||
|
element: '#cp-app-kanban-content',
|
||||||
|
gutter: '15px',
|
||||||
|
widthBoard: '300px',
|
||||||
|
onChange: function() {
|
||||||
|
console.log("Board object has changed");
|
||||||
|
config.onLocal();
|
||||||
|
}
|
||||||
|
,click: function (el) {
|
||||||
|
if (Kanban.inEditMode) {
|
||||||
|
console.log("An edit is already active");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Kanban.inEditMode = true;
|
||||||
|
var name = $(el).text();
|
||||||
|
$(el).html('');
|
||||||
|
$('<input></input>')
|
||||||
|
.attr({
|
||||||
|
'type': 'text',
|
||||||
|
'name': 'text',
|
||||||
|
'id': 'kanban_edit',
|
||||||
|
'size': '30',
|
||||||
|
'value': name
|
||||||
|
})
|
||||||
|
.appendTo(el);
|
||||||
|
$('#kanban_edit').focus();
|
||||||
|
$('#kanban_edit').blur(function() {
|
||||||
|
var name = $('#kanban_edit').val();
|
||||||
|
$(el).text(name);
|
||||||
|
var board = $(el.parentNode.parentNode).attr("data-id");
|
||||||
|
var pos = Kanban.findElementPosition(el);
|
||||||
|
console.log(pos);
|
||||||
|
console.log(board);
|
||||||
|
Kanban.getBoardJSON(board).item[pos].title = name;
|
||||||
|
Kanban.onChange();
|
||||||
|
Kanban.inEditMode = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
boardTitleClick: function (el) {
|
||||||
|
if (Kanban.inEditMode) {
|
||||||
|
console.log("An edit is already active");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Kanban.inEditMode = true;
|
||||||
|
var name = $(el).text();
|
||||||
|
$(el).html('');
|
||||||
|
$('<input></input>')
|
||||||
|
.attr({
|
||||||
|
'type': 'text',
|
||||||
|
'name': 'text',
|
||||||
|
'id': 'kanban_edit',
|
||||||
|
'size': '30',
|
||||||
|
'value': name
|
||||||
|
})
|
||||||
|
.appendTo(el);
|
||||||
|
$('#kanban_edit').focus();
|
||||||
|
$('#kanban_edit').blur(function() {
|
||||||
|
var name = $('#kanban_edit').val();
|
||||||
|
$(el).text(name);
|
||||||
|
var board = $(el.parentNode.parentNode).attr("data-id");
|
||||||
|
Kanban.getBoardJSON(board).title = name;
|
||||||
|
Kanban.onChange();
|
||||||
|
Kanban.inEditMode = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
colorClick: function (el, boardId) {
|
||||||
|
console.log("in color click");
|
||||||
|
var board = $(el.parentNode).attr("data-id");
|
||||||
|
var boardJSON = Kanban.getBoardJSON(board);
|
||||||
|
var currentColor = boardJSON.color;
|
||||||
|
console.log("Current color " + currentColor);
|
||||||
|
var index = Kanban.options.colors.findIndex(function(element) { return (element==currentColor) }) + 1;
|
||||||
|
console.log("Next index " + index);
|
||||||
|
if (index>=Kanban.options.colors.length)
|
||||||
|
index = 0;
|
||||||
|
var nextColor = Kanban.options.colors[index];
|
||||||
|
console.log("Next color " + nextColor);
|
||||||
|
boardJSON.color = nextColor;
|
||||||
|
$(el).removeClass("kanban-header-" + currentColor);
|
||||||
|
$(el).addClass("kanban-header-" + nextColor);
|
||||||
|
Kanban.onChange();
|
||||||
|
|
||||||
|
},
|
||||||
|
removeClick: function(el, boardId) {
|
||||||
|
if (confirm("Do you want to delete this board?")) {
|
||||||
|
console.log("Delete board");
|
||||||
|
var boardName = $(el.parentNode.parentNode).attr("data-id");
|
||||||
|
for (index in Kanban.options.boards) {
|
||||||
|
if (Kanban.options.boards[index].id == boardName) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
Kanban.options.boards.splice(index, 1);
|
||||||
|
Kanban.removeBoard(boardName);
|
||||||
|
Kanban.onChange();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buttonClick: function (el, boardId) {
|
||||||
|
console.log(el);
|
||||||
|
console.log(boardId);
|
||||||
|
// create a form to enter element
|
||||||
|
var formItem = document.createElement('form');
|
||||||
|
formItem.setAttribute("class", "itemform");
|
||||||
|
formItem.innerHTML = '<div class="form-group"><textarea class="form-control" rows="2" autofocus></textarea></div><div class="form-group"><button type="submit" class="btn btn-primary btn-xs">Submit</button><button type="button" id="CancelBtn" class="btn btn-default btn-xs pull-right">Cancel</button></div>'
|
||||||
|
|
||||||
|
Kanban.addForm(boardId, formItem);
|
||||||
|
formItem.addEventListener("submit", function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var text = e.target[0].value
|
||||||
|
Kanban.addElement(boardId, {
|
||||||
|
"title": text,
|
||||||
|
})
|
||||||
|
formItem.parentNode.removeChild(formItem);
|
||||||
|
});
|
||||||
|
document.getElementById('CancelBtn').onclick = function () {
|
||||||
|
formItem.parentNode.removeChild(formItem)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
addItemButton: true,
|
||||||
|
boards: boards
|
||||||
|
});
|
||||||
|
|
||||||
|
var addBoardDefault = document.getElementById('kanban-addboard');
|
||||||
|
addBoardDefault.addEventListener('click', function () {
|
||||||
|
var counter = 1;
|
||||||
|
found = false;
|
||||||
|
while (found) {
|
||||||
|
for (var board in Kanban.options.boards) {
|
||||||
|
if (board.id == "board" + counter) {
|
||||||
|
counter++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Kanban.addBoards(
|
||||||
|
[{
|
||||||
|
"id" : "board" + counter,
|
||||||
|
"title": "New Board",
|
||||||
|
"color": "yellow",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"title": "Item 1",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
Kanban.onChange();
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
var toDoButton = document.getElementById('addToDo');
|
||||||
|
toDoButton.addEventListener('click', function () {
|
||||||
|
Kanban.addElement(
|
||||||
|
"_todo",
|
||||||
|
{
|
||||||
|
"title": "Test Add",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
var addBoardDefault = document.getElementById('addDefault');
|
||||||
|
addBoardDefault.addEventListener('click', function () {
|
||||||
|
Kanban.addBoards(
|
||||||
|
[{
|
||||||
|
"id": "_default",
|
||||||
|
"title": "Kanban Default",
|
||||||
|
"item": [
|
||||||
|
{
|
||||||
|
"title": "Default Item",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Default Item 2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Default Item 3",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
var removeBoard = document.getElementById('removeBoard');
|
||||||
|
removeBoard.addEventListener('click', function () {
|
||||||
|
Kanban.removeBoard('_done');
|
||||||
|
});
|
||||||
|
|
||||||
|
var removeElement = document.getElementById('removeElement');
|
||||||
|
removeElement.addEventListener('click', function () {
|
||||||
|
Kanban.removeElement('_test_delete');
|
||||||
|
});
|
||||||
|
|
||||||
|
var allEle = Kanban.getBoardElements('_todo');
|
||||||
|
allEle.forEach(function (item, index) {
|
||||||
|
//console.log(item);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
cpNfInner = common.startRealtime(config);
|
||||||
|
metadataMgr = cpNfInner.metadataMgr;
|
||||||
|
|
||||||
|
cpNfInner.onInfiniteSpinner(function () {
|
||||||
|
if (APP.unrecoverable) { return; }
|
||||||
|
setEditable(false);
|
||||||
|
UI.confirm(Messages.realtime_unrecoverableError, function (yes) {
|
||||||
|
if (!yes) { return; }
|
||||||
|
common.gotoURL();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#save').on('click', function () {
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
common.onLogout(function () { setEditable(false); });
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var main = function () {
|
||||||
|
var common;
|
||||||
|
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
$(waitFor(function () {
|
||||||
|
UI.addLoadingScreen();
|
||||||
|
var $div = $('<div>').append(Pages['/kanban/']());
|
||||||
|
$('body').append($div.html());
|
||||||
|
$('body').addClass("cp-app-kanban");
|
||||||
|
}));
|
||||||
|
SFCommon.create(waitFor(function (c) { APP.common = common = c; }));
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
common.getSframeChannel().onReady(waitFor());
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
common.handleNewFile(waitFor);
|
||||||
|
}).nThen(function (/*waitFor*/) {
|
||||||
|
andThen(common);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
main();
|
||||||
|
});
|
@ -0,0 +1,151 @@
|
|||||||
|
|
||||||
|
.kanban-container-outer {
|
||||||
|
position: relative;
|
||||||
|
box-sizing: border-box;
|
||||||
|
width: 100%;
|
||||||
|
overflow: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-container {
|
||||||
|
width: 200%;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-container * {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-container:after {
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board {
|
||||||
|
position: relative;
|
||||||
|
float: left;
|
||||||
|
background: #E2E4E6;
|
||||||
|
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
margin: 10px;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board.disabled-board{
|
||||||
|
opacity: .3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board.is-moving.gu-mirror {
|
||||||
|
transform: rotate(3deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board.is-moving.gu-mirror .kanban-drag {
|
||||||
|
overflow: hidden;
|
||||||
|
padding-right: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board header {
|
||||||
|
font-size: 16px;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board header .kanban-title-board {
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board header .kanban-title-button {
|
||||||
|
float: right;
|
||||||
|
line-height: 1;
|
||||||
|
padding: .25rem .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board .kanban-drag {
|
||||||
|
min-height: 200px;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-board:after {
|
||||||
|
clear: both;
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-item {
|
||||||
|
background: #fff;
|
||||||
|
padding: 15px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
transition: all 0.3s cubic-bezier(0.23, 1, 0.32, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-item:hover {
|
||||||
|
cursor: move;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-item:last-child {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-item.is-moving.gu-mirror {
|
||||||
|
transform: rotate(3deg);
|
||||||
|
height: auto !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-header-yellow { background: #FC3; }
|
||||||
|
.kanban-header-orange { background: #F91; }
|
||||||
|
.kanban-header-blue { background: #0AC; }
|
||||||
|
.kanban-header-red { background: #E43; }
|
||||||
|
.kanban-header-green { background: #8C4; }
|
||||||
|
|
||||||
|
#kanban-addboard {
|
||||||
|
float: left;
|
||||||
|
margin: 30px;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 5px;
|
||||||
|
padding-top: 3;
|
||||||
|
padding-bottom: 3px;
|
||||||
|
border: 1px solid;
|
||||||
|
width: 30px;
|
||||||
|
text-align: center;
|
||||||
|
background: #d4d4e8;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.kanban-removeboard {
|
||||||
|
float: right;
|
||||||
|
margin: 10px;
|
||||||
|
padding: 3px;
|
||||||
|
width: 30px;
|
||||||
|
text-align: center;
|
||||||
|
background: #eee;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dragula CSS */
|
||||||
|
.gu-mirror {
|
||||||
|
position: fixed !important;
|
||||||
|
margin: 0 !important;
|
||||||
|
z-index: 9999 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gu-hide {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gu-unselectable {
|
||||||
|
-webkit-user-select: none !important;
|
||||||
|
-moz-user-select: none !important;
|
||||||
|
-ms-user-select: none !important;
|
||||||
|
user-select: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gu-transit {
|
||||||
|
opacity: 0.2 !important;
|
||||||
|
transform: rotate(0deg) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
text-align: right;
|
||||||
|
margin-button: 5px;
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,25 @@
|
|||||||
|
html, body {
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
#sbox-iframe {
|
||||||
|
position:fixed;
|
||||||
|
top:0px;
|
||||||
|
left:0px;
|
||||||
|
bottom:0px;
|
||||||
|
right:0px;
|
||||||
|
width:100%;
|
||||||
|
height:100%;
|
||||||
|
border:none;
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
#sbox-filePicker-iframe {
|
||||||
|
position: fixed;
|
||||||
|
top:0; left:0;
|
||||||
|
bottom:0; right:0;
|
||||||
|
width:100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 0;
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
// Load #1, load as little as possible because we are in a race to get the loading screen up.
|
||||||
|
define([
|
||||||
|
'/bower_components/nthen/index.js',
|
||||||
|
'/api/config',
|
||||||
|
'/common/dom-ready.js',
|
||||||
|
'/common/requireconfig.js',
|
||||||
|
'/common/sframe-common-outer.js',
|
||||||
|
], function (nThen, ApiConfig, DomReady, RequireConfig, SFCommonO) {
|
||||||
|
var requireConfig = RequireConfig();
|
||||||
|
|
||||||
|
// Loaded in load #2
|
||||||
|
nThen(function (waitFor) {
|
||||||
|
DomReady.onReady(waitFor());
|
||||||
|
}).nThen(function (waitFor) {
|
||||||
|
var req = {
|
||||||
|
cfg: requireConfig,
|
||||||
|
req: [ '/common/loading.js' ],
|
||||||
|
pfx: window.location.origin
|
||||||
|
};
|
||||||
|
window.rc = requireConfig;
|
||||||
|
window.apiconf = ApiConfig;
|
||||||
|
document.getElementById('sbox-iframe').setAttribute('src',
|
||||||
|
ApiConfig.httpSafeOrigin + '/kanban/inner.html?' + requireConfig.urlArgs +
|
||||||
|
'#' + encodeURIComponent(JSON.stringify(req)));
|
||||||
|
|
||||||
|
// This is a cheap trick to avoid loading sframe-channel in parallel with the
|
||||||
|
// loading screen setup.
|
||||||
|
var done = waitFor();
|
||||||
|
var onMsg = function (msg) {
|
||||||
|
var data = JSON.parse(msg.data);
|
||||||
|
if (data.q !== 'READY') { return; }
|
||||||
|
window.removeEventListener('message', onMsg);
|
||||||
|
var _done = done;
|
||||||
|
done = function () { };
|
||||||
|
_done();
|
||||||
|
};
|
||||||
|
window.addEventListener('message', onMsg);
|
||||||
|
}).nThen(function (/*waitFor*/) {
|
||||||
|
SFCommonO.start({
|
||||||
|
useCreationScreen: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue