mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-29 08:50:58 +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:
parent
963485a3da
commit
18fe6d58ae
8 changed files with 173 additions and 34 deletions
|
@ -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',
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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: {
|
||||
|
|
Loading…
Reference in a new issue