1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-28 16:30:59 +01:00

Clicking in day view should create new event

Summary: Ref T8300, clicking in day view should create new event

Test Plan: Open day view, click in an empty slot, new event modal should open.

Reviewers: epriestley, #blessed_reviewers, chad

Reviewed By: epriestley, #blessed_reviewers

Subscribers: Korvin, epriestley

Maniphest Tasks: T8300

Differential Revision: https://secure.phabricator.com/D12990
This commit is contained in:
lkassianik 2015-05-24 11:22:33 -07:00
parent 963485a3da
commit 18fe6d58ae
8 changed files with 173 additions and 34 deletions

View file

@ -121,7 +121,7 @@ return array(
'rsrc/css/layout/phabricator-hovercard-view.css' => 'dd9121a9',
'rsrc/css/layout/phabricator-side-menu-view.css' => 'c1db9e9c',
'rsrc/css/layout/phabricator-source-code-view.css' => '2ceee894',
'rsrc/css/phui/calendar/phui-calendar-day.css' => 'feba82c5',
'rsrc/css/phui/calendar/phui-calendar-day.css' => 'd1cf6f93',
'rsrc/css/phui/calendar/phui-calendar-list.css' => 'c1c7f338',
'rsrc/css/phui/calendar/phui-calendar-month.css' => '476be7e0',
'rsrc/css/phui/calendar/phui-calendar.css' => 'ccabe893',
@ -331,7 +331,7 @@ return array(
'rsrc/js/application/aphlict/behavior-aphlict-listen.js' => 'b1a59974',
'rsrc/js/application/aphlict/behavior-aphlict-status.js' => 'ea681761',
'rsrc/js/application/auth/behavior-persona-login.js' => '9414ff18',
'rsrc/js/application/calendar/behavior-day-view.js' => 'dc0065ab',
'rsrc/js/application/calendar/behavior-day-view.js' => '28a60488',
'rsrc/js/application/calendar/behavior-event-all-day.js' => '38dcf3c8',
'rsrc/js/application/config/behavior-reorder-fields.js' => '14a827de',
'rsrc/js/application/conpherence/ConpherenceThreadManager.js' => '10246726',
@ -554,7 +554,7 @@ return array(
'javelin-behavior-dashboard-move-panels' => '82439934',
'javelin-behavior-dashboard-query-panel-select' => '453c5375',
'javelin-behavior-dashboard-tab-panel' => 'd4eecc63',
'javelin-behavior-day-view' => 'dc0065ab',
'javelin-behavior-day-view' => '28a60488',
'javelin-behavior-device' => 'a205cf28',
'javelin-behavior-differential-add-reviewers-and-ccs' => 'e10f8e18',
'javelin-behavior-differential-comment-jump' => '4fdb476d',
@ -767,7 +767,7 @@ return array(
'phui-box-css' => '7b3a2eed',
'phui-button-css' => 'de610129',
'phui-calendar-css' => 'ccabe893',
'phui-calendar-day-css' => 'feba82c5',
'phui-calendar-day-css' => 'd1cf6f93',
'phui-calendar-list-css' => 'c1c7f338',
'phui-calendar-month-css' => '476be7e0',
'phui-crumbs-view-css' => '594d719e',

View file

@ -14,8 +14,8 @@ final class PhabricatorCalendarEventEditController
}
public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
$user_phid = $user->getPHID();
$viewer = $request->getViewer();
$user_phid = $viewer->getPHID();
$error_name = true;
$error_start_date = true;
$error_end_date = true;
@ -25,9 +25,41 @@ final class PhabricatorCalendarEventEditController
$start_date_id = celerity_generate_unique_node_id();
$end_date_id = null;
$next_workflow = $request->getStr('next');
$uri_query = $request->getStr('query');
if ($this->isCreate()) {
$event = PhabricatorCalendarEvent::initializeNewCalendarEvent($user);
list($start_value, $end_value) = $this->getDefaultTimeValues($user);
$event = PhabricatorCalendarEvent::initializeNewCalendarEvent($viewer);
$create_start_year = $request->getInt('year');
$create_start_month = $request->getInt('month');
$create_start_day = $request->getInt('day');
$create_start_time = $request->getStr('time');
if ($create_start_year) {
$start = AphrontFormDateControlValue::newFromParts(
$viewer,
$create_start_year,
$create_start_month,
$create_start_day,
$create_start_time);
if (!$start->isValid()) {
return new Aphront400Response();
}
$start_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$start->getEpoch());
$end = clone $start_value->getDateTime();
$end->modify('+1 hour');
$end_value = AphrontFormDateControlValue::newFromEpoch(
$viewer,
$end->format('U'));
} else {
list($start_value, $end_value) = $this->getDefaultTimeValues($viewer);
}
$submit_label = pht('Create');
$page_title = pht('Create Event');
@ -38,7 +70,7 @@ final class PhabricatorCalendarEventEditController
$end_date_id = celerity_generate_unique_node_id();
} else {
$event = id(new PhabricatorCalendarEventQuery())
->setViewer($user)
->setViewer($viewer)
->withIDs(array($this->id))
->requireCapabilities(
array(
@ -51,10 +83,10 @@ final class PhabricatorCalendarEventEditController
}
$end_value = AphrontFormDateControlValue::newFromEpoch(
$user,
$viewer,
$event->getDateTo());
$start_value = AphrontFormDateControlValue::newFromEpoch(
$user,
$viewer,
$event->getDateFrom());
$submit_label = pht('Update');
@ -81,7 +113,7 @@ final class PhabricatorCalendarEventEditController
$icon = $event->getIcon();
$current_policies = id(new PhabricatorPolicyQuery())
->setViewer($user)
->setViewer($viewer)
->setObject($event)
->execute();
@ -106,9 +138,9 @@ final class PhabricatorCalendarEventEditController
$new_invitees = $this->getNewInviteeList($invitees, $event);
$status_attending = PhabricatorCalendarEventInvitee::STATUS_ATTENDING;
if ($this->isCreate()) {
$status = idx($new_invitees, $user->getPHID());
$status = idx($new_invitees, $viewer->getPHID());
if ($status) {
$new_invitees[$user->getPHID()] = $status_attending;
$new_invitees[$viewer->getPHID()] = $status_attending;
}
}
@ -161,14 +193,29 @@ final class PhabricatorCalendarEventEditController
->setNewValue($request->getStr('editPolicy'));
$editor = id(new PhabricatorCalendarEventEditor())
->setActor($user)
->setActor($viewer)
->setContentSourceFromRequest($request)
->setContinueOnNoEffect(true);
try {
$xactions = $editor->applyTransactions($event, $xactions);
$response = id(new AphrontRedirectResponse());
return $response->setURI('/E'.$event->getID());
switch ($next_workflow) {
case 'day':
if (!$uri_query) {
$uri_query = 'month';
}
$year = $start_value->getDateTime()->format('Y');
$month = $start_value->getDateTime()->format('m');
$day = $start_value->getDateTime()->format('d');
$response->setURI(
'/calendar/query/'.$uri_query.'/'.$year.'/'.$month.'/'.$day.'/');
break;
default:
$response->setURI('/E'.$event->getID());
break;
}
return $response;
} catch (PhabricatorApplicationTransactionValidationException $ex) {
$validation_exception = $ex;
$error_name = $ex->getShortMessage(
@ -204,7 +251,7 @@ final class PhabricatorCalendarEventEditController
$all_day_id);
$start_control = id(new AphrontFormDateControl())
->setUser($user)
->setUser($viewer)
->setName('start')
->setLabel(pht('Start'))
->setError($error_start_date)
@ -214,7 +261,7 @@ final class PhabricatorCalendarEventEditController
->setEndDateID($end_date_id);
$end_control = id(new AphrontFormDateControl())
->setUser($user)
->setUser($viewer)
->setName('end')
->setLabel(pht('End'))
->setError($error_end_date)
@ -228,13 +275,13 @@ final class PhabricatorCalendarEventEditController
->setValue($description);
$view_policies = id(new AphrontFormPolicyControl())
->setUser($user)
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
->setPolicyObject($event)
->setPolicies($current_policies)
->setName('viewPolicy');
$edit_policies = id(new AphrontFormPolicyControl())
->setUser($user)
->setUser($viewer)
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
->setPolicyObject($event)
->setPolicies($current_policies)
@ -244,14 +291,14 @@ final class PhabricatorCalendarEventEditController
->setLabel(pht('Subscribers'))
->setName('subscribers')
->setValue($subscribers)
->setUser($user)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource());
$invitees = id(new AphrontFormTokenizerControl())
->setLabel(pht('Invitees'))
->setName('invitees')
->setValue($invitees)
->setUser($user)
->setUser($viewer)
->setDatasource(new PhabricatorMetaMTAMailableDatasource());
if ($this->isCreate()) {
@ -269,7 +316,9 @@ final class PhabricatorCalendarEventEditController
->setValue($icon);
$form = id(new AphrontFormView())
->setUser($user)
->addHiddenInput('next', $next_workflow)
->addHiddenInput('query', $uri_query)
->setUser($viewer)
->appendChild($name)
->appendChild($all_day_checkbox)
->appendChild($start_control)
@ -351,19 +400,19 @@ final class PhabricatorCalendarEventEditController
return $new;
}
private function getDefaultTimeValues($user) {
private function getDefaultTimeValues($viewer) {
$start = new DateTime('@'.time());
$start->setTimeZone($user->getTimeZone());
$start->setTimeZone($viewer->getTimeZone());
$start->setTime($start->format('H'), 0, 0);
$start->modify('+1 hour');
$end = id(clone $start)->modify('+1 hour');
$start_value = AphrontFormDateControlValue::newFromEpoch(
$user,
$viewer,
$start->format('U'));
$end_value = AphrontFormDateControlValue::newFromEpoch(
$user,
$viewer,
$end->format('U'));
return array($start_value, $end_value);

View file

@ -390,12 +390,13 @@ final class PhabricatorCalendarEventSearchEngine
list($start_year, $start_month, $start_day) =
$this->getDisplayYearAndMonthAndDay($query);
$day_view = new PHUICalendarDayView(
$day_view = id(new PHUICalendarDayView(
$this->getDateFrom($query),
$this->getDateTo($query),
$start_year,
$start_month,
$start_day);
$start_day))
->setQuery($query->getQueryKey());
$day_view->setUser($viewer);
@ -408,7 +409,13 @@ final class PhabricatorCalendarEventSearchEngine
$viewer_is_invited = $status->getIsUserInvited($viewer->getPHID());
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$status,
PhabricatorPolicyCapability::CAN_EDIT);
$event = new AphrontCalendarEventView();
$event->setCanEdit($can_edit);
$event->setEventID($status->getID());
$event->setEpochRange($status->getDateFrom(), $status->getDateTo());
$event->setIsAllDay($status->getIsAllDay());

View file

@ -12,6 +12,7 @@ final class AphrontCalendarEventView extends AphrontView {
private $uri;
private $isAllDay;
private $icon;
private $canEdit;
public function setURI($uri) {
$this->uri = $uri;
@ -97,6 +98,14 @@ final class AphrontCalendarEventView extends AphrontView {
return $this->icon;
}
public function setCanEdit($can_edit) {
$this->canEdit = $can_edit;
return $this;
}
public function getCanEdit() {
return $this->canEdit;
}
public function getMultiDay() {
$nextday = strtotime('12:00 AM Tomorrow', $this->getEpochStart());

View file

@ -211,6 +211,19 @@ final class AphrontFormDateControlValue extends Phobject {
return $value;
}
public function getDateTime() {
$epoch = $this->getEpoch();
$date = null;
if ($epoch) {
$zone = $this->getTimezone();
$date = new DateTime('@'.$epoch);
$date->setTimeZone($zone);
}
return $date;
}
private function getTimezone() {
if ($this->zone) {
return $this->zone;

View file

@ -8,6 +8,7 @@ final class PHUICalendarDayView extends AphrontView {
private $month;
private $year;
private $browseURI;
private $query;
private $events = array();
private $allDayEvents = array();
@ -25,6 +26,14 @@ final class PHUICalendarDayView extends AphrontView {
return $this->browseURI;
}
public function setQuery($query) {
$this->query = $query;
return $this;
}
private function getQuery() {
return $this->query;
}
public function __construct(
$range_start,
$range_end,
@ -128,6 +137,7 @@ final class PHUICalendarDayView extends AphrontView {
'width' => '100%',
'top' => $top.'px',
'height' => $height.'px',
'canEdit' => $event->getCanEdit(),
);
}
}
@ -148,6 +158,10 @@ final class PHUICalendarDayView extends AphrontView {
Javelin::initBehavior(
'day-view',
array(
'year' => $first_event_hour->format('Y'),
'month' => $first_event_hour->format('m'),
'day' => $first_event_hour->format('d'),
'query' => $this->getQuery(),
'allDayEvents' => $js_today_all_day_events,
'todayEvents' => $js_today_events,
'hours' => $js_hours,

View file

@ -29,6 +29,11 @@
.phui-calendar-day-view td {
position: relative;
cursor: pointer;
}
.phui-calendar-day-view td:hover {
background: {$lightbluebackground};
}
.phui-calendar-day-view tr + tr td.phui-calendar-day-events {
@ -47,6 +52,10 @@ div.phui-calendar-day-event {
min-height: 30px;
}
.can-drag a {
cursor: move;
}
div.phui-calendar-day-event.all-day {
position: relative;
}

View file

@ -100,10 +100,15 @@ JX.behavior('day-view', function(config) {
},
name);
var class_name = 'phui-calendar-day-event';
if (e.canEdit) {
class_name = class_name + ' can-drag';
}
var div = JX.$N(
'div',
{
className: 'phui-calendar-day-event',
className: class_name,
sigil: sigil,
meta: {eventID: eventID, record: e, uri: uri},
style: {
@ -169,7 +174,11 @@ JX.behavior('day-view', function(config) {
var cell_event = JX.$N(
'td',
{
className: 'phui-calendar-day-events'
meta: {
time: hours[i]['hour_meridian']
},
className: 'phui-calendar-day-events',
sigil: 'phui-calendar-day-event-cell'
});
var row = JX.$N(
@ -195,6 +204,11 @@ JX.behavior('day-view', function(config) {
}
var year = config.year;
var month = config.month;
var day = config.day;
var query = config.query;
var hours = config.hours;
var first_event_hour = config.firstEventHour;
var first_event_hour_epoch = parseInt(config.firstEventHourEpoch, 10);
@ -234,6 +248,10 @@ JX.behavior('day-view', function(config) {
if (!e.isNormalMouseEvent()) {
return;
}
var data = e.getNodeData('phui-calendar-day-event');
if (!data.record.canEdit) {
return;
}
e.kill();
dragging = e.getNode('phui-calendar-day-event');
JX.DOM.alterClass(dragging, 'phui-drag', true);
@ -264,12 +282,13 @@ JX.behavior('day-view', function(config) {
dragging.style.top = new_top + 'px';
});
JX.Stratcom.listen('mouseup', null, function(){
var data = JX.Stratcom.getData(dragging);
var record = data.record;
if (!dragging) {
return;
}
var data = JX.Stratcom.getData(dragging);
var record = data.record;
if (new_top == offset_top) {
var now = new Date();
if (now.getTime() - click_time.getTime() < 250) {
@ -304,6 +323,25 @@ JX.behavior('day-view', function(config) {
}
});
JX.DOM.listen(table, 'click', 'phui-calendar-day-event-cell', function(e){
if (!e.isNormalClick()) {
return;
}
var data = e.getNodeData('phui-calendar-day-event-cell');
var time = data.time;
new JX.Workflow(
'/calendar/event/create/',
{
year: year,
month: month,
day: day,
time: time,
next: 'day',
query: query
})
.start();
});
var hourly_events_wrapper = JX.$N(
'div',
{style: {