Enables variance in AdditionalContent based on achievements granted to a particular team (#44)
* WIP * Enables content branching by achievement
This commit is contained in:
Родитель
8cccad906b
Коммит
964092b720
|
@ -9,6 +9,7 @@ import { getStaffPuzzleDetails } from 'modules'
|
|||
import { getStaffTeams, shouldRefreshTeams, shouldRefreshClues } from 'modules/staff';
|
||||
import { addAnswerToClue, addContentToClue, addLocationToClue, createClue, deleteClue, deleteContent, fetchStaffClueDetails, fetchStaffClues, relockClueForTeam, unlockClueForTeam } from 'modules/staff/clues/service';
|
||||
import { fetchStaffTeams } from "modules/staff/teams/service";
|
||||
import { fetchStaffAchievements, getAchievementsModule, shouldRefreshAchievements } from 'modules/staff/achievements';
|
||||
|
||||
import { AnswerForm, ClueForm, ContentForm, LocationForm } from './dialogs';
|
||||
import DialogRenderProp from './dialogs/DialogRenderProp';
|
||||
|
@ -70,6 +71,11 @@ class StaffClueDetails extends React.Component {
|
|||
if (shouldRefreshTeams(this.props.teams)) {
|
||||
this.props.fetchTeams();
|
||||
}
|
||||
|
||||
// Need the list of achievements for achievement-specific content unlocks
|
||||
if (shouldRefreshAchievements(this.props.achievements)) {
|
||||
this.props.fetchStaffAchievements();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
|
@ -163,6 +169,7 @@ class StaffClueDetails extends React.Component {
|
|||
renderButton={() => <><FaImages/> Add Content</>}
|
||||
renderBody={onComplete =>
|
||||
<ContentForm
|
||||
achievements={this.props.achievements.data}
|
||||
onSubmit={content => {
|
||||
this.props.addContentToClue(foundClue.tableOfContentId, content);
|
||||
onComplete();
|
||||
|
@ -186,6 +193,7 @@ class StaffClueDetails extends React.Component {
|
|||
/>
|
||||
<StaffClueContent
|
||||
content={foundClue.content}
|
||||
achievements={this.props.achievements.data}
|
||||
tableOfContentId={foundClue.tableOfContentId}
|
||||
addContentToClue={this.props.addContentToClue}
|
||||
addLocationToClue={this.props.addLocationToClue}
|
||||
|
@ -240,6 +248,7 @@ class StaffClueDetails extends React.Component {
|
|||
const mapStateToProps = (state, initProps) => ({
|
||||
user: state.user,
|
||||
clues: getStaffClues(state),
|
||||
achievements: getAchievementsModule(state),
|
||||
currentClue: getStaffPuzzleDetails(state, initProps.match.params.id),
|
||||
teams: getStaffTeams(state)
|
||||
})
|
||||
|
@ -256,6 +265,7 @@ const mapDispatchToProps = (dispatch) => ({
|
|||
deleteContent: (tableOfContentId, contentId) => dispatch(deleteContent(tableOfContentId, contentId)),
|
||||
unlockClueForTeam: (teamId, tableOfContentId, reason) => dispatch(unlockClueForTeam(teamId, tableOfContentId, reason)),
|
||||
relockClueForTeam: (teamId, tableOfContentId) => dispatch(relockClueForTeam(teamId, tableOfContentId)),
|
||||
fetchStaffAchievements: () => dispatch(fetchStaffAchievements())
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(StaffClueDetails);
|
|
@ -2,7 +2,7 @@ import React, { useState, useRef, useEffect } from 'react';
|
|||
import { Button, Form, FormGroup } from 'react-bootstrap'
|
||||
import CodeMirror from 'react-codemirror';
|
||||
|
||||
import { Content } from 'modules/types';
|
||||
import { Achievement, Content } from 'modules/types';
|
||||
import { ContentTemplate } from 'modules/staff/clues/models';
|
||||
|
||||
require('codemirror/mode/htmlmixed/htmlmixed');
|
||||
|
@ -10,15 +10,17 @@ require('codemirror/lib/codemirror.css');
|
|||
|
||||
type Props = Readonly<{
|
||||
content?: Content;
|
||||
achievements?: Array<Achievement>
|
||||
onSubmit: (contentTemplate: ContentTemplate) => void;
|
||||
}>;
|
||||
|
||||
export const ContentForm = ({ content, onSubmit }: Props) => {
|
||||
export const ContentForm = ({ content, achievements, onSubmit }: Props) => {
|
||||
const [contentId] = useState(content?.contentId ?? undefined);
|
||||
const [contentName, setContentName] = useState(content?.name ?? '');
|
||||
const [contentType, setContentType] = useState(content?.contentType ?? 'PlainText');
|
||||
const [stringContent, setStringContent] = useState(content?.stringContent ?? '');
|
||||
const [binaryContent, setBinaryContent] = useState(null);
|
||||
const [achievementUnlockId, setAchievementUnlockId] = useState(content?.achievementUnlockId ?? undefined);
|
||||
|
||||
const codeMirror = useRef<ReactCodeMirror.ReactCodeMirror | null>(null);
|
||||
|
||||
|
@ -102,6 +104,19 @@ export const ContentForm = ({ content, onSubmit }: Props) => {
|
|||
<Form.Control.Feedback type="invalid">Content must not be empty, and if a youtube URL must include embed in the URL</Form.Control.Feedback>
|
||||
</FormGroup>
|
||||
}
|
||||
|
||||
<FormGroup>
|
||||
<Form.Label>Unlocked by Achievement</Form.Label>
|
||||
<Form.Control as="select"
|
||||
disabled={!!content || !achievements}
|
||||
value={achievementUnlockId}
|
||||
onChange={event => setAchievementUnlockId(event.target.value)}>
|
||||
<option value="" selected>None</option>
|
||||
{
|
||||
achievements?.map((achievement) => <option value={achievement.achievementId}>{achievement.name}</option>)
|
||||
}
|
||||
</Form.Control>
|
||||
</FormGroup>
|
||||
|
||||
<Button onClick={() => {
|
||||
onSubmit({
|
||||
|
@ -109,7 +124,8 @@ export const ContentForm = ({ content, onSubmit }: Props) => {
|
|||
contentName,
|
||||
contentType,
|
||||
binaryContent: contentType === 'Image' ? binaryContent : undefined,
|
||||
stringContent: contentName !== 'Image' ? stringContent : undefined
|
||||
stringContent: contentName !== 'Image' ? stringContent : undefined,
|
||||
achievementUnlockId
|
||||
});
|
||||
}}>
|
||||
{content ? 'Update' : 'Add'}
|
||||
|
|
|
@ -3,7 +3,7 @@ import { FiExternalLink } from 'react-icons/fi';
|
|||
import { useSelector } from 'react-redux';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { Content } from "modules/types";
|
||||
import { Achievement, Content } from "modules/types";
|
||||
|
||||
type ContentProps = Readonly<{
|
||||
content: Content;
|
||||
|
@ -83,9 +83,10 @@ type AdditionalContentProps = Readonly<{
|
|||
content: Content;
|
||||
teamId?: string;
|
||||
playerId?: string;
|
||||
achievements?: Achievement[]
|
||||
}>;
|
||||
|
||||
export const AdditionalContent = ({ content, teamId, playerId }: AdditionalContentProps) => {
|
||||
export const AdditionalContent = ({ content, teamId, playerId, achievements }: AdditionalContentProps) => {
|
||||
let tokenReplacedContent = { ...content };
|
||||
let teamShortName = useSelector(store => _.get(store, "user.teamShortName"));
|
||||
|
||||
|
@ -100,19 +101,38 @@ export const AdditionalContent = ({ content, teamId, playerId }: AdditionalConte
|
|||
tokenReplacedContent.stringContent = tokenReplacedContent.stringContent.replace(/\[\[shortName\]\]/g, teamShortName.trim());
|
||||
}
|
||||
|
||||
let returnContent = <></>;
|
||||
if (content.contentType.trim() === "PlainText") {
|
||||
return <TextContent content={tokenReplacedContent} />
|
||||
returnContent = <TextContent content={tokenReplacedContent} />
|
||||
} else if (content.contentType.trim() === "RichText") {
|
||||
return <HtmlContent content={tokenReplacedContent} />
|
||||
returnContent = <HtmlContent content={tokenReplacedContent} />
|
||||
} else if (content.contentType.trim() === "Location") {
|
||||
return <LocationContent content={tokenReplacedContent} />
|
||||
returnContent = <LocationContent content={tokenReplacedContent} />
|
||||
} else if (content.contentType.trim() === "Hyperlink") {
|
||||
return <HyperlinkContent content={tokenReplacedContent} />
|
||||
returnContent = <HyperlinkContent content={tokenReplacedContent} />
|
||||
} else if (content.contentType.trim() === "Image") {
|
||||
return <ImageContent content={tokenReplacedContent} />
|
||||
returnContent = <ImageContent content={tokenReplacedContent} />
|
||||
} else if (content.contentType.trim() === "YoutubeUrl") {
|
||||
return <YoutubeContent content={tokenReplacedContent} />
|
||||
returnContent = <YoutubeContent content={tokenReplacedContent} />
|
||||
}
|
||||
|
||||
let matchingAchievement = undefined;
|
||||
if (content.achievementUnlockId && achievements)
|
||||
{
|
||||
matchingAchievement = achievements.find(achievement => achievement.achievementId === content.achievementUnlockId);
|
||||
}
|
||||
|
||||
if (matchingAchievement)
|
||||
{
|
||||
return <div>
|
||||
{returnContent}
|
||||
<br />
|
||||
<b>NOTE: The above content is unlocked by achievement:</b>
|
||||
<p>{matchingAchievement.name}</p>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
return returnContent;
|
||||
}
|
||||
|
||||
return <></>;
|
||||
};
|
|
@ -2,7 +2,7 @@ import { Button, Card, Col, Container, Row } from "react-bootstrap";
|
|||
import { FaEdit, FaTrashAlt, FaAngleDoubleUp } from 'react-icons/fa';
|
||||
import moment from "moment";
|
||||
|
||||
import { Content, SkipPlot, SolvedPlot, UnsolvedPlot } from "modules/types";
|
||||
import { Achievement, Content, SkipPlot, SolvedPlot, UnsolvedPlot } from "modules/types";
|
||||
import { ContentTemplate, LocationTemplate } from "modules/staff/clues";
|
||||
|
||||
import DialogRenderProp from '../dialogs/DialogRenderProp';
|
||||
|
@ -11,6 +11,7 @@ import { AdditionalContent } from "../presentation/AdditionalContent";
|
|||
|
||||
type Props = Readonly<{
|
||||
content: Content[];
|
||||
achievements: Achievement[];
|
||||
tableOfContentId: string;
|
||||
addContentToClue: (tableOfContentId: string, contentTemplate: ContentTemplate) => void;
|
||||
addLocationToClue: (tableOfContentId: string, locationTemplate: LocationTemplate) => void;
|
||||
|
@ -19,13 +20,14 @@ type Props = Readonly<{
|
|||
|
||||
type ActionProps = Readonly<{
|
||||
contentItem: Content;
|
||||
achievements: Achievement[]
|
||||
tableOfContentId: string;
|
||||
addContentToClue: (tableOfContentId: string, contentTemplate: ContentTemplate) => void;
|
||||
addLocationToClue: (tableOfContentId: string, locationTemplate: LocationTemplate) => void;
|
||||
deleteContent: (tableOfContentId: string, contentId: string) => void;
|
||||
}>;
|
||||
|
||||
const ContentActions = ({ addContentToClue, addLocationToClue, deleteContent, tableOfContentId, contentItem }: ActionProps) => {
|
||||
const ContentActions = ({ addContentToClue, addLocationToClue, deleteContent, tableOfContentId, contentItem, achievements }: ActionProps) => {
|
||||
return (
|
||||
<Row>
|
||||
<Col style={{ alignContent: 'center' }}>
|
||||
|
@ -49,6 +51,7 @@ const ContentActions = ({ addContentToClue, addLocationToClue, deleteContent, ta
|
|||
return (
|
||||
<ContentForm
|
||||
content={contentItem}
|
||||
achievements={achievements}
|
||||
onSubmit={content => {
|
||||
addContentToClue(tableOfContentId, content);
|
||||
onComplete();
|
||||
|
@ -74,13 +77,14 @@ type ContentCardProps = Readonly<{
|
|||
title: string;
|
||||
description: JSX.Element;
|
||||
contentList: Content[];
|
||||
achievements: Achievement[];
|
||||
tableOfContentId: string;
|
||||
addContentToClue: (tableOfContentId: string, contentTemplate: ContentTemplate) => void;
|
||||
addLocationToClue: (tableOfContentId: string, locationTemplate: LocationTemplate) => void;
|
||||
deleteContent: (tableOfContentId: string, contentId: string) => void;
|
||||
}>;
|
||||
|
||||
const ContentCard = ({ title, description, contentList, tableOfContentId, addContentToClue, addLocationToClue, deleteContent }: ContentCardProps) => {
|
||||
const ContentCard = ({ title, description, contentList, achievements, tableOfContentId, addContentToClue, addLocationToClue, deleteContent }: ContentCardProps) => {
|
||||
if (contentList.length > 0) {
|
||||
return (
|
||||
<Card style={{ justifySelf: "center", margin: "40px" }}>
|
||||
|
@ -90,17 +94,18 @@ const ContentCard = ({ title, description, contentList, tableOfContentId, addCon
|
|||
</Card.Header>
|
||||
<Card.Text>
|
||||
<Container fluid>
|
||||
{contentList.map(content =>
|
||||
{contentList.map(content =>
|
||||
<>
|
||||
<Row style={{ margin: "15px" }}>
|
||||
<AdditionalContent content={content}/>
|
||||
<AdditionalContent content={content} achievements={achievements}/>
|
||||
</Row>
|
||||
<ContentActions
|
||||
addContentToClue={addContentToClue}
|
||||
addLocationToClue={addLocationToClue}
|
||||
deleteContent={deleteContent}
|
||||
tableOfContentId={tableOfContentId}
|
||||
contentItem={content} />
|
||||
contentItem={content}
|
||||
achievements={achievements} />
|
||||
</>
|
||||
)}
|
||||
</Container>
|
||||
|
@ -112,7 +117,7 @@ const ContentCard = ({ title, description, contentList, tableOfContentId, addCon
|
|||
}
|
||||
};
|
||||
|
||||
export const StaffClueContent = ({ content, tableOfContentId, addContentToClue, addLocationToClue, deleteContent }: Props) => {
|
||||
export const StaffClueContent = ({ content, achievements, tableOfContentId, addContentToClue, addLocationToClue, deleteContent }: Props) => {
|
||||
const sortedContent = content.sort((a, b) => moment.utc(b.lastUpdated).diff(moment.utc(a.lastUpdated)));
|
||||
|
||||
if (content.length > 0) {
|
||||
|
@ -125,6 +130,7 @@ export const StaffClueContent = ({ content, tableOfContentId, addContentToClue,
|
|||
<>
|
||||
<ContentCard
|
||||
title="Unsolved Plot"
|
||||
achievements={achievements}
|
||||
description={<em>Teams will see this on both the home page and puzzle page, but only when the puzzle is <strong>unsolved</strong>.</em>}
|
||||
contentList={unsolvedPlotContent}
|
||||
tableOfContentId={tableOfContentId}
|
||||
|
@ -135,6 +141,7 @@ export const StaffClueContent = ({ content, tableOfContentId, addContentToClue,
|
|||
|
||||
<ContentCard
|
||||
title="Solved Plot"
|
||||
achievements={achievements}
|
||||
description={<em>Teams will see this on both the home page and puzzle page, but only when the puzzle is <strong>solved</strong>.</em>}
|
||||
contentList={solvedPlotContent}
|
||||
tableOfContentId={tableOfContentId}
|
||||
|
@ -145,6 +152,7 @@ export const StaffClueContent = ({ content, tableOfContentId, addContentToClue,
|
|||
|
||||
<ContentCard
|
||||
title="Skip Plot"
|
||||
achievements={achievements}
|
||||
description={<em>If a team is <strong>skipped</strong> over this clue, they will see this on the home page, but this clue will not show up on all clues.</em>}
|
||||
contentList={skippedPlotContent}
|
||||
tableOfContentId={tableOfContentId}
|
||||
|
@ -155,6 +163,7 @@ export const StaffClueContent = ({ content, tableOfContentId, addContentToClue,
|
|||
|
||||
<ContentCard
|
||||
title="Other Content"
|
||||
achievements={achievements}
|
||||
description={<em>Teams will only see this on the puzzle page, regardless of solve status</em>}
|
||||
contentList={otherContent}
|
||||
tableOfContentId={tableOfContentId}
|
||||
|
|
|
@ -51,6 +51,7 @@ export type ContentTemplate = Readonly<{
|
|||
contentName: string;
|
||||
stringContent?: string;
|
||||
binaryContent?: any;
|
||||
achievementUnlockId?: string;
|
||||
}>;
|
||||
|
||||
export type LocationTemplate = Readonly<{
|
||||
|
|
|
@ -113,6 +113,7 @@ export const addContentToClue = (tableOfContentId: string, contentTemplate: Cont
|
|||
body.append("contentName", contentTemplate.contentName);
|
||||
body.append("contentType", contentTemplate.contentType);
|
||||
body.append("binaryContent", contentTemplate.binaryContent);
|
||||
contentTemplate.achievementUnlockId && body.append("achievementUnlockId", contentTemplate.achievementUnlockId);
|
||||
|
||||
doServiceRequest(
|
||||
dispatch,
|
||||
|
|
|
@ -50,6 +50,7 @@ export type Content = Readonly<{
|
|||
latitude?: number;
|
||||
longitude?: number;
|
||||
locationFlags?: number;
|
||||
achievementUnlockId?: string;
|
||||
}>;
|
||||
|
||||
export type PlayerSubmission = Readonly<{
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
USE [gamecontrol]
|
||||
GO
|
||||
SET QUOTED_IDENTIFIER ON
|
||||
GO
|
||||
INSERT INTO [dbo].[Event] ([EventId], [EventName])
|
||||
VALUES (
|
||||
'88888888-8888-8888-8888-888888888888',
|
||||
|
|
|
@ -731,6 +731,7 @@ CREATE TABLE [dbo].[AdditionalContent](
|
|||
[LastUpdate] [datetime] NOT NULL,
|
||||
[EncryptionKey] [varbinary](max) NULL,
|
||||
[ContentText] [nvarchar](max) NULL,
|
||||
[AchievementUnlockId] [uniqueidentifier] NULL,
|
||||
CONSTRAINT [PK_AdditionalContent] PRIMARY KEY CLUSTERED
|
||||
(
|
||||
[ContentId] ASC
|
||||
|
@ -3120,6 +3121,7 @@ BEGIN
|
|||
AdditionalContent.LastUpdate as ContentLastUpdated,
|
||||
AdditionalContent.EncryptionKey,
|
||||
AdditionalContent.ContentText,
|
||||
AdditionalContent.AchievementUnlockId,
|
||||
Location.LocationId,
|
||||
Location.Name AS LocationName,
|
||||
Location.LastUpdate as LocationLastUpdated,
|
||||
|
@ -3159,6 +3161,7 @@ BEGIN
|
|||
AdditionalContent.LastUpdate as ContentLastUpdated,
|
||||
AdditionalContent.EncryptionKey,
|
||||
AdditionalContent.ContentText,
|
||||
AdditionalContent.AchievementUnlockId,
|
||||
Location.LocationId,
|
||||
Location.Name AS LocationName,
|
||||
Location.LastUpdate as LocationLastUpdated,
|
||||
|
|
|
@ -15,6 +15,7 @@ using Microsoft.EntityFrameworkCore;
|
|||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
@ -50,6 +51,7 @@ namespace GameControl.Server.Controllers.Player
|
|||
var eventSubmissions = this.dbContext.GetValidSubmissions(eventInstanceId).ToList();
|
||||
var sortOverridesRow = this.dbContext.TeamAdditionalData.AsNoTracking().FirstOrDefault(p => p.Team == participation.Team.Value && p.DataKey == TeamSortOverrideViewModel.AdditionalDataKey);
|
||||
|
||||
var achievementIds = this.dbContext.GetAchievementsForTeam(participation.Team.Value).Select(a => a.AchievementId).ToImmutableHashSet();
|
||||
var overrides = new List<TeamSortOverrideViewModel>();
|
||||
|
||||
Dictionary<Guid, List<AdditionalContentForTeam>> contentDictionary = new Dictionary<Guid, List<AdditionalContentForTeam>>();
|
||||
|
@ -86,13 +88,21 @@ namespace GameControl.Server.Controllers.Player
|
|||
clue.Content = new List<ContentViewModel>();
|
||||
if (contentDictionary.ContainsKey(clue.TableOfContentId))
|
||||
{
|
||||
|
||||
IEnumerable<AdditionalContentForTeam> contentUnlockedByAchievements = contentDictionary[clue.TableOfContentId]
|
||||
.Where(p => !p.AchievementUnlockId.HasValue || achievementIds.Contains(p.AchievementUnlockId.Value));
|
||||
|
||||
if (clue.IsSolved)
|
||||
{
|
||||
clue.Content = contentDictionary[clue.TableOfContentId].Where(p => p.ContentName != ContentViewModel.UnsolvedPlot && p.ContentName != ContentViewModel.SkipPlot).Select(p => new ContentViewModel(p));
|
||||
clue.Content = contentUnlockedByAchievements
|
||||
.Where(p => p.ContentName != ContentViewModel.UnsolvedPlot && p.ContentName != ContentViewModel.SkipPlot)
|
||||
.Select(p => new ContentViewModel(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
clue.Content = contentDictionary[clue.TableOfContentId].Where(p => p.ContentName != ContentViewModel.SolvedPlot && p.ContentName != ContentViewModel.SkipPlot).Select(p => new ContentViewModel(p));
|
||||
clue.Content = contentUnlockedByAchievements
|
||||
.Where(p => p.ContentName != ContentViewModel.SolvedPlot && p.ContentName != ContentViewModel.SkipPlot)
|
||||
.Select(p => new ContentViewModel(p));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace GameControl.Server.Database.SprocTypes
|
|||
|
||||
public string ContentText { get; set; }
|
||||
|
||||
public Guid? AchievementUnlockId { get; set; }
|
||||
|
||||
public string ShortName { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
|
|
@ -16,6 +16,8 @@ namespace GameControl.Server.Database.SprocTypes
|
|||
|
||||
public string ContentText { get; set; }
|
||||
|
||||
public Guid? AchievementUnlockId { get; set; }
|
||||
|
||||
public string ShortName { get; set; }
|
||||
|
||||
public string FileName { get; set; }
|
||||
|
|
|
@ -23,5 +23,7 @@ namespace GameControl.Server.Database.Tables
|
|||
public DateTime LastUpdate { get; set; }
|
||||
|
||||
public byte[] EncryptionKey { get; set; }
|
||||
|
||||
public Guid? AchievementUnlockId { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,5 +14,7 @@ namespace GameControl.Server.RequestTypes
|
|||
public string StringContent { get; set; }
|
||||
|
||||
public IFormFile BinaryContent { get; set; }
|
||||
|
||||
public Guid? AchievementUnlockId { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ namespace GameControl.Server.Util
|
|||
ContentType = content.ContentType,
|
||||
Name = content.ContentName,
|
||||
ContentText = content.StringContent,
|
||||
LastUpdate = DateTime.UtcNow
|
||||
LastUpdate = DateTime.UtcNow,
|
||||
AchievementUnlockId = content.AchievementUnlockId,
|
||||
};
|
||||
|
||||
dbContext.AdditionalContent.Add(newContent);
|
||||
|
@ -48,6 +49,7 @@ namespace GameControl.Server.Util
|
|||
ContentType = content.ContentType,
|
||||
Name = content.ContentName,
|
||||
LastUpdate = DateTime.UtcNow,
|
||||
AchievementUnlockId = content.AchievementUnlockId,
|
||||
};
|
||||
|
||||
var targetPath =
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using GameControl.Server.Database.SprocTypes;
|
||||
using GameControl.Server.Database.Tables;
|
||||
using GameControl.Server.Util;
|
||||
using Microsoft.EntityFrameworkCore.Query.Internal;
|
||||
using System;
|
||||
|
||||
namespace GameControl.Server.ViewModel
|
||||
|
@ -18,6 +19,7 @@ namespace GameControl.Server.ViewModel
|
|||
this.ContentType = source.ContentType.Trim();
|
||||
this.Name = source.Name;
|
||||
this.LastUpdated = source.LastUpdate;
|
||||
this.AchievementUnlockId = source.AchievementUnlockId;
|
||||
|
||||
if (source.ContentType.Trim().Equals("PlainText", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
source.ContentType.Trim().Equals("RichText", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
|
@ -51,6 +53,7 @@ namespace GameControl.Server.ViewModel
|
|||
this.ContentType = source.ContentType.Trim();
|
||||
this.Name = source.ContentName;
|
||||
this.LastUpdated = source.ContentLastUpdated.Value;
|
||||
this.AchievementUnlockId = source.AchievementUnlockId;
|
||||
|
||||
if (source.ContentType.Trim().Equals("PlainText", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
source.ContentType.Trim().Equals("RichText", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
|
@ -96,6 +99,7 @@ namespace GameControl.Server.ViewModel
|
|||
this.ContentType = source.ContentType.Trim();
|
||||
this.Name = source.ContentName;
|
||||
this.LastUpdated = source.ContentLastUpdated.Value;
|
||||
this.AchievementUnlockId = source.AchievementUnlockId;
|
||||
|
||||
if (source.ContentType.Trim().Equals("PlainText", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
source.ContentType.Trim().Equals("RichText", StringComparison.InvariantCultureIgnoreCase) ||
|
||||
|
@ -151,5 +155,7 @@ namespace GameControl.Server.ViewModel
|
|||
public int LocationFlags { get; set; }
|
||||
|
||||
public DateTime LastUpdated { get; set; }
|
||||
|
||||
public Guid? AchievementUnlockId { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче