From c1275b567109d033f181260e2ef84a302152c132 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 27 Sep 2017 10:28:10 +0200 Subject: [PATCH 01/20] Prepare secure poll --- www/{poll => oldpoll}/index.html | 0 www/{poll => oldpoll}/main.js | 0 www/{poll => oldpoll}/poll.less | 0 www/{poll => oldpoll}/render.js | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename www/{poll => oldpoll}/index.html (100%) rename www/{poll => oldpoll}/main.js (100%) rename www/{poll => oldpoll}/poll.less (100%) rename www/{poll => oldpoll}/render.js (100%) diff --git a/www/poll/index.html b/www/oldpoll/index.html similarity index 100% rename from www/poll/index.html rename to www/oldpoll/index.html diff --git a/www/poll/main.js b/www/oldpoll/main.js similarity index 100% rename from www/poll/main.js rename to www/oldpoll/main.js diff --git a/www/poll/poll.less b/www/oldpoll/poll.less similarity index 100% rename from www/poll/poll.less rename to www/oldpoll/poll.less diff --git a/www/poll/render.js b/www/oldpoll/render.js similarity index 100% rename from www/poll/render.js rename to www/oldpoll/render.js From 66da349ee404782bdfda236602b02c07b2074ffb Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 27 Sep 2017 18:52:04 +0200 Subject: [PATCH 02/20] Sandboxed Poll app with less2 --- customize.dist/pages.js | 31 +- customize.dist/src/less2/main.less | 2 +- www/drive/inner.js | 4 - www/poll/app-drive.less | 820 ++++++++++++++++++++++++ www/poll/app-poll.less | 477 ++++++++++++++ www/poll/index.html | 38 ++ www/poll/inner.html | 20 + www/poll/inner.js | 972 +++++++++++++++++++++++++++++ www/poll/main.js | 41 ++ www/poll/render.js | 453 ++++++++++++++ www/whiteboard/inner.js | 2 +- 11 files changed, 2837 insertions(+), 23 deletions(-) create mode 100644 www/poll/app-drive.less create mode 100644 www/poll/app-poll.less create mode 100644 www/poll/index.html create mode 100644 www/poll/inner.html create mode 100644 www/poll/inner.js create mode 100644 www/poll/main.js create mode 100644 www/poll/render.js diff --git a/customize.dist/pages.js b/customize.dist/pages.js index 55945ccd2..2427b2a28 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -638,48 +638,45 @@ define([ Pages['/poll/'] = Pages['/poll/index.html'] = function () { return [ - appToolbar(), - h('div#content', [ - h('div#poll', [ - h('div#howItWorks', [ + appToolbar3(), + h('div#cp-app-poll-content', [ + h('div#cp-app-poll-form', [ + h('div#cp-app-poll-help', [ h('h1', 'CryptPoll'), setHTML(h('h2'), Msg.poll_subtitle), h('p', Msg.poll_p_save), h('p', Msg.poll_p_encryption) ]), - h('div.upper', [ - h('button#publish.btn.btn-success', { + h('div.cp-app-poll-upper', [ + h('button#cp-app-poll-action-publish.btn.btn-success', { style: { display: 'none' } }, Msg.poll_publish_button), - h('button#admin.btn.btn-primary', { + h('button#cp-app-poll-action-admin.btn.btn-primary', { style: { display: 'none' }, title: Msg.poll_admin_button }, Msg.poll_admin_button), - h('button#help.btn.btn-secondary', { + h('button#cp-app-poll-action-help.btn.btn-secondary', { title: Msg.poll_show_help_button }, Msg.poll_show_help_button) ]), - h('div.realtime', [ + h('div.cp-app-poll-realtime', [ h('br'), h('center', [ - h('textarea#description', { + h('textarea#cp-app-poll-description', { rows: "5", cols: "50", disabled: true }), h('br') ]), - h('div#tableContainer', [ - h('div#tableScroll'), - h('button#create-user.btn.btn-secondary', { + h('div#cp-app-poll-table-container', [ + h('div#cp-app-poll-table-scroll'), + h('button#cp-app-poll-create-user.btn.btn-secondary', { title: Msg.poll_create_user }, h('span.fa.fa-plus')), - h('button#create-option.btn.btn-secondary', { + h('button#cp-app-poll-create-option.btn.btn-secondary', { title: Msg.poll_create_option }, h('span.fa.fa-plus')), - h('button#commit.btn.btn-secondary', { - title: Msg.poll_commit - }, h('span.fa.fa-check')) ]) ]) ]) diff --git a/customize.dist/src/less2/main.less b/customize.dist/src/less2/main.less index 51450db27..5f7c7e071 100644 --- a/customize.dist/src/less2/main.less +++ b/customize.dist/src/less2/main.less @@ -28,6 +28,6 @@ body.cp-app-code { @import "../../../code/app-code.less"; } body.cp-app-slide { @import "../../../slide/app-slide.less"; } body.cp-app-file { @import "../../../file/app-file.less"; } body.cp-app-filepicker { @import "../../../filepicker/app-filepicker.less"; } -//body.cp-app-poll { @import "../../../poll/app-poll.less"; } +body.cp-app-poll { @import "../../../poll/app-poll.less"; } body.cp-app-whiteboard { @import "../../../whiteboard/app-whiteboard.less"; } diff --git a/www/drive/inner.js b/www/drive/inner.js index f8ed897ed..fdde8d906 100644 --- a/www/drive/inner.js +++ b/www/drive/inner.js @@ -1,6 +1,5 @@ define([ 'jquery', - '/bower_components/chainpad-crypto/crypto.js', '/bower_components/textpatcher/TextPatcher.js', '/common/toolbar3.js', 'json.sortify', @@ -12,7 +11,6 @@ define([ '/common/common-realtime.js', '/common/userObject.js', '/customize/application_config.js', - '/common/mergeDrive.js', '/common/sframe-chainpad-listmap.js', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', @@ -20,7 +18,6 @@ define([ 'less!/customize/src/less2/main.less', ], function ( $, - Crypto, TextPatcher, Toolbar, JSONSortify, @@ -32,7 +29,6 @@ define([ CommonRealtime, FO, AppConfig, - Merge, Listmap) { var Messages = Cryptpad.Messages; diff --git a/www/poll/app-drive.less b/www/poll/app-drive.less new file mode 100644 index 000000000..ea027d76e --- /dev/null +++ b/www/poll/app-drive.less @@ -0,0 +1,820 @@ +@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/leftside-menu.less'; +@import (once) "../../customize/src/less2/include/tools.less"; +@import (once) "../../customize/src/less2/include/limit-bar.less"; + +.toolbar_main(); +.fileupload_main(); +.alertify_main(); +.limit-bar_main(); + +@drive_hover: #eee; +@drive_hover-light: lighten(@drive_hover, 20%); +@drive_info-box-bg: #d2e1f2; +@drive_info-box-border: #bbb; +@drive_table-header-fg: #555; +@drive_table-header-bg: #e8e8e8; +@drive_mobile-tree-border-col: #ccc; + +@drive_content-fg: @colortheme_sidebar-right-fg; +@drive_content-bg: @colortheme_sidebar-right-bg; +@drive_content-bg-ro: darken(@drive_content-bg, 10%); + + +/* PAGE */ + +display: flex; +flex-flow: column; +max-height: 100%; +min-height: auto; + +.cp-unselectable { + .tools_unselectable(); +} + +/* local mixins */ +.drive_fileIcon { + li { + display: inline-block; + margin: 10px 10px; + width: 140px; + height: 140px; + text-align: center; + vertical-align: top; + overflow: hidden; + text-overflow: ellipsis; + padding-top: 5px; + padding-bottom: 5px; + + &:not(.cp-app-drive-element-selected):not(.cp-app-drive-element-selected-tmp) { + border: 1px solid #CCC; + } + .cp-app-drive-element-name { + width: 100%; + height: 48px; + margin: 8px 0; + display: inline-block; + //align-items: center; + //justify-content: center; + overflow: hidden; + //text-overflow: ellipsis; + word-wrap: break-word; + } + .cp-app-drive-element-truncated { + display: block; + position: absolute; + bottom: 0px; + left: 0; right: 0; + text-align: center; + } + img.cp-app-drive-content-icon { + height: 48px; + max-height: none; + max-width: none; + margin: 8px 0; + } + .fa { + display: block; + margin: auto; + font-size: 48px; + margin: 8px 0; + text-align: center; + &.listonly { + display: none; + } + } + } +} + +img.cp-app-drive-icon { + max-width: 20px; + max-height: 16px; +} + +.cp-app-drive-container { + flex: 1; + overflow: auto; + width: 100%; + display: flex; + flex-flow: row; + @media screen and (max-width: @browser_media-medium-screen) { + display: block; + #cp-app-drive-toolbar { + .path .element { + display: none; + } + } + #cp-app-drive-tree { + resize: none; + width: 100%; + max-width: unset; + max-height: unset; + border-bottom: 1px solid @drive_mobile-tree-border-col; + .cp-app-drive-tree-category { + margin-top: 0.5em; + } + } + } +} + +div:focus { + outline: none; +} + +.fa { + font-family: FontAwesome; +} + +ul { + list-style: none; + padding-left: 0px; // Remove the default padding +} + +li { + padding: 0px 5px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.cp-app-drive-context { + display: none; + position: absolute; + z-index: 500; + li { + padding: 0; + font-size: @colortheme_app-font-size; + a { + cursor: pointer; + } + } +} + +.cp-app-drive-element-droppable { + background-color: #FE9A2E; + color: #222; +} + +.cp-app-drive-element-selected { + background: #666 !important; + color: #eee; + margin: -1px; + .fa-minus-square-o, .fa-plus-square-o { + color: @colortheme_sidebar-left-fg; + } +} + +.cp-app-drive-element-selected-tmp { + border: 1px dotted #bbb; + background: #AAA; + color: #ddd; + margin: -1px; + .fa-minus-square-o, .fa-plus-square-o { + color: @colortheme_sidebar-left-fg; + } +} + +span { + &.fa-folder, &.fa-folder-open { + //color: #FEDE8B; + //text-shadow: -1px 0 black, 0 1px black, 1px 0 black, 0 -1px black; + } +} + +/* TREE */ + + +#cp-app-drive-tree { + font-size: @colortheme_app-font-size; + //border-right: 1px solid #ccc; + box-sizing: border-box; + background: @colortheme_sidebar-left-bg; + overflow: auto; + resize: horizontal; + width: auto; + white-space: nowrap; + max-width: 500px; + min-width: 200px; + padding: 0px; + color: @colortheme_sidebar-left-fg; + display: flex; + flex-flow: column; + max-height: 100%; + .cp-app-drive-tree-categories-container { + flex: 1; + max-width: 500px; + overflow: auto; + } + img.cp-app-drive-icon { + margin-bottom: 3px; + margin-left: -2px; + } + .cp-app-drive-tree-docs { + margin-top: 20px; + //padding: 0 0 0 20px; + padding: 0; + cursor: auto; + &li, li { + padding: 0; + &.cp-app-drive-element-collapsed ul { + display: none; + } + input { + width: ~"calc(100% - 30px)"; + padding: 0 10px; + border: 0; + color: lighten(@colortheme_sidebar-left-fg, 40%); + } + & > span.cp-app-drive-element-row { + overflow: hidden; + text-overflow: ellipsis; + //min-width: ~"calc(100% + 5px)"; + .leftside-menu-category_main(); + width: ~"calc(100% + 5px)"; + margin: 0; + margin-bottom: -6px; + display: inline-block; + cursor: pointer; + margin-left: -5px; + padding-left: 5px; + } + & > span.cp-app-drive-element-row:not(.cp-app-drive-element-selected):not(.cp-app-drive-element-active):hover { + } + } + } + span.cp-app-drive-element { + cursor: pointer; + } + .cp-app-drive-tree-category { + margin: 0; + margin-top: 15px; + .cp-app-drive-tree-root { + &> .fa { + min-width: 30px; + cursor: pointer; + } + } + li { + padding: 0; + .cp-app-drive-element-row { + display: block; + padding-left: 20px; + .leftside-menu-category_main(); + margin: 0; + .fa { + width: 25px; + } + } + } + } + .cp-app-drive-tree-category:last-child { + margin-bottom: 20px; + } + .limit-container { + margin-top: 0; + } + #cp-app-drive-tree-search { + text-align: center; + padding: 0; + position: relative; + input { + background: lighten(@colortheme_drive-bg, 8%); + color: @colortheme_drive-color; + .tools_placeholder-color(@colortheme_drive-color); + outline-width: 0px; + border-radius: 0; + width: 100%; + //border: 1px solid #ccc; + border: 0; + border-right: 1px solid lighten(@colortheme_drive-bg, 16%); + //border-right: 0; + height: @variables_bar-height; + padding: 0 5px; + padding-left: 45px; + &:focus { + outline-width: 0px; + } + } + .cp-app-drive-tree-search-con { + color: @colortheme_drive-color; + position: absolute; + left: 20px; // TODO align with drive categories + top: 8px; + } + } + .fa.cp-app-drive-icon-expcol { + margin-left: -10px; + font-size: 14px; + position: absolute; + left: -20px; + top: 10px; + width: 11px !important; + height: 11px !important; + padding: 0; + margin: 0; + background: white; + z-index: 10; + cursor: default; + &:before { + position:relative; + top: -1px; + } + } + .cp-app-drive-tree-docs { + .cp-app-drive-tree-root > .cp-app-drive-element-row > .cp-app-drive-icon-expcol { + position: relative; + top:0; + left: -10px; + } + .cp-app-drive-tree-root > .cp-app-drive-element-row > .cp-app-drive-icon-folder { + margin-left: -5px; + } + .cp-app-drive-tree-root { + &> .cp-app-drive-element-row { + padding-left: 20px; + } + &> ul { + padding-left: 30px; + } + } + } + + // Expand/collapse lines + .cp-app-drive-tree-docs ul { + margin: 0px 0px 0px 10px; + list-style: none; + padding-left: 10px; + li { + position: relative; + &:before { + position: absolute; + left: -15px; + top: -11px; + content: ''; + display: block; + border-left: 1px solid @colortheme_sidebar-left-branch; + height: ~"calc(1em + 11px)"; + border-bottom: 1px solid @colortheme_sidebar-left-branch; + width: 15px; + } + &:after { + position: absolute; + left: -15px; + bottom: -7px; + content: ''; + display: block; + border-left: 1px solid @colortheme_sidebar-left-branch; + height: 100%; + } + &.cp-app-drive-tree-root { + margin: 0px 0px 0px -10px; + &:before { + display: none; + } + &:after { + display: none; + } + } + &:last-child:after { + display: none; + } + } + } +} + +/* CONTENT */ +#cp-app-drive-content-container { + display: flex; + flex-flow: column; + flex: 1; + // Needed to avoid the folder's path to overflows + // https://stackoverflow.com/questions/38223879/white-space-nowrap-breaks-flexbox-layout + min-width: 0; +} +#cp-app-drive-content { + box-sizing: border-box; + background: @drive_content-bg; + color: @drive_content-fg; + overflow: auto; + flex: 1; + display: flex; + flex-flow: column; + position: relative; + .cp-app-drive-content-select-box { + display: none; + background-color: rgba(100, 100, 100, 0.7); + position: absolute; + z-index: 50; + } + &.cp-app-drive-readonly { + background: @drive_content-bg-ro; + } + h1 { + padding-left: 10px; + margin-top: 10px; + } + .cp-app-drive-content-info-box { + line-height: 2em; + padding: 0.25em 0.75em; + margin: 1em; + background: @drive_info-box-bg; + span { + cursor: pointer; + float: right; + margin-top: 0.5em; + } + } + li { + cursor: default; + &:not(.cp-app-drive-element-header) { + &:hover { + &:not(.-cp-app-drive-element-selected, .cp-app-drive-element-selected-tmp) { + background-color: @drive_hover; + } + } + } + } + #cp-app-drive-content-folder { + li { + &.cp-app-drive-search-result { + border-bottom: 1px solid @drive_info-box-border; + display: block; + &:hover { + background-color: initial; + } + table { + width: 100%; + .cp-app-drive-search-label2 { + width: 150px; + font-size: 15px; + text-align: right; + padding-right: 15px; + } + .cp-app-drive-search-opendir { + a { + cursor: pointer; + color: #41b7d8; + &:hover { + color: #014c8c; + text-decoration: underline; + } + } + } + .cp-app-drive-search-path { + font-style: italic; + direction: rtl; + .cp-app-drive-path-element { + display: inline-block; + margin-right: 5px; + } + } + .cp-app-drive-search-title { + font-weight: bold; + cursor: pointer; + &:hover { + background-color: @drive_hover; + } + } + .cp-app-drive-search-col2 { + width: 250px; + } + td.cp-app-drive-search-icon { + width: 50px; + font-size: 40px; + } + } + } + } + } + .cp-app-drive-element { + .cp-app-drive-element-truncated { display: none; } + } + div.cp-app-drive-content-grid { + padding: 20px; + .drive_fileIcon; + li { + &.cp-app-drive-element { + position: relative; + } + input { + width: 100%; + margin-top: 5px; + } + .cp-app-drive-element-state { + position: absolute; + top: 3px; + right: 3px; + .fa { + margin:0; + font-size: 18px; + } + } + } + .cp-app-drive-element-list { + display: none; + } + .cp-app-drive-new-ghost { + cursor: pointer; + opacity: 0.5; + padding: 0; + &:hover { + opacity: 0.7; + } + .fa { + cursor: pointer; + font-size: 90px; + margin-top: 5px; + margin-bottom: 0; + } + } + } + + .cp-app-drive-content-list { + .cp-app-drive-element-grid { + display: none; + } + // Make it act as a table! + padding-left: 20px; + ul { + display: table; + width: 100%; + padding: 0px 10px; + } + li { + display: table-row; + &> span { + padding: 0 5px; + display: table-cell; + } + &:not(.cp-app-drive-element-header) { + height: @variables_bar-height; + line-height: @variables_bar-height; + } + &.cp-app-drive-element-header { + cursor: default; + color: @drive_table-header-fg; + span { + &:not(.fa) { + text-align: left; + } + &.sortasc, &.sortdesc { + float: right; + } + } + &> span { + padding: 15px 5px; + &.cp-app-drive-sort-active { + font-weight: bold; + } + &.cp-app-drive-sort-clickable { + cursor: pointer; + &:hover { + background: @drive_table-header-bg; + } + } + } + } + } + .cp-app-drive-element { + span { + overflow: hidden; + white-space: nowrap; + box-sizing: border-box; + &.cp-app-drive-element-state { + .fa:not(:last-child) { + margin-right: 5px; + } + } + &.cp-app-drive-content-icon, &.cp-app-drive-element-state { + width: 30px; + } + &.cp-app-drive-element-type, &.cp-app-drive-element-atime, &.cp-app-drive-element-ctime { + width: 175px; + } + &.cp-app-drive-element-title { + width: 250px; + @media screen and (max-width: 1200px) { + display: none; + } + } + &.cp-app-drive-element-folders, &.cp-app-drive-element-files { + width: 150px; + } + } + } + } +} + +#cp-app-drive-content-folder { + padding-right: 10px; + flex: 1; +} + +#cp-app-drive-new-ghost-dialog.cp-modal-container { + .drive_fileIcon; + + li:not(.cp-app-drive-element-selected):hover { + border: 1px solid white; + } + .cp-modal { + display: flex; + flex-flow: column; + li, li .fa { + cursor: pointer; + } + &> p { + margin: 50px; + } + &> div { + display: flex; + flex-wrap: wrap; + justify-content: center; + align-content: center; + overflow-y: auto; + .cp-app-drive-new-upload { + break-after: always; + page-break-after: always; + } + } + } + + @media screen and (max-height: @browser_media-not-big) { + .cp-modal { + & > p { + display: none; + } + & > div { + align-content: unset; + li { + height: 40px; + width: 90%; + display: flex; + align-items: center; + .fa { + font-size: 32px; + } + .cp-app-drive-new-name { + height: auto; + } + } + } + } + } +} + + +/* Toolbar */ + +#cp-app-drive-toolbar { + background: lighten(@colortheme_drive-bg, 8%); + color: @colortheme_drive-color; + //height: 30px; + //display: flex; + //flex-flow: row; + z-index: 100; + box-sizing: border-box; + height: @variables_bar-height; + padding: 0; + display: flex; + flex-flow: row; + + * { + outline-width: 0; + &:focus { + outline-width: 0; + } + } + + .history { + float: right; + .cp-toolbar-drawer-element { + display: none; + } + } + + .cp-app-drive-toolbar-rightside, .cp-app-drive-toolbar-leftside { + display: inline-block; + margin: 0; + padding: 0; + .fa { + margin: 0; + } + button { + height: @variables_bar-height; + padding: 0 10px; + border: none; + border-radius: 0; + box-sizing: border-box; + background: transparent; + font-size: @colortheme_app-font-size; + color: @colortheme_drive-color; + transition: all 0.15s; + .drawer { + display: none; + } + .fa, span { + font-size: @colortheme_app-font-size; + } + &:hover { + background: @colortheme_drive-bg; + } + &.cp-app-drive-toolbar-active { + display: none; + } + } + } + .cp-app-drive-toolbar-rightside { + float: right; + & > * { + float: right; + } + #cp-app-drive-toolbar-contextbuttons { + display: inline-block; + height: 100%; + } + padding-left: 10px; + } + .cp-app-drive-toolbar-leftside { + & > span { + height: 100%; + margin: 0; + } + button { + padding: 0 10px; + .fa { + margin-right: 5px; + } + .cp-dropdown-button-title { + display: inline-flex; + height: @variables_bar-height; + align-items: center; + span:not(.fa) { + line-height: 23px; + } + } + } + } + + button { + font: @colortheme_app-font; + span { + font: @colortheme_app-font; + } + .fa, &.fa { + font-family: FontAwesome; + } + } + /* The container
- needed to position the dropdown content */ + .cp-dropdown-container { + margin: 2px 2px; + line-height: 1em; + position: relative; + display: inline-block; + } + .cp-dropdown-content { + margin-right: 2px; + } + + .cp-app-drive-path { + flex: 1; + width: 100%; + height: @variables_bar-height; + line-height: @variables_bar-height; + cursor: default; + width: auto; + overflow: hidden; + white-space: nowrap; + direction: rtl; + max-width: 100%; + text-align: left; + .cp-app-drive-path-element { + display: inline-block; + height: @variables_bar-height; + line-height: @variables_bar-height; + font-size: @colortheme_app-font-size; + padding: 0 5px; + border: 0; + background: darken(@colortheme_drive-bg, 10%); + color: @colortheme_drive-color; + box-sizing: border-box; + transition: all 0.15s; + &.cp-app-drive-path-separator { + color: #ccc; + } + &.cp-app-drive-path-lickable { + cursor: pointer; + &:hover { + background: darken(@colortheme_drive-bg, 15%); + } + } + } + } +} + + + diff --git a/www/poll/app-poll.less b/www/poll/app-poll.less new file mode 100644 index 000000000..fd751249d --- /dev/null +++ b/www/poll/app-poll.less @@ -0,0 +1,477 @@ +@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'; + +.toolbar_main(); +.fileupload_main(); +.alertify_main(); +.tokenfield_main(); + +@poll-fore: #555; +@poll-th-bg: #aaa; +@poll-th-user-bg: #999; +@poll-td-bg: #aaa; +@poll-editing: #88b8cc; +@poll-placeholder: #666; +@poll-border-color: #555; +@poll-cover-color: #000; +@poll-fg: #000; +@poll-option-yellow: #ff5; +@poll-option-gray: #ccc; + +.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-poll-content { + display: flex; + flex: 1; + #cp-app-poll-form { + flex: 1; + overflow-y: auto; + } +} + +/*.cp-toolbar-container h2 { + font: normal normal normal 12px Arial, Helvetica, Tahoma, Verdana, Sans-Serif; + color: #000; + line-height: auto; +} +.cp-toolbar-container { + display: block; +}*/ + +.cp-app-poll-table-text-cell input[type="text"] { + width: 400px; +} + +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"]::placeholder { + color: @poll-placeholder; +} + +table#cp-app-poll-table { + margin: 0px; +} +#cp-app-poll-table-container { + position: relative; + padding: 29px; + padding-right: 79px; +} +#cp-app-poll-table-container button { + height: 2rem; + display: none; +} +#cp-app-poll-publish { + display: none; +} +#cp-app-poll-action-publish, #cp-app-poll-action-admin { + margin-top: 15px; + margin-bottom: 15px; +} +#cp-app-poll-create-user { + position: absolute; + display: inline-block; + /*left: 0px;*/ + top: 55px; + width: 50px; + overflow: hidden; +} +#cp-app-poll-create-option { + width: 50px; +} +#cp-app-poll-table-scroll { + overflow-y: hidden; + overflow-x: auto; + margin-left: calc(~"30% - 50px + 31px"); + max-width: 70%; + width: auto; + display: inline-block; +} +#cp-app-poll-description { + padding: 15px; + margin: auto; + + min-width: 80%; + width: 80%; + min-height: 7em; + font-size: 20px; + font-weight: bold; + border: 1px solid black; + +} +#cp-app-poll-description[disabled] { + resize: none; + color: #000; + border: 1px solid #444; +} + +#cp-app-poll-help { + width: 80%; + margin: auto; +} +div.cp-app-poll-upper { + width: 80%; + margin: auto; + + & > * { + margin-right: 1em; + } +} + +// from cryptpad.less + +table { + border-collapse: collapse; + border-spacing: 0; + margin: 20px; +} +tbody { + border: 1px solid @poll-border-color; + * { + box-sizing: border-box; + } + tr { + text-align: center; + &:first-of-type th{ + font-size: 20px; + border-top: 0px; + font-weight: bold; + padding: 10px; + text-decoration: underline; + &.table-refresh { + color: @colortheme_cp-green; + text-decoration: none; + cursor: pointer; + } + + } + &:nth-child(odd) { + background-color: @colortheme_light-base; + } + th:first-of-type { + border-left: 0px; + } + th { + box-sizing: border-box; + border: 1px solid @poll-border-color; + } + th, td { + color: @poll-fore; + + .cp-app-poll-table-remove { + cursor: pointer; + } + } + th:last-child { + border-right: 0px; + } + } + + td { + border-right: 1px solid @poll-border-color; + padding: 12px; + padding-top: 0px; + padding-bottom: 0px; + &:last-child { + border-right: none; + } + } +} + +div.cp-app-poll-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; + + table { + border-collapse: collapse; + width: ~"calc(100% - 1px)"; + .cp-app-poll-table-editing { + background-color: @poll-editing; + } + tr { + td:first-child { + position:absolute; + left: 29px; + top: auto; + width: ~"calc(30% - 50px)"; + } + td { + padding: 0px; + margin: 0px; + + div.cp-app-poll-table-text-cell { + padding: 0px; + margin: 0px; + height: 100%; + + input { + width: 80%; + width: 90%; + height: 100%; + border: 0px; + &[disabled] { + background-color: transparent; + color: @poll-fg; + font-weight: bold; + } + } + } + + &.cp-app-poll-table-checkbox-cell { + margin: 0px; + padding: 0px; + height: 100%; + min-width: 150px; + + div.cp-app-poll-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-poll-table-cover { + display: block; + font-weight: bold; + + color: @poll-cover-color; + + &:after { + height: 100%; + } + + display: block; + &.yes { + background-color: @colortheme_cp-green; + } + + &.uncommitted { + background: #ddd; + } + + &.mine { + display: none; + } + } + } + } + } + + input[type="number"][value="0"] { + ~ .cp-app-poll-table-cover { + background-color: @colortheme_cp-red; + &:after { content: "✖"; } + } + } + input[type="number"][value="1"] { + ~ .cp-app-poll-table-cover { + background-color: @colortheme_cp-green; + &:after { content: "✔"; } + } + } + input[type="number"][value="2"] { + ~ .cp-app-poll-table-cover { + background-color: @poll-option-yellow; + &:after { content: "~"; } + } + } + input[type="number"][value="3"] { + ~ .cp-app-poll-table-cover { + background-color: @poll-option-gray; + &:after { content: "?"; } + } + } + } + } + } + } + + input { + &[type="text"] { + height: auto; + width: 80%; + } + } + span { + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; + } + thead { + td { + padding: 0px 5px; + background: @poll-th-bg; + border-radius: 20px 20px 0 0; + //text-align: center; + &:nth-of-type(2) { + background: @poll-th-user-bg; + .cp-app-poll-table-lock { + cursor: default; + } + } + input { + &[type="text"] { + width: 100%; + box-sizing: border-box; + padding: 1px 5px; + &[disabled] { + color: @poll-fg; + border: 1px solid transparent; + } + } + } + } + } + + tbody { + td:not(.cp-app-poll-table-editing) { + .cp-app-poll-table-text-cell { + background: @poll-td-bg; + } + } + .cp-app-poll-table-text-cell { + //border-radius: 20px 0 0 20px; + input[type="text"] { + width: ~"calc(100% - 50px)"; + padding: 0 0.5em; + } + .cp-app-poll-table-edit { + float:right; + margin: 0 10px 0 0; + } + .cp-app-poll-table-remove { + float: left; + margin: 0 0 0 10px; + } + } + tr:not(:first-child) { + td:not(:first-child) { + label { + border-top: 1px solid @poll-border-color; + } + } + } + } + .cp-app-poll-table-edit { + color: @poll-cover-color; + cursor: pointer; + float: left; + margin-left: 10px; + } + + .cp-app-poll-table-lock { + margin-left: ~"calc(50% - 0.5em)"; + cursor: pointer; + width: 1em; + text-align: center; + } + .cp-app-poll-table-remove { + float: right; + margin-right: 10px; + } + + thead { + tr { + th { + input[type="text"][disabled] { + background-color: transparent; + color: @poll-fore; + font-weight: bold; + } + .cp-app-poll-table-remove { + cursor: pointer; + font-size: 20px; + } + } + } + } + tbody { + tr { + td { + + } + } + } + tfoot { + tr { + border: none; + td { + border: none; + text-align: center; + .save { + padding: 15px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + } + } + } + } + } + + #adduser, + #addoption { + color: @colortheme_cp-green; + border: 1px solid @colortheme_cp-green; + padding: 15px; + cursor: pointer; + } + + #adduser { .top-left; } + #addoption { .bottom-left; } +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; +} + diff --git a/www/poll/index.html b/www/poll/index.html new file mode 100644 index 000000000..e3f7eacc4 --- /dev/null +++ b/www/poll/index.html @@ -0,0 +1,38 @@ + + + + CryptPad + + + + + + + +'; From 5cf86bf74ab1f069888a29d7bf75ad9783856ae7 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 3 Oct 2017 14:11:11 +0200 Subject: [PATCH 05/20] Update UI in poll and remove old code --- customize.dist/pages.js | 19 +- customize.dist/translations/messages.fr.js | 4 + customize.dist/translations/messages.js | 4 + www/common/sframe-common-outer.js | 1 + www/poll/app-poll.less | 30 ++-- www/poll/inner.js | 199 ++++++++------------- www/poll/main.js | 2 +- www/poll/render.js | 2 +- 8 files changed, 100 insertions(+), 161 deletions(-) diff --git a/customize.dist/pages.js b/customize.dist/pages.js index 2427b2a28..5bf87b928 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -570,15 +570,12 @@ define([ }; var appToolbar = function () { - return h('div#toolbar.cryptpad-toolbar'); - }; - var appToolbar3 = function () { return h('div#cp-toolbar.cp-toolbar-container'); }; Pages['/whiteboard/'] = Pages['/whiteboard/index.html'] = function () { return [ - appToolbar3(), + appToolbar(), h('div#cp-app-whiteboard-canvas-area', h('canvas#cp-app-whiteboard-canvas', { width: 600, height: 600 @@ -638,7 +635,7 @@ define([ Pages['/poll/'] = Pages['/poll/index.html'] = function () { return [ - appToolbar3(), + appToolbar(), h('div#cp-app-poll-content', [ h('div#cp-app-poll-form', [ h('div#cp-app-poll-help', [ @@ -647,18 +644,6 @@ define([ h('p', Msg.poll_p_save), h('p', Msg.poll_p_encryption) ]), - h('div.cp-app-poll-upper', [ - h('button#cp-app-poll-action-publish.btn.btn-success', { - style: { display: 'none' } - }, Msg.poll_publish_button), - h('button#cp-app-poll-action-admin.btn.btn-primary', { - style: { display: 'none' }, - title: Msg.poll_admin_button - }, Msg.poll_admin_button), - h('button#cp-app-poll-action-help.btn.btn-secondary', { - title: Msg.poll_show_help_button - }, Msg.poll_show_help_button) - ]), h('div.cp-app-poll-realtime', [ h('br'), h('center', [ diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index 118eb6f7b..fb04d7bc0 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -256,6 +256,10 @@ define(function () { out.poll_show_help_button = "Afficher l'aide"; out.poll_hide_help_button = "Cacher l'aide"; + out.poll_bookmark_col = "Marquer cette colonne comme favorite pour qu'elle soit toujours déverouillée et affichée en première position."; + out.poll_bookmarked_col = "Voici votre colonne favorite; elle sera toujours dévérouillée et affichée en première position."; + out.poll_total = 'TOTAL'; + // Canvas out.canvas_clear = "Nettoyer"; out.canvas_delete = "Supprimer la sélection"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index fc7c204d9..755c52a53 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -258,6 +258,10 @@ define(function () { out.poll_show_help_button = "Show help"; out.poll_hide_help_button = "Hide help"; + out.poll_bookmark_col = 'Bookmark this column so that it is always unlocked and displayed at the beginning for you'; + out.poll_bookmarked_col = 'This is your bookmarked column. It will always be unlocked and displayed at the beginning for you.'; + out.poll_total = 'TOTAL'; + // Canvas out.canvas_clear = "Clear"; out.canvas_delete = "Delete selection"; diff --git a/www/common/sframe-common-outer.js b/www/common/sframe-common-outer.js index f50bc1de2..878b355f0 100644 --- a/www/common/sframe-common-outer.js +++ b/www/common/sframe-common-outer.js @@ -62,6 +62,7 @@ define([ Cryptpad.ready(waitFor()); })); }).nThen(function (waitFor) { + $('#sbox-iframe').focus(); sframeChan.on('EV_CACHE_PUT', function (x) { Object.keys(x).forEach(function (k) { diff --git a/www/poll/app-poll.less b/www/poll/app-poll.less index 8960d1094..7714e5538 100644 --- a/www/poll/app-poll.less +++ b/www/poll/app-poll.less @@ -4,6 +4,7 @@ @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'; .toolbar_main(); .fileupload_main(); @@ -93,13 +94,6 @@ table#cp-app-poll-table { border-radius: 0; border: 0; } -#cp-app-poll-publish { - display: none; -} -#cp-app-poll-action-publish, #cp-app-poll-action-admin { - margin-top: 15px; - margin-bottom: 15px; -} #cp-app-poll-create-user { display: inline-flex; height: 24px; @@ -128,29 +122,24 @@ table#cp-app-poll-table { min-width: 80%; width: 80%; min-height: 7em; - font-size: 20px; - font-weight: bold; + font: @colortheme_app-font; + //font-size: 20px; + /*font-weight: bold;*/ border: 1px solid black; } #cp-app-poll-description[disabled] { resize: none; color: #000; - border: 1px solid #444; + border: 1px solid transparent; + background-color: #eeeeee; + font: @colortheme_app-font; } #cp-app-poll-help { width: 80%; margin: auto; } -div.cp-app-poll-upper { - width: 80%; - margin: auto; - - & > * { - margin-right: 1em; - } -} // from cryptpad.less @@ -169,6 +158,7 @@ tbody { } td { + .tools_unselectable(); border-right: 1px solid @poll-border-color; padding: 12px; padding-top: 0px; @@ -274,7 +264,7 @@ div.cp-app-poll-realtime { margin: 0px; padding: 0px; height: 100%; - min-width: 150px; + min-width: 100px; div.cp-app-poll-table-checkbox-contain { display: inline-block; @@ -387,6 +377,8 @@ div.cp-app-poll-realtime { } input { &[type="text"] { + overflow: hidden; + text-overflow: ellipsis; break-after: always; width: ~"calc(100% - 2px)"; // borders... box-sizing: border-box; diff --git a/www/poll/inner.js b/www/poll/inner.js index 57916294e..18eefacd4 100644 --- a/www/poll/inner.js +++ b/www/poll/inner.js @@ -2,7 +2,6 @@ define([ 'jquery', '/bower_components/textpatcher/TextPatcher.js', '/common/toolbar3.js', - 'json.sortify', '/common/cryptpad-common.js', '/common/common-util.js', '/common/cryptget.js', @@ -23,7 +22,6 @@ define([ $, TextPatcher, Toolbar, - JSONSortify, Cryptpad, Util, Cryptget, @@ -51,36 +49,16 @@ define([ var debug = $.noop; //console.log; - var stringify = function (obj) { - return JSONSortify(obj); - }; - - var onConnectError = function () { - Cryptpad.errorLoadingScreen(Messages.websocketError); - }; - var HIDE_INTRODUCTION_TEXT = "hide-text"; var metadataMgr; var Title; - var defaultName; var common; - var readOnly; - - - - - - - - var copyObject = function (obj) { return JSON.parse(JSON.stringify(obj)); }; - - /* Make sure that the realtime data structure has all the required fields */ @@ -102,8 +80,9 @@ define([ proxy.type = 'poll'; }; - - + /* + Set the user id (user column) in the pad attributes + */ var setUserId = function (id, cb) { cb =cb || $.noop; APP.userid = id; @@ -128,8 +107,11 @@ define([ }; var isUncommitted = function (id) { - return APP.uncommitted.content.colsOrder.indexOf(id) !== -1 || - APP.uncommitted.content.rowsOrder.indexOf(id) !== -1; + var idArr = id.split('_'); + var idx = idArr[0]; + var idy = idArr[1] || idArr[0]; // if id is y-{...} (no 'x'), use idArr[0] as 'y' coordinate + return APP.uncommitted.content.colsOrder.indexOf(idx) !== -1 || + APP.uncommitted.content.rowsOrder.indexOf(idy) !== -1; }; var mergeUncommitted = function (proxy, uncommitted, commit) { @@ -175,10 +157,9 @@ define([ return newObj; }; - var styleUncommittedColumn = function () { + var styleUserColumn = function () { var userid = APP.userid; - // TODO: move? // Enable input for the userid column $('input[disabled="disabled"][data-rt-id^="' + userid + '"]').removeAttr('disabled') .attr('placeholder', Messages.poll_userPlaceholder); @@ -188,10 +169,9 @@ define([ .addClass("cp-app-poll-table-own"); $('.cp-app-poll-table-bookmark[data-rt-id="' + userid + '"]').css('visibility', '') .removeClass('fa-bookmark-o').addClass('fa-bookmark') - .attr('title', 'TODO: this is your bookmarked column. It will always be unlocked and displayed at the beginning for you'); - //.addClass('fa-unlock').removeClass('fa-lock').attr('title', Messages.poll_unlocked); - //$('.cp-app-poll-table-remove[data-rt-id="' + userid + '"]').remove(); - + .attr('title', Messages.poll_bookmarked_col); + }; + var styleUncommittedColumn = function () { var $scroll = $('#cp-app-poll-table-scroll'); var hasScroll = $scroll.width() < $scroll[0].scrollWidth; APP.uncommitted.content.colsOrder.forEach(function(id) { @@ -222,7 +202,6 @@ define([ //$('.uncommitted input[type="text"]').attr("placeholder", Messages.poll_userPlaceholder); }); }; - var unlockElements = function () { APP.unlocked.row.forEach(function (id) { var $input = $('input[type="text"][disabled="disabled"][data-rt-id="' + id + '"]').removeAttr('disabled'); @@ -238,7 +217,6 @@ define([ .removeClass('fa-lock').attr('title', Messages.poll_unlocked); }); }; - var updateTableButtons = function () { var uncomColId = APP.uncommitted.content.colsOrder[0]; var uncomRowId = APP.uncommitted.content.rowsOrder[0]; @@ -264,7 +242,6 @@ define([ //$('#create-user').css('left', width + 30 + 'px'); } }; - var setTablePublished = function (bool) { if (bool) { if (APP.$publish) { APP.$publish.hide(); } @@ -276,7 +253,6 @@ define([ $('#cp-app-poll-form').removeClass('cp-app-poll-published'); } }; - var addCount = function () { var $scroll = $('#cp-app-poll-table-scroll'); var hasScroll = $scroll.width() < $scroll[0].scrollWidth; @@ -292,7 +268,7 @@ define([ 'text-align': 'center', 'line-height': $thead.height()+'px' }) - .text('TOTAL'); // TODO + .text(Messages.poll_total); var winner = { v: 0, ids: [] @@ -322,16 +298,12 @@ define([ }; var updateDisplayedTable = function () { + styleUserColumn(); styleUncommittedColumn(); unlockElements(); updateTableButtons(); setTablePublished(APP.proxy.published); addCount(); - - /* - APP.proxy.table.rowsOrder.forEach(function (rowId) { - $('[data-rt-id="' + rowId +'"]').val(APP.proxy.table.rows[rowId] || ''); - });*/ }; var unlockColumn = function (id, cb) { @@ -386,7 +358,7 @@ define([ var colsOrder = sortColumns(displayedObj.content.colsOrder, APP.userid); var conf = { cols: colsOrder, - readOnly: readOnly + readOnly: APP.readOnly }; common.notify(); @@ -530,7 +502,6 @@ define([ }); }); } else if (isEdit) { - //hideInputs(span); unlockRow(id, function () { change(null, null, null, null, function() { $('input[data-rt-id="' + id + '"]').focus(); @@ -546,10 +517,8 @@ define([ }); }); } else if (isBookmark) { - //hideInputs(span); handleBookmark(id); } else if (isLock && isLocked) { - //hideInputs(span); unlockColumn(id, function () { change(null, null, null, null, function() { $('input[data-rt-id="' + id + '"]').focus(); @@ -581,12 +550,6 @@ define([ if (!target) { return void debug("NO TARGET"); } var nodeName = target && target.nodeName; - //var shouldLock = $(target).hasClass('fa-unlock'); - - /*if ((!$(target).parents('#cp-app-poll-table tbody').length && - $(target).hasClass('cp-app-poll-table-lock'))) { - //hideInputs(e); - }*/ switch (nodeName) { case 'INPUT': @@ -619,9 +582,6 @@ define([ handleInput(input[0]); break; case 'SPAN': - /*if (shouldLock) { - break; - }*/ handleSpan(target); break; case undefined: @@ -636,17 +596,45 @@ define([ /* */ + var updatePublishButton = function () { + if (!APP.ready || !APP.proxy || !APP.$publishButton) { return; } + var p = APP.proxy.published; + var msg = (p ? Messages.poll_admin_button : Messages.poll_publish_button); + APP.$publishButton.attr('title', msg); + if (p) { + APP.$publishButton.removeClass('fa-check').addClass('fa-pencil'); + return; + } + APP.$publishButton.addClass('fa-check').removeClass('fa-pencil'); + }; var publish = APP.publish = function (bool) { - if (!APP.ready) { return; } - if (APP.proxy.published !== bool) { - APP.proxy.published = bool; + if (!APP.readOnly) { + if (!APP.ready) { return; } + if (APP.proxy.published !== bool) { + APP.proxy.published = bool; + } + } else { + // If readOnly, always put the app in published mode + bool = true; } setTablePublished(bool); ['textarea'].forEach(function (sel) { $(sel).attr('disabled', bool); }); + updatePublishButton(); }; + var updateHelpButton = function () { + if (!APP.$helpButton) { return; } + var help = $('#cp-app-poll-help').is(':visible'); + var msg = (help ? Messages.poll_hide_help_button : Messages.poll_show_help_button); + APP.$helpButton.attr('title', msg); + if (help) { + APP.$helpButton.addClass('cp-toolbar-button-active'); + return; + } + APP.$helpButton.removeClass('cp-toolbar-button-active'); + }; var showHelp = function(help) { if (typeof help === 'undefined') { help = !$('#cp-app-poll-help').is(':visible'); @@ -656,22 +644,9 @@ define([ $('#cp-app-poll-help').toggle(help); $('#cp-app-poll-action-help').text(msg); + updateHelpButton(); }; - - - - - - - - - - - - - - var setEditable = function (editable) { APP.readOnly = !editable; @@ -710,7 +685,7 @@ define([ APP.proxy.description = n; }; - var onReady = function (info, userid, readOnly) { + var onReady = function (info, userid) { var proxy = APP.proxy; var isNew = false; @@ -750,7 +725,7 @@ define([ var uncommitted = APP.uncommitted = {}; prepareProxy(proxy, copyObject(Render.Example)); prepareProxy(uncommitted, copyObject(Render.Example)); - if (!readOnly) { + if (!APP.readOnly) { var coluid = Render.coluid(); if (proxy.content.colsOrder.indexOf(userid) === -1 && uncommitted.content.colsOrder.indexOf(userid) === -1) { @@ -772,7 +747,7 @@ define([ var colsOrder = sortColumns(displayedObj.content.colsOrder, userid); - var $table = APP.$table = $(Render.asHTML(displayedObj, null, colsOrder, readOnly)); + var $table = APP.$table = $(Render.asHTML(displayedObj, null, colsOrder, APP.readOnly)); var getUncommitted = function (type) { var ret = {}, toRemove; @@ -830,23 +805,7 @@ define([ }); }); - // #publish button is removed in readonly - APP.$publish = $('#cp-app-poll-action-publish') - .click(function () { - publish(true); - }); - - APP.$admin = $('#cp-app-poll-action-admin') - .click(function () { - publish(false); - }); - - APP.$help = $('#cp-app-poll-action-help') - .click(function () { - showHelp(); - }); - - if (!readOnly) { + if (!APP.readOnly) { setUserId(userid); } @@ -899,19 +858,18 @@ define([ } Cryptpad.removeLoadingScreen(); + if (isNew) { + common.openTemplatePicker(); + } }; var onDisconnect = function () { setEditable(false); - // TODO toolar.failed? - APP.toolbar.failed(); Cryptpad.alert(Messages.common_connectionLost, undefined, true); }; - var onReconnect = function (info) { + var onReconnect = function () { setEditable(true); - // TODO: reconnecting?? - APP.toolbar.reconnecting(info.myId); Cryptpad.findOKButton().click(); }; @@ -934,14 +892,14 @@ define([ displayed: ['title', 'useradmin', 'spinner', 'share', 'userlist', 'newpad', 'limit'], title: Title.getTitleConfig(), metadataMgr: metadataMgr, - readOnly: readOnly, + readOnly: APP.readOnly, realtime: info.realtime, common: Cryptpad, sfCommon: common, $container: APP.$bar, $contentContainer: APP.$content }; - var toolbar = APP.toolbar = Toolbar.create(configTb); + APP.toolbar = Toolbar.create(configTb); Title.setToolbar(APP.toolbar); @@ -951,32 +909,35 @@ define([ var md = copyObject(metadataMgr.getMetadata()); APP.proxy.metadata = md; }); - return; // TODO - - - /* add a forget button */ var forgetCb = function (err) { if (err) { return; } setEditable(false); }; - var $forgetPad = Cryptpad.createButton('forget', true, {}, forgetCb); + var $forgetPad = common.createButton('forget', true, {}, forgetCb); $rightside.append($forgetPad); - // set the hash - if (!readOnly) { Cryptpad.replaceHash(editHash); } - /* save as template */ - if (!Cryptpad.isTemplate(window.location.href)) { + if (!metadataMgr.getPrivateData().isTemplate) { var templateObj = { rt: info.realtime, - Crypt: Cryptget, - getTitle: function () { return document.title; } + getTitle: function () { return metadataMgr.getMetadata().title; } }; - var $templateButton = Cryptpad.createButton('template', true, templateObj); + var $templateButton = common.createButton('template', true, templateObj); $rightside.append($templateButton); } + + var $help = common.createButton().click(function () { showHelp(); }).appendTo($rightside); + APP.$helpButton = $help; + updateHelpButton(); + + if (APP.readOnly) { publish(true); return; } + var $publish = common.createButton() + .removeClass('fa-question').addClass('fa-check') + .click(function () { publish(!APP.proxy.published); }).appendTo($rightside); + APP.$publishButton = $publish; + updatePublishButton(); }; @@ -998,7 +959,7 @@ define([ } metadataMgr.onChange(function () { if (typeof(metadataMgr.getPrivateData().readOnly) === 'boolean') { - readOnly = metadataMgr.getPrivateData().readOnly; + APP.readOnly = metadataMgr.getPrivateData().readOnly; privReady(); } }); @@ -1018,11 +979,10 @@ define([ logLevel: 1 }; - if (readOnly) { - $('#cp-app-poll-create-user, #cp-app-poll-create-option, #cp-app-poll-action-publish, #cp-app-poll-action-admin').remove(); + if (APP.readOnly) { + $('#cp-app-poll-create-user, #cp-app-poll-create-option').remove(); } - var metadataMgr; var rt = APP.rt = Listmap.create(listmapConfig); APP.proxy = rt.proxy; @@ -1032,7 +992,7 @@ define([ if (e) { console.error(e); } if (!userid) { userid = Render.coluid(); } APP.userid = userid; - onReady(info, userid, readOnly); + onReady(info, userid); }); }) .on('disconnect', onDisconnect) @@ -1049,13 +1009,6 @@ define([ showHelp(false); } }); - - /*Cryptpad.onError(function (info) { - if (info && info.type === "store") { - onConnectError(); - } - });*/ - //Cryptpad.onLogout(function () { setEditable(false); }); }); }; main(); diff --git a/www/poll/main.js b/www/poll/main.js index 66493ef48..04c9b8f2f 100644 --- a/www/poll/main.js +++ b/www/poll/main.js @@ -5,7 +5,7 @@ define([ 'jquery', '/common/requireconfig.js', '/common/sframe-common-outer.js', -], function (nThen, ApiConfig, $, RequireConfig, SFCommonO, Cryptpad, Netflux) { +], function (nThen, ApiConfig, $, RequireConfig, SFCommonO) { var requireConfig = RequireConfig(); // Loaded in load #2 diff --git a/www/poll/render.js b/www/poll/render.js index c9f6f7c1f..cbf6bf2ca 100644 --- a/www/poll/render.js +++ b/www/poll/render.js @@ -287,7 +287,7 @@ var Renderer = function (Cryptpad) { var makeBookmarkElement = Render.makeBookmarkElement = function (id) { return ['SPAN', { 'data-rt-id': id, - 'title': 'TODO: Bookmark this column so that it is always unlocked and displayed at the beginning for you.', + 'title': Cryptpad.Messages.poll_bookmark_col, 'style': 'visibility: hidden;', class: 'cp-app-poll-table-bookmark fa fa-bookmark-o', }, []]; From 707d3b3e94269f831806364bc644dc89f187061f Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 3 Oct 2017 16:50:59 +0200 Subject: [PATCH 06/20] Ability to export polls as csv --- www/poll/app-poll.less | 11 ++++--- www/poll/inner.js | 67 ++++++++++++++++++++++++++++++++++++++++-- www/poll/render.js | 2 +- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/www/poll/app-poll.less b/www/poll/app-poll.less index 7714e5538..f310acf9f 100644 --- a/www/poll/app-poll.less +++ b/www/poll/app-poll.less @@ -341,10 +341,7 @@ div.cp-app-poll-realtime { } } span { - user-select: none; - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; + .tools_unselectable(); } thead { td { @@ -374,6 +371,12 @@ div.cp-app-poll-realtime { width: 1em; text-align: center; } + .cp-app-poll-table-bookmark { + color: darken(@poll-th-fg, 30%); + &.cp-app-poll-table-bookmark-full { + color: @poll-th-fg; + } + } } input { &[type="text"] { diff --git a/www/poll/inner.js b/www/poll/inner.js index 18eefacd4..d8610ae9e 100644 --- a/www/poll/inner.js +++ b/www/poll/inner.js @@ -34,6 +34,7 @@ define([ Renderer) { var Messages = Cryptpad.Messages; + var saveAs = window.saveAs; var Render = Renderer(Cryptpad); var APP = window.APP = { @@ -59,6 +60,59 @@ define([ return JSON.parse(JSON.stringify(obj)); }; + var getCSV = APP.getCSV = function () { + if (!APP.proxy) { return; } + var data = copyObject(APP.proxy.content); + var res = ''; + + var escapeStr = function (str) { + return '"' + str.replace(/"/g, '""') + '"'; + }; + + [null].concat(data.rowsOrder).forEach(function (rowId, i) { + [null].concat(data.colsOrder).forEach(function (colId, j) { + // thead + if (i === 0) { + if (j === 0) { res += ','; return; } + if (!colId) { throw new Error("Invalid data"); } + res += escapeStr(data.cols[colId] || Messages.anonymous) + ','; + return; + } + // tbody + if (!rowId) { throw new Error("Invalid data"); } + if (j === 0) { + res += escapeStr(data.rows[rowId] || Messages.poll_optionPlaceholder) + ','; + return; + } + if (!colId) { throw new Error("Invalid data"); } + res += (data.cells[colId + '_' + rowId] || 3) + ','; + }); + // last column: total + // thead + if (i === 0) { + res += escapeStr(Messages.poll_total) + '\n'; + return; + } + // tbody + if (!rowId) { throw new Error("Invalid data"); } + res += APP.count[rowId] || '?'; + res += '\n'; + }); + + return res; + }; + var exportFile = function () { + var csv = getCSV(); + var suggestion = Title.suggestTitle(Title.defaultTitle); + Cryptpad.prompt(Messages.exportPrompt, + Cryptpad.fixFileName(suggestion) + '.csv', function (filename) { + if (!(typeof(filename) === 'string' && filename)) { return; } + var blob = new Blob([csv], {type: "application/csv;charset=utf-8"}); + saveAs(blob, filename); + }); + }; + + /* Make sure that the realtime data structure has all the required fields */ @@ -168,7 +222,7 @@ define([ $('[data-rt-id^="' + userid + '"]').closest('td') .addClass("cp-app-poll-table-own"); $('.cp-app-poll-table-bookmark[data-rt-id="' + userid + '"]').css('visibility', '') - .removeClass('fa-bookmark-o').addClass('fa-bookmark') + .addClass('cp-app-poll-table-bookmark-full') .attr('title', Messages.poll_bookmarked_col); }; var styleUncommittedColumn = function () { @@ -273,6 +327,7 @@ define([ v: 0, ids: [] }; + APP.count = {}; APP.proxy.content.rowsOrder.forEach(function (rId) { var count = Object.keys(APP.proxy.content.cells) .filter(function (k) { @@ -284,6 +339,7 @@ define([ } else if (count && count === winner.v) { winner.ids.push(rId); } + APP.count[rId] = count; APP.$table.find('[data-rt-count-id="' + rId + '"]') .text(count) .css({ @@ -928,12 +984,17 @@ define([ $rightside.append($templateButton); } - var $help = common.createButton().click(function () { showHelp(); }).appendTo($rightside); + /* add an export button */ + var $export = common.createButton('export', true, {}, exportFile); + $rightside.append($export); + + var $help = common.createButton('', true).click(function () { showHelp(); }) + .appendTo($rightside); APP.$helpButton = $help; updateHelpButton(); if (APP.readOnly) { publish(true); return; } - var $publish = common.createButton() + var $publish = common.createButton('', true) .removeClass('fa-question').addClass('fa-check') .click(function () { publish(!APP.proxy.published); }).appendTo($rightside); APP.$publishButton = $publish; diff --git a/www/poll/render.js b/www/poll/render.js index cbf6bf2ca..5428535ac 100644 --- a/www/poll/render.js +++ b/www/poll/render.js @@ -289,7 +289,7 @@ var Renderer = function (Cryptpad) { 'data-rt-id': id, 'title': Cryptpad.Messages.poll_bookmark_col, 'style': 'visibility: hidden;', - class: 'cp-app-poll-table-bookmark fa fa-bookmark-o', + class: 'cp-app-poll-table-bookmark fa fa-thumb-tack', }, []]; }; From 68bda922911c303a497b8ec6c04cb1f1b4859474 Mon Sep 17 00:00:00 2001 From: yflory Date: Tue, 3 Oct 2017 19:04:29 +0200 Subject: [PATCH 07/20] Use codemirror for description in poll --- customize.dist/pages.js | 3 +- www/common/metadata-manager.js | 1 - www/common/sframe-common-codemirror.js | 102 +++++++++++++------------ www/common/sframe-common-title.js | 1 - www/poll/app-poll.less | 39 +++++++--- www/poll/inner.js | 62 ++++++++------- 6 files changed, 120 insertions(+), 88 deletions(-) diff --git a/customize.dist/pages.js b/customize.dist/pages.js index 5bf87b928..b944e2624 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -646,12 +646,13 @@ define([ ]), h('div.cp-app-poll-realtime', [ h('br'), - h('center', [ + h('div', [ h('textarea#cp-app-poll-description', { rows: "5", cols: "50", disabled: true }), + h('div#cp-app-poll-description-published'), h('br') ]), h('div#cp-app-poll-table-container', [ diff --git a/www/common/metadata-manager.js b/www/common/metadata-manager.js index e319c3ecb..1c8994d00 100644 --- a/www/common/metadata-manager.js +++ b/www/common/metadata-manager.js @@ -68,7 +68,6 @@ define(['json.sortify'], function (Sortify) { }; var change = function (lazy) { dirty = true; - console.error('METADATA CHANGE CALLED'); setTimeout(function () { checkUpdate(lazy); }); diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index 6686a9a55..098972161 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -9,6 +9,58 @@ define([ var saveAs = window.saveAs; var module = {}; + var cursorToPos = function(cursor, oldText) { + var cLine = cursor.line; + var cCh = cursor.ch; + var pos = 0; + var textLines = oldText.split("\n"); + for (var line = 0; line <= cLine; line++) { + if(line < cLine) { + pos += textLines[line].length+1; + } + else if(line === cLine) { + pos += cCh; + } + } + return pos; + }; + + var posToCursor = function(position, newText) { + var cursor = { + line: 0, + ch: 0 + }; + var textLines = newText.substr(0, position).split("\n"); + cursor.line = textLines.length - 1; + cursor.ch = textLines[cursor.line].length; + return cursor; + }; + + module.setValueAndCursor = function (editor, oldDoc, remoteDoc, TextPatcher) { + var scroll = editor.getScrollInfo(); + //get old cursor here + var oldCursor = {}; + oldCursor.selectionStart = cursorToPos(editor.getCursor('from'), oldDoc); + oldCursor.selectionEnd = cursorToPos(editor.getCursor('to'), oldDoc); + + editor.setValue(remoteDoc); + editor.save(); + + var op = TextPatcher.diff(oldDoc, remoteDoc); + var selects = ['selectionStart', 'selectionEnd'].map(function (attr) { + return TextPatcher.transformCursor(oldCursor[attr], op); + }); + + if(selects[0] === selects[1]) { + editor.setCursor(posToCursor(selects[0], remoteDoc)); + } + else { + editor.setSelection(posToCursor(selects[0], remoteDoc), posToCursor(selects[1], remoteDoc)); + } + + editor.scrollTo(scroll.left, scroll.top); + }; + module.create = function (Common, defaultMode, CMeditor) { var exp = {}; var Messages = Cryptpad.Messages; @@ -253,56 +305,8 @@ define([ onLocal(); }; - var cursorToPos = function(cursor, oldText) { - var cLine = cursor.line; - var cCh = cursor.ch; - var pos = 0; - var textLines = oldText.split("\n"); - for (var line = 0; line <= cLine; line++) { - if(line < cLine) { - pos += textLines[line].length+1; - } - else if(line === cLine) { - pos += cCh; - } - } - return pos; - }; - - var posToCursor = function(position, newText) { - var cursor = { - line: 0, - ch: 0 - }; - var textLines = newText.substr(0, position).split("\n"); - cursor.line = textLines.length - 1; - cursor.ch = textLines[cursor.line].length; - return cursor; - }; - exp.setValueAndCursor = function (oldDoc, remoteDoc, TextPatcher) { - var scroll = editor.getScrollInfo(); - //get old cursor here - var oldCursor = {}; - oldCursor.selectionStart = cursorToPos(editor.getCursor('from'), oldDoc); - oldCursor.selectionEnd = cursorToPos(editor.getCursor('to'), oldDoc); - - editor.setValue(remoteDoc); - editor.save(); - - var op = TextPatcher.diff(oldDoc, remoteDoc); - var selects = ['selectionStart', 'selectionEnd'].map(function (attr) { - return TextPatcher.transformCursor(oldCursor[attr], op); - }); - - if(selects[0] === selects[1]) { - editor.setCursor(posToCursor(selects[0], remoteDoc)); - } - else { - editor.setSelection(posToCursor(selects[0], remoteDoc), posToCursor(selects[1], remoteDoc)); - } - - editor.scrollTo(scroll.left, scroll.top); + return module.setValueAndCursor(editor, oldDoc, remoteDoc, TextPatcher); }; return exp; diff --git a/www/common/sframe-common-title.js b/www/common/sframe-common-title.js index b716c090e..6e0712011 100644 --- a/www/common/sframe-common-title.js +++ b/www/common/sframe-common-title.js @@ -41,7 +41,6 @@ define(['jquery'], function ($) { }; metadataMgr.onChange(function () { - console.error('METADATA CHANGE'); var md = metadataMgr.getMetadata(); if ($title) { $title.find('span.cp-toolbar-title-value').text(md.title || md.defaultTitle); diff --git a/www/poll/app-poll.less b/www/poll/app-poll.less index f310acf9f..4c2ecadae 100644 --- a/www/poll/app-poll.less +++ b/www/poll/app-poll.less @@ -21,6 +21,8 @@ @poll-td-bg: @poll-th-bg; @poll-td-fg: @poll-th-fg; +@poll-help-bg: #bbffbb; // lightgreen + @poll-uncommitted-cell: #eee; @poll-uncommitted-bg: #ddd; //lighten(@poll-th-bg, 50%); @poll-uncommitted-text: black; @@ -116,29 +118,48 @@ table#cp-app-poll-table { display: inline-block; } #cp-app-poll-description { + &~ .CodeMirror { + margin: auto; + min-width: 80%; + width: 80%; + min-height: 200px; + border: 1px solid black; + } +} +#cp-app-poll-description-published { + display: none; padding: 15px; margin: auto; min-width: 80%; width: 80%; min-height: 7em; - font: @colortheme_app-font; - //font-size: 20px; - /*font-weight: bold;*/ - border: 1px solid black; - -} -#cp-app-poll-description[disabled] { - resize: none; color: #000; border: 1px solid transparent; background-color: #eeeeee; font: @colortheme_app-font; + text-align: left; +} +.cp-app-poll-published { + #cp-app-poll-description { + display: none; + &~ .CodeMirror { + display: none; + } + } + #cp-app-poll-description-published { + display: block; + &:empty { + display: none; + } + } } #cp-app-poll-help { - width: 80%; + width: 100%; margin: auto; + padding: 20px 10%; + background: @poll-help-bg; } // from cryptpad.less diff --git a/www/poll/inner.js b/www/poll/inner.js index d8610ae9e..23b565ac9 100644 --- a/www/poll/inner.js +++ b/www/poll/inner.js @@ -12,6 +12,12 @@ define([ '/common/sframe-chainpad-listmap.js', '/customize/pages.js', '/poll/render.js', + '/common/diffMarked.js', + '/common/sframe-common-codemirror.js', + + 'cm/lib/codemirror', + 'cm/mode/markdown/markdown', + 'css!cm/lib/codemirror.css', '/bower_components/file-saver/FileSaver.min.js', @@ -31,7 +37,10 @@ define([ AppConfig, Listmap, Pages, - Renderer) + Renderer, + DiffMd, + SframeCM, + CMeditor) { var Messages = Cryptpad.Messages; var saveAs = window.saveAs; @@ -138,7 +147,7 @@ define([ Set the user id (user column) in the pad attributes */ var setUserId = function (id, cb) { - cb =cb || $.noop; + cb = cb || $.noop; APP.userid = id; common.setPadAttribute('userid', id, function (e) { if (e) { @@ -213,6 +222,7 @@ define([ var styleUserColumn = function () { var userid = APP.userid; + if (!userid) { return; } // Enable input for the userid column $('input[disabled="disabled"][data-rt-id^="' + userid + '"]').removeAttr('disabled') @@ -538,6 +548,7 @@ define([ /* Called whenever an event is fired on a span */ var handleSpan = function (span) { + if (!span) { return; } var id = span.getAttribute('data-rt-id'); var type = Render.typeofId(id); var isRemove = span.className && span.className.split(' ') @@ -570,6 +581,7 @@ define([ if (!res) { return; } Render.removeColumn(APP.proxy, id, function () { change(); + if (id === APP.userid) { setUserId(''); } }); }); } else if (isBookmark) { @@ -674,9 +686,9 @@ define([ bool = true; } setTablePublished(bool); - ['textarea'].forEach(function (sel) { + /*['textarea'].forEach(function (sel) { $(sel).attr('disabled', bool); - }); + });*/ updatePublishButton(); }; @@ -722,23 +734,19 @@ define([ } }; + var updatePublishedDescription = function () { + var v = APP.editor.getValue(); + DiffMd.apply(DiffMd.render(v || Messages.poll_descriptionHint), APP.$descriptionPublished); + }; var updateDescription = function (old, n) { var o = APP.$description.val(); - var op = TextPatcher.diff(o, n || ''); - var el = APP.$description[0]; - - var selects = ['selectionStart', 'selectionEnd'].map(function (attr) { - return TextPatcher.transformCursor(el[attr], op); - }); - APP.$description.val(n); - if (op) { - el.selectionStart = selects[0]; - el.selectionEnd = selects[1]; - } + SframeCM.setValueAndCursor(APP.editor, o, n, TextPatcher); + updatePublishedDescription(); common.notify(); }; var updateLocalDescription = function (n) { APP.proxy.description = n; + updatePublishedDescription(); }; var onReady = function (info, userid) { @@ -847,6 +855,7 @@ define([ APP.$createCol = $('#cp-app-poll-create-user').click(function () { var uncommittedCopy = { content: getUncommitted('col') }; var id = uncommittedCopy.content.colsOrder[0]; + if (!APP.userid) { setUserId(id); } mergeUncommitted(proxy, uncommittedCopy, true); change(null, null, null, null, function() { handleSpan($('.cp-app-poll-table-lock[data-rt-id="' + id + '"]')[0]); @@ -861,21 +870,11 @@ define([ }); }); - if (!APP.readOnly) { - setUserId(userid); - } - // Description - var resize = function () { - var lineCount = APP.$description.val().split('\n').length; - APP.$description.css('height', lineCount + 'rem'); - }; - APP.$description.on('change keyup', function () { - var val = APP.$description.val(); + APP.editor.on('change', function () { + var val = APP.editor.getValue(); updateLocalDescription(val); - resize(); }); - resize(); $('#cp-app-poll-table-scroll').html('').prepend($table); updateDisplayedTable(); @@ -1031,9 +1030,18 @@ define([ APP.$body = $('body'); APP.$bar = $('#cp-toolbar'); APP.$content = $('#cp-app-poll-content'); + APP.$descriptionPublished = $('#cp-app-poll-description-published'); APP.$description = $('#cp-app-poll-description') .attr('placeholder', Messages.poll_descriptionHint || 'description'); + APP.editor = CMeditor.fromTextArea(APP.$description[0], { + lineNumbers: true, + lineWrapping: true, + styleActiveLine : true, + mode: "markdown", + }); + + var listmapConfig = { data: {}, common: common, From 846b1a9fb33f6df139bd2dee2def842fda4073d8 Mon Sep 17 00:00:00 2001 From: yflory Date: Wed, 4 Oct 2017 15:39:18 +0200 Subject: [PATCH 08/20] Improve description UI in poll. Enable tags and mediatag --- customize.dist/pages.js | 1 + customize.dist/translations/messages.fr.js | 4 +- customize.dist/translations/messages.js | 4 +- www/poll/app-poll.less | 7 +++ www/poll/inner.js | 53 ++++++++++++++++++++-- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/customize.dist/pages.js b/customize.dist/pages.js index b944e2624..9e249b6db 100644 --- a/customize.dist/pages.js +++ b/customize.dist/pages.js @@ -650,6 +650,7 @@ define([ h('textarea#cp-app-poll-description', { rows: "5", cols: "50", + placeholder: Msg.poll_descriptionHint, disabled: true }), h('div#cp-app-poll-description-published'), diff --git a/customize.dist/translations/messages.fr.js b/customize.dist/translations/messages.fr.js index fb04d7bc0..0c2756d49 100644 --- a/customize.dist/translations/messages.fr.js +++ b/customize.dist/translations/messages.fr.js @@ -246,7 +246,9 @@ define(function () { out.poll_removeUser = "Êtes-vous sûr de vouloir supprimer cet utilisateur ?"; out.poll_titleHint = "Titre"; - out.poll_descriptionHint = "Description"; + out.poll_descriptionHint = "Décrivez votre sondage puis cliquer sur le bouton ✓ (Publier).\n" + + "La description peut contenir de la syntaxe markdown, et vous pouvez y ajouter des images stockées dans votre CryptDrive.\n" + + "Toutes les personnes possédant le lien d'édition de ce sondage peuvent modifier la description, bien que ce soit déconseillé."; out.poll_remove = "Supprimer"; out.poll_edit = "Modifier"; diff --git a/customize.dist/translations/messages.js b/customize.dist/translations/messages.js index 755c52a53..29c969628 100644 --- a/customize.dist/translations/messages.js +++ b/customize.dist/translations/messages.js @@ -248,7 +248,9 @@ define(function () { out.poll_removeUser = "Are you sure you'd like to remove this user?"; out.poll_titleHint = "Title"; - out.poll_descriptionHint = "Describe your poll, and use the 'publish' button when you're done. Anyone with the link can change the description, but this is discouraged."; + out.poll_descriptionHint = "Describe your poll, and use the ✓ (publish) button when you're done.\n" + + "The description can be written using markdown syntax and you can embed media elements from your CryptDrive.\n" + + "Anyone with the link can change the description, but this is discouraged."; out.poll_remove = "Remove"; out.poll_edit = "Edit"; diff --git a/www/poll/app-poll.less b/www/poll/app-poll.less index 4c2ecadae..b6ed472cb 100644 --- a/www/poll/app-poll.less +++ b/www/poll/app-poll.less @@ -124,6 +124,9 @@ table#cp-app-poll-table { width: 80%; min-height: 200px; border: 1px solid black; + .CodeMirror-placeholder { + color: #777; + } } } #cp-app-poll-description-published { @@ -139,6 +142,10 @@ table#cp-app-poll-table { background-color: #eeeeee; font: @colortheme_app-font; text-align: left; + media-tag > * { + max-width: 100%; + max-height: 20em; + } } .cp-app-poll-published { #cp-app-poll-description { diff --git a/www/poll/inner.js b/www/poll/inner.js index 23b565ac9..8e7bd8af3 100644 --- a/www/poll/inner.js +++ b/www/poll/inner.js @@ -16,6 +16,7 @@ define([ '/common/sframe-common-codemirror.js', 'cm/lib/codemirror', + 'cm/addon/display/placeholder', 'cm/mode/markdown/markdown', 'css!cm/lib/codemirror.css', @@ -685,11 +686,13 @@ define([ // If readOnly, always put the app in published mode bool = true; } + $(APP.$mediaTagButton).toggle(!bool); setTablePublished(bool); /*['textarea'].forEach(function (sel) { $(sel).attr('disabled', bool); });*/ updatePublishButton(); + APP.editor.refresh(); }; var updateHelpButton = function () { @@ -736,10 +739,11 @@ define([ var updatePublishedDescription = function () { var v = APP.editor.getValue(); - DiffMd.apply(DiffMd.render(v || Messages.poll_descriptionHint), APP.$descriptionPublished); + DiffMd.apply(DiffMd.render(v || ''), APP.$descriptionPublished); }; var updateDescription = function (old, n) { - var o = APP.$description.val(); + var o = APP.editor.getValue(); + console.error(n); SframeCM.setValueAndCursor(APP.editor, o, n, TextPatcher); updatePublishedDescription(); common.notify(); @@ -749,6 +753,18 @@ define([ updatePublishedDescription(); }; + var checkDeletedCells = function () { + // faster than forEach? + var c; + for (var k in APP.proxy.content.cells) { + c = Render.getCoordinates(k); + if (APP.proxy.content.colsOrder.indexOf(c[0]) === -1 || + APP.proxy.content.rowsOrder.indexOf(c[1]) === -1) { + console.log('deleting ' + k); + delete APP.proxy.content.cells[k]; + } + } + }; var onReady = function (info, userid) { var proxy = APP.proxy; @@ -767,6 +783,8 @@ define([ proxy.content = proxy.table; delete proxy.table; } + checkDeletedCells(); + if (proxy && proxy.metadata) { metadataMgr.updateMetadata(proxy.metadata); } @@ -878,7 +896,7 @@ define([ $('#cp-app-poll-table-scroll').html('').prepend($table); updateDisplayedTable(); - updateDescription(null, APP.proxy.description); + updateDescription(null, APP.proxy.description || ''); $table .click(handleClick) @@ -998,6 +1016,31 @@ define([ .click(function () { publish(!APP.proxy.published); }).appendTo($rightside); APP.$publishButton = $publish; updatePublishButton(); + + var fileDialogCfg = { + onSelect: function (data) { + if (data.type === 'file' && APP.editor) { + var mt = ''; + APP.editor.replaceSelection(mt); + return; + } + } + }; + common.initFilePicker(fileDialogCfg); + APP.$mediaTagButton = $('