|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"presets": [
|
||||
["env", { "modules": false }],
|
||||
"stage-3"
|
||||
]
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
.DS_Store
|
||||
.sass-cache/
|
||||
.project/
|
||||
.idea/
|
||||
|
@ -5,8 +6,14 @@ build/
|
|||
css/*.map
|
||||
nbproject/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
package-lock.json
|
||||
Thumbs.db
|
||||
yarn-error.log
|
||||
*.cmd
|
||||
*.lock
|
||||
*.iml
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.suo
|
||||
|
|
22
.travis.yml
|
@ -7,35 +7,33 @@ services:
|
|||
- postgresql
|
||||
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.2
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libxml2-utils
|
||||
|
||||
|
||||
env:
|
||||
global:
|
||||
- CORE_BRANCH=stable14
|
||||
- APP_NAME=polls
|
||||
matrix:
|
||||
- DB=mysql;CLOUD=nextcloud;CORE_BRANCH=stable12
|
||||
- DB=sqlite;CLOUD=nextcloud;CORE_BRANCH=stable12
|
||||
- DB=pgsql;CLOUD=nextcloud;CORE_BRANCH=stable12
|
||||
- DB=mysql;CLOUD=owncloud;CORE_BRANCH=stable10
|
||||
- DB=mysql
|
||||
- DB=pgsql
|
||||
- DB=sqlite
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.composer/cache
|
||||
|
||||
before_install:
|
||||
# Install NC / oC and app
|
||||
- if [ $CLOUD = 'nextcloud' ]; then wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh; fi
|
||||
- if [ $CLOUD = 'owncloud' ]; then wget https://raw.githubusercontent.com/owncloud/administration/master/travis-ci/before_install.sh; fi
|
||||
# Install NC and app
|
||||
- wget https://raw.githubusercontent.com/nextcloud/travis_ci/master/before_install.sh;
|
||||
- bash ./before_install.sh $APP_NAME $CORE_BRANCH $DB
|
||||
- if [ $CLOUD = 'nextcloud' ]; then cd ../server; fi
|
||||
- if [ $CLOUD = 'owncloud' ]; then cd ../core; fi
|
||||
- cd ../server;
|
||||
- ./occ app:enable $APP_NAME
|
||||
|
||||
before_script:
|
||||
|
@ -57,4 +55,4 @@ after_success:
|
|||
- php ocular.phar code-coverage:upload --format=php-clover clover.xml
|
||||
|
||||
after_failure:
|
||||
- cat ../../data/${CLOUD}.log
|
||||
- cat ../../data/nextcloud.log
|
||||
|
|
26
CHANGELOG.md
|
@ -2,7 +2,33 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.9.0] - tbD
|
||||
|
||||
### Added
|
||||
- create/edit page
|
||||
- rewrite as a vue app
|
||||
- improved UI
|
||||
- introduced new NC date time picker from vue-nextcloud
|
||||
- added option to forbid "maybe" vote
|
||||
|
||||
- vote page
|
||||
- made polls table scrollable
|
||||
- show new vote options after voting
|
||||
|
||||
### Changed
|
||||
- Compatibility to NC 14
|
||||
- Introduced vue
|
||||
- Changing database theme
|
||||
- Polls is a Nextcloud only app now. If you wish to proceed developing the ownCloud version, make a fork from the `stable-0.8` branch.
|
||||
|
||||
### Fixed
|
||||
- 'Edit poll' did not work from poll's details view (#294)
|
||||
- Bug which makes voting impossible after edit
|
||||
- Write escapes option texts to db (#341)
|
||||
- ... a lot more minor bugs
|
||||
|
||||
See https://github.com/nextcloud/polls/milestone/9?closed=1 for all changes and additions.
|
||||
|
||||
## [0.8.3] - 2018-08-30
|
||||
|
||||
### Added
|
||||
|
|
64
Makefile
|
@ -8,19 +8,14 @@
|
|||
# * which
|
||||
# * curl: used if phpunit and composer are not installed to fetch them from the web
|
||||
# * tar: for building the archive
|
||||
# * sass: for building css files for ownCloud
|
||||
|
||||
app_name=$(notdir $(CURDIR))
|
||||
build_tools_directory=$(CURDIR)/build/tools
|
||||
build_source_directory=$(CURDIR)/build/source
|
||||
appstore_build_directory=$(CURDIR)/build/artifacts/appstore
|
||||
appstore_package_name=$(appstore_build_directory)/$(app_name)
|
||||
marketplace_build_directory=$(CURDIR)/build/artifacts/marketplace
|
||||
marketplace_package_name=$(marketplace_build_directory)/$(app_name)
|
||||
nc_cert_directory=$(HOME)/.nextcloud/certificates
|
||||
oc_cert_directory=$(HOME)/.owncloud/certificates
|
||||
composer=$(shell which composer 2> /dev/null)
|
||||
sass=$(shell which sass 2> /dev/null)
|
||||
|
||||
all: composer
|
||||
|
||||
|
@ -43,9 +38,7 @@ endif
|
|||
# Removes the appstore build
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf ./.sass-cache
|
||||
rm -rf ./build
|
||||
rm -rf ./css/*.css
|
||||
|
||||
# Builds the source package for the app store, ignores php and js tests
|
||||
.PHONY: appstore
|
||||
|
@ -65,7 +58,7 @@ appstore:
|
|||
--exclude="ISSUE_TEMPLATE.md" \
|
||||
--exclude="karma.*" \
|
||||
--exclude="Makefile" \
|
||||
--exclude="package.json" \
|
||||
--exclude="package*" \
|
||||
--exclude="phpunit*xml" \
|
||||
--exclude="protractor.*" \
|
||||
--exclude="build" \
|
||||
|
@ -81,6 +74,7 @@ appstore:
|
|||
--exclude="js/.*" \
|
||||
--exclude="l10n/no-php" \
|
||||
--exclude="node_modules" \
|
||||
--exclude="screenshots" \
|
||||
--exclude="src" \
|
||||
--exclude="tests" \
|
||||
--exclude="vendor" \
|
||||
|
@ -93,60 +87,6 @@ appstore:
|
|||
openssl dgst -sha512 -sign $(nc_cert_directory)/$(app_name).key $(appstore_build_directory)/$(app_name).tar.gz | openssl base64; \
|
||||
fi
|
||||
|
||||
# Builds the source package for the marketplace, ignores php and js tests
|
||||
.PHONY: marketplace
|
||||
marketplace:
|
||||
ifeq (,$(sass))
|
||||
@echo "No sass command available, please install it and rerun"
|
||||
else
|
||||
sass --sourcemap=none --update ./src/css-oc:css
|
||||
rm -rf $(marketplace_build_directory)
|
||||
rm -rf $(build_source_directory)
|
||||
mkdir -p $(marketplace_build_directory)
|
||||
mkdir -p $(build_source_directory)
|
||||
|
||||
rsync -a \
|
||||
--include="js/vendor" \
|
||||
--include="css/vendor" \
|
||||
--exclude="*.log" \
|
||||
--exclude=".*" \
|
||||
--exclude="bower.json" \
|
||||
--exclude="composer.*" \
|
||||
--exclude="ISSUE_TEMPLATE.md" \
|
||||
--exclude="karma.*" \
|
||||
--exclude="Makefile" \
|
||||
--exclude="package.json" \
|
||||
--exclude="phpunit*xml" \
|
||||
--exclude="protractor.*" \
|
||||
--exclude="build" \
|
||||
--exclude="css/*.scss" \
|
||||
--exclude="js/node_modules" \
|
||||
--exclude="js/tests" \
|
||||
--exclude="js/test" \
|
||||
--exclude="js/*.log" \
|
||||
--exclude="js/package.json" \
|
||||
--exclude="js/bower.json" \
|
||||
--exclude="js/karma.*" \
|
||||
--exclude="js/protractor.*" \
|
||||
--exclude="js/.*" \
|
||||
--exclude="l10n/no-php" \
|
||||
--exclude="node_modules" \
|
||||
--exclude="src" \
|
||||
--exclude="tests" \
|
||||
--exclude="vendor" \
|
||||
./ $(build_source_directory)/$(app_name)
|
||||
|
||||
# We need to replace Nc screenshot urls with the oC ones
|
||||
sed -i -E "s~(<screenshot>)([^<]*).(png|jpg|jpeg)(</screenshot>)~\1\2-oc.\3\4~" $(build_source_directory)/$(app_name)/appinfo/info.xml
|
||||
|
||||
tar cvzf $(marketplace_package_name).tar.gz --directory="$(build_source_directory)" $(app_name)
|
||||
|
||||
@if [ -f $(oc_cert_directory)/$(app_name).key ]; then \
|
||||
echo "Signing package..."; \
|
||||
openssl dgst -sha512 -sign $(oc_cert_directory)/$(app_name).key $(marketplace_build_directory)/$(app_name).tar.gz | openssl base64; \
|
||||
fi
|
||||
endif
|
||||
|
||||
.PHONY: test
|
||||
test: composer
|
||||
$(CURDIR)/vendor/phpunit/phpunit/phpunit --coverage-clover clover.xml -c phpunit.xml
|
||||
|
|
10
README.md
|
@ -5,7 +5,7 @@
|
|||
[![Code Coverage](https://img.shields.io/scrutinizer/coverage/g/nextcloud/polls.svg?style=flat-square)](https://scrutinizer-ci.com/g/nextcloud/polls)
|
||||
[![Software License](https://img.shields.io/badge/license-AGPL-brightgreen.svg?style=flat-square)](LICENSE)
|
||||
|
||||
This is a poll app, similar to doodle or dudle, for Nextcloud / ownCloud written in PHP and JS / jQuery.
|
||||
This is a poll app, similar to doodle or dudle, for Nextcloud written in PHP and JS / jQuery.
|
||||
It is a rework of the already existing [polls app](https://github.com/raduvatav/polls) written by @raduvatav.
|
||||
|
||||
### Features
|
||||
|
@ -22,17 +22,17 @@ It is a rework of the already existing [polls app](https://github.com/raduvatav/
|
|||
|
||||
![Vote](https://github.com/nextcloud/polls/blob/master/screenshots/vote.png)
|
||||
|
||||
![New poll](https://github.com/nextcloud/polls/blob/master/screenshots/edit-poll.png)
|
||||
|
||||
![Vote mobile portrait](https://github.com/nextcloud/polls/blob/master/screenshots/vote-mobile-portrait.png)
|
||||
|
||||
![Vote mobile landscape](https://github.com/nextcloud/polls/blob/master/screenshots/vote-mobile-landscape.png)
|
||||
|
||||
![New poll](https://github.com/nextcloud/polls/blob/master/screenshots/edit-poll.png)
|
||||
|
||||
## Installation / Update
|
||||
This app is supposed to work on Nextcloud version 12+ or ownCloud version 10.
|
||||
This app is supposed to work on Nextcloud version 13+.
|
||||
|
||||
### Install latest release
|
||||
You can download and install the latest release from the [Nextcloud app store](https://apps.nextcloud.com/apps/polls) or from the [ownCloud marketplace](https://marketplace.owncloud.com/apps/polls).
|
||||
You can download and install the latest release from the [Nextcloud app store](https://apps.nextcloud.com/apps/polls) or a legacy version from the [ownCloud marketplace](https://marketplace.owncloud.com/apps/polls).
|
||||
|
||||
### Install from git
|
||||
If you want to run the latest development version from git source, you need to clone the repo to your apps folder:
|
||||
|
|
|
@ -1,230 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<database>
|
||||
<name>*dbname*</name>
|
||||
<create>true</create>
|
||||
<overwrite>false</overwrite>
|
||||
<charset>utf8</charset>
|
||||
<table>
|
||||
<name>*dbprefix*polls_events</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
<default>0</default>
|
||||
</field>
|
||||
<field>
|
||||
<name>hash</name>
|
||||
<type>text</type>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>type</name>
|
||||
<type>integer</type>
|
||||
<notnull>false</notnull>
|
||||
<length>16</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>title</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>128</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>description</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>1024</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>owner</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>created</name>
|
||||
<type>timestamp</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>access</name>
|
||||
<type>text</type>
|
||||
<notnull>false</notnull>
|
||||
<length>1024</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>expire</name>
|
||||
<type>timestamp</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>is_anonymous</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
</field>
|
||||
<field>
|
||||
<name>full_anonymous</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
<name>*dbprefix*polls_dts</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
</field>
|
||||
<field>
|
||||
<name>poll_id</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>dt</name>
|
||||
<type>timestamp</type>
|
||||
<length>32</length>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
<name>*dbprefix*polls_txts</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
</field>
|
||||
<field>
|
||||
<name>poll_id</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>text</name>
|
||||
<type>text</type>
|
||||
<length>256</length>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
<name>*dbprefix*polls_particip</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
</field>
|
||||
<field>
|
||||
<name>poll_id</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>dt</name>
|
||||
<type>timestamp</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>type</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>user_id</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
<name>*dbprefix*polls_particip_text</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
</field>
|
||||
<field>
|
||||
<name>poll_id</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>text</name>
|
||||
<type>text</type>
|
||||
<length>256</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>user_id</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>type</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
<name>*dbprefix*polls_comments</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
<default>0</default>
|
||||
</field>
|
||||
<field>
|
||||
<name>poll_id</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>user_id</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>dt</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>32</length>
|
||||
</field>
|
||||
<field>
|
||||
<name>comment</name>
|
||||
<type>text</type>
|
||||
<notnull>false</notnull>
|
||||
<length>1024</length>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
<table>
|
||||
<name>*dbprefix*polls_notif</name>
|
||||
<declaration>
|
||||
<field>
|
||||
<name>id</name>
|
||||
<type>integer</type>
|
||||
<default>0</default>
|
||||
<notnull>true</notnull>
|
||||
<autoincrement>1</autoincrement>
|
||||
</field>
|
||||
<field>
|
||||
<name>poll_id</name>
|
||||
<type>integer</type>
|
||||
</field>
|
||||
<field>
|
||||
<name>user_id</name>
|
||||
<type>text</type>
|
||||
<notnull>true</notnull>
|
||||
<length>64</length>
|
||||
</field>
|
||||
</declaration>
|
||||
</table>
|
||||
</database>
|
|
@ -5,7 +5,7 @@
|
|||
<name>Polls</name>
|
||||
<summary>A polls app, similar to doodle/dudle with the possibility to restrict access.</summary>
|
||||
<description>A polls app, similar to doodle/dudle with the possibility to restrict access (members, certain groups/users, hidden and public).</description>
|
||||
<version>0.8.3</version>
|
||||
<version>0.9.0</version>
|
||||
<licence>agpl</licence>
|
||||
<author>Vinzenz Rosenkranz</author>
|
||||
<author>René Gieling</author>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<admin>https://github.com/nextcloud/polls/blob/master/README.md</admin>
|
||||
</documentation>
|
||||
<category>tools</category>
|
||||
<category>social</category>
|
||||
<category>social</category>
|
||||
<category>organization</category>
|
||||
<website>https://github.com/nextcloud/polls</website>
|
||||
<bugs>https://github.com/nextcloud/polls/issues</bugs>
|
||||
|
@ -23,7 +23,6 @@
|
|||
<screenshot>https://raw.githubusercontent.com/nextcloud/polls/master/screenshots/vote.png</screenshot>
|
||||
<screenshot>https://raw.githubusercontent.com/nextcloud/polls/master/screenshots/edit-poll.png</screenshot>
|
||||
<dependencies>
|
||||
<owncloud min-version="8.2" max-version="10.0" />
|
||||
<nextcloud min-version="11" max-version="14" />
|
||||
<nextcloud min-version="14" max-version="14" />
|
||||
</dependencies>
|
||||
</info>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
* @copyright Copyright (c] 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
|
@ -9,7 +9,7 @@
|
|||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
* License, or (at your option] any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
@ -21,19 +21,22 @@
|
|||
*
|
||||
*/
|
||||
|
||||
$app = new \OCA\Polls\AppInfo\Application();
|
||||
$app->registerRoutes($this, array(
|
||||
'routes' => array(
|
||||
array('name' => 'page#index', 'url' => '/', 'verb' => 'GET'),
|
||||
array('name' => 'page#goto_poll', 'url' => '/poll/{hash}', 'verb' => 'GET'),
|
||||
array('name' => 'page#edit_poll', 'url' => '/edit/{hash}', 'verb' => 'GET'),
|
||||
array('name' => 'page#create_poll', 'url' => '/create', 'verb' => 'GET'),
|
||||
array('name' => 'page#delete_poll', 'url' => '/delete', 'verb' => 'POST'),
|
||||
array('name' => 'page#update_poll', 'url' => '/update', 'verb' => 'POST'),
|
||||
array('name' => 'page#insert_poll', 'url' => '/insert', 'verb' => 'POST'),
|
||||
array('name' => 'page#insert_vote', 'url' => '/insert/vote', 'verb' => 'POST'),
|
||||
array('name' => 'page#insert_comment', 'url' => '/insert/comment', 'verb' => 'POST'),
|
||||
array('name' => 'page#search', 'url' => '/search', 'verb' => 'POST'),
|
||||
array('name' => 'page#get_display_name', 'url' => '/get/displayname', 'verb' => 'POST'),
|
||||
)
|
||||
));
|
||||
return [
|
||||
'routes' => [
|
||||
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
|
||||
['name' => 'page#goto_poll', 'url' => '/poll/{hash}', 'verb' => 'GET'],
|
||||
['name' => 'page#edit_poll', 'url' => '/edit/{hash}', 'verb' => 'GET'],
|
||||
['name' => 'page#create_poll', 'url' => '/create', 'verb' => 'GET'],
|
||||
['name' => 'page#delete_poll', 'url' => '/delete', 'verb' => 'POST'],
|
||||
['name' => 'page#update_poll', 'url' => '/update', 'verb' => 'POST'],
|
||||
['name' => 'page#insert_poll', 'url' => '/insert', 'verb' => 'POST'],
|
||||
['name' => 'page#insert_vote', 'url' => '/insert/vote', 'verb' => 'POST'],
|
||||
['name' => 'page#insert_comment', 'url' => '/insert/comment', 'verb' => 'POST'],
|
||||
['name' => 'page#search', 'url' => '/search', 'verb' => 'POST'],
|
||||
['name' => 'page#get_display_name', 'url' => '/get/displayname', 'verb' => 'POST'],
|
||||
['name' => 'api#write_poll', 'url' => '/write', 'verb' => 'POST'],
|
||||
['name' => 'api#get_poll', 'url' => '/get/poll/{hash}', 'verb' => 'GET'],
|
||||
['name' => 'api#get_site_users_and_groups', 'url' => '/get/siteusers', 'verb' => 'POST'],
|
||||
['name' => 'api#get_system', 'url' => '/get/system', 'verb' => 'GET']
|
||||
]
|
||||
];
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
$hover-color: #f7f7f7;
|
||||
|
||||
$bg_no: #ffede9;
|
||||
$bg_maybe: #fcf7e1;
|
||||
$bg_unvoted: #fff4c8;
|
||||
$bg_yes: #ebf5d6;
|
||||
$bg_information: #b19c3e;
|
||||
|
||||
$fg_no: #f45573;
|
||||
$fg_maybe: #f0db98;
|
||||
$fg_unvoted: #f0db98;
|
||||
$fg_yes: #49bc49;
|
||||
|
||||
$bg_current_user: #f7f7f7;
|
||||
$fg_current_user: #0082c9;
|
|
@ -1,103 +0,0 @@
|
|||
@import 'polls-variables.scss';
|
||||
@import 'main.scss';
|
||||
|
||||
.user-group-list {
|
||||
display: none;
|
||||
border: 1px solid #DDD;
|
||||
margin: 15px;
|
||||
padding: 5px;
|
||||
border-radius: 3px;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
#sec_name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* #app-content #app-content-wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
*/
|
||||
.cl_access_item {
|
||||
padding: 5px;
|
||||
background-color: white;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: #EEE;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background-color: #409AE7;
|
||||
color: #FFF;
|
||||
&:hover {
|
||||
background-color: #FF6F6F;
|
||||
color: #FFF;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
textarea {
|
||||
min-height: 66px;
|
||||
}
|
||||
|
||||
.choices {
|
||||
margin-top: 10px;
|
||||
td {
|
||||
min-width: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
table{
|
||||
td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.icon-close {
|
||||
cursor: pointer;
|
||||
background-color: $bg_no; /*red*/
|
||||
padding: 0 5px;
|
||||
background-image: url('../img/no-vote.svg');
|
||||
}
|
||||
|
||||
.icon-checkmark {
|
||||
cursor: pointer;
|
||||
background-color: $bg_yes; /*green*/
|
||||
padding: 0 5px;
|
||||
background-image: url('../img/yes-vote.svg');
|
||||
}
|
||||
}
|
||||
|
||||
.text-row, .date-row {
|
||||
font-weight: bold;
|
||||
padding: 2px 5px;
|
||||
background-color: #337AB7;
|
||||
color: #FFF;
|
||||
text-align: left;
|
||||
&:hover {
|
||||
background-color: #ff6f6f;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#selected-dates-table tr:first-child td {
|
||||
font-weight: bold;
|
||||
padding: 2px 5px;
|
||||
background-color: #337AB7;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
#expiration {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
#pollDesc {
|
||||
width: 100%;
|
||||
}
|
|
@ -1,5 +1,30 @@
|
|||
@import 'polls-variables.scss';
|
||||
@import 'main.scss';
|
||||
@import 'colors.scss';
|
||||
|
||||
$row-padding: 15px;
|
||||
$table-padding: 4px;
|
||||
|
||||
$date-width: 120px;
|
||||
$participants-width: 95px;
|
||||
$group-2-2-width: max($date-width, $participants-width);
|
||||
|
||||
$owner-width: 140px;
|
||||
$access-width: 140px;
|
||||
$group-2-1-width: max($access-width, $date-width);
|
||||
$group-2-width: $owner-width + $group-2-1-width + $group-2-2-width;
|
||||
|
||||
$action-width: 44px;
|
||||
$thumbnail-width: 44px;
|
||||
$thumbnail-icon-width: 32px;
|
||||
$name-width: 150px;
|
||||
$description-width: 150px;
|
||||
$group-1-1-width: max($name-width, $description-width);
|
||||
$group-1-width: $thumbnail-width + $group-1-1-width + $action-width;
|
||||
|
||||
$group-master-width: max($group-1-width, $group-2-width);
|
||||
|
||||
$mediabreak-1: ($group-1-width + $owner-width + $access-width + $date-width + $date-width + $participants-width + $row-padding * 2);
|
||||
$mediabreak-2: ($group-1-width + $group-2-width + $row-padding * 2);
|
||||
$mediabreak-3: $group-1-width + $owner-width + max($group-2-1-width, $group-2-2-width) + $row-padding *2 ;
|
||||
|
||||
.table {
|
||||
width: 100%;
|
||||
|
@ -12,7 +37,7 @@
|
|||
|
||||
line-height: 2em;
|
||||
transition: background-color 0.3s ease;
|
||||
background-color: $color-main-background;
|
||||
background-color: var(--color-main-background);
|
||||
min-height: 4em;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
|
@ -65,7 +90,7 @@
|
|||
|
||||
|
||||
.flex-column {
|
||||
/* padding: 0 $table-padding; */
|
||||
padding: 0 $table-padding;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
@ -101,7 +126,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.participants {
|
||||
.participants{
|
||||
width: $participants-width;
|
||||
div {
|
||||
&.partic_voted {
|
||||
|
@ -125,12 +150,17 @@
|
|||
|
||||
}
|
||||
|
||||
.actions {
|
||||
width: $action-width;
|
||||
position: relative;
|
||||
overflow: initial;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
background-size: $thumbnail-icon-width;
|
||||
width: $thumbnail-width;
|
||||
height: $thumbnail-width;
|
||||
/* padding-right: $table-padding; */
|
||||
padding-right: $table-padding;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
&.progress, &.endless {
|
||||
|
|
130
css/main.scss
|
@ -3,6 +3,24 @@ h1 {
|
|||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
#app, #create-poll {
|
||||
header {
|
||||
padding-top: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
/* allow horizontal scrollbar
|
||||
otherwise user management is not usable on mobile */
|
||||
@media only screen and (max-width: 768px) {
|
||||
#app-content {
|
||||
overflow-x: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
#app-content-wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.icon-polls {
|
||||
background-color: black;
|
||||
-webkit-mask: url('../img/app.svg') no-repeat 50% 50%;
|
||||
|
@ -11,6 +29,10 @@ h1 {
|
|||
|
||||
|
||||
#controls {
|
||||
// adopted from NC13 for compatibily with OC10 and NC11-NC12
|
||||
width: 100%;
|
||||
position: relative;
|
||||
top: 4px;
|
||||
h2 {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
@ -38,16 +60,15 @@ h1 {
|
|||
padding: 0px 15px;
|
||||
}
|
||||
|
||||
.col-70 {
|
||||
width: 65%;
|
||||
float: left;
|
||||
padding: 0px 15px;
|
||||
}
|
||||
.col-70 { width: 65%; float: left; padding: 0px 15px; }
|
||||
|
||||
.col-30 {
|
||||
width: 35%;
|
||||
float: left;
|
||||
padding: 0px 15px;
|
||||
.col-30 { width: 35%; float: left; padding: 0px 15px; }
|
||||
|
||||
@media(max-width: 992px) {
|
||||
.col-70, .col-30, .col-50 {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,6 +77,11 @@ input[type="text"] {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
/* textarea {
|
||||
min-width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
*/
|
||||
.form-actions {
|
||||
padding: 15px;
|
||||
}
|
||||
|
@ -64,21 +90,8 @@ input[type="text"] {
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
div {
|
||||
.new_poll {
|
||||
width: 100%;
|
||||
}
|
||||
.scroll_div {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.scroll_div_dialog {
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
div.new_poll {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input.table_button {
|
||||
|
@ -89,6 +102,17 @@ input.table_button {
|
|||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.scroll_div {
|
||||
width: 100%;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
div.scroll_div_dialog {
|
||||
width: 100%;
|
||||
height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.bordered {
|
||||
border-left: 1px solid #FFF;
|
||||
|
@ -137,12 +161,11 @@ td.td_shown {
|
|||
font-size: 2em;
|
||||
}
|
||||
|
||||
.input_title {
|
||||
.input_title{
|
||||
display: block;
|
||||
font-size: 1.2em;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.padded td {
|
||||
padding: 10px;
|
||||
}
|
||||
|
@ -191,30 +214,33 @@ td.td_shown {
|
|||
cursor: pointer;
|
||||
padding: 0px 5px 0px 5px;
|
||||
|
||||
&:hover {
|
||||
background-color: #ffccca;
|
||||
}
|
||||
}
|
||||
|
||||
.cl_del_item:hover {
|
||||
background-color: #ffccca;
|
||||
}
|
||||
.cl_maybe:before, .cl_maybe:after{
|
||||
content: "?";
|
||||
}
|
||||
|
||||
.cl_user_comments {
|
||||
table-layout: fixed;
|
||||
td {
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
word-wrap: break-word;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.cl_user_comments td {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.cl_user_comments th {
|
||||
word-wrap: break-word;
|
||||
vertical-align: top;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user_comment {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.user_comment {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
|
@ -266,29 +292,29 @@ td.td_shown {
|
|||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
width: 1%;
|
||||
|
||||
input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-addon input[type="checkbox"] {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.input-group-btn {
|
||||
vertical-align: top;
|
||||
.btn {
|
||||
height: 31.25px;
|
||||
border: 1px solid #DDD;
|
||||
margin: 0;
|
||||
border-radius: 3px;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.input-group-btn .btn {
|
||||
height: 31.25px;
|
||||
border: 1px solid #DDD;
|
||||
margin: 0;
|
||||
border-radius: 3px;
|
||||
vertical-align: middle;
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.input-group>input {
|
||||
position: relative;
|
||||
/* z-index: 2; */
|
||||
z-index: 2;
|
||||
float: left;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
// colors
|
||||
$hover-color: #f7f7f7;
|
||||
|
||||
$bg_no: #ffede9;
|
||||
$bg_maybe: #fcf7e1;
|
||||
$bg_unvoted: #fff4c8;
|
||||
$bg_yes: #ebf5d6;
|
||||
$bg_information: #b19c3e;
|
||||
|
||||
$fg_no: #f45573;
|
||||
$fg_maybe: #f0db98;
|
||||
$fg_unvoted: #f0db98;
|
||||
$fg_yes: #49bc49;
|
||||
|
||||
$bg_current_user: #f7f7f7;
|
||||
$fg_current_user: #0082c9;
|
||||
|
||||
// various structure data
|
||||
$navigation-width: 300px;
|
||||
$sidebar-min-width: 300px;
|
||||
$sidebar-max-width: 500px;
|
||||
|
||||
// list.scss definition
|
||||
$border_current_user: 2px solid;
|
||||
$border_user: 1px solid #ddd;
|
||||
$user-column-width: 265px;
|
||||
|
||||
$row-padding: 15px;
|
||||
$table-padding: 4px;
|
||||
|
||||
$date-width: 120px;
|
||||
$participants-width: 80px;
|
||||
$group-2-2-width: max($date-width, $participants-width);
|
||||
|
||||
$owner-width: 140px;
|
||||
$access-width: 140px;
|
||||
$group-2-1-width: max($access-width, $date-width);
|
||||
$group-2-width: $owner-width + $group-2-1-width + $group-2-2-width;
|
||||
|
||||
$action-width: 44px;
|
||||
$thumbnail-width: 44px;
|
||||
$thumbnail-icon-width: 32px;
|
||||
$name-width: 150px;
|
||||
$description-width: 150px;
|
||||
$group-1-1-width: max($name-width, $description-width);
|
||||
$group-1-width: $thumbnail-width + $group-1-1-width + $action-width;
|
||||
|
||||
$group-master-width: max($group-1-width, $group-2-width);
|
||||
|
||||
$mediabreak-1: ($group-1-width + $owner-width + $access-width + $date-width + $date-width + $participants-width + $row-padding * 2);
|
||||
$mediabreak-2: ($group-1-width + $group-2-width + $row-padding * 2);
|
||||
$mediabreak-3: $group-1-width + $owner-width + max($group-2-1-width, $group-2-2-width) + $row-padding *2 ;
|
393
css/sidebar.scss
|
@ -1,230 +1,225 @@
|
|||
@import 'polls-variables.scss';
|
||||
@import 'colors.scss';
|
||||
|
||||
$border_current_user: 2px solid;
|
||||
$border_user: 1px solid #ddd;
|
||||
$user-column-width: 265px;
|
||||
|
||||
#polls-sidebar {
|
||||
width: 520px;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 1;
|
||||
min-width: 300px;
|
||||
/* padding-top: 8px; */
|
||||
/* margin-top: 3px; */
|
||||
border-left: 1px solid $color-border;
|
||||
/* -webkit-transition: margin-right 300ms; */
|
||||
border-left: 1px solid var(--color-border);
|
||||
transition: margin-right 300ms;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
/* visibility: visible; */
|
||||
z-index: 500;
|
||||
/* height: 100%; */
|
||||
> div, > ul {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.authorRow {
|
||||
align-items: center;
|
||||
.author {
|
||||
margin-left: 8px;
|
||||
opacity: .5;
|
||||
flex-grow: 1;
|
||||
&.external {
|
||||
margin-right: 33px;
|
||||
opacity: 1;
|
||||
> input {
|
||||
width: 100%
|
||||
.authorRow {
|
||||
align-items: center;
|
||||
.author {
|
||||
margin-left: 8px;
|
||||
opacity: .5;
|
||||
flex-grow: 1;
|
||||
&.external {
|
||||
margin-right: 33px;
|
||||
opacity: 1;
|
||||
> input {
|
||||
width: 100%
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.detailsView {
|
||||
z-index: 1000 !important;
|
||||
.close.flex-row {
|
||||
justify-content: flex-end;
|
||||
margin: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.header.flex-row {
|
||||
flex-direction: row;
|
||||
flex-grow: 0;
|
||||
align-items: flex-start;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
padding: 0 17px;
|
||||
}
|
||||
|
||||
.pollInformation {
|
||||
width: 220px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
padding-right: 15px;
|
||||
|
||||
.authorRow {
|
||||
.leftLabel {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.detailsView {
|
||||
z-index: 1000 !important;
|
||||
.close.flex-row {
|
||||
justify-content: flex-end;
|
||||
margin: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.cloud {
|
||||
margin: 4px 0;
|
||||
|
||||
> span {
|
||||
color: #fff;
|
||||
margin: 2px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
float: left;
|
||||
text-shadow: 1px 1px #666;
|
||||
background-color: #aaa;
|
||||
|
||||
}
|
||||
.open {
|
||||
background-color: $fg_yes;
|
||||
}
|
||||
.expired {
|
||||
background-color: $fg_no;
|
||||
}
|
||||
.information {
|
||||
background-color: $bg_information;
|
||||
}
|
||||
}
|
||||
}
|
||||
#expired_info {
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.pollActions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 15px;
|
||||
|
||||
.close {
|
||||
margin: 15px;
|
||||
background-position: right top;
|
||||
height: 30px;
|
||||
.header.flex-row {
|
||||
flex-direction: row;
|
||||
flex-grow: 0;
|
||||
align-items: flex-start;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
padding: 0 17px;
|
||||
}
|
||||
|
||||
> ul > li {
|
||||
&:focus, &:hover, &.active, a.selected {
|
||||
&, > a {
|
||||
opacity: 1;
|
||||
box-shadow: inset 2px 0 #0082c9;
|
||||
.pollInformation {
|
||||
width: 220px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
padding-right: 15px;
|
||||
|
||||
.authorRow {
|
||||
.leftLabel {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
> a[class*="icon-"],
|
||||
> ul > li > a[class*="icon-"],
|
||||
> a[style*="background-image"],
|
||||
> ul > li > a[style*="background-image"] {
|
||||
padding-left: 44px;
|
||||
.cloud {
|
||||
margin: 4px 0;
|
||||
|
||||
> span {
|
||||
color: #fff;
|
||||
margin: 2px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
float: left;
|
||||
text-shadow: 1px 1px #666;
|
||||
background-color: #aaa;
|
||||
|
||||
}
|
||||
.open {
|
||||
background-color: $fg_yes;
|
||||
}
|
||||
.expired {
|
||||
background-color: $fg_no;
|
||||
}
|
||||
.information {
|
||||
background-color: $bg_information;
|
||||
}
|
||||
}
|
||||
}
|
||||
#expired_info {
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.pollActions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 15px;
|
||||
|
||||
.close {
|
||||
margin: 15px;
|
||||
background-position: right top;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
> ul > li {
|
||||
&:focus, &:hover, &.active, a.selected {
|
||||
&, > a {
|
||||
opacity: 1;
|
||||
box-shadow: inset 2px 0 #0082c9;
|
||||
}
|
||||
}
|
||||
|
||||
> a[class*="icon-"],
|
||||
> ul > li > a[class*="icon-"],
|
||||
> a[style*="background-image"],
|
||||
> ul > li > a[style*="background-image"] {
|
||||
padding-left: 44px;
|
||||
}
|
||||
|
||||
> a,
|
||||
> ul > li > a {
|
||||
background-size: 16px 16px;
|
||||
background-position: 14px center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
justify-content: space-between;
|
||||
line-height: 44px;
|
||||
min-height: 44px;
|
||||
padding: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: #000;
|
||||
opacity: 0.57;
|
||||
flex: 1 1 0;
|
||||
z-index: 100;
|
||||
}
|
||||
a,
|
||||
.app-navigation-entry-deleted {
|
||||
padding-left: 44px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
#configurationsTabView {
|
||||
.configBox {
|
||||
padding: 8px 8px;
|
||||
|
||||
> .title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
> div {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
input.hasDatepicker {
|
||||
margin-left:17px;
|
||||
}
|
||||
&.oneline {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
#commentsTabView {
|
||||
|
||||
.newCommentForm div.message:empty:before {
|
||||
content: attr(data-placeholder);
|
||||
color: grey;
|
||||
}
|
||||
#commentBox {
|
||||
border: 1px solid #dbdbdb;
|
||||
border-radius: 3px;
|
||||
padding: 7px 6px;
|
||||
margin: 3px 3px 3px 40px;
|
||||
cursor: text;
|
||||
}
|
||||
.comment {
|
||||
margin-bottom: 30px;
|
||||
|
||||
.comment-header {
|
||||
background-color: #EEE;
|
||||
border-bottom: 1px solid #DDD;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
float: right;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.date {
|
||||
right: 0;
|
||||
top: 5px;
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-left: 40px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
> a,
|
||||
> ul > li > a {
|
||||
background-size: 16px 16px;
|
||||
background-position: 14px center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
justify-content: space-between;
|
||||
line-height: 44px;
|
||||
min-height: 44px;
|
||||
padding: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: #000;
|
||||
opacity: 0.57;
|
||||
flex: 1 1 0;
|
||||
z-index: 100;
|
||||
}
|
||||
a,
|
||||
.app-navigation-entry-deleted {
|
||||
padding-left: 44px !important;
|
||||
|
||||
.new-comment {
|
||||
.submitComment {
|
||||
align-self: last baseline;
|
||||
width: 30px;
|
||||
margin: 0;
|
||||
padding: 7px 9px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
.icon-loading-small {
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#configurationsTabView {
|
||||
.configBox {
|
||||
padding: 8px 8px;
|
||||
|
||||
> .title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
> div {
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
input.hasDatepicker {
|
||||
margin-left:17px;
|
||||
}
|
||||
&.oneline {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#commentsTabView {
|
||||
|
||||
.newCommentForm div.message:empty:before {
|
||||
content: attr(data-placeholder);
|
||||
color: grey;
|
||||
}
|
||||
#commentBox {
|
||||
border: 1px solid #dbdbdb;
|
||||
border-radius: 3px;
|
||||
padding: 7px 6px;
|
||||
margin: 3px 3px 3px 40px;
|
||||
cursor: text;
|
||||
}
|
||||
.comment {
|
||||
margin-bottom: 30px;
|
||||
|
||||
.comment-header {
|
||||
background-color: #EEE;
|
||||
border-bottom: 1px solid #DDD;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
float: right;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.date {
|
||||
right: 0;
|
||||
top: 5px;
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-left: 40px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
|
||||
.new-comment {
|
||||
.submitComment {
|
||||
align-self: last baseline;
|
||||
width: 30px;
|
||||
margin: 0;
|
||||
padding: 7px 9px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
.icon-loading-small {
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
566
css/vote.scss
|
@ -1,113 +1,117 @@
|
|||
@import 'polls-variables.scss';
|
||||
@import 'main.scss';
|
||||
@import 'colors.scss';
|
||||
|
||||
$border_current_user: 2px solid;
|
||||
$border_user: 1px solid #ddd;
|
||||
$user-column-width: 265px;
|
||||
|
||||
#content {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
}
|
||||
#votings {
|
||||
position: relative !important;
|
||||
.description {
|
||||
.expired-vote{
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
#app-content {
|
||||
width: 100%;
|
||||
overflow-x: hidden;
|
||||
|
||||
#votings {
|
||||
position: relative !important;
|
||||
padding: 12px 17px;
|
||||
.table {
|
||||
overflow-x: auto;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
}
|
||||
padding: 12px 17px;
|
||||
}
|
||||
|
||||
.header {
|
||||
margin-left: $user-column-width;
|
||||
padding: 0 17px;
|
||||
align-items: initial;
|
||||
.vote.option {
|
||||
.date-box {
|
||||
flex-grow: 1;
|
||||
.description {
|
||||
.expired-vote{
|
||||
color: var(--color-error);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.header {
|
||||
margin-left: $user-column-width;
|
||||
padding: 0 17px;
|
||||
align-items: initial;
|
||||
|
||||
.date-box {
|
||||
padding: 0 2px;
|
||||
align-items: center;
|
||||
.month, .dayow {
|
||||
font-size: 1.2em;
|
||||
color: var(--color-text-lighter);
|
||||
}
|
||||
|
||||
.day {
|
||||
font-size: 1.8em;
|
||||
margin: 5px 0 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.counter {
|
||||
.counter {
|
||||
font-size: 18px;
|
||||
.yes, .no {
|
||||
margin: 0 2px;
|
||||
.svg {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 24px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
}
|
||||
}
|
||||
.yes {
|
||||
color: $fg_yes;
|
||||
.svg {
|
||||
background-image: url('../img/yes-vote.svg');
|
||||
}
|
||||
}
|
||||
.no {
|
||||
color: $fg_no;
|
||||
.svg {
|
||||
background-image: url('../img/no-vote.svg');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.winner {
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
color: $fg_yes;
|
||||
}
|
||||
.vote.option {
|
||||
.date-box {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.counter {
|
||||
flex-grow: 0;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.user {
|
||||
border-top: $border_user;
|
||||
height: 44px;
|
||||
padding: 0 17px;
|
||||
}
|
||||
.first {
|
||||
flex-grow: 0;
|
||||
height: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
flex-shrink: 0;
|
||||
width: $user-column-width;
|
||||
}
|
||||
|
||||
.user {
|
||||
border-top: $border_user;
|
||||
height: 44px;
|
||||
padding: 0 17px;
|
||||
}
|
||||
|
||||
.first {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: $user-column-width;
|
||||
}
|
||||
|
||||
.vote, .poll-cell {
|
||||
flex-grow: 1;
|
||||
width: 85px;
|
||||
margin: 2px;
|
||||
align-items:center;
|
||||
}
|
||||
|
||||
.date-box {
|
||||
padding: 0 2px;
|
||||
align-items: center;
|
||||
.month, .dayow {
|
||||
font-size: 1.2em;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.day {
|
||||
font-size: 1.8em;
|
||||
margin: 5px 0 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.winner {
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
color: $fg_yes;
|
||||
}
|
||||
|
||||
.counter {
|
||||
font-size: 18px;
|
||||
.yes, .no {
|
||||
margin: 0 2px;
|
||||
.svg {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 24px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
.vote, .poll-cell {
|
||||
flex-grow: 1;
|
||||
width: 85px;
|
||||
margin: 2px;
|
||||
align-items:center;
|
||||
}
|
||||
}
|
||||
.yes {
|
||||
color: $fg_yes;
|
||||
.svg {
|
||||
background-image: url('../img/yes-vote.svg');
|
||||
}
|
||||
}
|
||||
.no {
|
||||
color: $fg_no;
|
||||
.svg {
|
||||
background-image: url('../img/no-vote.svg');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
.name {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
@ -118,13 +122,6 @@
|
|||
background-size: 32px;
|
||||
height: 44px;
|
||||
|
||||
&.active {
|
||||
cursor: pointer;
|
||||
border: 2px solid;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
&.yes {
|
||||
background-color: $bg_yes;
|
||||
color: $fg_yes;
|
||||
|
@ -144,11 +141,28 @@
|
|||
}
|
||||
|
||||
&.unvoted {
|
||||
background-color: $bg_unvoted;
|
||||
color: $fg_unvoted;
|
||||
background-color: $bg_unvoted;
|
||||
background-color: $bg_no;
|
||||
color: $fg_no;
|
||||
&:before {
|
||||
content: attr(data-unvoted);
|
||||
color: $fg_no;
|
||||
font-size: 14px;
|
||||
font-style: italic;
|
||||
font-weight: bold;
|
||||
line-height: 38px;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
cursor: pointer;
|
||||
border: 2px solid;
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
&.unvoted {
|
||||
background-color: $bg_maybe;
|
||||
color: $fg_maybe;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toggle-cell {
|
||||
|
@ -229,192 +243,6 @@
|
|||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.authorRow {
|
||||
position: relative;
|
||||
.author {
|
||||
margin-left: 8px;
|
||||
opacity: .5;
|
||||
flex-grow: 1;
|
||||
&.external {
|
||||
margin-right: 33px;
|
||||
opacity: 1;
|
||||
> input {
|
||||
width: 100%
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.detailsView {
|
||||
z-index: 1000 !important;
|
||||
.close.flex-row {
|
||||
justify-content: flex-end;
|
||||
margin: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.header.flex-row {
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
margin-left: 0;
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
.pollInformation {
|
||||
width: 220px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
padding-right: 15px;
|
||||
|
||||
|
||||
.authorRow {
|
||||
.leftLabel {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.cloud {
|
||||
margin: 4px 0;
|
||||
|
||||
> span {
|
||||
color: #fff;
|
||||
margin: 2px;
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
float: left;
|
||||
text-shadow: 1px 1px #666;
|
||||
background-color: #aaa;
|
||||
|
||||
}
|
||||
.open {
|
||||
background-color: $fg_yes;
|
||||
}
|
||||
.expired {
|
||||
background-color: $fg_no;
|
||||
}
|
||||
.information {
|
||||
background-color: $bg_information;
|
||||
}
|
||||
}
|
||||
}
|
||||
#expired_info {
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
.pollActions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-right: 15px;
|
||||
|
||||
.close {
|
||||
margin: 15px;
|
||||
background-position: right top;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
> ul > li {
|
||||
&:focus, &:hover, &.active, a.selected {
|
||||
&, > a {
|
||||
opacity: 1;
|
||||
box-shadow: inset 2px 0 #0082c9;
|
||||
}
|
||||
}
|
||||
|
||||
> a[class*="icon-"],
|
||||
> ul > li > a[class*="icon-"],
|
||||
> a[style*="background-image"],
|
||||
> ul > li > a[style*="background-image"] {
|
||||
padding-left: 44px;
|
||||
}
|
||||
|
||||
> a,
|
||||
> ul > li > a {
|
||||
background-size: 16px 16px;
|
||||
background-position: 14px center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
justify-content: space-between;
|
||||
line-height: 44px;
|
||||
min-height: 44px;
|
||||
padding: 0 12px;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
color: #000;
|
||||
opacity: 0.57;
|
||||
flex: 1 1 0;
|
||||
z-index: 100;
|
||||
}
|
||||
a,
|
||||
.app-navigation-entry-deleted {
|
||||
padding-left: 44px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#commentsTabView {
|
||||
|
||||
.newCommentForm div.message:empty:before {
|
||||
content: attr(data-placeholder);
|
||||
color: grey;
|
||||
}
|
||||
#commentBox {
|
||||
border: 1px solid #dbdbdb;
|
||||
border-radius: 3px;
|
||||
padding: 7px 6px;
|
||||
margin: 3px 3px 3px 40px;
|
||||
cursor: text;
|
||||
}
|
||||
.comment {
|
||||
margin-bottom: 30px;
|
||||
|
||||
.comment-header {
|
||||
background-color: #EEE;
|
||||
border-bottom: 1px solid #DDD;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.comment-date {
|
||||
float: right;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.date {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 5px;
|
||||
opacity: .5;
|
||||
}
|
||||
}
|
||||
|
||||
.message {
|
||||
margin-left: 40px;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
|
||||
.new-comment {
|
||||
.submitComment {
|
||||
align-self: last baseline;
|
||||
width: 30px;
|
||||
margin: 0;
|
||||
padding: 7px 9px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
opacity: .3;
|
||||
}
|
||||
|
||||
.icon-loading-small {
|
||||
float: left;
|
||||
margin-top: 10px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media all and (max-width: (768px) ) {
|
||||
#app-content {
|
||||
position: relative !important;
|
||||
|
@ -422,88 +250,94 @@
|
|||
}
|
||||
@media all and (max-width: (480px) ) {
|
||||
|
||||
#votings {
|
||||
#app-content #votings {
|
||||
padding: 0px 2px;
|
||||
}
|
||||
|
||||
.flex-row {
|
||||
flex-direction: column;
|
||||
|
||||
&.user-cell, &.counter, &.counter .yes, &.counter .no, &.controls, &.breadcrump, &.submitPoll, &.newCommentForm, &.close {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&.header {
|
||||
flex-grow: 1;
|
||||
margin-left: 0;
|
||||
margin-top: 44px;
|
||||
width: 120px;
|
||||
padding: 0 0 0 4px;
|
||||
.vote {
|
||||
padding-right: 10px;
|
||||
&.option {
|
||||
align-items: baseline;
|
||||
width: 100%;
|
||||
border-top: $border_user;
|
||||
.flex-row {
|
||||
flex-direction: column;
|
||||
.first {
|
||||
height: 44px;
|
||||
width: unset;
|
||||
}
|
||||
&.time {
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
border-top: $border_user;
|
||||
.counter {
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
|
||||
&.user-cell, &.counter, &.counter .yes, &.counter .no, &.controls, &.breadcrump, &.submitPoll, &.newCommentForm, &.close {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&.header {
|
||||
flex-grow: 1;
|
||||
margin-left: 0;
|
||||
margin-top: 44px;
|
||||
width: 120px;
|
||||
padding: 0 0 0 4px;
|
||||
.vote {
|
||||
padding-right: 10px;
|
||||
&.option {
|
||||
align-items: baseline;
|
||||
width: 100%;
|
||||
border-top: $border_user;
|
||||
}
|
||||
&.time {
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
border-top: $border_user;
|
||||
.counter {
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.user {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.current-user {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
padding:0;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
|
||||
.poll-cell {
|
||||
border:none;
|
||||
border-radius: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
background-color: transparent;
|
||||
padding: 0 2px;
|
||||
&.active {
|
||||
&.yes {
|
||||
background-image: url('../img/yes-vote-bordered.svg');
|
||||
}
|
||||
|
||||
&.no {
|
||||
background-image: url('../img/no-vote-bordered.svg');
|
||||
}
|
||||
|
||||
&.maybe {
|
||||
background-image: url('../img/maybe-vote-bordered.svg');
|
||||
}
|
||||
&.unvoted {
|
||||
background-image: url('../img/unvoted-vote-bordered.svg');
|
||||
}
|
||||
}
|
||||
}
|
||||
.user-cell {
|
||||
position: absolute;
|
||||
left: 22px;
|
||||
}
|
||||
.poll-cell, .toggle-cell {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&.user {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.current-user {
|
||||
display: flex;
|
||||
width: 44px;
|
||||
padding:0;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
|
||||
.poll-cell {
|
||||
border:none;
|
||||
border-radius: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
background-color: transparent;
|
||||
padding: 0 2px;
|
||||
&.active {
|
||||
&.yes {
|
||||
background-image: url('../img/yes-vote-bordered.svg');
|
||||
}
|
||||
|
||||
&.no {
|
||||
background-image: url('../img/no-vote-bordered.svg');
|
||||
}
|
||||
|
||||
&.maybe {
|
||||
background-image: url('../img/maybe-vote-bordered.svg');
|
||||
}
|
||||
&.unvoted {
|
||||
background-image: url('../img/unvoted-vote-bordered.svg');
|
||||
}
|
||||
}
|
||||
}
|
||||
.user-cell {
|
||||
position: absolute;
|
||||
left: 22px;
|
||||
}
|
||||
.poll-cell, .toggle-cell {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.description {
|
||||
margin: 4px;
|
||||
}
|
||||
|
@ -548,10 +382,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.first {
|
||||
height: 44px;
|
||||
width: unset;
|
||||
}
|
||||
|
||||
#options.flex-row {
|
||||
flex-direction: column;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg4"
|
||||
height="16"
|
||||
width="16"
|
||||
viewbox="0 0 16 16"
|
||||
version="1.1">
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8" />
|
||||
<g
|
||||
id="XMLID_2_"
|
||||
transform="matrix(0.22613747,0,0,0.23288366,-2.8432917,-3.1784157)">
|
||||
<path
|
||||
d="M 19.4,18 V 78 H 76.5 V 31.4 L 65.3,18 H 58.4 V 40.9 H 28 V 18 Z m 22.9,2.9 V 35.2 H 53.7 V 20.9 Z M 28,50.4 H 68 V 72.3 H 28 Z m 5.7,4.7 V 58 h 28.6 v -2.9 z m 0,8.6 v 2.9 h 28.6 v -2.9 z"
|
||||
class="st0"
|
||||
id="XMLID_9_" />
|
||||
</g>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 1.0 KiB |
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg4"
|
||||
height="20"
|
||||
width="4"
|
||||
viewbox="0 0 16 16"
|
||||
version="1.1"
|
||||
sodipodi:docname="toggle.svg"
|
||||
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
id="namedview6"
|
||||
showgrid="false"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="-2.3727798"
|
||||
inkscape:cy="9.3760237"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<metadata
|
||||
id="metadata10">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs8" />
|
||||
<rect
|
||||
style="fill:#00000d;fill-opacity:1;stroke:#000000;stroke-width:0.5714286;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:19.89999962;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="rect4513"
|
||||
width="1.4285715"
|
||||
height="1.4285713"
|
||||
x="1.2857143"
|
||||
y="13.285715" />
|
||||
<rect
|
||||
style="fill:#00000d;fill-opacity:1;stroke:#000000;stroke-width:0.5714286;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:19.89999962;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="rect4513-2"
|
||||
width="1.4285715"
|
||||
height="1.4285715"
|
||||
x="1.2857143"
|
||||
y="17.285715" />
|
||||
<rect
|
||||
style="fill:#00000d;fill-opacity:1;stroke:#000000;stroke-width:0.5714286;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:19.89999962;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="rect4513-6"
|
||||
width="1.4285715"
|
||||
height="1.4285715"
|
||||
x="1.2857143"
|
||||
y="9.2857151" />
|
||||
<rect
|
||||
style="fill:#00000d;fill-opacity:1;stroke:#000000;stroke-width:0.5714286;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:19.89999962;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="rect4513-26"
|
||||
width="1.4285716"
|
||||
height="1.4285715"
|
||||
x="1.2857141"
|
||||
y="5.2857151" />
|
||||
<rect
|
||||
style="fill:#00000d;fill-opacity:1;stroke:#000000;stroke-width:0.5714286;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:19.89999962;stroke-dasharray:none;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="rect4513-9"
|
||||
width="1.4285715"
|
||||
height="1.4285715"
|
||||
x="1.2857143"
|
||||
y="1.2857143" />
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 3.1 KiB |
|
@ -1,5 +1,5 @@
|
|||
function deletePoll($pollEl) {
|
||||
var str = t('polls', 'Do you really want to delete that poll (new)?') + '\n\n' + $($pollEl).attr('data-value');
|
||||
var str = t('polls', 'Do you really want to delete this new poll?') + '\n\n' + $($pollEl).attr('data-value');
|
||||
if (confirm(str)) {
|
||||
var form = document.form_delete_poll;
|
||||
var hiddenId = document.createElement("input");
|
||||
|
@ -10,3 +10,5 @@ function deletePoll($pollEl) {
|
|||
form.submit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,637 +0,0 @@
|
|||
var g_chosen_datetimes = [];
|
||||
var g_chosen_texts = [];
|
||||
var g_chosen_groups = [];
|
||||
var g_chosen_users = [];
|
||||
var chosen_type = 'event';
|
||||
var access_type = '';
|
||||
var isAnonymous;
|
||||
var hideNames;
|
||||
|
||||
function selectItem(cell) {
|
||||
cell.removeClass('icon-close');
|
||||
cell.addClass('icon-checkmark');
|
||||
cell.removeClass('date-text-not-selected');
|
||||
cell.addClass('date-text-selected');
|
||||
if (cell.attr('class').indexOf('is-text') > -1) {
|
||||
var id = cell.attr('id');
|
||||
g_chosen_texts.push(id.substring(id.indexOf('_') + 1));
|
||||
} else {
|
||||
var dateId = cell.parent().attr('id'); //timestamp of date
|
||||
var timeId = cell.attr('id');
|
||||
g_chosen_datetimes.push(parseInt(dateId) + parseInt(timeId));
|
||||
}
|
||||
}
|
||||
|
||||
function deselectItem(cell) {
|
||||
var id;
|
||||
var index;
|
||||
var dateId;
|
||||
var timeId;
|
||||
cell.removeClass('icon-checkmark');
|
||||
cell.addClass('icon-close');
|
||||
cell.removeClass('date-text-selected');
|
||||
cell.addClass('date-text-not-selected');
|
||||
if (cell.attr('class').indexOf('is-text') > -1) {
|
||||
id = cell.attr('id');
|
||||
index = g_chosen_texts.indexOf(id.substring(id.indexOf('_') + 1));
|
||||
if (index > -1) {
|
||||
g_chosen_texts.splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
dateId = cell.parent().attr('id'); //timestamp of date
|
||||
timeId = cell.attr('id');
|
||||
index = g_chosen_datetimes.indexOf(parseInt(dateId) + parseInt(timeId));
|
||||
if (index > -1) {
|
||||
g_chosen_datetimes.splice(index, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function insertText(text, set) {
|
||||
if (typeof set == 'undefined') {
|
||||
set = false;
|
||||
}
|
||||
var table = document.getElementById('selected-texts-table');
|
||||
var tr = table.insertRow(-1);
|
||||
var td = tr.insertCell(-1);
|
||||
td.innerHTML = text;
|
||||
td.className = 'text-row';
|
||||
td = tr.insertCell(-1);
|
||||
if (set) {
|
||||
td.className = 'icon-checkmark is-text date-text-selected';
|
||||
} else {
|
||||
td.className = 'icon-close is-text date-text-not-selected';
|
||||
}
|
||||
td.id = 'text_' + text;
|
||||
}
|
||||
|
||||
function addRowToList(ts, text, timeTs) {
|
||||
if (typeof timeTs == 'undefined') {
|
||||
timeTs = -1;
|
||||
}
|
||||
var table = document.getElementById('selected-dates-table');
|
||||
var rows = table.rows;
|
||||
var td, tr, tdId;
|
||||
var i, j;
|
||||
var curr;
|
||||
if (rows.length == 0) {
|
||||
tr = table.insertRow(-1); //start new header
|
||||
tr.insertCell(-1);
|
||||
tr = table.insertRow(-1); //append new row
|
||||
tr.id = ts;
|
||||
tr.className = 'toggleable-row';
|
||||
td = tr.insertCell(-1);
|
||||
td.className = 'date-row';
|
||||
td.innerHTML = text;
|
||||
return;
|
||||
}
|
||||
for ( i=1; i<rows.length; i++) {
|
||||
curr = rows[i];
|
||||
if (curr.id == ts) {
|
||||
for (j=1; j<curr.cells.length; j++) {
|
||||
td = curr.cells[j];
|
||||
tdId = curr.cells[j].id;
|
||||
if ( timeTs == tdId) {
|
||||
td.className = 'icon-checkmark date-text-selected';
|
||||
}
|
||||
}
|
||||
return; //already in table, cancel
|
||||
} else if (curr.id > ts) {
|
||||
tr = table.insertRow(i); //insert row at current index
|
||||
tr.id = ts;
|
||||
tr.className = 'toggleable-row';
|
||||
td = tr.insertCell(-1);
|
||||
td.className = 'date-row';
|
||||
td.innerHTML = text;
|
||||
for (j=1; j<rows[0].cells.length; j++) {
|
||||
tdId = rows[0].cells[j].id;
|
||||
td = tr.insertCell(-1);
|
||||
if (timeTs == tdId) {
|
||||
td.className = 'icon-checkmark date-text-selected';
|
||||
} else {
|
||||
td.className = 'icon-close date-text-not-selected';
|
||||
}
|
||||
td.id = tdId;
|
||||
td.innerHTML = '';
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
tr = table.insertRow(-1); //highest value, append new row
|
||||
tr.id = ts;
|
||||
tr.className = 'toggleable-row';
|
||||
td = tr.insertCell(-1);
|
||||
td.className = 'date-row';
|
||||
td.innerHTML = text;
|
||||
for (j=1; j<rows[0].cells.length; j++) {
|
||||
tdId = rows[0].cells[j].id;
|
||||
td = tr.insertCell(-1);
|
||||
if (timeTs == tdId) {
|
||||
td.className = 'icon-checkmark date-text-selected';
|
||||
} else {
|
||||
td.className = 'icon-close date-text-not-selected';
|
||||
}
|
||||
td.id = tdId;
|
||||
td.innerHTML = '';
|
||||
}
|
||||
}
|
||||
|
||||
function addColToList(ts, text, dateTs) {
|
||||
if (typeof dateTs == 'undefined') {
|
||||
dateTs = -1;
|
||||
}
|
||||
var table = document.getElementById('selected-dates-table');
|
||||
var rows = table.rows;
|
||||
var tr, row, td, cells, tmpRow;
|
||||
var i, curr;
|
||||
var index = -1;
|
||||
if (rows.length == 0) {
|
||||
tr = table.insertRow(-1);
|
||||
tr.insertCell(-1);
|
||||
}
|
||||
rows = table.rows;
|
||||
tmpRow = rows[0];
|
||||
for (i=0; i<tmpRow.cells.length; i++) {
|
||||
curr = tmpRow.cells[i];
|
||||
if (curr.id == ts) {
|
||||
return; //already in table, cancel
|
||||
} else if (curr.id > ts) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<rows.length; i++) {
|
||||
row = rows[i];
|
||||
cells = row.cells;
|
||||
td = row.insertCell(index);
|
||||
//only display time in header row
|
||||
if (i==0) {
|
||||
td.innerHTML = text;
|
||||
td.className = 'date-col';
|
||||
} else {
|
||||
td.innerHTML = '';
|
||||
if (row.id == dateTs) {
|
||||
td.className = 'icon-checkmark date-text-selected';
|
||||
} else {
|
||||
td.className = 'icon-close date-text-not-selected';
|
||||
}
|
||||
}
|
||||
td.id = ts;
|
||||
}
|
||||
}
|
||||
|
||||
function debounce(f, wait, immediate) {
|
||||
var timeout;
|
||||
return function () {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
var later = function () {
|
||||
timeout = null;
|
||||
if (!immediate) {
|
||||
f.apply(context, args);
|
||||
}
|
||||
};
|
||||
var callNow = immediate && !timeout;
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
if (callNow) {
|
||||
f.apply(context, args);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
// enable / disable date picker
|
||||
var i;
|
||||
$('#id_expire_set').click(function (){
|
||||
$('#id_expire_date').prop("disabled", !this.checked);
|
||||
if (this.checked) {
|
||||
$("#id_expire_date").focus();
|
||||
}
|
||||
});
|
||||
|
||||
var anonOptions = document.getElementById('anonOptions');
|
||||
$('#hideNames').click(function () {
|
||||
hideNames = this.checked;
|
||||
});
|
||||
|
||||
$('#isAnonymous').click(function () {
|
||||
isAnonymous = this.checked;
|
||||
if (isAnonymous) {
|
||||
anonOptions.style.display = 'inline';
|
||||
} else {
|
||||
anonOptions.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
var privateRadio = document.getElementById('private');
|
||||
var hiddenRadio = document.getElementById('hidden');
|
||||
var publicRadio = document.getElementById('public');
|
||||
var selectRadio = document.getElementById('select');
|
||||
if (privateRadio.checked) {
|
||||
access_type = 'registered';
|
||||
} else if (hiddenRadio.checked) {
|
||||
access_type = 'hidden';
|
||||
} else if (publicRadio.checked) {
|
||||
access_type = 'public';
|
||||
} else if (selectRadio.checked) {
|
||||
access_type = 'select';
|
||||
}
|
||||
|
||||
isAnonymous = document.getElementById('isAnonymous').checked;
|
||||
hideNames = anonOptions.checked;
|
||||
|
||||
var accessValues = document.getElementById('accessValues');
|
||||
if (accessValues.value.length > 0) {
|
||||
var list = document.getElementById('selected-search-list-id');
|
||||
var accessValueArr = accessValues.value.split(';');
|
||||
for (i=0; i<accessValueArr.length; i++) {
|
||||
var val = accessValueArr[i];
|
||||
if (val == '') {
|
||||
continue;
|
||||
}
|
||||
var li = document.createElement('li');
|
||||
li.id = val;
|
||||
li.className = 'cl_item cl_access_item selected';
|
||||
var index = val.indexOf('group_');
|
||||
if (index == 0) {
|
||||
g_chosen_groups.push(val);
|
||||
li.className += ' is-group';
|
||||
li.appendChild(document.createTextNode(val.substring(6) + " (group)"));
|
||||
list.appendChild(li);
|
||||
} else {
|
||||
index = val.indexOf('user_');
|
||||
if (index == 0) {
|
||||
g_chosen_users.push(val);
|
||||
li.className = 'cl_item cl_access_item selected';
|
||||
var username = val.substring(5);
|
||||
$.post(OC.generateUrl('/apps/polls/get/displayname'), {username: username}, function (data) {
|
||||
li.appendChild(document.createTextNode(username + " (" + data + ")"));
|
||||
list.appendChild(li);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var chosenDates = document.getElementById('chosenDates').value;
|
||||
var chosen = '';
|
||||
if (chosenDates.length > 0) {
|
||||
chosen = JSON.parse(chosenDates);
|
||||
}
|
||||
var text = document.getElementById('text');
|
||||
var event = document.getElementById('event');
|
||||
if (event.checked) {
|
||||
chosen_type = event.value;
|
||||
if (chosenDates.length > 0) {
|
||||
g_chosen_datetimes = chosen;
|
||||
}
|
||||
for (i=0; i<chosen.length; i++) {
|
||||
var date = new Date(chosen[i]*1000);
|
||||
var year = date.getFullYear();
|
||||
var month = date.getMonth();
|
||||
var day = date.getDate();
|
||||
var newDate = new Date(year, month, day).getTime(); //save timestamp without time of day
|
||||
month = '0' + (month+1); //month is 0-11, so +1
|
||||
day = '0' + day;
|
||||
var dateStr = day.substr(-2) + '.' + month.substr(-2) + '.' + year;
|
||||
var hours = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
var ms = (hours * 60 * 60 * 1000) + (minutes * 60 * 1000); //time of day in milliseconds
|
||||
hours = '0' + hours;
|
||||
minutes = '0' + minutes;
|
||||
var timeStr = hours.substr(-2) + ':' + minutes.substr(-2);
|
||||
addRowToList(newDate/1000, dateStr, ms/1000);
|
||||
addColToList(ms/1000, timeStr, newDate/1000);
|
||||
}
|
||||
} else {
|
||||
chosen_type = text.value;
|
||||
if (chosenDates.length > 0) {
|
||||
g_chosen_texts = chosen;
|
||||
}
|
||||
for (i=0; i<chosen.length; i++) {
|
||||
insertText(chosen[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
var expirepicker = jQuery('#id_expire_date').datetimepicker({
|
||||
inline: false,
|
||||
onSelectDate: function (date) {
|
||||
var year = date.getFullYear();
|
||||
var month = date.getMonth();
|
||||
var day = date.getDate();
|
||||
// set expiry date to the last second before midnight of the choosen date (local time)
|
||||
var newDate = new Date(year, month, day, 23, 59, 59).getTime()/1000;
|
||||
document.getElementById('expireTs').value = newDate;
|
||||
},
|
||||
timepicker: false,
|
||||
format: 'd.m.Y'
|
||||
});
|
||||
|
||||
var datepicker = jQuery('#datetimepicker').datetimepicker({
|
||||
inline:true,
|
||||
step: 15,
|
||||
todayButton: true,
|
||||
onSelectDate: function (date) {
|
||||
var year = date.getFullYear();
|
||||
var month = date.getMonth();
|
||||
var day = date.getDate();
|
||||
var newDate = new Date(year, month, day).getTime(); //save timestamp without time of day
|
||||
month = '0' + (month+1); //month is 0-11, so +1
|
||||
day = '0' + day;
|
||||
var dateStr = day.substr(-2) + '.' + month.substr(-2) + '.' + year;
|
||||
addRowToList(newDate/1000, dateStr);
|
||||
},
|
||||
onSelectTime: function (date) {
|
||||
var hours = date.getHours();
|
||||
var minutes = date.getMinutes();
|
||||
var ms = (hours * 60 * 60 * 1000) + (minutes * 60 * 1000); //time of day in milliseconds
|
||||
hours = '0' + hours;
|
||||
minutes = '0' + minutes;
|
||||
var timeStr = hours.substr(-2) + ':' + minutes.substr(-2);
|
||||
addColToList(ms/1000, timeStr);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.date-row', function () {
|
||||
var tr = $(this).parent();
|
||||
var dateId = parseInt(tr.attr('id'));
|
||||
var index = tr.index();
|
||||
var cells = tr[0].cells; //convert jQuery object to DOM
|
||||
for (var i=1; i<cells.length; i++) {
|
||||
var cell = cells[i];
|
||||
var delIndex = g_chosen_datetimes.indexOf(dateId + parseInt(cell.id));
|
||||
if (delIndex > -1) {
|
||||
g_chosen_datetimes.splice(delIndex, 1);
|
||||
}
|
||||
}
|
||||
var table = document.getElementById('selected-dates-table');
|
||||
table.deleteRow(index);
|
||||
});
|
||||
|
||||
$(document).on('click', '.date-col', function () {
|
||||
var cellIndex = $(this).index();
|
||||
var timeId = parseInt($(this).attr('id'));
|
||||
var table = document.getElementById('selected-dates-table');
|
||||
var rows = table.rows;
|
||||
rows[0].deleteCell(cellIndex);
|
||||
for (var i=1; i<rows.length; i++) {
|
||||
var row = rows[i];
|
||||
var delIndex = g_chosen_datetimes.indexOf(parseInt(row.id) + timeId);
|
||||
if (delIndex > -1) {
|
||||
g_chosen_datetimes.splice(delIndex, 1);
|
||||
}
|
||||
row.deleteCell(cellIndex);
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('click', '.text-row', function () {
|
||||
var tr = $(this).parent();
|
||||
var rowIndex = tr.index();
|
||||
var name = $(this).html();
|
||||
var delIndex = g_chosen_texts.indexOf(name);
|
||||
if (delIndex > -1) {
|
||||
g_chosen_texts.splice(delIndex, 1);
|
||||
}
|
||||
var table = document.getElementById('selected-texts-table');
|
||||
table.deleteRow(rowIndex);
|
||||
});
|
||||
|
||||
$(document).on('click', '.icon-close', function () {
|
||||
selectItem($(this));
|
||||
});
|
||||
|
||||
$(document).on('click', '.icon-checkmark', function () {
|
||||
deselectItem($(this));
|
||||
});
|
||||
|
||||
$(document).on('click', '#text-submit', function () {
|
||||
var text = document.getElementById('text-title');
|
||||
if (text.value.length == 0) {
|
||||
alert('Please enter a text!');
|
||||
return false;
|
||||
}
|
||||
insertText(text.value);
|
||||
text.value = '';
|
||||
});
|
||||
|
||||
$(document).on('click', '.cl_item', function () {
|
||||
var index;
|
||||
var list = document.getElementById('selected-search-list-id');
|
||||
var isGroup = $(this).hasClass('is-group');
|
||||
if ($(this).hasClass('selected')) {
|
||||
if (isGroup) {
|
||||
index = g_chosen_groups.indexOf(this.id);
|
||||
}
|
||||
else {
|
||||
index = g_chosen_users.indexOf(this.id);
|
||||
}
|
||||
if (index > -1) {
|
||||
if (isGroup) {
|
||||
g_chosen_groups.splice(index, 1);
|
||||
}
|
||||
else {
|
||||
g_chosen_users.splice(index, 1);
|
||||
}
|
||||
$(this).remove();
|
||||
}
|
||||
} else {
|
||||
if (!isGroup) {
|
||||
var text = this.id.replace('user_', '');
|
||||
g_chosen_users.push(this.id);
|
||||
} else {
|
||||
g_chosen_groups.push(this.id);
|
||||
}
|
||||
document.getElementById('user-group-search-box').value = '';
|
||||
var li = document.createElement('li');
|
||||
li.id = this.id;
|
||||
li.className = 'cl_item cl_access_item selected' + (isGroup ? ' is-group' : '');
|
||||
if (!isGroup) {
|
||||
$.post(OC.generateUrl('/apps/polls/get/displayname'), {username: text}, function (data) {
|
||||
li.appendChild(document.createTextNode(text + " (" + data + ")"));
|
||||
list.appendChild(li);
|
||||
});
|
||||
} else {
|
||||
li.appendChild(document.createTextNode($(this).html()));
|
||||
list.appendChild(li);
|
||||
}
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
|
||||
$('.toggleable-row').hover(
|
||||
function () {
|
||||
var td = this.insertCell(-1);
|
||||
td.className = 'toggle-all selected-all';
|
||||
}, function () {
|
||||
$(this).find('td:last-child').remove();
|
||||
}
|
||||
);
|
||||
|
||||
$(document).on('click', '.toggle-all', function () {
|
||||
var children;
|
||||
var i;
|
||||
if ($(this).attr('class').indexOf('selected-all') > -1) {
|
||||
children = $(this).parent().children('.icon-checkmark');
|
||||
for (i=0; i<children.length; i++) {
|
||||
deselectItem($(children[i]));
|
||||
}
|
||||
$(this).removeClass('selected-all');
|
||||
$(this).addClass('selected-none');
|
||||
} else {
|
||||
children = $(this).parent().children('.icon-close');
|
||||
for (i=0; i<children.length; i++) {
|
||||
selectItem($(children[i]));
|
||||
}
|
||||
$(this).removeClass('selected-none');
|
||||
$(this).addClass('selected-all');
|
||||
}
|
||||
});
|
||||
|
||||
$('input[type=radio][name=pollType]').change(function () {
|
||||
if (this.value == 'event') {
|
||||
chosen_type = 'event';
|
||||
document.getElementById('text-select-container').style.display = 'none';
|
||||
document.getElementById('date-select-container').style.display = 'inline';
|
||||
} else {
|
||||
chosen_type = 'text';
|
||||
document.getElementById('text-select-container').style.display = 'inline';
|
||||
document.getElementById('date-select-container').style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
$('input[type=radio][name=accessType]').click(function () {
|
||||
access_type = this.value;
|
||||
if (access_type == 'select') {
|
||||
$("#access_rights").show();
|
||||
$("#selected_access").show();
|
||||
} else {
|
||||
$("#access_rights").hide();
|
||||
$("#selected_access").hide();
|
||||
}
|
||||
});
|
||||
|
||||
$('input[type=checkbox][name=check_expire]').change(function () {
|
||||
if (!$(this).is(':checked')) {
|
||||
document.getElementById('expireTs').value = '';
|
||||
}
|
||||
});
|
||||
|
||||
$('#user-group-search-box').on('input', debounce(function () {
|
||||
var ul = document.getElementById('live-search-list-id');
|
||||
while(ul.firstChild) {
|
||||
ul.removeChild(ul.firstChild);
|
||||
}
|
||||
var val = $(this).val();
|
||||
if (val.length < 3) {
|
||||
return;
|
||||
}
|
||||
var formData = {
|
||||
searchTerm: val,
|
||||
groups: JSON.stringify(g_chosen_groups),
|
||||
users: JSON.stringify(g_chosen_users)
|
||||
};
|
||||
$.post(OC.generateUrl('/apps/polls/search'), formData, function (data) {
|
||||
for (var i=0; i<data.length; i++) {
|
||||
var ug = data[i];
|
||||
var li = document.createElement('li');
|
||||
li.className = 'cl_item cl_access_item';
|
||||
if (ug.isGroup) {
|
||||
li.id = 'group_' + ug.gid;
|
||||
li.className += ' is-group';
|
||||
li.appendChild(document.createTextNode(ug.gid + " (group)"));
|
||||
ul.appendChild(li);
|
||||
} else {
|
||||
li.id = 'user_' + ug.uid;
|
||||
li.appendChild(document.createTextNode(ug.uid + " (" + ug.displayName + ")"));
|
||||
var span = document.createElement('span');
|
||||
span.id = 'sec_name';
|
||||
span.appendChild(document.createTextNode(ug.uid));
|
||||
li.appendChild(span);
|
||||
ul.appendChild(li);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 250));
|
||||
|
||||
$('.live-search-list-user li').each(function (){
|
||||
$(this).attr('data-search-term', $(this).text().toLowerCase());
|
||||
});
|
||||
|
||||
$('.live-search-box-user').on('keyup', function (){
|
||||
var searchTerm = $(this).val().toLowerCase();
|
||||
$('.live-search-list-user li').each(function (){
|
||||
if ( $(this).filter('[data-search-term *= ' + searchTerm + ']').length > 0
|
||||
|| searchTerm.length < 1
|
||||
) {
|
||||
$(this).show();
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('.live-search-list-group li').each(function (){
|
||||
$(this).attr('data-search-term', $(this).text().toLowerCase());
|
||||
});
|
||||
|
||||
$('.live-search-box-group').on('keyup', function (){
|
||||
var searchTerm = $(this).val().toLowerCase();
|
||||
$('.live-search-list-group li').each(function (){
|
||||
if (
|
||||
$(this).filter('[data-search-term *= ' + searchTerm + ']').length > 0 ||
|
||||
searchTerm.length < 1
|
||||
) {
|
||||
$(this).show();
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var form = document.finish_poll;
|
||||
var submit_finish_poll = document.getElementById('submit_finish_poll');
|
||||
if (submit_finish_poll !== null) {
|
||||
submit_finish_poll.onclick = function () {
|
||||
if (
|
||||
g_chosen_datetimes.length == 0 &&
|
||||
g_chosen_texts.length == 0
|
||||
) {
|
||||
alert(t('polls', 'Nothing selected!\nClick on cells to turn them green.'));
|
||||
return false;
|
||||
}
|
||||
if (chosen_type == 'event') {
|
||||
form.elements.chosenDates.value = JSON.stringify(g_chosen_datetimes);
|
||||
}
|
||||
else {
|
||||
form.elements.chosenDates.value = JSON.stringify(g_chosen_texts);
|
||||
}
|
||||
var title = document.getElementById('pollTitle');
|
||||
if (
|
||||
title == null ||
|
||||
title.value.length == 0
|
||||
) {
|
||||
alert(t('polls', 'You must enter at least a title for the new poll.'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (access_type == 'select') {
|
||||
if (
|
||||
g_chosen_groups.length == 0 &&
|
||||
g_chosen_users == 0
|
||||
) {
|
||||
alert(t('polls', 'Please select at least one user or group!'));
|
||||
return false;
|
||||
}
|
||||
form.elements.accessValues.value = JSON.stringify({
|
||||
groups: g_chosen_groups,
|
||||
users: g_chosen_users
|
||||
});
|
||||
}
|
||||
form.elements.isAnonymous.value = isAnonymous;
|
||||
form.elements.hideNames.value = hideNames;
|
||||
form.submit();
|
||||
};
|
||||
}
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
/** global: Clipboard */
|
||||
/* global clipboard, navigator */
|
||||
$(document).ready(function () {
|
||||
var clipboard = new Clipboard('.copy-link');
|
||||
clipboard.on('success', function (e) {
|
||||
|
@ -18,13 +18,14 @@ $(document).ready(function () {
|
|||
}
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
var $input = $(e.trigger);
|
||||
var actionMsg = '';
|
||||
if (/iPhone|iPad/i.test(navigator.userAgent)) {
|
||||
actionMsg = t('core', 'Not supported!');
|
||||
} else if (/Mac/i.test(navigator.userAgent)) {
|
||||
actionMsg = t('core', 'Press ⌘-C to copy.');
|
||||
actionMsg = t('core', 'Press ?-C to copy.');
|
||||
} else {
|
||||
actionMsg = t('core', 'Press Ctrl-C to copy.');
|
||||
}
|
||||
|
@ -36,7 +37,7 @@ $(document).ready(function () {
|
|||
.tooltip('show');
|
||||
_.delay(function () {
|
||||
$input.tooltip('hide');
|
||||
if (OC.Share.Social.Collection.size() == 0) {
|
||||
if (OC.Share.Social.Collection.size() === 0) {
|
||||
$input.attr('data-original-title', t('core', 'Copy'))
|
||||
.tooltip('fixTitle');
|
||||
} else {
|
||||
|
|
65
js/vote.js
|
@ -1,12 +1,23 @@
|
|||
/** global: Clipboard */
|
||||
var newUserDates = [];
|
||||
var newUserTypes = [];
|
||||
/* global Clipboard, Handlebars, navigator */
|
||||
|
||||
var newUserOptions = [];
|
||||
var newUserAnswers = [];
|
||||
|
||||
var maxVotes = 0;
|
||||
var valuesChanged = false;
|
||||
|
||||
var maybeAllowed = true;
|
||||
var tzOffset = new Date().getTimezoneOffset();
|
||||
|
||||
// HTML template for new comment (handlebars.js)
|
||||
var tmpl_comment = Handlebars.compile('<li class="comment flex-column"> ' +
|
||||
'<div class="authorRow user-cell flex-row"> ' +
|
||||
'<div class="avatar missing" title="{{userId}}"></div> ' +
|
||||
'<div class="author">{{displayName}}</div>' +
|
||||
'<div class="date has-tooltip live-relative-timestamp datespan" data-timestamp="{{timeStamp}}" title="{{date}}">{{relativeNow}}</div>' +
|
||||
'</div>' +
|
||||
'<div class="message wordwrap comment-content">{{comment}}</div>' +
|
||||
'</li>');
|
||||
|
||||
$.fn.switchClass = function (a, b) {
|
||||
this.removeClass(a);
|
||||
this.addClass(b);
|
||||
|
@ -16,7 +27,6 @@ $.fn.switchClass = function (a, b) {
|
|||
function updateCommentsCount() {
|
||||
$('#comment-counter').removeClass('no-comments');
|
||||
$('#comment-counter').text(parseInt($('#comment-counter').text()) +1);
|
||||
|
||||
}
|
||||
|
||||
function updateBest() {
|
||||
|
@ -64,7 +74,9 @@ function switchSidebar() {
|
|||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
var clipboard = new Clipboard('.copy-link');
|
||||
|
||||
clipboard.on('success', function(e) {
|
||||
var $input = $(e.trigger);
|
||||
$input.tooltip('hide')
|
||||
|
@ -82,6 +94,7 @@ $(document).ready(function () {
|
|||
}
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
clipboard.on('error', function (e) {
|
||||
var $input = $(e.trigger);
|
||||
var actionMsg = '';
|
||||
|
@ -100,7 +113,7 @@ $(document).ready(function () {
|
|||
.tooltip('show');
|
||||
_.delay(function () {
|
||||
$input.tooltip('hide');
|
||||
if (OC.Share.Social.Collection.size() == 0) {
|
||||
if (OC.Share.Social.Collection.size() === 0) {
|
||||
$input.attr('data-original-title', t('core', 'Copy'))
|
||||
.tooltip('fixTitle');
|
||||
} else {
|
||||
|
@ -111,6 +124,10 @@ $(document).ready(function () {
|
|||
// count how many times in each date
|
||||
updateBest();
|
||||
|
||||
if ($('#app-content').hasClass('maybedisallowed')) {
|
||||
maybeAllowed = false;
|
||||
}
|
||||
|
||||
// Temporary hack - Check if we have Nextcloud or ownCloud with an anonymous user
|
||||
var hideAvatars = false;
|
||||
if (!document.getElementById('nextcloud')) {
|
||||
|
@ -158,25 +175,25 @@ $(document).ready(function () {
|
|||
}
|
||||
}
|
||||
var check_notif = document.getElementById('check_notif');
|
||||
var newUserDates = [], newUserTypes = [];
|
||||
var newUserOptions = [], newUserAnswers = [];
|
||||
$('.poll-cell.active').each(function () {
|
||||
if($(this).hasClass('no')) {
|
||||
newUserTypes.push(0);
|
||||
newUserAnswers.push('no');
|
||||
} else if ($(this).hasClass('yes')) {
|
||||
newUserTypes.push(1);
|
||||
newUserAnswers.push('yes');
|
||||
} else if($(this).hasClass('maybe')) {
|
||||
newUserTypes.push(2);
|
||||
newUserAnswers.push('maybe');
|
||||
} else {
|
||||
newUserTypes.push(-1);
|
||||
newUserAnswers.push('no');
|
||||
}
|
||||
if (isNaN($(this).attr('data-value'))) {
|
||||
newUserDates.push($(this).attr('data-value'));
|
||||
newUserOptions.push($(this).attr('data-value'));
|
||||
} else {
|
||||
newUserDates.push(parseInt($(this).attr('data-value')));
|
||||
newUserOptions.push(parseInt($(this).attr('data-value')));
|
||||
}
|
||||
});
|
||||
form.elements.dates.value = JSON.stringify(newUserDates);
|
||||
form.elements.types.value = JSON.stringify(newUserTypes);
|
||||
form.elements.options.value = JSON.stringify(newUserOptions);
|
||||
form.elements.answers.value = JSON.stringify(newUserAnswers);
|
||||
form.elements.receiveNotifications.value = (check_notif && check_notif.checked) ? 'true' : 'false';
|
||||
form.elements.changed.value = valuesChanged ? 'true' : 'false';
|
||||
form.submit();
|
||||
|
@ -206,17 +223,7 @@ $(document).ready(function () {
|
|||
};
|
||||
$('.new-comment .icon-loading-small').show();
|
||||
$.post(form.action, data, function (data) {
|
||||
var newCommentElement = '<li class="comment flex-column"> ' +
|
||||
'<div class="authorRow user-cell flex-row"> ' +
|
||||
'<div class="avatar missing" title="' + data.userId + '"></div> ' +
|
||||
'<div class="author">' + data.displayName + '</div>' +
|
||||
'<div class="date has-tooltip live-relative-timestamp datespan" data-timestamp="' + Date.now() + '" title="' + data.date + '">' + t('polls', 'just now') + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="message wordwrap comment-content">' + data.comment + '</div>' +
|
||||
'</li>';
|
||||
|
||||
|
||||
$('#no-comments').after(newCommentElement);
|
||||
$('#no-comments').after(tmpl_comment(data));
|
||||
|
||||
if (!$('#no-comments').hasClass('hidden')) {
|
||||
$('#no-comments').addClass('hidden');
|
||||
|
@ -268,7 +275,11 @@ $(document).on('click', '.toggle-cell, .poll-cell.active', function () {
|
|||
$nextClass = 'no';
|
||||
$toggleAllClasses= 'yes';
|
||||
} else if($(this).hasClass('no')) {
|
||||
$nextClass = 'maybe';
|
||||
if (maybeAllowed) {
|
||||
$nextClass = 'maybe';
|
||||
} else {
|
||||
$nextClass = 'yes';
|
||||
}
|
||||
$toggleAllClasses= 'no';
|
||||
} else if($(this).hasClass('maybe')) {
|
||||
$nextClass = 'yes';
|
||||
|
|
|
@ -68,4 +68,4 @@
|
|||
"You are not allowed to edit this poll or the poll does not exist." : "Sinulla ei ole oikeutta muokata tätä kyselyä tai kyselyä ei ole olemassa.",
|
||||
"You are not allowed to delete this poll or the poll does not exist." : "Sinulla ei ole oikeutta poistaa tätä kyselyä tai kyselyä ei ole olemassa."
|
||||
},"pluralForm" :"nplurals=2; plural=(n != 1);"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,10 @@ namespace OCA\Polls\AppInfo;
|
|||
|
||||
use OCA\Polls\Controller\PageController;
|
||||
use OCA\Polls\Db\CommentMapper;
|
||||
use OCA\Polls\Db\DateMapper;
|
||||
use OCA\Polls\Db\OptionsMapper;
|
||||
use OCA\Polls\Db\EventMapper;
|
||||
use OCA\Polls\Db\NotificationMapper;
|
||||
use OCA\Polls\Db\ParticipationMapper;
|
||||
use OCA\Polls\Db\ParticipationTextMapper;
|
||||
use OCA\Polls\Db\TextMapper;
|
||||
use OCA\Polls\Db\VotesMapper;
|
||||
use OCP\AppFramework\App;
|
||||
use OCP\IContainer;
|
||||
|
||||
|
@ -49,7 +47,7 @@ class Application extends App {
|
|||
/**
|
||||
* Controllers
|
||||
*/
|
||||
$container->registerService('PageController', function (IContainer $c) {
|
||||
$container->registerService('PageController', function(IContainer $c) {
|
||||
return new PageController(
|
||||
$c->query('AppName'),
|
||||
$c->query('Request'),
|
||||
|
@ -61,84 +59,70 @@ class Application extends App {
|
|||
$c->query('ServerContainer')->getURLGenerator(),
|
||||
$c->query('UserId'),
|
||||
$c->query('CommentMapper'),
|
||||
$c->query('DateMapper'),
|
||||
$c->query('OptionsMapper'),
|
||||
$c->query('EventMapper'),
|
||||
$c->query('NotificationMapper'),
|
||||
$c->query('ParticipationMapper'),
|
||||
$c->query('ParticipationTextMapper'),
|
||||
$c->query('TextMapper')
|
||||
$c->query('VotesMapper')
|
||||
);
|
||||
});
|
||||
|
||||
$container->registerService('UserManager', function (IContainer $c) {
|
||||
$container->registerService('UserManager', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getUserManager();
|
||||
});
|
||||
|
||||
$container->registerService('GroupManager', function (IContainer $c) {
|
||||
$container->registerService('GroupManager', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getGroupManager();
|
||||
});
|
||||
|
||||
$container->registerService('AvatarManager', function (IContainer $c) {
|
||||
$container->registerService('AvatarManager', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getAvatarManager();
|
||||
});
|
||||
|
||||
$container->registerService('Logger', function (IContainer $c) {
|
||||
$container->registerService('Logger', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getLogger();
|
||||
});
|
||||
|
||||
$container->registerService('L10N', function (IContainer $c) {
|
||||
$container->registerService('L10N', function(IContainer $c) {
|
||||
return $c->query('ServerContainer')->getL10N($c->query('AppName'));
|
||||
});
|
||||
|
||||
$container->registerService('CommentMapper', function (IContainer $c) use ($server) {
|
||||
$container->registerService('CommentMapper', function(IContainer $c) use ($server) {
|
||||
return new CommentMapper(
|
||||
$server->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
|
||||
$container->registerService('DateMapper', function (IContainer $c) use ($server) {
|
||||
return new DateMapper(
|
||||
$container->registerService('OptionsMapper', function(IContainer $c) use ($server) {
|
||||
return new OptionsMapper(
|
||||
$server->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
|
||||
$container->registerService('EventMapper', function (IContainer $c) use ($server) {
|
||||
$container->registerService('EventMapper', function(IContainer $c) use ($server) {
|
||||
return new EventMapper(
|
||||
$server->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
|
||||
$container->registerService('NotificationMapper', function (IContainer $c) use ($server) {
|
||||
$container->registerService('NotificationMapper', function(IContainer $c) use ($server) {
|
||||
return new NotificationMapper(
|
||||
$server->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
|
||||
$container->registerService('ParticipationMapper', function (IContainer $c) use ($server) {
|
||||
return new ParticipationMapper(
|
||||
$container->registerService('VotesMapper', function(IContainer $c) use ($server) {
|
||||
return new VotesMapper(
|
||||
$server->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
|
||||
$container->registerService('ParticipationTextMapper', function (IContainer $c) use ($server) {
|
||||
return new ParticipationTextMapper(
|
||||
$server->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
|
||||
$container->registerService('TextMapper', function (IContainer $c) use ($server) {
|
||||
return new TextMapper(
|
||||
$server->getDatabaseConnection()
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Register navigation entry for main navigation.
|
||||
*/
|
||||
public function registerNavigationEntry() {
|
||||
$container = $this->getContainer();
|
||||
$container->query('OCP\INavigationManager')->add(function () use ($container) {
|
||||
$container->query('OCP\INavigationManager')->add(function() use ($container) {
|
||||
$urlGenerator = $container->query('OCP\IURLGenerator');
|
||||
$l10n = $container->query('OCP\IL10N');
|
||||
return [
|
||||
|
|
|
@ -0,0 +1,419 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @author René Gieling <github@dartcafe.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http;
|
||||
use OCP\AppFramework\Http\DataResponse;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IRequest;
|
||||
use OCP\IUser;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Security\ISecureRandom;
|
||||
|
||||
use OCA\Polls\Db\Event;
|
||||
use OCA\Polls\Db\EventMapper;
|
||||
use OCA\Polls\Db\Options;
|
||||
use OCA\Polls\Db\OptionsMapper;
|
||||
use OCA\Polls\Db\Votes;
|
||||
use OCA\Polls\Db\VotesMapper;
|
||||
use OCA\Polls\Db\Comment;
|
||||
use OCA\Polls\Db\CommentMapper;
|
||||
|
||||
|
||||
|
||||
class ApiController extends Controller {
|
||||
|
||||
private $eventMapper;
|
||||
private $optionsMapper;
|
||||
private $votesMapper;
|
||||
private $commentMapper;
|
||||
private $systemConfig;
|
||||
|
||||
/**
|
||||
* PageController constructor.
|
||||
* @param string $appName
|
||||
* @param IRequest $request
|
||||
* @param string $userId
|
||||
* @param EventMapper $eventMapper
|
||||
* @param OptionsMapper $optionsMapper
|
||||
* @param VotesMapper $VotesMapper
|
||||
* @param CommentMapper $CommentMapper
|
||||
*/
|
||||
public function __construct(
|
||||
$appName,
|
||||
IConfig $systemConfig,
|
||||
IGroupManager $groupManager,
|
||||
IRequest $request,
|
||||
IUserManager $userManager,
|
||||
$userId,
|
||||
EventMapper $eventMapper,
|
||||
OptionsMapper $optionsMapper,
|
||||
VotesMapper $VotesMapper,
|
||||
CommentMapper $CommentMapper
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->userId = $userId;
|
||||
$this->groupManager = $groupManager;
|
||||
$this->systemConfig = $systemConfig;
|
||||
$this->userManager = $userManager;
|
||||
$this->eventMapper = $eventMapper;
|
||||
$this->optionsMapper = $optionsMapper;
|
||||
$this->votesMapper = $VotesMapper;
|
||||
$this->commentMapper = $CommentMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function getSiteUsersAndGroups($query = '', $getGroups = true, $getUsers = true, $skipGroups = array(), $skipUsers = array()) {
|
||||
$list = array();
|
||||
$data = array();
|
||||
if ($getGroups) {
|
||||
$groups = $this->groupManager->search($query);
|
||||
foreach ($groups as $group) {
|
||||
if (!in_array($group->getGID(), $skipGroups)) {
|
||||
$list[] = [
|
||||
'id' => $group->getGID(),
|
||||
'type' => 'group',
|
||||
'displayName' => $group->getGID(),
|
||||
'avatarURL' => ''
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($getUsers) {
|
||||
$users = $this->userManager->searchDisplayName($query);
|
||||
foreach ($users as $user) {
|
||||
if (!in_array($user->getUID(), $skipUsers)) {
|
||||
$list[] = [
|
||||
'id' => $user->getUID(),
|
||||
'type' => 'user',
|
||||
'displayName' => $user->getDisplayName(),
|
||||
'avatarURL' => '',
|
||||
'lastLogin' => $user->getLastLogin(),
|
||||
'cloudId' => $user->getCloudId()
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data['siteusers'] = $list;
|
||||
return new DataResponse($data, Http::STATUS_OK);
|
||||
}
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @return Array
|
||||
*/
|
||||
function convertAccessList($item) {
|
||||
$split = Array();
|
||||
if (strpos($item, 'user_') === 0) {
|
||||
$user = $this->userManager->get(substr($item, 5));
|
||||
$split = [
|
||||
'id' => $user->getUID(),
|
||||
'type' => 'user',
|
||||
'displayName' => $user->getDisplayName(),
|
||||
'avatarURL' => ''
|
||||
];
|
||||
} elseif (strpos($item, 'group_') === 0) {
|
||||
$group = substr($item, 6);
|
||||
$group = $this->groupManager->get($group);
|
||||
$split = [
|
||||
'id' => $group->getGID(),
|
||||
'type' => 'group',
|
||||
'displayName' => $group->getDisplayName(),
|
||||
'avatarURL' => '',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
return($split);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @PublicPage
|
||||
* @param string $hash
|
||||
* @return DataResponse
|
||||
*/
|
||||
|
||||
public function getPoll($hash) {
|
||||
if (!\OC::$server->getUserSession()->getUser() instanceof IUser) {
|
||||
return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
try {
|
||||
$poll = $this->eventMapper->findByHash($hash);
|
||||
|
||||
if ($poll->getExpire() === null) {
|
||||
$expired = false;
|
||||
$expiration = false;
|
||||
} else {
|
||||
$expired = time() > strtotime($poll->getExpire());
|
||||
$expiration = true;
|
||||
}
|
||||
|
||||
if ($poll->getType() == 0) {
|
||||
$pollType = 'datePoll';
|
||||
} else {
|
||||
$pollType = 'textPoll';
|
||||
};
|
||||
|
||||
if ($poll->getOwner() !== \OC::$server->getUserSession()->getUser()->getUID()) {
|
||||
$mode = 'create';
|
||||
} else {
|
||||
$mode = 'edit';
|
||||
}
|
||||
$accessList = Array();
|
||||
$accessType = $poll->getAccess();
|
||||
if (!strpos('|public|hidden|registered', $accessType)) {
|
||||
$accessList = explode(';',$accessType);
|
||||
$accessList = array_filter($accessList);
|
||||
$accessList = array_map(Array($this,'convertAccessList'), $accessList);
|
||||
$accessType = 'select';
|
||||
}
|
||||
|
||||
$data = array();
|
||||
$commentsList = array();
|
||||
$optionList = array();
|
||||
$votesList = array();
|
||||
|
||||
} catch (DoesNotExistException $e) {
|
||||
return new DataResponse($e, Http::STATUS_NOT_FOUND);
|
||||
};
|
||||
|
||||
|
||||
try {
|
||||
$options = $this->optionsMapper->findByPoll($poll->getId());
|
||||
foreach ($options as $optionElement) {
|
||||
$optionList[] = [
|
||||
'id' => $optionElement->getId(),
|
||||
'text' => $optionElement->getPollOptionText(),
|
||||
'timestamp' => $optionElement->getTimestamp()
|
||||
];
|
||||
};
|
||||
} catch (DoesNotExistException $e) {
|
||||
// ignore
|
||||
};
|
||||
|
||||
try {
|
||||
$votes = $this->votesMapper->findByPoll($poll->getId());
|
||||
foreach ($votes as $voteElement) {
|
||||
$votesList[] = [
|
||||
'id' => $voteElement->getId(),
|
||||
'userId' => $voteElement->getUserId(),
|
||||
'voteOptionId' => $voteElement->getVoteOptionId(),
|
||||
'voteOptionText' => $voteElement->getVoteOptionText(),
|
||||
'voteAnswer' => $voteElement->getVoteAnswer()
|
||||
];
|
||||
};
|
||||
} catch (DoesNotExistException $e) {
|
||||
// ignore
|
||||
};
|
||||
|
||||
try {
|
||||
$comments = $this->commentMapper->findByPoll($poll->getId());
|
||||
foreach ($comments as $commentElement) {
|
||||
$commentsList[] = [
|
||||
'id' => $commentElement->getId(),
|
||||
'userId' => $commentElement->getUserId(),
|
||||
'date' => $commentElement->getDt() . ' UTC',
|
||||
'comment' => $commentElement->getComment()
|
||||
];
|
||||
};
|
||||
} catch (DoesNotExistException $e) {
|
||||
// ignore
|
||||
};
|
||||
|
||||
$data['poll'] = [
|
||||
'result' => 'found',
|
||||
'mode' => $mode,
|
||||
'comments' => $commentsList,
|
||||
'votes' => $votesList,
|
||||
'shares' => $accessList,
|
||||
'event' => [
|
||||
'id' => $poll->getId(),
|
||||
'hash' => $hash,
|
||||
'type' => $pollType,
|
||||
'title' => $poll->getTitle(),
|
||||
'description' => $poll->getDescription(),
|
||||
'owner' => $poll->getOwner(),
|
||||
'created' => $poll->getCreated(),
|
||||
'access' => $accessType,
|
||||
'expiration' => $expiration,
|
||||
'expired' => $expired,
|
||||
'expirationDate' => $poll->getExpire(),
|
||||
'isAnonymous' => $poll->getIsAnonymous(),
|
||||
'fullAnonymous' => $poll->getFullAnonymous(),
|
||||
'disallowMaybe' => $poll->getDisallowMaybe()
|
||||
],
|
||||
'options' => [
|
||||
'pollDates' => [],
|
||||
'pollTexts' => $optionList
|
||||
]
|
||||
];
|
||||
|
||||
return new DataResponse($data, Http::STATUS_OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @param string $poll
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function writePoll($event, $options, $shares, $mode) {
|
||||
$user = \OC::$server->getUserSession()->getUser();
|
||||
|
||||
if (!$user instanceof IUser) {
|
||||
return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
$userId = \OC::$server->getUserSession()->getUser()->getUID();
|
||||
|
||||
$newEvent = new Event();
|
||||
|
||||
// Set the configuration options entered by the user
|
||||
$newEvent->setTitle($event['title']);
|
||||
$newEvent->setDescription($event['description']);
|
||||
|
||||
$newEvent->setType($event['type']);
|
||||
$newEvent->setIsAnonymous($event['isAnonymous']);
|
||||
$newEvent->setFullAnonymous($event['fullAnonymous']);
|
||||
$newEvent->setDisallowMaybe($event['disallowMaybe']);
|
||||
|
||||
if ($event['access'] === 'select') {
|
||||
$shareAccess = '';
|
||||
foreach ($shares as $shareElement) {
|
||||
if ($shareElement['type'] === 'user') {
|
||||
$shareAccess = $shareAccess . 'user_' . $shareElement['id'] . ';';
|
||||
} elseif ($shareElement['type'] === 'group') {
|
||||
$shareAccess = $shareAccess . 'group_' . $shareElement['id'] . ';';
|
||||
}
|
||||
}
|
||||
$newEvent->setAccess(rtrim($shareAccess, ';'));
|
||||
} else {
|
||||
$newEvent->setAccess($event['access']);
|
||||
}
|
||||
|
||||
if ($event['expiration']) {
|
||||
$newEvent->setExpire($event['expirationDate']);
|
||||
} else {
|
||||
$newEvent->setExpire(null);
|
||||
}
|
||||
|
||||
if ($event['type'] === 'datePoll') {
|
||||
$newEvent->setType(0);
|
||||
} elseif ($event['type'] === 'textPoll') {
|
||||
$newEvent->setType(1);
|
||||
}
|
||||
|
||||
if ($mode === 'edit') {
|
||||
// Edit existing poll
|
||||
$oldPoll = $this->eventMapper->findByHash($event['hash']);
|
||||
|
||||
// Check if current user is allowed to edit existing poll
|
||||
if ($oldPoll->getOwner() !== $userId) {
|
||||
// If current user is not owner of existing poll deny access
|
||||
return new DataResponse(null, Http::STATUS_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
// else take owner, hash and id of existing poll
|
||||
$newEvent->setOwner($oldPoll->getOwner());
|
||||
$newEvent->setHash($oldPoll->getHash());
|
||||
$newEvent->setId($oldPoll->getId());
|
||||
$this->eventMapper->update($newEvent);
|
||||
$this->optionsMapper->deleteByPoll($newEvent->getId());
|
||||
|
||||
} elseif ($mode === 'create') {
|
||||
// Create new poll
|
||||
// Define current user as owner, set new creation date and create a new hash
|
||||
$newEvent->setOwner($userId);
|
||||
$newEvent->setCreated(date('Y-m-d H:i:s'));
|
||||
$newEvent->setHash(\OC::$server->getSecureRandom()->generate(
|
||||
16,
|
||||
ISecureRandom::CHAR_DIGITS .
|
||||
ISecureRandom::CHAR_LOWER .
|
||||
ISecureRandom::CHAR_UPPER
|
||||
));
|
||||
$newEvent = $this->eventMapper->insert($newEvent);
|
||||
}
|
||||
|
||||
// Update options
|
||||
if ($event['type'] === 'datePoll') {
|
||||
foreach ($options['pollDates'] as $optionElement) {
|
||||
$newOption = new Options();
|
||||
|
||||
$newOption->setPollId($newEvent->getId());
|
||||
$newOption->setPollOptionText(date('Y-m-d H:i:s', $optionElement['timestamp']));
|
||||
$newOption->setTimestamp($optionElement['timestamp']);
|
||||
|
||||
$this->optionsMapper->insert($newOption);
|
||||
}
|
||||
} elseif ($event['type'] === "textPoll") {
|
||||
foreach ($options['pollTexts'] as $optionElement) {
|
||||
$newOption = new Options();
|
||||
|
||||
$newOption->setPollId($newEvent->getId());
|
||||
$newOption->setpollOptionText(htmlspecialchars($optionElement['text']));
|
||||
|
||||
$this->optionsMapper->insert($newOption);
|
||||
}
|
||||
}
|
||||
return new DataResponse(array(
|
||||
'id' => $newEvent->getId(),
|
||||
'hash' => $newEvent->getHash()
|
||||
), Http::STATUS_OK);
|
||||
|
||||
}
|
||||
|
||||
private function getVendor() {
|
||||
// this should really be a JSON file
|
||||
require \OC::$SERVERROOT . '/version.php';
|
||||
/** @var string $vendor */
|
||||
return (string) $vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @return DataResponse
|
||||
*/
|
||||
public function getSystem() {
|
||||
$userId = \OC::$server->getUserSession()->getUser()->getUID();
|
||||
$data['system'] = [
|
||||
'versionArray' => \OCP\Util::getVersion(),
|
||||
'version' => implode('.', \OCP\Util::getVersion()),
|
||||
'vendor' => $this->getVendor(),
|
||||
'language' => $this->systemConfig->getUserValue($userId, 'core', 'lang')
|
||||
];
|
||||
return new DataResponse($data, Http::STATUS_OK);
|
||||
}
|
||||
}
|
|
@ -25,18 +25,14 @@ namespace OCA\Polls\Controller;
|
|||
|
||||
use OCA\Polls\Db\Comment;
|
||||
use OCA\Polls\Db\CommentMapper;
|
||||
use OCA\Polls\Db\Date;
|
||||
use OCA\Polls\Db\DateMapper;
|
||||
use OCA\Polls\Db\Event;
|
||||
use OCA\Polls\Db\EventMapper;
|
||||
use OCA\Polls\Db\Notification;
|
||||
use OCA\Polls\Db\NotificationMapper;
|
||||
use OCA\Polls\Db\Participation;
|
||||
use OCA\Polls\Db\ParticipationMapper;
|
||||
use OCA\Polls\Db\ParticipationText;
|
||||
use OCA\Polls\Db\ParticipationTextMapper;
|
||||
use OCA\Polls\Db\Text;
|
||||
use OCA\Polls\Db\TextMapper;
|
||||
use OCA\Polls\Db\Options;
|
||||
use OCA\Polls\Db\OptionsMapper;
|
||||
use OCA\Polls\Db\Votes;
|
||||
use OCA\Polls\Db\VotesMapper;
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
|
@ -52,19 +48,17 @@ use OCP\IURLGenerator;
|
|||
use OCP\IUserManager;
|
||||
use OCP\Mail\IMailer;
|
||||
use OCP\Security\ISecureRandom;
|
||||
use OCP\User;
|
||||
use OCP\User; //To do: replace according to API
|
||||
use OCP\Util;
|
||||
|
||||
class PageController extends Controller {
|
||||
|
||||
private $userId;
|
||||
private $commentMapper;
|
||||
private $dateMapper;
|
||||
private $eventMapper;
|
||||
private $notificationMapper;
|
||||
private $participationMapper;
|
||||
private $participationTextMapper;
|
||||
private $textMapper;
|
||||
private $optionsMapper;
|
||||
private $votesMapper;
|
||||
private $urlGenerator;
|
||||
private $userMgr;
|
||||
private $avatarManager;
|
||||
|
@ -84,12 +78,10 @@ class PageController extends Controller {
|
|||
* @param IURLGenerator $urlGenerator
|
||||
* @param string $userId
|
||||
* @param CommentMapper $commentMapper
|
||||
* @param DateMapper $dateMapper
|
||||
* @param EventMapper $eventMapper
|
||||
* @param NotificationMapper $notificationMapper
|
||||
* @param ParticipationMapper $ParticipationMapper
|
||||
* @param ParticipationTextMapper $ParticipationTextMapper
|
||||
* @param TextMapper $textMapper
|
||||
* @param OptionsMapper $optionsMapper
|
||||
* @param VotesMapper $VotesMapper
|
||||
*/
|
||||
public function __construct(
|
||||
$appName,
|
||||
|
@ -102,12 +94,10 @@ class PageController extends Controller {
|
|||
IURLGenerator $urlGenerator,
|
||||
$userId,
|
||||
CommentMapper $commentMapper,
|
||||
DateMapper $dateMapper,
|
||||
OptionsMapper $optionsMapper,
|
||||
EventMapper $eventMapper,
|
||||
NotificationMapper $notificationMapper,
|
||||
ParticipationMapper $ParticipationMapper,
|
||||
ParticipationTextMapper $ParticipationTextMapper,
|
||||
TextMapper $textMapper
|
||||
VotesMapper $VotesMapper
|
||||
) {
|
||||
parent::__construct($appName, $request);
|
||||
$this->userMgr = $userMgr;
|
||||
|
@ -118,12 +108,10 @@ class PageController extends Controller {
|
|||
$this->urlGenerator = $urlGenerator;
|
||||
$this->userId = $userId;
|
||||
$this->commentMapper = $commentMapper;
|
||||
$this->dateMapper = $dateMapper;
|
||||
$this->eventMapper = $eventMapper;
|
||||
$this->notificationMapper = $notificationMapper;
|
||||
$this->participationMapper = $ParticipationMapper;
|
||||
$this->participationTextMapper = $ParticipationTextMapper;
|
||||
$this->textMapper = $textMapper;
|
||||
$this->optionsMapper = $optionsMapper;
|
||||
$this->votesMapper = $VotesMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,13 +121,11 @@ class PageController extends Controller {
|
|||
public function index() {
|
||||
$polls = $this->eventMapper->findAllForUserWithInfo($this->userId);
|
||||
$comments = $this->commentMapper->findDistinctByUser($this->userId);
|
||||
$partic = $this->participationMapper->findDistinctByUser($this->userId);
|
||||
$particText = $this->participationTextMapper->findDistinctByUser($this->userId);
|
||||
$votes = $this->votesMapper->findDistinctByUser($this->userId);
|
||||
$response = new TemplateResponse('polls', 'main.tmpl', [
|
||||
'polls' => $polls,
|
||||
'comments' => $comments,
|
||||
'participations' => $partic,
|
||||
'participations_text' => $particText,
|
||||
'votes' => $votes,
|
||||
'userId' => $this->userId,
|
||||
'userMgr' => $this->userMgr,
|
||||
'urlGenerator' => $this->urlGenerator
|
||||
|
@ -224,16 +210,11 @@ class PageController extends Controller {
|
|||
} catch (DoesNotExistException $e) {
|
||||
return new TemplateResponse('polls', 'no.acc.tmpl', []);
|
||||
}
|
||||
if ($poll->getType() === 0) {
|
||||
$dates = $this->dateMapper->findByPoll($poll->getId());
|
||||
$votes = $this->participationMapper->findByPoll($poll->getId());
|
||||
$participants = $this->participationMapper->findParticipantsByPoll($poll->getId());
|
||||
} else {
|
||||
$dates = $this->textMapper->findByPoll($poll->getId());
|
||||
$votes = $this->participationTextMapper->findByPoll($poll->getId());
|
||||
$participants = $this->participationTextMapper->findParticipantsByPoll($poll->getId());
|
||||
}
|
||||
$options = $this->optionsMapper->findByPoll($poll->getId());
|
||||
$votes = $this->votesMapper->findByPoll($poll->getId());
|
||||
$participants = $this->votesMapper->findParticipantsByPoll($poll->getId());
|
||||
$comments = $this->commentMapper->findByPoll($poll->getId());
|
||||
|
||||
try {
|
||||
$notification = $this->notificationMapper->findByUserAndPoll($poll->getId(), $this->userId);
|
||||
} catch (DoesNotExistException $e) {
|
||||
|
@ -242,10 +223,10 @@ class PageController extends Controller {
|
|||
if ($this->hasUserAccess($poll)) {
|
||||
return new TemplateResponse('polls', 'goto.tmpl', [
|
||||
'poll' => $poll,
|
||||
'dates' => $dates,
|
||||
'options' => $options,
|
||||
'comments' => $comments,
|
||||
'votes' => $votes,
|
||||
'participants' => $participants,
|
||||
'participant' => $participants,
|
||||
'notification' => $notification,
|
||||
'userId' => $this->userId,
|
||||
'userMgr' => $this->userMgr,
|
||||
|
@ -272,10 +253,8 @@ class PageController extends Controller {
|
|||
$poll = new Event();
|
||||
$poll->setId($pollId);
|
||||
$this->eventMapper->delete($poll);
|
||||
$this->textMapper->deleteByPoll($pollId);
|
||||
$this->dateMapper->deleteByPoll($pollId);
|
||||
$this->participationMapper->deleteByPoll($pollId);
|
||||
$this->participationTextMapper->deleteByPoll($pollId);
|
||||
$this->optionsMapper->deleteByPoll($pollId);
|
||||
$this->votesMapper->deleteByPoll($pollId);
|
||||
$this->commentMapper->deleteByPoll($pollId);
|
||||
$url = $this->urlGenerator->linkToRoute('polls.page.index');
|
||||
return new RedirectResponse($url);
|
||||
|
@ -288,227 +267,19 @@ class PageController extends Controller {
|
|||
* @return TemplateResponse
|
||||
*/
|
||||
public function editPoll($hash) {
|
||||
$poll = $this->eventMapper->findByHash($hash);
|
||||
if ($this->userId !== $poll->getOwner()) {
|
||||
return new TemplateResponse('polls', 'no.create.tmpl');
|
||||
}
|
||||
if ($poll->getType() === 0) {
|
||||
$dates = $this->dateMapper->findByPoll($poll->getId());
|
||||
} else {
|
||||
$dates = $this->textMapper->findByPoll($poll->getId());
|
||||
}
|
||||
return new TemplateResponse('polls', 'create.tmpl', [
|
||||
'poll' => $poll,
|
||||
'dates' => $dates,
|
||||
'userId' => $this->userId,
|
||||
'userMgr' => $this->userMgr,
|
||||
'urlGenerator' => $this->urlGenerator
|
||||
'urlGenerator' => $this->urlGenerator,
|
||||
'hash' => $hash
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @param int $pollId
|
||||
* @param string $pollType
|
||||
* @param string $pollTitle
|
||||
* @param string $pollDesc
|
||||
* @param string $userId
|
||||
* @param string $chosenDates
|
||||
* @param int $expireTs
|
||||
* @param string $accessType
|
||||
* @param string $accessValues
|
||||
* @param bool $isAnonymous
|
||||
* @param bool $hideNames
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function updatePoll(
|
||||
$pollId,
|
||||
$pollType,
|
||||
$pollTitle,
|
||||
$pollDesc,
|
||||
$userId,
|
||||
$chosenDates,
|
||||
$expireTs,
|
||||
$accessType,
|
||||
$accessValues,
|
||||
$isAnonymous,
|
||||
$hideNames
|
||||
) {
|
||||
|
||||
|
||||
$event = $this->eventMapper->find($pollId);
|
||||
$event->setTitle($pollTitle);
|
||||
$event->setDescription($pollDesc);
|
||||
$event->setIsAnonymous($isAnonymous ? 1 : 0);
|
||||
$event->setFullAnonymous($isAnonymous && $hideNames ? 1 : 0);
|
||||
|
||||
if ($accessType === 'select') {
|
||||
if (isset($accessValues)) {
|
||||
$accessValues = json_decode($accessValues);
|
||||
if ($accessValues !== null) {
|
||||
$groups = array();
|
||||
$users = array();
|
||||
if ($accessValues->groups !== null) {
|
||||
$groups = $accessValues->groups;
|
||||
}
|
||||
if ($accessValues->users !== null) {
|
||||
$users = $accessValues->users;
|
||||
}
|
||||
$accessType = '';
|
||||
foreach ($groups as $gid) {
|
||||
$accessType .= $gid . ';';
|
||||
}
|
||||
foreach ($users as $uid) {
|
||||
$accessType .= $uid . ';';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$event->setAccess($accessType);
|
||||
/** @var string[] $chosenDates */
|
||||
$chosenDates = json_decode($chosenDates);
|
||||
|
||||
$expire = null;
|
||||
if ($expireTs !== 0 && $expireTs !== '') {
|
||||
$expire = date('Y-m-d H:i:s', $expireTs);
|
||||
}
|
||||
$event->setExpire($expire);
|
||||
|
||||
$this->dateMapper->deleteByPoll($pollId);
|
||||
$this->textMapper->deleteByPoll($pollId);
|
||||
if ($pollType === 'event') {
|
||||
$event->setType(0);
|
||||
$this->eventMapper->update($event);
|
||||
sort($chosenDates);
|
||||
foreach ($chosenDates as $el) {
|
||||
$date = new Date();
|
||||
$date->setPollId($pollId);
|
||||
$date->setDt(date('Y-m-d H:i:s', $el));
|
||||
$this->dateMapper->insert($date);
|
||||
}
|
||||
} else {
|
||||
$event->setType(1);
|
||||
$this->eventMapper->update($event);
|
||||
foreach ($chosenDates as $el) {
|
||||
$text = new Text();
|
||||
$text->setPollId($pollId);
|
||||
$text->setText($el);
|
||||
$this->textMapper->insert($text);
|
||||
}
|
||||
}
|
||||
$url = $this->urlGenerator->linkToRoute('polls.page.index');
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
*/
|
||||
public function createPoll() {
|
||||
return new TemplateResponse('polls', 'create.tmpl',
|
||||
['userId' => $this->userId, 'userMgr' => $this->userMgr, 'urlGenerator' => $this->urlGenerator]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
* @NoCSRFRequired
|
||||
* @param string $pollType
|
||||
* @param string $pollTitle
|
||||
* @param string $pollDesc
|
||||
* @param string $userId
|
||||
* @param string $chosenDates
|
||||
* @param int $expireTs
|
||||
* @param string $accessType
|
||||
* @param string $accessValues
|
||||
* @param bool $isAnonymous
|
||||
* @param bool $hideNames
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function insertPoll(
|
||||
$pollType,
|
||||
$pollTitle,
|
||||
$pollDesc,
|
||||
$userId,
|
||||
$chosenDates,
|
||||
$expireTs,
|
||||
$accessType,
|
||||
$accessValues,
|
||||
$isAnonymous,
|
||||
$hideNames
|
||||
) {
|
||||
$event = new Event();
|
||||
$event->setTitle($pollTitle);
|
||||
$event->setDescription($pollDesc);
|
||||
$event->setOwner($userId);
|
||||
$event->setCreated(date('Y-m-d H:i:s'));
|
||||
$event->setHash(\OC::$server->getSecureRandom()->generate(
|
||||
16,
|
||||
ISecureRandom::CHAR_DIGITS .
|
||||
ISecureRandom::CHAR_LOWER .
|
||||
ISecureRandom::CHAR_UPPER
|
||||
));
|
||||
$event->setIsAnonymous($isAnonymous ? 1 : 0);
|
||||
$event->setFullAnonymous($isAnonymous && $hideNames ? 1 : 0);
|
||||
|
||||
if ($accessType === 'select') {
|
||||
if (isset($accessValues)) {
|
||||
$accessValues = json_decode($accessValues);
|
||||
if ($accessValues !== null) {
|
||||
$groups = array();
|
||||
$users = array();
|
||||
if ($accessValues->groups !== null) {
|
||||
$groups = $accessValues->groups;
|
||||
}
|
||||
if ($accessValues->users !== null) {
|
||||
$users = $accessValues->users;
|
||||
}
|
||||
$accessType = '';
|
||||
foreach ($groups as $gid) {
|
||||
$accessType .= $gid . ';';
|
||||
}
|
||||
foreach ($users as $uid) {
|
||||
$accessType .= $uid . ';';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$event->setAccess($accessType);
|
||||
/** @var string[] $chosenDates */
|
||||
$chosenDates = json_decode($chosenDates);
|
||||
|
||||
$expire = null;
|
||||
if ($expireTs !== 0 && $expireTs !== '') {
|
||||
$expire = date('Y-m-d H:i:s', $expireTs);
|
||||
}
|
||||
$event->setExpire($expire);
|
||||
|
||||
if ($pollType === 'event') {
|
||||
$event->setType(0);
|
||||
$ins = $this->eventMapper->insert($event);
|
||||
$pollId = $ins->getId();
|
||||
sort($chosenDates);
|
||||
foreach ($chosenDates as $el) {
|
||||
$date = new Date();
|
||||
$date->setPollId($pollId);
|
||||
$date->setDt(date('Y-m-d H:i:s', $el));
|
||||
$this->dateMapper->insert($date);
|
||||
}
|
||||
} else {
|
||||
$event->setType(1);
|
||||
$ins = $this->eventMapper->insert($event);
|
||||
$pollId = $ins->getId();
|
||||
$cnt = 1;
|
||||
foreach ($chosenDates as $el) {
|
||||
$text = new Text();
|
||||
$text->setPollId($pollId);
|
||||
$text->setText($el . '_' . $cnt);
|
||||
$this->textMapper->insert($text);
|
||||
$cnt++;
|
||||
}
|
||||
}
|
||||
$url = $this->urlGenerator->linkToRoute('polls.page.index');
|
||||
return new RedirectResponse($url);
|
||||
['urlGenerator' => $this->urlGenerator]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -517,13 +288,13 @@ class PageController extends Controller {
|
|||
* @PublicPage
|
||||
* @param int $pollId
|
||||
* @param string $userId
|
||||
* @param string $types
|
||||
* @param string $dates
|
||||
* @param string $answers
|
||||
* @param string $options
|
||||
* @param bool $receiveNotifications
|
||||
* @param bool $changed
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function insertVote($pollId, $userId, $types, $dates, $receiveNotifications, $changed) {
|
||||
public function insertVote($pollId, $userId, $answers, $options, $receiveNotifications, $changed) {
|
||||
if ($this->userId !== null) {
|
||||
if ($receiveNotifications) {
|
||||
try {
|
||||
|
@ -547,31 +318,20 @@ class PageController extends Controller {
|
|||
}
|
||||
}
|
||||
$poll = $this->eventMapper->find($pollId);
|
||||
|
||||
if ($changed) {
|
||||
$dates = json_decode($dates);
|
||||
$types = json_decode($types);
|
||||
$count_dates = count($dates);
|
||||
if ($poll->getType() === 0) {
|
||||
$this->participationMapper->deleteByPollAndUser($pollId, $userId);
|
||||
} else {
|
||||
$this->participationTextMapper->deleteByPollAndUser($pollId, $userId);
|
||||
}
|
||||
for ($i = 0; $i < $count_dates; $i++) {
|
||||
if ($poll->getType() === 0) {
|
||||
$part = new Participation();
|
||||
$part->setPollId($pollId);
|
||||
$part->setUserId($userId);
|
||||
$part->setDt(date('Y-m-d H:i:s', $dates[$i]));
|
||||
$part->setType($types[$i]);
|
||||
$this->participationMapper->insert($part);
|
||||
} else {
|
||||
$part = new ParticipationText();
|
||||
$part->setPollId($pollId);
|
||||
$part->setUserId($userId);
|
||||
$part->setText($dates[$i]);
|
||||
$part->setType($types[$i]);
|
||||
$this->participationTextMapper->insert($part);
|
||||
}
|
||||
$options = json_decode($options);
|
||||
$answers = json_decode($answers);
|
||||
$count_options = count($options);
|
||||
$this->votesMapper->deleteByPollAndUser($pollId, $userId);
|
||||
|
||||
for ($i = 0; $i < $count_options; $i++) {
|
||||
$vote = new Votes();
|
||||
$vote->setPollId($pollId);
|
||||
$vote->setUserId($userId);
|
||||
$vote->setVoteOptionText(htmlspecialchars($options[$i]));
|
||||
$vote->setVoteAnswer($answers[$i]);
|
||||
$this->votesMapper->insert($vote);
|
||||
|
||||
}
|
||||
$this->sendNotifications($pollId, $userId);
|
||||
|
@ -598,16 +358,19 @@ class PageController extends Controller {
|
|||
$comment->setDt(date('Y-m-d H:i:s'));
|
||||
$this->commentMapper->insert($comment);
|
||||
$this->sendNotifications($pollId, $userId);
|
||||
$timeStamp = time();
|
||||
$displayName = $userId;
|
||||
$user = $this->userMgr->get($userId);
|
||||
if ($user !== null) {
|
||||
$displayName = $user->getDisplayName();
|
||||
}
|
||||
return new JSONResponse(array(
|
||||
'comment' => $commentBox,
|
||||
'date' => date('Y-m-d H:i:s'),
|
||||
'userId' => $userId,
|
||||
'displayName' => $displayName
|
||||
'displayName' => $displayName,
|
||||
'timeStamp' => $timeStamp * 100,
|
||||
'date' => date('Y-m-d H:i:s', $timeStamp),
|
||||
'relativeNow' => $this->trans->t('just now'),
|
||||
'comment' => $commentBox
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -666,15 +429,15 @@ class PageController extends Controller {
|
|||
$sUsers[] = str_replace('user_', '', $su);
|
||||
}
|
||||
foreach ($userNames as $u) {
|
||||
$alreadyAdded = false;
|
||||
$allreadyAdded = false;
|
||||
foreach ($sUsers as &$su) {
|
||||
if ($su === $u->getUID()) {
|
||||
unset($su);
|
||||
$alreadyAdded = true;
|
||||
$allreadyAdded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$alreadyAdded) {
|
||||
if (!$allreadyAdded) {
|
||||
$users[] = array('uid' => $u->getUID(), 'displayName' => $u->getDisplayName(), 'isGroup' => false);
|
||||
} else {
|
||||
continue;
|
||||
|
@ -703,12 +466,14 @@ class PageController extends Controller {
|
|||
}
|
||||
// Nextcloud >= 12
|
||||
$groups = $this->groupManager->getUserGroups(\OC::$server->getUserSession()->getUser());
|
||||
return array_map(function ($group) {
|
||||
return array_map(function($group) {
|
||||
return $group->getGID();
|
||||
}, $groups);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user has access to this poll
|
||||
*
|
||||
* @param Event $poll
|
||||
* @return bool
|
||||
*/
|
||||
|
@ -749,4 +514,20 @@ class PageController extends Controller {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Check if user is owner of this poll
|
||||
*
|
||||
* @param Event $poll
|
||||
* @return bool
|
||||
*/
|
||||
|
||||
private function userIsOwner($poll) {
|
||||
$owner = $poll->getOwner();
|
||||
|
||||
if ($owner === $this->userId) {
|
||||
return true;
|
||||
}
|
||||
Util::writeLog('polls', $this->userId, Util::ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* @method string getUserId()
|
||||
* @method void setUserId(string $value)
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
use OCP\AppFramework\Db\Mapper;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class DateMapper extends Mapper {
|
||||
|
||||
/**
|
||||
* DateMapper constructor.
|
||||
* @param IDBConnection $db
|
||||
*/
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, 'polls_dts', '\OCA\Polls\Db\Date');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pollId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return Date[]
|
||||
*/
|
||||
public function findByPoll($pollId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT * FROM ' . $this->getTableName() . ' WHERE poll_id = ?';
|
||||
return $this->findEntities($sql, [$pollId], $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pollId
|
||||
*/
|
||||
public function deleteByPoll($pollId) {
|
||||
$sql = 'DELETE FROM ' . $this->getTableName() . ' WHERE poll_id = ?';
|
||||
$this->execute($sql, [$pollId]);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* @method integer getType()
|
||||
* @method void setType(integer $value)
|
||||
|
@ -45,6 +47,8 @@ namespace OCA\Polls\Db;
|
|||
* @method void setIsAnonymous(integer $value)
|
||||
* @method integer getFullAnonymous()
|
||||
* @method void setFullAnonymous(integer $value)
|
||||
* @method integer getDisallowMaybe()
|
||||
* @method void setDisallowMaybe(integer $value)
|
||||
*/
|
||||
class Event extends Model {
|
||||
protected $type;
|
||||
|
@ -57,6 +61,7 @@ class Event extends Model {
|
|||
protected $hash;
|
||||
protected $isAnonymous;
|
||||
protected $fullAnonymous;
|
||||
protected $disallowMaybe;
|
||||
|
||||
/**
|
||||
* Event constructor.
|
||||
|
@ -65,5 +70,6 @@ class Event extends Model {
|
|||
$this->addType('type', 'integer');
|
||||
$this->addType('isAnonymous', 'integer');
|
||||
$this->addType('fullAnonymous', 'integer');
|
||||
$this->addType('disallowMaybe', 'integer');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,8 +90,8 @@ class EventMapper extends Mapper {
|
|||
*PREFIX*polls_events.is_anonymous,
|
||||
*PREFIX*polls_events.full_anonymous
|
||||
FROM *PREFIX*polls_events
|
||||
LEFT JOIN *PREFIX*polls_particip
|
||||
ON *PREFIX*polls_events.id = *PREFIX*polls_particip.id
|
||||
LEFT JOIN *PREFIX*polls_votes
|
||||
ON *PREFIX*polls_events.id = *PREFIX*polls_votes.id
|
||||
LEFT JOIN *PREFIX*polls_comments
|
||||
ON *PREFIX*polls_events.id = *PREFIX*polls_comments.id
|
||||
WHERE
|
||||
|
@ -99,7 +99,7 @@ class EventMapper extends Mapper {
|
|||
OR
|
||||
*PREFIX*polls_events.access != ?
|
||||
OR
|
||||
*PREFIX*polls_particip.user_id = ?
|
||||
*PREFIX*polls_votes.user_id = ?
|
||||
OR
|
||||
*PREFIX*polls_comments.user_id = ?
|
||||
ORDER BY created';
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* @method string getUserId()
|
||||
* @method void setUserId(string $value)
|
||||
|
|
|
@ -24,20 +24,27 @@
|
|||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* @method string getDt()
|
||||
* @method void setDt(string $value)
|
||||
* @method integer getPollId()
|
||||
* @method void setPollId(integer $value)
|
||||
* @method string getPollOptionText()
|
||||
* @method void setPollOptionText(string $value)
|
||||
* @method string getTimestamp()
|
||||
* @method void setTimestamp(Integer $value)
|
||||
*/
|
||||
class Date extends Model {
|
||||
protected $dt;
|
||||
class Options extends Model {
|
||||
protected $pollId;
|
||||
protected $pollOptionText;
|
||||
protected $timestamp;
|
||||
|
||||
/**
|
||||
* Date constructor.
|
||||
* Options constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->addType('pollId', 'integer');
|
||||
$this->addType('pollOptionText', 'string');
|
||||
$this->addType('timestamp', 'integer');
|
||||
}
|
||||
}
|
|
@ -26,14 +26,14 @@ namespace OCA\Polls\Db;
|
|||
use OCP\AppFramework\Db\Mapper;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class TextMapper extends Mapper {
|
||||
class OptionsMapper extends Mapper {
|
||||
|
||||
/**
|
||||
* TextMapper constructor.
|
||||
* @param IDBConnection $db
|
||||
*/
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, 'polls_txts', '\OCA\Polls\Db\Text');
|
||||
parent::__construct($db, 'polls_options', '\OCA\Polls\Db\Options');
|
||||
}
|
||||
|
||||
/**
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
* @author Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
/**
|
||||
* @method string getDt()
|
||||
* @method void setDt(string $value)
|
||||
* @method string getUserId()
|
||||
* @method void setUserId(string $value)
|
||||
* @method integer getPollId()
|
||||
* @method void setPollId(integer $value)
|
||||
* @method integer getType()
|
||||
* @method void setType(integer $value)
|
||||
*/
|
||||
class Participation extends Model {
|
||||
protected $dt;
|
||||
protected $userId;
|
||||
protected $pollId;
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* Participation constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->addType('pollId', 'integer');
|
||||
$this->addType('type', 'integer');
|
||||
}
|
||||
}
|
|
@ -1,88 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
use OCP\AppFramework\Db\Mapper;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class ParticipationTextMapper extends Mapper {
|
||||
|
||||
/**
|
||||
* ParticipationTextMapper constructor.
|
||||
* @param IDBConnection $db
|
||||
*/
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, 'polls_particip_text', '\OCA\Polls\Db\ParticipationText');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pollId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return ParticipationText[]
|
||||
*/
|
||||
public function findByPoll($pollId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT * FROM ' . $this->getTableName() . ' WHERE poll_id = ?';
|
||||
return $this->findEntities($sql, [$pollId], $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return ParticipationText[]
|
||||
*/
|
||||
public function findDistinctByUser($userId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT DISTINCT * FROM ' . $this->getTableName() . ' WHERE user_id = ?';
|
||||
return $this->findEntities($sql, [$userId], $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pollId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return ParticipationText[]
|
||||
*/
|
||||
public function findParticipantsByPoll($pollId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT DISTINCT user_id FROM ' . $this->getTableName() . ' WHERE poll_id = ?';
|
||||
return $this->findEntities($sql, [$pollId], $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pollId
|
||||
*/
|
||||
public function deleteByPoll($pollId) {
|
||||
$sql = 'DELETE FROM ' . $this->getTableName() . ' WHERE poll_id = ?';
|
||||
$this->execute($sql, [$pollId]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $pollId
|
||||
* @param string $userId
|
||||
*/
|
||||
public function deleteByPollAndUser($pollId, $userId) {
|
||||
$sql = 'DELETE FROM ' . $this->getTableName() . ' WHERE poll_id = ? AND user_id = ?';
|
||||
$this->execute($sql, [$pollId, $userId]);
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
* @author Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
/**
|
||||
* @method string getText()
|
||||
* @method void setText(string $value)
|
||||
* @method integer getPollId()
|
||||
* @method void setPollId(integer $value)
|
||||
*/
|
||||
class Text extends Model {
|
||||
protected $text;
|
||||
protected $pollId;
|
||||
|
||||
/**
|
||||
* Text constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->addType('pollId', 'integer');
|
||||
}
|
||||
}
|
|
@ -24,27 +24,32 @@
|
|||
|
||||
namespace OCA\Polls\Db;
|
||||
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
|
||||
/**
|
||||
* @method text getText()
|
||||
* @method void setText(text $value)
|
||||
* @method string getUserId()
|
||||
* @method void setUserId(string $value)
|
||||
* @method integer getPollId()
|
||||
* @method void setPollId(integer $value)
|
||||
* @method integer getType()
|
||||
* @method void setType(integer $value)
|
||||
* @method string getUserId()
|
||||
* @method void setUserId(string $value)
|
||||
* @method integer getVoteOptionId()
|
||||
* @method void setVoteOptionId(integer $value)
|
||||
* @method integer getVoteOptionText()
|
||||
* @method void setVoteOptionText(string $value)
|
||||
* @method integer getVoteAnswer()
|
||||
* @method void setVoteAnswer(string $value)
|
||||
*/
|
||||
class ParticipationText extends Model {
|
||||
protected $text;
|
||||
protected $userId;
|
||||
class Votes extends Model {
|
||||
protected $pollId;
|
||||
protected $type;
|
||||
protected $userId;
|
||||
protected $voteOptionId;
|
||||
protected $voteOptionText;
|
||||
protected $voteAnswer;
|
||||
|
||||
/**
|
||||
* ParticipationText constructor.
|
||||
* Options constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->addType('pollId', 'integer');
|
||||
$this->addType('type', 'integer');
|
||||
$this->addType('vote_type', 'integer');
|
||||
}
|
||||
}
|
|
@ -26,21 +26,21 @@ namespace OCA\Polls\Db;
|
|||
use OCP\AppFramework\Db\Mapper;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
class ParticipationMapper extends Mapper {
|
||||
class VotesMapper extends Mapper {
|
||||
|
||||
/**
|
||||
* ParticipationMapper constructor.
|
||||
* VotesMapper constructor.
|
||||
* @param IDBConnection $db
|
||||
*/
|
||||
public function __construct(IDBConnection $db) {
|
||||
parent::__construct($db, 'polls_particip', '\OCA\Polls\Db\Participation');
|
||||
parent::__construct($db, 'polls_votes', '\OCA\Polls\Db\Votes');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return Participation[]
|
||||
* @return Votes[]
|
||||
*/
|
||||
public function findDistinctByUser($userId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT DISTINCT * FROM ' . $this->getTableName() . ' WHERE user_id = ?';
|
||||
|
@ -51,7 +51,7 @@ class ParticipationMapper extends Mapper {
|
|||
* @param int $pollId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return Participation[]
|
||||
* @return Votes[]
|
||||
*/
|
||||
public function findByPoll($pollId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT * FROM ' . $this->getTableName() . ' WHERE poll_id = ?';
|
||||
|
@ -62,7 +62,7 @@ class ParticipationMapper extends Mapper {
|
|||
* @param int $pollId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @return Participation[]
|
||||
* @return Votes[]
|
||||
*/
|
||||
public function findParticipantsByPoll($pollId, $limit = null, $offset = null) {
|
||||
$sql = 'SELECT DISTINCT user_id FROM ' . $this->getTableName() . ' WHERE poll_id = ?';
|
|
@ -0,0 +1,380 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 René Gieling <github@dartcafe.de>
|
||||
*
|
||||
* @author René Gieling <github@dartcafe.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Migration;
|
||||
|
||||
use Doctrine\DBAL\Exception\TableNotFoundException;
|
||||
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
use OCP\Migration\IOutput;
|
||||
|
||||
/**
|
||||
* Installation class for the polls app.
|
||||
* Initial db creation
|
||||
*/
|
||||
class Version009000Date20171202105141 extends SimpleMigrationStep {
|
||||
|
||||
/** @var IDBConnection */
|
||||
protected $connection;
|
||||
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @param IDBConnection $connection
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(IDBConnection $connection, IConfig $config) {
|
||||
$this->connection = $connection;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if (!$schema->hasTable('polls_events')) {
|
||||
$table = $schema->createTable('polls_events');
|
||||
$table->addColumn('id', Type::INTEGER, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
]);
|
||||
$table->addColumn('hash', Type::STRING, [
|
||||
'notnull' => false,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('type', Type::BIGINT, [
|
||||
'notnull' => false,
|
||||
'length' => 16,
|
||||
]);
|
||||
$table->addColumn('title', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 128,
|
||||
]);
|
||||
$table->addColumn('description', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 1024,
|
||||
]);
|
||||
$table->addColumn('owner', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('created', Type::DATETIME, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
$table->addColumn('access', Type::STRING, [
|
||||
'notnull' => false,
|
||||
'length' => 1024,
|
||||
]);
|
||||
$table->addColumn('expire', Type::DATETIME, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
$table->addColumn('is_anonymous', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
'default' => 0,
|
||||
]);
|
||||
$table->addColumn('full_anonymous', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
'default' => 0,
|
||||
]);
|
||||
$table->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
if (!$schema->hasTable('polls_options')) {
|
||||
$table = $schema->createTable('polls_options');
|
||||
$table->addColumn('id', Type::INTEGER, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
]);
|
||||
$table->addColumn('poll_id', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
$table->addColumn('poll_option_text', Type::STRING, [
|
||||
'notnull' => false, // maybe true?
|
||||
'length' => 256,
|
||||
]);
|
||||
$table->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
if (!$schema->hasTable('polls_votes')) {
|
||||
$table = $schema->createTable('polls_votes');
|
||||
$table->addColumn('id', Type::INTEGER, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
]);
|
||||
$table->addColumn('poll_id', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
$table->addColumn('user_id', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('vote_option_id', Type::INTEGER, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('vote_option_text', Type::STRING, [
|
||||
'notnull' => false, // maybe true?
|
||||
'length' => 256,
|
||||
]);
|
||||
$table->addColumn('vote_answer', Type::STRING, [
|
||||
'notnull' => false,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
if (!$schema->hasTable('polls_comments')) {
|
||||
$table = $schema->createTable('polls_comments');
|
||||
$table->addColumn('id', Type::INTEGER, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
]);
|
||||
$table->addColumn('poll_id', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
$table->addColumn('user_id', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->addColumn('dt', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 32,
|
||||
]);
|
||||
$table->addColumn('comment', Type::STRING, [
|
||||
'notnull' => false,
|
||||
'length' => 1024,
|
||||
]);
|
||||
$table->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
if (!$schema->hasTable('polls_notif')) {
|
||||
$table = $schema->createTable('polls_notif');
|
||||
$table->addColumn('id', Type::INTEGER, [
|
||||
'autoincrement' => true,
|
||||
'notnull' => true,
|
||||
]);
|
||||
$table->addColumn('poll_id', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
]);
|
||||
$table->addColumn('user_id', Type::STRING, [
|
||||
'notnull' => true,
|
||||
'length' => 64,
|
||||
]);
|
||||
$table->setPrimaryKey(['id']);
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if ($schema->hasTable('polls_dts')) {
|
||||
$this->copyDateOptions();
|
||||
$this->copyDateVotes();
|
||||
}
|
||||
if ($schema->hasTable('polls_txts')) {
|
||||
$this->copyTextOptions();
|
||||
$this->copyTextVotes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy date options
|
||||
*/
|
||||
protected function copyDateOptions() {
|
||||
$insert = $this->connection->getQueryBuilder();
|
||||
$insert->insert('polls_options')
|
||||
->values([
|
||||
'poll_id' => $insert->createParameter('poll_id'),
|
||||
// Decide between one of both
|
||||
// 'poll_date' => $insert->createParameter('poll_date'),
|
||||
'poll_option_text' => $insert->createParameter('poll_option_text'),
|
||||
]);
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->select('*')
|
||||
->from('polls_dts');
|
||||
$result = $query->execute();
|
||||
while ($row = $result->fetch()) {
|
||||
$insert
|
||||
->setParameter('poll_id', $row['poll_id'])
|
||||
// Decide between one of both
|
||||
// ->setParameter('poll_date', $row['dt'])
|
||||
->setParameter('poll_option_text', date($row['dt']));
|
||||
$insert->execute();
|
||||
}
|
||||
$result->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy text options
|
||||
*/
|
||||
protected function copyTextOptions() {
|
||||
$insert = $this->connection->getQueryBuilder();
|
||||
$insert->insert('polls_options')
|
||||
->values([
|
||||
'poll_id' => $insert->createParameter('poll_id'),
|
||||
// Decide between one of both
|
||||
// 'poll_text' => $insert->createParameter('poll_text'),
|
||||
'poll_option_text' => $insert->createParameter('poll_option_text'),
|
||||
]);
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->select('*')
|
||||
->from('polls_txts');
|
||||
$result = $query->execute();
|
||||
while ($row = $result->fetch()) {
|
||||
$insert
|
||||
->setParameter('poll_id', $row['poll_id'])
|
||||
// Decide between one of both
|
||||
// ->setParameter('poll_text', $row['text'])
|
||||
->setParameter('poll_option_text', preg_replace("/_\d*$/", "$1", $row['text']));
|
||||
$insert->execute();
|
||||
}
|
||||
$result->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy date votes
|
||||
*/
|
||||
protected function copyDateVotes() {
|
||||
$insert = $this->connection->getQueryBuilder();
|
||||
$insert->insert('polls_votes')
|
||||
->values([
|
||||
'poll_id' => $insert->createParameter('poll_id'),
|
||||
'user_id' => $insert->createParameter('user_id'),
|
||||
// 'vote_date' => $insert->createParameter('vote_date'),
|
||||
'vote_option_id' => $insert->createParameter('vote_option_id'),
|
||||
'vote_option_text' => $insert->createParameter('vote_option_text'),
|
||||
// 'vote_type' => $insert->createParameter('vote_type'),
|
||||
'vote_answer' => $insert->createParameter('vote_answer'),
|
||||
]);
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->select('*')
|
||||
->from('polls_particip');
|
||||
$result = $query->execute();
|
||||
while ($row = $result->fetch()) {
|
||||
$insert
|
||||
->setParameter('poll_id', $row['poll_id'])
|
||||
->setParameter('user_id', $row['user_id'])
|
||||
// ->setParameter('vote_date', $row['dt'])
|
||||
->setParameter('vote_option_id', $this->findOptionId($row['poll_id'], $row['dt']))
|
||||
->setParameter('vote_option_text', date($row['dt']))
|
||||
// ->setParameter('vote_type', $row['type'])
|
||||
->setParameter('vote_answer', $this->translateVoteTypeToAnswer($row['type']));
|
||||
$insert->execute();
|
||||
}
|
||||
$result->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy text votes
|
||||
*/
|
||||
protected function copyTextVotes() {
|
||||
$insert = $this->connection->getQueryBuilder();
|
||||
$insert->insert('polls_votes')
|
||||
->values([
|
||||
'poll_id' => $insert->createParameter('poll_id'),
|
||||
'user_id' => $insert->createParameter('user_id'),
|
||||
// 'vote_text' => $insert->createParameter('vote_text'),
|
||||
'vote_option_id' => $insert->createParameter('vote_option_id'),
|
||||
'vote_option_text' => $insert->createParameter('vote_option_text'),
|
||||
// 'vote_type' => $insert->createParameter('vote_type'),
|
||||
'vote_answer' => $insert->createParameter('vote_answer'),
|
||||
]);
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->select('*')
|
||||
->from('polls_particip_text');
|
||||
$result = $query->execute();
|
||||
while ($row = $result->fetch()) {
|
||||
$insert
|
||||
->setParameter('poll_id', $row['poll_id'])
|
||||
->setParameter('user_id', $row['user_id'])
|
||||
// ->setParameter('vote_text', $row['text'])
|
||||
->setParameter('vote_option_id', $this->findOptionId($row['poll_id'], preg_replace("/_\d*$/", "$1", $row['text'])))
|
||||
->setParameter('vote_option_text', preg_replace("/_\d*$/", "$1", $row['text']))
|
||||
// ->setParameter('vote_type', $row['type'])
|
||||
->setParameter('vote_answer', $this->translateVoteTypeToAnswer($row['type']));
|
||||
$insert->execute();
|
||||
}
|
||||
$result->closeCursor();
|
||||
}
|
||||
/**
|
||||
* @param int $voteType
|
||||
* @return string
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
protected function findOptionId($pollId, $text) {
|
||||
$queryFind = $this->connection->getQueryBuilder();
|
||||
$queryFind->select(['id'])
|
||||
->from('polls_options')
|
||||
// ->where($queryFind->expr()->eq('poll_id', $pollId))
|
||||
// ->andWhere($queryFind->expr()->eq('poll_option', $text));
|
||||
->where('poll_id = "' . $pollId . '"')
|
||||
->andWhere('poll_option_text ="' . $text . '"');
|
||||
|
||||
$resultFind = $queryFind->execute();
|
||||
$row = $resultFind->fetch();
|
||||
return $row['id'];
|
||||
|
||||
}
|
||||
|
||||
protected function translateVoteTypeToAnswer($voteType) {
|
||||
switch ($voteType) {
|
||||
case 0:
|
||||
$answer = "no";
|
||||
break;
|
||||
case 1:
|
||||
$answer = "yes";
|
||||
break;
|
||||
case 2:
|
||||
$answer = "maybe";
|
||||
break;
|
||||
default:
|
||||
$answer = "no";
|
||||
}
|
||||
return $answer;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Polls\Migration;
|
||||
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
use OCP\Migration\IOutput;
|
||||
|
||||
/**
|
||||
* Deleting unused tables 'polls_dts', 'polls_txts', 'polls_particip' and 'polls_particip_text'
|
||||
* after migration in 'Version009000Date20171202105141.php'
|
||||
*/
|
||||
|
||||
class Version009000Date20180202213017 extends SimpleMigrationStep {
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
if ($schema->hasTable('polls_dts')) {
|
||||
$schema->dropTable('polls_dts');
|
||||
}
|
||||
if ($schema->hasTable('polls_txts')) {
|
||||
$schema->dropTable('polls_txts');
|
||||
}
|
||||
if ($schema->hasTable('polls_particip')) {
|
||||
$schema->dropTable('polls_particip');
|
||||
}
|
||||
if ($schema->hasTable('polls_particip_text')) {
|
||||
$schema->dropTable('polls_particip_text');
|
||||
}
|
||||
return $schema;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @author Joas Schilling <coding@schilljs.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
namespace OCA\Polls\Migration;
|
||||
|
||||
use Doctrine\DBAL\Exception\TableNotFoundException;
|
||||
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
use OCP\Migration\IOutput;
|
||||
|
||||
/**
|
||||
* Auto-generated migration step: Please modify to your needs!
|
||||
* Adding column 'disallow_maybe' to table 'polls_events'
|
||||
*/
|
||||
class Version009000Date20180421050115 extends SimpleMigrationStep {
|
||||
/** @var IDBConnection */
|
||||
protected $connection;
|
||||
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @param IDBConnection $connection
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(IDBConnection $connection, IConfig $config) {
|
||||
$this->connection = $connection;
|
||||
$this->config = $config;
|
||||
}
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
$table = $schema->getTable('polls_events');
|
||||
$table->addColumn('disallow_maybe', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
'default' => 0
|
||||
]);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
namespace OCA\Polls\Migration;
|
||||
|
||||
use Doctrine\DBAL\Exception\TableNotFoundException;
|
||||
use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IConfig;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
use OCP\Migration\IOutput;
|
||||
|
||||
/**
|
||||
* Adding timestamp to options table
|
||||
*/
|
||||
class Version009000Date20180501201949 extends SimpleMigrationStep {
|
||||
/** @var IDBConnection */
|
||||
protected $connection;
|
||||
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @param IDBConnection $connection
|
||||
* @param IConfig $config
|
||||
*/
|
||||
public function __construct(IDBConnection $connection, IConfig $config) {
|
||||
$this->connection = $connection;
|
||||
$this->config = $config;
|
||||
}
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @return null|ISchemaWrapper
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function changeSchema(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
$table = $schema->getTable('polls_options');
|
||||
$table->addColumn('timestamp', Type::INTEGER, [
|
||||
'notnull' => false,
|
||||
'default' => 0
|
||||
]);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
* @since 13.0.0
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "polls",
|
||||
"description": "Polls app for nextcloud",
|
||||
"version": "0.9.0",
|
||||
"author": "Rene Gieling",
|
||||
"license": "AGPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"live": "cross-env NODE_ENV=development webpack --progress --hot --config src/js/webpack.config.js --watch",
|
||||
"dev": "cross-env NODE_ENV=development webpack --progress --hide-modules --config src/js/webpack.config.js --watch",
|
||||
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules --config src/js/webpack.config.js",
|
||||
"test": "cross-env NODE_ENV=development webpack --progress --hide-modules --config src/js/webpack.config.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nextcloud/polls.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/nextcloud/polls/issues"
|
||||
},
|
||||
"homepage": "https://github.com/nextcloud/polls#readme",
|
||||
"dependencies": {
|
||||
"axios": "^0.17.1",
|
||||
"lodash": "^4.17.11",
|
||||
"moment": "^2.22.1",
|
||||
"nextcloud-vue": "^0.2.0",
|
||||
"velocity-animate": "^1.5.1",
|
||||
"vue": "^2.5.16",
|
||||
"vue-js-modal": "^1.3.26"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 1%",
|
||||
"last 2 versions",
|
||||
"not ie <= 8"
|
||||
],
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"babel-preset-stage-3": "^6.24.1",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^0.28.8",
|
||||
"file-loader": "^1.1.6",
|
||||
"node-sass": "^4.9.3",
|
||||
"sass-loader": "^7.1.0",
|
||||
"vue-loader": "^13.7.3",
|
||||
"vue-template-compiler": "^2.5.17",
|
||||
"webpack": "^3.12.0"
|
||||
}
|
||||
}
|
Двоичные данные
screenshots/edit-poll-oc.png
До Ширина: | Высота: | Размер: 80 KiB |
Двоичные данные
screenshots/edit-poll.png
До Ширина: | Высота: | Размер: 81 KiB После Ширина: | Высота: | Размер: 57 KiB |
Двоичные данные
screenshots/overview-oc.png
До Ширина: | Высота: | Размер: 130 KiB |
Двоичные данные
screenshots/overview.png
До Ширина: | Высота: | Размер: 128 KiB После Ширина: | Высота: | Размер: 82 KiB |
Двоичные данные
screenshots/vote-mobile-landscape.png
До Ширина: | Высота: | Размер: 36 KiB После Ширина: | Высота: | Размер: 38 KiB |
Двоичные данные
screenshots/vote-mobile-portrait.png
До Ширина: | Высота: | Размер: 41 KiB После Ширина: | Высота: | Размер: 132 KiB |
Двоичные данные
screenshots/vote-oc.png
До Ширина: | Высота: | Размер: 132 KiB |
Двоичные данные
screenshots/vote.png
До Ширина: | Высота: | Размер: 136 KiB После Ширина: | Высота: | Размер: 46 KiB |
|
@ -0,0 +1,580 @@
|
|||
<template>
|
||||
<div id="create-poll">
|
||||
<controls :index-page="indexPage" :intitle="title">
|
||||
<button @click="writePoll(poll.mode)" class="button btn primary" :disabled="writingPoll">
|
||||
<span>{{ saveButtonTitle }}</span>
|
||||
<span v-if="writingPoll" class="icon-loading-small"></span>
|
||||
</button>
|
||||
<button @click="switchSidebar" class="button">
|
||||
<span class="symbol icon-settings"></span>
|
||||
</button>
|
||||
</controls>
|
||||
|
||||
<div class="workbench">
|
||||
<div>
|
||||
<h2>{{ t('polls', 'Poll description') }}</h2>
|
||||
|
||||
<label>{{ t('polls', 'Title') }}</label>
|
||||
<input type="text" id="pollTitle" :class="{ error: titleEmpty }" v-model="poll.event.title">
|
||||
|
||||
<label>{{ t('polls', 'Description') }}</label>
|
||||
<textarea id="pollDesc" v-model="poll.event.description" style="resize: vertical; width: 100%;"></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>{{ t('polls', 'Vote options') }}</h2>
|
||||
|
||||
<div v-if="poll.mode == 'create'">
|
||||
<input id="datePoll" v-model="poll.event.type" value="datePoll" type="radio" class="radio" :disabled="protect"/>
|
||||
<label for="datePoll">{{ t('polls', 'Event schedule') }}</label>
|
||||
<input id="textPoll" v-model="poll.event.type" value="textPoll" type="radio" class="radio" :disabled="protect"/>
|
||||
<label for="textPoll">{{ t('polls', 'Text based') }}</label>
|
||||
</div>
|
||||
|
||||
|
||||
<date-picker @change="addNewPollDate"
|
||||
v-bind="optionDatePicker"
|
||||
v-model="newPollDate"
|
||||
style="width:100%"
|
||||
v-show="poll.event.type === 'datePoll'"
|
||||
confirm />
|
||||
|
||||
<transition-group
|
||||
id="date-poll-list"
|
||||
name="list"
|
||||
tag="ul"
|
||||
class="poll-table"
|
||||
v-show="poll.event.type === 'datePoll'">
|
||||
<li
|
||||
is="date-poll-item"
|
||||
v-for="(pollDate, index) in poll.options.pollDates"
|
||||
:option="pollDate"
|
||||
:key="pollDate.id"
|
||||
@remove="poll.options.pollDates.splice(index, 1)">
|
||||
</li>
|
||||
</transition-group>
|
||||
|
||||
|
||||
<div id="poll-item-selector-text" v-show="poll.event.type === 'textPoll'" >
|
||||
<input v-model="newPollText" @keyup.enter="addNewPollText()" :placeholder=" t('polls', 'Add option') ">
|
||||
</div>
|
||||
|
||||
<transition-group
|
||||
id="text-poll-list"
|
||||
name="list"
|
||||
tag="ul"
|
||||
class="poll-table"
|
||||
v-show="poll.event.type === 'textPoll'">
|
||||
<li
|
||||
is="text-poll-item"
|
||||
v-for="(pollText, index) in poll.options.pollTexts"
|
||||
:option="pollText"
|
||||
:key="pollText.id"
|
||||
@remove="poll.options.pollTexts.splice(index, 1)">
|
||||
</li>
|
||||
</transition-group>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<side-bar v-if="sidebar">
|
||||
<user-div :description="t('polls', 'Owner')" :user-id="poll.event.owner"></user-div>
|
||||
|
||||
<ul class="tabHeaders">
|
||||
<li class="tabHeader selected" data-tabid="configurationsTabView" data-tabindex="0">
|
||||
<a href="#">{{ t('polls', 'Configuration') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div v-if="protect">
|
||||
<span>{{ t('polls', 'Configuration is locked. Changing options may result in unwanted behaviour, but you can unlock it anyway.') }}</span>
|
||||
<button @click="protect=false" > {{ t('polls', 'Unlock configuration ') }} </button>
|
||||
</div>
|
||||
<div id="configurationsTabView" class="tab">
|
||||
|
||||
<div class="configBox" v-if="poll.mode =='edit'">
|
||||
<label class="title">{{ t('polls', 'Poll type') }}</label>
|
||||
<input id="datePoll" v-model="poll.event.type" value="datePoll" type="radio" class="radio" :disabled="protect"/>
|
||||
<label for="datePoll">{{ t('polls', 'Event schedule') }}</label>
|
||||
<input id="textPoll" v-model="poll.event.type" value="textPoll" type="radio" class="radio" :disabled="protect"/>
|
||||
<label for="textPoll">{{ t('polls', 'Text based') }}</label>
|
||||
</div>
|
||||
|
||||
<div class="configBox">
|
||||
<label class="title">{{ t('polls', 'Poll configurations') }}</label>
|
||||
|
||||
<input :disabled="protect" id="disallowMaybe" v-model="poll.event.disallowMaybe"type="checkbox" class="checkbox" />
|
||||
<label for="disallowMaybe">{{ t('polls', 'Disallow maybe vote') }}</label>
|
||||
|
||||
<input :disabled="protect" id="anonymous" v-model="poll.event.isAnonymous"type="checkbox" class="checkbox" />
|
||||
<label for="anonymous">{{ t('polls', 'Anonymous poll') }}</label>
|
||||
|
||||
<input :disabled="protect" id="trueAnonymous" v-model="poll.event.fullAnonymous" v-show="poll.event.isAnonymous" type="checkbox" class="checkbox"/>
|
||||
<label for="trueAnonymous" v-show="poll.event.isAnonymous">{{ t('polls', 'Hide user names for admin') }} </label>
|
||||
|
||||
<input :disabled="protect" id="expiration" v-model="poll.event.expiration" type="checkbox" class="checkbox" />
|
||||
<label for="expiration">{{ t('polls', 'Expires') }}</label>
|
||||
|
||||
<date-picker v-bind="expirationDatePicker"
|
||||
:disabled="protect"
|
||||
v-model="poll.event.expirationDate"
|
||||
v-show="poll.event.expiration"
|
||||
style="width:170px"
|
||||
:time-picker-options="{ start: '00:00', step: '00:05', end: '23:55' }" />
|
||||
|
||||
</div>
|
||||
|
||||
<div class="configBox">
|
||||
<label class="title">{{ t('polls', 'Access') }}</label>
|
||||
<input :disabled="protect" type="radio" v-model="poll.event.access" value="registered" id="private" class="radio"/>
|
||||
<label for="private">{{ t('polls', 'Registered users only') }}</label>
|
||||
<input :disabled="protect" type="radio" v-model="poll.event.access" value="hidden" id="hidden" class="radio"/>
|
||||
<label for="hidden">{{ t('polls', 'hidden') }}</label>
|
||||
<input :disabled="protect" type="radio" v-model="poll.event.access" value="public" id="public" class="radio"/>
|
||||
<label for="public">{{ t('polls', 'Public access') }}</label>
|
||||
<input :disabled="protect" type="radio" v-model="poll.event.access" value="select" id="select" class="radio"/>
|
||||
<label for="select">{{ t('polls', 'Only shared') }}</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<share-div :active-shares="poll.shares"
|
||||
@update-shares="updateShares"
|
||||
@remove-share="removeShare"
|
||||
hide-names="true"
|
||||
:placeholder="t('polls', 'Name of user or group')"
|
||||
v-show="poll.event.access === 'select'"/>
|
||||
|
||||
</side-bar>
|
||||
<div class="loading-overlay" v-if="loadingPoll">
|
||||
<span class="icon-loading"></span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import moment from 'moment';
|
||||
import lodash from 'lodash';
|
||||
|
||||
import DatePollItem from './components/datePollItem.vue';
|
||||
import TextPollItem from './components/textPollItem.vue';
|
||||
|
||||
export default {
|
||||
name: 'create-poll',
|
||||
|
||||
components: {
|
||||
'DatePollItem': DatePollItem,
|
||||
'TextPollItem': TextPollItem,
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
poll: {
|
||||
mode: 'create',
|
||||
comments: [],
|
||||
votes: [],
|
||||
shares: [],
|
||||
event: {
|
||||
id: 0,
|
||||
hash: '',
|
||||
type: 'datePoll',
|
||||
title: '',
|
||||
description: '',
|
||||
owner:'',
|
||||
created: '',
|
||||
access: 'public',
|
||||
expiration: false,
|
||||
expirationDate: '',
|
||||
expired: false,
|
||||
isAnonymous: false,
|
||||
fullAnonymous: false,
|
||||
disallowMaybe: false,
|
||||
},
|
||||
options: {
|
||||
pollDates: [],
|
||||
pollTexts: []
|
||||
}
|
||||
},
|
||||
system:[],
|
||||
lang: '',
|
||||
locale: '',
|
||||
placeholder: '',
|
||||
newPollDate: '',
|
||||
newPollTime: '',
|
||||
newPollText: '',
|
||||
nextPollDateId: 1,
|
||||
nextPollTextId: 1,
|
||||
protect: false,
|
||||
writingPoll: false,
|
||||
loadingPoll: true,
|
||||
sidebar: false,
|
||||
titleEmpty: false,
|
||||
indexPage: '',
|
||||
longDateFormat: '',
|
||||
dateTimeFormat: '',
|
||||
}
|
||||
},
|
||||
|
||||
created: function() {
|
||||
this.indexPage = OC.generateUrl('apps/polls/');
|
||||
this.getSystemValues();
|
||||
this.lang = OC.getLanguage();
|
||||
try {
|
||||
this.locale = OC.getLocale();
|
||||
} catch (e) {
|
||||
if (e instanceof TypeError) {
|
||||
this.locale = this.lang;
|
||||
} else {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
moment.locale(this.locale);
|
||||
this.longDateFormat = moment.localeData().longDateFormat('L');
|
||||
this.dateTimeFormat = moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT');
|
||||
var urlArray = window.location.pathname.split( '/' );
|
||||
|
||||
if (urlArray[urlArray.length - 1] === 'create') {
|
||||
this.poll.event.owner = OC.getCurrentUser().uid;
|
||||
this.loadingPoll = false
|
||||
} else {
|
||||
this.loadPoll(urlArray[urlArray.length - 1])
|
||||
this.protect = true;
|
||||
this.poll.mode = 'edit';
|
||||
};
|
||||
|
||||
if (window.innerWidth >1024) {
|
||||
this.sidebar = true;
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
langShort: function () {
|
||||
return this.lang.split("-")[0]
|
||||
},
|
||||
|
||||
title: function() {
|
||||
if (this.poll.event.title === '') {
|
||||
return t('polls','Create new poll');
|
||||
} else {
|
||||
return this.poll.event.title;
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
saveButtonTitle: function() {
|
||||
if (this.writingPoll) {
|
||||
return t('polls', 'Writing poll')
|
||||
} else if (this.poll.mode === 'edit') {
|
||||
return t('polls', 'Update poll')
|
||||
} else {
|
||||
return t('polls', 'Create new poll')
|
||||
}
|
||||
},
|
||||
localeData: function () {
|
||||
return moment.localeData(moment.locale(this.locale))
|
||||
},
|
||||
|
||||
expirationDatePicker: function () {
|
||||
return {
|
||||
editable: true,
|
||||
minuteStep: 1,
|
||||
type: 'datetime',
|
||||
lang: this.lang.split("-")[0],
|
||||
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
|
||||
placeholder: t('polls', 'Expiration date')
|
||||
}
|
||||
},
|
||||
|
||||
optionDatePicker: function () {
|
||||
return {
|
||||
editable: false,
|
||||
minuteStep: 1,
|
||||
type: 'datetime',
|
||||
format: moment.localeData().longDateFormat('L') + ' ' + moment.localeData().longDateFormat('LT'),
|
||||
lang: this.lang.split("-")[0],
|
||||
placeholder: t('polls', 'Click to add a date'),
|
||||
timePickerOptions: {
|
||||
start: '00:00',
|
||||
step: '00:05',
|
||||
end: '23:55'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
watch: {
|
||||
title () {
|
||||
// only used when the title changes after page load
|
||||
document.title = t('polls','Polls') + ' - ' + this.title;
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
switchSidebar () {
|
||||
this.sidebar = !this.sidebar;
|
||||
},
|
||||
|
||||
getSystemValues: function() {
|
||||
axios.get(OC.generateUrl('apps/polls/get/system'))
|
||||
.then((response) => {
|
||||
this.system = response.data.system;
|
||||
}, (error) => {
|
||||
this.poll.event.hash = '';
|
||||
console.log(error.response);
|
||||
});
|
||||
},
|
||||
|
||||
addShare: function (item){
|
||||
this.poll.shares.push(item);
|
||||
},
|
||||
|
||||
updateShares: function (share){
|
||||
this.poll.shares= share.slice(0);
|
||||
},
|
||||
|
||||
removeShare: function (item){
|
||||
this.poll.shares.splice(this.poll.shares.indexOf(item), 1);
|
||||
},
|
||||
|
||||
addNewPollDate: function (newPollDate) {
|
||||
if (newPollDate != null) {
|
||||
this.newPollDate = moment(newPollDate);
|
||||
this.poll.options.pollDates.push({
|
||||
id: this.nextPollDateId++,
|
||||
timestamp: moment(newPollDate).unix(),
|
||||
});
|
||||
this.poll.options.pollDates = _.sortBy(this.poll.options.pollDates, 'timestamp');
|
||||
}
|
||||
},
|
||||
|
||||
addNewPollText: function () {
|
||||
if (this.newPollText !== null & this.newPollText !== '') {
|
||||
this.poll.options.pollTexts.push({
|
||||
id: this.nextPollTextId++,
|
||||
text: this.newPollText
|
||||
});
|
||||
}
|
||||
this.newPollText = '';
|
||||
},
|
||||
|
||||
writePoll: function (mode) {
|
||||
this.writingPoll = true
|
||||
if (mode !== '') {
|
||||
this.poll.mode = mode;
|
||||
}
|
||||
if (this.poll.event.title.length === 0) {
|
||||
this.titleEmpty = true;
|
||||
} else {
|
||||
this.titleEmpty = false;
|
||||
axios.post(OC.generateUrl('apps/polls/write'), this.poll)
|
||||
.then((response) => {
|
||||
this.poll.mode = 'edit';
|
||||
this.poll.event.hash = response.data.hash;
|
||||
this.poll.event.id = response.data.id;
|
||||
this.writingPoll = false;
|
||||
// window.location.href = OC.generateUrl('apps/polls/edit/' + this.poll.event.hash);
|
||||
}, (error) => {
|
||||
this.poll.event.hash = '';
|
||||
console.log(this.poll.event.hash);
|
||||
console.log(error.response);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
loadPoll: function (hash) {
|
||||
this.loadingPoll = true
|
||||
axios.get(OC.generateUrl('apps/polls/get/poll/' + hash))
|
||||
.then((response) => {
|
||||
this.poll = response.data.poll;
|
||||
if (this.poll.event.expirationDate !== null) {
|
||||
this.poll.event.expirationDate = new Date(moment.utc(this.poll.event.expirationDate))
|
||||
} else {
|
||||
this.poll.event.expirationDate = ''
|
||||
}
|
||||
|
||||
if (this.poll.event.type === 'datePoll') {
|
||||
var i;
|
||||
for (i = 0; i < this.poll.options.pollTexts.length; i++) {
|
||||
this.addNewPollDate(new Date(moment.utc(this.poll.options.pollTexts[i].text)))
|
||||
}
|
||||
this.poll.options.pollTexts = [];
|
||||
}
|
||||
this.loadingPoll = false
|
||||
this.newPollDate = ''
|
||||
this.newPollText = ''
|
||||
}, (error) => {
|
||||
this.poll.event.hash = '';
|
||||
console.log(error.response);
|
||||
this.loadingPoll = false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
#create-poll {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
input.hasTimepicker {
|
||||
width: 75px;
|
||||
}
|
||||
}
|
||||
|
||||
.polls-content {
|
||||
display: flex;
|
||||
padding-top: 45px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
input[type="text"] {
|
||||
display: block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.workbench {
|
||||
margin-top: 45px;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-wrap: wrap;
|
||||
overflow-x: hidden;
|
||||
|
||||
|
||||
> div {
|
||||
min-width: 245px;
|
||||
max-width: 540px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-overlay {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
opacity: 0.9;
|
||||
z-index: 1001;
|
||||
.icon-loading {
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-left: -35px;
|
||||
margin-top: -10px;
|
||||
&::after {
|
||||
border: 10px solid var(--color-loading-light);
|
||||
border-top-color: var(--color-primary-element);
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.polls-sidebar {
|
||||
margin-top: 45px;
|
||||
width: 40%;
|
||||
|
||||
.configBox {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px 8px;
|
||||
|
||||
&> .title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
input, textarea {
|
||||
&.error {
|
||||
border: 2px solid var(--color-error);
|
||||
box-shadow: 1px 0 var(--border-radius) var(--color-box-shadow);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transitions for inserting and removing list items */
|
||||
.list-enter-active, .list-leave-active {
|
||||
transition: all 0.5s ease;
|
||||
}
|
||||
|
||||
.list-enter, .list-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.list-move {
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
/* */
|
||||
|
||||
|
||||
#poll-item-selector-text {
|
||||
> input {
|
||||
width: 100%
|
||||
}
|
||||
}
|
||||
|
||||
.poll-table {
|
||||
>li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
line-height: 2em;
|
||||
min-height: 4em;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
|
||||
&:hover, &:active {
|
||||
transition: var(--background-dark) 0.3s ease;
|
||||
background-color: var(--color-loading-light); //$hover-color;
|
||||
}
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
font-size: 1.2em;
|
||||
opacity: 0.7;
|
||||
white-space: normal;
|
||||
padding-right: 4px;
|
||||
&.avatar {
|
||||
flex-grow: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> div:nth-last-child(1) {
|
||||
justify-content: center;
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
&.button-inline{
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.tab {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
/* global Vue, oc_userconfig */
|
||||
<template>
|
||||
<div class="cloud">
|
||||
<span class="expired" v-if="options.expired">{{ t('polls', 'Expired')}} </span>
|
||||
<span class="open" v-if="options.expiration">{{ t('polls', 'Expires %n', 1, expirationdate) }}</span>
|
||||
<span class="open" v-else>{{ t('polls', 'Expires never') }}</span>
|
||||
|
||||
<span class="information">{{ options.access }}</span>
|
||||
<span class="information" v-if="options.isAnonymous"> {{ t('polls', 'Anonymous poll') }}</span>
|
||||
<span class="information" v-if="options.fullAnonymous"> {{ t('polls', 'Usernames hidden to Owner') }}</span>
|
||||
<span class="information" v-if="options.isAnonymous & !options.fullAnonymous"> {{ t('polls', 'Usernames visible to Owner') }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['options', ],
|
||||
|
||||
computed: {
|
||||
expirationdate: function() {
|
||||
var date = moment(this.options.expirationDate, moment.localeData().longDateFormat('L')).fromNow();
|
||||
return date
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,108 @@
|
|||
/* global Vue, oc_userconfig */
|
||||
<template>
|
||||
<div class="user-row" :class="type">
|
||||
<div v-show="description" class="description">{{description}}</div>
|
||||
<div class="avatar"><img :src="avatarURL" :width="size" :height="size" :title="computedDisplayName"></div>
|
||||
<div v-show="!hideNames" class="user-name">{{ computedDisplayName }}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
hideNames: {
|
||||
default: false
|
||||
},
|
||||
userId: {
|
||||
type: String,
|
||||
default: OC.getCurrentUser().uid
|
||||
},
|
||||
displayName: {
|
||||
type: String
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 32
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'user'
|
||||
},
|
||||
description: String
|
||||
},
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
nothidden: false,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
computedDisplayName: function () {
|
||||
var value = this.displayName;
|
||||
|
||||
if (this.userId === OC.getCurrentUser().uid) {
|
||||
value = OC.getCurrentUser().displayName;
|
||||
} else {
|
||||
if (!this.displayName) {
|
||||
value = this.userId;
|
||||
}
|
||||
}
|
||||
if (this.type === 'group') {
|
||||
value = value + ' (' + t('polls','Group') +')';
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
avatarURL: function() {
|
||||
if (this.userId === OC.getCurrentUser().uid) {
|
||||
return OC.generateUrl(
|
||||
'/avatar/{user}/{size}?v={version}',
|
||||
{
|
||||
user: OC.getCurrentUser().uid,
|
||||
size: Math.ceil(this.size * window.devicePixelRatio),
|
||||
version: oc_userconfig.avatar.version
|
||||
})
|
||||
} else {
|
||||
return OC.generateUrl(
|
||||
'/avatar/{user}/{size}',
|
||||
{
|
||||
user: this.userId,
|
||||
size: Math.ceil(this.size * window.devicePixelRatio),
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.user-row {
|
||||
display: flex;
|
||||
flex-grow: 0;
|
||||
align-items: center;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
|
||||
> div {
|
||||
margin: 2px 4px 2px 4px;
|
||||
}
|
||||
|
||||
.description {
|
||||
opacity: 0.7;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
opacity: 0.5;
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,29 @@
|
|||
<template>
|
||||
<div class="breadcrump">
|
||||
<div class="crumb svg">
|
||||
<a :href="indexPage">
|
||||
<img class="svg" :src="imagePath" alt="Home">
|
||||
</a>
|
||||
</div>
|
||||
<div class="crumb svg last">
|
||||
<span v-text="intitle" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['intitle','indexPage'],
|
||||
data: function () {
|
||||
return {
|
||||
imagePath: OC.imagePath('core', 'places/home.svg'),
|
||||
};
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.breadcrump {
|
||||
flex-grow: 1;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,54 @@
|
|||
<template>
|
||||
<div class="controls">
|
||||
<breadcrump :index-page="indexPage" :intitle="intitle"></breadcrump>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Breadcrump from './_base-breadcrump.vue';
|
||||
export default {
|
||||
components: {
|
||||
Breadcrump
|
||||
},
|
||||
props: ['intitle','indexPage'],
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
position: fixed;
|
||||
background: var(--color-main-background);
|
||||
width: 100%;
|
||||
height: 45px;
|
||||
z-index: 1001;
|
||||
.button, button {
|
||||
flex-shrink: 0;
|
||||
height: 36px;
|
||||
padding: 7px 10px;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--color-text-lighter);
|
||||
&.primary {
|
||||
background: var(--color-primary);
|
||||
color: var(--color-primary-text);
|
||||
}
|
||||
}
|
||||
|
||||
.breadcrump {
|
||||
overflow: hidden;
|
||||
min-width: 35px;
|
||||
div.crumb:last-child {
|
||||
flex-shrink: 1;
|
||||
overflow: hidden;
|
||||
> span {
|
||||
flex-shrink: 1;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,16 @@
|
|||
<template>
|
||||
<div class="polls-sidebar" >
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.polls-sidebar {
|
||||
min-width: 300px;
|
||||
border-left: 1px solid var(--color-border);
|
||||
z-index: 500;
|
||||
> div, > ul {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<li>
|
||||
<div>{{option.timestamp | localFullDate}}</div>
|
||||
<div>
|
||||
<a @click="$emit('remove')" class="icon-delete"></a>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['option'],
|
||||
filters: {
|
||||
localFullDate: function (timestamp) {
|
||||
if (!timestamp) return '';
|
||||
if (!moment(timestamp).isValid()) return 'Invalid Date';
|
||||
if (timestamp < 999999999999) timestamp = timestamp *1000;
|
||||
return moment(timestamp).format('llll');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,184 @@
|
|||
<template>
|
||||
<div>
|
||||
<h2> {{ t('polls', 'Share with') }}</h2>
|
||||
<multiselect
|
||||
v-model="shares"
|
||||
:options="users"
|
||||
:option-height=32
|
||||
:multiple="true"
|
||||
:close-on-select="false"
|
||||
:clear-on-select="false"
|
||||
:preserve-search="true"
|
||||
label="displayName"
|
||||
track-by="id"
|
||||
:options-limit="20"
|
||||
id="ajax"
|
||||
@search-change="loadUsersAsync"
|
||||
@close="updateShares"
|
||||
:loading="isLoading"
|
||||
:internal-search="false"
|
||||
:hide-selected="true"
|
||||
:searchable="true"
|
||||
:preselect-first="true"
|
||||
:placeholder="placeholder">
|
||||
<template slot="selection" slot-scope="{ values, search, isOpen }">
|
||||
<span class="multiselect__single" v-if="values.length && !isOpen">
|
||||
{{ values.length }} users selected
|
||||
</span>
|
||||
</template>
|
||||
<template slot="option" slot-scope="props">
|
||||
<div class="option__desc">
|
||||
<user-div :user-id="props.option.id" :display-name="props.option.displayName" :type="props.option.type"></user-div>
|
||||
</div>
|
||||
</template>
|
||||
</multiselect>
|
||||
|
||||
<transition-group tag="ul" v-bind:css="false" class="shared-list">
|
||||
<li v-for="(item, index) in sortedShares"
|
||||
v-bind:key="item.displayName"
|
||||
v-bind:data-index="index">
|
||||
<div class="options">
|
||||
<a @click="removeShare(index, item)" class="icon icon-delete svg delete-poll"></a>
|
||||
</div>
|
||||
<user-div :user-id="item.id" :display-name="item.displayName" :type="item.type" :hide-names="hideNames"></user-div>
|
||||
</li>
|
||||
</transition-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import { Multiselect } from 'nextcloud-vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Multiselect
|
||||
},
|
||||
|
||||
props: ['placeholder', 'activeShares','hideNames'],
|
||||
|
||||
data: function () {
|
||||
return {
|
||||
shares: [],
|
||||
users: [],
|
||||
isLoading: false,
|
||||
siteUsersListOptions: {
|
||||
getUsers: true,
|
||||
getGroups: true,
|
||||
query: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
sortedShares: function() {
|
||||
return this.shares.sort(this.sortByDisplayname)
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
removeShare: function (index, item){
|
||||
this.$emit('remove-share', item);
|
||||
},
|
||||
|
||||
updateShares: function (){
|
||||
this.$emit('update-shares', this.shares);
|
||||
},
|
||||
|
||||
loadUsersAsync: function (query) {
|
||||
this.isLoading = false
|
||||
this.siteUsersListOptions.query = query
|
||||
axios.post(OC.generateUrl('apps/polls/get/siteusers'), this.siteUsersListOptions)
|
||||
.then((response) => {
|
||||
this.users = response.data.siteusers
|
||||
this.isLoading = false
|
||||
}, (error) => {
|
||||
console.log(error.response)
|
||||
});
|
||||
},
|
||||
|
||||
sortByDisplayname: function (a, b) {
|
||||
if (a.displayName.toLowerCase() < b.displayName.toLowerCase()) return -1;
|
||||
if (a.displayName.toLowerCase() > b.displayName.toLowerCase()) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
},
|
||||
watch: {
|
||||
activeShares(value) {
|
||||
this.shares = value.slice(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.shared-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
padding-top: 8px;
|
||||
|
||||
> li {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
display: flex;
|
||||
position: relative;
|
||||
top: 13px;
|
||||
left: 43px;
|
||||
}
|
||||
|
||||
div, select {
|
||||
&.multiselect:not(.multiselect-vue), &.multiselect:not(.multiselect-vue) {
|
||||
max-width: unset;
|
||||
}
|
||||
}
|
||||
|
||||
.multiselect {
|
||||
width: 100%;
|
||||
.multiselect__content-wrapper li > span {
|
||||
height: unset;
|
||||
}
|
||||
.option__desc {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
||||
.multiselect__option--highlight {
|
||||
background: #41b883;
|
||||
outline: none;
|
||||
color: #fff;
|
||||
&::after {
|
||||
content: attr(data-select);
|
||||
background: #41b883;
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.multiselect__option--selected {
|
||||
&::after {
|
||||
content: attr(data-selected);
|
||||
color: silver;
|
||||
}
|
||||
&.multiselect__option--highlight {
|
||||
background: #ff6a6a;
|
||||
color: #fff;
|
||||
&::after {
|
||||
background: #ff6a6a;
|
||||
content: attr(data-deselect);
|
||||
color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,22 @@
|
|||
<template>
|
||||
<div class="close flex-row">
|
||||
<a id="closeDetails" @:click="hideSidebar" class="close icon-close has-tooltip-bottom" :title="closeDetailLabel" href="#" :alt="closeDetailLabelAlt"></a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data: function () {
|
||||
return {
|
||||
closeDetailLabel: t('Close details'),
|
||||
closeDetailLabelAlt: t('Close')
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
hideSidebar: function () {
|
||||
OC.Apps.hideAppSidebar();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<template>
|
||||
<li>
|
||||
<div>{{ option.text }}</div>
|
||||
<div>
|
||||
<a @click="$emit('remove')" class="icon icon-delete svg delete-poll"></a>
|
||||
</div>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: ['option'],
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,34 @@
|
|||
/*jshint esversion: 6 */
|
||||
import Vue from 'vue';
|
||||
import Create from './Create.vue';
|
||||
import { DatetimePicker } from 'nextcloud-vue';
|
||||
import Controls from './components/_base-controls.vue';
|
||||
import SideBarClose from './components/sideBarClose.vue';
|
||||
import UserDiv from './components/_base-UserDiv.vue';
|
||||
import SideBar from './components/_base-SideBar.vue';
|
||||
import ShareDiv from './components/shareDiv.vue';
|
||||
|
||||
Vue.config.debug = true
|
||||
Vue.config.devTools = true
|
||||
Vue.component('Controls', Controls);
|
||||
Vue.component('DatePicker', DatetimePicker);
|
||||
Vue.component('SideBarClose', SideBarClose);
|
||||
Vue.component('UserDiv', UserDiv);
|
||||
Vue.component('SideBar', SideBar);
|
||||
Vue.component('ShareDiv', ShareDiv);
|
||||
|
||||
Vue.mixin({
|
||||
methods: {
|
||||
t: function(app, text, vars, count, options) {
|
||||
return OC.L10N.translate(app, text, vars, count, options)
|
||||
},
|
||||
n: function(app, textSingular, textPlural, count, vars, options) {
|
||||
return OC.L10N.translatePlural(app, textSingular, textPlural, count, vars, options)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
new Vue({
|
||||
el: '#create-poll',
|
||||
render: h => h(Create)
|
||||
});
|
|
@ -0,0 +1,80 @@
|
|||
var path = require('path')
|
||||
var webpack = require('webpack')
|
||||
|
||||
module.exports = {
|
||||
entry: './src/js/main.js',
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../../js'),
|
||||
publicPath: '/js/',
|
||||
filename: 'create-poll.js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
'vue-style-loader',
|
||||
'css-loader',
|
||||
'sass-loader'
|
||||
],
|
||||
}, {
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader',
|
||||
options: {
|
||||
loaders: {
|
||||
}
|
||||
// other vue-loader options go here
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpg|gif|svg)$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[ext]?[hash]'
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js'
|
||||
},
|
||||
extensions: ['*', '.js', '.vue', '.json']
|
||||
},
|
||||
devServer: {
|
||||
historyApiFallback: true,
|
||||
noInfo: true,
|
||||
overlay: true
|
||||
},
|
||||
performance: {
|
||||
hints: false
|
||||
},
|
||||
devtool: '#eval-source-map'
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
module.exports.devtool = '#source-map'
|
||||
// http://vue-loader.vuejs.org/en/workflow/production.html
|
||||
module.exports.plugins = (module.exports.plugins || []).concat([
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
sourceMap: false,
|
||||
comments: false,
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
minimize: true
|
||||
})
|
||||
])
|
||||
}
|
|
@ -1,8 +1,9 @@
|
|||
<?php
|
||||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
*
|
||||
* @author Vinzenz Rosenkranz <vinzenz.rosenkranz@gmail.com>
|
||||
* @author René Gieling <github@dartcafe.de>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
|
@ -20,179 +21,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
use OCP\Util;
|
||||
use OCP\Template;
|
||||
|
||||
Util::addStyle('polls', 'createpoll');
|
||||
Util::addStyle('polls', 'vendor/jquery.datetimepicker.min');
|
||||
Util::addScript('polls', 'create_edit');
|
||||
Util::addScript('polls', 'vendor/jquery.datetimepicker.full.min');
|
||||
|
||||
$userId = $_['userId'];
|
||||
/** @var \OCP\IUserManager $userMgr */
|
||||
$userMgr = $_['userMgr'];
|
||||
/** @var \OCP\IURLGenerator $urlGenerator */
|
||||
$urlGenerator = $_['urlGenerator'];
|
||||
$isUpdate = isset($_['poll']) && $_['poll'] !== null;
|
||||
$isAnonymous = false;
|
||||
$hideNames = false;
|
||||
|
||||
if ($isUpdate) {
|
||||
/** @var OCA\Polls\Db\Event $poll */
|
||||
$poll = $_['poll'];
|
||||
$isAnonymous = $poll->getIsAnonymous();
|
||||
$hideNames = $isAnonymous && $poll->getFullAnonymous();
|
||||
/** @var OCA\Polls\Db\Date[]|OCA\Polls\Db\Text[] $dates */
|
||||
$dates = $_['dates'];
|
||||
$chosen = '[';
|
||||
foreach ($dates as $d) {
|
||||
if ($poll->getType() === 0) {
|
||||
$chosen .= strtotime($d->getDt());
|
||||
} else {
|
||||
$chosen .= '"' . $d->getText() . '"';
|
||||
}
|
||||
$chosen .= ',';
|
||||
}
|
||||
$chosen = trim($chosen, ',');
|
||||
$chosen .= ']';
|
||||
$title = $poll->getTitle();
|
||||
$desc = $poll->getDescription();
|
||||
if ($poll->getExpire() !== null) {
|
||||
$expireTs = strtotime($poll->getExpire());
|
||||
$expireStr = date('d.m.Y', $expireTs);
|
||||
}
|
||||
$access = $poll->getAccess();
|
||||
$accessTypes = $access;
|
||||
if (
|
||||
$access !== 'registered'
|
||||
&& $access !== 'hidden' && $access !== 'public'
|
||||
) {
|
||||
$access = 'select';
|
||||
}
|
||||
}
|
||||
?>
|
||||
|
||||
<div id="app-content">
|
||||
|
||||
<div id="controls">
|
||||
<div id="breadcrump">
|
||||
<div class="crumb svg" data-dir="/">
|
||||
<a href="<?php p($urlGenerator->linkToRoute('polls.page.index')); ?>">
|
||||
<img class="svg" src="<?php print_unescaped(Template::image_path('core', 'places/home.svg')); ?>" alt="Home">
|
||||
</a>
|
||||
</div>
|
||||
<div class="crumb svg last">
|
||||
<span>
|
||||
<?php if ($isUpdate): ?>
|
||||
<?php p($l->t('Edit poll') . ' ' . $poll->getTitle()); ?>
|
||||
<?php else: ?>
|
||||
<?php p($l->t('Create new poll')); ?>
|
||||
<?php endif; ?>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($isUpdate): ?>
|
||||
<form name="finish_poll" action="<?php p($urlGenerator->linkToRoute('polls.page.update_poll')); ?>" method="POST">
|
||||
<input type="hidden" name="pollId" value="<?php p($poll->getId()); ?>" />
|
||||
<?php else: ?>
|
||||
<form name="finish_poll" action="<?php p($urlGenerator->linkToRoute('polls.page.insert_poll')); ?>" method="POST">
|
||||
<?php endif; ?>
|
||||
<input type="hidden" name="chosenDates" id="chosenDates" value="<?php if (isset($chosen)) p($chosen); ?>" />
|
||||
<input type="hidden" name="expireTs" id="expireTs" value="<?php if (isset($expireTs)) p($expireTs); ?>" />
|
||||
<input type="hidden" name="userId" id="userId" value="<?php p($userId); ?>" />
|
||||
|
||||
<header class="row">
|
||||
</header>
|
||||
|
||||
<div class="new_poll row">
|
||||
<div class="col-50">
|
||||
<label for="pollTitle" class="input_title"><?php p($l->t('Title')); ?></label>
|
||||
<input type="text" class="input_field" id="pollTitle" name="pollTitle" value="<?php if (isset($title)) p($title); ?>" />
|
||||
<label for="pollDesc" class="input_title"><?php p($l->t('Description')); ?></label>
|
||||
<textarea class="input_field" id="pollDesc" name="pollDesc"><?php if (isset($desc)) p($desc); ?></textarea>
|
||||
|
||||
<label class="input_title"><?php p($l->t('Access')); ?></label>
|
||||
|
||||
<input type="radio" name="accessType" id="private" value="registered" class="radio" <?php if (!$isUpdate || $access === 'registered') print_unescaped('checked'); ?> />
|
||||
<label for="private"><?php p($l->t('Registered users only')); ?></label>
|
||||
|
||||
<input type="radio" name="accessType" id="hidden" value="hidden" class="radio" <?php if ($isUpdate && $access === 'hidden') print_unescaped('checked'); ?> />
|
||||
<label for="hidden"><?php p($l->t('hidden')); ?></label>
|
||||
|
||||
<input type="radio" name="accessType" id="public" value="public" class="radio" <?php if ($isUpdate && $access === 'public') print_unescaped('checked'); ?> />
|
||||
<label for="public"><?php p($l->t('Public access')); ?></label>
|
||||
|
||||
<input type="radio" name="accessType" id="select" value="select" class="radio" <?php if ($isUpdate && $access === 'select') print_unescaped('checked'); ?>>
|
||||
<label for="select"><?php p($l->t('Select')); ?></label>
|
||||
<span id="id_label_select">...</span>
|
||||
|
||||
<div id="selected_access" class="row user-group-list">
|
||||
<ul id="selected-search-list-id">
|
||||
</ul>
|
||||
</div>
|
||||
<div id="access_rights" class="row user-group-list">
|
||||
<div class="col-50">
|
||||
<input type="text" class="live-search-box" id="user-group-search-box" placeholder="<?php p($l->t('User/Group search')); ?>" />
|
||||
<ul class="live-search-list" id="live-search-list-id">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="accessValues" id="accessValues" value="<?php if ($isUpdate && $access === 'select') p($accessTypes) ?>" />
|
||||
|
||||
<input id="isAnonymous" name="isAnonymous" type="checkbox" class="checkbox" <?php $isAnonymous ? print_unescaped('value="true" checked') : print_unescaped('value="false"'); ?> />
|
||||
<label for="isAnonymous" class="input_title"><?php p($l->t('Anonymous')) ?></label>
|
||||
|
||||
<div id="anonOptions" style="display:none;">
|
||||
<input id="hideNames" name="hideNames" type="checkbox" class="checkbox" <?php $hideNames ? print_unescaped('value="true" checked') : print_unescaped('value="false"'); ?> />
|
||||
<label for="hideNames" class="input_title"><?php p($l->t('Hide user names for admin')) ?></label>
|
||||
</div>
|
||||
|
||||
<input id="id_expire_set" name="check_expire" type="checkbox" class="checkbox" <?php ($isUpdate && $poll->getExpire() !== null) ? print_unescaped('value="true" checked') : print_unescaped('value="false"'); ?> />
|
||||
<label for="id_expire_set" class="input_title"><?php p($l->t('Expires')); ?></label>
|
||||
<div class="input-group" id="expiration">
|
||||
<input id="id_expire_date" type="text" required="" <?php (!$isUpdate || $poll->getExpire() === null) ? print_unescaped('disabled="true"') : print_unescaped('value="' . $expireStr . '"'); ?> name="expire_date_input" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-50">
|
||||
|
||||
<input type="radio" name="pollType" id="event" value="event" class="radio" <?php if (!$isUpdate || $poll->getType() === 0) print_unescaped('checked'); ?> />
|
||||
<label for="event"><?php p($l->t('Event schedule')); ?></label>
|
||||
|
||||
<!-- TODO texts to db -->
|
||||
<input type="radio" name="pollType" id="text" value="text" class="radio" <?php if ($isUpdate && $poll->getType() === 1) print_unescaped('checked'); ?>>
|
||||
<label for="text"><?php p($l->t('Text based')); ?></label>
|
||||
|
||||
<div id="date-select-container" <?php if ($isUpdate && $poll->getType() === 1) print_unescaped('style="display:none;"'); ?> >
|
||||
<label for="datetimepicker" class="input_title"><?php p($l->t('Dates')); ?></label>
|
||||
<input id="datetimepicker" type="text" />
|
||||
<table id="selected-dates-table" class="choices">
|
||||
</table>
|
||||
</div>
|
||||
<div id="text-select-container" <?php if(!$isUpdate || $poll->getType() === 0) print_unescaped('style="display:none;"'); ?> >
|
||||
<label for="text-title" class="input_title"><?php p($l->t('Text item')); ?></label>
|
||||
<div class="input-group">
|
||||
<input type="text" id="text-title" placeholder="<?php print_unescaped('Insert text...'); ?>" />
|
||||
<div class="input-group-btn">
|
||||
<input type="button" id="text-submit" class="button btn" value="<?php p($l->t('Add')); ?>" class="btn"/>
|
||||
</div>
|
||||
</div>
|
||||
<table id="selected-texts-table" class="choices">
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<?php if ($isUpdate): ?>
|
||||
<input type="submit" id="submit_finish_poll" class="button btn primary" value="<?php p($l->t('Update poll')); ?>" />
|
||||
<?php else: ?>
|
||||
<input type="submit" id="submit_finish_poll" class="button btn primary" value="<?php p($l->t('Create poll')); ?>" />
|
||||
<?php endif; ?>
|
||||
<a href="<?php p($urlGenerator->linkToRoute('polls.page.index')); ?>" id="submit_cancel_poll" class="button"><?php p($l->t('Cancel')); ?></a>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="create-poll"></div>
|
||||
<?php \OCP\Util::addScript('polls', 'create-poll'); ?>
|
||||
|
|
|
@ -21,14 +21,18 @@
|
|||
*
|
||||
*/
|
||||
|
||||
use OCP\User;
|
||||
use OCP\User; //To do: replace according to API
|
||||
use OCP\Util;
|
||||
use OCP\Template;
|
||||
|
||||
Util::addStyle('polls', 'main');
|
||||
Util::addStyle('polls', 'flex');
|
||||
Util::addStyle('polls', 'vote');
|
||||
Util::addStyle('polls', 'sidebar');
|
||||
if (!User::isLoggedIn()) {
|
||||
Util::addStyle('polls', 'public');
|
||||
}
|
||||
|
||||
Util::addScript('polls', 'app');
|
||||
Util::addScript('polls', 'vote');
|
||||
|
||||
|
@ -41,9 +45,9 @@
|
|||
$avaMgr = $_['avatarManager'];
|
||||
/** @var \OCA\Polls\Db\Event $poll */
|
||||
$poll = $_['poll'];
|
||||
/** @var OCA\Polls\Db\Date[]|OCA\Polls\Db\Text[] $dates */
|
||||
$dates = $_['dates'];
|
||||
/** @var OCA\Polls\Db\Participation[]|OCA\Polls\Db\ParticipationText[] $votes */
|
||||
/** @var OCA\Polls\Db\Options[] $options */
|
||||
$options = $_['options'];
|
||||
/** @var OCA\Polls\Db\Votes[] $votes */
|
||||
$votes = $_['votes'];
|
||||
/** @var \OCA\Polls\Db\Comment[] $comments */
|
||||
$comments = $_['comments'];
|
||||
|
@ -52,7 +56,15 @@
|
|||
|
||||
$isAnonymous = $poll->getIsAnonymous() && $userId !== $poll->getOwner();
|
||||
$hideNames = $poll->getIsAnonymous() && $poll->getFullAnonymous();
|
||||
if ($poll->getDisallowMaybe()) {
|
||||
$maybe = 'maybedisallowed';
|
||||
} else {
|
||||
$maybe = 'maybeallowed';
|
||||
}
|
||||
$access = $poll->getAccess();
|
||||
$updatedPoll = false;
|
||||
$dataUnvoted = '';
|
||||
|
||||
if ($poll->getExpire() === null) {
|
||||
$expired = false;
|
||||
} else {
|
||||
|
@ -88,24 +100,28 @@
|
|||
|
||||
// init array for counting 'yes'-votes for each date
|
||||
$total = array();
|
||||
for ($i = 0; $i < count($dates); $i++) {
|
||||
for ($i = 0; $i < count($votes); $i++) {
|
||||
$total['yes'][$i] = 0;
|
||||
$total['no'][$i] = 0;
|
||||
$total['maybe'][$i] = 0;
|
||||
}
|
||||
$userVoted = array();
|
||||
$pollUrl = $urlGenerator->linkToRouteAbsolute('polls.page.goto_poll', ['hash' => $poll->getHash()]);
|
||||
?>
|
||||
|
||||
<div id="app-content" class="<?php p($statusClass . ' ' . $pollTypeClass); ?>">
|
||||
<div id="app-content" class="<?php p($statusClass . ' ' . $pollTypeClass . ' ' . $maybe); ?>">
|
||||
<div id="controls" class="controls">
|
||||
|
||||
<div id="breadcrump" class="breadcrump">
|
||||
<?php if (User::isLoggedIn()) : ?>
|
||||
<div class="crumb svg" data-dir="/">
|
||||
|
||||
<?php if (User::isLoggedIn()) : ?>
|
||||
<div class="crumb svg">
|
||||
<a href="<?php p($urlGenerator->linkToRoute('polls.page.index')); ?>">
|
||||
<img class="svg" src="<?php print_unescaped(Template::image_path('core', 'places/home.svg')); ?>" alt="Home">
|
||||
</a>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="crumb svg last">
|
||||
<span><?php p($poll->getTitle()); ?></span>
|
||||
</div>
|
||||
|
@ -124,44 +140,45 @@
|
|||
</div>
|
||||
|
||||
<div id="votings" class="main-container">
|
||||
<div class="wordwrap description"><span><?php print_unescaped($description); ?></span>
|
||||
<?php
|
||||
if ($expired) {
|
||||
print_unescaped('<span class="' . $statusClass . '">' . $l->t('The poll expired on %s. Voting is disabled, but you can still comment.', array(date('d.m.Y H:i', strtotime($poll->getExpire())))) . '</span>');
|
||||
}?>
|
||||
<div class="wordwrap description">
|
||||
<span>
|
||||
<?php print_unescaped($description); ?>
|
||||
</span>
|
||||
<?php if ($expired) { print_unescaped('<span class="' . $statusClass . '">' . $l->t('The poll expired on %s. Voting is disabled, but you can still comment.', array(date('d.m.Y H:i', strtotime($poll->getExpire())))) . '</span>'); }?>
|
||||
</div>
|
||||
|
||||
<div class="table">
|
||||
<ul class="flex-row header" >
|
||||
<?php
|
||||
foreach ($dates as $dateElement) {
|
||||
if ($poll->getType() === 0) {
|
||||
$timestamp = strtotime($dateElement->getDt());
|
||||
print_unescaped('<li id="slot_' . $dateElement->getId() . '" title="' . $dateElement->getDt() . ' ' . date_default_timezone_get() . '" class="flex-column vote time has-tooltip" data-timestamp="' . $timestamp . '"data-value-utc="' . $dateElement->getDt() . '">');
|
||||
|
||||
print_unescaped(' <div class="date-box flex-column">');
|
||||
print_unescaped(' <div class="month">' . $l->t(date('M', $timestamp)) . '</div>');
|
||||
print_unescaped(' <div class="day">' . date('j', $timestamp) . '</div>');
|
||||
print_unescaped(' <div class="dayow">' . $l->t(date('D', $timestamp)) . '</div>');
|
||||
print_unescaped(' <div class="time">' . date('G:i', $timestamp) . ' UTC</div>');
|
||||
print_unescaped(' </div>');
|
||||
} else {
|
||||
print_unescaped('<li id="slot_' . $dateElement->getId() . '" title="' . preg_replace('/_\d+$/', '', $dateElement->getText()) . '" class="flex-column vote option">');
|
||||
print_unescaped(' <div class="date-box flex-column">' . preg_replace('/_\d+$/', '', $dateElement->getText()) . '</div>');
|
||||
}
|
||||
print_unescaped('<div class="counter flex-row">');
|
||||
print_unescaped(' <div class="yes flex-row">');
|
||||
print_unescaped(' <div class="svg"></div>');
|
||||
print_unescaped(' <div id="counter_yes_voteid_' . $dateElement->getId() . '" class ="result-cell yes" data-voteId="' . $dateElement->getId() . '">0</div>');
|
||||
<ul class="flex-row header" >
|
||||
<?php
|
||||
foreach ($options as $optionElement) {
|
||||
if ($poll->getType() === 0) {
|
||||
$timestamp = strtotime($optionElement->getPollOptionText());
|
||||
print_unescaped('<li id="slot_' . $optionElement->getId() . '" title="' . $optionElement->getPollOptionText() . ' ' . date_default_timezone_get() . '" class="flex-column vote time has-tooltip" data-timestamp="' . $timestamp . '"data-value-utc="' . $optionElement->getPollOptionText() . '">');
|
||||
print_unescaped(' <div class="date-box flex-column">');
|
||||
print_unescaped(' <div class="month">' . $l->t(date('M', $timestamp)) . '</div>');
|
||||
print_unescaped(' <div class="day">' . date('j', $timestamp) . '</div>');
|
||||
print_unescaped(' <div class="dayow">' . $l->t(date('D', $timestamp)) . '</div>');
|
||||
print_unescaped(' <div class="time">' . date('G:i', $timestamp) . ' UTC</div>');
|
||||
print_unescaped(' </div>');
|
||||
print_unescaped(' <div class="no flex-row">');
|
||||
print_unescaped(' <div class="svg"></div>');
|
||||
print_unescaped(' <div id="counter_no_voteid_' . $dateElement->getId() . '" class ="result-cell no" data-voteId="' . $dateElement->getId() . '">0</div>');
|
||||
print_unescaped(' </div>');
|
||||
print_unescaped('</div>');
|
||||
} else {
|
||||
print_unescaped('<li id="slot_' . $optionElement->getId() . '" title="' . $optionElement->getPollOptionText() . '" class="flex-column vote option">');
|
||||
print_unescaped(' <div class="date-box flex-column">' . $optionElement->getPollOptionText() . '</div>');
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
</ul>
|
||||
print_unescaped('<div class="counter flex-row">');
|
||||
print_unescaped(' <div class="yes flex-row">');
|
||||
print_unescaped(' <div class="svg"></div>');
|
||||
print_unescaped(' <div id="counter_yes_voteid_' . $optionElement->getId() . '" class ="result-cell yes" data-voteId="' . $optionElement->getId() . '">0</div>');
|
||||
print_unescaped(' </div>');
|
||||
print_unescaped(' <div class="no flex-row">');
|
||||
print_unescaped(' <div class="svg"></div>');
|
||||
print_unescaped(' <div id="counter_no_voteid_' . $optionElement->getId() . '" class ="result-cell no" data-voteId="' . $optionElement->getId() . '">0</div>');
|
||||
print_unescaped(' </div>');
|
||||
print_unescaped('</div>');
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<ul class="flex-column table-body">
|
||||
<?php
|
||||
if ($votes !== null) {
|
||||
|
@ -169,7 +186,6 @@
|
|||
$others = array();
|
||||
$displayName = '';
|
||||
$avatarName = '';
|
||||
$activeClass = '';
|
||||
foreach ($votes as $vote) {
|
||||
if (!isset($others[$vote->getUserId()])) {
|
||||
$others[$vote->getUserId()] = array();
|
||||
|
@ -192,7 +208,7 @@
|
|||
!$isAnonymous &&
|
||||
!$hideNames
|
||||
) {
|
||||
$displayName = $userMgr->get($usr)->getDisplayName();
|
||||
$displayName = $usr;
|
||||
$avatarName = $usr;
|
||||
} else {
|
||||
if ($isAnonymous || $hideNames) {
|
||||
|
@ -216,37 +232,16 @@
|
|||
// loop over dts
|
||||
$i_tot = 0;
|
||||
|
||||
foreach ($dates as $dateElement) {
|
||||
if ($poll->getType() === 0) {
|
||||
$dateId = strtotime($dateElement->getDt());
|
||||
$pollId = 'voteid_' . $dateElement->getId();
|
||||
} else {
|
||||
$dateId = $dateElement->getText();
|
||||
$pollId = 'voteid_' . $dateElement->getId();
|
||||
}
|
||||
foreach ($options as $optionElement) {
|
||||
// look what user voted for this dts
|
||||
$class = 'flex-column poll-cell no';
|
||||
foreach ($others[$usr] as $vote) {
|
||||
$voteVal = null;
|
||||
if ($poll->getType() === 0) {
|
||||
$voteVal = strtotime($vote->getDt());
|
||||
} else {
|
||||
$voteVal = $vote->getText();
|
||||
}
|
||||
if ($dateId === $voteVal) {
|
||||
if ($vote->getType() === 1) {
|
||||
$class = 'flex-column poll-cell yes';
|
||||
$total['yes'][$i_tot]++;
|
||||
} else if ($vote->getType() === 0) {
|
||||
$class = 'flex-column poll-cell no';
|
||||
$total['no'][$i_tot]++;
|
||||
} else if ($vote->getType() === 2) {
|
||||
$class = 'flex-column poll-cell maybe';
|
||||
}
|
||||
if ($optionElement->getPollOptionText() === $vote->getVoteOptionText()) {
|
||||
$class = $vote->getVoteAnswer();
|
||||
break;
|
||||
}
|
||||
$class = 'no';
|
||||
}
|
||||
print_unescaped('<li id="' . $pollId . '" class="' . $class . '"></li>');
|
||||
print_unescaped('<li id="voteid_' . $optionElement->getId() . '" class="flex-column poll-cell ' . $class . '"></li>');
|
||||
$i_tot++;
|
||||
}
|
||||
|
||||
|
@ -254,8 +249,6 @@
|
|||
print_unescaped('</li>');
|
||||
}
|
||||
}
|
||||
$totalYesOthers = array_merge(array(), $total['yes']);
|
||||
$totalNoOthers = array_merge(array(), $total['no']);
|
||||
$toggleTooltip = $l->t('Switch all options at once');
|
||||
if (!$expired) {
|
||||
print_unescaped('<li class="flex-row user current-user">');
|
||||
|
@ -264,51 +257,45 @@
|
|||
if (User::isLoggedIn()) {
|
||||
print_unescaped(' <div class="avatar has-tooltip" title="' . ($userId) . '"></div>');
|
||||
print_unescaped(' <div class="name">');
|
||||
p($userMgr->get($userId)->getDisplayName());
|
||||
p($userId);
|
||||
} else {
|
||||
print_unescaped(' <div class="avatar has-tooltip" title="?"></div>');
|
||||
print_unescaped(' <div id="id_ac_detected" class="name external current-user"><input type="text" name="user_name" id="user_name" placeholder="' . $l->t('Your name here') . '" />');
|
||||
}
|
||||
print_unescaped(' </div>');
|
||||
print_unescaped(' </div>');
|
||||
if ($maybe === 'maybeallowed') {
|
||||
print_unescaped(' <div id="toggle-cell" class="toggle-cell has-tooltip maybe" title="' . $toggleTooltip . '">');
|
||||
} else {
|
||||
print_unescaped(' <div id="toggle-cell" class="toggle-cell has-tooltip yes" title="' . $toggleTooltip . '">');
|
||||
}
|
||||
print_unescaped(' <div class="toggle"></div>');
|
||||
print_unescaped(' </div>');
|
||||
print_unescaped('</div>');
|
||||
print_unescaped('<ul class="flex-row">');
|
||||
|
||||
$i_tot = 0;
|
||||
foreach ($dates as $dateElement) {
|
||||
if ($poll->getType() === 0) {
|
||||
$dateId = strtotime($dateElement->getDt());
|
||||
$pollId = 'voteid_' . $dateElement->getId();
|
||||
} else {
|
||||
$dateId = $dateElement->getText();
|
||||
$pollId = 'voteid_' . $dateElement->getId();
|
||||
}
|
||||
foreach ($options as $optionElement) {
|
||||
// see if user already has data for this event
|
||||
$class = 'no';
|
||||
$activeClass = 'flex-column active poll-cell';
|
||||
$dataUnvoted = '';
|
||||
if (isset($userVoted)) {
|
||||
foreach ($userVoted as $obj) {
|
||||
$voteVal = null;
|
||||
if ($poll->getType() === 0) {
|
||||
$voteVal = strtotime($obj->getDt());
|
||||
} else {
|
||||
$voteVal = $obj->getText();
|
||||
}
|
||||
if ($voteVal === $dateId) {
|
||||
if ($obj->getType() === 1) {
|
||||
$class = 'yes';
|
||||
$total['yes'][$i_tot]++;
|
||||
} else if ($obj->getType() === 2) {
|
||||
$class = 'maybe';
|
||||
}
|
||||
foreach ($userVoted as $vote) {
|
||||
if ($optionElement->getPollOptionText() === $vote->getVoteOptionText()) {
|
||||
$class = $vote->getVoteAnswer();
|
||||
break;
|
||||
} else {
|
||||
$class = 'unvoted';
|
||||
}
|
||||
}
|
||||
}
|
||||
print_unescaped('<li id="' . $pollId . '" class="' . $activeClass . ' ' . $class . '" data-value="' . $dateId . '"></li>');
|
||||
|
||||
if ($class === 'unvoted') {
|
||||
$dataUnvoted = $l->t('New');
|
||||
$updatedPoll = true;
|
||||
}
|
||||
|
||||
print_unescaped('<li id="voteid_' . $optionElement->getId() . '" class="flex-column active poll-cell ' . $class . '" data-value="' . $optionElement->getPollOptionText() . '" data-unvoted="' . $dataUnvoted . '"></li>');
|
||||
|
||||
$i_tot++;
|
||||
}
|
||||
|
@ -318,24 +305,33 @@
|
|||
?>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<?php if ($updatedPoll) : ?>
|
||||
<div class="updated-poll alert">
|
||||
<p> <?php p($l->t('This poll was updated since your last visit. Please check your votes.')); ?></p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="submitPoll flex-row">
|
||||
<div>
|
||||
<form class="finish_vote" name="finish_vote" action="<?php p($urlGenerator->linkToRoute('polls.page.insert_vote')); ?>" method="POST">
|
||||
<input type="hidden" name="pollId" value="<?php p($poll->getId()); ?>" />
|
||||
<input type="hidden" name="userId" value="<?php p($userId); ?>" />
|
||||
<input type="hidden" name="dates" value="<?php p($poll->getId()); ?>" />
|
||||
<input type="hidden" name="types" value="<?php p($poll->getId()); ?>" />
|
||||
<input type="hidden" name="options" value="<?php p($poll->getId()); ?>" />
|
||||
<input type="hidden" name="answers" value="<?php p($poll->getId()); ?>" />
|
||||
<input type="hidden" name="receiveNotifications" />
|
||||
<input type="hidden" name="changed" />
|
||||
<input type="button" id="submit_finish_vote" class="button btn" value="<?php p($l->t('Vote!')); ?>" />
|
||||
<input type="button" id="submit_finish_vote" class="button btn primary" value="<?php p($l->t('Vote!')); ?>" />
|
||||
</form>
|
||||
</div>
|
||||
<?php if (User::isLoggedIn()) : ?>
|
||||
|
||||
<?php if (User::isLoggedIn()) : ?>
|
||||
<div class="notification">
|
||||
<input type="checkbox" id="check_notif" class="checkbox" <?php if ($notification !== null) print_unescaped(' checked'); ?> />
|
||||
<label for="check_notif"><?php p($l->t('Receive notification email on activity')); ?></label>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -351,7 +347,7 @@
|
|||
<div class="authorRow user-cell flex-row">
|
||||
<div class="description leftLabel"><?php p($l->t('Owner')); ?></div>
|
||||
<div class="avatar has-tooltip-bottom" title="<?php p($poll->getOwner())?>"></div>
|
||||
<div class="author"><?php p($userMgr->get($poll->getOwner())->getDisplayName()); ?></div>
|
||||
<div class="author"><?php p($poll->getOwner()); ?></div>
|
||||
</div>
|
||||
|
||||
<div class="cloud">
|
||||
|
@ -407,30 +403,31 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<?php if ($expired) : ?>
|
||||
<div id="expired_info">
|
||||
<h2><?php p($l->t('Poll expired')); ?></h2>
|
||||
<p>
|
||||
<?php p($l->t('The poll expired on %s. Voting is disabled, but you can still comment.', array(date('d.m.Y H:i', strtotime($poll->getExpire()))))); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php if ($expired) : ?>
|
||||
<div id="expired_info">
|
||||
<h2><?php p($l->t('Poll expired')); ?></h2>
|
||||
<p>
|
||||
<?php p($l->t('The poll expired on %s. Voting is disabled, but you can still comment.', array(date('d.m.Y H:i', strtotime($poll->getExpire()))))); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<ul class="tabHeaders">
|
||||
<li class="tabHeader selected" data-tabid="commentsTabView" data-tabindex="0">
|
||||
<a href="#"><?php p($l->t('Comments')); ?></a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tabsContainer">
|
||||
<div id="commentsTabView" class="tab commentsTabView">
|
||||
<div class="newCommentRow comment new-comment">
|
||||
<?php if (User::isLoggedIn()) : ?>
|
||||
|
||||
<?php if (User::isLoggedIn()) : ?>
|
||||
<div class="authorRow user-cell flex-row">
|
||||
<div class="avatar has-tooltip" title="<?php p($userId)?>"></div>
|
||||
<div class="author"><?php p($userMgr->get($userId)->getDisplayName()) ?></div>
|
||||
<div class="author"><?php p($userId) ?></div>
|
||||
</div>
|
||||
|
||||
<?php else: ?>
|
||||
<?php else: ?>
|
||||
<a href="<?php p($urlGenerator->linkToRouteAbsolute('core.login.showLoginForm')); ?>"><?php p($l->t('Login or ...')); ?></a>
|
||||
<div class="authorRow user-cell flex-row">
|
||||
<div class="avatar has-tooltip" title="?"></div>
|
||||
|
@ -438,7 +435,8 @@
|
|||
<input type="text" name="user_name_comm" id="user_name_comm" placeholder="<?php p($l->t('Your name here')); ?>" />
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<form class="newCommentForm flex-row" name="send_comment" action="<?php p($urlGenerator->linkToRoute('polls.page.insert_comment')); ?>" method="POST">
|
||||
<input type="hidden" name="pollId" value="<?php p($poll->getId()); ?>" />
|
||||
<input type="hidden" name="userId" value="<?php p($userId); ?>" />
|
||||
|
@ -467,7 +465,7 @@
|
|||
// Comment is from current user
|
||||
// -> display user
|
||||
$avatarName = $userId;
|
||||
$displayName = $userMgr->get($userId)->getDisplayName();
|
||||
$displayName = $userId;
|
||||
|
||||
} else if (!$isAnonymous && !$hideNames) {
|
||||
// comment is from another user,
|
||||
|
@ -476,9 +474,6 @@
|
|||
// -> display user
|
||||
$avatarName = $comment->getUserId();
|
||||
$displayName = $avatarName;
|
||||
if ($userMgr->get($comment->getUserId()) !== null) {
|
||||
$displayName = $userMgr->get($avatarName)->getDisplayName();
|
||||
}
|
||||
} else {
|
||||
// in all other cases
|
||||
// -> make user anonymous
|
||||
|
@ -501,6 +496,6 @@
|
|||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<form id="form_delete_poll" name="form_delete_poll" action="<?php p($urlGenerator->linkToRoute('polls.page.delete_poll')); ?>" method="POST"></form>
|
||||
</div>
|
||||
|
||||
|
||||
<form id="form_delete_poll" name="form_delete_poll" action="<?php p($urlGenerator->linkToRoute('polls.page.delete_poll')); ?>" method="POST"></form>
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
/** @var \OCA\Polls\Db\Event[] $polls */
|
||||
$polls = $_['polls'];
|
||||
?>
|
||||
|
||||
<div id="app-content">
|
||||
<div id="controls">
|
||||
<div class="breadcrump">
|
||||
|
@ -97,11 +98,7 @@
|
|||
$owner = $poll->getOwner();
|
||||
|
||||
$expiry_style = '';
|
||||
if ($poll->getType() === 0) {
|
||||
$participated = $_['participations'];
|
||||
} else {
|
||||
$participated = $_['participations_text'];
|
||||
}
|
||||
$participated = $_['votes'];
|
||||
$participated_class = 'partic_no';
|
||||
$participated_title = 'You did not vote';
|
||||
$participated_count = count($participated);
|
||||
|
@ -115,6 +112,7 @@
|
|||
$owner = $l->t('Yourself');
|
||||
}
|
||||
|
||||
|
||||
$timestamp_style = '';
|
||||
$expiry_style = ' endless';
|
||||
$expiry_date = $l->t('Never');
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<?php p($l->t('Access denied')); ?>
|
||||
</h1>
|
||||
<h2>
|
||||
<?php p($l->t('You are not allowed to delete this poll or the poll does not exist.')); ?>
|
||||
<?php p($l->t('You are either not allowed to delete this poll or it doesn\'t exist.')); ?>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -62,7 +62,7 @@ class PageControllerTest extends UnitTestCase {
|
|||
$commentMapper = $this->getMockBuilder('OCA\Polls\Db\CommentMapper')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$dateMapper = $this->getMockBuilder('OCA\Polls\Db\DateMapper')
|
||||
$optionsMapper = $this->getMockBuilder('OCA\Polls\Db\OptionsMapper')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$eventMapper = $this->getMockBuilder('OCA\Polls\Db\EventMapper')
|
||||
|
@ -71,13 +71,7 @@ class PageControllerTest extends UnitTestCase {
|
|||
$notificationMapper = $this->getMockBuilder('OCA\Polls\Db\NotificationMapper')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$participationMapper = $this->getMockBuilder('OCA\Polls\Db\ParticipationMapper')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$participationTextMapper = $this->getMockBuilder('OCA\Polls\Db\ParticipationTextMapper')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$textMapper = $this->getMockBuilder('OCA\Polls\Db\TextMapper')
|
||||
$votesMapper = $this->getMockBuilder('OCA\Polls\Db\VotesMapper')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
|
@ -92,12 +86,10 @@ class PageControllerTest extends UnitTestCase {
|
|||
$urlGenerator,
|
||||
$this->userId,
|
||||
$commentMapper,
|
||||
$dateMapper,
|
||||
$optionsMapper,
|
||||
$eventMapper,
|
||||
$notificationMapper,
|
||||
$participationMapper,
|
||||
$participationTextMapper,
|
||||
$textMapper
|
||||
$votesMapper
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -25,18 +25,18 @@ namespace OCA\Polls\Tests\Unit\Db;
|
|||
|
||||
use OCA\Polls\Db\Event;
|
||||
use OCA\Polls\Db\EventMapper;
|
||||
use OCA\Polls\Db\Text;
|
||||
use OCA\Polls\Db\TextMapper;
|
||||
use OCA\Polls\Db\Options;
|
||||
use OCA\Polls\Db\OptionsMapper;
|
||||
use OCA\Polls\Tests\Unit\UnitTestCase;
|
||||
use OCP\IDBConnection;
|
||||
use League\FactoryMuffin\Faker\Facade as Faker;
|
||||
|
||||
class TextMapperTest extends UnitTestCase {
|
||||
class OptionsMapperTest extends UnitTestCase {
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $con;
|
||||
/** @var TextMapper */
|
||||
private $textMapper;
|
||||
/** @var OptionsMapper */
|
||||
private $optionsMapper;
|
||||
/** @var EventMapper */
|
||||
private $eventMapper;
|
||||
|
||||
|
@ -46,52 +46,52 @@ class TextMapperTest extends UnitTestCase {
|
|||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->con = \OC::$server->getDatabaseConnection();
|
||||
$this->textMapper = new TextMapper($this->con);
|
||||
$this->optionsMapper = new OptionsMapper($this->con);
|
||||
$this->eventMapper = new EventMapper($this->con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create some fake data and persist them to the database.
|
||||
*
|
||||
* @return Text
|
||||
* @return Options
|
||||
*/
|
||||
public function testCreate() {
|
||||
/** @var Event $event */
|
||||
$event = $this->fm->instance('OCA\Polls\Db\Event');
|
||||
$this->assertInstanceOf(Event::class, $this->eventMapper->insert($event));
|
||||
|
||||
/** @var Text $text */
|
||||
$text = $this->fm->instance('OCA\Polls\Db\Text');
|
||||
$text->setPollId($event->getId());
|
||||
$this->assertInstanceOf(Text::class, $this->textMapper->insert($text));
|
||||
/** @var Options $options */
|
||||
$options = $this->fm->instance('OCA\Polls\Db\Options');
|
||||
$options->setPollId($event->getId());
|
||||
$this->assertInstanceOf(Options::class, $this->optionsMapper->insert($options));
|
||||
|
||||
return $text;
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the previously created entry and persist the changes.
|
||||
*
|
||||
* @depends testCreate
|
||||
* @param Text $text
|
||||
* @return Text
|
||||
* @param Options $options
|
||||
* @return Options
|
||||
*/
|
||||
public function testUpdate(Text $text) {
|
||||
$newText = Faker::paragraph();
|
||||
$text->setText($newText());
|
||||
$this->textMapper->update($text);
|
||||
public function testUpdate(Options $options) {
|
||||
$newPollOptionText = Faker::paragraph();
|
||||
$options->setPollOptionText($newPollOptionText());
|
||||
$this->optionsMapper->update($options);
|
||||
|
||||
return $text;
|
||||
return $options;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete the previously created entries from the database.
|
||||
*
|
||||
* @depends testUpdate
|
||||
* @param Text $text
|
||||
* @param Options $options
|
||||
*/
|
||||
public function testDelete(Text $text) {
|
||||
$event = $this->eventMapper->find($text->getPollId());
|
||||
$this->textMapper->delete($text);
|
||||
public function testDelete(Options $options) {
|
||||
$event = $this->eventMapper->find($options->getPollId());
|
||||
$this->optionsMapper->delete($options);
|
||||
$this->eventMapper->delete($event);
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @author Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Tests\Unit\Db;
|
||||
|
||||
use OCA\Polls\Db\Event;
|
||||
use OCA\Polls\Db\EventMapper;
|
||||
use OCA\Polls\Db\Participation;
|
||||
use OCA\Polls\Db\ParticipationMapper;
|
||||
use OCA\Polls\Tests\Unit\UnitTestCase;
|
||||
use OCP\IDBConnection;
|
||||
use League\FactoryMuffin\Faker\Facade as Faker;
|
||||
|
||||
class ParticipationMapperTest extends UnitTestCase {
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $con;
|
||||
/** @var ParticipationMapper */
|
||||
private $participationMapper;
|
||||
/** @var EventMapper */
|
||||
private $eventMapper;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->con = \OC::$server->getDatabaseConnection();
|
||||
$this->participationMapper = new ParticipationMapper($this->con);
|
||||
$this->eventMapper = new EventMapper($this->con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create some fake data and persist them to the database.
|
||||
*
|
||||
* @return Participation
|
||||
*/
|
||||
public function testCreate() {
|
||||
/** @var Event $event */
|
||||
$event = $this->fm->instance('OCA\Polls\Db\Event');
|
||||
$this->assertInstanceOf(Event::class, $this->eventMapper->insert($event));
|
||||
|
||||
/** @var Participation $participation */
|
||||
$participation = $this->fm->instance('OCA\Polls\Db\Participation');
|
||||
$participation->setPollId($event->getId());
|
||||
$this->assertInstanceOf(Participation::class, $this->participationMapper->insert($participation));
|
||||
|
||||
return $participation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the previously created entry and persist the changes.
|
||||
*
|
||||
* @depends testCreate
|
||||
* @param Participation $participation
|
||||
* @return Participation
|
||||
*/
|
||||
public function testUpdate(Participation $participation) {
|
||||
$newDt = Faker::date('Y-m-d H:i:s');
|
||||
$participation->setDt($newDt());
|
||||
$this->participationMapper->update($participation);
|
||||
|
||||
return $participation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the previously created entries from the database.
|
||||
*
|
||||
* @depends testUpdate
|
||||
* @param Participation $participation
|
||||
*/
|
||||
public function testDelete(Participation $participation) {
|
||||
$event = $this->eventMapper->find($participation->getPollId());
|
||||
$this->participationMapper->delete($participation);
|
||||
$this->eventMapper->delete($event);
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @author Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OCA\Polls\Tests\Unit\Db;
|
||||
|
||||
use OCA\Polls\Db\Event;
|
||||
use OCA\Polls\Db\EventMapper;
|
||||
use OCA\Polls\Db\ParticipationText;
|
||||
use OCA\Polls\Db\ParticipationTextMapper;
|
||||
use OCA\Polls\Tests\Unit\UnitTestCase;
|
||||
use OCP\IDBConnection;
|
||||
use League\FactoryMuffin\Faker\Facade as Faker;
|
||||
|
||||
class ParticipationTextMapperTest extends UnitTestCase {
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $con;
|
||||
/** @var ParticipationTextMapper */
|
||||
private $participationTextMapper;
|
||||
/** @var EventMapper */
|
||||
private $eventMapper;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->con = \OC::$server->getDatabaseConnection();
|
||||
$this->participationTextMapper = new ParticipationTextMapper($this->con);
|
||||
$this->eventMapper = new EventMapper($this->con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create some fake data and persist them to the database.
|
||||
*
|
||||
* @return ParticipationText
|
||||
*/
|
||||
public function testCreate() {
|
||||
/** @var Event $event */
|
||||
$event = $this->fm->instance('OCA\Polls\Db\Event');
|
||||
$this->assertInstanceOf(Event::class, $this->eventMapper->insert($event));
|
||||
|
||||
/** @var ParticipationText $participationText */
|
||||
$participationText = $this->fm->instance('OCA\Polls\Db\ParticipationText');
|
||||
$participationText->setPollId($event->getId());
|
||||
$this->assertInstanceOf(ParticipationText::class, $this->participationTextMapper->insert($participationText));
|
||||
|
||||
return $participationText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the previously created entry and persist the changes.
|
||||
*
|
||||
* @depends testCreate
|
||||
* @param ParticipationText $participationText
|
||||
* @return ParticipationText
|
||||
*/
|
||||
public function testUpdate(ParticipationText $participationText) {
|
||||
$newText = Faker::paragraph();
|
||||
$participationText->setText($newText());
|
||||
$this->participationTextMapper->update($participationText);
|
||||
|
||||
return $participationText;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the previously created entries from the database.
|
||||
*
|
||||
* @depends testUpdate
|
||||
* @param ParticipationText $participationText
|
||||
*/
|
||||
public function testDelete(ParticipationText $participationText) {
|
||||
$event = $this->eventMapper->find($participationText->getPollId());
|
||||
$this->participationTextMapper->delete($participationText);
|
||||
$this->eventMapper->delete($event);
|
||||
}
|
||||
}
|
|
@ -23,20 +23,20 @@
|
|||
|
||||
namespace OCA\Polls\Tests\Unit\Db;
|
||||
|
||||
use OCA\Polls\Db\Date;
|
||||
use OCA\Polls\Db\DateMapper;
|
||||
use OCA\Polls\Db\Event;
|
||||
use OCA\Polls\Db\EventMapper;
|
||||
use OCA\Polls\Db\Votes;
|
||||
use OCA\Polls\Db\VotesMapper;
|
||||
use OCA\Polls\Tests\Unit\UnitTestCase;
|
||||
use OCP\IDBConnection;
|
||||
use League\FactoryMuffin\Faker\Facade as Faker;
|
||||
|
||||
class DateMapperTest extends UnitTestCase {
|
||||
class VotesMapperTest extends UnitTestCase {
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $con;
|
||||
/** @var DateMapper */
|
||||
private $dateMapper;
|
||||
/** @var VotesMapper */
|
||||
private $votesMapper;
|
||||
/** @var EventMapper */
|
||||
private $eventMapper;
|
||||
|
||||
|
@ -46,52 +46,54 @@ class DateMapperTest extends UnitTestCase {
|
|||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->con = \OC::$server->getDatabaseConnection();
|
||||
$this->dateMapper = new DateMapper($this->con);
|
||||
$this->votesMapper = new VotesMapper($this->con);
|
||||
$this->eventMapper = new EventMapper($this->con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create some fake data and persist them to the database.
|
||||
*
|
||||
* @return Date
|
||||
* @return Votes
|
||||
*/
|
||||
public function testCreate() {
|
||||
/** @var Event $event */
|
||||
$event = $this->fm->instance('OCA\Polls\Db\Event');
|
||||
$this->assertInstanceOf(Event::class, $this->eventMapper->insert($event));
|
||||
|
||||
/** @var Date $date */
|
||||
$date = $this->fm->instance('OCA\Polls\Db\Date');
|
||||
$date->setPollId($event->getId());
|
||||
$this->assertInstanceOf(Date::class, $this->dateMapper->insert($date));
|
||||
|
||||
/** @var Votes $votes */
|
||||
$votes = $this->fm->instance('OCA\Polls\Db\Votes');
|
||||
$votes->setPollId($event->getId());
|
||||
$votes->setVoteOptionId(1);
|
||||
$this->assertInstanceOf(Votes::class, $this->votesMapper->insert($votes));
|
||||
|
||||
return $date;
|
||||
return $votes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the previously created entry and persist the changes.
|
||||
*
|
||||
* @depends testCreate
|
||||
* @param Date $date
|
||||
* @return Date
|
||||
* @param Votes $votes
|
||||
* @return Votes
|
||||
*/
|
||||
public function testUpdate(Date $date) {
|
||||
$newDt = Faker::date('Y-m-d H:i:s');
|
||||
$date->setDt($newDt());
|
||||
$this->dateMapper->update($date);
|
||||
public function testUpdate(Votes $votes) {
|
||||
$newVoteOptionText = Faker::date('Y-m-d H:i:s');
|
||||
$votes->setVoteOptionText($newVoteOptionText());
|
||||
$this->votesMapper->update($votes);
|
||||
|
||||
return $date;
|
||||
return $votes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the previously created entries from the database.
|
||||
*
|
||||
* @depends testUpdate
|
||||
* @param Date $date
|
||||
* @param Votes $votes
|
||||
*/
|
||||
public function testDelete(Date $date) {
|
||||
$event = $this->eventMapper->find($date->getPollId());
|
||||
$this->dateMapper->delete($date);
|
||||
public function testDelete(Votes $votes) {
|
||||
$event = $this->eventMapper->find($votes->getPollId());
|
||||
$this->votesMapper->delete($votes);
|
||||
$this->eventMapper->delete($event);
|
||||
}
|
||||
}
|
|
@ -28,9 +28,9 @@ use League\FactoryMuffin\Faker\Facade as Faker;
|
|||
*/
|
||||
$fm->define('OCA\Polls\Db\Comment')->setDefinitions([
|
||||
'userId' => Faker::firstNameMale(),
|
||||
'dt' => function () {
|
||||
'dt' => function() {
|
||||
$date = new DateTime('today');
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
},
|
||||
'comment' => Faker::text(256)
|
||||
'comment' => Faker::text(255)
|
||||
]);
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @author Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* General factory for the date model.
|
||||
*/
|
||||
$fm->define('OCA\Polls\Db\Date')->setDefinitions([
|
||||
'dt' => function () {
|
||||
$date = new DateTime('today');
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
}
|
||||
]);
|
|
@ -29,14 +29,14 @@ use League\FactoryMuffin\Faker\Facade as Faker;
|
|||
$fm->define('OCA\Polls\Db\Event')->setDefinitions([
|
||||
'type' => 0,
|
||||
'title' => Faker::sentence(10),
|
||||
'description' => Faker::text(256),
|
||||
'description' => Faker::text(255),
|
||||
'owner' => Faker::firstNameMale(),
|
||||
'created' => function () {
|
||||
'created' => function() {
|
||||
$date = new DateTime('today');
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
},
|
||||
'access' => 'registered',
|
||||
'expire' => function () {
|
||||
'expire' => function() {
|
||||
$date = new DateTime('tomorrow');
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
},
|
||||
|
|
|
@ -26,6 +26,6 @@ use League\FactoryMuffin\Faker\Facade as Faker;
|
|||
/**
|
||||
* General factory for the text model.
|
||||
*/
|
||||
$fm->define('OCA\Polls\Db\Text')->setDefinitions([
|
||||
'text' => Faker::text(256)
|
||||
$fm->define('OCA\Polls\Db\Options')->setDefinitions([
|
||||
'pollOptionText' => Faker::text(255)
|
||||
]);
|
|
@ -1,36 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2017 Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @author Kai Schröer <git@schroeer.co>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
use League\FactoryMuffin\Faker\Facade as Faker;
|
||||
|
||||
/**
|
||||
* General factory for the participation model.
|
||||
*/
|
||||
$fm->define('OCA\Polls\Db\Participation')->setDefinitions([
|
||||
'userId' => Faker::firstNameMale(),
|
||||
'dt' => function () {
|
||||
$date = new DateTime('today');
|
||||
return $date->format('Y-m-d H:i:s');
|
||||
},
|
||||
'type' => 0
|
||||
]);
|
|
@ -24,10 +24,10 @@
|
|||
use League\FactoryMuffin\Faker\Facade as Faker;
|
||||
|
||||
/**
|
||||
* General factory for the participation text model.
|
||||
* General factory for the votes model.
|
||||
*/
|
||||
$fm->define('OCA\Polls\Db\ParticipationText')->setDefinitions([
|
||||
'text' => Faker::text(256),
|
||||
$fm->define('OCA\Polls\Db\Votes')->setDefinitions([
|
||||
'voteOptionText' => Faker::text(255),
|
||||
'userId' => Faker::firstNameMale(),
|
||||
'type' => 0
|
||||
'voteAnswer' => 'yes'
|
||||
]);
|